bh_arr(OverloadOption) operator_overloads[Binary_Op_Count] = { 0 };
bh_arr(OverloadOption) unary_operator_overloads[Unary_Op_Count] = { 0 };
+void prepare_builtins() {
+ builtin_string_type = NULL;
+ builtin_cstring_type = NULL;
+ builtin_range_type = NULL;
+ builtin_range_type_type = NULL;
+ builtin_vararg_type = NULL;
+ builtin_vararg_type_type = NULL;
+ builtin_context_variable = NULL;
+ builtin_allocator_type = NULL;
+ builtin_iterator_type = NULL;
+ builtin_optional_type = NULL;
+ builtin_callsite_type = NULL;
+ builtin_any_type = NULL;
+ builtin_code_type = NULL;
+ builtin_link_options_type = NULL;
+ builtin_package_id_type = NULL;
+
+ type_table_node = NULL;
+ foreign_blocks_node = NULL;
+ foreign_block_type = NULL;
+ tagged_procedures_node = NULL;
+ builtin_initialize_data_segments = NULL;
+ builtin_run_init_procedures = NULL;
+ init_procedures = NULL;
+ builtin_implicit_bool_cast = NULL;
+}
+
void initialize_builtins(bh_allocator a) {
// HACK
builtin_package_token.text = bh_strdup(global_heap_allocator, builtin_package_token.text);
return;
}
+ init_procedures = NULL;
bh_arr_new(global_heap_allocator, init_procedures, 4);
fori (i, 0, Binary_Op_Count) {
+ operator_overloads[i] = NULL;
bh_arr_new(global_heap_allocator, operator_overloads[i], 4);
}
fori (i, 0, Unary_Op_Count) {
+ unary_operator_overloads[i] = NULL;
bh_arr_new(global_heap_allocator, unary_operator_overloads[i], 4);
}
IntrinsicMap* intrinsic = &builtin_intrinsics[0];
+ intrinsic_table = NULL;
while (intrinsic->name != NULL) {
shput(intrinsic_table, intrinsic->name, intrinsic->intrinsic);
intrinsic++;
+#define BH_INTERNAL_ALLOCATOR (global_heap_allocator)
#define BH_DEBUG
#include "parser.h"
#include "utils.h"
CheckStatus check_directive_first(AstDirectiveFirst *first);
CheckStatus check_directive_export_name(AstDirectiveExportName *ename);
-// HACK HACK HACK
-b32 expression_types_must_be_known = 0;
-b32 all_checks_are_final = 1;
-b32 inside_for_iterator = 0;
-bh_arr(AstFor *) for_node_stack = NULL;
-static bh_imap __binop_impossible_cache[Binary_Op_Count];
-static AstCall __op_maybe_overloaded;
-static Entity *current_entity = NULL;
-
#define STATEMENT_LEVEL 1
#define EXPRESSION_LEVEL 2
}
}
-// HACK: This should be baked into a structure, not a global variable.
-static bh_arr(Type **) expected_return_type_stack = NULL;
-
CheckStatus check_return(AstReturn* retnode) {
Type ** expected_return_type;
- if (retnode->count >= (u32) bh_arr_length(expected_return_type_stack)) {
+ if (retnode->count >= (u32) bh_arr_length(context.checker.expected_return_type_stack)) {
ERROR_(retnode->token->pos, "Too many repeated 'return's here. Expected a maximum of %d.",
- bh_arr_length(expected_return_type_stack));
+ bh_arr_length(context.checker.expected_return_type_stack));
}
- expected_return_type = expected_return_type_stack[bh_arr_length(expected_return_type_stack) - retnode->count - 1];
+ expected_return_type = context.checker.expected_return_type_stack[bh_arr_length(context.checker.expected_return_type_stack) - retnode->count - 1];
if (retnode->expr) {
CHECK(expression, &retnode->expr);
fornode_expr_checked:
- bh_arr_push(for_node_stack, fornode);
+ bh_arr_push(context.checker.for_node_stack, fornode);
- old_inside_for_iterator = inside_for_iterator;
- inside_for_iterator = 0;
+ old_inside_for_iterator = context.checker.inside_for_iterator;
+ context.checker.inside_for_iterator = 0;
iter_type = fornode->iter->type;
if (type_struct_constructed_from_poly_struct(iter_type, builtin_iterator_type)) {
- inside_for_iterator = 1;
+ context.checker.inside_for_iterator = 1;
}
do {
CheckStatus cs = check_block(fornode->stmt);
- inside_for_iterator = old_inside_for_iterator;
+ context.checker.inside_for_iterator = old_inside_for_iterator;
if (cs > Check_Errors_Start) return cs;
} while(0);
- bh_arr_pop(for_node_stack);
+ bh_arr_pop(context.checker.for_node_stack);
return Check_Success;
}
}
static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop, AstTyped* third_argument) {
- if (bh_arr_length(operator_overloads[binop->operation]) == 0) return &__op_maybe_overloaded;
+ if (bh_arr_length(operator_overloads[binop->operation]) == 0) return &context.checker.__op_maybe_overloaded;
if (binop->overload_args == NULL || binop->overload_args->values[1] == NULL) {
if (binop->overload_args == NULL) {
if (binop_is_assignment(binop->operation)) {
binop->overload_args->values[0] = (AstTyped *) make_address_of(context.ast_alloc, binop->left);
- u32 current_all_checks_are_final = all_checks_are_final;
- all_checks_are_final = 0;
+ u32 current_all_checks_are_final = context.checker.all_checks_are_final;
+ context.checker.all_checks_are_final = 0;
u32 current_checking_level_store = current_checking_level;
CheckStatus cs = check_address_of((AstAddressOf **) &binop->overload_args->values[0]);
current_checking_level = current_checking_level_store;
- all_checks_are_final = current_all_checks_are_final;
+ context.checker.all_checks_are_final = current_all_checks_are_final;
if (cs == Check_Yield_Macro) return (AstCall *) &node_that_signals_a_yield;
if (cs == Check_Error) return NULL;
}
static AstCall* unaryop_try_operator_overload(AstUnaryOp* unop) {
- if (bh_arr_length(unary_operator_overloads[unop->operation]) == 0) return &__op_maybe_overloaded;
+ if (bh_arr_length(unary_operator_overloads[unop->operation]) == 0) return &context.checker.__op_maybe_overloaded;
if (unop->overload_args == NULL || unop->overload_args->values[0] == NULL) {
if (unop->overload_args == NULL) {
binop->flags |= Ast_Flag_Comptime;
}
- if (expression_types_must_be_known) {
+ if (context.checker.expression_types_must_be_known) {
if (binop->left->type == NULL || binop->right->type == NULL) {
ERROR(binop->token->pos, "Internal compiler error: one of the operands types is unknown here.");
}
u64 cache_key = 0;
if (binop->left->type && binop->right->type) {
- if (!__binop_impossible_cache[binop->operation].hashes) {
- bh_imap_init(&__binop_impossible_cache[binop->operation], global_heap_allocator, 256);
+ if (!context.checker.__binop_impossible_cache[binop->operation].hashes) {
+ bh_imap_init(&context.checker.__binop_impossible_cache[binop->operation], global_heap_allocator, 256);
}
cache_key = ((u64) (binop->left->type->id) << 32ll) | (u64) binop->right->type->id;
- if (bh_imap_has(&__binop_impossible_cache[binop->operation], cache_key)) {
+ if (bh_imap_has(&context.checker.__binop_impossible_cache[binop->operation], cache_key)) {
goto definitely_not_op_overload;
}
}
if (implicit_call == (AstCall *) &node_that_signals_a_yield)
YIELD(binop->token->pos, "Trying to resolve operator overload.");
- if (implicit_call != NULL && implicit_call != &__op_maybe_overloaded) {
+ if (implicit_call != NULL && implicit_call != &context.checker.__op_maybe_overloaded) {
// NOTE: Not a binary op
implicit_call->next = binop->next;
*pbinop = (AstBinaryOp *) implicit_call;
return Check_Success;
}
- if (cache_key && implicit_call != &__op_maybe_overloaded) {
- bh_imap_put(&__binop_impossible_cache[binop->operation], cache_key, 1);
+ if (cache_key && implicit_call != &context.checker.__op_maybe_overloaded) {
+ bh_imap_put(&context.checker.__binop_impossible_cache[binop->operation], cache_key, 1);
}
}
binop->type = &basic_types[Basic_Kind_Bool];
}
- if (all_checks_are_final) {
+ if (context.checker.all_checks_are_final) {
binop->flags |= Ast_Flag_Has_Been_Checked;
if (binop->flags & Ast_Flag_Comptime) {
if (unaryop->operation == Unary_Op_Try) {
AstCall* call = unaryop_try_operator_overload(unaryop);
if (call == (AstCall *) &node_that_signals_a_yield) YIELD(unaryop->token->pos, "Waiting on potential operator overload.");
- if (call != NULL && call != &__op_maybe_overloaded) {
+ if (call != NULL && call != &context.checker.__op_maybe_overloaded) {
call->next = unaryop->next;
*(AstCall **) punop = call;
fill_in_type((AstTyped *) doblock);
- bh_arr_push(expected_return_type_stack, &doblock->type);
+ bh_arr_push(context.checker.expected_return_type_stack, &doblock->type);
doblock->block->rules = Block_Rule_Do_Block;
CHECK(block, doblock->block);
if (doblock->type == &type_auto_return) doblock->type = &basic_types[Basic_Kind_Void];
- bh_arr_pop(expected_return_type_stack);
+ bh_arr_pop(context.checker.expected_return_type_stack);
doblock->flags |= Ast_Flag_Has_Been_Checked;
return Check_Success;
}
CheckStatus check_remove_directive(AstDirectiveRemove *remove) {
- if (!inside_for_iterator) {
+ if (!context.checker.inside_for_iterator) {
ERROR(remove->token->pos, "#remove is only allowed in the body of a for-loop over an iterator.");
}
}
CheckStatus check_directive_first(AstDirectiveFirst *first) {
- if (bh_arr_length(for_node_stack) == 0) {
+ if (bh_arr_length(context.checker.for_node_stack) == 0) {
ERROR(first->token->pos, "#first is only allowed in the body of a for-loop.");
}
- first->for_node = bh_arr_last(for_node_stack);
+ first->for_node = bh_arr_last(context.checker.for_node_stack);
assert(first->for_node);
first->for_node->has_first = 1;
}
}
- bh_arr_clear(expected_return_type_stack);
- bh_arr_push(expected_return_type_stack, &func->type->Function.return_type);
+ bh_arr_clear(context.checker.expected_return_type_stack);
+ bh_arr_push(context.checker.expected_return_type_stack, &func->type->Function.return_type);
- inside_for_iterator = 0;
- if (for_node_stack) bh_arr_clear(for_node_stack);
+ context.checker.inside_for_iterator = 0;
+ if (context.checker.for_node_stack) bh_arr_clear(context.checker.for_node_stack);
if (func->body) {
CheckStatus status = check_block(func->body);
}
}
- if (*bh_arr_last(expected_return_type_stack) == &type_auto_return) {
- *bh_arr_last(expected_return_type_stack) = &basic_types[Basic_Kind_Void];
+ if (*bh_arr_last(context.checker.expected_return_type_stack) == &type_auto_return) {
+ *bh_arr_last(context.checker.expected_return_type_stack) = &basic_types[Basic_Kind_Void];
}
func->flags |= Ast_Flag_Has_Been_Checked;
}
CheckStatus check_static_if(AstIf* static_if) {
- expression_types_must_be_known = 1;
+ context.checker.expression_types_must_be_known = 1;
CheckStatus result = check_expression(&static_if->cond);
- expression_types_must_be_known = 0;
+ context.checker.expression_types_must_be_known = 0;
if (result == Check_Yield_Macro) return Check_Yield_Macro;
if (result > Check_Errors_Start || !(static_if->cond->flags & Ast_Flag_Comptime)) {
if (inject->dest->kind == Ast_Kind_Package) {
pac = ((AstPackage *) inject->dest)->package;
} else {
- pac = current_entity->package;
+ pac = context.checker.current_entity->package;
}
add_entities_for_node(NULL, (AstNode *) binding, scope, pac);
void check_entity(Entity* ent) {
CheckStatus cs = Check_Success;
- current_entity = ent;
+ context.checker.current_entity = ent;
+ context.checker.all_checks_are_final = 1;
switch (ent->type) {
case Entity_Type_Foreign_Function_Header:
core_installation = CORE_INSTALLATION;
#endif
#ifdef _BH_WINDOWS
- core_installation = bh_alloc_array(global_heap_allocator, u8, 512);
+ core_installation = bh_alloc_array(alloc, u8, 512);
GetEnvironmentVariableA("ONYX_PATH", core_installation, 512);
#endif
options.passthrough_argument_data = &argv[2];
arg_parse_start = argc;
- bh_arr_push(options.files, bh_aprintf(global_heap_allocator, "%s/tools/onyx-pkg.onyx", core_installation));
+ bh_arr_push(options.files, bh_aprintf(alloc, "%s/tools/onyx-pkg.onyx", core_installation));
}
#ifdef ENABLE_RUN_WITH_WASMER
else if (!strcmp(argv[1], "run")) {
static void context_init(CompileOptions* opts) {
types_init();
+ prepare_builtins();
+
+ memset(&context, 0, sizeof context);
context.options = opts;
context.cycle_detected = 0;
static void context_free() {
bh_arena_free(&context.ast_arena);
bh_arr_free(context.loaded_files);
-
- compile_opts_free(context.options);
}
static void parse_source_file(bh_file_contents* file_contents) {
(u32) ent->micro_attempts);
}
- // CLEANUP: There should be a nicer way to track if the builtins have
- // already been initialized.
- static b32 builtins_initialized = 0;
-
EntityState before_state = ent->state;
switch (before_state) {
case Entity_State_Error:
break;
case Entity_State_Parse:
- if (!builtins_initialized) {
- builtins_initialized = 1;
+ if (!context.builtins_initialized) {
+ context.builtins_initialized = 1;
initialize_builtins(context.ast_alloc);
introduce_build_options(context.ast_alloc);
}
}
#endif
-bh_managed_heap mh;
-
-int main(int argc, char *argv[]) {
+static bh_managed_heap mh;
+CompilerProgress do_compilation(CompileOptions *compile_opts) {
bh_scratch_init(&global_scratch, bh_heap_allocator(), 256 * 1024); // NOTE: 256 KiB
global_scratch_allocator = bh_scratch_allocator(&global_scratch);
- // SPEED: This used to be a managed heap allocator where all allocations
- // were tracked and would be automatically freed at the end of execution.
- // I don't know why I ever did that because that is the job of the operating
- // system when a process exits.
- // global_heap_allocator = bh_heap_allocator();
- bh_managed_heap_init(&mh);
- global_heap_allocator = bh_managed_heap_allocator(&mh);
+ // bh_managed_heap_init(&mh);
+ // global_heap_allocator = bh_managed_heap_allocator(&mh);
+ global_heap_allocator = bh_heap_allocator();
+ context_init(compile_opts);
+
+ return onyx_compile();
+}
+
+void cleanup_compilation() {
+ context_free();
+
+ bh_scratch_free(&global_scratch);
+ // bh_managed_heap_free(&mh);
+}
- CompileOptions compile_opts = compile_opts_parse(global_heap_allocator, argc, argv);
- context_init(&compile_opts);
+int main(int argc, char *argv[]) {
+ CompileOptions compile_opts = compile_opts_parse(bh_heap_allocator(), argc, argv);
CompilerProgress compiler_progress = ONYX_COMPILER_PROGRESS_ERROR;
switch (compile_opts.action) {
}
case ONYX_COMPILE_ACTION_CHECK:
- compiler_progress = onyx_compile();
+ compiler_progress = do_compilation(&compile_opts);
break;
case ONYX_COMPILE_ACTION_COMPILE:
- compiler_progress = onyx_compile();
+ compiler_progress = do_compilation(&compile_opts);
if (compiler_progress == ONYX_COMPILER_PROGRESS_SUCCESS) {
onyx_flush_module();
}
#ifdef ENABLE_RUN_WITH_WASMER
case ONYX_COMPILE_ACTION_RUN:
- compiler_progress = onyx_compile();
+ compiler_progress = do_compilation(&compile_opts);
if (compiler_progress == ONYX_COMPILER_PROGRESS_SUCCESS) {
if (!onyx_run()) {
compiler_progress = ONYX_COMPILER_PROGRESS_ERROR;
}
switch (compiler_progress) {
- case ONYX_COMPILER_PROGRESS_ERROR:
- break;
-
case ONYX_COMPILER_PROGRESS_FAILED_OUTPUT:
bh_printf_err("Failed to open file for writing: '%s'\n", compile_opts.target_file);
break;
-
- case ONYX_COMPILER_PROGRESS_SUCCESS:
- break;
}
- context_free();
-
- bh_scratch_free(&global_scratch);
- bh_managed_heap_free(&mh);
+ cleanup_compilation();
+ compile_opts_free(&compile_opts);
return compiler_progress != ONYX_COMPILER_PROGRESS_SUCCESS;
}