Files
not-python-rust/src/main.rs

75 lines
1.7 KiB
Rust
Raw Normal View History

// trait_upcasting - https://github.com/rust-lang/rust/issues/65991
// stabilization in progress
#![feature(trait_upcasting)]
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>
2024-09-23 18:12:32 -07:00
#![feature(coerce_unsized)]
mod ast;
mod builtins;
mod compiler;
mod disassemble;
mod obj;
mod parser;
mod token;
mod vm;
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>
2024-09-23 18:12:32 -07:00
use std::collections::HashMap;
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::path::PathBuf;
use clap::Parser as ClapParser;
use thiserror::Error;
#[derive(ClapParser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
#[arg(short, long, help = "Dump program disassembly and exit")]
disassemble: bool,
#[arg(help = "The path of the file to run")]
path: PathBuf,
}
#[derive(Debug, Error)]
struct ProgramError(String);
impl fmt::Display for ProgramError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", self.0)
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args = Args::parse();
let mut file = File::open(&args.path)?;
let mut contents = String::new();
file.read_to_string(&mut contents)?;
let mut parser = parser::Parser::new(contents, &args.path)?;
let ast = parser.parse_all()?;
if parser.was_error() {
return Err(ProgramError("error occurred, exiting".to_string()).into());
}
// initialize type system
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>
2024-09-23 18:12:32 -07:00
let mut builtins = HashMap::new();
obj::init_types(&mut builtins);
crate::builtins::init_builtins(&mut builtins);
// compile
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>
2024-09-23 18:12:32 -07:00
let (chunk, constants, globals) = compiler::Compiler::new(&builtins).compile(&ast)?;
if args.disassemble {
disassemble::disassemble(&chunk, &constants, &globals);
return Ok(());
}
// run
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>
2024-09-23 18:12:32 -07:00
let mut vm = vm::Vm::new(chunk.into(), constants, globals, builtins);
vm.run();
Ok(())
}