From: Brendan Hansen Date: Tue, 12 Jan 2021 04:22:12 +0000 (-0600) Subject: began work on multiple return values X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=e0a0c45abdeeefe38b0496fcf5fd2bdf5d125f93;p=onyx.git began work on multiple return values --- diff --git a/bin/onyx b/bin/onyx index 738c0715..c9a1216e 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index a2ff9115..83880b4d 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -25,6 +25,7 @@ typedef struct AstFileContents AstFileContents; typedef struct AstStructLiteral AstStructLiteral; typedef struct AstArrayLiteral AstArrayLiteral; typedef struct AstRangeLiteral AstRangeLiteral; +typedef struct AstCompound AstCompound; typedef struct AstDirectiveSolidify AstDirectiveSolidify; @@ -56,6 +57,7 @@ typedef struct AstEnumType AstEnumType; typedef struct AstEnumValue AstEnumValue; typedef struct AstTypeAlias AstTypeAlias; typedef struct AstTypeRawAlias AstTypeRawAlias; +typedef struct AstCompoundType AstCompoundType; typedef struct AstBinding AstBinding; typedef struct AstMemRes AstMemRes; @@ -106,6 +108,8 @@ typedef enum AstKind { Ast_Kind_Unary_Op, Ast_Kind_Binary_Op, + Ast_Kind_Compound, + Ast_Kind_Type_Start, Ast_Kind_Type, Ast_Kind_Basic_Type, @@ -121,6 +125,7 @@ typedef enum AstKind { Ast_Kind_Enum_Type, Ast_Kind_Type_Alias, Ast_Kind_Type_Raw_Alias, + Ast_Kind_Type_Compound, Ast_Kind_Type_End, Ast_Kind_Struct_Member, @@ -516,6 +521,11 @@ struct AstIntrinsicCall { VarArgKind va_kind; }; +struct AstCompound { + AstTyped_base; + + bh_arr(AstTyped *) exprs; +}; struct AstDirectiveSolidify { AstTyped_base; @@ -668,6 +678,11 @@ struct AstEnumType { struct AstEnumValue { AstTyped_base; AstNumLit* value; }; struct AstTypeAlias { AstType_base; AstType* to; }; struct AstTypeRawAlias { AstType_base; Type* to; }; +struct AstCompoundType { + AstType_base; + + bh_arr(AstType *) types; +}; // Top level nodes struct AstBinding { AstTyped_base; AstNode* node; }; @@ -988,13 +1003,22 @@ AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstP // NOTE: Useful inlined functions static inline b32 is_lval(AstNode* node) { - return (node->kind == Ast_Kind_Local) + if ((node->kind == Ast_Kind_Local) || (node->kind == Ast_Kind_Param) || (node->kind == Ast_Kind_Global) || (node->kind == Ast_Kind_Dereference) || (node->kind == Ast_Kind_Array_Access) || (node->kind == Ast_Kind_Field_Access) - || (node->kind == Ast_Kind_Memres); + || (node->kind == Ast_Kind_Memres)) + return 1; + + if (node->kind == Ast_Kind_Compound) { + b32 all_lval = 1; + bh_arr_each(AstTyped *, expr, ((AstCompound *) node)->exprs) all_lval = all_lval && is_lval((AstNode *) *expr); + return all_lval; + } + + return 0; } static inline b32 binop_is_assignment(BinaryOp binop) { diff --git a/include/onyxtypes.h b/include/onyxtypes.h index 0d071135..6d92d21b 100644 --- a/include/onyxtypes.h +++ b/include/onyxtypes.h @@ -91,6 +91,11 @@ typedef struct StructMember { bh_arr(StructMember *) memarr; \ bh_arr(struct AstPolySolution) poly_sln; \ }) \ + TYPE_KIND(Compound, struct { \ + u32 count; \ + u32 size; \ + Type* types[]; \ + }) \ TYPE_KIND(Array, struct { u32 size; u32 count; Type *elem; }) \ TYPE_KIND(Slice, struct { Type *ptr_to_data; }) \ TYPE_KIND(DynArray, struct { Type *ptr_to_data; }) \ @@ -101,6 +106,7 @@ typedef struct StructMember { Type* backing; \ }) + typedef enum TypeKind { Type_Kind_Invalid, @@ -135,6 +141,7 @@ extern Type basic_types[]; struct AstType; struct AstFunction; +struct AstCompound; b32 types_are_compatible(Type* t1, Type* t2); u32 type_size_of(Type* type); @@ -142,6 +149,7 @@ u32 type_alignment_of(Type* type); Type* type_build_from_ast(bh_allocator alloc, struct AstType* type_node); Type* type_build_function_type(bh_allocator alloc, struct AstFunction* func); +Type* type_build_compound_type(bh_allocator alloc, struct AstCompound* compound); Type* type_make_pointer(bh_allocator alloc, Type* to); Type* type_make_array(bh_allocator alloc, Type* to, u32 count); diff --git a/onyx.exe b/onyx.exe index e585b16a..b503b6cb 100644 Binary files a/onyx.exe and b/onyx.exe differ diff --git a/src/onyxastnodes.c b/src/onyxastnodes.c index c90dc282..8c7b15a3 100644 --- a/src/onyxastnodes.c +++ b/src/onyxastnodes.c @@ -28,6 +28,8 @@ static const char* ast_node_names[] = { "UN_OP", "BIN_OP", + "COMPOUND", + "TYPE_START (BAD)", "TYPE", "BASIC_TYPE", @@ -43,6 +45,7 @@ static const char* ast_node_names[] = { "ENUM TYPE", "TYPE_ALIAS", "TYPE RAW ALIAS", + "COMPOUND TYPE", "TYPE_END (BAD)", "STRUCT MEMBER", diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 49d1ab0f..12f47cc2 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -31,6 +31,7 @@ CheckStatus check_unaryop(AstUnaryOp** punop); CheckStatus check_struct_literal(AstStructLiteral* sl); CheckStatus check_array_literal(AstArrayLiteral* al); CheckStatus check_range_literal(AstRangeLiteral** range); +CheckStatus check_compound(AstCompound* compound); CheckStatus check_expression(AstTyped** expr); CheckStatus check_address_of(AstAddressOf* aof); CheckStatus check_dereference(AstDereference* deref); @@ -1111,6 +1112,16 @@ CheckStatus check_range_literal(AstRangeLiteral** prange) { return Check_Success; } +CheckStatus check_compound(AstCompound* compound) { + bh_arr_each(AstTyped *, expr, compound->exprs) { + CHECK(expression, expr); + resolve_expression_type(*expr); + } + + compound->type = type_build_compound_type(semstate.node_allocator, compound); + return Check_Success; +} + CheckStatus check_address_of(AstAddressOf* aof) { CHECK(expression, &aof->expr); @@ -1386,6 +1397,10 @@ CheckStatus check_expression(AstTyped** pexpr) { *pexpr = (AstTyped *) ((AstDirectiveSolidify *) expr)->resolved_proc; break; + case Ast_Kind_Compound: + CHECK(compound, (AstCompound *) expr); + break; + case Ast_Kind_StrLit: break; case Ast_Kind_File_Contents: break; case Ast_Kind_Overloaded_Function: break; diff --git a/src/onyxparser.c b/src/onyxparser.c index 48ea0bf9..e8e5a403 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -27,7 +27,9 @@ static AstNumLit* parse_float_literal(OnyxParser* parser); static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret); static b32 parse_possible_array_literal(OnyxParser* parser, AstTyped* left, AstTyped** ret); static AstTyped* parse_factor(OnyxParser* parser); -static AstTyped* parse_expression(OnyxParser* parser); +static AstTyped* parse_compound_assignment(OnyxParser* parser, AstTyped* lhs); +static AstTyped* parse_compound_expression(OnyxParser* parser, b32 assignment_allowed); +static AstTyped* parse_expression(OnyxParser* parser, b32 assignment_allowed); static AstIfWhile* parse_if_stmt(OnyxParser* parser); static AstIfWhile* parse_while_stmt(OnyxParser* parser); static AstFor* parse_for_stmt(OnyxParser* parser); @@ -193,7 +195,7 @@ static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped* left, Ast name = NULL; } - AstTyped *expr = parse_expression(parser); + AstTyped *expr = parse_expression(parser, 0); if (is_named) { AstStructMember* sm = make_node(AstStructMember, Ast_Kind_Struct_Member); @@ -230,7 +232,7 @@ static b32 parse_possible_array_literal(OnyxParser* parser, AstTyped* left, AstT expect_token(parser, '.'); expect_token(parser, '['); while (parser->curr->type != ']') { - AstTyped* value = parse_expression(parser); + AstTyped* value = parse_expression(parser, 0); bh_arr_push(al->values, value); if (parser->curr->type != ']') @@ -258,7 +260,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { switch ((u16) parser->curr->type) { case '(': { consume_token(parser); - AstTyped* expr = parse_expression(parser); + AstTyped* expr = parse_compound_expression(parser, 0); expect_token(parser, ')'); retval = expr; break; @@ -570,7 +572,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { switch ((u16) parser->curr->type) { case '[': { OnyxToken *open_bracket = expect_token(parser, '['); - AstTyped *expr = parse_expression(parser); + AstTyped *expr = parse_compound_expression(parser, 0); AstKind kind = Ast_Kind_Array_Access; @@ -610,7 +612,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { AstArgument* arg = make_node(AstArgument, Ast_Kind_Argument); arg->token = parser->curr; - arg->value = parse_expression(parser); + arg->value = parse_expression(parser, 0); if (arg != NULL && arg->kind != Ast_Kind_Error) { bh_arr_push(call_node->arg_arr, arg); @@ -728,6 +730,47 @@ static BinaryOp binary_op_from_token_type(TokenType t) { } } +static AstTyped* parse_compound_assignment(OnyxParser* parser, AstTyped* lhs) { + if (parser->curr->type != '=') return lhs; + + AstBinaryOp* assignment = make_node(AstBinaryOp, Ast_Kind_Binary_Op); + assignment->token = expect_token(parser, '='); + assignment->operation = Binary_Op_Assign; + assignment->left = lhs; + assignment->right = parse_compound_expression(parser, 0); + + return (AstTyped *) assignment; +} + +static AstTyped* parse_compound_expression(OnyxParser* parser, b32 assignment_allowed) { + AstTyped* first = parse_expression(parser, assignment_allowed); + + if (parser->curr->type == ',') { + AstCompound* compound = make_node(AstCompound, Ast_Kind_Compound); + compound->token = parser->curr; + + bh_arr_new(global_heap_allocator, compound->exprs, 2); + bh_arr_push(compound->exprs, first); + + while (parser->curr->type == ',') { + if (parser->hit_unexpected_token) return (AstTyped *) compound; + consume_token(parser); + + AstTyped* expr = parse_expression(parser, 0); + bh_arr_push(compound->exprs, expr); + + if (assignment_allowed && parser->curr->type == '=') { + return parse_compound_assignment(parser, (AstTyped *) compound); + } + } + + return (AstTyped *) compound; + + } else { + return first; + } +} + // + // - // * @@ -747,7 +790,7 @@ static BinaryOp binary_op_from_token_type(TokenType t) { // %= // // With expected precedence rules -static AstTyped* parse_expression(OnyxParser* parser) { +static AstTyped* parse_expression(OnyxParser* parser, b32 assignment_allowed) { bh_arr(AstBinaryOp*) tree_stack = NULL; bh_arr_new(global_heap_allocator, tree_stack, 4); bh_arr_set_length(tree_stack, 0); @@ -764,6 +807,7 @@ static AstTyped* parse_expression(OnyxParser* parser) { bin_op_kind = binary_op_from_token_type(parser->curr->type); if (bin_op_kind == Binary_Op_Count) goto expression_done; + if (binop_is_assignment(bin_op_kind) && !assignment_allowed) goto expression_done; bin_op_tok = parser->curr; consume_token(parser); @@ -824,13 +868,13 @@ static AstIfWhile* parse_if_stmt(OnyxParser* parser) { assignment->operation = Binary_Op_Assign; assignment->token = expect_token(parser, '='); assignment->left = (AstTyped *) if_node->local; - assignment->right = parse_expression(parser); + assignment->right = parse_expression(parser, 0); if_node->assignment = assignment; expect_token(parser, ';'); } - AstTyped* cond = parse_expression(parser); + AstTyped* cond = parse_expression(parser, 1); AstBlock* true_stmt = parse_block(parser); if_node->cond = cond; @@ -843,7 +887,7 @@ static AstIfWhile* parse_if_stmt(OnyxParser* parser) { consume_token(parser); AstIfWhile* elseif_node = make_node(AstIfWhile, Ast_Kind_If); - cond = parse_expression(parser); + cond = parse_expression(parser, 1); true_stmt = parse_block(parser); elseif_node->cond = cond; @@ -881,13 +925,13 @@ static AstIfWhile* parse_while_stmt(OnyxParser* parser) { assignment->operation = Binary_Op_Assign; assignment->token = expect_token(parser, '='); assignment->left = (AstTyped *) while_node->local; - assignment->right = parse_expression(parser); + assignment->right = parse_expression(parser, 0); while_node->assignment = assignment; expect_token(parser, ';'); } - while_node->cond = parse_expression(parser); + while_node->cond = parse_expression(parser, 1); while_node->true_stmt = parse_block(parser); if (parser->curr->type == Token_Type_Keyword_Else) { @@ -913,7 +957,7 @@ static AstFor* parse_for_stmt(OnyxParser* parser) { for_node->var = var_node; expect_token(parser, ':'); - for_node->iter = parse_expression(parser); + for_node->iter = parse_expression(parser, 1); for_node->stmt = parse_block(parser); return for_node; @@ -935,13 +979,13 @@ static AstSwitch* parse_switch_stmt(OnyxParser* parser) { assignment->operation = Binary_Op_Assign; assignment->token = expect_token(parser, '='); assignment->left = (AstTyped *) switch_node->local; - assignment->right = parse_expression(parser); + assignment->right = parse_expression(parser, 0); switch_node->assignment = assignment; expect_token(parser, ';'); } - switch_node->expr = parse_expression(parser); + switch_node->expr = parse_expression(parser, 1); expect_token(parser, '{'); while (parser->curr->type == Token_Type_Keyword_Case) { @@ -960,13 +1004,13 @@ static AstSwitch* parse_switch_stmt(OnyxParser* parser) { break; } - AstTyped* value = parse_expression(parser); + AstTyped* value = parse_expression(parser, 1); bh_arr_push(case_values, value); while (parser->curr->type == ',') { if (parser->hit_unexpected_token) return switch_node; consume_token(parser); - value = parse_expression(parser); + value = parse_expression(parser, 1); bh_arr_push(case_values, value); } @@ -1028,7 +1072,7 @@ static i32 parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret) assignment->token = parser->curr; consume_token(parser); - AstTyped* expr = parse_expression(parser); + AstTyped* expr = parse_expression(parser, 1); if (expr == NULL) return 1; assignment->right = expr; @@ -1048,7 +1092,7 @@ static AstReturn* parse_return_stmt(OnyxParser* parser) { AstTyped* expr = NULL; if (parser->curr->type != ';') { - expr = parse_expression(parser); + expr = parse_compound_expression(parser, 0); if (expr == NULL || expr == (AstTyped *) &error_node) { return (AstReturn *) &error_node; @@ -1131,7 +1175,7 @@ static AstNode* parse_use_stmt(OnyxParser* parser) { } else { AstUse* use_node = make_node(AstUse, Ast_Kind_Use); use_node->token = use_token; - use_node->expr = parse_expression(parser); + use_node->expr = parse_expression(parser, 1); return (AstNode *) use_node; } } @@ -1177,7 +1221,7 @@ static AstNode* parse_statement(OnyxParser* parser) { case Token_Type_Literal_Integer: case Token_Type_Literal_Float: case Token_Type_Literal_String: - retval = (AstNode *) parse_expression(parser); + retval = (AstNode *) parse_compound_expression(parser, 1); break; case Token_Type_Keyword_If: @@ -1438,7 +1482,7 @@ static AstType* parse_type(OnyxParser* parser) { AstType** insertion = (AstType **) &((AstArrayType *) new)->count_expr; parse_polymorphic_variable(parser, &insertion); } else { - ((AstArrayType *) new)->count_expr = parse_expression(parser); + ((AstArrayType *) new)->count_expr = parse_expression(parser, 0); } } @@ -1559,7 +1603,7 @@ static AstType* parse_type(OnyxParser* parser) { case Token_Type_Literal_Float: case Token_Type_Literal_True: case Token_Type_Literal_False: - *next_insertion = (AstType *) parse_expression(parser); + *next_insertion = (AstType *) parse_expression(parser, 0); next_insertion = NULL; break; } @@ -1676,7 +1720,7 @@ static AstStructType* parse_struct(OnyxParser* parser) { if (parser->curr->type == '=') { consume_token(parser); - mem->initial_value = parse_expression(parser); + mem->initial_value = parse_expression(parser, 0); } expect_token(parser, ';'); @@ -1767,7 +1811,7 @@ static void parse_function_params(OnyxParser* parser, AstFunction* func) { if (parser->curr->type == '=' && curr_param.vararg_kind == VA_Kind_Not_VA) { consume_token(parser); - curr_param.default_value = parse_expression(parser); + curr_param.default_value = parse_expression(parser, 0); } bh_arr_push(func->params, curr_param); @@ -1814,7 +1858,7 @@ static AstFunction* parse_function_definition(OnyxParser* parser) { while (parser->curr->type != '}') { if (parser->hit_unexpected_token) return (AstFunction *) ofunc; - AstTyped* o_node = parse_expression(parser); + AstTyped* o_node = parse_expression(parser, 0); bh_arr_push(ofunc->overloads, o_node); @@ -1859,7 +1903,7 @@ static AstFunction* parse_function_definition(OnyxParser* parser) { onyx_report_error(parser->curr->pos, "#add_overload cannot be placed on procedures inside of other scopes"); } - func_def->overloaded_function = (AstNode *) parse_expression(parser); + func_def->overloaded_function = (AstNode *) parse_expression(parser, 0); } } @@ -2046,7 +2090,7 @@ static AstTyped* parse_top_level_expression(OnyxParser* parser) { return (AstTyped *) parse_enum_declaration(parser); } else { - return parse_expression(parser); + return parse_expression(parser, 1); } } @@ -2148,14 +2192,14 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) { if (parser->curr->type == '=') { consume_token(parser); - memres->initial_value = parse_expression(parser); + memres->initial_value = parse_expression(parser, 1); } else { memres->type_node = parse_type(parser); if (parser->curr->type == '=') { consume_token(parser); - memres->initial_value = parse_expression(parser); + memres->initial_value = parse_expression(parser, 1); } } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 494c8814..5cc05d9c 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -14,6 +14,7 @@ static void symres_call(AstCall* call); static void symres_size_of(AstSizeOf* so); static void symres_align_of(AstAlignOf* so); static void symres_field_access(AstFieldAccess** fa); +static void symres_compound(AstCompound* compound); static void symres_expression(AstTyped** expr); static void symres_return(AstReturn* ret); static void symres_if(AstIfWhile* ifnode); @@ -271,6 +272,12 @@ static void symres_field_access(AstFieldAccess** fa) { } } +static void symres_compound(AstCompound* compound) { + bh_arr_each(AstTyped *, expr, compound->exprs) { + symres_expression(expr); + } +} + static void symres_pipe(AstBinaryOp** pipe) { AstCall* call_node = (AstCall *) (*pipe)->right; symres_expression((AstTyped **) &call_node); @@ -405,6 +412,10 @@ static void symres_expression(AstTyped** expr) { symres_directive_solidify((AstDirectiveSolidify **) expr); break; + case Ast_Kind_Compound: + symres_compound((AstCompound *) *expr); + break; + default: break; } } diff --git a/src/onyxtypes.c b/src/onyxtypes.c index 6da02121..e824988d 100644 --- a/src/onyxtypes.c +++ b/src/onyxtypes.c @@ -231,6 +231,17 @@ b32 types_are_compatible(Type* t1, Type* t2) { return types_are_compatible(t1->DynArray.ptr_to_data->Pointer.elem, t2->DynArray.ptr_to_data->Pointer.elem); } + case Type_Kind_Compound: { + if (t2->kind != Type_Kind_Compound) return 0; + if (t1->Compound.count != t2->Compound.count) return 0; + + fori (i, 0, (i64) t1->Compound.count) { + if (!types_are_compatible(t1->Compound.types[i], t2->Compound.types[i])) return 0; + } + + return 1; + } + default: assert(("Invalid type", 0)); break; @@ -542,6 +553,23 @@ Type* type_build_function_type(bh_allocator alloc, AstFunction* func) { return func_type; } +Type* type_build_compound_type(bh_allocator alloc, AstCompound* compound) { + i64 expr_count = bh_arr_length(compound->exprs); + + Type* comp_type = bh_alloc(alloc, sizeof(Type) + sizeof(Type *) * expr_count); + comp_type->kind = Type_Kind_Compound; + comp_type->Compound.size = 0; + comp_type->Compound.count = expr_count; + + fori (i, 0, expr_count) { + assert(compound->exprs[i]->type != NULL); + comp_type->Compound.size += type_size_of(compound->exprs[i]->type); + comp_type->Compound.types[i] = compound->exprs[i]->type; + } + + return comp_type; +} + Type* type_make_pointer(bh_allocator alloc, Type* to) { Type* ptr_type = bh_alloc_item(alloc, Type);