added 'Any' type and any typed varargs
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 26 Jun 2021 03:08:57 +0000 (22:08 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 26 Jun 2021 03:08:57 +0000 (22:08 -0500)
bin/onyx
core/builtin.onyx
include/onyxastnodes.h
src/onyxbuiltins.c
src/onyxchecker.c
src/onyxwasm.c

index f7c894b32b61703c45e0c236eafec35fa17a0064..04e726d99cf7f3e066a353513b94853ac614c8f0 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index f43a1bb7cee41e0335a07844e2b6fff9c55efd2d..977d37c0f1e1d03138b213fc59fe2a2964fdef54 100644 (file)
@@ -180,3 +180,10 @@ CallSite :: struct {
     line   : u32;
     column : u32;
 }
+
+
+
+Any :: struct {
+    data: rawptr;
+    type: type_expr;
+}
index fb6c3943294b2e325fc5cbb2950f30d9214e23c1..e6fbfed6fed35a900e402e2bcebb797726b9a3a1 100644 (file)
@@ -467,6 +467,7 @@ typedef enum ParamPassType {
 typedef enum VarArgKind {
     VA_Kind_Not_VA,
     VA_Kind_Typed,
+    VA_Kind_Any,
     VA_Kind_Untyped,
 } VarArgKind;
 
@@ -1204,6 +1205,7 @@ extern AstTyped *builtin_context_variable;
 extern AstType  *builtin_allocator_type;
 extern AstType  *builtin_iterator_type;
 extern AstType  *builtin_callsite_type;
+extern AstType  *builtin_any_type;
 extern AstTyped *type_table_node;
 
 typedef struct BuiltinSymbol {
index 85bdd5d7cf5b3a648c13c6bacc05c0973cbc905c..65fe57addbb55431a33b778fa3cd773d76f51b44 100644 (file)
@@ -47,6 +47,7 @@ AstTyped *builtin_context_variable;
 AstType  *builtin_allocator_type;
 AstType  *builtin_iterator_type;
 AstType  *builtin_callsite_type;
+AstType  *builtin_any_type;
 
 AstTyped *type_table_node = NULL;
 
@@ -391,6 +392,12 @@ void initialize_builtins(bh_allocator a) {
         return;
     }
 
+    builtin_any_type = (AstType *) symbol_raw_resolve(p->scope, "Any");
+    if (builtin_any_type == NULL) {
+        onyx_report_error((OnyxFilePos) { 0 }, "'Any' struct not found in builtin package.");
+        return;
+    }
+
     p = package_lookup("builtin.type_info");
     if (p != NULL) {
         type_table_node = (AstTyped *) symbol_raw_resolve(p->scope, "type_table");
index bb46103befeac2da7f261ac373f72d8b371d69be..b01fcbda9dae6256c042a2773a8b3b564d106c6b 100644 (file)
@@ -555,6 +555,9 @@ CheckStatus check_call(AstCall* call) {
     Type* variadic_type = NULL;
     AstParam* variadic_param = NULL;
 
+    // SPEED CLEANUP: Caching the any type here.
+    Type* any_type = type_build_from_ast(context.ast_alloc, builtin_any_type);
+
     ArgState arg_state = AS_Expecting_Exact;
     u32 arg_pos = 0;
     while (1) {
@@ -592,9 +595,18 @@ CheckStatus check_call(AstCall* call) {
             }
 
             case AS_Expecting_Typed_VA: {
+                if (arg_pos >= (u32) bh_arr_length(arg_arr)) goto type_checking_done;
+
+                if (variadic_type->id == any_type->id) {
+                    call->va_kind = VA_Kind_Any;
+
+                    resolve_expression_type(arg_arr[arg_pos]->value);
+                    arg_arr[arg_pos]->va_kind = VA_Kind_Any; 
+                    break;
+                }
+
                 call->va_kind = VA_Kind_Typed;
 
-                if (arg_pos >= (u32) bh_arr_length(arg_arr)) goto type_checking_done;
                 if (!type_check_or_auto_cast(&arg_arr[arg_pos]->value, variadic_type)) {
                     onyx_report_error(arg_arr[arg_pos]->token->pos,
                             "The procedure '%s' expects a value of type '%s' for the variadic parameter, '%b', got '%s'.",
index a8823798637d089340b15c3df861c881fd584ebd..6ea30958c39efbf022fa1d373306720dec9d72f4 100644 (file)
@@ -1391,6 +1391,13 @@ EMIT_FUNC(call, AstCall* call) {
     u32 vararg_count  = 0;
     i32 vararg_offset = -1;
 
+    u32* vararg_any_offsets=NULL;
+    u32* vararg_any_types=NULL;
+    if (call->va_kind == VA_Kind_Any) {
+        vararg_any_offsets = bh_alloc_array(global_scratch_allocator, u32, bh_arr_length(call->args.values));
+        vararg_any_types   = bh_alloc_array(global_scratch_allocator, u32, bh_arr_length(call->args.values));
+    }
+
     bh_arr_each(AstTyped *, parg, call->args.values) {
         AstArgument* arg = (AstArgument *) *parg;
         if (arg->is_baked) continue;
@@ -1425,11 +1432,38 @@ EMIT_FUNC(call, AstCall* call) {
                 WI(WI_PTR_ADD);
             }
 
+            if (arg->va_kind == VA_Kind_Any) {
+                vararg_any_offsets[vararg_count - 1] = reserve_size;
+                vararg_any_types[vararg_count - 1] = arg->value->type->id;
+            }
+
             reserve_size += type_size_of(arg->value->type);
         }
     }
 
     switch (call->va_kind) {
+        case VA_Kind_Any: {
+            vararg_offset = reserve_size;
+
+            i32 any_size = type_size_of(type_build_from_ast(context.ast_alloc, builtin_any_type));
+
+            fori (i, 0, vararg_count) {
+                WIL(WI_LOCAL_GET, stack_top_store_local);
+                WIL(WI_LOCAL_GET, stack_top_store_local);
+                WID(WI_PTR_CONST, vararg_any_offsets[i]);
+                WI(WI_PTR_ADD);
+                emit_store_instruction(mod, &code, &basic_types[Basic_Kind_Rawptr], vararg_offset + i * any_size);
+
+                WIL(WI_LOCAL_GET, stack_top_store_local);
+                WID(WI_I32_CONST, vararg_any_types[i]);
+                emit_store_instruction(mod, &code, &basic_types[Basic_Kind_Type_Index], vararg_offset + i * any_size + 8);
+
+                reserve_size += any_size;
+            }
+            
+            // fallthrough
+        }
+
         case VA_Kind_Typed: {
             WIL(WI_LOCAL_GET, stack_top_store_local);
             if (vararg_offset > 0) {