} else {
AstTyped* returned_value = parse_compound_expression(parser, 0);
+ if (returned_value == NULL) goto function_defined;
AstReturn* return_node = make_node(AstReturn, Ast_Kind_Return);
return_node->token = returned_value->token;
ENTITY_SUBMIT(add_overload);
return;
}
+ else if (parse_possible_directive(parser, "inject")) {
+ AstInjection *inject = make_node(AstInjection, Ast_Kind_Injection);
+ inject->token = dir_token;
+
+ parser->parse_calls = 0;
+ inject->full_loc = parse_expression(parser, 0);
+ parser->parse_calls = 1;
+
+ // See comment above
+ if (next_tokens_are(parser, 2, ':', ':')) {
+ consume_tokens(parser, 2);
+ }
+
+ inject->to_inject = parse_expression(parser, 0);
+
+ ENTITY_SUBMIT(inject);
+ return;
+ }
else if (parse_possible_directive(parser, "export")) {
AstDirectiveExport *export = make_node(AstDirectiveExport, Ast_Kind_Directive_Export);
export->token = dir_token;
SYMRES(expression, &library->library_symbol);
break;
}
+
+ case Ast_Kind_Injection: {
+ AstInjection *inject = (AstInjection *) directive;
+
+ if (inject->dest == NULL) {
+ if (inject->full_loc == NULL) return Symres_Error;
+
+ if (inject->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;
+ 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) {
+ onyx_report_error(inject->token->pos, Error_Critical, "Cannot #inject here.");
+ return Symres_Error;
+ }
+
+ AstBinding *binding = onyx_ast_node_new(context.ast_alloc, sizeof(AstBinding), Ast_Kind_Binding);
+ binding->token = inject->symbol;
+ binding->node = (AstNode *) inject->to_inject;
+
+ Package *pac = NULL;
+ if (inject->dest->kind == Ast_Kind_Package) {
+ pac = ((AstPackage *) inject->dest)->package;
+ }
+
+ add_entities_for_node(NULL, (AstNode *) binding, scope, pac);
+ return Symres_Complete;
+ }
}
return Symres_Success;
}
void package_reinsert_use_packages(Package* package) {
+ if (!package) return;
if (!package->use_package_entities) return;
bh_arr_each(Entity *, use_package, package->use_package_entities) {
return total_len;
}
+static Scope **get_scope_from_node_helper(AstNode *node) {
+ b32 used_pointer = 0;
+
+ while (1) {
+ if (!node) return NULL;
+
+ switch (node->kind) {
+ case Ast_Kind_Type_Raw_Alias: node = (AstNode *) ((AstTypeRawAlias *) node)->to->ast_type; break;
+ case Ast_Kind_Type_Alias: node = (AstNode *) ((AstTypeAlias *) node)->to; break;
+ case Ast_Kind_Alias: node = (AstNode *) ((AstAlias *) node)->alias; break;
+ case Ast_Kind_Pointer_Type: {
+ if (used_pointer) goto all_types_peeled_off;
+ used_pointer = 1;
+
+ node = (AstNode *) ((AstPointerType *) node)->elem;
+ break;
+ }
+
+ default: goto all_types_peeled_off;
+ }
+ }
+
+all_types_peeled_off:
+ if (!node) return NULL;
+
+ switch (node->kind) {
+ case Ast_Kind_Package: {
+ AstPackage* package = (AstPackage *) node;
+ if (package->package == NULL) return NULL;
+
+ return &package->package->scope;
+ }
+
+ case Ast_Kind_Enum_Type: {
+ AstEnumType* etype = (AstEnumType *) node;
+ return &etype->scope;
+ }
+
+ case Ast_Kind_Struct_Type: {
+ AstStructType* stype = (AstStructType *) node;
+ return &stype->scope;
+ }
+
+ case Ast_Kind_Poly_Struct_Type: {
+ AstPolyStructType* pstype = (AstPolyStructType *) node;
+ AstStructType* stype = pstype->base_struct;
+ return &stype->scope;
+ }
+ }
+
+ return NULL;
+}
+
+Scope *get_scope_from_node(AstNode *node) {
+ if (!node) return NULL;
+
+ Scope **pscope = get_scope_from_node_helper(node);
+ if (!pscope) return NULL;
+ return *pscope;
+}
+
+Scope *get_scope_from_node_or_create(AstNode *node) {
+ if (!node) return NULL;
+
+ Scope **pscope = get_scope_from_node_helper(node);
+ if (!pscope) return NULL;
+
+ // Create the scope if it does not exist.
+ // This uses a NULL parent, which I think is what
+ // is used in other parts of the compiler for struct/enum
+ // scopes?
+ if (!*pscope) {
+ assert(node->token);
+ *pscope = scope_create(context.ast_alloc, NULL, node->token->pos);
+ }
+
+ return *pscope;
+}
+
u32 levenshtein_distance(const char *str1, const char *str2) {
i32 m = strlen(str1) + 1;
i32 n = strlen(str2) + 1;
}
char *find_closest_symbol_in_node(AstNode* node, char *sym) {
- b32 used_pointer = 0;
-
- while (1) {
- if (!node) return NULL;
-
- switch (node->kind) {
- case Ast_Kind_Type_Raw_Alias: node = (AstNode *) ((AstTypeRawAlias *) node)->to->ast_type; break;
- case Ast_Kind_Type_Alias: node = (AstNode *) ((AstTypeAlias *) node)->to; break;
- case Ast_Kind_Alias: node = (AstNode *) ((AstAlias *) node)->alias; break;
- case Ast_Kind_Pointer_Type: {
- if (used_pointer) goto all_types_peeled_off;
- used_pointer = 1;
-
- node = (AstNode *) ((AstPointerType *) node)->elem;
- break;
- }
-
- default: goto all_types_peeled_off;
- }
- }
-
-all_types_peeled_off:
- if (!node) return NULL;
-
- switch (node->kind) {
- case Ast_Kind_Package: {
- AstPackage* package = (AstPackage *) node;
- if (package->package == NULL) return NULL;
-
- u32 dist;
- return find_closest_symbol_in_scope(package->package->scope, sym, &dist);
- }
-
- case Ast_Kind_Enum_Type: {
- AstEnumType* etype = (AstEnumType *) node;
- u32 dist;
- return find_closest_symbol_in_scope(etype->scope, sym, &dist);
- }
-
- case Ast_Kind_Struct_Type: {
- AstStructType* stype = (AstStructType *) node;
-
- u32 dist;
- char *closest = find_closest_symbol_in_scope(stype->scope, sym, &dist);
-
- Type *type = type_build_from_ast(context.ast_alloc, (AstType *) stype);
- assert(type);
- bh_arr_each(StructMember *, mem, type->Struct.memarr) {
- u32 d = levenshtein_distance((*mem)->name, sym);
- if (d < dist) {
- dist = d;
- closest = (*mem)->name;
- }
- }
-
- return closest;
- }
-
- case Ast_Kind_Poly_Struct_Type: {
- AstPolyStructType* pstype = (AstPolyStructType *) node;
- AstStructType* stype = pstype->base_struct;
- u32 dist;
- char *closest = find_closest_symbol_in_scope(stype->scope, sym, &dist);
-
- bh_arr_each(AstPolyStructParam, param, pstype->poly_params) {
- token_toggle_end(param->token);
- u32 d = levenshtein_distance(param->token->text, sym);
-
- if (d < dist) {
- dist = d;
- closest = bh_strdup(context.ast_alloc, param->token->text);
- }
- token_toggle_end(param->token);
- }
-
- return closest;
- }
-
- case Ast_Kind_Poly_Call_Type: {
+ Scope *scope = get_scope_from_node(node);
+ if (!scope) {
+ if (node->kind == Ast_Kind_Poly_Call_Type) {
AstPolyCallType* pcall = (AstPolyCallType *) node;
return find_closest_symbol_in_node((AstNode *) pcall->callee, sym);
}
+
+ return NULL;
}
- return NULL;
+ u32 dist;
+ return find_closest_symbol_in_scope(scope, sym, &dist);
}