assignment: Add variable assignment

* Syntax for x = y
* Compiler creates Inst::Store thunks
* New Vm::store function

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2023-04-02 01:55:51 -07:00
parent bfe7ca33bd
commit 4d005494a3
6 changed files with 6767 additions and 2376 deletions

View File

@@ -1,3 +1,4 @@
println(123); println(123);
println(None); println(None);
println("hell world"); message = "hell world";
println(message);

View File

@@ -37,7 +37,17 @@ impl Compiler {
fn emit_stmt(&mut self, stmt: &SpStmt) -> Thunk { fn emit_stmt(&mut self, stmt: &SpStmt) -> Thunk {
match stmt.inner() { match stmt.inner() {
Stmt::Assign(_lhs_expr, _expr) => todo!(), Stmt::Assign(lhs_expr, expr) => match lhs_expr.inner() {
AssignLhs::Name(n) => {
let name = self.scope().lookup_scoped(n).unwrap();
let mut thunk = self.emit_expr(expr);
thunk.push(Inst::Store(name));
thunk
}
AssignLhs::Complex(_, _) => {
todo!("Complex LHS foo.bar assign")
}
},
Stmt::Expr(expr) => { Stmt::Expr(expr) => {
let mut thunk = self.emit_expr(expr); let mut thunk = self.emit_expr(expr);
thunk.push(Inst::Pop); thunk.push(Inst::Pop);
@@ -91,7 +101,7 @@ impl Compiler {
fn gather_names(&mut self, stmts: &Vec<SpStmt>) { fn gather_names(&mut self, stmts: &Vec<SpStmt>) {
for stmt in stmts { for stmt in stmts {
match stmt.inner() { match stmt.inner() {
Stmt::Assign(lhs, _) => match lhs { Stmt::Assign(lhs, _) => match lhs.inner() {
AssignLhs::Name(name) => { AssignLhs::Name(name) => {
self.scope_mut().insert_local(name); self.scope_mut().insert_local(name);
} }

View File

@@ -2,7 +2,7 @@ use crate::syn::Spanned;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Stmt { pub enum Stmt {
Assign(AssignLhs, Expr), Assign(SpAssignLhs, SpExpr),
Expr(SpExpr), Expr(SpExpr),
If { If {
if_true: SpCondExpr, if_true: SpCondExpr,
@@ -20,6 +20,8 @@ pub enum Stmt {
}, },
} }
pub type SpAssignLhs = Spanned<AssignLhs>;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum AssignLhs { pub enum AssignLhs {
/// A simple assignment. /// A simple assignment.

View File

@@ -22,6 +22,13 @@ pub SpStmt = Spanned<Stmt>;
pub Stmt: Stmt = { pub Stmt: Stmt = {
<SpExpr> => Stmt::Expr(<>), <SpExpr> => Stmt::Expr(<>),
<lhs:SpAssignLhs> "=" <expr:SpExpr> => Stmt::Assign(lhs, expr),
}
pub SpAssignLhs = Spanned<AssignLhs>;
pub AssignLhs: AssignLhs = {
<Name> => { AssignLhs::Name(<>) }
} }
pub SpExpr = Spanned<Expr>; pub SpExpr = Spanned<Expr>;

File diff suppressed because it is too large Load Diff

View File

@@ -91,6 +91,18 @@ impl Vm {
None None
} }
pub fn store(&mut self, name: Name, value: Option<ObjPtr>) {
for frame in self.frames_mut() {
match frame {
Frame::User(frame) => {
frame.locals_mut().insert(name, value);
return;
}
Frame::Builtin(_frame) => continue,
}
}
}
pub fn make_frame(&self, fun: ObjPtr, args: Vec<ObjPtr>) -> Option<Frame> { pub fn make_frame(&self, fun: ObjPtr, args: Vec<ObjPtr>) -> Option<Frame> {
let fun_any = fun.as_any(); let fun_any = fun.as_any();
if fun_any.is::<BuiltinFun>() { if fun_any.is::<BuiltinFun>() {
@@ -134,7 +146,11 @@ impl Vm {
todo!("Throw exception: Could not load name {name:?} (is it set?)"); todo!("Throw exception: Could not load name {name:?} (is it set?)");
} }
} }
Inst::Store(_name) => todo!(), Inst::Store(name) => {
let name = *name;
let value = self.pop_stack().expect("Stack underflow");
self.store(name, Some(value));
}
Inst::GetAttr(_attr) => todo!(), Inst::GetAttr(_attr) => todo!(),
Inst::Pop => { Inst::Pop => {
self self