Started work on importing external functions
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 19 Jun 2020 03:09:00 +0000 (22:09 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 19 Jun 2020 03:09:00 +0000 (22:09 -0500)
docs/plan
include/onyxparser.h
onyx
progs/game.onyx [new file with mode: 0644]
progs/minimal.onyx
src/onyxparser.c
src/onyxutils.c
src/onyxwasm.c

index 66c9d3f8ffd208f0850fbb574c0d2ac015afd04f..21597ed3db66e2c25f5e5c9e40a56af54fd53f1d 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -55,6 +55,7 @@ HOW:
                [X] Curly braces are required for all bodies of blocks
                [X] Numeric literals are parsed
                [X] Numeric literals have the minimum type detected
+        [ ] Foreign imports (functions only)
                [ ] Comparison operators
                [ ] Proper boolean type
                [ ] Conditional branching works as expected
index 80690f2f71d5d0e79f0b7610f5e63b447144b298..b80e2cb97937aecd14e304bf70a2b4fbb0dd15e5 100644 (file)
@@ -13,6 +13,7 @@ typedef struct OnyxAstNodeScope OnyxAstNodeScope;
 typedef struct OnyxAstNodeBlock OnyxAstNodeBlock;
 typedef struct OnyxAstNodeParam OnyxAstNodeParam;
 typedef struct OnyxAstNodeFuncDef OnyxAstNodeFuncDef;
+typedef struct OnyxAstNodeForeign OnyxAstNodeForeign;
 typedef struct OnyxAstNodeCall OnyxAstNodeCall;
 
 typedef struct OnyxParser {
@@ -40,6 +41,7 @@ typedef enum OnyxAstNodeKind {
        ONYX_AST_NODE_KIND_PROGRAM,
 
        ONYX_AST_NODE_KIND_FUNCDEF,
+    ONYX_AST_NODE_KIND_FOREIGN,
        ONYX_AST_NODE_KIND_BLOCK,
        ONYX_AST_NODE_KIND_SCOPE,
        ONYX_AST_NODE_KIND_LOCAL,
@@ -173,6 +175,16 @@ struct OnyxAstNodeFuncDef {
        OnyxAstNodeParam *params;
 };
 
+struct OnyxAstNodeForeign {
+       OnyxAstNodeKind kind;
+       u32 flags;
+       OnyxToken *mod_token;
+       OnyxTypeInfo *type;
+       OnyxAstNode *next;
+    OnyxToken *name_token;
+       OnyxAstNode *import;
+};
+
 struct OnyxAstNodeCall {
        OnyxAstNodeKind kind;
        u32 flags;
@@ -205,6 +217,7 @@ union OnyxAstNode {
        OnyxAstNodeScope as_scope;
        OnyxAstNodeCall as_call;
     OnyxAstNodeNumLit as_numlit;
+    OnyxAstNodeForeign as_foreign;
 };
 
 const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind);
diff --git a/onyx b/onyx
index 944178d4425bfbc47110af7efa3e051240acdc11..e09523b81a2d60ab26149a45a80840c4abdf1129 100755 (executable)
Binary files a/onyx and b/onyx differ
diff --git a/progs/game.onyx b/progs/game.onyx
new file mode 100644 (file)
index 0000000..85ac24d
--- /dev/null
@@ -0,0 +1,16 @@
+
+gfx_draw_rect :: foreign "gfx" "draw_rect" proc (x i32, y i32, w i32, h i32) ---
+
+update :: proc ---
+
+draw :: proc {
+    draw_rect(0, 0, 100, 100);
+}
+
+export main :: proc {
+
+    while true {
+        update();
+        draw();
+    }
+}
index 8b153fc775d0ec5f7f76afdbe5bf6b036f797ed3..83b863d61f09ef291c785befe4d72c34e5d0319e 100644 (file)
@@ -1,4 +1,7 @@
-foo :: proc () -> i32 {
+
+print :: foreign "host" "print" proc (value i32) ---
+
+foo :: proc -> i32 {
        return 10 as i32;
 }
 
@@ -17,6 +20,7 @@ diff_square :: proc (a i32, b i32) -> i32 {
 export do_stuff :: proc -> i32 {
        res := diff_square((4 + 5) as i32, (2 + 3) as i32);
        res = res + foo();
+    // res should be 66
     return res;
 }
 
index 0c5d5dae03f9c9eb95f4a11219f1b7894d3748cf..b0ad386179f89208d110037fb9b8be81ee2fbaab 100644 (file)
@@ -7,6 +7,7 @@ static const char* ast_node_names[] = {
        "PROGRAM",
 
        "FUNCDEF",
+    "FOREIGN",
        "BLOCK",
        "SCOPE",
        "LOCAL",
@@ -682,6 +683,32 @@ static OnyxAstNodeFuncDef* parse_function_definition(OnyxParser* parser) {
        return func_def;
 }
 
+static OnyxAstNode* parse_top_level_symbol(OnyxParser* parser) {
+    if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) {
+        OnyxAstNodeFuncDef* func_def = parse_function_definition(parser);
+        return (OnyxAstNode *) func_def;
+
+    } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_STRUCT) {
+        // Handle struct case
+        assert(0);
+    } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_FOREIGN) {
+        parser_next_token(parser);
+
+        OnyxAstNodeForeign* foreign = (OnyxAstNodeForeign *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_FOREIGN);
+        foreign->mod_token = expect(parser, TOKEN_TYPE_LITERAL_STRING);
+        foreign->name_token = expect(parser, TOKEN_TYPE_LITERAL_STRING);
+        foreign->import = parse_top_level_symbol(parser);
+
+        return (OnyxAstNode *) foreign;
+    } else {
+        onyx_message_add(parser->msgs,
+                ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN,
+                parser->curr_token->pos,
+                onyx_get_token_type_name(parser->curr_token->type));
+        return &error_node;
+    }
+}
+
 static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) {
        switch (parser->curr_token->type) {
                case TOKEN_TYPE_KEYWORD_USE:
@@ -713,38 +740,28 @@ static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) {
                                expect(parser, TOKEN_TYPE_SYM_COLON);
                                expect(parser, TOKEN_TYPE_SYM_COLON);
 
-                               if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) {
-                                       OnyxAstNodeFuncDef* func_def = parse_function_definition(parser);
-                                       func_def->token = symbol;
+                OnyxAstNode* node = parse_top_level_symbol(parser);
+                if (node->kind == ONYX_AST_NODE_KIND_FUNCDEF) {
+                    node->token = symbol;
 
-                                       onyx_token_null_toggle(*symbol);
+                    onyx_token_null_toggle(*symbol);
 
-                                       if (!bh_table_has(OnyxAstNode *, parser->identifiers, symbol->token)) {
-                                               bh_table_put(OnyxAstNode *, parser->identifiers, symbol->token, (OnyxAstNode *) func_def);
-                                       } else {
-                                               onyx_message_add(parser->msgs,
-                                                               ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION,
-                                                               symbol->pos,
-                                                               symbol->token);
+                    if (!bh_table_has(OnyxAstNode *, parser->identifiers, symbol->token)) {
+                        bh_table_put(OnyxAstNode *, parser->identifiers, symbol->token, node);
+                    } else {
+                        onyx_message_add(parser->msgs,
+                                ONYX_MESSAGE_TYPE_FUNCTION_REDEFINITION,
+                                symbol->pos,
+                                symbol->token);
 
-                                               // NOTE: I really wish C had defer...
-                                               onyx_token_null_toggle(*symbol);
-                                               return NULL;
-                                       }
-
-                                       onyx_token_null_toggle(*symbol);
-                                       return (OnyxAstNode *) func_def;
+                        // NOTE: I really wish C had defer...
+                        onyx_token_null_toggle(*symbol);
+                        return NULL;
+                    }
 
-                               } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_STRUCT) {
-                                       // Handle struct case
-                                       assert(0);
-                               } else {
-                                       onyx_message_add(parser->msgs,
-                                                       ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN,
-                                                       parser->curr_token->pos,
-                                                       onyx_get_token_type_name(parser->curr_token->type));
-                                       break;
-                               }
+                    onyx_token_null_toggle(*symbol);
+                }
+                return node;
                        }
 
                default: break;
index 055932fd26859efde71ea4ba2276f16a2916ce3e..5f0e97c960200de9f6403a1d0ae5e9c45065ddfe 100644 (file)
@@ -19,7 +19,8 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) {
        }
 
        case ONYX_AST_NODE_KIND_FUNCDEF: {
-               bh_printf("(%b) ", node->token->token, node->token->length);
+        if (node->token)
+            bh_printf("(%b) ", node->token->token, node->token->length);
                OnyxAstNodeFuncDef* fd = &node->as_funcdef;
 
                print_indent;
@@ -123,6 +124,22 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) {
                break;
        }
 
