From: Brendan Hansen Date: Thu, 22 Apr 2021 17:44:36 +0000 (-0500) Subject: added unary field access for enum/struct members X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=8043e80e20d249ca45988decdc3582ef5324d6cc;p=onyx.git added unary field access for enum/struct members --- diff --git a/bin/onyx b/bin/onyx index 51554867..4e721af4 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/docs/bugs b/docs/bugs index 172bc1ed..632a068f 100644 --- a/docs/bugs +++ b/docs/bugs @@ -64,6 +64,7 @@ List of known bugs: .{ -1, 0 }, .{ -1, 1 }, .{ 0, 1 }, ]; +[ ] :UnaryFieldAccessIsGross List of things to change: [X] Currently, there is no way to use the initialized members of a structure without using a struct literal. diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index 71de59dc..941f6a80 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -20,6 +20,7 @@ NODE(Dereference) \ NODE(ArrayAccess) \ NODE(FieldAccess) \ + NODE(UnaryFieldAccess) \ NODE(SizeOf) \ NODE(AlignOf) \ NODE(FileContents) \ @@ -152,6 +153,7 @@ typedef enum AstKind { Ast_Kind_Array_Access, Ast_Kind_Slice, Ast_Kind_Field_Access, + Ast_Kind_Unary_Field_Access, Ast_Kind_Pipe, Ast_Kind_Method_Call, Ast_Kind_Range_Literal, @@ -501,6 +503,12 @@ struct AstFieldAccess { AstTyped_base; AstTyped *expr; u32 offset; u32 idx; ch struct AstSizeOf { AstTyped_base; AstType *so_ast_type; Type *so_type; u64 size; }; struct AstAlignOf { AstTyped_base; AstType *ao_ast_type; Type *ao_type; u64 alignment; }; struct AstFileContents { AstTyped_base; OnyxToken *filename; u32 addr, size; }; +struct AstUnaryFieldAccess { + AstTyped_base; + + // "token" represents the field. This does not need an "offset" or an "index" + // because this node is meant to be replaced. +}; struct AstStructLiteral { AstTyped_base; diff --git a/modules/webgl2/webgl2.js b/modules/webgl2/webgl2.js index 61d565a1..bd533993 100644 --- a/modules/webgl2/webgl2.js +++ b/modules/webgl2/webgl2.js @@ -249,7 +249,7 @@ window.ONYX_MODULES.push({ stencilOp(fail, zfail, mask) { gl.stencilOp(fail, zfail, mask); }, stencilOpSeparate(face, fail, zfail, zpass) { gl.stencilOpSeparate(face, fail, zfail, zpass); }, texImage2D(target, level, internalforamt, width, height, border, format, type, pixels, pixelslen) { - const data = new DataView(window.ONYX_MEMORY.buffer, pixels, pixelslen); + const data = new Uint8Array(window.ONYX_MEMORY.buffer, pixels, pixelslen); gl.texImage2D(target, level, internalforamt, width, height, border, format, type, data); }, texParameterf(target, pname, param) { gl.texParameterf(target, pname, param); }, diff --git a/src/onyxastnodes.c b/src/onyxastnodes.c index 08dad627..866f2620 100644 --- a/src/onyxastnodes.c +++ b/src/onyxastnodes.c @@ -56,9 +56,10 @@ static const char* ast_node_names[] = { "RETURN", "ADDRESS OF", "DEREFERENCE", - "ARRAY_ACCESS", + "ARRAY ACCESS", "SLICE", - "FIELD_ACCESS", + "FIELD ACCESS", + "UNARY FIELD ACCESS" "PIPE", "METHOD_CALL", "RANGE", @@ -423,8 +424,8 @@ b32 convert_numlit_to_type(AstNumLit* num, Type* type) { // NOTE: Returns 0 if it was not possible to make the types compatible. b32 type_check_or_auto_cast(AstTyped** pnode, Type* type) { AstTyped* node = *pnode; - assert(type != NULL); - assert(node != NULL); + if (type == NULL) return 0; + if (node == NULL) return 0; if (node_is_type((AstNode *) node)) return 0; @@ -446,6 +447,15 @@ b32 type_check_or_auto_cast(AstTyped** pnode, Type* type) { return 1; } + if (node->kind == Ast_Kind_Unary_Field_Access) { + AstType* ast_type = type->ast_type; + AstNode* resolved = try_symbol_resolve_from_node((AstNode *) ast_type, node->token); + if (resolved == NULL) return 0; + + *pnode = (AstTyped *) resolved; + return 1; + } + if (node->kind == Ast_Kind_Overloaded_Function) { AstTyped* func = find_matching_overload_by_type(((AstOverloadedFunction *) node)->overloads, type); if (func == NULL) return 0; diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 3a401869..00b8159e 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -257,7 +257,7 @@ CheckStatus check_switch(AstSwitch* switchnode) { if (switchnode->assignment != NULL) CHECK(statement, (AstNode **) &switchnode->assignment); CHECK(expression, &switchnode->expr); - resolve_expression_type(switchnode->expr); + Type* resolved_expr_type = resolve_expression_type(switchnode->expr); if (!type_is_integer(switchnode->expr->type) && switchnode->expr->type->kind != Type_Kind_Enum) { onyx_report_error(switchnode->expr->token->pos, "expected integer or enum type for switch expression"); return Check_Error; @@ -273,6 +273,11 @@ CheckStatus check_switch(AstSwitch* switchnode) { bh_arr_each(AstTyped *, value, sc->values) { CHECK(expression, value); + // :UnaryFieldAccessIsGross + if ((*value)->kind == Ast_Kind_Unary_Field_Access) { + type_check_or_auto_cast(value, resolved_expr_type); + } + if ((*value)->kind == Ast_Kind_Range_Literal) { AstRangeLiteral* rl = (AstRangeLiteral *) (*value); resolve_expression_type(rl->low); @@ -659,6 +664,19 @@ CheckStatus check_binop_assignment(AstBinaryOp* binop, b32 assignment_is_ok) { CheckStatus check_binaryop_compare(AstBinaryOp** pbinop) { AstBinaryOp* binop = *pbinop; + // :UnaryFieldAccessIsGross + if (binop->left->kind == Ast_Kind_Unary_Field_Access || binop->right->kind == Ast_Kind_Unary_Field_Access) { + if (type_check_or_auto_cast(&binop->left, binop->right->type)); + else if (type_check_or_auto_cast(&binop->right, binop->left->type)); + else { + report_bad_binaryop(binop); + return Check_Error; + } + + binop->type = &basic_types[Basic_Kind_Bool]; + return Check_Success; + } + if ( type_is_structlike_strict(binop->left->type) || type_is_structlike_strict(binop->right->type)) { report_bad_binaryop(binop); @@ -673,7 +691,6 @@ CheckStatus check_binaryop_compare(AstBinaryOp** pbinop) { if (ltype->kind == Type_Kind_Pointer) ltype = &basic_types[Basic_Kind_Rawptr]; if (rtype->kind == Type_Kind_Pointer) rtype = &basic_types[Basic_Kind_Rawptr]; - if (!types_are_compatible(ltype, rtype)) { b32 left_ac = node_is_auto_cast((AstNode *) binop->left); b32 right_ac = node_is_auto_cast((AstNode *) binop->right); @@ -1419,6 +1436,7 @@ CheckStatus check_expression(AstTyped** pexpr) { case Ast_Kind_Polymorphic_Proc: break; case Ast_Kind_Package: break; case Ast_Kind_Error: break; + case Ast_Kind_Unary_Field_Access: break; // NOTE: The only way to have an Intrinsic_Call node is to have gone through the // checking of a call node at least once. diff --git a/src/onyxparser.c b/src/onyxparser.c index f2325b8e..475edfe9 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -5,7 +5,6 @@ // Things that need to be cleaned up in the parser: // - control block local variables should be more extensible and reuse more code -// - package name parsing #include "onyxlex.h" #include "onyxerrors.h" @@ -42,6 +41,7 @@ static AstNumLit* parse_int_literal(OnyxParser* parser); 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 b32 parse_possible_unary_field_access(OnyxParser* parser, AstTyped** ret); static void parse_arguments(OnyxParser* parser, TokenType end_token, Arguments* args); static AstTyped* parse_factor(OnyxParser* parser); static AstTyped* parse_compound_assignment(OnyxParser* parser, AstTyped* lhs); @@ -267,6 +267,17 @@ static b32 parse_possible_array_literal(OnyxParser* parser, AstTyped* left, AstT return 1; } +static b32 parse_possible_unary_field_access(OnyxParser* parser, AstTyped** ret) { + if (!next_tokens_are(parser, 2, '.', Token_Type_Symbol)) return 0; + + AstUnaryFieldAccess* ufl = make_node(AstUnaryFieldAccess, Ast_Kind_Unary_Field_Access); + expect_token(parser, '.'); + ufl->token = expect_token(parser, Token_Type_Symbol); + + *ret = (AstTyped *) ufl; + return 1; +} + static void parse_arguments(OnyxParser* parser, TokenType end_token, Arguments* args) { while (!consume_token_if_next(parser, end_token)) { if (parser->hit_unexpected_token) return; @@ -355,6 +366,7 @@ static AstTyped* parse_factor(OnyxParser* parser) { case '.': { if (parse_possible_struct_literal(parser, NULL, &retval)) return retval; if (parse_possible_array_literal(parser, NULL, &retval)) return retval; + if (parse_possible_unary_field_access(parser, &retval)) return retval; goto no_match; }