Add return statement

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
Slendi 2024-02-28 15:07:07 +02:00
parent 6d94a65649
commit 1d9277e200
4 changed files with 62 additions and 2 deletions

View File

@ -20,6 +20,7 @@ NodeKind :: enum {
VariableDeclaration,
Cast,
BitwiseCast,
Ret,
//
Function,
@ -301,6 +302,16 @@ node_create_bitwise_cast :: proc(
return
}
node_create_ret :: proc(range: TextRange, value: ^Node) -> (ret: ^Node) {
ret = new(Node)
ret^ = {
kind = .Ret,
range = range,
children = {value},
}
return
}
node_create_struct_enum_or_union :: proc(
range: TextRange,
kind: NodeKind,

View File

@ -101,6 +101,8 @@ parser_parse_statement :: proc(parser: ^Parser) -> (ret: ^Node) {
ret = parser_parse_enum_definition(parser)
} else if parser.tok.kind == .Union {
ret = parser_parse_union_definition(parser)
} else if parser.tok.kind == .Ret {
ret = parser_parse_ret(parser)
} else {
ret = parser_parse_expression(parser)
expect(parser, .Semicolon)
@ -111,6 +113,17 @@ parser_parse_statement :: proc(parser: ^Parser) -> (ret: ^Node) {
return
}
@(private = "file")
parser_parse_ret :: proc(parser: ^Parser) -> ^Node {
range := parser.tok.range
expect(parser, .Ret)
if parser.tok.kind == .Semicolon {
return node_create_ret(range, nil)
}
ret := parser_parse_expression(parser)
return node_create_ret(range, ret)
}
@(private = "file")
parser_parse_struct_definition :: proc(parser: ^Parser) -> ^Node {
range := parser.tok.range

View File

@ -2,7 +2,7 @@ let asdf := 123.0
let poop :: 12 as f32 + 2.0 * asdf
fn name(a b: f32) i32 {
a + b
ret (a + b) as i32
}
name 123 as f32 456.0

View File

@ -7,6 +7,7 @@ Scope :: struct {
function_definitions: map[int]^FunctionType, // A map to nodes which are the function definitions
variable_definitions: map[int]^Type, // A map to types
variable_mutability_definitions: map[int]bool, // A map to a variable's mutability
function_return_type: ^Type,
}
@(private = "file")
@ -66,6 +67,8 @@ scope_enter :: proc() {
append(&scope_stack, Scope{})
scope_stack[len(scope_stack) - 1].function_definitions = make(map[int]^FunctionType)
scope_stack[len(scope_stack) - 1].variable_definitions = make(map[int]^Type)
scope_stack[len(scope_stack) - 1].variable_mutability_definitions = make(map[int]bool)
scope_stack[len(scope_stack) - 1].function_return_type = nil
}
scope_leave :: proc() {
@ -99,6 +102,15 @@ scope_function_lookup :: proc(name: [dynamic]u8) -> ^FunctionType {
return nil
}
scope_function_return_type_lookup :: proc() -> ^Type {
#reverse for &scope in scope_stack {
if scope.function_return_type != nil {
return scope.function_return_type
}
}
return nil
}
type_check_function_call :: proc(ast: ^Node, parent_ast: ^Node, must_be_function := true) -> ^FunctionType {
name : [dynamic]u8
if ast.kind == .FunctionCall {
@ -230,6 +242,28 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) {
case .UnaryExpression:
// FIXME: Verify that the operation is possible
type_check(ast.children[0], ast)
case .Ret:
function_return_type := scope_function_return_type_lookup()
if function_return_type == nil {
append(&g_message_list,
message_create(
.Error,
fmt.aprintf("Return statement outside of function"),
ast.range,
),
)
} else {
type_check(ast.children[0], ast)
if !compare_types(function_return_type, ast.children[0].return_type) {
append(&g_message_list,
message_create(
.Error,
fmt.aprintf("Type mismatch: {} and {}", function_return_type, ast.children[0].return_type),
ast.range,
),
)
}
}
case .Cast:
type_check(ast.children[0], ast)
type_to := ast_to_type(ast.children[1])
@ -260,15 +294,17 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) {
scope_stack[len(scope_stack) - 1].variable_definitions[get_character_sum_of_dyn_arr(&ast.children[0].value.([dynamic]u8))] = ast.return_type
case .Function:
scope_enter()
ast.return_type = ast_to_type(ast.children[0])
scope_stack[len(scope_stack) - 1].function_return_type = ast.return_type
for child, i in ast.children {
if i < 2 {
continue
}
type_check(child, ast)
scope_stack[len(scope_stack) - 1].variable_definitions[get_character_sum_of_dyn_arr(&child.children[0].value.([dynamic]u8))] = child.return_type
scope_stack[len(scope_stack) - 1].variable_mutability_definitions[get_character_sum_of_dyn_arr(&child.children[0].value.([dynamic]u8))] = true
}
type_check(ast.children[1], ast)
ast.return_type = ast.children[0].return_type
scope_leave()
case:
fmt.panicf("Unhandled node kind in type_check: {}", ast.kind)