diff --git a/forge_core/src/ast.rs b/forge_core/src/ast.rs index 006dbda..6539d64 100644 --- a/forge_core/src/ast.rs +++ b/forge_core/src/ast.rs @@ -75,7 +75,7 @@ pub struct Return(pub Option); #[derive(PartialEq, Clone, Debug)] pub struct Assignment { pub lvalue: Lvalue, - pub rvalue: Rvalue, + pub rvalue: Expr, } // An lvalue is just a tag on an expr. Any expr parses just fine as an lvalue... not all exprs @@ -103,18 +103,12 @@ impl From for Lvalue { } } -#[derive(PartialEq, Clone, Debug)] -pub enum Rvalue { - Expr(Expr), - String(String), -} - #[derive(PartialEq, Clone, Debug)] pub struct VarDecl { pub name: String, pub typename: Option, pub size: Option, - pub initial: Option, + pub initial: Option, } #[derive(PartialEq, Clone, Debug)] @@ -174,10 +168,11 @@ pub enum Expr { Neg(BoxExpr), Deref(BoxExpr), Address(Lvalue), - Call(BoxExpr, Vec), + Call(BoxExpr, Vec), Subscript(BoxExpr, BoxExpr), Member(BoxExpr, String), Infix(BoxExpr, Operator, BoxExpr), + String(String), } #[repr(transparent)] @@ -225,15 +220,3 @@ impl From<&str> for Expr { Self::Name(String::from(value)) } } - -impl From for Rvalue { - fn from(value: i32) -> Self { - Self::Expr(value.into()) - } -} - -impl From<&str> for Rvalue { - fn from(value: &str) -> Self { - Self::String(value.into()) - } -} diff --git a/forge_core/src/compiler.rs b/forge_core/src/compiler.rs index 26dccb2..6f08efb 100644 --- a/forge_core/src/compiler.rs +++ b/forge_core/src/compiler.rs @@ -270,7 +270,7 @@ impl Compilable for Assignment { impl Compilable for VarDecl { fn process(self, state: &mut State, sig: Option<&mut CompiledFn>) -> Result<(), CompileError> { - let mut sig = sig.expect("Var declaration outside function"); + let sig = sig.expect("Var declaration outside function"); if self.typename.is_some() || self.size.is_some() { todo!("Structs and arrays are not yet supported") } @@ -293,24 +293,6 @@ impl Compilable for VarDecl { /////////////////////////////////////////////////////////// -impl Compilable for Rvalue { - fn process(self, state: &mut State, sig: Option<&mut CompiledFn>) -> Result<(), CompileError> { - let sig = sig.expect("Assignment outside function"); - // For a normal expr, eval and leave on the stack; for a string literal, add it to - // the str table and push the label's address - match self { - Rvalue::Expr(e) => e.process(state, Some(sig)), - Rvalue::String(string) => { - let label = state.add_string(&string); - sig.emit_arg("push", label); - Ok(()) - } - } - } -} - -/////////////////////////////////////////////////////////// - /// Evaluate an lvalue and leave its address on the stack (ready to be consumed by storew) impl Compilable for Lvalue { fn process(self, state: &mut State, sig: Option<&mut CompiledFn>) -> Result<(), CompileError> { @@ -324,7 +306,8 @@ impl Compilable for Lvalue { Expr::Not(_) | Expr::Address(_) | Expr::Call(_, _) | - Expr::Infix(_, _, _) => { + Expr::Infix(_, _, _) | + Expr::String(_) => { Err(CompileError(0, 0, String::from("Not a valid lvalue"))) } @@ -444,6 +427,11 @@ impl Compilable for Expr { sig.emit("loadw"); Ok(()) } + Expr::String(string) => { + let label = state.add_string(&string); + sig.emit_arg("push", label); + Ok(()) + } Expr::Call(_, _) => todo!(), Expr::Subscript(_, _) => todo!("Structs and arrays are not yen supported"), Expr::Member(_, _) => todo!("Structs and arrays are not yen supported"), @@ -558,7 +546,11 @@ pub fn eval_const(expr: Expr, scope: &Scope) -> Result { let val = eval_const(*e.0, scope)?; Ok(if val != 0 { 0 } else { 1 }) } - Expr::Address(_) | Expr::Deref(_) => Err(CompileError( + // A note about Expr::String here: 'const foo="banana"' won't hit this point; it'll be + // (currently) parsed as a special case of const. The only things that will hit this are + // const expressions that include strings, like '"foo"[2]' or something. Those can't be + // (generally) calculated at compile time, so, they're an error. + Expr::Address(_) | Expr::Deref(_) | Expr::String(_) => Err(CompileError( 0, 0, String::from("Addresses are not known at compile time"), diff --git a/forge_core/src/forge_parser.rs b/forge_core/src/forge_parser.rs index 0648c80..d207d2b 100644 --- a/forge_core/src/forge_parser.rs +++ b/forge_core/src/forge_parser.rs @@ -323,58 +323,20 @@ impl AstNode for Assignment { fn from_pair(pair: Pair) -> Self { let mut pairs = pair.into_inner(); let lvalue = Expr::from_pair(pairs.next().unwrap()).into(); - let rvalue = Rvalue::from_pair(pairs.next().unwrap()); + let rvalue = Expr::from_pair(pairs.next().unwrap()); Self { lvalue, rvalue } } } /////////////////////////////////////////////////////////////////////////////////////////// -// impl AstNode for Lvalue { -// const RULE: Rule = Rule::lvalue; -// fn from_pair(pair: Pair) -> Self { -// let mut pairs = pair.into_inner(); -// let first = pairs.next().unwrap(); -// if first.as_rule() == Rule::expr { -// Self::Expr(Expr::from_pair(first).into()) -// } else { -// let name = String::from(first.as_str()); -// let subscripts: Vec<_> = pairs -// .map(|p| match p.as_rule() { -// Rule::subscript => Suffix::Subscript(Expr::from_pair(p.first()).into()), -// Rule::member => Suffix::Member(p.first_as_string()), -// _ => unreachable!(), -// }) -// .collect(); -// Self::Name(name, subscripts) -// } -// } -// } - -/////////////////////////////////////////////////////////////////////////////////////////// - -impl AstNode for Rvalue { - const RULE: Rule = Rule::rvalue; - - fn from_pair(pair: Pair) -> Self { - let pair = pair.first(); - match pair.as_rule() { - Rule::string => Self::String(pair.into_quoted_string()), - Rule::expr => Self::Expr(Expr::from_pair(pair)), - _ => unreachable!(), - } - } -} - -/////////////////////////////////////////////////////////////////////////////////////////// - impl AstNode for VarDecl { const RULE: Rule = Rule::var_decl; fn from_pair(pair: Pair) -> Self { let mut inner = pair.into_inner(); let name = String::from(inner.next().unwrap().as_str()); let Varinfo { typename, size } = Varinfo::from_pair(inner.next().unwrap()); - let initial = inner.next().map(Rvalue::from_pair); + let initial = inner.next().map(Expr::from_pair); Self { name, typename, @@ -460,6 +422,7 @@ impl AstNode for Expr { Rule::number => Expr::Number(term.into_number()), Rule::name => Expr::Name(String::from(term.as_str())), Rule::expr => Expr::from_pair(term), + Rule::string => Self::String(term.into_quoted_string()), _ => unreachable!(), }) .map_infix(|lhs, op, rhs| Expr::Infix(lhs.into(), Operator::from_pair(op), rhs.into())) @@ -473,7 +436,7 @@ impl AstNode for Expr { .map_postfix(|expr, suffix| match suffix.as_rule() { Rule::arglist => Expr::Call( expr.into(), - suffix.into_inner().map(Rvalue::from_pair).collect(), + suffix.into_inner().map(Expr::from_pair).collect(), ), Rule::subscript => { Expr::Subscript(expr.into(), Expr::from_pair(suffix.first()).into()) @@ -901,7 +864,7 @@ mod test { //Calls with strings assert_eq!( Expr::from_str("blah(\"foo\", 2)"), - Ok(Expr::Call("blah".into(), vec!["foo".into(), 2.into()])) + Ok(Expr::Call("blah".into(), vec![Expr::String("foo".into()), 2.into()])) ); } @@ -924,7 +887,7 @@ mod test { Statement::from_str("foo = 7;"), Ok(Statement::Assignment(Assignment { lvalue: "foo".into(), - rvalue: Rvalue::Expr(7.into()), + rvalue: 7.into(), })) ); @@ -932,7 +895,7 @@ mod test { Assignment::from_str("foo[45] = 7"), Ok(Assignment { lvalue: Expr::Subscript("foo".into(), 45.into()).into(), - rvalue: Rvalue::Expr(7.into()), + rvalue: 7.into(), }) ); @@ -940,7 +903,7 @@ mod test { Assignment::from_str("*foo = 12"), Ok(Assignment { lvalue: Expr::Deref("foo".into()).into(), - rvalue: Rvalue::Expr(12.into()) + rvalue: 12.into() }) ); } diff --git a/forge_core/src/new.pest b/forge_core/src/new.pest index fe6fb04..026b5c8 100644 --- a/forge_core/src/new.pest +++ b/forge_core/src/new.pest @@ -19,8 +19,7 @@ escape = @{ "\\" ~ ("t" | "r" | "n" | "0" | "\\" | "\"") } string_inner = ${ !("\"" | "\\") ~ ANY | escape } string = ${ "\"" ~ string_inner* ~ "\"" } -assignment = { expr ~ "=" ~ rvalue } -rvalue = { expr | string } +assignment = { expr ~ "=" ~ expr } add = { "+" } sub = { "-" } @@ -64,12 +63,12 @@ operator = _{ } expr = { prefix* ~ term ~ suffix* ~ (operator ~ prefix* ~ term ~ suffix*)* } -term = _{ number | name | "(" ~ expr ~ ")" } +term = _{ number | name | "(" ~ expr ~ ")" | string } suffix = _{ modifier | arglist } modifier = _{ subscript | member } subscript = { "[" ~ expr ~ "]" } -arglist = { "(" ~ (rvalue ~ ("," ~ rvalue)*)? ~ ")" } +arglist = { "(" ~ (expr ~ ("," ~ expr)*)? ~ ")" } member = { "." ~ name } statement = { asm | ((return_stmt | var_decl | assignment | expr) ~ ";") | conditional | while_loop | repeat_loop } @@ -91,11 +90,11 @@ return_stmt = { "return" ~ expr? } conditional = { "if" ~ "(" ~ expr ~ ")" ~ block ~ ("else" ~ block)? } while_loop = { "while" ~ "(" ~ expr ~ ")" ~ block } repeat_loop = { "repeat" ~ "(" ~ expr ~ ")" ~ name? ~ block } -var_decl = { "var" ~ name ~ varinfo ~ ("=" ~ rvalue)? } +var_decl = { "var" ~ name ~ varinfo ~ ("=" ~ expr)? } global = { "global" ~ name ~ varinfo ~ ";" } typename = { ":" ~ name } size = { "[" ~ expr ~ "]" } -const_decl = { "const" ~ name ~ "=" ~ (expr | string) ~ ";" } +const_decl = { "const" ~ name ~ "=" ~ (string | expr) ~ ";" } struct_decl = { "struct" ~ name ~ "{" ~ members ~ "}" } member_decl = { name ~ varinfo }