From 7f81a3e35ab0b02ef7695cb399cd7302e98d6296 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Thu, 27 Jun 2024 16:29:45 +0200 Subject: Add initial pointer and array access/declaration typechecking --- src/main.c | 58 ++++++++++++++++++++++++++++++++++++++++++----------- src/parser.c | 3 +-- tests/semantics.bad | 12 ++++++++--- 3 files changed, 56 insertions(+), 17 deletions(-) diff --git a/src/main.c b/src/main.c index b0207f7..669984b 100644 --- a/src/main.c +++ b/src/main.c @@ -57,6 +57,12 @@ typedef struct Symbol { SymbolKind kind; } Symbol; +typedef struct ArraySymbol { + Str name; + Str type; + sz size; +} ArraySymbol; + typedef struct Fun { Str name; Str param_type; @@ -74,6 +80,7 @@ typedef struct Struct { Node *val; } Struct; +MAPDEF(ArrayMap, arraymap, Str, ArraySymbol, str_hash, str_eq) MAPDEF(SymbolMap, symmap, Str, Symbol, str_hash, str_eq) MAPDEF(FunMap, funmap, Str, Fun, str_hash, str_eq) MAPDEF(EnumMap, enummap, Str, Enum, str_hash, str_eq) @@ -87,6 +94,7 @@ typedef struct Scope { FunMap *funcs; EnumMap *enums; StructMap *structs; + ArrayMap *arrays; struct Scope *parent; } Scope; @@ -478,6 +486,14 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { a->err = true; return cstr(""); } + if (node->var_type->is_ptr) { + type_name = str_concat(cstr("@"), type_name, a->storage); + } + if (node->var_type->kind == NODE_ARR_TYPE) { + type_name = str_concat(cstr("@"), type_name, a->storage); + // TODO: typecheck size + // TODO: register array in scope + } if (node->var_val) { Str type = type_inference(a, node->var_val, scope); if (!type.size) { @@ -506,7 +522,12 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { } } } - symmap_insert(&scope->symbols, symbol, type->val, a->storage); + symmap_insert(&scope->symbols, symbol, + (Symbol){ + .name = type_name, + .kind = SYM_VAR, + }, + a->storage); return node->type; } @@ -856,6 +877,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { node->type = type->val.name; return node->type; } break; + case NODE_SYMBOL_IDX: case NODE_SYMBOL: { Str symbol = node->value.str; SymbolMap *type = find_type(scope, symbol); @@ -865,9 +887,22 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { a->err = true; return cstr(""); } + Str type_name = type->val.name; + if (node->kind == NODE_SYMBOL_IDX) { + Str idx_type = type_inference(a, node->arr_size, scope); + if (!strset_lookup(&a->integer_types, idx_type)) { + emit_semantic_error( + a, node, cstr("can't resolve non integer index")); + return cstr(""); + } + type_name = str_remove_prefix(type_name, cstr("@")); + } + if (node->is_ptr) { + type_name = str_concat(cstr("@"), type_name, a->storage); + } - FindEnumResult e = find_enum(scope, type->val.name); - if (e.map && str_eq(symbol, type->val.name)) { + FindEnumResult e = find_enum(scope, type_name); + if (e.map && str_eq(symbol, type_name)) { if (!node->next) { eprintln( "%s:%d:%d: error: unspecified enum field for symbol " @@ -877,7 +912,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { return cstr(""); } // Check if there is a next and it matches the enum field. - Str field = str_concat(type->val.name, cstr("."), a->storage); + Str field = str_concat(type_name, cstr("."), a->storage); field = str_concat(field, node->next->value.str, a->storage); if (!enummap_lookup(&e.scope->enums, field)) { eprintln( @@ -888,24 +923,23 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { a->err = true; return cstr(""); } - node->next->type = type->val.name; - node->type = type->val.name; + node->next->type = type_name; + node->type = type_name; return node->next->type; } - FindStructResult s = find_struct(scope, type->val.name); + FindStructResult s = find_struct(scope, type_name); if (s.map) { - if (str_eq(symbol, type->val.name)) { + if (str_eq(symbol, type_name)) { eprintln( "%s:%d:%d: error: struct incomplete struct literal " "'%s', did you mean to use %s:{}?", - a->file_name, node->line, node->col, symbol, - symbol); + a->file_name, node->line, node->col, symbol, symbol); a->err = true; return cstr(""); } else { if (node->next) { - Str chain = type->val.name; + Str chain = type_name; Node *next = node; while (next->next) { next = next->next; @@ -927,7 +961,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) { } } } - node->type = type->val.name; + node->type = type_name; return node->type; } break; 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) { } } else if (parse_match(parser, TOK_LSQUARE)) { node->kind = NODE_SYMBOL_IDX; - parse_consume(parser, TOK_NUM_INT, cstr("no array size given")); - parse_number(parser); + parse_expr(parser, PREC_LOW); node->arr_size = array_pop(parser->nodes); parse_consume(parser, TOK_RSQUARE, 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 @@ ; We can have static arrays and have indexed access. -; let numbers: int[0xff] -let numbers: int[0xff] -set numbers[0] = 32 +let a = 1 +let numbers: @int +set numbers[a] = 32 set numbers[1] = numbers[0] +let numbers_arr: int[0xff] +set numbers_arr[0] = numbers[0] +let ptr_arr: @int[0xff] +set ptr_arr[0] = @numbers[0] + +; TODO: test pointers/arrays on structs ; ; Arrays are syntactic sugar for pointers (@). ; let ptr:@u32 = numbers -- cgit v1.2.1