| 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,6 +1033,7 @@ enum BuiltinFnId { |
| 1033 | BuiltinFnIdCDefine, | 1033 | BuiltinFnIdCDefine, |
| 1034 | BuiltinFnIdCUndef, | 1034 | BuiltinFnIdCUndef, |
| 1035 | BuiltinFnIdCompileVar, | 1035 | BuiltinFnIdCompileVar, |
| 1036 | BuiltinFnIdConstEval, | ||
| 1036 | }; | 1037 | }; |
| 1037 | 1038 | ||
| 1038 | struct BuiltinFnEntry { | 1039 | struct BuiltinFnEntry { |
src/analyze.cpp+19-1| ... | @@ -4127,8 +4127,26 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry | ... | @@ -4127,8 +4127,26 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry |
| 4127 | buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(&var_name))); | 4127 | buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(&var_name))); |
| 4128 | return g->builtin_types.entry_invalid; | 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,6 +310,7 @@ static LLVMValueRef gen_builtin_fn_call_expr(CodeGen *g, AstNode *node) { |
| 310 | case BuiltinFnIdMaxValue: | 310 | case BuiltinFnIdMaxValue: |
| 311 | case BuiltinFnIdMemberCount: | 311 | case BuiltinFnIdMemberCount: |
| 312 | case BuiltinFnIdCompileVar: | 312 | case BuiltinFnIdCompileVar: |
| 313 | case BuiltinFnIdConstEval: | ||
| 313 | // caught by constant expression eval codegen | 314 | // caught by constant expression eval codegen |
| 314 | zig_unreachable(); | 315 | zig_unreachable(); |
| 315 | } | 316 | } |
| ... | @@ -3513,6 +3514,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -3513,6 +3514,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 3513 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCDefine, "c_define", 2); | 3514 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCDefine, "c_define", 2); |
| 3514 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "c_undef", 1); | 3515 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCUndef, "c_undef", 1); |
| 3515 | create_builtin_fn_with_arg_count(g, BuiltinFnIdCompileVar, "compile_var", 1); | 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,6 +2020,13 @@ fn func() -> bogus {} |
| 2020 | add_compile_fail_case("bogus compile var", R"SOURCE( | 2020 | add_compile_fail_case("bogus compile var", R"SOURCE( |
| 2021 | const x = @compile_var("bogus"); | 2021 | const x = @compile_var("bogus"); |
| 2022 | )SOURCE", 1, ".tmp_source.zig:2:24: error: unrecognized compile variable: 'bogus'"); | 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,3 +233,10 @@ fn const_expr_eval_on_single_expr_blocks_fn(x: i32, b: bool) -> i32 { |
| 233 | 233 | ||
| 234 | return result; | 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 | } |