Finish up function call implementation, it appears to be working
Functions are downcasted to a `Fun` trait, which will construct the appropriate stack frame. A few other things have been shifted around that affect internal APIs while things are still under construction. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -23,10 +23,14 @@ impl Compile {
|
||||
/// Compiles the given AST body.
|
||||
pub fn compile(mut self, body: &Body) -> error::Result<(ConstPool, UserFunRef)> {
|
||||
self.push_scope_layer();
|
||||
let main = thunk::CompileBody::new(&mut self)
|
||||
let mut main = thunk::CompileBody::new(&mut self)
|
||||
.compile(body)?
|
||||
.flatten()
|
||||
.to_vec();
|
||||
// XXX TODO(compile)
|
||||
// remove this when we get returns implemented
|
||||
main.push(crate::vm::inst::Inst::PushSym(crate::obj::reserved::NIL_NAME.sym));
|
||||
main.push(crate::vm::inst::Inst::Return);
|
||||
let globals_syms: std::collections::BTreeMap<_, _> = self.pop_scope_layer().unwrap()
|
||||
.into_iter()
|
||||
.map(|(sym, name)| (name, sym))
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
use crate::obj::prelude::*;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
// current TODO/problem: How should locals work?
|
||||
//
|
||||
// * I think we should have a global/local dichotomy in the VM. You can only look up the local
|
||||
// scope in the VM; inner functions that have captures should be created on the fly and detected
|
||||
// by the compiler. I.E. any lookups that are not local or global should be captured dynamically.
|
||||
// * Need to differentiate between locals collected on the compilation side vs. locals on the
|
||||
// object/vm side
|
||||
|
||||
pub type ScopeLocalSyms = BTreeMap<Sym, Name>;
|
||||
pub type ScopeLocals = Vec<Sym>;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Scope {
|
||||
scope: Vec<ScopeLocalSyms>,
|
||||
}
|
||||
@@ -77,10 +70,3 @@ impl Scope {
|
||||
self.scope.first_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Scope {
|
||||
fn default() -> Self {
|
||||
// empty global scope
|
||||
Self { scope: vec![Default::default()] }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -382,9 +382,13 @@ impl Visit for CompileBody<'_> {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let code = self.visit_body(&expr.body)?
|
||||
let mut code = self.visit_body(&expr.body)?
|
||||
.flatten()
|
||||
.to_vec();
|
||||
// XXX TODO(compile)
|
||||
// remove this when we get returns implemented
|
||||
code.push(Inst::PushSym(crate::obj::reserved::NIL_NAME.sym));
|
||||
code.push(Inst::Return);
|
||||
let (hdl, _fun) = self.compile.push_const(UserFun::new_obj(code, locals));
|
||||
|
||||
// TODO(compile) : determine return value at the end of the body (preferably at parse-time)
|
||||
@@ -397,6 +401,7 @@ impl Visit for CompileBody<'_> {
|
||||
let thunk = match atom {
|
||||
Atom::Ident(ident) => {
|
||||
let sym = global_sym(ident.to_string());
|
||||
// TODO : use "LOAD_GLOBAL" instead of "LOAD_LOCAL" when inside a user function
|
||||
if let Some(local) = self.compile.lookup_local(sym) {
|
||||
// get local
|
||||
Inst::LoadLocal(local).into()
|
||||
|
||||
Reference in New Issue
Block a user