Skip to content

Commit

Permalink
Starting top level so I can move to global and namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
jimmyhmiller committed Aug 10, 2024
1 parent 4dd20cf commit cddaf91
Show file tree
Hide file tree
Showing 8 changed files with 189 additions and 87 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"kind": "bin"
}
},
"args": ["resources/enum.bg"],
"args": ["resources/top_level.bg"],
"cwd": "${workspaceFolder}"
},
{
Expand Down
31 changes: 31 additions & 0 deletions resources/enum.bg
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
enum Action {
run { speed },
stop,
}

fn main() {
let action = Action.run { speed: 5 }

if action.speed >= 3 {
println("Fast")
}
println(action)
println(action.speed)

// TOOD: How do I represent this?
// It is a property access. So I need Action to exist
// in the scope. What is action? I guess it is type enum?
// If I print Action itself, what does it return?
// I need a "global" (or really namespace) environment for this.
// let stop = Action.stop

// println(stop)

"done"
}

// Expect
// Fast
// Action.run { speed: 5 }
// 5
// done
15 changes: 15 additions & 0 deletions resources/top_level.bg
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
let x = 2

println(x)

fn main() {
println("Hello, world!")
// TODO: this prints function...
// println(x)
"done"
}

// Expect
// 2
// Hello, world!
// done
105 changes: 59 additions & 46 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,15 @@ impl Ast {
ast_compiler.compile()
}

pub fn has_top_level(&self) -> bool {
self.nodes().iter().any(|node| {
!matches!(
node,
Ast::Function { .. } | Ast::Struct { .. } | Ast::Enum { .. }
)
})
}

pub fn nodes(&self) -> &Vec<Ast> {
match self {
Ast::Program { elements } => elements,
Expand All @@ -137,6 +146,8 @@ pub enum VariableLocation {
Register(VirtualRegister),
Local(usize),
FreeVariable(usize),
// The usize here is a string constant
GlobalVariable(usize),
}

impl From<&VariableLocation> for Value {
Expand All @@ -145,6 +156,7 @@ impl From<&VariableLocation> for Value {
VariableLocation::Register(reg) => Value::Register(*reg),
VariableLocation::Local(index) => Value::Local(*index),
VariableLocation::FreeVariable(index) => Value::FreeVariable(*index),
VariableLocation::GlobalVariable(name) => Value::GlobalVariable(name.clone()),
}
}
}
Expand Down Expand Up @@ -312,7 +324,7 @@ impl<'a> AstCompiler<'a> {
self.ir = old_ir;

if self.has_free_variables() {
return self.compile_closure(function_pointer)
return self.compile_closure(function_pointer);
}

let function = self.ir.function(Value::Function(function_pointer));
Expand Down Expand Up @@ -758,8 +770,15 @@ impl<'a> AstCompiler<'a> {
self.ir.load_local(reg, index);
self.ir.push_to_stack(reg.into());
}
VariableLocation::GlobalVariable(id) => {
let reg = self.ir.volatile_register();
self.ir.load_global(reg, id);
self.ir.push_to_stack(reg.into());
}
VariableLocation::FreeVariable(_) => {
panic!("We are trying to find this variable concretely and found a free variable")
panic!(
"We are trying to find this variable concretely and found a free variable"
)
}
}
}
Expand Down Expand Up @@ -913,69 +932,63 @@ impl<'a> AstCompiler<'a> {
.collect(),
});
}
Ast::Enum {
name,
variants,
} => {

Ast::Enum { name, variants } => {
let enum_repr = Enum {
name: name.clone(),
variants: variants
.iter()
.map(|variant| {
match variant {

Ast::EnumVariant { name, fields } => {
let fields = fields
.iter()
.map(|field| {
if let Ast::Identifier(name) = field {
name.clone()
} else {
panic!("Expected identifier got {:?}", field)
}
})
.collect();
EnumVariant::StructVariant {
name: name.clone(),
fields,
}
}
Ast::EnumStaticVariant { name } => {
EnumVariant::StaticVariant { name: name.clone() }
.map(|variant| match variant {
Ast::EnumVariant { name, fields } => {
let fields = fields
.iter()
.map(|field| {
if let Ast::Identifier(name) = field {
name.clone()
} else {
panic!("Expected identifier got {:?}", field)
}
})
.collect();
EnumVariant::StructVariant {
name: name.clone(),
fields,
}
_ => panic!("Expected enum variant got {:?}", variant)
}
Ast::EnumStaticVariant { name } => {
EnumVariant::StaticVariant { name: name.clone() }
}
_ => panic!("Expected enum variant got {:?}", variant),
})
.collect(),
};

self.compiler.add_enum(enum_repr);
for variant in variants.iter() {
match variant {
Ast::EnumVariant { name: variant_name, fields } => {
self.compiler.add_struct(Struct {
name: format!("{}.{}", name, variant_name),
fields: fields
.iter()
.map(|field| {
if let Ast::Identifier(name) = field {
name.clone()
} else {
panic!("Expected identifier got {:?}", field)
}
})
.collect(),
})
}
Ast::EnumVariant {
name: variant_name,
fields,
} => self.compiler.add_struct(Struct {
name: format!("{}.{}", name, variant_name),
fields: fields
.iter()
.map(|field| {
if let Ast::Identifier(name) = field {
name.clone()
} else {
panic!("Expected identifier got {:?}", field)
}
})
.collect(),
}),
Ast::EnumStaticVariant { name: _ } => {
// Do I need to do anything?
}
_ => panic!("Expected enum variant got {:?}", variant)
_ => panic!("Expected enum variant got {:?}", variant),
}
}
}
Ast::Let(_, _) => todo!(),
Ast::Let(_, _) => {}
_ => {}
}
}
Expand Down
14 changes: 14 additions & 0 deletions src/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub enum Value {
Pointer(usize),
Local(usize),
FreeVariable(usize),
GlobalVariable(usize),
True,
False,
Null,
Expand Down Expand Up @@ -802,6 +803,11 @@ impl Ir {
-((*free_variable + self.num_locals + 1) as i32),
);
}
Value::GlobalVariable(_global_variable) => {
// let register = alloc.allocate_register(index, *dest, lang);
// lang.load_global(register, *global_variable as i32);
todo!();
}
Value::Null => {
let register = alloc.allocate_register(index, *dest, lang);
lang.mov_64(register, 0b111_isize);
Expand Down Expand Up @@ -1014,6 +1020,10 @@ impl Ir {
);
lang.jump(exit);
}
Value::GlobalVariable(_global_variable) => {
// lang.load_global(lang.ret_reg(), *global_variable as i32);
todo!();
}
},
Instruction::HeapLoad(dest, ptr, offset) => {
let ptr = ptr.try_into().unwrap();
Expand Down Expand Up @@ -1355,4 +1365,8 @@ impl Ir {
free_variable_offset,
));
}

pub(crate) fn load_global(&self, _reg: VirtualRegister, _id: usize) -> Value {
todo!()
}
}
36 changes: 31 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ pub struct CommandLineArguments {
all_tests: bool,
#[clap(long, default_value = "false")]
test: bool,
#[clap(long, default_value = "false")]
debug: bool,
}

