From: Brendan Hansen Date: Wed, 23 Dec 2020 21:48:31 +0000 (-0600) Subject: made range literals not turn into struct literals X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=6e196da16cec6ba1ac3c0e57365da58085c5599d;p=onyx.git made range literals not turn into struct literals --- diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 35d32a21..fd081398 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -7,7 +7,7 @@ typedef struct AstNode AstNode; typedef struct AstTyped AstTyped; -typedef struct AstBinOp AstBinaryOp; +typedef struct AstBinaryOp AstBinaryOp; typedef struct AstUnaryOp AstUnaryOp; typedef struct AstNumLit AstNumLit; typedef struct AstStrLit AstStrLit; @@ -24,6 +24,7 @@ typedef struct AstAlignOf AstAlignOf; typedef struct AstFileContents AstFileContents; typedef struct AstStructLiteral AstStructLiteral; typedef struct AstArrayLiteral AstArrayLiteral; +typedef struct AstRangeLiteral AstRangeLiteral; typedef struct AstReturn AstReturn; typedef struct AstJump AstJump; @@ -134,7 +135,7 @@ typedef enum AstKind { Ast_Kind_Slice, Ast_Kind_Field_Access, Ast_Kind_Pipe, - Ast_Kind_Range, + Ast_Kind_Range_Literal, Ast_Kind_Size_Of, Ast_Kind_Align_Of, Ast_Kind_File_Contents, @@ -438,7 +439,7 @@ struct AstNode { AstNode_base }; struct AstTyped { AstTyped_base }; // Expression Nodes -struct AstBinOp { AstTyped_base; BinaryOp operation; AstTyped *left, *right; }; +struct AstBinaryOp { AstTyped_base; BinaryOp operation; AstTyped *left, *right; }; struct AstUnaryOp { AstTyped_base; UnaryOp operation; AstTyped *expr; }; struct AstNumLit { AstTyped_base; union { i32 i; i64 l; f32 f; f64 d; } value; }; struct AstStrLit { AstTyped_base; u64 addr; u64 length; }; @@ -466,6 +467,22 @@ struct AstArrayLiteral { bh_arr(AstTyped *) values; }; +struct AstRangeLiteral { + AstTyped_base; + + // HACK: Currently, range literals are parsed as binary operators, which means + // the first sizeof(AstBinaryOp) bytes of this structure must match that of + // AstBinaryOp, which means I need this dummy field here. + // - brendanfh 2020/12/23 + BinaryOp __unused_operation; + AstTyped *low, *high; + + // Currently, there is no way to specify this in the grammar, but it is set + // to be the initial value of the `step` member of the range structure in + // core/builtin.onyx. + // - brendanfh 2020/12/23 + AstTyped *step; +}; struct AstCall { AstTyped_base; diff --git a/onyx b/onyx index a7f14b60..dc37f1cd 100755 Binary files a/onyx and b/onyx differ diff --git a/src/onyxchecker.c b/src/onyxchecker.c index e6598289..dfbc9df3 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -18,12 +18,12 @@ CHECK(binaryop, AstBinaryOp** pbinop, b32 assignment_is_ok); CHECK(unaryop, AstUnaryOp** punop); CHECK(struct_literal, AstStructLiteral* sl); CHECK(array_literal, AstArrayLiteral* al); +CHECK(range_literal, AstRangeLiteral** range); CHECK(expression, AstTyped** expr); CHECK(address_of, AstAddressOf* aof); CHECK(dereference, AstDereference* deref); CHECK(array_access, AstArrayAccess* expr); CHECK(field_access, AstFieldAccess** pfield); -CHECK(range_literal, AstBinaryOp** range); CHECK(size_of, AstSizeOf* so); CHECK(align_of, AstAlignOf* ao); CHECK(global, AstGlobal* global); @@ -961,6 +961,38 @@ b32 check_array_literal(AstArrayLiteral* al) { return 0; } +b32 check_range_literal(AstRangeLiteral** prange) { + AstRangeLiteral* range = *prange; + if (check_expression(&range->low)) return 1; + if (check_expression(&range->high)) return 1; + + Type* expected_range_type = builtin_range_type_type; + StructMember smem; + + type_lookup_member(expected_range_type, "low", &smem); + if (!type_check_or_auto_cast(&range->low, smem.type)) { + onyx_report_error(range->token->pos, "Expected left side of range to be a 32-bit integer."); + return 1; + } + + type_lookup_member(expected_range_type, "high", &smem); + if (!type_check_or_auto_cast(&range->high, smem.type)) { + onyx_report_error(range->token->pos, "Expected right side of range to be a 32-bit integer."); + return 1; + } + + if (range->step == NULL) { + // HACK: This relies on the third member of the 'range' struct to exist, be the step, + // and have an initial_value. + AstStructMember* step_member = ((AstStructType *) builtin_range_type)->members[2]; + if (check_expression(&step_member->initial_value)) return 1; + + range->step = step_member->initial_value; + } + + return 0; +} + b32 check_address_of(AstAddressOf* aof) { if (check_expression(&aof->expr)) return 1; @@ -1116,55 +1148,6 @@ b32 check_field_access(AstFieldAccess** pfield) { return 0; } -b32 check_range_literal(AstBinaryOp** prange) { - AstBinaryOp* range = *prange; - if (check_expression(&range->left)) return 1; - if (check_expression(&range->right)) return 1; - - Type* expected_range_type = builtin_range_type_type; - StructMember smem; - - type_lookup_member(expected_range_type, "low", &smem); - if (!type_check_or_auto_cast(&range->left, smem.type)) { - onyx_report_error(range->token->pos, "Expected left side of range to be a 32-bit integer."); - return 1; - } - - type_lookup_member(expected_range_type, "high", &smem); - if (!type_check_or_auto_cast(&range->right, smem.type)) { - onyx_report_error(range->token->pos, "Expected right side of range to be a 32-bit integer."); - return 1; - } - - // NOTE: Implicitly converting this to a struct literal because that makes the - // WASM generation easier and more robust for return a range from a procedure - // and the like. This could be improved as struct literals are made more throughout - // the code base. - // - brendanfh, 2020/09/03 - AstStructLiteral* rsl = onyx_ast_node_new(semstate.node_allocator, sizeof(AstStructLiteral), Ast_Kind_Struct_Literal); - bh_arr_new(global_heap_allocator, rsl->values, 3); - - bh_arr_insert_end(rsl->values, 2); - type_lookup_member(expected_range_type, "low", &smem); - rsl->values[smem.idx] = range->left; - type_lookup_member(expected_range_type, "high", &smem); - rsl->values[smem.idx] = range->right; - - // HACK: This relies on the third member of the 'range' struct to exist, be the step, - // and have an intial_value. - AstStructMember* step_member = ((AstStructType *) builtin_range_type)->members[2]; - if (check_expression(&step_member->initial_value)) return 1; - bh_arr_push(rsl->values, step_member->initial_value); - - rsl->token = range->token; - rsl->type = expected_range_type; - - // NOTE: Not a binary op - *prange = (AstBinaryOp *) rsl; - - return 0; -} - b32 check_size_of(AstSizeOf* so) { fill_in_array_count(so->so_ast_type); @@ -1224,14 +1207,14 @@ b32 check_expression(AstTyped** pexpr) { case Ast_Kind_Local: break; - case Ast_Kind_Address_Of: retval = check_address_of((AstAddressOf *) expr); break; - case Ast_Kind_Dereference: retval = check_dereference((AstDereference *) expr); break; + case Ast_Kind_Address_Of: retval = check_address_of((AstAddressOf *) expr); break; + case Ast_Kind_Dereference: retval = check_dereference((AstDereference *) expr); break; case Ast_Kind_Slice: - case Ast_Kind_Array_Access: retval = check_array_access((AstArrayAccess *) expr); break; - case Ast_Kind_Field_Access: retval = check_field_access((AstFieldAccess **) pexpr); break; - case Ast_Kind_Size_Of: retval = check_size_of((AstSizeOf *) expr); break; - case Ast_Kind_Align_Of: retval = check_align_of((AstAlignOf *) expr); break; - case Ast_Kind_Range: retval = check_range_literal((AstBinaryOp **) pexpr); break; + case Ast_Kind_Array_Access: retval = check_array_access((AstArrayAccess *) expr); break; + case Ast_Kind_Field_Access: retval = check_field_access((AstFieldAccess **) pexpr); break; + case Ast_Kind_Size_Of: retval = check_size_of((AstSizeOf *) expr); break; + case Ast_Kind_Align_Of: retval = check_align_of((AstAlignOf *) expr); break; + case Ast_Kind_Range_Literal: retval = check_range_literal((AstRangeLiteral **) pexpr); break; case Ast_Kind_Global: if (expr->type == NULL) { diff --git a/src/onyxclone.c b/src/onyxclone.c index 31cd7e75..6d4bf71c 100644 --- a/src/onyxclone.c +++ b/src/onyxclone.c @@ -74,11 +74,12 @@ static inline i32 ast_kind_to_size(AstNode* node) { case Ast_Kind_Slice: return sizeof(AstArrayAccess); case Ast_Kind_Field_Access: return sizeof(AstFieldAccess); case Ast_Kind_Pipe: return sizeof(AstBinaryOp); - case Ast_Kind_Range: return sizeof(AstBinaryOp); + case Ast_Kind_Range_Literal: return sizeof(AstRangeLiteral); case Ast_Kind_Size_Of: return sizeof(AstSizeOf); case Ast_Kind_Align_Of: return sizeof(AstAlignOf); case Ast_Kind_File_Contents: return sizeof(AstFileContents); case Ast_Kind_Struct_Literal: return sizeof(AstStructLiteral); + case Ast_Kind_Array_Literal: return sizeof(AstArrayLiteral); case Ast_Kind_If: return sizeof(AstIfWhile); case Ast_Kind_For: return sizeof(AstFor); case Ast_Kind_While: return sizeof(AstIfWhile); @@ -124,7 +125,6 @@ AstNode* ast_clone(bh_allocator a, void* n) { switch ((u16) node->kind) { case Ast_Kind_Binary_Op: - case Ast_Kind_Range: ((AstBinaryOp *) nn)->left = (AstTyped *) ast_clone(a, ((AstBinaryOp *) node)->left); ((AstBinaryOp *) nn)->right = (AstTyped *) ast_clone(a, ((AstBinaryOp *) node)->right); break; @@ -193,6 +193,26 @@ AstNode* ast_clone(bh_allocator a, void* n) { break; } + case Ast_Kind_Array_Literal: { + AstArrayLiteral* st = (AstArrayLiteral *) node; + AstArrayLiteral* dt = (AstArrayLiteral *) nn; + + dt->atnode = (AstTyped *) ast_clone(a, st->atnode); + + dt->values = NULL; + bh_arr_new(global_heap_allocator, dt->values, bh_arr_length(st->values)); + bh_arr_each(AstTyped *, val, st->values) + bh_arr_push(dt->values, (AstTyped *) ast_clone(a, *val)); + + break; + } + + case Ast_Kind_Range_Literal: + ((AstRangeLiteral *) nn)->low = (AstTyped *) ast_clone(a, ((AstRangeLiteral *) node)->low); + ((AstRangeLiteral *) nn)->high = (AstTyped *) ast_clone(a, ((AstRangeLiteral *) node)->high); + ((AstRangeLiteral *) nn)->step = (AstTyped *) ast_clone(a, ((AstRangeLiteral *) node)->step); + break; + case Ast_Kind_Return: ((AstReturn *) nn)->expr = (AstTyped *) ast_clone(a, ((AstReturn *) node)->expr); break; diff --git a/src/onyxparser.c b/src/onyxparser.c index 2f7e7a5b..d393cea7 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -749,7 +749,7 @@ static AstTyped* parse_expression(OnyxParser* parser) { bin_op = make_node(AstBinaryOp, Ast_Kind_Pipe); } else if (bin_op_kind == Binary_Op_Range) { - bin_op = make_node(AstBinaryOp, Ast_Kind_Range); + bin_op = (AstBinaryOp *) make_node(AstRangeLiteral, Ast_Kind_Range_Literal); } else { bin_op = make_node(AstBinaryOp, Ast_Kind_Binary_Op); diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 0e7fe68c..fba688fa 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -435,9 +435,9 @@ static void symres_expression(AstTyped** expr) { case Ast_Kind_Size_Of: symres_size_of((AstSizeOf *)*expr); break; case Ast_Kind_Align_Of: symres_align_of((AstAlignOf *)*expr); break; - case Ast_Kind_Range: - symres_expression(&((AstBinaryOp *)(*expr))->left); - symres_expression(&((AstBinaryOp *)(*expr))->right); + case Ast_Kind_Range_Literal: + symres_expression(&((AstRangeLiteral *)(*expr))->low); + symres_expression(&((AstRangeLiteral *)(*expr))->high); (*expr)->type_node = symres_type(builtin_range_type); diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 3ae39b74..9374d372 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -391,6 +391,7 @@ EMIT_FUNC(struct_lval, AstTyped* lval); EMIT_FUNC(struct_store, Type* type, u64 offset); EMIT_FUNC(struct_literal, AstStructLiteral* sl); EMIT_FUNC(array_literal, AstArrayLiteral* al); +EMIT_FUNC(range_literal, AstRangeLiteral* range); EMIT_FUNC(expression, AstTyped* expr); EMIT_FUNC(cast, AstUnaryOp* cast); EMIT_FUNC(return, AstReturn* ret); @@ -2130,6 +2131,16 @@ EMIT_FUNC(array_literal, AstArrayLiteral* al) { *pcode = code; } +EMIT_FUNC(range_literal, AstRangeLiteral* range) { + bh_arr(WasmInstruction) code = *pcode; + + emit_expression(mod, &code, range->low); + emit_expression(mod, &code, range->high); + emit_expression(mod, &code, range->step); + + *pcode = code; +} + EMIT_FUNC(location, AstTyped* expr) { bh_arr(WasmInstruction) code = *pcode; @@ -2292,6 +2303,11 @@ EMIT_FUNC(expression, AstTyped* expr) { break; } + case Ast_Kind_Range_Literal: { + emit_range_literal(mod, &code, (AstRangeLiteral *) expr); + break; + } + case Ast_Kind_Function: { i32 elemidx = get_element_idx(mod, (AstFunction *) expr); WID(WI_I32_CONST, elemidx);