Commit 3c27cb2527
Changed files (4)
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);
}
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;
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");
}
//////////////////////////////////////////////////////////////////////////////
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;
+ }
+}