Starting work on globals
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 30 Jun 2020 21:16:08 +0000 (16:16 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Tue, 30 Jun 2020 21:16:08 +0000 (16:16 -0500)
.vimspector.json
include/onyxparser.h
onyx
progs/test.onyx
src/onyx.c
src/onyxparser.c
src/onyxutils.c

index 1ecdcd93858baf22615289e2dc78a90229f0d7c4..b101bde4314e9348fcc1ea1a90161183b631e2d9 100644 (file)
@@ -6,7 +6,7 @@
                 "type": "cppdbg",
                 "request": "launch",
                 "program": "${workspaceFolder}/onyx",
-                "args": ["progs/other.onyx", "progs/test.onyx"],
+                "args": ["-ast", "progs/other.onyx", "progs/test.onyx"],
                 "stopAtEntry": true,
                 "cwd": "${workspaceFolder}",
                 "environment": [],
index 312b2d549894327cca195b9708086247dd9cdf21..6f256564a81cc1c5f5ee217c8e4ab1462321f6fc 100644 (file)
@@ -18,6 +18,7 @@ typedef struct OnyxAstNodeWhile OnyxAstNodeWhile;
 typedef struct OnyxAstNodeParam OnyxAstNodeParam;
 typedef struct OnyxAstNodeFuncDef OnyxAstNodeFuncDef;
 typedef struct OnyxAstNodeForeign OnyxAstNodeForeign;
+typedef struct OnyxAstNodeGlobal OnyxAstNodeGlobal;
 typedef struct OnyxAstNodeCall OnyxAstNodeCall;
 typedef struct OnyxAstNodeFile OnyxAstNodeFile;
 
@@ -43,6 +44,7 @@ typedef enum OnyxAstNodeKind {
     ONYX_AST_NODE_KIND_BLOCK,
     ONYX_AST_NODE_KIND_SCOPE,
     ONYX_AST_NODE_KIND_LOCAL,
+    ONYX_AST_NODE_KIND_GLOBAL,
     ONYX_AST_NODE_KIND_SYMBOL,
 
     ONYX_AST_NODE_KIND_UNARY_OP,
@@ -150,6 +152,7 @@ struct OnyxAstNodeNumLit {
     u32 flags;
     OnyxToken *token;
     OnyxTypeInfo *type;
+    u64 data;
     OnyxAstNode *next;
     union { i32 i; i64 l; f32 f; f64 d; } value;
 };
@@ -239,6 +242,16 @@ struct OnyxAstNodeForeign {
     OnyxAstNode *import;
 };
 
+struct OnyxAstNodeGlobal {
+    OnyxAstNodeKind kind;
+    u32 flags;
+    OnyxToken *token;
+    OnyxTypeInfo *type;
+    u64 data;
+    OnyxAstNode* next;
+    OnyxAstNode* initial_value;
+};
+
 struct OnyxAstNodeCall {
     OnyxAstNodeKind kind;
     u32 flags;
@@ -286,6 +299,7 @@ union OnyxAstNode {
     OnyxAstNodeBinOp as_binop;
     OnyxAstNodeUnaryOp as_unaryop;
     OnyxAstNodeForeign as_foreign;
+    OnyxAstNodeGlobal as_global;
     OnyxAstNodeIf as_if;
     OnyxAstNodeWhile as_while;
     OnyxAstNodeFile as_file;
diff --git a/onyx b/onyx
index 5315494571a3da2d56f489cedee4c57828380b97..b186232adac92ad907a8b23da4511e362ccbdb4d 100755 (executable)
Binary files a/onyx and b/onyx differ
index 1f635f5b537088d534bb59e59bae133086b0cd20..a0a8af2fc5f2c22e35517baa2ac45886cb26c1ee 100644 (file)
@@ -22,6 +22,8 @@ something_else :: proc (n i32) -> i32 {
 // symbol := 5                  Global mutable variable
 // symbol : i32                 Global mutable i32 (defaults to 0 initial value)
 
+global_value := 5 + 6;
+
 // This is the entry point
 export main :: proc {
     i := 0;
index 051d0562f6bccb651a5ec3419ca5ec55af0dfe95..ec1d942057c73f7cc3df6317a89128081c66aa01 100644 (file)
@@ -30,6 +30,8 @@ typedef struct OnyxCompileOptions {
     bh_allocator allocator;
     CompileAction action;
 
+    u32 print_ast : 1;
+
     bh_arr(const char *) files;
     const char* target_file;
 } OnyxCompileOptions;
@@ -57,6 +59,8 @@ static OnyxCompileOptions compile_opts_parse(bh_allocator alloc, int argc, char
         .allocator = alloc,
         .action = ONYX_COMPILE_ACTION_PRINT_HELP,
 
+        .print_ast = 0,
+
         .files = NULL,
         .target_file = "out.wasm",
     };
@@ -72,6 +76,9 @@ static OnyxCompileOptions compile_opts_parse(bh_allocator alloc, int argc, char
             options.action = ONYX_COMPILE_ACTION_COMPILE;
             options.target_file = argv[++i];
         }
+        else if (!strcmp(argv[i], "-ast")) {
+            options.print_ast = 1;
+        }
         else {
             options.action = ONYX_COMPILE_ACTION_COMPILE;
             bh_arr_push(options.files, argv[i]);
@@ -136,6 +143,11 @@ i32 onyx_compile(OnyxCompileOptions* opts, CompilerState* compiler_state) {
     bh_table_each_start(bh_file_contents, compiler_state->loaded_files);
         OnyxAstNodeFile* file_node = parse_source_file(&value, compiler_state);
 
+        if (opts->print_ast) {
+            onyx_ast_print((OnyxAstNode *) file_node, 0);
+            bh_printf("\n");
+        }
+
         if (!root_file) {
             root_file = file_node;
         }
@@ -155,6 +167,11 @@ i32 onyx_compile(OnyxCompileOptions* opts, CompilerState* compiler_state) {
     OnyxSemPassState sp_state = onyx_sempass_create(compiler_state->sp_alloc, compiler_state->ast_alloc, &compiler_state->msgs);
     onyx_sempass(&sp_state, root_file);
 
+    if (opts->print_ast) {
+        onyx_ast_print((OnyxAstNode *) root_file, 0);
+        bh_printf("\n");
+    }
+
     if (onyx_message_has_errors(&compiler_state->msgs)) {
         return ONYX_COMPILER_PROGRESS_FAILED_SEMPASS;
     }
index d045613e090a43f6daf574990f7714f8e1279116..af39eb91cc4165f575cd54d3ec83b0cb2beed79c 100644 (file)
@@ -12,6 +12,7 @@ static const char* ast_node_names[] = {
     "BLOCK",
     "SCOPE",
     "LOCAL",
+    "GLOBAL",
     "SYMBOL",
 
     "UN_OP",
@@ -19,7 +20,6 @@ static const char* ast_node_names[] = {
 
     "TYPE",
     "LITERAL",
-    "CAST",
     "PARAM",
     "ARGUMENT",
     "CALL",
@@ -28,6 +28,8 @@ static const char* ast_node_names[] = {
 
     "IF",
     "WHILE",
+    "BREAK",
+    "CONTINUE",
 
     "ONYX_AST_NODE_KIND_COUNT",
 };
@@ -705,29 +707,50 @@ static OnyxAstNodeFuncDef* parse_function_definition(OnyxParser* parser) {
     return func_def;
 }
 
-static OnyxAstNode* parse_top_level_symbol(OnyxParser* parser) {
+static OnyxAstNode* parse_foreign(OnyxParser* parser) {
+    expect(parser, TOKEN_TYPE_KEYWORD_FOREIGN);
+
+    OnyxAstNodeForeign* foreign = 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);
+
     if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) {
-        OnyxAstNodeFuncDef* func_def = parse_function_definition(parser);
-        return (OnyxAstNode *) func_def;
+        foreign->import = (OnyxAstNode *) parse_function_definition(parser);
+
+    } else {
+        OnyxTypeInfo* type = parse_type(parser);
+
+        OnyxAstNodeGlobal* global = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_GLOBAL);
+        global->type = type;
+        global->flags |= ONYX_AST_FLAG_LVAL;
+
+        foreign->import = (OnyxAstNode *) global;
+    }
+
+    return (OnyxAstNode *) foreign;
+}
+
+static OnyxAstNode* parse_top_level_constant_symbol(OnyxParser* parser) {
+    if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) {
+        return (OnyxAstNode *) parse_function_definition(parser);
 
     } 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 = 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);
+    } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_FOREIGN) {
+        return (OnyxAstNode *) parse_foreign(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;
+        // Global constant with initial value
+        OnyxAstNodeGlobal* global = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_GLOBAL);
+        global->initial_value = parse_expression(parser);
+        global->type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+        global->flags |= ONYX_AST_FLAG_CONST;
+        global->flags |= ONYX_AST_FLAG_LVAL;
+        global->flags |= ONYX_AST_FLAG_COMPTIME;
+
+        return (OnyxAstNode *) global;
     }
 }
 
@@ -759,21 +782,43 @@ static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) {
                 OnyxToken* symbol = parser->curr_token;
                 parser_next_token(parser);
 
-                expect(parser, TOKEN_TYPE_SYM_COLON);
                 expect(parser, TOKEN_TYPE_SYM_COLON);
 
-                OnyxAstNode* node = parse_top_level_symbol(parser);
-                if (node->kind == ONYX_AST_NODE_KIND_FUNCDEF) {
-                    node->token = symbol;
-                }
+                if (parser->curr_token->type == TOKEN_TYPE_SYM_COLON) {
+                    parser_next_token(parser);
+
+                    OnyxAstNode* node = parse_top_level_constant_symbol(parser);
 
-                if (node->kind == ONYX_AST_NODE_KIND_FOREIGN) {
-                    OnyxAstNodeForeign* foreign = &node->as_foreign;
+                    if (node->kind == ONYX_AST_NODE_KIND_FOREIGN) {
+                        node->as_foreign.import->token = symbol;
+
+                    } else {
+                        node->token = symbol;
+                    }
 
-                    foreign->import->token = symbol;
+                    return node;
+
+                } else if (parser->curr_token->type == TOKEN_TYPE_SYM_EQUALS) {
+                    parser_next_token(parser);
+
+                    OnyxAstNodeGlobal* global = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_GLOBAL);
+                    global->token = symbol;
+                    global->flags |= ONYX_AST_FLAG_LVAL;
+                    global->initial_value = parse_expression(parser);
+                    global->type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+
+                    return (OnyxAstNode *) global;
+
+                } else {
+                    onyx_token_null_toggle(*parser->curr_token);
+                    onyx_message_add(parser->msgs,
+                            ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN,
+                            parser->curr_token->pos,
+                            parser->curr_token->token);
+                    onyx_token_null_toggle(*parser->curr_token);
                 }
 
-                return node;
+                return &error_node;
             }
 
         default: break;
index c98dd67f5ae8c0e9018da4b6855fdee7eb66d0dd..cae6546a407e659b297d5d6f0a2eccff44591e90 100644 (file)
@@ -18,8 +18,12 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) {
 
     switch (node->kind) {
     case ONYX_AST_NODE_KIND_PROGRAM: {
+        OnyxAstNodeFile* file_node = &node->as_file;
+        if (file_node->contents)
+            onyx_ast_print(file_node->contents, indent + 1);
+
         if (node->next)
-            onyx_ast_print(node->next, indent + 1);
+            onyx_ast_print(node->next, indent);
 
         break;
     }
@@ -97,6 +101,19 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) {
         break;
     }
 
+    case ONYX_AST_NODE_KIND_GLOBAL: {
+        OnyxAstNodeGlobal* global = &node->as_global;
+        bh_printf("%b %s", global->token->token, global->token->length, global->type->name);
+        if (global->initial_value) {
+            onyx_ast_print(global->initial_value, indent + 1);
+        }
+
+        if (node->next) {
+            onyx_ast_print(node->next, indent);
+        }
+        break;
+    }
+
     case ONYX_AST_NODE_KIND_SYMBOL: {
         bh_printf("%b", node->token->token, node->token->length);
         if (node->next) {
@@ -176,6 +193,19 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) {
         break;
     }
 
+    case ONYX_AST_NODE_KIND_BIN_OP: {
+        OnyxAstNodeBinOp* binop = &node->as_binop;
+        bh_printf("%b", binop->token->token, binop->token->length);
+
+        onyx_ast_print(node->left, indent + 1);
+        onyx_ast_print(node->right, indent + 1);
+        if (node->next) {
+            onyx_ast_print(node->next, indent);
+        }
+
+        break;
+    }
+
     default: {
         onyx_ast_print(node->left, indent + 1);
         onyx_ast_print(node->right, indent + 1);