zig

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

commit 6e6d138c2f50f95fe9c6b4acbc16ffa17475a4a5 (tree)
parent 651dc31247c2f637925ed6a6e92c8bc1a19efd5c
Author: Andrew Kelley <superjoe30@gmail.com>
Date:   Thu, 25 Aug 2016 20:52:35 -0700

add ability to explicitly cast enum with no payload to int

Diffstat:
Msrc/all_types.hpp | 1+
Msrc/analyze.cpp | 15++++++++++++++-
Msrc/codegen.cpp | 2++
Msrc/eval.cpp | 3+++
Atest/cases/enum_to_int.zig | 24++++++++++++++++++++++++
5 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/src/all_types.hpp b/src/all_types.hpp @@ -404,6 +404,7 @@ enum CastOp { CastOpBoolToInt, CastOpResizeSlice, CastOpIntToEnum, + CastOpEnumToInt, CastOpBytesToSlice, }; diff --git a/src/analyze.cpp b/src/analyze.cpp @@ -2641,7 +2641,12 @@ static TypeTableEntry *analyze_container_init_expr(CodeGen *g, ImportTableEntry codegen->type_entry = fixed_size_array_type; codegen->source_node = node; if (!const_val->ok) { - context->fn_entry->struct_val_expr_alloca_list.append(codegen); + if (!context->fn_entry) { + add_node_error(g, node, + buf_sprintf("unable to evaluate constant expression")); + } else { + context->fn_entry->struct_val_expr_alloca_list.append(codegen); + } } return fixed_size_array_type; @@ -4601,6 +4606,14 @@ static TypeTableEntry *analyze_cast_expr(CodeGen *g, ImportTableEntry *import, B return resolve_cast(g, context, node, expr_node, wanted_type, CastOpIntToEnum, false); } + // explicit cast from enum type with no payload to integer + if (wanted_type->id == TypeTableEntryIdInt && + actual_type->id == TypeTableEntryIdEnum && + actual_type->data.enumeration.gen_field_count == 0) + { + return resolve_cast(g, context, node, expr_node, wanted_type, CastOpEnumToInt, false); + } + add_node_error(g, node, buf_sprintf("invalid cast from type '%s' to '%s'", buf_ptr(&actual_type->name), diff --git a/src/codegen.cpp b/src/codegen.cpp @@ -1062,6 +1062,8 @@ static LLVMValueRef gen_cast_expr(CodeGen *g, AstNode *node) { case CastOpIntToEnum: return gen_widen_or_shorten(g, node, actual_type, wanted_type->data.enumeration.tag_type, expr_val); + case CastOpEnumToInt: + return gen_widen_or_shorten(g, node, actual_type->data.enumeration.tag_type, wanted_type, expr_val); } zig_unreachable(); } diff --git a/src/eval.cpp b/src/eval.cpp @@ -694,6 +694,9 @@ void eval_const_expr_implicit_cast(CastOp cast_op, const_val->ok = true; break; } + case CastOpEnumToInt: + bignum_init_unsigned(&const_val->data.x_bignum, other_val->data.x_enum.tag); + const_val->ok = true; } } diff --git a/test/cases/enum_to_int.zig b/test/cases/enum_to_int.zig @@ -0,0 +1,24 @@ +const assert = @import("std").debug.assert; + +enum Number { + Zero, + One, + Two, + Three, + Four, +} + +#attribute("test") +fn enumToInt() { + shouldEqual(Number.Zero, 0); + shouldEqual(Number.One, 1); + shouldEqual(Number.Two, 2); + shouldEqual(Number.Three, 3); + shouldEqual(Number.Four, 4); +} + +// TODO add test with this disabled +#static_eval_enable(false) +fn shouldEqual(n: Number, expected: usize) { + assert(usize(n) == expected); +}