diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/analyze.cpp | 113 | ||||
| -rw-r--r-- | src/parser.cpp | 233 | ||||
| -rw-r--r-- | src/parser.hpp | 2 |
3 files changed, 296 insertions, 52 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp index a8986e9992..6f272c2065 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -974,7 +974,6 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t } else { symbol_name = buf_sprintf("_%s", buf_ptr(&fn_table_entry->symbol_name)); } - // TODO mangle the name if it's a generic instance fn_table_entry->fn_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_type->data.fn.raw_type_ref); @@ -2828,6 +2827,60 @@ static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) { } } +static bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry) { + switch (type_entry->id) { + case TypeTableEntryIdEnum: + { + ConstEnumValue *enum1 = &a->data.x_enum; + ConstEnumValue *enum2 = &b->data.x_enum; + if (enum1->tag == enum2->tag) { + TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum1->tag]; + if (type_has_bits(enum_field->type_entry)) { + zig_panic("TODO const expr analyze enum special value for equality"); + } else { + return true; + } + } + return false; + } + case TypeTableEntryIdMetaType: + return a->data.x_type == b->data.x_type; + case TypeTableEntryIdVoid: + return true; + case TypeTableEntryIdPureError: + return a->data.x_err.err == b->data.x_err.err; + case TypeTableEntryIdFn: + return a->data.x_fn == b->data.x_fn; + case TypeTableEntryIdBool: + return a->data.x_bool == b->data.x_bool; + case TypeTableEntryIdInt: + case TypeTableEntryIdFloat: + case TypeTableEntryIdNumLitFloat: + case TypeTableEntryIdNumLitInt: + return bignum_cmp_eq(&a->data.x_bignum, &b->data.x_bignum); + case TypeTableEntryIdPointer: + zig_panic("TODO"); + case TypeTableEntryIdArray: + zig_panic("TODO"); + case TypeTableEntryIdStruct: + zig_panic("TODO"); + case TypeTableEntryIdUndefLit: + zig_panic("TODO"); + case TypeTableEntryIdMaybe: + zig_panic("TODO"); + case TypeTableEntryIdErrorUnion: + zig_panic("TODO"); + case TypeTableEntryIdTypeDecl: + zig_panic("TODO"); + case TypeTableEntryIdNamespace: + zig_panic("TODO"); + case TypeTableEntryIdGenericFn: + case TypeTableEntryIdInvalid: + case TypeTableEntryIdUnreachable: + zig_unreachable(); + } +} + static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) { @@ -2887,39 +2940,8 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im } answer = bignum_cmp(&op1_val->data.x_bignum, &op2_val->data.x_bignum); - - } else if (resolved_type->id == TypeTableEntryIdEnum) { - ConstEnumValue *enum1 = &op1_val->data.x_enum; - ConstEnumValue *enum2 = &op2_val->data.x_enum; - bool are_equal = false; - if (enum1->tag == enum2->tag) { - TypeEnumField *enum_field = &op1_type->data.enumeration.fields[enum1->tag]; - if (type_has_bits(enum_field->type_entry)) { - zig_panic("TODO const expr analyze enum special value for equality"); - } else { - are_equal = true; - } - } - if (bin_op_type == BinOpTypeCmpEq) { - answer = are_equal; - } else if (bin_op_type == BinOpTypeCmpNotEq) { - answer = !are_equal; - } else { - zig_unreachable(); - } - } else if (resolved_type->id == TypeTableEntryIdPureError) { - bool are_equal = op1_val->data.x_err.err == op2_val->data.x_err.err; - - if (bin_op_type == BinOpTypeCmpEq) { - answer = are_equal; - } else if (bin_op_type == BinOpTypeCmpNotEq) { - answer = !are_equal; - } else { - zig_unreachable(); - } - } else if (resolved_type->id == TypeTableEntryIdFn) { - bool are_equal = (op1_val->data.x_fn == op2_val->data.x_fn); - + } else { + bool are_equal = const_values_equal(op1_val, op2_val, resolved_type); if (bin_op_type == BinOpTypeCmpEq) { answer = are_equal; } else if (bin_op_type == BinOpTypeCmpNotEq) { @@ -2927,8 +2949,6 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im } else { zig_unreachable(); } - } else { - zig_unreachable(); } bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var; @@ -4682,7 +4702,6 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp generic_param_value->node = *param_node; } - auto entry = g->generic_table.maybe_get(generic_fn_type_id); if (entry) { AstNode *impl_decl_node = entry->value; @@ -4693,9 +4712,10 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp // make a type from the generic parameters supplied assert(decl_node->type == NodeTypeFnProto); - AstNode *impl_fn_def_node = ast_clone_subtree(decl_node->data.fn_proto.fn_def_node); + AstNode *impl_fn_def_node = ast_clone_subtree(decl_node->data.fn_proto.fn_def_node, &g->next_node_index); AstNode *impl_decl_node = impl_fn_def_node->data.fn_def.fn_proto; - impl_decl_node->data.fn_proto.fn_def_node = impl_fn_def_node; + + preview_fn_proto_instance(g, import, impl_decl_node, child_context); @@ -6233,7 +6253,20 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) { } bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) { - // TODO + if (a->decl_node != b->decl_node) return false; + assert(a->generic_param_count == b->generic_param_count); + for (int i = 0; i < a->generic_param_count; i += 1) { + GenericParamValue *a_val = &a->generic_params[i]; + GenericParamValue *b_val = &b->generic_params[i]; + assert(a_val->type == b_val->type); + ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->const_val; + ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->const_val; + assert(a_const_val->ok); + assert(b_const_val->ok); + if (!const_values_equal(a_const_val, b_const_val, a_val->type)) { + return false; + } + } return true; } diff --git a/src/parser.cpp b/src/parser.cpp index 74cf191629..df1fe65310 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -2842,20 +2842,231 @@ void normalize_parent_ptrs(AstNode *node) { ast_visit_node_children(node, normalize_parent_ptrs_visit, nullptr); } -static AstNode *clone_node(AstNode *old_node) { - AstNode *new_node = allocate_nonzero<AstNode>(1); - memcpy(new_node, old_node, sizeof(AstNode)); - return new_node; +static void clone_subtree_list(ZigList<AstNode *> *dest, ZigList<AstNode *> *src, uint32_t *next_node_index) { + memset(dest, 0, sizeof(ZigList<AstNode *>)); + dest->resize(src->length); + for (int i = 0; i < src->length; i += 1) { + dest->at(i) = ast_clone_subtree(src->at(i), next_node_index); + } } -static void ast_clone_subtree_visit(AstNode **node, void *context) { - *node = clone_node(*node); - (*node)->parent_field = node; - ast_visit_node_children(*node, ast_clone_subtree_visit, nullptr); +static void clone_subtree_list_ptr(ZigList<AstNode *> **dest_ptr, ZigList<AstNode *> *src, + uint32_t *next_node_index) +{ + if (src) { + ZigList<AstNode *> *dest = allocate<ZigList<AstNode *>>(1); + *dest_ptr = dest; + clone_subtree_list(dest, src, next_node_index); + } +} + +static void clone_subtree_field(AstNode **dest, AstNode *src, uint32_t *next_node_index) { + *dest = ast_clone_subtree(src, next_node_index); + (*dest)->parent_field = dest; +} + +static void clone_subtree_tld(TopLevelDecl *dest, TopLevelDecl *src, uint32_t *next_node_index) { + clone_subtree_list_ptr(&dest->directives, src->directives, next_node_index); } -AstNode *ast_clone_subtree(AstNode *old_node) { - AstNode *new_node = clone_node(old_node); - ast_visit_node_children(new_node, ast_clone_subtree_visit, nullptr); +AstNode *ast_clone_subtree(AstNode *old_node, uint32_t *next_node_index) { + AstNode *new_node = allocate_nonzero<AstNode>(1); + memcpy(new_node, old_node, sizeof(AstNode)); + new_node->create_index = *next_node_index; + *next_node_index += 1; + + switch (new_node->type) { + case NodeTypeRoot: + clone_subtree_list(&new_node->data.root.top_level_decls, &old_node->data.root.top_level_decls, + next_node_index); + break; + case NodeTypeFnProto: + clone_subtree_tld(&new_node->data.fn_proto.top_level_decl, &old_node->data.fn_proto.top_level_decl, + next_node_index); + clone_subtree_field(&new_node->data.fn_proto.return_type, old_node->data.fn_proto.return_type, + next_node_index); + clone_subtree_list(&new_node->data.fn_proto.generic_params, + &old_node->data.fn_proto.generic_params, next_node_index); + clone_subtree_list(&new_node->data.fn_proto.params, &old_node->data.fn_proto.params, + next_node_index); + + break; + case NodeTypeFnDef: + clone_subtree_field(&new_node->data.fn_def.fn_proto, old_node->data.fn_def.fn_proto, next_node_index); + new_node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = new_node; + clone_subtree_field(&new_node->data.fn_def.body, old_node->data.fn_def.body, next_node_index); + break; + case NodeTypeFnDecl: + clone_subtree_field(&new_node->data.fn_decl.fn_proto, old_node->data.fn_decl.fn_proto, + next_node_index); + break; + case NodeTypeParamDecl: + clone_subtree_field(&new_node->data.param_decl.type, old_node->data.param_decl.type, next_node_index); + break; + case NodeTypeBlock: + clone_subtree_list(&new_node->data.block.statements, &old_node->data.block.statements, + next_node_index); + break; + case NodeTypeDirective: + clone_subtree_field(&new_node->data.directive.expr, old_node->data.directive.expr, next_node_index); + break; + case NodeTypeReturnExpr: + clone_subtree_field(&new_node->data.return_expr.expr, old_node->data.return_expr.expr, next_node_index); + break; + case NodeTypeDefer: + clone_subtree_field(&new_node->data.defer.expr, old_node->data.defer.expr, next_node_index); + break; + case NodeTypeVariableDeclaration: + clone_subtree_list_ptr(&new_node->data.variable_declaration.top_level_decl.directives, + old_node->data.variable_declaration.top_level_decl.directives, next_node_index); + clone_subtree_field(&new_node->data.variable_declaration.type, old_node->data.variable_declaration.type, next_node_index); + clone_subtree_field(&new_node->data.variable_declaration.expr, old_node->data.variable_declaration.expr, next_node_index); + break; + case NodeTypeTypeDecl: + clone_subtree_list_ptr(&new_node->data.type_decl.top_level_decl.directives, + old_node->data.type_decl.top_level_decl.directives, next_node_index); + clone_subtree_field(&new_node->data.type_decl.child_type, old_node->data.type_decl.child_type, next_node_index); + break; + case NodeTypeErrorValueDecl: + // none + break; + case NodeTypeBinOpExpr: + clone_subtree_field(&new_node->data.bin_op_expr.op1, old_node->data.bin_op_expr.op1, next_node_index); + clone_subtree_field(&new_node->data.bin_op_expr.op2, old_node->data.bin_op_expr.op2, next_node_index); + break; + case NodeTypeUnwrapErrorExpr: + clone_subtree_field(&new_node->data.unwrap_err_expr.op1, old_node->data.unwrap_err_expr.op1, next_node_index); + clone_subtree_field(&new_node->data.unwrap_err_expr.symbol, old_node->data.unwrap_err_expr.symbol, next_node_index); + clone_subtree_field(&new_node->data.unwrap_err_expr.op2, old_node->data.unwrap_err_expr.op2, next_node_index); + break; + case NodeTypeNumberLiteral: + // none + break; + case NodeTypeStringLiteral: + // none + break; + case NodeTypeCharLiteral: + // none + break; + case NodeTypeSymbol: + // none + break; + case NodeTypePrefixOpExpr: + clone_subtree_field(&new_node->data.prefix_op_expr.primary_expr, old_node->data.prefix_op_expr.primary_expr, next_node_index); + break; + case NodeTypeFnCallExpr: + clone_subtree_field(&new_node->data.fn_call_expr.fn_ref_expr, old_node->data.fn_call_expr.fn_ref_expr, next_node_index); + clone_subtree_list(&new_node->data.fn_call_expr.params, &old_node->data.fn_call_expr.params, next_node_index); + break; + case NodeTypeArrayAccessExpr: + clone_subtree_field(&new_node->data.array_access_expr.array_ref_expr, old_node->data.array_access_expr.array_ref_expr, next_node_index); + clone_subtree_field(&new_node->data.array_access_expr.subscript, old_node->data.array_access_expr.subscript, next_node_index); + break; + case NodeTypeSliceExpr: + clone_subtree_field(&new_node->data.slice_expr.array_ref_expr, old_node->data.slice_expr.array_ref_expr, next_node_index); + clone_subtree_field(&new_node->data.slice_expr.start, old_node->data.slice_expr.start, next_node_index); + clone_subtree_field(&new_node->data.slice_expr.end, old_node->data.slice_expr.end, next_node_index); + break; + case NodeTypeFieldAccessExpr: + clone_subtree_field(&new_node->data.field_access_expr.struct_expr, old_node->data.field_access_expr.struct_expr, next_node_index); + break; + case NodeTypeUse: + clone_subtree_field(&new_node->data.use.expr, old_node->data.use.expr, next_node_index); + clone_subtree_list_ptr(&new_node->data.use.top_level_decl.directives, + old_node->data.use.top_level_decl.directives, next_node_index); + break; + case NodeTypeBoolLiteral: + // none + break; + case NodeTypeNullLiteral: + // none + break; + case NodeTypeUndefinedLiteral: + // none + break; + case NodeTypeIfBoolExpr: + clone_subtree_field(&new_node->data.if_bool_expr.condition, old_node->data.if_bool_expr.condition, next_node_index); + clone_subtree_field(&new_node->data.if_bool_expr.then_block, old_node->data.if_bool_expr.then_block, next_node_index); + clone_subtree_field(&new_node->data.if_bool_expr.else_node, old_node->data.if_bool_expr.else_node, next_node_index); + break; + case NodeTypeIfVarExpr: + clone_subtree_field(&new_node->data.if_var_expr.var_decl.type, old_node->data.if_var_expr.var_decl.type, next_node_index); + clone_subtree_field(&new_node->data.if_var_expr.var_decl.expr, old_node->data.if_var_expr.var_decl.expr, next_node_index); + clone_subtree_field(&new_node->data.if_var_expr.then_block, old_node->data.if_var_expr.then_block, next_node_index); + clone_subtree_field(&new_node->data.if_var_expr.else_node, old_node->data.if_var_expr.else_node, next_node_index); + break; + case NodeTypeWhileExpr: + clone_subtree_field(&new_node->data.while_expr.condition, old_node->data.while_expr.condition, next_node_index); + clone_subtree_field(&new_node->data.while_expr.body, old_node->data.while_expr.body, next_node_index); + break; + case NodeTypeForExpr: + clone_subtree_field(&new_node->data.for_expr.elem_node, old_node->data.for_expr.elem_node, next_node_index); + clone_subtree_field(&new_node->data.for_expr.array_expr, old_node->data.for_expr.array_expr, next_node_index); + clone_subtree_field(&new_node->data.for_expr.index_node, old_node->data.for_expr.index_node, next_node_index); + clone_subtree_field(&new_node->data.for_expr.body, old_node->data.for_expr.body, next_node_index); + break; + case NodeTypeSwitchExpr: + clone_subtree_field(&new_node->data.switch_expr.expr, old_node->data.switch_expr.expr, next_node_index); + clone_subtree_list(&new_node->data.switch_expr.prongs, &old_node->data.switch_expr.prongs, + next_node_index); + break; + case NodeTypeSwitchProng: + clone_subtree_list(&new_node->data.switch_prong.items, &old_node->data.switch_prong.items, + next_node_index); + clone_subtree_field(&new_node->data.switch_prong.var_symbol, old_node->data.switch_prong.var_symbol, next_node_index); + clone_subtree_field(&new_node->data.switch_prong.expr, old_node->data.switch_prong.expr, next_node_index); + break; + case NodeTypeSwitchRange: + clone_subtree_field(&new_node->data.switch_range.start, old_node->data.switch_range.start, next_node_index); + clone_subtree_field(&new_node->data.switch_range.end, old_node->data.switch_range.end, next_node_index); + break; + case NodeTypeLabel: + // none + break; + case NodeTypeGoto: + // none + break; + case NodeTypeBreak: + // none + break; + case NodeTypeContinue: + // none + break; + case NodeTypeAsmExpr: + zig_panic("TODO"); + break; + case NodeTypeStructDecl: + clone_subtree_list(&new_node->data.struct_decl.fields, &old_node->data.struct_decl.fields, + next_node_index); + clone_subtree_list(&new_node->data.struct_decl.fns, &old_node->data.struct_decl.fns, + next_node_index); + clone_subtree_list_ptr(&new_node->data.struct_decl.top_level_decl.directives, + old_node->data.struct_decl.top_level_decl.directives, next_node_index); + break; + case NodeTypeStructField: + clone_subtree_field(&new_node->data.struct_field.type, old_node->data.struct_field.type, next_node_index); + clone_subtree_list_ptr(&new_node->data.struct_field.top_level_decl.directives, + old_node->data.struct_field.top_level_decl.directives, next_node_index); + break; + case NodeTypeContainerInitExpr: + clone_subtree_field(&new_node->data.container_init_expr.type, old_node->data.container_init_expr.type, next_node_index); + clone_subtree_list(&new_node->data.container_init_expr.entries, + &old_node->data.container_init_expr.entries, next_node_index); + break; + case NodeTypeStructValueField: + clone_subtree_field(&new_node->data.struct_val_field.expr, old_node->data.struct_val_field.expr, next_node_index); + break; + case NodeTypeArrayType: + clone_subtree_field(&new_node->data.array_type.size, old_node->data.array_type.size, next_node_index); + clone_subtree_field(&new_node->data.array_type.child_type, old_node->data.array_type.child_type, next_node_index); + break; + case NodeTypeErrorType: + // none + break; + case NodeTypeTypeLiteral: + // none + break; + } + return new_node; } diff --git a/src/parser.hpp b/src/parser.hpp index 00f7ad1eed..58da0234e6 100644 --- a/src/parser.hpp +++ b/src/parser.hpp @@ -24,7 +24,7 @@ void ast_print(AstNode *node, int indent); void normalize_parent_ptrs(AstNode *node); -AstNode *ast_clone_subtree(AstNode *node); +AstNode *ast_clone_subtree(AstNode *node, uint32_t *next_node_index); void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context); #endif |
