OBJ_FILES=\
build/onyxlex.o \
build/onyxparser.o \
+ build/onyxtypes.o \
build/onyxsempass.o \
build/onyxsymres.o \
build/onyxchecker.o \
#define ONYXASTNODES_H
#include "onyxlex.h"
+#include "onyxtypes.h"
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 AstNodeLocalGroup AstNodeLocalGroup;
-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 AstNodeIntrinsicCall AstNodeIntrinsicCall;
-typedef struct AstNodeArgument AstNodeArgument;
-typedef struct AstNodeUse AstNodeUse;
-
-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_LOCAL_GROUP,
- 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_INTRINSIC_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_unsigned : 1;
- u32 is_float : 1;
- u32 is_bool : 1;
- u32 is_known : 1;
-} TypeInfo;
-
-extern TypeInfo builtin_types[];
+typedef struct AstTyped AstTyped;
+typedef struct AstUnaryOp AstUnaryOp;
+typedef struct AstBinOp AstBinaryOp;
+typedef struct AstAssign AstAssign;
+typedef struct AstNumLit AstNumLit;
+typedef struct AstLocal AstLocal;
+typedef struct AstLocalGroup AstLocalGroup;
+typedef struct AstReturn AstReturn;
+typedef struct AstBlock AstBlock;
+typedef struct AstIf AstIf;
+typedef struct AstWhile AstWhile;
+typedef struct AstFunction AstFunction;
+typedef struct AstForeign AstForeign;
+typedef struct AstGlobal AstGlobal;
+typedef struct AstCall AstCall;
+typedef struct AstIntrinsicCall AstIntrinsicCall;
+typedef struct AstArgument AstArgument;
+typedef struct AstUse AstUse;
+
+typedef enum AstKind {
+ Ast_Kind_Error,
+ Ast_Kind_Program,
+ Ast_Kind_Use,
+
+ Ast_Kind_Function,
+ Ast_Kind_Foreign,
+ Ast_Kind_Block,
+ Ast_Kind_Local_Group,
+ Ast_Kind_Local,
+ Ast_Kind_Global,
+ Ast_Kind_Symbol,
+
+ Ast_Kind_Unary_Op,
+ Ast_Kind_Binary_Op,
+
+ Ast_Kind_Type,
+ Ast_Kind_Literal,
+ Ast_Kind_Param,
+ Ast_Kind_Argument,
+ Ast_Kind_Call,
+ Ast_Kind_Intrinsic_Call,
+ Ast_Kind_Assignment,
+ Ast_Kind_Return,
+
+ Ast_Kind_If,
+ Ast_Kind_While,
+ Ast_Kind_Break,
+ Ast_Kind_Continue,
+
+ Ast_Kind_Count
+} AstKind;
// NOTE: Some of these flags will overlap since there are
// only 32-bits of flags to play with
-typedef enum OnyxAstFlags {
+typedef enum AstFlags {
// Top-level flags
- ONYX_AST_FLAG_EXPORTED = BH_BIT(0),
- ONYX_AST_FLAG_LVAL = BH_BIT(1),
- ONYX_AST_FLAG_CONST = BH_BIT(2),
- ONYX_AST_FLAG_COMPTIME = BH_BIT(3),
+ Ast_Flag_Exported = BH_BIT(0),
+ Ast_Flag_Lval = BH_BIT(1),
+ Ast_Flag_Const = BH_BIT(2),
+ Ast_Flag_Comptime = BH_BIT(3),
// Function flags
- ONYX_AST_FLAG_INLINE = BH_BIT(8),
- ONYX_AST_FLAG_INTRINSIC = BH_BIT(9),
-} OnyxAstFlags;
-
-typedef enum OnyxUnaryOp {
- ONYX_UNARY_OP_NEGATE,
- ONYX_UNARY_OP_NOT,
- ONYX_UNARY_OP_CAST,
-} OnyxUnaryOp;
-
-typedef enum OnyxBinaryOp {
- ONYX_BINARY_OP_ADD = 0,
- ONYX_BINARY_OP_MINUS = 1,
- ONYX_BINARY_OP_MULTIPLY = 2,
- ONYX_BINARY_OP_DIVIDE = 3,
- ONYX_BINARY_OP_MODULUS = 4,
-
- ONYX_BINARY_OP_EQUAL = 5,
- ONYX_BINARY_OP_NOT_EQUAL = 6,
- ONYX_BINARY_OP_LESS = 7,
- ONYX_BINARY_OP_LESS_EQUAL = 8,
- ONYX_BINARY_OP_GREATER = 9,
- ONYX_BINARY_OP_GREATER_EQUAL = 10,
-} OnyxBinaryOp;
-
-// NOTE: AstNode and AstNodeTyped need to be EXACTLY the same for
-// all arguments existing in AstNode. I do this to avoid a nested
+ Ast_Flag_Inline = BH_BIT(8),
+ Ast_Flag_Intrinsic = BH_BIT(9),
+} AstFlags;
+
+typedef enum UnaryOp {
+ Unary_Op_Negate,
+ Unary_Op_Not,
+ Unary_Op_Cast,
+} UnaryOp;
+
+typedef enum BinaryOp {
+ Binary_Op_Add = 0,
+ Binary_Op_Minus = 1,
+ Binary_Op_Multiply = 2,
+ Binary_Op_Divide = 3,
+ Binary_Op_Modulus = 4,
+
+ Binary_Op_Equal = 5,
+ Binary_Op_Not_Equal = 6,
+ Binary_Op_Less = 7,
+ Binary_Op_Less_Equal = 8,
+ Binary_Op_Greater = 9,
+ Binary_Op_Greater_Equal = 10,
+} BinaryOp;
+
+// NOTE: AstNode and AstTyped 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;
+ AstKind kind;
u32 flags;
OnyxToken *token;
AstNode *next;
};
-struct AstNodeTyped {
- AstNodeKind kind;
+struct AstTyped {
+ AstKind kind;
u32 flags;
OnyxToken *token;
AstNode *next;
- TypeInfo *type;
+ Type *type;
};
-struct AstNodeBinOp {
- AstNodeTyped base;
+struct AstBinOp {
+ AstTyped base;
- OnyxBinaryOp operation;
+ BinaryOp operation;
- AstNodeTyped *left, *right;
+ AstTyped *left, *right;
};
-struct AstNodeUnaryOp {
- AstNodeTyped base;
+struct AstUnaryOp {
+ AstTyped base;
- OnyxUnaryOp operation;
+ UnaryOp operation;
- AstNodeTyped *expr;
+ AstTyped *expr;
};
-struct AstNodeAssign {
+struct AstAssign {
AstNode base;
- AstNodeTyped* lval;
- AstNodeTyped* expr;
+ AstTyped* lval;
+ AstTyped* expr;
};
-struct AstNodeNumLit {
- AstNodeTyped base;
+struct AstNumLit {
+ AstTyped base;
union { i32 i; i64 l; f32 f; f64 d; } value;
};
-struct AstNodeLocal {
- AstNodeTyped base;
+struct AstLocal {
+ AstTyped base;
- AstNodeLocal *prev_local;
+ AstLocal *prev_local;
};
-struct AstNodeReturn {
+struct AstReturn {
AstNode base;
- AstNodeTyped* expr;
+ AstTyped* expr;
};
-struct AstNodeLocalGroup {
+struct AstLocalGroup {
AstNode base;
- AstNodeLocalGroup *prev_group;
- AstNodeLocal *last_local;
+ AstLocalGroup *prev_group;
+ AstLocal *last_local;
};
-struct AstNodeBlock {
+struct AstBlock {
AstNode base;
AstNode *body;
- AstNodeLocalGroup *locals;
+ AstLocalGroup *locals;
};
-struct AstNodeIf {
+struct AstIf {
AstNode base;
- AstNodeTyped *cond;
+ AstTyped *cond;
union {
- AstNodeIf *as_if;
- AstNodeBlock* as_block;
+ AstIf *as_if;
+ AstBlock* as_block;
} true_block, false_block;
};
-struct AstNodeWhile {
+struct AstWhile {
AstNode base;
- AstNodeTyped *cond;
- AstNodeBlock *body;
+ AstTyped *cond;
+ AstBlock *body;
};
-struct AstNodeFunction {
- AstNodeTyped base;
+struct AstFunction {
+ AstTyped base;
- AstNodeBlock *body;
- AstNodeLocal *params;
+ AstBlock *body;
+ AstLocal *params;
};
-struct AstNodeForeign {
+struct AstForeign {
AstNode base;
OnyxToken *mod_token, *name_token;
AstNode *import;
};
-struct AstNodeGlobal {
- AstNodeTyped base;
+struct AstGlobal {
+ AstTyped base;
- AstNodeTyped *initial_value;
+ AstTyped *initial_value;
};
-struct AstNodeCall {
- AstNodeTyped base;
+struct AstCall {
+ AstTyped base;
- AstNodeArgument *arguments; // NOTE: Expressions that form the actual param list
+ AstArgument *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
AstNode *callee; // NOTE: Function definition node
};
-struct AstNodeArgument {
- AstNodeTyped base;
+struct AstArgument {
+ AstTyped base;
- AstNodeTyped *value;
+ AstTyped *value;
};
typedef enum OnyxIntrinsic {
// NOTE: This needs to have 'arguments' in the
// same position as AstNodeCall
-struct AstNodeIntrinsicCall {
- AstNodeTyped base;
+struct AstIntrinsicCall {
+ AstTyped base;
- AstNodeArgument *arguments;
+ AstArgument *arguments;
OnyxIntrinsic intrinsic;
};
-struct AstNodeUse {
+struct AstUse {
AstNode base;
OnyxToken *filename;
};
typedef struct OnyxProgram {
- bh_arr(AstNodeGlobal *) globals;
- bh_arr(AstNodeFunction *) functions;
- bh_arr(AstNodeForeign *) foreigns;
+ bh_arr(AstGlobal *) globals;
+ bh_arr(AstFunction *) functions;
+ bh_arr(AstForeign *) foreigns;
} OnyxProgram;
#endif // #ifndef ONYXASTNODES_H
#include "bh.h"
typedef enum TokenType {
- TOKEN_TYPE_ASCII_END = 256,
- TOKEN_TYPE_UNKNOWN = 256,
- TOKEN_TYPE_END_STREAM = 257,
-
- TOKEN_TYPE_COMMENT = 258,
-
- TOKEN_TYPE_KEYWORD_STRUCT = 259,
- TOKEN_TYPE_KEYWORD_USE = 260,
- TOKEN_TYPE_KEYWORD_EXPORT = 261,
- TOKEN_TYPE_KEYWORD_IF = 262,
- TOKEN_TYPE_KEYWORD_ELSE = 263,
- TOKEN_TYPE_KEYWORD_ELSEIF = 264,
- TOKEN_TYPE_KEYWORD_RETURN = 265,
- TOKEN_TYPE_KEYWORD_FOREIGN = 266,
- TOKEN_TYPE_KEYWORD_PROC = 267,
- TOKEN_TYPE_KEYWORD_CAST = 268,
- TOKEN_TYPE_KEYWORD_WHILE = 269,
- TOKEN_TYPE_KEYWORD_BREAK = 270,
- TOKEN_TYPE_KEYWORD_CONTINUE = 271,
-
- TOKEN_TYPE_RIGHT_ARROW = 272,
- TOKEN_TYPE_LEFT_ARROW = 273,
-
- TOKEN_TYPE_GREATER_EQUAL = 274,
- TOKEN_TYPE_LESS_EQUAL = 275,
- TOKEN_TYPE_EQUAL_EQUAL = 276,
- TOKEN_TYPE_NOT_EQUAL = 277,
- TOKEN_TYPE_PLUS_EQUAL = 278,
- TOKEN_TYPE_MINUS_EQUAL = 279,
- TOKEN_TYPE_STAR_EQUAL = 280,
- TOKEN_TYPE_FSLASH_EQUAL = 281,
- TOKEN_TYPE_PERCENT_EQUAL = 282,
-
- TOKEN_TYPE_SYMBOL = 283,
- TOKEN_TYPE_LITERAL_STRING = 284,
- TOKEN_TYPE_LITERAL_NUMERIC = 285,
- TOKEN_TYPE_LITERAL_BOOL_TRUE = 286,
- TOKEN_TYPE_LITERAL_BOOL_FALSE = 287,
-
- TOKEN_TYPE_COUNT = 288
+ Token_Type_Ascii_End = 256,
+ Token_Type_Unknown = 256,
+ Token_Type_End_Stream = 257,
+
+ Token_Type_Comment = 258,
+
+ Token_Type_Keyword_Struct = 259,
+ Token_Type_Keyword_Use = 260,
+ Token_Type_Keyword_Export = 261,
+ Token_Type_Keyword_If = 262,
+ Token_Type_Keyword_Else = 263,
+ Token_Type_Keyword_Elseif = 264,
+ Token_Type_Keyword_Return = 265,
+ Token_Type_Keyword_Foreign = 266,
+ Token_Type_Keyword_Proc = 267,
+ Token_Type_Keyword_Cast = 268,
+ Token_Type_Keyword_While = 269,
+ Token_Type_Keyword_Break = 270,
+ Token_Type_Keyword_Continue = 271,
+
+ Token_Type_Right_Arrow = 272,
+ Token_Type_Left_Arrow = 273,
+
+ Token_Type_Greater_Equal = 274,
+ Token_Type_Less_Equal = 275,
+ Token_Type_Equal_Equal = 276,
+ Token_Type_Not_Equal = 277,
+ Token_Type_Plus_Equal = 278,
+ Token_Type_Minus_Equal = 279,
+ Token_Type_Star_Equal = 280,
+ Token_Type_Fslash_Equal = 281,
+ Token_Type_Percent_Equal = 282,
+
+ Token_Type_Symbol = 283,
+ Token_Type_Literal_String = 284,
+ Token_Type_Literal_Numeric = 285,
+ Token_Type_Literal_True = 286,
+ Token_Type_Literal_False = 287,
+
+ Token_Type_Count = 288
} TokenType;
typedef struct OnyxFilePos {
bh_allocator allocator;
} OnyxParser;
-const char* onyx_ast_node_kind_string(AstNodeKind kind);
-void* onyx_ast_node_new(bh_allocator alloc, i32 size, AstNodeKind kind);
+const char* onyx_ast_node_kind_string(AstKind kind);
+void* onyx_ast_node_new(bh_allocator alloc, i32 size, AstKind kind);
OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, OnyxMessages* msgs);
void onyx_parser_free(OnyxParser* parser);
bh_arr(AstNode *) onyx_parse(OnyxParser *parser);
OnyxMessages *msgs;
// NOTE: Used in symbol resolution phase
- AstNodeLocalGroup* curr_local_group;
+ AstLocalGroup* curr_local_group;
// NOTE: Used in type checking phase
TypeInfo* expected_return_type;
--- /dev/null
+#ifndef ONYXTYPES_H
+#define ONYXTYPES_H
+
+#include "bh.h"
+
+enum BasicKind {
+ Basic_Kind_Void,
+
+ Basic_Kind_Bool,
+
+ Basic_Kind_I8,
+ Basic_Kind_U8,
+ Basic_Kind_I16,
+ Basic_Kind_U16,
+ Basic_Kind_I32,
+ Basic_Kind_U32,
+ Basic_Kind_I64,
+ Basic_Kind_U64,
+
+ Basic_Kind_F32,
+ Basic_Kind_F64,
+
+ Basic_Kind_Rawptr,
+};
+
+enum BasicFlag {
+ Basic_Flag_Boolean = BH_BIT(0),
+ Basic_Flag_Integer = BH_BIT(1),
+ Basic_Flag_Unsigned = BH_BIT(2),
+ Basic_Flag_Float = BH_BIT(3),
+ Basic_Flag_Pointer = BH_BIT(4),
+
+ Basic_Flag_Numeric = Basic_Flag_Integer | Basic_Flag_Float,
+ Basic_Flag_Ordered = Basic_Flag_Integer | Basic_Flag_Float | Basic_Flag_Pointer,
+ Basic_Flag_Constant_Type = Basic_Flag_Boolean | Basic_Flag_Numeric | Basic_Flag_Pointer,
+ Basic_Flag_Numeric_Ordered = Basic_Flag_Numeric | Basic_Flag_Ordered,
+};
+
+typedef struct TypeBasic {
+ enum BasicKind kind;
+ u32 flags;
+ i64 size; // NOTE: In bytes
+ const char* name;
+} TypeBasic;
+
+// NOTE: Forward declaration for some of the types below
+typedef struct Type Type;
+
+#define TYPE_KINDS \
+ TYPE_KIND(Basic, TypeBasic) \
+ TYPE_KIND(Pointer, struct { Type *elem; })
+
+typedef enum TypeKind {
+ Type_Kind_Invalid,
+
+#define TYPE_KIND(k, ...) Type_Kind_##k,
+ TYPE_KINDS
+#undef TYPE_KIND
+
+ Type_Kind_Count,
+} TypeKind;
+
+#define TYPE_KIND(k, ...) typedef __VA_ARGS__ Type ## k;
+ TYPE_KINDS
+#undef TYPE_KIND
+
+enum TypeFlag {
+ Type_Flag_Default
+};
+
+struct Type {
+ TypeKind kind;
+
+ union {
+#define TYPE_KIND(k, ...) Type##k k;
+ TYPE_KINDS
+#undef TYPE_KIND
+ };
+
+ u32 flags;
+};
+
+extern Type basic_types[];
+
+
+#endif // #ifndef ONYX_TYPES
extern bh_managed_heap global_heap;
extern bh_allocator global_heap_allocator;
-const char* onyx_ast_node_kind_string(AstNodeKind kind);
+const char* onyx_ast_node_kind_string(AstKind kind);
void onyx_ast_print(AstNode* program, i32 indent);
// }
export main :: proc {
+ print_i32(clz_i32(16));
print_f32(sqrt_f32(2.0f));
print_i32(5 * 6 + 2 * 3);
bh_arr(AstNode *) top_nodes = parse_source_file(compiler_state, &fc);
- bh_arr(AstNodeUse *) uses = NULL;
+ bh_arr(AstUse *) uses = NULL;
bh_arr_each(AstNode *, node, top_nodes) {
switch ((*node)->kind) {
- case AST_NODE_KIND_USE:
- bh_arr_push(uses, (AstNodeUse *) *node);
+ case Ast_Kind_Use:
+ bh_arr_push(uses, (AstUse *) *node);
break;
- case AST_NODE_KIND_GLOBAL:
- bh_arr_push(compiler_state->program.globals, (AstNodeGlobal *) (*node));
+ case Ast_Kind_Global:
+ bh_arr_push(compiler_state->program.globals, (AstGlobal *) (*node));
break;
- case AST_NODE_KIND_FOREIGN:
- bh_arr_push(compiler_state->program.foreigns, (AstNodeForeign *) (*node));
+ case Ast_Kind_Foreign:
+ bh_arr_push(compiler_state->program.foreigns, (AstForeign *) (*node));
break;
- case AST_NODE_KIND_FUNCTION:
- bh_arr_push(compiler_state->program.functions, (AstNodeFunction *) (*node));
+ case Ast_Kind_Function:
+ bh_arr_push(compiler_state->program.functions, (AstFunction *) (*node));
break;
default:
}
}
- bh_arr_each(AstNodeUse *, use_node, uses) {
+ bh_arr_each(AstUse *, use_node, uses) {
char* formatted_name = bh_aprintf(
global_heap_allocator,
"%b.onyx",
#define BH_DEBUG
#include "onyxsempass.h"
-static void check_function(OnyxSemPassState* state, AstNodeFunction* func);
-static void check_block(OnyxSemPassState* state, AstNodeBlock* block);
+static void check_function(OnyxSemPassState* state, AstFunction* func);
+static void check_block(OnyxSemPassState* state, AstBlock* block);
static void check_statement_chain(OnyxSemPassState* state, AstNode* start);
static void check_statement(OnyxSemPassState* state, AstNode* stmt);
-static void check_assignment(OnyxSemPassState* state, AstNodeAssign* assign);
-static void check_return(OnyxSemPassState* state, AstNodeReturn* retnode);
-static void check_if(OnyxSemPassState* state, AstNodeIf* ifnode);
-static void check_while(OnyxSemPassState* state, AstNodeWhile* whilenode);
-static void check_call(OnyxSemPassState* state, AstNodeCall* call);
-static void check_expression(OnyxSemPassState* state, AstNodeTyped* expr);
-static void check_global(OnyxSemPassState* state, AstNodeGlobal* global);
-
-static void check_assignment(OnyxSemPassState* state, AstNodeAssign* assign) {
- if (assign->lval->kind == AST_NODE_KIND_SYMBOL) {
+static void check_assignment(OnyxSemPassState* state, AstAssign* assign);
+static void check_return(OnyxSemPassState* state, AstReturn* retnode);
+static void check_if(OnyxSemPassState* state, AstIf* ifnode);
+static void check_while(OnyxSemPassState* state, AstWhile* whilenode);
+static void check_call(OnyxSemPassState* state, AstCall* call);
+static void check_expression(OnyxSemPassState* state, AstTyped* expr);
+static void check_global(OnyxSemPassState* state, AstGlobal* global);
+
+static void check_assignment(OnyxSemPassState* state, AstAssign* assign) {
+ if (assign->lval->kind == Ast_Kind_Symbol) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
assign->lval->token->pos,
return;
}
- if ((assign->lval->flags & ONYX_AST_FLAG_CONST) != 0 && assign->lval->type->is_known) {
+ if ((assign->lval->flags & Ast_Flag_Const) != 0 && assign->lval->type->is_known) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_ASSIGN_CONST,
assign->base.token->pos,
return;
}
- if ((assign->lval->flags & ONYX_AST_FLAG_LVAL) == 0) {
+ if ((assign->lval->flags & Ast_Flag_Lval) == 0) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_NOT_LVAL,
assign->base.token->pos,
}
}
-static void check_return(OnyxSemPassState* state, AstNodeReturn* retnode) {
+static void check_return(OnyxSemPassState* state, AstReturn* retnode) {
if (retnode->expr) {
check_expression(state, retnode->expr);
}
}
-static void check_if(OnyxSemPassState* state, AstNodeIf* ifnode) {
+static void check_if(OnyxSemPassState* state, AstIf* ifnode) {
check_expression(state, ifnode->cond);
if (ifnode->cond->type != &builtin_types[TYPE_INFO_KIND_BOOL]) {
onyx_message_add(state->msgs,
if (ifnode->false_block.as_if) check_statement(state, (AstNode *) ifnode->false_block.as_block);
}
-static void check_while(OnyxSemPassState* state, AstNodeWhile* whilenode) {
+static void check_while(OnyxSemPassState* state, AstWhile* whilenode) {
check_expression(state, whilenode->cond);
if (whilenode->cond->type != &builtin_types[TYPE_INFO_KIND_BOOL]) {
onyx_message_add(state->msgs,
check_block(state, whilenode->body);
}
-static void check_call(OnyxSemPassState* state, AstNodeCall* call) {
- AstNodeFunction* callee = (AstNodeFunction *) call->callee;
+static void check_call(OnyxSemPassState* state, AstCall* call) {
+ AstFunction* callee = (AstFunction *) call->callee;
- if (callee->base.kind == AST_NODE_KIND_SYMBOL) {
+ if (callee->base.kind == Ast_Kind_Symbol) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
callee->base.token->pos,
return;
}
- if (callee->base.kind != AST_NODE_KIND_FUNCTION) {
+ if (callee->base.kind != Ast_Kind_Function) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_CALL_NON_FUNCTION,
call->base.token->pos,
// NOTE: If we calling an intrinsic function, translate the
// call into an intrinsic call node.
- if (callee->base.flags & ONYX_AST_FLAG_INTRINSIC) {
- call->base.kind = AST_NODE_KIND_INTRINSIC_CALL;
+ if (callee->base.flags & Ast_Flag_Intrinsic) {
+ call->base.kind = Ast_Kind_Intrinsic_Call;
call->callee = NULL;
onyx_token_null_toggle(callee->base.token);
else if (!strcmp("max_f64", intr_name)) intrinsic = ONYX_INTRINSIC_F64_MAX;
else if (!strcmp("copysign_f64", intr_name)) intrinsic = ONYX_INTRINSIC_F64_COPYSIGN;
- ((AstNodeIntrinsicCall *)call)->intrinsic = intrinsic;
+ ((AstIntrinsicCall *)call)->intrinsic = intrinsic;
onyx_token_null_toggle(callee->base.token);
}
call->base.type = callee->base.type;
- AstNodeLocal* formal_param = callee->params;
- AstNodeArgument* actual_param = call->arguments;
+ AstLocal* formal_param = callee->params;
+ AstArgument* actual_param = call->arguments;
i32 arg_pos = 0;
while (formal_param != NULL && actual_param != NULL) {
- check_expression(state, (AstNodeTyped *) actual_param);
+ check_expression(state, (AstTyped *) actual_param);
if (formal_param->base.type != actual_param->base.type) {
onyx_message_add(state->msgs,
}
arg_pos++;
- formal_param = (AstNodeLocal *) formal_param->base.next;
- actual_param = (AstNodeArgument *) actual_param->base.next;
+ formal_param = (AstLocal *) formal_param->base.next;
+ actual_param = (AstArgument *) actual_param->base.next;
}
if (formal_param != NULL && actual_param == NULL) {
}
}
-static void check_expression(OnyxSemPassState* state, AstNodeTyped* expr) {
+static void check_expression(OnyxSemPassState* state, AstTyped* expr) {
switch (expr->kind) {
- case AST_NODE_KIND_BIN_OP:
+ case Ast_Kind_Binary_Op:
expr->type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
- check_expression(state, ((AstNodeBinOp *) expr)->left);
- check_expression(state, ((AstNodeBinOp *) expr)->right);
+ check_expression(state, ((AstBinaryOp *) expr)->left);
+ check_expression(state, ((AstBinaryOp *) expr)->right);
- if (((AstNodeBinOp *) expr)->left->type == NULL) {
+ if (((AstBinaryOp *) expr)->left->type == NULL) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
expr->token->pos,
return;
}
- if (((AstNodeBinOp *) expr)->right->type == NULL) {
+ if (((AstBinaryOp *) expr)->right->type == NULL) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
expr->token->pos,
return;
}
- if (((AstNodeBinOp *) expr)->left->type != ((AstNodeBinOp *) expr)->right->type) {
+ if (((AstBinaryOp *) expr)->left->type != ((AstBinaryOp *) expr)->right->type) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_BINOP_MISMATCH_TYPE,
expr->token->pos,
- ((AstNodeBinOp *) expr)->left->type->name,
- ((AstNodeBinOp *) expr)->right->type->name);
+ ((AstBinaryOp *) expr)->left->type->name,
+ ((AstBinaryOp *) expr)->right->type->name);
return;
}
- if (((AstNodeBinOp *) expr)->operation >= ONYX_BINARY_OP_EQUAL
- && ((AstNodeBinOp *) expr)->operation <= ONYX_BINARY_OP_GREATER_EQUAL) {
+ if (((AstBinaryOp *) expr)->operation >= Binary_Op_Equal
+ && ((AstBinaryOp *) expr)->operation <= Binary_Op_Greater_Equal) {
expr->type = &builtin_types[TYPE_INFO_KIND_BOOL];
} else {
- expr->type = ((AstNodeBinOp *) expr)->left->type;
+ expr->type = ((AstBinaryOp *) expr)->left->type;
}
break;
- case AST_NODE_KIND_UNARY_OP:
- if (((AstNodeUnaryOp *) expr)->operation != ONYX_UNARY_OP_CAST) {
- check_expression(state, ((AstNodeUnaryOp *) expr)->expr);
- expr->type = ((AstNodeUnaryOp *) expr)->expr->type;
+ case Ast_Kind_Unary_Op:
+ if (((AstUnaryOp *) expr)->operation != Unary_Op_Cast) {
+ check_expression(state, ((AstUnaryOp *) expr)->expr);
+ expr->type = ((AstUnaryOp *) expr)->expr->type;
}
break;
- case AST_NODE_KIND_CALL:
- check_call(state, (AstNodeCall *) expr);
+ case Ast_Kind_Call:
+ check_call(state, (AstCall *) expr);
break;
- case AST_NODE_KIND_BLOCK:
- check_block(state, (AstNodeBlock *) expr);
+ case Ast_Kind_Block:
+ check_block(state, (AstBlock *) expr);
break;
- case AST_NODE_KIND_SYMBOL:
+ case Ast_Kind_Symbol:
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
expr->token->pos,
expr->token->text, expr->token->length);
break;
- case AST_NODE_KIND_LOCAL:
- case AST_NODE_KIND_PARAM:
+ case Ast_Kind_Local:
+ case Ast_Kind_Param:
if (!expr->type->is_known) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
}
break;
- case AST_NODE_KIND_GLOBAL:
+ case Ast_Kind_Global:
if (!expr->type->is_known) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
}
break;
- case AST_NODE_KIND_ARGUMENT:
- check_expression(state, ((AstNodeArgument *) expr)->value);
- expr->type = ((AstNodeArgument *) expr)->value->type;
+ case Ast_Kind_Argument:
+ check_expression(state, ((AstArgument *) expr)->value);
+ expr->type = ((AstArgument *) expr)->value->type;
break;
- case AST_NODE_KIND_LITERAL:
+ case Ast_Kind_Literal:
// NOTE: Literal types should have been decided
// in the parser (for now).
assert(expr->type->is_known);
}
}
-static void check_global(OnyxSemPassState* state, AstNodeGlobal* global) {
+static void check_global(OnyxSemPassState* state, AstGlobal* global) {
if (global->initial_value) {
check_expression(state, global->initial_value);
static void check_statement(OnyxSemPassState* state, AstNode* stmt) {
switch (stmt->kind) {
- case AST_NODE_KIND_ASSIGNMENT: check_assignment(state, (AstNodeAssign *) stmt); break;
- case AST_NODE_KIND_RETURN: check_return(state, (AstNodeReturn *) stmt); break;
- case AST_NODE_KIND_IF: check_if(state, (AstNodeIf *) stmt); break;
- case AST_NODE_KIND_WHILE: check_while(state, (AstNodeWhile *) stmt); break;
- case AST_NODE_KIND_CALL: check_call(state, (AstNodeCall *) stmt); break;
- case AST_NODE_KIND_BLOCK: check_block(state, (AstNodeBlock *) stmt); break;
+ case Ast_Kind_Assignment: check_assignment(state, (AstAssign *) stmt); break;
+ case Ast_Kind_Return: check_return(state, (AstReturn *) stmt); break;
+ case Ast_Kind_If: check_if(state, (AstIf *) stmt); break;
+ case Ast_Kind_While: check_while(state, (AstWhile *) stmt); break;
+ case Ast_Kind_Call: check_call(state, (AstCall *) stmt); break;
+ case Ast_Kind_Block: check_block(state, (AstBlock *) stmt); break;
default: break;
}
}
}
-static void check_block(OnyxSemPassState* state, AstNodeBlock* block) {
+static void check_block(OnyxSemPassState* state, AstBlock* block) {
check_statement_chain(state, block->body);
- forll(AstNodeLocal, local, block->locals->last_local, prev_local) {
+ forll(AstLocal, local, block->locals->last_local, prev_local) {
if (!local->base.type->is_known) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
}
}
-static void check_function(OnyxSemPassState* state, AstNodeFunction* func) {
- for (AstNodeLocal *param = func->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
+static void check_function(OnyxSemPassState* state, AstFunction* func) {
+ for (AstLocal *param = func->params; param != NULL; param = (AstLocal *) param->base.next) {
if (!param->base.type->is_known) {
onyx_message_add(state->msgs,
ONYX_MESSAGE_TYPE_LITERAL,
void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program) {
- bh_arr_each(AstNodeGlobal *, global, program->globals)
+ bh_arr_each(AstGlobal *, global, program->globals)
check_global(state, *global);
- bh_arr_each(AstNodeFunction *, function, program->functions)
+ bh_arr_each(AstFunction *, function, program->functions)
check_function(state, *function);
}
}
const char* onyx_get_token_type_name(TokenType tkn_type) {
- if (tkn_type < TOKEN_TYPE_ASCII_END) {
+ if (tkn_type < Token_Type_Ascii_End) {
return bh_aprintf(global_scratch_allocator, "%c", (char) tkn_type);
} else {
- return token_type_names[tkn_type - TOKEN_TYPE_ASCII_END];
+ return token_type_names[tkn_type - Token_Type_Ascii_End];
}
}
while (char_is_whitespace(*tokenizer->curr) && tokenizer->curr != tokenizer->end)
INCREMENT_CURR_TOKEN(tokenizer)
- tk.type = TOKEN_TYPE_UNKNOWN;
+ tk.type = Token_Type_Unknown;
tk.text = tokenizer->curr;
tk.length = 1;
tk.pos.line_start = tokenizer->line_start;
tk.pos.column = (i32)(tokenizer->curr - tokenizer->line_start) + 1;
if (tokenizer->curr == tokenizer->end) {
- tk.type = TOKEN_TYPE_END_STREAM;
+ tk.type = Token_Type_End_Stream;
goto token_parsed;
}
// Comments
if (*tokenizer->curr == '/' && *(tokenizer->curr + 1) == '/') {
tokenizer->curr += 2;
- tk.type = TOKEN_TYPE_COMMENT;
+ tk.type = Token_Type_Comment;
tk.text = tokenizer->curr;
while (*tokenizer->curr != '\n') {
goto token_parsed;
}
- LITERAL_TOKEN("struct", 1, TOKEN_TYPE_KEYWORD_STRUCT);
- LITERAL_TOKEN("export", 1, TOKEN_TYPE_KEYWORD_EXPORT);
- LITERAL_TOKEN("use", 1, TOKEN_TYPE_KEYWORD_USE);
- LITERAL_TOKEN("if", 1, TOKEN_TYPE_KEYWORD_IF);
- LITERAL_TOKEN("elseif", 1, TOKEN_TYPE_KEYWORD_ELSEIF);
- LITERAL_TOKEN("else", 1, TOKEN_TYPE_KEYWORD_ELSE);
- LITERAL_TOKEN("foreign", 1, TOKEN_TYPE_KEYWORD_FOREIGN);
- LITERAL_TOKEN("return", 1, TOKEN_TYPE_KEYWORD_RETURN);
- LITERAL_TOKEN("proc", 1, TOKEN_TYPE_KEYWORD_PROC);
- LITERAL_TOKEN("as", 1, TOKEN_TYPE_KEYWORD_CAST);
- LITERAL_TOKEN("while", 1, TOKEN_TYPE_KEYWORD_WHILE);
- LITERAL_TOKEN("break", 1, TOKEN_TYPE_KEYWORD_BREAK);
- LITERAL_TOKEN("continue", 1, TOKEN_TYPE_KEYWORD_CONTINUE);
- LITERAL_TOKEN("true", 1, TOKEN_TYPE_LITERAL_BOOL_TRUE);
- LITERAL_TOKEN("false", 1, TOKEN_TYPE_LITERAL_BOOL_FALSE);
- LITERAL_TOKEN("->", 0, TOKEN_TYPE_RIGHT_ARROW);
- LITERAL_TOKEN("<-", 0, TOKEN_TYPE_RIGHT_ARROW);
- LITERAL_TOKEN("<=", 0, TOKEN_TYPE_LESS_EQUAL);
- LITERAL_TOKEN(">=", 0, TOKEN_TYPE_GREATER_EQUAL);
- LITERAL_TOKEN("==", 0, TOKEN_TYPE_EQUAL_EQUAL);
- LITERAL_TOKEN("!=", 0, TOKEN_TYPE_NOT_EQUAL);
- LITERAL_TOKEN("+=", 0, TOKEN_TYPE_PLUS_EQUAL);
- LITERAL_TOKEN("-=", 0, TOKEN_TYPE_MINUS_EQUAL);
- LITERAL_TOKEN("*=", 0, TOKEN_TYPE_STAR_EQUAL);
- LITERAL_TOKEN("/=", 0, TOKEN_TYPE_FSLASH_EQUAL);
- LITERAL_TOKEN("%=", 0, TOKEN_TYPE_PERCENT_EQUAL);
+ LITERAL_TOKEN("struct", 1, Token_Type_Keyword_Struct);
+ LITERAL_TOKEN("export", 1, Token_Type_Keyword_Export);
+ LITERAL_TOKEN("use", 1, Token_Type_Keyword_Use);
+ LITERAL_TOKEN("if", 1, Token_Type_Keyword_If);
+ LITERAL_TOKEN("elseif", 1, Token_Type_Keyword_Elseif);
+ LITERAL_TOKEN("else", 1, Token_Type_Keyword_Else);
+ LITERAL_TOKEN("foreign", 1, Token_Type_Keyword_Foreign);
+ LITERAL_TOKEN("return", 1, Token_Type_Keyword_Return);
+ LITERAL_TOKEN("proc", 1, Token_Type_Keyword_Proc);
+ LITERAL_TOKEN("as", 1, Token_Type_Keyword_Cast);
+ LITERAL_TOKEN("while", 1, Token_Type_Keyword_While);
+ LITERAL_TOKEN("break", 1, Token_Type_Keyword_Break);
+ LITERAL_TOKEN("continue", 1, Token_Type_Keyword_Continue);
+ LITERAL_TOKEN("true", 1, Token_Type_Literal_True);
+ LITERAL_TOKEN("false", 1, Token_Type_Literal_False);
+ LITERAL_TOKEN("->", 0, Token_Type_Right_Arrow);
+ LITERAL_TOKEN("<-", 0, Token_Type_Right_Arrow);
+ LITERAL_TOKEN("<=", 0, Token_Type_Less_Equal);
+ LITERAL_TOKEN(">=", 0, Token_Type_Greater_Equal);
+ LITERAL_TOKEN("==", 0, Token_Type_Equal_Equal);
+ LITERAL_TOKEN("!=", 0, Token_Type_Not_Equal);
+ LITERAL_TOKEN("+=", 0, Token_Type_Plus_Equal);
+ LITERAL_TOKEN("-=", 0, Token_Type_Minus_Equal);
+ LITERAL_TOKEN("*=", 0, Token_Type_Star_Equal);
+ LITERAL_TOKEN("/=", 0, Token_Type_Fslash_Equal);
+ LITERAL_TOKEN("%=", 0, Token_Type_Percent_Equal);
// Symbols
if (char_is_alpha(*tk.text)) {
}
tk.length = len;
- tk.type = TOKEN_TYPE_SYMBOL;
+ tk.type = Token_Type_Symbol;
goto token_parsed;
}
INCREMENT_CURR_TOKEN(tokenizer);
tk.text++;
- tk.type = TOKEN_TYPE_LITERAL_STRING;
+ tk.type = Token_Type_Literal_String;
tk.length = len;
goto token_parsed;
}
INCREMENT_CURR_TOKEN(tokenizer);
}
- tk.type = TOKEN_TYPE_LITERAL_NUMERIC;
+ tk.type = Token_Type_Literal_Numeric;
tk.length = len;
INCREMENT_CURR_TOKEN(tokenizer);
OnyxToken* tk;
do {
tk = onyx_get_token(tokenizer);
- } while (tk->type != TOKEN_TYPE_END_STREAM);
+ } while (tk->type != Token_Type_End_Stream);
}
{ 0xffffffff } // Sentinel
};
-static AstNode error_node = { AST_NODE_KIND_ERROR, 0, NULL, NULL };
+static AstNode error_node = { Ast_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(TokenType token_type);
static OnyxToken* expect(OnyxParser* parser, TokenType token_type);
-static AstNodeNumLit* parse_numeric_literal(OnyxParser* parser);
-static AstNodeTyped* parse_factor(OnyxParser* parser);
-static AstNodeTyped* parse_expression(OnyxParser* parser);
-static AstNodeIf* parse_if_stmt(OnyxParser* parser);
-static AstNodeWhile* parse_while_stmt(OnyxParser* parser);
+static AstNumLit* parse_numeric_literal(OnyxParser* parser);
+static AstTyped* parse_factor(OnyxParser* parser);
+static AstTyped* parse_expression(OnyxParser* parser);
+static AstIf* parse_if_stmt(OnyxParser* parser);
+static AstWhile* 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 AstReturn* parse_return_statement(OnyxParser* parser);
+static AstBlock* 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_type(OnyxParser* parser);
+static AstLocal* parse_function_params(OnyxParser* parser);
+static AstFunction* 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->curr_token++;
- while (parser->curr_token->type == TOKEN_TYPE_COMMENT) parser->curr_token++;
+ while (parser->curr_token->type == Token_Type_Comment) parser->curr_token++;
}
static void parser_prev_token(OnyxParser* parser) {
// TODO: This is probably wrong
- while (parser->prev_token->type == TOKEN_TYPE_COMMENT) parser->prev_token--;
+ while (parser->prev_token->type == Token_Type_Comment) parser->prev_token--;
parser->curr_token = parser->prev_token;
parser->prev_token--;
}
return (token_type == ';')
|| (token_type == '}')
|| (token_type == '{')
- || (token_type == TOKEN_TYPE_END_STREAM);
+ || (token_type == Token_Type_End_Stream);
}
static void find_token(OnyxParser* parser, TokenType token_type) {
return token;
}
-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;
+static AstNumLit* parse_numeric_literal(OnyxParser* parser) {
+ AstNumLit* lit_node = make_node(AstNumLit, Ast_Kind_Literal);
+ lit_node->base.token = expect(parser, Token_Type_Literal_Numeric);
+ lit_node->base.flags |= Ast_Flag_Comptime;
lit_node->value.l = 0ll;
onyx_token_null_toggle(lit_node->base.token);
return lit_node;
}
-static AstNodeTyped* parse_factor(OnyxParser* parser) {
- AstNodeTyped* retval = NULL;
+static AstTyped* parse_factor(OnyxParser* parser) {
+ AstTyped* retval = NULL;
switch ((u16) parser->curr_token->type) {
case '(':
{
parser_next_token(parser);
- AstNodeTyped* expr = parse_expression(parser);
+ AstTyped* expr = parse_expression(parser);
expect(parser, ')');
retval = expr;
break;
case '-':
{
parser_next_token(parser);
- AstNodeTyped* factor = parse_factor(parser);
+ AstTyped* factor = parse_factor(parser);
- AstNodeUnaryOp* negate_node = make_node(AstNodeUnaryOp, AST_NODE_KIND_UNARY_OP);
- negate_node->operation = ONYX_UNARY_OP_NEGATE;
+ AstUnaryOp* negate_node = make_node(AstUnaryOp, Ast_Kind_Unary_Op);
+ negate_node->operation = Unary_Op_Negate;
negate_node->expr = factor;
- if ((factor->flags & ONYX_AST_FLAG_COMPTIME) != 0) {
- negate_node->base.flags |= ONYX_AST_FLAG_COMPTIME;
+ if ((factor->flags & Ast_Flag_Comptime) != 0) {
+ negate_node->base.flags |= Ast_Flag_Comptime;
}
- retval = (AstNodeTyped *) negate_node;
+ retval = (AstTyped *) negate_node;
break;
}
- case TOKEN_TYPE_SYMBOL:
+ case Token_Type_Symbol:
{
- OnyxToken* sym_token = expect(parser, TOKEN_TYPE_SYMBOL);
- AstNodeTyped* sym_node = make_node(AstNode, AST_NODE_KIND_SYMBOL);
+ OnyxToken* sym_token = expect(parser, Token_Type_Symbol);
+ AstTyped* sym_node = make_node(AstTyped, Ast_Kind_Symbol);
sym_node->token = sym_token;
if (parser->curr_token->type != '(') {
}
// NOTE: Function call
- AstNodeCall* call_node = make_node(AstNodeCall, AST_NODE_KIND_CALL);
+ AstCall* call_node = make_node(AstCall, Ast_Kind_Call);
call_node->base.token = expect(parser, '(');
call_node->callee = (AstNode *) sym_node;
- AstNodeArgument** prev = &call_node->arguments;
- AstNodeArgument* curr = NULL;
+ AstArgument** prev = &call_node->arguments;
+ AstArgument* curr = NULL;
while (parser->curr_token->type != ')') {
- curr = make_node(AstNodeArgument, AST_NODE_KIND_ARGUMENT);
+ curr = make_node(AstArgument, Ast_Kind_Argument);
curr->value = parse_expression(parser);
- if (curr != NULL && curr->base.kind != AST_NODE_KIND_ERROR) {
+ if (curr != NULL && curr->base.kind != Ast_Kind_Error) {
*prev = curr;
- prev = (AstNodeArgument **) &curr->base.next;
+ prev = (AstArgument **) &curr->base.next;
}
if (parser->curr_token->type == ')')
parser->curr_token->pos,
onyx_get_token_type_name(','),
onyx_get_token_type_name(parser->curr_token->type));
- return (AstNodeTyped *) &error_node;
+ return (AstTyped *) &error_node;
}
parser_next_token(parser);
}
parser_next_token(parser);
- retval = (AstNodeTyped *) call_node;
+ retval = (AstTyped *) call_node;
break;
}
- case TOKEN_TYPE_LITERAL_NUMERIC:
- retval = (AstNodeTyped *) parse_numeric_literal(parser);
+ case Token_Type_Literal_Numeric:
+ retval = (AstTyped *) parse_numeric_literal(parser);
break;
- case TOKEN_TYPE_LITERAL_BOOL_TRUE:
+ case Token_Type_Literal_True:
{
- AstNodeNumLit* bool_node = make_node(AstNodeNumLit, AST_NODE_KIND_LITERAL);
+ AstNumLit* bool_node = make_node(AstNumLit, Ast_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->base.token = expect(parser, Token_Type_Literal_True);
bool_node->value.i = 1;
- retval = (AstNodeTyped *) bool_node;
+ retval = (AstTyped *) bool_node;
break;
}
- case TOKEN_TYPE_LITERAL_BOOL_FALSE:
+ case Token_Type_Literal_False:
{
- AstNodeNumLit* bool_node = make_node(AstNodeNumLit, AST_NODE_KIND_LITERAL);
+ AstNumLit* bool_node = make_node(AstNumLit, Ast_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->base.token = expect(parser, Token_Type_Literal_False);
bool_node->value.i = 0;
- retval = (AstNodeTyped *) bool_node;
+ retval = (AstTyped *) bool_node;
break;
}
return NULL;
}
- if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_CAST) {
+ if (parser->curr_token->type == Token_Type_Keyword_Cast) {
parser_next_token(parser);
- AstNodeUnaryOp* cast_node = make_node(AstNodeUnaryOp, AST_NODE_KIND_UNARY_OP);
+ AstUnaryOp* cast_node = make_node(AstUnaryOp, Ast_Kind_Unary_Op);
cast_node->base.type = parse_type(parser);
- cast_node->operation = ONYX_UNARY_OP_CAST;
+ cast_node->operation = Unary_Op_Cast;
cast_node->expr = retval;
- retval = (AstNodeTyped *) cast_node;
+ retval = (AstTyped *) cast_node;
}
return retval;
}
-static inline i32 get_precedence(OnyxBinaryOp kind) {
+static inline i32 get_precedence(BinaryOp kind) {
switch (kind) {
- case ONYX_BINARY_OP_EQUAL: return 3;
- case ONYX_BINARY_OP_NOT_EQUAL: return 3;
+ case Binary_Op_Equal: return 3;
+ case Binary_Op_Not_Equal: return 3;
- case ONYX_BINARY_OP_LESS_EQUAL: return 4;
- case ONYX_BINARY_OP_LESS: return 4;
- case ONYX_BINARY_OP_GREATER_EQUAL: return 4;
- case ONYX_BINARY_OP_GREATER: return 4;
+ case Binary_Op_Less_Equal: return 4;
+ case Binary_Op_Less: return 4;
+ case Binary_Op_Greater_Equal: return 4;
+ case Binary_Op_Greater: return 4;
- case ONYX_BINARY_OP_ADD: return 5;
- case ONYX_BINARY_OP_MINUS: return 5;
+ case Binary_Op_Add: return 5;
+ case Binary_Op_Minus: return 5;
- case ONYX_BINARY_OP_MULTIPLY: return 6;
- case ONYX_BINARY_OP_DIVIDE: return 6;
+ case Binary_Op_Multiply: return 6;
+ case Binary_Op_Divide: return 6;
- case ONYX_BINARY_OP_MODULUS: return 7;
+ case Binary_Op_Modulus: return 7;
default: return -1;
}
}
-static AstNodeTyped* parse_expression(OnyxParser* parser) {
- bh_arr(AstNodeBinOp*) tree_stack = NULL;
+static AstTyped* parse_expression(OnyxParser* parser) {
+ bh_arr(AstBinaryOp*) tree_stack = NULL;
bh_arr_new(global_scratch_allocator, tree_stack, 4);
bh_arr_set_length(tree_stack, 0);
- AstNodeTyped* left = parse_factor(parser);
- AstNodeTyped* right;
- AstNodeTyped* root = left;
+ AstTyped* left = parse_factor(parser);
+ AstTyped* right;
+ AstTyped* root = left;
- OnyxBinaryOp bin_op_kind;
+ BinaryOp bin_op_kind;
OnyxToken* bin_op_tok;
while (1) {
bin_op_kind = -1;
switch ((u16) parser->curr_token->type) {
- case TOKEN_TYPE_EQUAL_EQUAL: bin_op_kind = ONYX_BINARY_OP_EQUAL; break;
- case TOKEN_TYPE_NOT_EQUAL: bin_op_kind = ONYX_BINARY_OP_NOT_EQUAL; break;
- case TOKEN_TYPE_LESS_EQUAL: bin_op_kind = ONYX_BINARY_OP_LESS_EQUAL; break;
- case TOKEN_TYPE_GREATER_EQUAL: bin_op_kind = ONYX_BINARY_OP_GREATER_EQUAL; break;
- case '<': bin_op_kind = ONYX_BINARY_OP_LESS; break;
- case '>': bin_op_kind = ONYX_BINARY_OP_GREATER; break;
-
- case '+': bin_op_kind = ONYX_BINARY_OP_ADD; break;
- case '-': bin_op_kind = ONYX_BINARY_OP_MINUS; break;
- case '*': bin_op_kind = ONYX_BINARY_OP_MULTIPLY; break;
- case '/': bin_op_kind = ONYX_BINARY_OP_DIVIDE; break;
- case '%': bin_op_kind = ONYX_BINARY_OP_MODULUS; break;
+ case Token_Type_Equal_Equal: bin_op_kind = Binary_Op_Equal; break;
+ case Token_Type_Not_Equal: bin_op_kind = Binary_Op_Not_Equal; break;
+ case Token_Type_Less_Equal: bin_op_kind = Binary_Op_Less_Equal; break;
+ case Token_Type_Greater_Equal: bin_op_kind = Binary_Op_Greater_Equal; break;
+ case '<': bin_op_kind = Binary_Op_Less; break;
+ case '>': bin_op_kind = Binary_Op_Greater; break;
+
+ case '+': bin_op_kind = Binary_Op_Add; break;
+ case '-': bin_op_kind = Binary_Op_Minus; break;
+ case '*': bin_op_kind = Binary_Op_Multiply; break;
+ case '/': bin_op_kind = Binary_Op_Divide; break;
+ case '%': bin_op_kind = Binary_Op_Modulus; break;
default: goto expression_done;
}
bin_op_tok = parser->curr_token;
parser_next_token(parser);
- AstNodeBinOp* bin_op = make_node(AstNodeBinOp, AST_NODE_KIND_BIN_OP);
+ AstBinaryOp* bin_op = make_node(AstBinaryOp, Ast_Kind_Binary_Op);
bin_op->operation = bin_op_kind;
bin_op->base.token = bin_op_tok;
if (bh_arr_is_empty(tree_stack)) {
// NOTE: new is now the root node
bin_op->left = root;
- root = (AstNodeTyped *) bin_op;
+ root = (AstTyped *) bin_op;
} else {
bin_op->left = bh_arr_last(tree_stack)->right;
- bh_arr_last(tree_stack)->right = (AstNodeTyped *) bin_op;
+ bh_arr_last(tree_stack)->right = (AstTyped *) bin_op;
}
bh_arr_push(tree_stack, bin_op);
right = parse_factor(parser);
bin_op->right = right;
- if ((left->flags & ONYX_AST_FLAG_COMPTIME) != 0 && (right->flags & ONYX_AST_FLAG_COMPTIME) != 0) {
- bin_op->base.flags |= ONYX_AST_FLAG_COMPTIME;
+ if ((left->flags & Ast_Flag_Comptime) != 0 && (right->flags & Ast_Flag_Comptime) != 0) {
+ bin_op->base.flags |= Ast_Flag_Comptime;
}
}
}
return root;
}
-static AstNodeIf* parse_if_stmt(OnyxParser* parser) {
- expect(parser, TOKEN_TYPE_KEYWORD_IF);
+static AstIf* parse_if_stmt(OnyxParser* parser) {
+ expect(parser, Token_Type_Keyword_If);
- AstNodeTyped* cond = parse_expression(parser);
- AstNodeBlock* true_block = parse_block(parser);
+ AstTyped* cond = parse_expression(parser);
+ AstBlock* true_block = parse_block(parser);
- AstNodeIf* if_node = make_node(AstNodeIf, AST_NODE_KIND_IF);
- AstNodeIf* root_if = if_node;
+ AstIf* if_node = make_node(AstIf, Ast_Kind_If);
+ AstIf* root_if = if_node;
if_node->cond = cond;
if (true_block != NULL)
if_node->true_block.as_block = true_block;
- while (parser->curr_token->type == TOKEN_TYPE_KEYWORD_ELSEIF) {
+ while (parser->curr_token->type == Token_Type_Keyword_Elseif) {
parser_next_token(parser);
- AstNodeIf* elseif_node = make_node(AstNodeIf, AST_NODE_KIND_IF);
+ AstIf* elseif_node = make_node(AstIf, Ast_Kind_If);
cond = parse_expression(parser);
true_block = parse_block(parser);
if_node = elseif_node;
}
- if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_ELSE) {
+ if (parser->curr_token->type == Token_Type_Keyword_Else) {
parser_next_token(parser);
- AstNodeBlock* false_block = parse_block(parser);
+ AstBlock* false_block = parse_block(parser);
if (false_block != NULL)
if_node->false_block.as_block = false_block;
}
return root_if;
}
-static AstNodeWhile* parse_while_stmt(OnyxParser* parser) {
- OnyxToken* while_token = expect(parser, TOKEN_TYPE_KEYWORD_WHILE);
+static AstWhile* parse_while_stmt(OnyxParser* parser) {
+ OnyxToken* while_token = expect(parser, Token_Type_Keyword_While);
- AstNodeTyped* cond = parse_expression(parser);
- AstNodeBlock* body = parse_block(parser);
+ AstTyped* cond = parse_expression(parser);
+ AstBlock* body = parse_block(parser);
- AstNodeWhile* while_node = make_node(AstNodeWhile, AST_NODE_KIND_WHILE);
+ AstWhile* while_node = make_node(AstWhile, Ast_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, AstNode** ret) {
- if (parser->curr_token->type != TOKEN_TYPE_SYMBOL) return 0;
- OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL);
+ if (parser->curr_token->type != Token_Type_Symbol) return 0;
+ OnyxToken* symbol = expect(parser, Token_Type_Symbol);
switch ((u16) parser->curr_token->type) {
// NOTE: Declaration
TypeInfo* type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
// NOTE: var: type
- if (parser->curr_token->type == TOKEN_TYPE_SYMBOL) {
+ if (parser->curr_token->type == Token_Type_Symbol) {
type = parse_type(parser);
}
- AstNodeLocal* local = make_node(AstNodeLocal, AST_NODE_KIND_LOCAL);
+ AstLocal* local = make_node(AstLocal, Ast_Kind_Local);
local->base.token = symbol;
local->base.type = type;
- local->base.flags |= ONYX_AST_FLAG_LVAL; // NOTE: DELETE
+ local->base.flags |= Ast_Flag_Lval; // NOTE: DELETE
*ret = (AstNode *) local;
if (parser->curr_token->type == '=' || parser->curr_token->type == ':') {
if (parser->curr_token->type == ':') {
- local->base.flags |= ONYX_AST_FLAG_CONST;
+ local->base.flags |= Ast_Flag_Const;
}
- AstNodeAssign* assignment = make_node(AstNodeAssign, AST_NODE_KIND_ASSIGNMENT);
+ AstAssign* assignment = make_node(AstAssign, Ast_Kind_Assignment);
local->base.next = (AstNode *) assignment;
assignment->base.token = parser->curr_token;
parser_next_token(parser);
- AstNodeTyped* expr = parse_expression(parser);
+ AstTyped* expr = parse_expression(parser);
if (expr == NULL) {
onyx_token_null_toggle(parser->curr_token);
onyx_message_add(parser->msgs,
}
assignment->expr = expr;
- AstNode* left_symbol = make_node(AstNode, AST_NODE_KIND_SYMBOL);
+ AstNode* left_symbol = make_node(AstNode, Ast_Kind_Symbol);
left_symbol->token = symbol;
- assignment->lval = (AstNodeTyped *) left_symbol;
+ assignment->lval = (AstTyped *) left_symbol;
}
return 1;
}
// NOTE: Assignment
case '=':
{
- AstNodeAssign* assignment = make_node(AstNodeAssign, AST_NODE_KIND_ASSIGNMENT);
+ AstAssign* assignment = make_node(AstAssign, Ast_Kind_Assignment);
assignment->base.token = parser->curr_token;
parser_next_token(parser);
- AstNode* lval = make_node(AstNode, AST_NODE_KIND_SYMBOL);
+ AstNode* lval = make_node(AstNode, Ast_Kind_Symbol);
lval->token = symbol;
- AstNodeTyped* rval = parse_expression(parser);
+ AstTyped* rval = parse_expression(parser);
assignment->expr = rval;
- assignment->lval = (AstNodeTyped *) lval;
+ assignment->lval = (AstTyped *) lval;
*ret = (AstNode *) assignment;
return 1;
}
- case TOKEN_TYPE_PLUS_EQUAL:
- case TOKEN_TYPE_MINUS_EQUAL:
- case TOKEN_TYPE_STAR_EQUAL:
- case TOKEN_TYPE_FSLASH_EQUAL:
- case TOKEN_TYPE_PERCENT_EQUAL:
+ case Token_Type_Plus_Equal:
+ case Token_Type_Minus_Equal:
+ case Token_Type_Star_Equal:
+ case Token_Type_Fslash_Equal:
+ case Token_Type_Percent_Equal:
{
- OnyxBinaryOp bin_op;
- if (parser->curr_token->type == TOKEN_TYPE_PLUS_EQUAL) bin_op = ONYX_BINARY_OP_ADD;
- else if (parser->curr_token->type == TOKEN_TYPE_MINUS_EQUAL) bin_op = ONYX_BINARY_OP_MINUS;
- else if (parser->curr_token->type == TOKEN_TYPE_STAR_EQUAL) bin_op = ONYX_BINARY_OP_MULTIPLY;
- else if (parser->curr_token->type == TOKEN_TYPE_FSLASH_EQUAL) bin_op = ONYX_BINARY_OP_DIVIDE;
- else if (parser->curr_token->type == TOKEN_TYPE_PERCENT_EQUAL) bin_op = ONYX_BINARY_OP_MODULUS;
+ BinaryOp bin_op;
+ if (parser->curr_token->type == Token_Type_Plus_Equal) bin_op = Binary_Op_Add;
+ else if (parser->curr_token->type == Token_Type_Minus_Equal) bin_op = Binary_Op_Minus;
+ else if (parser->curr_token->type == Token_Type_Star_Equal) bin_op = Binary_Op_Multiply;
+ else if (parser->curr_token->type == Token_Type_Fslash_Equal) bin_op = Binary_Op_Divide;
+ else if (parser->curr_token->type == Token_Type_Percent_Equal) bin_op = Binary_Op_Modulus;
parser_next_token(parser);
- AstNodeTyped* expr = parse_expression(parser);
+ AstTyped* expr = parse_expression(parser);
- AstNodeBinOp* bin_op_node = make_node(AstNodeBinOp, AST_NODE_KIND_BIN_OP);
+ AstBinaryOp* bin_op_node = make_node(AstBinaryOp, Ast_Kind_Binary_Op);
bin_op_node->operation = bin_op;
- AstNode* bin_op_left = make_node(AstNode, AST_NODE_KIND_SYMBOL);
+ AstNode* bin_op_left = make_node(AstNode, Ast_Kind_Symbol);
bin_op_left->token = symbol;
- bin_op_node->left = (AstNodeTyped *) bin_op_left;
+ bin_op_node->left = (AstTyped *) bin_op_left;
bin_op_node->right = expr;
- AstNodeAssign* assign_node = make_node(AstNodeAssign, AST_NODE_KIND_ASSIGNMENT);
+ AstAssign* assign_node = make_node(AstAssign, Ast_Kind_Assignment);
// TODO: Maybe I don't need to make another lval node?
- AstNode* lval = make_node(AstNode, AST_NODE_KIND_SYMBOL);
+ AstNode* lval = make_node(AstNode, Ast_Kind_Symbol);
lval->token = symbol;
- assign_node->lval = (AstNodeTyped *) lval;
- assign_node->expr = (AstNodeTyped *) bin_op_node;
+ assign_node->lval = (AstTyped *) lval;
+ assign_node->expr = (AstTyped *) bin_op_node;
*ret = (AstNode *) assign_node;
return 0;
}
-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);
+static AstReturn* parse_return_statement(OnyxParser* parser) {
+ AstReturn* return_node = make_node(AstReturn, Ast_Kind_Return);
+ return_node->base.token = expect(parser, Token_Type_Keyword_Return);
- AstNodeTyped* expr = NULL;
+ AstTyped* expr = NULL;
if (parser->curr_token->type != ';') {
expr = parse_expression(parser);
- if (expr == NULL || expr == (AstNodeTyped *) &error_node) {
- return (AstNodeReturn *) &error_node;
+ if (expr == NULL || expr == (AstTyped *) &error_node) {
+ return (AstReturn *) &error_node;
} else {
return_node->expr = expr;
}
AstNode* retval = NULL;
switch ((u16) parser->curr_token->type) {
- case TOKEN_TYPE_KEYWORD_RETURN:
+ case Token_Type_Keyword_Return:
retval = (AstNode *) parse_return_statement(parser);
break;
retval = (AstNode *) parse_block(parser);
break;
- case TOKEN_TYPE_SYMBOL:
+ case Token_Type_Symbol:
if (parse_symbol_statement(parser, &retval)) break;
// fallthrough
case '+':
case '-':
case '!':
- case TOKEN_TYPE_LITERAL_NUMERIC:
- case TOKEN_TYPE_LITERAL_STRING:
+ case Token_Type_Literal_Numeric:
+ case Token_Type_Literal_String:
retval = (AstNode *) parse_expression(parser);
break;
- case TOKEN_TYPE_KEYWORD_IF:
+ case Token_Type_Keyword_If:
needs_semicolon = 0;
retval = (AstNode *) parse_if_stmt(parser);
break;
- case TOKEN_TYPE_KEYWORD_WHILE:
+ case Token_Type_Keyword_While:
needs_semicolon = 0;
retval = (AstNode *) parse_while_stmt(parser);
break;
- case TOKEN_TYPE_KEYWORD_BREAK:
- retval = make_node(AstNode, AST_NODE_KIND_BREAK);
- retval->token = expect(parser, TOKEN_TYPE_KEYWORD_BREAK);
+ case Token_Type_Keyword_Break:
+ retval = make_node(AstNode, Ast_Kind_Break);
+ retval->token = expect(parser, Token_Type_Keyword_Break);
break;
- case TOKEN_TYPE_KEYWORD_CONTINUE:
- retval = make_node(AstNode, AST_NODE_KIND_BREAK);
- retval->token = expect(parser, TOKEN_TYPE_KEYWORD_CONTINUE);
+ case Token_Type_Keyword_Continue:
+ retval = make_node(AstNode, Ast_Kind_Break);
+ retval->token = expect(parser, Token_Type_Keyword_Continue);
break;
default:
return retval;
}
-static AstNodeBlock* parse_block(OnyxParser* parser) {
- AstNodeBlock* block = make_node(AstNodeBlock, AST_NODE_KIND_BLOCK);
- AstNodeLocalGroup* lg = make_node(AstNodeLocalGroup, AST_NODE_KIND_LOCAL_GROUP);
+static AstBlock* parse_block(OnyxParser* parser) {
+ AstBlock* block = make_node(AstBlock, Ast_Kind_Block);
+ AstLocalGroup* lg = make_node(AstLocalGroup, Ast_Kind_Local_Group);
block->locals = lg;
// --- is for an empty block
while (parser->curr_token->type != '}') {
stmt = parse_statement(parser);
- if (stmt != NULL && stmt->kind != AST_NODE_KIND_ERROR) {
+ if (stmt != NULL && stmt->kind != Ast_Kind_Error) {
*next = stmt;
while (stmt->next != NULL) stmt = stmt->next;
static TypeInfo* parse_type(OnyxParser* parser) {
TypeInfo* type_info = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
- OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL);
+ OnyxToken* symbol = expect(parser, Token_Type_Symbol);
if (symbol == NULL) return type_info;
onyx_token_null_toggle(symbol);
if (!bh_table_has(AstNode*, parser->identifiers, symbol->text)) {
onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_UNKNOWN_TYPE, symbol->pos, symbol->text);
} else {
- AstNodeTyped* type_info_node = bh_table_get(AstNodeTyped*, parser->identifiers, symbol->text);
+ AstTyped* type_info_node = bh_table_get(AstTyped*, parser->identifiers, symbol->text);
- if (type_info_node->kind == AST_NODE_KIND_TYPE) {
+ if (type_info_node->kind == Ast_Kind_Type) {
type_info = type_info_node->type;
}
}
return type_info;
}
-static AstNodeLocal* parse_function_params(OnyxParser* parser) {
+static AstLocal* parse_function_params(OnyxParser* parser) {
if (parser->curr_token->type != '(')
return NULL;
return NULL;
}
- AstNodeLocal* first_param = NULL;
- AstNodeLocal* curr_param = NULL;
- AstNodeLocal* trailer = NULL;
+ AstLocal* first_param = NULL;
+ AstLocal* curr_param = NULL;
+ AstLocal* trailer = NULL;
OnyxToken* symbol;
while (parser->curr_token->type != ')') {
if (parser->curr_token->type == ',') parser_next_token(parser);
- symbol = expect(parser, TOKEN_TYPE_SYMBOL);
+ symbol = expect(parser, Token_Type_Symbol);
expect(parser, ':');
- curr_param = make_node(AstNodeLocal, AST_NODE_KIND_PARAM);
+ curr_param = make_node(AstLocal, Ast_Kind_Param);
curr_param->base.token = symbol;
- curr_param->base.flags |= ONYX_AST_FLAG_CONST;
+ curr_param->base.flags |= Ast_Flag_Const;
curr_param->base.type = parse_type(parser);
if (first_param == NULL) first_param = curr_param;
if (parser->curr_token->type != '#') return 0;
expect(parser, '#');
- OnyxToken* sym = expect(parser, TOKEN_TYPE_SYMBOL);
+ OnyxToken* sym = expect(parser, Token_Type_Symbol);
b32 match = (strlen(dir) == sym->length) && (strncmp(dir, sym->text, sym->length) == 0);
if (!match) {
return match;
}
-static AstNodeFunction* parse_function_definition(OnyxParser* parser) {
- expect(parser, TOKEN_TYPE_KEYWORD_PROC);
+static AstFunction* parse_function_definition(OnyxParser* parser) {
+ expect(parser, Token_Type_Keyword_Proc);
- AstNodeFunction* func_def = make_node(AstNodeFunction, AST_NODE_KIND_FUNCTION);
+ AstFunction* func_def = make_node(AstFunction, Ast_Kind_Function);
while (parser->curr_token->type == '#') {
if (parse_possible_directive(parser, "intrinsic")) {
- func_def->base.flags |= ONYX_AST_FLAG_INTRINSIC;
+ func_def->base.flags |= Ast_Flag_Intrinsic;
}
else if (parse_possible_directive(parser, "inline")) {
- func_def->base.flags |= ONYX_AST_FLAG_INLINE;
+ func_def->base.flags |= Ast_Flag_Inline;
}
else {
OnyxToken* directive_token = expect(parser, '#');
- OnyxToken* symbol_token = expect(parser, TOKEN_TYPE_SYMBOL);
+ OnyxToken* symbol_token = expect(parser, Token_Type_Symbol);
onyx_message_add(parser->msgs,
ONYX_MESSAGE_TYPE_UNKNOWN_DIRECTIVE,
}
}
- AstNodeLocal* params = parse_function_params(parser);
+ AstLocal* params = parse_function_params(parser);
func_def->params = params;
- if (parser->curr_token->type == TOKEN_TYPE_RIGHT_ARROW) {
- expect(parser, TOKEN_TYPE_RIGHT_ARROW);
+ if (parser->curr_token->type == Token_Type_Right_Arrow) {
+ expect(parser, Token_Type_Right_Arrow);
TypeInfo* return_type = parse_type(parser);
func_def->base.type = return_type;
}
static AstNode* parse_foreign(OnyxParser* parser) {
- expect(parser, TOKEN_TYPE_KEYWORD_FOREIGN);
+ expect(parser, Token_Type_Keyword_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);
+ AstForeign* foreign = make_node(AstForeign, Ast_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) {
+ if (parser->curr_token->type == Token_Type_Keyword_Proc) {
foreign->import = (AstNode *) parse_function_definition(parser);
} else {
TypeInfo* type = parse_type(parser);
- AstNodeGlobal* global = make_node(AstNodeGlobal, AST_NODE_KIND_GLOBAL);
+ AstGlobal* global = make_node(AstGlobal, Ast_Kind_Global);
global->base.type = type;
- global->base.flags |= ONYX_AST_FLAG_LVAL;
+ global->base.flags |= Ast_Flag_Lval;
foreign->import = (AstNode *) global;
}
}
static AstNode* parse_top_level_constant_symbol(OnyxParser* parser) {
- if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) {
+ if (parser->curr_token->type == Token_Type_Keyword_Proc) {
return (AstNode *) parse_function_definition(parser);
- } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_STRUCT) {
+ } 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) {
+ } else if (parser->curr_token->type == Token_Type_Keyword_Foreign) {
return (AstNode *) parse_foreign(parser);
} else {
// Global constant with initial value
- AstNodeGlobal* global = make_node(AstNodeGlobal, AST_NODE_KIND_GLOBAL);
+ AstGlobal* global = make_node(AstGlobal, Ast_Kind_Global);
global->initial_value = parse_expression(parser);
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;
+ global->base.flags |= Ast_Flag_Const;
+ global->base.flags |= Ast_Flag_Lval;
+ global->base.flags |= Ast_Flag_Comptime;
return (AstNode *) global;
}
static AstNode* parse_top_level_statement(OnyxParser* parser) {
switch (parser->curr_token->type) {
- case TOKEN_TYPE_KEYWORD_USE:
+ case 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);
+ AstUse* use_node = make_node(AstUse, Ast_Kind_Use);
+ use_node->base.token = expect(parser, Token_Type_Keyword_Use);
+ use_node->filename = expect(parser, Token_Type_Literal_String);
return (AstNode *) use_node;
}
- case TOKEN_TYPE_KEYWORD_EXPORT:
+ case Token_Type_Keyword_Export:
{
- expect(parser, TOKEN_TYPE_KEYWORD_EXPORT);
- if (parser->curr_token->type != TOKEN_TYPE_SYMBOL) {
+ expect(parser, Token_Type_Keyword_Export);
+ if (parser->curr_token->type != Token_Type_Symbol) {
onyx_message_add(parser->msgs,
ONYX_MESSAGE_TYPE_EXPECTED_TOKEN,
parser->curr_token->pos,
- onyx_get_token_type_name(TOKEN_TYPE_SYMBOL),
+ onyx_get_token_type_name(Token_Type_Symbol),
onyx_get_token_type_name(parser->curr_token->type));
break;
}
AstNode* top_level_decl = parse_top_level_statement(parser);
- top_level_decl->flags |= ONYX_AST_FLAG_EXPORTED;
+ top_level_decl->flags |= Ast_Flag_Exported;
return top_level_decl;
}
- case TOKEN_TYPE_SYMBOL:
+ case Token_Type_Symbol:
{
OnyxToken* symbol = parser->curr_token;
parser_next_token(parser);
TypeInfo* type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
- if (parser->curr_token->type == TOKEN_TYPE_SYMBOL) {
+ if (parser->curr_token->type == Token_Type_Symbol) {
type = parse_type(parser);
}
AstNode* node = parse_top_level_constant_symbol(parser);
- if (node->kind == AST_NODE_KIND_GLOBAL) {
- ((AstNodeGlobal *) node)->base.type = type;
+ if (node->kind == Ast_Kind_Global) {
+ ((AstGlobal *) node)->base.type = type;
}
- if (node->kind == AST_NODE_KIND_FOREIGN) {
- ((AstNodeForeign *) node)->import->token = symbol;
+ if (node->kind == Ast_Kind_Foreign) {
+ ((AstForeign *) node)->import->token = symbol;
} else {
node->token = symbol;
} else if (parser->curr_token->type == '=') {
parser_next_token(parser);
- AstNodeGlobal* global = make_node(AstNodeGlobal, AST_NODE_KIND_GLOBAL);
+ AstGlobal* global = make_node(AstGlobal, Ast_Kind_Global);
global->base.token = symbol;
- global->base.flags |= ONYX_AST_FLAG_LVAL;
+ global->base.flags |= Ast_Flag_Lval;
global->initial_value = parse_expression(parser);
global->base.type = type;
// 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, i32 size, AstNodeKind kind) {
+void* onyx_ast_node_new(bh_allocator alloc, i32 size, AstKind kind) {
void* node = bh_alloc(alloc, size);
memset(node, 0, size);
- *(AstNodeKind *) node = kind;
+ *(AstKind *) node = kind;
return node;
}
TypeInfo* it = &builtin_types[0];
while (it->kind != 0xffffffff) {
- AstNodeTyped* tmp = onyx_ast_node_new(alloc, sizeof(AstNodeTyped), AST_NODE_KIND_TYPE);
+ AstTyped* tmp = onyx_ast_node_new(alloc, sizeof(AstTyped), Ast_Kind_Type);
tmp->type = it;
bh_table_put(AstNode*, parser.identifiers, (char *)it->name, tmp);
it++;
bh_arr(AstNode *) top_level_nodes = NULL;
bh_arr_new(global_heap_allocator, top_level_nodes, 4);
- while (parser->curr_token->type != TOKEN_TYPE_END_STREAM) {
+ while (parser->curr_token->type != Token_Type_End_Stream) {
AstNode* curr_stmt = parse_top_level_statement(parser);
// Building a linked list of statements down the "next" chain
// 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(AstNodeBlock*) traversal_queue = NULL;
+ bh_arr(AstBlock*) traversal_queue = NULL;
bh_arr_new(global_scratch_allocator, traversal_queue, 4);
bh_arr_set_length(traversal_queue, 0);
- bh_arr_each(AstNodeFunction *, func, program->functions) {
- AstNodeLocalGroup* top_locals = (*func)->body->locals;
+ bh_arr_each(AstFunction *, func, program->functions) {
+ AstLocalGroup* top_locals = (*func)->body->locals;
bh_arr_push(traversal_queue, (*func)->body);
while (!bh_arr_is_empty(traversal_queue)) {
- AstNodeBlock* block = traversal_queue[0];
+ AstBlock* block = traversal_queue[0];
- if (block->base.kind == AST_NODE_KIND_IF) {
- AstNodeIf* if_node = (AstNodeIf *) block;
+ if (block->base.kind == Ast_Kind_If) {
+ AstIf* if_node = (AstIf *) block;
if (if_node->true_block.as_block != NULL)
bh_arr_push(traversal_queue, if_node->true_block.as_block);
} else {
if (block->locals != top_locals && block->locals->last_local != NULL) {
- AstNodeLocal* last_local = block->locals->last_local;
+ AstLocal* last_local = block->locals->last_local;
while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local;
last_local->prev_local = top_locals->last_local;
AstNode* walker = block->body;
while (walker) {
- if (walker->kind == AST_NODE_KIND_BLOCK) {
- bh_arr_push(traversal_queue, (AstNodeBlock *) walker);
+ if (walker->kind == Ast_Kind_Block) {
+ bh_arr_push(traversal_queue, (AstBlock *) walker);
- } else if (walker->kind == AST_NODE_KIND_WHILE) {
- bh_arr_push(traversal_queue, ((AstNodeWhile *) walker)->body);
+ } else if (walker->kind == Ast_Kind_While) {
+ bh_arr_push(traversal_queue, ((AstWhile *) walker)->body);
- } else if (walker->kind == AST_NODE_KIND_IF) {
- if (((AstNodeIf *) walker)->true_block.as_block != NULL)
- bh_arr_push(traversal_queue, ((AstNodeIf *) walker)->true_block.as_block);
+ } else if (walker->kind == Ast_Kind_If) {
+ if (((AstIf *) walker)->true_block.as_block != NULL)
+ bh_arr_push(traversal_queue, ((AstIf *) walker)->true_block.as_block);
- if (((AstNodeIf *) walker)->false_block.as_block != NULL)
- bh_arr_push(traversal_queue, ((AstNodeIf *) walker)->false_block.as_block);
+ if (((AstIf *) walker)->false_block.as_block != NULL)
+ bh_arr_push(traversal_queue, ((AstIf *) walker)->false_block.as_block);
}
walker = walker->next;
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 local_group_enter(OnyxSemPassState* state, AstNodeLocalGroup* local_group);
+static void local_group_enter(OnyxSemPassState* state, AstLocalGroup* local_group);
static void local_group_leave(OnyxSemPassState* state);
-static void symres_local(OnyxSemPassState* state, AstNodeLocal** local);
-static void symres_call(OnyxSemPassState* state, AstNodeCall* call);
+static void symres_local(OnyxSemPassState* state, AstLocal** local);
+static void symres_call(OnyxSemPassState* state, AstCall* 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_assignment(OnyxSemPassState* state, AstAssign* assign);
+static void symres_return(OnyxSemPassState* state, AstReturn* ret);
+static void symres_if(OnyxSemPassState* state, AstIf* ifnode);
+static void symres_while(OnyxSemPassState* state, AstWhile* 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 symres_block(OnyxSemPassState* state, AstBlock* block);
+static void symres_function(OnyxSemPassState* state, AstFunction* func);
static void symbol_introduce(OnyxSemPassState* state, AstNode* symbol) {
onyx_token_null_toggle(symbol->token);
bh_table_put(SemPassSymbol *, state->symbols, symbol->token->text, sp_sym);
- if (symbol->kind == AST_NODE_KIND_LOCAL) {
- AstNodeLocal* local = (AstNodeLocal *) symbol;
+ if (symbol->kind == Ast_Kind_Local) {
+ AstLocal* local = (AstLocal *) symbol;
local->prev_local = state->curr_local_group->last_local;
state->curr_local_group->last_local = local;
}
return sp_sym->node;
}
-static void local_group_enter(OnyxSemPassState* state, AstNodeLocalGroup* local_group) {
+static void local_group_enter(OnyxSemPassState* state, AstLocalGroup* local_group) {
local_group->prev_group = state->curr_local_group;
state->curr_local_group = local_group;
}
static void local_group_leave(OnyxSemPassState* state) {
assert(state->curr_local_group != NULL);
- for (AstNodeLocal *walker = state->curr_local_group->last_local; walker != NULL; walker = walker->prev_local) {
+ for (AstLocal *walker = state->curr_local_group->last_local; walker != NULL; walker = walker->prev_local) {
symbol_remove(state, (AstNode *) walker);
}
return 1;
}
-static void symres_local(OnyxSemPassState* state, AstNodeLocal** local) {
+static void symres_local(OnyxSemPassState* state, AstLocal** local) {
symbol_introduce(state, (AstNode *) *local);
}
-static void symres_call(OnyxSemPassState* state, AstNodeCall* call) {
+static void symres_call(OnyxSemPassState* state, AstCall* call) {
AstNode* callee = symbol_resolve(state, call->callee);
if (callee) call->callee = callee;
else DEBUG_HERE;
static void symres_expression(OnyxSemPassState* state, AstNode** expr) {
switch ((*expr)->kind) {
- case AST_NODE_KIND_BIN_OP:
- symres_expression(state, (AstNode **) &((AstNodeBinOp *)(*expr))->left);
- symres_expression(state, (AstNode **) &((AstNodeBinOp *)(*expr))->right);
+ case Ast_Kind_Binary_Op:
+ symres_expression(state, (AstNode **) &((AstBinaryOp *)(*expr))->left);
+ symres_expression(state, (AstNode **) &((AstBinaryOp *)(*expr))->right);
break;
- case AST_NODE_KIND_UNARY_OP:
- symres_expression(state, (AstNode **) &((AstNodeUnaryOp *)(*expr))->expr);
+ case Ast_Kind_Unary_Op:
+ symres_expression(state, (AstNode **) &((AstUnaryOp *)(*expr))->expr);
break;
- case AST_NODE_KIND_CALL: symres_call(state, (AstNodeCall *) *expr); break;
+ case Ast_Kind_Call: symres_call(state, (AstCall *) *expr); break;
- case AST_NODE_KIND_BLOCK: symres_block(state, (AstNodeBlock *) *expr); break;
+ case Ast_Kind_Block: symres_block(state, (AstBlock *) *expr); break;
- case AST_NODE_KIND_SYMBOL:
+ case Ast_Kind_Symbol:
*expr = symbol_resolve(state, *expr);
break;
// NOTE: This is a good case, since it means the symbol is already resolved
- case AST_NODE_KIND_LOCAL: break;
+ case Ast_Kind_Local: break;
- case AST_NODE_KIND_LITERAL: break;
+ case Ast_Kind_Literal: break;
default:
DEBUG_HERE;
}
}
-static void symres_assignment(OnyxSemPassState* state, AstNodeAssign* assign) {
- AstNodeTyped* lval = (AstNodeTyped *) symbol_resolve(state, (AstNode *) assign->lval);
+static void symres_assignment(OnyxSemPassState* state, AstAssign* assign) {
+ AstTyped* lval = (AstTyped *) symbol_resolve(state, (AstNode *) assign->lval);
if (lval == NULL) return;
assign->lval = lval;
symres_expression(state, (AstNode **) &assign->expr);
}
-static void symres_return(OnyxSemPassState* state, AstNodeReturn* ret) {
+static void symres_return(OnyxSemPassState* state, AstReturn* ret) {
if (ret->expr)
symres_expression(state, (AstNode **) &ret->expr);
}
-static void symres_if(OnyxSemPassState* state, AstNodeIf* ifnode) {
+static void symres_if(OnyxSemPassState* state, AstIf* ifnode) {
symres_expression(state, (AstNode **) &ifnode->cond);
if (ifnode->true_block.as_if != NULL) {
- if (ifnode->true_block.as_if->base.kind == AST_NODE_KIND_BLOCK)
+ if (ifnode->true_block.as_if->base.kind == Ast_Kind_Block)
symres_block(state, ifnode->true_block.as_block);
- else if (ifnode->true_block.as_if->base.kind == AST_NODE_KIND_IF)
+ else if (ifnode->true_block.as_if->base.kind == Ast_Kind_If)
symres_if(state, ifnode->true_block.as_if);
else DEBUG_HERE;
}
if (ifnode->false_block.as_if != NULL) {
- if (ifnode->false_block.as_if->base.kind == AST_NODE_KIND_BLOCK)
+ if (ifnode->false_block.as_if->base.kind == Ast_Kind_Block)
symres_block(state, ifnode->false_block.as_block);
- else if (ifnode->false_block.as_if->base.kind == AST_NODE_KIND_IF)
+ else if (ifnode->false_block.as_if->base.kind == Ast_Kind_If)
symres_if(state, ifnode->false_block.as_if);
else DEBUG_HERE;
}
}
-static void symres_while(OnyxSemPassState* state, AstNodeWhile* whilenode) {
+static void symres_while(OnyxSemPassState* state, AstWhile* 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, AstNode* stmt) {
switch (stmt->kind) {
- 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;
+ case Ast_Kind_Local: symres_local(state, (AstLocal **) &stmt); return 1;
+ case Ast_Kind_Assignment: symres_assignment(state, (AstAssign *) stmt); return 0;
+ case Ast_Kind_Return: symres_return(state, (AstReturn *) stmt); return 0;
+ case Ast_Kind_If: symres_if(state, (AstIf *) stmt); return 0;
+ case Ast_Kind_While: symres_while(state, (AstWhile *) stmt); return 0;
+ case Ast_Kind_Call: symres_call(state, (AstCall *) stmt); return 0;
+ case Ast_Kind_Argument: symres_expression(state, (AstNode **) &((AstArgument *)stmt)->value); return 0;
+ case Ast_Kind_Block: symres_block(state, (AstBlock *) stmt); return 0;
default: return 0;
}
}
}
-static void symres_block(OnyxSemPassState* state, AstNodeBlock* block) {
+static void symres_block(OnyxSemPassState* state, AstBlock* block) {
local_group_enter(state, block->locals);
if (block->body)
symres_statement_chain(state, block->body, &block->body);
local_group_leave(state);
}
-static void symres_function(OnyxSemPassState* state, AstNodeFunction* func) {
- for (AstNodeLocal *param = func->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
+static void symres_function(OnyxSemPassState* state, AstFunction* func) {
+ for (AstLocal *param = func->params; param != NULL; param = (AstLocal *) param->base.next) {
symbol_introduce(state, (AstNode *) param);
}
symres_block(state, func->body);
- for (AstNodeLocal *param = func->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
+ for (AstLocal *param = func->params; param != NULL; param = (AstLocal *) 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(AstNodeGlobal *, global, program->globals)
+ bh_arr_each(AstGlobal *, global, program->globals)
if (!symbol_unique_introduce(state, (AstNode *) *global)) return;
- bh_arr_each(AstNodeFunction *, function, program->functions)
+ bh_arr_each(AstFunction *, function, program->functions)
if (!symbol_unique_introduce(state, (AstNode *) *function)) return;
- bh_arr_each(AstNodeForeign *, foreign, program->foreigns) {
- AstNodeKind import_kind = (*foreign)->import->kind;
+ bh_arr_each(AstForeign *, foreign, program->foreigns) {
+ AstKind import_kind = (*foreign)->import->kind;
- if (import_kind == AST_NODE_KIND_FUNCTION || import_kind == AST_NODE_KIND_GLOBAL)
+ if (import_kind == Ast_Kind_Function || import_kind == Ast_Kind_Global)
if (!symbol_unique_introduce(state, (*foreign)->import)) return;
}
// NOTE: Then, resolve all symbols in all functions
- bh_arr_each(AstNodeFunction *, function, program->functions)
+ bh_arr_each(AstFunction *, function, program->functions)
symres_function(state, *function);
}
--- /dev/null
+#include "onyxtypes.h"
+
+Type basic_types[] = {
+ { Type_Kind_Basic, { Basic_Kind_Void, 0, 0, "void" } },
+
+ { Type_Kind_Basic, { Basic_Kind_Bool, Basic_Flag_Boolean, 1, "bool" } },
+
+ { Type_Kind_Basic, { Basic_Kind_I8, Basic_Flag_Integer, 1, "i8" } },
+ { Type_Kind_Basic, { Basic_Kind_I16, Basic_Flag_Integer, 2, "i16" } },
+ { Type_Kind_Basic, { Basic_Kind_I32, Basic_Flag_Integer, 4, "i32" } },
+ { Type_Kind_Basic, { Basic_Kind_I64, Basic_Flag_Integer, 8, "i64" } },
+
+ { Type_Kind_Basic, { Basic_Kind_U8, Basic_Flag_Integer | Basic_Flag_Unsigned, 1, "u8" } },
+ { Type_Kind_Basic, { Basic_Kind_U16, Basic_Flag_Integer | Basic_Flag_Unsigned, 2, "u16" } },
+ { Type_Kind_Basic, { Basic_Kind_U32, Basic_Flag_Integer | Basic_Flag_Unsigned, 4, "u32" } },
+ { Type_Kind_Basic, { Basic_Kind_U64, Basic_Flag_Integer | Basic_Flag_Unsigned, 8, "u64" } },
+
+ { Type_Kind_Basic, { Basic_Kind_F32, Basic_Flag_Float, 4, "f32" } },
+ { Type_Kind_Basic, { Basic_Kind_F64, Basic_Flag_Float, 8, "f64" } },
+
+ { Type_Kind_Basic, { Basic_Kind_Rawptr, Basic_Flag_Pointer, 4, "rawptr" } },
+};
+
+b32 types_are_compatible(Type* t1, Type* t2) {
+ // NOTE: If they are pointing to the same thing,
+ // it is safe to assume they are the same type
+ if (t1 == t2) return 1;
+
+ switch (t1->kind) {
+ case Type_Kind_Basic:
+ if (t2->kind == Type_Kind_Basic) {
+ // HACK: Not sure if this is right way to check this?
+ return t1 == t2;
+ }
+ break;
+
+ case Type_Kind_Pointer:
+ if (t2->kind == Type_Kind_Pointer) {
+ return types_are_compatible(t1->Pointer.elem, t2->Pointer.elem);
+ }
+ break;
+
+ default:
+ assert(("Invalid type", 0));
+ break;
+ }
+
+ return 0;
+}
"AST_NODE_KIND_COUNT",
};
-const char* onyx_ast_node_kind_string(AstNodeKind kind) {
+const char* onyx_ast_node_kind_string(AstKind kind) {
return ast_node_names[kind];
}
#define WI(instr) bh_arr_push(code, ((WasmInstruction){ instr, 0x00 }));
#define WID(instr, data) bh_arr_push(code, ((WasmInstruction){ instr, data }));
-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_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstFunction* fd);
+static void compile_block(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstBlock* 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_call(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeCall* call);
-static void compile_intrinsic_call(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeIntrinsicCall* call);
-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) {
+static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstTyped* lval);
+static void compile_assignment(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstAssign* assign);
+static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstIf* if_node);
+static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstWhile* while_node);
+static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstBinaryOp* binop);
+static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstUnaryOp* unop);
+static void compile_call(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstCall* call);
+static void compile_intrinsic_call(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstIntrinsicCall* call);
+static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstTyped* expr);
+static void compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstUnaryOp* cast);
+static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstReturn* ret);
+
+static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstFunction* fd) {
if (fd->body == NULL) return;
bh_arr(WasmInstruction) code = *pcode;
*pcode = code;
}
-static void compile_block(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeBlock* block) {
+static void compile_block(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstBlock* block) {
bh_arr(WasmInstruction) code = *pcode;
WID(WI_BLOCK_START, 0x40);
bh_arr(WasmInstruction) code = *pcode;
switch (stmt->kind) {
- 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_BLOCK: compile_block(mod, &code, (AstNodeBlock *) stmt); break;
-
- case AST_NODE_KIND_CALL:
- case AST_NODE_KIND_INTRINSIC_CALL:
- compile_expression(mod, &code, (AstNodeTyped *) stmt);
+ case Ast_Kind_Return: compile_return(mod, &code, (AstReturn *) stmt); break;
+ case Ast_Kind_Assignment: compile_assignment(mod, &code, (AstAssign *) stmt); break;
+ case Ast_Kind_If: compile_if(mod, &code, (AstIf *) stmt); break;
+ case Ast_Kind_While: compile_while(mod, &code, (AstWhile *) stmt); break;
+ case Ast_Kind_Break: compile_structured_jump(mod, &code, 0); break;
+ case Ast_Kind_Continue: compile_structured_jump(mod, &code, 1); break;
+ case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) stmt); break;
+
+ case Ast_Kind_Call:
+ case Ast_Kind_Intrinsic_Call:
+ compile_expression(mod, &code, (AstTyped *) stmt);
break;
*pcode = code;
}
-static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeTyped* lval) {
+static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstTyped* lval) {
bh_arr(WasmInstruction) code = *pcode;
- if (lval->kind == AST_NODE_KIND_LOCAL || lval->kind == AST_NODE_KIND_PARAM) {
+ if (lval->kind == Ast_Kind_Local || lval->kind == Ast_Kind_Param) {
i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) lval);
WID(WI_LOCAL_SET, localidx);
- } else if (lval->kind == AST_NODE_KIND_GLOBAL) {
+ } else if (lval->kind == Ast_Kind_Global) {
i32 globalidx = (i32) bh_imap_get(&mod->global_map, (u64) lval);
WID(WI_GLOBAL_SET, globalidx);
*pcode = code;
}
-static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeIf* if_node) {
+static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstIf* if_node) {
bh_arr(WasmInstruction) code = *pcode;
compile_expression(mod, &code, if_node->cond);
if (if_node->true_block.as_if) {
// NOTE: This is kind of gross, but making a function for this doesn't feel right
- if (if_node->true_block.as_if->base.kind == AST_NODE_KIND_IF) {
+ if (if_node->true_block.as_if->base.kind == Ast_Kind_If) {
forll (AstNode, stmt, (AstNode *) if_node->true_block.as_if, next) {
compile_statement(mod, &code, stmt);
}
- } else if (if_node->true_block.as_if->base.kind == AST_NODE_KIND_BLOCK) {
+ } else if (if_node->true_block.as_if->base.kind == Ast_Kind_Block) {
forll (AstNode, stmt, if_node->true_block.as_block->body, next) {
compile_statement(mod, &code, stmt);
}
if (if_node->false_block.as_if) {
WI(WI_ELSE);
- if (if_node->false_block.as_if->base.kind == AST_NODE_KIND_IF) {
+ if (if_node->false_block.as_if->base.kind == Ast_Kind_If) {
forll (AstNode, stmt, (AstNode *) if_node->false_block.as_if, next) {
compile_statement(mod, &code, stmt);
}
- } else if (if_node->false_block.as_if->base.kind == AST_NODE_KIND_BLOCK) {
+ } else if (if_node->false_block.as_if->base.kind == Ast_Kind_Block) {
forll (AstNode, stmt, if_node->false_block.as_block->body, next) {
compile_statement(mod, &code, stmt);
}
*pcode = code;
}
-static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeWhile* while_node) {
+static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstWhile* while_node) {
bh_arr(WasmInstruction) code = *pcode;
WID(WI_BLOCK_START, 0x40);
*pcode = code;
}
-static void compile_assignment(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeAssign* assign) {
+static void compile_assignment(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstAssign* assign) {
bh_arr(WasmInstruction) code = *pcode;
compile_expression(mod, &code, assign->expr);
/* 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, AstNodeBinOp* binop) {
+static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstBinaryOp* binop) {
bh_arr(WasmInstruction) code = *pcode;
b32 is_sign_significant = 0;
switch (binop->operation) {
- case ONYX_BINARY_OP_DIVIDE:
- case ONYX_BINARY_OP_MODULUS:
- case ONYX_BINARY_OP_LESS:
- case ONYX_BINARY_OP_LESS_EQUAL:
- case ONYX_BINARY_OP_GREATER:
- case ONYX_BINARY_OP_GREATER_EQUAL:
+ case Binary_Op_Divide:
+ case Binary_Op_Modulus:
+ case Binary_Op_Less:
+ case Binary_Op_Less_Equal:
+ case Binary_Op_Greater:
+ case Binary_Op_Greater_Equal:
is_sign_significant = 1;
default: break;
*pcode = code;
}
-static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeUnaryOp* unop) {
+static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstUnaryOp* unop) {
bh_arr(WasmInstruction) code = *pcode;
switch (unop->operation) {
- case ONYX_UNARY_OP_NEGATE:
+ case Unary_Op_Negate:
{
TypeInfoKind type_kind = unop->base.type->kind;
break;
}
- case ONYX_UNARY_OP_NOT:
+ case Unary_Op_Not:
compile_expression(mod, &code, unop->expr);
WI(WI_I32_EQZ);
break;
- case ONYX_UNARY_OP_CAST: compile_cast(mod, &code, unop); break;
+ case Unary_Op_Cast: compile_cast(mod, &code, unop); break;
}
*pcode = code;
}
-static void compile_call(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeCall* call) {
+static void compile_call(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstCall* call) {
bh_arr(WasmInstruction) code = *pcode;
- for (AstNodeArgument *arg = call->arguments;
+ for (AstArgument *arg = call->arguments;
arg != NULL;
- arg = (AstNodeArgument *) arg->base.next) {
+ arg = (AstArgument *) arg->base.next) {
compile_expression(mod, &code, arg->value);
}
*pcode = code;
}
-static void compile_intrinsic_call(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeIntrinsicCall* call) {
+static void compile_intrinsic_call(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstIntrinsicCall* call) {
bh_arr(WasmInstruction) code = *pcode;
i32 place_arguments_normally = 1;
if (0) place_arguments_normally = 0;
if (place_arguments_normally) {
- for (AstNodeArgument *arg = call->arguments;
+ for (AstArgument *arg = call->arguments;
arg != NULL;
- arg = (AstNodeArgument *) arg->base.next) {
+ arg = (AstArgument *) arg->base.next) {
compile_expression(mod, &code, arg->value);
}
}
*pcode = code;
}
-static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeTyped* expr) {
+static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstTyped* expr) {
bh_arr(WasmInstruction) code = *pcode;
switch (expr->kind) {
- case AST_NODE_KIND_BIN_OP:
- compile_binop(mod, &code, (AstNodeBinOp *) expr);
+ case Ast_Kind_Binary_Op:
+ compile_binop(mod, &code, (AstBinaryOp *) expr);
break;
- case AST_NODE_KIND_UNARY_OP:
- compile_unaryop(mod, &code, (AstNodeUnaryOp *) expr);
+ case Ast_Kind_Unary_Op:
+ compile_unaryop(mod, &code, (AstUnaryOp *) expr);
break;
- case AST_NODE_KIND_LOCAL:
- case AST_NODE_KIND_PARAM:
+ case Ast_Kind_Local:
+ case Ast_Kind_Param:
{
i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) expr);
break;
}
- case AST_NODE_KIND_GLOBAL:
+ case Ast_Kind_Global:
{
i32 globalidx = (i32) bh_imap_get(&mod->global_map, (u64) expr);
break;
}
- case AST_NODE_KIND_LITERAL:
+ case Ast_Kind_Literal:
{
- AstNodeNumLit* lit = (AstNodeNumLit *) expr;
+ AstNumLit* lit = (AstNumLit *) expr;
WasmType lit_type = onyx_type_to_wasm_type(lit->base.type);
WasmInstruction instr = { WI_NOP, 0 };
break;
}
- case AST_NODE_KIND_BLOCK: compile_block(mod, &code, (AstNodeBlock *) expr); break;
+ case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) expr); break;
- case AST_NODE_KIND_CALL:
- compile_call(mod, &code, (AstNodeCall *) expr);
+ case Ast_Kind_Call:
+ compile_call(mod, &code, (AstCall *) expr);
break;
- case AST_NODE_KIND_INTRINSIC_CALL:
- compile_intrinsic_call(mod, &code, (AstNodeIntrinsicCall *) expr);
+ case Ast_Kind_Intrinsic_Call:
+ compile_intrinsic_call(mod, &code, (AstIntrinsicCall *) expr);
break;
default:
/* 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, AstNodeUnaryOp* cast) {
+static void compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstUnaryOp* cast) {
bh_arr(WasmInstruction) code = *pcode;
compile_expression(mod, &code, cast->expr);
*pcode = code;
}
-static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeReturn* ret) {
+static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstReturn* ret) {
bh_arr(WasmInstruction) code = *pcode;
if (ret->expr) {
*pcode = code;
}
-static i32 generate_type_idx(OnyxWasmModule* mod, AstNodeFunction* fd) {
+static i32 generate_type_idx(OnyxWasmModule* mod, AstFunction* fd) {
static char type_repr_buf[128];
char* t = type_repr_buf;
- AstNodeLocal* param = fd->params;
+ AstLocal* 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->base.type);
param_count++;
- param = (AstNodeLocal *) param->base.next;
+ param = (AstLocal *) param->base.next;
}
*(t++) = ':';
return type_idx;
}
-static void compile_function(OnyxWasmModule* mod, AstNodeFunction* fd) {
+static void compile_function(OnyxWasmModule* mod, AstFunction* fd) {
// NOTE: Don't compile intrinsics
- if (fd->base.flags & ONYX_AST_FLAG_INTRINSIC) return;
+ if (fd->base.flags & Ast_Flag_Intrinsic) return;
i32 type_idx = generate_type_idx(mod, fd);
bh_arr_new(mod->allocator, wasm_func.code, 4);
- if (fd->base.flags & ONYX_AST_FLAG_EXPORTED) {
+ if (fd->base.flags & Ast_Flag_Exported) {
onyx_token_null_toggle(fd->base.token);
i32 func_idx = (i32) bh_imap_get(&mod->func_map, (u64) fd);
if (fd->body != NULL) {
// NOTE: Generate the local map
i32 localidx = 0;
- for (AstNodeLocal *param = fd->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
+ for (AstLocal *param = fd->params; param != NULL; param = (AstLocal *) 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 (AstNodeLocal, local, fd->body->locals->last_local, prev_local) {
+ forll (AstLocal, local, fd->body->locals->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++);
bh_imap_clear(&mod->local_map);
}
-static void compile_global_declaration(OnyxWasmModule* module, AstNodeGlobal* global) {
+static void compile_global_declaration(OnyxWasmModule* module, AstGlobal* global) {
WasmGlobal glob = {
.type = onyx_type_to_wasm_type(global->base.type),
- .mutable = (global->base.flags & ONYX_AST_FLAG_CONST) == 0,
+ .mutable = (global->base.flags & Ast_Flag_Const) == 0,
.initial_value = NULL,
};
return;
}
- if ((global->base.flags & ONYX_AST_FLAG_EXPORTED) != 0) {
+ if ((global->base.flags & Ast_Flag_Exported) != 0) {
onyx_token_null_toggle(global->base.token);
i32 global_idx = (i32) bh_imap_get(&module->func_map, (u64) global);
bh_arr_push(module->globals, glob);
}
-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);
+static void compile_foreign(OnyxWasmModule* module, AstForeign* foreign) {
+ if (foreign->import->kind == Ast_Kind_Function) {
+ i32 type_idx = generate_type_idx(module, (AstFunction *) foreign->import);
WasmImport import = {
.kind = WASM_FOREIGN_FUNCTION,
bh_arr_push(module->imports, import);
- } else if (foreign->import->kind == AST_NODE_KIND_GLOBAL) {
- WasmType global_type = onyx_type_to_wasm_type(((AstNodeGlobal *) foreign->import)->base.type);
+ } else if (foreign->import->kind == Ast_Kind_Global) {
+ WasmType global_type = onyx_type_to_wasm_type(((AstGlobal *) 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(AstNodeForeign *, foreign, program->foreigns) {
- AstNodeKind import_kind = (*foreign)->import->kind;
+ bh_arr_each(AstForeign *, foreign, program->foreigns) {
+ AstKind import_kind = (*foreign)->import->kind;
- if (import_kind == AST_NODE_KIND_FUNCTION) {
+ if (import_kind == Ast_Kind_Function) {
module->next_func_idx++;
bh_imap_put(&module->func_map, (u64) (*foreign)->import, module->next_import_func_idx++);
}
- else if (import_kind == AST_NODE_KIND_GLOBAL) {
+ else if (import_kind == Ast_Kind_Global) {
module->next_global_idx++;
bh_imap_put(&module->global_map, (u64) (*foreign)->import, module->next_import_global_idx++);
}
compile_foreign(module, *foreign);
}
- bh_arr_each(AstNodeFunction *, function, program->functions) {
- if (((*function)->base.flags & ONYX_AST_FLAG_INTRINSIC) == 0)
+ bh_arr_each(AstFunction *, function, program->functions) {
+ if (((*function)->base.flags & Ast_Flag_Intrinsic) == 0)
bh_imap_put(&module->func_map, (u64) *function, module->next_func_idx++);
}
- bh_arr_each(AstNodeGlobal *, global, program->globals)
+ bh_arr_each(AstGlobal *, global, program->globals)
bh_imap_put(&module->global_map, (u64) *global, module->next_global_idx++);
// NOTE: Then, compile everything
- bh_arr_each(AstNodeFunction *, function, program->functions)
+ bh_arr_each(AstFunction *, function, program->functions)
compile_function(module, *function);
- bh_arr_each(AstNodeGlobal *, global, program->globals)
+ bh_arr_each(AstGlobal *, global, program->globals)
compile_global_declaration(module, *global);
}