authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-12 13:30:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-04-12 13:30:52-07:00
logbe4df96e4b80a3307b3661fd5ca3114478499daf
treeb4a65aecebe565e7602b6ebe796e8dc96fb6b049
parentaa89fd3b3e4522fe9199049a4fcc6bdc69f4bfde

passing all tests


5 files changed, 240 insertions(+), 164 deletions(-)

src/analyze.cpp+46-25
...@@ -35,7 +35,8 @@ static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node,...@@ -35,7 +35,8 @@ static TypeTableEntry *resolve_expr_const_val_as_type(CodeGen *g, AstNode *node,
35static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,35static TypeTableEntry *resolve_expr_const_val_as_unsigned_num_lit(CodeGen *g, AstNode *node,
36 TypeTableEntry *expected_type, uint64_t x);36 TypeTableEntry *expected_type, uint64_t x);
37static AstNode *find_decl(BlockContext *context, Buf *name);37static AstNode *find_decl(BlockContext *context, Buf *name);
38static 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);
39static TopLevelDecl *get_as_top_level_decl(AstNode *node);40static TopLevelDecl *get_as_top_level_decl(AstNode *node);
40static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,41static VariableTableEntry *analyze_variable_declaration_raw(CodeGen *g, ImportTableEntry *import,
41 BlockContext *context, AstNode *source_node,42 BlockContext *context, AstNode *source_node,
...@@ -957,6 +958,19 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t...@@ -957,6 +958,19 @@ static void resolve_function_proto(CodeGen *g, AstNode *node, FnTableEntry *fn_t
957 add_node_error(g, directive_node,958 add_node_error(g, directive_node,
958 buf_sprintf("#condition valid only on exported symbols"));959 buf_sprintf("#condition valid only on exported symbols"));
959 }960 }
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 }
960 } else {974 } else {
961 add_node_error(g, directive_node,975 add_node_error(g, directive_node,
962 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));976 buf_sprintf("invalid directive: '%s'", buf_ptr(name)));
...@@ -2227,9 +2241,9 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry...@@ -2227,9 +2241,9 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry
2227 const_val->ok = false;2241 const_val->ok = false;
2228 }2242 }
2229 }2243 }
2230 if (!const_val->ok) {2244 }
2231 context->fn_entry->struct_val_expr_alloca_list.append(codegen);2245 if (!const_val->ok) {
2232 }2246 context->fn_entry->struct_val_expr_alloca_list.append(codegen);
2233 }2247 }
22342248
2235 for (int i = 0; i < actual_field_count; i += 1) {2249 for (int i = 0; i < actual_field_count; i += 1) {
...@@ -2381,7 +2395,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -2381,7 +2395,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
2381 AstNode *decl_node = entry ? entry->value : nullptr;2395 AstNode *decl_node = entry ? entry->value : nullptr;
2382 if (decl_node) {2396 if (decl_node) {
2383 bool pointer_only = false;2397 bool pointer_only = false;
2384 return analyze_decl_ref(g, node, decl_node, pointer_only);2398 return analyze_decl_ref(g, node, decl_node, pointer_only, context);
2385 } else {2399 } else {
2386 add_node_error(g, node,2400 add_node_error(g, node,
2387 buf_sprintf("container '%s' has no member called '%s'",2401 buf_sprintf("container '%s' has no member called '%s'",
...@@ -2408,7 +2422,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i...@@ -2408,7 +2422,7 @@ static TypeTableEntry *analyze_field_access_expr(CodeGen *g, ImportTableEntry *i
2408 add_error_note(g, msg, decl_node, buf_sprintf("declared here"));2422 add_error_note(g, msg, decl_node, buf_sprintf("declared here"));
2409 }2423 }
2410 bool pointer_only = false;2424 bool pointer_only = false;
2411 return analyze_decl_ref(g, node, decl_node, pointer_only);2425 return analyze_decl_ref(g, node, decl_node, pointer_only, context);
2412 } else {2426 } else {
2413 const char *import_name = namespace_import->path ? buf_ptr(namespace_import->path) : "(C import)";2427 const char *import_name = namespace_import->path ? buf_ptr(namespace_import->path) : "(C import)";
2414 add_node_error(g, node,2428 add_node_error(g, node,
...@@ -2674,8 +2688,21 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *...@@ -2674,8 +2688,21 @@ static TypeTableEntry *analyze_error_literal_expr(CodeGen *g, ImportTableEntry *
2674 return g->builtin_types.entry_invalid;2688 return g->builtin_types.entry_invalid;
2675}2689}
26762690
2677static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var) {2691static bool var_is_pure(VariableTableEntry *var, BlockContext *context) {
2692 if (var->block_context->fn_entry == context->fn_entry) {
2693 // variable was declared in the current function, so it's OK.
2694 return true;
2695 }
2696 return var->is_const && var->type->deep_const;
2697}
2698
2699static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, VariableTableEntry *var,
2700 BlockContext *context)
2701{
2678 get_resolved_expr(source_node)->variable = var;2702 get_resolved_expr(source_node)->variable = var;
2703 if (!var_is_pure(var, context)) {
2704 mark_impure_fn(context);
2705 }
2679 if (var->is_const && var->val_node) {2706 if (var->is_const && var->val_node) {
2680 ConstExprValue *other_const_val = &get_resolved_expr(var->val_node)->const_val;2707 ConstExprValue *other_const_val = &get_resolved_expr(var->val_node)->const_val;
2681 if (other_const_val->ok) {2708 if (other_const_val->ok) {
...@@ -2686,7 +2713,7 @@ static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, Variabl...@@ -2686,7 +2713,7 @@ static TypeTableEntry *analyze_var_ref(CodeGen *g, AstNode *source_node, Variabl
2686}2713}
26872714
2688static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,2715static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNode *decl_node,
2689 bool pointer_only)2716 bool pointer_only, BlockContext *block_context)
2690{2717{
2691 resolve_top_level_decl(g, decl_node, pointer_only);2718 resolve_top_level_decl(g, decl_node, pointer_only);
2692 TopLevelDecl *tld = get_as_top_level_decl(decl_node);2719 TopLevelDecl *tld = get_as_top_level_decl(decl_node);
...@@ -2696,7 +2723,7 @@ static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNod...@@ -2696,7 +2723,7 @@ static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNod
26962723
2697 if (decl_node->type == NodeTypeVariableDeclaration) {2724 if (decl_node->type == NodeTypeVariableDeclaration) {
2698 VariableTableEntry *var = decl_node->data.variable_declaration.variable;2725 VariableTableEntry *var = decl_node->data.variable_declaration.variable;
2699 return analyze_var_ref(g, source_node, var);2726 return analyze_var_ref(g, source_node, var, block_context);
2700 } else if (decl_node->type == NodeTypeFnProto) {2727 } else if (decl_node->type == NodeTypeFnProto) {
2701 if (decl_node->data.fn_proto.generic_params.length > 0) {2728 if (decl_node->data.fn_proto.generic_params.length > 0) {
2702 TypeTableEntry *type_entry = decl_node->data.fn_proto.generic_fn_type;2729 TypeTableEntry *type_entry = decl_node->data.fn_proto.generic_fn_type;
...@@ -2716,14 +2743,6 @@ static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNod...@@ -2716,14 +2743,6 @@ static TypeTableEntry *analyze_decl_ref(CodeGen *g, AstNode *source_node, AstNod
2716 }2743 }
2717}2744}
27182745
2719static bool var_is_pure(VariableTableEntry *var, TypeTableEntry *var_type, BlockContext *context) {
2720 if (var->block_context->fn_entry == context->fn_entry) {
2721 // variable was declared in the current function, so it's OK.
2722 return true;
2723 }
2724 return var->is_const && var->type->deep_const;
2725}
2726
2727static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,2746static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import, BlockContext *context,
2728 TypeTableEntry *expected_type, AstNode *node, bool pointer_only)2747 TypeTableEntry *expected_type, AstNode *node, bool pointer_only)
2729{2748{
...@@ -2740,16 +2759,13 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,...@@ -2740,16 +2759,13 @@ static TypeTableEntry *analyze_symbol_expr(CodeGen *g, ImportTableEntry *import,
27402759
2741 VariableTableEntry *var = find_variable(g, context, variable_name);2760 VariableTableEntry *var = find_variable(g, context, variable_name);
2742 if (var) {2761 if (var) {
2743 TypeTableEntry *var_type = analyze_var_ref(g, node, var);2762 TypeTableEntry *var_type = analyze_var_ref(g, node, var, context);
2744 if (!var_is_pure(var, var_type, context)) {
2745 mark_impure_fn(context);
2746 }
2747 return var_type;2763 return var_type;
2748 }2764 }
27492765
2750 AstNode *decl_node = find_decl(context, variable_name);2766 AstNode *decl_node = find_decl(context, variable_name);
2751 if (decl_node) {2767 if (decl_node) {
2752 return analyze_decl_ref(g, node, decl_node, pointer_only);2768 return analyze_decl_ref(g, node, decl_node, pointer_only, context);
2753 }2769 }
27542770
2755 if (import->any_imports_failed) {2771 if (import->any_imports_failed) {
...@@ -2992,7 +3008,8 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,...@@ -2992,7 +3008,8 @@ static TypeTableEntry *analyze_bin_op_expr(CodeGen *g, ImportTableEntry *import,
2992 }3008 }
29933009
2994 analyze_expression(g, import, context, expected_rhs_type, node->data.bin_op_expr.op2);3010 analyze_expression(g, import, context, expected_rhs_type, node->data.bin_op_expr.op2);
2995 return resolve_expr_const_val_as_void(g, node);3011 // not const ok because expression has side effects
3012 return g->builtin_types.entry_void;
2996 }3013 }
2997 case BinOpTypeBoolOr:3014 case BinOpTypeBoolOr:
2998 case BinOpTypeBoolAnd:3015 case BinOpTypeBoolAnd:
...@@ -4473,12 +4490,16 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,...@@ -4473,12 +4490,16 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
4473 actual_param_count += 1;4490 actual_param_count += 1;
4474 }4491 }
44754492
4493 bool ok_invocation = true;
4494
4476 if (fn_type->data.fn.fn_type_id.is_var_args) {4495 if (fn_type->data.fn.fn_type_id.is_var_args) {
4477 if (actual_param_count < src_param_count) {4496 if (actual_param_count < src_param_count) {
4497 ok_invocation = false;
4478 add_node_error(g, node,4498 add_node_error(g, node,
4479 buf_sprintf("expected at least %d arguments, got %d", src_param_count, actual_param_count));4499 buf_sprintf("expected at least %d arguments, got %d", src_param_count, actual_param_count));
4480 }4500 }
4481 } else if (src_param_count != actual_param_count) {4501 } else if (src_param_count != actual_param_count) {
4502 ok_invocation = false;
4482 add_node_error(g, node,4503 add_node_error(g, node,
4483 buf_sprintf("expected %d arguments, got %d", src_param_count, actual_param_count));4504 buf_sprintf("expected %d arguments, got %d", src_param_count, actual_param_count));
4484 }4505 }
...@@ -4517,7 +4538,7 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,...@@ -4517,7 +4538,7 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import,
4517 }4538 }
45184539
4519 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;4540 FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry;
4520 if (fn_table_entry && fn_table_entry->is_pure && all_args_const_expr) {4541 if (ok_invocation && fn_table_entry && fn_table_entry->is_pure && all_args_const_expr) {
4521 if (fn_table_entry->anal_state == FnAnalStateReady) {4542 if (fn_table_entry->anal_state == FnAnalStateReady) {
4522 analyze_fn_body(g, fn_table_entry);4543 analyze_fn_body(g, fn_table_entry);
4523 } else if (fn_table_entry->anal_state == FnAnalStateProbing) {4544 } else if (fn_table_entry->anal_state == FnAnalStateProbing) {
...@@ -4726,7 +4747,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import...@@ -4726,7 +4747,7 @@ static TypeTableEntry *analyze_fn_call_expr(CodeGen *g, ImportTableEntry *import
4726 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&4747 if (fn_ref_expr->type == NodeTypeFieldAccessExpr &&
4727 fn_ref_expr->data.field_access_expr.is_member_fn)4748 fn_ref_expr->data.field_access_expr.is_member_fn)
4728 {4749 {
4729 struct_node = fn_ref_expr;4750 struct_node = fn_ref_expr->data.field_access_expr.struct_expr;
4730 } else {4751 } else {
4731 struct_node = nullptr;4752 struct_node = nullptr;
4732 }4753 }
src/eval.cpp+93-12
...@@ -70,6 +70,7 @@ static bool eval_block(EvalFn *ef, AstNode *node, ConstExprValue *out) {...@@ -70,6 +70,7 @@ static bool eval_block(EvalFn *ef, AstNode *node, ConstExprValue *out) {
7070
71 for (int i = 0; i < node->data.block.statements.length; i += 1) {71 for (int i = 0; i < node->data.block.statements.length; i += 1) {
72 AstNode *child = node->data.block.statements.at(i);72 AstNode *child = node->data.block.statements.at(i);
73 memset(out, 0, sizeof(ConstExprValue));
73 if (eval_expr(ef, child, out)) return true;74 if (eval_expr(ef, child, out)) return true;
74 }75 }
7576
...@@ -109,7 +110,6 @@ void eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,...@@ -109,7 +110,6 @@ void eval_const_expr_bin_op(ConstExprValue *op1_val, TypeTableEntry *op1_type,
109{110{
110 assert(op1_val->ok);111 assert(op1_val->ok);
111 assert(op2_val->ok);112 assert(op2_val->ok);
112 assert(op1_type == op2_type);
113113
114 switch (bin_op) {114 switch (bin_op) {
115 case BinOpTypeAssign:115 case BinOpTypeAssign:
...@@ -275,6 +275,7 @@ static bool eval_symbol_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)...@@ -275,6 +275,7 @@ static bool eval_symbol_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val)
275275
276 Buf *name = &node->data.symbol_expr.symbol;276 Buf *name = &node->data.symbol_expr.symbol;
277 EvalVar *var = find_var(ef, name);277 EvalVar *var = find_var(ef, name);
278 assert(var);
278279
279 *out_val = var->value;280 *out_val = var->value;
280281
...@@ -374,6 +375,8 @@ void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -374,6 +375,8 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
374 *const_val = *other_val;375 *const_val = *other_val;
375 break;376 break;
376 case CastOpPointerReinterpret:377 case CastOpPointerReinterpret:
378 if (other_type->id == TypeTableEntryIdPointer &&
379 new_type->id == TypeTableEntryIdPointer)
377 {380 {
378 TypeTableEntry *other_child_type = other_type->data.pointer.child_type;381 TypeTableEntry *other_child_type = other_type->data.pointer.child_type;
379 TypeTableEntry *new_child_type = new_type->data.pointer.child_type;382 TypeTableEntry *new_child_type = new_type->data.pointer.child_type;
...@@ -393,8 +396,47 @@ void eval_const_expr_implicit_cast(CastOp cast_op,...@@ -393,8 +396,47 @@ void eval_const_expr_implicit_cast(CastOp cast_op,
393 } else {396 } else {
394 zig_panic("TODO");397 zig_panic("TODO");
395 }398 }
396 break;399 } else if (other_type->id == TypeTableEntryIdMaybe &&
400 new_type->id == TypeTableEntryIdMaybe)
401 {
402 if (!other_val->data.x_maybe) {
403 *const_val = *other_val;
404 break;
405 }
406
407 TypeTableEntry *other_ptr_type = other_type->data.maybe.child_type;
408 TypeTableEntry *new_ptr_type = new_type->data.maybe.child_type;
409
410 if (other_ptr_type->id == TypeTableEntryIdPointer &&
411 new_ptr_type->id == TypeTableEntryIdPointer)
412 {
413 TypeTableEntry *other_child_type = other_ptr_type->data.pointer.child_type;
414 TypeTableEntry *new_child_type = new_ptr_type->data.pointer.child_type;
415
416 if ((other_child_type->id == TypeTableEntryIdInt ||
417 other_child_type->id == TypeTableEntryIdFloat) &&
418 (new_child_type->id == TypeTableEntryIdInt ||
419 new_child_type->id == TypeTableEntryIdFloat))
420 {
421 ConstExprValue *ptr_parent = allocate<ConstExprValue>(1);
422 ConstExprValue **ptr_val = allocate<ConstExprValue*>(1);
423 *ptr_val = other_val->data.x_maybe->data.x_ptr.ptr[0];
424 ptr_parent->data.x_ptr.ptr = ptr_val;
425 ptr_parent->data.x_ptr.len = 1;
426 ptr_parent->ok = true;
427
428 const_val->data.x_maybe = ptr_parent;
429 const_val->ok = true;
430 const_val->undef = other_val->undef;
431 const_val->depends_on_compile_var = other_val->depends_on_compile_var;
432 } else {
433 zig_panic("TODO");
434 }
435 } else {
436 zig_panic("TODO");
437 }
397 }438 }
439 break;
398 case CastOpPtrToInt:440 case CastOpPtrToInt:
399 case CastOpIntToPtr:441 case CastOpIntToPtr:
400 // can't do it442 // can't do it
...@@ -684,6 +726,7 @@ static bool eval_field_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou...@@ -684,6 +726,7 @@ static bool eval_field_access_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou
684 if (eval_expr(ef, struct_expr, &struct_val)) return true;726 if (eval_expr(ef, struct_expr, &struct_val)) return true;
685 ConstExprValue *field_value = struct_val.data.x_struct.fields[tsf->src_index];727 ConstExprValue *field_value = struct_val.data.x_struct.fields[tsf->src_index];
686 *out_val = *field_value;728 *out_val = *field_value;
729 assert(out_val->ok);
687 } else {730 } else {
688 zig_panic("TODO");731 zig_panic("TODO");
689 }732 }
...@@ -916,11 +959,45 @@ static bool eval_char_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou...@@ -916,11 +959,45 @@ static bool eval_char_literal_expr(EvalFn *ef, AstNode *node, ConstExprValue *ou
916 return false;959 return false;
917}960}
918961
962static bool eval_while_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val) {
963 assert(node->type == NodeTypeWhileExpr);
964
965 AstNode *cond_node = node->data.while_expr.condition;
966 AstNode *body_node = node->data.while_expr.body;
967
968 EvalScope *my_scope = allocate<EvalScope>(1);
969 my_scope->block_context = body_node->block_context;
970 ef->scope_stack.append(my_scope);
971
972 for (;;) {
973 my_scope->vars.resize(0);
974
975 ConstExprValue cond_val = {0};
976 if (eval_expr(ef, cond_node, &cond_val)) return true;
977
978 if (!cond_val.data.x_bool) break;
979
980 ConstExprValue body_val = {0};
981 if (eval_expr(ef, body_node, &body_val)) return true;
982
983 ef->root->branches_used += 1;
984 }
985
986 ef->scope_stack.pop();
987
988 return false;
989}
990
919static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {991static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
920 if (ef->root->branches_used > ef->root->branch_quota) {992 if (ef->root->branches_used > ef->root->branch_quota) {
921 ef->root->exceeded_quota_node = node;993 ef->root->exceeded_quota_node = node;
922 return true;994 return true;
923 }995 }
996 ConstExprValue *const_val = &get_resolved_expr(node)->const_val;
997 if (const_val->ok) {
998 *out = *const_val;
999 return false;
1000 }
924 switch (node->type) {1001 switch (node->type) {
925 case NodeTypeBlock:1002 case NodeTypeBlock:
926 return eval_block(ef, node, out);1003 return eval_block(ef, node, out);
...@@ -952,23 +1029,16 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {...@@ -952,23 +1029,16 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
952 return eval_number_literal_expr(ef, node, out);1029 return eval_number_literal_expr(ef, node, out);
953 case NodeTypeCharLiteral:1030 case NodeTypeCharLiteral:
954 return eval_char_literal_expr(ef, node, out);1031 return eval_char_literal_expr(ef, node, out);
955 case NodeTypeRoot:1032 case NodeTypeWhileExpr:
956 case NodeTypeFnProto:1033 return eval_while_expr(ef, node, out);
957 case NodeTypeFnDef:
958 case NodeTypeFnDecl:
959 case NodeTypeParamDecl:
960 case NodeTypeDirective:
961 case NodeTypeDefer:1034 case NodeTypeDefer:
962 case NodeTypeTypeDecl:
963 case NodeTypeErrorValueDecl:1035 case NodeTypeErrorValueDecl:
964 case NodeTypeUnwrapErrorExpr:1036 case NodeTypeUnwrapErrorExpr:
965 case NodeTypeStringLiteral:1037 case NodeTypeStringLiteral:
966 case NodeTypeSliceExpr:1038 case NodeTypeSliceExpr:
967 case NodeTypeUse:
968 case NodeTypeNullLiteral:1039 case NodeTypeNullLiteral:
969 case NodeTypeUndefinedLiteral:1040 case NodeTypeUndefinedLiteral:
970 case NodeTypeIfVarExpr:1041 case NodeTypeIfVarExpr:
971 case NodeTypeWhileExpr:
972 case NodeTypeSwitchExpr:1042 case NodeTypeSwitchExpr:
973 case NodeTypeSwitchProng:1043 case NodeTypeSwitchProng:
974 case NodeTypeSwitchRange:1044 case NodeTypeSwitchRange:
...@@ -976,13 +1046,22 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {...@@ -976,13 +1046,22 @@ static bool eval_expr(EvalFn *ef, AstNode *node, ConstExprValue *out) {
976 case NodeTypeGoto:1046 case NodeTypeGoto:
977 case NodeTypeBreak:1047 case NodeTypeBreak:
978 case NodeTypeContinue:1048 case NodeTypeContinue:
979 case NodeTypeAsmExpr:
980 case NodeTypeStructDecl:1049 case NodeTypeStructDecl:
981 case NodeTypeStructField:1050 case NodeTypeStructField:
982 case NodeTypeStructValueField:1051 case NodeTypeStructValueField:
983 case NodeTypeArrayType:1052 case NodeTypeArrayType:
984 case NodeTypeErrorType:1053 case NodeTypeErrorType:
985 case NodeTypeTypeLiteral:1054 case NodeTypeTypeLiteral:
1055 zig_panic("TODO");
1056 case NodeTypeRoot:
1057 case NodeTypeFnProto:
1058 case NodeTypeFnDef:
1059 case NodeTypeFnDecl:
1060 case NodeTypeUse:
1061 case NodeTypeAsmExpr:
1062 case NodeTypeParamDecl:
1063 case NodeTypeDirective:
1064 case NodeTypeTypeDecl:
986 zig_unreachable();1065 zig_unreachable();
987 }1066 }
988}1067}
...@@ -1054,6 +1133,8 @@ bool eval_fn(CodeGen *g, AstNode *node, FnTableEntry *fn, ConstExprValue *out_va...@@ -1054,6 +1133,8 @@ bool eval_fn(CodeGen *g, AstNode *node, FnTableEntry *fn, ConstExprValue *out_va
1054 return true;1133 return true;
1055 }1134 }
10561135
1136 assert(out_val->ok);
1137
1057 return efr.abort;1138 return efr.abort;
1058}1139}
10591140
std/rand.zig+1
...@@ -7,6 +7,7 @@ pub struct Rand {...@@ -7,6 +7,7 @@ pub struct Rand {
7 index: isize,7 index: isize,
88
9 /// Initialize random state with the given seed.9 /// Initialize random state with the given seed.
10 #static_eval_enable(false)
10 pub fn init(seed: u32) -> Rand {11 pub fn init(seed: u32) -> Rand {
11 var r: Rand = undefined;12 var r: Rand = undefined;
12 r.index = 0;13 r.index = 0;
test/run_tests.cpp+3-121
...@@ -218,6 +218,7 @@ pub fn bar_function() {...@@ -218,6 +218,7 @@ pub fn bar_function() {
218 )SOURCE");218 )SOURCE");
219219
220 add_source_file(tc, "other.zig", R"SOURCE(220 add_source_file(tc, "other.zig", R"SOURCE(
221#static_eval_enable(false)
221pub fn foo_function() -> bool {222pub fn foo_function() -> bool {
222 // this one conflicts with the one from foo223 // this one conflicts with the one from foo
223 return true;224 return true;
...@@ -406,20 +407,6 @@ pub fn main(args: [][]u8) -> %void {...@@ -406,20 +407,6 @@ pub fn main(args: [][]u8) -> %void {
406}407}
407 )SOURCE", "loop\nloop\nloop\nloop\n");408 )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
423 add_simple_case("@sizeof() and @typeof()", R"SOURCE(410 add_simple_case("@sizeof() and @typeof()", R"SOURCE(
424const io = @import("std").io;411const io = @import("std").io;
425const x: u16 = 13;412const x: u16 = 13;
...@@ -431,23 +418,6 @@ pub fn main(args: [][]u8) -> %void {...@@ -431,23 +418,6 @@ pub fn main(args: [][]u8) -> %void {
431}418}
432 )SOURCE", "2\n");419 )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
451 add_simple_case("pointer dereferencing", R"SOURCE(421 add_simple_case("pointer dereferencing", R"SOURCE(
452const io = @import("std").io;422const io = @import("std").io;
453423
...@@ -565,24 +535,6 @@ pub fn main(args: [][]u8) -> %void {...@@ -565,24 +535,6 @@ pub fn main(args: [][]u8) -> %void {
565 "min i64: -9223372036854775808\n");535 "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
586 add_simple_case("overflow intrinsics", R"SOURCE(538 add_simple_case("overflow intrinsics", R"SOURCE(
587const io = @import("std").io;539const io = @import("std").io;
588pub fn main(args: [][]u8) -> %void {540pub fn main(args: [][]u8) -> %void {
...@@ -730,29 +682,6 @@ pub fn main(args: [][]u8) -> %void {...@@ -730,29 +682,6 @@ pub fn main(args: [][]u8) -> %void {
730}682}
731 )SOURCE", "OK\n");683 )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
756 add_simple_case("string concatenation", R"SOURCE(685 add_simple_case("string concatenation", R"SOURCE(
757const io = @import("std").io;686const io = @import("std").io;
758pub fn main(args: [][]u8) -> %void {687pub fn main(args: [][]u8) -> %void {
...@@ -808,54 +737,6 @@ pub fn main(args: [][]u8) -> %void {...@@ -808,54 +737,6 @@ pub fn main(args: [][]u8) -> %void {
808}737}
809 )SOURCE", "OK\n");738 )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
859 add_simple_case("call result of if else expression", R"SOURCE(740 add_simple_case("call result of if else expression", R"SOURCE(
860const io = @import("std").io;741const io = @import("std").io;
861fn a() -> []u8 { "a\n" }742fn a() -> []u8 { "a\n" }
...@@ -1496,7 +1377,8 @@ fn a(x: i32) {...@@ -1496,7 +1377,8 @@ fn a(x: i32) {
1496struct Foo {1377struct Foo {
1497 y: [get()]u8,1378 y: [get()]u8,
1498}1379}
1499fn get() -> isize { 1 }1380var global_var: isize = 1;
1381fn get() -> isize { global_var }
1500 )SOURCE", 1, ".tmp_source.zig:3:9: error: unable to evaluate constant expression");1382 )SOURCE", 1, ".tmp_source.zig:3:9: error: unable to evaluate constant expression");
15011383
15021384
test/self_hosted.zig+97-6
...@@ -123,18 +123,18 @@ fn short_circuit() {...@@ -123,18 +123,18 @@ fn short_circuit() {
123 var hit_3 = false;123 var hit_3 = false;
124 var hit_4 = false;124 var hit_4 = false;
125125
126 if (true || { assert(false); false }) {126 if (true || {assert_runtime(false); false}) {
127 hit_1 = true;127 hit_1 = true;
128 }128 }
129 if (false || { hit_2 = true; false }) {129 if (false || { hit_2 = true; false }) {
130 assert(false);130 assert_runtime(false);
131 }131 }
132132
133 if (true && { hit_3 = true; false }) {133 if (true && { hit_3 = true; false }) {
134 %%io.stdout.printf("BAD 3\n");134 assert_runtime(false);
135 }135 }
136 if (false && { assert(false); false }) {136 if (false && {assert_runtime(false); false}) {
137 assert(false);137 assert_runtime(false);
138 } else {138 } else {
139 hit_4 = true;139 hit_4 = true;
140 }140 }
...@@ -144,6 +144,11 @@ fn short_circuit() {...@@ -144,6 +144,11 @@ fn short_circuit() {
144 assert(hit_4);144 assert(hit_4);
145}145}
146146
147#static_eval_enable(false)
148fn assert_runtime(b: bool) {
149 if (!b) unreachable{}
150}
151
147#attribute("test")152#attribute("test")
148fn modify_operators() {153fn modify_operators() {
149 var i : i32 = 0;154 var i : i32 = 0;
...@@ -509,6 +514,7 @@ enum Fruit {...@@ -509,6 +514,7 @@ enum Fruit {
509 Orange,514 Orange,
510 Banana,515 Banana,
511}516}
517#static_eval_enable(false)
512fn non_const_switch_on_enum(fruit: Fruit) {518fn non_const_switch_on_enum(fruit: Fruit) {
513 switch (fruit) {519 switch (fruit) {
514 Apple => unreachable{},520 Apple => unreachable{},
...@@ -521,6 +527,7 @@ fn non_const_switch_on_enum(fruit: Fruit) {...@@ -521,6 +527,7 @@ fn non_const_switch_on_enum(fruit: Fruit) {
521fn switch_statement() {527fn switch_statement() {
522 non_const_switch(SwitchStatmentFoo.C);528 non_const_switch(SwitchStatmentFoo.C);
523}529}
530#static_eval_enable(false)
524fn non_const_switch(foo: SwitchStatmentFoo) {531fn non_const_switch(foo: SwitchStatmentFoo) {
525 const val: i32 = switch (foo) {532 const val: i32 = switch (foo) {
526 A => 1,533 A => 1,
...@@ -549,6 +556,7 @@ enum SwitchProngWithVarEnum {...@@ -549,6 +556,7 @@ enum SwitchProngWithVarEnum {
549 Two: f32,556 Two: f32,
550 Meh,557 Meh,
551}558}
559#static_eval_enable(false)
552fn switch_prong_with_var_fn(a: SwitchProngWithVarEnum) {560fn switch_prong_with_var_fn(a: SwitchProngWithVarEnum) {
553 switch(a) {561 switch(a) {
554 One => |x| {562 One => |x| {
...@@ -569,6 +577,7 @@ fn err_return_in_assignment() {...@@ -569,6 +577,7 @@ fn err_return_in_assignment() {
569 %%do_err_return_in_assignment();577 %%do_err_return_in_assignment();
570}578}
571579
580#static_eval_enable(false)
572fn do_err_return_in_assignment() -> %void {581fn do_err_return_in_assignment() -> %void {
573 var x : i32 = undefined;582 var x : i32 = undefined;
574 x = %return make_a_non_err();583 x = %return make_a_non_err();
...@@ -608,7 +617,7 @@ fn explicit_cast_maybe_pointers() {...@@ -608,7 +617,7 @@ fn explicit_cast_maybe_pointers() {
608617
609#attribute("test")618#attribute("test")
610fn const_expr_eval_on_single_expr_blocks() {619fn const_expr_eval_on_single_expr_blocks() {
611 if (const_expr_eval_on_single_expr_blocks_fn(1, true) != 3) unreachable{}620 assert(const_expr_eval_on_single_expr_blocks_fn(1, true) == 3);
612}621}
613622
614fn const_expr_eval_on_single_expr_blocks_fn(x: i32, b: bool) -> i32 {623fn const_expr_eval_on_single_expr_blocks_fn(x: i32, b: bool) -> i32 {
...@@ -736,6 +745,7 @@ fn generic_malloc_free() {...@@ -736,6 +745,7 @@ fn generic_malloc_free() {
736 mem_free(u8)(a);745 mem_free(u8)(a);
737}746}
738const some_mem : [100]u8 = undefined;747const some_mem : [100]u8 = undefined;
748#static_eval_enable(false)
739fn mem_alloc(T: type)(n: isize) -> %[]T {749fn mem_alloc(T: type)(n: isize) -> %[]T {
740 return (&T)(&some_mem[0])[0...n];750 return (&T)(&some_mem[0])[0...n];
741}751}
...@@ -789,6 +799,7 @@ var goto_counter: i32 = 0;...@@ -789,6 +799,7 @@ var goto_counter: i32 = 0;
789fn goto_leave_defer_scope() {799fn goto_leave_defer_scope() {
790 test_goto_leave_defer_scope(true);800 test_goto_leave_defer_scope(true);
791}801}
802#static_eval_enable(false)
792fn test_goto_leave_defer_scope(b: bool) {803fn test_goto_leave_defer_scope(b: bool) {
793 var it_worked = false;804 var it_worked = false;
794805
...@@ -820,3 +831,83 @@ fn cast_small_unsigned_to_larger_signed() {...@@ -820,3 +831,83 @@ fn cast_small_unsigned_to_larger_signed() {
820}831}
821fn cast_small_unsigned_to_larger_signed_1(x: u8) -> i16 { x }832fn cast_small_unsigned_to_larger_signed_1(x: u8) -> i16 { x }
822fn cast_small_unsigned_to_larger_signed_2(x: u16) -> isize { x }833fn cast_small_unsigned_to_larger_signed_2(x: u16) -> isize { x }
834
835
836#attribute("test")
837fn implicit_cast_after_unreachable() {
838 assert(outer() == 1234);
839}
840fn inner() -> i32 { 1234 }
841fn outer() -> isize {
842 return inner();
843}
844
845
846#attribute("test")
847fn else_if_expression() {
848 assert(else_if_expression_f(1) == 1);
849}
850fn else_if_expression_f(c: u8) -> u8 {
851 if (c == 0) {
852 0
853 } else if (c == 1) {
854 1
855 } else {
856 2
857 }
858}
859
860#attribute("test")
861fn err_binary_operator() {
862 const a = err_binary_operator_g(true) %% 3;
863 const b = err_binary_operator_g(false) %% 3;
864 assert(a == 3);
865 assert(b == 10);
866}
867error ItBroke;
868fn err_binary_operator_g(x: bool) -> %isize {
869 if (x) {
870 error.ItBroke
871 } else {
872 10
873 }
874}
875
876#attribute("test")
877fn unwrap_simple_value_from_error() {
878 const i = %%unwrap_simple_value_from_error_do();
879 assert(i == 13);
880}
881fn unwrap_simple_value_from_error_do() -> %isize { 13 }
882
883
884#attribute("test")
885fn store_member_function_in_variable() {
886 const instance = MemberFnTestFoo { .x = 1234, };
887 const member_fn = MemberFnTestFoo.member;
888 const result = member_fn(instance);
889 assert(result == 1234);
890}
891struct MemberFnTestFoo {
892 x: i32,
893 fn member(foo: MemberFnTestFoo) -> i32 { foo.x }
894}
895
896#attribute("test")
897fn call_member_function_directly() {
898 const instance = MemberFnTestFoo { .x = 1234, };
899 const result = MemberFnTestFoo.member(instance);
900 assert(result == 1234);
901}
902
903#attribute("test")
904fn member_functions() {
905 const r = MemberFnRand {.seed = 1234};
906 assert(r.get_seed() == 1234);
907}
908struct MemberFnRand {
909 seed: u32,
910 pub fn get_seed(r: MemberFnRand) -> u32 {
911 r.seed
912 }
913}