fn main() -> Result<(), Box<dyn Error>> {
Expand Down Expand Up @@ -337,6 +339,7 @@ fn run_all_tests(args: CommandLineArguments) -> Result<(), Box<dyn Error>> {
gc_always: args.gc_always,
all_tests: false,
test: true,
debug: args.debug,
};
main_inner(args)?;
}
Expand Down Expand Up @@ -454,7 +457,9 @@ fn main_inner(args: CommandLineArguments) -> Result<(), Box<dyn Error>> {
.add_builtin_function("__pause", __pause::<Alloc> as *const u8, true)?;

let beginnings_of_standard_library = include_str!("../resources/std.bg");
runtime.compiler.compile(beginnings_of_standard_library)?;
runtime
.compiler
.compile("std.bg", beginnings_of_standard_library)?;

let mut parser = Parser::new(source);
let ast = parser.parse();
Expand All @@ -463,7 +468,10 @@ fn main_inner(args: CommandLineArguments) -> Result<(), Box<dyn Error>> {
}

let compile_time = Instant::now();
runtime.compiler.compile_ast(ast)?;

// TODO: Need better name for top_level
// It should really be the top level of a namespace
let top_level = runtime.compiler.compile_ast(&program, ast)?;

runtime.compiler.check_functions();
if args.show_times {
Expand All @@ -476,12 +484,29 @@ fn main_inner(args: CommandLineArguments) -> Result<(), Box<dyn Error>> {
runtime.memory.stack_map = runtime.compiler.stack_map.clone();

let time = Instant::now();
let f = runtime.get_function0("main");
let result = f();
if let Some(top_level) = top_level {
if let Some(f) = runtime.get_function0(&top_level) {
f();
} else {
panic!(
"We are supposed to have top level, but didn't find the function {}",
top_level
);
}
}

if let Some(f) = runtime.get_function0("main") {
let result = f();
runtime.println(result as usize);
} else {
if args.debug {
println!("No main function");
}
}

if args.show_times {
println!("Time {:?}", time.elapsed());
}
runtime.println(result as usize);

if has_expect {
let source = std::fs::read_to_string(program)?;
Expand Down Expand Up @@ -534,6 +559,7 @@ fn try_all_examples() -> Result<(), Box<dyn Error>> {
gc_always: false,
all_tests: true,
test: false,
debug: false,
};
run_all_tests(args)?;
Ok(())
Expand Down
Loading

0 comments on commit cddaf91

Please sign in to comment.