mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Added Enum.lookup and Enum.lookup_field.
This commit is contained in:
@@ -22,6 +22,16 @@ struct SliceRaw
|
||||
usz len;
|
||||
}
|
||||
|
||||
macro @enum_lookup($Type, #value, value)
|
||||
{
|
||||
var $elements = $Type.elements;
|
||||
$for var $i = 0; $i < $elements; $i++:
|
||||
var $val = $Type.from_ordinal($i);
|
||||
if ($val.#value == value) return $val;
|
||||
$endfor
|
||||
return NOT_FOUND?;
|
||||
}
|
||||
|
||||
|
||||
module std::core::runtime @if(WASM_NOLIBC);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
- Improved error messages on `Foo { 3, abc }` #2099.
|
||||
- `Foo[1..2] = { .baz = 123 }` inference now works. #2095
|
||||
- Deprecated old inference with slice copy. Copying must now ensure a slicing operator at the end of the right hand side: `foo[1..2] = bar[..]` rather than the old `foo[1..2] = bar`. The old behaviour can be mostly retained with `--use-old-slice-copy`).
|
||||
- Added `Enum.lookup` and `Enum.lookup_field`.
|
||||
|
||||
### Fixes
|
||||
- Trying to cast an enum to int and back caused the compiler to crash.
|
||||
|
||||
@@ -1903,6 +1903,7 @@ extern const char *builtin_defines[NUMBER_OF_BUILTIN_DEFINES];
|
||||
extern const char *type_property_list[NUMBER_OF_TYPE_PROPERTIES];
|
||||
extern const char *kw_std__core;
|
||||
extern const char *kw_std__core__types;
|
||||
extern const char *kw_std__core__runtime;
|
||||
extern const char *kw_std__io;
|
||||
extern const char *kw_typekind;
|
||||
extern const char *kw_FILE_NOT_FOUND;
|
||||
@@ -1910,6 +1911,7 @@ extern const char *kw_IoError;
|
||||
|
||||
extern const char *kw_at_deprecated;
|
||||
extern const char *kw_at_ensure;
|
||||
extern const char *kw_at_enum_lookup;
|
||||
extern const char *kw_at_param;
|
||||
extern const char *kw_at_pure;
|
||||
extern const char *kw_at_require;
|
||||
|
||||
@@ -1386,6 +1386,8 @@ typedef enum
|
||||
TYPE_PROPERTY_IS_ORDERED,
|
||||
TYPE_PROPERTY_IS_SUBSTRUCT,
|
||||
TYPE_PROPERTY_LEN,
|
||||
TYPE_PROPERTY_LOOKUP,
|
||||
TYPE_PROPERTY_LOOKUP_FIELD,
|
||||
TYPE_PROPERTY_MAX,
|
||||
TYPE_PROPERTY_MEMBERSOF,
|
||||
TYPE_PROPERTY_METHODSOF,
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "sema_internal.h"
|
||||
#include <math.h>
|
||||
|
||||
#include "parser_internal.h"
|
||||
|
||||
#define RETURN_SEMA_FUNC_ERROR(_decl, _node, ...) do { sema_error_at(context, (_node)->span, __VA_ARGS__); SEMA_NOTE(_decl, "The definition was here."); return false; } while (0)
|
||||
#define RETURN_NOTE_FUNC_DEFINITION do { SEMA_NOTE(callee->definition, "The definition was here."); return false; } while (0);
|
||||
#define RESOLVE(expr__, check__) \
|
||||
@@ -116,8 +118,6 @@ static inline bool sema_expr_analyse_ct_nameof(SemaContext *context, Expr *expr)
|
||||
static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr);
|
||||
|
||||
// -- returns
|
||||
static inline void context_pop_returns(SemaContext *context, Ast **restore);
|
||||
static inline Ast **context_push_returns(SemaContext *context);
|
||||
static inline Type *context_unify_returns(SemaContext *context);
|
||||
|
||||
// -- addr helpers
|
||||
@@ -442,31 +442,6 @@ static void expr_binary_unify_failability(Expr *expr, Expr *left, Expr *right)
|
||||
expr->type = type_add_optional(left->type, IS_OPTIONAL(right));
|
||||
}
|
||||
|
||||
static inline void context_pop_returns(SemaContext *context, Ast **restore)
|
||||
{
|
||||
if (!context->returns_cache && context->returns)
|
||||
{
|
||||
context->returns_cache = context->returns;
|
||||
}
|
||||
context->returns = restore;
|
||||
}
|
||||
|
||||
static inline Ast **context_push_returns(SemaContext *context)
|
||||
{
|
||||
Ast** old_returns = context->returns;
|
||||
if (context->returns_cache)
|
||||
{
|
||||
context->returns = context->returns_cache;
|
||||
context->returns_cache = NULL;
|
||||
vec_resize(context->returns, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
context->returns = NULL;
|
||||
}
|
||||
return old_returns;
|
||||
}
|
||||
|
||||
CondResult sema_check_comp_time_bool(SemaContext *context, Expr *expr)
|
||||
{
|
||||
CondResult result = COND_MISSING;
|
||||
@@ -2837,7 +2812,7 @@ INLINE bool sema_expr_analyse_from_ordinal(SemaContext *context, Expr *expr, Exp
|
||||
Expr **args = expr->call_expr.arguments;
|
||||
unsigned arg_count = vec_size(args);
|
||||
Decl *decl = tag->type_call_expr.type;
|
||||
if (arg_count != 1) RETURN_SEMA_ERROR(expr, "Expected a single string argument to 'from_ordinal'.");
|
||||
if (arg_count != 1) RETURN_SEMA_ERROR(expr, "Expected a single integer argument to 'from_ordinal'.");
|
||||
Expr *key = args[0];
|
||||
if (!sema_analyse_expr(context, key)) return false;
|
||||
if (!type_is_integer(key->type))
|
||||
@@ -2873,13 +2848,87 @@ INLINE bool sema_expr_analyse_from_ordinal(SemaContext *context, Expr *expr, Exp
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE bool sema_expr_analyse_lookup(SemaContext *context, Expr *expr, Expr *tag, bool inline_field)
|
||||
{
|
||||
Expr **args = expr->call_expr.arguments;
|
||||
unsigned arg_count = vec_size(args);
|
||||
Decl *decl = tag->type_call_expr.type;
|
||||
if (inline_field)
|
||||
{
|
||||
if (arg_count != 1) RETURN_SEMA_ERROR(expr, "Expected one (1) argument to 'lookup'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (arg_count != 2) RETURN_SEMA_ERROR(expr, "'lookup_field' requires two arguments: the name of the field and the value to search for.");
|
||||
}
|
||||
Expr *key = inline_field ? args[0] : args[1];
|
||||
if (!sema_analyse_expr(context, key)) return false;
|
||||
ArrayIndex index;
|
||||
if (inline_field)
|
||||
{
|
||||
if (!decl->is_substruct || decl->enums.inline_value)
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "'lookup' requires an inline associated value, use 'Enum.lookup_field(fieldname, value)' instead.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Expr *ident = sema_expr_resolve_access_child(context, args[0], NULL);
|
||||
if (!ident) return false;
|
||||
const char *child = ident->unresolved_ident_expr.ident;
|
||||
FOREACH_IDX(i, Decl *, param, decl->enums.parameters)
|
||||
{
|
||||
if (param->name && param->name == child)
|
||||
{
|
||||
index = i;
|
||||
goto FOUND;
|
||||
}
|
||||
}
|
||||
RETURN_SEMA_ERROR(args[0], "There is no associated value of %s with the name '%s'.", type_quoted_error_string(decl->type), child);
|
||||
}
|
||||
index = decl->enums.inline_index;
|
||||
FOUND:;
|
||||
Decl *match = decl->enums.parameters[index];
|
||||
if (!cast_implicit(context, key, match->type, false)) return false;
|
||||
Decl *d = sema_find_symbol(context, kw_at_enum_lookup);
|
||||
if (!d || d->unit->module->name->module != kw_std__core__runtime)
|
||||
{
|
||||
RETURN_SEMA_ERROR(expr, "Missing main enum lookup macro '%s' in '%s'.", kw_at_enum_lookup, kw_std__core__runtime);
|
||||
}
|
||||
Expr *type = expr_new_expr(EXPR_TYPEINFO, expr);
|
||||
type->type_expr = type_info_new_base(decl->type, tag->span);
|
||||
expr->expr_kind = EXPR_CALL;
|
||||
while (vec_size(args) < 3) vec_add(args, NULL);
|
||||
args[0] = type;
|
||||
Expr *unresolved_ident = expr_new_expr(EXPR_UNRESOLVED_IDENTIFIER, expr);
|
||||
unresolved_ident->unresolved_ident_expr.ident = match->name;
|
||||
args[1] = unresolved_ident;
|
||||
args[2] = key;
|
||||
Expr *call = expr_new_expr(EXPR_UNRESOLVED_IDENTIFIER, expr);
|
||||
Path *new_path = CALLOCS(Path);
|
||||
new_path->module = kw_std__core__runtime;
|
||||
new_path->span = expr->span;
|
||||
new_path->len = strlen(kw_std__core__runtime);
|
||||
call->unresolved_ident_expr = (ExprUnresolvedIdentifier) { .ident = kw_at_enum_lookup, .path = new_path };
|
||||
expr->call_expr = (ExprCall) { .arguments = args, .function = exprid(call) };
|
||||
expr->resolve_status = RESOLVE_NOT_DONE;
|
||||
return sema_analyse_expr(context, expr);
|
||||
}
|
||||
|
||||
static inline bool sema_expr_analyse_typecall(SemaContext *context, Expr *expr)
|
||||
{
|
||||
Expr *tag = exprptr(expr->call_expr.function);
|
||||
expr->call_expr.arguments = sema_expand_vasplat_exprs(context, expr->call_expr.arguments);
|
||||
if (tag->type_call_expr.property == TYPE_PROPERTY_FROM_ORDINAL)
|
||||
switch (tag->type_call_expr.property)
|
||||
{
|
||||
return sema_expr_analyse_from_ordinal(context, expr, tag);
|
||||
case TYPE_PROPERTY_FROM_ORDINAL:
|
||||
return sema_expr_analyse_from_ordinal(context, expr, tag);
|
||||
case TYPE_PROPERTY_LOOKUP:
|
||||
return sema_expr_analyse_lookup(context, expr, tag, true);
|
||||
case TYPE_PROPERTY_LOOKUP_FIELD:
|
||||
return sema_expr_analyse_lookup(context, expr, tag, false);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Expr **args = expr->call_expr.arguments;
|
||||
unsigned arg_count = vec_size(args);
|
||||
@@ -4267,6 +4316,8 @@ static inline bool sema_expr_analyse_member_access(SemaContext *context, Expr *e
|
||||
case TYPE_PROPERTY_TAGOF:
|
||||
case TYPE_PROPERTY_HAS_TAGOF:
|
||||
case TYPE_PROPERTY_FROM_ORDINAL:
|
||||
case TYPE_PROPERTY_LOOKUP:
|
||||
case TYPE_PROPERTY_LOOKUP_FIELD:
|
||||
expr->expr_kind = EXPR_TYPECALL;
|
||||
expr->type_call_expr = (ExprTypeCall) { .type = decl, .property = type_property };
|
||||
return true;
|
||||
@@ -4775,6 +4826,8 @@ static bool sema_expr_rewrite_to_typeid_property(SemaContext *context, Expr *exp
|
||||
case TYPE_PROPERTY_IS_EQ:
|
||||
case TYPE_PROPERTY_IS_ORDERED:
|
||||
case TYPE_PROPERTY_IS_SUBSTRUCT:
|
||||
case TYPE_PROPERTY_LOOKUP:
|
||||
case TYPE_PROPERTY_LOOKUP_FIELD:
|
||||
case TYPE_PROPERTY_MAX:
|
||||
case TYPE_PROPERTY_MEMBERSOF:
|
||||
case TYPE_PROPERTY_METHODSOF:
|
||||
@@ -4962,6 +5015,8 @@ static bool sema_type_property_is_valid_for_type(Type *original_type, TypeProper
|
||||
return false;
|
||||
}
|
||||
case TYPE_PROPERTY_FROM_ORDINAL:
|
||||
case TYPE_PROPERTY_LOOKUP:
|
||||
case TYPE_PROPERTY_LOOKUP_FIELD:
|
||||
return type->canonical->type_kind == TYPE_ENUM;
|
||||
case TYPE_PROPERTY_MIN:
|
||||
case TYPE_PROPERTY_MAX:
|
||||
@@ -5114,6 +5169,8 @@ static bool sema_expr_rewrite_to_type_property(SemaContext *context, Expr *expr,
|
||||
case TYPE_PROPERTY_TAGOF:
|
||||
case TYPE_PROPERTY_HAS_TAGOF:
|
||||
case TYPE_PROPERTY_FROM_ORDINAL:
|
||||
case TYPE_PROPERTY_LOOKUP:
|
||||
case TYPE_PROPERTY_LOOKUP_FIELD:
|
||||
expr->expr_kind = EXPR_TYPECALL;
|
||||
expr->type_call_expr = (ExprTypeCall) {
|
||||
.type = type->type_kind == TYPE_FUNC_PTR
|
||||
|
||||
@@ -40,11 +40,12 @@ const char *builtin_defines[NUMBER_OF_BUILTIN_DEFINES];
|
||||
const char *type_property_list[NUMBER_OF_TYPE_PROPERTIES];
|
||||
const char *kw_at_deprecated;
|
||||
const char *kw_at_ensure;
|
||||
const char *kw_at_enum_lookup;
|
||||
const char *kw_at_jump;
|
||||
const char *kw_at_param;
|
||||
const char *kw_at_pure;
|
||||
const char *kw_at_require;
|
||||
const char *kw_at_return;
|
||||
const char *kw_at_jump;
|
||||
const char *kw_in;
|
||||
const char *kw_inout;
|
||||
const char *kw_len;
|
||||
@@ -62,6 +63,7 @@ const char *kw_self;
|
||||
const char *kw_std;
|
||||
const char *kw_std__core;
|
||||
const char *kw_std__core__types;
|
||||
const char *kw_std__core__runtime;
|
||||
const char *kw_std__io;
|
||||
const char *kw_type;
|
||||
const char *kw_typekind;
|
||||
@@ -146,6 +148,7 @@ void symtab_init(uint32_t capacity)
|
||||
kw_std = KW_DEF("std");
|
||||
kw_std__core = KW_DEF("std::core");
|
||||
kw_std__core__types = KW_DEF("std::core::types");
|
||||
kw_std__core__runtime = KW_DEF("std::core::runtime");
|
||||
kw_std__io = KW_DEF("std::io");
|
||||
kw_type = KW_DEF("type");
|
||||
kw_winmain = KW_DEF("wWinMain");
|
||||
@@ -161,12 +164,15 @@ void symtab_init(uint32_t capacity)
|
||||
type_property_list[TYPE_PROPERTY_ELEMENTS] = KW_DEF("elements");
|
||||
type_property_list[TYPE_PROPERTY_EXTNAMEOF] = KW_DEF("extnameof");
|
||||
type_property_list[TYPE_PROPERTY_FROM_ORDINAL] = KW_DEF("from_ordinal");
|
||||
|
||||
type_property_list[TYPE_PROPERTY_GET] = KW_DEF("get");
|
||||
type_property_list[TYPE_PROPERTY_INF] = KW_DEF("inf");
|
||||
type_property_list[TYPE_PROPERTY_INNER] = KW_DEF("inner");
|
||||
type_property_list[TYPE_PROPERTY_IS_EQ] = KW_DEF("is_eq");
|
||||
type_property_list[TYPE_PROPERTY_IS_ORDERED] = KW_DEF("is_ordered");
|
||||
type_property_list[TYPE_PROPERTY_IS_SUBSTRUCT] = KW_DEF("is_substruct");
|
||||
type_property_list[TYPE_PROPERTY_LOOKUP] = KW_DEF("lookup");
|
||||
type_property_list[TYPE_PROPERTY_LOOKUP_FIELD] = KW_DEF("lookup_field");
|
||||
type_property_list[TYPE_PROPERTY_KINDOF] = KW_DEF("kindof");
|
||||
type_property_list[TYPE_PROPERTY_MEMBERSOF] = KW_DEF("membersof");
|
||||
type_property_list[TYPE_PROPERTY_METHODSOF] = KW_DEF("methodsof");
|
||||
@@ -308,13 +314,14 @@ void symtab_init(uint32_t capacity)
|
||||
|
||||
type = TOKEN_AT_IDENT;
|
||||
|
||||
kw_at_ensure = KW_DEF("@ensure");
|
||||
kw_at_deprecated = KW_DEF("@deprecated");
|
||||
kw_at_ensure = KW_DEF("@ensure");
|
||||
kw_at_enum_lookup = KW_DEF("@enum_lookup");
|
||||
kw_at_jump = KW_DEF("@jump");
|
||||
kw_at_param = KW_DEF("@param");
|
||||
kw_at_pure = KW_DEF("@pure");
|
||||
kw_at_require = KW_DEF("@require");
|
||||
kw_at_return = KW_DEF("@return");
|
||||
kw_at_jump = KW_DEF("@jump");
|
||||
attribute_list[ATTRIBUTE_ALIGN] = KW_DEF("@align");
|
||||
attribute_list[ATTRIBUTE_BENCHMARK] = KW_DEF("@benchmark");
|
||||
attribute_list[ATTRIBUTE_BIGENDIAN] = KW_DEF("@bigendian");
|
||||
|
||||
130
test/test_suite/enumerations/enum_lookup.c3t
Normal file
130
test/test_suite/enumerations/enum_lookup.c3t
Normal file
@@ -0,0 +1,130 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
import std;
|
||||
|
||||
typedef Baz = int;
|
||||
enum Foo : char (inline Baz x, String hello)
|
||||
{
|
||||
ABC = { 123, "ugh" },
|
||||
DEF = { 444, "hello" }
|
||||
}
|
||||
fn int main(String[] a)
|
||||
{
|
||||
Foo? x = Foo.lookup_field(hello, "hello");
|
||||
Foo? y = Foo.lookup(3);
|
||||
return x.ordinal ?? 222;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
define i32 @test.main(ptr %0, i64 %1) #0 {
|
||||
entry:
|
||||
%a = alloca %"char[][]", align 8
|
||||
%x = alloca i8, align 1
|
||||
%x.f = alloca i64, align 8
|
||||
%blockret = alloca i8, align 1
|
||||
%cmp.idx = alloca i64, align 8
|
||||
%cmp.idx4 = alloca i64, align 8
|
||||
%y = alloca i8, align 1
|
||||
%y.f = alloca i64, align 8
|
||||
store ptr %0, ptr %a, align 8
|
||||
%ptradd = getelementptr inbounds i8, ptr %a, i64 8
|
||||
store i64 %1, ptr %ptradd, align 8
|
||||
br i1 false, label %slice_cmp_values, label %slice_cmp_exit
|
||||
|
||||
slice_cmp_values: ; preds = %entry
|
||||
store i64 0, ptr %cmp.idx, align 8
|
||||
br label %slice_loop_start
|
||||
|
||||
slice_loop_start: ; preds = %slice_loop_comparison, %slice_cmp_values
|
||||
%2 = load i64, ptr %cmp.idx, align 8
|
||||
%lt = icmp slt i64 %2, 3
|
||||
br i1 %lt, label %slice_loop_comparison, label %slice_cmp_exit
|
||||
|
||||
slice_loop_comparison: ; preds = %slice_loop_start
|
||||
%ptradd1 = getelementptr inbounds i8, ptr @.str.3, i64 %2
|
||||
%ptradd2 = getelementptr inbounds i8, ptr @.str.2, i64 %2
|
||||
%3 = load i8, ptr %ptradd1, align 1
|
||||
%4 = load i8, ptr %ptradd2, align 1
|
||||
%eq = icmp eq i8 %3, %4
|
||||
%5 = add i64 %2, 1
|
||||
store i64 %5, ptr %cmp.idx, align 8
|
||||
br i1 %eq, label %slice_loop_start, label %slice_cmp_exit
|
||||
|
||||
slice_cmp_exit: ; preds = %slice_loop_comparison, %slice_loop_start, %entry
|
||||
%slice_cmp_phi = phi i1 [ true, %slice_loop_start ], [ false, %entry ], [ false, %slice_loop_comparison ]
|
||||
br i1 %slice_cmp_phi, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %slice_cmp_exit
|
||||
store i8 0, ptr %blockret, align 1
|
||||
br label %expr_block.exit
|
||||
|
||||
if.exit: ; preds = %slice_cmp_exit
|
||||
br i1 true, label %slice_cmp_values3, label %slice_cmp_exit11
|
||||
|
||||
slice_cmp_values3: ; preds = %if.exit
|
||||
store i64 0, ptr %cmp.idx4, align 8
|
||||
br label %slice_loop_start5
|
||||
|
||||
slice_loop_start5: ; preds = %slice_loop_comparison7, %slice_cmp_values3
|
||||
%6 = load i64, ptr %cmp.idx4, align 8
|
||||
%lt6 = icmp slt i64 %6, 5
|
||||
br i1 %lt6, label %slice_loop_comparison7, label %slice_cmp_exit11
|
||||
|
||||
slice_loop_comparison7: ; preds = %slice_loop_start5
|
||||
%ptradd8 = getelementptr inbounds i8, ptr @.str.4, i64 %6
|
||||
%ptradd9 = getelementptr inbounds i8, ptr @.str.2, i64 %6
|
||||
%7 = load i8, ptr %ptradd8, align 1
|
||||
%8 = load i8, ptr %ptradd9, align 1
|
||||
%eq10 = icmp eq i8 %7, %8
|
||||
%9 = add i64 %6, 1
|
||||
store i64 %9, ptr %cmp.idx4, align 8
|
||||
br i1 %eq10, label %slice_loop_start5, label %slice_cmp_exit11
|
||||
|
||||
slice_cmp_exit11: ; preds = %slice_loop_comparison7, %slice_loop_start5, %if.exit
|
||||
%slice_cmp_phi12 = phi i1 [ true, %slice_loop_start5 ], [ false, %if.exit ], [ false, %slice_loop_comparison7 ]
|
||||
br i1 %slice_cmp_phi12, label %if.then13, label %if.exit14
|
||||
|
||||
if.then13: ; preds = %slice_cmp_exit11
|
||||
store i8 1, ptr %blockret, align 1
|
||||
br label %expr_block.exit
|
||||
|
||||
if.exit14: ; preds = %slice_cmp_exit11
|
||||
store i64 ptrtoint (ptr @std.core.builtin.NOT_FOUND to i64), ptr %x.f, align 8
|
||||
br label %after_assign
|
||||
|
||||
expr_block.exit: ; preds = %if.then13, %if.then
|
||||
%10 = load i8, ptr %blockret, align 1
|
||||
store i8 %10, ptr %x, align 1
|
||||
store i64 0, ptr %x.f, align 8
|
||||
br label %after_assign
|
||||
|
||||
after_assign: ; preds = %expr_block.exit, %if.exit14
|
||||
br label %if.exit16
|
||||
|
||||
if.exit16: ; preds = %after_assign
|
||||
br label %if.exit17
|
||||
|
||||
if.exit17: ; preds = %if.exit16
|
||||
store i64 ptrtoint (ptr @std.core.builtin.NOT_FOUND to i64), ptr %y.f, align 8
|
||||
br label %after_assign18
|
||||
|
||||
after_assign18: ; preds = %if.exit17
|
||||
%optval = load i64, ptr %x.f, align 8
|
||||
%not_err = icmp eq i64 %optval, 0
|
||||
%11 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
|
||||
br i1 %11, label %after_check, label %else_block
|
||||
|
||||
after_check: ; preds = %after_assign18
|
||||
%12 = load i8, ptr %x, align 1
|
||||
%zext = zext i8 %12 to i32
|
||||
br label %phi_block
|
||||
|
||||
else_block: ; preds = %after_assign18
|
||||
br label %phi_block
|
||||
|
||||
phi_block: ; preds = %else_block, %after_check
|
||||
%val = phi i32 [ %zext, %after_check ], [ 222, %else_block ]
|
||||
ret i32 %val
|
||||
}
|
||||
|
||||
32
test/test_suite/enumerations/lookup_errors.c3
Normal file
32
test/test_suite/enumerations/lookup_errors.c3
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
typedef Baz = int;
|
||||
enum Foo : char (inline Baz x, String hello)
|
||||
{
|
||||
ABC = { 123, "ugh" },
|
||||
DEF = { 444, "hello" }
|
||||
}
|
||||
enum Bar : char (Baz x)
|
||||
{
|
||||
HELLO = 123,
|
||||
}
|
||||
|
||||
fn void test1()
|
||||
{
|
||||
(void)Bar.lookup(123); // #error: 'lookup' requires an inline associated value
|
||||
}
|
||||
|
||||
fn void test2()
|
||||
{
|
||||
Foo.lookup(123, 322); // #error: Expected one (1)
|
||||
Foo.lookup(); // #error: Expected one (1)
|
||||
Foo.lookup_field(0); // #error: requires two arguments
|
||||
Foo.lookup_field(33, 22, 44); // #error: requires two arguments
|
||||
}
|
||||
|
||||
fn void test3()
|
||||
{
|
||||
Foo.lookup("hello"); // #error: possible to cast 'String'
|
||||
Foo.lookup_field("hello", "hello"); // #error: identifier
|
||||
Foo.lookup_field(hello, 2); // #error: possible to cast 'int'
|
||||
Foo.lookup_field(err, 4); // #error: no associated value of
|
||||
}
|
||||
Reference in New Issue
Block a user