Strings are just another kind of expr
This commit is contained in:
+4
-21
@@ -75,7 +75,7 @@ pub struct Return(pub Option<Expr>);
|
||||
#[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<Expr> 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<String>,
|
||||
pub size: Option<Expr>,
|
||||
pub initial: Option<Rvalue>,
|
||||
pub initial: Option<Expr>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
@@ -174,10 +168,11 @@ pub enum Expr {
|
||||
Neg(BoxExpr),
|
||||
Deref(BoxExpr),
|
||||
Address(Lvalue),
|
||||
Call(BoxExpr, Vec<Rvalue>),
|
||||
Call(BoxExpr, Vec<Expr>),
|
||||
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<i32> 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())
|
||||
}
|
||||
}
|
||||
|
||||
+13
-21
@@ -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<i32, CompileError> {
|
||||
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"),
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
Reference in New Issue
Block a user