| ... | ... | @@ -756,11 +756,11 @@ static TypeTableEntryId container_to_type(ContainerKind kind) { |
| 756 | 756 | zig_unreachable(); |
| 757 | 757 | } |
| 758 | 758 | |
| 759 | | TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import, |
| 759 | TypeTableEntry *get_partial_container_type(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| 760 | 760 | ContainerKind kind, AstNode *decl_node, const char *name) |
| 761 | 761 | { |
| 762 | 762 | TypeTableEntryId type_id = container_to_type(kind); |
| 763 | | TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, import->block_context); |
| 763 | TypeTableEntry *entry = new_container_type_entry(type_id, decl_node, context); |
| 764 | 764 | |
| 765 | 765 | switch (kind) { |
| 766 | 766 | case ContainerKindStruct: |
| ... | ... | @@ -1171,6 +1171,8 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt |
| 1171 | 1171 | uint64_t biggest_align_in_bits = 0; |
| 1172 | 1172 | uint64_t biggest_union_member_size_in_bits = 0; |
| 1173 | 1173 | |
| 1174 | BlockContext *context = enum_type->data.enumeration.block_context; |
| 1175 | |
| 1174 | 1176 | // set temporary flag |
| 1175 | 1177 | enum_type->data.enumeration.embedded_in_current = true; |
| 1176 | 1178 | |
| ... | ... | @@ -1179,7 +1181,7 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt |
| 1179 | 1181 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); |
| 1180 | 1182 | TypeEnumField *type_enum_field = &enum_type->data.enumeration.fields[i]; |
| 1181 | 1183 | type_enum_field->name = &field_node->data.struct_field.name; |
| 1182 | | TypeTableEntry *field_type = analyze_type_expr(g, import, import->block_context, |
| 1184 | TypeTableEntry *field_type = analyze_type_expr(g, import, context, |
| 1183 | 1185 | field_node->data.struct_field.type); |
| 1184 | 1186 | type_enum_field->type_entry = field_type; |
| 1185 | 1187 | type_enum_field->value = i; |
| ... | ... | @@ -1362,12 +1364,14 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE |
| 1362 | 1364 | // this field should be set to true only during the recursive calls to resolve_struct_type |
| 1363 | 1365 | struct_type->data.structure.embedded_in_current = true; |
| 1364 | 1366 | |
| 1367 | BlockContext *context = struct_type->data.structure.block_context; |
| 1368 | |
| 1365 | 1369 | int gen_field_index = 0; |
| 1366 | 1370 | for (int i = 0; i < field_count; i += 1) { |
| 1367 | 1371 | AstNode *field_node = decl_node->data.struct_decl.fields.at(i); |
| 1368 | 1372 | TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; |
| 1369 | 1373 | type_struct_field->name = &field_node->data.struct_field.name; |
| 1370 | | TypeTableEntry *field_type = analyze_type_expr(g, import, import->block_context, |
| 1374 | TypeTableEntry *field_type = analyze_type_expr(g, import, context, |
| 1371 | 1375 | field_node->data.struct_field.type); |
| 1372 | 1376 | type_struct_field->type_entry = field_type; |
| 1373 | 1377 | type_struct_field->src_index = i; |
| ... | ... | @@ -1469,16 +1473,28 @@ static void get_fully_qualified_decl_name(Buf *buf, AstNode *decl_node, uint8_t |
| 1469 | 1473 | } |
| 1470 | 1474 | |
| 1471 | 1475 | static void preview_generic_fn_proto(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 1472 | | assert(node->type == NodeTypeFnProto); |
| 1476 | if (node->type == NodeTypeFnProto) { |
| 1477 | if (node->data.fn_proto.generic_params_is_var_args) { |
| 1478 | add_node_error(g, node, buf_sprintf("generic parameters cannot be var args")); |
| 1479 | node->data.fn_proto.skip = true; |
| 1480 | node->data.fn_proto.generic_fn_type = g->builtin_types.entry_invalid; |
| 1481 | return; |
| 1482 | } |
| 1473 | 1483 | |
| 1474 | | if (node->data.fn_proto.generic_params_is_var_args) { |
| 1475 | | add_node_error(g, node, buf_sprintf("generic parameters cannot be var args")); |
| 1476 | | node->data.fn_proto.skip = true; |
| 1477 | | node->data.fn_proto.generic_fn_type = g->builtin_types.entry_invalid; |
| 1478 | | return; |
| 1484 | node->data.fn_proto.generic_fn_type = get_generic_fn_type(g, node); |
| 1485 | } else if (node->type == NodeTypeStructDecl) { |
| 1486 | if (node->data.struct_decl.generic_params_is_var_args) { |
| 1487 | add_node_error(g, node, buf_sprintf("generic parameters cannot be var args")); |
| 1488 | node->data.struct_decl.skip = true; |
| 1489 | node->data.struct_decl.generic_fn_type = g->builtin_types.entry_invalid; |
| 1490 | return; |
| 1491 | } |
| 1492 | |
| 1493 | node->data.struct_decl.generic_fn_type = get_generic_fn_type(g, node); |
| 1494 | } else { |
| 1495 | zig_unreachable(); |
| 1479 | 1496 | } |
| 1480 | 1497 | |
| 1481 | | node->data.fn_proto.generic_fn_type = get_generic_fn_type(g, node); |
| 1482 | 1498 | } |
| 1483 | 1499 | |
| 1484 | 1500 | static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstNode *proto_node, |
| ... | ... | @@ -1538,6 +1554,50 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, AstNode *prot |
| 1538 | 1554 | |
| 1539 | 1555 | } |
| 1540 | 1556 | |
| 1557 | static void scan_struct_decl(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) { |
| 1558 | assert(node->type == NodeTypeStructDecl); |
| 1559 | |
| 1560 | Buf *name = &node->data.struct_decl.name; |
| 1561 | TypeTableEntry *container_type = get_partial_container_type(g, import, context, |
| 1562 | node->data.struct_decl.kind, node, buf_ptr(name)); |
| 1563 | node->data.struct_decl.type_entry = container_type; |
| 1564 | |
| 1565 | // handle the member function definitions independently |
| 1566 | for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) { |
| 1567 | AstNode *child_node = node->data.struct_decl.fns.at(i); |
| 1568 | get_as_top_level_decl(child_node)->parent_decl = node; |
| 1569 | BlockContext *child_context = get_container_block_context(container_type); |
| 1570 | scan_decls(g, import, child_context, child_node); |
| 1571 | } |
| 1572 | } |
| 1573 | |
| 1574 | static void resolve_struct_instance(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 1575 | TypeTableEntry *type_entry = node->data.struct_decl.type_entry; |
| 1576 | assert(type_entry); |
| 1577 | |
| 1578 | // struct/enum member fns will get resolved independently |
| 1579 | |
| 1580 | switch (node->data.struct_decl.kind) { |
| 1581 | case ContainerKindStruct: |
| 1582 | resolve_struct_type(g, import, type_entry); |
| 1583 | break; |
| 1584 | case ContainerKindEnum: |
| 1585 | resolve_enum_type(g, import, type_entry); |
| 1586 | break; |
| 1587 | case ContainerKindUnion: |
| 1588 | resolve_union_type(g, import, type_entry); |
| 1589 | break; |
| 1590 | } |
| 1591 | } |
| 1592 | |
| 1593 | static void resolve_struct_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) { |
| 1594 | if (node->data.struct_decl.generic_params.length > 0) { |
| 1595 | return preview_generic_fn_proto(g, import, node); |
| 1596 | } else { |
| 1597 | return resolve_struct_instance(g, import, node); |
| 1598 | } |
| 1599 | } |
| 1600 | |
| 1541 | 1601 | static void preview_error_value_decl(CodeGen *g, AstNode *node) { |
| 1542 | 1602 | assert(node->type == NodeTypeErrorValueDecl); |
| 1543 | 1603 | |
| ... | ... | @@ -1587,25 +1647,8 @@ static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only) |
| 1587 | 1647 | preview_fn_proto(g, import, node); |
| 1588 | 1648 | break; |
| 1589 | 1649 | case NodeTypeStructDecl: |
| 1590 | | { |
| 1591 | | TypeTableEntry *type_entry = node->data.struct_decl.type_entry; |
| 1592 | | |
| 1593 | | // struct/enum member fns will get resolved independently |
| 1594 | | |
| 1595 | | switch (node->data.struct_decl.kind) { |
| 1596 | | case ContainerKindStruct: |
| 1597 | | resolve_struct_type(g, import, type_entry); |
| 1598 | | break; |
| 1599 | | case ContainerKindEnum: |
| 1600 | | resolve_enum_type(g, import, type_entry); |
| 1601 | | break; |
| 1602 | | case ContainerKindUnion: |
| 1603 | | resolve_union_type(g, import, type_entry); |
| 1604 | | break; |
| 1605 | | } |
| 1606 | | |
| 1607 | | break; |
| 1608 | | } |
| 1650 | resolve_struct_decl(g, import, node); |
| 1651 | break; |
| 1609 | 1652 | case NodeTypeVariableDeclaration: |
| 1610 | 1653 | { |
| 1611 | 1654 | AstNodeVariableDeclaration *variable_declaration = &node->data.variable_declaration; |
| ... | ... | @@ -2729,6 +2772,7 @@ static TypeTableEntry *resolve_expr_const_val_as_generic_fn(CodeGen *g, AstNode |
| 2729 | 2772 | return type_entry; |
| 2730 | 2773 | } |
| 2731 | 2774 | |
| 2775 | |
| 2732 | 2776 | static TypeTableEntry *resolve_expr_const_val_as_err(CodeGen *g, AstNode *node, ErrorTableEntry *err) { |
| 2733 | 2777 | Expr *expr = get_resolved_expr(node); |
| 2734 | 2778 | expr->const_val.ok = true; |
| ... | ... | @@ -2888,7 +2932,13 @@ static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNod |
| 2888 | 2932 | return resolve_expr_const_val_as_fn(g, source_node, fn_entry); |
| 2889 | 2933 | } |
| 2890 | 2934 | } else if (decl_node->type == NodeTypeStructDecl) { |
| 2891 | | return resolve_expr_const_val_as_type(g, source_node, decl_node->data.struct_decl.type_entry); |
| 2935 | if (decl_node->data.struct_decl.generic_params.length > 0) { |
| 2936 | TypeTableEntry *type_entry = decl_node->data.struct_decl.generic_fn_type; |
| 2937 | assert(type_entry); |
| 2938 | return resolve_expr_const_val_as_generic_fn(g, source_node, type_entry); |
| 2939 | } else { |
| 2940 | return resolve_expr_const_val_as_type(g, source_node, decl_node->data.struct_decl.type_entry); |
| 2941 | } |
| 2892 | 2942 | } else if (decl_node->type == NodeTypeTypeDecl) { |
| 2893 | 2943 | return resolve_expr_const_val_as_type(g, source_node, decl_node->data.type_decl.child_type_entry); |
| 2894 | 2944 | } else { |
| ... | ... | @@ -5043,9 +5093,16 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp |
| 5043 | 5093 | assert(generic_fn_type->id == TypeTableEntryIdGenericFn); |
| 5044 | 5094 | |
| 5045 | 5095 | AstNode *decl_node = generic_fn_type->data.generic_fn.decl_node; |
| 5046 | | assert(decl_node->type == NodeTypeFnProto); |
| 5096 | ZigList<AstNode *> *generic_params; |
| 5097 | if (decl_node->type == NodeTypeFnProto) { |
| 5098 | generic_params = &decl_node->data.fn_proto.generic_params; |
| 5099 | } else if (decl_node->type == NodeTypeStructDecl) { |
| 5100 | generic_params = &decl_node->data.struct_decl.generic_params; |
| 5101 | } else { |
| 5102 | zig_unreachable(); |
| 5103 | } |
| 5047 | 5104 | |
| 5048 | | int expected_param_count = decl_node->data.fn_proto.generic_params.length; |
| 5105 | int expected_param_count = generic_params->length; |
| 5049 | 5106 | int actual_param_count = node->data.fn_call_expr.params.length; |
| 5050 | 5107 | |
| 5051 | 5108 | if (actual_param_count != expected_param_count) { |
| ... | ... | @@ -5061,7 +5118,7 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp |
| 5061 | 5118 | |
| 5062 | 5119 | BlockContext *child_context = decl_node->owner->block_context; |
| 5063 | 5120 | for (int i = 0; i < actual_param_count; i += 1) { |
| 5064 | | AstNode *generic_param_decl_node = decl_node->data.fn_proto.generic_params.at(i); |
| 5121 | AstNode *generic_param_decl_node = generic_params->at(i); |
| 5065 | 5122 | assert(generic_param_decl_node->type == NodeTypeParamDecl); |
| 5066 | 5123 | |
| 5067 | 5124 | AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type; |
| ... | ... | @@ -5104,24 +5161,36 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp |
| 5104 | 5161 | auto entry = g->generic_table.maybe_get(generic_fn_type_id); |
| 5105 | 5162 | if (entry) { |
| 5106 | 5163 | AstNode *impl_decl_node = entry->value; |
| 5107 | | assert(impl_decl_node->type == NodeTypeFnProto); |
| 5108 | | FnTableEntry *fn_table_entry = impl_decl_node->data.fn_proto.fn_table_entry; |
| 5109 | | return resolve_expr_const_val_as_fn(g, node, fn_table_entry); |
| 5164 | if (impl_decl_node->type == NodeTypeFnProto) { |
| 5165 | FnTableEntry *fn_table_entry = impl_decl_node->data.fn_proto.fn_table_entry; |
| 5166 | return resolve_expr_const_val_as_fn(g, node, fn_table_entry); |
| 5167 | } else if (impl_decl_node->type == NodeTypeStructDecl) { |
| 5168 | TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry; |
| 5169 | return resolve_expr_const_val_as_type(g, node, type_entry); |
| 5170 | } else { |
| 5171 | zig_unreachable(); |
| 5172 | } |
| 5110 | 5173 | } |
| 5111 | 5174 | |
| 5112 | 5175 | // make a type from the generic parameters supplied |
| 5113 | | assert(decl_node->type == NodeTypeFnProto); |
| 5114 | | AstNode *impl_fn_def_node = ast_clone_subtree(decl_node->data.fn_proto.fn_def_node, &g->next_node_index); |
| 5115 | | AstNode *impl_decl_node = impl_fn_def_node->data.fn_def.fn_proto; |
| 5116 | | |
| 5117 | | |
| 5176 | if (decl_node->type == NodeTypeFnProto) { |
| 5177 | AstNode *impl_fn_def_node = ast_clone_subtree(decl_node->data.fn_proto.fn_def_node, &g->next_node_index); |
| 5178 | AstNode *impl_decl_node = impl_fn_def_node->data.fn_def.fn_proto; |
| 5118 | 5179 | |
| 5119 | | preview_fn_proto_instance(g, import, impl_decl_node, child_context); |
| 5120 | | |
| 5121 | | g->generic_table.put(generic_fn_type_id, impl_decl_node); |
| 5122 | | |
| 5123 | | FnTableEntry *fn_table_entry = impl_decl_node->data.fn_proto.fn_table_entry; |
| 5124 | | return resolve_expr_const_val_as_fn(g, node, fn_table_entry); |
| 5180 | preview_fn_proto_instance(g, import, impl_decl_node, child_context); |
| 5181 | g->generic_table.put(generic_fn_type_id, impl_decl_node); |
| 5182 | FnTableEntry *fn_table_entry = impl_decl_node->data.fn_proto.fn_table_entry; |
| 5183 | return resolve_expr_const_val_as_fn(g, node, fn_table_entry); |
| 5184 | } else if (decl_node->type == NodeTypeStructDecl) { |
| 5185 | AstNode *impl_decl_node = ast_clone_subtree(decl_node, &g->next_node_index); |
| 5186 | g->generic_table.put(generic_fn_type_id, impl_decl_node); |
| 5187 | scan_struct_decl(g, import, child_context, impl_decl_node); |
| 5188 | TypeTableEntry *type_entry = impl_decl_node->data.struct_decl.type_entry; |
| 5189 | resolve_struct_type(g, import, type_entry); |
| 5190 | return resolve_expr_const_val_as_type(g, node, type_entry); |
| 5191 | } else { |
| 5192 | zig_unreachable(); |
| 5193 | } |
| 5125 | 5194 | } |
| 5126 | 5195 | |
| 5127 | 5196 | static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context, |
| ... | ... | @@ -6065,7 +6134,8 @@ static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, BlockContex |
| 6065 | 6134 | tld->name = name; |
| 6066 | 6135 | |
| 6067 | 6136 | bool want_as_export = (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport); |
| 6068 | | bool is_generic = (node->type == NodeTypeFnProto && node->data.fn_proto.generic_params.length > 0); |
| 6137 | bool is_generic = (node->type == NodeTypeFnProto && node->data.fn_proto.generic_params.length > 0) || |
| 6138 | (node->type == NodeTypeStructDecl && node->data.struct_decl.generic_params.length > 0); |
| 6069 | 6139 | if (!is_generic && want_as_export) { |
| 6070 | 6140 | g->export_queue.append(node); |
| 6071 | 6141 | } |
| ... | ... | @@ -6093,21 +6163,12 @@ static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *conte |
| 6093 | 6163 | case NodeTypeStructDecl: |
| 6094 | 6164 | { |
| 6095 | 6165 | Buf *name = &node->data.struct_decl.name; |
| 6096 | | TypeTableEntry *container_type = get_partial_container_type(g, import, |
| 6097 | | node->data.struct_decl.kind, node, buf_ptr(name)); |
| 6098 | | node->data.struct_decl.type_entry = container_type; |
| 6099 | 6166 | add_top_level_decl(g, import, context, node, name); |
| 6100 | | |
| 6101 | | // handle the member function definitions independently |
| 6102 | | for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) { |
| 6103 | | AstNode *child_node = node->data.struct_decl.fns.at(i); |
| 6104 | | get_as_top_level_decl(child_node)->parent_decl = node; |
| 6105 | | BlockContext *child_context = get_container_block_context(container_type); |
| 6106 | | scan_decls(g, import, child_context, child_node); |
| 6167 | if (node->data.struct_decl.generic_params.length == 0) { |
| 6168 | scan_struct_decl(g, import, context, node); |
| 6107 | 6169 | } |
| 6108 | | |
| 6109 | | break; |
| 6110 | 6170 | } |
| 6171 | break; |
| 6111 | 6172 | case NodeTypeFnDef: |
| 6112 | 6173 | node->data.fn_def.fn_proto->data.fn_proto.fn_def_node = node; |
| 6113 | 6174 | scan_decls(g, import, context, node->data.fn_def.fn_proto); |