Add support for while loops

This commit is contained in:
Slendi 2024-03-02 21:47:36 +02:00
parent 907a5d12ca
commit 3f2ee15302
5 changed files with 81 additions and 10 deletions

View File

@ -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)
}
}

View File

@ -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)

View File

@ -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")

View File

@ -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 {

View File

@ -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
}