Add return statement
Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
parent
6d94a65649
commit
1d9277e200
11
ast.odin
11
ast.odin
@ -20,6 +20,7 @@ NodeKind :: enum {
|
|||||||
VariableDeclaration,
|
VariableDeclaration,
|
||||||
Cast,
|
Cast,
|
||||||
BitwiseCast,
|
BitwiseCast,
|
||||||
|
Ret,
|
||||||
|
|
||||||
//
|
//
|
||||||
Function,
|
Function,
|
||||||
@ -301,6 +302,16 @@ node_create_bitwise_cast :: proc(
|
|||||||
return
|
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(
|
node_create_struct_enum_or_union :: proc(
|
||||||
range: TextRange,
|
range: TextRange,
|
||||||
kind: NodeKind,
|
kind: NodeKind,
|
||||||
|
13
parser.odin
13
parser.odin
@ -101,6 +101,8 @@ parser_parse_statement :: proc(parser: ^Parser) -> (ret: ^Node) {
|
|||||||
ret = parser_parse_enum_definition(parser)
|
ret = parser_parse_enum_definition(parser)
|
||||||
} else if parser.tok.kind == .Union {
|
} else if parser.tok.kind == .Union {
|
||||||
ret = parser_parse_union_definition(parser)
|
ret = parser_parse_union_definition(parser)
|
||||||
|
} else if parser.tok.kind == .Ret {
|
||||||
|
ret = parser_parse_ret(parser)
|
||||||
} else {
|
} else {
|
||||||
ret = parser_parse_expression(parser)
|
ret = parser_parse_expression(parser)
|
||||||
expect(parser, .Semicolon)
|
expect(parser, .Semicolon)
|
||||||
@ -111,6 +113,17 @@ parser_parse_statement :: proc(parser: ^Parser) -> (ret: ^Node) {
|
|||||||
return
|
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")
|
@(private = "file")
|
||||||
parser_parse_struct_definition :: proc(parser: ^Parser) -> ^Node {
|
parser_parse_struct_definition :: proc(parser: ^Parser) -> ^Node {
|
||||||
range := parser.tok.range
|
range := parser.tok.range
|
||||||
|
@ -2,7 +2,7 @@ let asdf := 123.0
|
|||||||
let poop :: 12 as f32 + 2.0 * asdf
|
let poop :: 12 as f32 + 2.0 * asdf
|
||||||
|
|
||||||
fn name(a b: f32) i32 {
|
fn name(a b: f32) i32 {
|
||||||
a + b
|
ret (a + b) as i32
|
||||||
}
|
}
|
||||||
|
|
||||||
name 123 as f32 456.0
|
name 123 as f32 456.0
|
||||||
|
@ -7,6 +7,7 @@ Scope :: struct {
|
|||||||
function_definitions: map[int]^FunctionType, // A map to nodes which are the function definitions
|
function_definitions: map[int]^FunctionType, // A map to nodes which are the function definitions
|
||||||
variable_definitions: map[int]^Type, // A map to types
|
variable_definitions: map[int]^Type, // A map to types
|
||||||
variable_mutability_definitions: map[int]bool, // A map to a variable's mutability
|
variable_mutability_definitions: map[int]bool, // A map to a variable's mutability
|
||||||
|
function_return_type: ^Type,
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private = "file")
|
@(private = "file")
|
||||||
@ -66,6 +67,8 @@ scope_enter :: proc() {
|
|||||||
append(&scope_stack, Scope{})
|
append(&scope_stack, Scope{})
|
||||||
scope_stack[len(scope_stack) - 1].function_definitions = make(map[int]^FunctionType)
|
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_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() {
|
scope_leave :: proc() {
|
||||||
@ -99,6 +102,15 @@ scope_function_lookup :: proc(name: [dynamic]u8) -> ^FunctionType {
|
|||||||
return nil
|
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 {
|
type_check_function_call :: proc(ast: ^Node, parent_ast: ^Node, must_be_function := true) -> ^FunctionType {
|
||||||
name : [dynamic]u8
|
name : [dynamic]u8
|
||||||
if ast.kind == .FunctionCall {
|
if ast.kind == .FunctionCall {
|
||||||
@ -230,6 +242,28 @@ type_check :: proc(ast: ^Node, parent_ast: ^Node) {
|
|||||||
case .UnaryExpression:
|
case .UnaryExpression:
|
||||||
// FIXME: Verify that the operation is possible
|
// FIXME: Verify that the operation is possible
|
||||||
type_check(ast.children[0], ast)
|
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:
|
case .Cast:
|
||||||
type_check(ast.children[0], ast)
|
type_check(ast.children[0], ast)
|
||||||
type_to := ast_to_type(ast.children[1])
|
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
|
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:
|
case .Function:
|
||||||
scope_enter()
|
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 {
|
for child, i in ast.children {
|
||||||
if i < 2 {
|
if i < 2 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
type_check(child, ast)
|
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_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)
|
type_check(ast.children[1], ast)
|
||||||
ast.return_type = ast.children[0].return_type
|
|
||||||
scope_leave()
|
scope_leave()
|
||||||
case:
|
case:
|
||||||
fmt.panicf("Unhandled node kind in type_check: {}", ast.kind)
|
fmt.panicf("Unhandled node kind in type_check: {}", ast.kind)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user