added unary field access for enum/struct members
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 22 Apr 2021 17:44:36 +0000 (12:44 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 22 Apr 2021 17:44:36 +0000 (12:44 -0500)
bin/onyx
docs/bugs
include/onyxastnodes.h
modules/webgl2/webgl2.js
src/onyxastnodes.c
src/onyxchecker.c
src/onyxparser.c

index 51554867e6f646b313c53d36745aefa25ed65c80..4e721af441c0eef44e6ce9c636558c9ed5c5771a 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 172bc1edf29a1a5cfeb4f449e0438c8dfe504284..632a068fbd5dec1876f26f12d9d61dd7b98ab07b 100644 (file)
--- 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.
index 71de59dce5cf4866bd000664258898ab26506330..941f6a80bf2a18e53597ac320524e597c7ab548a 100644 (file)
@@ -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;
 
index 61d565a14c3c268cfb786eaefe08f620edf72268..bd5339936379059d152f471dea94bb1e7f0dce32 100644 (file)
@@ -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); },
index 08dad627242fda01c8d6f77dfa414f339379e58e..866f2620787a35a6831bd6cfe864b3873982d777 100644 (file)
@@ -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;
index 3a401869c819d7cbc2c51d15c67a7c8a485d6095..00b8159e19e4251a0ddeb7018d2a4e866ebc521a 100644 (file)
@@ -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.
index f2325b8e9f4a653dcc40c6cbec88d8a842edf6ba..475edfe924708a4762b73618b04335a610206bbe 100644 (file)
@@ -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;
         }