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