diff --git a/pong.cat b/pong.cat index c525e22..241e7c3 100644 --- a/pong.cat +++ b/pong.cat @@ -1,3 +1,18 @@ +struct Vec2 { + x y: f32, +} + +struct Rect { + pos size: Vec2, +} + +let CONSTPOS :: .Vec2 {20.0 20.0} +let CONSTSZ :: .Vec2 {100.0 100.0} +let CONST :: .Rect {(CONSTPOS) (CONSTSZ)} + +\ FIXME: LLVM IR geneartion is borked +\ let CONST :: .Rect { .Vec2 { 20.0 20.0 } .Vec2 { 100.0 100.0 } } + struct Color { r g b a: u8, } @@ -47,10 +62,10 @@ fn DrawTextWrap(text: []u8, x y size: i32, c: Color) { DrawText text x y size (ColorToRaylib c) } -let WHITE :: .Color{255 255 255 255} -let BLACK :: .Color{0 0 0 255} -let RED :: .Color{255 0 0 255} -let BLUE :: .Color{0 0 255 255} +let WHITE :: .Color {255 255 255 255} +let BLACK :: .Color {0 0 0 255} +let RED :: .Color {255 0 0 255} +let BLUE :: .Color {0 0 255 255} InitWindow 800 450 Raylib SetTargetFPS 60 @@ -58,6 +73,10 @@ SetTargetFPS 60 fn GetScreenWidth i32 fn GetScreenHeight i32 +fn DrawRect(rect: Rect, c: Color) { + DrawRectangleWrap (rect.pos.x as i32) (rect.pos.y as i32) (rect.size.x as i32) (rect.size.y as i32) c +} + let logox := GetScreenWidth / 2 - 128 let logoy := GetScreenHeight / 2 - 128 @@ -121,6 +140,8 @@ for WindowShouldClose == 0 { ClearBackgroundWrap WHITE DrawFPS 20 20 + DrawRect CONST RED + if state == 0 { if (fc/15)%2 != 0 { DrawRectangleWrap logox logoy 16 16 BLACK diff --git a/src/llvm_emitter.odin b/src/llvm_emitter.odin index ee1b0bf..cf51681 100644 --- a/src/llvm_emitter.odin +++ b/src/llvm_emitter.odin @@ -325,20 +325,23 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil mod: LLVMModuleRef, builder: LLVMBuilderRef, node: ^Node, - ) -> LLVMValueRef { + ) -> ( + LLVMValueRef, + LLVMValueRef, + ) { if node.kind == .Integer { - return generate_llvm_integer(ctx, mod, builder, node) + return generate_llvm_integer(ctx, mod, builder, node), nil } else if node.kind == .String { - return generate_llvm_string(ctx, mod, builder, node) + return generate_llvm_string(ctx, mod, builder, node), nil } else if node.kind == .Float { - return generate_llvm_float(ctx, mod, builder, node) + return generate_llvm_float(ctx, mod, builder, node), nil } else if node.kind == .FunctionCall { - return generate_llvm_function_call(ctx, mod, builder, node) + return generate_llvm_function_call(ctx, mod, builder, node), nil } else if node.kind == .Identifier { def := llvm_scope_find_definition(&node.value.([dynamic]u8)) type := llvm_scope_find_type(&node.value.([dynamic]u8)) def_value := LLVMBuildLoad2(builder, type, def, "loadtmp") - return def_value + return def_value, nil } else if node.kind == .StructInitializer { struct_name := &node.value.([dynamic]u8) struct_type := llvm_scope_find_type(struct_name) @@ -347,30 +350,44 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil &g_message_list, message_create(.Error, fmt.aprintf("Struct '%s' not found", struct_name), node.range), ) - return nil + return nil, nil } struct_value := g_last_alloca - struct_values := [dynamic]LLVMValueRef{} for &field, i in node.children[:] { + last_alloc_a := g_last_alloca field_value := generate_llvm_expression(ctx, mod, builder, field) + g_last_alloca = last_alloc_a ptr_field := LLVMBuildStructGEP2(builder, struct_type, struct_value, uint(i), "inigep") LLVMBuildStore(builder, field_value, ptr_field) - append(&struct_values, field_value) } - return struct_value + return struct_value, nil } else if node.kind == .FieldAccess { + struct_name: ^[dynamic]u8 + struct_value: LLVMValueRef if node.children[0].kind == .FieldAccess { - append( - &g_message_list, - message_create(.FIXME, fmt.aprintf("Nested field accesses are not implemented."), node.range), - ) - return nil + struct_name = &node.children[0].return_type.struct_type.name + _, struct_value = generate_llvm_value(ctx, mod, builder, node.children[0]) + } else if node.children[0].kind == .Identifier { + struct_name = &node.children[0].value.([dynamic]u8) + } else { + panic("LLVM: Invalid LHS") + } + + type_struct := llvm_scope_find_type(struct_name) + if type_struct == nil { + fmt.println("Unable to find struct type definition") + } + + def_struct := llvm_scope_find_definition(struct_name) + if struct_value != nil { + def_struct = struct_value + } + if def_struct == nil { + fmt.println("Unable to find struct definition") } - def_struct := llvm_scope_find_definition(&node.children[0].value.([dynamic]u8)) - type_struct := llvm_scope_find_type(&node.children[0].value.([dynamic]u8)) type_ref := generate_llvm_type_from_node(ctx, mod, builder, node.return_type) struct_field_data := LLVMBuildAlloca(builder, type_ref, "struct_field") @@ -383,7 +400,7 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil ) def_value := LLVMBuildLoad2(builder, type_ref, def, "loadtmp") - return def_value + return def_value, def } fmt.panicf("FIXME: Implement other node kinds. Got: {}", node.kind) @@ -507,7 +524,8 @@ generate_llvm :: proc(ctx: LLVMContextRef, mod: LLVMModuleRef, builder: LLVMBuil node.kind == .Identifier || node.kind == .StructInitializer || node.kind == .FieldAccess { - return generate_llvm_value(ctx, mod, builder, node) + v, _ := generate_llvm_value(ctx, mod, builder, node) + return v } if node.kind == .FunctionCall { return generate_llvm_function_call(ctx, mod, builder, node) diff --git a/src/type.odin b/src/type.odin index 0f57b08..4e78a32 100644 --- a/src/type.odin +++ b/src/type.odin @@ -61,6 +61,19 @@ compare_types :: proc(a: ^Type, b: ^Type) -> (ret: bool, cast_required: bool) { return } + if (a.kind == .Struct && b.kind != .Struct) { + return false, false + } + if (a.kind != .Struct && b.kind == .Struct) { + return false, false + } + if (a.kind == .Struct && b.kind == .Struct) { + if (compare_dyn_arrs(&a.struct_type.name, &b.struct_type.name)) { + return true, false + } + return false, false + } + if (a.kind == .Integer || a.kind == .Float) && (a.bit_size > b.bit_size) { ret = true cast_required = true diff --git a/src/type_checker.odin b/src/type_checker.odin index c1712d0..8782951 100644 --- a/src/type_checker.odin +++ b/src/type_checker.odin @@ -268,22 +268,19 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { if rhs.kind != .Identifier { append( &g_message_list, - message_create(.Error, fmt.aprintf("Field access rhs is not an identifier or field access: {}", rhs.kind), rhs.range), - ) + message_create( + .Error, + fmt.aprintf("Field access rhs is not an identifier or field access: {}", rhs.kind), + rhs.range, + ), + ) break } if lhs.kind == .FieldAccess { type_check(lhs, ast) if lhs.return_type.kind != .Struct { - append( - &g_message_list, - message_create( - .Error, - fmt.aprintf("LHS is not a Struct type"), - lhs.range, - ), - ) + append(&g_message_list, message_create(.Error, fmt.aprintf("LHS is not a Struct type"), lhs.range)) } struct_ = scope_struct_lookup(lhs.return_type.struct_type.name) @@ -308,9 +305,7 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { struct_index: u64 = 0 found_field := false - fmt.println("==") for &field, i in struct_.fields { - fmt.printf("- %s\n", field.name) if compare_dyn_arrs(&field.name, &rhs.value.([dynamic]u8)) { ast.return_type = field.type found_field = true @@ -347,17 +342,13 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { type := scope_variable_lookup(ast.children[0].value.([dynamic]u8)) if type != nil { - if len(ast.children) != 1 { - append(&g_message_list, message_create(.Error, "Variable is not a function", ast.range)) - break - } - name := ast.children[0].value.([dynamic]u8) free(ast.children[0]) clear(&ast.children) ast.return_type = type ast.kind = .Identifier ast.value = name + type_check(ast, parent_ast) } else { fn := type_check_function_call(ast, parent_ast) if fn != nil { @@ -394,8 +385,8 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { fmt.aprintf( "Type mismatch in function call for `%s`: Wanted {}, got {}", fn.name, - param, - ast.children[i + 1].return_type, + type_to_string(param), + type_to_string(ast.children[i + 1].return_type), ), ast.range, ), @@ -467,11 +458,11 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { ) } } else if ast.value_token_kind == .Equals || - ast.value_token_kind == .NotEquals || - ast.value_token_kind == .GreaterThan || - ast.value_token_kind == .GreaterThanOrEqual || - ast.value_token_kind == .LessThan || - ast.value_token_kind == .LessThanOrEqual { + ast.value_token_kind == .NotEquals || + ast.value_token_kind == .GreaterThan || + ast.value_token_kind == .GreaterThanOrEqual || + ast.value_token_kind == .LessThan || + ast.value_token_kind == .LessThanOrEqual { ast.return_type = type_create_integer(1, true) } // FIXME: Verify that the operation is possible @@ -670,6 +661,8 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { type_check(child, ast) } + node_print(ast) + struct_ := find_struct(ast.value.([dynamic]u8)) if struct_ == nil { append( @@ -697,6 +690,7 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { idx := 0 for &child in ast.children { + fmt.printf("Comp {} and {} (struct f)\n", child.return_type.kind, struct_.fields[idx].type.kind) ok, cast_required := compare_types(child.return_type, struct_.fields[idx].type) if cast_required { cast_ := node_create_cast({}, child, {}) @@ -710,10 +704,10 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) { .Error, fmt.aprintf( "Type mismatch in struct initializer: Wanted {}, got {}", - struct_.fields[idx].type, - child.return_type, + type_to_string(struct_.fields[idx].type), + type_to_string(child.return_type), ), - ast.range, + child.range, ), ) }