From: Brendan Hansen Date: Sun, 20 Sep 2020 20:22:41 +0000 (-0500) Subject: nasty bug fix with polymorphic structs destroying scope tree X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=091bc968080a2e6aadeca0881e060060937a6d9a;p=onyx.git nasty bug fix with polymorphic structs destroying scope tree --- diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 8c97f6a2..97432168 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -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) { diff --git a/include/onyxutils.h b/include/onyxutils.h index 4e2b1f43..bf6b9ba3 100644 --- a/include/onyxutils.h +++ b/include/onyxutils.h @@ -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); diff --git a/misc/onyx.vim b/misc/onyx.vim index b1378b2d..2afb167e 100644 --- a/misc/onyx.vim +++ b/misc/onyx.vim @@ -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 416b2df4..068a56a1 100755 Binary files a/onyx and b/onyx differ diff --git a/src/onyxparser.c b/src/onyxparser.c index c04587ce..2503d2d4 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -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; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 1077fa2d..146494fe 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -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() { diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 0569314d..8d961b08 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -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); diff --git a/src/onyxutils.c b/src/onyxutils.c index 832272d5..05eeb478 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -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: