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;
typedef struct AstFileContents AstFileContents;
typedef struct AstStructLiteral AstStructLiteral;
typedef struct AstArrayLiteral AstArrayLiteral;
+typedef struct AstRangeLiteral AstRangeLiteral;
typedef struct AstReturn AstReturn;
typedef struct AstJump AstJump;
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,
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; };
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;
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);
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;
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);
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) {
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);
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;
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;
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);
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);
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);
*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;
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);