// The builtin _start proc.
// Sets up everything needed for execution.
-_start :: () -> void #export "_start" {
+#export "_start" () {
__runtime_initialize();
args: [] cstr = .{ null, 0 };
// The builtin _start proc.
// Sets up everything needed for execution.
-_start :: () -> void #export "_start" {
+#export "_start" () {
__runtime_initialize();
args : [] cstr;
NODE(DirectiveError) \
NODE(DirectiveAddOverload) \
NODE(DirectiveOperator) \
+ NODE(DirectiveExport) \
\
NODE(Return) \
NODE(Jump) \
Ast_Kind_Directive_Error,
Ast_Kind_Directive_Add_Overload,
Ast_Kind_Directive_Operator,
+ Ast_Kind_Directive_Export,
Ast_Kind_Count
} AstKind;
OnyxToken* name;
- union {
- // NOTE: Used when a global is exported with a specific name
- OnyxToken* exported_name;
-
- // NOTE: Used when the global is declared as foreign
- struct {
- OnyxToken* foreign_module;
- OnyxToken* foreign_name;
- };
- };
+ OnyxToken* foreign_module;
+ OnyxToken* foreign_name;
};
struct AstParam {
// HACK CLEANUP: This does not need to have a local buried inside of it.
// procedure call. Then it is set to the token of the call node.
OnyxToken* generated_from;
+ // NOTE: This is NULL, unless this function is used in a "#export" directive.
+ // It is undefined which name it will have if there are multiple export directives
+ // for this particular function.
+ OnyxToken* exported_name;
+
union {
- // NOTE: Used when a function is exported with a specific name
- OnyxToken* exported_name;
OnyxToken* intrinsic_name;
// NOTE: Used when the function is declared as foreign
AstTyped *overload;
};
+struct AstDirectiveExport {
+ AstNode_base;
+
+ OnyxToken* export_name;
+ AstTyped* export;
+};
typedef enum EntityState {
Entity_State_Error,
return bar;
}
-f :: () -> [5] [2] u32 #export "IAMTHEFUNCTION" {
+f :: () -> [5] [2] u32 {
// This method of returning an array will leak memory, since this is never freed.
// mem := cast(^u32) calloc(sizeof [5] [2] u32);
// for i: 0 .. 10 do mem[i] = 1234 + i;
Vec2 :: struct { x: i32; y: i32; }
Entity :: struct { use pos: Vec2; }
-array_literal_optim :: () -> void #export {
+array_literal_optim :: () -> void {
bar : [5] u32;
bar = u32.[ 1, 2, 3, 4, 5 ];
bar[2] = 1234;
"STATIC ERROR",
"ADD OVERLOAD",
"OPERATOR OVERLOAD",
+ "EXPORT",
"AST_NODE_KIND_COUNT",
};
fill_in_type((AstTyped *) global);
if (global->type == NULL) {
- onyx_report_error(global->token->pos,
- "Unable to resolve type for global '%b'.",
- global->exported_name->text,
- global->exported_name->length);
+ onyx_report_error(global->token->pos, "Unable to resolve type for global.");
return Check_Error;
}
func->type = type_build_function_type(context.ast_alloc, func);
+ /*
+ CLEANUP: These checks need to be ported to a process directive check.
if ((func->flags & Ast_Flag_Exported) != 0) {
if ((func->flags & Ast_Flag_Foreign) != 0) {
onyx_report_error(func->token->pos, "exporting a foreign function");
return Check_Error;
}
}
+ */
return Check_Success;
}
break;
}
+ case Ast_Kind_Directive_Export:
case Ast_Kind_Directive_Add_Overload:
case Ast_Kind_Directive_Operator: {
ent.type = Entity_Type_Process_Directive;
func_def->flags |= Ast_Flag_Foreign;
}
- else if (parse_possible_directive(parser, "export")) {
- func_def->flags |= Ast_Flag_Exported;
-
- if (parser->curr->type == Token_Type_Literal_String) {
- func_def->exported_name = expect_token(parser, Token_Type_Literal_String);
- }
- }
-
// HACK: NullProcHack
else if (parse_possible_directive(parser, "null")) {
func_def->flags |= Ast_Flag_Proc_Is_Null;
global_node->flags |= Ast_Flag_Foreign;
}
- else if (parse_possible_directive(parser, "export")) {
- global_node->flags |= Ast_Flag_Exported;
-
- if (parser->curr->type == Token_Type_Literal_String) {
- global_node->exported_name = expect_token(parser, Token_Type_Literal_String);
- }
- }
-
else {
OnyxToken* directive_token = expect_token(parser, '#');
OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol);
if (node->kind == Ast_Kind_Function) {
AstFunction* func = (AstFunction *) node;
- if (func->exported_name == NULL)
- func->exported_name = symbol;
+ if (func->intrinsic_name == NULL)
+ func->intrinsic_name = symbol;
func->name = symbol;
} else if (node->kind == Ast_Kind_Polymorphic_Proc) {
AstPolyProc* proc = (AstPolyProc *) node;
- if (proc->base_func->exported_name == NULL)
- proc->base_func->exported_name = symbol;
+ if (proc->base_func->intrinsic_name == NULL)
+ proc->base_func->intrinsic_name = symbol;
proc->base_func->name = symbol;
} else if (node->kind == Ast_Kind_Global) {
AstGlobal* global = (AstGlobal *) node;
- if (global->exported_name == NULL)
- global->exported_name = symbol;
-
global->name = symbol;
} else if (node->kind != Ast_Kind_Overloaded_Function
ENTITY_SUBMIT(add_overload);
return;
}
+ else if (parse_possible_directive(parser, "export")) {
+ AstDirectiveExport *export = make_node(AstDirectiveExport, Ast_Kind_Directive_Export);
+ export->token = dir_token;
+ export->export_name = expect_token(parser, Token_Type_Literal_String);
+
+ export->export = parse_expression(parser, 0);
+
+ ENTITY_SUBMIT(export);
+ return;
+ }
else {
OnyxToken* directive_token = expect_token(parser, '#');
OnyxToken* symbol_token = expect_token(parser, Token_Type_Symbol);
bh_arr_push(operator_overloads[operator->operator], operator->overload);
break;
}
+
+ case Ast_Kind_Directive_Export: {
+ AstDirectiveExport *export = (AstDirectiveExport *) directive;
+ SYMRES(expression, &export->export);
+
+ export->export->flags |= Ast_Flag_Exported;
+
+ if (export->export->kind == Ast_Kind_Function) {
+ AstFunction *func = (AstFunction *) export->export;
+ func->exported_name = export->export_name;
+ }
+
+ break;
+ }
}
return Symres_Success;
case Entity_Type_String_Literal: ss = symres_expression(&ent->expr); break;
case Entity_Type_Struct_Member_Default: ss = symres_struct_defaults((AstType *) ent->type_alias); break;
case Entity_Type_Process_Directive: ss = symres_process_directive((AstNode *) ent->expr);
- next_state = Entity_State_Finalized;
break;
default: break;
i32 func_idx = (i32) bh_imap_get(&mod->index_map, (u64) fd);
- if (fd->flags & Ast_Flag_Exported) {
- token_toggle_end(fd->exported_name);
-
- WasmExport wasm_export = {
- .kind = WASM_FOREIGN_FUNCTION,
- .idx = func_idx,
- };
- bh_table_put(WasmExport, mod->exports, fd->exported_name->text, wasm_export);
- mod->export_count++;
-
- token_toggle_end(fd->exported_name);
- }
-
// If there is no body then don't process the code
if (fd->body != NULL) {
// NOTE: Generate the local map
return;
}
+static void emit_export_directive(OnyxWasmModule* mod, AstDirectiveExport* export) {
+ assert(export->export_name);
+ assert(export->export);
+
+ token_toggle_end(export->export_name);
+
+ i64 idx = bh_imap_get(&mod->index_map, (u64) export->export);
+
+ WasmExport wasm_export;
+ wasm_export.idx = (i32) idx;
+
+ switch (export->export->kind) {
+ case Ast_Kind_Function: wasm_export.kind = WASM_FOREIGN_FUNCTION;
+ break;
+
+ case Ast_Kind_Global: wasm_export.kind = WASM_FOREIGN_GLOBAL;
+ break;
+ }
+
+ bh_table_put(WasmExport, mod->exports, export->export_name->text, wasm_export);
+ mod->export_count++;
+
+ token_toggle_end(export->export_name);
+ return;
+}
+
static void emit_global(OnyxWasmModule* module, AstGlobal* global) {
WasmType global_type = onyx_type_to_wasm_type(global->type);
i32 global_idx = (i32) bh_imap_get(&module->index_map, (u64) global);
- if ((global->flags & Ast_Flag_Exported) != 0) {
- token_toggle_end(global->exported_name);
-
- WasmExport wasm_export = {
- .kind = WASM_FOREIGN_GLOBAL,
- .idx = global_idx,
- };
- bh_table_put(WasmExport, module->exports, global->exported_name->text, wasm_export);
- module->export_count++;
-
- token_toggle_end(global->exported_name);
- }
-
bh_arr_new(global_heap_allocator, glob.initial_value, 1);
switch (global_type) {
break;
}
+ case Entity_Type_Process_Directive: {
+ if (ent->expr->kind == Ast_Kind_Directive_Export) {
+ emit_export_directive(module, (AstDirectiveExport *) ent->expr);
+ }
+ break;
+ }
+
case Entity_Type_Function: emit_function(module, ent->function); break;
case Entity_Type_Global: emit_global(module, ent->global); break;