authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-08 00:24:48-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-09-08 00:24:48-04:00
logd324b1befa6c7f0fd5d18ffe45a98d104a62d8a0
tree0258132b13007f3b93cabc2ca54f4d17689e0c2d
parentde7e88c38fcaa37c98c2425be341568e8e193ffc

ability to infer parameter types


10 files changed, 245 insertions(+), 82 deletions(-)

doc/langref.md+1-1
...@@ -45,7 +45,7 @@ Label = Symbol ":"...@@ -45,7 +45,7 @@ Label = Symbol ":"
4545
46Expression = BlockExpression | NonBlockExpression46Expression = BlockExpression | NonBlockExpression
4747
48TypeExpr = PrefixOpExpression48TypeExpr = PrefixOpExpression | "var"
4949
50NonBlockExpression = ReturnExpression | AssignmentExpression50NonBlockExpression = ReturnExpression | AssignmentExpression
5151
src/all_types.hpp+12
...@@ -194,6 +194,7 @@ enum NodeType {...@@ -194,6 +194,7 @@ enum NodeType {
194 NodeTypeArrayType,194 NodeTypeArrayType,
195 NodeTypeErrorType,195 NodeTypeErrorType,
196 NodeTypeTypeLiteral,196 NodeTypeTypeLiteral,
197 NodeTypeVarLiteral,
197};198};
198199
199struct AstNodeRoot {200struct AstNodeRoot {
...@@ -218,6 +219,7 @@ struct AstNodeFnProto {...@@ -218,6 +219,7 @@ struct AstNodeFnProto {
218 Expr resolved_expr;219 Expr resolved_expr;
219 // computed from params field220 // computed from params field
220 int inline_arg_count;221 int inline_arg_count;
222 int inline_or_var_type_arg_count;
221 // if this is a generic function implementation, this points to the generic node223 // if this is a generic function implementation, this points to the generic node
222 AstNode *generic_proto_node;224 AstNode *generic_proto_node;
223};225};
...@@ -754,6 +756,11 @@ struct AstNodeTypeLiteral {...@@ -754,6 +756,11 @@ struct AstNodeTypeLiteral {
754 Expr resolved_expr;756 Expr resolved_expr;
755};757};
756758
759struct AstNodeVarLiteral {
760 // populated by semantic analyzer
761 Expr resolved_expr;
762};
763
757struct AstNode {764struct AstNode {
758 enum NodeType type;765 enum NodeType type;
759 int line;766 int line;
...@@ -812,6 +819,7 @@ struct AstNode {...@@ -812,6 +819,7 @@ struct AstNode {
812 AstNodeArrayType array_type;819 AstNodeArrayType array_type;
813 AstNodeErrorType error_type;820 AstNodeErrorType error_type;
814 AstNodeTypeLiteral type_literal;821 AstNodeTypeLiteral type_literal;
822 AstNodeVarLiteral var_literal;
815 } data;823 } data;
816};824};
817825
...@@ -836,6 +844,7 @@ struct FnTypeParamInfo {...@@ -836,6 +844,7 @@ struct FnTypeParamInfo {
836struct GenericParamValue {844struct GenericParamValue {
837 TypeTableEntry *type;845 TypeTableEntry *type;
838 AstNode *node;846 AstNode *node;
847 int impl_index;
839};848};
840849
841struct GenericFnTypeId {850struct GenericFnTypeId {
...@@ -976,6 +985,7 @@ struct TypeTableEntryTypeDecl {...@@ -976,6 +985,7 @@ struct TypeTableEntryTypeDecl {
976985
977enum TypeTableEntryId {986enum TypeTableEntryId {
978 TypeTableEntryIdInvalid,987 TypeTableEntryIdInvalid,
988 TypeTableEntryIdVar,
979 TypeTableEntryIdMetaType,989 TypeTableEntryIdMetaType,
980 TypeTableEntryIdVoid,990 TypeTableEntryIdVoid,
981 TypeTableEntryIdBool,991 TypeTableEntryIdBool,
...@@ -1229,6 +1239,7 @@ struct CodeGen {...@@ -1229,6 +1239,7 @@ struct CodeGen {
1229 TypeTableEntry *entry_num_lit_float;1239 TypeTableEntry *entry_num_lit_float;
1230 TypeTableEntry *entry_undef;1240 TypeTableEntry *entry_undef;
1231 TypeTableEntry *entry_null;1241 TypeTableEntry *entry_null;
1242 TypeTableEntry *entry_var;
1232 TypeTableEntry *entry_pure_error;1243 TypeTableEntry *entry_pure_error;
1233 TypeTableEntry *entry_os_enum;1244 TypeTableEntry *entry_os_enum;
1234 TypeTableEntry *entry_arch_enum;1245 TypeTableEntry *entry_arch_enum;
...@@ -1337,6 +1348,7 @@ struct VariableTableEntry {...@@ -1337,6 +1348,7 @@ struct VariableTableEntry {
1337 LLVMValueRef param_value_ref;1348 LLVMValueRef param_value_ref;
1338 bool force_depends_on_compile_var;1349 bool force_depends_on_compile_var;
1339 ImportTableEntry *import;1350 ImportTableEntry *import;
1351 bool shadowable;
1340};1352};
13411353
1342struct ErrorTableEntry {1354struct ErrorTableEntry {
src/analyze.cpp+153-69
...@@ -109,6 +109,7 @@ static AstNode *first_executing_node(AstNode *node) {...@@ -109,6 +109,7 @@ static AstNode *first_executing_node(AstNode *node) {
109 case NodeTypeErrorType:109 case NodeTypeErrorType:
110 case NodeTypeTypeLiteral:110 case NodeTypeTypeLiteral:
111 case NodeTypeContainerInitExpr:111 case NodeTypeContainerInitExpr:
112 case NodeTypeVarLiteral:
112 return node;113 return node;
113 }114 }
114 zig_unreachable();115 zig_unreachable();
...@@ -219,6 +220,7 @@ static int bits_needed_for_unsigned(uint64_t x) {...@@ -219,6 +220,7 @@ static int bits_needed_for_unsigned(uint64_t x) {
219static bool type_is_complete(TypeTableEntry *type_entry) {220static bool type_is_complete(TypeTableEntry *type_entry) {
220 switch (type_entry->id) {221 switch (type_entry->id) {
221 case TypeTableEntryIdInvalid:222 case TypeTableEntryIdInvalid:
223 case TypeTableEntryIdVar:
222 zig_unreachable();224 zig_unreachable();
223 case TypeTableEntryIdStruct:225 case TypeTableEntryIdStruct:
224 return type_entry->data.structure.complete;226 return type_entry->data.structure.complete;
...@@ -919,39 +921,6 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor...@@ -919,39 +921,6 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
919 fn_type_id.is_var_args = fn_proto->is_var_args;921 fn_type_id.is_var_args = fn_proto->is_var_args;
920 fn_type_id.return_type = analyze_type_expr(g, import, context, fn_proto->return_type);922 fn_type_id.return_type = analyze_type_expr(g, import, context, fn_proto->return_type);
921923
922 switch (fn_type_id.return_type->id) {
923 case TypeTableEntryIdInvalid:
924 fn_proto->skip = true;
925 break;
926 case TypeTableEntryIdNumLitFloat:
927 case TypeTableEntryIdNumLitInt:
928 case TypeTableEntryIdUndefLit:
929 case TypeTableEntryIdNullLit:
930 case TypeTableEntryIdNamespace:
931 case TypeTableEntryIdGenericFn:
932 fn_proto->skip = true;
933 add_node_error(g, fn_proto->return_type,
934 buf_sprintf("return type '%s' not allowed", buf_ptr(&fn_type_id.return_type->name)));
935 break;
936 case TypeTableEntryIdMetaType:
937 case TypeTableEntryIdUnreachable:
938 case TypeTableEntryIdVoid:
939 case TypeTableEntryIdBool:
940 case TypeTableEntryIdInt:
941 case TypeTableEntryIdFloat:
942 case TypeTableEntryIdPointer:
943 case TypeTableEntryIdArray:
944 case TypeTableEntryIdStruct:
945 case TypeTableEntryIdMaybe:
946 case TypeTableEntryIdErrorUnion:
947 case TypeTableEntryIdPureError:
948 case TypeTableEntryIdEnum:
949 case TypeTableEntryIdUnion:
950 case TypeTableEntryIdFn:
951 case TypeTableEntryIdTypeDecl:
952 break;
953 }
954
955 for (int i = 0; i < fn_type_id.param_count; i += 1) {924 for (int i = 0; i < fn_type_id.param_count; i += 1) {
956 AstNode *child = fn_proto->params.at(i);925 AstNode *child = fn_proto->params.at(i);
957 assert(child->type == NodeTypeParamDecl);926 assert(child->type == NodeTypeParamDecl);
...@@ -996,6 +965,10 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor...@@ -996,6 +965,10 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
996 case TypeTableEntryIdFn:965 case TypeTableEntryIdFn:
997 case TypeTableEntryIdTypeDecl:966 case TypeTableEntryIdTypeDecl:
998 break;967 break;
968 case TypeTableEntryIdVar:
969 // var types are treated as generic functions; if we get to this code we should
970 // already be an instantiated function.
971 zig_unreachable();
999 }972 }
1000 if (type_entry->id == TypeTableEntryIdInvalid) {973 if (type_entry->id == TypeTableEntryIdInvalid) {
1001 fn_proto->skip = true;974 fn_proto->skip = true;
...@@ -1005,6 +978,42 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor...@@ -1005,6 +978,42 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
1005 param_info->is_noalias = child->data.param_decl.is_noalias;978 param_info->is_noalias = child->data.param_decl.is_noalias;
1006 }979 }
1007980
981 switch (fn_type_id.return_type->id) {
982 case TypeTableEntryIdInvalid:
983 fn_proto->skip = true;
984 break;
985 case TypeTableEntryIdNumLitFloat:
986 case TypeTableEntryIdNumLitInt:
987 case TypeTableEntryIdUndefLit:
988 case TypeTableEntryIdNullLit:
989 case TypeTableEntryIdNamespace:
990 case TypeTableEntryIdGenericFn:
991 fn_proto->skip = true;
992 add_node_error(g, fn_proto->return_type,
993 buf_sprintf("return type '%s' not allowed", buf_ptr(&fn_type_id.return_type->name)));
994 break;
995 case TypeTableEntryIdMetaType:
996 case TypeTableEntryIdUnreachable:
997 case TypeTableEntryIdVoid:
998 case TypeTableEntryIdBool:
999 case TypeTableEntryIdInt:
1000 case TypeTableEntryIdFloat:
1001 case TypeTableEntryIdPointer:
1002 case TypeTableEntryIdArray:
1003 case TypeTableEntryIdStruct:
1004 case TypeTableEntryIdMaybe:
1005 case TypeTableEntryIdErrorUnion:
1006 case TypeTableEntryIdPureError:
1007 case TypeTableEntryIdEnum:
1008 case TypeTableEntryIdUnion:
1009 case TypeTableEntryIdFn:
1010 case TypeTableEntryIdTypeDecl:
1011 break;
1012 case TypeTableEntryIdVar:
1013 zig_panic("TODO var return type");
1014 }
1015
1016
1008 if (fn_proto->skip) {1017 if (fn_proto->skip) {
1009 return g->builtin_types.entry_invalid;1018 return g->builtin_types.entry_invalid;
1010 }1019 }
...@@ -1618,6 +1627,11 @@ static void preview_generic_fn_proto(CodeGen *g, ImportTableEntry *import, AstNo...@@ -1618,6 +1627,11 @@ static void preview_generic_fn_proto(CodeGen *g, ImportTableEntry *import, AstNo
1618 node->data.struct_decl.generic_fn_type = get_generic_fn_type(g, node);1627 node->data.struct_decl.generic_fn_type = get_generic_fn_type(g, node);
1619}1628}
16201629
1630static bool get_is_generic_fn(AstNode *proto_node) {
1631 assert(proto_node->type == NodeTypeFnProto);
1632 return proto_node->data.fn_proto.inline_or_var_type_arg_count > 0;
1633}
1634
1621static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstNode *proto_node,1635static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstNode *proto_node,
1622 BlockContext *containing_context)1636 BlockContext *containing_context)
1623{1637{
...@@ -1628,7 +1642,7 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN...@@ -1628,7 +1642,7 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN
1628 }1642 }
16291643
1630 bool is_generic_instance = proto_node->data.fn_proto.generic_proto_node;1644 bool is_generic_instance = proto_node->data.fn_proto.generic_proto_node;
1631 bool is_generic_fn = proto_node->data.fn_proto.inline_arg_count > 0;1645 bool is_generic_fn = get_is_generic_fn(proto_node);
1632 assert(!is_generic_instance || !is_generic_fn);1646 assert(!is_generic_instance || !is_generic_fn);
16331647
1634 AstNode *parent_decl = proto_node->data.fn_proto.top_level_decl.parent_decl;1648 AstNode *parent_decl = proto_node->data.fn_proto.top_level_decl.parent_decl;
...@@ -1875,6 +1889,7 @@ static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only)...@@ -1875,6 +1889,7 @@ static void resolve_top_level_decl(CodeGen *g, AstNode *node, bool pointer_only)
1875 case NodeTypeArrayType:1889 case NodeTypeArrayType:
1876 case NodeTypeErrorType:1890 case NodeTypeErrorType:
1877 case NodeTypeTypeLiteral:1891 case NodeTypeTypeLiteral:
1892 case NodeTypeVarLiteral:
1878 zig_unreachable();1893 zig_unreachable();
1879 }1894 }
18801895
...@@ -1936,6 +1951,9 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {...@@ -1936,6 +1951,9 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {
19361951
1937 case TypeTableEntryIdTypeDecl:1952 case TypeTableEntryIdTypeDecl:
1938 return type_has_codegen_value(type_entry->data.type_decl.canonical_type);1953 return type_has_codegen_value(type_entry->data.type_decl.canonical_type);
1954
1955 case TypeTableEntryIdVar:
1956 zig_unreachable();
1939 }1957 }
1940 zig_unreachable();1958 zig_unreachable();
1941}1959}
...@@ -3374,6 +3392,9 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im...@@ -3374,6 +3392,9 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im
3374 add_node_error(g, node,3392 add_node_error(g, node,
3375 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));3393 buf_sprintf("operator not allowed for type '%s'", buf_ptr(&resolved_type->name)));
3376 return g->builtin_types.entry_invalid;3394 return g->builtin_types.entry_invalid;
3395
3396 case TypeTableEntryIdVar:
3397 zig_unreachable();
3377 }3398 }
33783399
3379 ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;3400 ConstExprValue *op1_val = &get_resolved_expr(*op1)->const_val;
...@@ -3751,20 +3772,22 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,...@@ -3751,20 +3772,22 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
3751}3772}
37523773
3753// Set name to nullptr to make the variable anonymous (not visible to programmer).3774// Set name to nullptr to make the variable anonymous (not visible to programmer).
3754static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, ImportTableEntry *import,3775static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_node, ImportTableEntry *import,
3755 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const, AstNode *val_node)3776 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const, AstNode *val_node,
3777 bool shadowable)
3756{3778{
3757 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);3779 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);
3758 variable_entry->type = type_entry;3780 variable_entry->type = type_entry;
3759 variable_entry->block_context = context;3781 variable_entry->block_context = context;
3760 variable_entry->import = import;3782 variable_entry->import = import;
3783 variable_entry->shadowable = shadowable;
37613784
3762 if (name) {3785 if (name) {
3763 buf_init_from_buf(&variable_entry->name, name);3786 buf_init_from_buf(&variable_entry->name, name);
37643787
3765 if (type_entry->id != TypeTableEntryIdInvalid) {3788 if (type_entry->id != TypeTableEntryIdInvalid) {
3766 VariableTableEntry *existing_var = find_variable(g, context, name);3789 VariableTableEntry *existing_var = find_variable(g, context, name);
3767 if (existing_var) {3790 if (existing_var && !existing_var->shadowable) {
3768 ErrorMsg *msg = add_node_error(g, source_node,3791 ErrorMsg *msg = add_node_error(g, source_node,
3769 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));3792 buf_sprintf("redeclaration of variable '%s'", buf_ptr(name)));
3770 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));3793 add_error_note(g, msg, existing_var->decl_node, buf_sprintf("previous declaration is here"));
...@@ -3805,6 +3828,12 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Impor...@@ -3805,6 +3828,12 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Impor
3805 return variable_entry;3828 return variable_entry;
3806}3829}
38073830
3831static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, ImportTableEntry *import,
3832 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const, AstNode *val_node)
3833{
3834 return add_local_var_shadowable(g, source_node, import, context, name, type_entry, is_const, val_node, false);
3835}
3836
3808static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *import,3837static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *import,
3809 BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *node)3838 BlockContext *parent_context, TypeTableEntry *expected_type, AstNode *node)
3810{3839{
...@@ -5227,6 +5256,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry...@@ -5227,6 +5256,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
5227 case TypeTableEntryIdNullLit:5256 case TypeTableEntryIdNullLit:
5228 case TypeTableEntryIdNamespace:5257 case TypeTableEntryIdNamespace:
5229 case TypeTableEntryIdGenericFn:5258 case TypeTableEntryIdGenericFn:
5259 case TypeTableEntryIdVar:
5230 add_node_error(g, expr_node,5260 add_node_error(g, expr_node,
5231 buf_sprintf("type '%s' not eligible for @typeOf", buf_ptr(&type_entry->name)));5261 buf_sprintf("type '%s' not eligible for @typeOf", buf_ptr(&type_entry->name)));
5232 return g->builtin_types.entry_invalid;5262 return g->builtin_types.entry_invalid;
...@@ -5542,23 +5572,22 @@ static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableE...@@ -5542,23 +5572,22 @@ static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableE
5542 return g->builtin_types.entry_invalid;5572 return g->builtin_types.entry_invalid;
5543 }5573 }
55445574
5545 int inline_arg_count = decl_node->data.fn_proto.inline_arg_count;5575 int inline_or_var_type_arg_count = decl_node->data.fn_proto.inline_or_var_type_arg_count;
5546 assert(inline_arg_count > 0);5576 assert(inline_or_var_type_arg_count > 0);
55475577
5548 BlockContext *child_context = decl_node->owner->block_context;5578 BlockContext *child_context = decl_node->owner->block_context;
5549 int next_generic_param_index = 0;5579 int next_generic_param_index = 0;
55505580
5551 GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1);5581 GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1);
5552 generic_fn_type_id->decl_node = decl_node;5582 generic_fn_type_id->decl_node = decl_node;
5553 generic_fn_type_id->generic_param_count = inline_arg_count;5583 generic_fn_type_id->generic_param_count = inline_or_var_type_arg_count;
5554 generic_fn_type_id->generic_params = allocate<GenericParamValue>(inline_arg_count);5584 generic_fn_type_id->generic_params = allocate<GenericParamValue>(inline_or_var_type_arg_count);
55555585
5586 int next_impl_i = 0;
5556 for (int call_i = 0; call_i < call_param_count; call_i += 1) {5587 for (int call_i = 0; call_i < call_param_count; call_i += 1) {
5557 int proto_i = call_i + struct_node_1_or_0;5588 int proto_i = call_i + struct_node_1_or_0;
5558 AstNode *generic_param_decl_node = decl_node->data.fn_proto.params.at(proto_i);5589 AstNode *generic_param_decl_node = decl_node->data.fn_proto.params.at(proto_i);
5559 assert(generic_param_decl_node->type == NodeTypeParamDecl);5590 assert(generic_param_decl_node->type == NodeTypeParamDecl);
5560 bool is_inline = generic_param_decl_node->data.param_decl.is_inline;
5561 if (!is_inline) continue;
55625591
5563 AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type;5592 AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type;
5564 TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner, child_context,5593 TypeTableEntry *expected_param_type = analyze_type_expr(g, decl_node->owner, child_context,
...@@ -5567,9 +5596,17 @@ static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableE...@@ -5567,9 +5596,17 @@ static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableE
5567 return expected_param_type;5596 return expected_param_type;
5568 }5597 }
55695598
5599 bool is_var_type = (expected_param_type->id == TypeTableEntryIdVar);
5600 bool is_inline = generic_param_decl_node->data.param_decl.is_inline;
5601 if (!is_inline && !is_var_type) {
5602 next_impl_i += 1;
5603 continue;
5604 }
5605
5606
5570 AstNode **param_node = &call_node->data.fn_call_expr.params.at(call_i);5607 AstNode **param_node = &call_node->data.fn_call_expr.params.at(call_i);
5571 TypeTableEntry *param_type = analyze_expression(g, import, parent_context,5608 TypeTableEntry *param_type = analyze_expression(g, import, parent_context,
5572 expected_param_type, *param_node);5609 is_var_type ? nullptr : expected_param_type, *param_node);
5573 if (param_type->id == TypeTableEntryIdInvalid) {5610 if (param_type->id == TypeTableEntryIdInvalid) {
5574 return param_type;5611 return param_type;
5575 }5612 }
...@@ -5578,27 +5615,32 @@ static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableE...@@ -5578,27 +5615,32 @@ static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableE
5578 child_context = new_block_context(generic_param_decl_node, child_context);5615 child_context = new_block_context(generic_param_decl_node, child_context);
55795616
5580 ConstExprValue *const_val = &get_resolved_expr(*param_node)->const_val;5617 ConstExprValue *const_val = &get_resolved_expr(*param_node)->const_val;
5581 if (const_val->ok) {5618 if (is_inline && !const_val->ok) {
5582 VariableTableEntry *var = add_local_var(g, generic_param_decl_node, decl_node->owner, child_context,
5583 generic_param_decl_node->data.param_decl.name, param_type, true, *param_node);
5584 // This generic function instance could be called with anything, so when this variable is read it
5585 // needs to know that it depends on compile time variable data.
5586 var->force_depends_on_compile_var = true;
5587 } else {
5588 add_node_error(g, *param_node,5619 add_node_error(g, *param_node,
5589 buf_sprintf("unable to evaluate constant expression for inline parameter"));5620 buf_sprintf("unable to evaluate constant expression for inline parameter"));
55905621
5591 return g->builtin_types.entry_invalid;5622 return g->builtin_types.entry_invalid;
5592 }5623 }
55935624
5625 VariableTableEntry *var = add_local_var_shadowable(g, generic_param_decl_node, decl_node->owner, child_context,
5626 generic_param_decl_node->data.param_decl.name, param_type, true, *param_node, true);
5627 // This generic function instance could be called with anything, so when this variable is read it
5628 // needs to know that it depends on compile time variable data.
5629 var->force_depends_on_compile_var = true;
5630
5594 GenericParamValue *generic_param_value =5631 GenericParamValue *generic_param_value =
5595 &generic_fn_type_id->generic_params[next_generic_param_index];5632 &generic_fn_type_id->generic_params[next_generic_param_index];
5596 generic_param_value->type = param_type;5633 generic_param_value->type = param_type;
5597 generic_param_value->node = *param_node;5634 generic_param_value->node = is_inline ? *param_node : nullptr;
5635 generic_param_value->impl_index = next_impl_i;
5598 next_generic_param_index += 1;5636 next_generic_param_index += 1;
5637
5638 if (!is_inline) {
5639 next_impl_i += 1;
5640 }
5599 }5641 }
56005642
5601 assert(next_generic_param_index == inline_arg_count);5643 assert(next_generic_param_index == inline_or_var_type_arg_count);
56025644
5603 auto entry = g->generic_table.maybe_get(generic_fn_type_id);5645 auto entry = g->generic_table.maybe_get(generic_fn_type_id);
5604 FnTableEntry *impl_fn;5646 FnTableEntry *impl_fn;
...@@ -5612,8 +5654,23 @@ static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableE...@@ -5612,8 +5654,23 @@ static TypeTableEntry *analyze_fn_call_with_inline_args(CodeGen *g, ImportTableE
5612 &g->next_node_index, AstCloneSpecialOmitInlineParams);5654 &g->next_node_index, AstCloneSpecialOmitInlineParams);
5613 AstNode *impl_decl_node = impl_fn_def_node->data.fn_def.fn_proto;5655 AstNode *impl_decl_node = impl_fn_def_node->data.fn_def.fn_proto;
5614 impl_decl_node->data.fn_proto.inline_arg_count = 0;5656 impl_decl_node->data.fn_proto.inline_arg_count = 0;
5657 impl_decl_node->data.fn_proto.inline_or_var_type_arg_count = 0;
5615 impl_decl_node->data.fn_proto.generic_proto_node = decl_node;5658 impl_decl_node->data.fn_proto.generic_proto_node = decl_node;
56165659
5660 // replace var arg types with actual types
5661 for (int generic_arg_i = 0; generic_arg_i < inline_or_var_type_arg_count; generic_arg_i += 1) {
5662 GenericParamValue *generic_param_value = &generic_fn_type_id->generic_params[generic_arg_i];
5663 if (!generic_param_value->node) {
5664 int impl_i = generic_param_value->impl_index;
5665 AstNode *impl_param_decl_node = impl_decl_node->data.fn_proto.params.at(impl_i);
5666 assert(impl_param_decl_node->type == NodeTypeParamDecl);
5667
5668 impl_param_decl_node->data.param_decl.type = create_ast_type_node(g, import,
5669 generic_param_value->type, impl_param_decl_node);
5670 normalize_parent_ptrs(impl_param_decl_node);
5671 }
5672 }
5673
5617 preview_fn_proto_instance(g, import, impl_decl_node, child_context);5674 preview_fn_proto_instance(g, import, impl_decl_node, child_context);
5618 g->generic_table.put(generic_fn_type_id, impl_decl_node);5675 g->generic_table.put(generic_fn_type_id, impl_decl_node);
5619 impl_fn = impl_decl_node->data.fn_proto.fn_table_entry;5676 impl_fn = impl_decl_node->data.fn_proto.fn_table_entry;
...@@ -5660,6 +5717,9 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp...@@ -5660,6 +5717,9 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp
5660 if (expected_param_type->id == TypeTableEntryIdInvalid) {5717 if (expected_param_type->id == TypeTableEntryIdInvalid) {
5661 return expected_param_type;5718 return expected_param_type;
5662 }5719 }
5720
5721
5722
5663 AstNode **param_node = &node->data.fn_call_expr.params.at(i);5723 AstNode **param_node = &node->data.fn_call_expr.params.at(i);
56645724
5665 TypeTableEntry *param_type = analyze_expression(g, import, parent_context, expected_param_type,5725 TypeTableEntry *param_type = analyze_expression(g, import, parent_context, expected_param_type,
...@@ -6605,6 +6665,9 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn...@@ -6605,6 +6665,9 @@ static TypeTableEntry *analyze_expression_pointer_only(CodeGen *g, ImportTableEn
6605 case NodeTypeSwitchExpr:6665 case NodeTypeSwitchExpr:
6606 return_type = analyze_switch_expr(g, import, context, expected_type, node);6666 return_type = analyze_switch_expr(g, import, context, expected_type, node);
6607 break;6667 break;
6668 case NodeTypeVarLiteral:
6669 return_type = resolve_expr_const_val_as_type(g, node, g->builtin_types.entry_var, false);
6670 break;
6608 case NodeTypeSwitchProng:6671 case NodeTypeSwitchProng:
6609 case NodeTypeSwitchRange:6672 case NodeTypeSwitchRange:
6610 case NodeTypeDirective:6673 case NodeTypeDirective:
...@@ -6750,18 +6813,25 @@ static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, BlockContex...@@ -6750,18 +6813,25 @@ static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, BlockContex
6750 }6813 }
6751}6814}
67526815
6753static int fn_proto_inline_arg_count(AstNode *proto_node) {6816static void count_inline_and_var_args(AstNode *proto_node) {
6754 assert(proto_node->type == NodeTypeFnProto);6817 assert(proto_node->type == NodeTypeFnProto);
6755 int result = 0;6818
6819 int *inline_arg_count = &proto_node->data.fn_proto.inline_arg_count;
6820 int *inline_or_var_type_arg_count = &proto_node->data.fn_proto.inline_or_var_type_arg_count;
6821
6822 *inline_arg_count = 0;
6823 *inline_or_var_type_arg_count = 0;
6824
6756 for (int i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {6825 for (int i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
6757 AstNode *param_node = proto_node->data.fn_proto.params.at(i);6826 AstNode *param_node = proto_node->data.fn_proto.params.at(i);
6758 assert(param_node->type == NodeTypeParamDecl);6827 assert(param_node->type == NodeTypeParamDecl);
6759 result += param_node->data.param_decl.is_inline ? 1 : 0;6828 bool is_inline = param_node->data.param_decl.is_inline;
6829 *inline_arg_count += is_inline ? 1 : 0;
6830 *inline_or_var_type_arg_count += (is_inline ||
6831 param_node->data.param_decl.type->type == NodeTypeVarLiteral) ? 1 : 0;
6760 }6832 }
6761 return result;
6762}6833}
67636834
6764
6765static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) {6835static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node) {
6766 switch (node->type) {6836 switch (node->type) {
6767 case NodeTypeRoot:6837 case NodeTypeRoot:
...@@ -6804,7 +6874,7 @@ static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *conte...@@ -6804,7 +6874,7 @@ static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *conte
6804 add_node_error(g, node, buf_sprintf("missing function name"));6874 add_node_error(g, node, buf_sprintf("missing function name"));
6805 break;6875 break;
6806 }6876 }
6807 node->data.fn_proto.inline_arg_count = fn_proto_inline_arg_count(node);6877 count_inline_and_var_args(node);
68086878
6809 add_top_level_decl(g, import, context, node, fn_name);6879 add_top_level_decl(g, import, context, node, fn_name);
6810 break;6880 break;
...@@ -6861,6 +6931,7 @@ static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *conte...@@ -6861,6 +6931,7 @@ static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *conte
6861 case NodeTypeArrayType:6931 case NodeTypeArrayType:
6862 case NodeTypeErrorType:6932 case NodeTypeErrorType:
6863 case NodeTypeTypeLiteral:6933 case NodeTypeTypeLiteral:
6934 case NodeTypeVarLiteral:
6864 zig_unreachable();6935 zig_unreachable();
6865 }6936 }
6866}6937}
...@@ -7118,6 +7189,8 @@ Expr *get_resolved_expr(AstNode *node) {...@@ -7118,6 +7189,8 @@ Expr *get_resolved_expr(AstNode *node) {
7118 return &node->data.switch_expr.resolved_expr;7189 return &node->data.switch_expr.resolved_expr;
7119 case NodeTypeFnProto:7190 case NodeTypeFnProto:
7120 return &node->data.fn_proto.resolved_expr;7191 return &node->data.fn_proto.resolved_expr;
7192 case NodeTypeVarLiteral:
7193 return &node->data.var_literal.resolved_expr;
7121 case NodeTypeSwitchProng:7194 case NodeTypeSwitchProng:
7122 case NodeTypeSwitchRange:7195 case NodeTypeSwitchRange:
7123 case NodeTypeRoot:7196 case NodeTypeRoot:
...@@ -7192,6 +7265,7 @@ static TopLevelDecl *get_as_top_level_decl(AstNode *node) {...@@ -7192,6 +7265,7 @@ static TopLevelDecl *get_as_top_level_decl(AstNode *node) {
7192 case NodeTypeArrayType:7265 case NodeTypeArrayType:
7193 case NodeTypeErrorType:7266 case NodeTypeErrorType:
7194 case NodeTypeTypeLiteral:7267 case NodeTypeTypeLiteral:
7268 case NodeTypeVarLiteral:
7195 zig_unreachable();7269 zig_unreachable();
7196 }7270 }
7197 zig_unreachable();7271 zig_unreachable();
...@@ -7250,6 +7324,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {...@@ -7250,6 +7324,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
7250 case TypeTableEntryIdNullLit:7324 case TypeTableEntryIdNullLit:
7251 case TypeTableEntryIdNamespace:7325 case TypeTableEntryIdNamespace:
7252 case TypeTableEntryIdGenericFn:7326 case TypeTableEntryIdGenericFn:
7327 case TypeTableEntryIdVar:
7253 zig_unreachable();7328 zig_unreachable();
7254 case TypeTableEntryIdUnreachable:7329 case TypeTableEntryIdUnreachable:
7255 case TypeTableEntryIdVoid:7330 case TypeTableEntryIdVoid:
...@@ -7392,6 +7467,7 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val)...@@ -7392,6 +7467,7 @@ static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val)
7392 case TypeTableEntryIdGenericFn:7467 case TypeTableEntryIdGenericFn:
7393 case TypeTableEntryIdInvalid:7468 case TypeTableEntryIdInvalid:
7394 case TypeTableEntryIdUnreachable:7469 case TypeTableEntryIdUnreachable:
7470 case TypeTableEntryIdVar:
7395 zig_unreachable();7471 zig_unreachable();
7396 }7472 }
7397 zig_unreachable();7473 zig_unreachable();
...@@ -7402,9 +7478,12 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {...@@ -7402,9 +7478,12 @@ uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {
7402 result += hash_ptr(id->decl_node);7478 result += hash_ptr(id->decl_node);
7403 for (int i = 0; i < id->generic_param_count; i += 1) {7479 for (int i = 0; i < id->generic_param_count; i += 1) {
7404 GenericParamValue *generic_param = &id->generic_params[i];7480 GenericParamValue *generic_param = &id->generic_params[i];
7405 ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->const_val;7481 if (generic_param->node) {
7406 assert(const_val->ok);7482 ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->const_val;
7407 result += hash_const_val(generic_param->type, const_val);7483 assert(const_val->ok);
7484 result += hash_const_val(generic_param->type, const_val);
7485 }
7486 result += hash_ptr(generic_param->type);
7408 }7487 }
7409 return result;7488 return result;
7410}7489}
...@@ -7415,13 +7494,17 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {...@@ -7415,13 +7494,17 @@ bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
7415 for (int i = 0; i < a->generic_param_count; i += 1) {7494 for (int i = 0; i < a->generic_param_count; i += 1) {
7416 GenericParamValue *a_val = &a->generic_params[i];7495 GenericParamValue *a_val = &a->generic_params[i];
7417 GenericParamValue *b_val = &b->generic_params[i];7496 GenericParamValue *b_val = &b->generic_params[i];
7418 assert(a_val->type == b_val->type);7497 if (a_val->type != b_val->type) return false;
7419 ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->const_val;7498 if (a_val->node && b_val->node) {
7420 ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->const_val;7499 ConstExprValue *a_const_val = &get_resolved_expr(a_val->node)->const_val;
7421 assert(a_const_val->ok);7500 ConstExprValue *b_const_val = &get_resolved_expr(b_val->node)->const_val;
7422 assert(b_const_val->ok);7501 assert(a_const_val->ok);
7423 if (!const_values_equal(a_const_val, b_const_val, a_val->type)) {7502 assert(b_const_val->ok);
7424 return false;7503 if (!const_values_equal(a_const_val, b_const_val, a_val->type)) {
7504 return false;
7505 }
7506 } else {
7507 assert(!a_val->node && !b_val->node);
7425 }7508 }
7426 }7509 }
7427 return true;7510 return true;
...@@ -7457,6 +7540,7 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)...@@ -7457,6 +7540,7 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)
7457 case TypeTableEntryIdVoid:7540 case TypeTableEntryIdVoid:
7458 case TypeTableEntryIdNamespace:7541 case TypeTableEntryIdNamespace:
7459 case TypeTableEntryIdGenericFn:7542 case TypeTableEntryIdGenericFn:
7543 case TypeTableEntryIdVar:
7460 zig_unreachable();7544 zig_unreachable();
7461 case TypeTableEntryIdArray:7545 case TypeTableEntryIdArray:
7462 return type_of_first_thing_in_memory(type_entry->data.array.child_type);7546 return type_of_first_thing_in_memory(type_entry->data.array.child_type);
src/ast_render.cpp+5
...@@ -213,6 +213,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -213,6 +213,8 @@ static const char *node_type_str(NodeType node_type) {
213 return "ErrorType";213 return "ErrorType";
214 case NodeTypeTypeLiteral:214 case NodeTypeTypeLiteral:
215 return "TypeLiteral";215 return "TypeLiteral";
216 case NodeTypeVarLiteral:
217 return "VarLiteral";
216 }218 }
217 zig_unreachable();219 zig_unreachable();
218}220}
...@@ -672,6 +674,9 @@ static void render_node(AstRender *ar, AstNode *node) {...@@ -672,6 +674,9 @@ static void render_node(AstRender *ar, AstNode *node) {
672 case NodeTypeTypeLiteral:674 case NodeTypeTypeLiteral:
673 fprintf(ar->f, "type");675 fprintf(ar->f, "type");
674 break;676 break;
677 case NodeTypeVarLiteral:
678 fprintf(ar->f, "var");
679 break;
675 }680 }
676}681}
677682
src/codegen.cpp+9
...@@ -3597,6 +3597,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {...@@ -3597,6 +3597,7 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
3597 case NodeTypeErrorType:3597 case NodeTypeErrorType:
3598 case NodeTypeTypeLiteral:3598 case NodeTypeTypeLiteral:
3599 case NodeTypeArrayType:3599 case NodeTypeArrayType:
3600 case NodeTypeVarLiteral:
3600 // caught by constant expression eval codegen3601 // caught by constant expression eval codegen
3601 zig_unreachable();3602 zig_unreachable();
3602 case NodeTypeRoot:3603 case NodeTypeRoot:
...@@ -3815,6 +3816,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE...@@ -3815,6 +3816,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
3815 case TypeTableEntryIdVoid:3816 case TypeTableEntryIdVoid:
3816 case TypeTableEntryIdNamespace:3817 case TypeTableEntryIdNamespace:
3817 case TypeTableEntryIdGenericFn:3818 case TypeTableEntryIdGenericFn:
3819 case TypeTableEntryIdVar:
3818 zig_unreachable();3820 zig_unreachable();
38193821
3820 }3822 }
...@@ -4362,6 +4364,12 @@ static void define_builtin_types(CodeGen *g) {...@@ -4362,6 +4364,12 @@ static void define_builtin_types(CodeGen *g) {
4362 entry->deep_const = true;4364 entry->deep_const = true;
4363 g->builtin_types.entry_null = entry;4365 g->builtin_types.entry_null = entry;
4364 }4366 }
4367 {
4368 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVar);
4369 buf_init_from_str(&entry->name, "(var)");
4370 entry->deep_const = true;
4371 g->builtin_types.entry_var = entry;
4372 }
43654373
4366 for (int int_size_i = 0; int_size_i < array_length(int_sizes_in_bits); int_size_i += 1) {4374 for (int int_size_i = 0; int_size_i < array_length(int_sizes_in_bits); int_size_i += 1) {
4367 int size_in_bits = int_sizes_in_bits[int_size_i];4375 int size_in_bits = int_sizes_in_bits[int_size_i];
...@@ -5129,6 +5137,7 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {...@@ -5129,6 +5137,7 @@ static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
5129 case TypeTableEntryIdNumLitInt:5137 case TypeTableEntryIdNumLitInt:
5130 case TypeTableEntryIdUndefLit:5138 case TypeTableEntryIdUndefLit:
5131 case TypeTableEntryIdNullLit:5139 case TypeTableEntryIdNullLit:
5140 case TypeTableEntryIdVar:
5132 zig_unreachable();5141 zig_unreachable();
5133 }5142 }
5134}5143}
src/eval.cpp+3
...@@ -55,9 +55,11 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *ty...@@ -55,9 +55,11 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *ty
55 zig_panic("TODO");55 zig_panic("TODO");
56 case TypeTableEntryIdNamespace:56 case TypeTableEntryIdNamespace:
57 zig_panic("TODO");57 zig_panic("TODO");
58 zig_panic("TODO");
58 case TypeTableEntryIdGenericFn:59 case TypeTableEntryIdGenericFn:
59 case TypeTableEntryIdInvalid:60 case TypeTableEntryIdInvalid:
60 case TypeTableEntryIdUnreachable:61 case TypeTableEntryIdUnreachable:
62 case TypeTableEntryIdVar:
61 zig_unreachable();63 zig_unreachable();
62 }64 }
63 zig_unreachable();65 zig_unreachable();
...@@ -1301,6 +1303,7 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {...@@ -1301,6 +1303,7 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
1301 case NodeTypeArrayType:1303 case NodeTypeArrayType:
1302 case NodeTypeErrorType:1304 case NodeTypeErrorType:
1303 case NodeTypeTypeLiteral:1305 case NodeTypeTypeLiteral:
1306 case NodeTypeVarLiteral:
1304 zig_panic("TODO");1307 zig_panic("TODO");
1305 case NodeTypeRoot:1308 case NodeTypeRoot:
1306 case NodeTypeFnProto:1309 case NodeTypeFnProto:
src/parser.cpp+27-7
...@@ -266,6 +266,20 @@ static void ast_parse_directives(ParseContext *pc, int *token_index,...@@ -266,6 +266,20 @@ static void ast_parse_directives(ParseContext *pc, int *token_index,
266 zig_unreachable();266 zig_unreachable();
267}267}
268268
269/*
270TypeExpr = PrefixOpExpression | "var"
271*/
272static AstNode *ast_parse_type_expr(ParseContext *pc, int *token_index, bool mandatory) {
273 Token *token = &pc->tokens->at(*token_index);
274 if (token->id == TokenIdKeywordVar) {
275 AstNode *node = ast_create_node(pc, NodeTypeVarLiteral, token);
276 *token_index += 1;
277 return node;
278 } else {
279 return ast_parse_prefix_op_expr(pc, token_index, mandatory);
280 }
281}
282
269/*283/*
270ParamDecl = option("noalias" | "inline") option("Symbol" ":") TypeExpr | "..."284ParamDecl = option("noalias" | "inline") option("Symbol" ":") TypeExpr | "..."
271*/285*/
...@@ -299,7 +313,7 @@ static AstNode *ast_parse_param_decl(ParseContext *pc, int *token_index) {...@@ -299,7 +313,7 @@ static AstNode *ast_parse_param_decl(ParseContext *pc, int *token_index) {
299 }313 }
300 }314 }
301315
302 node->data.param_decl.type = ast_parse_prefix_op_expr(pc, token_index, true);316 node->data.param_decl.type = ast_parse_type_expr(pc, token_index, true);
303317
304 normalize_parent_ptrs(node);318 normalize_parent_ptrs(node);
305 return node;319 return node;
...@@ -414,7 +428,7 @@ static AstNode *ast_parse_array_type_expr(ParseContext *pc, int *token_index, bo...@@ -414,7 +428,7 @@ static AstNode *ast_parse_array_type_expr(ParseContext *pc, int *token_index, bo
414 node->data.array_type.is_const = true;428 node->data.array_type.is_const = true;
415 }429 }
416430
417 node->data.array_type.child_type = ast_parse_prefix_op_expr(pc, token_index, true);431 node->data.array_type.child_type = ast_parse_type_expr(pc, token_index, true);
418432
419 normalize_parent_ptrs(node);433 normalize_parent_ptrs(node);
420 return node;434 return node;
...@@ -460,7 +474,7 @@ static void ast_parse_asm_output_item(ParseContext *pc, int *token_index, AstNod...@@ -460,7 +474,7 @@ static void ast_parse_asm_output_item(ParseContext *pc, int *token_index, AstNod
460 if (token->id == TokenIdSymbol) {474 if (token->id == TokenIdSymbol) {
461 asm_output->variable_name = token_buf(token);475 asm_output->variable_name = token_buf(token);
462 } else if (token->id == TokenIdArrow) {476 } else if (token->id == TokenIdArrow) {
463 asm_output->return_type = ast_parse_prefix_op_expr(pc, token_index, true);477 asm_output->return_type = ast_parse_type_expr(pc, token_index, true);
464 } else {478 } else {
465 ast_invalid_token_error(pc, token);479 ast_invalid_token_error(pc, token);
466 }480 }
...@@ -1354,7 +1368,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda...@@ -1354,7 +1368,7 @@ static AstNode *ast_parse_if_expr(ParseContext *pc, int *token_index, bool manda
1354 node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);1368 node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);
1355 } else if (eq_or_colon->id == TokenIdColon) {1369 } else if (eq_or_colon->id == TokenIdColon) {
1356 *token_index += 1;1370 *token_index += 1;
1357 node->data.if_var_expr.var_decl.type = ast_parse_prefix_op_expr(pc, token_index, true);1371 node->data.if_var_expr.var_decl.type = ast_parse_type_expr(pc, token_index, true);
13581372
1359 ast_eat_token(pc, token_index, TokenIdMaybeAssign);1373 ast_eat_token(pc, token_index, TokenIdMaybeAssign);
1360 node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);1374 node->data.if_var_expr.var_decl.expr = ast_parse_expression(pc, token_index, true);
...@@ -1504,7 +1518,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token...@@ -1504,7 +1518,7 @@ static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token
1504 normalize_parent_ptrs(node);1518 normalize_parent_ptrs(node);
1505 return node;1519 return node;
1506 } else if (eq_or_colon->id == TokenIdColon) {1520 } else if (eq_or_colon->id == TokenIdColon) {
1507 node->data.variable_declaration.type = ast_parse_prefix_op_expr(pc, token_index, true);1521 node->data.variable_declaration.type = ast_parse_type_expr(pc, token_index, true);
1508 Token *eq_token = &pc->tokens->at(*token_index);1522 Token *eq_token = &pc->tokens->at(*token_index);
1509 if (eq_token->id == TokenIdEq) {1523 if (eq_token->id == TokenIdEq) {
1510 *token_index += 1;1524 *token_index += 1;
...@@ -2038,7 +2052,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand...@@ -2038,7 +2052,7 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand
2038 Token *next_token = &pc->tokens->at(*token_index);2052 Token *next_token = &pc->tokens->at(*token_index);
2039 if (next_token->id == TokenIdArrow) {2053 if (next_token->id == TokenIdArrow) {
2040 *token_index += 1;2054 *token_index += 1;
2041 node->data.fn_proto.return_type = ast_parse_prefix_op_expr(pc, token_index, false);2055 node->data.fn_proto.return_type = ast_parse_type_expr(pc, token_index, false);
2042 } else {2056 } else {
2043 node->data.fn_proto.return_type = ast_create_void_type_node(pc, next_token);2057 node->data.fn_proto.return_type = ast_create_void_type_node(pc, next_token);
2044 }2058 }
...@@ -2315,7 +2329,7 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, int *token_index,...@@ -2315,7 +2329,7 @@ static AstNode *ast_parse_type_decl(ParseContext *pc, int *token_index,
23152329
2316 AstNode *node = ast_create_node(pc, NodeTypeTypeDecl, first_token);2330 AstNode *node = ast_create_node(pc, NodeTypeTypeDecl, first_token);
2317 node->data.type_decl.symbol = token_buf(name_tok);2331 node->data.type_decl.symbol = token_buf(name_tok);
2318 node->data.type_decl.child_type = ast_parse_prefix_op_expr(pc, token_index, true);2332 node->data.type_decl.child_type = ast_parse_type_expr(pc, token_index, true);
23192333
2320 ast_eat_token(pc, token_index, TokenIdSemicolon);2334 ast_eat_token(pc, token_index, TokenIdSemicolon);
23212335
...@@ -2628,6 +2642,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -2628,6 +2642,9 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
2628 case NodeTypeTypeLiteral:2642 case NodeTypeTypeLiteral:
2629 // none2643 // none
2630 break;2644 break;
2645 case NodeTypeVarLiteral:
2646 // none
2647 break;
2631 }2648 }
2632}2649}
26332650
...@@ -2907,6 +2924,9 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,...@@ -2907,6 +2924,9 @@ AstNode *ast_clone_subtree_special(AstNode *old_node, uint32_t *next_node_index,
2907 case NodeTypeTypeLiteral:2924 case NodeTypeTypeLiteral:
2908 // none2925 // none
2909 break;2926 break;
2927 case NodeTypeVarLiteral:
2928 // none
2929 break;
2910 }2930 }
29112931
2912 return new_node;2932 return new_node;
std/debug.zig+1-5
...@@ -73,11 +73,7 @@ fn findCompileUnitOffset(st: &ElfStackTrace, target_address: usize) -> %u64 {...@@ -73,11 +73,7 @@ fn findCompileUnitOffset(st: &ElfStackTrace, target_address: usize) -> %u64 {
7373
74 while (true) {74 while (true) {
75 const tag_id = %return st.self_exe_stream.readByte();75 const tag_id = %return st.self_exe_stream.readByte();
76 if (tag_id == DW.TAG_compile_unit) {76 // TODO iterate until we find the relevant compile unit
77
78 } else {
79
80 }
81 }77 }
82}78}
8379
test/cases/var_params.zig created+32
...@@ -0,0 +1,32 @@
1const assert = @import("std").debug.assert;
2
3#attribute("test")
4fn varParams() {
5 assert(max_i32(12, 34) == 34);
6 assert(max_f64(1.2, 3.4) == 3.4);
7
8 assert(max_i32_noeval(12, 34) == 34);
9 assert(max_f64_noeval(1.2, 3.4) == 3.4);
10}
11
12fn max(a: var, b: var) -> @typeOf(a) {
13 if (a > b) a else b
14}
15
16fn max_i32(a: i32, b: i32) -> i32 {
17 max(a, b)
18}
19
20fn max_f64(a: f64, b: f64) -> f64 {
21 max(a, b)
22}
23
24#static_eval_enable(false)
25fn max_i32_noeval(a: i32, b: i32) -> i32 {
26 max(a, b)
27}
28
29#static_eval_enable(false)
30fn max_f64_noeval(a: f64, b: f64) -> f64 {
31 max(a, b)
32}
test/self_hosted.zig+2
...@@ -3,11 +3,13 @@ const assert = std.debug.assert;...@@ -3,11 +3,13 @@ const assert = std.debug.assert;
3const str = std.str;3const str = std.str;
4const cstr = std.cstr;4const cstr = std.cstr;
5const other = @import("other.zig");5const other = @import("other.zig");
6// TODO '_' identifier for unused variable bindings
6const test_return_type_type = @import("cases/return_type_type.zig");7const test_return_type_type = @import("cases/return_type_type.zig");
7const test_zeroes = @import("cases/zeroes.zig");8const test_zeroes = @import("cases/zeroes.zig");
8const test_sizeof_and_typeof = @import("cases/sizeof_and_typeof.zig");9const test_sizeof_and_typeof = @import("cases/sizeof_and_typeof.zig");
9const test_maybe_return = @import("cases/maybe_return.zig");10const test_maybe_return = @import("cases/maybe_return.zig");
10const test_max_value_type = @import("cases/max_value_type.zig");11const test_max_value_type = @import("cases/max_value_type.zig");
12const test_var_params = @import("cases/var_params.zig");
1113
12// normal comment14// normal comment
13/// this is a documentation comment15/// this is a documentation comment