zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 3c27cb25279049cfdcde99d49045f5b8ec8981ba (tree)
parent 69109bc270c3167a3534dd32fc4f4def855e0be9
Author: Andrew Kelley <superjoe30@gmail.com>
Date:   Tue, 12 Apr 2016 17:33:46 -0700

more eval tests and fix eval call analyze code

Diffstat:
Msrc/analyze.cpp | 17++++++-----------
Msrc/eval.cpp | 4+++-
Mtest/run_tests.cpp | 15+++++++++++++++
Mtest/self_hosted.zig | 56+++++++++++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 77 insertions(+), 15 deletions(-)

diff --git 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 @@ -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 @@ -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 @@ -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; + } +}