next: (data: rawptr) -> (T, bool);
close: (data: rawptr) -> void = null_proc;
}
+
+
+CallSite :: struct {
+ file : str;
+ line : u32;
+ column : u32;
+}
\ No newline at end of file
NODE(PolyProc) \
\
NODE(Note) \
+ NODE(CallSite) \
\
NODE(Package)
Ast_Kind_Directive_Add_Overload,
Ast_Kind_Directive_Operator,
Ast_Kind_Directive_Export,
+ Ast_Kind_Call_Site,
Ast_Kind_Note,
AstNode_base;
};
+struct AstCallSite {
+ AstTyped_base;
+
+ OnyxToken* callsite_token;
+
+ AstStrLit* filename;
+ AstNumLit* line;
+ AstNumLit* column;
+};
+
typedef enum EntityState {
Entity_State_Error,
extern AstTyped *builtin_context_variable;
extern AstType *builtin_allocator_type;
extern AstType *builtin_iterator_type;
+extern AstType *builtin_callsite_type;
typedef struct BuiltinSymbol {
char* package;
}
// 'x' and 'y' are the top-left coordinates of the text. 'y' is NOT the baseline.
-draw_text :: (text: str, x: f32, y: f32, size := DEFAULT_TEXT_SIZE, color := gfx.Color4.{1,1,1}) {
+draw_text_raw :: (text: str, x: f32, y: f32, size := DEFAULT_TEXT_SIZE, color := gfx.Color4.{1,1,1}) {
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, font_texture);
gfx.set_texture(0);
}
@Themeing
-draw_button :: (use r: Rectangle, text: str) -> bool {
- gfx.set_texture();
+draw_text :: (use r: Rectangle, text: str, theme := ^default_text_theme) -> bool {
+ height := Rectangle.height(r);
+ draw_text_raw(text, x0, y0, theme.font_size * height, theme.text_color);
+}
- padding :: 10.0f @RawPixels
+@Themeing
+draw_button :: (use r: Rectangle, text: str, theme := ^default_button_theme) -> bool {
+ gfx.set_texture();
+ border_width := theme.border_width;
width, height := Rectangle.dimensions(r);
- gfx.rect(.{ x0, y0 }, .{ width, height }, .{ 0.2, 0.2, 0.2 });
- gfx.rect(.{ x0 + padding, y0 + padding }, .{ width - padding * 2, height - padding * 2 }, .{ 0.1, 0.1, 0.1 });
+ gfx.rect(.{ x0, y0 }, .{ width, height }, theme.border_color);
+ gfx.rect(.{ x0 + border_width, y0 + border_width }, .{ width - border_width * 2, height - border_width * 2 }, theme.background_color);
- font_size := height * .4;
+ font_size := height * theme.font_size;
text_width := font->get_width(text, font_size);
text_height := font->get_height(text, font_size);
- draw_text(text, x0 + (width - text_width) / 2, y0 + (height - text_height) / 2, font_size, .{ 1, 1, 1 });
+ draw_text_raw(text, x0 + (width - text_width) / 2, y0 + (height - text_height) / 2, font_size, theme.text_color);
return false;
}
// x0,y0 ------------+
// | |
// | |
- // +------------ x1, y1
+ // +------------ x1,y1
//
x0: f32 = 0;
height :: (use r: Rectangle) -> f32 do return math.abs(y1 - y0);
dimensions :: (use r: Rectangle) -> (width: f32, height: f32) {
- return math.abs(x1 - x0), math.abs(y1 - y0);
+ return width(r), height(r);
}
top_left :: (use r: Rectangle) -> (x: f32, y: f32) do return math.min(x0, x1), math.min(y0, y1);
+
+@Relocate
+Text_Theme :: struct {
+ text_color := gfx.Color4.{ 1, 1, 1 };
+ font_size := .4f; // Percentage of height of button
+}
+
+@Relocate
+Button_Theme :: struct {
+ @Bug
+ // I accidentally left this as 'text_color', and there was not a compiler error, even through there
+ // should have been. Instead it looked like the wrong offset was being used for the members and that
+ // was affecting the generated code.
+ use text_theme := Text_Theme.{};
+
+ background_color := gfx.Color4.{ 0.1, 0.1, 0.1 };
+
+ border_color := gfx.Color4.{ 0.2, 0.2, 0.2 };
+ border_width := 10.0f; @InPixels
+}
+
+@Bug // there is a compile-time known bug if either of the 'Button_Theme's below are omitted.
+default_button_theme: Button_Theme = Button_Theme.{};
+default_text_theme: Text_Theme = Text_Theme.{};
\ No newline at end of file
AstTyped *builtin_context_variable;
AstType *builtin_allocator_type;
AstType *builtin_iterator_type;
+AstType *builtin_callsite_type;
const BuiltinSymbol builtin_symbols[] = {
{ NULL, "void", (AstNode *) &basic_type_void },
return;
}
+ builtin_callsite_type = (AstType *) symbol_raw_resolve(p->scope, "CallSite");
+ if (builtin_callsite_type == NULL) {
+ onyx_report_error((OnyxFilePos) { 0 }, "'CallSite' struct not found in builtin package.");
+ return;
+ }
+
fori (i, 0, Binary_Op_Count) {
bh_arr_new(global_heap_allocator, operator_overloads[i], 4);
return Check_Error;
}
+ // HACK HACK HACK
+ // :CallSiteIsGross
+ bh_arr_each(AstArgument *, arg, arg_arr) {
+ AstTyped** arg_value = &(*arg)->value;
+
+ if ((*arg_value)->kind == Ast_Kind_Call_Site) {
+ AstCallSite* callsite = (AstCallSite *) ast_clone(context.ast_alloc, *arg_value);
+ callsite->callsite_token = call->token;
+
+ // HACK CLEANUP
+ OnyxToken* str_token = bh_alloc(context.ast_alloc, sizeof(OnyxToken));
+ str_token->text = bh_strdup(global_heap_allocator, (char *) call->token->pos.filename);
+ str_token->length = strlen(call->token->pos.filename);
+ str_token->pos = call->token->pos;
+ str_token->type = Token_Type_Literal_String;
+
+ AstStrLit* filename = bh_alloc_item(context.ast_alloc, AstStrLit);
+ memset(filename, 0, sizeof(AstStrLit));
+ filename->kind = Ast_Kind_StrLit;
+ filename->token = str_token;
+ filename->addr = 0;
+
+ add_entities_for_node(NULL, (AstNode *) filename, NULL, NULL);
+ callsite->filename = filename;
+
+ callsite->line = make_int_literal(context.ast_alloc, call->token->pos.line);
+ callsite->column = make_int_literal(context.ast_alloc, call->token->pos.column);
+
+ convert_numlit_to_type(callsite->line, &basic_types[Basic_Kind_U32]);
+ convert_numlit_to_type(callsite->column, &basic_types[Basic_Kind_U32]);
+
+ *arg_value = (AstTyped *) callsite;
+ }
+ }
+
// NOTE: If we are calling an intrinsic function, translate the
// call into an intrinsic call node.
if (callee->flags & Ast_Flag_Intrinsic) {
CHECK(compound, (AstCompound *) expr);
break;
+ case Ast_Kind_Call_Site: break;
+
case Ast_Kind_StrLit: break;
case Ast_Kind_File_Contents: break;
case Ast_Kind_Overloaded_Function: break;
case Ast_Kind_Local: {
AstTyped* typed_stmt = (AstTyped *) stmt;
fill_in_type(typed_stmt);
- if (typed_stmt->type_node != NULL && typed_stmt->type == NULL) return Check_Yield_Macro;
+ if (typed_stmt->type_node != NULL && typed_stmt->type == NULL) {
+ if (!node_is_type((AstNode *) typed_stmt->type_node)) {
+ onyx_report_error(stmt->token->pos, "Local's type is not a type.");
+ return Check_Error;
+ }
+
+ return Check_Yield_Macro;
+ }
return Check_Success;
}
}
if (local->type_node != NULL) CHECK(type, local->type_node);
+ if (local->type_node != NULL) {
+ if (!node_is_type((AstNode *) local->type_node)) {
+ onyx_report_error(local->token->pos, "Parameter type is not a type.");
+ return Check_Error;
+ }
+ }
fill_in_type((AstTyped *) local);
if (local->type == NULL) {
case Ast_Kind_Directive_Solidify: return sizeof(AstDirectiveSolidify);
case Ast_Kind_Compound: return sizeof(AstCompound);
case Ast_Kind_Named_Value: return sizeof(AstNamedValue);
+ case Ast_Kind_Call_Site: return sizeof(AstCallSite);
case Ast_Kind_Count: return 0;
}
parse_arguments(parser, ')', &call_node->args);
// Wrap expressions in AstArgument
- bh_arr_each(AstTyped *, arg, call_node->args.values)
+ bh_arr_each(AstTyped *, arg, call_node->args.values) {
+ if ((*arg) == NULL) continue;
*arg = (AstTyped *) make_argument(parser->allocator, *arg);
+ }
- bh_arr_each(AstNamedValue *, named_value, call_node->args.named_values)
+ bh_arr_each(AstNamedValue *, named_value, call_node->args.named_values) {
+ if ((*named_value)->value == NULL) continue;
(*named_value)->value = (AstTyped *) make_argument(parser->allocator, (AstTyped *) (*named_value)->value);
+ }
retval = (AstTyped *) call_node;
break;
}
}
- if (curr_param.vararg_kind == VA_Kind_Not_VA && consume_token_if_next(parser, '='))
- curr_param.default_value = parse_expression(parser, 0);
+ if (curr_param.vararg_kind == VA_Kind_Not_VA && consume_token_if_next(parser, '=')) {
+ OnyxToken* directive_token = parser->curr;
+
+ // :Callsite currently #callsite is only valid as a default value for a funciton parameter.
+ if (parse_possible_directive(parser, "callsite")) {
+ AstCallSite* cs = make_node(AstCallSite, Ast_Kind_Call_Site);
+ cs->token = directive_token;
+ cs->type_node = builtin_callsite_type;
+ curr_param.default_value = (AstTyped *) cs;
+
+ } else {
+ curr_param.default_value = parse_expression(parser, 0);
+ }
+ }
if (param_is_baked) {
param_is_baked = 0;
if (s_node->flags & Ast_Flag_Type_Is_Resolved) return Symres_Success;
s_node->flags |= Ast_Flag_Type_Is_Resolved;
-
- {
- bh_table(i32) mem_set;
- bh_table_init(global_heap_allocator, mem_set, bh_arr_length(s_node->members));
-
- bh_arr_each(AstStructMember *, member, s_node->members) {
- token_toggle_end((*member)->token);
-
- if (bh_table_has(i32, mem_set, (*member)->token->text)) {
- onyx_report_error((*member)->token->pos,
- "Duplicate struct member '%s'.",
- (*member)->token->text);
-
- token_toggle_end((*member)->token);
- return Symres_Error;
- }
-
- bh_table_put(i32, mem_set, (*member)->token->text, 1);
- token_toggle_end((*member)->token);
- }
-
- bh_table_free(mem_set);
- }
if (s_node->scope) {
// FIX: This is probably wrong for the long term.
.used = (((*member)->flags & Ast_Flag_Struct_Mem_Used) != 0),
};
+ if (bh_table_has(StructMember, s_type->Struct.members, (*member)->token->text)) {
+ onyx_report_error((*member)->token->pos, "Duplicate struct member, '%s'.", (*member)->token->text);
+ return NULL;
+ }
bh_table_put(StructMember, s_type->Struct.members, (*member)->token->text, smem);
token_toggle_end((*member)->token);
.used = 0,
};
+ if (bh_table_has(StructMember, s_type->Struct.members, (*psmem)->name)) {
+ onyx_report_error((*member)->token->pos, "Duplicate struct member, '%s'.", (*psmem)->name);
+ return NULL;
+ }
bh_table_put(StructMember, s_type->Struct.members, (*psmem)->name, new_smem);
}
}
package->package = package_lookup(package->package_name);
}
+ if (package->package == NULL) {
+ return NULL;
+ }
+
return symbol_raw_resolve(package->package->scope, symbol);
}
break;
}
+ case Ast_Kind_Call_Site: {
+ AstCallSite* callsite = (AstCallSite *) expr;
+
+ emit_expression(mod, &code, (AstTyped *) callsite->filename);
+ emit_expression(mod, &code, (AstTyped *) callsite->line);
+ emit_expression(mod, &code, (AstTyped *) callsite->column);
+ break;
+ }
+
default:
bh_printf("Unhandled case: %d\n", expr->kind);
DEBUG_HERE;