"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": [],
typedef struct OnyxAstNodeParam OnyxAstNodeParam;
typedef struct OnyxAstNodeFuncDef OnyxAstNodeFuncDef;
typedef struct OnyxAstNodeForeign OnyxAstNodeForeign;
+typedef struct OnyxAstNodeGlobal OnyxAstNodeGlobal;
typedef struct OnyxAstNodeCall OnyxAstNodeCall;
typedef struct OnyxAstNodeFile OnyxAstNodeFile;
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,
u32 flags;
OnyxToken *token;
OnyxTypeInfo *type;
+ u64 data;
OnyxAstNode *next;
union { i32 i; i64 l; f32 f; f64 d; } value;
};
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;
OnyxAstNodeBinOp as_binop;
OnyxAstNodeUnaryOp as_unaryop;
OnyxAstNodeForeign as_foreign;
+ OnyxAstNodeGlobal as_global;
OnyxAstNodeIf as_if;
OnyxAstNodeWhile as_while;
OnyxAstNodeFile as_file;
// 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;
bh_allocator allocator;
CompileAction action;
+ u32 print_ast : 1;
+
bh_arr(const char *) files;
const char* target_file;
} OnyxCompileOptions;
.allocator = alloc,
.action = ONYX_COMPILE_ACTION_PRINT_HELP,
+ .print_ast = 0,
+
.files = NULL,
.target_file = "out.wasm",
};
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]);
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;
}
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;
}
"BLOCK",
"SCOPE",
"LOCAL",
+ "GLOBAL",
"SYMBOL",
"UN_OP",
"TYPE",
"LITERAL",
- "CAST",
"PARAM",
"ARGUMENT",
"CALL",
"IF",
"WHILE",
+ "BREAK",
+ "CONTINUE",
"ONYX_AST_NODE_KIND_COUNT",
};
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;
}
}
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;
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;
}
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) {
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);