diff options
author | Bad Diode <bd@badd10de.dev> | 2024-06-27 17:01:21 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-06-27 17:01:21 +0200 |
commit | 3a639adc1daa7a17d100403583003c79d116748f (patch) | |
tree | 875174b37d6d52867fb29ac9d19215149de88f6a | |
parent | 7f81a3e35ab0b02ef7695cb399cd7302e98d6296 (diff) | |
download | bdl-3a639adc1daa7a17d100403583003c79d116748f.tar.gz bdl-3a639adc1daa7a17d100403583003c79d116748f.zip |
More pointers and array typechecking
-rw-r--r-- | src/main.c | 32 | ||||
-rw-r--r-- | tests/semantics.bad | 28 |
2 files changed, 40 insertions, 20 deletions
@@ -8,8 +8,9 @@ | |||
8 | #include "vm.c" | 8 | #include "vm.c" |
9 | 9 | ||
10 | // TODO: unions | 10 | // TODO: unions |
11 | // TODO: arrays and pointers | ||
12 | // TODO: embed (binary file) and include (source file) | 11 | // TODO: embed (binary file) and include (source file) |
12 | // TODO: revisit ast parsing for pointers and arrays (I think I'm missing corner | ||
13 | // cases). | ||
13 | 14 | ||
14 | typedef enum ExecMode { | 15 | typedef enum ExecMode { |
15 | RUN_NORMAL, | 16 | RUN_NORMAL, |
@@ -57,12 +58,6 @@ typedef struct Symbol { | |||
57 | SymbolKind kind; | 58 | SymbolKind kind; |
58 | } Symbol; | 59 | } Symbol; |
59 | 60 | ||
60 | typedef struct ArraySymbol { | ||
61 | Str name; | ||
62 | Str type; | ||
63 | sz size; | ||
64 | } ArraySymbol; | ||
65 | |||
66 | typedef struct Fun { | 61 | typedef struct Fun { |
67 | Str name; | 62 | Str name; |
68 | Str param_type; | 63 | Str param_type; |
@@ -80,7 +75,6 @@ typedef struct Struct { | |||
80 | Node *val; | 75 | Node *val; |
81 | } Struct; | 76 | } Struct; |
82 | 77 | ||
83 | MAPDEF(ArrayMap, arraymap, Str, ArraySymbol, str_hash, str_eq) | ||
84 | MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq) | 78 | MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq) |
85 | MAPDEF(FunMap, funmap, Str, Fun, str_hash, str_eq) | 79 | MAPDEF(FunMap, funmap, Str, Fun, str_hash, str_eq) |
86 | MAPDEF(EnumMap, enummap, Str, Enum, str_hash, str_eq) | 80 | MAPDEF(EnumMap, enummap, Str, Enum, str_hash, str_eq) |
@@ -94,7 +88,6 @@ typedef struct Scope { | |||
94 | FunMap *funcs; | 88 | FunMap *funcs; |
95 | EnumMap *enums; | 89 | EnumMap *enums; |
96 | StructMap *structs; | 90 | StructMap *structs; |
97 | ArrayMap *arrays; | ||
98 | struct Scope *parent; | 91 | struct Scope *parent; |
99 | } Scope; | 92 | } Scope; |
100 | 93 | ||
@@ -315,6 +308,12 @@ typecheck_field(Analyzer *a, Node *node, Scope *scope, Str symbol) { | |||
315 | node->field_type->line, node->field_type->col, field_type); | 308 | node->field_type->line, node->field_type->col, field_type); |
316 | a->err = true; | 309 | a->err = true; |
317 | } | 310 | } |
311 | if (node->field_type->is_ptr) { | ||
312 | field_type = str_concat(cstr("@"), field_type, a->storage); | ||
313 | } | ||
314 | if (node->field_type->kind == NODE_ARR_TYPE) { | ||
315 | field_type = str_concat(cstr("@"), field_type, a->storage); | ||
316 | } | ||
318 | if (structmap_lookup(&scope->structs, field_name)) { | 317 | if (structmap_lookup(&scope->structs, field_name)) { |
319 | eprintln("%s:%d:%d: error: struct field '%s' already exists", | 318 | eprintln("%s:%d:%d: error: struct field '%s' already exists", |
320 | a->file_name, node->line, node->col, field_name); | 319 | a->file_name, node->line, node->col, field_name); |
@@ -956,7 +955,20 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
956 | a->err = true; | 955 | a->err = true; |
957 | return cstr(""); | 956 | return cstr(""); |
958 | } | 957 | } |
959 | node->type = field->val.type; | 958 | Str field_type = field->val.type; |
959 | if (next->kind == NODE_SYMBOL_IDX) { | ||
960 | Str idx_type = | ||
961 | type_inference(a, next->arr_size, scope); | ||
962 | if (!strset_lookup(&a->integer_types, idx_type)) { | ||
963 | emit_semantic_error( | ||
964 | a, next, | ||
965 | cstr("can't resolve non integer index")); | ||
966 | return cstr(""); | ||
967 | } | ||
968 | field_type = | ||
969 | str_remove_prefix(field_type, cstr("@")); | ||
970 | } | ||
971 | node->type = field_type; | ||
960 | return node->type; | 972 | return node->type; |
961 | } | 973 | } |
962 | } | 974 | } |
diff --git a/tests/semantics.bad b/tests/semantics.bad index 1bb2ceb..4acc8d5 100644 --- a/tests/semantics.bad +++ b/tests/semantics.bad | |||
@@ -1,22 +1,30 @@ | |||
1 | ; We can have static arrays and have indexed access. | ||
2 | let a = 1 | 1 | let a = 1 |
3 | let numbers: @int | 2 | let numbers: @int |
4 | set numbers[a] = 32 | 3 | set numbers[a] = 32 |
5 | set numbers[1] = numbers[0] | 4 | set numbers[1] = numbers[0] |
5 | |||
6 | let numbers_arr: int[0xff] | 6 | let numbers_arr: int[0xff] |
7 | set numbers_arr[0] = numbers[0] | 7 | set numbers_arr[0] = numbers[0] |
8 | |||
8 | let ptr_arr: @int[0xff] | 9 | let ptr_arr: @int[0xff] |
9 | set ptr_arr[0] = @numbers[0] | 10 | set ptr_arr[0] = @numbers[0] |
10 | 11 | ||
11 | ; TODO: test pointers/arrays on structs | 12 | struct vec { |
12 | 13 | a: int | |
13 | ; ; Arrays are syntactic sugar for pointers (@). | 14 | b: str |
14 | ; let ptr:@u32 = numbers | 15 | } |
15 | ; set ptr[10] = 33 | 16 | let b: @vec |
16 | 17 | set b[0].a = 1 | |
17 | ; ; Strings hold a .mem and .size fields with the number of bytes it holds. | 18 | |
18 | ; let hello: str = "hello world" | 19 | struct ptrs { |
19 | ; set c[1] = 'a' ; "hallo world" | 20 | a: @int |
21 | b: str[128] | ||
22 | c: vec[100] | ||
23 | } | ||
24 | let c: ptrs | ||
25 | set c.a[0] = 1 | ||
26 | set c.b[0] = "ho" | ||
27 | ; set c.c[0].a = 1 ; this doesn't work at the moment | ||
20 | 28 | ||
21 | ; ; fun foo(a: int): int { | 29 | ; ; fun foo(a: int): int { |
22 | ; ; 1 | 30 | ; ; 1 |