More refactoring

This commit is contained in:
2023-08-05 11:07:09 -05:00
parent 63d63a1f68
commit e3b20aae41
4 changed files with 37 additions and 40 deletions
+4 -4
View File
@@ -137,7 +137,7 @@ pub struct RepeatLoop {
}
/// One of the five arithmetical operators
#[derive(Debug, PartialEq, Copy, Clone)]
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Operator {
Add,
Sub,
@@ -162,7 +162,6 @@ pub enum Operator {
#[derive(Debug, PartialEq, Clone)]
pub enum Suffix {
Subscript(BoxExpr),
Arglist(Vec<Rvalue>),
Member(String),
}
@@ -170,11 +169,12 @@ pub enum Suffix {
pub enum Expr {
Number(i32),
Name(String),
Expr(BoxExpr),
Not(BoxExpr),
Neg(BoxExpr),
Address(Lvalue),
Suffix(BoxExpr, Suffix),
Call(BoxExpr, Vec<Rvalue>),
Subscript(BoxExpr, BoxExpr),
Member(BoxExpr, String),
Infix(BoxExpr, Operator, BoxExpr),
}
+4 -10
View File
@@ -406,11 +406,6 @@ impl Compilable for Expr {
None => Err(CompileError(0, 0, format!("Unknown name {}", name))),
}
}
Expr::Expr(e) => {
// Just an expr containing an expr, recurse
(*e.0).process(state, Some(sig))?;
Ok(())
}
Expr::Neg(e) => {
(*e.0).process(state, Some(sig))?;
// To arithmetically negate something, invert and increment (2s complement)
@@ -425,9 +420,9 @@ impl Compilable for Expr {
}
// Handling addresses is very easy because processing an lvalue leaves the address on the stack
Expr::Address(lvalue) => lvalue.process(state, Some(sig)),
Expr::Suffix(_, _) => {
todo!()
}
Expr::Call(_, _) => todo!(),
Expr::Subscript(_, _) => todo!("Structs and arrays are not yen supported"),
Expr::Member(_, _) => todo!("Structs and arrays are not yen supported"),
Expr::Infix(lhs, op, rhs) => {
// Recurse on expressions, handling operators
(*lhs.0).process(state, Some(&mut sig))?;
@@ -531,7 +526,6 @@ pub fn eval_const(expr: Expr, scope: &Scope) -> Result<i32, CompileError> {
Err(CompileError(0, 0, format!("Unknown const {}", n)))
}
}
Expr::Expr(e) => eval_const(*e.0, scope),
Expr::Neg(e) => {
let val = eval_const(*e.0, scope)?;
Ok(-val)
@@ -545,7 +539,7 @@ pub fn eval_const(expr: Expr, scope: &Scope) -> Result<i32, CompileError> {
0,
String::from("Addresses are not known at compile time"),
)),
Expr::Suffix(_, _) => Err(CompileError(
Expr::Call(_, _) | Expr::Subscript(_, _) | Expr::Member(_, _) => Err(CompileError(
0,
0,
String::from("Constants must be statically defined"),
+28 -25
View File
@@ -23,7 +23,9 @@ lazy_static::lazy_static! {
.op(Op::infix(add, Left) | Op::infix(sub, Left))
.op(Op::infix(mul, Left) | Op::infix(div, Left) | Op::infix(modulus, Left))
.op(Op::prefix(Rule::prefix))
.op(Op::postfix(Rule::suffix))
.op(Op::postfix(Rule::arglist))
.op(Op::postfix(Rule::subscript))
.op(Op::postfix(Rule::member))
};
}
@@ -462,7 +464,17 @@ impl AstNode for Expr {
"!" => Expr::Not(expr.into()),
_ => unreachable!(),
})
.map_postfix(|expr, suffix| Expr::Suffix(expr.into(), Suffix::from_pair(suffix)))
.map_postfix(|expr, suffix| match suffix.as_rule() {
Rule::arglist => Expr::Call(
expr.into(),
suffix.into_inner().map(Rvalue::from_pair).collect(),
),
Rule::subscript => {
Expr::Subscript(expr.into(), Expr::from_pair(suffix.first()).into())
}
Rule::member => Expr::Member(expr.into(), suffix.first_as_string()),
_ => unreachable!(),
})
.parse(pair.into_inner())
}
}
@@ -512,8 +524,8 @@ impl AstNode for Suffix {
match first.as_rule() {
Rule::subscript => Self::Subscript(Expr::from_pair(first.first()).into()),
Rule::member => Self::Member(first.first_as_string()),
Rule::arglist => Self::Arglist(first.into_inner().map(Rvalue::from_pair).collect()),
rule => unreachable!("Expected a subscript, member, or arglist, got a {:?}", rule),
//Rule::arglist => Self::Arglist(first.into_inner().map(Rvalue::from_pair).collect()),
rule => unreachable!("Expected a subscript or member, got a {:?}", rule),
}
}
}
@@ -746,15 +758,15 @@ mod test {
// Simple suffix
assert_eq!(
Expr::from_str("foo[10]"),
Ok(Expr::Suffix("foo".into(), Subscript(10.into())))
Ok(Expr::Subscript("foo".into(), 10.into()))
);
// Multi-suffix
assert_eq!(
Expr::from_str("foo[10].bar"),
Ok(Expr::Suffix(
Expr::Suffix("foo".into(), Subscript(10.into())).into(),
Member("bar".into())
Ok(Expr::Member(
Expr::Subscript("foo".into(), 10.into()).into(),
"bar".into()
))
);
@@ -848,21 +860,18 @@ mod test {
))
);
// This is godawful but legal _as long as it parses like this._ The arglist suffix on the end
// goes on the "&foo" expression as a whole, so, it "calls" the address of foo. Essentially:
// This is godawful but legal _as long as it parses like this._ The arglist on the end goes
// on the "&foo" expression as a whole, so, it "calls" the address of foo. Essentially:
// "push foo; call" rather than "loadw foo; call"
assert_eq!(
Expr::from_str("&foo()"),
Ok(Expr::Suffix(
Expr::Address("foo".into()).into(),
Suffix::Arglist(vec![])
))
Ok(Expr::Call(Expr::Address("foo".into()).into(), vec![]))
)
}
#[test]
fn parse_calls() {
let blah = Expr::Suffix("blah".into(), Suffix::Arglist(vec![]));
let blah = Expr::Call("blah".into(), vec![]);
// Can Node parse a call?
assert_eq!(Expr::from_str("blah()"), Ok(blah.clone()));
@@ -873,19 +882,13 @@ mod test {
// Calls with args
assert_eq!(
Expr::from_str("blah(1, 2)"),
Ok(Expr::Suffix(
"blah".into(),
Suffix::Arglist(vec![1.into(), 2.into()])
))
Ok(Expr::Call("blah".into(), vec![1.into(), 2.into()]))
);
//Calls with strings
assert_eq!(
Expr::from_str("blah(\"foo\", 2)"),
Ok(Expr::Suffix(
"blah".into(),
Suffix::Arglist(vec!["foo".into(), 2.into()])
))
Ok(Expr::Call("blah".into(), vec!["foo".into(), 2.into()]))
);
}
@@ -952,8 +955,8 @@ mod test {
assert_eq!(
Block::from_str("{ foo(); bar(); }"),
Ok(Block(vec![
Statement::Expr(Expr::Suffix("foo".into(), Suffix::Arglist(vec![]))),
Statement::Expr(Expr::Suffix("bar".into(), Suffix::Arglist(vec![]))),
Statement::Expr(Expr::Call("foo".into(), vec![])),
Statement::Expr(Expr::Call("bar".into(), vec![])),
]))
);
}
+1 -1
View File
@@ -67,7 +67,7 @@ operator = _{
expr = { prefix* ~ term ~ suffix* ~ (operator ~ prefix* ~ term ~ suffix*)* }
term = _{ number | name | "(" ~ expr ~ ")" | "&" ~ lvalue }
suffix = { modifier | arglist }
suffix = _{ modifier | arglist }
modifier = _{ subscript | member }
subscript = { "[" ~ expr ~ "]" }
arglist = { "(" ~ (rvalue ~ ("," ~ rvalue)*)? ~ ")" }