diff options
-rw-r--r-- | src/main.c | 58 | ||||
-rw-r--r-- | src/parser.c | 3 | ||||
-rw-r--r-- | tests/semantics.bad | 12 |
3 files changed, 56 insertions, 17 deletions
@@ -57,6 +57,12 @@ typedef struct Symbol { | |||
57 | SymbolKind kind; | 57 | SymbolKind kind; |
58 | } Symbol; | 58 | } Symbol; |
59 | 59 | ||
60 | typedef struct ArraySymbol { | ||
61 | Str name; | ||
62 | Str type; | ||
63 | sz size; | ||
64 | } ArraySymbol; | ||
65 | |||
60 | typedef struct Fun { | 66 | typedef struct Fun { |
61 | Str name; | 67 | Str name; |
62 | Str param_type; | 68 | Str param_type; |
@@ -74,6 +80,7 @@ typedef struct Struct { | |||
74 | Node *val; | 80 | Node *val; |
75 | } Struct; | 81 | } Struct; |
76 | 82 | ||
83 | MAPDEF(ArrayMap, arraymap, Str, ArraySymbol, str_hash, str_eq) | ||
77 | MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq) | 84 | MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq) |
78 | MAPDEF(FunMap, funmap, Str, Fun, str_hash, str_eq) | 85 | MAPDEF(FunMap, funmap, Str, Fun, str_hash, str_eq) |
79 | MAPDEF(EnumMap, enummap, Str, Enum, str_hash, str_eq) | 86 | MAPDEF(EnumMap, enummap, Str, Enum, str_hash, str_eq) |
@@ -87,6 +94,7 @@ typedef struct Scope { | |||
87 | FunMap *funcs; | 94 | FunMap *funcs; |
88 | EnumMap *enums; | 95 | EnumMap *enums; |
89 | StructMap *structs; | 96 | StructMap *structs; |
97 | ArrayMap *arrays; | ||
90 | struct Scope *parent; | 98 | struct Scope *parent; |
91 | } Scope; | 99 | } Scope; |
92 | 100 | ||
@@ -478,6 +486,14 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
478 | a->err = true; | 486 | a->err = true; |
479 | return cstr(""); | 487 | return cstr(""); |
480 | } | 488 | } |
489 | if (node->var_type->is_ptr) { | ||
490 | type_name = str_concat(cstr("@"), type_name, a->storage); | ||
491 | } | ||
492 | if (node->var_type->kind == NODE_ARR_TYPE) { | ||
493 | type_name = str_concat(cstr("@"), type_name, a->storage); | ||
494 | // TODO: typecheck size | ||
495 | // TODO: register array in scope | ||
496 | } | ||
481 | if (node->var_val) { | 497 | if (node->var_val) { |
482 | Str type = type_inference(a, node->var_val, scope); | 498 | Str type = type_inference(a, node->var_val, scope); |
483 | if (!type.size) { | 499 | if (!type.size) { |
@@ -506,7 +522,12 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
506 | } | 522 | } |
507 | } | 523 | } |
508 | } | 524 | } |
509 | symmap_insert(&scope->symbols, symbol, type->val, a->storage); | 525 | symmap_insert(&scope->symbols, symbol, |
526 | (Symbol){ | ||
527 | .name = type_name, | ||
528 | .kind = SYM_VAR, | ||
529 | }, | ||
530 | a->storage); | ||
510 | return node->type; | 531 | return node->type; |
511 | } | 532 | } |
512 | 533 | ||
@@ -856,6 +877,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
856 | node->type = type->val.name; | 877 | node->type = type->val.name; |
857 | return node->type; | 878 | return node->type; |
858 | } break; | 879 | } break; |
880 | case NODE_SYMBOL_IDX: | ||
859 | case NODE_SYMBOL: { | 881 | case NODE_SYMBOL: { |
860 | Str symbol = node->value.str; | 882 | Str symbol = node->value.str; |
861 | SymbolMap *type = find_type(scope, symbol); | 883 | SymbolMap *type = find_type(scope, symbol); |
@@ -865,9 +887,22 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
865 | a->err = true; | 887 | a->err = true; |
866 | return cstr(""); | 888 | return cstr(""); |
867 | } | 889 | } |
890 | Str type_name = type->val.name; | ||
891 | if (node->kind == NODE_SYMBOL_IDX) { | ||
892 | Str idx_type = type_inference(a, node->arr_size, scope); | ||
893 | if (!strset_lookup(&a->integer_types, idx_type)) { | ||
894 | emit_semantic_error( | ||
895 | a, node, cstr("can't resolve non integer index")); | ||
896 | return cstr(""); | ||
897 | } | ||
898 | type_name = str_remove_prefix(type_name, cstr("@")); | ||
899 | } | ||
900 | if (node->is_ptr) { | ||
901 | type_name = str_concat(cstr("@"), type_name, a->storage); | ||
902 | } | ||
868 | 903 | ||
869 | FindEnumResult e = find_enum(scope, type->val.name); | 904 | FindEnumResult e = find_enum(scope, type_name); |
870 | if (e.map && str_eq(symbol, type->val.name)) { | 905 | if (e.map && str_eq(symbol, type_name)) { |
871 | if (!node->next) { | 906 | if (!node->next) { |
872 | eprintln( | 907 | eprintln( |
873 | "%s:%d:%d: error: unspecified enum field for symbol " | 908 | "%s:%d:%d: error: unspecified enum field for symbol " |
@@ -877,7 +912,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
877 | return cstr(""); | 912 | return cstr(""); |
878 | } | 913 | } |
879 | // Check if there is a next and it matches the enum field. | 914 | // Check if there is a next and it matches the enum field. |
880 | Str field = str_concat(type->val.name, cstr("."), a->storage); | 915 | Str field = str_concat(type_name, cstr("."), a->storage); |
881 | field = str_concat(field, node->next->value.str, a->storage); | 916 | field = str_concat(field, node->next->value.str, a->storage); |
882 | if (!enummap_lookup(&e.scope->enums, field)) { | 917 | if (!enummap_lookup(&e.scope->enums, field)) { |
883 | eprintln( | 918 | eprintln( |
@@ -888,24 +923,23 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
888 | a->err = true; | 923 | a->err = true; |
889 | return cstr(""); | 924 | return cstr(""); |
890 | } | 925 | } |
891 | node->next->type = type->val.name; | 926 | node->next->type = type_name; |
892 | node->type = type->val.name; | 927 | node->type = type_name; |
893 | return node->next->type; | 928 | return node->next->type; |
894 | } | 929 | } |
895 | 930 | ||
896 | FindStructResult s = find_struct(scope, type->val.name); | 931 | FindStructResult s = find_struct(scope, type_name); |
897 | if (s.map) { | 932 | if (s.map) { |
898 | if (str_eq(symbol, type->val.name)) { | 933 | if (str_eq(symbol, type_name)) { |
899 | eprintln( | 934 | eprintln( |
900 | "%s:%d:%d: error: struct incomplete struct literal " | 935 | "%s:%d:%d: error: struct incomplete struct literal " |
901 | "'%s', did you mean to use %s:{}?", | 936 | "'%s', did you mean to use %s:{}?", |
902 | a->file_name, node->line, node->col, symbol, | 937 | a->file_name, node->line, node->col, symbol, symbol); |
903 | symbol); | ||
904 | a->err = true; | 938 | a->err = true; |
905 | return cstr(""); | 939 | return cstr(""); |
906 | } else { | 940 | } else { |
907 | if (node->next) { | 941 | if (node->next) { |
908 | Str chain = type->val.name; | 942 | Str chain = type_name; |
909 | Node *next = node; | 943 | Node *next = node; |
910 | while (next->next) { | 944 | while (next->next) { |
911 | next = next->next; | 945 | next = next->next; |
@@ -927,7 +961,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { | |||
927 | } | 961 | } |
928 | } | 962 | } |
929 | } | 963 | } |
930 | node->type = type->val.name; | 964 | node->type = type_name; |
931 | return node->type; | 965 | return node->type; |
932 | } break; | 966 | } break; |
933 | case NODE_STRUCT_LIT: { | 967 | case NODE_STRUCT_LIT: { |
diff --git a/src/parser.c b/src/parser.c index ce8eef8..cdd3c47 100644 --- a/src/parser.c +++ b/src/parser.c | |||
@@ -976,8 +976,7 @@ parse_symbol(Parser *parser) { | |||
976 | } | 976 | } |
977 | } else if (parse_match(parser, TOK_LSQUARE)) { | 977 | } else if (parse_match(parser, TOK_LSQUARE)) { |
978 | node->kind = NODE_SYMBOL_IDX; | 978 | node->kind = NODE_SYMBOL_IDX; |
979 | parse_consume(parser, TOK_NUM_INT, cstr("no array size given")); | 979 | parse_expr(parser, PREC_LOW); |
980 | parse_number(parser); | ||
981 | node->arr_size = array_pop(parser->nodes); | 980 | node->arr_size = array_pop(parser->nodes); |
982 | parse_consume(parser, TOK_RSQUARE, | 981 | parse_consume(parser, TOK_RSQUARE, |
983 | cstr("unmatched brackets ']' in array type")); | 982 | cstr("unmatched brackets ']' in array type")); |
diff --git a/tests/semantics.bad b/tests/semantics.bad index b0cc26e..1bb2ceb 100644 --- a/tests/semantics.bad +++ b/tests/semantics.bad | |||
@@ -1,8 +1,14 @@ | |||
1 | ; We can have static arrays and have indexed access. | 1 | ; We can have static arrays and have indexed access. |
2 | ; let numbers: int[0xff] | 2 | let a = 1 |
3 | let numbers: int[0xff] | 3 | let numbers: @int |
4 | set numbers[0] = 32 | 4 | set numbers[a] = 32 |
5 | set numbers[1] = numbers[0] | 5 | set numbers[1] = numbers[0] |
6 | let numbers_arr: int[0xff] | ||
7 | set numbers_arr[0] = numbers[0] | ||
8 | let ptr_arr: @int[0xff] | ||
9 | set ptr_arr[0] = @numbers[0] | ||
10 | |||
11 | ; TODO: test pointers/arrays on structs | ||
6 | 12 | ||
7 | ; ; Arrays are syntactic sugar for pointers (@). | 13 | ; ; Arrays are syntactic sugar for pointers (@). |
8 | ; let ptr:@u32 = numbers | 14 | ; let ptr:@u32 = numbers |