diff options
| author | gingerBill <bill@gingerbill.org> | 2018-07-29 10:50:15 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2018-07-29 10:50:15 +0100 |
| commit | 6512a3e5f24a3aecb1451f921455a93231412104 (patch) | |
| tree | e784404bf3ad291c54314e9ab9690e9bd9da754f /src/check_expr.cpp | |
| parent | 49f2124df0f644e183f0570dd047493678eaf9f1 (diff) | |
using Foo :: enum {A, B, C}; len(Foo)
Diffstat (limited to 'src/check_expr.cpp')
| -rw-r--r-- | src/check_expr.cpp | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 03747a26f..5596eb106 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2788,6 +2788,7 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 case BuiltinProc_offset_of: case BuiltinProc_type_info_of: case BuiltinProc_typeid_of: + case BuiltinProc_len: // NOTE(bill): The first arg may be a Type, this will be checked case by case break; default: @@ -2860,9 +2861,17 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 } case BuiltinProc_len: - case BuiltinProc_cap: { + check_expr_or_type(c, operand, ce->args[0]); + if (operand->mode == Addressing_Invalid) { + return false; + } + /* fallthrough */ + + case BuiltinProc_cap: + { // len :: proc(Type) -> int // cap :: proc(Type) -> int + Type *op_type = type_deref(operand->type); Type *type = t_int; AddressingMode mode = Addressing_Invalid; @@ -2890,6 +2899,11 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 mode = Addressing_Value; } else if (is_type_map(op_type)) { mode = Addressing_Value; + } else if (operand->mode == Addressing_Type && is_type_enum(op_type) && id == BuiltinProc_len) { + Type *bt = base_type(op_type); + mode = Addressing_Constant; + value = exact_value_i64(bt->Enum.fields.count); + type = t_untyped_integer; } if (mode == Addressing_Invalid) { |