@echo off
-set SOURCE_FILES=src/onyx.c src/onyxbuiltins.c src/onyxchecker.c src/onyxclone.c src/onyxdoc.c src/onyxentities.c src/onyxerrors.c src/onyxlex.c src/onyxparser.c src/onyxsempass.c src/onyxsymres.c src/onyxtypes.c src/onyxutils.c src/onyxwasm.c
+set SOURCE_FILES=src/onyx.c src/onyxastnodes.c src/onyxbuiltins.c src/onyxchecker.c src/onyxclone.c src/onyxdoc.c src/onyxentities.c src/onyxerrors.c src/onyxlex.c src/onyxparser.c src/onyxsempass.c src/onyxsymres.c src/onyxtypes.c src/onyxutils.c src/onyxwasm.c
if "%1" == "1" (
set FLAGS=/O2 /MT /Z7
#!/bin/sh
-C_FILES="onyx onyxbuiltins onyxchecker onyxclone onyxdoc onyxentities onyxerrors onyxlex onyxparser onyxsempass onyxsymres onyxtypes onyxutils onyxwasm"
+C_FILES="onyx onyxastnodes onyxbuiltins onyxchecker onyxclone onyxdoc onyxentities onyxerrors onyxlex onyxparser onyxsempass onyxsymres onyxtypes onyxutils onyxwasm"
TARGET='./bin/onyx'
CC='gcc'
Package* package;
};
+extern AstNode empty_node;
+
typedef enum EntityState {
Entity_State_Error,
AstTyped* ast_reduce(bh_allocator a, AstTyped* node);
AstNode* ast_clone(bh_allocator a, void* n);
void promote_numlit_to_larger(AstNumLit* num);
-AstNumLit* make_int_literal(bh_allocator, i64 value);
b32 convert_numlit_to_type(AstNumLit* num, Type* type);
b32 type_check_or_auto_cast(AstTyped** pnode, Type* type);
Type* resolve_expression_type(AstTyped* node);
b32 cast_is_legal(Type* from_, Type* to_, char** err_msg);
char* get_function_name(AstFunction* func);
+AstNumLit* make_int_literal(bh_allocator a, i64 value);
+AstNumLit* make_float_literal(bh_allocator a, f64 value);
+AstBinaryOp* make_binary_op(bh_allocator a, BinaryOp operation, AstTyped* left, AstTyped* right);
+AstArgument* make_argument(bh_allocator a, AstTyped* value);
+AstFieldAccess* make_field_access(bh_allocator a, AstTyped* node, char* field);
+
typedef enum PolyProcLookupMethod {
PPLM_By_Call,
PPLM_By_Function_Type,
--- /dev/null
+#include "onyxastnodes.h"
+#include "onyxsempass.h"
+#include "onyxparser.h"
+#include "onyxutils.h"
+
+AstNode empty_node = { Ast_Kind_Error, 0, NULL, NULL };
+
+static const char* ast_node_names[] = {
+ "ERROR",
+ "PROGRAM",
+ "PACKAGE",
+ "INCLUDE FILE",
+ "INCLUDE FOLDER",
+ "USE PACKAGE",
+ "ALIAS",
+ "MEMORY RESERVATION",
+
+ "BINDING",
+ "FUNCTION",
+ "OVERLOADED_FUNCTION",
+ "POLYMORPHIC PROC",
+ "BLOCK",
+ "LOCAL GROUP",
+ "LOCAL",
+ "GLOBAL",
+ "SYMBOL",
+
+ "UN_OP",
+ "BIN_OP",
+
+ "TYPE_START (BAD)",
+ "TYPE",
+ "BASIC_TYPE",
+ "POINTER_TYPE",
+ "FUNCTION_TYPE",
+ "ARRAY TYPE",
+ "SLICE TYPE",
+ "DYNARR TYPE",
+ "VARARG TYPE",
+ "STRUCT TYPE",
+ "POLYMORPHIC STRUCT TYPE",
+ "POLYMORPHIC STRUCT CALL TYPE",
+ "ENUM TYPE",
+ "TYPE_ALIAS",
+ "TYPE RAW ALIAS",
+ "TYPE_END (BAD)",
+
+ "STRUCT MEMBER",
+ "ENUM VALUE",
+
+ "NUMERIC LITERAL",
+ "STRING LITERAL",
+ "PARAM",
+ "ARGUMENT",
+ "CALL",
+ "INTRINSIC CALL",
+ "RETURN",
+ "ADDRESS OF",
+ "DEREFERENCE",
+ "ARRAY_ACCESS",
+ "SLICE",
+ "FIELD_ACCESS",
+ "PIPE",
+ "RANGE",
+ "SIZE OF",
+ "ALIGN OF",
+ "FILE CONTENTS",
+ "STRUCT LITERAL",
+ "ARRAY LITERAL",
+
+ "IF",
+ "FOR",
+ "WHILE",
+ "JUMP",
+ "USE",
+ "DEFER",
+ "SWITCH",
+ "SWITCH CASE",
+
+ "AST_NODE_KIND_COUNT",
+};
+
+const char* onyx_ast_node_kind_string(AstKind kind) {
+ return ast_node_names[kind];
+}
+
+const char *binaryop_string[Binary_Op_Count] = {
+ "+", "-", "*", "/", "%",
+ "==", "!=", "<", "<=", ">", ">=",
+ "&", "|", "^", "<<", ">>", ">>>",
+ "&&", "||",
+
+ "NONE",
+ "=", "+=", "-=", "*=", "/=", "%=",
+ "&=", "|=", "^=", "<<=", ">>=", ">>>=",
+ "NONE",
+
+ "|>", "..",
+};
+
+const char* entity_state_strings[Entity_State_Count] = {
+ "Error",
+ "Parse Builtin",
+ "Parse",
+ "Resolve_Symbols",
+ "Check_Types",
+ "Code_Gen",
+ "Finalized",
+};
+
+const char* entity_type_strings[Entity_Type_Count] = {
+ "Unknown",
+ "Add to Load Path",
+ "Load File",
+ "Use Package",
+ "String Literal",
+ "File Contents",
+ "Enum",
+ "Type Alias",
+ "Memory Reservation Type",
+ "Use",
+ "Polymorphic Proc",
+ "Foreign_Function Header",
+ "Foreign_Global Header",
+ "Function Header",
+ "Global Header",
+ "Struct Member Default",
+ "Memory Reservation",
+ "Expression",
+ "Global",
+ "Overloaded_Function",
+ "Function",
+};
+
+#define REDUCE_BINOP_ALL(op) \
+ if (type_is_small_integer(res->type) || type_is_bool(res->type)) { \
+ res->value.i = left->value.i op right->value.i; \
+ } else if (type_is_integer(res->type) \
+ || res->type->Basic.kind == Basic_Kind_Int_Unsized \
+ || res->type->kind == Type_Kind_Enum) { \
+ res->value.l = left->value.l op right->value.l; \
+ } else if (res->type->Basic.kind == Basic_Kind_F32) { \
+ res->value.f = left->value.f op right->value.f; \
+ } else if (res->type->Basic.kind == Basic_Kind_F64 || res->type->Basic.kind == Basic_Kind_Float_Unsized) { \
+ res->value.d = left->value.d op right->value.d; \
+ } \
+ break;
+
+#define REDUCE_BINOP_INT(op) \
+ if (type_is_small_integer(res->type) || type_is_bool(res->type)) { \
+ res->value.i = left->value.i op right->value.i; \
+ } else if (type_is_integer(res->type) \
+ || res->type->Basic.kind == Basic_Kind_Int_Unsized \
+ || res->type->kind == Type_Kind_Enum) { \
+ res->value.l = left->value.l op right->value.l; \
+ } \
+ break;
+
+#define REDUCE_BINOP_BOOL(op) \
+ if (type_is_bool(res->type)) { \
+ res->value.i = left->value.i op right->value.i; \
+ } \
+ break;
+
+AstNumLit* ast_reduce_binop(bh_allocator a, AstBinaryOp* node) {
+ AstNumLit* left = (AstNumLit *) ast_reduce(a, node->left);
+ AstNumLit* right = (AstNumLit *) ast_reduce(a, node->right);
+
+ if (left->kind != Ast_Kind_NumLit || right->kind != Ast_Kind_NumLit) {
+ node->left = (AstTyped *) left;
+ node->right = (AstTyped *) right;
+ return (AstNumLit *) node;
+ }
+
+ AstNumLit* res = onyx_ast_node_new(a, sizeof(AstNumLit), Ast_Kind_NumLit);
+ res->token = node->token;
+ res->flags |= Ast_Flag_Comptime;
+ res->type_node = node->type_node;
+ res->type = node->type;
+
+ switch (node->operation) {
+ case Binary_Op_Add: REDUCE_BINOP_ALL(+);
+ case Binary_Op_Minus: REDUCE_BINOP_ALL(-);
+ case Binary_Op_Multiply: REDUCE_BINOP_ALL(*);
+ case Binary_Op_Divide: REDUCE_BINOP_ALL(/);
+ case Binary_Op_Modulus: REDUCE_BINOP_INT(%);
+
+ case Binary_Op_Equal: REDUCE_BINOP_ALL(==);
+ case Binary_Op_Not_Equal: REDUCE_BINOP_ALL(!=);
+ case Binary_Op_Less: REDUCE_BINOP_ALL(<);
+ case Binary_Op_Less_Equal: REDUCE_BINOP_ALL(<=);
+ case Binary_Op_Greater: REDUCE_BINOP_ALL(>);
+ case Binary_Op_Greater_Equal: REDUCE_BINOP_ALL(>=);
+
+ case Binary_Op_And: REDUCE_BINOP_INT(&);
+ case Binary_Op_Or: REDUCE_BINOP_INT(|);
+ case Binary_Op_Xor: REDUCE_BINOP_INT(^);
+ case Binary_Op_Shl: REDUCE_BINOP_INT(<<);
+ case Binary_Op_Shr: REDUCE_BINOP_INT(>>);
+ case Binary_Op_Sar: REDUCE_BINOP_INT(>>);
+
+ case Binary_Op_Bool_And: REDUCE_BINOP_BOOL(&&);
+ case Binary_Op_Bool_Or: REDUCE_BINOP_BOOL(||);
+
+ default: break;
+ }
+
+ return res;
+}
+
+#define REDUCE_UNOP(op) \
+ if (type_is_small_integer(unop->type) || type_is_bool(unop->type)) { \
+ res->value.i = op ((AstNumLit *) unop->expr)->value.i; \
+ } else if (type_is_integer(unop->type) || unop->type->Basic.kind == Basic_Kind_Int_Unsized) { \
+ res->value.l = op ((AstNumLit *) unop->expr)->value.l; \
+ } else if (unop->type->Basic.kind == Basic_Kind_F32) { \
+ res->value.f = op ((AstNumLit *) unop->expr)->value.f; \
+ } else if (unop->type->Basic.kind == Basic_Kind_F64 || unop->type->Basic.kind == Basic_Kind_Float_Unsized) { \
+ res->value.d = op ((AstNumLit *) unop->expr)->value.d; \
+ } \
+ break;
+
+#define REDUCE_UNOP_INT(op) \
+ if (type_is_small_integer(unop->type) || type_is_bool(unop->type)) { \
+ res->value.i = op ((AstNumLit *) unop->expr)->value.i; \
+ } else if (type_is_integer(unop->type)) { \
+ res->value.l = op ((AstNumLit *) unop->expr)->value.l; \
+ }
+
+AstTyped* ast_reduce_unaryop(bh_allocator a, AstUnaryOp* unop) {
+ unop->expr = ast_reduce(a, unop->expr);
+
+ if (unop->expr->kind != Ast_Kind_NumLit) {
+ return (AstTyped *) unop;
+ }
+
+ AstNumLit* res = onyx_ast_node_new(a, sizeof(AstNumLit), Ast_Kind_NumLit);
+ res->token = unop->token;
+ res->flags |= Ast_Flag_Comptime;
+ res->type_node = unop->type_node;
+ res->type = unop->type;
+
+ switch (unop->operation) {
+ case Unary_Op_Negate: REDUCE_UNOP(-);
+ case Unary_Op_Not: {
+ if (type_is_bool(res->type)) res->value.i = ! ((AstNumLit *) unop->expr)->value.i;
+ break;
+ }
+ case Unary_Op_Bitwise_Not: REDUCE_UNOP_INT(~);
+
+ default: return (AstTyped *) unop;
+ }
+
+ return (AstTyped *) res;
+}
+
+AstTyped* ast_reduce(bh_allocator a, AstTyped* node) {
+ assert(node->flags & Ast_Flag_Comptime);
+
+ switch (node->kind) {
+ case Ast_Kind_Binary_Op: return (AstTyped *) ast_reduce_binop(a, (AstBinaryOp *) node);
+ case Ast_Kind_Unary_Op: return (AstTyped *) ast_reduce_unaryop(a, (AstUnaryOp *) node);
+ case Ast_Kind_NumLit: return node;
+ case Ast_Kind_Enum_Value: return (AstTyped *) ((AstEnumValue *) node)->value;
+ default: return NULL;
+ }
+}
+
+void promote_numlit_to_larger(AstNumLit* num) {
+ assert(num->type != NULL);
+
+ if (type_is_integer(num->type) && num->type->Basic.size <= 4) {
+ // NOTE: Int32, Int16, Int8
+ i64 val = (i64) num->value.i;
+ num->value.l = val;
+ num->type = &basic_types[Basic_Kind_I64];
+ } else if (num->type->Basic.size <= 4) {
+ // NOTE: Float32
+ f64 val = (f64) num->value.f;
+ num->value.d = val;
+ num->type = &basic_types[Basic_Kind_F64];
+ }
+}
+
+// NOTE: Returns 1 if the conversion was successful.
+b32 convert_numlit_to_type(AstNumLit* num, Type* type) {
+ if (num->type == NULL)
+ num->type = type_build_from_ast(semstate.allocator, num->type_node);
+ assert(num->type);
+
+ if (types_are_compatible(num->type, type)) return 1;
+ if (!type_is_numeric(type)) return 0;
+
+ if (num->type->Basic.kind == Basic_Kind_Int_Unsized) {
+
+ //
+ // Integer literal auto cast rules:
+ // - Up in size always works
+ // - Down in size only works if value is in range of smaller type.
+ // - Cast to float only works if value is less than the maximum precise value for float size.
+ //
+
+ if (type->Basic.flags & Basic_Flag_Integer) {
+ if (type->Basic.flags & Basic_Flag_Unsigned) {
+ u64 value = (u64) num->value.l;
+ if (type->Basic.size == 8) {
+ num->type = type;
+ return 1;
+ }
+ switch (type->Basic.size) {
+ case 1: if (value <= 255) {
+ num->type = type;
+ return 1;
+ }
+ case 2: if (value <= 65535) {
+ num->type = type;
+ return 1;
+ }
+ case 4: if (value <= 4294967295) {
+ num->type = type;
+ return 1;
+ }
+ }
+
+ onyx_report_error(num->token->pos, "Unsigned integer constant with value '%l' does not fit into %d-bits.",
+ num->value.l,
+ type->Basic.size * 8);
+
+ } else {
+ i64 value = (i64) num->value.l;
+ switch (type->Basic.size) {
+ case 1: if (-128ll <= value && value <= 127ll) {
+ num->value.i = (i32) value;
+ num->type = type;
+ return 1;
+ } break;
+ case 2: if (-32768ll <= value && value <= 32767ll) {
+ num->value.i = (i32) value;
+ num->type = type;
+ return 1;
+ } break;
+ case 4: if (-2147483648ll <= value && value <= 2147483647ll) {
+ num->value.i = (i32) value;
+ num->type = type;
+ return 1;
+ } break;
+ case 8: { num->type = type;
+ return 1;
+ } break;
+ }
+
+ onyx_report_error(num->token->pos, "Integer constant with value '%l' does not fit into %d-bits.",
+ num->value.l,
+ type->Basic.size * 8);
+ }
+ }
+
+ else if (type->Basic.flags & Basic_Flag_Float) {
+ if (type->Basic.size == 4) {
+ // TODO(Brendan): Check these boundary conditions
+ if (bh_abs(num->value.l) >= (1 << 23)) {
+ onyx_report_error(num->token->pos, "Integer '%l' does not fit in 32-bit float exactly.", num->value.l);
+ return 0;
+ }
+
+ num->type = type;
+ num->value.f = (f32) num->value.l;
+ return 1;
+ }
+ if (type->Basic.size == 8) {
+ // TODO(Brendan): Check these boundary conditions
+ if (bh_abs(num->value.l) >= (1ull << 52)) {
+ onyx_report_error(num->token->pos, "Integer '%l' does not fit in 64-bit float exactly.", num->value.l);
+ return 0;
+ }
+
+ num->type = type;
+ num->value.d = (f64) num->value.l;
+ return 1;
+ }
+ }
+ }
+ else if (num->type->Basic.kind == Basic_Kind_Float_Unsized) {
+ // NOTE: Floats don't cast to integers implicitly.
+ if ((type->Basic.flags & Basic_Flag_Float) == 0) return 0;
+
+ if (type->Basic.kind == Basic_Kind_F32) {
+ num->value.f = (f32) num->value.d;
+ }
+
+ num->type = type;
+ return 1;
+ }
+ else if (num->type->Basic.kind == Basic_Kind_F32) {
+ // NOTE: Floats don't cast to integers implicitly.
+ if ((type->Basic.flags & Basic_Flag_Float) == 0) return 0;
+
+ if (type->Basic.kind == Basic_Kind_F64) {
+ num->value.d = (f64) num->value.f;
+ num->type = type;
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+// NOTE: Returns 0 if it was not possible to make the types compatible.
+b32 type_check_or_auto_cast(AstTyped** pnode, Type* type) {
+ AstTyped* node = *pnode;
+ assert(type != NULL);
+ assert(node != NULL);
+
+ if (node->kind == Ast_Kind_Polymorphic_Proc) {
+ AstFunction* func = polymorphic_proc_lookup((AstPolyProc *) node, PPLM_By_Function_Type, type, node->token->pos);
+ if (func == NULL) return 0;
+
+ *pnode = (AstTyped *) func;
+ node = *pnode;
+ }
+
+ // HACK: NullProcHack
+ if (type->kind == Type_Kind_Function && (node->flags & Ast_Flag_Proc_Is_Null) != 0) return 1;
+
+ if (types_are_compatible(node->type, type)) return 1;
+ if (node_is_auto_cast((AstNode *) node)) {
+ char* dummy;
+ if (!cast_is_legal(((AstUnaryOp *) node)->expr->type, type, &dummy)) {
+ return 0;
+
+ } else {
+ ((AstUnaryOp *) node)->type = type;
+ return 1;
+ }
+ }
+ else if (node->kind == Ast_Kind_NumLit) {
+ if (convert_numlit_to_type((AstNumLit *) node, type)) return 1;
+ }
+
+ return 0;
+}
+
+Type* resolve_expression_type(AstTyped* node) {
+ if (node->type == NULL)
+ node->type = type_build_from_ast(semstate.allocator, node->type_node);
+
+ if (node->kind == Ast_Kind_NumLit && node->type->kind == Type_Kind_Basic) {
+ if (node->type->Basic.kind == Basic_Kind_Int_Unsized) {
+ if ((((u64) ((AstNumLit *) node)->value.l) >> 32) > 0)
+ convert_numlit_to_type((AstNumLit *) node, &basic_types[Basic_Kind_I64]);
+ else
+ convert_numlit_to_type((AstNumLit *) node, &basic_types[Basic_Kind_I32]);
+ }
+ else if (node->type->Basic.kind == Basic_Kind_Float_Unsized) {
+ convert_numlit_to_type((AstNumLit *) node, &basic_types[Basic_Kind_F64]);
+ }
+ }
+
+ return node->type;
+}
+
+static const b32 cast_legality[][11] = {
+ /* I8 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+ /* U8 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+ /* I16 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+ /* U16 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
+ /* I32 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ /* U32 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ /* I64 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ /* U64 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+ /* F32 */ { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
+ /* F64 */ { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
+ /* PTR */ { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1 },
+};
+
+b32 cast_is_legal(Type* from_, Type* to_, char** err_msg) {
+ Type* from = from_;
+ Type* to = to_;
+
+ if (from->kind == Type_Kind_Enum) from = from->Enum.backing;
+ if (to->kind == Type_Kind_Enum) to = to->Enum.backing;
+
+ if (from->kind == Type_Kind_Struct || to->kind == Type_Kind_Struct) {
+ *err_msg = "Cannot cast to or from a struct.";
+ return 0;
+ }
+
+ if (from->kind == Type_Kind_Slice || to->kind == Type_Kind_Slice) {
+ *err_msg = "Cannot cast to or from a slice.";
+ return 0;
+ }
+
+ if (from->kind == Type_Kind_DynArray || to->kind == Type_Kind_DynArray) {
+ *err_msg = "Cannot cast to or from a dynamic array.";
+ return 0;
+ }
+
+ if (to->kind == Type_Kind_Function) {
+ *err_msg = "Cannot cast to a function.";
+ return 0;
+ }
+
+ if ( (type_is_simd(to) && !type_is_simd(from))
+ || (!type_is_simd(to) && type_is_simd(from))) {
+ *err_msg = "Can only perform a SIMD cast between SIMD types.";
+ return 0;
+ }
+
+ if (from->kind == Type_Kind_Basic && from->Basic.kind == Basic_Kind_Void) {
+ *err_msg = "Cannot cast from void.";
+ return 0;
+ }
+ i32 fromidx = -1, toidx = -1;
+ if (from->Basic.flags & Basic_Flag_Pointer || from->kind == Type_Kind_Array) {
+ fromidx = 10;
+ }
+ else if (from->Basic.flags & Basic_Flag_Integer) {
+ b32 unsign = (from->Basic.flags & Basic_Flag_Unsigned) != 0;
+
+ fromidx = log2_dumb(from->Basic.size) * 2 + unsign;
+ }
+ else if (from->Basic.flags & Basic_Flag_Float) {
+ if (from->Basic.size == 4) fromidx = 8;
+ else if (from->Basic.size == 8) fromidx = 9;
+ }
+
+ if (to->Basic.flags & Basic_Flag_Pointer || to->kind == Type_Kind_Array) {
+ toidx = 10;
+ }
+ else if (to->Basic.flags & Basic_Flag_Integer) {
+ b32 unsign = (to->Basic.flags & Basic_Flag_Unsigned) != 0;
+
+ toidx = log2_dumb(to->Basic.size) * 2 + unsign;
+ }
+ else if (to->Basic.flags & Basic_Flag_Float) {
+ if (to->Basic.size == 4) toidx = 8;
+ else if (to->Basic.size == 8) toidx = 9;
+ }
+
+ if (fromidx != -1 && toidx != -1) {
+ if (!cast_legality[fromidx][toidx]) {
+ *err_msg = bh_aprintf(global_heap_allocator, "Cast from '%s' to '%s' is not allowed.", type_get_name(from_), type_get_name(to_));
+ return 0;
+ }
+ }
+
+ *err_msg = NULL;
+ return 1;
+}
+
+char* get_function_name(AstFunction* func) {
+ if (func->name != NULL) {
+ return bh_aprintf(global_scratch_allocator, "%b", func->name->text, func->name->length);
+ }
+
+ if (func->exported_name != NULL) {
+ return bh_aprintf(global_scratch_allocator,
+ "EXPORTED:%b",
+ func->exported_name->text,
+ func->exported_name->length);
+ }
+
+ return "<anonymous procedure>";
+}
+
+
+
+AstNumLit* make_int_literal(bh_allocator a, i64 i) {
+ AstNumLit* num = onyx_ast_node_new(a, sizeof(AstNumLit), Ast_Kind_NumLit);
+ num->flags |= Ast_Flag_Comptime;
+
+ if (bh_abs(i) >= ((u64) 1 << 32))
+ num->type_node = (AstType *) &basic_type_i64;
+ else
+ num->type_node = (AstType *) &basic_type_i32;
+
+ num->value.l = i;
+ return num;
+}
+
+AstNumLit* make_float_literal(bh_allocator a, f64 d) {
+ // NOTE: Use convert_numlit_to_type to make this a concrete float
+ AstNumLit* num = onyx_ast_node_new(a, sizeof(AstNumLit), Ast_Kind_NumLit);
+ num->flags |= Ast_Flag_Comptime;
+ num->type_node = (AstType *) &basic_type_float_unsized;
+ num->value.d = d;
+ return num;
+}
+
+AstBinaryOp* make_binary_op(bh_allocator a, BinaryOp operation, AstTyped* left, AstTyped* right) {
+ AstBinaryOp* binop_node = onyx_ast_node_new(a, sizeof(AstBinaryOp), Ast_Kind_Binary_Op);
+ binop_node->left = left;
+ binop_node->right = right;
+ binop_node->operation = operation;
+ return binop_node;
+}
+
+AstArgument* make_argument(bh_allocator a, AstTyped* value) {
+ AstArgument* arg = onyx_ast_node_new(a, sizeof(AstArgument), Ast_Kind_Argument);
+ if (value->token) arg->token = value->token;
+ arg->value = value;
+ arg->type = value->type;
+ arg->next = NULL;
+ arg->va_kind = VA_Kind_Not_VA;
+ return arg;
+}
+
+AstFieldAccess* make_field_access(bh_allocator a, AstTyped* node, char* field) {
+ AstFieldAccess* fa = onyx_ast_node_new(a, sizeof(AstFieldAccess), Ast_Kind_Field_Access);
+ if (node->token) fa->token = node->token;
+ fa->field = field;
+ fa->expr = node;
+
+ return fa;
+}
+
if (callee->kind == Ast_Kind_Function) {
if (bh_arr_length(arg_arr) < bh_arr_length(callee->params)) {
- while (bh_arr_length(arg_arr) < bh_arr_length(callee->params)
- && callee->params[call->arg_count].default_value != NULL) {
+ while (bh_arr_length(arg_arr) < bh_arr_length(callee->params) && callee->params[call->arg_count].default_value != NULL) {
AstTyped* dv = callee->params[call->arg_count].default_value;
- AstArgument* new_arg = onyx_ast_node_new(semstate.node_allocator, sizeof(AstArgument), Ast_Kind_Argument);
- new_arg->token = dv->token;
- new_arg->value = dv;
- new_arg->next = NULL;
-
+ AstArgument* new_arg = make_argument(semstate.node_allocator, dv);
bh_arr_push(arg_arr, new_arg);
}
}
} else {
// NOTE: +=, -=, ...
- AstBinaryOp* binop_node = onyx_ast_node_new(
- semstate.node_allocator,
- sizeof(AstBinaryOp),
- Ast_Kind_Binary_Op);
-
- binop_node->token = binop->token;
- binop_node->left = binop->left;
- binop_node->right = binop->right;
-
- if (binop->operation == Binary_Op_Assign_Add) binop_node->operation = Binary_Op_Add;
- else if (binop->operation == Binary_Op_Assign_Minus) binop_node->operation = Binary_Op_Minus;
- else if (binop->operation == Binary_Op_Assign_Multiply) binop_node->operation = Binary_Op_Multiply;
- else if (binop->operation == Binary_Op_Assign_Divide) binop_node->operation = Binary_Op_Divide;
- else if (binop->operation == Binary_Op_Assign_Modulus) binop_node->operation = Binary_Op_Modulus;
- else if (binop->operation == Binary_Op_Assign_And) binop_node->operation = Binary_Op_And;
- else if (binop->operation == Binary_Op_Assign_Or) binop_node->operation = Binary_Op_Or;
- else if (binop->operation == Binary_Op_Assign_Xor) binop_node->operation = Binary_Op_Xor;
- else if (binop->operation == Binary_Op_Assign_Shl) binop_node->operation = Binary_Op_Shl;
- else if (binop->operation == Binary_Op_Assign_Shr) binop_node->operation = Binary_Op_Shr;
- else if (binop->operation == Binary_Op_Assign_Sar) binop_node->operation = Binary_Op_Sar;
-
- CHECK(binaryop, &binop_node, 0);
-
- binop->right = (AstTyped *) binop_node;
+ BinaryOp operation = -1;
+ if (binop->operation == Binary_Op_Assign_Add) operation = Binary_Op_Add;
+ else if (binop->operation == Binary_Op_Assign_Minus) operation = Binary_Op_Minus;
+ else if (binop->operation == Binary_Op_Assign_Multiply) operation = Binary_Op_Multiply;
+ else if (binop->operation == Binary_Op_Assign_Divide) operation = Binary_Op_Divide;
+ else if (binop->operation == Binary_Op_Assign_Modulus) operation = Binary_Op_Modulus;
+ else if (binop->operation == Binary_Op_Assign_And) operation = Binary_Op_And;
+ else if (binop->operation == Binary_Op_Assign_Or) operation = Binary_Op_Or;
+ else if (binop->operation == Binary_Op_Assign_Xor) operation = Binary_Op_Xor;
+ else if (binop->operation == Binary_Op_Assign_Shl) operation = Binary_Op_Shl;
+ else if (binop->operation == Binary_Op_Assign_Shr) operation = Binary_Op_Shr;
+ else if (binop->operation == Binary_Op_Assign_Sar) operation = Binary_Op_Sar;
+
+ AstBinaryOp* new_right = make_binary_op(semstate.node_allocator, operation, binop->left, binop->right);
+ new_right->token = binop->token;
+ CHECK(binaryop, &new_right, 0);
+
+ binop->right = (AstTyped *) new_right;
binop->operation = Binary_Op_Assign;
}
implicit_call->callee = overload;
implicit_call->va_kind = VA_Kind_Not_VA;
- bh_arr_each(AstTyped *, arg, args) {
- AstArgument* new_arg = onyx_ast_node_new(semstate.node_allocator, sizeof(AstArgument), Ast_Kind_Argument);
- new_arg->token = (*arg)->token;
- new_arg->type = (*arg)->type;
- new_arg->value = *arg;
- new_arg->va_kind = VA_Kind_Not_VA;
-
- *arg = (AstTyped *) new_arg;
- }
+ bh_arr_each(AstTyped *, arg, args)
+ *arg = (AstTyped *) make_argument(semstate.node_allocator, *arg);
implicit_call->arg_arr = (AstArgument **) args;
return implicit_call;
if (binop->operation != Binary_Op_Add && binop->operation != Binary_Op_Minus) goto bad_binaryop;
resolve_expression_type(binop->right);
- if (!type_is_integer(binop->right->type)) {
- onyx_report_error(binop->right->token->pos, "Expected integer type.");
- return Check_Error;
- }
+ if (!type_is_integer(binop->right->type)) goto bad_binaryop;
- AstNumLit* numlit = onyx_ast_node_new(semstate.node_allocator, sizeof(AstNumLit), Ast_Kind_NumLit);
+ AstNumLit* numlit = make_int_literal(semstate.node_allocator, type_size_of(binop->left->type->Pointer.elem));
numlit->token = binop->right->token;
numlit->type = binop->right->type;
- numlit->value.i = type_size_of(binop->left->type->Pointer.elem);
- AstBinaryOp* binop_node = onyx_ast_node_new(semstate.node_allocator, sizeof(AstBinaryOp), Ast_Kind_Binary_Op);
+ AstBinaryOp* binop_node = make_binary_op(semstate.node_allocator, Binary_Op_Multiply, binop->right, (AstTyped *) numlit);
binop_node->token = binop->token;
- binop_node->left = binop->right;
- binop_node->right = (AstTyped *) numlit;
- binop_node->operation = Binary_Op_Multiply;
-
CHECK(binaryop, &binop_node, 0);
binop->right = (AstTyped *) binop_node;
StructMember smem;
type_lookup_member(aa->addr->type, "data", &smem);
- AstFieldAccess* fa = onyx_ast_node_new(semstate.node_allocator, sizeof(AstFieldAccess), Ast_Kind_Field_Access);
- fa->token = aa->addr->token;
- fa->type = smem.type;
+
+ AstFieldAccess* fa = make_field_access(semstate.node_allocator, aa->addr, "data");
+ fa->type = smem.type;
fa->offset = smem.offset;
- fa->idx = smem.idx;
- fa->expr = aa->addr;
- fa->field = "data";
+ fa->idx = smem.idx;
aa->addr = (AstTyped *) fa;
aa->type = aa->addr->type->Pointer.elem;
}
-AstNumLit* make_int_literal(bh_allocator a, i64 i) {
- AstNumLit* num = onyx_ast_node_new(a, sizeof(AstNumLit), Ast_Kind_NumLit);
- if (bh_abs(i) >= ((u64) 1 << 32))
- num->type_node = (AstType *) &basic_type_i64;
- else
- num->type_node = (AstType *) &basic_type_i32;
-
- num->value.l = i;
- return num;
-}
-
static AstNumLit* parse_int_literal(OnyxParser* parser) {
AstNumLit* int_node = make_node(AstNumLit, Ast_Kind_NumLit);
int_node->token = expect_token(parser, Token_Type_Literal_Integer);
static void symres_memres(AstMemRes** memres);
static void symres_struct_defaults(AstType* st);
-static AstFieldAccess* make_field_access(AstTyped* node, char* field) {
- AstFieldAccess* fa = onyx_ast_node_new(semstate.node_allocator, sizeof(AstFieldAccess), Ast_Kind_Field_Access);
- fa->field = field;
- fa->expr = node;
-
- return fa;
-}
-
static void scope_enter(Scope* new_scope) {
semstate.curr_scope = new_scope;
}
if ((*pipe)->left == NULL) return;
- AstArgument* implicit_arg = onyx_ast_node_new(semstate.node_allocator,
- sizeof(AstArgument),
- Ast_Kind_Argument);
- implicit_arg->token = (*pipe)->left->token;
- implicit_arg->value = (*pipe)->left;
-
bh_arr_insertn(call_node->arg_arr, 0, 1);
- call_node->arg_arr[0] = implicit_arg;
+ call_node->arg_arr[0] = make_argument(semstate.node_allocator, (*pipe)->left);
call_node->arg_count++;
call_node->next = (*pipe)->next;
st = st->Pointer.elem;
bh_table_each_start(StructMember, st->Struct.members);
- AstFieldAccess* fa = make_field_access(use->expr, value.name);
+ AstFieldAccess* fa = make_field_access(semstate.node_allocator, use->expr, value.name);
symbol_raw_introduce(semstate.curr_scope, value.name, use->token->pos, (AstNode *) fa);
bh_table_each_end;
}
bh_table_each_start(StructMember, st->Struct.members);
- AstFieldAccess* fa = make_field_access((AstTyped *) param->local, value.name);
+ AstFieldAccess* fa = make_field_access(semstate.node_allocator, (AstTyped *) param->local, value.name);
symbol_raw_introduce(semstate.curr_scope, value.name, param->local->token->pos, (AstNode *) fa);
bh_table_each_end;
(*value)->value->type = enum_node->etcache;
} else {
- AstNumLit* num = onyx_ast_node_new(semstate.node_allocator, sizeof(AstNumLit), Ast_Kind_NumLit);
- num->value.l = next_assign_value;
- num->flags |= Ast_Flag_Comptime;
+ AstNumLit* num = make_int_literal(semstate.node_allocator, next_assign_value);
num->type = enum_node->etcache;
(*value)->value = num;
#include "onyxastnodes.h"
#include "onyxsempass.h"
-
bh_scratch global_scratch;
bh_allocator global_scratch_allocator;
bh_managed_heap global_heap;
bh_allocator global_heap_allocator;
-static AstNode empty_node = { Ast_Kind_Error, 0, NULL, NULL };
-
-static const char* ast_node_names[] = {
- "ERROR",
- "PROGRAM",
- "PACKAGE",
- "INCLUDE FILE",
- "INCLUDE FOLDER",
- "USE PACKAGE",
- "ALIAS",
- "MEMORY RESERVATION",
-
- "BINDING",
- "FUNCTION",
- "OVERLOADED_FUNCTION",
- "POLYMORPHIC PROC",
- "BLOCK",
- "LOCAL GROUP",
- "LOCAL",
- "GLOBAL",
- "SYMBOL",
-
- "UN_OP",
- "BIN_OP",
-
- "TYPE_START (BAD)",
- "TYPE",
- "BASIC_TYPE",
- "POINTER_TYPE",
- "FUNCTION_TYPE",
- "ARRAY TYPE",
- "SLICE TYPE",
- "DYNARR TYPE",
- "VARARG TYPE",
- "STRUCT TYPE",
- "POLYMORPHIC STRUCT TYPE",
- "POLYMORPHIC STRUCT CALL TYPE",
- "ENUM TYPE",
- "TYPE_ALIAS",
- "TYPE RAW ALIAS",
- "TYPE_END (BAD)",
-
- "STRUCT MEMBER",
- "ENUM VALUE",
-
- "NUMERIC LITERAL",
- "STRING LITERAL",
- "PARAM",
- "ARGUMENT",
- "CALL",
- "INTRINSIC CALL",
- "RETURN",
- "ADDRESS OF",
- "DEREFERENCE",
- "ARRAY_ACCESS",
- "SLICE",
- "FIELD_ACCESS",
- "PIPE",
- "RANGE",
- "SIZE OF",
- "ALIGN OF",
- "FILE CONTENTS",
- "STRUCT LITERAL",
- "ARRAY LITERAL",
-
- "IF",
- "FOR",
- "WHILE",
- "JUMP",
- "USE",
- "DEFER",
- "SWITCH",
- "SWITCH CASE",
-
- "AST_NODE_KIND_COUNT",
-};
-
-const char* onyx_ast_node_kind_string(AstKind kind) {
- return ast_node_names[kind];
-}
-
-const char *binaryop_string[Binary_Op_Count] = {
- "+", "-", "*", "/", "%",
- "==", "!=", "<", "<=", ">", ">=",
- "&", "|", "^", "<<", ">>", ">>>",
- "&&", "||",
-
- "NONE",
- "=", "+=", "-=", "*=", "/=", "%=",
- "&=", "|=", "^=", "<<=", ">>=", ">>>=",
- "NONE",
-
- "|>", "..",
-};
-
-const char* entity_state_strings[Entity_State_Count] = {
- "Error",
- "Parse Builtin",
- "Parse",
- "Resolve_Symbols",
- "Check_Types",
- "Code_Gen",
- "Finalized",
-};
-
-const char* entity_type_strings[Entity_Type_Count] = {
- "Unknown",
- "Add to Load Path",
- "Load File",
- "Use Package",
- "String Literal",
- "File Contents",
- "Enum",
- "Type Alias",
- "Memory Reservation Type",
- "Use",
- "Polymorphic Proc",
- "Foreign_Function Header",
- "Foreign_Global Header",
- "Function Header",
- "Global Header",
- "Struct Member Default",
- "Memory Reservation",
- "Expression",
- "Global",
- "Overloaded_Function",
- "Function",
-};
-
-
void program_info_init(ProgramInfo* prog, bh_allocator alloc) {
prog->global_scope = scope_create(alloc, NULL, (OnyxFilePos) { 0 });
bh_table_clear(scope->symbols);
}
-#define REDUCE_BINOP_ALL(op) \
- if (type_is_small_integer(res->type) || type_is_bool(res->type)) { \
- res->value.i = left->value.i op right->value.i; \
- } else if (type_is_integer(res->type) \
- || res->type->Basic.kind == Basic_Kind_Int_Unsized \
- || res->type->kind == Type_Kind_Enum) { \
- res->value.l = left->value.l op right->value.l; \
- } else if (res->type->Basic.kind == Basic_Kind_F32) { \
- res->value.f = left->value.f op right->value.f; \
- } else if (res->type->Basic.kind == Basic_Kind_F64 || res->type->Basic.kind == Basic_Kind_Float_Unsized) { \
- res->value.d = left->value.d op right->value.d; \
- } \
- break;
-
-#define REDUCE_BINOP_INT(op) \
- if (type_is_small_integer(res->type) || type_is_bool(res->type)) { \
- res->value.i = left->value.i op right->value.i; \
- } else if (type_is_integer(res->type) \
- || res->type->Basic.kind == Basic_Kind_Int_Unsized \
- || res->type->kind == Type_Kind_Enum) { \
- res->value.l = left->value.l op right->value.l; \
- } \
- break;
-
-#define REDUCE_BINOP_BOOL(op) \
- if (type_is_bool(res->type)) { \
- res->value.i = left->value.i op right->value.i; \
- } \
- break;
-
-AstNumLit* ast_reduce_binop(bh_allocator a, AstBinaryOp* node) {
- AstNumLit* left = (AstNumLit *) ast_reduce(a, node->left);
- AstNumLit* right = (AstNumLit *) ast_reduce(a, node->right);
-
- if (left->kind != Ast_Kind_NumLit || right->kind != Ast_Kind_NumLit) {
- node->left = (AstTyped *) left;
- node->right = (AstTyped *) right;
- return (AstNumLit *) node;
- }
-
- AstNumLit* res = onyx_ast_node_new(a, sizeof(AstNumLit), Ast_Kind_NumLit);
- res->token = node->token;
- res->flags |= Ast_Flag_Comptime;
- res->type_node = node->type_node;
- res->type = node->type;
-
- switch (node->operation) {
- case Binary_Op_Add: REDUCE_BINOP_ALL(+);
- case Binary_Op_Minus: REDUCE_BINOP_ALL(-);
- case Binary_Op_Multiply: REDUCE_BINOP_ALL(*);
- case Binary_Op_Divide: REDUCE_BINOP_ALL(/);
- case Binary_Op_Modulus: REDUCE_BINOP_INT(%);
-
- case Binary_Op_Equal: REDUCE_BINOP_ALL(==);
- case Binary_Op_Not_Equal: REDUCE_BINOP_ALL(!=);
- case Binary_Op_Less: REDUCE_BINOP_ALL(<);
- case Binary_Op_Less_Equal: REDUCE_BINOP_ALL(<=);
- case Binary_Op_Greater: REDUCE_BINOP_ALL(>);
- case Binary_Op_Greater_Equal: REDUCE_BINOP_ALL(>=);
-
- case Binary_Op_And: REDUCE_BINOP_INT(&);
- case Binary_Op_Or: REDUCE_BINOP_INT(|);
- case Binary_Op_Xor: REDUCE_BINOP_INT(^);
- case Binary_Op_Shl: REDUCE_BINOP_INT(<<);
- case Binary_Op_Shr: REDUCE_BINOP_INT(>>);
- case Binary_Op_Sar: REDUCE_BINOP_INT(>>);
-
- case Binary_Op_Bool_And: REDUCE_BINOP_BOOL(&&);
- case Binary_Op_Bool_Or: REDUCE_BINOP_BOOL(||);
-
- default: break;
- }
-
- return res;
-}
-
-#define REDUCE_UNOP(op) \
- if (type_is_small_integer(unop->type) || type_is_bool(unop->type)) { \
- res->value.i = op ((AstNumLit *) unop->expr)->value.i; \
- } else if (type_is_integer(unop->type) || unop->type->Basic.kind == Basic_Kind_Int_Unsized) { \
- res->value.l = op ((AstNumLit *) unop->expr)->value.l; \
- } else if (unop->type->Basic.kind == Basic_Kind_F32) { \
- res->value.f = op ((AstNumLit *) unop->expr)->value.f; \
- } else if (unop->type->Basic.kind == Basic_Kind_F64 || unop->type->Basic.kind == Basic_Kind_Float_Unsized) { \
- res->value.d = op ((AstNumLit *) unop->expr)->value.d; \
- } \
- break;
-
-#define REDUCE_UNOP_INT(op) \
- if (type_is_small_integer(unop->type) || type_is_bool(unop->type)) { \
- res->value.i = op ((AstNumLit *) unop->expr)->value.i; \
- } else if (type_is_integer(unop->type)) { \
- res->value.l = op ((AstNumLit *) unop->expr)->value.l; \
- }
-
-AstTyped* ast_reduce_unaryop(bh_allocator a, AstUnaryOp* unop) {
- unop->expr = ast_reduce(a, unop->expr);
-
- if (unop->expr->kind != Ast_Kind_NumLit) {
- return (AstTyped *) unop;
- }
-
- AstNumLit* res = onyx_ast_node_new(a, sizeof(AstNumLit), Ast_Kind_NumLit);
- res->token = unop->token;
- res->flags |= Ast_Flag_Comptime;
- res->type_node = unop->type_node;
- res->type = unop->type;
-
- switch (unop->operation) {
- case Unary_Op_Negate: REDUCE_UNOP(-);
- case Unary_Op_Not: {
- if (type_is_bool(res->type)) res->value.i = ! ((AstNumLit *) unop->expr)->value.i;
- break;
- }
- case Unary_Op_Bitwise_Not: REDUCE_UNOP_INT(~);
-
- default: return (AstTyped *) unop;
- }
-
- return (AstTyped *) res;
-}
-
-AstTyped* ast_reduce(bh_allocator a, AstTyped* node) {
- assert(node->flags & Ast_Flag_Comptime);
-
- switch (node->kind) {
- case Ast_Kind_Binary_Op: return (AstTyped *) ast_reduce_binop(a, (AstBinaryOp *) node);
- case Ast_Kind_Unary_Op: return (AstTyped *) ast_reduce_unaryop(a, (AstUnaryOp *) node);
- case Ast_Kind_NumLit: return node;
- case Ast_Kind_Enum_Value: return (AstTyped *) ((AstEnumValue *) node)->value;
- default: return NULL;
- }
-}
-
-void promote_numlit_to_larger(AstNumLit* num) {
- assert(num->type != NULL);
-
- if (type_is_integer(num->type) && num->type->Basic.size <= 4) {
- // NOTE: Int32, Int16, Int8
- i64 val = (i64) num->value.i;
- num->value.l = val;
- num->type = &basic_types[Basic_Kind_I64];
- } else if (num->type->Basic.size <= 4) {
- // NOTE: Float32
- f64 val = (f64) num->value.f;
- num->value.d = val;
- num->type = &basic_types[Basic_Kind_F64];
- }
-}
-
static void insert_poly_slns_into_scope(Scope* scope, bh_arr(AstPolySolution) slns) {
bh_arr_each(AstPolySolution, sln, slns) {
AstNode *node = NULL;
return concrete_struct;
}
-// NOTE: Returns 1 if the conversion was successful.
-b32 convert_numlit_to_type(AstNumLit* num, Type* type) {
- if (num->type == NULL)
- num->type = type_build_from_ast(semstate.allocator, num->type_node);
- assert(num->type);
-
- if (types_are_compatible(num->type, type)) return 1;
- if (!type_is_numeric(type)) return 0;
-
- if (num->type->Basic.kind == Basic_Kind_Int_Unsized) {
-
- //
- // Integer literal auto cast rules:
- // - Up in size always works
- // - Down in size only works if value is in range of smaller type.
- // - Cast to float only works if value is less than the maximum precise value for float size.
- //
-
- if (type->Basic.flags & Basic_Flag_Integer) {
- if (type->Basic.flags & Basic_Flag_Unsigned) {
- u64 value = (u64) num->value.l;
- if (type->Basic.size == 8) {
- num->type = type;
- return 1;
- }
- switch (type->Basic.size) {
- case 1: if (value <= 255) {
- num->type = type;
- return 1;
- }
- case 2: if (value <= 65535) {
- num->type = type;
- return 1;
- }
- case 4: if (value <= 4294967295) {
- num->type = type;
- return 1;
- }
- }
-
- onyx_report_error(num->token->pos, "Unsigned integer constant with value '%l' does not fit into %d-bits.",
- num->value.l,
- type->Basic.size * 8);
-
- } else {
- i64 value = (i64) num->value.l;
- switch (type->Basic.size) {
- case 1: if (-128ll <= value && value <= 127ll) {
- num->value.i = (i32) value;
- num->type = type;
- return 1;
- } break;
- case 2: if (-32768ll <= value && value <= 32767ll) {
- num->value.i = (i32) value;
- num->type = type;
- return 1;
- } break;
- case 4: if (-2147483648ll <= value && value <= 2147483647ll) {
- num->value.i = (i32) value;
- num->type = type;
- return 1;
- } break;
- case 8: { num->type = type;
- return 1;
- } break;
- }
-
- onyx_report_error(num->token->pos, "Integer constant with value '%l' does not fit into %d-bits.",
- num->value.l,
- type->Basic.size * 8);
- }
- }
-
- else if (type->Basic.flags & Basic_Flag_Float) {
- if (type->Basic.size == 4) {
- // TODO(Brendan): Check these boundary conditions
- if (bh_abs(num->value.l) >= (1 << 23)) {
- onyx_report_error(num->token->pos, "Integer '%l' does not fit in 32-bit float exactly.", num->value.l);
- return 0;
- }
-
- num->type = type;
- num->value.f = (f32) num->value.l;
- return 1;
- }
- if (type->Basic.size == 8) {
- // TODO(Brendan): Check these boundary conditions
- if (bh_abs(num->value.l) >= (1ull << 52)) {
- onyx_report_error(num->token->pos, "Integer '%l' does not fit in 64-bit float exactly.", num->value.l);
- return 0;
- }
-
- num->type = type;
- num->value.d = (f64) num->value.l;
- return 1;
- }
- }
- }
- else if (num->type->Basic.kind == Basic_Kind_Float_Unsized) {
- // NOTE: Floats don't cast to integers implicitly.
- if ((type->Basic.flags & Basic_Flag_Float) == 0) return 0;
-
- if (type->Basic.kind == Basic_Kind_F32) {
- num->value.f = (f32) num->value.d;
- }
-
- num->type = type;
- return 1;
- }
- else if (num->type->Basic.kind == Basic_Kind_F32) {
- // NOTE: Floats don't cast to integers implicitly.
- if ((type->Basic.flags & Basic_Flag_Float) == 0) return 0;
-
- if (type->Basic.kind == Basic_Kind_F64) {
- num->value.d = (f64) num->value.f;
- num->type = type;
- return 1;
- }
- }
-
- return 0;
-}
-
-// NOTE: Returns 0 if it was not possible to make the types compatible.
-b32 type_check_or_auto_cast(AstTyped** pnode, Type* type) {
- AstTyped* node = *pnode;
- assert(type != NULL);
- assert(node != NULL);
-
- if (node->kind == Ast_Kind_Polymorphic_Proc) {
- AstFunction* func = polymorphic_proc_lookup((AstPolyProc *) node, PPLM_By_Function_Type, type, node->token->pos);
- if (func == NULL) return 0;
-
- *pnode = (AstTyped *) func;
- node = *pnode;
- }
-
- // HACK: NullProcHack
- if (type->kind == Type_Kind_Function && (node->flags & Ast_Flag_Proc_Is_Null) != 0) return 1;
-
- if (types_are_compatible(node->type, type)) return 1;
- if (node_is_auto_cast((AstNode *) node)) {
- char* dummy;
- if (!cast_is_legal(((AstUnaryOp *) node)->expr->type, type, &dummy)) {
- return 0;
-
- } else {
- ((AstUnaryOp *) node)->type = type;
- return 1;
- }
- }
- else if (node->kind == Ast_Kind_NumLit) {
- if (convert_numlit_to_type((AstNumLit *) node, type)) return 1;
- }
-
- return 0;
-}
-
-Type* resolve_expression_type(AstTyped* node) {
- if (node->type == NULL)
- node->type = type_build_from_ast(semstate.allocator, node->type_node);
-
- if (node->kind == Ast_Kind_NumLit && node->type->kind == Type_Kind_Basic) {
- if (node->type->Basic.kind == Basic_Kind_Int_Unsized) {
- if ((((u64) ((AstNumLit *) node)->value.l) >> 32) > 0)
- convert_numlit_to_type((AstNumLit *) node, &basic_types[Basic_Kind_I64]);
- else
- convert_numlit_to_type((AstNumLit *) node, &basic_types[Basic_Kind_I32]);
- }
- else if (node->type->Basic.kind == Basic_Kind_Float_Unsized) {
- convert_numlit_to_type((AstNumLit *) node, &basic_types[Basic_Kind_F64]);
- }
- }
-
- return node->type;
-}
-
-static const b32 cast_legality[][11] = {
- /* I8 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
- /* U8 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
- /* I16 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
- /* U16 */ { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
- /* I32 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
- /* U32 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
- /* I64 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
- /* U64 */ { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
- /* F32 */ { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
- /* F64 */ { 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0 },
- /* PTR */ { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1 },
-};
-
-b32 cast_is_legal(Type* from_, Type* to_, char** err_msg) {
- Type* from = from_;
- Type* to = to_;
-
- if (from->kind == Type_Kind_Enum) from = from->Enum.backing;
- if (to->kind == Type_Kind_Enum) to = to->Enum.backing;
-
- if (from->kind == Type_Kind_Struct || to->kind == Type_Kind_Struct) {
- *err_msg = "Cannot cast to or from a struct.";
- return 0;
- }
-
- if (from->kind == Type_Kind_Slice || to->kind == Type_Kind_Slice) {
- *err_msg = "Cannot cast to or from a slice.";
- return 0;
- }
-
- if (from->kind == Type_Kind_DynArray || to->kind == Type_Kind_DynArray) {
- *err_msg = "Cannot cast to or from a dynamic array.";
- return 0;
- }
-
- if (to->kind == Type_Kind_Function) {
- *err_msg = "Cannot cast to a function.";
- return 0;
- }
-
- if ( (type_is_simd(to) && !type_is_simd(from))
- || (!type_is_simd(to) && type_is_simd(from))) {
- *err_msg = "Can only perform a SIMD cast between SIMD types.";
- return 0;
- }
-
- if (from->kind == Type_Kind_Basic && from->Basic.kind == Basic_Kind_Void) {
- *err_msg = "Cannot cast from void.";
- return 0;
- }
- i32 fromidx = -1, toidx = -1;
- if (from->Basic.flags & Basic_Flag_Pointer || from->kind == Type_Kind_Array) {
- fromidx = 10;
- }
- else if (from->Basic.flags & Basic_Flag_Integer) {
- b32 unsign = (from->Basic.flags & Basic_Flag_Unsigned) != 0;
-
- fromidx = log2_dumb(from->Basic.size) * 2 + unsign;
- }
- else if (from->Basic.flags & Basic_Flag_Float) {
- if (from->Basic.size == 4) fromidx = 8;
- else if (from->Basic.size == 8) fromidx = 9;
- }
-
- if (to->Basic.flags & Basic_Flag_Pointer || to->kind == Type_Kind_Array) {
- toidx = 10;
- }
- else if (to->Basic.flags & Basic_Flag_Integer) {
- b32 unsign = (to->Basic.flags & Basic_Flag_Unsigned) != 0;
-
- toidx = log2_dumb(to->Basic.size) * 2 + unsign;
- }
- else if (to->Basic.flags & Basic_Flag_Float) {
- if (to->Basic.size == 4) toidx = 8;
- else if (to->Basic.size == 8) toidx = 9;
- }
-
- if (fromidx != -1 && toidx != -1) {
- if (!cast_legality[fromidx][toidx]) {
- *err_msg = bh_aprintf(global_heap_allocator, "Cast from '%s' to '%s' is not allowed.", type_get_name(from_), type_get_name(to_));
- return 0;
- }
- }
-
- *err_msg = NULL;
- return 1;
-}
-
-char* get_function_name(AstFunction* func) {
- if (func->name != NULL) {
- return bh_aprintf(global_scratch_allocator, "%b", func->name->text, func->name->length);
- }
-
- if (func->exported_name != NULL) {
- return bh_aprintf(global_scratch_allocator,
- "EXPORTED:%b",
- func->exported_name->text,
- func->exported_name->length);
- }
-
- return "<anonymous procedure>";
-}
-
void entity_bring_to_state(Entity* ent, EntityState state) {
while (ent->state != state) {
switch (ent->state) {