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:
@@ -1,3 +1,4 @@
|
|||||||
println(123);
|
println(123);
|
||||||
println(None);
|
println(None);
|
||||||
println("hell world");
|
message = "hell world";
|
||||||
|
println(message);
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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>;
|
||||||
|
|||||||
9097
src/syn/parser.rs
9097
src/syn/parser.rs
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user