diff options
Diffstat (limited to 'src/bootstrap')
| -rw-r--r-- | src/bootstrap/codegen.pry | 1450 | ||||
| -rw-r--r-- | src/bootstrap/llvm.pry | 353 | ||||
| -rw-r--r-- | src/bootstrap/main.pry | 80 | ||||
| -rw-r--r-- | src/bootstrap/parser.pry | 1456 | ||||
| -rw-r--r-- | src/bootstrap/tokenizer.pry | 553 |
5 files changed, 0 insertions, 3892 deletions
diff --git a/src/bootstrap/codegen.pry b/src/bootstrap/codegen.pry deleted file mode 100644 index cb054ec..0000000 --- a/src/bootstrap/codegen.pry +++ /dev/null @@ -1,1450 +0,0 @@ -import "!hashmap.pry"; - -import "llvm.pry"; - -let Variable = struct { - value: LLVMValueRef, - type: LLVMTypeRef, - node: *Node, - node_type: *Node, - stack_level: *i64, -}; - -let Scope = struct { - variables: *HashMap, -}; - -let Environment = struct { - scope_stack: **Scope, - scope_stack_len: i64, - arena: *arena, -}; - -let environment_create_scope = (e: *Environment) => void { - let scope = cast(*Scope, arena_alloc((*e).arena, sizeof(Scope))); - (*scope).variables = hashmap_init(16, (*e).arena); - (*((*e).scope_stack + cast(**Scope, (*e).scope_stack_len))) = scope; - (*e).scope_stack_len = (*e).scope_stack_len + 1; - - return; -}; - -let environment_drop_scope = (e: *Environment) => void { - (*e).scope_stack_len = (*e).scope_stack_len - 1; - - return; -}; - -let environment_get_variable = (e: *Environment, name: *i8) => *Variable { - let i = (*e).scope_stack_len; - let variable = cast(*Variable, null); - - while i > 0 { - i = i - 1; - let scope = *(((*e).scope_stack + cast(**Scope, i))); - assert(scope != cast(*Scope, null)); - let v = cast(*Variable, hashmap_get((*scope).variables, name)); - if v != cast(*Variable, null) { - if variable == cast(*Variable, null) { - variable = v; - }; - let stack_level = cast(*i64, arena_alloc((*e).arena, sizeof(i64))); - (*stack_level) = i; - (*variable).stack_level = stack_level; - }; - }; - - return variable; -}; - -let environment_add_variable = (e: *Environment, name: *i8, variable: *Variable) => void { - /* TODO: Dont allow shadowing if value != value or type != type (across things) */ - let top_scope = *(((*e).scope_stack + cast(**Scope, (*e).scope_stack_len - 1))); - hashmap_put((*top_scope).variables, name, cast(*void, variable)); - - return; -}; - -let environment_set_variable = (e: *Environment, name: *i8, variable: *Variable) => void { - let existing = environment_get_variable(e, name); - (*existing) = (*variable); - - return; -}; - -let environment_init = (alloc: *arena) => *Environment { - let e = cast(*Environment, arena_alloc(alloc, sizeof(Environment))); - (*e).scope_stack = cast(**Scope, arena_alloc(alloc, sizeof(*Scope) * 40)); - (*e).scope_stack_len = 0; - (*e).arena = alloc; - - environment_create_scope(e); - - return e; -}; - -let codegen = struct { - llvm_module: LLVMModuleRef, - llvm_context: LLVMContextRef, - builder: LLVMBuilderRef, - arena: *arena, - environment: *Environment, - - whil_loop_exit: LLVMBasicBlockRef, - whil_block: LLVMBasicBlockRef, - current_function: LLVMValueRef, - current_function_retur_type: *Node, - llvm_target_data: LLVMTargetDataRef, -}; - -let codegen_init = (alloc: *arena) => *codegen { - LLVMInitializeAllTargetInfos(); - LLVMInitializeAllTargetMCs(); - LLVMInitializeAllTargets(); - LLVMInitializeAllAsmPrinters(); - LLVMInitializeAllAsmParsers(); - - let module = LLVMModuleCreateWithName("module"); - let context = LLVMGetGlobalContext(); - let builder = LLVMCreateBuilder(); - - let c = cast(*codegen, arena_alloc(alloc, sizeof(codegen))); - - (*c).llvm_module = module; - (*c).llvm_target_data = LLVMGetModuleDataLayout(module); - (*c).llvm_context = context; - (*c).builder = builder; - (*c).arena = alloc; - (*c).environment = environment_init(alloc); - - return c; -}; - -let create_node = (c: *codegen, n: Node) => *Node { - let res = cast(*Node, arena_alloc((*c).arena, sizeof(Node))); - *res = n; - return res; -}; - -let codegen_create_variable = (c: *codegen, variable: Variable) => *Variable { - let v = cast(*Variable, arena_alloc((*c).arena, sizeof(Variable))); - *v = variable; - return v; -}; - -let compare_types = (c: *codegen, a: *Node, b: *Node, is_dereference: bool) => bool { - assert((*a).type >= NODE_TYPE_SIMPLE_TYPE); - assert((*a).type <= NODE_TYPE_STRUCT_TYPE); - assert((*b).type >= NODE_TYPE_SIMPLE_TYPE); - assert((*b).type <= NODE_TYPE_STRUCT_TYPE); - - if (*a).type == NODE_TYPE_SIMPLE_TYPE { - let simple_type_a = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*a).data); - if strcmp(simple_type_a.name, "varargs") { - return true; - }; - }; - - if is_dereference { - assert((*a).type == NODE_TYPE_POINTER_TYPE); - let pointer_type_a = *cast(*NODE_TYPE_POINTER_TYPE_DATA, (*a).data); - a = pointer_type_a.type; - }; - - if (*a).type != (*b).type { - printf("Types do not match: %d != ", (*a).type); - printf("%d\n", (*b).type); - return false; - }; - - if (*a).type == NODE_TYPE_SIMPLE_TYPE { - assert((*b).type == NODE_TYPE_SIMPLE_TYPE); - let simple_type_a = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*a).data); - let simple_type_b = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*b).data); - let eql = strcmp(simple_type_a.name, simple_type_b.name); - if !eql { - printf("Simple types do not match: %s != ", simple_type_a.name); - printf("%s\n", simple_type_b.name); - }; - return eql; - }; - - if (*a).type == NODE_TYPE_FUNCTION_TYPE { - assert((*b).type == NODE_TYPE_FUNCTION_TYPE); - let function_type_a = *cast(*NODE_TYPE_FUNCTION_TYPE_DATA, (*a).data); - let function_type_b = *cast(*NODE_TYPE_FUNCTION_TYPE_DATA, (*b).data); - - - if !compare_types(c, function_type_a.retur_type, function_type_b.retur_type, false) { - printf("Function return types do not match\n"); - return false; - }; - - if function_type_a.parameters_len != function_type_b.parameters_len { - printf("Function parameter lengths do not match\n"); - return false; - }; - - let i = 0; - while i < function_type_a.parameters_len { - let param_a = *(function_type_a.parameters + cast(**Node, i)); - let param_b = *(function_type_b.parameters + cast(**Node, i)); - if !compare_types(c, param_a, param_b, false) { - printf("Function parameter types do not match\n"); - return false; - }; - i = i + 1; - }; - - return true; - }; - - if (*a).type == NODE_TYPE_POINTER_TYPE { - assert((*b).type == NODE_TYPE_POINTER_TYPE); - let pointer_type_a = *cast(*NODE_TYPE_POINTER_TYPE_DATA, (*a).data); - let pointer_type_b = *cast(*NODE_TYPE_POINTER_TYPE_DATA, (*b).data); - if !compare_types(c, pointer_type_a.type, pointer_type_b.type, false) { - printf("Pointer types do not match\n"); - return false; - }; - return true; - }; - - if (*a).type == NODE_TYPE_STRUCT_TYPE { - assert((*b).type == NODE_TYPE_STRUCT_TYPE); - let struc_type_a = *cast(*NODE_TYPE_STRUCT_TYPE_DATA, (*a).data); - let struc_type_b = *cast(*NODE_TYPE_STRUCT_TYPE_DATA, (*b).data); - - if struc_type_a.fields_len != struc_type_b.fields_len { - printf("Struct field lengths do not match\n"); - return false; - }; - - let i = 0; - while i < struc_type_a.fields_len { - let field_a = *(struc_type_a.fields + cast(**Node, i)); - let field_b = *(struc_type_b.fields + cast(**Node, i)); - if !compare_types(c, field_a, field_b, false) { - printf("Struct field types do not match\n"); - return false; - }; - i = i + 1; - }; - - return true; - }; - - return false; -}; - -let codegen_get_llvm_type = (c: *codegen, node: *Node) => *LLVMTypeRef { - assert((*node).type >= NODE_TYPE_SIMPLE_TYPE); - assert((*node).type <= NODE_TYPE_STRUCT_TYPE); - - if (*node).type == NODE_TYPE_SIMPLE_TYPE { - let simple_type = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*node).data); - - if strcmp(simple_type.name, "i8") { - let r = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef))); - *r = LLVMInt8Type(); - return r; - }; - - if strcmp(simple_type.name, "i64") { - let r = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef))); - *r = LLVMInt64Type(); - return r; - }; - - if strcmp(simple_type.name, "bool") { - let r = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef))); - *r = LLVMInt1Type(); - return r; - }; - - if strcmp(simple_type.name, "void") { - let r = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef))); - *r = LLVMVoidType(); - return r; - }; - - if strcmp(simple_type.name, "varargs") { /* Hack for varargs (only used for printf) */ - let r = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef))); - *r = LLVMPointerType(LLVMInt64Type(), 0); - return r; - }; - - let v = environment_get_variable((*c).environment, simple_type.name); - if (v != cast(*Variable, null)) { - assert((*v).type != cast(LLVMTypeRef, null)); - let r = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef))); - *r = (*v).type; - return r; - }; - - printf("NO SIMPLE TYPE %s!\n", simple_type.name); - assert(false); - }; - - if (*node).type == NODE_TYPE_FUNCTION_TYPE { - let function_type = *cast(*NODE_TYPE_FUNCTION_TYPE_DATA, (*node).data); - let f_retur = function_type.retur_type; - let retur_type = codegen_get_llvm_type(c, f_retur); - assert(retur_type != cast(*LLVMTypeRef, null)); - if (*f_retur).type == NODE_TYPE_FUNCTION_TYPE { - (*retur_type) = LLVMPointerType(*retur_type, 0); - }; - - let paramtypes = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef) * 20)); - let paramtypes_len = 0; - let is_varargs = 0; - - let i = 0; - while i < function_type.parameters_len { - let param = *(function_type.parameters + cast(**Node, i)); - if (*param).type == NODE_TYPE_SIMPLE_TYPE { - let simple_type = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*param).data); - if strcmp(simple_type.name, "varargs") { - is_varargs = 1; - i = i + 1; - continue; - }; - }; - let typ = codegen_get_llvm_type(c, param); - assert(typ != cast(*LLVMTypeRef, null)); - if (*param).type == NODE_TYPE_FUNCTION_TYPE { - *typ = LLVMPointerType(*typ, 0); - }; - - (*(paramtypes + cast(*LLVMTypeRef, paramtypes_len))) = *typ; - paramtypes_len = paramtypes_len + 1; - - i = i + 1; - }; - let function_type = LLVMFunctionType(*retur_type, paramtypes, paramtypes_len, is_varargs); - let r = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef))); - *r = function_type; - return r; - }; - - if (*node).type == NODE_TYPE_POINTER_TYPE { - let pointer_type = *cast(*NODE_TYPE_POINTER_TYPE_DATA, (*node).data); - let inner_type = codegen_get_llvm_type(c, pointer_type.type); - assert(inner_type != cast(*LLVMTypeRef, null)); - let r = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef))); - *r = LLVMPointerType(*inner_type, 0); - return r; - }; - - printf("NO TYPEEE BOI %d\n", (*node).type); - assert(false); - - return cast(*LLVMTypeRef, null); -}; - -let codegen_generate_literal = (c: *codegen, literal_val: LLVMValueRef, name: *i8, node: *Node, node_type: *Node) => *Variable { - if name != cast(*i8, null) { - let e = (*c).environment; - if (*e).scope_stack_len == 1 { - let lt = codegen_get_llvm_type(c, node_type); - assert(lt != cast(*LLVMTypeRef, null)); - let v = Variable{}; - v.value = LLVMAddGlobal((*c).llvm_module, *lt, name); - v.type = cast(LLVMTypeRef, null); - v.stack_level = cast(*i64, null); - v.node = node; - v.node_type = node_type; - LLVMSetInitializer(v.value, literal_val); - return codegen_create_variable(c, v); - }; - }; - - - let v = Variable{}; - v.value = literal_val; - v.type = cast(LLVMTypeRef, null); - v.stack_level = cast(*i64, null); - v.node = node; - v.node_type = node_type; - return codegen_create_variable(c, v); -}; - -extern codegen_generate_statement = (*codegen, *Node) => i64; -extern codegen_generate_function_call_statement = (*codegen, *Node) => *Variable; -extern codegen_generate_expression_value = (*codegen, *Node, *i8) => *Variable; - -let StructField = struct { - value: LLVMValueRef, - type: *Node, -}; - -let codegen_get_struct_field = (c: *codegen, node: *Node, name: *i8) => *StructField { - let ptr = cast(*Variable, null); - if (*node).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER { - let identifier = *cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*node).data); - ptr = environment_get_variable((*c).environment, identifier.name); - }; - if (*node).type == NODE_UNARY_EXPRESSION { - let xd = (*cast(*NODE_UNARY_EXPRESSION_DATA, (*node).data)).expression; - ptr = codegen_generate_expression_value(c, xd, ""); - }; - - assert(ptr != cast(*Variable, null)); - - let typ = cast(*Node, null); - let ptr_typ = (*ptr).node_type; - if (*ptr_typ).type == NODE_TYPE_STRUCT_TYPE { - typ = ptr_typ; - }; - if (*ptr_typ).type == NODE_TYPE_POINTER_TYPE { - let pt = *cast(*NODE_TYPE_POINTER_TYPE_DATA, (*ptr_typ).data); - let pt_type = pt.type; - assert((*pt_type).type == NODE_TYPE_SIMPLE_TYPE); - let simple_type = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*pt_type).data); - let v = environment_get_variable((*c).environment, simple_type.name); - assert(v != cast(*Variable, null)); - typ = (*v).node_type; /* TODO: we shouldnt be able to get fields of pointers, we have to dref first */ - }; - if (*ptr_typ).type == NODE_TYPE_SIMPLE_TYPE { - let simple_type = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*ptr_typ).data); - let v = environment_get_variable((*c).environment, simple_type.name); - assert(v != cast(*Variable, null)); - typ = (*v).node_type; - }; - - assert(typ != cast(*Node, null)); - assert((*typ).type == NODE_TYPE_SIMPLE_TYPE); - let simple_type = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*typ).data); - assert((*simple_type.underlying_type).type == NODE_TYPE_STRUCT_TYPE); - let struc_type = *cast(*NODE_TYPE_STRUCT_TYPE_DATA, (*simple_type.underlying_type).data); - - let fieldIndex = cast(*i64, null); - - let i = 0; - while i < struc_type.fields_len { - let field = *(struc_type.fields + cast(**Node, i)); - assert((*field).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER); - let field_data = *cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*field).data); - if strcmp(name, field_data.name) { - let ii = cast(*i64, arena_alloc((*c).arena, sizeof(i64))); - *ii = i; - fieldIndex = ii; - break; - }; - i = i + 1; - }; - - assert(fieldIndex != cast(*i64, null)); - - let zero = LLVMConstInt(LLVMInt32Type(), 0, 0); - let llvmFieldIndex = LLVMConstInt(LLVMInt32Type(), *fieldIndex, 0); - let indices = cast(*LLVMValueRef, arena_alloc((*c).arena, sizeof(LLVMValueRef) * 2)); - (*(indices + cast(*LLVMValueRef, 0))) = zero; - (*(indices + cast(*LLVMValueRef, 1))) = llvmFieldIndex; - - let res = cast(*StructField, arena_alloc((*c).arena, sizeof(StructField))); - - let x = codegen_get_llvm_type(c, typ); - assert(x != cast(*LLVMTypeRef, null)); - (*res).value = LLVMBuildGEP2((*c).builder, *x, (*ptr).value, indices, 2, name); - let no = *(struc_type.fields + cast(**Node, *fieldIndex)); - assert((*no).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER); - let no_d = *cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*no).data); - (*res).type = no_d.type; - - return res; -}; - -let codegen_generate_expression_value = (c: *codegen, expression: *Node, name: *i8) => *Variable { - if ((*expression).type == NODE_PRIMARY_EXPRESSION_NULL) { - let inner_type_data = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*inner_type_data).name = "void"; - let inner_type = Node{}; - inner_type.type = NODE_TYPE_SIMPLE_TYPE; - inner_type.data = cast(*void, inner_type_data); - - let node_type_data = cast(*NODE_TYPE_POINTER_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_POINTER_TYPE_DATA))); - (*node_type_data).type = create_node(c, inner_type); - let node_type = Node{}; - node_type.type = NODE_TYPE_POINTER_TYPE; - node_type.data = cast(*void, node_type_data); - - return codegen_generate_literal(c, LLVMConstNull(LLVMPointerType(LLVMInt8Type(), 0)), name, expression, create_node(c, node_type)); - }; - - if ((*expression).type == NODE_PRIMARY_EXPRESSION_NUMBER) { - let n = (*cast(*NODE_PRIMARY_EXPRESSION_NUMBER_DATA, (*expression).data)).value; - - let node_type = Node{}; - node_type.type = NODE_TYPE_SIMPLE_TYPE; - - let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*d).name = "i64"; - (*d).underlying_type = cast(*Node, null); - node_type.data = cast(*void, d); - - return codegen_generate_literal(c, LLVMConstInt(LLVMInt64Type(), n, 0), name, expression, create_node(c, node_type)); - }; - - if ((*expression).type == NODE_PRIMARY_EXPRESSION_BOOLEAN) { - let b = (*cast(*NODE_PRIMARY_EXPRESSION_BOOLEAN_DATA, (*expression).data)).value; - - let node_type = Node{}; - node_type.type = NODE_TYPE_SIMPLE_TYPE; - - let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*d).name = "bool"; - (*d).underlying_type = cast(*Node, null); - node_type.data = cast(*void, d); - - let int_value = 0; - if b == true { - int_value = 1; - }; - - return codegen_generate_literal(c, LLVMConstInt(LLVMInt1Type(), int_value, 0), name, expression, create_node(c, node_type)); - }; - - if ((*expression).type == NODE_PRIMARY_EXPRESSION_CHAR) { - let ch = cast(i64, (*cast(*NODE_PRIMARY_EXPRESSION_CHAR_DATA, (*expression).data)).value); - - let node_type = Node{}; - node_type.type = NODE_TYPE_SIMPLE_TYPE; - - let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*d).name = "i8"; - (*d).underlying_type = cast(*Node, null); - node_type.data = cast(*void, d); - - return codegen_generate_literal(c, LLVMConstInt(LLVMInt8Type(), cast(i64, ch), 0), name, expression, create_node(c, node_type)); - }; - - if ((*expression).type == NODE_PRIMARY_EXPRESSION_STRING) { - let str = (*cast(*NODE_PRIMARY_EXPRESSION_STRING_DATA, (*expression).data)).value; - - let x = LLVMBuildGlobalStringPtr((*c).builder, str, ""); - - let inner_type_data = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*inner_type_data).name = "i8"; - let inner_type = Node{}; - inner_type.type = NODE_TYPE_SIMPLE_TYPE; - inner_type.data = cast(*void, inner_type_data); - - let node_type_data = cast(*NODE_TYPE_POINTER_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_POINTER_TYPE_DATA))); - (*node_type_data).type = create_node(c, inner_type); - let node_type = Node{}; - node_type.type = NODE_TYPE_POINTER_TYPE; - node_type.data = cast(*void, node_type_data); - - let v = Variable{}; - v.value = x; - v.type = cast(LLVMTypeRef, null); - v.stack_level = cast(*i64, null); - v.node = expression; - v.node_type = create_node(c, node_type); - - return codegen_create_variable(c, v); - }; - - if ((*expression).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER) { - let identifier = *cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*expression).data); - let variable = environment_get_variable((*c).environment, identifier.name); - assert(variable != cast(*Variable, null)); - let param_value = (*variable).value; - let v_type = (*variable).node_type; - - let done = false; - if (*v_type).type != NODE_TYPE_FUNCTION_TYPE { - let param_type = codegen_get_llvm_type(c, v_type); - assert(param_type != cast(*LLVMTypeRef, null)); - if (*v_type).type == NODE_TYPE_FUNCTION_TYPE { - (*param_type) = LLVMPointerType(*param_type, 0); - }; - param_value = LLVMBuildLoad2((*c).builder, *param_type, (*variable).value, ""); - done = true; - }; - - if !done { - if (*(*variable).stack_level) != 0 { - let param_type = codegen_get_llvm_type(c, v_type); - assert(param_type != cast(*LLVMTypeRef, null)); - if (*v_type).type == NODE_TYPE_FUNCTION_TYPE { - (*param_type) = LLVMPointerType(*param_type, 0); - }; - param_value = LLVMBuildLoad2((*c).builder, *param_type, (*variable).value, ""); - done = true; - }; - - }; - - return codegen_generate_literal(c, param_value, name, expression, (*variable).node_type); - }; - - if ((*expression).type == NODE_FUNCTION_DEFINITION) { - /* Functions should be declared "globally" */ - let builder_pos = LLVMGetInsertBlock((*c).builder); - - let llvm_param_types = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef) * 20)); - let param_types = cast(**Node, arena_alloc((*c).arena, sizeof(*Node) * 20)); - - let function_definition = *cast(*NODE_FUNCTION_DEFINITION_DATA, (*expression).data); - - let i = 0; - let is_varargs = 0; - while i < function_definition.parameters_len { - let node = *(function_definition.parameters + cast(**Node, i)); - assert((*node).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER); - let param = *cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*node).data); - let param_type = param.type; - if (*param_type).type == NODE_TYPE_SIMPLE_TYPE { - let simple_type = *(cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*param_type).data)); - if strcmp(simple_type.name, "varargs") { - is_varargs = 1; - }; - }; - let llvm_param_type = codegen_get_llvm_type(c, param_type); - assert(llvm_param_type != cast(*LLVMTypeRef, null)); - if (*param_type).type == NODE_TYPE_FUNCTION_TYPE { - (*llvm_param_type) = LLVMPointerType(*llvm_param_type, 0); - }; - - (*(llvm_param_types + cast(*LLVMTypeRef, i))) = *llvm_param_type; - (*(param_types + cast(**Node, i))) = param_type; - i = i + 1; - }; - - let f_ret = function_definition.retur_type; - let retur_type = codegen_get_llvm_type(c, f_ret); - assert(retur_type != cast(*LLVMTypeRef, null)); - if (*f_ret).type == NODE_TYPE_FUNCTION_TYPE { - (*retur_type) = LLVMPointerType(*retur_type, 0); - }; - - let function = cast(LLVMValueRef, null); - if name != cast(*i8, null) { - let v = environment_get_variable((*c).environment, name); - if (v != cast(*Variable, null)) { - function = (*v).value; - }; - }; - if function == cast(LLVMValueRef, null) { - let function_type = LLVMFunctionType(*retur_type, llvm_param_types, i, is_varargs); - let n_name = name; - if name == cast(*i8, null) { - n_name = "unnamed_func"; - }; - function = LLVMAddFunction((*c).llvm_module, n_name, function_type); - }; - - let function_entry = LLVMAppendBasicBlock(function, "entrypoint"); - LLVMPositionBuilderAtEnd((*c).builder, function_entry); - - environment_create_scope((*c).environment); - let last_function = (*c).current_function; - (*c).current_function = function; - let last_function_retur_type = (*c).current_function_retur_type; - (*c).current_function_retur_type = function_definition.retur_type; - - /* TODO: Defer. For now we do at the end */ - - let d = cast(*NODE_TYPE_FUNCTION_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_FUNCTION_TYPE_DATA))); - (*d).parameters = param_types; - (*d).parameters_len = i; - (*d).retur_type = function_definition.retur_type; - let n = Node{}; - let node_type = create_node(c, n); - (*node_type).type = NODE_TYPE_FUNCTION_TYPE; - (*node_type).data = cast(*void, d); - - /* Needed for recursive functions */ - if name != cast(*i8, null) { - let v = Variable{}; - v.value = function; - v.type = cast(LLVMTypeRef, null); - v.stack_level = cast(*i64, null); - v.node = expression; - v.node_type = node_type; - environment_add_variable((*c).environment, name, codegen_create_variable(c, v)); - }; - - let params = cast(*LLVMValueRef, arena_alloc((*c).arena, sizeof(LLVMValueRef) * function_definition.parameters_len)); - LLVMGetParams(function, params); - - let parameters_index = 0; - while parameters_index < function_definition.parameters_len { - let p = (*(params + cast(*LLVMValueRef, parameters_index))); - let param_node = *(function_definition.parameters + cast(**Node, parameters_index)); - assert((*param_node).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER); - let param = *cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*param_node).data); - let param_type = param.type; - let llvm_param_type = codegen_get_llvm_type(c, param_type); - assert(llvm_param_type != cast(*LLVMTypeRef, null)); - if (*param_type).type == NODE_TYPE_FUNCTION_TYPE { - (*llvm_param_type) = LLVMPointerType(*llvm_param_type, 0); - }; - let alloca = LLVMBuildAlloca((*c).builder, *llvm_param_type, param.name); - LLVMBuildStore((*c).builder, p, alloca); - - let v = Variable{}; - v.value = alloca; - v.type = cast(LLVMTypeRef, null); - v.stack_level = cast(*i64, null); - v.node = param_node; - v.node_type = param_type; - environment_add_variable((*c).environment, param.name, codegen_create_variable(c, v)); - parameters_index = parameters_index + 1; - }; - - i = 0; - while i < function_definition.statements_len { - let stmt = *(function_definition.statements + cast(**Node, i)); - - let res = codegen_generate_statement(c, stmt); - assert(res == 0); - - i = i + 1; - }; - - LLVMPositionBuilderAtEnd((*c).builder, builder_pos); - - let v = Variable{}; - v.value = function; - v.type = cast(LLVMTypeRef, null); - v.stack_level = cast(*i64, null); - v.node = expression; - v.node_type = node_type; - - /* TODO: Move to defer */ - (*c).current_function = last_function; - (*c).current_function_retur_type = last_function_retur_type; - environment_drop_scope((*c).environment); - - return codegen_create_variable(c, v); - }; - - if ((*expression).type == NODE_EQUALITY_EXPRESSION) { - let exp = (*(cast(*NODE_EQUALITY_EXPRESSION_DATA, (*expression).data))); - let lhs_value = codegen_generate_expression_value(c, exp.lhs, cast(*i8, null)); - assert(lhs_value != cast(*Variable, null)); - let rhs_value = codegen_generate_expression_value(c, exp.rhs, cast(*i8, null)); - assert(rhs_value != cast(*Variable, null)); - - assert(compare_types(c, (*lhs_value).node_type, (*rhs_value).node_type, false)); - - let op = -1; - - if exp.typ == EQUALITY_EXPRESSION_TYPE_EQ { - op = LLVMIntEQ; - }; - if exp.typ == EQUALITY_EXPRESSION_TYPE_NE { - op = LLVMIntNE; - }; - if exp.typ == EQUALITY_EXPRESSION_TYPE_GE { - op = LLVMIntSGE; - }; - if exp.typ == EQUALITY_EXPRESSION_TYPE_LE { - op = LLVMIntSLE; - }; - if exp.typ == EQUALITY_EXPRESSION_TYPE_LT { - op = LLVMIntSLT; - }; - if exp.typ == EQUALITY_EXPRESSION_TYPE_GT { - op = LLVMIntSGT; - }; - - assert(op != -1); - - let cmp = LLVMBuildICmp((*c).builder, cast(LLVMIntPredicate, op), (*lhs_value).value, (*rhs_value).value, ""); - - - let node_type = Node{}; - node_type.type = NODE_TYPE_SIMPLE_TYPE; - - let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*d).name = "bool"; - (*d).underlying_type = cast(*Node, null); - node_type.data = cast(*void, d); - - return codegen_generate_literal(c, cmp, name, expression, create_node(c, node_type)); - }; - - if ((*expression).type == NODE_ADDITIVE_EXPRESSION) { - let exp = (*(cast(*NODE_ADDITIVE_EXPRESSION_DATA, (*expression).data))); - let lhs_value = codegen_generate_expression_value(c, exp.lhs, cast(*i8, null)); - assert(lhs_value != cast(*Variable, null)); - let rhs_value = codegen_generate_expression_value(c, exp.rhs, cast(*i8, null)); - assert(rhs_value != cast(*Variable, null)); - - assert(compare_types(c, (*lhs_value).node_type, (*rhs_value).node_type, false)); - - let result = cast(LLVMValueRef, null); - let node_type = Node{}; - node_type.type = NODE_TYPE_SIMPLE_TYPE; - - let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*d).name = "i64"; - (*d).underlying_type = cast(*Node, null); - node_type.data = cast(*void, d); - - let pnode_type = create_node(c, node_type); - - if exp.addition { - let nt = (*lhs_value).node_type; - if (*nt).type == NODE_TYPE_POINTER_TYPE { - let ipt = cast(*NODE_TYPE_POINTER_TYPE_DATA, (*nt).data); - let llvmipt = codegen_get_llvm_type(c, (*ipt).type); - assert(llvmipt != cast(*LLVMTypeRef, null)); - let arr = cast(*LLVMValueRef, arena_alloc((*c).arena, sizeof(LLVMValueRef) * 1)); - (*(arr + cast(*LLVMValueRef, 0))) = (*rhs_value).value; - result = LLVMBuildGEP2((*c).builder, *llvmipt, (*lhs_value).value, arr, 1, ""); - pnode_type = (*lhs_value).node_type; - }; - if (*nt).type != NODE_TYPE_POINTER_TYPE { - result = LLVMBuildAdd((*c).builder, (*lhs_value).value, (*rhs_value).value, ""); - }; - - }; - if !exp.addition { - result = LLVMBuildSub((*c).builder, (*lhs_value).value, (*rhs_value).value, ""); - }; - - return codegen_generate_literal(c, result, name, expression, pnode_type); - }; - - if ((*expression).type == NODE_MULTIPLICATIVE_EXPRESSION) { - let exp = (*(cast(*NODE_MULTIPLICATIVE_EXPRESSION_DATA, (*expression).data))); - let lhs_value = codegen_generate_expression_value(c, exp.lhs, cast(*i8, null)); - assert(lhs_value != cast(*Variable, null)); - let rhs_value = codegen_generate_expression_value(c, exp.rhs, cast(*i8, null)); - assert(rhs_value != cast(*Variable, null)); - - assert(compare_types(c, (*lhs_value).node_type, (*rhs_value).node_type, false)); - - let result = cast(LLVMValueRef, null); - - if exp.typ == MULTIPLICATIVE_EXPRESSION_TYPE_MUL { - result = LLVMBuildMul((*c).builder, (*lhs_value).value, (*rhs_value).value, ""); - }; - if exp.typ == MULTIPLICATIVE_EXPRESSION_TYPE_DIV { - result = LLVMBuildSDiv((*c).builder, (*lhs_value).value, (*rhs_value).value, ""); - }; - if exp.typ == MULTIPLICATIVE_EXPRESSION_TYPE_MOD { - result = LLVMBuildSRem((*c).builder, (*lhs_value).value, (*rhs_value).value, ""); - }; - assert(result != cast(LLVMValueRef, null)); - - return codegen_generate_literal(c, result, name, expression, (*lhs_value).node_type); - }; - - if ((*expression).type == NODE_UNARY_EXPRESSION) { - let exp = (*(cast(*NODE_UNARY_EXPRESSION_DATA, (*expression).data))); - let k = codegen_generate_expression_value(c, exp.expression, cast(*i8, null)); - assert(k != cast(*Variable, null)); - - let r = cast(LLVMValueRef, null); - let typ = (*k).node_type; - - if exp.typ == UNARY_EXPRESSION_TYPE_NOT { - assert((*typ).type == NODE_TYPE_SIMPLE_TYPE); - let simple_type = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*typ).data); - assert(strcmp(simple_type.name, "bool")); - r = LLVMBuildICmp((*c).builder, cast(LLVMIntPredicate, LLVMIntEQ), (*k).value, LLVMConstInt(LLVMInt1Type(), 0, 0), ""); - let node_type = Node{}; - node_type.type = NODE_TYPE_SIMPLE_TYPE; - - let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*d).name = "bool"; - (*d).underlying_type = cast(*Node, null); - node_type.data = cast(*void, d); - typ = create_node(c, node_type); - }; - - if exp.typ == UNARY_EXPRESSION_TYPE_MINUS { - r = LLVMBuildNeg((*c).builder, (*k).value, ""); - let node_type = Node{}; - node_type.type = NODE_TYPE_SIMPLE_TYPE; - - let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*d).name = "i64"; - (*d).underlying_type = cast(*Node, null); - node_type.data = cast(*void, d); - typ = create_node(c, node_type); - }; - - if exp.typ == UNARY_EXPRESSION_TYPE_STAR { - assert((*typ).type == NODE_TYPE_POINTER_TYPE); - let n = (*k).node_type; - typ = (*cast(*NODE_TYPE_POINTER_TYPE_DATA, (*n).data)).type; - let ptr_type = codegen_get_llvm_type(c, typ); - assert(ptr_type != cast(*LLVMTypeRef, null)); - r = LLVMBuildLoad2((*c).builder, *ptr_type, (*k).value, ""); - }; - - return codegen_generate_literal(c, r, name, expression, typ); - }; - - if ((*expression).type == NODE_TYPE_FUNCTION_TYPE) { - let e = *((*c).environment); - assert(e.scope_stack_len == 1); - - let existing = environment_get_variable((*c).environment, name); - if (existing != cast(*Variable, null)) { - return existing; - }; - - let function_type = codegen_get_llvm_type(c, expression); - assert(function_type != cast(*LLVMTypeRef, null)); - let function = LLVMAddFunction((*c).llvm_module, name, *function_type); - let v = Variable{}; - v.value = function; - v.type = cast(LLVMTypeRef, null); - v.stack_level = cast(*i64, null); - v.node = expression; - v.node_type = expression; - return codegen_create_variable(c, v); - }; - - if ((*expression).type == NODE_FUNCTION_CALL_STATEMENT) { - return codegen_generate_function_call_statement(c, expression); - }; - - if ((*expression).type == NODE_CAST_STATEMENT) { - let exp = *cast(*NODE_CAST_STATEMENT_DATA, (*expression).data); - let val = codegen_generate_expression_value(c, exp.expression, ""); - assert(val != cast(*Variable, null)); - let v = Variable{}; - v.value = (*val).value; /* TODO: Do real casting */ - v.type = cast(LLVMTypeRef, null); - v.stack_level = cast(*i64, null); - v.node = expression; - v.node_type = exp.typ; - return codegen_create_variable(c, v); - }; - - if ((*expression).type == NODE_SIZEOF_STATEMENT) { - let exp = *cast(*NODE_SIZEOF_STATEMENT_DATA, (*expression).data); - let typ = codegen_get_llvm_type(c, exp.typ); - assert(typ != cast(*LLVMTypeRef, null)); - let size_in_bytes = LLVMStoreSizeOfType((*c).llvm_target_data, *typ); - let size_val = LLVMConstInt(LLVMInt64Type(), size_in_bytes, 0); - - let node_type = Node{}; - node_type.type = NODE_TYPE_SIMPLE_TYPE; - - let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*d).name = "i64"; - (*d).underlying_type = cast(*Node, null); - node_type.data = cast(*void, d); - - let v = Variable{}; - v.value = size_val; - v.type = cast(LLVMTypeRef, null); - v.stack_level = cast(*i64, null); - v.node = expression; - v.node_type = create_node(c, node_type); - return codegen_create_variable(c, v); - }; - - if ((*expression).type == NODE_TYPE_STRUCT_TYPE) { - let struc_data = *cast(*NODE_TYPE_STRUCT_TYPE_DATA, (*expression).data); - let dd = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*c).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*dd).name = name; - (*dd).underlying_type = expression; - let n = Node{}; - n.type = NODE_TYPE_SIMPLE_TYPE; - n.data = cast(*void, dd); - let simple_type_node = create_node(c, n); - - let struc_type = LLVMStructCreateNamed((*c).llvm_context, name); - - if name != cast(*i8, null) { - let v = Variable{}; - v.value = cast(LLVMValueRef, null); - v.type = struc_type; - v.stack_level = cast(*i64, null); - v.node = expression; - v.node_type = simple_type_node; - environment_add_variable((*c).environment, name, codegen_create_variable(c, v)); - }; - - let llvm_types = cast(*LLVMTypeRef, arena_alloc((*c).arena, sizeof(LLVMTypeRef) * 20)); - let i = 0; - while i < struc_data.fields_len { - let field = *(struc_data.fields + cast(**Node, i)); - assert((*field).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER); - let t = (*cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*field).data)).type; - let lt = codegen_get_llvm_type(c, t); - assert(lt != cast(*LLVMTypeRef, null)); - (*(llvm_types + cast(*LLVMTypeRef, i))) = *lt; - i = i + 1; - }; - - LLVMStructSetBody(struc_type, llvm_types, i, 0); - - let v = Variable{}; - v.value = cast(LLVMValueRef, null); - v.type = struc_type; - v.stack_level = cast(*i64, null); - v.node = expression; - v.node_type = simple_type_node; - return codegen_create_variable(c, v); - }; - - if ((*expression).type == NODE_TYPE_SIMPLE_TYPE) { - let simple_type_data = *cast(*NODE_TYPE_SIMPLE_TYPE_DATA, (*expression).data); - let typ = codegen_get_llvm_type(c, simple_type_data.underlying_type); - assert(typ != cast(*LLVMTypeRef, null)); - let v = Variable{}; - v.value = cast(LLVMValueRef, null); - v.type = *typ; - v.stack_level = cast(*i64, null); - v.node = expression; - v.node_type = simple_type_data.underlying_type; - return codegen_create_variable(c, v); - }; - - if ((*expression).type == NODE_STRUCT_INSTANCIATION) { - let struc_data = *cast(*NODE_STRUCT_INSTANCIATION_DATA, (*expression).data); - let v = environment_get_variable((*c).environment, struc_data.typ); - assert(v != cast(*Variable, null)); - return v; - }; - - if ((*expression).type == NODE_FIELD_ACCESS) { - let field_access = *cast(*NODE_FIELD_ACCESS_DATA, (*expression).data); - let x = codegen_get_struct_field(c, field_access.expression, field_access.name); - assert(x != cast(*StructField, null)); - let t = codegen_get_llvm_type(c, (*x).type); - assert(t != cast(*LLVMTypeRef, null)); - let loaded = LLVMBuildLoad2((*c).builder, *t, (*x).value, ""); - let v = Variable{}; - v.value = loaded; - v.type = cast(LLVMTypeRef, null); - v.stack_level = cast(*i64, null); - v.node = expression; - v.node_type = (*x).type; - return codegen_create_variable(c, v); - }; - - printf("ASSERT 1: %d\n", (*expression).type); - assert(false); - - return cast(*Variable, null); -}; - -let codegen_generate_assignment_statement = (c: *codegen, stmt: *NODE_ASSIGNMENT_STATEMENT_DATA) => i64 { - let lhs = *((*stmt).lhs); - let prhs = (*stmt).rhs; - - if (lhs.type == NODE_PRIMARY_EXPRESSION_IDENTIFIER) { - let identifier = (*cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, lhs.data)).name; - let variable = codegen_generate_expression_value(c, prhs, identifier); - assert(variable != cast(*Variable, null)); - - let env = (*(*c).environment); - if env.scope_stack_len == 1 { - environment_add_variable((*c).environment, identifier, variable); - return 0; - }; - - let ptr = cast(LLVMValueRef, null); - let typ = (*variable).node_type; - - if (*stmt).is_declaration { - let x = codegen_get_llvm_type(c, typ); - assert(x != cast(*LLVMTypeRef, null)); - if (*typ).type == NODE_TYPE_FUNCTION_TYPE { - *x = LLVMPointerType(*x, 0); - }; - ptr = LLVMBuildAlloca((*c).builder, *x, identifier); - }; - if !(*stmt).is_declaration { - let v = environment_get_variable((*c).environment, identifier); - assert(v != cast(*Variable, null)); - ptr = (*v).value; - typ = (*v).node_type; - /* TODO: Do this in more places! (everywhere get_llvm_type or get_variable?) Also check types in return and cmp */ - assert(compare_types(c, typ, (*variable).node_type, (*stmt).is_dereference)); - }; - - if (*stmt).is_dereference { - let ltyp = codegen_get_llvm_type(c, typ); - assert(ltyp != cast(*LLVMTypeRef, null)); - ptr = LLVMBuildLoad2((*c).builder, *ltyp, ptr, ""); - }; - - /* NOTE: structs have a null variable.value */ - if (*variable).value != cast(LLVMValueRef, null) { - LLVMBuildStore((*c).builder, (*variable).value, ptr); - }; - - if (*stmt).is_dereference { - let v = environment_get_variable((*c).environment, identifier); - assert(v != cast(*Variable, null)); - ptr = (*v).value; - }; - - let new_variable = Variable{}; - - new_variable.value = ptr; - new_variable.type = (*variable).type; - new_variable.stack_level = cast(*i64, null); - new_variable.node = (*variable).node; - new_variable.node_type = typ; - - if (*stmt).is_declaration { - environment_add_variable((*c).environment, identifier, codegen_create_variable(c, new_variable)); - }; - if !(*stmt).is_declaration { - environment_set_variable((*c).environment, identifier, codegen_create_variable(c, new_variable)); - }; - - return 0; - }; - - if (lhs.type == NODE_UNARY_EXPRESSION) { - let xd = (*cast(*NODE_UNARY_EXPRESSION_DATA, lhs.data)).expression; - let a = codegen_generate_expression_value(c, xd, cast(*i8, null)); - assert(a != cast(*Variable, null)); - let variable = codegen_generate_expression_value(c, prhs, cast(*i8, null)); - assert(variable != cast(*Variable, null)); - assert(compare_types(c, (*a).node_type, (*variable).node_type, true)); - LLVMBuildStore((*c).builder, (*variable).value, (*a).value); - - return 0; - }; - - if (lhs.type == NODE_FIELD_ACCESS) { - let field_access = (*cast(*NODE_FIELD_ACCESS_DATA, lhs.data)); - let xd = field_access.expression; - let name = field_access.name; - - let x = codegen_get_struct_field(c, xd, name); - assert(x != cast(*StructField, null)); - - let variable = codegen_generate_expression_value(c, prhs, cast(*i8, null)); - assert(compare_types(c, (*x).type, (*variable).node_type, (*stmt).is_dereference)); - LLVMBuildStore((*c).builder, (*variable).value, (*x).value); - - return 0; - }; - - printf("ASSERT 2 %d\n", lhs.type); - assert(false); - return 0; -}; - -let codegen_generate_return_statement = (c: *codegen, stmt: *NODE_RETURN_STATEMENT_DATA) => i64 { - let expression = (*stmt).expression; - - if expression == cast(*Node, null) { - LLVMBuildRetVoid((*c).builder); - return 0; - }; - - let val = codegen_generate_expression_value(c, expression, cast(*i8, null)); - assert(val != cast(*Variable, null)); - - assert(compare_types(c, (*c).current_function_retur_type, (*val).node_type, false)); - - LLVMBuildRet((*c).builder, (*val).value); - - return 0; -}; - -let get_function_return_type = (ic: *codegen, fun: *Node) => *Node { - if (*fun).type == NODE_FUNCTION_DEFINITION { - let d = cast(*NODE_FUNCTION_DEFINITION_DATA, (*fun).data); - return (*d).retur_type; - }; - if (*fun).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER { - let d = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*fun).data); - let f = environment_get_variable((*ic).environment, (*d).name); - if f == cast(*Variable, null) { - printf("NO variable 2: %s\n", (*d).name); - assert(false); - }; - let f_type = (*f).node_type; - assert((*f_type).type == NODE_TYPE_FUNCTION_TYPE); - return get_function_return_type(ic, f_type); - }; - if (*fun).type == NODE_TYPE_FUNCTION_TYPE { - let d = cast(*NODE_TYPE_FUNCTION_TYPE_DATA, (*fun).data); - return (*d).retur_type; - }; - assert(false); - return cast(*Node, null); -}; - -let codegen_generate_function_call_statement = (c: *codegen, statement: *Node) => *Variable { - assert((*statement).type == NODE_FUNCTION_CALL_STATEMENT); - let stmt = cast(*NODE_FUNCTION_CALL_STATEMENT_DATA, (*statement).data); - let expression = (*stmt).expression; - - let node = statement; - let function = cast(*Variable, null); - - if (*expression).type == NODE_PRIMARY_EXPRESSION_IDENTIFIER { - let ident = (*cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, (*expression).data)); - function = environment_get_variable((*c).environment, ident.name); - if function == cast(*Variable, null) { - printf("NO variable 1: %s\n", ident.name); - assert(false); - }; - - if LLVMGetValueKind((*function).value) != LLVMFunctionValueKind { - let lt = codegen_get_llvm_type(c, (*function).node_type); - assert(lt != cast(*LLVMTypeRef, null)); - (*function).value = LLVMBuildLoad2((*c).builder, LLVMPointerType(*lt, 0), (*function).value, ""); - node = (*function).node; - }; - }; - if (*expression).type == NODE_FUNCTION_DEFINITION { - function = codegen_generate_expression_value(c, expression, cast(*i8, null)); - }; - - assert(function != cast(*Variable, null)); - assert((*function).node_type != cast(*Node, null)); - let function_type = (*function).node_type; - assert((*function_type).type == NODE_TYPE_FUNCTION_TYPE); - let function_type_data = cast(*NODE_TYPE_FUNCTION_TYPE_DATA, (*function_type).data); - /* assert((*function_type_data).parameters_len == (*stmt).arguments_len); TODO: Varargs */ - - let arguments = cast(*LLVMValueRef, arena_alloc((*c).arena, sizeof(LLVMValueRef) * (*stmt).arguments_len)); - - let i = 0; - while i < (*stmt).arguments_len { - let argument = (*((*stmt).arguments + cast(**Node, i))); - let arg = codegen_generate_expression_value(c, argument, cast(*i8, null)); - assert(arg != cast(*Variable, null)); - let expected_type = *((*function_type_data).parameters + cast(**Node, i)); /* TODO: If varargs we shouldn't do this */ - - assert(compare_types(c, expected_type, (*arg).node_type, false)); - - (*(arguments + cast(*LLVMValueRef, i))) = (*arg).value; - - i = i + 1; - }; - - let function_type = codegen_get_llvm_type(c, (*function).node_type); - assert(function_type != cast(*LLVMTypeRef, null)); - - let res = LLVMBuildCall2((*c).builder, *function_type, (*function).value, arguments, i, ""); - - let function_return_type = get_function_return_type(c, (*function).node_type); - - let v = Variable{}; - - v.value = res; - v.type = cast(LLVMTypeRef, null); - v.stack_level = cast(*i64, null); - v.node = node; - v.node_type = function_return_type; - - return codegen_create_variable(c, v); -}; - -let codegen_generate_break_statement = (c: *codegen) => i64 { - assert((*c).whil_loop_exit != cast(LLVMBasicBlockRef, null)); - LLVMBuildBr((*c).builder, (*c).whil_loop_exit); - return 0; -}; - -let codegen_generate_continue_statement = (c: *codegen) => i64 { - assert((*c).whil_block != cast(LLVMBasicBlockRef, null)); - LLVMBuildBr((*c).builder, (*c).whil_block); - return 0; -}; - -let codegen_generate_if_statement = (c: *codegen, statement: *NODE_IF_STATEMENT_DATA) => *void { - let condition_value = codegen_generate_expression_value(c, (*statement).condition, cast(*i8, null)); - assert(condition_value != cast(*Variable, null)); - - let current_block = LLVMGetInsertBlock((*c).builder); - - let then_block = LLVMAppendBasicBlock((*c).current_function, "then_block"); - LLVMPositionBuilderAtEnd((*c).builder, then_block); - - let i = 0; - while i < (*statement).statements_len { - let stmt = (*((*statement).statements + cast(**Node, i))); - let res = codegen_generate_statement(c, stmt); - assert(res == 0); - i = i + 1; - }; - - let merge_block = LLVMAppendBasicBlock((*c).current_function, "merge_block"); - let last_instr = LLVMGetLastInstruction(LLVMGetInsertBlock((*c).builder)); - if last_instr == cast(LLVMValueRef, null) { - LLVMBuildBr((*c).builder, merge_block); - }; - if last_instr != cast(LLVMValueRef, null) { - if LLVMIsATerminatorInst(last_instr) == cast(LLVMValueRef, null) { - LLVMBuildBr((*c).builder, merge_block); - }; - }; - LLVMPositionBuilderAtEnd((*c).builder, current_block); - LLVMBuildCondBr((*c).builder, (*condition_value).value, then_block, merge_block); - LLVMPositionBuilderAtEnd((*c).builder, merge_block); - - return null; -}; - -let codegen_generate_while_statement = (c: *codegen, statement: *NODE_WHILE_STATEMENT_DATA) => *void { - let whil_block = LLVMAppendBasicBlock((*c).current_function, "while_block"); - LLVMBuildBr((*c).builder, whil_block); - LLVMPositionBuilderAtEnd((*c).builder, whil_block); - - let condition_value = codegen_generate_expression_value(c, (*statement).condition, cast(*i8, null)); - assert(condition_value != cast(*Variable, null)); - - let inner_block = LLVMAppendBasicBlock((*c).current_function, "inner_block"); - let outer_block = LLVMAppendBasicBlock((*c).current_function, "outer_block"); - LLVMBuildCondBr((*c).builder, (*condition_value).value, inner_block, outer_block); - - (*c).whil_loop_exit = outer_block; - (*c).whil_block = whil_block; - - LLVMPositionBuilderAtEnd((*c).builder, inner_block); - let i = 0; - while i < (*statement).statements_len { - let stmt = (*((*statement).statements + cast(**Node, i))); - let res = codegen_generate_statement(c, stmt); - assert(res == 0); - i = i + 1; - }; - - LLVMBuildBr((*c).builder, whil_block); - LLVMPositionBuilderAtEnd((*c).builder, outer_block); - - (*c).whil_loop_exit = cast(LLVMBasicBlockRef, null); - (*c).whil_block = cast(LLVMBasicBlockRef, null); - - return null; -}; - -extern codegen_generate = (*codegen, *Node) => i64; - -let codegen_generate_import_declaration = (c: *codegen, statement: *NODE_IMPORT_DECLARATION_DATA) => i64 { - return codegen_generate(c, (*statement).program); -}; - -let codegen_generate_statement = (c: *codegen, statement: *Node) => i64 { - let stmt = *statement; - - if stmt.type == NODE_ASSIGNMENT_STATEMENT { - return codegen_generate_assignment_statement(c, cast(*NODE_ASSIGNMENT_STATEMENT_DATA, stmt.data)); - }; - - if stmt.type == NODE_RETURN_STATEMENT { - return codegen_generate_return_statement(c, cast(*NODE_RETURN_STATEMENT_DATA, stmt.data)); - }; - - if stmt.type == NODE_FUNCTION_CALL_STATEMENT { - codegen_generate_function_call_statement(c, statement); - return 0; - }; - - if stmt.type == NODE_IF_STATEMENT { - codegen_generate_if_statement(c, cast(*NODE_IF_STATEMENT_DATA, stmt.data)); - return 0; - }; - - if stmt.type == NODE_WHILE_STATEMENT { - codegen_generate_while_statement(c, cast(*NODE_WHILE_STATEMENT_DATA, stmt.data)); - return 0; - }; - - if stmt.type == NODE_IMPORT_DECLARATION { - return codegen_generate_import_declaration(c, cast(*NODE_IMPORT_DECLARATION_DATA, stmt.data)); - }; - - if stmt.type == NODE_CONTINUE_STATEMENT { - return codegen_generate_continue_statement(c); - }; - - if stmt.type == NODE_BREAK_STATEMENT { - return codegen_generate_break_statement(c); - }; - - printf("ASSERT 3 %d\n", stmt.type); - assert(false); - - return 0; -}; - -let codegen_generate = (c: *codegen, ast: *Node) => i64 { - assert((*ast).type == NODE_PROGRAM); - - let program = *cast(*NODE_PROGRAM_DATA, (*ast).data); - - let i = 0; - while i < program.statements_len { - let stmt = *(program.statements + cast(**Node, i)); - - let res = codegen_generate_statement(c, stmt); - if res != 0 { - return 1; - }; - - i = i + 1; - }; - - return 0; -}; - -let codegen_compile = (c: *codegen, dump_ir: bool) => i64 { - /* Dump module */ - LLVMDumpModule((*c).llvm_module); - let message = cast(**i8, null); - - if dump_ir { - LLVMPrintModuleToFile((*c).llvm_module, "output.ll", message); - return 0; - }; - - /* Generate code */ - let triple = LLVMGetDefaultTargetTriple(); - let target_ref = cast(*LLVMTargetRef, arena_alloc((*c).arena, sizeof(*LLVMTargetRef))); - let result = LLVMGetTargetFromTriple(triple, target_ref, message); - if result != 0 { - printf("Target output: %s\n", *message); - LLVMDisposeMessage(*message); - }; - let target_machine = LLVMCreateTargetMachine( - *target_ref, - triple, - "", - "", - LLVMCodeGenLevelDefault, - LLVMRelocDefault, - LLVMCodeModelDefault, - ); - LLVMDisposeMessage(triple); - result = LLVMVerifyModule((*c).llvm_module, LLVMAbortProcessAction, message); - if result != 0 { - printf("Verification output: %s\n", *message); - LLVMDisposeMessage(*message); - }; - - /* Generate the object file */ - let filename = "bootstrap_output.o"; - LLVMTargetMachineEmitToFile( - target_machine, - (*c).llvm_module, - filename, - LLVMObjectFile, - cast(**i8, null), - ); - LLVMDisposeTargetMachine(target_machine); - printf("Object file generated: %s\n", filename); - - return 0; -}; - -let codegen_deinit = (c: *codegen) => void { - LLVMDisposeModule((*c).llvm_module); - LLVMShutdown(); - LLVMDisposeBuilder((*c).builder); - return; -}; diff --git a/src/bootstrap/llvm.pry b/src/bootstrap/llvm.pry deleted file mode 100644 index 2feb815..0000000 --- a/src/bootstrap/llvm.pry +++ /dev/null @@ -1,353 +0,0 @@ -extern LLVMInitializeAArch64TargetInfo = () => void; -extern LLVMInitializeAMDGPUTargetInfo = () => void; -extern LLVMInitializeARMTargetInfo = () => void; -extern LLVMInitializeAVRTargetInfo = () => void; -extern LLVMInitializeBPFTargetInfo = () => void; -extern LLVMInitializeHexagonTargetInfo = () => void; -extern LLVMInitializeLanaiTargetInfo = () => void; -extern LLVMInitializeLoongArchTargetInfo = () => void; -extern LLVMInitializeMipsTargetInfo = () => void; -extern LLVMInitializeMSP430TargetInfo = () => void; -extern LLVMInitializeNVPTXTargetInfo = () => void; -extern LLVMInitializePowerPCTargetInfo = () => void; -extern LLVMInitializeRISCVTargetInfo = () => void; -extern LLVMInitializeSparcTargetInfo = () => void; -extern LLVMInitializeSystemZTargetInfo = () => void; -extern LLVMInitializeVETargetInfo = () => void; -extern LLVMInitializeWebAssemblyTargetInfo = () => void; -extern LLVMInitializeX86TargetInfo = () => void; -extern LLVMInitializeXCoreTargetInfo = () => void; - -let LLVMInitializeAllTargetInfos = () => void { - LLVMInitializeAArch64TargetInfo(); - LLVMInitializeAMDGPUTargetInfo(); - LLVMInitializeARMTargetInfo(); - LLVMInitializeAVRTargetInfo(); - LLVMInitializeBPFTargetInfo(); - LLVMInitializeHexagonTargetInfo(); - LLVMInitializeLanaiTargetInfo(); - LLVMInitializeLoongArchTargetInfo(); - LLVMInitializeMipsTargetInfo(); - LLVMInitializeMSP430TargetInfo(); - LLVMInitializeNVPTXTargetInfo(); - LLVMInitializePowerPCTargetInfo(); - LLVMInitializeRISCVTargetInfo(); - LLVMInitializeSparcTargetInfo(); - LLVMInitializeSystemZTargetInfo(); - LLVMInitializeVETargetInfo(); - LLVMInitializeWebAssemblyTargetInfo(); - LLVMInitializeX86TargetInfo(); - LLVMInitializeXCoreTargetInfo(); - return; -}; - -extern LLVMInitializeAArch64Target = () => void; -extern LLVMInitializeAMDGPUTarget = () => void; -extern LLVMInitializeARMTarget = () => void; -extern LLVMInitializeAVRTarget = () => void; -extern LLVMInitializeBPFTarget = () => void; -extern LLVMInitializeHexagonTarget = () => void; -extern LLVMInitializeLanaiTarget = () => void; -extern LLVMInitializeLoongArchTarget = () => void; -extern LLVMInitializeMipsTarget = () => void; -extern LLVMInitializeMSP430Target = () => void; -extern LLVMInitializeNVPTXTarget = () => void; -extern LLVMInitializePowerPCTarget = () => void; -extern LLVMInitializeRISCVTarget = () => void; -extern LLVMInitializeSparcTarget = () => void; -extern LLVMInitializeSystemZTarget = () => void; -extern LLVMInitializeVETarget = () => void; -extern LLVMInitializeWebAssemblyTarget = () => void; -extern LLVMInitializeX86Target = () => void; -extern LLVMInitializeXCoreTarget = () => void; - -let LLVMInitializeAllTargets = () => void { - LLVMInitializeAArch64Target(); - LLVMInitializeAMDGPUTarget(); - LLVMInitializeARMTarget(); - LLVMInitializeAVRTarget(); - LLVMInitializeBPFTarget(); - LLVMInitializeHexagonTarget(); - LLVMInitializeLanaiTarget(); - LLVMInitializeLoongArchTarget(); - LLVMInitializeMipsTarget(); - LLVMInitializeMSP430Target(); - LLVMInitializeNVPTXTarget(); - LLVMInitializePowerPCTarget(); - LLVMInitializeRISCVTarget(); - LLVMInitializeSparcTarget(); - LLVMInitializeSystemZTarget(); - LLVMInitializeVETarget(); - LLVMInitializeWebAssemblyTarget(); - LLVMInitializeX86Target(); - LLVMInitializeXCoreTarget(); - return; -}; - -extern LLVMInitializeAArch64TargetMC = () => void; -extern LLVMInitializeAMDGPUTargetMC = () => void; -extern LLVMInitializeARMTargetMC = () => void; -extern LLVMInitializeAVRTargetMC = () => void; -extern LLVMInitializeBPFTargetMC = () => void; -extern LLVMInitializeHexagonTargetMC = () => void; -extern LLVMInitializeLanaiTargetMC = () => void; -extern LLVMInitializeLoongArchTargetMC = () => void; -extern LLVMInitializeMipsTargetMC = () => void; -extern LLVMInitializeMSP430TargetMC = () => void; -extern LLVMInitializeNVPTXTargetMC = () => void; -extern LLVMInitializePowerPCTargetMC = () => void; -extern LLVMInitializeRISCVTargetMC = () => void; -extern LLVMInitializeSparcTargetMC = () => void; -extern LLVMInitializeSystemZTargetMC = () => void; -extern LLVMInitializeVETargetMC = () => void; -extern LLVMInitializeWebAssemblyTargetMC = () => void; -extern LLVMInitializeX86TargetMC = () => void; -extern LLVMInitializeXCoreTargetMC = () => void; - -let LLVMInitializeAllTargetMCs = () => void { - LLVMInitializeAArch64TargetMC(); - LLVMInitializeAMDGPUTargetMC(); - LLVMInitializeARMTargetMC(); - LLVMInitializeAVRTargetMC(); - LLVMInitializeBPFTargetMC(); - LLVMInitializeHexagonTargetMC(); - LLVMInitializeLanaiTargetMC(); - LLVMInitializeLoongArchTargetMC(); - LLVMInitializeMipsTargetMC(); - LLVMInitializeMSP430TargetMC(); - LLVMInitializeNVPTXTargetMC(); - LLVMInitializePowerPCTargetMC(); - LLVMInitializeRISCVTargetMC(); - LLVMInitializeSparcTargetMC(); - LLVMInitializeSystemZTargetMC(); - LLVMInitializeVETargetMC(); - LLVMInitializeWebAssemblyTargetMC(); - LLVMInitializeX86TargetMC(); - LLVMInitializeXCoreTargetMC(); - return; -}; - -extern LLVMInitializeAArch64AsmPrinter = () => void; -extern LLVMInitializeAMDGPUAsmPrinter = () => void; -extern LLVMInitializeARMAsmPrinter = () => void; -extern LLVMInitializeAVRAsmPrinter = () => void; -extern LLVMInitializeBPFAsmPrinter = () => void; -extern LLVMInitializeHexagonAsmPrinter = () => void; -extern LLVMInitializeLanaiAsmPrinter = () => void; -extern LLVMInitializeLoongArchAsmPrinter = () => void; -extern LLVMInitializeMipsAsmPrinter = () => void; -extern LLVMInitializeMSP430AsmPrinter = () => void; -extern LLVMInitializeNVPTXAsmPrinter = () => void; -extern LLVMInitializePowerPCAsmPrinter = () => void; -extern LLVMInitializeRISCVAsmPrinter = () => void; -extern LLVMInitializeSparcAsmPrinter = () => void; -extern LLVMInitializeSystemZAsmPrinter = () => void; -extern LLVMInitializeVEAsmPrinter = () => void; -extern LLVMInitializeWebAssemblyAsmPrinter = () => void; -extern LLVMInitializeX86AsmPrinter = () => void; -extern LLVMInitializeXCoreAsmPrinter = () => void; - -let LLVMInitializeAllAsmPrinters = () => void { - LLVMInitializeAArch64AsmPrinter(); - LLVMInitializeAMDGPUAsmPrinter(); - LLVMInitializeARMAsmPrinter(); - LLVMInitializeAVRAsmPrinter(); - LLVMInitializeBPFAsmPrinter(); - LLVMInitializeHexagonAsmPrinter(); - LLVMInitializeLanaiAsmPrinter(); - LLVMInitializeLoongArchAsmPrinter(); - LLVMInitializeMipsAsmPrinter(); - LLVMInitializeMSP430AsmPrinter(); - LLVMInitializeNVPTXAsmPrinter(); - LLVMInitializePowerPCAsmPrinter(); - LLVMInitializeRISCVAsmPrinter(); - LLVMInitializeSparcAsmPrinter(); - LLVMInitializeSystemZAsmPrinter(); - LLVMInitializeVEAsmPrinter(); - LLVMInitializeWebAssemblyAsmPrinter(); - LLVMInitializeX86AsmPrinter(); - LLVMInitializeXCoreAsmPrinter(); - return; -}; - -extern LLVMInitializeAArch64AsmParser = () => void; -extern LLVMInitializeAMDGPUAsmParser = () => void; -extern LLVMInitializeARMAsmParser = () => void; -extern LLVMInitializeAVRAsmParser = () => void; -extern LLVMInitializeBPFAsmParser = () => void; -extern LLVMInitializeHexagonAsmParser = () => void; -extern LLVMInitializeLanaiAsmParser = () => void; -extern LLVMInitializeLoongArchAsmParser = () => void; -extern LLVMInitializeMipsAsmParser = () => void; -extern LLVMInitializeMSP430AsmParser = () => void; -extern LLVMInitializePowerPCAsmParser = () => void; -extern LLVMInitializeRISCVAsmParser = () => void; -extern LLVMInitializeSparcAsmParser = () => void; -extern LLVMInitializeSystemZAsmParser = () => void; -extern LLVMInitializeVEAsmParser = () => void; -extern LLVMInitializeWebAssemblyAsmParser = () => void; -extern LLVMInitializeX86AsmParser = () => void; - -let LLVMInitializeAllAsmParsers = () => void { - LLVMInitializeAArch64AsmParser(); - LLVMInitializeAMDGPUAsmParser(); - LLVMInitializeARMAsmParser(); - LLVMInitializeAVRAsmParser(); - LLVMInitializeBPFAsmParser(); - LLVMInitializeHexagonAsmParser(); - LLVMInitializeLanaiAsmParser(); - LLVMInitializeLoongArchAsmParser(); - LLVMInitializeMipsAsmParser(); - LLVMInitializeMSP430AsmParser(); - LLVMInitializePowerPCAsmParser(); - LLVMInitializeRISCVAsmParser(); - LLVMInitializeSparcAsmParser(); - LLVMInitializeSystemZAsmParser(); - LLVMInitializeVEAsmParser(); - LLVMInitializeWebAssemblyAsmParser(); - LLVMInitializeX86AsmParser(); - return; -}; - -extern LLVMInitializeAArch64Disassembler = () => void; -extern LLVMInitializeAMDGPUDisassembler = () => void; -extern LLVMInitializeARMDisassembler = () => void; -extern LLVMInitializeAVRDisassembler = () => void; -extern LLVMInitializeBPFDisassembler = () => void; -extern LLVMInitializeHexagonDisassembler = () => void; -extern LLVMInitializeLanaiDisassembler = () => void; -extern LLVMInitializeLoongArchDisassembler = () => void; -extern LLVMInitializeMipsDisassembler = () => void; -extern LLVMInitializeMSP430Disassembler = () => void; -extern LLVMInitializePowerPCDisassembler = () => void; -extern LLVMInitializeRISCVDisassembler = () => void; -extern LLVMInitializeSparcDisassembler = () => void; -extern LLVMInitializeSystemZDisassembler = () => void; -extern LLVMInitializeVEDisassembler = () => void; -extern LLVMInitializeWebAssemblyDisassembler = () => void; -extern LLVMInitializeX86Disassembler = () => void; -extern LLVMInitializeXCoreDisassembler = () => void; - -let LLVMInitializeAllDisassemblers = () => void { - LLVMInitializeAArch64Disassembler(); - LLVMInitializeAMDGPUDisassembler(); - LLVMInitializeARMDisassembler(); - LLVMInitializeAVRDisassembler(); - LLVMInitializeBPFDisassembler(); - LLVMInitializeHexagonDisassembler(); - LLVMInitializeLanaiDisassembler(); - LLVMInitializeLoongArchDisassembler(); - LLVMInitializeMipsDisassembler(); - LLVMInitializeMSP430Disassembler(); - LLVMInitializePowerPCDisassembler(); - LLVMInitializeRISCVDisassembler(); - LLVMInitializeSparcDisassembler(); - LLVMInitializeSystemZDisassembler(); - LLVMInitializeVEDisassembler(); - LLVMInitializeWebAssemblyDisassembler(); - LLVMInitializeX86Disassembler(); - LLVMInitializeXCoreDisassembler(); - return; -}; - -let LLVMBuilderRef = newtype *void; -let LLVMModuleRef = newtype *void; -let LLVMTargetDataRef = newtype *void; -let LLVMTargetMachineRef = newtype *void; -let LLVMContextRef = newtype *void; -let LLVMTargetRef = newtype *void; -let LLVMIntPredicate = newtype i64; - -let LLVMValueRef = newtype *void; -let LLVMValueKind = newtype i64; -let LLVMTypeRef = newtype *void; -let LLVMBasicBlockRef = newtype *void; - -extern LLVMGetModuleDataLayout = (LLVMModuleRef) => LLVMTargetDataRef; -extern LLVMConstInt = (LLVMTypeRef, i64, i64) => LLVMValueRef; -extern LLVMConstNull = (LLVMTypeRef) => LLVMValueRef; -extern LLVMInt64Type = () => LLVMTypeRef; -extern LLVMInt32Type = () => LLVMTypeRef; -extern LLVMInt1Type = () => LLVMTypeRef; -extern LLVMInt8Type = () => LLVMTypeRef; -extern LLVMVoidType = () => LLVMTypeRef; - -extern LLVMModuleCreateWithName = (*i8) => LLVMModuleRef; -extern LLVMGetGlobalContext = () => LLVMContextRef; -extern LLVMCreateBuilder = () => LLVMBuilderRef; -extern LLVMDisposeModule = (LLVMModuleRef) => void; -extern LLVMShutdown = () => void; -extern LLVMDisposeBuilder = (LLVMBuilderRef) => void; - -extern LLVMGetInsertBlock = (LLVMBuilderRef) => LLVMBasicBlockRef; - -extern LLVMDumpModule = (LLVMModuleRef) => void; -extern LLVMPrintModuleToFile = (LLVMModuleRef, *i8, **i8) => i64; -extern LLVMGetDefaultTargetTriple = () => *i8; -extern LLVMGetTargetFromTriple = (*i8, *LLVMTargetRef, **i8) => i64; -extern LLVMDisposeMessage = (*i8) => void; -extern LLVMCreateTargetMachine = (LLVMTargetRef, *i8, *i8, *i8, i64, i64, i64) => LLVMTargetMachineRef; -extern LLVMDisposeTargetMachine = (LLVMTargetMachineRef) => void; - -let LLVMCodeGenLevelDefault = 2; -let LLVMRelocDefault = 0; -let LLVMCodeModelDefault = 0; - -extern LLVMVerifyModule = (LLVMModuleRef, i64, **i8) => i64; - -let LLVMAbortProcessAction = 0; - -extern LLVMTargetMachineEmitToFile = (LLVMTargetMachineRef, LLVMModuleRef, *i8, i64, **i8) => i64; - -let LLVMObjectFile = 1; - -extern LLVMFunctionType = (LLVMTypeRef, *LLVMTypeRef, i64, i64) => LLVMTypeRef; -extern LLVMAddFunction = (LLVMModuleRef, *i8, LLVMTypeRef) => LLVMValueRef; -extern LLVMAppendBasicBlock = (LLVMValueRef, *i8) => LLVMBasicBlockRef; -extern LLVMPositionBuilderAtEnd = (LLVMBuilderRef, LLVMBasicBlockRef) => void; - -extern LLVMGetParams = (LLVMValueRef, *LLVMValueRef) => void; - -extern LLVMBuildRetVoid = (LLVMBuilderRef) => void; -extern LLVMBuildRet = (LLVMBuilderRef, LLVMValueRef) => void; -extern LLVMPointerType = (LLVMTypeRef, i64) => LLVMTypeRef; - -extern LLVMBuildCall2 = (LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, *LLVMValueRef, i64, *i8) => LLVMValueRef; -extern LLVMBuildGlobalStringPtr = (LLVMBuilderRef, *i8, *i8) => LLVMValueRef; -extern LLVMBuildAlloca = (LLVMBuilderRef, LLVMTypeRef, *i8) => LLVMValueRef; -extern LLVMBuildStore = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef) => LLVMValueRef; -extern LLVMBuildLoad2 = (LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, *i8) => LLVMValueRef; -extern LLVMGetLastInstruction = (LLVMBasicBlockRef) => LLVMValueRef; - -extern LLVMBuildBr = (LLVMBuilderRef, LLVMBasicBlockRef) => LLVMValueRef; -extern LLVMIsATerminatorInst = (LLVMValueRef) => LLVMValueRef; -extern LLVMBuildCondBr = (LLVMBuilderRef, LLVMValueRef, LLVMBasicBlockRef, LLVMBasicBlockRef) => LLVMValueRef; -extern LLVMBuildICmp = (LLVMBuilderRef, LLVMIntPredicate, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef; -extern LLVMBuildNeg = (LLVMBuilderRef, LLVMValueRef, *i8) => LLVMValueRef; -extern LLVMBuildSub = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef; -extern LLVMBuildAdd = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef; -extern LLVMBuildMul = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef; -extern LLVMBuildSDiv = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef; -extern LLVMBuildSRem = (LLVMBuilderRef, LLVMValueRef, LLVMValueRef, *i8) => LLVMValueRef; - -extern LLVMBuildGEP2 = (LLVMBuilderRef, LLVMTypeRef, LLVMValueRef, *LLVMValueRef, i64, *i8) => LLVMValueRef; -extern LLVMAddGlobal = (LLVMModuleRef, LLVMTypeRef, *i8) => LLVMValueRef; -extern LLVMSetInitializer = (LLVMValueRef, LLVMValueRef) => void; -extern LLVMGetValueKind = (LLVMValueRef) => LLVMValueKind; -let LLVMFunctionValueKind = cast(LLVMValueKind, 5); - -let LLVMIntEQ = 32; -let LLVMIntNE = 33; -let LLVMIntUGT = 34; -let LLVMIntUGE = 35; -let LLVMIntULT = 36; -let LLVMIntULE = 37; -let LLVMIntSGT = 38; -let LLVMIntSGE = 39; -let LLVMIntSLT = 40; -let LLVMIntSLE = 41; - -extern LLVMStoreSizeOfType = (LLVMTargetDataRef, LLVMTypeRef) => i64; -extern LLVMStructCreateNamed = (LLVMContextRef, *i8) => LLVMTypeRef; -extern LLVMStructSetBody = (LLVMTypeRef, *LLVMTypeRef, i64, i64) => void; - diff --git a/src/bootstrap/main.pry b/src/bootstrap/main.pry deleted file mode 100644 index a564965..0000000 --- a/src/bootstrap/main.pry +++ /dev/null @@ -1,80 +0,0 @@ -import "!stdlib.pry"; -import "!mem.pry"; - -let slice = struct { - data: *void, - data_len: i64, -}; - -import "tokenizer.pry"; -import "parser.pry"; -import "codegen.pry"; - -let read_file = (filename: *i8, alloc: *arena) => slice { - let file = fopen(filename, "r"); - - fseek(file, 0, 2); - let file_size = ftell(file); - fseek(file, 0, 0); - - let buf = cast(*i8, arena_alloc(alloc, file_size + 1)); - - let bytes_read = fread(buf, 1, file_size, file); - (*(buf + cast(*i8, bytes_read))) = '\0'; - - fclose(file); - - let sl = slice{}; - sl.data = cast(*void, buf); - sl.data_len = file_size; - return sl; -}; - -let main = (argc: i64, argv: **i8) => i64 { - if argc < 2 { - printf("Need filename!\n"); - return 1; - }; - - let generate_ir = false; - let filename = cast(*i8, null); - - let i = 0; - while i < (argc - 1) { - i = i + 1; - let arg = *(argv + cast(**i8, i)); - - if strcmp(arg, "--generate-ir") { - generate_ir = true; - continue; - }; - - if filename == cast(*i8, null) { - filename = arg; - continue; - }; - - assert(false); - }; - - printf("%s\n", filename); - - let alloc = arena_init(1024 * 1024 * 1024); - - let file = read_file(filename, alloc); - - let t = tokenizer_init(alloc, file); - let ts = tokenizer_tokenize(t); - - let p = parser_init(cast(*token, ts.data), ts.data_len, alloc, filename); - let ast = parse(p); - - let c = codegen_init(alloc); - let res = codegen_generate(c, ast); - let res = codegen_compile(c, generate_ir); - codegen_deinit(c); - - arena_free(alloc); - - return 0; -}; diff --git a/src/bootstrap/parser.pry b/src/bootstrap/parser.pry deleted file mode 100644 index 0b448d0..0000000 --- a/src/bootstrap/parser.pry +++ /dev/null @@ -1,1456 +0,0 @@ -import "tokenizer.pry"; - -extern fopen = (*i8, *i8) => *i8; -extern fgets = (*i8, i64, *i8) => void; -extern feof = (*i8) => bool; -extern fseek = (*i8, i64, i64) => i64; -extern lseek = (i64, i64, i64) => i64; -extern ftell = (*i8) => i64; -extern fread = (*i8, i64, i64, *i8) => i64; -extern fclose = (*i8) => *i8; - -extern strcpy = (*i8, *i8) => *i8; -extern dirname = (*i8) => *i8; -extern open = (*i8, i64) => i64; -extern openat = (i64, *i8, i64) => i64; -extern read = (i64, *i8, i64) => i64; -extern realpath = (*i8, *i8) => *i8; -extern snprintf = (*i8, i64, *i8, *i8, *i8) => i64; -extern strcpy = (*i8, *i8) => *i8; -extern strlen = (*i8) => i64; - -let Node = struct { - type: i64, - data: *void, -}; - -let NODE_PROGRAM = 1; -let NODE_STATEMENT = 2; -let NODE_ASSIGNMENT_STATEMENT = 3; -let NODE_IMPORT_DECLARATION = 4; -let NODE_FUNCTION_CALL_STATEMENT = 5; -let NODE_IF_STATEMENT = 6; -let NODE_WHILE_STATEMENT = 7; -let NODE_EQUALITY_EXPRESSION = 8; -let NODE_ADDITIVE_EXPRESSION = 9; -let NODE_MULTIPLICATIVE_EXPRESSION = 10; -let NODE_UNARY_EXPRESSION = 11; -let NODE_POSTFIX_EXPRESSION = 12; -let NODE_PRIMARY_EXPRESSION_NUMBER = 13; -let NODE_PRIMARY_EXPRESSION_BOOLEAN = 14; -let NODE_PRIMARY_EXPRESSION_NULL = 15; -let NODE_PRIMARY_EXPRESSION_CHAR = 16; -let NODE_PRIMARY_EXPRESSION_STRING = 17; -let NODE_PRIMARY_EXPRESSION_IDENTIFIER = 18; -let NODE_FUNCTION_DEFINITION = 19; -let NODE_STRUCT_INSTANCIATION = 20; -let NODE_FIELD_ACCESS = 21; -let NODE_TYPE_SIMPLE_TYPE = 22; -let NODE_TYPE_FUNCTION_TYPE = 23; -let NODE_TYPE_POINTER_TYPE = 24; -let NODE_TYPE_STRUCT_TYPE = 25; -let NODE_RETURN_STATEMENT = 26; -let NODE_CAST_STATEMENT = 27; -let NODE_SIZEOF_STATEMENT = 28; -let NODE_BREAK_STATEMENT = 29; -let NODE_CONTINUE_STATEMENT = 30; - -let EQUALITY_EXPRESSION_TYPE_EQ = 0; -let EQUALITY_EXPRESSION_TYPE_NE = 1; -let EQUALITY_EXPRESSION_TYPE_GE = 2; -let EQUALITY_EXPRESSION_TYPE_LE = 3; -let EQUALITY_EXPRESSION_TYPE_LT = 4; -let EQUALITY_EXPRESSION_TYPE_GT = 5; - -let MULTIPLICATIVE_EXPRESSION_TYPE_MUL = 0; -let MULTIPLICATIVE_EXPRESSION_TYPE_DIV = 1; -let MULTIPLICATIVE_EXPRESSION_TYPE_MOD = 2; - -let UNARY_EXPRESSION_TYPE_NOT = 0; -let UNARY_EXPRESSION_TYPE_MINUS = 1; -let UNARY_EXPRESSION_TYPE_STAR = 2; - -let NODE_PROGRAM_DATA = struct { - statements: **Node, - statements_len: i64, -}; - -let NODE_STATEMENT_DATA = struct { - statement: *Node, -}; - -let NODE_ASSIGNMENT_STATEMENT_DATA = struct { - is_declaration: bool, - is_dereference: bool, - lhs: *Node, - rhs: *Node, -}; - -let NODE_IMPORT_DECLARATION_DATA = struct { - filename: *i8, - program: *Node, -}; - -let NODE_FUNCTION_CALL_STATEMENT_DATA = struct { - expression: *Node, - arguments: **Node, - arguments_len: i64, -}; - -let NODE_IF_STATEMENT_DATA = struct { - condition: *Node, - statements: **Node, - statements_len: i64, -}; - -let NODE_WHILE_STATEMENT_DATA = struct { - condition: *Node, - statements: **Node, - statements_len: i64, -}; - -let NODE_EQUALITY_EXPRESSION_DATA = struct { - lhs: *Node, - rhs: *Node, - typ: i64, -}; - -let NODE_ADDITIVE_EXPRESSION_DATA = struct { - addition: bool, - lhs: *Node, - rhs: *Node, -}; - -let NODE_MULTIPLICATIVE_EXPRESSION_DATA = struct { - lhs: *Node, - rhs: *Node, - typ: i64, -}; - -let NODE_UNARY_EXPRESSION_DATA = struct { - typ: i64, - expression: *Node, -}; - -let NODE_POSTFIX_EXPRESSION_DATA = struct { - lhs: *Node, - rhs: *Node, -}; - -let NODE_PRIMARY_EXPRESSION_NUMBER_DATA = struct { - value: i64, -}; - -let NODE_PRIMARY_EXPRESSION_BOOLEAN_DATA = struct { - value: bool, -}; - -let NODE_PRIMARY_EXPRESSION_CHAR_DATA = struct { - value: i8, -}; - -let NODE_PRIMARY_EXPRESSION_STRING_DATA = struct { - value: *i8, -}; - -let NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA = struct { - name: *i8, - type: *Node, -}; - -let NODE_FUNCTION_DEFINITION_DATA = struct { - statements: **Node, - statements_len: i64, - parameters: **Node, - parameters_len: i64, - retur_type: *Node, -}; - -let NODE_STRUCT_INSTANCIATION_DATA = struct { - typ: *i8, -}; - -let NODE_FIELD_ACCESS_DATA = struct { - expression: *Node, - name: *i8, -}; - -let NODE_TYPE_SIMPLE_TYPE_DATA = struct { - name: *i8, - underlying_type: *Node, -}; - -let NODE_TYPE_FUNCTION_TYPE_DATA = struct { - parameters: **Node, - parameters_len: i64, - retur_type: *Node, -}; - -let NODE_TYPE_POINTER_TYPE_DATA = struct { - type: *Node, -}; - -let NODE_TYPE_STRUCT_TYPE_DATA = struct { - fields: **Node, - fields_len: i64, -}; - -let NODE_RETURN_STATEMENT_DATA = struct { - expression: *Node, -}; - -let NODE_CAST_STATEMENT_DATA = struct { - typ: *Node, - expression: *Node, -}; - -let NODE_SIZEOF_STATEMENT_DATA = struct { - typ: *Node, -}; - - -let parser = struct { - tokens: *token, - tokens_len: i64, - - offset: i64, - - arena: *arena, - filename: *i8, -}; - -extern parser_parse_statement = (*parser) => *Node; -extern parser_parse_expression = (*parser) => *Node; -extern parse_function_call_statement = (*parser) => *Node; -extern parser_parse_additive_expression = (*parser) => *Node; - -let parser_init = (ts: *token, ts_len: i64, ar: *arena, filename: *i8) => *parser { - let p = cast(*parser, arena_alloc(ar, sizeof(parser))); - - (*p).tokens = ts; - (*p).tokens_len = ts_len; - (*p).offset = 0; - (*p).arena = ar; - (*p).filename = filename; - - return p; -}; - -let create_node = (p: *parser, n: Node) => *Node { - let res = cast(*Node, arena_alloc((*p).arena, sizeof(Node))); - *res = n; - return res; -}; - -let parser_peek_token = (p: *parser) => *token { - if (*p).offset >= (*p).tokens_len { - return cast(*token, null); - }; - - return ((*p).tokens + cast(*token, (*p).offset)); -}; - - let parser_consume_token = (p: *parser) => *token { - if (*p).offset >= (*p).tokens_len { - return cast(*token, null); - }; - - let t = ((*p).tokens + cast(*token, (*p).offset)); - (*p).offset = (*p).offset + 1; - return t; -}; - -let parser_accept_token = (p: *parser, t: i64) => *token { - let curr_token = parser_peek_token(p); - if curr_token == cast(*token, null) { - return cast(*token, null); - }; - - if (*curr_token).type == t { - return parser_consume_token(p); - }; - return cast(*token, null); -}; - -let parser_accept_parse = (p: *parser, parsing_func: (*parser) => *Node) => *Node { - let prev_offset = (*p).offset; - let node = parsing_func(p); - if node == cast(*Node, null) { - (*p).offset = prev_offset; - }; - return node; -}; - -/* ReturnStatement ::= RETURN (Expression)? */ -let parser_parse_return_statement = (p: *parser) => *Node { - if parser_accept_token(p, TOKEN_RETURN) == cast(*token, null) { - return cast(*Node, null); - }; - - let maybe_expr = parser_accept_parse(p, parser_parse_expression); - - let d = cast(*NODE_RETURN_STATEMENT_DATA , arena_alloc((*p).arena, sizeof(NODE_RETURN_STATEMENT_DATA ))); - (*d).expression = maybe_expr; - - let r = Node{}; - r.type = NODE_RETURN_STATEMENT; - r.data = cast(*void, d); - - return create_node(p, r); -}; - -extern parser_parse_type = (*parser) => *Node; - -/* CastStatement ::= "cast" LPAREN TYPE "," Expression RPAREN */ -let parser_parse_cast_statement = (p: *parser) => *Node { - let ident = parser_accept_token(p, TOKEN_IDENTIFIER); - if ident == cast(*token, null) { - return cast(*Node, null); - }; - - if !strcmp(cast(*i8, (*ident).data), "cast") { - return cast(*Node, null); - }; - - if parser_accept_token(p, TOKEN_LPAREN) == cast(*token, null) { - return cast(*Node, null); - }; - - let typ = parser_parse_type(p); - if typ == cast(*Node, null) { - return cast(*Node, null); - }; - - if parser_accept_token(p, TOKEN_COMMA) == cast(*token, null) { - return cast(*Node, null); - }; - - let expression = parser_parse_expression(p); - if expression == cast(*Node, null) { - return cast(*Node, null); - }; - - if parser_accept_token(p, TOKEN_RPAREN) == cast(*token, null) { - return cast(*Node, null); - }; - - let d = cast(*NODE_CAST_STATEMENT_DATA , arena_alloc((*p).arena, sizeof(NODE_CAST_STATEMENT_DATA ))); - (*d).typ = typ; - (*d).expression = expression; - - let r = Node{}; - r.type = NODE_CAST_STATEMENT; - r.data = cast(*void, d); - - return create_node(p, r); -}; - -/* SizeOfStatement ::= "sizeof" LPAREN TYPE RPAREN */ -let parser_parse_sizeof_statement = (p: *parser) => *Node { - let ident = parser_accept_token(p, TOKEN_IDENTIFIER); - if ident == cast(*token, null) { - return cast(*Node, null); - }; - - if !strcmp(cast(*i8, (*ident).data), "sizeof") { - return cast(*Node, null); - }; - - if parser_accept_token(p, TOKEN_LPAREN) == cast(*token, null) { - return cast(*Node, null); - }; - - let typ = parser_parse_type(p); - if typ == cast(*Node, null) { - return cast(*Node, null); - }; - - if parser_accept_token(p, TOKEN_RPAREN) == cast(*token, null) { - return cast(*Node, null); - }; - - let d = cast(*NODE_SIZEOF_STATEMENT_DATA , arena_alloc((*p).arena, sizeof(NODE_SIZEOF_STATEMENT_DATA ))); - (*d).typ = typ; - - let r = Node{}; - r.type = NODE_SIZEOF_STATEMENT; - r.data = cast(*void, d); - - return create_node(p, r); -}; - -/* FunctionType ::= LPAREN (Type ("," Type)*)? RPAREN ARROW Type */ -let parser_parse_function_type = (p: *parser) => *Node { - if parser_accept_token(p, TOKEN_LPAREN) == cast(*token, null) { - return cast(*Node, null); - }; - - let parameters = cast(**Node, arena_alloc((*p).arena, sizeof(*Node) * 20)); - let parameters_len = 0; - let first = true; - while true { - if !first { - parser_accept_token(p, TOKEN_COMMA); - }; - first = false; - let type_annotation = parser_accept_parse(p, parser_parse_type); - if type_annotation == cast(*Node, null) { - break; - }; - (*(parameters + cast(**Node, parameters_len))) = type_annotation; - parameters_len = parameters_len + 1; - - }; - - if parser_accept_token(p, TOKEN_RPAREN) == cast(*token, null) { - return cast(*Node, null); - }; - if parser_accept_token(p, TOKEN_ARROW) == cast(*token, null) { - return cast(*Node, null); - }; - - let retur_typ = parser_parse_type(p); - if retur_typ == cast(*Node, null) { - return cast(*Node, null); - }; - - let d = cast(*NODE_TYPE_FUNCTION_TYPE_DATA, arena_alloc((*p).arena, sizeof(NODE_TYPE_FUNCTION_TYPE_DATA))); - (*d).parameters = parameters; - (*d).parameters_len = parameters_len; - (*d).retur_type = retur_typ; - - let r = Node{}; - r.type = NODE_TYPE_FUNCTION_TYPE; - r.data = cast(*void, d); - - return create_node(p, r); -}; - -/* Type ::= IDENTIFIER | FunctionType */ -let parser_parse_type = (p: *parser) => *Node { - let typ = parser_accept_parse(p, parser_parse_function_type); - if typ != cast(*Node, null) { - return typ; - }; - - let to = parser_consume_token(p); - assert(to != cast(*token, null)); - - /* TODO: we should only accept specific type identifiers */ - if (*to).type == TOKEN_IDENTIFIER { - let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*p).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*d).name = cast(*i8, (*to).data); - (*d).underlying_type = cast(*Node, null); - - let r = Node{}; - r.type = NODE_TYPE_SIMPLE_TYPE; - r.data = cast(*void, d); - - return create_node(p, r); - }; - - if (*to).type == TOKEN_MUL { - let d = cast(*NODE_TYPE_POINTER_TYPE_DATA, arena_alloc((*p).arena, sizeof(NODE_TYPE_POINTER_TYPE_DATA))); - (*d).type = parser_parse_type(p); - - let r = Node{}; - r.type = NODE_TYPE_POINTER_TYPE; - r.data = cast(*void, d); - - return create_node(p, r); - }; - - return cast(*Node, null); -}; - -/* IfStatement ::= "if" Expression LBRACE Statement* RBRACE */ -let parser_parse_if_statement = (p: *parser) => *Node { - if parser_accept_token(p, TOKEN_IF) == cast(*token, null) { - return cast(*Node, null); - }; - - let expression = parser_parse_expression(p); - if expression == cast(*Node, null) { - return cast(*Node, null); - }; - - if parser_accept_token(p, TOKEN_LBRACE) == cast(*token, null) { - return cast(*Node, null); - }; - - let statements = cast(**Node, arena_alloc((*p).arena, sizeof(*Node) * 100)); - let i = 0; - while true { - let n = parser_accept_parse(p, parser_parse_statement); - if n == cast(*Node, null) { - break; - }; - (*(statements + cast(**Node, i))) = n; - i = i + 1; - }; - - if parser_accept_token(p, TOKEN_RBRACE) == cast(*token, null) { - return cast(*Node, null); - }; - - let dd = cast(*NODE_IF_STATEMENT_DATA, arena_alloc((*p).arena, sizeof(NODE_IF_STATEMENT_DATA))); - (*dd).condition = expression; - (*dd).statements = statements; - (*dd).statements_len = i; - - let r = Node{}; - r.type = NODE_IF_STATEMENT; - r.data = cast(*void, dd); - - return create_node(p, r); -}; - -/* WhileStatement ::= "while" Expression LBRACE Statement* RBRACE */ -let parser_parse_while_statement = (p: *parser) => *Node { - if parser_accept_token(p, TOKEN_WHILE) == cast(*token, null) { - return cast(*Node, null); - }; - - let expression = parser_parse_expression(p); - if expression == cast(*Node, null) { - return cast(*Node, null); - }; - - if parser_accept_token(p, TOKEN_LBRACE) == cast(*token, null) { - return cast(*Node, null); - }; - - let statements = cast(**Node, arena_alloc((*p).arena, sizeof(*Node) * 100)); - let i = 0; - while true { - let n = parser_accept_parse(p, parser_parse_statement); - if n == cast(*Node, null) { - break; - }; - (*(statements + cast(**Node, i))) = n; - i = i + 1; - }; - - if parser_accept_token(p, TOKEN_RBRACE) == cast(*token, null) { - return cast(*Node, null); - }; - - let dd = cast(*NODE_WHILE_STATEMENT_DATA, arena_alloc((*p).arena, sizeof(NODE_WHILE_STATEMENT_DATA))); - (*dd).condition = expression; - (*dd).statements = statements; - (*dd).statements_len = i; - - let r = Node{}; - r.type = NODE_WHILE_STATEMENT; - r.data = cast(*void, dd); - - return create_node(p, r); -}; - -/* ExternDeclaration ::= "extern" IDENTIFIER EQUALS Type */ -let parser_parse_extern_declaration = (p: *parser) => *Node { - if parser_accept_token(p, TOKEN_EXTERN) == cast(*token, null) { - return cast(*Node, null); - }; - - let ident = parser_accept_token(p, TOKEN_IDENTIFIER); - if ident == cast(*token, null) { - return cast(*Node, null); - }; - if parser_accept_token(p, TOKEN_EQUALS) == cast(*token, null) { - return cast(*Node, null); - }; - let typ = parser_parse_type(p); - if typ == cast(*Node, null) { - return cast(*Node, null); - }; - - let d = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA))); - (*d).name = cast(*i8, (*ident).data); - (*d).type = cast(*Node, null); - - let n = Node{}; - n.type = NODE_PRIMARY_EXPRESSION_IDENTIFIER; - n.data = cast(*void, d); - - let dd = cast(*NODE_ASSIGNMENT_STATEMENT_DATA, arena_alloc((*p).arena, sizeof(NODE_ASSIGNMENT_STATEMENT_DATA))); - (*dd).is_declaration = false; - (*dd).is_dereference = false; - (*dd).lhs = create_node(p, n); - (*dd).rhs = typ; - - let r = Node{}; - r.type = NODE_ASSIGNMENT_STATEMENT; - r.data = cast(*void, dd); - - return create_node(p, r); -}; - -/* FunctionParameters ::= IDENTIFIER ":" Type ("," IDENTIFIER ":" Type)* */ -let parser_parse_function_parameters = (p: *parser) => *slice { - let node_list = cast(**Node, arena_alloc((*p).arena, sizeof(**Node) * 20)); - let i = 0; - while true { - if i != 0 { - parser_accept_token(p, TOKEN_COMMA); - }; - let ident = parser_accept_token(p, TOKEN_IDENTIFIER); - if ident == cast(*token, null) { - break; - }; - if parser_accept_token(p, TOKEN_COLON) == cast(*token, null) { - return cast(*slice, null); - }; - let type_annotation = parser_parse_type(p); - if type_annotation == cast(*Node, null) { - return cast(*slice, null); - }; - - let d = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA))); - (*d).name = cast(*i8, (*ident).data); - (*d).type = type_annotation; - let n = Node{}; - n.type = NODE_PRIMARY_EXPRESSION_IDENTIFIER; - n.data = cast(*void, d); - (*(node_list + cast(**Node, i))) = create_node(p, n); - - i = i + 1; - }; - - let s = cast(*slice, arena_alloc((*p).arena, sizeof(slice))); - (*s).data = cast(*void, node_list); - (*s).data_len = i; - return s; -}; - -/* TypeDefinition ::= "newtype" Type */ -let parser_parse_type_definition = (p: *parser) => *Node { - if parser_accept_token(p, TOKEN_TYPE) == cast(*token, null) { - return cast(*Node, null); - }; - - let typ = parser_parse_type(p); - if typ == cast(*Node, null) { - return cast(*Node, null); - }; - - let d = cast(*NODE_TYPE_SIMPLE_TYPE_DATA, arena_alloc((*p).arena, sizeof(NODE_TYPE_SIMPLE_TYPE_DATA))); - (*d).name = ""; - (*d).underlying_type = typ; - - let r = Node{}; - r.type = NODE_TYPE_SIMPLE_TYPE; - r.data = cast(*void, d); - - return create_node(p, r); -}; - -/* StructDefinition ::= "struct" LBRACE StructFields? RBRACE */ -let parser_parse_struct_definition = (p: *parser) => *Node { - if parser_accept_token(p, TOKEN_STRUCT) == cast(*token, null) { - return cast(*Node, null); - }; - if parser_accept_token(p, TOKEN_LBRACE) == cast(*token, null) { - return cast(*Node, null); - }; - - let fields = cast(**Node, arena_alloc((*p).arena, sizeof(*Node) * 20)); - let i = 0; - while true { - let field = parser_accept_parse(p, (ip: *parser) => *Node { - let ident = parser_accept_token(ip, TOKEN_IDENTIFIER); - if ident == cast(*token, null) { - return cast(*Node, null); - }; - if parser_accept_token(ip, TOKEN_COLON) == cast(*token, null) { - return cast(*Node, null); - }; - let typ_annotation = parser_parse_type(ip); - if typ_annotation == cast(*Node, null) { - return cast(*Node, null); - }; - printf("STRUCT TYP: %d\n" (*typ_annotation).type); - let d = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, arena_alloc((*ip).arena, sizeof(NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA))); - (*d).name = cast(*i8, (*ident).data); - (*d).type = typ_annotation; - let n = Node{}; - n.type = NODE_PRIMARY_EXPRESSION_IDENTIFIER; - n.data = cast(*void, d); - return create_node(ip, n); - }); - if field == cast(*Node, null) { - break; - }; - - parser_accept_token(p, TOKEN_COMMA); - - (*(fields + cast(**Node, i))) = field; - i = i + 1; - }; - - if parser_accept_token(p, TOKEN_RBRACE) == cast(*token, null) { - return cast(*Node, null); - }; - - let d = cast(*NODE_TYPE_STRUCT_TYPE_DATA, arena_alloc((*p).arena, sizeof(NODE_TYPE_STRUCT_TYPE_DATA))); - (*d).fields = fields; - (*d).fields_len = i; - let n = Node{}; - n.type = NODE_TYPE_STRUCT_TYPE; - n.data = cast(*void, d); - return create_node(p, n); -}; - -/* FunctionDefinition ::= LPAREN FunctionParameters? RPAREN ARROW IDENTIFIER LBRACE Statement* ReturnStatement SEMICOLON RBRACE */ -let parser_parse_function_definition = (p: *parser) => *Node { - if parser_accept_token(p, TOKEN_LPAREN) == cast(*token, null) { - return cast(*Node, null); - }; - let params = parser_parse_function_parameters(p); - if params == cast(*slice, null) { - return cast(*Node, null); - }; - if parser_accept_token(p, TOKEN_RPAREN) == cast(*token, null) { - return cast(*Node, null); - }; - if parser_accept_token(p, TOKEN_ARROW) == cast(*token, null) { - return cast(*Node, null); - }; - let retur_type = parser_parse_type(p); - if retur_type == cast(*Node, null) { - return cast(*Node, null); - }; - if parser_accept_token(p, TOKEN_LBRACE) == cast(*token, null) { - return cast(*Node, null); - }; - - let statements = cast(**Node, arena_alloc((*p).arena, sizeof(*Node) * 100)); - let i = 0; - while true { - let n = parser_accept_parse(p, parser_parse_statement); - if n == cast(*Node, null) { - break; - }; - (*(statements + cast(**Node, i))) = n; - i = i + 1; - }; - - - if parser_accept_token(p, TOKEN_RBRACE) == cast(*token, null) { - return cast(*Node, null); - }; - - - let d = cast(*NODE_FUNCTION_DEFINITION_DATA, arena_alloc((*p).arena, sizeof(NODE_FUNCTION_DEFINITION_DATA))); - (*d).statements = statements; - (*d).statements_len = i; - (*d).parameters = cast(**Node, (*params).data); - (*d).parameters_len = (*params).data_len; - (*d).retur_type = retur_type; - - let n = Node{}; - n.type = NODE_FUNCTION_DEFINITION; - n.data = cast(*void, d); - - return create_node(p, n); -}; - -/* StructInstantiation ::= IDENTIFIER LBRACE RBRACE */ -let parser_parse_struct_instanciation = (p: *parser) => *Node { - let typ = parser_accept_token(p, TOKEN_IDENTIFIER); - if typ == cast(*token, null) { - return cast(*Node, null); - }; - - if parser_accept_token(p, TOKEN_LBRACE) == cast(*token, null) { - return cast(*Node, null); - }; - if parser_accept_token(p, TOKEN_RBRACE) == cast(*token, null) { - return cast(*Node, null); - }; - - let d = cast(*NODE_STRUCT_INSTANCIATION_DATA, arena_alloc((*p).arena, sizeof(NODE_STRUCT_INSTANCIATION_DATA))); - (*d).typ = cast(*i8, (*typ).data); - - let n = Node{}; - n.type = NODE_STRUCT_INSTANCIATION; - n.data = cast(*void, d); - - return create_node(p, n); -}; - -extern parser_parse_primary_expression = (*parser) => *Node; - -/* FieldAccess ::= PrimaryExpression DOT IDENTIFIER */ -let parser_parse_field_access = (p: *parser) => *Node { - let expression = parser_parse_primary_expression(p); - if expression == cast(*Node, null) { - return cast(*Node, null); - }; - if parser_accept_token(p, TOKEN_DOT) == cast(*token, null) { - return cast(*Node, null); - }; - let ident = parser_accept_token(p, TOKEN_IDENTIFIER); - if ident == cast(*token, null) { - return cast(*Node, null); - }; - - let d = cast(*NODE_FIELD_ACCESS_DATA, arena_alloc((*p).arena, sizeof(NODE_FIELD_ACCESS_DATA))); - (*d).expression = expression; - (*d).name = cast(*i8, (*ident).data); - - let n = Node{}; - n.type = NODE_FIELD_ACCESS; - n.data = cast(*void, d); - - return create_node(p, n); -}; - -/* PrimaryExpression ::= NULL | NUMBER | BOOLEAN | CHAR | STRING | IDENTIFIER | FunctionDefinition | StructDefinition | StructInstantiation | FieldAccess | LPAREN Expression RPAREN */ -let parser_parse_primary_expression = (p: *parser) => *Node { - let stmt = parser_accept_parse(p, parser_parse_function_definition); - if stmt != cast(*Node, null) { - return stmt; - }; - let stmt = parser_accept_parse(p, parser_parse_type_definition); - if stmt != cast(*Node, null) { - return stmt; - }; - let stmt = parser_accept_parse(p, parser_parse_struct_definition); - if stmt != cast(*Node, null) { - return stmt; - }; - let stmt = parser_accept_parse(p, parser_parse_struct_instanciation); - if stmt != cast(*Node, null) { - return stmt; - }; - - if parser_accept_token(p, TOKEN_LPAREN) != cast(*token, null) { - let expr = parser_parse_expression(p); - if expr == cast(*Node, null) { - return cast(*Node, null); - }; - if parser_accept_token(p, TOKEN_RPAREN) == cast(*token, null) { - return cast(*Node, null); - }; - return expr; - }; - - let tok = parser_consume_token(p); - if tok == cast(*token, null) { - printf("NO TOK\n"); - return cast(*Node, null); - }; - - if (*tok).type == TOKEN_NULL { - let n = Node{}; - n.type = NODE_PRIMARY_EXPRESSION_NULL; - return create_node(p, n); - }; - - if (*tok).type == TOKEN_IDENTIFIER { - let d = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA))); - (*d).name = cast(*i8, (*tok).data); - (*d).type = cast(*Node, null); - let n = Node{}; - n.type = NODE_PRIMARY_EXPRESSION_IDENTIFIER; - n.data = cast(*void, d); - return create_node(p, n); - }; - - if (*tok).type == TOKEN_NUMBER { - let d = cast(*NODE_PRIMARY_EXPRESSION_NUMBER_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_NUMBER_DATA))); - (*d).value = *(cast(*i64, (*tok).data)); - let n = Node{}; - n.type = NODE_PRIMARY_EXPRESSION_NUMBER; - n.data = cast(*void, d); - return create_node(p, n); - }; - - if (*tok).type == TOKEN_BOOLEAN { - let d = cast(*NODE_PRIMARY_EXPRESSION_BOOLEAN_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_BOOLEAN_DATA))); - (*d).value = *(cast(*bool, (*tok).data)); - let n = Node{}; - n.type = NODE_PRIMARY_EXPRESSION_BOOLEAN; - n.data = cast(*void, d); - return create_node(p, n); - }; - - if (*tok).type == TOKEN_CHAR { - let d = cast(*NODE_PRIMARY_EXPRESSION_CHAR_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_CHAR_DATA))); - (*d).value = *(cast(*i8, (*tok).data)); - let n = Node{}; - n.type = NODE_PRIMARY_EXPRESSION_CHAR; - n.data = cast(*void, d); - return create_node(p, n); - }; - - if (*tok).type == TOKEN_STRING { - let d = cast(*NODE_PRIMARY_EXPRESSION_STRING_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_STRING_DATA))); - (*d).value = cast(*i8, (*tok).data); - let n = Node{}; - n.type = NODE_PRIMARY_EXPRESSION_STRING; - n.data = cast(*void, d); - return create_node(p, n); - }; - - return cast(*Node, null); -}; - -/* EqualityExpression ::= AdditiveExpression ("==" | "!=" | "<=" | ">=" | "<" | ">") AdditiveExpression */ -let parser_parse_equality_expression = (p: *parser) => *Node { - let lhs = parser_parse_additive_expression(p); - if lhs == cast(*Node, null) { - return cast(*Node, null); - }; - - let typ = -1; - let ex = parser_accept_parse(p, (ip: *parser) => *Node { - if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) { - return cast(*Node, null); - }; - if parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null) { - return cast(*Node, null); - }; - let n = Node{}; - return create_node(ip, n); - }); - if ex != cast(*Node, null) { - typ = EQUALITY_EXPRESSION_TYPE_EQ; - }; - - if (typ == -1) { - ex = parser_accept_parse(p, (ip: *parser) => *Node { - if (parser_accept_token(ip, TOKEN_BANG) == cast(*token, null)) { - return cast(*Node, null); - }; - if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) { - return cast(*Node, null); - }; - let n = Node{}; - return create_node(ip, n); - }); - if (ex != cast(*Node, null)) { - typ = EQUALITY_EXPRESSION_TYPE_NE; - }; - }; - - if (typ == -1) { - ex = parser_accept_parse(p, (ip: *parser) => *Node { - if (parser_accept_token(ip, TOKEN_LESS) == cast(*token, null)) { - return cast(*Node, null); - }; - if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) { - return cast(*Node, null); - }; - let n = Node{}; - return create_node(ip, n); - }); - if (ex != cast(*Node, null)) { - typ = EQUALITY_EXPRESSION_TYPE_LE; - }; - }; - - if (typ == -1) { - ex = parser_accept_parse(p, (ip: *parser) => *Node { - if (parser_accept_token(ip, TOKEN_GREATER) == cast(*token, null)) { - return cast(*Node, null); - }; - if (parser_accept_token(ip, TOKEN_EQUALS) == cast(*token, null)) { - return cast(*Node, null); - }; - let n = Node{}; - return create_node(ip, n); - }); - if (ex != cast(*Node, null)) { - typ = EQUALITY_EXPRESSION_TYPE_GE; - }; - }; - - if (typ == -1) { - if (parser_accept_token(p, TOKEN_LESS) != cast(*token, null)) { - typ = EQUALITY_EXPRESSION_TYPE_LT; - }; - }; - - if (typ == -1) { - if (parser_accept_token(p, TOKEN_GREATER) != cast(*token, null)) { - typ = EQUALITY_EXPRESSION_TYPE_GT; - }; - }; - - if typ == -1 { - return cast(*Node, null); - }; - - let rhs = parser_parse_additive_expression(p); - if rhs == cast(*Node, null) { - return cast(*Node, null); - }; - - let d = cast(*NODE_EQUALITY_EXPRESSION_DATA, arena_alloc((*p).arena, sizeof(NODE_EQUALITY_EXPRESSION_DATA))); - (*d).lhs = lhs; - (*d).rhs = rhs; - (*d).typ = typ; - - let n = Node{}; - n.type = NODE_EQUALITY_EXPRESSION ; - n.data = cast(*void, d); - - return create_node(p, n); -}; - -/* PostfixExpression ::= PrimaryExpression (CastStatement | SizeOfStatement | FunctionCallStatement | FieldAccess )* */ -let parser_parse_postfix_expression = (p: *parser) => *Node { - let ex = parser_accept_parse(p, parser_parse_cast_statement); - if ex != cast(*Node, null) { - return ex; - }; - let ex = parser_accept_parse(p, parser_parse_sizeof_statement); - if ex != cast(*Node, null) { - return ex; - }; - let ex = parser_accept_parse(p, parse_function_call_statement); - if ex != cast(*Node, null) { - return ex; - }; - let ex = parser_accept_parse(p, parser_parse_field_access); - if ex != cast(*Node, null) { - return ex; - }; - return parser_parse_primary_expression(p); -}; - -/* UnaryExpression ::= ("!" | "-" | "*") UnaryExpression | PostfixExpression */ -let parser_parse_unary_expression = (p: *parser) => *Node { - let typ = -1; - if parser_accept_token(p, TOKEN_BANG) != cast(*token, null) { - typ = UNARY_EXPRESSION_TYPE_NOT; - }; - if typ == -1 { - if parser_accept_token(p, TOKEN_MINUS) != cast(*token, null) { - typ = UNARY_EXPRESSION_TYPE_MINUS; - }; - }; - if typ == -1 { - if parser_accept_token(p, TOKEN_MUL) != cast(*token, null) { - typ = UNARY_EXPRESSION_TYPE_STAR; - }; - }; - if typ == -1 { - return parser_parse_postfix_expression(p); - }; - - let new_lhs_data = cast(*NODE_UNARY_EXPRESSION_DATA, arena_alloc((*p).arena, sizeof(NODE_UNARY_EXPRESSION_DATA))); - ((*new_lhs_data).typ) = typ; - let e = parser_parse_unary_expression(p); - if e == cast(*Node, null) { - return cast(*Node, null); - }; - ((*new_lhs_data).expression) = e; - let new_lhs = Node{}; - new_lhs.type = NODE_UNARY_EXPRESSION; - new_lhs.data = cast(*void, new_lhs_data); - return create_node(p, new_lhs); -}; - -/* MultiplicativeExpression ::= UnaryExpression (("*" | "/" | "%") UnaryExpression)* */ -let parser_parse_multiplicative_expression = (p: *parser) => *Node { - let lhs = parser_parse_unary_expression(p); - if lhs == cast(*Node, null) { - return cast(*Node, null); - }; - - while true { - let typ = -1; - if parser_accept_token(p, TOKEN_MUL) != cast(*token, null) { - typ = MULTIPLICATIVE_EXPRESSION_TYPE_MUL; - }; - if parser_accept_token(p, TOKEN_DIV) != cast(*token, null) { - typ = MULTIPLICATIVE_EXPRESSION_TYPE_DIV; - }; - if parser_accept_token(p, TOKEN_MOD) != cast(*token, null) { - typ = MULTIPLICATIVE_EXPRESSION_TYPE_MOD; - }; - if typ == -1 { - break; - }; - - let rhs = parser_parse_unary_expression(p); - if rhs == cast(*Node, null) { - return cast(*Node, null); - }; - - let new_lhs_data = cast(*NODE_MULTIPLICATIVE_EXPRESSION_DATA, arena_alloc((*p).arena, sizeof(NODE_MULTIPLICATIVE_EXPRESSION_DATA))); - ((*new_lhs_data).lhs) = lhs; - ((*new_lhs_data).rhs) = rhs; - ((*new_lhs_data).typ) = typ; - let new_lhs = Node{}; - new_lhs.type = NODE_MULTIPLICATIVE_EXPRESSION; - new_lhs.data = cast(*void, new_lhs_data); - lhs = create_node(p, new_lhs); - }; - return lhs; -}; - -/* AdditiveExpression ::= MultiplicativeExpression (("+" | "-") MultiplicativeExpression)* */ -let parser_parse_additive_expression = (p: *parser) => *Node { - let lhs = parser_parse_multiplicative_expression(p); - if lhs == cast(*Node, null) { - return cast(*Node, null); - }; - - while true { - let plus = parser_accept_token(p, TOKEN_PLUS); - let minus = parser_accept_token(p, TOKEN_MINUS); - - if plus == cast(*token, null) { - if minus == cast(*token, null) { - break; - }; - }; - - let rhs = parser_parse_multiplicative_expression(p); - if rhs == cast(*Node, null) { - return cast(*Node, null); - }; - - let new_lhs_data = cast(*NODE_ADDITIVE_EXPRESSION_DATA, arena_alloc((*p).arena, sizeof(NODE_ADDITIVE_EXPRESSION_DATA))); - ((*new_lhs_data).addition) = plus != cast(*token, null); - ((*new_lhs_data).lhs) = lhs; - ((*new_lhs_data).rhs) = rhs; - let new_lhs = Node{}; - new_lhs.type = NODE_ADDITIVE_EXPRESSION; - new_lhs.data = cast(*void, new_lhs_data); - lhs = create_node(p, new_lhs); - }; - return lhs; -}; - -/* Expression ::= EqualityExpression | AdditiveExpression */ -let parser_parse_expression = (p: *parser) => *Node { - let ex = parser_accept_parse(p, parser_parse_equality_expression); - if ex != cast(*Node, null) { - return ex; - }; - let ax = parser_accept_parse(p, parser_parse_additive_expression); - if ax != cast(*Node, null) { - return ax; - }; - - return cast(*Node, null); -}; - -/* AssignmentStatement ::= ("let")? ("*")? Expression EQUALS Expression */ -let parse_assignment_statement = (p: *parser) => *Node { - let is_declaration = false; - if parser_accept_token(p, TOKEN_LET) != cast(*token, null) { - is_declaration = true; - }; - - let is_dereference = false; - if parser_accept_token(p, TOKEN_MUL) != cast(*token, null) { - is_dereference = true; - }; - - let lhs = parser_parse_expression(p); - if lhs == cast(*Node, null) { - return cast(*Node, null); - }; - - if parser_accept_token(p, TOKEN_EQUALS) == cast(*token, null) { - return cast(*Node, null); - }; - - let rhs = parser_parse_expression(p); - if rhs == cast(*Node, null) { - return cast(*Node, null); - }; - - let d = cast(*NODE_ASSIGNMENT_STATEMENT_DATA , arena_alloc((*p).arena, sizeof(NODE_ASSIGNMENT_STATEMENT_DATA))); - (*d).is_declaration = is_declaration; - (*d).is_dereference = is_dereference; - (*d).lhs = lhs; - (*d).rhs = rhs; - let n = Node{}; - n.type = NODE_ASSIGNMENT_STATEMENT; - n.data = cast(*void, d); - return create_node(p, n); -}; - -extern parse = (*parser) => *Node; - -let parser_parse_import_declaration = (p: *parser) => *Node { - if parser_accept_token(p, TOKEN_IMPORT) == cast(*token, null) { - return cast(*Node, null); - }; - - let expr = parser_parse_primary_expression(p); - if expr == cast(*Node, null) { - return cast(*Node, null); - }; - - assert((*expr).type == NODE_PRIMARY_EXPRESSION_STRING); - - let impor_filename = (*cast(*NODE_PRIMARY_EXPRESSION_STRING_DATA, (*expr).data)).value; - let current_file = cast(*i8, arena_alloc((*p).arena, sizeof(i8) * 70)); - strcpy(current_file, (*p).filename); - - /* stdlib. TODO: this is very hacky and won't work if running the compiler binary by itself */ - if (*impor_filename) == '!' { - let buf = cast(*i8, arena_alloc((*p).arena, sizeof(i8) * 70)); - sprintf(buf, "./std/%s", (impor_filename + cast(*i8, 1))); - impor_filename = buf; - current_file = "."; - }; - - let dirpath = dirname(current_file); - let dir = open(dirpath, 0); - assert(dir != -1); - - let file = openat(dir, impor_filename, 0); - assert(file != -1); - - let file_size = lseek(file, 0, 2); - lseek(file, 0, 0); - let file_contents = cast(*i8, arena_alloc((*p).arena, file_size + 1)); - - let bytes_read = read(file, file_contents, file_size); - (*(file_contents + cast(*i8, bytes_read))) = '\0'; - - let f = slice{}; - f.data = cast(*void, file_contents); - f.data_len = file_size; - let inner_tokenizer = tokenizer_init((*p).arena, f); - let tokens = tokenizer_tokenize(inner_tokenizer); - - let buf2 = cast(*i8, arena_alloc((*p).arena, 90)); - strcpy(buf2, dirpath); - (*(buf2 + cast(*i8, strlen(dirpath)))) = '/'; - strcpy(buf2 + cast(*i8, strlen(dirpath) + 1), impor_filename); - let full_path = realpath(buf2, cast(*i8, null)); - - let inner_parser = parser_init(cast(*token, tokens.data), tokens.data_len, (*p).arena, full_path); - let ast = parse(inner_parser); - - let d = cast(*NODE_IMPORT_DECLARATION_DATA , arena_alloc((*p).arena, sizeof(NODE_IMPORT_DECLARATION_DATA))); - (*d).filename = impor_filename; - (*d).program = ast; - let n = Node{}; - n.type = NODE_IMPORT_DECLARATION; - n.data = cast(*void, d); - return create_node(p, n); -}; - -/* FunctionArguments ::= Expression ("," Expression)* */ -let parser_parse_function_arguments = (p: *parser) => *slice { - let node_list = cast(**Node, arena_alloc((*p).arena, sizeof(*Node) * 20)); - let first = true; - - let i = 0; - while true { - if !first { - parser_accept_token(p, TOKEN_COMMA); - }; - first = false; - let maybe_expr = parser_accept_parse(p, parser_parse_expression); - if maybe_expr == cast(*Node, null) { - let s = cast(*slice, arena_alloc((*p).arena, sizeof(slice))); - (*s).data = cast(*void, node_list); - (*s).data_len = i; - return s; - }; - - (*(node_list + cast(**Node, i))) = maybe_expr; - i = i + 1; - }; - - let s = cast(*slice, arena_alloc((*p).arena, sizeof(slice))); - (*s).data = cast(*void, node_list); - (*s).data_len = i; - return s; -}; - -/* FunctionCallStatement ::= (IDENTIFIER | FunctionDefinition) LPAREN FunctionArguments? RPAREN */ -let parse_function_call_statement = (p: *parser) => *Node { - let ident = parser_accept_token(p, TOKEN_IDENTIFIER); - let fn_def = parser_accept_parse(p, parser_parse_function_definition); - - if ident == cast(*token, null) { - if fn_def == cast(*Node, null) { - return cast(*Node, null); - }; - }; - - if parser_accept_token(p, TOKEN_LPAREN) == cast(*token, null) { - return cast(*Node, null); - }; - - let arguments = parser_parse_function_arguments(p); - if arguments == cast(*slice, null) { - return cast(*Node, null); - }; - - if parser_accept_token(p, TOKEN_RPAREN) == cast(*token, null) { - return cast(*Node, null); - }; - - let d = cast(*NODE_FUNCTION_CALL_STATEMENT_DATA , arena_alloc((*p).arena, sizeof(NODE_FUNCTION_CALL_STATEMENT_DATA))); - (*d).arguments = cast(**Node, (*arguments).data); - (*d).arguments_len = (*arguments).data_len; - - if fn_def != cast(*Node, null) { - (*d).expression = fn_def; - }; - if fn_def == cast(*Node, null) { - let expression_data = cast(*NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA, arena_alloc((*p).arena, sizeof(NODE_PRIMARY_EXPRESSION_IDENTIFIER_DATA))); - (*expression_data).name = cast(*i8, (*ident).data); - let expression = cast(*Node, arena_alloc((*p).arena, sizeof(Node))); - (*expression).type = NODE_PRIMARY_EXPRESSION_IDENTIFIER; - (*expression).data = cast(*void, expression_data); - (*d).expression = expression; - }; - - let n = Node{}; - n.type = NODE_FUNCTION_CALL_STATEMENT; - n.data = cast(*void, d); - return create_node(p, n); -}; - -/* Statement ::= (AssignmentStatement | ImportDeclaration | ExternDeclaration | CastStatement | SizeOfStatement | FunctionCallStatement | IfStatement | WhileStatement | ReturnStatement | "break" | "continue") SEMICOLON */ -let parser_parse_statement = (p: *parser) => *Node { - /* TODO: Can we not deal with cast / sizeof in parser? */ - let fn_call = parser_accept_parse(p, parser_parse_cast_statement); - if fn_call != cast(*Node, null) { - if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { - return cast(*Node, null); - }; - return fn_call; - }; - - let fn_call = parser_accept_parse(p, parser_parse_sizeof_statement); - if fn_call != cast(*Node, null) { - if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { - return cast(*Node, null); - }; - return fn_call; - }; - - let fn_call = parser_accept_parse(p, parse_function_call_statement); - if fn_call != cast(*Node, null) { - if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { - return cast(*Node, null); - }; - return fn_call; - }; - - let assignment = parser_accept_parse(p, parse_assignment_statement); - if assignment != cast(*Node, null) { - if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { - return cast(*Node, null); - }; - return assignment; - }; - - let retu = parser_accept_parse(p, parser_parse_return_statement); - if retu != cast(*Node, null) { - if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { - return cast(*Node, null); - }; - return retu; - }; - - let retu = parser_accept_parse(p, parser_parse_import_declaration); - if retu != cast(*Node, null) { - if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { - return cast(*Node, null); - }; - return retu; - }; - - let retu = parser_accept_parse(p, parser_parse_extern_declaration); - if retu != cast(*Node, null) { - if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { - return cast(*Node, null); - }; - return retu; - }; - - let retu = parser_accept_parse(p, parser_parse_if_statement); - if retu != cast(*Node, null) { - if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { - return cast(*Node, null); - }; - return retu; - }; - - let retu = parser_accept_parse(p, parser_parse_while_statement); - if retu != cast(*Node, null) { - if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { - return cast(*Node, null); - }; - return retu; - }; - - /* Break and continue */ - let retu = parser_accept_parse(p, (ip: *parser) => *Node { - if parser_accept_token(ip, TOKEN_BREAK) == cast(*token, null) { - return cast(*Node, null); - }; - - let n = Node{}; - n.type = NODE_BREAK_STATEMENT; - return create_node(ip, n); - }); - if retu != cast(*Node, null) { - if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { - return cast(*Node, null); - }; - return retu; - }; - - let retu = parser_accept_parse(p, (ip: *parser) => *Node { - if parser_accept_token(ip, TOKEN_CONTINUE) == cast(*token, null) { - return cast(*Node, null); - }; - - let n = Node{}; - n.type = NODE_CONTINUE_STATEMENT; - return create_node(ip, n); - }); - if retu != cast(*Node, null) { - if parser_accept_token(p, TOKEN_SEMICOLON) == cast(*token, null) { - return cast(*Node, null); - }; - return retu; - }; - - printf("None\n"); - - return cast(*Node, null); -}; - -/* Program ::= Statement+ */ -let parse_program = (p: *parser) => *Node { - let nodes = cast(**Node, arena_alloc((*p).arena, sizeof(*Node) * 50000)); - - let i = 0; - while (*p).offset < (*p).tokens_len { - let s = parser_parse_statement(p); - assert(s != cast(*Node, null)); - (*(nodes + cast(**Node, i))) = s; - i = i + 1; - }; - - let d = cast(*NODE_PROGRAM_DATA, arena_alloc((*p).arena, sizeof(NODE_PROGRAM_DATA))); - (*d).statements = nodes; - (*d).statements_len = i; - let n = Node{}; - n.type = NODE_PROGRAM; - n.data = cast(*void, d); - return create_node(p, n); -}; - -let parse = (p: *parser) => *Node { - return parse_program(p); -}; diff --git a/src/bootstrap/tokenizer.pry b/src/bootstrap/tokenizer.pry deleted file mode 100644 index ddc2cef..0000000 --- a/src/bootstrap/tokenizer.pry +++ /dev/null @@ -1,553 +0,0 @@ -extern strlen = (*i8) => i64; -extern memcpy = (*void, *void, i64) => void; -extern sprintf = (*i8, *i8, varargs) => void; -extern atoi = (*i8) => i64; - -import "!stdlib.pry"; -import "!mem.pry"; - -/* Keywords */ -let TOKEN_IMPORT = 1; -let TOKEN_LET = 2; -let TOKEN_EXTERN = 3; -let TOKEN_IF = 4; -let TOKEN_WHILE = 5; -let TOKEN_RETURN = 6; -let TOKEN_BREAK = 7; -let TOKEN_CONTINUE = 8; -let TOKEN_ARROW = 9; -let TOKEN_STRUCT = 10; -let TOKEN_TYPE = 34; - -/* Identifiers */ -let TOKEN_IDENTIFIER = 11; - -/* Literals */ -let TOKEN_NUMBER = 12; -let TOKEN_BOOLEAN = 13; -let TOKEN_NULL = 14; -let TOKEN_CHAR = 15; -let TOKEN_STRING = 16; - -/* Operators */ -let TOKEN_EQUALS = 17; -let TOKEN_PLUS = 18; -let TOKEN_MINUS = 19; -let TOKEN_MUL = 20; -let TOKEN_DIV = 21; -let TOKEN_MOD = 22; -let TOKEN_BANG = 23; -let TOKEN_LESS = 24; -let TOKEN_GREATER = 25; -let TOKEN_DOT = 26; - -/* Punctuation */ -let TOKEN_SEMICOLON = 27; -let TOKEN_COMMA = 28; -let TOKEN_COLON = 29; -let TOKEN_LPAREN = 30; -let TOKEN_RPAREN = 31; -let TOKEN_LBRACE = 32; -let TOKEN_RBRACE = 33; - -let token = struct { - type: i64, - data: *void, -}; - -let tokenizer = struct { - buf: *i8, - buf_len: i64, - offset: i64, - - arena: *arena, -}; - -let print_tokens = (ts: *token, ts_len: i64) => i64 { - let i = 0; - while i < ts_len { - let to = (*(ts + cast(*token, i))); - - if (to.type == TOKEN_IMPORT) { - printf("Import\n"); - }; - if (to.type == TOKEN_LET) { - printf("Let\n"); - }; - if (to.type == TOKEN_EXTERN) { - printf("Extern\n"); - }; - if (to.type == TOKEN_IF) { - printf("If\n"); - }; - if (to.type == TOKEN_WHILE) { - printf("While\n"); - }; - if (to.type == TOKEN_RETURN) { - printf("Return\n"); - }; - if (to.type == TOKEN_BREAK) { - printf("Break\n"); - }; - if (to.type == TOKEN_CONTINUE) { - printf("Continue\n"); - }; - if (to.type == TOKEN_ARROW) { - printf("Arrow\n"); - }; - if (to.type == TOKEN_STRUCT) { - printf("Struct\n"); - }; - if (to.type == TOKEN_TYPE) { - printf("Type\n"); - }; - if (to.type == TOKEN_IDENTIFIER) { - printf("Identifier: %s\n", cast(*i8, to.data)); - }; - if (to.type == TOKEN_NUMBER) { - printf("Number: %d\n", *cast(*i64, to.data)); - }; - if (to.type == TOKEN_BOOLEAN) { - printf("Boolean: %d\n", *cast(*bool, to.data)); - }; - if (to.type == TOKEN_NULL) { - printf("Null\n"); - }; - if (to.type == TOKEN_CHAR) { - printf("Char: %c\n", *cast(*i8, to.data)); - }; - if (to.type == TOKEN_STRING) { - printf("String: %s\n", cast(*i8, to.data)); - }; - if (to.type == TOKEN_EQUALS) { - printf("Equals\n"); - }; - if (to.type == TOKEN_PLUS) { - printf("Plus\n"); - }; - if (to.type == TOKEN_MINUS) { - printf("Minus\n"); - }; - if (to.type == TOKEN_MUL) { - printf("Mul\n"); - }; - if (to.type == TOKEN_DIV) { - printf("Div\n"); - }; - if (to.type == TOKEN_MOD) { - printf("Mod\n"); - }; - if (to.type == TOKEN_BANG) { - printf("Bang\n"); - }; - if (to.type == TOKEN_LESS) { - printf("Less\n"); - }; - if (to.type == TOKEN_GREATER) { - printf("Greater\n"); - }; - if (to.type == TOKEN_DOT) { - printf("Dot\n"); - }; - if (to.type == TOKEN_SEMICOLON) { - printf("Semicolon\n"); - }; - if (to.type == TOKEN_COMMA) { - printf("Comma\n"); - }; - if (to.type == TOKEN_COLON) { - printf("Colon\n"); - }; - if (to.type == TOKEN_LPAREN) { - printf("LParen\n"); - }; - if (to.type == TOKEN_RPAREN) { - printf("RParen\n"); - }; - if (to.type == TOKEN_LBRACE) { - printf("LBrace\n"); - }; - if (to.type == TOKEN_RBRACE) { - printf("RBrace\n"); - }; - - i = i + 1; - }; - - return 0; -}; - -let tokenizer_skip_whitespace = (t: *tokenizer) => void { - while true { - if (*t).offset >= (*t).buf_len { return; }; - let c = (*((*t).buf + cast(*i8, (*t).offset))); - if !iswhitespace(c) { - return; - }; - (*t).offset = (*t).offset + 1; - }; - - return; -}; - -let tokenizer_accept_string = (t: *tokenizer, str: *i8) => bool { - let str_len = strlen(str); - if (*t).offset + str_len > (*t).buf_len { return false; }; - - let s = cast(*i8, arena_alloc((*t).arena, 1000)); - memcpy(cast(*void, s), cast(*void, (*t).buf + cast(*i8, (*t).offset)), str_len); - - if strcmp(s, str) { - (*t).offset = (*t).offset + str_len; - return true; - }; - - return false; -}; - -let tokenizer_consume_until_condition = (t: *tokenizer, condition: (i8) => bool) => *i8 { - let start = (*t).offset; - let res = cast(*i8, arena_alloc((*t).arena, 1000)); - - while true { - if (*t).offset >= (*t).buf_len { - return res; - }; - - let c = (*((*t).buf + cast(*i8, (*t).offset))); - - let offset = (*t).offset; - if c == '\\' { - let next_c = (*((*t).buf + cast(*i8, offset + 1))); - - let any = false; - if next_c == 'n' { - (*(res + cast(*i8, offset - start))) = '\n'; - any = true; - }; - if next_c == 't' { - (*(res + cast(*i8, offset - start))) = '\t'; - any = true; - }; - if next_c == 'r' { - (*(res + cast(*i8, offset - start))) = '\r'; - any = true; - }; - if next_c == '0' { - (*(res + cast(*i8, offset - start))) = '\0'; - any = true; - }; - if next_c == '\\' { - (*(res + cast(*i8, offset - start))) = '\\'; - any = true; - }; - if !any { - (*(res + cast(*i8, offset - start))) = next_c; - }; - - offset = offset + 1; - offset = offset + 1; - (*t).offset = offset; - - continue; - }; - - if condition(c) { - return res; - }; - - (*(res + cast(*i8, offset - start))) = c; - (*(res + cast(*i8, offset - start + 1))) = '\0'; - - offset = offset + 1; - (*t).offset = offset; - }; - - return cast(*i8, null); -}; - -let tokenizer_accept_int_type = (t: *tokenizer) => *i64 { - let string = tokenizer_consume_until_condition(t, (c: i8) => bool { - return !isdigit(c); - }); - if string == cast(*i8, null) { - return cast(*i64, null); - }; - if strlen(string) == 0 { - return cast(*i64, null); - }; - let x = cast(*i64, arena_alloc((*t).arena, sizeof(i64))); - *x = atoi(string); - return x; -}; - -let tokenizer_accept_char_type = (t: *tokenizer) => *i8 { - let prev_offset = (*t).offset; - if !tokenizer_accept_string(t, "'") { - (*t).offset = prev_offset; - return cast(*i8, null); - }; - - let string = tokenizer_consume_until_condition(t, (c: i8) => bool { - return c == '\''; - }); - - if !tokenizer_accept_string(t, "'") { - (*t).offset = prev_offset; - return cast(*i8, null); - }; - - return string; -}; - -let tokenizer_accept_string_type = (t: *tokenizer) => *i8 { - let prev_offset = (*t).offset; - if !tokenizer_accept_string(t, "\"") { - (*t).offset = prev_offset; - return cast(*i8, null); - }; - - let string = tokenizer_consume_until_condition(t, (c: i8) => bool { - return c == '"'; - }); - - if !tokenizer_accept_string(t, "\"") { - (*t).offset = prev_offset; - return cast(*i8, null); - }; - - return string; -}; - -let tokenizer_skip_comments = (t: *tokenizer) => void { - if !tokenizer_accept_string(t, "/*") { return; }; - - while !tokenizer_accept_string(t, "*/") { - (*t).offset = (*t).offset + 1; - }; - - return; -}; - -let tokenizer_next = (t: *tokenizer) => *token { - tokenizer_skip_whitespace(t); - tokenizer_skip_comments(t); - tokenizer_skip_whitespace(t); - - if (*t).offset >= (*t).buf_len { - return cast(*token, null); - }; - - let to = cast(*token, arena_alloc((*t).arena, sizeof(token))); - - if tokenizer_accept_string(t, "import") { - (*to).type = TOKEN_IMPORT; - return to; - }; - if tokenizer_accept_string(t, "let") { - (*to).type = TOKEN_LET; - return to; - }; - if tokenizer_accept_string(t, "extern") { - (*to).type = TOKEN_EXTERN; - return to; - }; - if tokenizer_accept_string(t, "if") { - (*to).type = TOKEN_IF; - return to; - }; - if tokenizer_accept_string(t, "while") { - (*to).type = TOKEN_WHILE; - return to; - }; - if tokenizer_accept_string(t, "return") { - (*to).type = TOKEN_RETURN; - return to; - }; - if tokenizer_accept_string(t, "break") { - (*to).type = TOKEN_BREAK; - return to; - }; - if tokenizer_accept_string(t, "continue") { - (*to).type = TOKEN_CONTINUE; - return to; - }; - if tokenizer_accept_string(t, "true") { - (*to).type = TOKEN_BOOLEAN; - let data = cast(*bool, arena_alloc((*t).arena, sizeof(bool))); - *data = true; - (*to).data = cast(*void, data); - return to; - }; - if tokenizer_accept_string(t, "false") { - (*to).type = TOKEN_BOOLEAN; - let data = cast(*bool, arena_alloc((*t).arena, sizeof(bool))); - *data = false; - (*to).data = cast(*void, data); - return to; - }; - if tokenizer_accept_string(t, "null") { - (*to).type = TOKEN_NULL; - return to; - }; - if tokenizer_accept_string(t, "struct") { - (*to).type = TOKEN_STRUCT; - return to; - }; - if tokenizer_accept_string(t, "newtype") { - (*to).type = TOKEN_TYPE; - return to; - }; - - if tokenizer_accept_string(t, "=>") { - (*to).type = TOKEN_ARROW; - return to; - }; - if tokenizer_accept_string(t, ";") { - (*to).type = TOKEN_SEMICOLON; - return to; - }; - if tokenizer_accept_string(t, ",") { - (*to).type = TOKEN_COMMA; - return to; - }; - if tokenizer_accept_string(t, ":") { - (*to).type = TOKEN_COLON; - return to; - }; - if tokenizer_accept_string(t, "(") { - (*to).type = TOKEN_LPAREN; - return to; - }; - if tokenizer_accept_string(t, ")") { - (*to).type = TOKEN_RPAREN; - return to; - }; - if tokenizer_accept_string(t, "{") { - (*to).type = TOKEN_LBRACE; - return to; - }; - if tokenizer_accept_string(t, "}") { - (*to).type = TOKEN_RBRACE; - return to; - }; - if tokenizer_accept_string(t, "=") { - (*to).type = TOKEN_EQUALS; - return to; - }; - if tokenizer_accept_string(t, "+") { - (*to).type = TOKEN_PLUS; - return to; - }; - if tokenizer_accept_string(t, "-") { - (*to).type = TOKEN_MINUS; - return to; - }; - if tokenizer_accept_string(t, "*") { - (*to).type = TOKEN_MUL; - return to; - }; - if tokenizer_accept_string(t, "/") { - (*to).type = TOKEN_DIV; - return to; - }; - if tokenizer_accept_string(t, "%") { - (*to).type = TOKEN_MOD; - return to; - }; - if tokenizer_accept_string(t, "!") { - (*to).type = TOKEN_BANG; - return to; - }; - if tokenizer_accept_string(t, "<") { - (*to).type = TOKEN_LESS; - return to; - }; - if tokenizer_accept_string(t, ">") { - (*to).type = TOKEN_GREATER; - return to; - }; - if tokenizer_accept_string(t, ".") { - (*to).type = TOKEN_DOT; - return to; - }; - - let maybe_int = tokenizer_accept_int_type(t); - if maybe_int != cast(*i64, null) { - (*to).type = TOKEN_NUMBER; - (*to).data = cast(*void, maybe_int); - return to; - }; - - let maybe_char = tokenizer_accept_char_type(t); - if maybe_char != cast(*i8, null) { - (*to).type = TOKEN_CHAR; - (*to).data = cast(*void, maybe_char); - return to; - }; - - let maybe_string = tokenizer_accept_string_type(t); - if maybe_string != cast(*i8, null) { - (*to).type = TOKEN_STRING; - (*to).data = cast(*void, maybe_string); - return to; - }; - - let string = tokenizer_consume_until_condition(t, (c: i8) => bool { - if isalphanum(c) { - return false; - }; - if c == '_' { - return false; - }; - return true; - }); - if strlen(string) == 0 { - printf("NO IDENT!\n"); - return cast(*token, null); - }; - - (*to).type = TOKEN_IDENTIFIER; - (*to).data = cast(*void, string); - - return to; -}; - -let tokenizer_init = (alloc: *arena, file: slice) => *tokenizer { - let t = cast(*tokenizer, arena_alloc(alloc, sizeof(tokenizer))); - (*t).arena = alloc; - (*t).offset = 0; - (*t).buf = cast(*i8, file.data); - (*t).buf_len = file.data_len; - - printf("File size: %d\n", (*t).buf_len); - - printf("%s\n", (*t).buf); - - return t; -}; - -let tokenizer_tokenize = (t: *tokenizer) => slice { - let tokens = cast(*token, arena_alloc((*t).arena, sizeof(token) * 40000)); /* why does it not care about type here */ - let tokens_len = 0; - - while true { - let tk = tokenizer_next(t); - if tk == cast(*token, null) { - break; - }; - printf("Add token: %d\n", (*tk).type); - - (*(tokens + cast(*token, tokens_len))) = *tk; - tokens_len = tokens_len + 1; - }; - - printf("PRINT TOKENS: %d\n", tokens_len); - - print_tokens(tokens, tokens_len); - - let res = slice{}; - res.data = cast(*void, tokens); - res.data_len = tokens_len; - return res; -}; |