NODE(DirectiveLibrary) \
NODE(DirectiveRemove) \
NODE(DirectiveFirst) \
+ NODE(DirectiveExportName) \
\
NODE(Return) \
NODE(Jump) \
Ast_Kind_Directive_Library,
Ast_Kind_Directive_Remove,
Ast_Kind_Directive_First,
+ Ast_Kind_Directive_Export_Name,
Ast_Kind_Call_Site,
Ast_Kind_Code_Block,
AstFor *for_node;
};
+struct AstDirectiveExportName {
+ AstTyped_base;
+ AstFunction *func;
+ AstStrLit *name;
+ b32 created_export_entity : 1;
+};
+
struct AstNote {
AstNode_base;
};
"LIBRARY",
"REMOVE",
"FIRST",
+ "EXPORT NAME",
"CALL SITE",
"CODE BLOCK",
CheckStatus check_constraint_context(ConstraintContext *cc, Scope *scope, OnyxFilePos pos);
CheckStatus check_polyquery(AstPolyQuery *query);
CheckStatus check_directive_first(AstDirectiveFirst *first);
+CheckStatus check_directive_export_name(AstDirectiveExportName *ename);
// HACK HACK HACK
b32 expression_types_must_be_known = 0;
if (expr->type == NULL) YIELD(expr->token->pos, "Waiting to know constraint sentinel's type.");
break;
+ case Ast_Kind_Directive_Export_Name:
+ retval = check_directive_export_name((AstDirectiveExportName *) expr);
+ break;
+
case Ast_Kind_StrLit: break;
case Ast_Kind_File_Contents: break;
case Ast_Kind_Overloaded_Function: break;
return Check_Success;
}
+CheckStatus check_directive_export_name(AstDirectiveExportName *ename) {
+ if (ename->func->kind != Ast_Kind_Function) {
+ ERROR(ename->token->pos, "#export_name can only be used on functions.");
+ }
+
+ if (ename->type == NULL) YIELD(ename->token->pos, "This should never yield here...");
+
+ ename->flags |= Ast_Flag_Comptime;
+
+ //
+ // TODO: Cleanup this code. I feel like there should be some convenience functions
+ // to make string literals, tokens, exports, etc...
+ if (ename->func->exported_name == NULL) {
+ if (ename->created_export_entity) {
+ return Check_Yield_Macro;
+ }
+
+ // In this case, we know the function is not exported.
+ assert(ename->func->is_exported == 0);
+
+ char *random_name = bh_alloc_array(context.ast_alloc, char, 16);
+ random_name[15] = 0;
+ fori (i, 0, 15) random_name[i] = (rand() % 26) + 'a';
+
+ OnyxToken *name_token = bh_alloc_item(context.ast_alloc, OnyxToken);
+ memset(name_token, 0, sizeof(*name_token));
+ name_token->type = Token_Type_Literal_String;
+ name_token->length = 15;
+ name_token->text = random_name;
+
+ AstStrLit* name = bh_alloc_item(context.ast_alloc, AstStrLit);
+ memset(name, 0, sizeof(AstStrLit));
+ name->kind = Ast_Kind_StrLit;
+ name->token = name_token;
+ name->type_node = builtin_string_type;
+
+ add_entities_for_node(NULL, (AstNode *) name, NULL, NULL);
+ ename->name = name;
+
+ AstDirectiveExport *export = onyx_ast_node_new(context.ast_alloc, sizeof(AstDirectiveExport), Ast_Kind_Directive_Export);
+ export->token = ename->token;
+ export->export_name_expr = (AstTyped *) name;
+ export->export = (AstTyped *) ename->func;
+
+ add_entities_for_node(NULL, (AstNode *) export, NULL, NULL);
+
+ ename->created_export_entity = 1;
+ return Check_Yield_Macro;
+
+ } else {
+ AstStrLit* name = bh_alloc_item(context.ast_alloc, AstStrLit);
+ memset(name, 0, sizeof(AstStrLit));
+ name->kind = Ast_Kind_StrLit;
+ name->token = ename->func->exported_name;
+ name->type_node = builtin_string_type;
+
+ add_entities_for_node(NULL, (AstNode *) name, NULL, NULL);
+ ename->name = name;
+ }
+
+ return Check_Success;
+}
+
CheckStatus check_statement(AstNode** pstmt) {
AstNode* stmt = *pstmt;
}
export->export_name = export->export_name_expr->token;
+
+ AstFunction *exported_func = (AstFunction *) export->export;
+ if (exported_func->exported_name == NULL) {
+ exported_func->exported_name = export->export_name;
+ }
}
if (directive->kind == Ast_Kind_Directive_Init) {
case Ast_Kind_Constraint: return sizeof(AstConstraint);
case Ast_Kind_Directive_Remove: return sizeof(AstDirectiveRemove);
case Ast_Kind_Directive_First: return sizeof(AstDirectiveFirst);
+ case Ast_Kind_Directive_Export_Name: return sizeof(AstDirectiveExportName);
case Ast_Kind_Count: return 0;
}
C(AstFileContents, filename_expr);
E(nn);
break;
+
+ case Ast_Kind_Directive_Export_Name:
+ C(AstDirectiveExportName, func);
+ break;
}
clone_depth--;
retval = (AstTyped *) first;
break;
}
+ else if (parse_possible_directive(parser, "export_name")) {
+ AstDirectiveExportName *export_name = make_node(AstDirectiveExportName, Ast_Kind_Directive_Export_Name);
+ export_name->token = parser->curr - 1;
+ export_name->func = (AstFunction *) parse_factor(parser);
+ export_name->type_node = builtin_string_type;
+
+ retval = (AstTyped *) export_name;
+ break;
+ }
onyx_report_error(parser->curr->pos, Error_Critical, "Invalid directive in expression.");
return NULL;
break;
}
+ case Ast_Kind_Directive_Export_Name: {
+ AstDirectiveExportName *ename = (AstDirectiveExportName *) *expr;
+ SYMRES(expression, (AstTyped **) &ename->func);
+ break;
+ }
+
default: break;
}
if (export->export->kind == Ast_Kind_Function) {
AstFunction *func = (AstFunction *) export->export;
- func->exported_name = export->export_name;
func->is_exported = 1;
- if (func->is_exported) {
- if (func->is_foreign) {
- onyx_report_error(export->token->pos, Error_Critical, "Cannot export a foreign function.");
- return Symres_Error;
- }
+ if (func->is_foreign) {
+ onyx_report_error(export->token->pos, Error_Critical, "Cannot export a foreign function.");
+ return Symres_Error;
+ }
- if (func->is_intrinsic) {
- onyx_report_error(export->token->pos, Error_Critical, "Cannot export an intrinsic function.");
- return Symres_Error;
- }
+ if (func->is_intrinsic) {
+ onyx_report_error(export->token->pos, Error_Critical, "Cannot export an intrinsic function.");
+ return Symres_Error;
}
}
break;
}
+ case Ast_Kind_Directive_Export_Name: {
+ AstDirectiveExportName *ename = (AstDirectiveExportName *) expr;
+ emit_expression(mod, &code, (AstTyped *) ename->name);
+ break;
+ }
+
default:
bh_printf("Unhandled case: %d\n", expr->kind);
DEBUG_HERE;
break;
}
+ case Ast_Kind_Directive_Export_Name: {
+ AstDirectiveExportName *ename = (AstDirectiveExportName *) node;
+ node = (AstTyped *) ename->name;
+
+ // This fallthrough is very intentional. This replaces the value of "node"
+ // so the case below thinks it is just generating the constexpr of a string.
+ // fallthrough
+ }
+
case Ast_Kind_StrLit: {
AstStrLit* sl = (AstStrLit *) node;
arena.size = sizeof rawptr;
}
+get_allocated_arenas :: (arena: ^ArenaState) -> u32 {
+ arenas := 0;
+ walker := arena.first_arena;
+ while walker != null {
+ arenas += 1;
+ walker = walker.next;
+ }
+
+ return arenas;
+}
+
+get_allocated_bytes :: (arena: ^ArenaState) -> u32 {
+ return get_allocated_arenas(arena) * (arena.arena_size - 1) + arena.size;
+}
+
auto :: #match {
macro (size := 32 * 1024, $dest: Code = #(context.allocator)) {
alloc :: package core.alloc
reduce_explodes :: (use n: ^SnailNum, depth := 0) -> (reduced_something: bool, zero_node: bool) {
if depth <= 3 {
- did_reduce, zero_node := false, false;
-
if left != null {
- if did_reduce, zero_node = left->reduce_explodes(depth + 1); zero_node {
+ if did_reduce, zero_node := left->reduce_explodes(depth + 1); zero_node {
left = null;
+ return true, false;
+
+ } elseif did_reduce {
+ return true, false;
}
}
- if right != null && !did_reduce {
- if did_reduce, zero_node = right->reduce_explodes(depth + 1); zero_node {
+ if right != null {
+ if did_reduce, zero_node := right->reduce_explodes(depth + 1); zero_node {
right = null;
+ return true, false;
+
+ } elseif did_reduce {
+ return true, false;
}
}
- return did_reduce, false;
+ return false, false;
}
- pleft := n->pair_to_left();
- pright := n->pair_to_right();
+ pleft := n->number_to_left();
+ pright := n->number_to_right();
if pleft != null do *pleft += left_val;
if pright != null do *pright += right_val;
if new_right != null do new_right.parent = parent;
}
- pair_to_left :: (n: ^SnailNum) -> ^u32 {
+ number_to_left :: (n: ^SnailNum) -> ^u32 {
while n.parent != null && n.parent.left == n {
n = n.parent;
}
return ^n.right_val;
}
- pair_to_right :: (n: ^SnailNum) -> ^u32 {
+ number_to_right :: (n: ^SnailNum) -> ^u32 {
while n.parent != null && n.parent.right == n {
n = n.parent;
}
main :: () {
- num_arena := arena.make(context.allocator, 64 * 1024);
+ num_arena := arena.make(context.allocator, 256 * 1024);
SnailNum.allocator = alloc.as_allocator(^num_arena);
conv.register_custom_formatter(SnailNum.format);