[fine] Improvements to classes

- Classes are defined lazily
- Member access is via environment
- Member access is just a binary expression with a weird environment
- Slot loads look like variable loads now
- Associativity in the parser (ugh)
This commit is contained in:
John Doty 2024-01-22 23:17:02 -08:00
parent 0d48bfb113
commit 2839b43f6d
5 changed files with 286 additions and 123 deletions

View file

@ -487,6 +487,9 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
compiler_assert!(c, t, index < c.module.globals);
Instruction::StoreModule(index)
}
Location::Slot => {
ice!(c, t, "cannot have an identifier lvalue bind to a slot");
}
}
}
@ -496,6 +499,9 @@ fn compile_binary_expression(c: &mut Compiler, t: TreeRef, tr: &Tree) -> CR {
};
c.push(instruction);
}
// TODO: Member
// TODO: List element
_ => ice!(c, t, "Unsupported lvalue type"),
}
OK
@ -533,6 +539,10 @@ fn compile_load_declaration(c: &mut Compiler, t: TreeRef, declaration: &Declarat
compiler_assert!(c, t, index < c.module.globals);
Instruction::LoadModule(index)
}
Location::Slot => {
// TODO: Assert slot is in field range?
Instruction::LoadSlot(index)
}
}
}
Declaration::Function { declaration, .. } => {
@ -603,10 +613,11 @@ fn compile_argument(c: &mut Compiler, tree: &Tree) -> CR {
fn compile_new_object_expression(c: &mut Compiler, t: TreeRef, tree: &Tree) -> CR {
// We pass in the arguments.... by... field order?
let Type::Class(class) = c.semantics.type_of(t) else {
let Type::Class(ct, _) = c.semantics.type_of(t) else {
c.push(Instruction::Panic);
return OK;
};
let class = c.semantics.class_of(ct);
let field_list = tree.child_tree_of_kind(c.syntax, TreeKind::FieldList)?;
let mut field_bindings = HashMap::new();
@ -669,22 +680,10 @@ fn compile_field_value(c: &mut Compiler, t: TreeRef, tree: &Tree) -> CR {
}
fn compile_member_access(c: &mut Compiler, tree: &Tree) -> CR {
let lhs = tree.nth_tree(0)?;
compile_expression(c, lhs);
let id = tree.nth_token(2)?;
let Type::Class(cr) = c.semantics.type_of(lhs) else {
return None;
};
let Some((index, _fld)) = cr
.fields
.iter()
.enumerate()
.find(|(_, f)| &*f.name == id.as_str())
else {
return None;
};
c.push(Instruction::LoadSlot(index));
// In member access; the lhs sets up the object and in theory the rhs
// binds against it. ::shrug::
compile_expression(c, tree.nth_tree(0)?);
compile_expression(c, tree.nth_tree(2)?);
OK
}