authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-06 11:38:12-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-06 12:58:54-07:00
log67152f729431d58a9cd140498d50c1e9d795c34b
tree7997511873fe650e71f5efb527103688f62271b3
parente144ddab249af3737f04267c7f1f0f0e093ed314

support simple generic functions


9 files changed, 428 insertions(+), 418 deletions(-)

doc/langref.md+1-1
......@@ -25,7 +25,7 @@ UseDecl = "use" Expression ";"
2525
2626ExternDecl = "extern" (FnProto | VariableDeclaration) ";"
2727
28FnProto = "fn" option("Symbol") ParamDeclList option("->" TypeExpr)
28FnProto = "fn" option("Symbol") option(ParamDeclList) ParamDeclList option("->" TypeExpr)
2929
3030Directive = "#" "Symbol" "(" Expression ")"
3131
src/all_types.hpp+29-1
......@@ -193,8 +193,10 @@ struct AstNodeRoot {
193193struct AstNodeFnProto {
194194 TopLevelDecl top_level_decl;
195195 Buf name;
196 ZigList<AstNode *> generic_params;
196197 ZigList<AstNode *> params;
197198 AstNode *return_type;
199 bool generic_params_is_var_args;
198200 bool is_var_args;
199201 bool is_extern;
200202 bool is_inline;
......@@ -206,6 +208,7 @@ struct AstNodeFnProto {
206208 FnTableEntry *fn_table_entry;
207209 bool skip;
208210 Expr resolved_expr;
211 TypeTableEntry *generic_fn_type;
209212};
210213
211214struct AstNodeFnDef {
......@@ -797,6 +800,21 @@ struct FnTypeParamInfo {
797800 TypeTableEntry *type;
798801};
799802
803struct GenericParamValue {
804 TypeTableEntry *type;
805 AstNode *node;
806};
807
808struct GenericFnTypeId {
809 AstNode *decl_node; // the generic fn or container decl node
810 GenericParamValue *generic_params;
811 int generic_param_count;
812};
813
814uint32_t generic_fn_type_id_hash(GenericFnTypeId *id);
815bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b);
816
817
800818static const int fn_type_id_prealloc_param_info_count = 4;
801819struct FnTypeId {
802820 TypeTableEntry *return_type;
......@@ -812,7 +830,6 @@ struct FnTypeId {
812830uint32_t fn_type_id_hash(FnTypeId*);
813831bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
814832
815
816833struct TypeTableEntryPointer {
817834 TypeTableEntry *child_type;
818835 bool is_const;
......@@ -899,6 +916,10 @@ struct TypeTableEntryFn {
899916 LLVMCallConv calling_convention;
900917};
901918
919struct TypeTableEntryGenericFn {
920 AstNode *decl_node;
921};
922
902923struct TypeTableEntryTypeDecl {
903924 TypeTableEntry *child_type;
904925 TypeTableEntry *canonical_type;
......@@ -925,6 +946,7 @@ enum TypeTableEntryId {
925946 TypeTableEntryIdFn,
926947 TypeTableEntryIdTypeDecl,
927948 TypeTableEntryIdNamespace,
949 TypeTableEntryIdGenericFn,
928950};
929951
930952struct TypeTableEntry {
......@@ -947,6 +969,7 @@ struct TypeTableEntry {
947969 TypeTableEntryEnum enumeration;
948970 TypeTableEntryFn fn;
949971 TypeTableEntryTypeDecl type_decl;
972 TypeTableEntryGenericFn generic_fn;
950973 } data;
951974
952975 // use these fields to make sure we don't duplicate type table entries for the same type
......@@ -992,6 +1015,7 @@ struct FnTableEntry {
9921015 bool internal_linkage;
9931016 bool is_extern;
9941017 bool is_test;
1018 BlockContext *parent_block_context;
9951019
9961020 ZigList<AstNode *> cast_alloca_list;
9971021 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
......@@ -1047,6 +1071,7 @@ struct CodeGen {
10471071 HashMap<Buf *, TypeTableEntry *, buf_hash, buf_eql_buf> primitive_type_table;
10481072 HashMap<FnTypeId *, TypeTableEntry *, fn_type_id_hash, fn_type_id_eql> fn_type_table;
10491073 HashMap<Buf *, ErrorTableEntry *, buf_hash, buf_eql_buf> error_table;
1074 HashMap<GenericFnTypeId *, AstNode *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
10501075
10511076 ZigList<ImportTableEntry *> import_queue;
10521077 int import_queue_index;
......@@ -1172,7 +1197,10 @@ struct VariableTableEntry {
11721197 LLVMValueRef value_ref;
11731198 bool is_const;
11741199 bool is_ptr; // if true, value_ref is a pointer
1200 // which node is the declaration of the variable
11751201 AstNode *decl_node;
1202 // which node contains the ConstExprValue for this variable's value
1203 AstNode *val_node;
11761204 LLVMZigDILocalVariable *di_loc_var;
11771205 int src_arg_index;
11781206 int gen_arg_index;
src/analyze.cpp+250-31
......@@ -41,6 +41,7 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
4141 AstNodeVariableDeclaration *variable_declaration,
4242 bool expr_is_maybe, AstNode *decl_node);
4343static void scan_decls(CodeGen *g, ImportTableEntry *import, BlockContext *context, AstNode *node);
44static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry);
4445
4546static AstNode *first_executing_node(AstNode *node) {
4647 switch (node->type) {
......@@ -192,6 +193,7 @@ static bool type_is_complete(TypeTableEntry *type_entry) {
192193 case TypeTableEntryIdFn:
193194 case TypeTableEntryIdTypeDecl:
194195 case TypeTableEntryIdNamespace:
196 case TypeTableEntryIdGenericFn:
195197 return true;
196198 }
197199 zig_unreachable();
......@@ -201,6 +203,14 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
201203 return get_int_type(g, false, bits_needed_for_unsigned(x));
202204}
203205
206static TypeTableEntry *get_generic_fn_type(CodeGen *g, AstNode *decl_node) {
207 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdGenericFn);
208 buf_init_from_str(&entry->name, "(generic function)");
209 entry->zero_bits = true;
210 entry->data.generic_fn.decl_node = decl_node;
211 return entry;
212}
213
204214TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const) {
205215 assert(child_type->id != TypeTableEntryIdInvalid);
206216 TypeTableEntry **parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
......@@ -776,7 +786,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
776786 }
777787
778788 fn_type_id.is_var_args = fn_proto->is_var_args;
779 fn_type_id.return_type = analyze_type_expr(g, import, import->block_context, node->data.fn_proto.return_type);
789 fn_type_id.return_type = analyze_type_expr(g, import, context, node->data.fn_proto.return_type);
780790
781791 if (fn_type_id.return_type->id == TypeTableEntryIdInvalid) {
782792 fn_proto->skip = true;
......@@ -785,7 +795,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
785795 for (int i = 0; i < fn_type_id.param_count; i += 1) {
786796 AstNode *child = node->data.fn_proto.params.at(i);
787797 assert(child->type == NodeTypeParamDecl);
788 TypeTableEntry *type_entry = analyze_type_expr(g, import, import->block_context,
798 TypeTableEntry *type_entry = analyze_type_expr(g, import, context,
789799 child->data.param_decl.type);
790800 switch (type_entry->id) {
791801 case TypeTableEntryIdInvalid:
......@@ -797,6 +807,7 @@ static TypeTableEntry *analyze_fn_proto_type(CodeGen *g, ImportTableEntry *impor
797807 case TypeTableEntryIdMetaType:
798808 case TypeTableEntryIdUnreachable:
799809 case TypeTableEntryIdNamespace:
810 case TypeTableEntryIdGenericFn:
800811 fn_proto->skip = true;
801812 add_node_error(g, child->data.param_decl.type,
802813 buf_sprintf("parameter of type '%s' not allowed'", buf_ptr(&type_entry->name)));
......@@ -880,7 +891,7 @@ static bool resolve_const_expr_bool(CodeGen *g, ImportTableEntry *import, BlockC
880891}
881892
882893static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_table_entry,
883 ImportTableEntry *import)
894 ImportTableEntry *import, BlockContext *containing_context)
884895{
885896 assert(node->type == NodeTypeFnProto);
886897 AstNodeFnProto *fn_proto = &node->data.fn_proto;
......@@ -946,7 +957,7 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
946957
947958
948959
949 TypeTableEntry *fn_type = analyze_fn_proto_type(g, import, import->block_context, nullptr, node,
960 TypeTableEntry *fn_type = analyze_fn_proto_type(g, import, containing_context, nullptr, node,
950961 is_naked, is_cold);
951962
952963 fn_table_entry->type_entry = fn_type;
......@@ -963,6 +974,8 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
963974 } else {
964975 symbol_name = buf_sprintf("_%s", buf_ptr(&fn_table_entry->symbol_name));
965976 }
977 // TODO mangle the name if it's a generic instance
978
966979 fn_table_entry->fn_value = LLVMAddFunction(g->module, buf_ptr(symbol_name),
967980 fn_type->data.fn.raw_type_ref);
968981
......@@ -992,12 +1005,12 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
9921005 unsigned flags = 0;
9931006 bool is_optimized = g->is_release_build;
9941007 LLVMZigDISubprogram *subprogram = LLVMZigCreateFunction(g->dbuilder,
995 import->block_context->di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
1008 containing_context->di_scope, buf_ptr(&fn_table_entry->symbol_name), "",
9961009 import->di_file, line_number,
9971010 fn_type->di_type, fn_table_entry->internal_linkage,
9981011 is_definition, scope_line, flags, is_optimized, nullptr);
9991012
1000 BlockContext *context = new_block_context(fn_table_entry->fn_def_node, import->block_context);
1013 BlockContext *context = new_block_context(fn_table_entry->fn_def_node, containing_context);
10011014 fn_table_entry->fn_def_node->data.fn_def.block_context = context;
10021015 context->di_scope = LLVMZigSubprogramToScope(subprogram);
10031016 }
......@@ -1321,17 +1334,35 @@ static void get_fully_qualified_decl_name(Buf *buf, AstNode *decl_node, uint8_t
13211334 }
13221335}
13231336
1324static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, AstNode *proto_node) {
1337static void preview_generic_fn_proto(CodeGen *g, ImportTableEntry *import, AstNode *node) {
1338 assert(node->type == NodeTypeFnProto);
1339
1340 if (node->data.fn_proto.generic_params_is_var_args) {
1341 add_node_error(g, node, buf_sprintf("generic parameters cannot be var args"));
1342 node->data.fn_proto.skip = true;
1343 node->data.fn_proto.generic_fn_type = g->builtin_types.entry_invalid;
1344 return;
1345 }
1346
1347 node->data.fn_proto.generic_fn_type = get_generic_fn_type(g, node);
1348}
1349
1350static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstNode *proto_node,
1351 BlockContext *containing_context)
1352{
13251353 if (proto_node->data.fn_proto.skip) {
13261354 return;
13271355 }
13281356
1357 bool is_generic_instance = (proto_node->data.fn_proto.generic_params.length > 0);
1358
13291359 AstNode *parent_decl = proto_node->data.fn_proto.top_level_decl.parent_decl;
1360 Buf *proto_name = &proto_node->data.fn_proto.name;
13301361
13311362 AstNode *fn_def_node = proto_node->data.fn_proto.fn_def_node;
13321363 bool is_extern = proto_node->data.fn_proto.is_extern;
13331364
1334 Buf *proto_name = &proto_node->data.fn_proto.name;
1365 assert(!is_extern || !is_generic_instance);
13351366
13361367 if (!is_extern && proto_node->data.fn_proto.is_var_args) {
13371368 add_node_error(g, proto_node,
......@@ -1352,13 +1383,24 @@ static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, AstNode *prot
13521383 g->fn_defs.append(fn_table_entry);
13531384 }
13541385
1355 bool is_main_fn = !parent_decl && (import == g->root_import) && buf_eql_str(proto_name, "main");
1386 bool is_main_fn = !is_generic_instance &&
1387 !parent_decl && (import == g->root_import) &&
1388 buf_eql_str(proto_name, "main");
13561389 if (is_main_fn) {
13571390 g->main_fn = fn_table_entry;
13581391 }
13591392
13601393 proto_node->data.fn_proto.fn_table_entry = fn_table_entry;
1361 resolve_function_proto(g, proto_node, fn_table_entry, import);
1394 resolve_function_proto(g, proto_node, fn_table_entry, import, containing_context);
1395}
1396
1397static void preview_fn_proto(CodeGen *g, ImportTableEntry *import, AstNode *proto_node) {
1398 if (proto_node->data.fn_proto.generic_params.length > 0) {
1399 return preview_generic_fn_proto(g, import, proto_node);
1400 } else {
1401 return preview_fn_proto_instance(g, import, proto_node, import->block_context);
1402 }
1403
13621404}
13631405
13641406static void preview_error_value_decl(CodeGen *g, AstNode *node) {
......@@ -1539,6 +1581,7 @@ static bool type_has_codegen_value(TypeTableEntry *type_entry) {
15391581 case TypeTableEntryIdNumLitInt:
15401582 case TypeTableEntryIdUndefLit:
15411583 case TypeTableEntryIdNamespace:
1584 case TypeTableEntryIdGenericFn:
15421585 return false;
15431586
15441587 case TypeTableEntryIdBool:
......@@ -2433,6 +2476,15 @@ static TypeTableEntry *resolve_expr_const_val_as_fn(CodeGen *g, AstNode *node, F
24332476 return fn->type_entry;
24342477}
24352478
2479static TypeTableEntry *resolve_expr_const_val_as_generic_fn(CodeGen *g, AstNode *node,
2480 TypeTableEntry *type_entry)
2481{
2482 Expr *expr = get_resolved_expr(node);
2483 expr->const_val.ok = true;
2484 expr->const_val.data.x_type = type_entry;
2485 return type_entry;
2486}
2487
24362488static TypeTableEntry *resolve_expr_const_val_as_err(CodeGen *g, AstNode *node, ErrorTableEntry *err) {
24372489 Expr *expr = get_resolved_expr(node);
24382490 expr->const_val.ok = true;
......@@ -2570,14 +2622,10 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
25702622
25712623static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var) {
25722624 get_resolved_expr(source_node)->variable = var;
2573 if (var->is_const) {
2574 AstNode *decl_node = var->decl_node;
2575 if (decl_node->type == NodeTypeVariableDeclaration) {
2576 AstNode *expr_node = decl_node->data.variable_declaration.expr;
2577 ConstExprValue *other_const_val = &get_resolved_expr(expr_node)->const_val;
2578 if (other_const_val->ok) {
2579 return resolve_expr_const_val_as_other_expr(g, source_node, expr_node);
2580 }
2625 if (var->is_const && var->val_node) {
2626 ConstExprValue *other_const_val = &get_resolved_expr(var->val_node)->const_val;
2627 if (other_const_val->ok) {
2628 return resolve_expr_const_val_as_other_expr(g, source_node, var->val_node);
25812629 }
25822630 }
25832631 return var->type;
......@@ -2596,9 +2644,15 @@ static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNod
25962644 VariableTableEntry *var = decl_node->data.variable_declaration.variable;
25972645 return analyze_var_ref(g, source_node, var);
25982646 } else if (decl_node->type == NodeTypeFnProto) {
2599 FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
2600 assert(fn_entry->type_entry);
2601 return resolve_expr_const_val_as_fn(g, source_node, fn_entry);
2647 if (decl_node->data.fn_proto.generic_params.length > 0) {
2648 TypeTableEntry *type_entry = decl_node->data.fn_proto.generic_fn_type;
2649 assert(type_entry);
2650 return resolve_expr_const_val_as_generic_fn(g, source_node, type_entry);
2651 } else {
2652 FnTableEntry *fn_entry = decl_node->data.fn_proto.fn_table_entry;
2653 assert(fn_entry->type_entry);
2654 return resolve_expr_const_val_as_fn(g, source_node, fn_entry);
2655 }
26022656 } else if (decl_node->type == NodeTypeStructDecl) {
26032657 return resolve_expr_const_val_as_type(g, source_node, decl_node->data.struct_decl.type_entry);
26042658 } else if (decl_node->type == NodeTypeTypeDecl) {
......@@ -3113,7 +3167,7 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
31133167
31143168// Set name to nullptr to make the variable anonymous (not visible to programmer).
31153169static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, ImportTableEntry *import,
3116 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const)
3170 BlockContext *context, Buf *name, TypeTableEntry *type_entry, bool is_const, AstNode *val_node)
31173171{
31183172 VariableTableEntry *variable_entry = allocate<VariableTableEntry>(1);
31193173 variable_entry->type = type_entry;
......@@ -3160,6 +3214,8 @@ static VariableTableEntry *add_local_var(CodeGen *g, AstNode *source_node, Impor
31603214 variable_entry->is_const = is_const;
31613215 variable_entry->is_ptr = true;
31623216 variable_entry->decl_node = source_node;
3217 variable_entry->val_node = val_node;
3218
31633219
31643220 return variable_entry;
31653221}
......@@ -3182,7 +3238,7 @@ static TypeTableEntry *analyze_unwrap_error_expr(CodeGen *g, ImportTableEntry *i
31823238 var_node->block_context = child_context;
31833239 Buf *var_name = &var_node->data.symbol_expr.symbol;
31843240 node->data.unwrap_err_expr.var = add_local_var(g, var_node, import, child_context, var_name,
3185 g->builtin_types.entry_pure_error, true);
3241 g->builtin_types.entry_pure_error, true, nullptr);
31863242 } else {
31873243 child_context = parent_context;
31883244 }
......@@ -3260,7 +3316,8 @@ static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTa
32603316 assert(type != nullptr); // should have been caught by the parser
32613317
32623318 VariableTableEntry *var = add_local_var(g, source_node, import, context,
3263 &variable_declaration->symbol, type, is_const);
3319 &variable_declaration->symbol, type, is_const,
3320 expr_is_maybe ? nullptr : variable_declaration->expr);
32643321
32653322 variable_declaration->variable = var;
32663323
......@@ -3453,17 +3510,17 @@ static TypeTableEntry *analyze_for_expr(CodeGen *g, ImportTableEntry *import, Bl
34533510 elem_var_node->block_context = child_context;
34543511 Buf *elem_var_name = &elem_var_node->data.symbol_expr.symbol;
34553512 node->data.for_expr.elem_var = add_local_var(g, elem_var_node, import, child_context, elem_var_name,
3456 child_type, true);
3513 child_type, true, nullptr);
34573514
34583515 AstNode *index_var_node = node->data.for_expr.index_node;
34593516 if (index_var_node) {
34603517 Buf *index_var_name = &index_var_node->data.symbol_expr.symbol;
34613518 index_var_node->block_context = child_context;
34623519 node->data.for_expr.index_var = add_local_var(g, index_var_node, import, child_context, index_var_name,
3463 g->builtin_types.entry_isize, true);
3520 g->builtin_types.entry_isize, true, nullptr);
34643521 } else {
34653522 node->data.for_expr.index_var = add_local_var(g, node, import, child_context, nullptr,
3466 g->builtin_types.entry_isize, true);
3523 g->builtin_types.entry_isize, true, nullptr);
34673524 }
34683525
34693526 AstNode *for_body_node = node->data.for_expr.body;
......@@ -4330,6 +4387,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
43304387 case TypeTableEntryIdNumLitInt:
43314388 case TypeTableEntryIdUndefLit:
43324389 case TypeTableEntryIdNamespace:
4390 case TypeTableEntryIdGenericFn:
43334391 add_node_error(g, expr_node,
43344392 buf_sprintf("type '%s' not eligible for @typeof", buf_ptr(&type_entry->name)));
43354393 return g->builtin_types.entry_invalid;
......@@ -4541,6 +4599,92 @@ static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import,
45414599 return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);
45424600}
45434601
4602static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
4603 TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *generic_fn_type)
4604{
4605 assert(node->type == NodeTypeFnCallExpr);
4606 assert(generic_fn_type->id == TypeTableEntryIdGenericFn);
4607
4608 AstNode *decl_node = generic_fn_type->data.generic_fn.decl_node;
4609 assert(decl_node->type == NodeTypeFnProto);
4610
4611 int expected_param_count = decl_node->data.fn_proto.generic_params.length;
4612 int actual_param_count = node->data.fn_call_expr.params.length;
4613
4614 if (actual_param_count != expected_param_count) {
4615 add_node_error(g, first_executing_node(node),
4616 buf_sprintf("expected %d arguments, got %d", expected_param_count, actual_param_count));
4617 return g->builtin_types.entry_invalid;
4618 }
4619
4620 GenericFnTypeId *generic_fn_type_id = allocate<GenericFnTypeId>(1);
4621 generic_fn_type_id->decl_node = decl_node;
4622 generic_fn_type_id->generic_param_count = actual_param_count;
4623 generic_fn_type_id->generic_params = allocate<GenericParamValue>(actual_param_count);
4624
4625 BlockContext *child_context = import->block_context;
4626 for (int i = 0; i < actual_param_count; i += 1) {
4627 AstNode *generic_param_decl_node = decl_node->data.fn_proto.generic_params.at(i);
4628 assert(generic_param_decl_node->type == NodeTypeParamDecl);
4629
4630 AstNode **generic_param_type_node = &generic_param_decl_node->data.param_decl.type;
4631
4632 TypeTableEntry *expected_param_type = analyze_expression(g, decl_node->owner,
4633 decl_node->owner->block_context, nullptr, *generic_param_type_node);
4634 if (expected_param_type->id == TypeTableEntryIdInvalid) {
4635 return expected_param_type;
4636 }
4637 AstNode **param_node = &node->data.fn_call_expr.params.at(i);
4638
4639 TypeTableEntry *param_type = analyze_expression(g, import, child_context, expected_param_type,
4640 *param_node);
4641 if (param_type->id == TypeTableEntryIdInvalid) {
4642 return param_type;
4643 }
4644
4645 // set child_context so that the previous param is in scope
4646 child_context = new_block_context(generic_param_decl_node, child_context);
4647
4648 ConstExprValue *const_val = &get_resolved_expr(*param_node)->const_val;
4649 if (const_val->ok) {
4650 add_local_var(g, generic_param_decl_node, decl_node->owner, child_context,
4651 &generic_param_decl_node->data.param_decl.name, param_type, true, *param_node);
4652 } else {
4653 add_node_error(g, *param_node, buf_sprintf("unable to resolve constant expression"));
4654
4655 add_local_var(g, generic_param_decl_node, decl_node->owner, child_context,
4656 &generic_param_decl_node->data.param_decl.name, g->builtin_types.entry_invalid,
4657 true, nullptr);
4658
4659 return g->builtin_types.entry_invalid;
4660 }
4661
4662 GenericParamValue *generic_param_value = &generic_fn_type_id->generic_params[i];
4663 generic_param_value->type = param_type;
4664 generic_param_value->node = *param_node;
4665 }
4666
4667
4668 auto entry = g->generic_table.maybe_get(generic_fn_type_id);
4669 if (entry) {
4670 AstNode *impl_decl_node = entry->value;
4671 assert(impl_decl_node->type == NodeTypeFnProto);
4672 FnTableEntry *fn_table_entry = impl_decl_node->data.fn_proto.fn_table_entry;
4673 return resolve_expr_const_val_as_fn(g, node, fn_table_entry);
4674 }
4675
4676 // make a type from the generic parameters supplied
4677 assert(decl_node->type == NodeTypeFnProto);
4678 AstNode *impl_decl_node = ast_clone_subtree(decl_node);
4679
4680 preview_fn_proto_instance(g, import, decl_node, child_context);
4681
4682 g->generic_table.put(generic_fn_type_id, impl_decl_node);
4683
4684 FnTableEntry *fn_table_entry = decl_node->data.fn_proto.fn_table_entry;
4685 return resolve_expr_const_val_as_fn(g, node, fn_table_entry);
4686}
4687
45444688static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
45454689 TypeTableEntry *expected_type, AstNode *node)
45464690{
......@@ -4627,6 +4771,8 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
46274771
46284772 return analyze_fn_call_raw(g, import, context, expected_type, node,
46294773 const_val->data.x_fn, bare_struct_type);
4774 } else if (invoke_type_entry->id == TypeTableEntryIdGenericFn) {
4775 return analyze_generic_fn_call(g, import, context, expected_type, node, const_val->data.x_type);
46304776 } else {
46314777 add_node_error(g, fn_ref_expr,
46324778 buf_sprintf("type '%s' not a function", buf_ptr(&invoke_type_entry->name)));
......@@ -4971,7 +5117,7 @@ static TypeTableEntry *analyze_switch_expr(CodeGen *g, ImportTableEntry *import,
49715117 Buf *var_name = &var_node->data.symbol_expr.symbol;
49725118 var_node->block_context = child_context;
49735119 prong_node->data.switch_prong.var = add_local_var(g, var_node, import,
4974 child_context, var_name, var_type, true);
5120 child_context, var_name, var_type, true, nullptr);
49755121 prong_node->data.switch_prong.var_is_target_expr = var_is_target_expr;
49765122 }
49775123 }
......@@ -5391,7 +5537,7 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
53915537 }
53925538
53935539 VariableTableEntry *var = add_local_var(g, param_decl_node, import, context, &param_decl->name,
5394 type, true);
5540 type, true, nullptr);
53955541 var->src_arg_index = i;
53965542 param_decl_node->data.param_decl.variable = var;
53975543
......@@ -5413,7 +5559,9 @@ static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, BlockContex
54135559 tld->import = import;
54145560 tld->name = name;
54155561
5416 if (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport) {
5562 bool want_as_export = (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport);
5563 bool is_generic = (node->type == NodeTypeFnProto && node->data.fn_proto.generic_params.length > 0);
5564 if (!is_generic && want_as_export) {
54175565 g->export_queue.append(node);
54185566 }
54195567
......@@ -5909,6 +6057,7 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
59096057 case TypeTableEntryIdNumLitInt:
59106058 case TypeTableEntryIdUndefLit:
59116059 case TypeTableEntryIdNamespace:
6060 case TypeTableEntryIdGenericFn:
59126061 zig_unreachable();
59136062 case TypeTableEntryIdUnreachable:
59146063 case TypeTableEntryIdVoid:
......@@ -5965,7 +6114,6 @@ uint32_t fn_type_id_hash(FnTypeId *id) {
59656114 result += id->is_cold ? 3605523458 : 0;
59666115 result += id->is_var_args ? 1931444534 : 0;
59676116 result += hash_ptr(id->return_type);
5968 result += id->param_count;
59696117 for (int i = 0; i < id->param_count; i += 1) {
59706118 FnTypeParamInfo *info = &id->param_info[i];
59716119 result += info->is_noalias ? 892356923 : 0;
......@@ -5999,6 +6147,76 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b) {
59996147 return true;
60006148}
60016149
6150static uint32_t hash_const_val(TypeTableEntry *type, ConstExprValue *const_val) {
6151 switch (type->id) {
6152 case TypeTableEntryIdBool:
6153 return const_val->data.x_bool ? 127863866 : 215080464;
6154 case TypeTableEntryIdMetaType:
6155 return hash_ptr(const_val->data.x_type);
6156 case TypeTableEntryIdVoid:
6157 return 4149439618;
6158 case TypeTableEntryIdInt:
6159 case TypeTableEntryIdNumLitInt:
6160 return ((uint32_t)(bignum_to_twos_complement(&const_val->data.x_bignum) % UINT32_MAX)) * 1331471175;
6161 case TypeTableEntryIdFloat:
6162 case TypeTableEntryIdNumLitFloat:
6163 return const_val->data.x_bignum.data.x_float * UINT32_MAX;
6164 case TypeTableEntryIdPointer:
6165 return hash_ptr(const_val->data.x_ptr.ptr);
6166 case TypeTableEntryIdUndefLit:
6167 return 162837799;
6168 case TypeTableEntryIdArray:
6169 // TODO better hashing algorithm
6170 return 1166190605;
6171 case TypeTableEntryIdStruct:
6172 // TODO better hashing algorithm
6173 return 1532530855;
6174 case TypeTableEntryIdMaybe:
6175 if (const_val->data.x_maybe) {
6176 TypeTableEntry *child_type = type->data.maybe.child_type;
6177 return hash_const_val(child_type, const_val->data.x_maybe) * 1992916303;
6178 } else {
6179 return 4016830364;
6180 }
6181 case TypeTableEntryIdErrorUnion:
6182 // TODO better hashing algorithm
6183 return 3415065496;
6184 case TypeTableEntryIdPureError:
6185 // TODO better hashing algorithm
6186 return 2630160122;
6187 case TypeTableEntryIdEnum:
6188 // TODO better hashing algorithm
6189 return 31643936;
6190 case TypeTableEntryIdFn:
6191 return hash_ptr(const_val->data.x_fn);
6192 case TypeTableEntryIdTypeDecl:
6193 return hash_ptr(const_val->data.x_type);
6194 case TypeTableEntryIdNamespace:
6195 return hash_ptr(const_val->data.x_import);
6196 case TypeTableEntryIdGenericFn:
6197 case TypeTableEntryIdInvalid:
6198 case TypeTableEntryIdUnreachable:
6199 zig_unreachable();
6200 }
6201}
6202
6203uint32_t generic_fn_type_id_hash(GenericFnTypeId *id) {
6204 uint32_t result = 0;
6205 result += hash_ptr(id->decl_node);
6206 for (int i = 0; i < id->generic_param_count; i += 1) {
6207 GenericParamValue *generic_param = &id->generic_params[i];
6208 ConstExprValue *const_val = &get_resolved_expr(generic_param->node)->const_val;
6209 assert(const_val->ok);
6210 result += hash_const_val(generic_param->type, const_val);
6211 }
6212 return result;
6213}
6214
6215bool generic_fn_type_id_eql(GenericFnTypeId *a, GenericFnTypeId *b) {
6216 // TODO
6217 return true;
6218}
6219
60026220bool type_has_bits(TypeTableEntry *type_entry) {
60036221 assert(type_entry);
60046222 assert(type_entry->id != TypeTableEntryIdInvalid);
......@@ -6027,6 +6245,7 @@ static TypeTableEntry *type_of_first_thing_in_memory(TypeTableEntry *type_entry)
60276245 case TypeTableEntryIdMetaType:
60286246 case TypeTableEntryIdVoid:
60296247 case TypeTableEntryIdNamespace:
6248 case TypeTableEntryIdGenericFn:
60306249 zig_unreachable();
60316250 case TypeTableEntryIdArray:
60326251 return type_of_first_thing_in_memory(type_entry->data.array.child_type);
src/ast_render.cpp+22-311
......@@ -59,15 +59,6 @@ static const char *prefix_op_str(PrefixOp prefix_op) {
5959 zig_unreachable();
6060}
6161
62static const char *return_prefix_str(ReturnKind kind) {
63 switch (kind) {
64 case ReturnKindError: return "%";
65 case ReturnKindMaybe: return "?";
66 case ReturnKindUnconditional: return "";
67 }
68 zig_unreachable();
69}
70
7162static const char *visib_mod_string(VisibMod mod) {
7263 switch (mod) {
7364 case VisibModPub: return "pub ";
......@@ -195,316 +186,36 @@ static const char *node_type_str(NodeType node_type) {
195186 zig_unreachable();
196187}
197188
189struct AstPrint {
190 int indent;
191 FILE *f;
192};
198193
199void ast_print(FILE *f, AstNode *node, int indent) {
200 for (int i = 0; i < indent; i += 1) {
201 fprintf(f, " ");
202 }
203 assert(node->type == NodeTypeRoot || *node->parent_field == node);
204
205 switch (node->type) {
206 case NodeTypeRoot:
207 fprintf(f, "%s\n", node_type_str(node->type));
208 for (int i = 0; i < node->data.root.top_level_decls.length; i += 1) {
209 AstNode *child = node->data.root.top_level_decls.at(i);
210 ast_print(f, child, indent + 2);
211 }
212 break;
213 case NodeTypeFnDef:
214 {
215 fprintf(f, "%s\n", node_type_str(node->type));
216 AstNode *child = node->data.fn_def.fn_proto;
217 ast_print(f, child, indent + 2);
218 ast_print(f, node->data.fn_def.body, indent + 2);
219 break;
220 }
221 case NodeTypeFnProto:
222 {
223 Buf *name_buf = &node->data.fn_proto.name;
224 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
194static void ast_print_visit(AstNode **node_ptr, void *context) {
195 AstNode *node = *node_ptr;
196 AstPrint *ap = (AstPrint *)context;
225197
226 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
227 AstNode *child = node->data.fn_proto.params.at(i);
228 ast_print(f, child, indent + 2);
229 }
198 for (int i = 0; i < ap->indent; i += 1) {
199 fprintf(ap->f, " ");
200 }
230201
231 ast_print(f, node->data.fn_proto.return_type, indent + 2);
202 fprintf(ap->f, "%s\n", node_type_str(node->type));
232203
233 break;
234 }
235 case NodeTypeBlock:
236 {
237 fprintf(f, "%s\n", node_type_str(node->type));
238 for (int i = 0; i < node->data.block.statements.length; i += 1) {
239 AstNode *child = node->data.block.statements.at(i);
240 ast_print(f, child, indent + 2);
241 }
242 break;
243 }
244 case NodeTypeParamDecl:
245 {
246 Buf *name_buf = &node->data.param_decl.name;
247 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
204 AstPrint new_ap;
205 new_ap.indent = ap->indent + 2;
206 new_ap.f = ap->f;
248207
249 ast_print(f, node->data.param_decl.type, indent + 2);
208 ast_visit_node_children(node, ast_print_visit, &new_ap);
209}
250210
251 break;
252 }
253 case NodeTypeReturnExpr:
254 {
255 const char *prefix_str = return_prefix_str(node->data.return_expr.kind);
256 fprintf(f, "%s%s\n", prefix_str, node_type_str(node->type));
257 if (node->data.return_expr.expr)
258 ast_print(f, node->data.return_expr.expr, indent + 2);
259 break;
260 }
261 case NodeTypeDefer:
262 {
263 const char *prefix_str = return_prefix_str(node->data.defer.kind);
264 fprintf(f, "%s%s\n", prefix_str, node_type_str(node->type));
265 if (node->data.defer.expr)
266 ast_print(f, node->data.defer.expr, indent + 2);
267 break;
268 }
269 case NodeTypeVariableDeclaration:
270 {
271 Buf *name_buf = &node->data.variable_declaration.symbol;
272 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
273 if (node->data.variable_declaration.type)
274 ast_print(f, node->data.variable_declaration.type, indent + 2);
275 if (node->data.variable_declaration.expr)
276 ast_print(f, node->data.variable_declaration.expr, indent + 2);
277 break;
278 }
279 case NodeTypeTypeDecl:
280 {
281 Buf *name_buf = &node->data.type_decl.symbol;
282 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
283 ast_print(f, node->data.type_decl.child_type, indent + 2);
284 break;
285 }
286 case NodeTypeErrorValueDecl:
287 {
288 Buf *name_buf = &node->data.error_value_decl.name;
289 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
290 break;
291 }
292 case NodeTypeFnDecl:
293 fprintf(f, "%s\n", node_type_str(node->type));
294 ast_print(f, node->data.fn_decl.fn_proto, indent + 2);
295 break;
296 case NodeTypeBinOpExpr:
297 fprintf(f, "%s %s\n", node_type_str(node->type),
298 bin_op_str(node->data.bin_op_expr.bin_op));
299 ast_print(f, node->data.bin_op_expr.op1, indent + 2);
300 ast_print(f, node->data.bin_op_expr.op2, indent + 2);
301 break;
302 case NodeTypeUnwrapErrorExpr:
303 fprintf(f, "%s\n", node_type_str(node->type));
304 ast_print(f, node->data.unwrap_err_expr.op1, indent + 2);
305 if (node->data.unwrap_err_expr.symbol) {
306 ast_print(f, node->data.unwrap_err_expr.symbol, indent + 2);
307 }
308 ast_print(f, node->data.unwrap_err_expr.op2, indent + 2);
309 break;
310 case NodeTypeFnCallExpr:
311 fprintf(f, "%s\n", node_type_str(node->type));
312 ast_print(f, node->data.fn_call_expr.fn_ref_expr, indent + 2);
313 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
314 AstNode *child = node->data.fn_call_expr.params.at(i);
315 ast_print(f, child, indent + 2);
316 }
317 break;
318 case NodeTypeArrayAccessExpr:
319 fprintf(f, "%s\n", node_type_str(node->type));
320 ast_print(f, node->data.array_access_expr.array_ref_expr, indent + 2);
321 ast_print(f, node->data.array_access_expr.subscript, indent + 2);
322 break;
323 case NodeTypeSliceExpr:
324 fprintf(f, "%s\n", node_type_str(node->type));
325 ast_print(f, node->data.slice_expr.array_ref_expr, indent + 2);
326 ast_print(f, node->data.slice_expr.start, indent + 2);
327 if (node->data.slice_expr.end) {
328 ast_print(f, node->data.slice_expr.end, indent + 2);
329 }
330 break;
331 case NodeTypeDirective:
332 fprintf(f, "%s\n", node_type_str(node->type));
333 ast_print(f, node->data.directive.expr, indent + 2);
334 break;
335 case NodeTypePrefixOpExpr:
336 fprintf(f, "%s %s\n", node_type_str(node->type),
337 prefix_op_str(node->data.prefix_op_expr.prefix_op));
338 ast_print(f, node->data.prefix_op_expr.primary_expr, indent + 2);
339 break;
340 case NodeTypeNumberLiteral:
341 {
342 NumLit kind = node->data.number_literal.kind;
343 const char *name = node_type_str(node->type);
344 if (kind == NumLitUInt) {
345 fprintf(f, "%s uint %" PRIu64 "\n", name, node->data.number_literal.data.x_uint);
346 } else {
347 fprintf(f, "%s float %f\n", name, node->data.number_literal.data.x_float);
348 }
349 break;
350 }
351 case NodeTypeStringLiteral:
352 {
353 const char *c = node->data.string_literal.c ? "c" : "";
354 fprintf(f, "StringLiteral %s'%s'\n", c,
355 buf_ptr(&node->data.string_literal.buf));
356 break;
357 }
358 case NodeTypeCharLiteral:
359 {
360 fprintf(f, "%s '%c'\n", node_type_str(node->type), node->data.char_literal.value);
361 break;
362 }
363 case NodeTypeSymbol:
364 fprintf(f, "Symbol %s\n", buf_ptr(&node->data.symbol_expr.symbol));
365 break;
366 case NodeTypeUse:
367 fprintf(f, "%s\n", node_type_str(node->type));
368 ast_print(f, node->data.use.expr, indent + 2);
369 break;
370 case NodeTypeBoolLiteral:
371 fprintf(f, "%s '%s'\n", node_type_str(node->type),
372 node->data.bool_literal.value ? "true" : "false");
373 break;
374 case NodeTypeNullLiteral:
375 fprintf(f, "%s\n", node_type_str(node->type));
376 break;
377 case NodeTypeIfBoolExpr:
378 fprintf(f, "%s\n", node_type_str(node->type));
379 if (node->data.if_bool_expr.condition)
380 ast_print(f, node->data.if_bool_expr.condition, indent + 2);
381 ast_print(f, node->data.if_bool_expr.then_block, indent + 2);
382 if (node->data.if_bool_expr.else_node)
383 ast_print(f, node->data.if_bool_expr.else_node, indent + 2);
384 break;
385 case NodeTypeIfVarExpr:
386 {
387 Buf *name_buf = &node->data.if_var_expr.var_decl.symbol;
388 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
389 if (node->data.if_var_expr.var_decl.type)
390 ast_print(f, node->data.if_var_expr.var_decl.type, indent + 2);
391 if (node->data.if_var_expr.var_decl.expr)
392 ast_print(f, node->data.if_var_expr.var_decl.expr, indent + 2);
393 ast_print(f, node->data.if_var_expr.then_block, indent + 2);
394 if (node->data.if_var_expr.else_node)
395 ast_print(f, node->data.if_var_expr.else_node, indent + 2);
396 break;
397 }
398 case NodeTypeWhileExpr:
399 fprintf(f, "%s\n", node_type_str(node->type));
400 ast_print(f, node->data.while_expr.condition, indent + 2);
401 ast_print(f, node->data.while_expr.body, indent + 2);
402 break;
403 case NodeTypeForExpr:
404 fprintf(f, "%s\n", node_type_str(node->type));
405 ast_print(f, node->data.for_expr.elem_node, indent + 2);
406 ast_print(f, node->data.for_expr.array_expr, indent + 2);
407 if (node->data.for_expr.index_node) {
408 ast_print(f, node->data.for_expr.index_node, indent + 2);
409 }
410 ast_print(f, node->data.for_expr.body, indent + 2);
411 break;
412 case NodeTypeSwitchExpr:
413 fprintf(f, "%s\n", node_type_str(node->type));
414 ast_print(f, node->data.switch_expr.expr, indent + 2);
415 for (int i = 0; i < node->data.switch_expr.prongs.length; i += 1) {
416 AstNode *child_node = node->data.switch_expr.prongs.at(i);
417 ast_print(f, child_node, indent + 2);
418 }
419 break;
420 case NodeTypeSwitchProng:
421 fprintf(f, "%s\n", node_type_str(node->type));
422 for (int i = 0; i < node->data.switch_prong.items.length; i += 1) {
423 AstNode *child_node = node->data.switch_prong.items.at(i);
424 ast_print(f, child_node, indent + 2);
425 }
426 if (node->data.switch_prong.var_symbol) {
427 ast_print(f, node->data.switch_prong.var_symbol, indent + 2);
428 }
429 ast_print(f, node->data.switch_prong.expr, indent + 2);
430 break;
431 case NodeTypeSwitchRange:
432 fprintf(f, "%s\n", node_type_str(node->type));
433 ast_print(f, node->data.switch_range.start, indent + 2);
434 ast_print(f, node->data.switch_range.end, indent + 2);
435 break;
436 case NodeTypeLabel:
437 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.label.name));
438 break;
439 case NodeTypeGoto:
440 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.goto_expr.name));
441 break;
442 case NodeTypeBreak:
443 fprintf(f, "%s\n", node_type_str(node->type));
444 break;
445 case NodeTypeContinue:
446 fprintf(f, "%s\n", node_type_str(node->type));
447 break;
448 case NodeTypeUndefinedLiteral:
449 fprintf(f, "%s\n", node_type_str(node->type));
450 break;
451 case NodeTypeAsmExpr:
452 fprintf(f, "%s\n", node_type_str(node->type));
453 break;
454 case NodeTypeFieldAccessExpr:
455 fprintf(f, "%s '%s'\n", node_type_str(node->type),
456 buf_ptr(&node->data.field_access_expr.field_name));
457 ast_print(f, node->data.field_access_expr.struct_expr, indent + 2);
458 break;
459 case NodeTypeStructDecl:
460 fprintf(f, "%s '%s'\n",
461 node_type_str(node->type), buf_ptr(&node->data.struct_decl.name));
462 for (int i = 0; i < node->data.struct_decl.fields.length; i += 1) {
463 AstNode *child = node->data.struct_decl.fields.at(i);
464 ast_print(f, child, indent + 2);
465 }
466 for (int i = 0; i < node->data.struct_decl.fns.length; i += 1) {
467 AstNode *child = node->data.struct_decl.fns.at(i);
468 ast_print(f, child, indent + 2);
469 }
470 break;
471 case NodeTypeStructField:
472 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_field.name));
473 if (node->data.struct_field.type) {
474 ast_print(f, node->data.struct_field.type, indent + 2);
475 }
476 break;
477 case NodeTypeStructValueField:
478 fprintf(f, "%s '%s'\n", node_type_str(node->type), buf_ptr(&node->data.struct_val_field.name));
479 ast_print(f, node->data.struct_val_field.expr, indent + 2);
480 break;
481 case NodeTypeContainerInitExpr:
482 fprintf(f, "%s\n", node_type_str(node->type));
483 ast_print(f, node->data.container_init_expr.type, indent + 2);
484 for (int i = 0; i < node->data.container_init_expr.entries.length; i += 1) {
485 AstNode *child = node->data.container_init_expr.entries.at(i);
486 ast_print(f, child, indent + 2);
487 }
488 break;
489 case NodeTypeArrayType:
490 {
491 const char *const_str = node->data.array_type.is_const ? "const" : "var";
492 fprintf(f, "%s %s\n", node_type_str(node->type), const_str);
493 if (node->data.array_type.size) {
494 ast_print(f, node->data.array_type.size, indent + 2);
495 }
496 ast_print(f, node->data.array_type.child_type, indent + 2);
497 break;
498 }
499 case NodeTypeErrorType:
500 fprintf(f, "%s\n", node_type_str(node->type));
501 break;
502 case NodeTypeTypeLiteral:
503 fprintf(f, "%s\n", node_type_str(node->type));
504 break;
505 }
211void ast_print(FILE *f, AstNode *node, int indent) {
212 AstPrint ap;
213 ap.indent = indent;
214 ap.f = f;
215 ast_visit_node_children(node, ast_print_visit, &ap);
506216}
507217
218
508219struct AstRender {
509220 int indent;
510221 int indent_size;
src/ast_render.hpp+1
......@@ -9,6 +9,7 @@
99#define ZIG_AST_RENDER_HPP
1010
1111#include "all_types.hpp"
12#include "parser.hpp"
1213
1314#include <stdio.h>
1415
src/codegen.cpp+2
......@@ -62,6 +62,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
6262 g->primitive_type_table.init(32);
6363 g->fn_type_table.init(32);
6464 g->error_table.init(16);
65 g->generic_table.init(16);
6566 g->is_release_build = false;
6667 g->is_test_build = false;
6768 g->error_value_count = 1;
......@@ -2927,6 +2928,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, TypeTableEntry *type_entry, ConstE
29272928 case TypeTableEntryIdUndefLit:
29282929 case TypeTableEntryIdVoid:
29292930 case TypeTableEntryIdNamespace:
2931 case TypeTableEntryIdGenericFn:
29302932 zig_unreachable();
29312933
29322934 }
src/parser.cpp+110-72
......@@ -2243,7 +2243,7 @@ static AstNode *ast_parse_block(ParseContext *pc, int *token_index, bool mandato
22432243}
22442244
22452245/*
2246FnProto : "fn" option("Symbol") ParamDeclList option("->" PrefixOpExpression)
2246FnProto = "fn" option("Symbol") option(ParamDeclList) ParamDeclList option("->" TypeExpr)
22472247*/
22482248static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mandatory,
22492249 ZigList<AstNode*> *directives, VisibMod visib_mod)
......@@ -2273,6 +2273,17 @@ static AstNode *ast_parse_fn_proto(ParseContext *pc, int *token_index, bool mand
22732273
22742274 ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args);
22752275
2276 Token *maybe_lparen = &pc->tokens->at(*token_index);
2277 if (maybe_lparen->id == TokenIdLParen) {
2278 for (int i = 0; i < node->data.fn_proto.params.length; i += 1) {
2279 node->data.fn_proto.generic_params.append(node->data.fn_proto.params.at(i));
2280 }
2281 node->data.fn_proto.generic_params_is_var_args = node->data.fn_proto.is_var_args;
2282
2283 node->data.fn_proto.params.resize(0);
2284 ast_parse_param_decl_list(pc, token_index, &node->data.fn_proto.params, &node->data.fn_proto.is_var_args);
2285 }
2286
22762287 Token *next_token = &pc->tokens->at(*token_index);
22772288 if (next_token->id == TokenIdArrow) {
22782289 *token_index += 1;
......@@ -2626,72 +2637,73 @@ AstNode *ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner,
26262637 return pc.root;
26272638}
26282639
2629static void set_field(AstNode **field) {
2630 if (*field) {
2631 (*field)->parent_field = field;
2640static void visit_field(AstNode **node, void (*visit)(AstNode **, void *context), void *context) {
2641 if (*node) {
2642 visit(node, context);
26322643 }
26332644}
26342645
2635static void set_list_fields(ZigList<AstNode*> *list) {
2646static void visit_node_list(ZigList<AstNode *> *list, void (*visit)(AstNode **, void *context), void *context) {
26362647 if (list) {
26372648 for (int i = 0; i < list->length; i += 1) {
2638 set_field(&list->at(i));
2649 visit(&list->at(i), context);
26392650 }
26402651 }
26412652}
26422653
2643void normalize_parent_ptrs(AstNode *node) {
2654void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context) {
26442655 switch (node->type) {
26452656 case NodeTypeRoot:
2646 set_list_fields(&node->data.root.top_level_decls);
2657 visit_node_list(&node->data.root.top_level_decls, visit, context);
26472658 break;
26482659 case NodeTypeFnProto:
2649 set_field(&node->data.fn_proto.return_type);
2650 set_list_fields(node->data.fn_proto.top_level_decl.directives);
2651 set_list_fields(&node->data.fn_proto.params);
2660 visit_field(&node->data.fn_proto.return_type, visit, context);
2661 visit_node_list(node->data.fn_proto.top_level_decl.directives, visit, context);
2662 visit_node_list(&node->data.fn_proto.generic_params, visit, context);
2663 visit_node_list(&node->data.fn_proto.params, visit, context);
26522664 break;
26532665 case NodeTypeFnDef:
2654 set_field(&node->data.fn_def.fn_proto);
2655 set_field(&node->data.fn_def.body);
2666 visit_field(&node->data.fn_def.fn_proto, visit, context);
2667 visit_field(&node->data.fn_def.body, visit, context);
26562668 break;
26572669 case NodeTypeFnDecl:
2658 set_field(&node->data.fn_decl.fn_proto);
2670 visit_field(&node->data.fn_decl.fn_proto, visit, context);
26592671 break;
26602672 case NodeTypeParamDecl:
2661 set_field(&node->data.param_decl.type);
2673 visit_field(&node->data.param_decl.type, visit, context);
26622674 break;
26632675 case NodeTypeBlock:
2664 set_list_fields(&node->data.block.statements);
2676 visit_node_list(&node->data.block.statements, visit, context);
26652677 break;
26662678 case NodeTypeDirective:
2667 set_field(&node->data.directive.expr);
2679 visit_field(&node->data.directive.expr, visit, context);
26682680 break;
26692681 case NodeTypeReturnExpr:
2670 set_field(&node->data.return_expr.expr);
2682 visit_field(&node->data.return_expr.expr, visit, context);
26712683 break;
26722684 case NodeTypeDefer:
2673 set_field(&node->data.defer.expr);
2685 visit_field(&node->data.defer.expr, visit, context);
26742686 break;
26752687 case NodeTypeVariableDeclaration:
2676 set_list_fields(node->data.variable_declaration.top_level_decl.directives);
2677 set_field(&node->data.variable_declaration.type);
2678 set_field(&node->data.variable_declaration.expr);
2688 visit_node_list(node->data.variable_declaration.top_level_decl.directives, visit, context);
2689 visit_field(&node->data.variable_declaration.type, visit, context);
2690 visit_field(&node->data.variable_declaration.expr, visit, context);
26792691 break;
26802692 case NodeTypeTypeDecl:
2681 set_list_fields(node->data.type_decl.top_level_decl.directives);
2682 set_field(&node->data.type_decl.child_type);
2693 visit_node_list(node->data.type_decl.top_level_decl.directives, visit, context);
2694 visit_field(&node->data.type_decl.child_type, visit, context);
26832695 break;
26842696 case NodeTypeErrorValueDecl:
26852697 // none
26862698 break;
26872699 case NodeTypeBinOpExpr:
2688 set_field(&node->data.bin_op_expr.op1);
2689 set_field(&node->data.bin_op_expr.op2);
2700 visit_field(&node->data.bin_op_expr.op1, visit, context);
2701 visit_field(&node->data.bin_op_expr.op2, visit, context);
26902702 break;
26912703 case NodeTypeUnwrapErrorExpr:
2692 set_field(&node->data.unwrap_err_expr.op1);
2693 set_field(&node->data.unwrap_err_expr.symbol);
2694 set_field(&node->data.unwrap_err_expr.op2);
2704 visit_field(&node->data.unwrap_err_expr.op1, visit, context);
2705 visit_field(&node->data.unwrap_err_expr.symbol, visit, context);
2706 visit_field(&node->data.unwrap_err_expr.op2, visit, context);
26952707 break;
26962708 case NodeTypeNumberLiteral:
26972709 // none
......@@ -2706,27 +2718,27 @@ void normalize_parent_ptrs(AstNode *node) {
27062718 // none
27072719 break;
27082720 case NodeTypePrefixOpExpr:
2709 set_field(&node->data.prefix_op_expr.primary_expr);
2721 visit_field(&node->data.prefix_op_expr.primary_expr, visit, context);
27102722 break;
27112723 case NodeTypeFnCallExpr:
2712 set_field(&node->data.fn_call_expr.fn_ref_expr);
2713 set_list_fields(&node->data.fn_call_expr.params);
2724 visit_field(&node->data.fn_call_expr.fn_ref_expr, visit, context);
2725 visit_node_list(&node->data.fn_call_expr.params, visit, context);
27142726 break;
27152727 case NodeTypeArrayAccessExpr:
2716 set_field(&node->data.array_access_expr.array_ref_expr);
2717 set_field(&node->data.array_access_expr.subscript);
2728 visit_field(&node->data.array_access_expr.array_ref_expr, visit, context);
2729 visit_field(&node->data.array_access_expr.subscript, visit, context);
27182730 break;
27192731 case NodeTypeSliceExpr:
2720 set_field(&node->data.slice_expr.array_ref_expr);
2721 set_field(&node->data.slice_expr.start);
2722 set_field(&node->data.slice_expr.end);
2732 visit_field(&node->data.slice_expr.array_ref_expr, visit, context);
2733 visit_field(&node->data.slice_expr.start, visit, context);
2734 visit_field(&node->data.slice_expr.end, visit, context);
27232735 break;
27242736 case NodeTypeFieldAccessExpr:
2725 set_field(&node->data.field_access_expr.struct_expr);
2737 visit_field(&node->data.field_access_expr.struct_expr, visit, context);
27262738 break;
27272739 case NodeTypeUse:
2728 set_field(&node->data.use.expr);
2729 set_list_fields(node->data.use.top_level_decl.directives);
2740 visit_field(&node->data.use.expr, visit, context);
2741 visit_node_list(node->data.use.top_level_decl.directives, visit, context);
27302742 break;
27312743 case NodeTypeBoolLiteral:
27322744 // none
......@@ -2738,38 +2750,38 @@ void normalize_parent_ptrs(AstNode *node) {
27382750 // none
27392751 break;
27402752 case NodeTypeIfBoolExpr:
2741 set_field(&node->data.if_bool_expr.condition);
2742 set_field(&node->data.if_bool_expr.then_block);
2743 set_field(&node->data.if_bool_expr.else_node);
2753 visit_field(&node->data.if_bool_expr.condition, visit, context);
2754 visit_field(&node->data.if_bool_expr.then_block, visit, context);
2755 visit_field(&node->data.if_bool_expr.else_node, visit, context);
27442756 break;
27452757 case NodeTypeIfVarExpr:
2746 set_field(&node->data.if_var_expr.var_decl.type);
2747 set_field(&node->data.if_var_expr.var_decl.expr);
2748 set_field(&node->data.if_var_expr.then_block);
2749 set_field(&node->data.if_var_expr.else_node);
2758 visit_field(&node->data.if_var_expr.var_decl.type, visit, context);
2759 visit_field(&node->data.if_var_expr.var_decl.expr, visit, context);
2760 visit_field(&node->data.if_var_expr.then_block, visit, context);
2761 visit_field(&node->data.if_var_expr.else_node, visit, context);
27502762 break;
27512763 case NodeTypeWhileExpr:
2752 set_field(&node->data.while_expr.condition);
2753 set_field(&node->data.while_expr.body);
2764 visit_field(&node->data.while_expr.condition, visit, context);
2765 visit_field(&node->data.while_expr.body, visit, context);
27542766 break;
27552767 case NodeTypeForExpr:
2756 set_field(&node->data.for_expr.elem_node);
2757 set_field(&node->data.for_expr.array_expr);
2758 set_field(&node->data.for_expr.index_node);
2759 set_field(&node->data.for_expr.body);
2768 visit_field(&node->data.for_expr.elem_node, visit, context);
2769 visit_field(&node->data.for_expr.array_expr, visit, context);
2770 visit_field(&node->data.for_expr.index_node, visit, context);
2771 visit_field(&node->data.for_expr.body, visit, context);
27602772 break;
27612773 case NodeTypeSwitchExpr:
2762 set_field(&node->data.switch_expr.expr);
2763 set_list_fields(&node->data.switch_expr.prongs);
2774 visit_field(&node->data.switch_expr.expr, visit, context);
2775 visit_node_list(&node->data.switch_expr.prongs, visit, context);
27642776 break;
27652777 case NodeTypeSwitchProng:
2766 set_list_fields(&node->data.switch_prong.items);
2767 set_field(&node->data.switch_prong.var_symbol);
2768 set_field(&node->data.switch_prong.expr);
2778 visit_node_list(&node->data.switch_prong.items, visit, context);
2779 visit_field(&node->data.switch_prong.var_symbol, visit, context);
2780 visit_field(&node->data.switch_prong.expr, visit, context);
27692781 break;
27702782 case NodeTypeSwitchRange:
2771 set_field(&node->data.switch_range.start);
2772 set_field(&node->data.switch_range.end);
2783 visit_field(&node->data.switch_range.start, visit, context);
2784 visit_field(&node->data.switch_range.end, visit, context);
27732785 break;
27742786 case NodeTypeLabel:
27752787 // none
......@@ -2786,32 +2798,32 @@ void normalize_parent_ptrs(AstNode *node) {
27862798 case NodeTypeAsmExpr:
27872799 for (int i = 0; i < node->data.asm_expr.input_list.length; i += 1) {
27882800 AsmInput *asm_input = node->data.asm_expr.input_list.at(i);
2789 set_field(&asm_input->expr);
2801 visit_field(&asm_input->expr, visit, context);
27902802 }
27912803 for (int i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
27922804 AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);
2793 set_field(&asm_output->return_type);
2805 visit_field(&asm_output->return_type, visit, context);
27942806 }
27952807 break;
27962808 case NodeTypeStructDecl:
2797 set_list_fields(&node->data.struct_decl.fields);
2798 set_list_fields(&node->data.struct_decl.fns);
2799 set_list_fields(node->data.struct_decl.top_level_decl.directives);
2809 visit_node_list(&node->data.struct_decl.fields, visit, context);
2810 visit_node_list(&node->data.struct_decl.fns, visit, context);
2811 visit_node_list(node->data.struct_decl.top_level_decl.directives, visit, context);
28002812 break;
28012813 case NodeTypeStructField:
2802 set_field(&node->data.struct_field.type);
2803 set_list_fields(node->data.struct_field.top_level_decl.directives);
2814 visit_field(&node->data.struct_field.type, visit, context);
2815 visit_node_list(node->data.struct_field.top_level_decl.directives, visit, context);
28042816 break;
28052817 case NodeTypeContainerInitExpr:
2806 set_field(&node->data.container_init_expr.type);
2807 set_list_fields(&node->data.container_init_expr.entries);
2818 visit_field(&node->data.container_init_expr.type, visit, context);
2819 visit_node_list(&node->data.container_init_expr.entries, visit, context);
28082820 break;
28092821 case NodeTypeStructValueField:
2810 set_field(&node->data.struct_val_field.expr);
2822 visit_field(&node->data.struct_val_field.expr, visit, context);
28112823 break;
28122824 case NodeTypeArrayType:
2813 set_field(&node->data.array_type.size);
2814 set_field(&node->data.array_type.child_type);
2825 visit_field(&node->data.array_type.size, visit, context);
2826 visit_field(&node->data.array_type.child_type, visit, context);
28152827 break;
28162828 case NodeTypeErrorType:
28172829 // none
......@@ -2821,3 +2833,29 @@ void normalize_parent_ptrs(AstNode *node) {
28212833 break;
28222834 }
28232835}
2836
2837static void normalize_parent_ptrs_visit(AstNode **node, void *context) {
2838 (*node)->parent_field = node;
2839}
2840
2841void normalize_parent_ptrs(AstNode *node) {
2842 ast_visit_node_children(node, normalize_parent_ptrs_visit, nullptr);
2843}
2844
2845static AstNode *clone_node(AstNode *old_node) {
2846 AstNode *new_node = allocate_nonzero<AstNode>(1);
2847 memcpy(new_node, old_node, sizeof(AstNode));
2848 return new_node;
2849}
2850
2851static void ast_clone_subtree_visit(AstNode **node, void *context) {
2852 *node = clone_node(*node);
2853 (*node)->parent_field = node;
2854 ast_visit_node_children(*node, ast_clone_subtree_visit, nullptr);
2855}
2856
2857AstNode *ast_clone_subtree(AstNode *old_node) {
2858 AstNode *new_node = clone_node(old_node);
2859 ast_visit_node_children(new_node, ast_clone_subtree_visit, nullptr);
2860 return new_node;
2861}
src/parser.hpp+3-2
......@@ -20,10 +20,11 @@ void ast_token_error(Token *token, const char *format, ...);
2020AstNode * ast_parse(Buf *buf, ZigList<Token> *tokens, ImportTableEntry *owner, ErrColor err_color,
2121 uint32_t *next_node_index);
2222
23const char *node_type_str(NodeType node_type);
24
2523void ast_print(AstNode *node, int indent);
2624
2725void normalize_parent_ptrs(AstNode *node);
2826
27AstNode *ast_clone_subtree(AstNode *node);
28void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *context), void *context);
29
2930#endif
test/self_hosted.zig+10
......@@ -512,6 +512,16 @@ three)";
512512
513513
514514
515#attribute("test")
516fn simple_generic_fn() {
517 assert(max(i32)(3, -1) == 3);
518}
519
520fn max(T: type)(a: T, b: T) -> T {
521 return if (a > b) a else b;
522}
523
524
515525fn assert(b: bool) {
516526 if (!b) unreachable{}
517527}