authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-14 10:40:08-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-14 10:40:08-07:00
log579856e502eab87ea8a73a76dc63a2108e5a8cc8
treefeb34b0985b29f45073ac81e21982a368e0a3542
parent5a479720ec5786145dac6c85deae4e322bd5972e
parentfcedc35551cc6b14756499414e47c33004de3be4

Merge branch 'eval'


15 files changed, 1693 insertions(+), 469 deletions(-)

CMakeLists.txt+1
......@@ -41,6 +41,7 @@ set(ZIG_SOURCES
4141 "${CMAKE_SOURCE_DIR}/src/bignum.cpp"
4242 "${CMAKE_SOURCE_DIR}/src/tokenizer.cpp"
4343 "${CMAKE_SOURCE_DIR}/src/parser.cpp"
44 "${CMAKE_SOURCE_DIR}/src/eval.cpp"
4445 "${CMAKE_SOURCE_DIR}/src/analyze.cpp"
4546 "${CMAKE_SOURCE_DIR}/src/codegen.cpp"
4647 "${CMAKE_SOURCE_DIR}/src/buffer.cpp"
src/all_types.hpp+38-1
......@@ -496,8 +496,8 @@ struct AstNodeWhileExpr {
496496};
497497
498498struct AstNodeForExpr {
499 AstNode *elem_node; // always a symbol
500499 AstNode *array_expr;
500 AstNode *elem_node; // always a symbol
501501 AstNode *index_node; // always a symbol, might be null
502502 AstNode *body;
503503
......@@ -960,6 +960,7 @@ struct TypeTableEntry {
960960 LLVMZigDIType *di_type;
961961
962962 bool zero_bits;
963 bool deep_const;
963964
964965 union {
965966 TypeTableEntryPointer pointer;
......@@ -1005,6 +1006,13 @@ struct ImportTableEntry {
10051006 ZigList<AstNode *> use_decls;
10061007};
10071008
1009enum FnAnalState {
1010 FnAnalStateReady,
1011 FnAnalStateProbing,
1012 FnAnalStateComplete,
1013 FnAnalStateSkipped,
1014};
1015
10081016struct FnTableEntry {
10091017 LLVMValueRef fn_value;
10101018 AstNode *proto_node;
......@@ -1019,7 +1027,9 @@ struct FnTableEntry {
10191027 bool internal_linkage;
10201028 bool is_extern;
10211029 bool is_test;
1030 bool is_pure;
10221031 BlockContext *parent_block_context;
1032 FnAnalState anal_state;
10231033
10241034 ZigList<AstNode *> cast_alloca_list;
10251035 ZigList<StructValExprCodeGen *> struct_val_expr_alloca_list;
......@@ -1027,6 +1037,33 @@ struct FnTableEntry {
10271037 ZigList<AstNode *> goto_list;
10281038};
10291039
1040struct EvalVar {
1041 Buf *name;
1042 ConstExprValue value;
1043};
1044
1045struct EvalScope {
1046 BlockContext *block_context;
1047 ZigList<EvalVar> vars;
1048};
1049
1050struct EvalFnRoot {
1051 CodeGen *codegen;
1052 FnTableEntry *fn;
1053 AstNode *call_node;
1054 int branch_quota;
1055 int branches_used;
1056 AstNode *exceeded_quota_node;
1057 bool abort;
1058};
1059
1060struct EvalFn {
1061 EvalFnRoot *root;
1062 FnTableEntry *fn;
1063 ConstExprValue *return_expr;
1064 ZigList<EvalScope*> scope_stack;
1065};
1066
10301067enum BuiltinFnId {
10311068 BuiltinFnIdInvalid,
10321069 BuiltinFnIdMemcpy,
src/analyze.cpp+176-321
......@@ -13,6 +13,7 @@
1313#include "parseh.hpp"
1414#include "config.h"
1515#include "ast_render.hpp"
16#include "eval.hpp"
1617
1718static TypeTableEntry *analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1819 TypeTableEntry *expected_type, AstNode *node);
......@@ -34,7 +35,8 @@ static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node,
3435static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
3536 TypeTableEntry *expected_type, uint64_t x);
3637static AstNode *find_decl(BlockContext *context, Buf *name);
37static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node, bool pointer_only);
38static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
39 bool pointer_only, BlockContext *block_context);
3840static TopLevelDecl *get_as_top_level_decl(AstNode *node);
3941static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
4042 BlockContext *context, AstNode *source_node,
......@@ -206,6 +208,7 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x) {
206208static TypeTableEntry *get_generic_fn_type(CodeGen *g, AstNode *decl_node) {
207209 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdGenericFn);
208210 buf_init_from_str(&entry->name, "(generic function)");
211 entry->deep_const = true;
209212 entry->zero_bits = true;
210213 entry->data.generic_fn.decl_node = decl_node;
211214 return entry;
......@@ -219,6 +222,8 @@ TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool
219222 } else {
220223 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPointer);
221224
225 entry->deep_const = is_const && child_type->deep_const;
226
222227 const char *const_str = is_const ? "const " : "";
223228 buf_resize(&entry->name, 0);
224229 buf_appendf(&entry->name, "&%s%s", const_str, buf_ptr(&child_type->name));
......@@ -260,6 +265,8 @@ TypeTableEntry *get_maybe_type(CodeGen *g, TypeTableEntry *child_type) {
260265 assert(child_type->type_ref);
261266 assert(child_type->di_type);
262267
268 entry->deep_const = child_type->deep_const;
269
263270 buf_resize(&entry->name, 0);
264271 buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name));
265272
......@@ -343,6 +350,8 @@ static TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type) {
343350
344351 entry->data.error.child_type = child_type;
345352
353 entry->deep_const = child_type->deep_const;
354
346355 if (!type_has_bits(child_type)) {
347356 entry->type_ref = g->err_tag_type->type_ref;
348357 entry->di_type = g->err_tag_type->di_type;
......@@ -414,6 +423,7 @@ TypeTableEntry *get_array_type(CodeGen *g, TypeTableEntry *child_type, uint64_t
414423 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdArray);
415424 entry->type_ref = LLVMArrayType(child_type->type_ref, array_size);
416425 entry->zero_bits = (array_size == 0) || child_type->zero_bits;
426 entry->deep_const = child_type->deep_const;
417427
418428 buf_resize(&entry->name, 0);
419429 buf_appendf(&entry->name, "[%" PRIu64 "]%s", array_size, buf_ptr(&child_type->name));
......@@ -464,6 +474,8 @@ TypeTableEntry *get_slice_type(CodeGen *g, TypeTableEntry *child_type, bool is_c
464474 TypeTableEntry *var_peer = get_slice_type(g, child_type, false);
465475 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdStruct);
466476
477 entry->deep_const = child_type->deep_const;
478
467479 buf_resize(&entry->name, 0);
468480 buf_appendf(&entry->name, "[]const %s", buf_ptr(&child_type->name));
469481
......@@ -549,6 +561,7 @@ TypeTableEntry *get_typedecl_type(CodeGen *g, const char *name, TypeTableEntry *
549561
550562 buf_init_from_str(&entry->name, name);
551563
564 entry->deep_const = child_type->deep_const;
552565 entry->type_ref = child_type->type_ref;
553566 entry->di_type = child_type->di_type;
554567 entry->zero_bits = child_type->zero_bits;
......@@ -572,6 +585,7 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
572585 }
573586
574587 TypeTableEntry *fn_type = new_type_table_entry(TypeTableEntryIdFn);
588 fn_type->deep_const = true;
575589 fn_type->data.fn.fn_type_id = *fn_type_id;
576590 if (fn_type_id->param_info == &fn_type_id->prealloc_param_info[0]) {
577591 fn_type->data.fn.fn_type_id.param_info = &fn_type->data.fn.fn_type_id.prealloc_param_info[0];
......@@ -944,6 +958,19 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
944958 add_node_error(g, directive_node,
945959 buf_sprintf("#condition valid only on exported symbols"));
946960 }
961 } else if (buf_eql_str(name, "static_eval_enable")) {
962 if (fn_table_entry->is_extern) {
963 add_node_error(g, directive_node,
964 buf_sprintf("#static_val_enable invalid on extern functions"));
965 } else {
966 bool enable;
967 bool ok = resolve_const_expr_bool(g, import, import->block_context,
968 &directive_node->data.directive.expr, &enable);
969 if (!enable || !ok) {
970 fn_table_entry->is_pure = false;
971 }
972 // TODO cause compile error if enable is true and impure fn
973 }
947974 } else {
948975 add_node_error(g, directive_node,
949976 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
......@@ -1037,6 +1064,8 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
10371064
10381065 assert(enum_type->di_type);
10391066
1067 enum_type->deep_const = true;
1068
10401069 uint32_t field_count = decl_node->data.struct_decl.fields.length;
10411070
10421071 enum_type->data.enumeration.field_count = field_count;
......@@ -1064,6 +1093,10 @@ static void resolve_enum_type(CodeGen *g, ImportTableEntry *import, TypeTableEnt
10641093 type_enum_field->type_entry = field_type;
10651094 type_enum_field->value = i;
10661095
1096 if (!field_type->deep_const) {
1097 enum_type->deep_const = false;
1098 }
1099
10671100
10681101 di_enumerators[i] = LLVMZigCreateDebugEnumerator(g->dbuilder, buf_ptr(type_enum_field->name), i);
10691102
......@@ -1224,6 +1257,8 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
12241257
12251258 assert(struct_type->di_type);
12261259
1260 struct_type->deep_const = true;
1261
12271262 int field_count = decl_node->data.struct_decl.fields.length;
12281263
12291264 struct_type->data.structure.src_field_count = field_count;
......@@ -1247,6 +1282,10 @@ static void resolve_struct_type(CodeGen *g, ImportTableEntry *import, TypeTableE
12471282 type_struct_field->src_index = i;
12481283 type_struct_field->gen_index = -1;
12491284
1285 if (!field_type->deep_const) {
1286 struct_type->deep_const = false;
1287 }
1288
12501289 if (field_type->id == TypeTableEntryIdStruct) {
12511290 resolve_struct_type(g, import, field_type);
12521291 } else if (field_type->id == TypeTableEntryIdEnum) {
......@@ -1374,6 +1413,7 @@ static void preview_fn_proto_instance(CodeGen *g, ImportTableEntry *import, AstN
13741413 fn_table_entry->proto_node = proto_node;
13751414 fn_table_entry->fn_def_node = fn_def_node;
13761415 fn_table_entry->is_extern = is_extern;
1416 fn_table_entry->is_pure = !is_extern;
13771417
13781418 get_fully_qualified_decl_name(&fn_table_entry->symbol_name, proto_node, '_');
13791419
......@@ -2201,9 +2241,9 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
22012241 const_val->ok = false;
22022242 }
22032243 }
2204 if (!const_val->ok) {
2205 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
2206 }
2244 }
2245 if (!const_val->ok) {
2246 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
22072247 }
22082248
22092249 for (int i = 0; i < actual_field_count; i += 1) {
......@@ -2355,7 +2395,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
23552395 AstNode *decl_node = entry ? entry->value : nullptr;
23562396 if (decl_node) {
23572397 bool pointer_only = false;
2358 return analyze_decl_ref(g, node, decl_node, pointer_only);
2398 return analyze_decl_ref(g, node, decl_node, pointer_only, context);
23592399 } else {
23602400 add_node_error(g, node,
23612401 buf_sprintf("container '%s' has no member called '%s'",
......@@ -2382,7 +2422,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
23822422 add_error_note(g, msg, decl_node, buf_sprintf("declared here"));
23832423 }
23842424 bool pointer_only = false;
2385 return analyze_decl_ref(g, node, decl_node, pointer_only);
2425 return analyze_decl_ref(g, node, decl_node, pointer_only, context);
23862426 } else {
23872427 const char *import_name = namespace_import->path ? buf_ptr(namespace_import->path) : "(C import)";
23882428 add_node_error(g, node,
......@@ -2443,6 +2483,12 @@ static TypeTableEntry *analyze_slice_expr(CodeGen *g, ImportTableEntry *import,
24432483 return return_type;
24442484}
24452485
2486static void mark_impure_fn(BlockContext *context) {
2487 if (context->fn_entry) {
2488 context->fn_entry->is_pure = false;
2489 }
2490}
2491
24462492static TypeTableEntry *analyze_array_access_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
24472493 AstNode *node)
24482494{
......@@ -2607,26 +2653,6 @@ static TypeTableEntry *resolve_expr_const_val_as_float_num_lit(CodeGen *g, AstNo
26072653 return g->builtin_types.entry_num_lit_float;
26082654}
26092655
2610static TypeTableEntry *resolve_expr_const_val_as_bignum_op(CodeGen *g, AstNode *node,
2611 bool (*bignum_fn)(BigNum *, BigNum *, BigNum *), AstNode *op1, AstNode *op2,
2612 TypeTableEntry *resolved_type)
2613{
2614 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
2615 ConstExprValue *op1_val = &get_resolved_expr(op1)->const_val;
2616 ConstExprValue *op2_val = &get_resolved_expr(op2)->const_val;
2617
2618 const_val->ok = true;
2619
2620 if (bignum_fn(&const_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum)) {
2621 add_node_error(g, node,
2622 buf_sprintf("value cannot be represented in any integer type"));
2623 } else {
2624 num_lit_fits_in_other_type(g, node, resolved_type);
2625 }
2626
2627 return resolved_type;
2628}
2629
26302656static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *import,
26312657 BlockContext *context, AstNode *node, Buf *err_name)
26322658{
......@@ -2642,8 +2668,21 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
26422668 return g->builtin_types.entry_invalid;
26432669}
26442670
2645static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var) {
2671static bool var_is_pure(VariableTableEntry *var, BlockContext *context) {
2672 if (var->block_context->fn_entry == context->fn_entry) {
2673 // variable was declared in the current function, so it's OK.
2674 return true;
2675 }
2676 return var->is_const && var->type->deep_const;
2677}
2678
2679static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var,
2680 BlockContext *context)
2681{
26462682 get_resolved_expr(source_node)->variable = var;
2683 if (!var_is_pure(var, context)) {
2684 mark_impure_fn(context);
2685 }
26472686 if (var->is_const && var->val_node) {
26482687 ConstExprValue *other_const_val = &get_resolved_expr(var->val_node)->const_val;
26492688 if (other_const_val->ok) {
......@@ -2654,7 +2693,7 @@ static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, Variabl
26542693}
26552694
26562695static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
2657 bool pointer_only)
2696 bool pointer_only, BlockContext *block_context)
26582697{
26592698 resolve_top_level_decl(g, decl_node, pointer_only);
26602699 TopLevelDecl *tld = get_as_top_level_decl(decl_node);
......@@ -2664,7 +2703,7 @@ static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNod
26642703
26652704 if (decl_node->type == NodeTypeVariableDeclaration) {
26662705 VariableTableEntry *var = decl_node->data.variable_declaration.variable;
2667 return analyze_var_ref(g, source_node, var);
2706 return analyze_var_ref(g, source_node, var, block_context);
26682707 } else if (decl_node->type == NodeTypeFnProto) {
26692708 if (decl_node->data.fn_proto.generic_params.length > 0) {
26702709 TypeTableEntry *type_entry = decl_node->data.fn_proto.generic_fn_type;
......@@ -2700,12 +2739,13 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
27002739
27012740 VariableTableEntry *var = find_variable(g, context, variable_name);
27022741 if (var) {
2703 return analyze_var_ref(g, node, var);
2742 TypeTableEntry *var_type = analyze_var_ref(g, node, var, context);
2743 return var_type;
27042744 }
27052745
27062746 AstNode *decl_node = find_decl(context, variable_name);
27072747 if (decl_node) {
2708 return analyze_decl_ref(g, node, decl_node, pointer_only);
2748 return analyze_decl_ref(g, node, decl_node, pointer_only, context);
27092749 }
27102750
27112751 if (import->any_imports_failed) {
......@@ -2840,71 +2880,6 @@ static TypeTableEntry *analyze_lvalue(CodeGen *g, ImportTableEntry *import, Bloc
28402880 return expected_rhs_type;
28412881}
28422882
2843static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {
2844 if (bin_op == BinOpTypeBoolOr) {
2845 return a || b;
2846 } else if (bin_op == BinOpTypeBoolAnd) {
2847 return a && b;
2848 } else {
2849 zig_unreachable();
2850 }
2851}
2852
2853static bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry) {
2854 switch (type_entry->id) {
2855 case TypeTableEntryIdEnum:
2856 {
2857 ConstEnumValue *enum1 = &a->data.x_enum;
2858 ConstEnumValue *enum2 = &b->data.x_enum;
2859 if (enum1->tag == enum2->tag) {
2860 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum1->tag];
2861 if (type_has_bits(enum_field->type_entry)) {
2862 zig_panic("TODO const expr analyze enum special value for equality");
2863 } else {
2864 return true;
2865 }
2866 }
2867 return false;
2868 }
2869 case TypeTableEntryIdMetaType:
2870 return a->data.x_type == b->data.x_type;
2871 case TypeTableEntryIdVoid:
2872 return true;
2873 case TypeTableEntryIdPureError:
2874 return a->data.x_err.err == b->data.x_err.err;
2875 case TypeTableEntryIdFn:
2876 return a->data.x_fn == b->data.x_fn;
2877 case TypeTableEntryIdBool:
2878 return a->data.x_bool == b->data.x_bool;
2879 case TypeTableEntryIdInt:
2880 case TypeTableEntryIdFloat:
2881 case TypeTableEntryIdNumLitFloat:
2882 case TypeTableEntryIdNumLitInt:
2883 return bignum_cmp_eq(&a->data.x_bignum, &b->data.x_bignum);
2884 case TypeTableEntryIdPointer:
2885 zig_panic("TODO");
2886 case TypeTableEntryIdArray:
2887 zig_panic("TODO");
2888 case TypeTableEntryIdStruct:
2889 zig_panic("TODO");
2890 case TypeTableEntryIdUndefLit:
2891 zig_panic("TODO");
2892 case TypeTableEntryIdMaybe:
2893 zig_panic("TODO");
2894 case TypeTableEntryIdErrorUnion:
2895 zig_panic("TODO");
2896 case TypeTableEntryIdTypeDecl:
2897 zig_panic("TODO");
2898 case TypeTableEntryIdNamespace:
2899 zig_panic("TODO");
2900 case TypeTableEntryIdGenericFn:
2901 case TypeTableEntryIdInvalid:
2902 case TypeTableEntryIdUnreachable:
2903 zig_unreachable();
2904 }
2905 zig_unreachable();
2906}
2907
29082883static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
29092884 AstNode *node)
29102885{
......@@ -2944,39 +2919,11 @@ static TypeTableEntry *analyze_bool_bin_op_expr(CodeGen *g, ImportTableEntry *im
29442919 return g->builtin_types.entry_bool;
29452920 }
29462921
2947 bool answer;
2948 if (type_can_gt_lt_cmp) {
2949 bool (*bignum_cmp)(BigNum *, BigNum *);
2950 if (bin_op_type == BinOpTypeCmpEq) {
2951 bignum_cmp = bignum_cmp_eq;
2952 } else if (bin_op_type == BinOpTypeCmpNotEq) {
2953 bignum_cmp = bignum_cmp_neq;
2954 } else if (bin_op_type == BinOpTypeCmpLessThan) {
2955 bignum_cmp = bignum_cmp_lt;
2956 } else if (bin_op_type == BinOpTypeCmpGreaterThan) {
2957 bignum_cmp = bignum_cmp_gt;
2958 } else if (bin_op_type == BinOpTypeCmpLessOrEq) {
2959 bignum_cmp = bignum_cmp_lte;
2960 } else if (bin_op_type == BinOpTypeCmpGreaterOrEq) {
2961 bignum_cmp = bignum_cmp_gte;
2962 } else {
2963 zig_unreachable();
2964 }
29652922
2966 answer = bignum_cmp(&op1_val->data.x_bignum, &op2_val->data.x_bignum);
2967 } else {
2968 bool are_equal = const_values_equal(op1_val, op2_val, resolved_type);
2969 if (bin_op_type == BinOpTypeCmpEq) {
2970 answer = are_equal;
2971 } else if (bin_op_type == BinOpTypeCmpNotEq) {
2972 answer = !are_equal;
2973 } else {
2974 zig_unreachable();
2975 }
2976 }
2923 ConstExprValue *out_val = &get_resolved_expr(node)->const_val;
2924 eval_const_expr_bin_op(op1_val, op1_type, bin_op_type, op2_val, op2_type, out_val);
2925 return g->builtin_types.entry_bool;
29772926
2978 bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
2979 return resolve_expr_const_val_as_bool(g, node, answer, depends_on_compile_var);
29802927}
29812928
29822929static TypeTableEntry *analyze_logic_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
......@@ -3002,9 +2949,9 @@ static TypeTableEntry *analyze_logic_bin_op_expr(CodeGen *g, ImportTableEntry *i
30022949 return g->builtin_types.entry_bool;
30032950 }
30042951
3005 bool answer = eval_bool_bin_op_bool(op1_val->data.x_bool, bin_op_type, op2_val->data.x_bool);
3006 bool depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
3007 return resolve_expr_const_val_as_bool(g, node, answer, depends_on_compile_var);
2952 ConstExprValue *out_val = &get_resolved_expr(node)->const_val;
2953 eval_const_expr_bin_op(op1_val, op1_type, bin_op_type, op2_val, op2_type, out_val);
2954 return g->builtin_types.entry_bool;
30082955}
30092956
30102957static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
......@@ -3041,6 +2988,7 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
30412988 }
30422989
30432990 analyze_expression(g, import, context, expected_rhs_type, node->data.bin_op_expr.op2);
2991 // not const ok because expression has side effects
30442992 return g->builtin_types.entry_void;
30452993 }
30462994 case BinOpTypeBoolOr:
......@@ -3106,37 +3054,23 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
31063054 return resolved_type;
31073055 }
31083056
3109 if (bin_op_type == BinOpTypeAdd) {
3110 return resolve_expr_const_val_as_bignum_op(g, node, bignum_add, *op1, *op2, resolved_type);
3111 } else if (bin_op_type == BinOpTypeSub) {
3112 return resolve_expr_const_val_as_bignum_op(g, node, bignum_sub, *op1, *op2, resolved_type);
3113 } else if (bin_op_type == BinOpTypeMult) {
3114 return resolve_expr_const_val_as_bignum_op(g, node, bignum_mul, *op1, *op2, resolved_type);
3115 } else if (bin_op_type == BinOpTypeDiv) {
3116 ConstExprValue *op2_val = &get_resolved_expr(*op2)->const_val;
3117 if ((is_int && op2_val->data.x_bignum.data.x_uint == 0) ||
3118 (is_float && op2_val->data.x_bignum.data.x_float == 0.0))
3119 {
3057 ConstExprValue *out_val = &get_resolved_expr(node)->const_val;
3058 int err;
3059 if ((err = eval_const_expr_bin_op(op1_val, resolved_type, bin_op_type,
3060 op2_val, resolved_type, out_val)))
3061 {
3062 if (err == ErrorDivByZero) {
31203063 add_node_error(g, node, buf_sprintf("division by zero is undefined"));
31213064 return g->builtin_types.entry_invalid;
3122 } else {
3123 return resolve_expr_const_val_as_bignum_op(g, node, bignum_div, *op1, *op2, resolved_type);
3065 } else if (err == ErrorOverflow) {
3066 add_node_error(g, node, buf_sprintf("value cannot be represented in any integer type"));
3067 return g->builtin_types.entry_invalid;
31243068 }
3125 } else if (bin_op_type == BinOpTypeMod) {
3126 return resolve_expr_const_val_as_bignum_op(g, node, bignum_mod, *op1, *op2, resolved_type);
3127 } else if (bin_op_type == BinOpTypeBinOr) {
3128 return resolve_expr_const_val_as_bignum_op(g, node, bignum_or, *op1, *op2, resolved_type);
3129 } else if (bin_op_type == BinOpTypeBinAnd) {
3130 return resolve_expr_const_val_as_bignum_op(g, node, bignum_and, *op1, *op2, resolved_type);
3131 } else if (bin_op_type == BinOpTypeBinXor) {
3132 return resolve_expr_const_val_as_bignum_op(g, node, bignum_xor, *op1, *op2, resolved_type);
3133 } else if (bin_op_type == BinOpTypeBitShiftLeft) {
3134 return resolve_expr_const_val_as_bignum_op(g, node, bignum_shl, *op1, *op2, resolved_type);
3135 } else if (bin_op_type == BinOpTypeBitShiftRight) {
3136 return resolve_expr_const_val_as_bignum_op(g, node, bignum_shr, *op1, *op2, resolved_type);
3137 } else {
3138 zig_unreachable();
3069 return g->builtin_types.entry_invalid;
31393070 }
3071
3072 num_lit_fits_in_other_type(g, node, resolved_type);
3073 return resolved_type;
31403074 }
31413075 case BinOpTypeUnwrapMaybe:
31423076 {
......@@ -3720,6 +3654,10 @@ static TypeTableEntry *analyze_if_bool_expr(CodeGen *g, ImportTableEntry *import
37203654 }
37213655
37223656 ConstExprValue *cond_val = &get_resolved_expr(*cond)->const_val;
3657 if (cond_val->undef) {
3658 add_node_error(g, first_executing_node(*cond), buf_sprintf("branch on undefined value"));
3659 return cond_type;
3660 }
37233661 if (cond_val->ok && !cond_val->depends_on_compile_var) {
37243662 const char *str_val = cond_val->data.x_bool ? "true" : "false";
37253663 add_node_error(g, first_executing_node(*cond),
......@@ -3762,17 +3700,6 @@ static TypeTableEntry *analyze_if_var_expr(CodeGen *g, ImportTableEntry *import,
37623700 node, then_node, else_node, cond_is_const, cond_bool_val);
37633701}
37643702
3765static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type) {
3766 assert(int_type->id == TypeTableEntryIdInt);
3767
3768 for (int i = 0; i < CIntTypeCount; i += 1) {
3769 if (int_type == g->builtin_types.entry_c_int[i]) {
3770 return true;
3771 }
3772 }
3773 return false;
3774}
3775
37763703static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *import, BlockContext *context,
37773704 AstNode *node, const char *err_format, bool is_max)
37783705{
......@@ -3781,67 +3708,15 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
37813708
37823709 AstNode *type_node = node->data.fn_call_expr.params.at(0);
37833710 TypeTableEntry *type_entry = analyze_type_expr(g, import, context, type_node);
3711
37843712 if (type_entry->id == TypeTableEntryIdInvalid) {
37853713 return g->builtin_types.entry_invalid;
3786 } else if (type_entry->id == TypeTableEntryIdInt) {
3787 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3788 const_val->ok = true;
3789 const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry);
3790 if (is_max) {
3791 if (type_entry->data.integral.is_signed) {
3792 int64_t val;
3793 if (type_entry->data.integral.bit_count == 64) {
3794 val = INT64_MAX;
3795 } else if (type_entry->data.integral.bit_count == 32) {
3796 val = INT32_MAX;
3797 } else if (type_entry->data.integral.bit_count == 16) {
3798 val = INT16_MAX;
3799 } else if (type_entry->data.integral.bit_count == 8) {
3800 val = INT8_MAX;
3801 } else {
3802 zig_unreachable();
3803 }
3804 bignum_init_signed(&const_val->data.x_bignum, val);
3805 } else {
3806 uint64_t val;
3807 if (type_entry->data.integral.bit_count == 64) {
3808 val = UINT64_MAX;
3809 } else if (type_entry->data.integral.bit_count == 32) {
3810 val = UINT32_MAX;
3811 } else if (type_entry->data.integral.bit_count == 16) {
3812 val = UINT16_MAX;
3813 } else if (type_entry->data.integral.bit_count == 8) {
3814 val = UINT8_MAX;
3815 } else {
3816 zig_unreachable();
3817 }
3818 bignum_init_unsigned(&const_val->data.x_bignum, val);
3819 }
3820 } else {
3821 if (type_entry->data.integral.is_signed) {
3822 int64_t val;
3823 if (type_entry->data.integral.bit_count == 64) {
3824 val = INT64_MIN;
3825 } else if (type_entry->data.integral.bit_count == 32) {
3826 val = INT32_MIN;
3827 } else if (type_entry->data.integral.bit_count == 16) {
3828 val = INT16_MIN;
3829 } else if (type_entry->data.integral.bit_count == 8) {
3830 val = INT8_MIN;
3831 } else {
3832 zig_unreachable();
3833 }
3834 bignum_init_signed(&const_val->data.x_bignum, val);
3835 } else {
3836 bignum_init_unsigned(&const_val->data.x_bignum, 0);
3837 }
3838 }
3839 return type_entry;
3840 } else if (type_entry->id == TypeTableEntryIdFloat) {
3841 zig_panic("TODO analyze_min_max_value float");
3714 } else if (type_entry->id == TypeTableEntryIdInt ||
3715 type_entry->id == TypeTableEntryIdFloat ||
3716 type_entry->id == TypeTableEntryIdBool)
3717 {
3718 eval_min_max_value(g, type_entry, &get_resolved_expr(node)->const_val, is_max);
38423719 return type_entry;
3843 } else if (type_entry->id == TypeTableEntryIdBool) {
3844 return resolve_expr_const_val_as_bool(g, node, is_max, false);
38453720 } else {
38463721 add_node_error(g, node,
38473722 buf_sprintf(err_format, buf_ptr(&type_entry->name)));
......@@ -3849,92 +3724,19 @@ static TypeTableEntry *analyze_min_max_value(CodeGen *g, ImportTableEntry *impor
38493724 }
38503725}
38513726
3852static void eval_const_expr_implicit_cast(CodeGen *g, AstNode *node, AstNode *expr_node) {
3853 assert(node->type == NodeTypeFnCallExpr);
3854 ConstExprValue *other_val = &get_resolved_expr(expr_node)->const_val;
3855 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3856 if (!other_val->ok) {
3857 return;
3858 }
3859 const_val->depends_on_compile_var = other_val->depends_on_compile_var;
3860 const_val->undef = other_val->undef;
3861
3862 assert(other_val != const_val);
3863 switch (node->data.fn_call_expr.cast_op) {
3864 case CastOpNoCast:
3865 zig_unreachable();
3866 case CastOpNoop:
3867 case CastOpWidenOrShorten:
3868 case CastOpPointerReinterpret:
3869 *const_val = *other_val;
3870 break;
3871 case CastOpPtrToInt:
3872 case CastOpIntToPtr:
3873 // can't do it
3874 break;
3875 case CastOpToUnknownSizeArray:
3876 {
3877 TypeTableEntry *other_type = get_resolved_expr(expr_node)->type_entry;
3878 assert(other_type->id == TypeTableEntryIdArray);
3879
3880 ConstExprValue *all_fields = allocate<ConstExprValue>(2);
3881 ConstExprValue *ptr_field = &all_fields[0];
3882 ConstExprValue *len_field = &all_fields[1];
3883
3884 const_val->data.x_struct.fields = allocate<ConstExprValue*>(2);
3885 const_val->data.x_struct.fields[0] = ptr_field;
3886 const_val->data.x_struct.fields[1] = len_field;
3887
3888 ptr_field->ok = true;
3889 ptr_field->data.x_ptr.ptr = other_val->data.x_array.fields;
3890 ptr_field->data.x_ptr.len = other_type->data.array.len;
3891
3892 len_field->ok = true;
3893 bignum_init_unsigned(&len_field->data.x_bignum, other_type->data.array.len);
3894
3895 const_val->ok = true;
3896 break;
3897 }
3898 case CastOpMaybeWrap:
3899 const_val->data.x_maybe = other_val;
3900 const_val->ok = true;
3901 break;
3902 case CastOpErrorWrap:
3903 const_val->data.x_err.err = nullptr;
3904 const_val->data.x_err.payload = other_val;
3905 const_val->ok = true;
3906 break;
3907 case CastOpPureErrorWrap:
3908 const_val->data.x_err.err = other_val->data.x_err.err;
3909 const_val->ok = true;
3910 break;
3911 case CastOpErrToInt:
3912 {
3913 uint64_t value = other_val->data.x_err.err ? other_val->data.x_err.err->value : 0;
3914 bignum_init_unsigned(&const_val->data.x_bignum, value);
3915 const_val->ok = true;
3916 break;
3917 }
3918 case CastOpIntToFloat:
3919 bignum_cast_to_float(&const_val->data.x_bignum, &other_val->data.x_bignum);
3920 const_val->ok = true;
3921 break;
3922 case CastOpFloatToInt:
3923 bignum_cast_to_int(&const_val->data.x_bignum, &other_val->data.x_bignum);
3924 const_val->ok = true;
3925 break;
3926 case CastOpBoolToInt:
3927 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_bool ? 1 : 0);
3928 const_val->ok = true;
3929 break;
3930 }
3931}
3932
39333727static TypeTableEntry *resolve_cast(CodeGen *g, BlockContext *context, AstNode *node,
39343728 AstNode *expr_node, TypeTableEntry *wanted_type, CastOp op, bool need_alloca)
39353729{
39363730 node->data.fn_call_expr.cast_op = op;
3937 eval_const_expr_implicit_cast(g, node, expr_node);
3731
3732 ConstExprValue *other_val = &get_resolved_expr(expr_node)->const_val;
3733 TypeTableEntry *other_type = get_resolved_expr(expr_node)->type_entry;
3734 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
3735 if (other_val->ok) {
3736 eval_const_expr_implicit_cast(node->data.fn_call_expr.cast_op, other_val, other_type,
3737 const_val, wanted_type);
3738 }
3739
39383740 if (need_alloca) {
39393741 if (context->fn_entry) {
39403742 context->fn_entry->cast_alloca_list.append(node);
......@@ -4630,13 +4432,15 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
46304432 case BuiltinFnIdErrName:
46314433 return analyze_err_name(g, import, context, node);
46324434 case BuiltinFnIdBreakpoint:
4435 mark_impure_fn(context);
46334436 return g->builtin_types.entry_void;
46344437 }
46354438 zig_unreachable();
46364439}
46374440
46384441static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4639 TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *fn_type, TypeTableEntry *struct_type)
4442 TypeTableEntry *expected_type, AstNode *node, TypeTableEntry *fn_type,
4443 AstNode *struct_node)
46404444{
46414445 assert(node->type == NodeTypeFnCallExpr);
46424446
......@@ -4648,31 +4452,49 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
46484452 int src_param_count = fn_type->data.fn.fn_type_id.param_count;
46494453 int actual_param_count = node->data.fn_call_expr.params.length;
46504454
4651 if (struct_type) {
4455 if (struct_node) {
46524456 actual_param_count += 1;
46534457 }
46544458
4459 bool ok_invocation = true;
4460
46554461 if (fn_type->data.fn.fn_type_id.is_var_args) {
46564462 if (actual_param_count < src_param_count) {
4463 ok_invocation = false;
46574464 add_node_error(g, node,
46584465 buf_sprintf("expected at least %d arguments, got %d", src_param_count, actual_param_count));
46594466 }
46604467 } else if (src_param_count != actual_param_count) {
4468 ok_invocation = false;
46614469 add_node_error(g, node,
46624470 buf_sprintf("expected %d arguments, got %d", src_param_count, actual_param_count));
46634471 }
46644472
4473 bool all_args_const_expr = true;
4474
4475 if (struct_node) {
4476 ConstExprValue *struct_const_val = &get_resolved_expr(struct_node)->const_val;
4477 if (!struct_const_val->ok) {
4478 all_args_const_expr = false;
4479 }
4480 }
4481
46654482 // analyze each parameter. in the case of a method, we already analyzed the
46664483 // first parameter in order to figure out which struct we were calling a method on.
46674484 for (int i = 0; i < node->data.fn_call_expr.params.length; i += 1) {
4668 AstNode *child = node->data.fn_call_expr.params.at(i);
4485 AstNode **child = &node->data.fn_call_expr.params.at(i);
46694486 // determine the expected type for each parameter
46704487 TypeTableEntry *expected_param_type = nullptr;
4671 int fn_proto_i = i + (struct_type ? 1 : 0);
4488 int fn_proto_i = i + (struct_node ? 1 : 0);
46724489 if (fn_proto_i < src_param_count) {
46734490 expected_param_type = fn_type->data.fn.fn_type_id.param_info[fn_proto_i].type;
46744491 }
4675 analyze_expression(g, import, context, expected_param_type, child);
4492 analyze_expression(g, import, context, expected_param_type, *child);
4493
4494 ConstExprValue *const_arg_val = &get_resolved_expr(*child)->const_val;
4495 if (!const_arg_val->ok) {
4496 all_args_const_expr = false;
4497 }
46764498 }
46774499
46784500 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
......@@ -4681,6 +4503,27 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
46814503 return return_type;
46824504 }
46834505
4506 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
4507 if (ok_invocation && fn_table_entry && fn_table_entry->is_pure) {
4508 if (fn_table_entry->anal_state == FnAnalStateReady) {
4509 analyze_fn_body(g, fn_table_entry);
4510 }
4511 if (all_args_const_expr) {
4512 if (fn_table_entry->is_pure && fn_table_entry->anal_state == FnAnalStateComplete) {
4513 ConstExprValue *result_val = &get_resolved_expr(node)->const_val;
4514 if (eval_fn(g, node, fn_table_entry, result_val, 1000, struct_node)) {
4515 // function evaluation generated an error
4516 return g->builtin_types.entry_invalid;
4517 }
4518 return return_type;
4519 }
4520 }
4521 }
4522 if (!ok_invocation || !fn_table_entry || !fn_table_entry->is_pure) {
4523 // calling an impure fn is impure
4524 mark_impure_fn(context);
4525 }
4526
46844527 if (handle_is_ptr(return_type)) {
46854528 context->fn_entry->cast_alloca_list.append(node);
46864529 }
......@@ -4689,13 +4532,13 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
46894532}
46904533
46914534static TypeTableEntry *analyze_fn_call_raw(CodeGen *g, ImportTableEntry *import, BlockContext *context,
4692 TypeTableEntry *expected_type, AstNode *node, FnTableEntry *fn_table_entry, TypeTableEntry *struct_type)
4535 TypeTableEntry *expected_type, AstNode *node, FnTableEntry *fn_table_entry, AstNode *struct_node)
46934536{
46944537 assert(node->type == NodeTypeFnCallExpr);
46954538
46964539 node->data.fn_call_expr.fn_entry = fn_table_entry;
46974540
4698 return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_type);
4541 return analyze_fn_call_ptr(g, import, context, expected_type, node, fn_table_entry->type_entry, struct_node);
46994542}
47004543
47014544static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *import, BlockContext *parent_context,
......@@ -4721,7 +4564,7 @@ static TypeTableEntry *analyze_generic_fn_call(CodeGen *g, ImportTableEntry *imp
47214564 generic_fn_type_id->generic_param_count = actual_param_count;
47224565 generic_fn_type_id->generic_params = allocate<GenericParamValue>(actual_param_count);
47234566
4724 BlockContext *child_context = import->block_context;
4567 BlockContext *child_context = decl_node->owner->block_context;
47254568 for (int i = 0; i < actual_param_count; i += 1) {
47264569 AstNode *generic_param_decl_node = decl_node->data.fn_proto.generic_params.at(i);
47274570 assert(generic_param_decl_node->type == NodeTypeParamDecl);
......@@ -4861,17 +4704,17 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
48614704 return analyze_cast_expr(g, import, context, node);
48624705 }
48634706 } else if (invoke_type_entry->id == TypeTableEntryIdFn) {
4864 TypeTableEntry *bare_struct_type;
4707 AstNode *struct_node;
48654708 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
48664709 fn_ref_expr->data.field_access_expr.is_member_fn)
48674710 {
4868 bare_struct_type = fn_ref_expr->data.field_access_expr.bare_struct_type;
4711 struct_node = fn_ref_expr->data.field_access_expr.struct_expr;
48694712 } else {
4870 bare_struct_type = nullptr;
4713 struct_node = nullptr;
48714714 }
48724715
48734716 return analyze_fn_call_raw(g, import, context, expected_type, node,
4874 const_val->data.x_fn, bare_struct_type);
4717 const_val->data.x_fn, struct_node);
48754718 } else if (invoke_type_entry->id == TypeTableEntryIdGenericFn) {
48764719 return analyze_generic_fn_call(g, import, context, expected_type, node, const_val->data.x_type);
48774720 } else {
......@@ -5421,6 +5264,8 @@ static TypeTableEntry *analyze_block_expr(CodeGen *g, ImportTableEntry *import,
54215264static TypeTableEntry *analyze_asm_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
54225265 TypeTableEntry *expected_type, AstNode *node)
54235266{
5267 mark_impure_fn(context);
5268
54245269 node->data.asm_expr.return_count = 0;
54255270 TypeTableEntry *return_type = g->builtin_types.entry_void;
54265271 for (int i = 0; i < node->data.asm_expr.output_list.length; i += 1) {
......@@ -5641,8 +5486,10 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
56415486 if (fn_proto_node->data.fn_proto.skip) {
56425487 // we detected an error with this function definition which prevents us
56435488 // from further analyzing it.
5489 fn_table_entry->anal_state = FnAnalStateSkipped;
56445490 return;
56455491 }
5492 fn_table_entry->anal_state = FnAnalStateProbing;
56465493
56475494 BlockContext *context = node->data.fn_def.block_context;
56485495
......@@ -5676,6 +5523,10 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
56765523 param_decl_node->data.param_decl.variable = var;
56775524
56785525 var->gen_arg_index = fn_type->data.fn.gen_param_info[i].gen_index;
5526
5527 if (!type->deep_const) {
5528 fn_table_entry->is_pure = false;
5529 }
56795530 }
56805531
56815532 TypeTableEntry *expected_type = fn_type->data.fn.fn_type_id.return_type;
......@@ -5697,6 +5548,8 @@ static void analyze_fn_body(CodeGen *g, FnTableEntry *fn_table_entry) {
56975548 buf_ptr(&label->decl_node->data.label.name)));
56985549 }
56995550 }
5551
5552 fn_table_entry->anal_state = FnAnalStateComplete;
57005553}
57015554
57025555static void add_top_level_decl(CodeGen *g, ImportTableEntry *import, BlockContext *block_context,
......@@ -6005,7 +5858,9 @@ void semantic_analyze(CodeGen *g) {
60055858
60065859 for (int i = 0; i < g->fn_defs.length; i += 1) {
60075860 FnTableEntry *fn_entry = g->fn_defs.at(i);
6008 analyze_fn_body(g, fn_entry);
5861 if (fn_entry->anal_state == FnAnalStateReady) {
5862 analyze_fn_body(g, fn_entry);
5863 }
60095864 }
60105865}
60115866
src/ast_render.cpp+6-2
......@@ -326,9 +326,9 @@ static void render_node(AstRender *ar, AstNode *node) {
326326 AstNode *statement = node->data.block.statements.at(i);
327327 print_indent(ar);
328328 render_node(ar, statement);
329 fprintf(ar->f, ";\n");
329330 }
330331 ar->indent -= ar->indent_size;
331 fprintf(ar->f, "\n");
332332 print_indent(ar);
333333 fprintf(ar->f, "}");
334334 break;
......@@ -438,7 +438,11 @@ static void render_node(AstRender *ar, AstNode *node) {
438438 fprintf(ar->f, ")");
439439 break;
440440 case NodeTypeArrayAccessExpr:
441 zig_panic("TODO");
441 render_node(ar, node->data.array_access_expr.array_ref_expr);
442 fprintf(ar->f, "[");
443 render_node(ar, node->data.array_access_expr.subscript);
444 fprintf(ar->f, "]");
445 break;
442446 case NodeTypeSliceExpr:
443447 zig_panic("TODO");
444448 case NodeTypeFieldAccessExpr:
src/bignum.cpp+5
......@@ -71,6 +71,11 @@ bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed) {
7171 }
7272}
7373
74void bignum_truncate(BigNum *bn, int bit_count) {
75 assert(bn->kind == BigNumKindInt);
76 bn->data.x_uint &= (1LL << bit_count) - 1;
77}
78
7479uint64_t bignum_to_twos_complement(BigNum *bn) {
7580 assert(bn->kind == BigNumKindInt);
7681
src/bignum.hpp+2
......@@ -47,6 +47,8 @@ void bignum_negate(BigNum *dest, BigNum *op);
4747void bignum_cast_to_float(BigNum *dest, BigNum *op);
4848void bignum_cast_to_int(BigNum *dest, BigNum *op);
4949
50void bignum_truncate(BigNum *dest, int bit_count);
51
5052// returns the result of the comparison
5153bool bignum_cmp_eq(BigNum *op1, BigNum *op2);
5254bool bignum_cmp_neq(BigNum *op1, BigNum *op2);
src/codegen.cpp+24-7
......@@ -1074,15 +1074,12 @@ static LLVMValueRef gen_field_access_expr(CodeGen *g, AstNode *node, bool is_lva
10741074
10751075 AstNode *struct_expr = node->data.field_access_expr.struct_expr;
10761076 TypeTableEntry *struct_type = get_expr_type(struct_expr);
1077 Buf *name = &node->data.field_access_expr.field_name;
10781077
10791078 if (struct_type->id == TypeTableEntryIdArray) {
1080 if (buf_eql_str(name, "len")) {
1081 return LLVMConstInt(g->builtin_types.entry_isize->type_ref,
1082 struct_type->data.array.len, false);
1083 } else {
1084 zig_panic("gen_field_access_expr bad array field");
1085 }
1079 Buf *name = &node->data.field_access_expr.field_name;
1080 assert(buf_eql_str(name, "len"));
1081 return LLVMConstInt(g->builtin_types.entry_isize->type_ref,
1082 struct_type->data.array.len, false);
10861083 } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
10871084 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
10881085 {
......@@ -3036,6 +3033,7 @@ static void gen_const_globals(CodeGen *g) {
30363033 } else {
30373034 expr->const_llvm_val = gen_const_val(g, type_entry, const_val);
30383035 }
3036 assert(expr->const_llvm_val);
30393037 }
30403038}
30413039
......@@ -3466,23 +3464,27 @@ static void define_builtin_types(CodeGen *g) {
34663464 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNamespace);
34673465 buf_init_from_str(&entry->name, "(namespace)");
34683466 entry->zero_bits = true;
3467 entry->deep_const = true;
34693468 g->builtin_types.entry_namespace = entry;
34703469 }
34713470 {
34723471 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitFloat);
34733472 buf_init_from_str(&entry->name, "(float literal)");
34743473 entry->zero_bits = true;
3474 entry->deep_const = true;
34753475 g->builtin_types.entry_num_lit_float = entry;
34763476 }
34773477 {
34783478 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdNumLitInt);
34793479 buf_init_from_str(&entry->name, "(integer literal)");
34803480 entry->zero_bits = true;
3481 entry->deep_const = true;
34813482 g->builtin_types.entry_num_lit_int = entry;
34823483 }
34833484 {
34843485 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUndefLit);
34853486 buf_init_from_str(&entry->name, "(undefined)");
3487 entry->deep_const = true;
34863488 g->builtin_types.entry_undef = entry;
34873489 }
34883490
......@@ -3492,6 +3494,7 @@ static void define_builtin_types(CodeGen *g) {
34923494 for (;;) {
34933495 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
34943496 entry->type_ref = LLVMIntType(size_in_bits);
3497 entry->deep_const = true;
34953498
34963499 const char u_or_i = is_signed ? 'i' : 'u';
34973500 buf_resize(&entry->name, 0);
......@@ -3537,6 +3540,7 @@ static void define_builtin_types(CodeGen *g) {
35373540
35383541 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
35393542 entry->type_ref = LLVMIntType(size_in_bits);
3543 entry->deep_const = true;
35403544
35413545 buf_init_from_str(&entry->name, info->name);
35423546
......@@ -3556,6 +3560,7 @@ static void define_builtin_types(CodeGen *g) {
35563560 {
35573561 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdBool);
35583562 entry->type_ref = LLVMInt1Type();
3563 entry->deep_const = true;
35593564 buf_init_from_str(&entry->name, "bool");
35603565 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref);
35613566 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref);
......@@ -3568,6 +3573,7 @@ static void define_builtin_types(CodeGen *g) {
35683573 }
35693574 {
35703575 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
3576 entry->deep_const = true;
35713577 entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8);
35723578 buf_init_from_str(&entry->name, "isize");
35733579 entry->data.integral.is_signed = true;
......@@ -3584,6 +3590,7 @@ static void define_builtin_types(CodeGen *g) {
35843590 }
35853591 {
35863592 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdInt);
3593 entry->deep_const = true;
35873594 entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8);
35883595 buf_init_from_str(&entry->name, "usize");
35893596 entry->data.integral.is_signed = false;
......@@ -3600,6 +3607,7 @@ static void define_builtin_types(CodeGen *g) {
36003607 }
36013608 {
36023609 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
3610 entry->deep_const = true;
36033611 entry->type_ref = LLVMFloatType();
36043612 buf_init_from_str(&entry->name, "f32");
36053613 entry->data.floating.bit_count = 32;
......@@ -3615,6 +3623,7 @@ static void define_builtin_types(CodeGen *g) {
36153623 }
36163624 {
36173625 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
3626 entry->deep_const = true;
36183627 entry->type_ref = LLVMDoubleType();
36193628 buf_init_from_str(&entry->name, "f64");
36203629 entry->data.floating.bit_count = 64;
......@@ -3630,6 +3639,7 @@ static void define_builtin_types(CodeGen *g) {
36303639 }
36313640 {
36323641 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdFloat);
3642 entry->deep_const = true;
36333643 entry->type_ref = LLVMX86FP80Type();
36343644 buf_init_from_str(&entry->name, "c_long_double");
36353645 entry->data.floating.bit_count = 80;
......@@ -3645,6 +3655,7 @@ static void define_builtin_types(CodeGen *g) {
36453655 }
36463656 {
36473657 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdVoid);
3658 entry->deep_const = true;
36483659 entry->type_ref = LLVMVoidType();
36493660 entry->zero_bits = true;
36503661 buf_init_from_str(&entry->name, "void");
......@@ -3657,6 +3668,7 @@ static void define_builtin_types(CodeGen *g) {
36573668 }
36583669 {
36593670 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdUnreachable);
3671 entry->deep_const = true;
36603672 entry->type_ref = LLVMVoidType();
36613673 entry->zero_bits = true;
36623674 buf_init_from_str(&entry->name, "unreachable");
......@@ -3666,6 +3678,7 @@ static void define_builtin_types(CodeGen *g) {
36663678 }
36673679 {
36683680 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdMetaType);
3681 entry->deep_const = true;
36693682 buf_init_from_str(&entry->name, "type");
36703683 entry->zero_bits = true;
36713684 g->builtin_types.entry_type = entry;
......@@ -3688,6 +3701,7 @@ static void define_builtin_types(CodeGen *g) {
36883701
36893702 {
36903703 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdPureError);
3704 entry->deep_const = true;
36913705 buf_init_from_str(&entry->name, "error");
36923706
36933707 // TODO allow overriding this type and keep track of max value and emit an
......@@ -3703,6 +3717,7 @@ static void define_builtin_types(CodeGen *g) {
37033717
37043718 {
37053719 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
3720 entry->deep_const = true;
37063721 entry->zero_bits = true; // only allowed at compile time
37073722 buf_init_from_str(&entry->name, "@OS");
37083723 uint32_t field_count = target_os_count();
......@@ -3728,6 +3743,7 @@ static void define_builtin_types(CodeGen *g) {
37283743
37293744 {
37303745 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
3746 entry->deep_const = true;
37313747 entry->zero_bits = true; // only allowed at compile time
37323748 buf_init_from_str(&entry->name, "@Arch");
37333749 uint32_t field_count = target_arch_count();
......@@ -3759,6 +3775,7 @@ static void define_builtin_types(CodeGen *g) {
37593775
37603776 {
37613777 TypeTableEntry *entry = new_type_table_entry(TypeTableEntryIdEnum);
3778 entry->deep_const = true;
37623779 entry->zero_bits = true; // only allowed at compile time
37633780 buf_init_from_str(&entry->name, "@Environ");
37643781 uint32_t field_count = target_environ_count();
src/error.cpp+2
......@@ -12,6 +12,8 @@ const char *err_str(int err) {
1212 case ErrorFileNotFound: return "file not found";
1313 case ErrorFileSystem: return "file system error";
1414 case ErrorFileTooBig: return "file too big";
15 case ErrorDivByZero: return "division by zero";
16 case ErrorOverflow: return "overflow";
1517 }
1618 return "(invalid error)";
1719}
src/error.hpp+2
......@@ -19,6 +19,8 @@ enum Error {
1919 ErrorFileNotFound,
2020 ErrorFileSystem,
2121 ErrorFileTooBig,
22 ErrorDivByZero,
23 ErrorOverflow
2224};
2325
2426const char *err_str(int err);
src/eval.cpp created+1191
......@@ -0,0 +1,1191 @@
1#include "eval.hpp"
2#include "analyze.hpp"
3#include "error.hpp"
4
5static bool eval_fn_args(EvalFnRoot *efr, FnTableEntry *fn, ConstExprValue *args, ConstExprValue *out_val);
6
7bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry) {
8 switch (type_entry->id) {
9 case TypeTableEntryIdEnum:
10 {
11 ConstEnumValue *enum1 = &a->data.x_enum;
12 ConstEnumValue *enum2 = &b->data.x_enum;
13 if (enum1->tag == enum2->tag) {
14 TypeEnumField *enum_field = &type_entry->data.enumeration.fields[enum1->tag];
15 if (type_has_bits(enum_field->type_entry)) {
16 zig_panic("TODO const expr analyze enum special value for equality");
17 } else {
18 return true;
19 }
20 }
21 return false;
22 }
23 case TypeTableEntryIdMetaType:
24 return a->data.x_type == b->data.x_type;
25 case TypeTableEntryIdVoid:
26 return true;
27 case TypeTableEntryIdPureError:
28 return a->data.x_err.err == b->data.x_err.err;
29 case TypeTableEntryIdFn:
30 return a->data.x_fn == b->data.x_fn;
31 case TypeTableEntryIdBool:
32 return a->data.x_bool == b->data.x_bool;
33 case TypeTableEntryIdInt:
34 case TypeTableEntryIdFloat:
35 case TypeTableEntryIdNumLitFloat:
36 case TypeTableEntryIdNumLitInt:
37 return bignum_cmp_eq(&a->data.x_bignum, &b->data.x_bignum);
38 case TypeTableEntryIdPointer:
39 zig_panic("TODO");
40 case TypeTableEntryIdArray:
41 zig_panic("TODO");
42 case TypeTableEntryIdStruct:
43 zig_panic("TODO");
44 case TypeTableEntryIdUndefLit:
45 zig_panic("TODO");
46 case TypeTableEntryIdMaybe:
47 zig_panic("TODO");
48 case TypeTableEntryIdErrorUnion:
49 zig_panic("TODO");
50 case TypeTableEntryIdTypeDecl:
51 zig_panic("TODO");
52 case TypeTableEntryIdNamespace:
53 zig_panic("TODO");
54 case TypeTableEntryIdGenericFn:
55 case TypeTableEntryIdInvalid:
56 case TypeTableEntryIdUnreachable:
57 zig_unreachable();
58 }
59 zig_unreachable();
60}
61
62
63static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out);
64
65static bool eval_block(EvalFn *ef, AstNode *node, ConstExprValue *out) {
66 assert(node->type == NodeTypeBlock);
67
68 EvalScope *my_scope = allocate<EvalScope>(1);
69 my_scope->block_context = node->block_context;
70 ef->scope_stack.append(my_scope);
71
72 for (int i = 0; i < node->data.block.statements.length; i += 1) {
73 AstNode *child = node->data.block.statements.at(i);
74 memset(out, 0, sizeof(ConstExprValue));
75 if (eval_expr(ef, child, out)) return true;
76 }
77
78 ef->scope_stack.pop();
79
80 return false;
81}
82
83static bool eval_return(EvalFn *ef, AstNode *node, ConstExprValue *out) {
84 assert(node->type == NodeTypeReturnExpr);
85
86 eval_expr(ef, node->data.return_expr.expr, ef->return_expr);
87 return true;
88}
89
90static bool eval_bool_bin_op_bool(bool a, BinOpType bin_op, bool b) {
91 if (bin_op == BinOpTypeBoolOr) {
92 return a || b;
93 } else if (bin_op == BinOpTypeBoolAnd) {
94 return a && b;
95 } else {
96 zig_unreachable();
97 }
98}
99
100static int eval_const_expr_bin_op_bignum(ConstExprValue *op1_val, ConstExprValue *op2_val,
101 ConstExprValue *out_val, bool (*bignum_fn)(BigNum *, BigNum *, BigNum *))
102{
103 bool overflow = bignum_fn(&out_val->data.x_bignum, &op1_val->data.x_bignum, &op2_val->data.x_bignum);
104 if (overflow) {
105 return ErrorOverflow;
106 }
107
108 out_val->ok = true;
109 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
110 return 0;
111}
112
113int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
114 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val)
115{
116 assert(op1_val->ok);
117 assert(op2_val->ok);
118
119 switch (bin_op) {
120 case BinOpTypeAssign:
121 case BinOpTypeAssignTimes:
122 case BinOpTypeAssignDiv:
123 case BinOpTypeAssignMod:
124 case BinOpTypeAssignPlus:
125 case BinOpTypeAssignMinus:
126 case BinOpTypeAssignBitShiftLeft:
127 case BinOpTypeAssignBitShiftRight:
128 case BinOpTypeAssignBitAnd:
129 case BinOpTypeAssignBitXor:
130 case BinOpTypeAssignBitOr:
131 case BinOpTypeAssignBoolAnd:
132 case BinOpTypeAssignBoolOr:
133 out_val->ok = true;
134 return 0;
135 case BinOpTypeBoolOr:
136 case BinOpTypeBoolAnd:
137 assert(op1_type->id == TypeTableEntryIdBool);
138 assert(op2_type->id == TypeTableEntryIdBool);
139 out_val->data.x_bool = eval_bool_bin_op_bool(op1_val->data.x_bool, bin_op, op2_val->data.x_bool);
140 out_val->ok = true;
141 out_val->depends_on_compile_var = op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
142 return 0;
143 case BinOpTypeCmpEq:
144 case BinOpTypeCmpNotEq:
145 case BinOpTypeCmpLessThan:
146 case BinOpTypeCmpGreaterThan:
147 case BinOpTypeCmpLessOrEq:
148 case BinOpTypeCmpGreaterOrEq:
149 {
150 bool type_can_gt_lt_cmp = (op1_type->id == TypeTableEntryIdNumLitFloat ||
151 op1_type->id == TypeTableEntryIdNumLitInt ||
152 op1_type->id == TypeTableEntryIdFloat ||
153 op1_type->id == TypeTableEntryIdInt);
154 bool answer;
155 if (type_can_gt_lt_cmp) {
156 bool (*bignum_cmp)(BigNum *, BigNum *);
157 if (bin_op == BinOpTypeCmpEq) {
158 bignum_cmp = bignum_cmp_eq;
159 } else if (bin_op == BinOpTypeCmpNotEq) {
160 bignum_cmp = bignum_cmp_neq;
161 } else if (bin_op == BinOpTypeCmpLessThan) {
162 bignum_cmp = bignum_cmp_lt;
163 } else if (bin_op == BinOpTypeCmpGreaterThan) {
164 bignum_cmp = bignum_cmp_gt;
165 } else if (bin_op == BinOpTypeCmpLessOrEq) {
166 bignum_cmp = bignum_cmp_lte;
167 } else if (bin_op == BinOpTypeCmpGreaterOrEq) {
168 bignum_cmp = bignum_cmp_gte;
169 } else {
170 zig_unreachable();
171 }
172
173 answer = bignum_cmp(&op1_val->data.x_bignum, &op2_val->data.x_bignum);
174 } else {
175 bool are_equal = const_values_equal(op1_val, op2_val, op1_type);
176 if (bin_op == BinOpTypeCmpEq) {
177 answer = are_equal;
178 } else if (bin_op == BinOpTypeCmpNotEq) {
179 answer = !are_equal;
180 } else {
181 zig_unreachable();
182 }
183 }
184
185 out_val->depends_on_compile_var =
186 op1_val->depends_on_compile_var || op2_val->depends_on_compile_var;
187 out_val->data.x_bool = answer;
188 out_val->ok = true;
189 return 0;
190 }
191 case BinOpTypeAdd:
192 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_add);
193 case BinOpTypeBinOr:
194 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_or);
195 case BinOpTypeBinXor:
196 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_xor);
197 case BinOpTypeBinAnd:
198 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_and);
199 case BinOpTypeBitShiftLeft:
200 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shl);
201 case BinOpTypeBitShiftRight:
202 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_shr);
203 case BinOpTypeSub:
204 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_sub);
205 case BinOpTypeMult:
206 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mul);
207 case BinOpTypeDiv:
208 {
209 bool is_int = false;
210 bool is_float = false;
211 if (op1_type->id == TypeTableEntryIdInt ||
212 op1_type->id == TypeTableEntryIdNumLitInt)
213 {
214 is_int = true;
215 } else if (op1_type->id == TypeTableEntryIdFloat ||
216 op1_type->id == TypeTableEntryIdNumLitFloat)
217 {
218 is_float = true;
219 }
220 if ((is_int && op2_val->data.x_bignum.data.x_uint == 0) ||
221 (is_float && op2_val->data.x_bignum.data.x_float == 0.0))
222 {
223 return ErrorDivByZero;
224 } else {
225 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_div);
226 }
227 }
228 case BinOpTypeMod:
229 return eval_const_expr_bin_op_bignum(op1_val, op2_val, out_val, bignum_mod);
230 case BinOpTypeUnwrapMaybe:
231 zig_panic("TODO");
232 case BinOpTypeStrCat:
233 zig_panic("TODO");
234 case BinOpTypeInvalid:
235 zig_unreachable();
236 }
237 zig_unreachable();
238}
239
240static bool eval_bin_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
241 assert(node->type == NodeTypeBinOpExpr);
242
243 AstNode *op1 = node->data.bin_op_expr.op1;
244 AstNode *op2 = node->data.bin_op_expr.op2;
245
246 TypeTableEntry *op1_type = get_resolved_expr(op1)->type_entry;
247 TypeTableEntry *op2_type = get_resolved_expr(op2)->type_entry;
248
249 ConstExprValue op1_val = {0};
250 if (eval_expr(ef, op1, &op1_val)) return true;
251
252 ConstExprValue op2_val = {0};
253 if (eval_expr(ef, op2, &op2_val)) return true;
254
255 BinOpType bin_op = node->data.bin_op_expr.bin_op;
256
257 int err;
258 if ((err = eval_const_expr_bin_op(&op1_val, op1_type, bin_op, &op2_val, op2_type, out_val))) {
259 ef->root->abort = true;
260 if (err == ErrorDivByZero) {
261 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
262 buf_sprintf("function evaluation caused division by zero"));
263 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
264 add_error_note(ef->root->codegen, msg, node, buf_sprintf("division by zero here"));
265 } else if (err == ErrorOverflow) {
266 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
267 buf_sprintf("function evaluation caused overflow"));
268 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
269 add_error_note(ef->root->codegen, msg, node, buf_sprintf("overflow occurred here"));
270 } else {
271 zig_unreachable();
272 }
273 return true;
274 }
275
276 assert(out_val->ok);
277
278 return false;
279}
280
281static EvalVar *find_var(EvalFn *ef, Buf *name) {
282 int scope_index = ef->scope_stack.length - 1;
283 while (scope_index >= 0) {
284 EvalScope *scope = ef->scope_stack.at(scope_index);
285 for (int var_i = 0; var_i < scope->vars.length; var_i += 1) {
286 EvalVar *var = &scope->vars.at(var_i);
287 if (buf_eql_buf(var->name, name)) {
288 return var;
289 }
290 }
291 scope_index -= 1;
292 }
293
294 return nullptr;
295}
296
297static bool eval_symbol_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
298 assert(node->type == NodeTypeSymbol);
299
300 Buf *name = &node->data.symbol_expr.symbol;
301 EvalVar *var = find_var(ef, name);
302 assert(var);
303
304 *out_val = var->value;
305
306 return false;
307}
308
309static TypeTableEntry *resolve_expr_type(AstNode *node) {
310 Expr *expr = get_resolved_expr(node);
311 TypeTableEntry *type_entry = expr->type_entry;
312 assert(type_entry->id == TypeTableEntryIdMetaType);
313 ConstExprValue *const_val = &expr->const_val;
314 assert(const_val->ok);
315 return const_val->data.x_type;
316}
317
318static bool eval_container_init_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
319 assert(node->type == NodeTypeContainerInitExpr);
320
321 AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
322 ContainerInitKind kind = container_init_expr->kind;
323 TypeTableEntry *container_type = resolve_expr_type(container_init_expr->type);
324 out_val->ok = true;
325
326 if (container_type->id == TypeTableEntryIdStruct &&
327 !container_type->data.structure.is_unknown_size_array &&
328 kind == ContainerInitKindStruct)
329 {
330 int expr_field_count = container_init_expr->entries.length;
331 int actual_field_count = container_type->data.structure.src_field_count;
332 assert(expr_field_count == actual_field_count);
333
334 out_val->data.x_struct.fields = allocate<ConstExprValue*>(actual_field_count);
335
336 for (int i = 0; i < expr_field_count; i += 1) {
337 AstNode *val_field_node = container_init_expr->entries.at(i);
338 assert(val_field_node->type == NodeTypeStructValueField);
339
340 TypeStructField *type_field = val_field_node->data.struct_val_field.type_struct_field;
341 int field_index = type_field->src_index;
342
343 ConstExprValue src_field_val = {0};
344 if (eval_expr(ef, val_field_node->data.struct_val_field.expr, &src_field_val)) return true;
345
346 ConstExprValue *dest_field_val = allocate<ConstExprValue>(1);
347 *dest_field_val = src_field_val;
348
349 out_val->data.x_struct.fields[field_index] = dest_field_val;
350 out_val->depends_on_compile_var = out_val->depends_on_compile_var ||
351 src_field_val.depends_on_compile_var;
352 }
353 } else if (container_type->id == TypeTableEntryIdVoid) {
354 return false;
355 } else if (container_type->id == TypeTableEntryIdUnreachable) {
356 ef->root->abort = true;
357 ErrorMsg *msg = add_node_error(ef->root->codegen, ef->root->fn->fn_def_node,
358 buf_sprintf("function evaluation reached unreachable expression"));
359 add_error_note(ef->root->codegen, msg, ef->root->call_node, buf_sprintf("called from here"));
360 add_error_note(ef->root->codegen, msg, node, buf_sprintf("unreachable expression here"));
361 return true;
362 } else if (container_type->id == TypeTableEntryIdStruct &&
363 container_type->data.structure.is_unknown_size_array &&
364 kind == ContainerInitKindArray)
365 {
366
367 int elem_count = container_init_expr->entries.length;
368
369 out_val->ok = true;
370 out_val->data.x_array.fields = allocate<ConstExprValue*>(elem_count);
371
372 for (int i = 0; i < elem_count; i += 1) {
373 AstNode *elem_node = container_init_expr->entries.at(i);
374
375 ConstExprValue *elem_val = allocate<ConstExprValue>(1);
376 if (eval_expr(ef, elem_node, elem_val)) return true;
377
378 assert(elem_val->ok);
379
380 out_val->data.x_array.fields[i] = elem_val;
381 out_val->depends_on_compile_var = out_val->depends_on_compile_var ||
382 elem_val->depends_on_compile_var;
383 }
384 } else {
385 zig_panic("TODO");
386 }
387
388
389 return false;
390}
391
392static bool eval_if_bool_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
393 assert(node->type == NodeTypeIfBoolExpr);
394
395 ConstExprValue cond_val = {0};
396 if (eval_expr(ef, node->data.if_bool_expr.condition, &cond_val)) return true;
397
398 AstNode *exec_node = cond_val.data.x_bool ?
399 node->data.if_bool_expr.then_block : node->data.if_bool_expr.else_node;
400
401 if (exec_node) {
402 if (eval_expr(ef, exec_node, out_val)) return true;
403 }
404 out_val->ok = true;
405 return false;
406}
407
408void eval_const_expr_implicit_cast(CastOp cast_op,
409 ConstExprValue *other_val, TypeTableEntry *other_type,
410 ConstExprValue *const_val, TypeTableEntry *new_type)
411{
412 const_val->depends_on_compile_var = other_val->depends_on_compile_var;
413 const_val->undef = other_val->undef;
414
415 assert(other_val != const_val);
416 switch (cast_op) {
417 case CastOpNoCast:
418 zig_unreachable();
419 case CastOpNoop:
420 case CastOpWidenOrShorten:
421 *const_val = *other_val;
422 break;
423 case CastOpPointerReinterpret:
424 if (other_type->id == TypeTableEntryIdPointer &&
425 new_type->id == TypeTableEntryIdPointer)
426 {
427 TypeTableEntry *other_child_type = other_type->data.pointer.child_type;
428 TypeTableEntry *new_child_type = new_type->data.pointer.child_type;
429
430 if ((other_child_type->id == TypeTableEntryIdInt ||
431 other_child_type->id == TypeTableEntryIdFloat) &&
432 (new_child_type->id == TypeTableEntryIdInt ||
433 new_child_type->id == TypeTableEntryIdFloat))
434 {
435 ConstExprValue **ptr_val = allocate<ConstExprValue*>(1);
436 *ptr_val = other_val->data.x_ptr.ptr[0];
437 const_val->data.x_ptr.ptr = ptr_val;
438 const_val->data.x_ptr.len = 1;
439 const_val->ok = true;
440 const_val->undef = other_val->undef;
441 const_val->depends_on_compile_var = other_val->depends_on_compile_var;
442 } else {
443 zig_panic("TODO");
444 }
445 } else if (other_type->id == TypeTableEntryIdMaybe &&
446 new_type->id == TypeTableEntryIdMaybe)
447 {
448 if (!other_val->data.x_maybe) {
449 *const_val = *other_val;
450 break;
451 }
452
453 TypeTableEntry *other_ptr_type = other_type->data.maybe.child_type;
454 TypeTableEntry *new_ptr_type = new_type->data.maybe.child_type;
455
456 if (other_ptr_type->id == TypeTableEntryIdPointer &&
457 new_ptr_type->id == TypeTableEntryIdPointer)
458 {
459 TypeTableEntry *other_child_type = other_ptr_type->data.pointer.child_type;
460 TypeTableEntry *new_child_type = new_ptr_type->data.pointer.child_type;
461
462 if ((other_child_type->id == TypeTableEntryIdInt ||
463 other_child_type->id == TypeTableEntryIdFloat) &&
464 (new_child_type->id == TypeTableEntryIdInt ||
465 new_child_type->id == TypeTableEntryIdFloat))
466 {
467 ConstExprValue *ptr_parent = allocate<ConstExprValue>(1);
468 ConstExprValue **ptr_val = allocate<ConstExprValue*>(1);
469 *ptr_val = other_val->data.x_maybe->data.x_ptr.ptr[0];
470 ptr_parent->data.x_ptr.ptr = ptr_val;
471 ptr_parent->data.x_ptr.len = 1;
472 ptr_parent->ok = true;
473
474 const_val->data.x_maybe = ptr_parent;
475 const_val->ok = true;
476 const_val->undef = other_val->undef;
477 const_val->depends_on_compile_var = other_val->depends_on_compile_var;
478 } else {
479 zig_panic("TODO");
480 }
481 } else {
482 zig_panic("TODO");
483 }
484 }
485 break;
486 case CastOpPtrToInt:
487 case CastOpIntToPtr:
488 // can't do it
489 break;
490 case CastOpToUnknownSizeArray:
491 {
492 assert(other_type->id == TypeTableEntryIdArray);
493
494 ConstExprValue *all_fields = allocate<ConstExprValue>(2);
495 ConstExprValue *ptr_field = &all_fields[0];
496 ConstExprValue *len_field = &all_fields[1];
497
498 const_val->data.x_struct.fields = allocate<ConstExprValue*>(2);
499 const_val->data.x_struct.fields[0] = ptr_field;
500 const_val->data.x_struct.fields[1] = len_field;
501
502 ptr_field->ok = true;
503 ptr_field->data.x_ptr.ptr = other_val->data.x_array.fields;
504 ptr_field->data.x_ptr.len = other_type->data.array.len;
505
506 len_field->ok = true;
507 bignum_init_unsigned(&len_field->data.x_bignum, other_type->data.array.len);
508
509 const_val->ok = true;
510 break;
511 }
512 case CastOpMaybeWrap:
513 const_val->data.x_maybe = other_val;
514 const_val->ok = true;
515 break;
516 case CastOpErrorWrap:
517 const_val->data.x_err.err = nullptr;
518 const_val->data.x_err.payload = other_val;
519 const_val->ok = true;
520 break;
521 case CastOpPureErrorWrap:
522 const_val->data.x_err.err = other_val->data.x_err.err;
523 const_val->ok = true;
524 break;
525 case CastOpErrToInt:
526 {
527 uint64_t value = other_val->data.x_err.err ? other_val->data.x_err.err->value : 0;
528 bignum_init_unsigned(&const_val->data.x_bignum, value);
529 const_val->ok = true;
530 break;
531 }
532 case CastOpIntToFloat:
533 bignum_cast_to_float(&const_val->data.x_bignum, &other_val->data.x_bignum);
534 const_val->ok = true;
535 break;
536 case CastOpFloatToInt:
537 bignum_cast_to_int(&const_val->data.x_bignum, &other_val->data.x_bignum);
538 const_val->ok = true;
539 break;
540 case CastOpBoolToInt:
541 bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_bool ? 1 : 0);
542 const_val->ok = true;
543 break;
544 }
545}
546
547static bool int_type_depends_on_compile_var(CodeGen *g, TypeTableEntry *int_type) {
548 assert(int_type->id == TypeTableEntryIdInt);
549
550 for (int i = 0; i < CIntTypeCount; i += 1) {
551 if (int_type == g->builtin_types.entry_c_int[i]) {
552 return true;
553 }
554 }
555 return false;
556}
557
558void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max) {
559 if (type_entry->id == TypeTableEntryIdInt) {
560 const_val->ok = true;
561 const_val->depends_on_compile_var = int_type_depends_on_compile_var(g, type_entry);
562 if (is_max) {
563 if (type_entry->data.integral.is_signed) {
564 int64_t val;
565 if (type_entry->data.integral.bit_count == 64) {
566 val = INT64_MAX;
567 } else if (type_entry->data.integral.bit_count == 32) {
568 val = INT32_MAX;
569 } else if (type_entry->data.integral.bit_count == 16) {
570 val = INT16_MAX;
571 } else if (type_entry->data.integral.bit_count == 8) {
572 val = INT8_MAX;
573 } else {
574 zig_unreachable();
575 }
576 bignum_init_signed(&const_val->data.x_bignum, val);
577 } else {
578 uint64_t val;
579 if (type_entry->data.integral.bit_count == 64) {
580 val = UINT64_MAX;
581 } else if (type_entry->data.integral.bit_count == 32) {
582 val = UINT32_MAX;
583 } else if (type_entry->data.integral.bit_count == 16) {
584 val = UINT16_MAX;
585 } else if (type_entry->data.integral.bit_count == 8) {
586 val = UINT8_MAX;
587 } else {
588 zig_unreachable();
589 }
590 bignum_init_unsigned(&const_val->data.x_bignum, val);
591 }
592 } else {
593 if (type_entry->data.integral.is_signed) {
594 int64_t val;
595 if (type_entry->data.integral.bit_count == 64) {
596 val = INT64_MIN;
597 } else if (type_entry->data.integral.bit_count == 32) {
598 val = INT32_MIN;
599 } else if (type_entry->data.integral.bit_count == 16) {
600 val = INT16_MIN;
601 } else if (type_entry->data.integral.bit_count == 8) {
602 val = INT8_MIN;
603 } else {
604 zig_unreachable();
605 }
606 bignum_init_signed(&const_val->data.x_bignum, val);
607 } else {
608 bignum_init_unsigned(&const_val->data.x_bignum, 0);
609 }
610 }
611 } else if (type_entry->id == TypeTableEntryIdFloat) {
612 zig_panic("TODO analyze_min_max_value float");
613 } else if (type_entry->id == TypeTableEntryIdBool) {
614 const_val->ok = true;
615 const_val->data.x_bool = is_max;
616 } else {
617 zig_unreachable();
618 }
619}
620
621static bool eval_min_max(EvalFn *ef, AstNode *node, ConstExprValue *out_val, bool is_max) {
622 assert(node->type == NodeTypeFnCallExpr);
623 AstNode *type_node = node->data.fn_call_expr.params.at(0);
624 TypeTableEntry *type_entry = resolve_expr_type(type_node);
625 eval_min_max_value(ef->root->codegen, type_entry, out_val, is_max);
626 return false;
627}
628
629static bool eval_fn_with_overflow(EvalFn *ef, AstNode *node, ConstExprValue *out_val,
630 bool (*bignum_fn)(BigNum *dest, BigNum *op1, BigNum *op2))
631{
632 assert(node->type == NodeTypeFnCallExpr);
633
634 AstNode *type_node = node->data.fn_call_expr.params.at(0);
635 TypeTableEntry *int_type = resolve_expr_type(type_node);
636 assert(int_type->id == TypeTableEntryIdInt);
637
638 AstNode *op1_node = node->data.fn_call_expr.params.at(1);
639 AstNode *op2_node = node->data.fn_call_expr.params.at(2);
640 AstNode *result_node = node->data.fn_call_expr.params.at(3);
641
642 ConstExprValue op1_val = {0};
643 if (eval_expr(ef, op1_node, &op1_val)) return true;
644
645 ConstExprValue op2_val = {0};
646 if (eval_expr(ef, op2_node, &op2_val)) return true;
647
648 ConstExprValue result_ptr_val = {0};
649 if (eval_expr(ef, result_node, &result_ptr_val)) return true;
650
651 ConstExprValue *result_val = result_ptr_val.data.x_ptr.ptr[0];
652
653 out_val->ok = true;
654 bool overflow = bignum_fn(&result_val->data.x_bignum, &op1_val.data.x_bignum, &op2_val.data.x_bignum);
655
656 overflow = overflow || !bignum_fits_in_bits(&result_val->data.x_bignum,
657 int_type->data.integral.bit_count, int_type->data.integral.is_signed);
658
659 out_val->data.x_bool = overflow;
660
661 if (overflow) {
662 bignum_truncate(&result_val->data.x_bignum, int_type->data.integral.bit_count);
663 }
664
665 return false;
666}
667
668static bool eval_fn_call_builtin(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
669 assert(node->type == NodeTypeFnCallExpr);
670
671 BuiltinFnEntry *builtin_fn = node->data.fn_call_expr.builtin_fn;
672 switch (builtin_fn->id) {
673 case BuiltinFnIdMaxValue:
674 return eval_min_max(ef, node, out_val, true);
675 case BuiltinFnIdMinValue:
676 return eval_min_max(ef, node, out_val, false);
677 case BuiltinFnIdMulWithOverflow:
678 return eval_fn_with_overflow(ef, node, out_val, bignum_mul);
679 case BuiltinFnIdAddWithOverflow:
680 return eval_fn_with_overflow(ef, node, out_val, bignum_add);
681 case BuiltinFnIdSubWithOverflow:
682 return eval_fn_with_overflow(ef, node, out_val, bignum_sub);
683 case BuiltinFnIdMemcpy:
684 case BuiltinFnIdMemset:
685 case BuiltinFnIdSizeof:
686 case BuiltinFnIdAlignof:
687 case BuiltinFnIdMemberCount:
688 case BuiltinFnIdTypeof:
689 case BuiltinFnIdCInclude:
690 case BuiltinFnIdCDefine:
691 case BuiltinFnIdCUndef:
692 case BuiltinFnIdCompileVar:
693 case BuiltinFnIdConstEval:
694 case BuiltinFnIdCtz:
695 case BuiltinFnIdClz:
696 case BuiltinFnIdImport:
697 case BuiltinFnIdCImport:
698 case BuiltinFnIdErrName:
699 zig_panic("TODO");
700 case BuiltinFnIdBreakpoint:
701 case BuiltinFnIdInvalid:
702 zig_unreachable();
703 }
704
705 return false;
706}
707
708static bool eval_fn_call_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
709 assert(node->type == NodeTypeFnCallExpr);
710
711 AstNode *fn_ref_expr = node->data.fn_call_expr.fn_ref_expr;
712 CastOp cast_op = node->data.fn_call_expr.cast_op;
713 if (node->data.fn_call_expr.is_builtin) {
714 return eval_fn_call_builtin(ef, node, out_val);
715 } else if (cast_op != CastOpNoCast) {
716 TypeTableEntry *new_type = resolve_expr_type(fn_ref_expr);
717 AstNode *param_node = node->data.fn_call_expr.params.at(0);
718 TypeTableEntry *old_type = get_resolved_expr(param_node)->type_entry;
719 ConstExprValue param_val = {0};
720 if (eval_expr(ef, param_node, &param_val)) return true;
721 eval_const_expr_implicit_cast(cast_op, &param_val, old_type, out_val, new_type);
722 return false;
723 }
724
725 if (node->data.fn_call_expr.enum_type) {
726 zig_panic("TODO");
727 }
728
729 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
730
731 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
732 fn_ref_expr->data.field_access_expr.is_member_fn)
733 {
734 zig_panic("TODO");
735 }
736
737 if (!fn_table_entry) {
738 ConstExprValue fn_val = {0};
739 if (eval_expr(ef, fn_ref_expr, &fn_val)) return true;
740 fn_table_entry = fn_val.data.x_fn;
741 }
742
743 int param_count = node->data.fn_call_expr.params.length;
744 ConstExprValue *args = allocate<ConstExprValue>(param_count);
745 for (int i = 0; i < param_count; i += 1) {
746 AstNode *param_expr_node = node->data.fn_call_expr.params.at(i);
747 ConstExprValue *param_val = &args[i];
748 if (eval_expr(ef, param_expr_node, param_val)) return true;
749 }
750
751 ef->root->branches_used += 1;
752
753 eval_fn_args(ef->root, fn_table_entry, args, out_val);
754 return false;
755}
756
757static bool eval_field_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
758 assert(node->type == NodeTypeFieldAccessExpr);
759
760 AstNode *struct_expr = node->data.field_access_expr.struct_expr;
761 TypeTableEntry *struct_type = get_resolved_expr(struct_expr)->type_entry;
762
763 if (struct_type->id == TypeTableEntryIdArray) {
764 Buf *name = &node->data.field_access_expr.field_name;
765 assert(buf_eql_str(name, "len"));
766 zig_panic("TODO");
767 } else if (struct_type->id == TypeTableEntryIdStruct || (struct_type->id == TypeTableEntryIdPointer &&
768 struct_type->data.pointer.child_type->id == TypeTableEntryIdStruct))
769 {
770 TypeStructField *tsf = node->data.field_access_expr.type_struct_field;
771 assert(tsf);
772 if (struct_type->id == TypeTableEntryIdStruct) {
773 ConstExprValue struct_val = {0};
774 if (eval_expr(ef, struct_expr, &struct_val)) return true;
775 ConstExprValue *field_value = struct_val.data.x_struct.fields[tsf->src_index];
776 *out_val = *field_value;
777 assert(out_val->ok);
778 } else {
779 zig_panic("TODO");
780 }
781 } else if (struct_type->id == TypeTableEntryIdMetaType) {
782 TypeTableEntry *child_type = resolve_expr_type(struct_expr);
783 if (child_type->id == TypeTableEntryIdPureError) {
784 *out_val = get_resolved_expr(node)->const_val;
785 } else {
786 zig_panic("TODO");
787 }
788 } else if (struct_type->id == TypeTableEntryIdNamespace) {
789 zig_panic("TODO");
790 } else {
791 zig_unreachable();
792 }
793
794 return false;
795}
796
797static bool eval_for_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
798 assert(node->type == NodeTypeForExpr);
799
800 AstNode *array_node = node->data.for_expr.array_expr;
801 AstNode *elem_node = node->data.for_expr.elem_node;
802 AstNode *index_node = node->data.for_expr.index_node;
803 AstNode *body_node = node->data.for_expr.body;
804
805 TypeTableEntry *array_type = get_resolved_expr(array_node)->type_entry;
806
807 ConstExprValue array_val = {0};
808 if (eval_expr(ef, array_node, &array_val)) return true;
809
810 assert(elem_node->type == NodeTypeSymbol);
811 Buf *elem_var_name = &elem_node->data.symbol_expr.symbol;
812
813 Buf *index_var_name = nullptr;
814 if (index_node) {
815 assert(index_node->type == NodeTypeSymbol);
816 index_var_name = &index_node->data.symbol_expr.symbol;
817 }
818
819 uint64_t it_index = 0;
820 uint64_t array_len;
821 ConstExprValue **array_ptr_val;
822 if (array_type->id == TypeTableEntryIdArray) {
823 array_len = array_type->data.array.len;
824 array_ptr_val = array_val.data.x_array.fields;
825 } else if (array_type->id == TypeTableEntryIdStruct) {
826 ConstExprValue *len_field_val = array_val.data.x_struct.fields[1];
827 array_len = len_field_val->data.x_bignum.data.x_uint;
828 array_ptr_val = array_val.data.x_struct.fields[0]->data.x_ptr.ptr;
829 } else {
830 zig_unreachable();
831 }
832
833 EvalScope *my_scope = allocate<EvalScope>(1);
834 my_scope->block_context = body_node->block_context;
835 ef->scope_stack.append(my_scope);
836
837 for (; it_index < array_len; it_index += 1) {
838 my_scope->vars.resize(0);
839
840 if (index_var_name) {
841 my_scope->vars.add_one();
842 EvalVar *index_var = &my_scope->vars.last();
843 index_var->name = index_var_name;
844 memset(&index_var->value, 0, sizeof(ConstExprValue));
845 index_var->value.ok = true;
846 bignum_init_unsigned(&index_var->value.data.x_bignum, it_index);
847 }
848 {
849 my_scope->vars.add_one();
850 EvalVar *elem_var = &my_scope->vars.last();
851 elem_var->name = elem_var_name;
852 elem_var->value = *array_ptr_val[it_index];
853 }
854
855 ConstExprValue body_val = {0};
856 if (eval_expr(ef, body_node, &body_val)) return true;
857
858 ef->root->branches_used += 1;
859 }
860
861 ef->scope_stack.pop();
862
863 return false;
864}
865
866static bool eval_array_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
867 assert(node->type == NodeTypeArrayAccessExpr);
868
869 AstNode *array_ref_node = node->data.array_access_expr.array_ref_expr;
870 AstNode *index_node = node->data.array_access_expr.subscript;
871
872 TypeTableEntry *array_type = get_resolved_expr(array_ref_node)->type_entry;
873
874 ConstExprValue array_val = {0};
875 if (eval_expr(ef, array_ref_node, &array_val)) return true;
876
877 ConstExprValue index_val = {0};
878 if (eval_expr(ef, index_node, &index_val)) return true;
879 uint64_t index_int = index_val.data.x_bignum.data.x_uint;
880
881 if (array_type->id == TypeTableEntryIdPointer) {
882 if (index_int >= array_val.data.x_ptr.len) {
883 zig_panic("TODO");
884 }
885 *out_val = *array_val.data.x_ptr.ptr[index_int];
886 } else if (array_type->id == TypeTableEntryIdStruct) {
887 assert(array_type->data.structure.is_unknown_size_array);
888
889 ConstExprValue *len_value = array_val.data.x_struct.fields[1];
890 uint64_t len_int = len_value->data.x_bignum.data.x_uint;
891 if (index_int >= len_int) {
892 zig_panic("TODO");
893 }
894
895 ConstExprValue *ptr_value = array_val.data.x_struct.fields[0];
896 *out_val = *ptr_value->data.x_ptr.ptr[index_int];
897 } else if (array_type->id == TypeTableEntryIdArray) {
898 uint64_t array_len = array_type->data.array.len;
899 if (index_int >= array_len) {
900 zig_panic("TODO");
901 }
902 *out_val = *array_val.data.x_array.fields[index_int];
903 } else {
904 zig_unreachable();
905 }
906
907 return false;
908}
909
910static bool eval_bool_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
911 assert(node->type == NodeTypeBoolLiteral);
912
913 out_val->ok = true;
914 out_val->data.x_bool = node->data.bool_literal.value;
915
916 return false;
917}
918
919static bool eval_prefix_op_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
920 assert(node->type == NodeTypePrefixOpExpr);
921
922 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
923 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
924
925 ConstExprValue expr_val = {0};
926 if (eval_expr(ef, expr_node, &expr_val)) return true;
927
928 TypeTableEntry *expr_type = get_resolved_expr(expr_node)->type_entry;
929
930 switch (prefix_op) {
931 case PrefixOpBoolNot:
932 *out_val = expr_val;
933 out_val->data.x_bool = !out_val->data.x_bool;
934 break;
935 case PrefixOpDereference:
936 assert(expr_type->id == TypeTableEntryIdPointer);
937 *out_val = *expr_val.data.x_ptr.ptr[0];
938 break;
939 case PrefixOpAddressOf:
940 case PrefixOpConstAddressOf:
941 {
942 ConstExprValue *child_val = allocate<ConstExprValue>(1);
943 *child_val = expr_val;
944
945 ConstExprValue **ptr_val = allocate<ConstExprValue*>(1);
946 *ptr_val = child_val;
947
948 out_val->data.x_ptr.ptr = ptr_val;
949 out_val->data.x_ptr.len = 1;
950 out_val->ok = true;
951 break;
952 }
953 case PrefixOpBinNot:
954 case PrefixOpNegation:
955 case PrefixOpMaybe:
956 case PrefixOpError:
957 case PrefixOpUnwrapError:
958 case PrefixOpUnwrapMaybe:
959 zig_panic("TODO");
960 case PrefixOpInvalid:
961 zig_unreachable();
962 }
963
964 return false;
965}
966
967static bool eval_var_decl_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
968 assert(node->type == NodeTypeVariableDeclaration);
969
970 assert(node->data.variable_declaration.expr);
971
972 EvalScope *my_scope = ef->scope_stack.at(ef->scope_stack.length - 1);
973
974 my_scope->vars.add_one();
975 EvalVar *var = &my_scope->vars.last();
976 var->name = &node->data.variable_declaration.symbol;
977
978 if (eval_expr(ef, node->data.variable_declaration.expr, &var->value)) return true;
979
980 out_val->ok = true;
981
982 return false;
983}
984
985static bool eval_number_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
986 assert(node->type == NodeTypeNumberLiteral);
987 assert(!node->data.number_literal.overflow);
988
989 out_val->ok = true;
990 if (node->data.number_literal.kind == NumLitUInt) {
991 bignum_init_unsigned(&out_val->data.x_bignum, node->data.number_literal.data.x_uint);
992 } else if (node->data.number_literal.kind == NumLitFloat) {
993 bignum_init_float(&out_val->data.x_bignum, node->data.number_literal.data.x_float);
994 } else {
995 zig_unreachable();
996 }
997
998 return false;
999}
1000
1001static bool eval_char_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
1002 assert(node->type == NodeTypeCharLiteral);
1003
1004 out_val->ok = true;
1005 bignum_init_unsigned(&out_val->data.x_bignum, node->data.char_literal.value);
1006
1007 return false;
1008}
1009
1010static bool eval_while_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
1011 assert(node->type == NodeTypeWhileExpr);
1012
1013 AstNode *cond_node = node->data.while_expr.condition;
1014 AstNode *body_node = node->data.while_expr.body;
1015
1016 EvalScope *my_scope = allocate<EvalScope>(1);
1017 my_scope->block_context = body_node->block_context;
1018 ef->scope_stack.append(my_scope);
1019
1020 for (;;) {
1021 my_scope->vars.resize(0);
1022
1023 ConstExprValue cond_val = {0};
1024 if (eval_expr(ef, cond_node, &cond_val)) return true;
1025
1026 if (!cond_val.data.x_bool) break;
1027
1028 ConstExprValue body_val = {0};
1029 if (eval_expr(ef, body_node, &body_val)) return true;
1030
1031 ef->root->branches_used += 1;
1032 }
1033
1034 ef->scope_stack.pop();
1035
1036 return false;
1037}
1038
1039static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
1040 if (ef->root->branches_used > ef->root->branch_quota) {
1041 ef->root->exceeded_quota_node = node;
1042 return true;
1043 }
1044 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
1045 if (const_val->ok) {
1046 *out = *const_val;
1047 return false;
1048 }
1049 switch (node->type) {
1050 case NodeTypeBlock:
1051 return eval_block(ef, node, out);
1052 case NodeTypeReturnExpr:
1053 return eval_return(ef, node, out);
1054 case NodeTypeBinOpExpr:
1055 return eval_bin_op_expr(ef, node, out);
1056 case NodeTypeSymbol:
1057 return eval_symbol_expr(ef, node, out);
1058 case NodeTypeContainerInitExpr:
1059 return eval_container_init_expr(ef, node, out);
1060 case NodeTypeIfBoolExpr:
1061 return eval_if_bool_expr(ef, node, out);
1062 case NodeTypeFnCallExpr:
1063 return eval_fn_call_expr(ef, node, out);
1064 case NodeTypeFieldAccessExpr:
1065 return eval_field_access_expr(ef, node, out);
1066 case NodeTypeForExpr:
1067 return eval_for_expr(ef, node, out);
1068 case NodeTypeArrayAccessExpr:
1069 return eval_array_access_expr(ef, node, out);
1070 case NodeTypeBoolLiteral:
1071 return eval_bool_literal_expr(ef, node, out);
1072 case NodeTypePrefixOpExpr:
1073 return eval_prefix_op_expr(ef, node, out);
1074 case NodeTypeVariableDeclaration:
1075 return eval_var_decl_expr(ef, node, out);
1076 case NodeTypeNumberLiteral:
1077 return eval_number_literal_expr(ef, node, out);
1078 case NodeTypeCharLiteral:
1079 return eval_char_literal_expr(ef, node, out);
1080 case NodeTypeWhileExpr:
1081 return eval_while_expr(ef, node, out);
1082 case NodeTypeDefer:
1083 case NodeTypeErrorValueDecl:
1084 case NodeTypeUnwrapErrorExpr:
1085 case NodeTypeStringLiteral:
1086 case NodeTypeSliceExpr:
1087 case NodeTypeNullLiteral:
1088 case NodeTypeUndefinedLiteral:
1089 case NodeTypeIfVarExpr:
1090 case NodeTypeSwitchExpr:
1091 case NodeTypeSwitchProng:
1092 case NodeTypeSwitchRange:
1093 case NodeTypeLabel:
1094 case NodeTypeGoto:
1095 case NodeTypeBreak:
1096 case NodeTypeContinue:
1097 case NodeTypeStructDecl:
1098 case NodeTypeStructField:
1099 case NodeTypeStructValueField:
1100 case NodeTypeArrayType:
1101 case NodeTypeErrorType:
1102 case NodeTypeTypeLiteral:
1103 zig_panic("TODO");
1104 case NodeTypeRoot:
1105 case NodeTypeFnProto:
1106 case NodeTypeFnDef:
1107 case NodeTypeFnDecl:
1108 case NodeTypeUse:
1109 case NodeTypeAsmExpr:
1110 case NodeTypeParamDecl:
1111 case NodeTypeDirective:
1112 case NodeTypeTypeDecl:
1113 zig_unreachable();
1114 }
1115}
1116
1117static bool eval_fn_args(EvalFnRoot *efr, FnTableEntry *fn, ConstExprValue *args, ConstExprValue *out_val) {
1118 EvalFn ef = {0};
1119 ef.root = efr;
1120 ef.fn = fn;
1121 ef.return_expr = out_val;
1122
1123 EvalScope *root_scope = allocate<EvalScope>(1);
1124 root_scope->block_context = fn->fn_def_node->data.fn_def.body->block_context;
1125 ef.scope_stack.append(root_scope);
1126
1127 int param_count = fn->type_entry->data.fn.fn_type_id.param_count;
1128 for (int i = 0; i < param_count; i += 1) {
1129 AstNode *decl_param_node = fn->proto_node->data.fn_proto.params.at(i);
1130 assert(decl_param_node->type == NodeTypeParamDecl);
1131
1132 ConstExprValue *src_const_val = &args[i];
1133 assert(src_const_val->ok);
1134
1135 root_scope->vars.add_one();
1136 EvalVar *eval_var = &root_scope->vars.last();
1137 eval_var->name = &decl_param_node->data.param_decl.name;
1138 eval_var->value = *src_const_val;
1139 }
1140
1141 return eval_expr(&ef, fn->fn_def_node->data.fn_def.body, out_val);
1142
1143}
1144
1145bool eval_fn(CodeGen *g, AstNode *node, FnTableEntry *fn, ConstExprValue *out_val,
1146 int branch_quota, AstNode *struct_node)
1147{
1148 assert(node->type == NodeTypeFnCallExpr);
1149
1150 EvalFnRoot efr = {0};
1151 efr.codegen = g;
1152 efr.fn = fn;
1153 efr.call_node = node;
1154 efr.branch_quota = branch_quota;
1155
1156 int call_param_count = node->data.fn_call_expr.params.length;
1157 int type_param_count = fn->type_entry->data.fn.fn_type_id.param_count;
1158 ConstExprValue *args = allocate<ConstExprValue>(type_param_count);
1159 int next_arg_index = 0;
1160 if (struct_node) {
1161 ConstExprValue *struct_val = &get_resolved_expr(struct_node)->const_val;
1162 assert(struct_val->ok);
1163 args[next_arg_index] = *struct_val;
1164 next_arg_index += 1;
1165 }
1166 for (int call_index = 0; call_index < call_param_count; call_index += 1) {
1167 AstNode *call_param_node = node->data.fn_call_expr.params.at(call_index);
1168 ConstExprValue *src_const_val = &get_resolved_expr(call_param_node)->const_val;
1169 assert(src_const_val->ok);
1170 args[next_arg_index] = *src_const_val;
1171 next_arg_index += 1;
1172 }
1173 eval_fn_args(&efr, fn, args, out_val);
1174
1175 if (efr.exceeded_quota_node) {
1176 ErrorMsg *msg = add_node_error(g, fn->fn_def_node,
1177 buf_sprintf("function evaluation exceeded %d branches", efr.branch_quota));
1178
1179 add_error_note(g, msg, efr.call_node, buf_sprintf("called from here"));
1180 add_error_note(g, msg, efr.exceeded_quota_node, buf_sprintf("quota exceeded here"));
1181 return true;
1182 }
1183
1184 if (efr.abort) {
1185 return true;
1186 }
1187
1188 assert(out_val->ok);
1189 return false;
1190}
1191
src/eval.hpp created+26
......@@ -0,0 +1,26 @@
1/*
2 * Copyright (c) 2016 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_EVAL_HPP
9#define ZIG_EVAL_HPP
10
11#include "all_types.hpp"
12
13bool eval_fn(CodeGen *g, AstNode *node, FnTableEntry *fn, ConstExprValue *out_val, int branch_quota,
14 AstNode *struct_node);
15
16bool const_values_equal(ConstExprValue *a, ConstExprValue *b, TypeTableEntry *type_entry);
17int eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
18 BinOpType bin_op, ConstExprValue *op2_val, TypeTableEntry *op2_type, ConstExprValue *out_val);
19
20void eval_const_expr_implicit_cast(CastOp cast_op,
21 ConstExprValue *other_val, TypeTableEntry *other_type,
22 ConstExprValue *const_val, TypeTableEntry *new_type);
23
24void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max);
25
26#endif
src/parser.cpp+15-7
......@@ -2927,6 +2927,7 @@ static void clone_subtree_list(ZigList<AstNode *> *dest, ZigList<AstNode *> *src
29272927 dest->resize(src->length);
29282928 for (int i = 0; i < src->length; i += 1) {
29292929 dest->at(i) = ast_clone_subtree(src->at(i), next_node_index);
2930 dest->at(i)->parent_field = &dest->at(i);
29302931 }
29312932}
29322933
......@@ -2958,11 +2959,12 @@ AstNode *ast_clone_subtree(AstNode *old_node, uint32_t *next_node_index) {
29582959 memcpy(new_node, old_node, sizeof(AstNode));
29592960 new_node->create_index = *next_node_index;
29602961 *next_node_index += 1;
2962 new_node->parent_field = nullptr;
29612963
29622964 switch (new_node->type) {
29632965 case NodeTypeRoot:
2964 clone_subtree_list(&new_node->data.root.top_level_decls, &old_node->data.root.top_level_decls,
2965 next_node_index);
2966 clone_subtree_list(&new_node->data.root.top_level_decls,
2967 &old_node->data.root.top_level_decls, next_node_index);
29662968 break;
29672969 case NodeTypeFnProto:
29682970 clone_subtree_tld(&new_node->data.fn_proto.top_level_decl, &old_node->data.fn_proto.top_level_decl,
......@@ -3036,15 +3038,21 @@ AstNode *ast_clone_subtree(AstNode *old_node, uint32_t *next_node_index) {
30363038 // none
30373039 break;
30383040 case NodeTypePrefixOpExpr:
3039 clone_subtree_field(&new_node->data.prefix_op_expr.primary_expr, old_node->data.prefix_op_expr.primary_expr, next_node_index);
3041 clone_subtree_field(&new_node->data.prefix_op_expr.primary_expr,
3042 old_node->data.prefix_op_expr.primary_expr, next_node_index);
30403043 break;
30413044 case NodeTypeFnCallExpr:
3042 clone_subtree_field(&new_node->data.fn_call_expr.fn_ref_expr, old_node->data.fn_call_expr.fn_ref_expr, next_node_index);
3043 clone_subtree_list(&new_node->data.fn_call_expr.params, &old_node->data.fn_call_expr.params, next_node_index);
3045 assert(!old_node->data.fn_call_expr.resolved_expr.has_global_const);
3046 clone_subtree_field(&new_node->data.fn_call_expr.fn_ref_expr,
3047 old_node->data.fn_call_expr.fn_ref_expr, next_node_index);
3048 clone_subtree_list(&new_node->data.fn_call_expr.params,
3049 &old_node->data.fn_call_expr.params, next_node_index);
30443050 break;
30453051 case NodeTypeArrayAccessExpr:
3046 clone_subtree_field(&new_node->data.array_access_expr.array_ref_expr, old_node->data.array_access_expr.array_ref_expr, next_node_index);
3047 clone_subtree_field(&new_node->data.array_access_expr.subscript, old_node->data.array_access_expr.subscript, next_node_index);
3052 clone_subtree_field(&new_node->data.array_access_expr.array_ref_expr,
3053 old_node->data.array_access_expr.array_ref_expr, next_node_index);
3054 clone_subtree_field(&new_node->data.array_access_expr.subscript,
3055 old_node->data.array_access_expr.subscript, next_node_index);
30483056 break;
30493057 case NodeTypeSliceExpr:
30503058 clone_subtree_field(&new_node->data.slice_expr.array_ref_expr, old_node->data.slice_expr.array_ref_expr, next_node_index);
std/rand.zig+1
......@@ -7,6 +7,7 @@ pub struct Rand {
77 index: isize,
88
99 /// Initialize random state with the given seed.
10 #static_eval_enable(false)
1011 pub fn init(seed: u32) -> Rand {
1112 var r: Rand = undefined;
1213 r.index = 0;
test/run_tests.cpp+29-122
......@@ -218,6 +218,7 @@ pub fn bar_function() {
218218 )SOURCE");
219219
220220 add_source_file(tc, "other.zig", R"SOURCE(
221#static_eval_enable(false)
221222pub fn foo_function() -> bool {
222223 // this one conflicts with the one from foo
223224 return true;
......@@ -406,20 +407,6 @@ pub fn main(args: [][]u8) -> %void {
406407}
407408 )SOURCE", "loop\nloop\nloop\nloop\n");
408409
409 add_simple_case("implicit cast after unreachable", R"SOURCE(
410const io = @import("std").io;
411pub fn main(args: [][]u8) -> %void {
412 const x = outer();
413 if (x == 1234) {
414 %%io.stdout.printf("OK\n");
415 }
416}
417fn inner() -> i32 { 1234 }
418fn outer() -> isize {
419 return inner();
420}
421 )SOURCE", "OK\n");
422
423410 add_simple_case("@sizeof() and @typeof()", R"SOURCE(
424411const io = @import("std").io;
425412const x: u16 = 13;
......@@ -431,23 +418,6 @@ pub fn main(args: [][]u8) -> %void {
431418}
432419 )SOURCE", "2\n");
433420
434 add_simple_case("member functions", R"SOURCE(
435const io = @import("std").io;
436struct Rand {
437 seed: u32,
438 pub fn get_seed(r: Rand) -> u32 {
439 r.seed
440 }
441}
442pub fn main(args: [][]u8) -> %void {
443 const r = Rand {.seed = 1234};
444 if (r.get_seed() != 1234) {
445 %%io.stdout.printf("BAD seed\n");
446 }
447 %%io.stdout.printf("OK\n");
448}
449 )SOURCE", "OK\n");
450
451421 add_simple_case("pointer dereferencing", R"SOURCE(
452422const io = @import("std").io;
453423
......@@ -565,24 +535,6 @@ pub fn main(args: [][]u8) -> %void {
565535 "min i64: -9223372036854775808\n");
566536
567537
568 add_simple_case("else if expression", R"SOURCE(
569const io = @import("std").io;
570pub fn main(args: [][]u8) -> %void {
571 if (f(1) == 1) {
572 %%io.stdout.printf("OK\n");
573 }
574}
575fn f(c: u8) -> u8 {
576 if (c == 0) {
577 0
578 } else if (c == 1) {
579 1
580 } else {
581 2
582 }
583}
584 )SOURCE", "OK\n");
585
586538 add_simple_case("overflow intrinsics", R"SOURCE(
587539const io = @import("std").io;
588540pub fn main(args: [][]u8) -> %void {
......@@ -730,29 +682,6 @@ pub fn main(args: [][]u8) -> %void {
730682}
731683 )SOURCE", "OK\n");
732684
733 add_simple_case("%% binary operator", R"SOURCE(
734const io = @import("std").io;
735error ItBroke;
736fn g(x: bool) -> %isize {
737 if (x) {
738 error.ItBroke
739 } else {
740 10
741 }
742}
743pub fn main(args: [][]u8) -> %void {
744 const a = g(true) %% 3;
745 const b = g(false) %% 3;
746 if (a != 3) {
747 %%io.stdout.printf("BAD\n");
748 }
749 if (b != 10) {
750 %%io.stdout.printf("BAD\n");
751 }
752 %%io.stdout.printf("OK\n");
753}
754 )SOURCE", "OK\n");
755
756685 add_simple_case("string concatenation", R"SOURCE(
757686const io = @import("std").io;
758687pub fn main(args: [][]u8) -> %void {
......@@ -808,54 +737,6 @@ pub fn main(args: [][]u8) -> %void {
808737}
809738 )SOURCE", "OK\n");
810739
811 add_simple_case("unwrap simple value from error", R"SOURCE(
812const io = @import("std").io;
813fn do() -> %isize {
814 13
815}
816
817pub fn main(args: [][]u8) -> %void {
818 const i = %%do();
819 if (i != 13) {
820 %%io.stdout.printf("BAD\n");
821 }
822 %%io.stdout.printf("OK\n");
823}
824 )SOURCE", "OK\n");
825
826 add_simple_case("store member function in variable", R"SOURCE(
827const io = @import("std").io;
828struct Foo {
829 x: i32,
830 fn member(foo: Foo) -> i32 { foo.x }
831}
832pub fn main(args: [][]u8) -> %void {
833 const instance = Foo { .x = 1234, };
834 const member_fn = Foo.member;
835 const result = member_fn(instance);
836 if (result != 1234) {
837 %%io.stdout.printf("BAD\n");
838 }
839 %%io.stdout.printf("OK\n");
840}
841 )SOURCE", "OK\n");
842
843 add_simple_case("call member function directly", R"SOURCE(
844const io = @import("std").io;
845struct Foo {
846 x: i32,
847 fn member(foo: Foo) -> i32 { foo.x }
848}
849pub fn main(args: [][]u8) -> %void {
850 const instance = Foo { .x = 1234, };
851 const result = Foo.member(instance);
852 if (result != 1234) {
853 %%io.stdout.printf("BAD\n");
854 }
855 %%io.stdout.printf("OK\n");
856}
857 )SOURCE", "OK\n");
858
859740 add_simple_case("call result of if else expression", R"SOURCE(
860741const io = @import("std").io;
861742fn a() -> []u8 { "a\n" }
......@@ -1496,7 +1377,8 @@ fn a(x: i32) {
14961377struct Foo {
14971378 y: [get()]u8,
14981379}
1499fn get() -> isize { 1 }
1380var global_var: isize = 1;
1381fn get() -> isize { global_var }
15001382 )SOURCE", 1, ".tmp_source.zig:3:9: error: unable to evaluate constant expression");
15011383
15021384
......@@ -1599,6 +1481,31 @@ fn foo() {
15991481 const pointer = &array[0];
16001482}
16011483 )SOURCE", 1, ".tmp_source.zig:4:27: error: out of bounds array access");
1484
1485 add_compile_fail_case("compile time division by zero", R"SOURCE(
1486const x = foo(0);
1487fn foo(x: i32) -> i32 {
1488 1 / x
1489}
1490 )SOURCE", 3,
1491 ".tmp_source.zig:3:1: error: function evaluation caused division by zero",
1492 ".tmp_source.zig:2:14: note: called from here",
1493 ".tmp_source.zig:4:7: note: division by zero here");
1494
1495 add_compile_fail_case("branch on undefined value", R"SOURCE(
1496const x = if (undefined) true else false;
1497 )SOURCE", 1, ".tmp_source.zig:2:15: error: branch on undefined value");
1498
1499
1500 add_compile_fail_case("endless loop in function evaluation", R"SOURCE(
1501const seventh_fib_number = fibbonaci(7);
1502fn fibbonaci(x: i32) -> i32 {
1503 return fibbonaci(x - 1) + fibbonaci(x - 2);
1504}
1505 )SOURCE", 3,
1506 ".tmp_source.zig:3:1: error: function evaluation exceeded 1000 branches",
1507 ".tmp_source.zig:2:37: note: called from here",
1508 ".tmp_source.zig:4:40: note: quota exceeded here");
16021509}
16031510
16041511//////////////////////////////////////////////////////////////////////////////
......@@ -1760,7 +1667,7 @@ extern void (*fn_ptr)(void);
17601667 )SOURCE", 2,
17611668 "pub extern var fn_ptr: ?extern fn();",
17621669 R"SOURCE(pub inline fn foo() {
1763 (??fn_ptr)()
1670 (??fn_ptr)();
17641671})SOURCE");
17651672
17661673
test/self_hosted.zig+175-9
......@@ -123,18 +123,18 @@ fn short_circuit() {
123123 var hit_3 = false;
124124 var hit_4 = false;
125125
126 if (true || { assert(false); false }) {
126 if (true || {assert_runtime(false); false}) {
127127 hit_1 = true;
128128 }
129129 if (false || { hit_2 = true; false }) {
130 assert(false);
130 assert_runtime(false);
131131 }
132132
133133 if (true && { hit_3 = true; false }) {
134 %%io.stdout.printf("BAD 3\n");
134 assert_runtime(false);
135135 }
136 if (false && { assert(false); false }) {
137 assert(false);
136 if (false && {assert_runtime(false); false}) {
137 assert_runtime(false);
138138 } else {
139139 hit_4 = true;
140140 }
......@@ -144,6 +144,11 @@ fn short_circuit() {
144144 assert(hit_4);
145145}
146146
147#static_eval_enable(false)
148fn assert_runtime(b: bool) {
149 if (!b) unreachable{}
150}
151
147152#attribute("test")
148153fn modify_operators() {
149154 var i : i32 = 0;
......@@ -410,9 +415,7 @@ error err2;
410415
411416#attribute("test")
412417fn fn_call_of_struct_field() {
413 if (call_struct_field(Foo {.ptr = a_func,}) != 13) {
414 unreachable{};
415 }
418 assert(call_struct_field(Foo {.ptr = a_func,}) == 13);
416419}
417420
418421struct Foo {
......@@ -509,6 +512,7 @@ enum Fruit {
509512 Orange,
510513 Banana,
511514}
515#static_eval_enable(false)
512516fn non_const_switch_on_enum(fruit: Fruit) {
513517 switch (fruit) {
514518 Apple => unreachable{},
......@@ -521,6 +525,7 @@ fn non_const_switch_on_enum(fruit: Fruit) {
521525fn switch_statement() {
522526 non_const_switch(SwitchStatmentFoo.C);
523527}
528#static_eval_enable(false)
524529fn non_const_switch(foo: SwitchStatmentFoo) {
525530 const val: i32 = switch (foo) {
526531 A => 1,
......@@ -549,6 +554,7 @@ enum SwitchProngWithVarEnum {
549554 Two: f32,
550555 Meh,
551556}
557#static_eval_enable(false)
552558fn switch_prong_with_var_fn(a: SwitchProngWithVarEnum) {
553559 switch(a) {
554560 One => |x| {
......@@ -569,6 +575,7 @@ fn err_return_in_assignment() {
569575 %%do_err_return_in_assignment();
570576}
571577
578#static_eval_enable(false)
572579fn do_err_return_in_assignment() -> %void {
573580 var x : i32 = undefined;
574581 x = %return make_a_non_err();
......@@ -608,7 +615,7 @@ fn explicit_cast_maybe_pointers() {
608615
609616#attribute("test")
610617fn const_expr_eval_on_single_expr_blocks() {
611 if (const_expr_eval_on_single_expr_blocks_fn(1, true) != 3) unreachable{}
618 assert(const_expr_eval_on_single_expr_blocks_fn(1, true) == 3);
612619}
613620
614621fn const_expr_eval_on_single_expr_blocks_fn(x: i32, b: bool) -> i32 {
......@@ -736,6 +743,7 @@ fn generic_malloc_free() {
736743 mem_free(u8)(a);
737744}
738745const some_mem : [100]u8 = undefined;
746#static_eval_enable(false)
739747fn mem_alloc(T: type)(n: isize) -> %[]T {
740748 return (&T)(&some_mem[0])[0...n];
741749}
......@@ -789,6 +797,7 @@ var goto_counter: i32 = 0;
789797fn goto_leave_defer_scope() {
790798 test_goto_leave_defer_scope(true);
791799}
800#static_eval_enable(false)
792801fn test_goto_leave_defer_scope(b: bool) {
793802 var it_worked = false;
794803
......@@ -820,3 +829,160 @@ fn cast_small_unsigned_to_larger_signed() {
820829}
821830fn cast_small_unsigned_to_larger_signed_1(x: u8) -> i16 { x }
822831fn cast_small_unsigned_to_larger_signed_2(x: u16) -> isize { x }
832
833
834#attribute("test")
835fn implicit_cast_after_unreachable() {
836 assert(outer() == 1234);
837}
838fn inner() -> i32 { 1234 }
839fn outer() -> isize {
840 return inner();
841}
842
843
844#attribute("test")
845fn else_if_expression() {
846 assert(else_if_expression_f(1) == 1);
847}
848fn else_if_expression_f(c: u8) -> u8 {
849 if (c == 0) {
850 0
851 } else if (c == 1) {
852 1
853 } else {
854 2
855 }
856}
857
858#attribute("test")
859fn err_binary_operator() {
860 const a = err_binary_operator_g(true) %% 3;
861 const b = err_binary_operator_g(false) %% 3;
862 assert(a == 3);
863 assert(b == 10);
864}
865error ItBroke;
866fn err_binary_operator_g(x: bool) -> %isize {
867 if (x) {
868 error.ItBroke
869 } else {
870 10
871 }
872}
873
874#attribute("test")
875fn unwrap_simple_value_from_error() {
876 const i = %%unwrap_simple_value_from_error_do();
877 assert(i == 13);
878}
879fn unwrap_simple_value_from_error_do() -> %isize { 13 }
880
881
882#attribute("test")
883fn store_member_function_in_variable() {
884 const instance = MemberFnTestFoo { .x = 1234, };
885 const member_fn = MemberFnTestFoo.member;
886 const result = member_fn(instance);
887 assert(result == 1234);
888}
889struct MemberFnTestFoo {
890 x: i32,
891 fn member(foo: MemberFnTestFoo) -> i32 { foo.x }
892}
893
894#attribute("test")
895fn call_member_function_directly() {
896 const instance = MemberFnTestFoo { .x = 1234, };
897 const result = MemberFnTestFoo.member(instance);
898 assert(result == 1234);
899}
900
901#attribute("test")
902fn member_functions() {
903 const r = MemberFnRand {.seed = 1234};
904 assert(r.get_seed() == 1234);
905}
906struct MemberFnRand {
907 seed: u32,
908 pub fn get_seed(r: MemberFnRand) -> u32 {
909 r.seed
910 }
911}
912
913#attribute("test")
914fn static_function_evaluation() {
915 assert(statically_added_number == 3);
916}
917const statically_added_number = static_add(1, 2);
918fn static_add(a: i32, b: i32) -> i32 { a + b }
919
920
921#attribute("test")
922fn statically_initalized_list() {
923 assert(static_point_list[0].x == 1);
924 assert(static_point_list[0].y == 2);
925 assert(static_point_list[1].x == 3);
926 assert(static_point_list[1].y == 4);
927}
928struct Point {
929 x: i32,
930 y: i32,
931}
932const static_point_list = []Point { make_point(1, 2), make_point(3, 4) };
933fn make_point(x: i32, y: i32) -> Point {
934 return Point {
935 .x = x,
936 .y = y,
937 };
938}
939
940
941#attribute("test")
942fn static_eval_recursive() {
943 assert(seventh_fib_number == 21);
944}
945const seventh_fib_number = fibbonaci(7);
946fn fibbonaci(x: i32) -> i32 {
947 if (x <= 1) return 1;
948 return fibbonaci(x - 1) + fibbonaci(x - 2);
949}
950
951#attribute("test")
952fn static_eval_while() {
953 assert(static_eval_while_number == 1);
954}
955const static_eval_while_number = static_while_loop_1();
956fn static_while_loop_1() -> i32 {
957 return while_loop_2();
958}
959fn static_while_loop_2() -> i32 {
960 while (true) {
961 return 1;
962 }
963}
964
965#attribute("test")
966fn static_eval_list_init() {
967 assert(static_vec3.data[2] == 1.0);
968}
969const static_vec3 = vec3(0.0, 0.0, 1.0);
970pub struct Vec3 {
971 data: [3]f32,
972}
973pub fn vec3(x: f32, y: f32, z: f32) -> Vec3 {
974 Vec3 {
975 .data = []f32 { x, y, z, },
976 }
977}
978
979
980#attribute("test")
981fn generic_fn_with_implicit_cast() {
982 assert(get_first_byte(u8)([]u8 {13}) == 13);
983 assert(get_first_byte(u16)([]u16 {0, 13}) == 0);
984}
985fn get_byte(ptr: ?&u8) -> u8 {*??ptr}
986fn get_first_byte(T: type)(mem: []T) -> u8 {
987 get_byte((&u8)(&mem[0]))
988}