Added peek and poke
This commit is contained in:
@@ -174,6 +174,8 @@ pub enum Expr {
|
|||||||
Call(Call),
|
Call(Call),
|
||||||
New(BoxExpr),
|
New(BoxExpr),
|
||||||
Static(BoxExpr),
|
Static(BoxExpr),
|
||||||
|
Peek(BoxExpr),
|
||||||
|
Poke(BoxExpr, BoxExpr),
|
||||||
Subscript(BoxExpr, BoxExpr),
|
Subscript(BoxExpr, BoxExpr),
|
||||||
Infix(BoxExpr, Operator, BoxExpr),
|
Infix(BoxExpr, Operator, BoxExpr),
|
||||||
String(String),
|
String(String),
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ pub fn eval_const(expr: Expr, scope: &Scope) -> Result<i32, CompileError> {
|
|||||||
0,
|
0,
|
||||||
String::from("Addresses are not known at compile time"),
|
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,
|
||||||
0,
|
0,
|
||||||
String::from("Constants must be statically defined"),
|
String::from("Constants must be statically defined"),
|
||||||
|
|||||||
@@ -90,10 +90,25 @@ impl Compilable for Expr {
|
|||||||
size_expr.0.process(state, Some(sig), loc)?;
|
size_expr.0.process(state, Some(sig), loc)?;
|
||||||
compile_alloc(&mut sig);
|
compile_alloc(&mut sig);
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
}
|
||||||
Expr::Static(size_expr) => {
|
Expr::Static(size_expr) => {
|
||||||
compile_static(size_expr, state, sig)
|
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) => {
|
Expr::Subscript(array, index) => {
|
||||||
array.0.process(state, Some(sig), loc)?;
|
array.0.process(state, Some(sig), loc)?;
|
||||||
index.0.process(state, Some(sig), loc)?;
|
index.0.process(state, Some(sig), loc)?;
|
||||||
@@ -304,4 +319,21 @@ mod test {
|
|||||||
].join("\n")
|
].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::Call(_) |
|
||||||
Expr::New(_) |
|
Expr::New(_) |
|
||||||
Expr::Static(_) |
|
Expr::Static(_) |
|
||||||
|
Expr::Peek(_) |
|
||||||
|
Expr::Poke(_, _) |
|
||||||
Expr::Infix(_, _, _) |
|
Expr::Infix(_, _, _) |
|
||||||
Expr::String(_) => {
|
Expr::String(_) => {
|
||||||
Err(CompileError(0, 0, String::from("Not a valid lvalue")))
|
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::number => Expr::Number(term.into_number()),
|
||||||
PestRule::alloc => Expr::New(Expr::from_pair(term.first()).into()),
|
PestRule::alloc => Expr::New(Expr::from_pair(term.first()).into()),
|
||||||
PestRule::static_alloc => Expr::Static(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::name => Expr::Name(String::from(term.as_str())),
|
||||||
PestRule::expr => Expr::from_pair(term),
|
PestRule::expr => Expr::from_pair(term),
|
||||||
PestRule::string => Self::String(term.into_quoted_string()),
|
PestRule::string => Self::String(term.into_quoted_string()),
|
||||||
@@ -281,4 +288,14 @@ mod test {
|
|||||||
fn static_alloc() {
|
fn static_alloc() {
|
||||||
assert_eq!(Expr::from_str("static(8)"), Ok(Expr::Static(8.into())));
|
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*)* }
|
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 ~ ")" }
|
alloc = { "new" ~ "(" ~ expr ~ ")" }
|
||||||
static_alloc = { "static" ~ "(" ~ expr ~ ")" }
|
static_alloc = { "static" ~ "(" ~ expr ~ ")" }
|
||||||
|
peek_expr = { "peek" ~ "(" ~ expr ~ ")" }
|
||||||
|
poke_expr = { "poke" ~ "(" ~ expr ~ "," ~ expr ~ ")" }
|
||||||
|
|
||||||
suffix = _{ subscript | arglist }
|
suffix = _{ subscript | arglist }
|
||||||
subscript = { "[" ~ expr ~ "]" }
|
subscript = { "[" ~ expr ~ "]" }
|
||||||
|
|||||||
Reference in New Issue
Block a user