aboutsummaryrefslogtreecommitdiff
path: root/src/check_expr.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-07-29 10:50:15 +0100
committergingerBill <bill@gingerbill.org>2018-07-29 10:50:15 +0100
commit6512a3e5f24a3aecb1451f921455a93231412104 (patch)
treee784404bf3ad291c54314e9ab9690e9bd9da754f /src/check_expr.cpp
parent49f2124df0f644e183f0570dd047493678eaf9f1 (diff)
using Foo :: enum {A, B, C}; len(Foo)
Diffstat (limited to 'src/check_expr.cpp')
-rw-r--r--src/check_expr.cpp16
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) {