diff --git a/src/compile/locals.rs b/src/compile/locals.rs index 406daa3..d7ef3a9 100644 --- a/src/compile/locals.rs +++ b/src/compile/locals.rs @@ -9,7 +9,7 @@ pub struct CollectLocals<'c> { } // - Python's LEGB methodology seems to be good. Look up variables in this order: -// - Local +// - Name // - Enclosing functions (i.e. inner functions) // - Global // - Builtin @@ -35,7 +35,7 @@ impl Visit for CollectLocals<'_> { fn visit_assign_stmt(&mut self, assign: &AssignStmt) -> Self::Out { DefaultAccept::default_accept(assign, self); } fn visit_lhs_expr(&mut self, lhs_expr: &LhsExpr) -> Self::Out { match lhs_expr { - LhsExpr::Local(name) => { + LhsExpr::Name(name) => { let sym = global_sym(name.to_string()); self.compile.create_local(sym); } diff --git a/src/compile/mod.rs b/src/compile/mod.rs index 22007e0..4a17346 100644 --- a/src/compile/mod.rs +++ b/src/compile/mod.rs @@ -9,10 +9,10 @@ use std::collections::{BTreeMap, HashMap}; #[derive(Default)] pub struct Compile { const_data: ConstData, - globals: BTreeMap, - locals: Vec>, + globals: BTreeMap, + scope: Vec>, names: Vec, - next_local: Local, + next_local: Name, } impl Compile { @@ -54,8 +54,8 @@ impl Compile { /// /// This will search up the locals stack until the given name is found, ultimately ending with /// a global name lookup. - pub fn lookup_scope(&mut self, sym: Sym) -> Option { - self.locals + pub fn lookup_scope(&mut self, sym: Sym) -> Option { + self.scope .iter() .rev() .filter_map(|locals| locals.get(&sym)) @@ -65,7 +65,7 @@ impl Compile { } /// Looks up a variable name, or creates a global name if it doesn't exist. - pub fn lookup_scope_or_create_global(&mut self, sym: Sym) -> Local { + pub fn lookup_scope_or_create_global(&mut self, sym: Sym) -> Name { if let Some(local) = self.lookup_scope(sym) { local } else { @@ -74,8 +74,8 @@ impl Compile { } /// Creates a new local variable if it does not exist in the current local scope. - pub(crate) fn create_local(&mut self, sym: Sym) -> Local { - let locals = self.locals.last_mut().expect("scope"); + pub(crate) fn create_local(&mut self, sym: Sym) -> Name { + let locals = self.scope.last_mut().expect("scope"); if let Some(local) = locals.get(&sym) { *local } else { @@ -90,7 +90,7 @@ impl Compile { } /// Creates a new global variable if it does not exist in the current global scope. - pub fn create_global(&mut self, sym: Sym) -> Local { + pub fn create_global(&mut self, sym: Sym) -> Name { if let Some(global) = self.globals.get(&sym) { *global } else { @@ -105,12 +105,12 @@ impl Compile { /// Pushes an empty scope layer of local variables. pub(crate) fn push_scope_layer(&mut self) { - self.locals.push(Default::default()); + self.scope.push(Default::default()); } /// Pops a scope layer of local variables, if any are available. - pub(crate) fn pop_scope_layer(&mut self) -> Option> { - self.locals.pop() + pub(crate) fn pop_scope_layer(&mut self) -> Option> { + self.scope.pop() } /// Collects local variables for the given AST body non-recursively. diff --git a/src/compile/thunk.rs b/src/compile/thunk.rs index 367bbbd..f76d6d2 100644 --- a/src/compile/thunk.rs +++ b/src/compile/thunk.rs @@ -264,7 +264,7 @@ impl Visit for CompileBody<'_> { let attr = global_sym(expr.access.to_string()); thunk.push(Inst::SetAttr(attr)); } - LhsExpr::Local(local_name) => { + LhsExpr::Name(local_name) => { let sym = global_sym(local_name.to_string()); let local = self.compile.lookup_scope_or_create_global(sym); thunk = Inst::Pop(Some(local)).into(); @@ -349,9 +349,9 @@ impl Visit for CompileBody<'_> { let thunk = match atom { Atom::Ident(ident) => { let sym = global_sym(ident.to_string()); - let local = self.compile.lookup_scope_or_create_global(sym); + let name = self.compile.lookup_scope_or_create_global(sym); // get local - Inst::PushLocal(local).into() + Inst::LoadName(name).into() } Atom::Sym(sym) => { // push symbol diff --git a/src/obj/fun.rs b/src/obj/fun.rs index 04da11d..dabb8cd 100644 --- a/src/obj/fun.rs +++ b/src/obj/fun.rs @@ -1,4 +1,4 @@ -use crate::{obj::{names::*, prelude::*}, vm::{inst::Inst, Vm}}; +use crate::{obj::{reserved::*, prelude::*}, vm::{inst::Inst, Vm}}; use once_cell::sync::Lazy; use shredder::{GcSafeWrapper, Scan}; use std::fmt::{Debug, Formatter, self}; @@ -44,7 +44,7 @@ pub struct UserFun { code: Vec, // Safe because this is just an interner that points to symbols, which aren't GC'd #[shredder(unsafe_skip)] - locals: Locals, + locals: Names, } impl UserFun { @@ -52,7 +52,7 @@ impl UserFun { &self.code } - pub fn locals(&self) -> &Locals { + pub fn locals(&self) -> &Names { &self.locals } } diff --git a/src/obj/locals.rs b/src/obj/locals.rs deleted file mode 100644 index 5d4a42e..0000000 --- a/src/obj/locals.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::obj::ObjRef; -use std::collections::BTreeMap; - -handle_type!(Local); - -pub type Locals = BTreeMap; diff --git a/src/obj/mod.rs b/src/obj/mod.rs index 2af87d0..3405cd3 100644 --- a/src/obj/mod.rs +++ b/src/obj/mod.rs @@ -5,15 +5,15 @@ pub mod attrs; pub mod fun; pub mod int; pub mod intern; -pub mod locals; pub mod names; +pub mod reserved; pub mod str; pub mod sym; pub mod ty; pub mod prelude { pub use crate::obj::{ - attrs::*, fun::*, int::*, intern::*, locals::*, str::*, sym::*, ty::*, Obj, ObjRef, + attrs::*, fun::*, int::*, intern::*, names::*, str::*, sym::*, ty::*, Obj, ObjRef, }; } diff --git a/src/obj/names.rs b/src/obj/names.rs index bcb931c..596ee18 100644 --- a/src/obj/names.rs +++ b/src/obj/names.rs @@ -1,71 +1,6 @@ -use crate::obj::sym::{Sym, SymRef, global_sym, global_sym_ref}; -use once_cell::sync::Lazy; +use crate::obj::ObjRef; +use std::collections::BTreeMap; -macro_rules! name { - ($name:ident, $text:expr $(,)?) => { - pub static $name: Lazy = Lazy::new(|| { - let name = $text; - let sym = global_sym(name.to_string()); - NameInfo { name, sym, } - }); - } -} +handle_type!(Name); -pub struct NameInfo { - pub name: &'static str, - pub sym: Sym, -} - -impl NameInfo { - pub fn sym_ref(&self) -> SymRef { - global_sym_ref(self.sym) - } -} - -// -// Types -// -name!(INT_NAME, "Int"); -name!(TY_NAME, "Type"); -name!(SYM_NAME, "Sym"); - -// -// Members -// -name!(TY_MEMBER_NAME, "__type__"); -name!(CALL_MEMBER_NAME, "__call__"); -name!(NAME_MEMBER_NAME, "__name__"); -name!(GET_ATTR_MEMBER_NAME, "__get_attr__"); -name!(SET_ATTR_MEMBER_NAME, "__set_attr__"); -name!(SELF_MEMBER_NAME, "__self__"); -name!(FUNC_MEMBER_NAME, "__func__"); - -// -// Predefined VM-aware symbols -// -name!(SCOPE_NAME, "__scope__"); - -// -// Builtin functions -// -//name!(REPR_FUN_NAME, REPR_FUN_SYM, "repr"); -//name!(GET_LOCAL_FUN_NAME, GET_LOCAL_FUN_SYM, "get_local"); -//name!(SET_LOCAL_FUN_NAME, SET_LOCAL_FUN_SYM, "set_local"); - -// -// Builtin constants -// -name!(TRUE_NAME, "true"); -name!(FALSE_NAME, "false"); -name!(NIL_NAME, "nil"); - -// Operator function names -name!(EQ_EQ_OP_NAME, "__eq__"); -name!(LT_OP_NAME, "__lt__"); -name!(GT_OP_NAME, "__gt__"); -name!(LT_EQ_OP_NAME, "__le__"); -name!(GT_EQ_OP_NAME, "__ge__"); -name!(PLUS_OP_NAME, "__add__"); -name!(MINUS_OP_NAME, "__sub__"); -name!(TIMES_OP_NAME, "__mul__"); -name!(DIV_OP_NAME, "__div__"); +pub type Names = BTreeMap; diff --git a/src/obj/reserved.rs b/src/obj/reserved.rs new file mode 100644 index 0000000..56e1cae --- /dev/null +++ b/src/obj/reserved.rs @@ -0,0 +1,74 @@ +//! Reserved names for object members. + +use crate::obj::sym::{Sym, SymRef, global_sym, global_sym_ref}; +use once_cell::sync::Lazy; + +macro_rules! name { + ($name:ident, $text:expr $(,)?) => { + pub static $name: Lazy = Lazy::new(|| { + let name = $text; + let sym = global_sym(name.to_string()); + NameInfo { name, sym, } + }); + } +} + +pub struct NameInfo { + pub name: &'static str, + pub sym: Sym, +} + +impl NameInfo { + pub fn sym_ref(&self) -> SymRef { + global_sym_ref(self.sym) + } +} + +// +// Types +// +name!(INT_NAME, "Int"); +name!(TY_NAME, "Type"); +name!(SYM_NAME, "Sym"); + +// +// Members +// +name!(TY_MEMBER_NAME, "__type__"); +name!(CALL_MEMBER_NAME, "__call__"); +name!(NAME_MEMBER_NAME, "__name__"); +name!(GET_ATTR_MEMBER_NAME, "__get_attr__"); +name!(SET_ATTR_MEMBER_NAME, "__set_attr__"); +name!(SELF_MEMBER_NAME, "__self__"); +name!(FUNC_MEMBER_NAME, "__func__"); + +// +// Predefined VM-aware symbols +// +name!(SCOPE_NAME, "__scope__"); + +// +// Builtin functions +// +//name!(REPR_FUN_NAME, REPR_FUN_SYM, "repr"); +//name!(GET_LOCAL_FUN_NAME, GET_LOCAL_FUN_SYM, "get_local"); +//name!(SET_LOCAL_FUN_NAME, SET_LOCAL_FUN_SYM, "set_local"); + +// +// Builtin constants +// +name!(TRUE_NAME, "true"); +name!(FALSE_NAME, "false"); +name!(NIL_NAME, "nil"); + +// Operator function names +name!(EQ_EQ_OP_NAME, "__eq__"); +name!(LT_OP_NAME, "__lt__"); +name!(GT_OP_NAME, "__gt__"); +name!(LT_EQ_OP_NAME, "__le__"); +name!(GT_EQ_OP_NAME, "__ge__"); +name!(PLUS_OP_NAME, "__add__"); +name!(MINUS_OP_NAME, "__sub__"); +name!(TIMES_OP_NAME, "__mul__"); +name!(DIV_OP_NAME, "__div__"); + diff --git a/src/obj/sym.rs b/src/obj/sym.rs index 7c63187..44b3e9f 100644 --- a/src/obj/sym.rs +++ b/src/obj/sym.rs @@ -1,4 +1,4 @@ -use crate::obj::{intern::Interner, names::*, prelude::*}; +use crate::obj::{intern::Interner, reserved::*, prelude::*}; use once_cell::sync::Lazy; use std::{collections::BTreeMap, sync::{Arc, Mutex}}; diff --git a/src/obj/ty.rs b/src/obj/ty.rs index 224e604..d9c5976 100644 --- a/src/obj/ty.rs +++ b/src/obj/ty.rs @@ -1,4 +1,4 @@ -use crate::obj::{names::*, prelude::*}; +use crate::obj::{reserved::*, prelude::*}; use once_cell::sync::Lazy; use shredder::Scan; diff --git a/src/syn/ast.rs b/src/syn/ast.rs index 6cd90a0..04a1b06 100644 --- a/src/syn/ast.rs +++ b/src/syn/ast.rs @@ -75,7 +75,7 @@ impl> DefaultAccept for AssignStmt { #[derive(Debug, Clone, PartialEq, Eq)] pub enum LhsExpr { SetAttr(AccessExpr), - Local(String), + Name(String), } // @@ -94,7 +94,7 @@ impl> DefaultAccept for LhsExpr { fn default_accept(&self, visitor: &mut V) -> V::Out { match self { LhsExpr::SetAttr(a) => a.accept(visitor), - LhsExpr::Local(_) => {}, + LhsExpr::Name(_) => {}, } } } diff --git a/src/vm/frame.rs b/src/vm/frame.rs index 99a22a5..52b5218 100644 --- a/src/vm/frame.rs +++ b/src/vm/frame.rs @@ -26,20 +26,20 @@ unsafe impl GcSafe for FrameKind {} #[derive(Scan, Debug, Clone)] pub struct Frame { - locals: Locals, + locals: Names, kind: FrameKind, } impl Frame { - pub fn new(locals: Locals, kind: FrameKind) -> Self { + pub fn new(locals: Names, kind: FrameKind) -> Self { Self { locals, kind, } } - pub fn locals(&self) -> &Locals { + pub fn locals(&self) -> &Names { &self.locals } - pub fn locals_mut(&mut self) -> &mut Locals { + pub fn locals_mut(&mut self) -> &mut Names { &mut self.locals } diff --git a/src/vm/inst.rs b/src/vm/inst.rs index 343f38f..e6b3116 100644 --- a/src/vm/inst.rs +++ b/src/vm/inst.rs @@ -10,10 +10,10 @@ pub enum Inst { PushConst(ConstHandle), /// Looks up and pushes a local value. - PushLocal(Local), + LoadName(Name), /// Pop a value from the stack, possibly into a local symbol. - Pop(Option), + Pop(Option), /// Pops a symbol value and an object reference. /// @@ -119,7 +119,7 @@ impl Inst { match self { Inst::PushSym(_) => "PUSH_SYM", Inst::PushConst(_) => "PUSH_CONST", - Inst::PushLocal(_) => "PUSH_LOCAL", + Inst::LoadName(_) => "LOAD_NAME", Inst::Pop(_) => "POP", Inst::GetAttr(_) => "GET_ATTR", Inst::SetAttr(_) => "SET_ATTR", @@ -189,7 +189,7 @@ impl Display for InstFormatter<'_, '_> { format!("{:?}", obj) }, ), - Inst::PushLocal(local) => ( + Inst::LoadName(local) => ( local.index().to_string(), "TODO: local name".to_string(), ), diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 961c0a9..32e1a8a 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -4,7 +4,7 @@ pub mod frame; pub mod inst; use crate::{ - obj::{names::*, prelude::*}, + obj::{reserved::*, prelude::*}, vm::{consts::*, error::*, frame::*, inst::*}, }; use shredder::{GcSafe, Scanner, Scan}; @@ -129,7 +129,7 @@ impl<'c> Vm<'c> { let obj_ref = self.const_pool.get(hdl).clone(); self.push(obj_ref); } - Inst::PushLocal(_sym) => todo!(), + Inst::LoadName(_sym) => todo!(), Inst::Pop(Some(_sym)) => todo!(), Inst::Pop(None) => todo!(), Inst::GetAttr(sym) => {