made method call syntax more useful
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 5 Feb 2021 19:44:09 +0000 (13:44 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 5 Feb 2021 19:44:09 +0000 (13:44 -0600)
bin/onyx
core/math.onyx
include/onyxutils.h
onyx.exe
src/onyxchecker.c
src/onyxsymres.c
src/onyxutils.c

index 54b3bfd9b9cc7fa6687f00a274a8d38ea29372b0..a2d9e6ea7861fcb96e56088fac3680dab0b9c45d 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 08a5d3c7bfdd1d6bfc1bd71191982605b98e2c32..ff7ab779ea002148fc96a100fc73cd69c37bed6b 100644 (file)
@@ -139,6 +139,8 @@ atanh :: (t: $T) -> T {
 //      ln(x) = ln(2^n * v) = n * ln(2) + ln(v),   v is in [1, 2]
 //
 
+// FIX: This definition is very wrong. It casts E to be whatever the type of the argument is,
+// which if it is an integer, will be 2! This should always return a floating point number!
 exp :: (p: $T) -> T do return pow(base = cast(T) E, p = p);
 
 pow :: proc {
@@ -224,10 +226,10 @@ log :: (a: $T, base: $R) -> T {
 // operation first, and then default to a polymoprhic function that works on any type.
 // The clunky part about these at the moment is that, if you wanted to pass 'max' to
 // a procedure, you would have to pass 'max_poly' instead, because overloaded functions
-// are not resolved when used by value, i.e. foo : (f32) -> f32 = math.max; Even if they
-// would be however, the fact that these overloads are intrinsic means they cannot be
-// reference from the element section and therefore cannot be passed around or used as
-// values.
+// are not resolved when used by value, i.e. foo : (f32, f32) -> f32 = math.max; Even if
+// they would be however, the fact that these overloads are intrinsic means they cannot
+// be reference from the element section and therefore cannot be passed around or used
+// as values.
 max :: proc { wasm.max_f32, wasm.max_f64, max_poly }
 max_poly :: (a: $T, b: T) -> T {
     if a >= b do return a;
index 312ed66a4056978566aa411982349132091fe34c..90963f3fd19271dadb77965ac99cae4444572480 100644 (file)
@@ -20,6 +20,7 @@ void symbol_builtin_introduce(Scope* scope, char* sym, AstNode *node);
 void symbol_subpackage_introduce(Scope* scope, OnyxToken* sym, AstPackage *node);
 AstNode* symbol_raw_resolve(Scope* start_scope, char* sym);
 AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn);
+AstNode* try_symbol_raw_resolve_from_node(AstNode* node, char* symbol);
 AstNode* try_symbol_resolve_from_node(AstNode* node, OnyxToken* token);
 
 u32 char_to_base16_value(char x);
index 509874eeacfd103b65f662878ac20b4433e909c9..09b90cbc43282c55b2662569d476589f7a03e7eb 100644 (file)
Binary files a/onyx.exe and b/onyx.exe differ
index df291d41ae106dd39b0e59e61e87a73b4f0d9232..25bd07cf4a131f1776f88026245dc3bbc7c4c8ca 100644 (file)
@@ -17,8 +17,8 @@ typedef enum CheckStatus {
 } CheckStatus;
 
 CheckStatus check_block(AstBlock* block);
-CheckStatus check_statement_chain(AstNode* start);
-CheckStatus check_statement(AstNode* stmt);
+CheckStatus check_statement_chain(AstNode** start);
+CheckStatus check_statement(AstNode** pstmt);
 CheckStatus check_return(AstReturn* retnode);
 CheckStatus check_if(AstIfWhile* ifnode);
 CheckStatus check_while(AstIfWhile* whilenode);
@@ -36,6 +36,7 @@ CheckStatus check_address_of(AstAddressOf* aof);
 CheckStatus check_dereference(AstDereference* deref);
 CheckStatus check_array_access(AstArrayAccess* expr);
 CheckStatus check_field_access(AstFieldAccess** pfield);
+CheckStatus check_method_call(AstBinaryOp** mcall);
 CheckStatus check_size_of(AstSizeOf* so);
 CheckStatus check_align_of(AstAlignOf* ao);
 CheckStatus check_global(AstGlobal* global);
@@ -115,7 +116,7 @@ CheckStatus check_return(AstReturn* retnode) {
 }
 
 CheckStatus check_if(AstIfWhile* ifnode) {
-    if (ifnode->assignment != NULL) CHECK(statement, (AstNode *ifnode->assignment);
+    if (ifnode->assignment != NULL) CHECK(statement, (AstNode **) &ifnode->assignment);
 
     CHECK(expression, &ifnode->cond);
 
@@ -124,14 +125,14 @@ CheckStatus check_if(AstIfWhile* ifnode) {
         return Check_Error;
     }
 
-    if (ifnode->true_stmt)  CHECK(statement, (AstNode *ifnode->true_stmt);
-    if (ifnode->false_stmt) CHECK(statement, (AstNode *ifnode->false_stmt);
+    if (ifnode->true_stmt)  CHECK(statement, (AstNode **) &ifnode->true_stmt);
+    if (ifnode->false_stmt) CHECK(statement, (AstNode **) &ifnode->false_stmt);
 
     return Check_Success;
 }
 
 CheckStatus check_while(AstIfWhile* whilenode) {
-    if (whilenode->assignment != NULL) CHECK(statement, (AstNode *whilenode->assignment);
+    if (whilenode->assignment != NULL) CHECK(statement, (AstNode **) &whilenode->assignment);
 
     CHECK(expression, &whilenode->cond);
 
@@ -140,8 +141,8 @@ CheckStatus check_while(AstIfWhile* whilenode) {
         return Check_Error;
     }
 
-    if (whilenode->true_stmt)  CHECK(statement, (AstNode *whilenode->true_stmt);
-    if (whilenode->false_stmt) CHECK(statement, (AstNode *whilenode->false_stmt);
+    if (whilenode->true_stmt)  CHECK(statement, (AstNode **) &whilenode->true_stmt);
+    if (whilenode->false_stmt) CHECK(statement, (AstNode **) &whilenode->false_stmt);
 
     return Check_Success;
 }
@@ -240,7 +241,7 @@ static b32 add_case_to_switch_statement(AstSwitch* switchnode, u64 case_value, A
 }
 
 CheckStatus check_switch(AstSwitch* switchnode) {
-    if (switchnode->assignment != NULL) CHECK(statement, (AstNode *switchnode->assignment);
+    if (switchnode->assignment != NULL) CHECK(statement, (AstNode **) &switchnode->assignment);
 
     CHECK(expression, &switchnode->expr);
     resolve_expression_type(switchnode->expr);
@@ -1255,11 +1256,9 @@ CheckStatus check_array_access(AstArrayAccess* aa) {
             || aa->addr->type->kind == Type_Kind_DynArray
             || aa->addr->type->kind == Type_Kind_VarArgs) {
         // If we are accessing on a slice or a dynamic array, implicitly add a field access for the data member
-
         StructMember smem;
         type_lookup_member(aa->addr->type, "data", &smem);
 
-
         AstFieldAccess* fa = make_field_access(context.ast_alloc, aa->addr, "data");
         fa->type   = smem.type;
         fa->offset = smem.offset;
@@ -1314,23 +1313,18 @@ CheckStatus check_field_access(AstFieldAccess** pfield) {
     }
 
     if (!type_lookup_member(field->expr->type, field->field, &smem)) {
-        AstStructType* struct_node = (AstStructType *) field->expr->type->ast_type;
-        assert(struct_node);
-        assert(struct_node->kind == Ast_Kind_Struct_Type);
-        
-        AstNode* n = symbol_raw_resolve(struct_node->scope, field->field);
+        AstType* type_node = field->expr->type->ast_type;
+        AstNode* n = try_symbol_raw_resolve_from_node((AstNode *) type_node, field->field);
         if (n) {
             *pfield = (AstFieldAccess *) n;
             return Check_Success;
-            
-        } else {
-            onyx_report_error(field->token->pos,
-                "Field '%s' does not exists on '%s'.",
-                field->field,
-                node_get_type_name(field->expr));
-            
-            return Check_Error;   
         }
+
+        onyx_report_error(field->token->pos,
+            "Field '%s' does not exists on '%s'.",
+            field->field,
+            node_get_type_name(field->expr));
+        return Check_Error;   
     }
 
     field->offset = smem.offset;
@@ -1340,6 +1334,33 @@ CheckStatus check_field_access(AstFieldAccess** pfield) {
     return Check_Success;
 }
 
+CheckStatus check_method_call(AstBinaryOp** mcall) {
+    CHECK(expression, &(*mcall)->left);
+
+    AstTyped* implicit_argument = (*mcall)->left;
+    
+    // Implicitly take the address of the value if it is not already a pointer type.
+    // This could be weird to think about semantically so some testing with real code
+    // would be good.                                      - brendanfh 2020/02/05
+    if (implicit_argument->type->kind != Type_Kind_Pointer)
+        implicit_argument = (AstTyped *) make_address_of(context.ast_alloc, implicit_argument);
+    
+    implicit_argument = (AstTyped *) make_argument(context.ast_alloc, implicit_argument);
+
+    // Symbol resolution should have ensured that this is call node.
+    AstCall* call_node = (AstCall *) (*mcall)->right;
+    assert(call_node->kind == Ast_Kind_Call);
+
+    bh_arr_insertn(call_node->args.values, 0, 1);
+    call_node->args.values[0] = implicit_argument;
+
+    CHECK(call, call_node);
+    call_node->next = (*mcall)->next;
+
+    *mcall = (AstBinaryOp *) call_node;
+    return Check_Success;
+}
+
 CheckStatus check_size_of(AstSizeOf* so) {
     fill_in_array_count(so->so_ast_type);
 
@@ -1410,6 +1431,7 @@ CheckStatus check_expression(AstTyped** pexpr) {
         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_Method_Call:   retval = check_method_call((AstBinaryOp **) 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;
@@ -1495,7 +1517,9 @@ CheckStatus check_global(AstGlobal* global) {
     return Check_Success;
 }
 
-CheckStatus check_statement(AstNode* stmt) {
+CheckStatus check_statement(AstNode** pstmt) {
+    AstNode* stmt = *pstmt;
+
     switch (stmt->kind) {
         case Ast_Kind_Jump:       return Check_Success;
 
@@ -1505,29 +1529,29 @@ CheckStatus check_statement(AstNode* stmt) {
         case Ast_Kind_For:        return check_for((AstFor *) stmt);
         case Ast_Kind_Switch:     return check_switch((AstSwitch *) stmt);
         case Ast_Kind_Block:      return check_block((AstBlock *) stmt);
-        case Ast_Kind_Defer:      return check_statement(((AstDefer *) stmt)->stmt);
+        case Ast_Kind_Defer:      return check_statement(&((AstDefer *) stmt)->stmt);
 
         case Ast_Kind_Binary_Op:
             stmt->flags |= Ast_Flag_Expr_Ignored;
-            return check_binaryop((AstBinaryOp **) &stmt, 1);
+            return check_binaryop((AstBinaryOp **) pstmt, 1);
 
         default:
             stmt->flags |= Ast_Flag_Expr_Ignored;
-            return check_expression((AstTyped **) &stmt);
+            return check_expression((AstTyped **) pstmt);
     }
 }
 
-CheckStatus check_statement_chain(AstNode* start) {
-    while (start) {
+CheckStatus check_statement_chain(AstNode** start) {
+    while (*start) {
         CHECK(statement, start);
-        start = start->next;
+        start = &(*start)->next;
     }
 
     return Check_Success;
 }
 
 CheckStatus check_block(AstBlock* block) {
-    CHECK(statement_chain, block->body);
+    CHECK(statement_chain, &block->body);
 
     bh_arr_each(AstTyped *, value, block->allocate_exprs) {
         fill_in_type(*value);
index 126135cc1d3fa0815c1ab46e42cb8b65e1bd7095..dd3053ac92ee6b4cc893768440e11ae9a74bdb29 100644 (file)
@@ -315,7 +315,6 @@ static void symres_pipe(AstBinaryOp** pipe) {
     *pipe = (AstBinaryOp *) call_node;
 }
 
-// nocheckin
 // CLEANUP: This is an experimental feature and might be removed in the future.
 // I noticed a common pattern when writing in Onyx is something that looks like this:
 //
@@ -336,20 +335,10 @@ static void symres_method_call(AstBinaryOp** mcall) {
     symres_expression(&(*mcall)->left);
     if ((*mcall)->left == NULL) return;
 
-    bh_arr_insertn(call_node->args.values, 0, 1);
-
-    AstTyped* implicit_pointer = (AstTyped *) make_address_of(context.ast_alloc, (*mcall)->left);
-    call_node->args.values[0] = (AstTyped *) make_argument(context.ast_alloc, implicit_pointer);
-    
     AstFieldAccess* implicit_field_access = make_field_access(context.ast_alloc, (*mcall)->left, NULL);
     implicit_field_access->token = call_node->callee->token;
     call_node->callee = (AstTyped *) implicit_field_access;
     symres_expression((AstTyped **) &call_node);
-
-    call_node->next = (*mcall)->next;
-
-    // NOTE: Not a BinaryOp node
-    *mcall = (AstBinaryOp *) call_node;
 }
 
 static void symres_unaryop(AstUnaryOp** unaryop) {
index 9c6bd506308393e80f301ed796869011f43739ed..b1d99c21da39c2ae76fa2d82682d17f2603bca46 100644 (file)
@@ -140,13 +140,20 @@ AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn) {
     return res;
 }
 
-AstNode* try_symbol_resolve_from_node(AstNode* node, OnyxToken* token) {
+AstNode* try_symbol_raw_resolve_from_node(AstNode* node, char* symbol) {
+    // CLEANUP: So many checks for null....
+    if (!node) return NULL;
+
     if (node->kind == Ast_Kind_Type_Raw_Alias)
         node = (AstNode *) ((AstTypeRawAlias *) node)->to->ast_type;
 
+    if (!node) return NULL;
+
     if (node->kind == Ast_Kind_Type_Alias)
         node = (AstNode *) ((AstTypeAlias *) node)->to;
 
+    if (!node) return NULL;
+
     // A single pointer can be dereferenced to lookup symbols in struct.
     if (node->kind == Ast_Kind_Pointer_Type)
         node = (AstNode *) ((AstPointerType *) node)->elem;
@@ -156,28 +163,36 @@ AstNode* try_symbol_resolve_from_node(AstNode* node, OnyxToken* token) {
     switch (node->kind) {
         case Ast_Kind_Package: {
             AstPackage* package = (AstPackage *) node;
-            return symbol_resolve(package->package->scope, token);
+            return symbol_raw_resolve(package->package->scope, symbol);
         } 
 
         case Ast_Kind_Enum_Type: {
             AstEnumType* etype = (AstEnumType *) node;
-            return symbol_resolve(etype->scope, token);
+            return symbol_raw_resolve(etype->scope, symbol);
         }
 
         case Ast_Kind_Struct_Type: {
             AstStructType* stype = (AstStructType *) node;
-            return symbol_resolve(stype->scope, token);
+            return symbol_raw_resolve(stype->scope, symbol);
         }
 
         case Ast_Kind_Poly_Struct_Type: {
             AstStructType* stype = ((AstPolyStructType *) node)->base_struct;
-            return symbol_resolve(stype->scope, token);
+            return symbol_raw_resolve(stype->scope, symbol);
         }
     }
 
     return NULL;
 }
 
+AstNode* try_symbol_resolve_from_node(AstNode* node, OnyxToken* token) {
+    token_toggle_end(token);
+    AstNode* result = try_symbol_raw_resolve_from_node(node, token->text);
+    token_toggle_end(token);
+
+    return result;
+}
+
 void scope_clear(Scope* scope) {
     bh_table_clear(scope->symbols);
 }