Add type checker

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
Slendi 2024-02-28 15:07:06 +02:00
parent 537d93ced1
commit da19db1b23
6 changed files with 110 additions and 4 deletions

View File

@ -18,6 +18,8 @@ NodeKind :: enum {
IndexAccess,
FunctionCall,
VariableDeclaration,
Cast,
BitwiseCast,
//
Function,
@ -37,6 +39,7 @@ Node :: struct {
children: [dynamic]^Node,
value: TokenValue,
value_token_kind: TokenKind,
return_type: ^Type,
}
node_create_value :: proc(kind: NodeKind, range: TextRange, value: TokenValue) -> (ret: ^Node) {
@ -171,6 +174,9 @@ node_print :: proc(node: ^Node, indent := 0) {
if node.value_token_kind != .Invalid {
fmt.printf("{} ", node.value_token_kind)
}
if node.return_type != nil {
fmt.printf("-> {} ", node.return_type)
}
fmt.println("")
for child in node.children {
@ -265,6 +271,36 @@ node_create_variable :: proc(
return
}
node_create_cast :: proc(
range: TextRange,
value, type_: ^Node,
) -> (
ret: ^Node,
) {
ret = new(Node)
ret^ = {
kind = .Cast,
range = range,
children = {value, type_},
}
return
}
node_create_bitwise_cast :: proc(
range: TextRange,
value, type_: ^Node,
) -> (
ret: ^Node,
) {
ret = new(Node)
ret^ = {
kind = .BitwiseCast,
range = range,
children = {value, type_},
}
return
}
node_create_struct_enum_or_union :: proc(
range: TextRange,
kind: NodeKind,

View File

@ -306,10 +306,59 @@ lexer_read_identifier :: proc(lexer: ^Lexer) -> Token {
lexer_advance(lexer)
}
if compare_dyn_arr_string(
&str,
"fn",
) {return token_create(.Function, crange)} else if compare_dyn_arr_string(&str, "struct") {return token_create(.Struct, crange)} else if compare_dyn_arr_string(&str, "enum") {return token_create(.Enum, crange)} else if compare_dyn_arr_string(&str, "union") {return token_create(.Union, crange)} else if compare_dyn_arr_string(&str, "type") {return token_create(.Type, crange)} else if compare_dyn_arr_string(&str, "use") {return token_create(.Use, crange)} else if compare_dyn_arr_string(&str, "pub") {return token_create(.Pub, crange)} else if compare_dyn_arr_string(&str, "let") {return token_create(.Let, crange)} else if compare_dyn_arr_string(&str, "mut") {return token_create(.Mut, crange)} else if compare_dyn_arr_string(&str, "as") {return token_create(.As, crange)} else if compare_dyn_arr_string(&str, "in") {return token_create(.In, crange)} else if compare_dyn_arr_string(&str, "if") {return token_create(.If, crange)} else if compare_dyn_arr_string(&str, "else") {return token_create(.Else, crange)} else if compare_dyn_arr_string(&str, "elif") {return token_create(.Elif, crange)} else if compare_dyn_arr_string(&str, "for") {return token_create(.For, crange)} else if compare_dyn_arr_string(&str, "break") {return token_create(.Break, crange)} else if compare_dyn_arr_string(&str, "continue") {return token_create(.Continue, crange)} else if compare_dyn_arr_string(&str, "switch") {return token_create(.Switch, crange)} else if compare_dyn_arr_string(&str, "case") {return token_create(.Case, crange)} else if compare_dyn_arr_string(&str, "ret") {return token_create(.Ret, crange)} else if compare_dyn_arr_string(&str, "static") {return token_create(.Static, crange)} else if compare_dyn_arr_string(&str, "defer") {return token_create(.Defer, crange)} else if compare_dyn_arr_string(&str, "let") {return token_create(.Let, crange)} else if compare_dyn_arr_string(&str, "and") {return token_create(.And, crange)} else if compare_dyn_arr_string(&str, "or") {return token_create(.Or, crange)}
if compare_dyn_arr_string(&str, "fn") {
return token_create(.Function, crange)
} else if compare_dyn_arr_string(&str, "struct") {
return token_create(.Struct, crange)
} else if compare_dyn_arr_string(&str, "enum") {
return token_create(.Enum, crange)
} else if compare_dyn_arr_string(&str, "union") {
return token_create(.Union, crange)
} else if compare_dyn_arr_string(&str, "type") {
return token_create(.Type, crange)
} else if compare_dyn_arr_string(&str, "use") {
return token_create(.Use, crange)
} else if compare_dyn_arr_string(&str, "pub") {
return token_create(.Pub, crange)
} else if compare_dyn_arr_string(&str, "let") {
return token_create(.Let, crange)
} else if compare_dyn_arr_string(&str, "mut") {
return token_create(.Mut, crange)
} else if compare_dyn_arr_string(&str, "as") {
return token_create(.As, crange)
} else if compare_dyn_arr_string(&str, "bitwise_as") {
return token_create(.BitwiseAs, crange)
} else if compare_dyn_arr_string(&str, "in") {
return token_create(.In, crange)
} else if compare_dyn_arr_string(&str, "if") {
return token_create(.If, crange)
} else if compare_dyn_arr_string(&str, "else") {
return token_create(.Else, crange)
} else if compare_dyn_arr_string(&str, "elif") {
return token_create(.Elif, crange)
} else if compare_dyn_arr_string(&str, "for") {
return token_create(.For, crange)
} else if compare_dyn_arr_string(&str, "break") {
return token_create(.Break, crange)
} else if compare_dyn_arr_string(&str, "continue") {
return token_create(.Continue, crange)
} else if compare_dyn_arr_string(&str, "switch") {
return token_create(.Switch, crange)
} else if compare_dyn_arr_string(&str, "case") {
return token_create(.Case, crange)
} else if compare_dyn_arr_string(&str, "ret") {
return token_create(.Ret, crange)
} else if compare_dyn_arr_string(&str, "static") {
return token_create(.Static, crange)
} else if compare_dyn_arr_string(&str, "defer") {
return token_create(.Defer, crange)
} else if compare_dyn_arr_string(&str, "let") {
return token_create(.Let, crange)
} else if compare_dyn_arr_string(&str, "and") {
return token_create(.And, crange)
} else if compare_dyn_arr_string(&str, "or") {
return token_create(.Or, crange)
}
return token_create_u8(.Identifier, str, crange)
}

View File

@ -32,12 +32,14 @@ main :: proc() {
parser := parser_create(lexer)
ast := parser_parse(&parser)
type_check(ast, nil)
if len(g_message_list) > 0 {
for msg in g_message_list {
fmt.printf("%s\n", msg)
}
return
}
node_print(ast)
}

View File

@ -459,6 +459,14 @@ parser_parse_suffix :: proc(parser: ^Parser) -> ^Node {
return node_create_unary(.Increment, range, lhs)
} else if accept(parser, .Decrement) {
return node_create_unary(.Decrement, range, lhs)
} else if accept(parser, .As) {
type := parser_parse_type(parser)
range.end = type.range.end
return node_create_cast(range, lhs, type)
} else if accept(parser, .BitwiseAs) {
type := parser_parse_type(parser)
range.end = type.range.end
return node_create_bitwise_cast(range, lhs, type)
}
return lhs
}
@ -519,6 +527,7 @@ parser_parse_factor :: proc(parser: ^Parser) -> (ret: ^Node) {
parser.tok.kind != .CloseParen &&
parser.tok.kind != .Semicolon &&
parser.tok.kind != .Arrow &&
parser.tok.kind != .Assign &&
parser.tok.kind != .EOF {
prev := parser.can_be_function
parser.can_be_function = false
@ -527,6 +536,7 @@ parser_parse_factor :: proc(parser: ^Parser) -> (ret: ^Node) {
parser.tok.kind != .Semicolon &&
parser.tok.kind != .Arrow &&
parser.tok.kind != .EOF &&
parser.tok.kind != .Assign &&
parser_is_factor_token_or_prefix(parser.tok.kind) {
append(&args, parser_parse_expression(parser))
}

View File

@ -21,6 +21,7 @@ TokenKind :: enum {
Pub,
Mut,
As,
BitwiseAs,
In,
If,
Else,

View File

@ -11,3 +11,11 @@ compare_dyn_arr_string :: proc(a: ^[dynamic]u8, b: string) -> bool {
}
return true
}
get_character_sum_of_dyn_arr :: proc(a: ^[dynamic]u8) -> int {
sum := 0
for c in a {
sum += int(c)
}
return sum
}