diff --git a/src/llvm_emitter.odin b/src/llvm_emitter.odin index fe2fc7a..2ed1992 100644 --- a/src/llvm_emitter.odin +++ b/src/llvm_emitter.odin @@ -320,6 +320,24 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil return LLVMBuildICmp(builder, .LLVMIntUGE, lhs, rhs, "getmp") } } + case .Assign: + if node.children[0].kind != .Identifier { + fmt.panicf("LLVM-C: Left hand side of assignment is not an identifier") + } + name := &node.children[0].value.([dynamic]u8) + def := llvm_scope_find_definition(name) + if def == nil { + append( + &g_message_list, + message_create( + .Error, + fmt.aprintf("Variable '%s' not found", name), + node.range, + ), + ) + return nil + } + return LLVMBuildStore(builder, rhs, def) case: fmt.panicf("LLVM-C: Unexpected binary expression kind: {}", op) } @@ -402,10 +420,30 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil LLVMBuildBr(builder, basic_block) LLVMPositionBuilderAtEnd(builder, basic_block) scope_number^ += 1 + llvm_scope_enter("for_body", basic_block) generate_llvm_scope(ctx, mod, builder, function, node.children[3], scope_number, basic_block) + llvm_scope_leave() LLVMBuildBr(builder, basic_block) } else if loop_type == LoopType.While { - panic("FIXME: Implement while loops") + fmt.println("In while") + condition_block := LLVMAppendBasicBlockInContext(ctx, function, "while_condition") + body_block := LLVMAppendBasicBlockInContext(ctx, function, "while_body") + end_block := LLVMAppendBasicBlockInContext(ctx, function, "while_end") + + LLVMBuildBr(builder, condition_block) + + LLVMPositionBuilderAtEnd(builder, condition_block) + cond := generate_llvm_expression(ctx, mod, builder, node.children[1]) + LLVMBuildCondBr(builder, cond, body_block, end_block) + + LLVMPositionBuilderAtEnd(builder, body_block) + llvm_scope_enter("for_body", body_block) + scope_number^ += 1 + generate_llvm_scope(ctx, mod, builder, function, node.children[3], scope_number, body_block) + llvm_scope_leave() + LLVMBuildBr(builder, condition_block) + + LLVMPositionBuilderAtEnd(builder, end_block) } } diff --git a/src/main.odin b/src/main.odin index 7bb1326..d40fd54 100644 --- a/src/main.odin +++ b/src/main.odin @@ -38,8 +38,12 @@ main :: proc() { } return } + fmt.println("After parse:") + node_print(ast) clear(&g_message_list) type_check(ast, nil) + fmt.println("After type check:") + node_print(ast) if len(g_message_list) > 0 { for msg in g_message_list { fmt.printf("%s\n", msg) diff --git a/src/parser.odin b/src/parser.odin index d8416e0..275dee0 100644 --- a/src/parser.odin +++ b/src/parser.odin @@ -356,14 +356,29 @@ parser_parse_binary_expression :: proc( kinds: []TokenKind, next: proc(parser: ^Parser) -> ^Node, ) -> ^Node { + poo := false + if (parser.next.kind == .BitwiseLeftShift) { + fmt.println("parser_parse_bitwise {} {}", parser.tok.kind, parser.next.kind) + poo = true + } + lhs := next(parser) for kind in kinds { for accept(parser, kind) { + prev_can_be_function := parser.can_be_function + parser.can_be_function = false rhs := next(parser) lhs = node_create_binary(kind, lhs.range, lhs, rhs) lhs^.range.end = rhs.range.end + parser.can_be_function = prev_can_be_function } } + + if poo { + fmt.println("parser_parse_bitwise2 {} {}", parser.tok.kind, parser.next.kind) + + } + return lhs } @@ -431,7 +446,7 @@ parser_parse_multiplication :: proc(parser: ^Parser) -> ^Node { @(private = "file") parser_parse_exponent :: proc(parser: ^Parser) -> ^Node { - return parser_parse_binary_expression(parser, {.Exponent}, parser_parse_prefix_2) + return parser_parse_binary_expression(parser, {.Exponent}, parser_parse_bitwise) } @(private = "file") diff --git a/src/type_checker.odin b/src/type_checker.odin index 9842b11..c653ae2 100644 --- a/src/type_checker.odin +++ b/src/type_checker.odin @@ -98,6 +98,17 @@ scope_variable_lookup :: proc(name: [dynamic]u8) -> ^Type { return nil } +scope_variable_lookup_mutable :: proc(name: [dynamic]u8) -> bool { + name_ := name + #reverse for &scope in scope_stack { + type, ok := scope.variable_mutability_definitions[get_character_sum_of_dyn_arr(&name_)] + if ok { + return type + } + } + return false +} + scope_function_lookup :: proc(name: [dynamic]u8) -> ^FunctionType { name_ := name #reverse for &scope in scope_stack { @@ -241,11 +252,12 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { if ast.value_token_kind == .Assign { ast.return_type = nil - if !scope_stack[len(scope_stack) - 1].variable_mutability_definitions[get_character_sum_of_dyn_arr(&ast.children[0].value.([dynamic]u8))] { + + if !scope_variable_lookup_mutable(ast.children[0].value.([dynamic]u8)) { append(&g_message_list, message_create( .Error, - fmt.aprintf("Variable is not mutable: {}", ast.children[0].value.([dynamic]u8)), + fmt.aprintf("Variable is not mutable: %s", ast.children[0].value.([dynamic]u8)), ast.range, ), ) @@ -310,6 +322,7 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { ast.return_type = ast_to_type(ast.children[1]) } scope_stack[len(scope_stack) - 1].variable_definitions[get_character_sum_of_dyn_arr(&ast.children[0].value.([dynamic]u8))] = ast.return_type + scope_stack[len(scope_stack) - 1].variable_mutability_definitions[get_character_sum_of_dyn_arr(&ast.children[0].value.([dynamic]u8))] = !ast.value.(bool) case .If: type_check(ast.children[0], ast) if ast.children[0].return_type == nil || ast.children[0].return_type.kind != .Integer { diff --git a/test_type_checker.cat b/test_type_checker.cat index f7d54df..f543d42 100644 --- a/test_type_checker.cat +++ b/test_type_checker.cat @@ -11,11 +11,11 @@ fn put_i32(val: i32) i32 -\let amogus := 500 + (put_i32 8008135) -\ -\put_i32 69 * amogus + 420 +let amogus := 500 + (put_i32 8008135) -let a b := 2 1 +put_i32 69 * amogus + 420 + +let a b := 5 1 if a == 5 { if b { @@ -29,6 +29,7 @@ if a == 5 { put_i32 420 } -for { - put_i32 123456789 +for a != 0 { + put_i32 (1 << a) + a = a - 1 }