More refactoring
This commit is contained in:
@@ -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),
|
||||
}
|
||||
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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![])),
|
||||
]))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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)*)? ~ ")" }
|
||||
|
||||
Reference in New Issue
Block a user