From 3c27cb25279049cfdcde99d49045f5b8ec8981ba Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 12 Apr 2016 17:33:46 -0700 Subject: [PATCH] more eval tests and fix eval call analyze code --- src/analyze.cpp | 17 +++++--------- src/eval.cpp | 4 +++- test/run_tests.cpp | 15 ++++++++++++ test/self_hosted.zig | 56 +++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 77 insertions(+), 15 deletions(-) diff --git a/src/analyze.cpp b/src/analyze.cpp index 0cd234e3b8..f24d538ad8 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4504,28 +4504,23 @@ static TypeTableEntry *analyze_fn_call_ptr(CodeGen *g, ImportTableEntry *import, } FnTableEntry *fn_table_entry = node->data.fn_call_expr.fn_entry; - if (ok_invocation && fn_table_entry && fn_table_entry->is_pure && all_args_const_expr) { + if (ok_invocation && fn_table_entry && fn_table_entry->is_pure) { if (fn_table_entry->anal_state == FnAnalStateReady) { analyze_fn_body(g, fn_table_entry); - } else if (fn_table_entry->anal_state == FnAnalStateProbing) { - mark_impure_fn(context); } - if (fn_table_entry->is_pure) { - if (fn_table_entry->anal_state == FnAnalStateComplete) { + if (all_args_const_expr) { + if (fn_table_entry->is_pure && fn_table_entry->anal_state == FnAnalStateComplete) { ConstExprValue *result_val = &get_resolved_expr(node)->const_val; if (eval_fn(g, node, fn_table_entry, result_val, 1000, struct_node)) { // function evaluation generated an error return g->builtin_types.entry_invalid; } return return_type; - } else if (fn_table_entry->anal_state == FnAnalStateSkipped) { - return g->builtin_types.entry_invalid; } - } else { - // calling an impure fn is impure - mark_impure_fn(context); } - } else { + } + if (!ok_invocation || !fn_table_entry || !fn_table_entry->is_pure) { + // calling an impure fn is impure mark_impure_fn(context); } diff --git a/src/eval.cpp b/src/eval.cpp index 3e9d836a3e..34656c41e1 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -713,7 +713,9 @@ static bool eval_fn_call_expr(EvalFn *ef, AstNode *node, ConstExprValue *out_val } if (!fn_table_entry) { - zig_panic("TODO"); + ConstExprValue fn_val = {0}; + if (eval_expr(ef, fn_ref_expr, &fn_val)) return true; + fn_table_entry = fn_val.data.x_fn; } int param_count = node->data.fn_call_expr.params.length; diff --git a/test/run_tests.cpp b/test/run_tests.cpp index 5b3d68e72b..461ee4172c 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -1491,6 +1491,21 @@ fn foo(x: i32) -> i32 { ".tmp_source.zig:3:1: error: function evaluation caused division by zero", ".tmp_source.zig:2:14: note: called from here", ".tmp_source.zig:4:7: note: division by zero here"); + + add_compile_fail_case("branch on undefined value", R"SOURCE( +const x = if (undefined) true else false; + )SOURCE", 1, ".tmp_source.zig:2:15: error: branch on undefined value"); + + + add_compile_fail_case("endless loop in function evaluation", R"SOURCE( +const seventh_fib_number = fibbonaci(7); +fn fibbonaci(x: i32) -> i32 { + return fibbonaci(x - 1) + fibbonaci(x - 2); +} + )SOURCE", 3, + ".tmp_source.zig:3:1: error: function evaluation exceeded 1000 branches", + ".tmp_source.zig:2:37: note: called from here", + ".tmp_source.zig:4:40: note: quota exceeded here"); } ////////////////////////////////////////////////////////////////////////////// diff --git a/test/self_hosted.zig b/test/self_hosted.zig index 1becd42e75..4513b06dd7 100644 --- a/test/self_hosted.zig +++ b/test/self_hosted.zig @@ -415,9 +415,7 @@ error err2; #attribute("test") fn fn_call_of_struct_field() { - if (call_struct_field(Foo {.ptr = a_func,}) != 13) { - unreachable{}; - } + assert(call_struct_field(Foo {.ptr = a_func,}) == 13); } struct Foo { @@ -911,3 +909,55 @@ struct MemberFnRand { r.seed } } + +#attribute("test") +fn static_function_evaluation() { + assert(statically_added_number == 3); +} +const statically_added_number = static_add(1, 2); +fn static_add(a: i32, b: i32) -> i32 { a + b } + + +#attribute("test") +fn statically_initalized_list() { + assert(static_point_list[0].x == 1); + assert(static_point_list[0].y == 2); + assert(static_point_list[1].x == 3); + assert(static_point_list[1].y == 4); +} +struct Point { + x: i32, + y: i32, +} +const static_point_list = []Point { make_point(1, 2), make_point(3, 4) }; +fn make_point(x: i32, y: i32) -> Point { + return Point { + .x = x, + .y = y, + }; +} + + +#attribute("test") +fn static_eval_recursive() { + assert(seventh_fib_number == 21); +} +const seventh_fib_number = fibbonaci(7); +fn fibbonaci(x: i32) -> i32 { + if (x <= 1) return 1; + return fibbonaci(x - 1) + fibbonaci(x - 2); +} + +#attribute("test") +fn static_eval_while() { + assert(static_eval_while_number == 1); +} +const static_eval_while_number = static_while_loop_1(); +fn static_while_loop_1() -> i32 { + return while_loop_2(); +} +fn static_while_loop_2() -> i32 { + while (true) { + return 1; + } +}