AstType_base;
AstType* callee;
+ Type *resolved_type;
// NOTE: These nodes can be either AstTypes, or AstTyped expressions.
bh_arr(AstNode *) params;
pct->token = call->token;
pct->__unused = call->next;
pct->callee = (AstType *) call->callee;
- pct->params = (AstNode **) call->args.values;
+ pct->params = (AstNode **) bh_arr_copy(global_heap_allocator, call->args.values);
bh_arr_each(AstNode *, pp, pct->params) {
if ((*pp)->kind == Ast_Kind_Argument) {
*pp = (AstNode *) (*(AstArgument **) pp)->value;
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
n = try_symbol_raw_resolve_from_type(field->expr->type, field->field);
type_node = field->expr->type->ast_type;
+ if (!n) n = try_symbol_raw_resolve_from_node((AstNode *) field->expr, field->field);
if (!n) n = try_symbol_raw_resolve_from_node((AstNode *) type_node, field->field);
if (n) {
return Check_Yield_Macro;
}
+ char* type_name = (char *) node_get_type_name(field->expr);
+ if (field->expr->type == &basic_types[Basic_Kind_Type_Index]) {
+ Type *actual_type = type_build_from_ast(context.ast_alloc, (AstType *) field->expr);
+ type_name = (char *) type_get_name(actual_type);
+ }
+
if (!type_node) goto closest_not_found;
char* closest = find_closest_symbol_in_node((AstNode *) type_node, field->field);
if (closest) {
- ERROR_(field->token->pos, "Field '%s' does not exists on '%s'. Did you mean '%s'?", field->field, node_get_type_name(field->expr), closest);
+ ERROR_(field->token->pos, "Field '%s' does not exists on '%s'. Did you mean '%s'?", field->field, type_name, closest);
}
closest_not_found:
- ERROR_(field->token->pos, "Field '%s' does not exists on '%s'.", field->field, node_get_type_name(field->expr));
+ ERROR_(field->token->pos, "Field '%s' does not exists on '%s'.", field->field, type_name);
}
CheckStatus check_method_call(AstBinaryOp** pmcall) {
build_all_overload_options(ofunc->overloads, &all_overloads);
bh_arr_each(bh__imap_entry, entry, all_overloads.entries) {
- AstTyped* node = (AstTyped *) entry->key;
+ AstTyped* node = (AstTyped *) strip_aliases((AstNode *) entry->key);
if (node->kind == Ast_Kind_Overloaded_Function) continue;
if ( node->kind != Ast_Kind_Function
return Check_Success;
}
+ if (directive->kind == Ast_Kind_Injection) {
+ AstInjection *inject = (AstInjection *) directive;
+ if (!node_is_type((AstNode *) inject->dest)) {
+ CHECK(expression, &inject->dest);
+ }
+
+ Scope *scope = get_scope_from_node_or_create((AstNode *) inject->dest);
+ if (scope == NULL) {
+ YIELD_ERROR(inject->token->pos, "Cannot #inject here.");
+ }
+
+ AstBinding *binding = onyx_ast_node_new(context.ast_alloc, sizeof(AstBinding), Ast_Kind_Binding);
+ binding->token = inject->symbol;
+ binding->node = (AstNode *) inject->to_inject;
+ binding->documentation = inject->documentation;
+
+ Package *pac = NULL;
+ if (inject->dest->kind == Ast_Kind_Package) {
+ pac = ((AstPackage *) inject->dest)->package;
+ } else {
+ pac = current_entity->package;
+ }
+
+ add_entities_for_node(NULL, (AstNode *) binding, scope, pac);
+ return Check_Complete;
+ }
+
return Check_Success;
}
void check_entity(Entity* ent) {
CheckStatus cs = Check_Success;
+ current_entity = ent;
switch (ent->type) {
case Entity_Type_Foreign_Function_Header:
void token_toggle_end(OnyxToken* tkn) {
static char backup = 0;
char tmp = tkn->text[tkn->length];
+ assert(backup == '\0' || tmp == '\0'); // Sanity check
tkn->text[tkn->length] = backup;
backup = tmp;
}
onyx_report_error((parser->curr - 2)->pos, Error_Critical, "#Self is only allowed in an #inject block.");
}
- AstAlias* alias = make_node(AstAlias, Ast_Kind_Alias);
- alias->token = parser->injection_point->token;
- alias->alias = parser->injection_point;
- retval = (AstTyped *) alias;
+ retval = (AstTyped *) parser->injection_point;
break;
}
static void struct_type_create_scope(OnyxParser *parser, AstStructType *s_node) {
if (!s_node->scope) {
s_node->scope = scope_create(context.ast_alloc, parser->current_scope, s_node->token->pos);
- parser->current_scope = s_node->scope;
if (bh_arr_length(parser->current_symbol_stack) == 0) {
s_node->scope->name = "<anonymous>";
flush_stored_tags(parser, &s_node->meta_tags);
+ struct_type_create_scope(parser, s_node);
+ Scope *scope_to_restore_parser_to = parser->current_scope;
+ Scope *scope_symbols_in_structures_should_be_bound_to = s_node->scope;
+
// Parse polymorphic parameters
if (consume_token_if_next(parser, '(')) {
bh_arr(AstPolyStructParam) poly_params = NULL;
poly_struct->token = s_token;
poly_struct->poly_params = poly_params;
poly_struct->base_struct = s_node;
+ poly_struct->scope = s_node->scope;
+ s_node->scope = NULL;
}
// Parse constraints clause
}
expect_token(parser, '{');
-
- struct_type_create_scope(parser, s_node);
+
+ parser->current_scope = scope_symbols_in_structures_should_be_bound_to;
b32 member_is_used = 0;
bh_arr(OnyxToken *) member_list_temp = NULL;
}
}
- if (s_node->scope) parser->current_scope = parser->current_scope->parent;
+ parser->current_scope = scope_to_restore_parser_to;
bh_arr_free(member_list_temp);
return;
}
else if (parse_possible_directive(parser, "inject")) {
- AstTyped *injection_point;
- parser->parse_calls = 0;
- injection_point = parse_expression(parser, 0);
- parser->parse_calls = 1;
+ AstAlias *injection_point = make_node(AstAlias, Ast_Kind_Alias);
+ injection_point->alias = parse_expression(parser, 0);
+ injection_point->token = injection_point->alias->token;
if (peek_token(0)->type == '{') {
if (parser->injection_point) {
return;
}
- parser->injection_point = injection_point;
+ parser->injection_point = (AstTyped *) injection_point;
expect_token(parser, '{');
parse_top_level_statements_until(parser, '}');
AstInjection *inject = make_node(AstInjection, Ast_Kind_Injection);
inject->token = dir_token;
- inject->full_loc = injection_point;
+ inject->full_loc = (AstTyped *) injection_point;
inject->to_inject = parse_top_level_expression(parser);
if (parser->last_documentation_token) {
inject->documentation = parser->last_documentation_token;
b32 done = 0;
while (!done && param_type) {
switch (param_type->kind) {
- case Ast_Kind_Pointer_Type: to_replace = &((AstPointerType *) *to_replace)->elem; param_type = ((AstPointerType *) param_type)->elem; break;
- case Ast_Kind_Array_Type: to_replace = &((AstArrayType *) *to_replace)->elem; param_type = ((AstArrayType *) param_type)->elem; break;
- case Ast_Kind_Slice_Type: to_replace = &((AstSliceType *) *to_replace)->elem; param_type = ((AstSliceType *) param_type)->elem; break;
- case Ast_Kind_DynArr_Type: to_replace = &((AstDynArrType *) *to_replace)->elem; param_type = ((AstDynArrType *) param_type)->elem; break;
- case Ast_Kind_Alias: param_type = (AstType *) ((AstAlias *) param_type)->alias; break;
- case Ast_Kind_Type_Alias: param_type = ((AstTypeAlias *) param_type)->to; break;
+ case Ast_Kind_Pointer_Type: to_replace = &((AstPointerType *) *to_replace)->elem; param_type = ((AstPointerType *) param_type)->elem; break;
+ case Ast_Kind_Multi_Pointer_Type: to_replace = &((AstMultiPointerType *) *to_replace)->elem; param_type = ((AstMultiPointerType *) param_type)->elem; break;
+ case Ast_Kind_Array_Type: to_replace = &((AstArrayType *) *to_replace)->elem; param_type = ((AstArrayType *) param_type)->elem; break;
+ case Ast_Kind_Slice_Type: to_replace = &((AstSliceType *) *to_replace)->elem; param_type = ((AstSliceType *) param_type)->elem; break;
+ case Ast_Kind_DynArr_Type: to_replace = &((AstDynArrType *) *to_replace)->elem; param_type = ((AstDynArrType *) param_type)->elem; break;
+ case Ast_Kind_Alias: param_type = (AstType *) ((AstAlias *) param_type)->alias; break;
+ case Ast_Kind_Type_Alias: param_type = ((AstTypeAlias *) param_type)->to; break;
case Ast_Kind_Poly_Struct_Type: {
AutoPolymorphVariable apv;
apv.idx = param_idx;
pcall->flags |= Ast_Flag_Poly_Call_From_Auto;
bh_arr_new(global_heap_allocator, pcall->params, apv->variable_count);
- if (apv->base_type->kind == Ast_Kind_Poly_Struct_Type) {
+ AstType *dealiased_base_type = (AstType *) strip_aliases((AstNode *) apv->base_type);
+
+ if (dealiased_base_type->kind == Ast_Kind_Poly_Struct_Type) {
pp.type_expr = (AstType *) pcall;
} else {
pp.type_expr = apv->base_type;
return NULL;
}
+ assert(!ps_type->base_struct->scope);
+
if (ps_type->concrete_structs == NULL) {
sh_new_arena(ps_type->concrete_structs);
}
insert_poly_slns_into_scope(sln_scope, slns);
AstStructType* concrete_struct = (AstStructType *) ast_clone(context.ast_alloc, ps_type->base_struct);
+ concrete_struct->scope = scope_create(context.ast_alloc, sln_scope, ps_type->token->pos);
concrete_struct->polymorphic_error_loc = pos;
BH_MASK_SET(concrete_struct->flags, !error_if_failed, Ast_Flag_Header_Check_No_Error);
s_node->flags |= Ast_Flag_Type_Is_Resolved;
s_node->flags |= Ast_Flag_Comptime;
- if (s_node->scope) {
- assert(s_node->entity);
- assert(s_node->entity->scope);
- s_node->scope->parent = s_node->entity->scope;
-
- scope_enter(s_node->scope);
- }
+ assert(s_node->scope);
+ scope_enter(s_node->scope);
if (s_node->min_size_) SYMRES(expression, &s_node->min_size_);
if (s_node->min_alignment_) SYMRES(expression, &s_node->min_alignment_);
case Ast_Kind_Poly_Struct_Type: {
AstPolyStructType* pst_node = (AstPolyStructType *) *type;
-
- if (pst_node->scope == NULL) {
- pst_node->scope = scope_create(context.ast_alloc, pst_node->entity->scope, pst_node->token->pos);
- }
+ assert(pst_node->scope);
break;
}
if (inject->dest == NULL) {
if (inject->full_loc == NULL) return Symres_Error;
- if (inject->full_loc->kind != Ast_Kind_Field_Access) {
+ AstTyped *full_loc = (AstTyped *) strip_aliases((AstNode *) inject->full_loc);
+
+ if (full_loc->kind != Ast_Kind_Field_Access) {
onyx_report_error(inject->token->pos, Error_Critical, "#inject expects a dot (a.b) expression for the injection point.");
return Symres_Error;
}
- AstFieldAccess *acc = (AstFieldAccess *) inject->full_loc;
+ AstFieldAccess *acc = (AstFieldAccess *) full_loc;
inject->dest = acc->expr;
inject->symbol = acc->token;
}
SYMRES(expression, &inject->dest);
SYMRES(expression, &inject->to_inject);
-
- Scope *scope = get_scope_from_node_or_create((AstNode *) inject->dest);
- if (scope == NULL) {
- if (context.cycle_almost_detected >= 1) {
- onyx_report_error(inject->token->pos, Error_Critical, "Cannot #inject here.");
- return Symres_Error;
- }
-
- return Symres_Yield_Macro;
- }
-
- AstBinding *binding = onyx_ast_node_new(context.ast_alloc, sizeof(AstBinding), Ast_Kind_Binding);
- binding->token = inject->symbol;
- binding->node = (AstNode *) inject->to_inject;
- binding->documentation = inject->documentation;
-
- Package *pac = NULL;
- if (inject->dest->kind == Ast_Kind_Package) {
- pac = ((AstPackage *) inject->dest)->package;
- } else {
- pac = current_entity->package;
- }
-
- add_entities_for_node(NULL, (AstNode *) binding, scope, pac);
- return Symres_Complete;
+ break;
}
case Ast_Kind_Directive_This_Package: {
return Symres_Error;
}
- ent->function->foreign.import_name = make_string_literal(context.ast_alloc, ent->function->intrinsic_name);
+ ent->function->foreign.import_name = (AstTyped *) make_string_literal(context.ast_alloc, ent->function->intrinsic_name);
ent->function->foreign.module_name = fb->module_name;
ent->function->is_foreign = 1;
ent->function->is_foreign_dyncall = fb->uses_dyncall;
token_toggle_end((*member)->token);
if (shgeti(s_type->Struct.members, (*member)->token->text) != -1) {
onyx_report_error((*member)->token->pos, Error_Critical, "Duplicate struct member, '%s'.", (*member)->token->text);
+ token_toggle_end((*member)->token);
return NULL;
}
if (!concrete) return NULL;
if (concrete == (Type *) &node_that_signals_failure) return concrete;
concrete->Struct.constructed_from = (AstType *) ps_type;
+ pc_type->resolved_type = concrete;
return concrete;
}
// Temporarily disable the parent scope so that you can't access things
// "above" the structures scope. This leads to unintended behavior, as when
// you are accessing a static element on a structure, you don't expect to
- // bleed to the top level scope.
+ // bleed to the top level scope. This code is currently very GROSS, and
+ // should be refactored soon.
AstNode *result = NULL;
if (stype->scope) {
- Scope *tmp_parent = stype->scope->parent;
- stype->scope->parent = NULL;
+ Scope **tmp_parent;
+ Scope *tmp_parent_backup;
+ if (stype->stcache && stype->stcache->Struct.constructed_from) {
+ // Structs scope -> Poly Solution Scope -> Poly Struct Scope -> Enclosing Scope
+ tmp_parent = &stype->scope->parent->parent->parent;
+ } else {
+ tmp_parent = &stype->scope->parent;
+ }
+
+ tmp_parent_backup = *tmp_parent;
+ *tmp_parent = NULL;
+
result = symbol_raw_resolve(stype->scope, symbol);
- stype->scope->parent = tmp_parent;
+
+ *tmp_parent = tmp_parent_backup;
}
if (result == NULL && stype->stcache != NULL) {
}
case Ast_Kind_Poly_Struct_Type: {
- AstStructType* stype = ((AstPolyStructType *) node)->base_struct;
+ AstPolyStructType* stype = ((AstPolyStructType *) node);
return symbol_raw_resolve(stype->scope, symbol);
}
case Ast_Kind_Poly_Call_Type: {
- AstNode* callee = (AstNode *) ((AstPolyCallType *) node)->callee;
- return try_symbol_raw_resolve_from_node(callee, symbol);
+ AstPolyCallType* pctype = (AstPolyCallType *) node;
+ if (pctype->resolved_type) {
+ return try_symbol_raw_resolve_from_node((AstNode*) pctype->resolved_type->ast_type, symbol);
+ }
+ return NULL;
}
case Ast_Kind_Distinct_Type: {
case Ast_Kind_Poly_Struct_Type: {
AstPolyStructType* pstype = (AstPolyStructType *) node;
- AstStructType* stype = pstype->base_struct;
- return &stype->scope;
+ return &pstype->scope;
+ }
+
+ case Ast_Kind_Poly_Call_Type: {
+ AstPolyCallType* pctype = (AstPolyCallType *) node;
+ Type *t = type_build_from_ast(context.ast_alloc, (AstType *) pctype);
+ if (t) {
+ return &((AstStructType *) t->ast_type)->scope;
+ }
+ return NULL;
}
case Ast_Kind_Distinct_Type: {
}
default: {
- onyx_report_error(expr->token->pos, Error_Critical, "Unable to generate location for '%s'.", onyx_ast_node_kind_string(expr->kind));
+ if (expr->token) {
+ onyx_report_error(expr->token->pos, Error_Critical, "Unable to generate location for '%s'.", onyx_ast_node_kind_string(expr->kind));
+ } else {
+ OnyxFilePos pos = {0};
+ onyx_report_error(pos, Error_Critical, "Unable to generate location for '%s'.", onyx_ast_node_kind_string(expr->kind));
+ }
break;
}
}
for line: reader->lines(allocator = context.temp_allocator) {
out: csv.Output_Type;
- for entry: string.split_iter(line, #char ",")
+ for entry: string.split_iter(string.strip_trailing_whitespace(line), #char ",")
|> iter.enumerate()
{
header := &any_headers[entry.index];
for &member: output_type_info.members {
if !#first do io.write(writer, ",");
- io.write_format_va(writer, "{}", .[ .{cast(&u8) it + member.offset, member.type} ]);
+ io.write_format_va(writer, "{}", .[ .{cast([&] u8) it + member.offset, member.type} ]);
}
io.write(writer, "\n");