| author | |
| committer | |
| log | 26ea20d88fb1b201546e29058ac4aa5d4760a577 |
| tree | 9e6af6c20faa376f6ecfdd775950b8d29b4dea45 |
| parent | 049e9e581933921f2aaa1e60a8082c49fac236b2 |
closes #735 files changed, 36 insertions(+), 1 deletions(-)
src/all_types.hpp+1| ... | ... | @@ -1033,6 +1033,7 @@ enum BuiltinFnId { |
| 1033 | 1033 | BuiltinFnIdCDefine, |
| 1034 | 1034 | BuiltinFnIdCUndef, |
| 1035 | 1035 | BuiltinFnIdCompileVar, |
| 1036 | BuiltinFnIdConstEval, | |
| 1036 | 1037 | }; |
| 1037 | 1038 | |
| 1038 | 1039 | struct BuiltinFnEntry { |
src/analyze.cpp+19-1| ... | ... | @@ -4127,8 +4127,26 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 4127 | 4127 | buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(&var_name))); |
| 4128 | 4128 | return g->builtin_types.entry_invalid; |
| 4129 | 4129 | } |
| 4130 | } | |
| 4131 | case BuiltinFnIdConstEval: | |
| 4132 | { | |
| 4133 | AstNode **expr_node = node->data.fn_call_expr.params.at(0)->parent_field; | |
| 4134 | TypeTableEntry *resolved_type = analyze_expression(g, import, context, expected_type, *expr_node); | |
| 4135 | if (resolved_type->id == TypeTableEntryIdInvalid) { | |
| 4136 | return resolved_type; | |
| 4137 | } | |
| 4130 | 4138 | |
| 4131 | break; | |
| 4139 | ConstExprValue *const_expr_val = &get_resolved_expr(*expr_node)->const_val; | |
| 4140 | ||
| 4141 | if (!const_expr_val->ok) { | |
| 4142 | add_node_error(g, *expr_node, buf_sprintf("unable to evaluate constant expression")); | |
| 4143 | return resolved_type; | |
| 4144 | } | |
| 4145 | ||
| 4146 | ConstExprValue *const_val = &get_resolved_expr(node)->const_val; | |
| 4147 | *const_val = *const_expr_val; | |
| 4148 | ||
| 4149 | return resolved_type; | |
| 4132 | 4150 | } |
| 4133 | 4151 | |
| 4134 | 4152 | } |
src/codegen.cpp+2| ... | ... | @@ -310,6 +310,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 310 | 310 | case BuiltinFnIdMaxValue: |
| 311 | 311 | case BuiltinFnIdMemberCount: |
| 312 | 312 | case BuiltinFnIdCompileVar: |
| 313 | case BuiltinFnIdConstEval: | |
| 313 | 314 | // caught by constant expression eval codegen |
| 314 | 315 | zig_unreachable(); |
| 315 | 316 | } |
| ... | ... | @@ -3513,6 +3514,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 3513 | 3514 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCDefine, "c_define", 2); |
| 3514 | 3515 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "c_undef", 1); |
| 3515 | 3516 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileVar, "compile_var", 1); |
| 3517 | create_builtin_fn_with_arg_count(g, BuiltinFnIdConstEval, "const_eval", 1); | |
| 3516 | 3518 | } |
| 3517 | 3519 | |
| 3518 | 3520 |
test/run_tests.cpp+7| ... | ... | @@ -2020,6 +2020,13 @@ fn func() -> bogus {} |
| 2020 | 2020 | add_compile_fail_case("bogus compile var", R"SOURCE( |
| 2021 | 2021 | const x = @compile_var("bogus"); |
| 2022 | 2022 | )SOURCE", 1, ".tmp_source.zig:2:24: error: unrecognized compile variable: 'bogus'"); |
| 2023 | ||
| 2024 | ||
| 2025 | add_compile_fail_case("@const_eval", R"SOURCE( | |
| 2026 | fn a(x: i32) { | |
| 2027 | const y = @const_eval(x); | |
| 2028 | } | |
| 2029 | )SOURCE", 1, ".tmp_source.zig:3:27: error: unable to evaluate constant expression"); | |
| 2023 | 2030 | } |
| 2024 | 2031 | |
| 2025 | 2032 | ////////////////////////////////////////////////////////////////////////////// |
test/self_hosted.zig+7| ... | ... | @@ -233,3 +233,10 @@ fn const_expr_eval_on_single_expr_blocks_fn(x: i32, b: bool) -> i32 { |
| 233 | 233 | |
| 234 | 234 | return result; |
| 235 | 235 | } |
| 236 | ||
| 237 | ||
| 238 | #attribute("test") | |
| 239 | fn builtin_const_eval() { | |
| 240 | const x : i32 = @const_eval(1 + 2 + 3); | |
| 241 | if (x != @const_eval(6)) unreachable{}; | |
| 242 | } |