nasty bug fix with polymorphic structs destroying scope tree
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 20 Sep 2020 20:22:41 +0000 (15:22 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 20 Sep 2020 20:22:41 +0000 (15:22 -0500)
include/onyxastnodes.h
include/onyxutils.h
misc/onyx.vim
onyx
src/onyxparser.c
src/onyxsymres.c
src/onyxtypes.c
src/onyxutils.c

index 8c97f6a2a24c19c77c3f106f1e3832d8f5d3f588..97432168a17ddbfbd41aa7fb0a7316ab65761938 100644 (file)
@@ -69,10 +69,11 @@ typedef struct Package Package;
 
 typedef struct Scope {
     struct Scope *parent;
+    OnyxFilePos created_at;
     bh_table(AstNode *) symbols;
 } Scope;
 
-extern Scope* scope_create(bh_allocator a, Scope* parent);
+extern Scope* scope_create(bh_allocator a, Scope* parent, OnyxFilePos created_at);
 
 
 typedef enum AstKind {
@@ -777,7 +778,7 @@ typedef enum PolyProcLookupMethod {
 } PolyProcLookupMethod;
 AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lookup, ptr actual, OnyxFilePos pos);
 
-AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(Type *) params);
+AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(Type *) params, OnyxFilePos pos);
 
 // NOTE: Useful inlined functions
 static inline b32 is_lval(AstNode* node) {
index 4e2b1f4316f409a81c1be8e68b57c890b0a57312..bf6b9ba36bcb23f86ee68c61c3ee77b9c8c2a951 100644 (file)
@@ -14,7 +14,6 @@ void program_info_init(ProgramInfo* prog, bh_allocator alloc);
 Package* program_info_package_lookup(ProgramInfo* prog, char* package_name);
 Package* program_info_package_lookup_or_create(ProgramInfo* prog, char* package_name, Scope* parent_scope, bh_allocator alloc);
 
-Scope* scope_create(bh_allocator a, Scope* parent);
 void scope_include(Scope* target, Scope* source);
 b32 symbol_introduce(Scope* scope, OnyxToken* tkn, AstNode* symbol);
 b32 symbol_raw_introduce(Scope* scope, char* tkn, OnyxFilePos pos, AstNode* symbol);
index b1378b2dcbe0d298a35d465cf607d66181741886..2afb167e7ae15338941c397e10a9db91e6b44dff 100644 (file)
@@ -40,7 +40,7 @@ syn region onyxComment          start="/\*" end="\*/" contains=onyxCommentStart
 syn match onyxDefinitionGroup   "\<[a-zA-Z_][a-zA-Z0-9_]*\> *::" contains=onyxDefinition
 syn match onyxDefinition        "\<[a-zA-Z_][a-zA-Z0-9_]*\>" contained
 
-syn region onyxDirective        start="#" end=" "
+syn match onyxDirective         "\#[a-zA-Z_]\+"
 
 syn region onyxString              display start=+"+ skip=+\\\\\|\\"+ end=+"+ keepend
 
diff --git a/onyx b/onyx
index 416b2df40d2b511b0edd602000a36d5db96b7f7f..068a56a1e19098a39e3b37a3974b448e8e6ac743 100755 (executable)
Binary files a/onyx and b/onyx differ
index c04587cec227257187e1bfc2b3455fdaef7b2e99..2503d2d4634f65db194b595c260d25e325c12c39 100644 (file)
@@ -127,6 +127,14 @@ static AstNumLit* make_int_literal(bh_allocator a, i64 i) {
     return num;
 }
 
+static AstUnaryOp* wrap_in_auto_cast(bh_allocator a, AstTyped* expr) {
+    AstUnaryOp* ac = onyx_ast_node_new(a, sizeof(AstUnaryOp), Ast_Kind_Unary_Op);
+    ac->operation = Unary_Op_Auto_Cast;
+    ac->token = expr->token;
+    ac->expr = expr;
+    return ac;
+}
+
 
 static AstNumLit* parse_int_literal(OnyxParser* parser) {
     AstNumLit* int_node = make_node(AstNumLit, Ast_Kind_NumLit);
@@ -1316,7 +1324,7 @@ static AstType* parse_type(OnyxParser* parser) {
             }
 
             if (parser->curr->type == '(') {
-                consume_token(parser);
+                OnyxToken* paren_token = expect_token(parser, '(');
 
                 bh_arr(AstType *) params = NULL;
                 bh_arr_new(global_heap_allocator, params, 2);
@@ -1333,6 +1341,7 @@ static AstType* parse_type(OnyxParser* parser) {
                 expect_token(parser, ')');
 
                 AstPolyCallType* pc_type = make_node(AstPolyCallType, Ast_Kind_Poly_Call_Type);
+                pc_type->token = paren_token;
                 pc_type->callee = *next_insertion;
                 pc_type->params = params;
 
@@ -2034,7 +2043,7 @@ ParseResults onyx_parse(OnyxParser *parser) {
         parser->package = package;
     }
 
-    parser->file_scope = scope_create(parser->allocator, parser->package->private_scope);
+    parser->file_scope = scope_create(parser->allocator, parser->package->private_scope, parser->tokenizer->tokens[0].pos);
 
     AstUsePackage* implicit_use_builtin = make_node(AstUsePackage, Ast_Kind_Use_Package);
     implicit_use_builtin->package = (AstPackage *) &builtin_package_node;
index 1077fa2d66a396ae455c04d7a5e44a8559d873a1..146494fe9b384e27592834700bf99fe43956b5ab 100644 (file)
@@ -31,8 +31,8 @@ static void symres_enum(AstEnumType* enum_node);
 static void symres_memres(AstMemRes** memres);
 
 static void scope_enter(Scope* new_scope) {
-    if (new_scope->parent == NULL)
-        new_scope->parent = semstate.curr_scope;
+    // if (new_scope->parent == NULL)
+    //     new_scope->parent = semstate.curr_scope;
     semstate.curr_scope = new_scope;
 }
 
@@ -153,7 +153,7 @@ AstType* symres_type(AstType* type) {
 
     if (type->kind == Ast_Kind_Poly_Struct_Type) {
         AstPolyStructType* pst_node = (AstPolyStructType *) type;
-        pst_node->scope = scope_create(semstate.node_allocator, semstate.curr_scope);
+        pst_node->scope = scope_create(semstate.node_allocator, semstate.curr_scope, pst_node->token->pos);
 
         return type;
     }
@@ -261,12 +261,19 @@ static void symres_unaryop(AstUnaryOp** unaryop) {
 }
 
 static void symres_struct_literal(AstStructLiteral* sl) {
+    // @CLEANUP
     if (sl->stnode != NULL) symres_expression(&sl->stnode);
+    sl->stnode = (AstTyped *) symres_type((AstType *) sl->stnode);
     if (sl->stnode == NULL || sl->stnode->kind == Ast_Kind_Error || sl->stnode->kind == Ast_Kind_Symbol) return;
 
-    sl->type_node = symres_type((AstType *) sl->stnode);
+    sl->type_node = (AstType *) sl->stnode;
+    while (sl->type_node->kind == Ast_Kind_Type_Alias)
+        sl->type_node = ((AstTypeAlias *) sl->type_node)->to;
+
     sl->type = type_build_from_ast(semstate.allocator, sl->type_node);
 
+    if (sl->type == NULL) return;
+
     if (!type_is_structlike_strict(sl->type)) {
         onyx_report_error(sl->token->pos, "Type is not a constructable using a struct literal.");
         return;
@@ -301,10 +308,8 @@ static void symres_struct_literal(AstStructLiteral* sl) {
                 u32 idx = (*smem)->idx;
 
                 if (sl->values[idx] == NULL) {
-                    if (st->members[idx]->initial_value == NULL) {
-                        onyx_report_error(sl->token->pos, "No value was given for the field '%b'.",
-                                st->members[idx]->token->text,
-                                st->members[idx]->token->length);
+                    if (st->kind != Ast_Kind_Struct_Type || st->members[idx]->initial_value == NULL) {
+                        onyx_report_error(sl->token->pos, "No value was given for the field '%s'.", (*smem)->name);
                         return;
                     }
 
@@ -382,7 +387,7 @@ static void symres_return(AstReturn* ret) {
 
 static void symres_if(AstIfWhile* ifnode) {
     if (ifnode->assignment != NULL) {
-        ifnode->scope = scope_create(semstate.node_allocator, semstate.curr_scope);
+        ifnode->scope = scope_create(semstate.node_allocator, semstate.curr_scope, ifnode->token->pos);
         scope_enter(ifnode->scope);
 
         symbol_introduce(semstate.curr_scope, ifnode->local->token, (AstNode *) ifnode->local);
@@ -400,7 +405,7 @@ static void symres_if(AstIfWhile* ifnode) {
 
 static void symres_while(AstIfWhile* whilenode) {
     if (whilenode->assignment != NULL) {
-        whilenode->scope = scope_create(semstate.node_allocator, semstate.curr_scope);
+        whilenode->scope = scope_create(semstate.node_allocator, semstate.curr_scope, whilenode->token->pos);
         scope_enter(whilenode->scope);
 
         symbol_introduce(semstate.curr_scope, whilenode->local->token, (AstNode *) whilenode->local);
@@ -417,7 +422,7 @@ static void symres_while(AstIfWhile* whilenode) {
 }
 
 static void symres_for(AstFor* fornode) {
-    fornode->scope = scope_create(semstate.node_allocator, semstate.curr_scope);
+    fornode->scope = scope_create(semstate.node_allocator, semstate.curr_scope, fornode->token->pos);
     scope_enter(fornode->scope);
 
     symres_expression(&fornode->iter);
@@ -431,7 +436,7 @@ static void symres_for(AstFor* fornode) {
 
 static void symres_switch(AstSwitch* switchnode) {
     if (switchnode->assignment != NULL) {
-        switchnode->scope = scope_create(semstate.node_allocator, semstate.curr_scope);
+        switchnode->scope = scope_create(semstate.node_allocator, semstate.curr_scope, switchnode->token->pos);
         scope_enter(switchnode->scope);
 
         symbol_introduce(semstate.curr_scope, switchnode->local->token, (AstNode *) switchnode->local);
@@ -486,7 +491,7 @@ static void symres_statement_chain(AstNode** walker) {
 
 static void symres_block(AstBlock* block) {
     if (block->scope == NULL)
-        block->scope = scope_create(semstate.node_allocator, semstate.curr_scope);
+        block->scope = scope_create(semstate.node_allocator, semstate.curr_scope, block->token->pos);
 
     scope_enter(block->scope);
     bh_arr_push(semstate.block_stack, block);
@@ -500,7 +505,7 @@ static void symres_block(AstBlock* block) {
 
 void symres_function(AstFunction* func) {
     if (func->scope == NULL)
-        func->scope = scope_create(semstate.node_allocator, semstate.curr_scope);
+        func->scope = scope_create(semstate.node_allocator, semstate.curr_scope, func->token->pos);
 
     bh_arr_each(AstParam, param, func->params) {
         if (param->default_value != NULL) {
@@ -656,7 +661,7 @@ static void symres_enum(AstEnumType* enum_node) {
     if (enum_node->backing == NULL) return;
 
     enum_node->backing_type = type_build_from_ast(semstate.allocator, enum_node->backing);
-    enum_node->scope = scope_create(semstate.node_allocator, NULL);
+    enum_node->scope = scope_create(semstate.node_allocator, NULL, enum_node->token->pos);
 
     u64 next_assign_value = (enum_node->flags & Ast_Flag_Enum_Is_Flags) ? 1 : 0;
     bh_arr_each(AstEnumValue *, value, enum_node->values) {
@@ -705,7 +710,7 @@ static void symres_memres(AstMemRes** memres) {
 }
 
 static void symres_polyproc(AstPolyProc* pp) {
-    pp->poly_scope = scope_create(semstate.node_allocator, semstate.curr_scope);
+    pp->poly_scope = scope_create(semstate.node_allocator, semstate.curr_scope, pp->token->pos);
 }
 
 void onyx_resolve_symbols() {
index 0569314d1dad8372c4729b9a693ed669bd29f0c4..8d961b086637f4ca23e40c438c52565d34830fea 100644 (file)
@@ -297,6 +297,10 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
             if (a_node->count_expr) {
                 a_node->count_expr->type = type_build_from_ast(alloc, a_node->count_expr->type_node);
 
+                if (node_is_auto_cast((AstNode *) a_node->count_expr)) {
+                    a_node->count_expr = ((AstUnaryOp *) a_node)->expr;
+                }
+
                 // NOTE: Currently, the count_expr has to be an I32 literal
                 if (a_node->count_expr->kind != Ast_Kind_NumLit
                     || a_node->count_expr->type->kind != Type_Kind_Basic
@@ -442,7 +446,7 @@ Type* type_build_from_ast(bh_allocator alloc, AstType* type_node) {
                 bh_arr_push(param_types, type_build_from_ast(alloc, *ptype));
             }
 
-            AstStructType* concrete = polymorphic_struct_lookup(ps_type, param_types);
+            AstStructType* concrete = polymorphic_struct_lookup(ps_type, param_types, pc_type->token->pos);
 
             bh_arr_free(param_types);
 
index 832272d53d2abc775a6210638d20924dd1e193a1..05eeb47803136c4026c03ceb80dfc5fa5f994444 100644 (file)
@@ -95,7 +95,7 @@ const char* onyx_ast_node_kind_string(AstKind kind) {
 
 
 void program_info_init(ProgramInfo* prog, bh_allocator alloc) {
-    prog->global_scope = scope_create(alloc, NULL);
+    prog->global_scope = scope_create(alloc, NULL, (OnyxFilePos) { 0 });
 
     bh_table_init(alloc, prog->packages, 16);
 
@@ -122,8 +122,8 @@ Package* program_info_package_lookup_or_create(ProgramInfo* prog, char* package_
         memcpy(pac_name, package_name, strlen(package_name) + 1);
 
         package->name = pac_name;
-        package->scope = scope_create(alloc, parent_scope);
-        package->private_scope = scope_create(alloc, package->scope);
+        package->scope = scope_create(alloc, parent_scope, (OnyxFilePos) { 0 });
+        package->private_scope = scope_create(alloc, package->scope, (OnyxFilePos) { 0 });
 
         bh_table_put(Package *, prog->packages, pac_name, package);
 
@@ -131,9 +131,10 @@ Package* program_info_package_lookup_or_create(ProgramInfo* prog, char* package_
     }
 }
 
-Scope* scope_create(bh_allocator a, Scope* parent) {
+Scope* scope_create(bh_allocator a, Scope* parent, OnyxFilePos created_at) {
     Scope* scope = bh_alloc_item(a, Scope);
     scope->parent = parent;
+    scope->created_at = created_at;
     scope->symbols = NULL;
 
     bh_table_init(global_heap_allocator, scope->symbols, 64);
@@ -196,7 +197,7 @@ AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn) {
     AstNode* res = symbol_raw_resolve(start_scope, tkn->text);
 
     if (res == NULL) {
-        onyx_report_error(tkn->pos, "Unable to resolve symbol '%s'", tkn->text);
+        onyx_report_error(tkn->pos, "Unable to resolve symbol '%s'.", tkn->text);
         token_toggle_end(tkn);
         return &empty_node;
     }
@@ -523,12 +524,15 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lo
     }
 
     Type* old_return_type = semstate.expected_return_type;
+    Scope* old_scope = semstate.curr_scope;
     semstate.curr_scope = pp->poly_scope;
 
     AstFunction* func = (AstFunction *) ast_clone(semstate.node_allocator, pp->base_func);
     bh_table_put(AstFunction *, pp->concrete_funcs, key_buf, func);
 
     symres_function(func);
+    semstate.curr_scope = old_scope;
+
     if (onyx_has_errors()) goto has_error;
     if (check_function_header(func)) goto has_error;
     if (check_function(func)) goto has_error;
@@ -559,7 +563,7 @@ no_errors:
 
 
 
-AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(Type *) params) {
+AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(Type *) params, OnyxFilePos pos) {
     // @Cleanup
     assert(bh_arr_length(ps_type->poly_params) == bh_arr_length(params));
     assert(ps_type->scope != NULL);
@@ -597,13 +601,16 @@ AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(Type
 
     AstStructType* concrete_struct = (AstStructType *) ast_clone(semstate.node_allocator, ps_type->base_struct);
 
+    Scope* old_scope = semstate.curr_scope;
     semstate.curr_scope = ps_type->scope;
     concrete_struct = (AstStructType *) symres_type((AstType *) concrete_struct);
+    semstate.curr_scope = old_scope;
+
     if (onyx_has_errors()) goto has_error;
     goto no_errors;
 
 has_error:
-    // onyx_report_error((OnyxFilePos) { 0 }, "Error in polymorphic struct generated from this call site.");
+    // onyx_report_error(pos, "Error in polymorphic struct generated from this call site.");
     return NULL;
 
 no_errors: