Added peek and poke

This commit is contained in:
2024-05-03 23:45:29 -05:00
parent 46001c73f8
commit 4b836d076b
6 changed files with 58 additions and 3 deletions
+2
View File
@@ -174,6 +174,8 @@ pub enum Expr {
Call(Call),
New(BoxExpr),
Static(BoxExpr),
Peek(BoxExpr),
Poke(BoxExpr, BoxExpr),
Subscript(BoxExpr, BoxExpr),
Infix(BoxExpr, Operator, BoxExpr),
String(String),
+1 -1
View File
@@ -49,7 +49,7 @@ pub fn eval_const(expr: Expr, scope: &Scope) -> Result<i32, CompileError> {
0,
String::from("Addresses are not known at compile time"),
)),
Expr::Call(_) | Expr::Subscript(_, _) | Expr::New(_) => Err(CompileError(
Expr::Call(_) | Expr::Subscript(_, _) | Expr::New(_) | Expr::Peek(_) | Expr::Poke(_, _) => Err(CompileError(
0,
0,
String::from("Constants must be statically defined"),
+33 -1
View File
@@ -90,10 +90,25 @@ impl Compilable for Expr {
size_expr.0.process(state, Some(sig), loc)?;
compile_alloc(&mut sig);
Ok(())
},
}
Expr::Static(size_expr) => {
compile_static(size_expr, state, sig)
}
Expr::Peek(addr) => {
addr.0.process(state, Some(sig), loc)?;
sig.emit("load");
Ok(())
}
Expr::Poke(addr, val) => {
// To avoid confusion, we'll evaluate the args in this order and swap
addr.0.process(state, Some(sig), loc)?;
val.0.process(state, Some(sig), loc)?;
// This is an expr, so, we have to evaluate to something. So let's evaluate to the value poked.
// To that end, we'll grab the addr from the stack
sig.emit("pick 1");
sig.emit("store"); // The store consumes the new copy of the addr and the value, leaving the value
Ok(())
}
Expr::Subscript(array, index) => {
array.0.process(state, Some(sig), loc)?;
index.0.process(state, Some(sig), loc)?;
@@ -304,4 +319,21 @@ mod test {
].join("\n")
)
}
#[test]
fn test_peekpoke() {
assert_eq!(
test_body(state_for("fn test() { peek(10); poke(20, 30); }")),
vec![
"push 10",
"load",
"pop",
"push 20",
"push 30",
"pick 1",
"store",
"pop"
].join("\n")
)
}
}
@@ -20,6 +20,8 @@ impl Compilable for Lvalue {
Expr::Call(_) |
Expr::New(_) |
Expr::Static(_) |
Expr::Peek(_) |
Expr::Poke(_, _) |
Expr::Infix(_, _, _) |
Expr::String(_) => {
Err(CompileError(0, 0, String::from("Not a valid lvalue")))
+17
View File
@@ -20,6 +20,13 @@ impl AstNode for Expr {
PestRule::number => Expr::Number(term.into_number()),
PestRule::alloc => Expr::New(Expr::from_pair(term.first()).into()),
PestRule::static_alloc => Expr::Static(Expr::from_pair(term.first()).into()),
PestRule::peek_expr => Expr::Peek(Expr::from_pair(term.first()).into()),
PestRule::poke_expr => {
let mut it = term.into_inner();
let first = it.next().unwrap();
let second = it.next().unwrap();
Expr::Poke(Expr::from_pair(first).into(), Expr::from_pair(second).into())
},
PestRule::name => Expr::Name(String::from(term.as_str())),
PestRule::expr => Expr::from_pair(term),
PestRule::string => Self::String(term.into_quoted_string()),
@@ -281,4 +288,14 @@ mod test {
fn static_alloc() {
assert_eq!(Expr::from_str("static(8)"), Ok(Expr::Static(8.into())));
}
#[test]
fn peek() {
assert_eq!(Expr::from_str("peek(8)"), Ok(Expr::Peek(8.into())));
}
#[test]
fn poke() {
assert_eq!(Expr::from_str("poke(10, 20)"), Ok(Expr::Poke(10.into(), 20.into())));
}
}
+3 -1
View File
@@ -63,9 +63,11 @@ operator = _{
}
expr = { prefix* ~ term ~ suffix* ~ (operator ~ prefix* ~ term ~ suffix*)* }
term = _{ number | alloc | static_alloc | name | "(" ~ expr ~ ")" | string }
term = _{ number | alloc | static_alloc | peek_expr | poke_expr | name | "(" ~ expr ~ ")" | string }
alloc = { "new" ~ "(" ~ expr ~ ")" }
static_alloc = { "static" ~ "(" ~ expr ~ ")" }
peek_expr = { "peek" ~ "(" ~ expr ~ ")" }
poke_expr = { "poke" ~ "(" ~ expr ~ "," ~ expr ~ ")" }
suffix = _{ subscript | arglist }
subscript = { "[" ~ expr ~ "]" }