+    case ONYX_AST_NODE_KIND_FOREIGN: {
+        OnyxAstNodeForeign* foreign = &node->as_foreign;
+        bh_printf("%b:%b",
+                foreign->mod_token->token, foreign->mod_token->length,
+                foreign->name_token->token, foreign->name_token->length);
+
+        if (foreign->import) {
+            onyx_ast_print(foreign->import, indent + 1);
+        }
+
+               if (foreign->next) {
+                       onyx_ast_print(foreign->next, indent);
+               }
+        break;
+    }
+
        default: {
                onyx_ast_print(node->left, indent + 1);
                onyx_ast_print(node->right, indent + 1);
index 4d768fba0b8421f601219b37b4070aa0ead12e0f..f4515a4af67e87e5ee03c973d7dccc866bc64dea 100644 (file)
@@ -506,33 +506,36 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef*
        }
 
        // If there is no body then don't process the code
-       if (fd->body == NULL) return;
-
-       // NOTE: Generate the local map
-       i32 localidx = 0;
-       forll (OnyxAstNodeParam, param, fd->params, next) {
-        bh_imap_put(&mod->local_map, (u64) param, localidx++);
-       }
-
-       static const WasmType local_types[4] = { WASM_TYPE_INT32, WASM_TYPE_INT64, WASM_TYPE_FLOAT32, WASM_TYPE_FLOAT64 };
-
-       // HACK: This assumes that the order of the count members
-       // is the same as the order of the local_types above
-       u8* count = &wasm_func.locals.i32_count;
-       fori (ti, 0, 3) {
-               forll (OnyxAstNodeLocal, local, fd->body->scope->last_local, prev_local) {
-                       if (onyx_type_to_wasm_type(local->type) == local_types[ti]) {
-                bh_imap_put(&mod->local_map, (u64) local, localidx++);
-
-                               (*count)++;
-                       }
-               }
+       if (fd->body != NULL) {
+        // NOTE: Generate the local map
+        i32 localidx = 0;
+        forll (OnyxAstNodeParam, param, fd->params, next) {
+            bh_imap_put(&mod->local_map, (u64) param, localidx++);
+        }
+
+        static const WasmType local_types[4] = { WASM_TYPE_INT32, WASM_TYPE_INT64, WASM_TYPE_FLOAT32, WASM_TYPE_FLOAT64 };
+
+        // HACK: This assumes that the order of the count members
+        // is the same as the order of the local_types above
+        u8* count = &wasm_func.locals.i32_count;
+        fori (ti, 0, 3) {
+            forll (OnyxAstNodeLocal, local, fd->body->scope->last_local, prev_local) {
+                if (onyx_type_to_wasm_type(local->type) == local_types[ti]) {
+                    bh_imap_put(&mod->local_map, (u64) local, localidx++);
+
+                    (*count)++;
+                }
+            }
 
-               count++;
-       }
+            count++;
+        }
 
-       // Generate code
-       process_function_body(mod, &wasm_func, fd);
+        // Generate code
+        process_function_body(mod, &wasm_func, fd);
+    } else {
+        // NOTE: Empty bodies still need a block end instruction
+        bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_BLOCK_END, 0x00 }));
+    }
 
        bh_arr_push(mod->funcs, wasm_func);
 
@@ -540,6 +543,10 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef*
        bh_imap_clear(&mod->local_map);
 }
 
+void process_foreign(OnyxWasmModule* module, OnyxAstNodeForeign* foreign) {
+    
+}
+
 OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* program) {
        OnyxWasmModule module = {
                .allocator = alloc,
@@ -570,6 +577,9 @@ OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* progra
                        case ONYX_AST_NODE_KIND_FUNCDEF:
                                process_function_definition(&module, &walker->as_funcdef);
                                break;
+            case ONYX_AST_NODE_KIND_FOREIGN:
+                process_foreign(&module, &walker->as_foreign);
+                break;
                        default: break;
                }
 
@@ -804,10 +814,6 @@ static void output_instruction(WasmInstruction* instr, bh_buffer* buff) {
                case WI_LOCAL_GET:
                case WI_LOCAL_SET:
         case WI_CALL:
-                       leb = uint_to_uleb128((u64) instr->data.i1, &leb_len);
-                       bh_buffer_append(buff, leb, leb_len);
-                       break;
-
                case WI_BLOCK_START:
                        leb = uint_to_uleb128((u64) instr->data.i1, &leb_len);
                        bh_buffer_append(buff, leb, leb_len);