notes and comments

This commit is contained in:
Scott Richmond 2024-12-26 18:41:54 -05:00
parent ef0ac40dbe
commit 40d4f48878
3 changed files with 27 additions and 6 deletions

View File

@ -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). 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.

View File

@ -4,6 +4,7 @@ use crate::value::*;
use chumsky::prelude::SimpleSpan; use chumsky::prelude::SimpleSpan;
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use std::cell::OnceCell;
use std::rc::Rc; use std::rc::Rc;
#[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)] #[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive, ToPrimitive)]
@ -434,23 +435,35 @@ impl Chunk {
} }
} }
Fn(name, body, doc) => { 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); let mut chunk = Chunk::new(body, self.name, self.src);
chunk.compile(); chunk.compile();
if crate::DEBUG_COMPILE { if crate::DEBUG_COMPILE {
println!("==function: {name}=="); println!("==function: {name}==");
chunk.disassemble(); chunk.disassemble();
} }
let lfn = crate::value::LFn { let lfn = crate::value::LFn {
name, name,
doc: *doc, doc: *doc,
chunk, chunk,
closed: vec![],
}; };
let fn_val = Value::Fn(Rc::new(lfn));
self.emit_constant(fn_val); // TODO: close over everything accessed in the function
self.bind(name);
// TODO: pull the function off the stack, and set the OnceCell.
} }
FnDeclaration(name) => { FnDeclaration(name) => {
todo!() let lfn = Value::Fn(Rc::new(OnceCell::new()));
self.emit_constant(lfn);
self.bind(name);
} }
FnBody(clauses) => { FnBody(clauses) => {
self.emit_op(Op::ResetMatch); self.emit_op(Op::ResetMatch);

View File

@ -2,7 +2,7 @@ use crate::compiler::Chunk;
use crate::parser::Ast; use crate::parser::Ast;
use crate::spans::Spanned; use crate::spans::Spanned;
use imbl::{HashMap, Vector}; use imbl::{HashMap, Vector};
use std::cell::RefCell; use std::cell::{OnceCell, RefCell};
use std::rc::Rc; use std::rc::Rc;
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
@ -37,7 +37,7 @@ pub enum Value {
List(Box<Vector<Value>>), List(Box<Vector<Value>>),
Dict(Box<HashMap<usize, Value>>), Dict(Box<HashMap<usize, Value>>),
Box(Rc<RefCell<Value>>), Box(Rc<RefCell<Value>>),
Fn(Rc<LFn>), Fn(Rc<OnceCell<LFn>>),
} }
impl std::fmt::Display for Value { impl std::fmt::Display for Value {