diff options
Diffstat (limited to 'src/parser')
| -rw-r--r-- | src/parser/parser_stmt.c | 26 | ||||
| -rw-r--r-- | src/parser/parser_utils.c | 37 |
2 files changed, 59 insertions, 4 deletions
diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c index 699b9fc..db47d16 100644 --- a/src/parser/parser_stmt.c +++ b/src/parser/parser_stmt.c @@ -1665,17 +1665,26 @@ ASTNode *parse_for(ParserContext *ctx, Lexer *l) var_name[var.len] = 0; ASTNode *obj_expr = start_expr; + char *iter_method = "iterator"; + + // Check for reference iteration: for x in &vec + if (obj_expr->type == NODE_EXPR_UNARY && + obj_expr->unary.op && strcmp(obj_expr->unary.op, "&") == 0) + { + obj_expr = obj_expr->unary.operand; + iter_method = "iter_ref"; + } // var __it = obj.iterator(); ASTNode *it_decl = ast_create(NODE_VAR_DECL); it_decl->var_decl.name = xstrdup("__it"); it_decl->var_decl.type_str = NULL; // inferred - // obj.iterator() + // obj.iterator() or obj.iter_ref() ASTNode *call_iter = ast_create(NODE_EXPR_CALL); ASTNode *memb_iter = ast_create(NODE_EXPR_MEMBER); memb_iter->member.target = obj_expr; - memb_iter->member.field = xstrdup("iterator"); + memb_iter->member.field = xstrdup(iter_method); call_iter->call.callee = memb_iter; call_iter->call.args = NULL; call_iter->call.arg_count = 0; @@ -3391,6 +3400,19 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) n->impl_trait.target_type = name2; n->impl_trait.methods = h; add_to_impl_list(ctx, n); + + // If target struct is generic, register this impl as a template + ASTNode *def = find_struct_def(ctx, name2); + if (def && ((def->type == NODE_STRUCT && def->strct.is_template) || + (def->type == NODE_ENUM && def->enm.is_template))) + { + const char *gp = "T"; + if (def->type == NODE_STRUCT && def->strct.generic_param_count > 0) + gp = def->strct.generic_params[0]; + // TODO: Enum generic params support if needed + register_impl_template(ctx, name2, gp, n); + } + return n; } else diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c index 1f881b7..f96ed24 100644 --- a/src/parser/parser_utils.c +++ b/src/parser/parser_utils.c @@ -1518,6 +1518,11 @@ ASTNode *copy_ast_replacing(ASTNode *n, const char *p, const char *c, const char new_node->impl.struct_name = replace_type_str(n->impl.struct_name, p, c, os, ns); new_node->impl.methods = copy_ast_replacing(n->impl.methods, p, c, os, ns); break; + case NODE_IMPL_TRAIT: + new_node->impl_trait.trait_name = xstrdup(n->impl_trait.trait_name); + new_node->impl_trait.target_type = replace_type_str(n->impl_trait.target_type, p, c, os, ns); + new_node->impl_trait.methods = copy_ast_replacing(n->impl_trait.methods, p, c, os, ns); + break; default: break; } @@ -1879,8 +1884,17 @@ void instantiate_methods(ParserContext *ctx, GenericImplTemplate *it, it->struct_name, mangled_struct_name); it->impl_node->next = backup_next; // Restore - new_impl->impl.struct_name = xstrdup(mangled_struct_name); - ASTNode *meth = new_impl->impl.methods; + + ASTNode *meth = NULL; + + if (new_impl->type == NODE_IMPL) { + new_impl->impl.struct_name = xstrdup(mangled_struct_name); + meth = new_impl->impl.methods; + } else if (new_impl->type == NODE_IMPL_TRAIT) { + new_impl->impl_trait.target_type = xstrdup(mangled_struct_name); + meth = new_impl->impl_trait.methods; + } + while (meth) { char *suffix = meth->func.name + strlen(it->struct_name); @@ -1995,6 +2009,16 @@ void instantiate_generic(ParserContext *ctx, const char *tpl, const char *arg, ASTNode *i = ast_create(NODE_STRUCT); i->strct.name = xstrdup(m); i->strct.is_template = 0; + + // Copy type attributes (e.g. has_drop) + i->type_info = type_new(TYPE_STRUCT); + i->type_info->name = xstrdup(m); + if (t->struct_node->type_info) + { + i->type_info->traits = t->struct_node->type_info->traits; + i->type_info->is_restrict = t->struct_node->type_info->is_restrict; + } + // Use first generic param for substitution (single-param backward compat) const char *gp = (t->struct_node->strct.generic_param_count > 0) ? t->struct_node->strct.generic_params[0] @@ -2009,6 +2033,15 @@ void instantiate_generic(ParserContext *ctx, const char *tpl, const char *arg, ASTNode *i = ast_create(NODE_ENUM); i->enm.name = xstrdup(m); i->enm.is_template = 0; + + // Copy type attributes (e.g. has_drop) + i->type_info = type_new(TYPE_ENUM); + i->type_info->name = xstrdup(m); + if (t->struct_node->type_info) + { + i->type_info->traits = t->struct_node->type_info->traits; + } + ASTNode *h = 0, *tl = 0; ASTNode *v = t->struct_node->enm.variants; while (v) |
