From: Brendan Hansen Date: Tue, 12 Jan 2021 20:32:07 +0000 (-0600) Subject: multiple declarations work in procedure bodies X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=18f5548cc795a39a9bcde4f53a35def3d112b00a;p=onyx.git multiple declarations work in procedure bodies --- diff --git a/bin/onyx b/bin/onyx index 4d6e3d91..dddbe4b5 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 879d89a9..72083320 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -987,6 +987,8 @@ AstNumLit* make_float_literal(bh_allocator a, f64 value); AstBinaryOp* make_binary_op(bh_allocator a, BinaryOp operation, AstTyped* left, AstTyped* right); AstArgument* make_argument(bh_allocator a, AstTyped* value); AstFieldAccess* make_field_access(bh_allocator a, AstTyped* node, char* field); +AstLocal* make_local(bh_allocator a, OnyxToken* token, AstType* type_node); +AstNode* make_symbol(bh_allocator a, OnyxToken* sym); typedef enum PolyProcLookupMethod { PPLM_By_Call, diff --git a/onyx.exe b/onyx.exe index 56839afc..2e658aab 100644 Binary files a/onyx.exe and b/onyx.exe differ diff --git a/src/onyxastnodes.c b/src/onyxastnodes.c index 8c7b15a3..b94cc535 100644 --- a/src/onyxastnodes.c +++ b/src/onyxastnodes.c @@ -617,3 +617,16 @@ AstFieldAccess* make_field_access(bh_allocator a, AstTyped* node, char* field) { return fa; } +AstLocal* make_local(bh_allocator a, OnyxToken* token, AstType* type_node) { + AstLocal* local = onyx_ast_node_new(a, sizeof(AstLocal), Ast_Kind_Local); + local->token = token; + local->type_node = type_node; + + return local; +} + +AstNode* make_symbol(bh_allocator a, OnyxToken* sym) { + AstNode* symbol = onyx_ast_node_new(a, sizeof(AstNode), Ast_Kind_Symbol); + symbol->token = sym; + return symbol; +} diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 03ffaf50..d5b7cf12 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -591,7 +591,24 @@ CheckStatus check_binop_assignment(AstBinaryOp* binop, b32 assignment_is_ok) { // NOTE: This is the 'type inference' system. Very stupid, but very easy. // If a left operand has an unknown type, fill it in with the type of // the right hand side. - if (binop->left->type == NULL) binop->left->type = resolve_expression_type(binop->right); + if (binop->left->type == NULL) { + resolve_expression_type(binop->right); + + if (binop->right->type->kind == Type_Kind_Compound) { + i32 expr_count = binop->right->type->Compound.count; + AstCompound* lhs = (AstCompound *) binop->left; + assert(lhs->kind == Ast_Kind_Compound); + + fori (i, 0, expr_count) { + lhs->exprs[i]->type = binop->right->type->Compound.types[i]; + } + + lhs->type = type_build_compound_type(semstate.node_allocator, lhs); + + } else { + binop->left->type = binop->right->type; + } + } } else { // NOTE: +=, -=, ... @@ -1115,7 +1132,7 @@ CheckStatus check_range_literal(AstRangeLiteral** prange) { CheckStatus check_compound(AstCompound* compound) { bh_arr_each(AstTyped *, expr, compound->exprs) { CHECK(expression, expr); - resolve_expression_type(*expr); + resolve_expression_type(*expr); } compound->type = type_build_compound_type(semstate.node_allocator, compound); @@ -1194,7 +1211,9 @@ CheckStatus check_array_access(AstArrayAccess* aa) { resolve_expression_type(aa->expr); if (aa->expr->type->kind != Type_Kind_Basic || (aa->expr->type->Basic.kind != Basic_Kind_I32 && aa->expr->type->Basic.kind != Basic_Kind_U32)) { - onyx_report_error(aa->token->pos, "Expected type u32 or i32 for index."); + onyx_report_error(aa->token->pos, + "Expected type u32 or i32 for index, got '%s'.", + type_get_name(aa->expr->type)); return Check_Error; } diff --git a/src/onyxparser.c b/src/onyxparser.c index 51277e20..5d309d98 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -5,6 +5,7 @@ // NOTE: The one weird define you need to know before read the code below #define make_node(nclass, kind) onyx_ast_node_new(parser->allocator, sizeof(nclass), kind) +#define peek_token(ahead) (parser->curr + ahead) #define STORE_PARSER_STATE \ OnyxToken* __parser_curr = parser->curr; \ @@ -167,7 +168,7 @@ static AstNumLit* parse_float_literal(OnyxParser* parser) { static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret) { if (parser->curr->type != '.' - || (parser->curr + 1)->type != '{') return 0; + || peek_token(1)->type != '{') return 0; AstStructLiteral* sl = make_node(AstStructLiteral, Ast_Kind_Struct_Literal); sl->token = parser->curr; @@ -182,7 +183,7 @@ static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, Ast expect_token(parser, '.'); expect_token(parser, '{'); - b32 is_named = ((parser->curr + 1)->type == '='); + b32 is_named = (peek_token(1)->type == '='); OnyxToken* name = NULL; while (parser->curr->type != '}') { @@ -220,7 +221,7 @@ static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, Ast static b32 parse_possible_array_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret) { if (parser->curr->type != '.' - || (parser->curr + 1)->type != '[') return 0; + || peek_token(1)->type != '[') return 0; AstArrayLiteral* al = make_node(AstArrayLiteral, Ast_Kind_Array_Literal); al->token = parser->curr; @@ -858,9 +859,9 @@ static AstIfWhile* parse_if_stmt(OnyxParser* parser) { AstIfWhile* root_if = if_node; - if ((parser->curr + 1)->type == ':') { - if_node->local = make_node(AstLocal, Ast_Kind_Local); - if_node->local->token = expect_token(parser, Token_Type_Symbol); + if (peek_token(1)->type == ':') { + OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol); + if_node->local = make_local(parser->allocator, local_sym, NULL); expect_token(parser, ':'); @@ -915,9 +916,9 @@ static AstIfWhile* parse_while_stmt(OnyxParser* parser) { AstIfWhile* while_node = make_node(AstIfWhile, Ast_Kind_While); while_node->token = while_token; - if ((parser->curr + 1)->type == ':') { - while_node->local = make_node(AstLocal, Ast_Kind_Local); - while_node->local->token = expect_token(parser, Token_Type_Symbol); + if (peek_token(1)->type == ':') { + OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol); + while_node->local = make_local(parser->allocator, local_sym, NULL); expect_token(parser, ':'); @@ -951,8 +952,8 @@ static AstFor* parse_for_stmt(OnyxParser* parser) { for_node->by_pointer = 1; } - AstLocal* var_node = make_node(AstLocal, Ast_Kind_Local); - var_node->token = expect_token(parser, Token_Type_Symbol); + OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol); + AstLocal* var_node = make_local(parser->allocator, local_sym, NULL); for_node->var = var_node; @@ -969,9 +970,9 @@ static AstSwitch* parse_switch_stmt(OnyxParser* parser) { bh_arr_new(global_heap_allocator, switch_node->cases, 4); - if ((parser->curr + 1)->type == ':') { - switch_node->local = make_node(AstLocal, Ast_Kind_Local); - switch_node->local->token = expect_token(parser, Token_Type_Symbol); + if (peek_token(1)->type == ':') { + OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol); + switch_node->local = make_local(parser->allocator, local_sym, NULL); expect_token(parser, ':'); @@ -1027,6 +1028,63 @@ static AstSwitch* parse_switch_stmt(OnyxParser* parser) { return switch_node; } +static i32 parse_possible_compound_symbol_declaration(OnyxParser* parser, AstNode** ret) { + u32 token_offset = 0; + while (peek_token(token_offset)->type == Token_Type_Symbol) { + token_offset += 1; + + if (peek_token(token_offset)->type != ',') break; + token_offset += 1; + } + + if (peek_token(token_offset)->type != ':') return 0; + + // At this point, we are sure it is a compound declaration. + AstCompound* local_compound = make_node(AstCompound, Ast_Kind_Compound); + bh_arr_new(global_heap_allocator, local_compound->exprs, token_offset / 2); + + AstLocal* first_local = NULL; + AstLocal* prev_local = NULL; + + while (parser->curr->type == Token_Type_Symbol) { + if (parser->hit_unexpected_token) return 1; + + OnyxToken* local_sym = expect_token(parser, Token_Type_Symbol); + AstLocal* new_local = make_local(parser->allocator, local_sym, NULL); + + if (prev_local == NULL) { + first_local = new_local; + } else { + prev_local->next = (AstNode *) new_local; + } + prev_local = new_local; + + AstNode* sym_node = make_symbol(parser->allocator, local_sym); + bh_arr_push(local_compound->exprs, (AstTyped *) sym_node); + + if (parser->curr->type == ',') + expect_token(parser, ','); + } + + expect_token(parser, ':'); + + if (parser->curr->type == '=') { + AstBinaryOp* assignment = make_binary_op(parser->allocator, Binary_Op_Assign, (AstTyped *) local_compound, NULL); + assignment->token = expect_token(parser, '='); + assignment->right = parse_compound_expression(parser, 0); + + prev_local->next = (AstNode *) assignment; + + } else { + AstType* type_for_all = parse_type(parser); + bh_arr_each(AstTyped *, local, local_compound->exprs) + (*local)->type_node = type_for_all; + } + + *ret = (AstNode *) first_local; + return 1; +} + // Returns: // 0 - if this was not a symbol declaration. // 1 - if this was a local declaration. @@ -1036,9 +1094,18 @@ static AstSwitch* parse_switch_stmt(OnyxParser* parser) { // : : // := // :: +// (, )* : +// (, )* := static i32 parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret) { + // Has to start with a symbol to be a declaration if (parser->curr->type != Token_Type_Symbol) return 0; - if ((parser->curr + 1)->type != ':') return 0; + + // If the token after the symbol is a comma, assume this is a compound declaration. + if (peek_token(1)->type == ',') { + return parse_possible_compound_symbol_declaration(parser, ret); + } + + if (peek_token(1)->type != ':') return 0; OnyxToken* symbol = expect_token(parser, Token_Type_Symbol); expect_token(parser, ':'); @@ -1060,9 +1127,7 @@ static i32 parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret) type_node = parse_type(parser); } - AstLocal* local = make_node(AstLocal, Ast_Kind_Local); - local->token = symbol; - local->type_node = type_node; + AstLocal* local = make_local(parser->allocator, symbol, type_node); *ret = (AstNode *) local; if (parser->curr->type == '=') { @@ -1304,19 +1369,15 @@ static AstNode* parse_statement(OnyxParser* parser) { } case Token_Type_Keyword_Use: { - // AstUse* use_node = make_node(AstUse, Ast_Kind_Use); - // use_node->token = expect_token(parser, Token_Type_Keyword_Use); - // use_node->expr = parse_expression(parser); - needs_semicolon = 0; + retval = (AstNode *) parse_use_stmt(parser); break; } case '#': { if (parse_possible_directive(parser, "context_scope")) { - AstLocal* context_tmp = make_node(AstLocal, Ast_Kind_Local); - context_tmp->type_node = builtin_context_variable->type_node; + AstLocal* context_tmp = make_local(parser->allocator, NULL, builtin_context_variable->type_node); AstBinaryOp* assignment = make_node(AstBinaryOp, Ast_Kind_Binary_Op); assignment->operation = Binary_Op_Assign; @@ -1527,7 +1588,7 @@ static AstType* parse_type(OnyxParser* parser) { while (parser->curr->type != ')') { if (parser->hit_unexpected_token) return root; - if ((parser->curr + 1)->type == ':') { + if (peek_token(1)->type == ':') { expect_token(parser, Token_Type_Symbol); expect_token(parser, ':'); } @@ -1792,8 +1853,8 @@ static void parse_function_params(OnyxParser* parser, AstFunction* func) { expect_token(parser, ':'); curr_param.vararg_kind = VA_Kind_Not_VA; - curr_param.local = make_node(AstLocal, Ast_Kind_Param); - curr_param.local->token = symbol; + curr_param.local = make_local(parser->allocator, symbol, NULL); + curr_param.local->kind = Ast_Kind_Param; if (param_use) { curr_param.local->flags |= Ast_Flag_Param_Use; diff --git a/src/onyxtypes.c b/src/onyxtypes.c index ed76107d..718d8942 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -576,6 +576,9 @@ Type* type_build_function_type(bh_allocator alloc, AstFunction* func) { Type* type_build_compound_type(bh_allocator alloc, AstCompound* compound) { i64 expr_count = bh_arr_length(compound->exprs); + fori (i, 0, expr_count) { + if (compound->exprs[i]->type == NULL) return NULL; + } Type* comp_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * expr_count); comp_type->kind = Type_Kind_Compound; diff --git a/src/onyxutils.c b/src/onyxutils.c index 2fca21dd..639e8dbd 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -78,13 +78,14 @@ b32 symbol_introduce(Scope* scope, OnyxToken* tkn, AstNode* symbol) { } b32 symbol_raw_introduce(Scope* scope, char* name, OnyxFilePos pos, AstNode* symbol) { - if (bh_table_has(AstNode *, scope->symbols, name)) { - if (bh_table_get(AstNode *, scope->symbols, name) != symbol) { - onyx_report_error(pos, "Redeclaration of symbol '%s'.", name); - return 0; + if (strcmp(name, "_")) { + if (bh_table_has(AstNode *, scope->symbols, name)) { + if (bh_table_get(AstNode *, scope->symbols, name) != symbol) { + onyx_report_error(pos, "Redeclaration of symbol '%s'.", name); + return 0; + } + return 1; } - - return 1; } bh_table_put(AstNode *, scope->symbols, name, symbol); diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 24ff36ab..8b7c6c47 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -2445,10 +2445,15 @@ EMIT_FUNC(expression, AstTyped* expr) { assert(0); } - // FIX: This is going to be wrong for structs and compound types. + // FIX: This is going to be wrong for struct types. if (expr->flags & Ast_Flag_Expr_Ignored && !type_results_in_void(expr->type)) { - WI(WI_DROP); + if (expr->type->kind == Type_Kind_Compound) { + fori (i, 0, expr->type->Compound.count) + WI(WI_DROP); + } else { + WI(WI_DROP); + } } *pcode = code; @@ -3234,6 +3239,12 @@ void emit_entity(Entity* ent) { case Entity_Type_Function_Header: if (!should_emit_function(ent->function)) break; + // bh_printf("%d -> %s:%d:%d\n", + // module->next_func_idx, + // ent->expr->token->pos.filename, + // ent->expr->token->pos.line, + // ent->expr->token->pos.column); + bh_imap_put(&module->index_map, (u64) ent->function, module->next_func_idx++); break;