[fine] WIP: Classes

This commit is contained in:
John Doty 2024-01-20 08:56:53 -08:00
parent e6c96fde38
commit 0ee89bf26b
7 changed files with 370 additions and 59 deletions

View file

@ -42,6 +42,7 @@ pub enum Instruction {
StoreModule(usize),
StringAdd,
Dup,
NewObject(usize),
}
pub enum Export {
@ -488,6 +489,7 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
Declaration::ExternFunction { .. } => Instruction::Panic,
Declaration::Function { .. } => Instruction::Panic,
Declaration::Class { .. } => Instruction::Panic,
};
c.push(instruction);
}
@ -545,6 +547,23 @@ fn compile_identifier_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> O
Instruction::LoadFunction(index)
}
Declaration::ExternFunction { id, .. } => Instruction::LoadExternFunction(id.id()),
Declaration::Class { declaration, .. } => {
let key = FunctionKey { tree: *declaration };
let index = match c.function_bindings.get(&key) {
Some(index) => *index,
None => {
let tree = &c.syntax[*declaration];
compiler_assert_eq!(c, t, tree.kind, TreeKind::ClassDecl);
compile_class_declaration(c, t, tree, false)?;
*c.function_bindings
.get(&key)
.expect("did not compile the class constructor!")
}
};
Instruction::LoadFunction(index)
}
};
c.push(instruction);
@ -705,13 +724,58 @@ fn compile_function_declaration(c: &mut Compiler, t: TreeRef, tree: &Tree, gen_v
OK
}
fn compile_class_declaration(c: &mut Compiler, t: TreeRef, tree: &Tree, gen_value: bool) -> CR {
// Only compile a given function once.
// Classes get compiled as constructor functions which get called.
let fk = FunctionKey { tree: t };
if !c.function_bindings.contains_key(&fk) {
let name = tree.nth_token(1)?;
let field_count = tree.children.len() - 2;
let function_index = c.temp_functions.len();
c.temp_functions.push(None);
c.pending_functions.push((
fk.clone(),
function_index,
Function::new(name.as_str(), field_count),
));
c.function_bindings.insert(fk, function_index);
c.module
.exports
.insert(name.to_string(), Export::Function(function_index));
}
if gen_value {
c.push(Instruction::PushNothing);
}
OK
}
fn compile_function(c: &mut Compiler, t: TreeRef) -> CR {
let tree = &c.syntax[t];
let block = tree.child_of_kind(c.syntax, TreeKind::Block)?;
match tree.kind {
TreeKind::FunctionDecl => {
let block = tree.child_of_kind(c.syntax, TreeKind::Block)?;
compile_expression(c, block);
}
TreeKind::ClassDecl => {
let count = tree.children_of_kind(c.syntax, TreeKind::FieldDecl).count();
for i in 0..count {
c.push(Instruction::LoadArgument(count - 1 - i));
}
let name = tree.nth_token(1)?.as_str();
let name_index = c.add_string(name.to_string());
c.push(Instruction::PushString(name_index));
c.push(Instruction::NewObject(count));
}
_ => ice!(c, t, "what is this tree doing in compile_function?"),
}
compile_expression(c, block);
c.push(Instruction::Return);
OK
}