diff --git a/compiler/ast/nodes.oc b/compiler/ast/nodes.oc index 239ec4e..24ffc63 100644 --- a/compiler/ast/nodes.oc +++ b/compiler/ast/nodes.oc @@ -67,8 +67,6 @@ struct Variable { //* Original parsed type, for keeping track of locations parsed_type: &Type - - is_dead: bool } def Variable::new(type: &Type): &Variable { @@ -84,7 +82,6 @@ struct Structure { type: &Type is_union: bool span: Span - is_dead: bool format_spec: str format_args: str @@ -116,7 +113,6 @@ struct Enum { shared_fields: &Vector<&Variable> variants: &Vector<&EnumVariant> type: &Type - is_dead: bool // To quickly check if this is a "normal" enum with no values stored has_values: bool @@ -229,8 +225,6 @@ struct Function { exits: bool is_static: bool parent_type: &Type - - is_dead: bool } def Function::new(): &Function { diff --git a/compiler/ast/scopes.oc b/compiler/ast/scopes.oc index d40119d..c67a13e 100644 --- a/compiler/ast/scopes.oc +++ b/compiler/ast/scopes.oc @@ -17,8 +17,10 @@ enum SymbolType { Namespace Variable Constant - Closure - ClosedVariable + + ClosureType // Represents the closure type, eg: @fn(i32, i32): str + Closure // Represents an actual closure function, eg: |a: 32, b: 32|: str { ... } + ClosedVariable // Represents a variable captured by a closure Enum EnumVariant @@ -125,6 +127,7 @@ struct Symbol { extern_name: str template: &Template + is_dead: bool = false } def Symbol::out_name(&this): str { diff --git a/compiler/lsp/utils.oc b/compiler/lsp/utils.oc index a0968f2..62a30ae 100644 --- a/compiler/lsp/utils.oc +++ b/compiler/lsp/utils.oc @@ -173,7 +173,7 @@ def try_gen_expr_string(expr: &AST): str => match expr.type { } def gen_hover_string(sym: &Symbol): str => match sym.type { - TypeDef => gen_type_string(sym.u.type_def) + ClosureType | TypeDef => gen_type_string(sym.u.type_def) Function => gen_type_string(sym.u.func.type) Variable => { let sb = Buffer::make() @@ -238,6 +238,7 @@ def get_symbol_typedef(sym: &Symbol): &Type => match sym.type { Enum => sym.u.enom.type EnumVariant => sym.u.enum_var.parent.type EnumField => sym.u.enum_field.variant.parent.type + ClosureType => sym.u.type_def Closure => sym.u.func.type ClosedVariable => sym.u.closed_var.orig.type // else => std::panic(f"get_symbol_typedef: unhandled symbol type: {sym.type}") diff --git a/compiler/passes/code_generator.oc b/compiler/passes/code_generator.oc index 313fe9c..071affb 100644 --- a/compiler/passes/code_generator.oc +++ b/compiler/passes/code_generator.oc @@ -289,7 +289,7 @@ def CodeGenerator::gen_yield_expression(&this, expr: &AST) { def CodeGenerator::gen_constant(&this, node: &AST) { let const_ = node.u.var_decl - if const_.is_dead return + if const_.sym.is_dead return if not const_.sym.is_extern { .gen_indent() @@ -314,7 +314,7 @@ def CodeGenerator::gen_constants(&this, ns: &Namespace) { def CodeGenerator::gen_global_variables(&this, ns: &Namespace) { for node : ns.variables.iter() { let var = node.u.var_decl - if var.is_dead continue + if var.sym.is_dead continue if not var.sym.is_extern { .gen_var_declaration(node) .out += ";\n" @@ -1411,7 +1411,7 @@ def CodeGenerator::gen_function(&this, func: &Function) { if struc.sym.is_templated() then return } if func.sym.is_templated() then return - if func.is_dead then return + if func.sym.is_dead then return .gen_debug_info(func.sym.span) .gen_function_decl(func) @@ -1464,7 +1464,7 @@ def CodeGenerator::gen_function_decl_toplevel(&this, func: &Function) { let sym = instance.resolved assert sym.type == Function let func = sym.u.func - if func.is_dead then continue + if func.sym.is_dead then continue .gen_function_decl(func) if func.exits then .out += " __attribute__((noreturn))" @@ -1473,7 +1473,7 @@ def CodeGenerator::gen_function_decl_toplevel(&this, func: &Function) { return } - if func.is_dead then return + if func.sym.is_dead then return .gen_function_decl(func) if func.exits then .out += " __attribute__((noreturn))" .out += ";\n" @@ -1524,7 +1524,7 @@ def CodeGenerator::gen_enum_dbg_method(&this, enom: &Enum) { def CodeGenerator::gen_struct_typedef(&this, struc: &Structure) { if struc.sym.is_extern return - if struc.is_dead return + if struc.sym.is_dead return let strufull_name = struc.sym.out_name() if struc.is_union { @@ -1535,11 +1535,13 @@ def CodeGenerator::gen_struct_typedef(&this, struc: &Structure) { } def CodeGenerator::gen_closure_type_typedef(&this, sym: &Symbol) { + if sym.is_dead return let name = sym.out_name() .out <<= `typedef struct {name} {name};\n` } def CodeGenerator::gen_closure_type_def(&this, sym: &Symbol) { + if sym.is_dead return let name = sym.out_name() let type = sym.u.type_def .out <<= `struct {name} \{\n` @@ -1558,12 +1560,14 @@ def CodeGenerator::gen_closure_type_def(&this, sym: &Symbol) { } def CodeGenerator::gen_closure_typedef(&this, clos: &Function) { + if clos.sym.is_dead return let name = clos.sym.out_name() let type_name = cls::ctx_type(clos) .out <<= `typedef struct {type_name} {type_name};\n` } def CodeGenerator::gen_closure_def(&this, clos: &Function) { + if clos.sym.is_dead return let name = clos.sym.out_name() let type_name = cls::ctx_type(clos) @@ -1586,6 +1590,7 @@ def CodeGenerator::gen_closure_def(&this, clos: &Function) { } def CodeGenerator::gen_closure_func_decl(&this, clos: &Function) { + if clos.sym.is_dead return let name = clos.sym.out_name() let type = clos.type @@ -1602,6 +1607,7 @@ def CodeGenerator::gen_closure_func_decl(&this, clos: &Function) { } def CodeGenerator::gen_closure_func(&this, clos: &Function) { + if clos.sym.is_dead return let name = clos.sym.out_name() let type = clos.type @@ -1627,18 +1633,22 @@ def CodeGenerator::gen_closure_func(&this, clos: &Function) { def CodeGenerator::gen_sym_typedef(&this, sym: &Symbol) => match sym.type { Structure => .gen_struct_typedef(sym.u.struc) Enum => .gen_enum_typedef(sym.u.enom) + Closure => .gen_closure_typedef(sym.u.func) + ClosureType => .gen_closure_type_typedef(sym) else => assert false, `Unhandled symbol type in CodeGenerator::gen_typedef: {sym.type}` } def CodeGenerator::gen_sym_def(&this, sym: &Symbol) => match sym.type { Structure => .gen_struct_def(sym.u.struc) Enum => .gen_enum_def(sym.u.enom) + Closure => .gen_closure_def(sym.u.func) + ClosureType => .gen_closure_type_def(sym) else => assert false, `Unhandled symbol type in CodeGenerator::gen_def: {sym.type}` } def CodeGenerator::gen_enum_typedef(&this, enom: &Enum) { if enom.sym.is_extern return - if enom.is_dead return + if enom.sym.is_dead return let name = enom.sym.out_name() if enom.has_values { @@ -1651,7 +1661,7 @@ def CodeGenerator::gen_enum_typedef(&this, enom: &Enum) { def CodeGenerator::gen_struct_def(&this, struc: &Structure) { if struc.sym.is_extern return - if struc.is_dead then return + if struc.sym.is_dead then return let strufull_name = struc.sym.out_name() if struc.is_union { @@ -1672,7 +1682,7 @@ def CodeGenerator::gen_struct_def(&this, struc: &Structure) { } def CodeGenerator::gen_enum_def(&this, enom: &Enum) { - if enom.is_dead then return + if enom.sym.is_dead then return let name = enom.sym.out_name() defer .gen_enum_dbg_method(enom) @@ -1737,24 +1747,12 @@ def CodeGenerator::generate(&this): str { for sym in .o.program.ordered_symbols.iter() { .gen_sym_typedef(sym) } - for cty in .o.program.closure_types.iter() { - .gen_closure_type_typedef(cty.sym) - } - for clos in .o.program.closures.iter() { - .gen_closure_typedef(clos) - } .out += "\n" .out += "/* Structs */\n" for sym in .o.program.ordered_symbols.iter() { .gen_sym_def(sym) } - for cty in .o.program.closure_types.iter() { - .gen_closure_type_def(cty.sym) - } - for clos in .o.program.closures.iter() { - .gen_closure_def(clos) - } .out += "/* function declarations */\n" .gen_function_decls(.o.program.global) diff --git a/compiler/passes/mark_dead_code.oc b/compiler/passes/mark_dead_code.oc index f1280dc..ea1a444 100644 --- a/compiler/passes/mark_dead_code.oc +++ b/compiler/passes/mark_dead_code.oc @@ -41,12 +41,14 @@ def MarkDeadCode::mark_sym(&this, sym: &Symbol) { Function => .mark_function(sym.u.func) Structure => .mark_struct(sym.u.struc) Enum => .mark_enum(sym.u.enom) - Constant | Variable => { .mark_type(sym.u.var.type) .mark(sym.u.var.default_value) - sym.u.var.is_dead = false + sym.u.var.sym.is_dead = false } + Closure => .mark_function(sym.u.closure) + ClosureType => .mark_type(sym.u.type_def) + ClosedVariable => .mark_sym(sym.u.closed_var.orig.sym) else => {} } } @@ -55,7 +57,7 @@ def MarkDeadCode::mark_function(&this, f: &Function) { if not f? or .done.contains(f as u64) return .done.add(f as u64) - f.is_dead = false + f.sym.is_dead = false .mark(f.body) for param : f.params.iter() { @@ -68,7 +70,7 @@ def MarkDeadCode::mark_type(&this, typ: &Type) { match typ.base { Pointer | Alias => .mark_type(typ.u.ptr) Array => .mark_type(typ.u.arr.elem_type) - FunctionPtr => { + FunctionPtr | Closure => { let ft = typ.u.func .mark_type(ft.return_type) for param : ft.params.iter() { @@ -90,7 +92,7 @@ def MarkDeadCode::mark_struct(&this, s: &Structure) { if not s? or .done.contains(s as u64) return .done.add(s as u64) - s.is_dead = false + s.sym.is_dead = false for field : s.fields.iter() { .mark_type(field.type) } @@ -100,7 +102,7 @@ def MarkDeadCode::mark_enum(&this, e: &Enum) { if not e? or .done.contains(e as u64) return .done.add(e as u64) - e.is_dead = false + e.sym.is_dead = false for var in e.variants.iter() { .mark_sym(var.sym) for field in var.specific_fields.iter() { @@ -223,14 +225,7 @@ def MarkDeadCode::find_main_function(&this, program: &Program): &Function { def MarkDeadCode::mark_sym_as_dead_by_default(&this, sym: &Symbol) { if not sym? return - - match sym.type { - Function => sym.u.func.is_dead = true - Structure => sym.u.struc.is_dead = true - Enum => sym.u.enom.is_dead = true - Constant | Variable => sym.u.var.is_dead = true - else => {} - } + sym.is_dead = true if sym.template? { for instance : sym.template.instances.iter() { @@ -271,6 +266,12 @@ def MarkDeadCode::run(program: &Program) { pass.mark_sym_as_dead_by_default(c.u.var_decl.sym) } } + for cty in program.closure_types.iter() { + pass.mark_sym_as_dead_by_default(cty.sym) + } + for clos in program.closures.iter() { + pass.mark_sym_as_dead_by_default(clos.sym) + } // For constants and variables, mark their types as used if main? { diff --git a/compiler/passes/mod.oc b/compiler/passes/mod.oc index eedc4f3..84818d8 100644 --- a/compiler/passes/mod.oc +++ b/compiler/passes/mod.oc @@ -16,8 +16,8 @@ def run_typecheck_passes(program: &Program) { //* Generates code for the program and returns it def run_codegen_passes(program: &Program): str { - ReorderSymbols::run(program) MarkDeadCode::run(program) + ReorderSymbols::run(program) let code = CodeGenerator::run(program) return code } \ No newline at end of file diff --git a/compiler/passes/typechecker.oc b/compiler/passes/typechecker.oc index 59f4355..deab4c1 100644 --- a/compiler/passes/typechecker.oc +++ b/compiler/passes/typechecker.oc @@ -89,7 +89,7 @@ def TypeChecker::get_closure_type(&this, params: &Vector<&Variable>, return_type let closure_name = `_ClosureTy_{.o.program.closure_types.size}` .o.program.closure_types.push(canon) - let sym = Symbol::new(TypeDef, ns: null, closure_name, closure_name, closure_name, span) + let sym = Symbol::new(ClosureType, ns: null, closure_name, closure_name, closure_name, span) sym.u.type_def = canon canon.sym = sym }