Revamp object system, start using gc crate

Wow, what a ride. I think everything should be working now. In short:

* Objects use the `gc` crate, which as a `Gc` garbage-collected pointer
  type. I may choose to implement my own in contiguous memory in the
  future. We will see.
* The type system is no longer global. This is a bit of a burden,
  because now, whenever you want to create a new object, you need to
  pass its type object into the `Obj::instantiate` method, as well as
  its `::create` static method.
* This burden is somewhat alleviated by the `ObjFactory` trait, which
  helps create new objects as long as you have access to a `builtins`
  hashmap. So something that would normally look like this:

    fn init_builtins(builtins: &mut HashMap<String, ObjP>) {
        let print_builtin = upcast_obj(BuiltinFunctionInst::create(
            ObjP::clone(&builtins.get("BuiltinFunction").unwrap()),
            "print",
            print,
            1
        );
        builtins.insert("print".to_string(), print_builtin)
        // other builtins inserted here...
    }

  now looks like this:

    fn init_builtins(builtins: &mut HashMap<String, ObjP>) {
        let print_builtin = builtins.create_builtin_function("print", print, 1);
        builtins.insert("print".to_string(), print_builtin);
    }

(turns out, if all you need is a HashMap<String, ObjP>, you can
implement ObjFactory for HashMap<String, ObjP> itself(!))

Overall, I'm happier with this design, and I think this is what is going
to get merged. It's a little weird to be querying type names that are
used in the language itself to get those type objects, but whatever
works, I guess.

Next up is vtables.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2024-09-23 18:12:32 -07:00
parent 24b06851c7
commit 8b931e9d12
8 changed files with 502 additions and 356 deletions

View File

@@ -33,7 +33,7 @@ fn disassemble_chunk(chunk: &Chunk, constants: &Vec<ObjP>, globals: &Vec<String>
}
Op::PushConstant(constant_id) => {
op_str = "PUSH_CONSTANT";
arg = format!("{}", &constants[*constant_id as usize]);
arg = format!("{}", &constants[*constant_id as usize].borrow());
info = format!("(constant ID {constant_id})");
}
Op::GetLocal(local_id) => {
@@ -60,12 +60,12 @@ fn disassemble_chunk(chunk: &Chunk, constants: &Vec<ObjP>, globals: &Vec<String>
}
Op::GetAttr(constant_id) => {
op_str = "GET_ATTR";
arg = format!("{}", &constants[*constant_id as usize]);
arg = format!("{}", &constants[*constant_id as usize].borrow());
info = format!("(constant ID {constant_id})");
}
Op::SetAttr(constant_id) => {
op_str = "SET_ATTR";
arg = format!("{}", &constants[*constant_id as usize]);
arg = format!("{}", &constants[*constant_id as usize].borrow());
info = format!("(constant ID {constant_id})");
}
Op::Jump(jump_offset) => {
@@ -145,7 +145,11 @@ pub fn disassemble(chunk: &Chunk, constants: &Vec<ObjP>, globals: &Vec<String>)
disassemble_chunk(chunk, constants, globals);
for constant in constants {
if let Some(fun) = constant.as_any().downcast_ref::<UserFunctionInst>() {
if let Some(fun) = constant
.borrow()
.as_any()
.downcast_ref::<UserFunctionInst>()
{
println!();
println!(
"== {} starting on line {}",