Strings are just another kind of expr

This commit is contained in:
2023-08-14 00:26:02 -05:00
parent c6aea2f78f
commit 64f09619a2
4 changed files with 30 additions and 93 deletions
+4 -21
View File
@@ -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
View File
@@ -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"),
+8 -45
View File
@@ -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()
})
);
}
+5 -6
View File
@@ -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 }