[fine] WIP: Classes
This commit is contained in:
parent
e6c96fde38
commit
0ee89bf26b
7 changed files with 370 additions and 59 deletions
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue