Update how scope rules work, and update implementation
* Currently, scopes are only allowed to look at their locals and the
globals. Inner functions cannot refer to values in their parent
functions. This will change eventually.
* Scope lookup is split between globals and locals. Locals are defined
in a scope if they are explicitly assigned to.
* i.e. `a = foo` will treat `a` as a local in the current scope if
it appears anywhere in that scope. This does not extend to
setattrs; `a.b = foo` will not trigger `a` into being a local var.
* `Package` objects are no longer returned from the compiler - instead,
a user function is returned.
* Other various changes and renames
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
use crate::{obj::{reserved::*, prelude::*}, vm::{inst::Inst, signal::*, Vm}};
|
||||
use crate::{obj::{reserved::*, prelude::*}, vm::{consts::ConstPool, inst::Inst, signal::*, Vm}};
|
||||
use once_cell::sync::Lazy;
|
||||
use shredder::{GcSafeWrapper, Scan};
|
||||
use std::fmt::{Debug, Formatter, self};
|
||||
use std::{fmt::{Debug, Formatter, self}, io::{self, Write}};
|
||||
|
||||
pub type FunLocals = Vec<Sym>;
|
||||
|
||||
//
|
||||
// struct UserFun
|
||||
@@ -18,11 +20,11 @@ pub struct UserFun {
|
||||
code: Vec<Inst>,
|
||||
// Safe because this is just an interner that points to symbols, which aren't GC'd
|
||||
#[shredder(unsafe_skip)]
|
||||
locals: Locals,
|
||||
locals: FunLocals,
|
||||
}
|
||||
|
||||
impl UserFun {
|
||||
pub fn new_obj(code: Vec<Inst>, locals: Locals) -> UserFunRef {
|
||||
pub fn new_obj(code: Vec<Inst>, locals: FunLocals) -> UserFunRef {
|
||||
let obj_ref = ObjRef::new(UserFun {
|
||||
vtable: Default::default(), // this is a placeholder for the real vtable
|
||||
attrs: Default::default(),
|
||||
@@ -47,9 +49,88 @@ impl UserFun {
|
||||
&self.code
|
||||
}
|
||||
|
||||
pub fn locals(&self) -> &Locals {
|
||||
pub fn locals(&self) -> &FunLocals {
|
||||
&self.locals
|
||||
}
|
||||
|
||||
pub fn dump(&self, writer: &mut dyn Write, const_pool: &ConstPool, globals: &FunLocals) -> io::Result<()> {
|
||||
fn num_digits(n: usize, radix: usize) -> usize {
|
||||
((n as f64) + 1.0).log(radix as f64).ceil() as usize
|
||||
}
|
||||
|
||||
// column widths
|
||||
let addr_w = num_digits(self.code().len(), 16).max(4);
|
||||
let inst_col = 16 - addr_w;
|
||||
let inst_w = 16;
|
||||
|
||||
for (addr, inst) in self.code().iter().enumerate() {
|
||||
let (param_val, mut param_name) = match inst {
|
||||
Inst::PushSym(sym) | Inst::GetAttr(sym) | Inst::SetAttr(sym) => (
|
||||
sym.index().to_string(),
|
||||
global_sym_lookup(*sym).unwrap().to_string(),
|
||||
),
|
||||
Inst::PushConst(hdl) => (
|
||||
hdl.index().to_string(),
|
||||
{
|
||||
let obj_ref = const_pool.get(*hdl);
|
||||
read_obj!(let obj = obj_ref);
|
||||
format!("{:?}", obj)
|
||||
},
|
||||
),
|
||||
Inst::LoadLocal(local) => (
|
||||
local.index().to_string(),
|
||||
global_sym_lookup(self.locals()[local.index()]).unwrap().to_string(),
|
||||
),
|
||||
Inst::PopLocal(local) => {
|
||||
if let Some(local) = local {
|
||||
let index = local.index();
|
||||
let sym = self.locals()[index];
|
||||
let name = global_sym_lookup(sym).unwrap().to_string();
|
||||
(index.to_string(), name)
|
||||
} else {
|
||||
("(discarded)".to_string(), String::new())
|
||||
}
|
||||
}
|
||||
Inst::PopGlobal(global) => {
|
||||
if let Some(global) = global{
|
||||
let index = global.index();
|
||||
let sym = globals[index];
|
||||
let name = global_sym_lookup(sym).unwrap().to_string();
|
||||
(index.to_string(), name)
|
||||
} else {
|
||||
("(discarded)".to_string(), String::new())
|
||||
}
|
||||
}
|
||||
Inst::Jump(addr) | Inst::JumpTrue(addr) => (
|
||||
addr.to_string(),
|
||||
String::new(),
|
||||
),
|
||||
Inst::Call(argc) => (
|
||||
argc.to_string(),
|
||||
String::new(),
|
||||
),
|
||||
_ => (String::new(), String::new()),
|
||||
};
|
||||
|
||||
if !param_name.is_empty() {
|
||||
param_name = format!("({})", param_name);
|
||||
}
|
||||
|
||||
writeln!(
|
||||
writer,
|
||||
"{:0addr_w$x}{space: >inst_col$}{: <inst_w$}{: <4} {}",
|
||||
addr,
|
||||
inst.name(),
|
||||
param_val,
|
||||
param_name,
|
||||
space = "",
|
||||
addr_w = addr_w,
|
||||
inst_w = inst_w,
|
||||
inst_col = inst_col,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl_obj!(UserFun);
|
||||
|
||||
Reference in New Issue
Block a user