notes and comments
This commit is contained in:
parent
ef0ac40dbe
commit
40d4f48878
|
@ -229,3 +229,11 @@ struct StackFrame<'a> {
|
|||
|
||||
This gives us a way to access everything we need: where to return to, the root of the stack, the chunk (function->chunk), the closures (function->closures).
|
||||
|
||||
### 2024-12-26
|
||||
One particular concern here, which needs some work: recursion is challenging.
|
||||
|
||||
In particular, the issue is that if, as I have been planning, a function closes over all its values at the moment it is compiled, the only value type that requires updating is a function. A function can be declared but not yet defined, and then when another function that uses that function is defined, the closed-over value will be to the declaration but not the definition.
|
||||
|
||||
One way to handle this, I think is using `std::cell::OnceCell`. Rather than a `RefCell`, `OnceCell` has no runtime overhead. Instead, what happens is you effectively put a `None` in the cell. Then, once you have the value you want to put in there, you call `set` on the `OnceCell`, and it does what it needs to.
|
||||
|
||||
This allows for the closures to be closed over right after compilation.
|
||||
|
|
|
@ -4,6 +4,7 @@ use crate::value::*;
|
|||
use chumsky::prelude::SimpleSpan;
|
||||
use num_derive::{FromPrimitive, ToPrimitive};
|
||||
use num_traits::FromPrimitive;
|
||||
use std::cell::OnceCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
|
||||
|
@ -434,23 +435,35 @@ impl Chunk {
|
|||
}
|
||||
}
|
||||
Fn(name, body, doc) => {
|
||||
// first, declare the function
|
||||
// TODO: or, check if the function has already been declared!
|
||||
let init_val = Value::Fn(Rc::new(OnceCell::new()));
|
||||
self.emit_constant(init_val);
|
||||
self.bind(name);
|
||||
|
||||
// compile the function
|
||||
let mut chunk = Chunk::new(body, self.name, self.src);
|
||||
chunk.compile();
|
||||
if crate::DEBUG_COMPILE {
|
||||
println!("==function: {name}==");
|
||||
chunk.disassemble();
|
||||
}
|
||||
|
||||
let lfn = crate::value::LFn {
|
||||
name,
|
||||
doc: *doc,
|
||||
chunk,
|
||||
closed: vec![],
|
||||
};
|
||||
let fn_val = Value::Fn(Rc::new(lfn));
|
||||
self.emit_constant(fn_val);
|
||||
self.bind(name);
|
||||
|
||||
// TODO: close over everything accessed in the function
|
||||
|
||||
// TODO: pull the function off the stack, and set the OnceCell.
|
||||
}
|
||||
FnDeclaration(name) => {
|
||||
todo!()
|
||||
let lfn = Value::Fn(Rc::new(OnceCell::new()));
|
||||
self.emit_constant(lfn);
|
||||
self.bind(name);
|
||||
}
|
||||
FnBody(clauses) => {
|
||||
self.emit_op(Op::ResetMatch);
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::compiler::Chunk;
|
|||
use crate::parser::Ast;
|
||||
use crate::spans::Spanned;
|
||||
use imbl::{HashMap, Vector};
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{OnceCell, RefCell};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
@ -37,7 +37,7 @@ pub enum Value {
|
|||
List(Box<Vector<Value>>),
|
||||
Dict(Box<HashMap<usize, Value>>),
|
||||
Box(Rc<RefCell<Value>>),
|
||||
Fn(Rc<LFn>),
|
||||
Fn(Rc<OnceCell<LFn>>),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Value {
|
||||
|
|
Loading…
Reference in New Issue
Block a user