#include "bh.h"
-typedef enum OnyxTokenType {
+typedef enum TokenType {
TOKEN_TYPE_UNKNOWN,
TOKEN_TYPE_END_STREAM,
TOKEN_TYPE_LITERAL_BOOL_FALSE,
TOKEN_TYPE_COUNT
-} OnyxTokenType;
+} TokenType;
typedef struct OnyxFilePos {
const char* filename;
} OnyxFilePos;
typedef struct OnyxToken {
- OnyxTokenType type;
+ TokenType type;
i32 length;
char* token;
OnyxFilePos pos;
bh_arr(OnyxToken) tokens;
} OnyxTokenizer;
-const char* onyx_get_token_type_name(OnyxTokenType tkn_type);
-void onyx_token_null_toggle(OnyxToken tkn);
+const char* onyx_get_token_type_name(TokenType tkn_type);
+void onyx_token_null_toggle(OnyxToken* tkn);
OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer);
OnyxTokenizer onyx_tokenizer_create(bh_allocator allocator, bh_file_contents *fc);
void onyx_tokenizer_free(OnyxTokenizer* tokenizer);
#include "onyxlex.h"
#include "onyxmsgs.h"
-typedef union OnyxAstNode OnyxAstNode;
-typedef struct OnyxAstNodeUnaryOp OnyxAstNodeUnaryOp;
-typedef struct OnyxAstNodeBinOp OnyxAstNodeBinOp;
-typedef struct OnyxAstNodeNumLit OnyxAstNodeNumLit;
-typedef struct OnyxAstNodeLocal OnyxAstNodeLocal;
-typedef struct OnyxAstNodeScope OnyxAstNodeScope;
-typedef struct OnyxAstNodeBlock OnyxAstNodeBlock;
-typedef struct OnyxAstNodeIf OnyxAstNodeIf;
-typedef struct OnyxAstNodeWhile OnyxAstNodeWhile;
-typedef struct OnyxAstNodeParam OnyxAstNodeParam;
-typedef struct OnyxAstNodeFunction OnyxAstNodeFunction;
-typedef struct OnyxAstNodeForeign OnyxAstNodeForeign;
-typedef struct OnyxAstNodeGlobal OnyxAstNodeGlobal;
-typedef struct OnyxAstNodeCall OnyxAstNodeCall;
-typedef struct OnyxAstNodeUse OnyxAstNodeUse;
+typedef struct AstNode AstNode;
+typedef struct AstNodeTyped AstNodeTyped;
+typedef struct AstNodeUnaryOp AstNodeUnaryOp;
+typedef struct AstNodeBinOp AstNodeBinOp;
+typedef struct AstNodeAssign AstNodeAssign;
+typedef struct AstNodeNumLit AstNodeNumLit;
+typedef struct AstNodeLocal AstNodeLocal;
+typedef struct AstNodeScope AstNodeScope;
+typedef struct AstNodeReturn AstNodeReturn;
+typedef struct AstNodeBlock AstNodeBlock;
+typedef struct AstNodeIf AstNodeIf;
+typedef struct AstNodeWhile AstNodeWhile;
+typedef struct AstNodeFunction AstNodeFunction;
+typedef struct AstNodeForeign AstNodeForeign;
+typedef struct AstNodeGlobal AstNodeGlobal;
+typedef struct AstNodeCall AstNodeCall;
+typedef struct AstNodeArgument AstNodeArgument;
+typedef struct AstNodeUse AstNodeUse;
typedef struct OnyxParser {
OnyxTokenizer *tokenizer; // NOTE: not used since all tokens are lexed before parsing starts
// NOTE: Identifiers currently is only used to resolve type names
// at parse time, since these are the only symbols we know.
- bh_table(OnyxAstNode *) identifiers;
+ bh_table(AstNode *) identifiers;
OnyxMessages *msgs;
bh_allocator allocator;
} OnyxParser;
-typedef enum OnyxAstNodeKind {
- ONYX_AST_NODE_KIND_ERROR,
- ONYX_AST_NODE_KIND_PROGRAM,
- ONYX_AST_NODE_KIND_USE,
-
- ONYX_AST_NODE_KIND_FUNCTION,
- ONYX_AST_NODE_KIND_FOREIGN,
- 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,
- ONYX_AST_NODE_KIND_BIN_OP,
-
- ONYX_AST_NODE_KIND_TYPE,
- ONYX_AST_NODE_KIND_LITERAL,
- ONYX_AST_NODE_KIND_PARAM,
- ONYX_AST_NODE_KIND_ARGUMENT,
- ONYX_AST_NODE_KIND_CALL,
- ONYX_AST_NODE_KIND_ASSIGNMENT,
- ONYX_AST_NODE_KIND_RETURN,
-
- ONYX_AST_NODE_KIND_IF,
- ONYX_AST_NODE_KIND_WHILE,
- ONYX_AST_NODE_KIND_BREAK,
- ONYX_AST_NODE_KIND_CONTINUE,
-
- ONYX_AST_NODE_KIND_COUNT
-} OnyxAstNodeKind;
-
-typedef enum OnyxTypeInfoKind {
- ONYX_TYPE_INFO_KIND_UNKNOWN,
- ONYX_TYPE_INFO_KIND_VOID,
- ONYX_TYPE_INFO_KIND_BOOL,
-
- ONYX_TYPE_INFO_KIND_UINT32,
- ONYX_TYPE_INFO_KIND_UINT64,
-
- ONYX_TYPE_INFO_KIND_INT32,
- ONYX_TYPE_INFO_KIND_INT64,
-
- ONYX_TYPE_INFO_KIND_FLOAT32,
- ONYX_TYPE_INFO_KIND_FLOAT64,
- ONYX_TYPE_INFO_KIND_SOFT_FLOAT, // 64-bits of data but could be treated as 32-bit
-} OnyxTypeInfoKind;
-
-typedef struct OnyxTypeInfo {
- OnyxTypeInfoKind kind;
+typedef enum AstNodeKind {
+ AST_NODE_KIND_ERROR,
+ AST_NODE_KIND_PROGRAM,
+ AST_NODE_KIND_USE,
+
+ AST_NODE_KIND_FUNCTION,
+ AST_NODE_KIND_FOREIGN,
+ AST_NODE_KIND_BLOCK,
+ AST_NODE_KIND_SCOPE,
+ AST_NODE_KIND_LOCAL,
+ AST_NODE_KIND_GLOBAL,
+ AST_NODE_KIND_SYMBOL,
+
+ AST_NODE_KIND_UNARY_OP,
+ AST_NODE_KIND_BIN_OP,
+
+ AST_NODE_KIND_TYPE,
+ AST_NODE_KIND_LITERAL,
+ AST_NODE_KIND_PARAM,
+ AST_NODE_KIND_ARGUMENT,
+ AST_NODE_KIND_CALL,
+ AST_NODE_KIND_ASSIGNMENT,
+ AST_NODE_KIND_RETURN,
+
+ AST_NODE_KIND_IF,
+ AST_NODE_KIND_WHILE,
+ AST_NODE_KIND_BREAK,
+ AST_NODE_KIND_CONTINUE,
+
+ AST_NODE_KIND_COUNT
+} AstNodeKind;
+
+typedef enum TypeInfoKind {
+ TYPE_INFO_KIND_UNKNOWN,
+ TYPE_INFO_KIND_VOID,
+ TYPE_INFO_KIND_BOOL,
+
+ TYPE_INFO_KIND_UINT32,
+ TYPE_INFO_KIND_UINT64,
+
+ TYPE_INFO_KIND_INT32,
+ TYPE_INFO_KIND_INT64,
+
+ TYPE_INFO_KIND_FLOAT32,
+ TYPE_INFO_KIND_FLOAT64,
+ TYPE_INFO_KIND_SOFT_FLOAT, // 64-bits of data but could be treated as 32-bit
+} TypeInfoKind;
+
+typedef struct TypeInfo {
+ TypeInfoKind kind;
u32 size; // in bytes
const char* name;
u32 is_int : 1;
u32 is_float : 1;
u32 is_bool : 1;
u32 is_known : 1;
-} OnyxTypeInfo;
+} TypeInfo;
-extern OnyxTypeInfo builtin_types[];
+extern TypeInfo builtin_types[];
// NOTE: Some of these flags will overlap since there are
// only 32-bits of flags to play with
ONYX_BINARY_OP_GREATER_EQUAL = 10,
} OnyxBinaryOp;
-struct OnyxAstNodeBinOp {
- OnyxAstNodeKind kind;
+// NOTE: AstNode and AstNodeTyped need to be EXACTLY the same for
+// all arguments existing in AstNode. I do this to avoid a nested
+// "inheiritance" where you would have to say node.base.base.next
+// for example
+struct AstNode {
+ AstNodeKind kind;
u32 flags;
OnyxToken *token;
- OnyxTypeInfo *type;
- OnyxBinaryOp operation;
- OnyxAstNode *next;
- OnyxAstNode *left;
- OnyxAstNode *right;
+ AstNode *next;
};
-struct OnyxAstNodeUnaryOp {
- OnyxAstNodeKind kind;
+struct AstNodeTyped {
+ AstNodeKind kind;
u32 flags;
OnyxToken *token;
- OnyxTypeInfo *type;
+ AstNode *next;
+ TypeInfo *type;
+};
+
+struct AstNodeBinOp {
+ AstNodeTyped base;
+
+ OnyxBinaryOp operation;
+
+ AstNodeTyped *left, *right;
+};
+
+struct AstNodeUnaryOp {
+ AstNodeTyped base;
+
OnyxUnaryOp operation;
- OnyxAstNode *next;
- OnyxAstNode *left;
+
+ AstNodeTyped *expr;
};
-struct OnyxAstNodeNumLit {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *type;
- u64 data;
- OnyxAstNode *next;
+struct AstNodeAssign {
+ AstNode base;
+
+ AstNodeTyped* lval;
+ AstNodeTyped* expr;
+};
+
+struct AstNodeNumLit {
+ AstNodeTyped base;
+
union { i32 i; i64 l; f32 f; f64 d; } value;
};
-struct OnyxAstNodeLocal {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *type;
- u64 data; // NOTE: Unused
- OnyxAstNode *next;
- OnyxAstNodeLocal *prev_local;
+struct AstNodeLocal {
+ AstNodeTyped base;
+
+ AstNodeLocal *prev_local;
};
-struct OnyxAstNodeParam {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token; // NOTE: Symbol name i.e. 'a', 'b'
- OnyxTypeInfo *type;
- u64 data; // NOTE: UNUSED
- OnyxAstNodeParam *next;
- OnyxAstNodeLocal *prev_local;
+struct AstNodeReturn {
+ AstNode base;
+
+ AstNodeTyped* expr;
};
-struct OnyxAstNodeScope {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token; // NOTE: UNUSED
- OnyxTypeInfo *type; // NOTE: UNUSED
- u64 data; // NOTE: UNUSED
- OnyxAstNodeScope *prev_scope;
- OnyxAstNodeLocal *last_local;
+struct AstNodeScope {
+ AstNode base;
+
+ AstNodeScope *prev_scope;
+ AstNodeLocal *last_local;
};
-struct OnyxAstNodeBlock {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *return_type;
- u64 data; // NOTE: UNUSED
- OnyxAstNode *next;
- OnyxAstNode *body;
- OnyxAstNodeScope *scope;
+struct AstNodeBlock {
+ AstNode base;
+
+ AstNode *body;
+ AstNodeScope *scope;
};
-struct OnyxAstNodeIf {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token; // NOTE: UNUSED
- u64 data; // NOTE: UNUSED
- OnyxAstNode *false_block;
- OnyxAstNode *next;
- OnyxAstNode *cond;
- OnyxAstNode *true_block;
+struct AstNodeIf {
+ AstNode base;
+
+ AstNodeTyped *cond;
+ AstNode *true_block;
+ AstNode *false_block;
};
-struct OnyxAstNodeWhile {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token; // NOTE: UNUSED
- OnyxTypeInfo *type;
- u64 data;
- OnyxAstNode *next;
- OnyxAstNode *cond;
- OnyxAstNodeBlock *body;
+struct AstNodeWhile {
+ AstNode base;
+
+ AstNodeTyped *cond;
+ AstNodeBlock *body;
};
-struct OnyxAstNodeFunction {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token; // This will point to the symbol token to identify it
- OnyxTypeInfo *return_type;
- u64 data;
- OnyxAstNode *next;
- OnyxAstNodeBlock *body;
- OnyxAstNodeParam *params;
+struct AstNodeFunction {
+ AstNodeTyped base;
+
+ AstNodeBlock *body;
+ AstNodeLocal *params;
};
-struct OnyxAstNodeForeign {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *mod_token;
- OnyxTypeInfo *type;
- u64 data;
- OnyxAstNode *next;
- OnyxToken *name_token;
- OnyxAstNode *import;
+struct AstNodeForeign {
+ AstNode base;
+
+ OnyxToken *mod_token, *name_token;
+ AstNode *import;
};
-struct OnyxAstNodeGlobal {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *type;
- u64 data;
- OnyxAstNode* next;
- OnyxAstNode* initial_value;
+struct AstNodeGlobal {
+ AstNodeTyped base;
+
+ AstNodeTyped *initial_value;
};
-struct OnyxAstNodeCall {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *type; // NOTE: The type that the function returns
- u64 data;
- OnyxAstNode *next;
- OnyxAstNode *callee; // NOTE: Function definition node
- OnyxAstNode *arguments; // NOTE: Expressions that form the actual param list
- // They will be chained down using the "next" property
- // unless this becomes used by something else
+struct AstNodeCall {
+ AstNodeTyped base;
+
+ AstNode *callee; // NOTE: Function definition node
+ AstNodeArgument *arguments; // NOTE: Expressions that form the actual param list
+ // They will be chained down using the "next" property
+ // unless this becomes used by something else
};
-struct OnyxAstNodeUse {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *type;
- u64 data;
- OnyxAstNode *next;
- OnyxToken *filename;
+struct AstNodeArgument {
+ AstNodeTyped base;
+
+ AstNodeTyped *value;
};
-union OnyxAstNode {
-
- // Generic node structure for capturing all binary ops and statements
- struct {
- OnyxAstNodeKind kind;
- u32 flags;
- OnyxToken *token;
- OnyxTypeInfo *type;
- u64 data;
- OnyxAstNode *next;
- OnyxAstNode *left;
- OnyxAstNode *right;
- };
-
- OnyxAstNodeBlock as_block;
- OnyxAstNodeParam as_param;
- OnyxAstNodeLocal as_local;
- OnyxAstNodeScope as_scope;
- OnyxAstNodeCall as_call;
- OnyxAstNodeNumLit as_numlit;
- OnyxAstNodeBinOp as_binop;
- OnyxAstNodeUnaryOp as_unaryop;
- OnyxAstNodeIf as_if;
- OnyxAstNodeWhile as_while;
- OnyxAstNodeUse as_use;
- OnyxAstNodeFunction as_function;
- OnyxAstNodeGlobal as_global;
- OnyxAstNodeForeign as_foreign;
+struct AstNodeUse {
+ AstNode base;
+
+ OnyxToken *filename;
};
typedef struct OnyxProgram {
- bh_arr(OnyxAstNodeUse *) uses;
- bh_arr(OnyxAstNodeGlobal *) globals;
- bh_arr(OnyxAstNodeFunction *) functions;
- bh_arr(OnyxAstNodeForeign *) foreigns;
+ bh_arr(AstNodeUse *) uses;
+ bh_arr(AstNodeGlobal *) globals;
+ bh_arr(AstNodeFunction *) functions;
+ bh_arr(AstNodeForeign *) foreigns;
} OnyxProgram;
-const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind);
-void* onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind);
+const char* onyx_ast_node_kind_string(AstNodeKind kind);
+void* onyx_ast_node_new(bh_allocator alloc, i32 size, AstNodeKind kind);
OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, OnyxMessages* msgs);
void onyx_parser_free(OnyxParser* parser);
-OnyxAstNode* onyx_parse(OnyxParser *parser);
+AstNode* onyx_parse(OnyxParser *parser);
#endif // #ifndef ONYXPARSER_H
#include "onyxmsgs.h"
typedef struct SemPassSymbol {
- OnyxAstNode *node;
+ AstNode *node;
struct SemPassSymbol *shadowed;
} SemPassSymbol;
OnyxMessages *msgs;
// NOTE: Used in symbol resolution phase
- OnyxAstNodeScope* curr_scope;
+ AstNodeScope* curr_scope;
// NOTE: Used in type checking phase
- OnyxTypeInfo* expected_return_type;
+ TypeInfo* expected_return_type;
bh_table(SemPassSymbol *) symbols;
} OnyxSemPassState;
extern bh_managed_heap global_heap;
extern bh_allocator global_heap_allocator;
-void onyx_ast_print(OnyxAstNode* program, i32 indent);
+void onyx_ast_print(AstNode* program, i32 indent);
bh_arr_free(opts->files);
}
-static OnyxAstNode* parse_source_file(CompilerState* compiler_state, bh_file_contents* file_contents) {
+static AstNode* parse_source_file(CompilerState* compiler_state, bh_file_contents* file_contents) {
// NOTE: Maybe don't want to recreate the tokenizer and parser for every file
if (compiler_state->options->verbose_output)
bh_printf("[Lexing] %s\n", file_contents->filename);
bh_table_put(bh_file_contents, compiler_state->loaded_files, (char *) filename, fc);
fc = bh_table_get(bh_file_contents, compiler_state->loaded_files, (char *) filename);
- OnyxAstNode* root_node = parse_source_file(compiler_state, &fc);
+ AstNode* root_node = parse_source_file(compiler_state, &fc);
if (compiler_state->options->print_ast) {
onyx_ast_print(root_node, 0);
bh_printf("\n");
}
- OnyxAstNode* walker = root_node;
+ AstNode* walker = root_node;
while (walker) {
switch (walker->kind) {
- case ONYX_AST_NODE_KIND_USE:
- bh_arr_push(compiler_state->program.uses, &walker->as_use);
+ case AST_NODE_KIND_USE:
+ bh_arr_push(compiler_state->program.uses, (AstNodeUse *) walker);
break;
- case ONYX_AST_NODE_KIND_GLOBAL:
- bh_arr_push(compiler_state->program.globals, &walker->as_global);
+ case AST_NODE_KIND_GLOBAL:
+ bh_arr_push(compiler_state->program.globals, (AstNodeGlobal *) walker);
break;
- case ONYX_AST_NODE_KIND_FOREIGN:
- bh_arr_push(compiler_state->program.foreigns, &walker->as_foreign);
+ case AST_NODE_KIND_FOREIGN:
+ bh_arr_push(compiler_state->program.foreigns, (AstNodeForeign *) walker);
break;
- case ONYX_AST_NODE_KIND_FUNCTION:
- bh_arr_push(compiler_state->program.functions, &walker->as_function);
+ case AST_NODE_KIND_FUNCTION:
+ bh_arr_push(compiler_state->program.functions, (AstNodeFunction *) walker);
break;
- case ONYX_AST_NODE_KIND_PROGRAM:
+ case AST_NODE_KIND_PROGRAM:
// Dummy initial node
break;
walker = walker->next;
}
- bh_arr_each(OnyxAstNodeUse *, use_node, compiler_state->program.uses) {
+ bh_arr_each(AstNodeUse *, use_node, compiler_state->program.uses) {
char* formatted_name = bh_aprintf(
global_heap_allocator,
"%b.onyx",
#include "bh.h"
#include "onyxlex.h"
-static const char* onyx_token_type_names[] = {
+static const char* token_type_names[] = {
"TOKEN_TYPE_UNKNOWN",
"TOKEN_TYPE_END_STREAM",
}
#endif
-static b32 token_lit(OnyxTokenizer* tokenizer, OnyxToken* tk, char* lit, b32 is_word, OnyxTokenType type) {
+static b32 token_lit(OnyxTokenizer* tokenizer, OnyxToken* tk, char* lit, b32 is_word, TokenType type) {
i64 len = chars_match(tokenizer->curr, lit);
if (len > 0) {
if (is_word && char_is_alphanum(*(tokenizer->curr + len)) || charset_contains("_$", *(tokenizer->curr + len)))
return 0;
}
-const char* onyx_get_token_type_name(OnyxTokenType tkn_type) {
- return onyx_token_type_names[tkn_type];
+const char* onyx_get_token_type_name(TokenType tkn_type) {
+ return token_type_names[tkn_type];
}
-void onyx_token_null_toggle(OnyxToken tkn) {
+void onyx_token_null_toggle(OnyxToken* tkn) {
static char backup = 0;
- char tmp = tkn.token[tkn.length];
- tkn.token[tkn.length] = backup;
+ char tmp = tkn->token[tkn->length];
+ tkn->token[tkn->length] = backup;
backup = tmp;
}
#include "onyxparser.h"
#include "onyxutils.h"
+// NOTE: The one weird define you need to know before read the code below
+#define make_node(nclass, kind) onyx_ast_node_new(parser->allocator, sizeof(nclass), kind)
+
static const char* ast_node_names[] = {
"ERROR",
"PROGRAM",
"BREAK",
"CONTINUE",
- "ONYX_AST_NODE_KIND_COUNT",
+ "AST_NODE_KIND_COUNT",
};
-struct OnyxTypeInfo builtin_types[] = {
- { ONYX_TYPE_INFO_KIND_UNKNOWN, 0, "unknown" },
- { ONYX_TYPE_INFO_KIND_VOID, 0, "void", 0, 0, 0, 0, 1 },
+struct TypeInfo builtin_types[] = {
+ { TYPE_INFO_KIND_UNKNOWN, 0, "unknown" },
+ { TYPE_INFO_KIND_VOID, 0, "void", 0, 0, 0, 0, 1 },
- { ONYX_TYPE_INFO_KIND_BOOL, 1, "bool", 0, 1, 0, 1, 1 },
+ { TYPE_INFO_KIND_BOOL, 1, "bool", 0, 1, 0, 1, 1 },
- { ONYX_TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0, 1 },
- { ONYX_TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0, 1 },
+ { TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0, 1 },
+ { TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0, 1 },
- { ONYX_TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0, 1 },
- { ONYX_TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0, 1 },
+ { TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0, 1 },
+ { TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0, 1 },
- { ONYX_TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0, 1 },
- { ONYX_TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0, 1},
- { ONYX_TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0, 1 },
+ { TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0, 1 },
+ { TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0, 1},
+ { TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0, 1 },
{ 0xffffffff } // Sentinel
};
-static OnyxAstNode error_node = { { ONYX_AST_NODE_KIND_ERROR, 0, NULL, &builtin_types[0], 0, NULL, NULL, NULL } };
+static AstNode error_node = { AST_NODE_KIND_ERROR, 0, NULL, NULL };
// NOTE: Forward declarations
static void parser_next_token(OnyxParser* parser);
static void parser_prev_token(OnyxParser* parser);
-static b32 is_terminating_token(OnyxTokenType token_type);
-static OnyxToken* expect(OnyxParser* parser, OnyxTokenType token_type);
-static OnyxAstNodeScope* enter_scope(OnyxParser* parser);
-static OnyxAstNodeScope* leave_scope(OnyxParser* parser);
-static void insert_identifier(OnyxParser* parser, OnyxAstNode* ident, b32 is_local);
-static void remove_identifier(OnyxParser* parser, OnyxAstNode* ident);
-static OnyxAstNodeNumLit* parse_numeric_literal(OnyxParser* parser);
-static OnyxAstNode* parse_factor(OnyxParser* parser);
-static OnyxAstNode* parse_bin_op(OnyxParser* parser, OnyxAstNode* left);
-static OnyxAstNode* parse_expression(OnyxParser* parser);
-static OnyxAstNodeIf* parse_if_stmt(OnyxParser* parser);
-static OnyxAstNodeWhile* parse_while_stmt(OnyxParser* parser);
-static b32 parse_symbol_statement(OnyxParser* parser, OnyxAstNode** ret);
-static OnyxAstNode* parse_return_statement(OnyxParser* parser);
-static OnyxAstNodeBlock* parse_block(OnyxParser* parser);
-static OnyxAstNode* parse_statement(OnyxParser* parser);
-static OnyxTypeInfo* parse_type(OnyxParser* parser);
-static OnyxAstNodeParam* parse_function_params(OnyxParser* parser);
-static OnyxAstNodeFunction* parse_function_definition(OnyxParser* parser);
-static OnyxAstNode* parse_top_level_statement(OnyxParser* parser);
+static b32 is_terminating_token(TokenType token_type);
+static OnyxToken* expect(OnyxParser* parser, TokenType token_type);
+static AstNodeScope* enter_scope(OnyxParser* parser);
+static AstNodeScope* leave_scope(OnyxParser* parser);
+static void insert_identifier(OnyxParser* parser, AstNode* ident, b32 is_local);
+static void remove_identifier(OnyxParser* parser, AstNode* ident);
+static AstNodeNumLit* parse_numeric_literal(OnyxParser* parser);
+static AstNodeTyped* parse_factor(OnyxParser* parser);
+static AstNodeTyped* parse_bin_op(OnyxParser* parser, AstNode* left);
+static AstNodeTyped* parse_expression(OnyxParser* parser);
+static AstNodeIf* parse_if_stmt(OnyxParser* parser);
+static AstNodeWhile* parse_while_stmt(OnyxParser* parser);
+static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret);
+static AstNodeReturn* parse_return_statement(OnyxParser* parser);
+static AstNodeBlock* parse_block(OnyxParser* parser);
+static AstNode* parse_statement(OnyxParser* parser);
+static TypeInfo* parse_type(OnyxParser* parser);
+static AstNodeLocal* parse_function_params(OnyxParser* parser);
+static AstNodeFunction* parse_function_definition(OnyxParser* parser);
+static AstNode* parse_top_level_statement(OnyxParser* parser);
static void parser_next_token(OnyxParser* parser) {
parser->prev_token = parser->curr_token;
parser->prev_token--;
}
-static b32 is_terminating_token(OnyxTokenType token_type) {
+static b32 is_terminating_token(TokenType token_type) {
switch (token_type) {
case TOKEN_TYPE_SYM_SEMICOLON:
case TOKEN_TYPE_CLOSE_BRACE:
}
}
-static void find_token(OnyxParser* parser, OnyxTokenType token_type) {
+static void find_token(OnyxParser* parser, TokenType token_type) {
while (parser->curr_token->type != token_type && !is_terminating_token(parser->curr_token->type)) {
parser_next_token(parser);
}
}
// Advances to next token no matter what
-static OnyxToken* expect(OnyxParser* parser, OnyxTokenType token_type) {
+static OnyxToken* expect(OnyxParser* parser, TokenType token_type) {
OnyxToken* token = parser->curr_token;
parser_next_token(parser);
return token;
}
-static OnyxAstNodeNumLit* parse_numeric_literal(OnyxParser* parser) {
- OnyxAstNodeNumLit* lit_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LITERAL);
- lit_node->token = expect(parser, TOKEN_TYPE_LITERAL_NUMERIC);
- lit_node->flags |= ONYX_AST_FLAG_COMPTIME;
+static AstNodeNumLit* parse_numeric_literal(OnyxParser* parser) {
+ AstNodeNumLit* lit_node = make_node(AstNodeNumLit, AST_NODE_KIND_LITERAL);
+ lit_node->base.token = expect(parser, TOKEN_TYPE_LITERAL_NUMERIC);
+ lit_node->base.flags |= ONYX_AST_FLAG_COMPTIME;
lit_node->value.l = 0ll;
- onyx_token_null_toggle(*lit_node->token);
+ onyx_token_null_toggle(lit_node->base.token);
- OnyxTypeInfo* type;
- char* tok = lit_node->token->token;
+ TypeInfo* type;
+ char* tok = lit_node->base.token->token;
// NOTE: charset_contains() behaves more like string_contains()
// so I'm using it in this case
if (charset_contains(tok, '.')) {
- if (tok[lit_node->token->length - 1] == 'f') {
- type = &builtin_types[ONYX_TYPE_INFO_KIND_FLOAT32];
+ if (tok[lit_node->base.token->length - 1] == 'f') {
+ type = &builtin_types[TYPE_INFO_KIND_FLOAT32];
lit_node->value.f = strtof(tok, NULL);
} else {
- type = &builtin_types[ONYX_TYPE_INFO_KIND_FLOAT64];
+ type = &builtin_types[TYPE_INFO_KIND_FLOAT64];
lit_node->value.d = strtod(tok, NULL);
}
} else {
i64 value = strtoll(tok, NULL, 0);
if (bh_abs(value) < ((u64) 1 << 32)) {
- type = &builtin_types[ONYX_TYPE_INFO_KIND_INT32];
+ type = &builtin_types[TYPE_INFO_KIND_INT32];
} else {
- type = &builtin_types[ONYX_TYPE_INFO_KIND_INT64];
+ type = &builtin_types[TYPE_INFO_KIND_INT64];
}
lit_node->value.l = value;
}
- lit_node->type = type;
- onyx_token_null_toggle(*lit_node->token);
+ lit_node->base.type = type;
+ onyx_token_null_toggle(lit_node->base.token);
return lit_node;
}
-static OnyxAstNode* parse_factor(OnyxParser* parser) {
- OnyxAstNode* retval = NULL;
+static AstNodeTyped* parse_factor(OnyxParser* parser) {
+ AstNodeTyped* retval = NULL;
switch (parser->curr_token->type) {
case TOKEN_TYPE_OPEN_PAREN:
{
parser_next_token(parser);
- OnyxAstNode* expr = parse_expression(parser);
+ AstNodeTyped* expr = parse_expression(parser);
expect(parser, TOKEN_TYPE_CLOSE_PAREN);
retval = expr;
break;
case TOKEN_TYPE_SYM_MINUS:
{
parser_next_token(parser);
- OnyxAstNode* factor = parse_factor(parser);
+ AstNodeTyped* factor = parse_factor(parser);
- OnyxAstNodeUnaryOp* negate_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_UNARY_OP);
+ AstNodeUnaryOp* negate_node = make_node(AstNodeUnaryOp, AST_NODE_KIND_UNARY_OP);
negate_node->operation = ONYX_UNARY_OP_NEGATE;
- negate_node->left = factor;
- negate_node->type = factor->type;
+ negate_node->expr = factor;
if ((factor->flags & ONYX_AST_FLAG_COMPTIME) != 0) {
- negate_node->flags |= ONYX_AST_FLAG_COMPTIME;
+ negate_node->base.flags |= ONYX_AST_FLAG_COMPTIME;
}
- retval = (OnyxAstNode *) negate_node;
+ retval = (AstNodeTyped *) negate_node;
break;
}
case TOKEN_TYPE_SYMBOL:
{
OnyxToken* sym_token = expect(parser, TOKEN_TYPE_SYMBOL);
- OnyxAstNode* sym_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SYMBOL);
+ AstNodeTyped* sym_node = make_node(AstNode, AST_NODE_KIND_SYMBOL);
sym_node->token = sym_token;
if (parser->curr_token->type != TOKEN_TYPE_OPEN_PAREN) {
}
// NOTE: Function call
- OnyxAstNodeCall* call_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_CALL);
- call_node->token = expect(parser, TOKEN_TYPE_OPEN_PAREN);
- call_node->callee = sym_node;
- // NOTE: Return type is stored on function definition's type
- // This may have to change if we want multiple returns
- call_node->type = sym_node->type;
-
- OnyxAstNode** prev = &call_node->arguments;
- OnyxAstNode* curr = NULL;
+ AstNodeCall* call_node = make_node(AstNodeCall, AST_NODE_KIND_CALL);
+ call_node->base.token = expect(parser, TOKEN_TYPE_OPEN_PAREN);
+ call_node->callee = (AstNode *) sym_node;
+
+ AstNodeArgument** prev = &call_node->arguments;
+ AstNodeArgument* curr = NULL;
while (parser->curr_token->type != TOKEN_TYPE_CLOSE_PAREN) {
- curr = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ARGUMENT);
- curr->left = parse_expression(parser);
- curr->type = curr->left->type;
+ curr = make_node(AstNodeArgument, AST_NODE_KIND_ARGUMENT);
+ curr->value = parse_expression(parser);
- if (curr != NULL && curr->kind != ONYX_AST_NODE_KIND_ERROR) {
+ if (curr != NULL && curr->base.kind != AST_NODE_KIND_ERROR) {
*prev = curr;
- prev = &curr->next;
+ prev = (AstNodeArgument **) &curr->base.next;
}
if (parser->curr_token->type == TOKEN_TYPE_CLOSE_PAREN)
parser->curr_token->pos,
onyx_get_token_type_name(TOKEN_TYPE_SYM_COMMA),
onyx_get_token_type_name(parser->curr_token->type));
- return &error_node;
+ return (AstNodeTyped *) &error_node;
}
parser_next_token(parser);
}
parser_next_token(parser);
- retval = (OnyxAstNode *) call_node;
+ retval = (AstNodeTyped *) call_node;
break;
}
case TOKEN_TYPE_LITERAL_NUMERIC:
- retval = (OnyxAstNode *) parse_numeric_literal(parser);
+ retval = (AstNodeTyped *) parse_numeric_literal(parser);
break;
case TOKEN_TYPE_LITERAL_BOOL_TRUE:
{
- OnyxAstNodeNumLit* bool_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LITERAL);
- bool_node->type = &builtin_types[ONYX_TYPE_INFO_KIND_BOOL];
- bool_node->token = expect(parser, TOKEN_TYPE_LITERAL_BOOL_TRUE);
+ AstNodeNumLit* bool_node = make_node(AstNodeNumLit, AST_NODE_KIND_LITERAL);
+ bool_node->base.type = &builtin_types[TYPE_INFO_KIND_BOOL];
+ bool_node->base.token = expect(parser, TOKEN_TYPE_LITERAL_BOOL_TRUE);
bool_node->value.i = 1;
- retval = (OnyxAstNode *) bool_node;
+ retval = (AstNodeTyped *) bool_node;
break;
}
case TOKEN_TYPE_LITERAL_BOOL_FALSE:
{
- OnyxAstNodeNumLit* bool_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LITERAL);
- bool_node->type = &builtin_types[ONYX_TYPE_INFO_KIND_BOOL];
- bool_node->token = expect(parser, TOKEN_TYPE_LITERAL_BOOL_FALSE);
+ AstNodeNumLit* bool_node = make_node(AstNodeNumLit, AST_NODE_KIND_LITERAL);
+ bool_node->base.type = &builtin_types[TYPE_INFO_KIND_BOOL];
+ bool_node->base.token = expect(parser, TOKEN_TYPE_LITERAL_BOOL_FALSE);
bool_node->value.i = 0;
- retval = (OnyxAstNode *) bool_node;
+ retval = (AstNodeTyped *) bool_node;
break;
}
if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_CAST) {
parser_next_token(parser);
- OnyxAstNodeUnaryOp* cast_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_UNARY_OP);
+ AstNodeUnaryOp* cast_node = make_node(AstNodeUnaryOp, AST_NODE_KIND_UNARY_OP);
+ cast_node->base.type = parse_type(parser);
cast_node->operation = ONYX_UNARY_OP_CAST;
- cast_node->type = parse_type(parser);
- cast_node->left = retval;
- retval = (OnyxAstNode *) cast_node;
+ cast_node->expr = retval;
+ retval = (AstNodeTyped *) cast_node;
}
return retval;
}
}
-static OnyxAstNode* parse_expression(OnyxParser* parser) {
- bh_arr(OnyxAstNodeBinOp*) tree_stack = NULL;
+static AstNodeTyped* parse_expression(OnyxParser* parser) {
+ bh_arr(AstNodeBinOp*) tree_stack = NULL;
bh_arr_new(global_scratch_allocator, tree_stack, 4);
bh_arr_set_length(tree_stack, 0);
- OnyxAstNode* left = parse_factor(parser);
- OnyxAstNode* right;
- OnyxAstNode* root = left;
+ AstNodeTyped* left = parse_factor(parser);
+ AstNodeTyped* right;
+ AstNodeTyped* root = left;
OnyxBinaryOp bin_op_kind;
OnyxToken* bin_op_tok;
bin_op_tok = parser->curr_token;
parser_next_token(parser);
- OnyxAstNodeBinOp* bin_op = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_BIN_OP);
+ AstNodeBinOp* bin_op = make_node(AstNodeBinOp, AST_NODE_KIND_BIN_OP);
bin_op->operation = bin_op_kind;
- bin_op->token = bin_op_tok;
+ bin_op->base.token = bin_op_tok;
while ( !bh_arr_is_empty(tree_stack) &&
get_precedence(bh_arr_last(tree_stack)->operation) >= get_precedence(bin_op_kind))
if (bh_arr_is_empty(tree_stack)) {
// NOTE: new is now the root node
bin_op->left = root;
- root = (OnyxAstNode *) bin_op;
+ root = (AstNodeTyped *) bin_op;
} else {
bin_op->left = bh_arr_last(tree_stack)->right;
- bh_arr_last(tree_stack)->right = (OnyxAstNode *) bin_op;
+ bh_arr_last(tree_stack)->right = (AstNodeTyped *) bin_op;
}
bh_arr_push(tree_stack, bin_op);
right = parse_factor(parser);
bin_op->right = right;
- bin_op->type = right->type;
if ((left->flags & ONYX_AST_FLAG_COMPTIME) != 0 && (right->flags & ONYX_AST_FLAG_COMPTIME) != 0) {
- bin_op->flags |= ONYX_AST_FLAG_COMPTIME;
+ bin_op->base.flags |= ONYX_AST_FLAG_COMPTIME;
}
}
}
return root;
}
-static OnyxAstNodeIf* parse_if_stmt(OnyxParser* parser) {
+static AstNodeIf* parse_if_stmt(OnyxParser* parser) {
expect(parser, TOKEN_TYPE_KEYWORD_IF);
- OnyxAstNode* cond = parse_expression(parser);
- OnyxAstNode* true_block = (OnyxAstNode *) parse_block(parser);
+ AstNodeTyped* cond = parse_expression(parser);
+ AstNode* true_block = (AstNode *) parse_block(parser);
- OnyxAstNodeIf* if_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_IF);
- OnyxAstNodeIf* root_if = if_node;
+ AstNodeIf* if_node = make_node(AstNodeIf, AST_NODE_KIND_IF);
+ AstNodeIf* root_if = if_node;
if_node->cond = cond;
if (true_block != NULL)
while (parser->curr_token->type == TOKEN_TYPE_KEYWORD_ELSEIF) {
parser_next_token(parser);
- OnyxAstNodeIf* elseif_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_IF);
+ AstNodeIf* elseif_node = make_node(AstNodeIf, AST_NODE_KIND_IF);
cond = parse_expression(parser);
- true_block = (OnyxAstNode *) parse_block(parser);
+ true_block = (AstNode *) parse_block(parser);
elseif_node->cond = cond;
if (true_block != NULL)
elseif_node->true_block = true_block;
- if_node->false_block = (OnyxAstNode *) elseif_node;
+ if_node->false_block = (AstNode *) elseif_node;
if_node = elseif_node;
}
if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_ELSE) {
parser_next_token(parser);
- OnyxAstNode* false_block = (OnyxAstNode *) parse_block(parser);
+ AstNode* false_block = (AstNode *) parse_block(parser);
if (false_block != NULL)
if_node->false_block = false_block;
}
return root_if;
}
-static OnyxAstNodeWhile* parse_while_stmt(OnyxParser* parser) {
+static AstNodeWhile* parse_while_stmt(OnyxParser* parser) {
OnyxToken* while_token = expect(parser, TOKEN_TYPE_KEYWORD_WHILE);
- OnyxAstNode* cond = parse_expression(parser);
- OnyxAstNodeBlock* body = parse_block(parser);
+ AstNodeTyped* cond = parse_expression(parser);
+ AstNodeBlock* body = parse_block(parser);
- OnyxAstNodeWhile* while_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_WHILE);
- while_node->token = while_token;
+ AstNodeWhile* while_node = make_node(AstNodeWhile, AST_NODE_KIND_WHILE);
+ while_node->base.token = while_token;
while_node->cond = cond;
while_node->body = body;
// Returns 1 if the symbol was consumed. Returns 0 otherwise
// ret is set to the statement to insert
-static b32 parse_symbol_statement(OnyxParser* parser, OnyxAstNode** ret) {
+static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret) {
if (parser->curr_token->type != TOKEN_TYPE_SYMBOL) return 0;
OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL);
case TOKEN_TYPE_SYM_COLON:
{
parser_next_token(parser);
- OnyxTypeInfo* type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+ TypeInfo* type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
// NOTE: var: type
if (parser->curr_token->type == TOKEN_TYPE_SYMBOL) {
type = parse_type(parser);
}
- OnyxAstNodeLocal* local = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LOCAL);
- local->token = symbol;
- local->type = type;
- local->flags |= ONYX_AST_FLAG_LVAL; // NOTE: DELETE
- *ret = (OnyxAstNode *) local;
+ AstNodeLocal* local = make_node(AstNodeLocal, AST_NODE_KIND_LOCAL);
+ local->base.token = symbol;
+ local->base.type = type;
+ local->base.flags |= ONYX_AST_FLAG_LVAL; // NOTE: DELETE
+ *ret = (AstNode *) local;
if (parser->curr_token->type == TOKEN_TYPE_SYM_EQUALS || parser->curr_token->type == TOKEN_TYPE_SYM_COLON) {
if (parser->curr_token->type == TOKEN_TYPE_SYM_COLON) {
- local->flags |= ONYX_AST_FLAG_CONST;
+ local->base.flags |= ONYX_AST_FLAG_CONST;
}
- OnyxAstNode* assignment = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ASSIGNMENT);
- local->next = assignment;
- assignment->token = parser->curr_token;
+ AstNodeAssign* assignment = make_node(AstNodeAssign, AST_NODE_KIND_ASSIGNMENT);
+ local->base.next = (AstNode *) assignment;
+ assignment->base.token = parser->curr_token;
parser_next_token(parser);
- OnyxAstNode* expr = parse_expression(parser);
+ AstNodeTyped* expr = parse_expression(parser);
if (expr == NULL) {
- onyx_token_null_toggle(*parser->curr_token);
+ onyx_token_null_toggle(parser->curr_token);
onyx_message_add(parser->msgs,
ONYX_MESSAGE_TYPE_EXPECTED_EXPRESSION,
- assignment->token->pos,
+ assignment->base.token->pos,
parser->curr_token->token);
- onyx_token_null_toggle(*parser->curr_token);
+ onyx_token_null_toggle(parser->curr_token);
return 1;
}
- assignment->right = expr;
+ assignment->expr = expr;
- OnyxAstNode* left_symbol = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SYMBOL);
+ AstNode* left_symbol = make_node(AstNode, AST_NODE_KIND_SYMBOL);
left_symbol->token = symbol;
- assignment->left = left_symbol;
+ assignment->lval = (AstNodeTyped *) left_symbol;
}
return 1;
}
// NOTE: Assignment
case TOKEN_TYPE_SYM_EQUALS:
{
- OnyxAstNode* assignment = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ASSIGNMENT);
- assignment->token = parser->curr_token;
+ AstNodeAssign* assignment = make_node(AstNodeAssign, AST_NODE_KIND_ASSIGNMENT);
+ assignment->base.token = parser->curr_token;
parser_next_token(parser);
- OnyxAstNode* lval = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SYMBOL);
+ AstNode* lval = make_node(AstNode, AST_NODE_KIND_SYMBOL);
lval->token = symbol;
- OnyxAstNode* rval = parse_expression(parser);
- assignment->right = rval;
- assignment->left = lval;
- *ret = assignment;
+ AstNodeTyped* rval = parse_expression(parser);
+ assignment->expr = rval;
+ assignment->lval = (AstNodeTyped *) lval;
+ *ret = (AstNode *) assignment;
return 1;
}
return 0;
}
-static OnyxAstNode* parse_return_statement(OnyxParser* parser) {
- OnyxAstNode* return_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_RETURN);
- return_node->token = expect(parser, TOKEN_TYPE_KEYWORD_RETURN);
+static AstNodeReturn* parse_return_statement(OnyxParser* parser) {
+ AstNodeReturn* return_node = make_node(AstNodeReturn, AST_NODE_KIND_RETURN);
+ return_node->base.token = expect(parser, TOKEN_TYPE_KEYWORD_RETURN);
- OnyxAstNode* expr = NULL;
+ AstNodeTyped* expr = NULL;
if (parser->curr_token->type != TOKEN_TYPE_SYM_SEMICOLON) {
expr = parse_expression(parser);
- if (expr == NULL || expr == &error_node) {
- return &error_node;
+ if (expr == NULL || expr == (AstNodeTyped *) &error_node) {
+ return (AstNodeReturn *) &error_node;
} else {
- return_node->left = expr;
+ return_node->expr = expr;
}
}
return return_node;
}
-static OnyxAstNode* parse_statement(OnyxParser* parser) {
+static AstNode* parse_statement(OnyxParser* parser) {
b32 needs_semicolon = 1;
- OnyxAstNode* retval = NULL;
+ AstNode* retval = NULL;
switch (parser->curr_token->type) {
case TOKEN_TYPE_KEYWORD_RETURN:
- retval = parse_return_statement(parser);
+ retval = (AstNode *) parse_return_statement(parser);
break;
case TOKEN_TYPE_OPEN_BRACE:
needs_semicolon = 0;
- retval = (OnyxAstNode *) parse_block(parser);
+ retval = (AstNode *) parse_block(parser);
break;
case TOKEN_TYPE_SYMBOL:
case TOKEN_TYPE_SYM_BANG:
case TOKEN_TYPE_LITERAL_NUMERIC:
case TOKEN_TYPE_LITERAL_STRING:
- retval = parse_expression(parser);
+ retval = (AstNode *) parse_expression(parser);
break;
case TOKEN_TYPE_KEYWORD_IF:
needs_semicolon = 0;
- retval = (OnyxAstNode *) parse_if_stmt(parser);
+ retval = (AstNode *) parse_if_stmt(parser);
break;
case TOKEN_TYPE_KEYWORD_WHILE:
needs_semicolon = 0;
- retval = (OnyxAstNode *) parse_while_stmt(parser);
+ retval = (AstNode *) parse_while_stmt(parser);
break;
case TOKEN_TYPE_KEYWORD_BREAK:
- retval = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_BREAK);
+ retval = make_node(AstNode, AST_NODE_KIND_BREAK);
retval->token = expect(parser, TOKEN_TYPE_KEYWORD_BREAK);
break;
case TOKEN_TYPE_KEYWORD_CONTINUE:
- retval = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_CONTINUE);
+ retval = make_node(AstNode, AST_NODE_KIND_BREAK);
retval->token = expect(parser, TOKEN_TYPE_KEYWORD_CONTINUE);
break;
return retval;
}
-static OnyxAstNodeBlock* parse_block(OnyxParser* parser) {
- OnyxAstNodeBlock* block = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_BLOCK);
- OnyxAstNodeScope* scope = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SCOPE);
+static AstNodeBlock* parse_block(OnyxParser* parser) {
+ AstNodeBlock* block = make_node(AstNodeBlock, AST_NODE_KIND_BLOCK);
+ AstNodeScope* scope = make_node(AstNodeScope, AST_NODE_KIND_SCOPE);
block->scope = scope;
// --- is for an empty block
expect(parser, TOKEN_TYPE_OPEN_BRACE);
- OnyxAstNode** next = &block->body;
- OnyxAstNode* stmt = NULL;
+ AstNode** next = &block->body;
+ AstNode* stmt = NULL;
while (parser->curr_token->type != TOKEN_TYPE_CLOSE_BRACE) {
stmt = parse_statement(parser);
- if (stmt != NULL && stmt->kind != ONYX_AST_NODE_KIND_ERROR) {
+ if (stmt != NULL && stmt->kind != AST_NODE_KIND_ERROR) {
*next = stmt;
while (stmt->next != NULL) stmt = stmt->next;
return block;
}
-static OnyxTypeInfo* parse_type(OnyxParser* parser) {
- OnyxTypeInfo* type_info = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+static TypeInfo* parse_type(OnyxParser* parser) {
+ TypeInfo* type_info = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL);
if (symbol == NULL) return type_info;
- onyx_token_null_toggle(*symbol);
+ onyx_token_null_toggle(symbol);
- if (!bh_table_has(OnyxAstNode*, parser->identifiers, symbol->token)) {
+ if (!bh_table_has(AstNode*, parser->identifiers, symbol->token)) {
onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_UNKNOWN_TYPE, symbol->pos, symbol->token);
} else {
- OnyxAstNode* type_info_node = bh_table_get(OnyxAstNode*, parser->identifiers, symbol->token);
+ AstNodeTyped* type_info_node = bh_table_get(AstNodeTyped*, parser->identifiers, symbol->token);
- if (type_info_node->kind == ONYX_AST_NODE_KIND_TYPE) {
+ if (type_info_node->kind == AST_NODE_KIND_TYPE) {
type_info = type_info_node->type;
}
}
- onyx_token_null_toggle(*symbol);
+ onyx_token_null_toggle(symbol);
return type_info;
}
-static OnyxAstNodeParam* parse_function_params(OnyxParser* parser) {
+static AstNodeLocal* parse_function_params(OnyxParser* parser) {
if (parser->curr_token->type != TOKEN_TYPE_OPEN_PAREN)
return NULL;
return NULL;
}
- OnyxAstNodeParam* first_param = NULL;
- OnyxAstNodeParam* curr_param = NULL;
- OnyxAstNodeParam* trailer = NULL;
+ AstNodeLocal* first_param = NULL;
+ AstNodeLocal* curr_param = NULL;
+ AstNodeLocal* trailer = NULL;
OnyxToken* symbol;
while (parser->curr_token->type != TOKEN_TYPE_CLOSE_PAREN) {
symbol = expect(parser, TOKEN_TYPE_SYMBOL);
expect(parser, TOKEN_TYPE_SYM_COLON);
- curr_param = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PARAM);
- curr_param->token = symbol;
- curr_param->type = parse_type(parser);
- curr_param->flags |= ONYX_AST_FLAG_CONST;
+ curr_param = make_node(AstNodeLocal, AST_NODE_KIND_PARAM);
+ curr_param->base.token = symbol;
+ curr_param->base.flags |= ONYX_AST_FLAG_CONST;
+ curr_param->base.type = parse_type(parser);
if (first_param == NULL) first_param = curr_param;
- curr_param->next = NULL;
- if (trailer) trailer->next = curr_param;
+ curr_param->base.next = NULL;
+ if (trailer) trailer->base.next = (AstNode *) curr_param;
trailer = curr_param;
}
return first_param;
}
-static OnyxAstNodeFunction* parse_function_definition(OnyxParser* parser) {
+static AstNodeFunction* parse_function_definition(OnyxParser* parser) {
expect(parser, TOKEN_TYPE_KEYWORD_PROC);
- OnyxAstNodeFunction* func_def = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_FUNCTION);
+ AstNodeFunction* func_def = make_node(AstNodeFunction, AST_NODE_KIND_FUNCTION);
- OnyxAstNodeParam* params = parse_function_params(parser);
+ AstNodeLocal* params = parse_function_params(parser);
func_def->params = params;
if (parser->curr_token->type == TOKEN_TYPE_RIGHT_ARROW) {
expect(parser, TOKEN_TYPE_RIGHT_ARROW);
- OnyxTypeInfo* return_type = parse_type(parser);
- func_def->return_type = return_type;
+ TypeInfo* return_type = parse_type(parser);
+ func_def->base.type = return_type;
} else {
- func_def->return_type = &builtin_types[ONYX_TYPE_INFO_KIND_VOID];
+ func_def->base.type = &builtin_types[TYPE_INFO_KIND_VOID];
}
func_def->body = parse_block(parser);
return func_def;
}
-static OnyxAstNode* parse_foreign(OnyxParser* parser) {
+static AstNode* parse_foreign(OnyxParser* parser) {
expect(parser, TOKEN_TYPE_KEYWORD_FOREIGN);
- OnyxAstNodeForeign* foreign = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_FOREIGN);
+ AstNodeForeign* foreign = make_node(AstNodeForeign, 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) {
- foreign->import = (OnyxAstNode *) parse_function_definition(parser);
+ foreign->import = (AstNode *) parse_function_definition(parser);
} else {
- OnyxTypeInfo* type = parse_type(parser);
+ TypeInfo* 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;
+ AstNodeGlobal* global = make_node(AstNodeGlobal, AST_NODE_KIND_GLOBAL);
+ global->base.type = type;
+ global->base.flags |= ONYX_AST_FLAG_LVAL;
- foreign->import = (OnyxAstNode *) global;
+ foreign->import = (AstNode *) global;
}
- return (OnyxAstNode *) foreign;
+ return (AstNode *) foreign;
}
-static OnyxAstNode* parse_top_level_constant_symbol(OnyxParser* parser) {
+static AstNode* parse_top_level_constant_symbol(OnyxParser* parser) {
if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) {
- return (OnyxAstNode *) parse_function_definition(parser);
+ return (AstNode *) 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) {
- return (OnyxAstNode *) parse_foreign(parser);
+ return (AstNode *) parse_foreign(parser);
} else {
// Global constant with initial value
- OnyxAstNodeGlobal* global = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_GLOBAL);
+ AstNodeGlobal* global = make_node(AstNodeGlobal, 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;
+ global->base.type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
+ global->base.flags |= ONYX_AST_FLAG_CONST;
+ global->base.flags |= ONYX_AST_FLAG_LVAL;
+ global->base.flags |= ONYX_AST_FLAG_COMPTIME;
- return (OnyxAstNode *) global;
+ return (AstNode *) global;
}
}
-static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) {
+static AstNode* parse_top_level_statement(OnyxParser* parser) {
switch (parser->curr_token->type) {
case TOKEN_TYPE_KEYWORD_USE:
{
- OnyxAstNodeUse* use_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_USE);
- use_node->token = expect(parser, TOKEN_TYPE_KEYWORD_USE);
+ AstNodeUse* use_node = make_node(AstNodeUse, AST_NODE_KIND_USE);
+ use_node->base.token = expect(parser, TOKEN_TYPE_KEYWORD_USE);
use_node->filename = expect(parser, TOKEN_TYPE_LITERAL_STRING);
- return (OnyxAstNode *) use_node;
+ return (AstNode *) use_node;
}
case TOKEN_TYPE_KEYWORD_EXPORT:
break;
}
- OnyxAstNode* top_level_decl = parse_top_level_statement(parser);
+ AstNode* top_level_decl = parse_top_level_statement(parser);
top_level_decl->flags |= ONYX_AST_FLAG_EXPORTED;
return top_level_decl;
}
expect(parser, TOKEN_TYPE_SYM_COLON);
- OnyxTypeInfo* type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+ TypeInfo* type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
if (parser->curr_token->type == TOKEN_TYPE_SYMBOL) {
type = parse_type(parser);
if (parser->curr_token->type == TOKEN_TYPE_SYM_COLON) {
parser_next_token(parser);
- OnyxAstNode* node = parse_top_level_constant_symbol(parser);
+ AstNode* node = parse_top_level_constant_symbol(parser);
- if (node->kind == ONYX_AST_NODE_KIND_GLOBAL) {
- node->type = type;
+ if (node->kind == AST_NODE_KIND_GLOBAL) {
+ ((AstNodeGlobal *) node)->base.type = type;
}
- if (node->kind == ONYX_AST_NODE_KIND_FOREIGN) {
- node->as_foreign.import->token = symbol;
+ if (node->kind == AST_NODE_KIND_FOREIGN) {
+ ((AstNodeForeign *) node)->import->token = symbol;
} else {
node->token = symbol;
} 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;
+ AstNodeGlobal* global = make_node(AstNodeGlobal, AST_NODE_KIND_GLOBAL);
+ global->base.token = symbol;
+ global->base.flags |= ONYX_AST_FLAG_LVAL;
global->initial_value = parse_expression(parser);
- global->type = type;
+ global->base.type = type;
- return (OnyxAstNode *) global;
+ return (AstNode *) global;
} else {
- onyx_token_null_toggle(*parser->curr_token);
+ 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);
+ onyx_token_null_toggle(parser->curr_token);
}
return &error_node;
-const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind) {
+const char* onyx_ast_node_kind_string(AstNodeKind kind) {
return ast_node_names[kind];
}
// NOTE: This returns a void* so I don't need to cast it everytime I use it
-void* onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind) {
- OnyxAstNode* node = bh_alloc_item(alloc, OnyxAstNode);
- node->kind = kind;
- node->flags = 0;
- node->token = NULL;
- node->type = NULL;
- node->data = 0;
- node->next = NULL;
- node->left = NULL;
- node->right = NULL;
+void* onyx_ast_node_new(bh_allocator alloc, i32 size, AstNodeKind kind) {
+ void* node = bh_alloc(alloc, size);
+
+ memset(node, 0, size);
+ *(AstNodeKind *) node = kind;
return node;
}
bh_table_init(bh_heap_allocator(), parser.identifiers, 61);
- OnyxTypeInfo* it = &builtin_types[0];
+ TypeInfo* it = &builtin_types[0];
while (it->kind != 0xffffffff) {
- OnyxAstNode* tmp = onyx_ast_node_new(alloc, ONYX_AST_NODE_KIND_TYPE);
+ AstNodeTyped* tmp = onyx_ast_node_new(alloc, sizeof(AstNodeTyped), AST_NODE_KIND_TYPE);
tmp->type = it;
- bh_table_put(OnyxAstNode*, parser.identifiers, (char *)it->name, tmp);
+ bh_table_put(AstNode*, parser.identifiers, (char *)it->name, tmp);
it++;
}
bh_table_free(parser->identifiers);
}
-OnyxAstNode* onyx_parse(OnyxParser *parser) {
- OnyxAstNode* program = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PROGRAM);
+AstNode* onyx_parse(OnyxParser *parser) {
+ AstNode* program = make_node(AstNode, AST_NODE_KIND_PROGRAM);
- OnyxAstNode** prev_stmt = &program->next;
- OnyxAstNode* curr_stmt = NULL;
+ AstNode** prev_stmt = &program->next;
+ AstNode* curr_stmt = NULL;
while (parser->curr_token->type != TOKEN_TYPE_END_STREAM) {
curr_stmt = parse_top_level_statement(parser);
.symbols = NULL,
};
- bh_table_init(bh_heap_allocator(), state.symbols, 61);
+ bh_table_init(global_heap_allocator, state.symbols, 61);
return state;
}
// defined in sub-scopes up to the function-block level. This is a
// requirement of WASM, but not of other targets.
static void collapse_scopes(OnyxProgram* program) {
- bh_arr(OnyxAstNodeBlock*) traversal_queue = NULL;
+ bh_arr(AstNodeBlock*) traversal_queue = NULL;
bh_arr_new(global_scratch_allocator, traversal_queue, 4);
bh_arr_set_length(traversal_queue, 0);
- bh_arr_each(OnyxAstNodeFunction *, func, program->functions) {
- OnyxAstNodeScope* top_scope = (*func)->body->scope;
+ bh_arr_each(AstNodeFunction *, func, program->functions) {
+ AstNodeScope* top_scope = (*func)->body->scope;
bh_arr_push(traversal_queue, (*func)->body);
while (!bh_arr_is_empty(traversal_queue)) {
- OnyxAstNodeBlock* block = traversal_queue[0];
+ AstNodeBlock* block = traversal_queue[0];
- if (block->kind == ONYX_AST_NODE_KIND_IF) {
- OnyxAstNodeIf* if_node = (OnyxAstNodeIf *) block;
+ if (block->base.kind == AST_NODE_KIND_IF) {
+ AstNodeIf* if_node = (AstNodeIf *) block;
if (if_node->true_block)
- bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) if_node->true_block);
+ bh_arr_push(traversal_queue, (AstNodeBlock *) if_node->true_block);
if (if_node->false_block)
- bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) if_node->false_block);
+ bh_arr_push(traversal_queue, (AstNodeBlock *) if_node->false_block);
} else {
if (block->scope != top_scope && block->scope->last_local != NULL) {
- OnyxAstNodeLocal* last_local = block->scope->last_local;
+ AstNodeLocal* last_local = block->scope->last_local;
while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local;
last_local->prev_local = top_scope->last_local;
block->scope->last_local = NULL;
}
- OnyxAstNode* walker = block->body;
+ AstNode* walker = block->body;
while (walker) {
- if (walker->kind == ONYX_AST_NODE_KIND_BLOCK) {
- bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker);
+ if (walker->kind == AST_NODE_KIND_BLOCK) {
+ bh_arr_push(traversal_queue, (AstNodeBlock *) walker);
- } else if (walker->kind == ONYX_AST_NODE_KIND_WHILE) {
- bh_arr_push(traversal_queue, walker->as_while.body);
+ } else if (walker->kind == AST_NODE_KIND_WHILE) {
+ bh_arr_push(traversal_queue, ((AstNodeWhile *) walker)->body);
- } else if (walker->kind == ONYX_AST_NODE_KIND_IF) {
- if (walker->as_if.true_block)
- bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker->as_if.true_block);
+ } else if (walker->kind == AST_NODE_KIND_IF) {
+ if (((AstNodeIf *) walker)->true_block)
+ bh_arr_push(traversal_queue, (AstNodeBlock *) ((AstNodeIf *) walker)->true_block);
- if (walker->as_if.false_block)
- bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker->as_if.false_block);
+ if (((AstNodeIf *) walker)->false_block)
+ bh_arr_push(traversal_queue, (AstNodeBlock *) ((AstNodeIf *) walker)->false_block);
}
walker = walker->next;
#define BH_DEBUG
#include "onyxsempass.h"
-static void symbol_introduce(OnyxSemPassState* state, OnyxAstNode* symbol);
-static b32 symbol_unique_introduce(OnyxSemPassState* state, OnyxAstNode* symbol);
-static void symbol_remove(OnyxSemPassState* state, OnyxAstNode* symbol);
-static OnyxAstNode* symbol_resolve(OnyxSemPassState* state, OnyxAstNode* symbol);
-static void scope_enter(OnyxSemPassState* state, OnyxAstNodeScope* scope);
-static OnyxAstNodeScope* scope_leave(OnyxSemPassState* state);
-static void symres_local(OnyxSemPassState* state, OnyxAstNodeLocal** local);
-static void symres_call(OnyxSemPassState* state, OnyxAstNode* call);
-static void symres_expression(OnyxSemPassState* state, OnyxAstNode** expr);
-static void symres_assignment(OnyxSemPassState* state, OnyxAstNode* assign);
-static void symres_return(OnyxSemPassState* state, OnyxAstNode* ret);
-static void symres_if(OnyxSemPassState* state, OnyxAstNodeIf* ifnode);
-static void symres_while(OnyxSemPassState* state, OnyxAstNodeWhile* whilenode);
-static void symres_statement_chain(OnyxSemPassState* state, OnyxAstNode* walker, OnyxAstNode** trailer);
-static b32 symres_statement(OnyxSemPassState* state, OnyxAstNode* stmt);
-static void symres_block(OnyxSemPassState* state, OnyxAstNodeBlock* block);
-static void symres_function(OnyxSemPassState* state, OnyxAstNodeFunction* func);
-
-static void symbol_introduce(OnyxSemPassState* state, OnyxAstNode* symbol) {
- onyx_token_null_toggle(*symbol->token);
+static void symbol_introduce(OnyxSemPassState* state, AstNode* symbol);
+static b32 symbol_unique_introduce(OnyxSemPassState* state, AstNode* symbol);
+static void symbol_remove(OnyxSemPassState* state, AstNode* symbol);
+static AstNode* symbol_resolve(OnyxSemPassState* state, AstNode* symbol);
+static void scope_enter(OnyxSemPassState* state, AstNodeScope* scope);
+static AstNodeScope* scope_leave(OnyxSemPassState* state);
+static void symres_local(OnyxSemPassState* state, AstNodeLocal** local);
+static void symres_call(OnyxSemPassState* state, AstNodeCall* call);
+static void symres_expression(OnyxSemPassState* state, AstNode** expr);
+static void symres_assignment(OnyxSemPassState* state, AstNodeAssign* assign);
+static void symres_return(OnyxSemPassState* state, AstNodeReturn* ret);
+static void symres_if(OnyxSemPassState* state, AstNodeIf* ifnode);
+static void symres_while(OnyxSemPassState* state, AstNodeWhile* whilenode);
+static void symres_statement_chain(OnyxSemPassState* state, AstNode* walker, AstNode** trailer);
+static b32 symres_statement(OnyxSemPassState* state, AstNode* stmt);
+static void symres_block(OnyxSemPassState* state, AstNodeBlock* block);
+static void symres_function(OnyxSemPassState* state, AstNodeFunction* func);
+
+static void symbol_introduce(OnyxSemPassState* state, AstNode* symbol) {
+ onyx_token_null_toggle(symbol->token);
SemPassSymbol* sp_sym = (SemPassSymbol *) bh_alloc_item(state->allocator, SemPassSymbol);
sp_sym->node = symbol;
bh_table_put(SemPassSymbol *, state->symbols, symbol->token->token, sp_sym);
- if (symbol->kind == ONYX_AST_NODE_KIND_LOCAL) {
- OnyxAstNodeLocal* local = &symbol->as_local;
+ if (symbol->kind == AST_NODE_KIND_LOCAL) {
+ AstNodeLocal* local = (AstNodeLocal *) symbol;
local->prev_local = state->curr_scope->last_local;
state->curr_scope->last_local = local;
}
- onyx_token_null_toggle(*symbol->token);
+ onyx_token_null_toggle(symbol->token);
}
-static void symbol_remove(OnyxSemPassState* state, OnyxAstNode* symbol) {
- onyx_token_null_toggle(*symbol->token);
+static void symbol_remove(OnyxSemPassState* state, AstNode* symbol) {
+ onyx_token_null_toggle(symbol->token);
SemPassSymbol* sp_sym = bh_table_get(SemPassSymbol *, state->symbols, symbol->token->token);
bh_table_delete(SemPassSymbol *, state->symbols, symbol->token->token);
}
- onyx_token_null_toggle(*symbol->token);
+ onyx_token_null_toggle(symbol->token);
}
-static OnyxAstNode* symbol_resolve(OnyxSemPassState* state, OnyxAstNode* symbol) {
- onyx_token_null_toggle(*symbol->token);
+static AstNode* symbol_resolve(OnyxSemPassState* state, AstNode* symbol) {
+ onyx_token_null_toggle(symbol->token);
if (!bh_table_has(SemPassSymbol *, state->symbols, symbol->token->token)) {
onyx_message_add(state->msgs,
symbol->token->pos,
symbol->token->token);
- onyx_token_null_toggle(*symbol->token);
+ onyx_token_null_toggle(symbol->token);
return symbol;
}
SemPassSymbol* sp_sym = bh_table_get(SemPassSymbol *, state->symbols, symbol->token->token);
- onyx_token_null_toggle(*symbol->token);
+ onyx_token_null_toggle(symbol->token);
return sp_sym->node;
}
-static void scope_enter(OnyxSemPassState* state, OnyxAstNodeScope* scope) {
+static void scope_enter(OnyxSemPassState* state, AstNodeScope* scope) {
scope->prev_scope = state->curr_scope;
state->curr_scope = scope;
}
-static OnyxAstNodeScope* scope_leave(OnyxSemPassState* state) {
+static AstNodeScope* scope_leave(OnyxSemPassState* state) {
// NOTE: Can't leave a scope if there is no scope
assert(state->curr_scope != NULL);
- for (OnyxAstNodeLocal *walker = state->curr_scope->last_local; walker != NULL; walker = walker->prev_local) {
- symbol_remove(state, (OnyxAstNode *) walker);
+ for (AstNodeLocal *walker = state->curr_scope->last_local; walker != NULL; walker = walker->prev_local) {
+ symbol_remove(state, (AstNode *) walker);
}
state->curr_scope = state->curr_scope->prev_scope;
return state->curr_scope;
}
-static b32 symbol_unique_introduce(OnyxSemPassState* state, OnyxAstNode* symbol) {
- onyx_token_null_toggle(*symbol->token);
+static b32 symbol_unique_introduce(OnyxSemPassState* state, AstNode* symbol) {
+ onyx_token_null_toggle(symbol->token);
// NOTE: If the function hasn't already been defined
if (!bh_table_has(SemPassSymbol *, state->symbols, symbol->token->token)) {
symbol->token->token);
// NOTE: I really wish C had defer...
- onyx_token_null_toggle(*symbol->token);
+ onyx_token_null_toggle(symbol->token);
return 0;
}
- onyx_token_null_toggle(*symbol->token);
+ onyx_token_null_toggle(symbol->token);
return 1;
}
-static void symres_local(OnyxSemPassState* state, OnyxAstNodeLocal** local) {
- symbol_introduce(state, (OnyxAstNode *) *local);
+static void symres_local(OnyxSemPassState* state, AstNodeLocal** local) {
+ symbol_introduce(state, (AstNode *) *local);
}
-static void symres_call(OnyxSemPassState* state, OnyxAstNode* stmt) {
- OnyxAstNodeCall* call = &stmt->as_call;
-
- OnyxAstNode* callee = symbol_resolve(state, call->callee);
+static void symres_call(OnyxSemPassState* state, AstNodeCall* call) {
+ AstNode* callee = symbol_resolve(state, call->callee);
if (callee) call->callee = callee;
else DEBUG_HERE;
- symres_statement_chain(state, call->arguments, &call->arguments);
+ symres_statement_chain(state, (AstNode *) call->arguments, (AstNode **) &call->arguments);
}
-static void symres_expression(OnyxSemPassState* state, OnyxAstNode** expr) {
+static void symres_expression(OnyxSemPassState* state, AstNode** expr) {
switch ((*expr)->kind) {
- case ONYX_AST_NODE_KIND_BIN_OP:
- symres_expression(state, &(*expr)->left);
- symres_expression(state, &(*expr)->right);
+ case AST_NODE_KIND_BIN_OP:
+ symres_expression(state, (AstNode **) &((AstNodeBinOp *)(*expr))->left);
+ symres_expression(state, (AstNode **) &((AstNodeBinOp *)(*expr))->right);
break;
- case ONYX_AST_NODE_KIND_UNARY_OP:
- symres_expression(state, &(*expr)->left);
+ case AST_NODE_KIND_UNARY_OP:
+ symres_expression(state, (AstNode **) &((AstNodeUnaryOp *)(*expr))->expr);
break;
- case ONYX_AST_NODE_KIND_CALL: symres_call(state, *expr); break;
+ case AST_NODE_KIND_CALL: symres_call(state, (AstNodeCall *) *expr); break;
- case ONYX_AST_NODE_KIND_BLOCK: symres_block(state, &(*expr)->as_block); break;
+ case AST_NODE_KIND_BLOCK: symres_block(state, (AstNodeBlock *) *expr); break;
- case ONYX_AST_NODE_KIND_SYMBOL:
+ case AST_NODE_KIND_SYMBOL:
*expr = symbol_resolve(state, *expr);
break;
// NOTE: This is a good case, since it means the symbol is already resolved
- case ONYX_AST_NODE_KIND_LOCAL: break;
+ case AST_NODE_KIND_LOCAL: break;
- case ONYX_AST_NODE_KIND_LITERAL: break;
+ case AST_NODE_KIND_LITERAL: break;
default:
DEBUG_HERE;
}
}
-static void symres_assignment(OnyxSemPassState* state, OnyxAstNode* assign) {
- OnyxAstNode* lval = symbol_resolve(state, assign->left);
+static void symres_assignment(OnyxSemPassState* state, AstNodeAssign* assign) {
+ AstNodeTyped* lval = (AstNodeTyped *) symbol_resolve(state, (AstNode *) assign->lval);
if (lval == NULL) return;
- assign->left = lval;
+ assign->lval = lval;
- symres_expression(state, &assign->right);
+ symres_expression(state, (AstNode **) &assign->expr);
}
-static void symres_return(OnyxSemPassState* state, OnyxAstNode* ret) {
- if (ret->left)
- symres_expression(state, &ret->left);
+static void symres_return(OnyxSemPassState* state, AstNodeReturn* ret) {
+ if (ret->expr)
+ symres_expression(state, (AstNode **) &ret->expr);
}
-static void symres_if(OnyxSemPassState* state, OnyxAstNodeIf* ifnode) {
- symres_expression(state, &ifnode->cond);
+static void symres_if(OnyxSemPassState* state, AstNodeIf* ifnode) {
+ symres_expression(state, (AstNode **) &ifnode->cond);
if (ifnode->true_block) {
- if (ifnode->true_block->kind == ONYX_AST_NODE_KIND_BLOCK)
- symres_block(state, &ifnode->true_block->as_block);
+ if (ifnode->true_block->kind == AST_NODE_KIND_BLOCK)
+ symres_block(state, (AstNodeBlock *) ifnode->true_block);
- else if (ifnode->true_block->kind == ONYX_AST_NODE_KIND_IF)
- symres_if(state, &ifnode->true_block->as_if);
+ else if (ifnode->true_block->kind == AST_NODE_KIND_IF)
+ symres_if(state, (AstNodeIf *) ifnode->true_block);
else DEBUG_HERE;
}
if (ifnode->false_block) {
- if (ifnode->false_block->kind == ONYX_AST_NODE_KIND_BLOCK)
- symres_block(state, &ifnode->false_block->as_block);
+ if (ifnode->false_block->kind == AST_NODE_KIND_BLOCK)
+ symres_block(state, (AstNodeBlock *) ifnode->false_block);
- else if (ifnode->false_block->kind == ONYX_AST_NODE_KIND_IF)
- symres_if(state, &ifnode->false_block->as_if);
+ else if (ifnode->false_block->kind == AST_NODE_KIND_IF)
+ symres_if(state, (AstNodeIf *) ifnode->false_block);
else DEBUG_HERE;
}
}
-static void symres_while(OnyxSemPassState* state, OnyxAstNodeWhile* whilenode) {
- symres_expression(state, &whilenode->cond);
+static void symres_while(OnyxSemPassState* state, AstNodeWhile* whilenode) {
+ symres_expression(state, (AstNode **) &whilenode->cond);
symres_block(state, whilenode->body);
}
// NOTE: Returns 1 if the statment should be removed
-static b32 symres_statement(OnyxSemPassState* state, OnyxAstNode* stmt) {
+static b32 symres_statement(OnyxSemPassState* state, AstNode* stmt) {
switch (stmt->kind) {
- case ONYX_AST_NODE_KIND_LOCAL: symres_local(state, (OnyxAstNodeLocal **) &stmt); return 1;
- case ONYX_AST_NODE_KIND_ASSIGNMENT: symres_assignment(state, stmt); return 0;
- case ONYX_AST_NODE_KIND_RETURN: symres_return(state, stmt); return 0;
- case ONYX_AST_NODE_KIND_IF: symres_if(state, &stmt->as_if); return 0;
- case ONYX_AST_NODE_KIND_WHILE: symres_while(state, &stmt->as_while); return 0;
- case ONYX_AST_NODE_KIND_CALL: symres_call(state, stmt); return 0;
- case ONYX_AST_NODE_KIND_ARGUMENT: symres_expression(state, (OnyxAstNode **) &stmt->left); return 0;
- case ONYX_AST_NODE_KIND_BLOCK: symres_block(state, &stmt->as_block); return 0;
+ case AST_NODE_KIND_LOCAL: symres_local(state, (AstNodeLocal **) &stmt); return 1;
+ case AST_NODE_KIND_ASSIGNMENT: symres_assignment(state, (AstNodeAssign *) stmt); return 0;
+ case AST_NODE_KIND_RETURN: symres_return(state, (AstNodeReturn *) stmt); return 0;
+ case AST_NODE_KIND_IF: symres_if(state, (AstNodeIf *) stmt); return 0;
+ case AST_NODE_KIND_WHILE: symres_while(state, (AstNodeWhile *) stmt); return 0;
+ case AST_NODE_KIND_CALL: symres_call(state, (AstNodeCall *) stmt); return 0;
+ case AST_NODE_KIND_ARGUMENT: symres_expression(state, (AstNode **) &((AstNodeArgument *)stmt)->value); return 0;
+ case AST_NODE_KIND_BLOCK: symres_block(state, (AstNodeBlock *) stmt); return 0;
default: return 0;
}
}
-static void symres_statement_chain(OnyxSemPassState* state, OnyxAstNode* walker, OnyxAstNode** trailer) {
+static void symres_statement_chain(OnyxSemPassState* state, AstNode* walker, AstNode** trailer) {
while (walker) {
if (symres_statement(state, walker)) {
*trailer = walker->next;
- OnyxAstNode* tmp = walker->next;
+ AstNode* tmp = walker->next;
walker->next = NULL;
walker = tmp;
} else {
}
}
-static void symres_block(OnyxSemPassState* state, OnyxAstNodeBlock* block) {
+static void symres_block(OnyxSemPassState* state, AstNodeBlock* block) {
scope_enter(state, block->scope);
if (block->body)
symres_statement_chain(state, block->body, &block->body);
scope_leave(state);
}
-static void symres_function(OnyxSemPassState* state, OnyxAstNodeFunction* func) {
- forll(OnyxAstNodeParam, param, func->params, next) {
- symbol_introduce(state, (OnyxAstNode *) param);
+static void symres_function(OnyxSemPassState* state, AstNodeFunction* func) {
+ for (AstNodeLocal *param = func->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
+ symbol_introduce(state, (AstNode *) param);
}
symres_block(state, func->body);
- forll(OnyxAstNodeParam, param, func->params, next) {
- symbol_remove(state, (OnyxAstNode *) param);
+ for (AstNodeLocal *param = func->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
+ symbol_remove(state, (AstNode *) param);
}
}
void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program) {
// NOTE: First, introduce all global symbols
- bh_arr_each(OnyxAstNodeGlobal *, global, program->globals)
- if (!symbol_unique_introduce(state, (OnyxAstNode *) *global)) return;
+ bh_arr_each(AstNodeGlobal *, global, program->globals)
+ if (!symbol_unique_introduce(state, (AstNode *) *global)) return;
- bh_arr_each(OnyxAstNodeFunction *, function, program->functions)
- if (!symbol_unique_introduce(state, (OnyxAstNode *) *function)) return;
+ bh_arr_each(AstNodeFunction *, function, program->functions)
+ if (!symbol_unique_introduce(state, (AstNode *) *function)) return;
- bh_arr_each(OnyxAstNodeForeign *, foreign, program->foreigns) {
- OnyxAstNodeKind import_kind = (*foreign)->import->kind;
+ bh_arr_each(AstNodeForeign *, foreign, program->foreigns) {
+ AstNodeKind import_kind = (*foreign)->import->kind;
- if (import_kind == ONYX_AST_NODE_KIND_FUNCTION || import_kind == ONYX_AST_NODE_KIND_GLOBAL)
+ if (import_kind == AST_NODE_KIND_FUNCTION || import_kind == AST_NODE_KIND_GLOBAL)
if (!symbol_unique_introduce(state, (*foreign)->import)) return;
}
// NOTE: Then, resolve all symbols in all functions
- bh_arr_each(OnyxAstNodeFunction *, function, program->functions)
+ bh_arr_each(AstNodeFunction *, function, program->functions)
symres_function(state, *function);
}
#define BH_DEBUG
#include "onyxsempass.h"
-static void typecheck_function(OnyxSemPassState* state, OnyxAstNodeFunction* func);
-static void typecheck_block(OnyxSemPassState* state, OnyxAstNodeBlock* block);
-static void typecheck_statement_chain(OnyxSemPassState* state, OnyxAstNode* start);
-static void typecheck_statement(OnyxSemPassState* state, OnyxAstNode* stmt);
-static void typecheck_assignment(OnyxSemPassState* state, OnyxAstNode* assign);
-static void typecheck_return(OnyxSemPassState* state, OnyxAstNode* retnode);
-static void typecheck_if(OnyxSemPassState* state, OnyxAstNodeIf* ifnode);
-static void typecheck_while(OnyxSemPassState* state, OnyxAstNodeWhile* whilenode);
-static void typecheck_call(OnyxSemPassState* state, OnyxAstNodeCall* call);
-static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr);
-static void typecheck_global(OnyxSemPassState* state, OnyxAstNodeGlobal* global);
-
-static void typecheck_assignment(OnyxSemPassState* state, OnyxAstNode* assign) {
- if (assign->left->kind == ONYX_AST_NODE_KIND_SYMBOL) {
+static void typecheck_function(OnyxSemPassState* state, AstNodeFunction* func);
+static void typecheck_block(OnyxSemPassState* state, AstNodeBlock* block);
+static void typecheck_statement_chain(OnyxSemPassState* state, AstNode* start);
+static void typecheck_statement(OnyxSemPassState* state, AstNode* stmt);
+static void typecheck_assignment(OnyxSemPassState* state, AstNodeAssign* assign);
+static void typecheck_return(OnyxSemPassState* state, AstNodeReturn* retnode);
+static void typecheck_if(OnyxSemPassState* state, AstNodeIf* ifnode);
+static void typecheck_while(OnyxSemPassState* state, AstNodeWhile* whilenode);
+static void typecheck_call(OnyxSemPassState* state, AstNodeCall* call);
+static void typecheck_expression(OnyxSemPassState* state, AstNodeTyped* expr);
+static void typecheck_global(OnyxSemPassState* state, AstNodeGlobal* global);
+
+static void typecheck_assignment(OnyxSemPassState* state, AstNodeAssign* assign) {
+ if (assign->lval->kind == AST_NODE_KIND_SYMBOL) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
- assign->left->token->pos,
- assign->left->token->token, assign->left->token->length);
+ assign->lval->token->pos,
+ assign->lval->token->token, assign->lval->token->length);
return;
}
- if ((assign->left->flags & ONYX_AST_FLAG_CONST) != 0 && assign->left->type->is_known) {
+ if ((assign->lval->flags & ONYX_AST_FLAG_CONST) != 0 && assign->lval->type->is_known) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_ASSIGN_CONST,
- assign->token->pos,
- assign->left->token->token, assign->left->token->length);
+ assign->base.token->pos,
+ assign->lval->token->token, assign->lval->token->length);
return;
}
- if ((assign->left->flags & ONYX_AST_FLAG_LVAL) == 0) {
+ if ((assign->lval->flags & ONYX_AST_FLAG_LVAL) == 0) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_NOT_LVAL,
- assign->token->pos,
- assign->left->token->token, assign->left->token->length);
+ assign->base.token->pos,
+ assign->lval->token->token, assign->lval->token->length);
return;
}
- typecheck_expression(state, assign->right);
+ typecheck_expression(state, assign->expr);
- if (!assign->left->type->is_known) {
- assign->left->type = assign->right->type;
+ if (!assign->lval->type->is_known) {
+ assign->lval->type = assign->expr->type;
} else {
- if (assign->left->type != assign->right->type) {
+ if (assign->lval->type != assign->expr->type) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_ASSIGNMENT_TYPE_MISMATCH,
- assign->token->pos,
- assign->left->type->name, assign->right->type->name);
+ assign->base.token->pos,
+ assign->lval->type->name, assign->expr->type->name);
return;
}
}
}
-static void typecheck_return(OnyxSemPassState* state, OnyxAstNode* retnode) {
- if (retnode->left) {
- typecheck_expression(state, retnode->left);
+static void typecheck_return(OnyxSemPassState* state, AstNodeReturn* retnode) {
+ if (retnode->expr) {
+ typecheck_expression(state, retnode->expr);
- if (retnode->left->type != state->expected_return_type) {
+ if (retnode->expr->type != state->expected_return_type) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_FUNCTION_RETURN_MISMATCH,
- retnode->left->token->pos,
- retnode->left->type->name, state->expected_return_type->name);
+ retnode->expr->token->pos,
+ retnode->expr->type->name, state->expected_return_type->name);
}
} else {
if (state->expected_return_type->size > 0) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
- retnode->token->pos,
+ retnode->base.token->pos,
"returning from non-void function without value");
}
}
}
-static void typecheck_if(OnyxSemPassState* state, OnyxAstNodeIf* ifnode) {
+static void typecheck_if(OnyxSemPassState* state, AstNodeIf* ifnode) {
typecheck_expression(state, ifnode->cond);
- if (ifnode->cond->type != &builtin_types[ONYX_TYPE_INFO_KIND_BOOL]) {
+ if (ifnode->cond->type != &builtin_types[TYPE_INFO_KIND_BOOL]) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
ifnode->cond->token->pos,
if (ifnode->false_block) typecheck_statement(state, ifnode->false_block);
}
-static void typecheck_while(OnyxSemPassState* state, OnyxAstNodeWhile* whilenode) {
+static void typecheck_while(OnyxSemPassState* state, AstNodeWhile* whilenode) {
typecheck_expression(state, whilenode->cond);
- if (whilenode->cond->type != &builtin_types[ONYX_TYPE_INFO_KIND_BOOL]) {
+ if (whilenode->cond->type != &builtin_types[TYPE_INFO_KIND_BOOL]) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
whilenode->cond->token->pos,
typecheck_block(state, whilenode->body);
}
-static void typecheck_call(OnyxSemPassState* state, OnyxAstNodeCall* call) {
- OnyxAstNodeFunction* callee = (OnyxAstNodeFunction *) call->callee;
+static void typecheck_call(OnyxSemPassState* state, AstNodeCall* call) {
+ AstNodeFunction* callee = (AstNodeFunction *) call->callee;
- if (callee->kind == ONYX_AST_NODE_KIND_SYMBOL) {
+ if (callee->base.kind == AST_NODE_KIND_SYMBOL) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
- callee->token->pos,
- callee->token->token, callee->token->length);
+ callee->base.token->pos,
+ callee->base.token->token, callee->base.token->length);
return;
}
- if (callee->kind != ONYX_AST_NODE_KIND_FUNCTION) {
+ if (callee->base.kind != AST_NODE_KIND_FUNCTION) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_CALL_NON_FUNCTION,
- call->token->pos,
- callee->token->token, callee->token->length);
+ call->base.token->pos,
+ callee->base.token->token, callee->base.token->length);
return;
}
- call->type = callee->return_type;
+ call->base.type = callee->base.type;
- OnyxAstNodeParam* formal_param = callee->params;
- OnyxAstNode* actual_param = call->arguments;
+ AstNodeLocal* formal_param = callee->params;
+ AstNodeArgument* actual_param = call->arguments;
i32 arg_pos = 0;
while (formal_param != NULL && actual_param != NULL) {
- typecheck_expression(state, actual_param);
+ typecheck_expression(state, (AstNodeTyped *) actual_param);
- if (formal_param->type != actual_param->type) {
+ if (formal_param->base.type != actual_param->base.type) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_FUNCTION_PARAM_TYPE_MISMATCH,
- call->token->pos,
- callee->token->token, callee->token->length,
- formal_param->type->name, arg_pos,
- actual_param->type->name);
+ call->base.token->pos,
+ callee->base.token->token, callee->base.token->length,
+ formal_param->base.type->name, arg_pos,
+ actual_param->base.type->name);
return;
}
arg_pos++;
- formal_param = formal_param->next;
- actual_param = actual_param->next;
+ formal_param = (AstNodeLocal *) formal_param->base.next;
+ actual_param = (AstNodeArgument *) actual_param->base.next;
}
if (formal_param != NULL && actual_param == NULL) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
- call->token->pos,
+ call->base.token->pos,
"too few arguments to function call");
return;
}
if (formal_param == NULL && actual_param != NULL) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
- call->token->pos,
+ call->base.token->pos,
"too many arguments to function call");
return;
}
}
-static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr) {
+static void typecheck_expression(OnyxSemPassState* state, AstNodeTyped* expr) {
switch (expr->kind) {
- case ONYX_AST_NODE_KIND_BIN_OP:
- expr->type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+ case AST_NODE_KIND_BIN_OP:
+ expr->type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
- typecheck_expression(state, expr->left);
- typecheck_expression(state, expr->right);
+ typecheck_expression(state, ((AstNodeBinOp *) expr)->left);
+ typecheck_expression(state, ((AstNodeBinOp *) expr)->right);
- if (expr->left->type == NULL) {
+ if (((AstNodeBinOp *) expr)->left->type == NULL) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
expr->token->pos,
return;
}
- if (expr->right->type == NULL) {
+ if (((AstNodeBinOp *) expr)->right->type == NULL) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
expr->token->pos,
return;
}
- if (expr->left->type != expr->right->type) {
+ if (((AstNodeBinOp *) expr)->left->type != ((AstNodeBinOp *) expr)->right->type) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_BINOP_MISMATCH_TYPE,
expr->token->pos,
- expr->left->type->name,
- expr->right->type->name);
+ ((AstNodeBinOp *) expr)->left->type->name,
+ ((AstNodeBinOp *) expr)->right->type->name);
return;
}
- if (expr->as_binop.operation >= ONYX_BINARY_OP_EQUAL
- && expr->as_binop.operation <= ONYX_BINARY_OP_GREATER_EQUAL) {
- expr->type = &builtin_types[ONYX_TYPE_INFO_KIND_BOOL];
+ if (((AstNodeBinOp *) expr)->operation >= ONYX_BINARY_OP_EQUAL
+ && ((AstNodeBinOp *) expr)->operation <= ONYX_BINARY_OP_GREATER_EQUAL) {
+ expr->type = &builtin_types[TYPE_INFO_KIND_BOOL];
} else {
- expr->type = expr->left->type;
+ expr->type = ((AstNodeBinOp *) expr)->left->type;
}
break;
- case ONYX_AST_NODE_KIND_UNARY_OP:
- if (expr->as_unaryop.operation != ONYX_UNARY_OP_CAST) {
- typecheck_expression(state, expr->left);
- expr->type = expr->left->type;
+ case AST_NODE_KIND_UNARY_OP:
+ if (((AstNodeUnaryOp *) expr)->operation != ONYX_UNARY_OP_CAST) {
+ typecheck_expression(state, ((AstNodeUnaryOp *) expr)->expr);
+ expr->type = ((AstNodeUnaryOp *) expr)->expr->type;
}
break;
- case ONYX_AST_NODE_KIND_CALL:
- typecheck_call(state, &expr->as_call);
+ case AST_NODE_KIND_CALL:
+ typecheck_call(state, (AstNodeCall *) expr);
break;
- case ONYX_AST_NODE_KIND_BLOCK:
- typecheck_block(state, &expr->as_block);
+ case AST_NODE_KIND_BLOCK:
+ typecheck_block(state, (AstNodeBlock *) expr);
break;
- case ONYX_AST_NODE_KIND_SYMBOL:
+ case AST_NODE_KIND_SYMBOL:
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
expr->token->pos,
expr->token->token, expr->token->length);
break;
- case ONYX_AST_NODE_KIND_LOCAL:
- case ONYX_AST_NODE_KIND_PARAM:
+ case AST_NODE_KIND_LOCAL:
+ case AST_NODE_KIND_PARAM:
if (!expr->type->is_known) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
}
break;
- case ONYX_AST_NODE_KIND_GLOBAL:
+ case AST_NODE_KIND_GLOBAL:
if (!expr->type->is_known) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
}
break;
- case ONYX_AST_NODE_KIND_ARGUMENT:
- typecheck_expression(state, expr->left);
- expr->type = expr->left->type;
+ case AST_NODE_KIND_ARGUMENT:
+ typecheck_expression(state, ((AstNodeArgument *) expr)->value);
+ expr->type = ((AstNodeArgument *) expr)->value->type;
break;
- case ONYX_AST_NODE_KIND_LITERAL:
+ case AST_NODE_KIND_LITERAL:
// NOTE: Literal types should have been decided
// in the parser (for now).
assert(expr->type->is_known);
}
}
-static void typecheck_global(OnyxSemPassState* state, OnyxAstNodeGlobal* global) {
+static void typecheck_global(OnyxSemPassState* state, AstNodeGlobal* global) {
if (global->initial_value) {
typecheck_expression(state, global->initial_value);
- if (global->type->is_known) {
- if (global->type != global->initial_value->type) {
+ if (global->base.type->is_known) {
+ if (global->base.type != global->initial_value->type) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_GLOBAL_TYPE_MISMATCH,
- global->token->pos,
- global->token->token, global->token->length,
- global->type->name, global->initial_value->type->name);
+ global->base.token->pos,
+ global->base.token->token, global->base.token->length,
+ global->base.type->name, global->initial_value->type->name);
return;
}
} else {
if (global->initial_value->type)
- global->type = global->initial_value->type;
+ global->base.type = global->initial_value->type;
}
} else {
- if (!global->type || !global->type->is_known) {
+ if (!global->base.type || !global->base.type->is_known) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
- global->token->pos,
+ global->base.token->pos,
"global variable with unknown type");
}
}
}
-static void typecheck_statement(OnyxSemPassState* state, OnyxAstNode* stmt) {
+static void typecheck_statement(OnyxSemPassState* state, AstNode* stmt) {
switch (stmt->kind) {
- case ONYX_AST_NODE_KIND_ASSIGNMENT: typecheck_assignment(state, stmt); break;
- case ONYX_AST_NODE_KIND_RETURN: typecheck_return(state, stmt); break;
- case ONYX_AST_NODE_KIND_IF: typecheck_if(state, &stmt->as_if); break;
- case ONYX_AST_NODE_KIND_WHILE: typecheck_while(state, &stmt->as_while); break;
- case ONYX_AST_NODE_KIND_CALL: typecheck_call(state, &stmt->as_call); break;
- case ONYX_AST_NODE_KIND_BLOCK: typecheck_block(state, &stmt->as_block); break;
+ case AST_NODE_KIND_ASSIGNMENT: typecheck_assignment(state, (AstNodeAssign *) stmt); break;
+ case AST_NODE_KIND_RETURN: typecheck_return(state, (AstNodeReturn *) stmt); break;
+ case AST_NODE_KIND_IF: typecheck_if(state, (AstNodeIf *) stmt); break;
+ case AST_NODE_KIND_WHILE: typecheck_while(state, (AstNodeWhile *) stmt); break;
+ case AST_NODE_KIND_CALL: typecheck_call(state, (AstNodeCall *) stmt); break;
+ case AST_NODE_KIND_BLOCK: typecheck_block(state, (AstNodeBlock *) stmt); break;
default: break;
}
}
-static void typecheck_statement_chain(OnyxSemPassState* state, OnyxAstNode* start) {
+static void typecheck_statement_chain(OnyxSemPassState* state, AstNode* start) {
while (start) {
typecheck_statement(state, start);
start = start->next;
}
}
-static void typecheck_block(OnyxSemPassState* state, OnyxAstNodeBlock* block) {
+static void typecheck_block(OnyxSemPassState* state, AstNodeBlock* block) {
typecheck_statement_chain(state, block->body);
- forll(OnyxAstNodeLocal, local, block->scope->last_local, prev_local) {
- if (!local->type->is_known) {
+ forll(AstNodeLocal, local, block->scope->last_local, prev_local) {
+ if (!local->base.type->is_known) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
- local->token->pos,
- local->token->token, local->token->length);
+ local->base.token->pos,
+ local->base.token->token, local->base.token->length);
return;
}
}
}
-static void typecheck_function(OnyxSemPassState* state, OnyxAstNodeFunction* func) {
- forll(OnyxAstNodeParam, param, func->params, next) {
- if (!param->type->is_known) {
+static void typecheck_function(OnyxSemPassState* state, AstNodeFunction* func) {
+ for (AstNodeLocal *param = func->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
+ if (!param->base.type->is_known) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
- param->token->pos,
+ param->base.token->pos,
"function parameter types must be known");
return;
}
- if (param->type->size == 0) {
+ if (param->base.type->size == 0) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
- param->token->pos,
+ param->base.token->pos,
"function parameters must have non-void types");
return;
}
}
- state->expected_return_type = func->return_type;
+ state->expected_return_type = func->base.type;
if (func->body) {
typecheck_block(state, func->body);
}
void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program) {
- bh_arr_each(OnyxAstNodeGlobal *, global, program->globals)
+ bh_arr_each(AstNodeGlobal *, global, program->globals)
typecheck_global(state, *global);
- bh_arr_each(OnyxAstNodeFunction *, function, program->functions)
+ bh_arr_each(AstNodeFunction *, function, program->functions)
typecheck_function(state, *function);
}
#define print_indent { if (indent > 0) bh_printf("\n"); for (int i = 0; i < indent; i++) bh_printf(" "); }
-void onyx_ast_print(OnyxAstNode* node, i32 indent) {
- if (node == NULL) return;
-
- print_indent;
- bh_printf("(%d) %s ", node->flags, onyx_ast_node_kind_string(node->kind));
-
- switch (node->kind) {
- case ONYX_AST_NODE_KIND_USE: {
- OnyxAstNodeUse* use_node = &node->as_use;
- bh_printf("%b", use_node->filename->token, use_node->filename->length);
-
- if (use_node->next)
- onyx_ast_print(use_node->next, indent);
-
- break;
- }
-
- case ONYX_AST_NODE_KIND_FUNCTION: {
- if (node->token)
- bh_printf("(%b) ", node->token->token, node->token->length);
- OnyxAstNodeFunction* fd = &node->as_function;
-
+void onyx_ast_print(AstNode* node, i32 indent) {
+ while (node) {
print_indent;
- bh_printf("Params ");
- if (fd->params)
- onyx_ast_print((OnyxAstNode *) fd->params, 0);
+ bh_printf("(%d) %s ", node->flags, onyx_ast_node_kind_string(node->kind));
- print_indent;
- bh_printf("Returns %s", fd->return_type->name);
+ switch (node->kind) {
+ case AST_NODE_KIND_USE: {
+ AstNodeUse* use_node = (AstNodeUse *) node;
+ bh_printf("%b", use_node->filename->token, use_node->filename->length);
- print_indent;
- bh_printf("Body");
- if (fd->body)
- onyx_ast_print((OnyxAstNode *) fd->body, indent + 1);
+ break;
+ }
- if (fd->next)
- onyx_ast_print((OnyxAstNode *) fd->next, indent);
+ case AST_NODE_KIND_FUNCTION: {
+ if (node->token)
+ bh_printf("(%b) ", node->token->token, node->token->length);
+ AstNodeFunction* fd = (AstNodeFunction *) node;
- break;
- }
+ print_indent;
+ bh_printf("Params ");
+ if (fd->params)
+ onyx_ast_print((AstNode *) fd->params, 0);
- case ONYX_AST_NODE_KIND_PARAM: {
- OnyxAstNodeParam* param = &node->as_param;
- bh_printf("%b %s", param->token->token, param->token->length, param->type->name);
- if (param->next && indent == 0) {
- bh_printf(", ");
- onyx_ast_print((OnyxAstNode *) param->next, 0);
- }
+ print_indent;
+ bh_printf("Returns %s", fd->base.type->name);
- break;
- }
+ print_indent;
+ bh_printf("Body");
+ if (fd->body)
+ onyx_ast_print((AstNode *) fd->body, indent + 1);
- case ONYX_AST_NODE_KIND_BLOCK: {
- OnyxAstNodeBlock* block = &node->as_block;
- if (block->scope) {
- onyx_ast_print((OnyxAstNode *) block->scope, indent + 1);
+ break;
}
- if (block->body) {
- onyx_ast_print((OnyxAstNode *) block->body, indent + 1);
- }
+ case AST_NODE_KIND_PARAM: {
+ AstNodeLocal* param = (AstNodeLocal *) node;
+ bh_printf("%b %s", param->base.token->token, param->base.token->length, param->base.type->name);
+ if (param->base.next && indent == 0) {
+ bh_printf(", ");
+ onyx_ast_print((AstNode *) param->base.next, 0);
+ }
- if (block->next) {
- onyx_ast_print(block->next, indent);
+ return;
}
- break;
- }
+ case AST_NODE_KIND_BLOCK: {
+ AstNodeBlock* block = (AstNodeBlock *) node;
+ if (block->scope) {
+ onyx_ast_print((AstNode *) block->scope, indent + 1);
+ }
- case ONYX_AST_NODE_KIND_SCOPE: {
- OnyxAstNodeScope* scope = &node->as_scope;
- if (scope->last_local) {
- onyx_ast_print((OnyxAstNode *) scope->last_local, 0);
+ if (block->body) {
+ onyx_ast_print((AstNode *) block->body, indent + 1);
+ }
+
+ break;
}
- break;
- }
+ case AST_NODE_KIND_SCOPE: {
+ AstNodeScope* scope = (AstNodeScope *) scope;
+ if (scope->last_local) {
+ onyx_ast_print((AstNode *) scope->last_local, 0);
+ }
- case ONYX_AST_NODE_KIND_LOCAL: {
- OnyxAstNodeLocal* local = &node->as_local;
- bh_printf("%b %s", local->token->token, local->token->length, local->type->name);
- if (local->prev_local && indent == 0) {
- bh_printf(", ");
- onyx_ast_print((OnyxAstNode *) local->prev_local, 0);
- } else if (local->next && indent != 0) {
- onyx_ast_print(local->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);
+ case AST_NODE_KIND_LOCAL: {
+ AstNodeLocal* local = (AstNodeLocal *) node;
+ bh_printf("%b %s", local->base.token->token, local->base.token->length, local->base.type->name);
+ if (local->prev_local && indent == 0) {
+ bh_printf(", ");
+ onyx_ast_print((AstNode *) local->prev_local, 0);
+ }
+ break;
}
- if (node->next) {
- onyx_ast_print(node->next, indent);
+ case AST_NODE_KIND_GLOBAL: {
+ AstNodeGlobal* global = (AstNodeGlobal *) node;
+ bh_printf("%b %s", global->base.token->token, global->base.token->length, global->base.type->name);
+ if (global->initial_value) {
+ onyx_ast_print((AstNode *) global->initial_value, indent + 1);
+ }
+
+ if (node->next) {
+ onyx_ast_print(node->next, indent);
+ }
+ break;
}
- break;
- }
- case ONYX_AST_NODE_KIND_SYMBOL: {
- bh_printf("%b", node->token->token, node->token->length);
- if (node->next) {
- onyx_ast_print(node->next, indent);
+ case AST_NODE_KIND_SYMBOL: {
+ bh_printf("%b", node->token->token, node->token->length);
+ if (node->next) {
+ onyx_ast_print(node->next, indent);
+ }
+ break;
}
- break;
- }
- case ONYX_AST_NODE_KIND_RETURN: {
- if (node->left) {
- onyx_ast_print(node->left, indent + 1);
+ case AST_NODE_KIND_RETURN: {
+ AstNodeReturn* ret = (AstNodeReturn *) node;
+ if (ret->expr) {
+ onyx_ast_print((AstNode *) ret->expr, indent + 1);
+ }
+
+ break;
}
- break;
- }
+ case AST_NODE_KIND_LITERAL: {
+ AstNodeNumLit* lit = (AstNodeNumLit *) node;
+ bh_printf("(%s) %b", lit->base.type->name, lit->base.token->token, lit->base.token->length);
- case ONYX_AST_NODE_KIND_LITERAL: {
- bh_printf("(%s) %b", node->type->name, node->token->token, node->token->length);
- if (node->next) {
- onyx_ast_print(node->next, indent);
+ break;
}
- break;
- }
- case ONYX_AST_NODE_KIND_CALL: {
- OnyxAstNodeCall* call = &node->as_call;
- if (call->callee) {
- if (call->callee->kind == ONYX_AST_NODE_KIND_FUNCTION) {
- bh_printf("function: %b", call->callee->token->token, call->callee->token->length);
- } else {
- onyx_ast_print(call->callee, indent + 1);
+ case AST_NODE_KIND_CALL: {
+ AstNodeCall* call = (AstNodeCall *) node;
+ if (call->callee) {
+ if (call->callee->kind == AST_NODE_KIND_FUNCTION) {
+ bh_printf("function: %b", call->callee->token->token, call->callee->token->length);
+ } else {
+ onyx_ast_print(call->callee, indent + 1);
+ }
}
+ onyx_ast_print((AstNode *) call->arguments, indent + 1);
+
+ break;
}
- onyx_ast_print(call->arguments, indent + 1);
- if (call->next) {
- onyx_ast_print(call->next, 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);
+ case AST_NODE_KIND_FOREIGN: {
+ AstNodeForeign* foreign = (AstNodeForeign *) node;
+ 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->import) {
+ onyx_ast_print(foreign->import, indent + 1);
+ }
- if (foreign->next) {
- onyx_ast_print(foreign->next, indent);
+ break;
}
- break;
- }
- case ONYX_AST_NODE_KIND_IF: {
- OnyxAstNodeIf* if_node = &node->as_if;
- if (if_node->cond) {
- print_indent;
- bh_printf("Condition:");
- onyx_ast_print(if_node->cond, indent + 1);
- }
- if (if_node->true_block) {
- print_indent;
- bh_printf("True block:");
- onyx_ast_print(if_node->true_block, indent + 1);
- }
- if (if_node->false_block) {
- print_indent;
- bh_printf("False block:");
- onyx_ast_print(if_node->false_block, indent + 1);
- }
- if (if_node->next) {
- onyx_ast_print(if_node->next, indent);
+ case AST_NODE_KIND_IF: {
+ AstNodeIf* if_node = (AstNodeIf *) node;
+ if (if_node->cond) {
+ print_indent;
+ bh_printf("Condition:");
+ onyx_ast_print((AstNode *) if_node->cond, indent + 1);
+ }
+ if (if_node->true_block) {
+ print_indent;
+ bh_printf("True block:");
+ onyx_ast_print(if_node->true_block, indent + 1);
+ }
+ if (if_node->false_block) {
+ print_indent;
+ bh_printf("False block:");
+ onyx_ast_print(if_node->false_block, indent + 1);
+ }
+
+ break;
}
- break;
- }
- case ONYX_AST_NODE_KIND_BIN_OP: {
- OnyxAstNodeBinOp* binop = &node->as_binop;
- bh_printf("%b", binop->token->token, binop->token->length);
+ case AST_NODE_KIND_BIN_OP: {
+ AstNodeBinOp* binop = (AstNodeBinOp *) node;
+ bh_printf("%b", binop->base.token->token, binop->base.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);
- }
+ onyx_ast_print((AstNode *) binop->left, indent + 1);
+ onyx_ast_print((AstNode *) binop->right, indent + 1);
- break;
- }
+ break;
+ }
- default: {
- onyx_ast_print(node->left, indent + 1);
- onyx_ast_print(node->right, indent + 1);
- if (node->next) {
- onyx_ast_print(node->next, indent);
+ default:
+ break;
}
- break;
- }
+
+ node = node->next;
}
}
}
}
-static WasmType onyx_type_to_wasm_type(OnyxTypeInfo* type) {
+static WasmType onyx_type_to_wasm_type(TypeInfo* type) {
if (type->is_bool) return WASM_TYPE_INT32;
else if (type->is_int) {
if (type->size == 4) return WASM_TYPE_INT32;
return WASM_TYPE_VOID;
}
-static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeFunction* fd);
-static void compile_block(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeBlock* block);
-static void compile_statement(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* stmt);
-static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* lval);
-static void compile_assignment(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* assign);
-static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeIf* if_node);
-static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeWhile* while_node);
-static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeBinOp* binop);
-static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeUnaryOp* unop);
-static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* expr);
-static void compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeUnaryOp* cast);
-static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* ret);
-
-static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeFunction* fd) {
+static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeFunction* fd);
+static void compile_block(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeBlock* block);
+static void compile_statement(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNode* stmt);
+static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeTyped* lval);
+static void compile_assignment(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeAssign* assign);
+static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeIf* if_node);
+static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeWhile* while_node);
+static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeBinOp* binop);
+static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeUnaryOp* unop);
+static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeTyped* expr);
+static void compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeUnaryOp* cast);
+static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeReturn* ret);
+
+static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeFunction* fd) {
if (fd->body == NULL) return;
bh_arr(WasmInstruction) code = *pcode;
- forll (OnyxAstNode, stmt, fd->body->body, next) {
+ forll (AstNode, stmt, fd->body->body, next) {
compile_statement(mod, &code, stmt);
}
*pcode = code;
}
-static void compile_block(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeBlock* block) {
+static void compile_block(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeBlock* block) {
bh_arr(WasmInstruction) code = *pcode;
bh_arr_push(code, ((WasmInstruction){ WI_BLOCK_START, 0x40 }));
- forll (OnyxAstNode, stmt, block->body, next) {
+ forll (AstNode, stmt, block->body, next) {
compile_statement(mod, &code, stmt);
}
*pcode = code;
}
-static void compile_statement(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* stmt) {
+static void compile_statement(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNode* stmt) {
bh_arr(WasmInstruction) code = *pcode;
switch (stmt->kind) {
- case ONYX_AST_NODE_KIND_SCOPE: break;
- case ONYX_AST_NODE_KIND_RETURN: compile_return(mod, &code, stmt); break;
- case ONYX_AST_NODE_KIND_ASSIGNMENT: compile_assignment(mod, &code, stmt); break;
- case ONYX_AST_NODE_KIND_IF: compile_if(mod, &code, (OnyxAstNodeIf *) stmt); break;
- case ONYX_AST_NODE_KIND_WHILE: compile_while(mod, &code, (OnyxAstNodeWhile *) stmt); break;
- case ONYX_AST_NODE_KIND_BREAK: compile_structured_jump(mod, &code, 0); break;
- case ONYX_AST_NODE_KIND_CONTINUE: compile_structured_jump(mod, &code, 1); break;
- case ONYX_AST_NODE_KIND_CALL: compile_expression(mod, &code, stmt); break;
- case ONYX_AST_NODE_KIND_BLOCK: compile_block(mod, &code, (OnyxAstNodeBlock *) stmt); break;
+ case AST_NODE_KIND_SCOPE: break;
+ case AST_NODE_KIND_RETURN: compile_return(mod, &code, (AstNodeReturn *) stmt); break;
+ case AST_NODE_KIND_ASSIGNMENT: compile_assignment(mod, &code, (AstNodeAssign *) stmt); break;
+ case AST_NODE_KIND_IF: compile_if(mod, &code, (AstNodeIf *) stmt); break;
+ case AST_NODE_KIND_WHILE: compile_while(mod, &code, (AstNodeWhile *) stmt); break;
+ case AST_NODE_KIND_BREAK: compile_structured_jump(mod, &code, 0); break;
+ case AST_NODE_KIND_CONTINUE: compile_structured_jump(mod, &code, 1); break;
+ case AST_NODE_KIND_CALL: compile_expression(mod, &code, (AstNodeTyped *) stmt); break;
+ case AST_NODE_KIND_BLOCK: compile_block(mod, &code, (AstNodeBlock *) stmt); break;
default: break;
}
*pcode = code;
}
-static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* lval) {
+static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeTyped* lval) {
bh_arr(WasmInstruction) code = *pcode;
- if (lval->kind == ONYX_AST_NODE_KIND_LOCAL || lval->kind == ONYX_AST_NODE_KIND_PARAM) {
+ if (lval->kind == AST_NODE_KIND_LOCAL || lval->kind == AST_NODE_KIND_PARAM) {
i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) lval);
bh_arr_push(code, ((WasmInstruction){ WI_LOCAL_SET, localidx }));
- } else if (lval->kind == ONYX_AST_NODE_KIND_GLOBAL) {
+ } else if (lval->kind == AST_NODE_KIND_GLOBAL) {
i32 globalidx = (i32) bh_imap_get(&mod->global_map, (u64) lval);
bh_arr_push(code, ((WasmInstruction){ WI_GLOBAL_SET, globalidx }));
*pcode = code;
}
-static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeIf* if_node) {
+static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeIf* if_node) {
bh_arr(WasmInstruction) code = *pcode;
compile_expression(mod, &code, if_node->cond);
if (if_node->true_block) {
// NOTE: This is kind of gross, but making a function for this doesn't feel right
- if (if_node->true_block->kind == ONYX_AST_NODE_KIND_IF) {
- forll (OnyxAstNode, stmt, if_node->true_block, next) {
+ if (if_node->true_block->kind == AST_NODE_KIND_IF) {
+ forll (AstNode, stmt, if_node->true_block, next) {
compile_statement(mod, &code, stmt);
}
- } else if (if_node->true_block->kind == ONYX_AST_NODE_KIND_BLOCK) {
- forll (OnyxAstNode, stmt, if_node->true_block->as_block.body, next) {
+ } else if (if_node->true_block->kind == AST_NODE_KIND_BLOCK) {
+ forll (AstNode, stmt, ((AstNodeBlock *) if_node->true_block)->body, next) {
compile_statement(mod, &code, stmt);
}
}
if (if_node->false_block) {
bh_arr_push(code, ((WasmInstruction){ WI_ELSE, 0x00 }));
- if (if_node->false_block->kind == ONYX_AST_NODE_KIND_IF) {
- forll (OnyxAstNode, stmt, if_node->false_block, next) {
+ if (if_node->false_block->kind == AST_NODE_KIND_IF) {
+ forll (AstNode, stmt, if_node->false_block, next) {
compile_statement(mod, &code, stmt);
}
- } else if (if_node->false_block->kind == ONYX_AST_NODE_KIND_BLOCK) {
- forll (OnyxAstNode, stmt, if_node->false_block->as_block.body, next) {
+ } else if (if_node->false_block->kind == AST_NODE_KIND_BLOCK) {
+ forll (AstNode, stmt, ((AstNodeBlock *) if_node->false_block)->body, next) {
compile_statement(mod, &code, stmt);
}
}
*pcode = code;
}
-static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeWhile* while_node) {
+static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeWhile* while_node) {
bh_arr(WasmInstruction) code = *pcode;
bh_arr_push(code, ((WasmInstruction){ WI_BLOCK_START, 0x40 }));
bh_arr_push(mod->structured_jump_target, 1);
bh_arr_push(mod->structured_jump_target, 2);
- forll (OnyxAstNode, stmt, while_node->body->body, next) {
+ forll (AstNode, stmt, while_node->body->body, next) {
compile_statement(mod, &code, stmt);
}
*pcode = code;
}
-static void compile_assignment(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* assign) {
+static void compile_assignment(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeAssign* assign) {
bh_arr(WasmInstruction) code = *pcode;
- compile_expression(mod, &code, assign->right);
- compile_assign_lval(mod, &code, assign->left);
+ compile_expression(mod, &code, assign->expr);
+ compile_assign_lval(mod, &code, assign->lval);
*pcode = code;
}
/* GTE */ { WI_I32_GE_S, WI_I64_GE_S, WI_F32_GE, WI_F64_GE },
};
-static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeBinOp* binop) {
+static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeBinOp* binop) {
bh_arr(WasmInstruction) code = *pcode;
b32 is_sign_significant = 0;
*pcode = code;
}
-static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeUnaryOp* unop) {
+static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeUnaryOp* unop) {
bh_arr(WasmInstruction) code = *pcode;
switch (unop->operation) {
case ONYX_UNARY_OP_NEGATE:
{
- OnyxTypeInfoKind type_kind = unop->type->kind;
+ TypeInfoKind type_kind = unop->base.type->kind;
- if (type_kind == ONYX_TYPE_INFO_KIND_INT32) {
+ if (type_kind == TYPE_INFO_KIND_INT32) {
bh_arr_push(code, ((WasmInstruction){ WI_I32_CONST, 0x00 }));
- compile_expression(mod, &code, unop->left);
+ compile_expression(mod, &code, unop->expr);
bh_arr_push(code, ((WasmInstruction){ WI_I32_SUB, 0x00 }));
- } else if (type_kind == ONYX_TYPE_INFO_KIND_INT64) {
+ } else if (type_kind == TYPE_INFO_KIND_INT64) {
bh_arr_push(code, ((WasmInstruction){ WI_I64_CONST, 0x00 }));
- compile_expression(mod, &code, unop->left);
+ compile_expression(mod, &code, unop->expr);
bh_arr_push(code, ((WasmInstruction){ WI_I64_SUB, 0x00 }));
} else {
- compile_expression(mod, &code, unop->left);
+ compile_expression(mod, &code, unop->expr);
- if (type_kind == ONYX_TYPE_INFO_KIND_FLOAT32)
+ if (type_kind == TYPE_INFO_KIND_FLOAT32)
bh_arr_push(code, ((WasmInstruction){ WI_F32_NEG, 0x00 }));
- if (type_kind == ONYX_TYPE_INFO_KIND_FLOAT64)
+ if (type_kind == TYPE_INFO_KIND_FLOAT64)
bh_arr_push(code, ((WasmInstruction){ WI_F32_NEG, 0x00 }));
}
}
case ONYX_UNARY_OP_NOT:
- compile_expression(mod, &code, unop->left);
+ compile_expression(mod, &code, unop->expr);
bh_arr_push(code, ((WasmInstruction){ WI_I32_EQZ, 0x00 }));
break;
*pcode = code;
}
-static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* expr) {
+static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeTyped* expr) {
bh_arr(WasmInstruction) code = *pcode;
switch (expr->kind) {
- case ONYX_AST_NODE_KIND_BIN_OP:
- compile_binop(mod, &code, &expr->as_binop);
+ case AST_NODE_KIND_BIN_OP:
+ compile_binop(mod, &code, (AstNodeBinOp *) expr);
break;
- case ONYX_AST_NODE_KIND_UNARY_OP:
- compile_unaryop(mod, &code, &expr->as_unaryop);
+ case AST_NODE_KIND_UNARY_OP:
+ compile_unaryop(mod, &code, (AstNodeUnaryOp *) expr);
break;
- case ONYX_AST_NODE_KIND_LOCAL:
- case ONYX_AST_NODE_KIND_PARAM:
+ case AST_NODE_KIND_LOCAL:
+ case AST_NODE_KIND_PARAM:
{
i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) expr);
break;
}
- case ONYX_AST_NODE_KIND_GLOBAL:
+ case AST_NODE_KIND_GLOBAL:
{
i32 globalidx = (i32) bh_imap_get(&mod->global_map, (u64) expr);
break;
}
- case ONYX_AST_NODE_KIND_LITERAL:
+ case AST_NODE_KIND_LITERAL:
{
- OnyxAstNodeNumLit* lit = &expr->as_numlit;
- WasmType lit_type = onyx_type_to_wasm_type(lit->type);
+ AstNodeNumLit* lit = (AstNodeNumLit *) expr;
+ WasmType lit_type = onyx_type_to_wasm_type(lit->base.type);
WasmInstruction instr = { WI_NOP, 0 };
if (lit_type == WASM_TYPE_INT32) {
break;
}
- case ONYX_AST_NODE_KIND_BLOCK: compile_block(mod, &code, (OnyxAstNodeBlock *) expr); break;
+ case AST_NODE_KIND_BLOCK: compile_block(mod, &code, (AstNodeBlock *) expr); break;
- case ONYX_AST_NODE_KIND_CALL:
+ case AST_NODE_KIND_CALL:
{
- OnyxAstNodeCall* call = &expr->as_call;
- forll (OnyxAstNode, arg, call->arguments, next) {
- compile_expression(mod, &code, arg->left);
+ AstNodeCall* call = (AstNodeCall *) expr;
+ for (AstNodeArgument *arg = call->arguments;
+ arg != NULL;
+ arg = (AstNodeArgument *) arg->base.next) {
+ compile_expression(mod, &code, arg->value);
}
i32 func_idx = (i32) bh_imap_get(&mod->func_map, (u64) call->callee);
/* 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 void compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeUnaryOp* cast) {
+static void compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeUnaryOp* cast) {
bh_arr(WasmInstruction) code = *pcode;
- compile_expression(mod, &code, cast->left);
+ compile_expression(mod, &code, cast->expr);
- OnyxTypeInfo* from = cast->left->type;
- OnyxTypeInfo* to = cast->type;
+ TypeInfo* from = cast->expr->type;
+ TypeInfo* to = cast->base.type;
i32 fromidx = 0, toidx = 0;
if (from->is_int) {
*pcode = code;
}
-static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* ret) {
+static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeReturn* ret) {
bh_arr(WasmInstruction) code = *pcode;
- if (ret->left) {
- compile_expression(mod, &code, ret->left);
+ if (ret->expr) {
+ compile_expression(mod, &code, ret->expr);
}
bh_arr_push(code, ((WasmInstruction){ WI_RETURN, 0x00 }));
*pcode = code;
}
-static i32 generate_type_idx(OnyxWasmModule* mod, OnyxAstNodeFunction* fd) {
+static i32 generate_type_idx(OnyxWasmModule* mod, AstNodeFunction* fd) {
static char type_repr_buf[128];
char* t = type_repr_buf;
- OnyxAstNodeParam* param = fd->params;
+ AstNodeLocal* param = fd->params;
i32 param_count = 0;
while (param) {
// HACK: Using these directly as part of a string feels weird but they are
// valid characters so I don't think it is going to be much of an issue
- *(t++) = (char) onyx_type_to_wasm_type(param->type);
+ *(t++) = (char) onyx_type_to_wasm_type(param->base.type);
param_count++;
- param = param->next;
+ param = (AstNodeLocal *) param->base.next;
}
*(t++) = ':';
- WasmType return_type = onyx_type_to_wasm_type(fd->return_type);
+ WasmType return_type = onyx_type_to_wasm_type(fd->base.type);
*(t++) = (char) return_type;
*t = '\0';
return type_idx;
}
-static void compile_function(OnyxWasmModule* mod, OnyxAstNodeFunction* fd) {
+static void compile_function(OnyxWasmModule* mod, AstNodeFunction* fd) {
i32 type_idx = generate_type_idx(mod, fd);
WasmFunc wasm_func = {
bh_arr_new(mod->allocator, wasm_func.code, 4);
- if (fd->flags & ONYX_AST_FLAG_EXPORTED) {
- onyx_token_null_toggle(*fd->token);
+ if (fd->base.flags & ONYX_AST_FLAG_EXPORTED) {
+ onyx_token_null_toggle(fd->base.token);
i32 func_idx = (i32) bh_imap_get(&mod->func_map, (u64) fd);
.kind = WASM_FOREIGN_FUNCTION,
.idx = func_idx,
};
- bh_table_put(WasmExport, mod->exports, fd->token->token, wasm_export);
+ bh_table_put(WasmExport, mod->exports, fd->base.token->token, wasm_export);
mod->export_count++;
- onyx_token_null_toggle(*fd->token);
+ onyx_token_null_toggle(fd->base.token);
}
// If there is no body then don't process the code
if (fd->body != NULL) {
// NOTE: Generate the local map
i32 localidx = 0;
- forll (OnyxAstNodeParam, param, fd->params, next) {
+ for (AstNodeLocal *param = fd->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
bh_imap_put(&mod->local_map, (u64) param, localidx++);
}
// 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]) {
+ forll (AstNodeLocal, local, fd->body->scope->last_local, prev_local) {
+ if (onyx_type_to_wasm_type(local->base.type) == local_types[ti]) {
bh_imap_put(&mod->local_map, (u64) local, localidx++);
(*count)++;
bh_imap_clear(&mod->local_map);
}
-static void compile_global_declaration(OnyxWasmModule* module, OnyxAstNodeGlobal* global) {
+static void compile_global_declaration(OnyxWasmModule* module, AstNodeGlobal* global) {
WasmGlobal glob = {
- .type = onyx_type_to_wasm_type(global->type),
- .mutable = (global->flags & ONYX_AST_FLAG_CONST) == 0,
+ .type = onyx_type_to_wasm_type(global->base.type),
+ .mutable = (global->base.flags & ONYX_AST_FLAG_CONST) == 0,
.initial_value = NULL,
};
if (!global->initial_value) {
onyx_message_add(module->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
- global->token->pos,
+ global->base.token->pos,
"global without initial value");
return;
}
- if ((global->flags & ONYX_AST_FLAG_EXPORTED) != 0) {
- onyx_token_null_toggle(*global->token);
+ if ((global->base.flags & ONYX_AST_FLAG_EXPORTED) != 0) {
+ onyx_token_null_toggle(global->base.token);
i32 global_idx = (i32) bh_imap_get(&module->func_map, (u64) global);
.kind = WASM_FOREIGN_GLOBAL,
.idx = global_idx,
};
- bh_table_put(WasmExport, module->exports, global->token->token, wasm_export);
+ bh_table_put(WasmExport, module->exports, global->base.token->token, wasm_export);
module->export_count++;
- onyx_token_null_toggle(*global->token);
+ onyx_token_null_toggle(global->base.token);
}
compile_expression(module, &glob.initial_value, global->initial_value);
bh_arr_push(module->globals, glob);
}
-static void compile_foreign(OnyxWasmModule* module, OnyxAstNodeForeign* foreign) {
- if (foreign->import->kind == ONYX_AST_NODE_KIND_FUNCTION) {
- i32 type_idx = generate_type_idx(module, &foreign->import->as_function);
+static void compile_foreign(OnyxWasmModule* module, AstNodeForeign* foreign) {
+ if (foreign->import->kind == AST_NODE_KIND_FUNCTION) {
+ i32 type_idx = generate_type_idx(module, (AstNodeFunction *) foreign->import);
WasmImport import = {
.kind = WASM_FOREIGN_FUNCTION,
bh_arr_push(module->imports, import);
- } else if (foreign->import->kind == ONYX_AST_NODE_KIND_GLOBAL) {
- WasmType global_type = onyx_type_to_wasm_type(foreign->import->type);
+ } else if (foreign->import->kind == AST_NODE_KIND_GLOBAL) {
+ WasmType global_type = onyx_type_to_wasm_type(((AstNodeGlobal *) foreign->import)->base.type);
WasmImport import = {
.kind = WASM_FOREIGN_GLOBAL,
void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program) {
// NOTE: First, introduce all indicies for globals and functions
- bh_arr_each(OnyxAstNodeForeign *, foreign, program->foreigns) {
- OnyxAstNodeKind import_kind = (*foreign)->import->kind;
+ bh_arr_each(AstNodeForeign *, foreign, program->foreigns) {
+ AstNodeKind import_kind = (*foreign)->import->kind;
- if (import_kind == ONYX_AST_NODE_KIND_FUNCTION) {
+ if (import_kind == AST_NODE_KIND_FUNCTION) {
module->next_func_idx++;
bh_imap_put(&module->func_map, (u64) (*foreign)->import, module->next_import_func_idx++);
}
- else if (import_kind == ONYX_AST_NODE_KIND_GLOBAL) {
+ else if (import_kind == AST_NODE_KIND_GLOBAL) {
module->next_global_idx++;
bh_imap_put(&module->global_map, (u64) (*foreign)->import, module->next_import_func_idx++);
}
compile_foreign(module, *foreign);
}
- bh_arr_each(OnyxAstNodeFunction *, function, program->functions)
+ bh_arr_each(AstNodeFunction *, function, program->functions)
bh_imap_put(&module->func_map, (u64) *function, module->next_func_idx++);
- bh_arr_each(OnyxAstNodeGlobal *, global, program->globals)
+ bh_arr_each(AstNodeGlobal *, global, program->globals)
bh_imap_put(&module->global_map, (u64) *global, module->next_global_idx++);
// NOTE: Then, compile everything
- bh_arr_each(OnyxAstNodeFunction *, function, program->functions)
+ bh_arr_each(AstNodeFunction *, function, program->functions)
compile_function(module, *function);
- bh_arr_each(OnyxAstNodeGlobal *, global, program->globals)
+ bh_arr_each(AstNodeGlobal *, global, program->globals)
compile_global_declaration(module, *global);
}