Added '__heap_start' builtin; more cases for casting
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 20 Jul 2020 00:39:56 +0000 (19:39 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 20 Jul 2020 00:39:56 +0000 (19:39 -0500)
include/onyxastnodes.h
onyx
progs/arrays.onyx
progs/print_funcs.onyx
src/onyxlex.c
src/onyxparser.c
src/onyxsymres.c
src/onyxwasm.c

index 25791afb9d39b687a03315c59b23279b7182a453..c2fc7c676f6a97e0a4caa9444099daadc261f87c 100644 (file)
@@ -346,6 +346,16 @@ extern AstBasicType basic_type_f32;
 extern AstBasicType basic_type_f64;
 extern AstBasicType basic_type_rawptr;
 
+extern AstNumLit builtin_heap_start;
+
+typedef struct BuiltinSymbol {
+    char*    sym;
+    AstNode* node;
+} BuiltinSymbol;
+
+extern const BuiltinSymbol builtin_symbols[];
+
+
 
 // NOTE: Useful inlined functions
 static inline b32 is_lval(AstNode* node) {
diff --git a/onyx b/onyx
index 6bf00b5ab2f28ff59e7bd418de71621604a85ec6..03babad22da9c27cb3fd3ccf2e1e3a45c95bc39e 100755 (executable)
Binary files a/onyx and b/onyx differ
index eab2ac0319d426456d8e9a5a74b70d2f0cc07b89..a7ec6d2daefe8bde8f472df9686f3afbd4eb0b44 100644 (file)
@@ -21,21 +21,15 @@ min :: proc #overloaded {
 
 // NOTE: in-place insertion sort
 sort :: proc (src: ^i32, len: i32) {
-    i := 0;
-    while i < len {
+    for i: 0, len {
         smallest := i;
 
-        j := i + 1;
-        while j < len {
+        for j: i + 1, len
             if src[j] < src[smallest] smallest = j;
-            j += 1;
-        }
 
         tmp :: src[smallest];
         src[smallest] = src[i];
         src[i] = tmp;
-
-        i += 1;
     }
 }
 
@@ -44,8 +38,8 @@ for_test :: proc {
     for i: 0, 10 print(i);
 }
 
-str_test :: proc #export "main" {
-    hello_str :: "Hello World!";
+str_test :: proc #export {
+    hello_str :: "Hello World! 123";
 
     // Address of and dereference cancel each other out
     print(^*hello_str);
@@ -58,17 +52,13 @@ str_test :: proc #export "main" {
 }
 
 // Don't need to bind this function to a symbol
-proc #export "main2" {
-    print(min(10.0, 12.0));
+proc #export "main" {
+    print(__heap_start as i32);
 
-    global_arr = 128 as ^i32;
+    global_arr = __heap_start as ^i32;
     len :: 10;
 
-    i := 0;
-    while i < len {
-        global_arr[i] = (len - i) * 10;
-        i += 1;
-    }
+    for i: 0, len global_arr[i] = (len - i) * 10;
 
     print(global_arr, len);
 
@@ -76,6 +66,4 @@ proc #export "main2" {
 
     print(1234567);
     print(global_arr, len);
-
-    str_test();
 }
index e232cb25c22cd490eed7ae8fccb86cbd434e2589..2cd75ddcad2598598c14c3236dae9d35a276ee62 100644 (file)
@@ -5,35 +5,19 @@ print_i64  :: proc #foreign "host" "print" (value: i64) ---
 print_f64  :: proc #foreign "host" "print" (value: f64) ---
 
 print_i32arr :: proc (arr: ^i32, len: i32) {
-    i := 0;
-    while i < len {
-        print(arr[i]);
-        i += 1;
-    }
+    for i: 0, len print(arr[i]);
 }
 
 print_i64arr :: proc (arr: ^i64, len: i32) {
-    i := 0;
-    while i < len {
-        print(arr[i]);
-        i += 1;
-    }
+    for i: 0, len print(arr[i]);
 }
 
 print_f32arr :: proc (arr: ^f32, len: i32) {
-    i := 0;
-    while i < len {
-        print(arr[i]);
-        i += 1;
-    }
+    for i: 0, len print(arr[i]);
 }
 
 print_f64arr :: proc (arr: ^f64, len: i32) {
-    i := 0;
-    while i < len {
-        print(arr[i]);
-        i += 1;
-    }
+    for i: 0, len print(arr[i]);
 }
 
 // NOTE: print null-terminated string
index afc0b6c5b36781777f8509a6fbdfa83a4785434c..5b2acd127bd31e13414b54aed9e1d3eafd95a44f 100644 (file)
@@ -19,6 +19,7 @@ static const char* token_type_names[] = {
     "proc",
     "as",
     "while",
+    "for",
     "break",
     "continue",
 
@@ -157,7 +158,7 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) {
     LITERAL_TOKEN("%=",         0, Token_Type_Percent_Equal);
 
     // Symbols
-    if (char_is_alpha(*tk.text)) {
+    if (char_is_alpha(*tk.text) || *tokenizer->curr == '_') {
         u64 len = 0;
         while (char_is_alphanum(*tokenizer->curr) || charset_contains("_$", *tokenizer->curr)) {
             len++;
index 097af9cbadb916aef4ad09e35f5f3514a5bc5b83..a630e36b3ba7a3cddc6cd6b6ca75ce41c353c5c1 100644 (file)
@@ -8,20 +8,6 @@
 
 static AstNode error_node = { Ast_Kind_Error, 0, NULL, NULL };
 
-AstBasicType basic_type_void   = { { Ast_Kind_Basic_Type, 0, "void"   }, &basic_types[Basic_Kind_Void]  };
-AstBasicType basic_type_bool   = { { Ast_Kind_Basic_Type, 0, "bool"   }, &basic_types[Basic_Kind_Bool]  };
-AstBasicType basic_type_i8     = { { Ast_Kind_Basic_Type, 0, "i8"     }, &basic_types[Basic_Kind_I8]    };
-AstBasicType basic_type_u8     = { { Ast_Kind_Basic_Type, 0, "u8"     }, &basic_types[Basic_Kind_U8]    };
-AstBasicType basic_type_i16    = { { Ast_Kind_Basic_Type, 0, "i16"    }, &basic_types[Basic_Kind_I16]   };
-AstBasicType basic_type_u16    = { { Ast_Kind_Basic_Type, 0, "u16"    }, &basic_types[Basic_Kind_U16]   };
-AstBasicType basic_type_i32    = { { Ast_Kind_Basic_Type, 0, "i32"    }, &basic_types[Basic_Kind_I32]   };
-AstBasicType basic_type_u32    = { { Ast_Kind_Basic_Type, 0, "u32"    }, &basic_types[Basic_Kind_U32]   };
-AstBasicType basic_type_i64    = { { Ast_Kind_Basic_Type, 0, "i64"    }, &basic_types[Basic_Kind_I64]   };
-AstBasicType basic_type_u64    = { { Ast_Kind_Basic_Type, 0, "u64"    }, &basic_types[Basic_Kind_U64]   };
-AstBasicType basic_type_f32    = { { Ast_Kind_Basic_Type, 0, "f32"    }, &basic_types[Basic_Kind_F32]   };
-AstBasicType basic_type_f64    = { { Ast_Kind_Basic_Type, 0, "f64"    }, &basic_types[Basic_Kind_F64]   };
-AstBasicType basic_type_rawptr = { { Ast_Kind_Basic_Type, 0, "rawptr" }, &basic_types[Basic_Kind_Rawptr] };
-
 // NOTE: Forward declarations
 static void consume_token(OnyxParser* parser);
 static void unconsume_token(OnyxParser* parser);
index f504daa3d6b450103cfac7efb109eeada849230c..ca3c274f51b1040f524ec46b531b497f54161d64 100644 (file)
@@ -1,9 +1,45 @@
 #define BH_DEBUG
 #include "onyxsempass.h"
 
+AstBasicType basic_type_void   = { { Ast_Kind_Basic_Type, 0, "void"   }, &basic_types[Basic_Kind_Void]  };
+AstBasicType basic_type_bool   = { { Ast_Kind_Basic_Type, 0, "bool"   }, &basic_types[Basic_Kind_Bool]  };
+AstBasicType basic_type_i8     = { { Ast_Kind_Basic_Type, 0, "i8"     }, &basic_types[Basic_Kind_I8]    };
+AstBasicType basic_type_u8     = { { Ast_Kind_Basic_Type, 0, "u8"     }, &basic_types[Basic_Kind_U8]    };
+AstBasicType basic_type_i16    = { { Ast_Kind_Basic_Type, 0, "i16"    }, &basic_types[Basic_Kind_I16]   };
+AstBasicType basic_type_u16    = { { Ast_Kind_Basic_Type, 0, "u16"    }, &basic_types[Basic_Kind_U16]   };
+AstBasicType basic_type_i32    = { { Ast_Kind_Basic_Type, 0, "i32"    }, &basic_types[Basic_Kind_I32]   };
+AstBasicType basic_type_u32    = { { Ast_Kind_Basic_Type, 0, "u32"    }, &basic_types[Basic_Kind_U32]   };
+AstBasicType basic_type_i64    = { { Ast_Kind_Basic_Type, 0, "i64"    }, &basic_types[Basic_Kind_I64]   };
+AstBasicType basic_type_u64    = { { Ast_Kind_Basic_Type, 0, "u64"    }, &basic_types[Basic_Kind_U64]   };
+AstBasicType basic_type_f32    = { { Ast_Kind_Basic_Type, 0, "f32"    }, &basic_types[Basic_Kind_F32]   };
+AstBasicType basic_type_f64    = { { Ast_Kind_Basic_Type, 0, "f64"    }, &basic_types[Basic_Kind_F64]   };
+AstBasicType basic_type_rawptr = { { Ast_Kind_Basic_Type, 0, "rawptr" }, &basic_types[Basic_Kind_Rawptr] };
+
+AstNumLit builtin_heap_start = { Ast_Kind_NumLit, 0, NULL, NULL, (AstType *) &basic_type_rawptr, NULL, 0 };
+
+const BuiltinSymbol builtin_symbols[] = {
+    { "void",       (AstNode *) &basic_type_void },
+    { "bool",       (AstNode *) &basic_type_bool },
+    { "i8",         (AstNode *) &basic_type_i8 },
+    { "u8",         (AstNode *) &basic_type_u8 },
+    { "i16",        (AstNode *) &basic_type_i16 },
+    { "u16",        (AstNode *) &basic_type_u16 },
+    { "i32",        (AstNode *) &basic_type_i32 },
+    { "u32",        (AstNode *) &basic_type_u32 },
+    { "i64",        (AstNode *) &basic_type_i64 },
+    { "u64",        (AstNode *) &basic_type_u64 },
+    { "f32",        (AstNode *) &basic_type_f32 },
+    { "f64",        (AstNode *) &basic_type_f64 },
+    { "rawptr",     (AstNode *) &basic_type_rawptr },
+
+    { "__heap_start", (AstNode *) &builtin_heap_start },
+
+    { NULL, NULL },
+};
+
 static b32  symbol_introduce(OnyxToken* tkn, AstNode* symbol);
+static void symbol_builtin_introduce(char* sym, AstNode *node);
 static AstNode* symbol_resolve(OnyxToken* tkn);
-static void symbol_basic_type_introduce(AstBasicType* basic_type);
 static void scope_enter(Scope* new_scope);
 static void scope_leave();
 
@@ -42,8 +78,8 @@ static b32 symbol_introduce(OnyxToken* tkn, AstNode* symbol) {
     return 1;
 }
 
-static void symbol_basic_type_introduce(AstBasicType* basic_type) {
-    bh_table_put(AstNode *, semstate.curr_scope->symbols, basic_type->name, (AstNode *) basic_type);
+static void symbol_builtin_introduce(char* sym, AstNode *node) {
+    bh_table_put(AstNode *, semstate.curr_scope->symbols, sym, node);
 }
 
 static AstNode* symbol_resolve(OnyxToken* tkn) {
@@ -316,19 +352,11 @@ void onyx_resolve_symbols(ProgramInfo* program) {
     scope_enter(semstate.global_scope);
 
     // NOTE: Add types to global scope
-    symbol_basic_type_introduce(&basic_type_void);
-    symbol_basic_type_introduce(&basic_type_bool);
-    symbol_basic_type_introduce(&basic_type_i8);
-    symbol_basic_type_introduce(&basic_type_u8);
-    symbol_basic_type_introduce(&basic_type_i16);
-    symbol_basic_type_introduce(&basic_type_u16);
-    symbol_basic_type_introduce(&basic_type_i32);
-    symbol_basic_type_introduce(&basic_type_u32);
-    symbol_basic_type_introduce(&basic_type_i64);
-    symbol_basic_type_introduce(&basic_type_u64);
-    symbol_basic_type_introduce(&basic_type_f32);
-    symbol_basic_type_introduce(&basic_type_f64);
-    symbol_basic_type_introduce(&basic_type_rawptr);
+    BuiltinSymbol* bsym = (BuiltinSymbol *) &builtin_symbols[0];
+    while (bsym->sym != NULL) {
+        symbol_builtin_introduce(bsym->sym, bsym->node);
+        bsym++;
+    }
 
     bh_arr_each(AstBinding *, binding, program->bindings)
         if (!symbol_introduce((*binding)->token, (*binding)->node)) return;
index 972db89f738e68d1d67a68bea3a871e09b39d1c2..7e949cc3aa520a103a4baace04abb3c81776e314 100644 (file)
@@ -212,6 +212,7 @@ static WasmType onyx_type_to_wasm_type(Type* type) {
             if (basic->size <= 4) return WASM_TYPE_INT32;
             if (basic->size == 8) return WASM_TYPE_INT64;
         }
+        if (basic->flags & Basic_Flag_Pointer) return WASM_TYPE_INT32;
         if (basic->flags & Basic_Flag_Float) {
             if (basic->size <= 4) return WASM_TYPE_FLOAT32;
             if (basic->size == 8) return WASM_TYPE_FLOAT64;
@@ -848,14 +849,17 @@ COMPILE_FUNC(expression, AstTyped* expr) {
     *pcode = code;
 }
 
-static const WasmInstructionType cast_map[][6] = {
-    //          I32                  U32                I64              U64                F32                F64
-    /* I32 */ { WI_NOP,            WI_NOP,            WI_I64_FROM_I32_S, WI_I64_FROM_I32_S, WI_F32_FROM_I32_S, WI_F64_FROM_I32_S },
-    /* U32 */ { WI_NOP,            WI_NOP,            WI_I64_FROM_I32_U, WI_I64_FROM_I32_U, WI_F32_FROM_I32_U, WI_F64_FROM_I32_U },
-    /* I64 */ { WI_I32_FROM_I64,   WI_I32_FROM_I64,   WI_NOP,            WI_NOP,            WI_F32_FROM_I64_S, WI_F64_FROM_I64_S },
-    /* U64 */ { WI_I32_FROM_I64,   WI_I32_FROM_I64,   WI_NOP,            WI_NOP,            WI_F32_FROM_I64_U, WI_F64_FROM_I64_U },
-    /* F32 */ { WI_I32_FROM_F32_S, WI_I32_FROM_F32_U, WI_I64_FROM_F32_S, WI_I64_FROM_F32_U, WI_NOP,            WI_F64_FROM_F32   },
-    /* F64 */ { WI_I32_FROM_F64_S, WI_I32_FROM_F64_U, WI_I64_FROM_F64_S, WI_I64_FROM_F64_U, WI_F32_FROM_F64,   WI_NOP,           },
+static const WasmInstructionType cast_map[][9] = {
+    //          I8              I16                 I32                 U32                I64                U64                F32                F64                PTR
+    /* I8  */ { WI_NOP,         WI_I32_EXTEND_8_S,  WI_I32_EXTEND_8_S,  WI_NOP,            WI_I64_FROM_I32_S, WI_I64_FROM_I32_S, WI_UNREACHABLE,    WI_UNREACHABLE,    WI_UNREACHABLE },
+    /* I16 */ { WI_NOP,         WI_NOP,             WI_I32_EXTEND_16_S, WI_NOP,            WI_I64_FROM_I32_U, WI_I64_FROM_I32_U, WI_F32_FROM_I32_U, WI_F64_FROM_I32_U, WI_UNREACHABLE },
+    /* I32 */ { WI_NOP,         WI_NOP,             WI_NOP,             WI_NOP,            WI_I64_FROM_I32_S, WI_I64_FROM_I32_S, WI_F32_FROM_I32_S, WI_F64_FROM_I32_S, WI_NOP },
+    /* U32 */ { WI_NOP,         WI_NOP,             WI_NOP,             WI_NOP,            WI_I64_FROM_I32_U, WI_I64_FROM_I32_U, WI_F32_FROM_I32_U, WI_F64_FROM_I32_U, WI_NOP },
+    /* I64 */ { WI_NOP,         WI_NOP,             WI_I32_FROM_I64,    WI_I32_FROM_I64,   WI_NOP,            WI_NOP,            WI_F32_FROM_I64_S, WI_F64_FROM_I64_S, WI_I32_FROM_I64 },
+    /* U64 */ { WI_NOP,         WI_NOP,             WI_I32_FROM_I64,    WI_I32_FROM_I64,   WI_NOP,            WI_NOP,            WI_F32_FROM_I64_U, WI_F64_FROM_I64_U, WI_I32_FROM_I64 },
+    /* F32 */ { WI_UNREACHABLE, WI_UNREACHABLE,     WI_I32_FROM_F32_S,  WI_I32_FROM_F32_U, WI_I64_FROM_F32_S, WI_I64_FROM_F32_U, WI_NOP,            WI_F64_FROM_F32,   WI_UNREACHABLE },
+    /* F64 */ { WI_UNREACHABLE, WI_UNREACHABLE,     WI_I32_FROM_F64_S,  WI_I32_FROM_F64_U, WI_I64_FROM_F64_S, WI_I64_FROM_F64_U, WI_F32_FROM_F64,   WI_NOP,            WI_UNREACHABLE },
+    /* PTR */ { WI_UNREACHABLE, WI_UNREACHABLE,     WI_NOP,             WI_NOP,            WI_I64_FROM_I32_U, WI_I64_FROM_I32_U, WI_UNREACHABLE,    WI_UNREACHABLE,    WI_NOP },
 };
 
 COMPILE_FUNC(cast, AstUnaryOp* cast) {
@@ -866,36 +870,57 @@ COMPILE_FUNC(cast, AstUnaryOp* cast) {
     Type* from = cast->expr->type;
     Type* to = cast->type;
 
-    i32 fromidx = 0, toidx = 0;
+    i32 fromidx = -1, toidx = -1;
     if (from->Basic.flags & Basic_Flag_Integer) {
         b32 unsign = (from->Basic.flags & Basic_Flag_Unsigned) != 0;
 
-        if (from->Basic.size == 4 && !unsign) fromidx = 0;
-        else if (from->Basic.size == 4 && unsign) fromidx = 1;
-        else if (from->Basic.size == 8 && !unsign) fromidx = 2;
-        else if (from->Basic.size == 8 && unsign) fromidx = 3;
+        if      (from->Basic.size == 1 && !unsign) fromidx = 0;
+        else if (from->Basic.size == 1 && unsign)  fromidx = -1;
+        else if (from->Basic.size == 2 && !unsign) fromidx = 1;
+        else if (from->Basic.size == 2 && unsign)  fromidx = -1;
+        else if (from->Basic.size == 4 && !unsign) fromidx = 2;
+        else if (from->Basic.size == 4 && unsign)  fromidx = 3;
+        else if (from->Basic.size == 8 && !unsign) fromidx = 4;
+        else if (from->Basic.size == 8 && unsign)  fromidx = 5;
     }
     else if (from->Basic.flags & Basic_Flag_Float) {
-        if (from->Basic.size == 4) fromidx = 4;
-        else if (from->Basic.size == 8) fromidx = 5;
+        if      (from->Basic.size == 4) fromidx = 6;
+        else if (from->Basic.size == 8) fromidx = 7;
+    }
+    else if (from->Basic.flags & Basic_Flag_Pointer) {
+        fromidx = 8;
     }
 
     if (to->Basic.flags & Basic_Flag_Integer) {
         b32 unsign = (to->Basic.flags & Basic_Flag_Unsigned) != 0;
 
-        if (to->Basic.size == 4 && !unsign) toidx = 0;
-        else if (to->Basic.size == 4 && unsign) toidx = 1;
-        else if (to->Basic.size == 8 && !unsign) toidx = 2;
-        else if (to->Basic.size == 8 && unsign) toidx = 3;
+        if      (to->Basic.size == 1 && !unsign) toidx = 0;
+        else if (to->Basic.size == 1 && unsign)  toidx = -1;
+        else if (to->Basic.size == 2 && !unsign) toidx = 1;
+        else if (to->Basic.size == 2 && unsign)  toidx = -1;
+        else if (to->Basic.size == 4 && !unsign) toidx = 2;
+        else if (to->Basic.size == 4 && unsign)  toidx = 3;
+        else if (to->Basic.size == 8 && !unsign) toidx = 4;
+        else if (to->Basic.size == 8 && unsign)  toidx = 5;
     }
     else if (to->Basic.flags & Basic_Flag_Float) {
-        if (to->Basic.size == 4) toidx = 4;
-        else if (to->Basic.size == 8) toidx = 5;
+        if      (to->Basic.size == 4) toidx = 6;
+        else if (to->Basic.size == 8) toidx = 7;
+    }
+    else if (to->Basic.flags & Basic_Flag_Pointer) {
+        toidx = 8;
     }
 
-    WasmInstructionType cast_op = cast_map[fromidx][toidx];
-    if (cast_op != WI_NOP) {
-        WI(cast_op);
+    if (fromidx != -1 && toidx != -1) {
+        WasmInstructionType cast_op = cast_map[fromidx][toidx];
+        if (cast_op == WI_UNREACHABLE) {
+            onyx_message_add(Msg_Type_Literal,
+                    cast->token->pos,
+                    "bad cast");
+        }
+        else if (cast_op != WI_NOP) {
+            WI(cast_op);
+        }
     }
 
     *pcode = code;
@@ -1216,8 +1241,11 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, ProgramInfo* program) {
         }
     }
 
-
-
+    // NOTE: Round up to the nearest multiple of 16
+    builtin_heap_start.value.i =
+        (module->next_datum_offset & 15)
+        ? ((module->next_datum_offset >> 4) + 1) << 4
+        : module->next_datum_offset;
 
     // NOTE: Then, compile everything
     bh_arr_each(Entity, entity, program->entities) {