Added peek and poke
This commit is contained in:
@@ -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),
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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")))
|
||||
|
||||
@@ -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())));
|
||||
}
|
||||
}
|
||||
@@ -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 ~ "]" }
|
||||
|
||||
Reference in New Issue
Block a user