closing works, so does importing from Prelude!
This commit is contained in:
parent
567d3da4be
commit
6a01089973
|
@ -1,5 +1,13 @@
|
|||
base :print! ("Hello from Prelude")
|
||||
& base :print! ("Hello from Prelude")
|
||||
|
||||
fn add (x, y) -> base :add (x, y)
|
||||
& I can't figure out why I need this, but I do
|
||||
& Otherwise the validator won't close over `base`
|
||||
let base = base
|
||||
|
||||
#{add}
|
||||
fn add (x as :number, y as :number) -> base :add (x, y)
|
||||
|
||||
fn dec (n as :number) -> base :sub (n, 1)
|
||||
|
||||
fn sub (x as :number, y as :number) -> base :sub (x, y)
|
||||
|
||||
#{add, dec, sub}
|
||||
|
|
25
src/main.rs
25
src/main.rs
|
@ -95,11 +95,12 @@ pub fn prelude<'src>() -> Process<'src> {
|
|||
let mut v6or = Validator::new(p_ast, *p_span, &base_names);
|
||||
v6or.validate();
|
||||
|
||||
// dbg!(&v6or);
|
||||
|
||||
let mut base_ctx = Process::<'src> {
|
||||
locals: vec![],
|
||||
locals: base_pkg,
|
||||
ast: p_ast,
|
||||
prelude: base_pkg,
|
||||
args: Value::Nil,
|
||||
prelude: vec![],
|
||||
fn_info: v6or.fn_info,
|
||||
};
|
||||
|
||||
|
@ -128,7 +129,6 @@ pub fn prelude<'src>() -> Process<'src> {
|
|||
locals: vec![],
|
||||
ast: &Ast::Nil,
|
||||
prelude: p_ctx,
|
||||
args: Value::Nil,
|
||||
fn_info: base_ctx.fn_info,
|
||||
}
|
||||
}
|
||||
|
@ -158,10 +158,12 @@ pub fn run(src: &'static str) {
|
|||
|
||||
v6or.validate();
|
||||
|
||||
dbg!(&v6or);
|
||||
// dbg!(&v6or);
|
||||
// dbg!(&v6or.fn_info);
|
||||
|
||||
let mut proc = prelude();
|
||||
proc.ast = *
|
||||
// dbg!(&proc.fn_info);
|
||||
proc.fn_info.extend(&mut v6or.fn_info.into_iter());
|
||||
|
||||
let result = proc.eval();
|
||||
|
@ -174,9 +176,16 @@ pub fn run(src: &'static str) {
|
|||
|
||||
pub fn main() {
|
||||
let src = "
|
||||
let bar = :bar
|
||||
fn foo () -> bar
|
||||
foo ()
|
||||
fn fib {
|
||||
(1) -> 1
|
||||
(2) -> 1
|
||||
(n) -> add (
|
||||
fib (dec (n))
|
||||
fib (sub (n, 2))
|
||||
)
|
||||
}
|
||||
|
||||
fib (25)
|
||||
";
|
||||
run(src);
|
||||
// struct_scalpel::print_dissection_info::<value::Value>()
|
||||
|
|
|
@ -35,7 +35,6 @@ pub struct Process<'src> {
|
|||
pub locals: Vec<(String, Value<'src>)>,
|
||||
pub prelude: Vec<(String, Value<'src>)>,
|
||||
pub ast: &'src Ast,
|
||||
pub args: Value<'src>,
|
||||
pub fn_info: std::collections::HashMap<*const Ast, FnInfo>,
|
||||
}
|
||||
|
||||
|
@ -502,16 +501,17 @@ impl<'src> Process<'src> {
|
|||
Fn(name, clauses, doc) => {
|
||||
let doc = doc.map(|s| s.to_string());
|
||||
let ptr: *const Ast = root;
|
||||
dbg!(&root);
|
||||
dbg!(&ptr);
|
||||
dbg!(&self.fn_info);
|
||||
// dbg!(&root);
|
||||
// dbg!(&ptr);
|
||||
// dbg!(&self.fn_info);
|
||||
let info = self.fn_info.get(&ptr).unwrap();
|
||||
let FnInfo::Defined(_, enclosing) = info else {
|
||||
let FnInfo::Defined(_, _, enclosing) = info else {
|
||||
unreachable!()
|
||||
};
|
||||
let enclosing = enclosing
|
||||
.iter()
|
||||
.map(|name| (name.clone(), self.resolve(name).unwrap().clone()))
|
||||
.filter(|binding| binding != name)
|
||||
.map(|binding| (binding.clone(), self.resolve(binding).unwrap().clone()))
|
||||
.collect();
|
||||
let the_fn = Value::Fn::<'src>(Rc::new(crate::value::Fn::<'src> {
|
||||
name: name.to_string(),
|
||||
|
|
|
@ -33,7 +33,7 @@ pub enum Arity {
|
|||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum FnInfo {
|
||||
Declared,
|
||||
Defined(HashSet<Arity>, HashSet<String>),
|
||||
Defined(String, HashSet<Arity>, HashSet<String>),
|
||||
Unknown,
|
||||
}
|
||||
|
||||
|
@ -130,7 +130,7 @@ impl<'a> Validator<'a> {
|
|||
let root = self.ast;
|
||||
match root {
|
||||
Error => unreachable!(),
|
||||
Word(name) | Ast::Splat(name) => {
|
||||
Word(name) | Splat(name) => {
|
||||
if !self.resolved(name) {
|
||||
self.err(format!("unbound name `{name}`"))
|
||||
} else {
|
||||
|
@ -309,7 +309,7 @@ impl<'a> Validator<'a> {
|
|||
|
||||
//TODO: check arities of prelude fns, too
|
||||
let fn_binding = self.bound(name);
|
||||
if let Some((_, _, FnInfo::Defined(arities, _))) = fn_binding {
|
||||
if let Some((_, _, FnInfo::Defined(_, arities, _))) = fn_binding {
|
||||
let num_args = args.len();
|
||||
if !match_arities(arities, num_args as u8) {
|
||||
self.err(format!("arity mismatch: no clause in function `{name}` with {num_args} argument(s)"))
|
||||
|
@ -453,11 +453,12 @@ impl<'a> Validator<'a> {
|
|||
let mut closed_over = HashSet::new();
|
||||
for binding in self.status.used_bindings.iter().skip(from) {
|
||||
if self.bound(binding.as_str()).is_some() {
|
||||
// println!("{name} closing over {binding}");
|
||||
closed_over.insert(binding.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let info = FnInfo::Defined(arities, closed_over);
|
||||
let info = FnInfo::Defined(name.to_string(), arities, closed_over);
|
||||
|
||||
let root_ptr: *const Ast = root;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user