mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
"Old style" enums
name and value information `count`, `min_value`, `max_value` constants
This commit is contained in:
+27
-17
@@ -1,21 +1,31 @@
|
|||||||
#import "fmt.odin";
|
#import "fmt.odin";
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
fmt.printf("%f", 123);
|
using Type_Info;
|
||||||
|
is_type_integer :: proc(info: ^Type_Info) -> bool {
|
||||||
|
if info == nil {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
match type i : type_info_base(info) {
|
||||||
|
case Integer:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ti := type_info_base(type_info(Allocator_Mode));
|
||||||
|
match type e : ti {
|
||||||
|
case Enum:
|
||||||
|
is_int := is_type_integer(e.base);
|
||||||
|
for i : 0..<e.names.count {
|
||||||
|
name := e.names[i];
|
||||||
|
value := e.values[i];
|
||||||
|
if is_int {
|
||||||
|
fmt.printf("%s - %d\n", name, value.i);
|
||||||
|
} else {
|
||||||
|
fmt.printf("%s - %f\n", name, value.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Standard Library Development:
|
|
||||||
* Formatted printf
|
|
||||||
* The Variable
|
|
||||||
* math
|
|
||||||
- Trig
|
|
||||||
- Random
|
|
||||||
- atoi
|
|
||||||
* Memory allocation
|
|
||||||
* File IO
|
|
||||||
* Timing
|
|
||||||
- Regular and OS
|
|
||||||
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|||||||
+6
-2
@@ -25,6 +25,10 @@ Type_Info_Record :: struct #ordered {
|
|||||||
packed: bool;
|
packed: bool;
|
||||||
ordered: bool;
|
ordered: bool;
|
||||||
}
|
}
|
||||||
|
Type_Info_Enum_Value :: raw_union {
|
||||||
|
f: f64;
|
||||||
|
i: i64;
|
||||||
|
}
|
||||||
|
|
||||||
Type_Info :: union {
|
Type_Info :: union {
|
||||||
Named: struct #ordered {
|
Named: struct #ordered {
|
||||||
@@ -74,7 +78,7 @@ Type_Info :: union {
|
|||||||
Enum: struct #ordered {
|
Enum: struct #ordered {
|
||||||
base: ^Type_Info;
|
base: ^Type_Info;
|
||||||
names: []string;
|
names: []string;
|
||||||
// TODO(bill): store values some how. Maybe using a raw_union
|
values: []Type_Info_Enum_Value;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +119,7 @@ fmuladd64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64"
|
|||||||
|
|
||||||
|
|
||||||
Allocator_Mode :: enum u8 {
|
Allocator_Mode :: enum u8 {
|
||||||
ALLOC = iota,
|
ALLOC,
|
||||||
FREE,
|
FREE,
|
||||||
FREE_ALL,
|
FREE_ALL,
|
||||||
RESIZE,
|
RESIZE,
|
||||||
|
|||||||
+33
-37
@@ -190,36 +190,30 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) {
|
|||||||
if info.ordered { buffer_write_string(buf, "#ordered "); }
|
if info.ordered { buffer_write_string(buf, "#ordered "); }
|
||||||
buffer_write_string(buf, "{");
|
buffer_write_string(buf, "{");
|
||||||
for field, i : info.fields {
|
for field, i : info.fields {
|
||||||
if i > 0 {
|
|
||||||
buffer_write_string(buf, ", ");
|
|
||||||
}
|
|
||||||
buffer_write_string(buf, field.name);
|
buffer_write_string(buf, field.name);
|
||||||
buffer_write_string(buf, ": ");
|
buffer_write_string(buf, ": ");
|
||||||
buffer_write_type(buf, field.type_info);
|
buffer_write_type(buf, field.type_info);
|
||||||
|
buffer_write_byte(buf, ';');
|
||||||
}
|
}
|
||||||
buffer_write_string(buf, "}");
|
buffer_write_string(buf, "}");
|
||||||
|
|
||||||
case Union:
|
case Union:
|
||||||
buffer_write_string(buf, "union {");
|
buffer_write_string(buf, "union {");
|
||||||
for field, i : info.fields {
|
for field, i : info.fields {
|
||||||
if i > 0 {
|
|
||||||
buffer_write_string(buf, ", ");
|
|
||||||
}
|
|
||||||
buffer_write_string(buf, field.name);
|
buffer_write_string(buf, field.name);
|
||||||
buffer_write_string(buf, ": ");
|
buffer_write_string(buf, ": ");
|
||||||
buffer_write_type(buf, field.type_info);
|
buffer_write_type(buf, field.type_info);
|
||||||
|
buffer_write_byte(buf, ';');
|
||||||
}
|
}
|
||||||
buffer_write_string(buf, "}");
|
buffer_write_string(buf, "}");
|
||||||
|
|
||||||
case Raw_Union:
|
case Raw_Union:
|
||||||
buffer_write_string(buf, "raw_union {");
|
buffer_write_string(buf, "raw_union {");
|
||||||
for field, i : info.fields {
|
for field, i : info.fields {
|
||||||
if i > 0 {
|
|
||||||
buffer_write_string(buf, ", ");
|
|
||||||
}
|
|
||||||
buffer_write_string(buf, field.name);
|
buffer_write_string(buf, field.name);
|
||||||
buffer_write_string(buf, ": ");
|
buffer_write_string(buf, ": ");
|
||||||
buffer_write_type(buf, field.type_info);
|
buffer_write_type(buf, field.type_info);
|
||||||
|
buffer_write_byte(buf, ';');
|
||||||
}
|
}
|
||||||
buffer_write_string(buf, "}");
|
buffer_write_string(buf, "}");
|
||||||
|
|
||||||
@@ -232,14 +226,6 @@ buffer_write_type :: proc(buf: ^Buffer, ti: ^Type_Info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
make_any :: proc(type_info: ^Type_Info, data: rawptr) -> any {
|
|
||||||
a: any;
|
|
||||||
a.type_info = type_info;
|
|
||||||
a.data = data;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bprint :: proc(buf: ^Buffer, args: ...any) -> int {
|
bprint :: proc(buf: ^Buffer, args: ...any) -> int {
|
||||||
is_type_string :: proc(info: ^Type_Info) -> bool {
|
is_type_string :: proc(info: ^Type_Info) -> bool {
|
||||||
using Type_Info;
|
using Type_Info;
|
||||||
@@ -411,7 +397,8 @@ fmt_write_padding :: proc(fi: ^Fmt_Info, width: int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: string) {
|
fmt_integer :: proc(fi: ^Fmt_Info, u: u64, base: int, signed: bool, digits: string) {
|
||||||
negative := signed && (u as i64) < 0;
|
u_i64 := u as i64;
|
||||||
|
negative := signed && u_i64 < 0;
|
||||||
if negative {
|
if negative {
|
||||||
u = -u;
|
u = -u;
|
||||||
}
|
}
|
||||||
@@ -591,12 +578,14 @@ fmt_string :: proc(fi: ^Fmt_Info, s: string, verb: rune) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
|
fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
|
||||||
if verb != 'p' {
|
match verb {
|
||||||
|
case 'p', 'v':
|
||||||
|
default:
|
||||||
fmt_bad_verb(fi, verb);
|
fmt_bad_verb(fi, verb);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
u := p as uint as u64;
|
u := p as uint as u64;
|
||||||
if !fi.hash {
|
if !fi.hash || verb == 'v' {
|
||||||
buffer_write_string(fi.buf, "0x");
|
buffer_write_string(fi.buf, "0x");
|
||||||
}
|
}
|
||||||
fmt_integer(fi, u, 16, false, __DIGITS_UPPER);
|
fmt_integer(fi, u, 16, false, __DIGITS_UPPER);
|
||||||
@@ -612,14 +601,12 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
using Type_Info;
|
using Type_Info;
|
||||||
match type info : v.type_info {
|
match type info : v.type_info {
|
||||||
case Named:
|
case Named:
|
||||||
if verb != 'v' {
|
|
||||||
fmt_bad_verb(fi, verb);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
a := make_any(info.base, v.data);
|
|
||||||
match type b : info.base {
|
match type b : info.base {
|
||||||
case Struct:
|
case Struct:
|
||||||
|
if verb != 'v' {
|
||||||
|
fmt_bad_verb(fi, verb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
buffer_write_string(fi.buf, info.name);
|
buffer_write_string(fi.buf, info.name);
|
||||||
buffer_write_byte(fi.buf, '{');
|
buffer_write_byte(fi.buf, '{');
|
||||||
for f, i : b.fields {
|
for f, i : b.fields {
|
||||||
@@ -630,12 +617,12 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
// bprint_any(fi.buf, f.offset);
|
// bprint_any(fi.buf, f.offset);
|
||||||
buffer_write_string(fi.buf, " = ");
|
buffer_write_string(fi.buf, " = ");
|
||||||
data := v.data as ^byte + f.offset;
|
data := v.data as ^byte + f.offset;
|
||||||
fmt_arg(fi, make_any(f.type_info, data), 'v');
|
fmt_arg(fi, any{f.type_info, data as rawptr}, 'v');
|
||||||
}
|
}
|
||||||
buffer_write_byte(fi.buf, '}');
|
buffer_write_byte(fi.buf, '}');
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt_value(fi, a, verb);
|
fmt_value(fi, any{info.base, v.data}, verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
case Boolean: fmt_arg(fi, v, verb);
|
case Boolean: fmt_arg(fi, v, verb);
|
||||||
@@ -644,14 +631,18 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
case String: fmt_arg(fi, v, verb);
|
case String: fmt_arg(fi, v, verb);
|
||||||
|
|
||||||
case Pointer:
|
case Pointer:
|
||||||
fmt_pointer(fi, (v.data as ^rawptr)^, verb);
|
if v.type_info == type_info(^Type_Info) {
|
||||||
|
buffer_write_type(fi.buf, (v.data as ^^Type_Info)^);
|
||||||
|
} else {
|
||||||
|
fmt_pointer(fi, (v.data as ^rawptr)^, verb);
|
||||||
|
}
|
||||||
|
|
||||||
case Maybe:
|
case Maybe:
|
||||||
// TODO(bill): Correct verbs for Maybe types?
|
// TODO(bill): Correct verbs for Maybe types?
|
||||||
size := mem.size_of_type_info(info.elem);
|
size := mem.size_of_type_info(info.elem);
|
||||||
data := slice_ptr(v.data as ^byte, size+1);
|
data := slice_ptr(v.data as ^byte, size+1);
|
||||||
if data[size] != 0 {
|
if data[size] != 0 {
|
||||||
fmt_arg(fi, make_any(info.elem, v.data), verb);
|
fmt_arg(fi, any{info.elem, v.data}, verb);
|
||||||
} else {
|
} else {
|
||||||
buffer_write_string(fi.buf, "nil");
|
buffer_write_string(fi.buf, "nil");
|
||||||
}
|
}
|
||||||
@@ -669,7 +660,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
buffer_write_string(fi.buf, ", ");
|
buffer_write_string(fi.buf, ", ");
|
||||||
}
|
}
|
||||||
data := v.data as ^byte + i*info.elem_size;
|
data := v.data as ^byte + i*info.elem_size;
|
||||||
fmt_arg(fi, make_any(info.elem, data), 'v');
|
fmt_arg(fi, any{info.elem, data as rawptr}, 'v');
|
||||||
}
|
}
|
||||||
|
|
||||||
case Slice:
|
case Slice:
|
||||||
@@ -686,7 +677,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
buffer_write_string(fi.buf, ", ");
|
buffer_write_string(fi.buf, ", ");
|
||||||
}
|
}
|
||||||
data := slice.data + i*info.elem_size;
|
data := slice.data + i*info.elem_size;
|
||||||
fmt_arg(fi, make_any(info.elem, data), 'v');
|
fmt_arg(fi, any{info.elem, data as rawptr}, 'v');
|
||||||
}
|
}
|
||||||
|
|
||||||
case Vector:
|
case Vector:
|
||||||
@@ -713,7 +704,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data := v.data as ^byte + i*info.elem_size;
|
data := v.data as ^byte + i*info.elem_size;
|
||||||
fmt_value(fi, make_any(info.elem, data), 'v');
|
fmt_value(fi, any{info.elem, data as rawptr}, 'v');
|
||||||
}
|
}
|
||||||
|
|
||||||
case Struct:
|
case Struct:
|
||||||
@@ -728,7 +719,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
buffer_write_string(fi.buf, " = ");
|
buffer_write_string(fi.buf, " = ");
|
||||||
data := v.data as ^byte + f.offset;
|
data := v.data as ^byte + f.offset;
|
||||||
ti := f.type_info;
|
ti := f.type_info;
|
||||||
fmt_value(fi, make_any(ti, data), 'v');
|
fmt_value(fi, any{ti, data as rawptr}, 'v');
|
||||||
}
|
}
|
||||||
|
|
||||||
case Union:
|
case Union:
|
||||||
@@ -737,7 +728,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
buffer_write_string(fi.buf, "(raw_union)");
|
buffer_write_string(fi.buf, "(raw_union)");
|
||||||
|
|
||||||
case Enum:
|
case Enum:
|
||||||
fmt_value(fi, make_any(info.base, v.data), verb);
|
fmt_arg(fi, any{info.base, v.data}, verb);
|
||||||
|
|
||||||
case Procedure:
|
case Procedure:
|
||||||
buffer_write_type(fi.buf, v.type_info);
|
buffer_write_type(fi.buf, v.type_info);
|
||||||
@@ -753,11 +744,16 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
|
|||||||
}
|
}
|
||||||
fi.arg = arg;
|
fi.arg = arg;
|
||||||
|
|
||||||
if verb == 'T' { // Type Info
|
if verb == 'T' {
|
||||||
buffer_write_type(fi.buf, arg.type_info);
|
ti := arg.type_info;
|
||||||
|
if ti == type_info(^Type_Info) {
|
||||||
|
ti = (arg.data as ^^Type_Info)^;
|
||||||
|
}
|
||||||
|
buffer_write_type(fi.buf, ti);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
base_arg := arg;
|
base_arg := arg;
|
||||||
base_arg.type_info = type_info_base(base_arg.type_info);
|
base_arg.type_info = type_info_base(base_arg.type_info);
|
||||||
match type a : base_arg {
|
match type a : base_arg {
|
||||||
|
|||||||
@@ -249,9 +249,6 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
|||||||
}
|
}
|
||||||
e->flags |= EntityFlag_Visited;
|
e->flags |= EntityFlag_Visited;
|
||||||
|
|
||||||
c->context.iota = e->Constant.value;
|
|
||||||
e->Constant.value = (ExactValue){0};
|
|
||||||
|
|
||||||
if (type_expr) {
|
if (type_expr) {
|
||||||
Type *t = check_type(c, type_expr);
|
Type *t = check_type(c, type_expr);
|
||||||
if (!is_type_constant_type(t)) {
|
if (!is_type_constant_type(t)) {
|
||||||
@@ -259,7 +256,6 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
|||||||
error_node(type_expr, "Invalid constant type `%s`", str);
|
error_node(type_expr, "Invalid constant type `%s`", str);
|
||||||
gb_string_free(str);
|
gb_string_free(str);
|
||||||
e->type = t_invalid;
|
e->type = t_invalid;
|
||||||
c->context.iota = (ExactValue){0};
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
e->type = t;
|
e->type = t;
|
||||||
@@ -270,9 +266,6 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
|||||||
check_expr_or_type(c, &operand, init);
|
check_expr_or_type(c, &operand, init);
|
||||||
}
|
}
|
||||||
if (operand.mode == Addressing_Type) {
|
if (operand.mode == Addressing_Type) {
|
||||||
c->context.iota = (ExactValue){0};
|
|
||||||
|
|
||||||
e->Constant.value = (ExactValue){0};
|
|
||||||
e->kind = Entity_TypeName;
|
e->kind = Entity_TypeName;
|
||||||
|
|
||||||
DeclInfo *d = c->context.decl;
|
DeclInfo *d = c->context.decl;
|
||||||
@@ -282,7 +275,6 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
|||||||
}
|
}
|
||||||
|
|
||||||
check_init_constant(c, e, &operand);
|
check_init_constant(c, e, &operand);
|
||||||
c->context.iota = (ExactValue){0};
|
|
||||||
|
|
||||||
if (operand.mode == Addressing_Invalid) {
|
if (operand.mode == Addressing_Invalid) {
|
||||||
error(e->token, "Illegal cyclic declaration");
|
error(e->token, "Illegal cyclic declaration");
|
||||||
|
|||||||
+153
-56
@@ -263,11 +263,13 @@ bool check_is_assignable_to(Checker *c, Operand *operand, Type *type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ^T <- rawptr
|
// ^T <- rawptr
|
||||||
|
#if 0
|
||||||
// TODO(bill): Should C-style (not C++) pointer cast be allowed?
|
// TODO(bill): Should C-style (not C++) pointer cast be allowed?
|
||||||
// if (is_type_pointer(dst) && is_type_rawptr(src)) {
|
if (is_type_pointer(dst) && is_type_rawptr(src)) {
|
||||||
// return true;
|
return true;
|
||||||
// }
|
}
|
||||||
|
#endif
|
||||||
|
#if 1
|
||||||
// rawptr <- ^T
|
// rawptr <- ^T
|
||||||
if (is_type_rawptr(dst) && is_type_pointer(src)) {
|
if (is_type_rawptr(dst) && is_type_pointer(src)) {
|
||||||
// TODO(bill): Handle this properly
|
// TODO(bill): Handle this properly
|
||||||
@@ -276,8 +278,7 @@ bool check_is_assignable_to(Checker *c, Operand *operand, Type *type) {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
if (dst->kind == Type_Array && src->kind == Type_Array) {
|
if (dst->kind == Type_Array && src->kind == Type_Array) {
|
||||||
if (are_types_identical(dst->Array.elem, src->Array.elem)) {
|
if (are_types_identical(dst->Array.elem, src->Array.elem)) {
|
||||||
@@ -702,20 +703,21 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
|
|||||||
map_entity_init_with_reserve(&entity_map, c->tmp_allocator, 2*(et->fields.count));
|
map_entity_init_with_reserve(&entity_map, c->tmp_allocator, 2*(et->fields.count));
|
||||||
|
|
||||||
Entity **fields = gb_alloc_array(c->allocator, Entity *, et->fields.count);
|
Entity **fields = gb_alloc_array(c->allocator, Entity *, et->fields.count);
|
||||||
isize field_index = 0;
|
isize field_count = 0;
|
||||||
|
|
||||||
Type *constant_type = enum_type;
|
Type *constant_type = enum_type;
|
||||||
if (named_type != NULL) {
|
if (named_type != NULL) {
|
||||||
constant_type = named_type;
|
constant_type = named_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *prev_expr = NULL;
|
ExactValue iota = make_exact_value_integer(-1);
|
||||||
|
ExactValue min_value = make_exact_value_integer(0);
|
||||||
i64 iota = 0;
|
ExactValue max_value = make_exact_value_integer(0);
|
||||||
|
|
||||||
for_array(i, et->fields) {
|
for_array(i, et->fields) {
|
||||||
AstNode *field = et->fields.e[i];
|
AstNode *field = et->fields.e[i];
|
||||||
AstNode *ident = NULL;
|
AstNode *ident = NULL;
|
||||||
|
AstNode *init = NULL;
|
||||||
if (field->kind == AstNode_FieldValue) {
|
if (field->kind == AstNode_FieldValue) {
|
||||||
ast_node(fv, FieldValue, field);
|
ast_node(fv, FieldValue, field);
|
||||||
if (fv->field == NULL || fv->field->kind != AstNode_Ident) {
|
if (fv->field == NULL || fv->field->kind != AstNode_Ident) {
|
||||||
@@ -723,7 +725,7 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ident = fv->field;
|
ident = fv->field;
|
||||||
prev_expr = fv->value;
|
init = fv->value;
|
||||||
} else if (field->kind == AstNode_Ident) {
|
} else if (field->kind == AstNode_Ident) {
|
||||||
ident = field;
|
ident = field;
|
||||||
} else {
|
} else {
|
||||||
@@ -732,48 +734,73 @@ void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *nod
|
|||||||
}
|
}
|
||||||
String name = ident->Ident.string;
|
String name = ident->Ident.string;
|
||||||
|
|
||||||
if (str_ne(name, str_lit("_"))) {
|
if (init != NULL) {
|
||||||
ExactValue v = make_exact_value_integer(iota);
|
Operand o = {0};
|
||||||
Entity *e = make_entity_constant(c->allocator, c->context.scope, ident->Ident, constant_type, v);
|
check_expr(c, &o, init);
|
||||||
e->identifier = ident;
|
if (o.mode != Addressing_Constant) {
|
||||||
e->flags |= EntityFlag_Visited;
|
error_node(init, "Enumeration value must be a constant");
|
||||||
|
o.mode = Addressing_Invalid;
|
||||||
|
|
||||||
AstNode *init = prev_expr;
|
|
||||||
if (init == NULL) {
|
|
||||||
error_node(field, "Missing initial expression for enumeration, e.g. iota");
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
if (o.mode != Addressing_Invalid) {
|
||||||
ExactValue context_iota = c->context.iota;
|
check_assignment(c, &o, constant_type, str_lit("enumeration"));
|
||||||
c->context.iota = e->Constant.value;
|
|
||||||
e->Constant.value = (ExactValue){0};
|
|
||||||
|
|
||||||
Operand operand = {0};
|
|
||||||
check_expr(c, &operand, init);
|
|
||||||
|
|
||||||
check_init_constant(c, e, &operand);
|
|
||||||
c->context.iota = context_iota;
|
|
||||||
|
|
||||||
if (operand.mode == Addressing_Constant) {
|
|
||||||
HashKey key = hash_string(name);
|
|
||||||
if (map_entity_get(&entity_map, key) != NULL) {
|
|
||||||
error_node(ident, "`%.*s` is already declared in this enumeration", LIT(name));
|
|
||||||
} else {
|
|
||||||
map_entity_set(&entity_map, key, e);
|
|
||||||
add_entity(c, c->context.scope, NULL, e);
|
|
||||||
fields[field_index++] = e;
|
|
||||||
add_entity_use(c, field, e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (o.mode != Addressing_Invalid) {
|
||||||
|
iota = o.value;
|
||||||
|
} else {
|
||||||
|
iota = exact_binary_operator_value(Token_Add, iota, make_exact_value_integer(1));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
iota = exact_binary_operator_value(Token_Add, iota, make_exact_value_integer(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE(bill): Skip blank identifiers
|
||||||
|
if (str_eq(name, str_lit("_"))) {
|
||||||
|
continue;
|
||||||
|
} else if (str_eq(name, str_lit("count"))) {
|
||||||
|
error_node(field, "`count` is a reserved identifier for enumerations");
|
||||||
|
continue;
|
||||||
|
} else if (str_eq(name, str_lit("min_value"))) {
|
||||||
|
error_node(field, "`min_value` is a reserved identifier for enumerations");
|
||||||
|
continue;
|
||||||
|
} else if (str_eq(name, str_lit("max_value"))) {
|
||||||
|
error_node(field, "`max_value` is a reserved identifier for enumerations");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compare_exact_values(Token_Gt, min_value, iota)) {
|
||||||
|
min_value = iota;
|
||||||
|
}
|
||||||
|
if (compare_exact_values(Token_Lt, max_value, iota)) {
|
||||||
|
max_value = iota;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity *e = make_entity_constant(c->allocator, c->context.scope, ident->Ident, constant_type, iota);
|
||||||
|
e->identifier = ident;
|
||||||
|
e->flags |= EntityFlag_Visited;
|
||||||
|
|
||||||
|
HashKey key = hash_string(name);
|
||||||
|
if (map_entity_get(&entity_map, key) != NULL) {
|
||||||
|
error_node(ident, "`%.*s` is already declared in this enumeration", LIT(name));
|
||||||
|
} else {
|
||||||
|
map_entity_set(&entity_map, key, e);
|
||||||
|
add_entity(c, c->context.scope, NULL, e);
|
||||||
|
fields[field_count++] = e;
|
||||||
|
add_entity_use(c, field, e);
|
||||||
}
|
}
|
||||||
iota++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_ASSERT(field_index <= et->fields.count);
|
GB_ASSERT(field_count <= et->fields.count);
|
||||||
|
|
||||||
enum_type->Record.fields = fields;
|
enum_type->Record.fields = fields;
|
||||||
enum_type->Record.field_count = field_index;
|
enum_type->Record.field_count = field_count;
|
||||||
|
|
||||||
|
enum_type->Record.enum_count = make_entity_constant(c->allocator, c->context.scope,
|
||||||
|
make_token_ident(str_lit("count")), t_int, make_exact_value_integer(field_count));
|
||||||
|
enum_type->Record.enum_min_value = make_entity_constant(c->allocator, c->context.scope,
|
||||||
|
make_token_ident(str_lit("min_value")), constant_type, min_value);
|
||||||
|
enum_type->Record.enum_max_value = make_entity_constant(c->allocator, c->context.scope,
|
||||||
|
make_token_ident(str_lit("max_value")), constant_type, max_value);
|
||||||
|
|
||||||
gb_temp_arena_memory_end(tmp);
|
gb_temp_arena_memory_end(tmp);
|
||||||
}
|
}
|
||||||
@@ -926,15 +953,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) {
|
|||||||
o->type = t_invalid;
|
o->type = t_invalid;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e == e_iota) {
|
o->value = e->Constant.value;
|
||||||
if (c->context.iota.kind == ExactValue_Invalid) {
|
|
||||||
error(e->token, "Use of `iota` outside a enumeration is not allowed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
o->value = c->context.iota;
|
|
||||||
} else {
|
|
||||||
o->value = e->Constant.value;
|
|
||||||
}
|
|
||||||
if (o->value.kind == ExactValue_Invalid) {
|
if (o->value.kind == ExactValue_Invalid) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -4091,7 +4110,6 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Slice:
|
case Type_Slice:
|
||||||
@@ -4162,6 +4180,85 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Type_Basic: {
|
||||||
|
if (!is_type_any(t)) {
|
||||||
|
if (cl->elems.count != 0) {
|
||||||
|
error_node(node, "Illegal compound literal");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (cl->elems.count == 0) {
|
||||||
|
break; // NOTE(bill): No need to init
|
||||||
|
}
|
||||||
|
{ // Checker values
|
||||||
|
Type *field_types[2] = {t_type_info_ptr, t_rawptr};
|
||||||
|
isize field_count = 2;
|
||||||
|
if (cl->elems.e[0]->kind == AstNode_FieldValue) {
|
||||||
|
bool fields_visited[2] = {0};
|
||||||
|
|
||||||
|
for_array(i, cl->elems) {
|
||||||
|
AstNode *elem = cl->elems.e[i];
|
||||||
|
if (elem->kind != AstNode_FieldValue) {
|
||||||
|
error_node(elem, "Mixture of `field = value` and value elements in a `any` literal is not allowed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ast_node(fv, FieldValue, elem);
|
||||||
|
if (fv->field->kind != AstNode_Ident) {
|
||||||
|
gbString expr_str = expr_to_string(fv->field);
|
||||||
|
error_node(elem, "Invalid field name `%s` in `any` literal", expr_str);
|
||||||
|
gb_string_free(expr_str);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String name = fv->field->Ident.string;
|
||||||
|
|
||||||
|
Selection sel = lookup_field(c->allocator, type, name, o->mode == Addressing_Type);
|
||||||
|
if (sel.entity == NULL) {
|
||||||
|
error_node(elem, "Unknown field `%.*s` in `any` literal", LIT(name));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
isize index = sel.index.e[0];
|
||||||
|
|
||||||
|
if (fields_visited[index]) {
|
||||||
|
error_node(elem, "Duplicate field `%.*s` in `any` literal", LIT(name));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fields_visited[index] = true;
|
||||||
|
check_expr(c, o, fv->value);
|
||||||
|
|
||||||
|
// NOTE(bill): `any` literals can never be constant
|
||||||
|
is_constant = false;
|
||||||
|
|
||||||
|
check_assignment(c, o, field_types[index], str_lit("`any` literal"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for_array(index, cl->elems) {
|
||||||
|
AstNode *elem = cl->elems.e[index];
|
||||||
|
if (elem->kind == AstNode_FieldValue) {
|
||||||
|
error_node(elem, "Mixture of `field = value` and value elements in a `any` literal is not allowed");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
check_expr(c, o, elem);
|
||||||
|
if (index >= field_count) {
|
||||||
|
error_node(o->expr, "Too many values in `any` literal, expected %td", field_count);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE(bill): `any` literals can never be constant
|
||||||
|
is_constant = false;
|
||||||
|
|
||||||
|
check_assignment(c, o, field_types[index], str_lit("`any` literal"));
|
||||||
|
}
|
||||||
|
if (cl->elems.count < field_count) {
|
||||||
|
error(cl->close, "Too few values in `any` literal, expected %td, got %td", field_count, cl->elems.count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
gbString str = type_to_string(type);
|
gbString str = type_to_string(type);
|
||||||
error_node(node, "Invalid compound literal type `%s`", str);
|
error_node(node, "Invalid compound literal type `%s`", str);
|
||||||
|
|||||||
+12
-4
@@ -210,7 +210,6 @@ typedef struct CheckerContext {
|
|||||||
Scope * scope;
|
Scope * scope;
|
||||||
DeclInfo * decl;
|
DeclInfo * decl;
|
||||||
u32 stmt_state_flags;
|
u32 stmt_state_flags;
|
||||||
ExactValue iota; // Value of `iota` in a constant declaration; Invalid otherwise
|
|
||||||
} CheckerContext;
|
} CheckerContext;
|
||||||
|
|
||||||
#define MAP_TYPE TypeAndValue
|
#define MAP_TYPE TypeAndValue
|
||||||
@@ -549,7 +548,6 @@ void init_universal_scope(BuildContext *bc) {
|
|||||||
// Constants
|
// Constants
|
||||||
add_global_constant(a, str_lit("true"), t_untyped_bool, make_exact_value_bool(true));
|
add_global_constant(a, str_lit("true"), t_untyped_bool, make_exact_value_bool(true));
|
||||||
add_global_constant(a, str_lit("false"), t_untyped_bool, make_exact_value_bool(false));
|
add_global_constant(a, str_lit("false"), t_untyped_bool, make_exact_value_bool(false));
|
||||||
add_global_constant(a, str_lit("iota"), t_untyped_integer, make_exact_value_integer(0));
|
|
||||||
|
|
||||||
add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil));
|
add_global_entity(make_entity_nil(a, str_lit("nil"), t_untyped_nil));
|
||||||
|
|
||||||
@@ -570,9 +568,10 @@ void init_universal_scope(BuildContext *bc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
t_u8_ptr = make_type_pointer(a, t_u8);
|
t_u8_ptr = make_type_pointer(a, t_u8);
|
||||||
t_int_ptr = make_type_pointer(a, t_int);
|
t_int_ptr = make_type_pointer(a, t_int);
|
||||||
e_iota = scope_lookup_entity(universal_scope, str_lit("iota"));
|
t_i64_ptr = make_type_pointer(a, t_i64);
|
||||||
|
t_f64_ptr = make_type_pointer(a, t_f64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1020,6 +1019,11 @@ void init_preload(Checker *c) {
|
|||||||
compiler_error("Could not find type declaration for `Type_Info_Member`\n"
|
compiler_error("Could not find type declaration for `Type_Info_Member`\n"
|
||||||
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
||||||
}
|
}
|
||||||
|
Entity *type_info_enum_value_entity = current_scope_lookup_entity(c->global_scope, str_lit("Type_Info_Enum_Value"));
|
||||||
|
if (type_info_entity == NULL) {
|
||||||
|
compiler_error("Could not find type declaration for `Type_Info_Enum_Value`\n"
|
||||||
|
"Is `runtime.odin` missing from the `core` directory relative to odin.exe?");
|
||||||
|
}
|
||||||
t_type_info = type_info_entity->type;
|
t_type_info = type_info_entity->type;
|
||||||
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
|
||||||
GB_ASSERT(is_type_union(type_info_entity->type));
|
GB_ASSERT(is_type_union(type_info_entity->type));
|
||||||
@@ -1028,6 +1032,10 @@ void init_preload(Checker *c) {
|
|||||||
t_type_info_member = type_info_member_entity->type;
|
t_type_info_member = type_info_member_entity->type;
|
||||||
t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
|
t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
|
||||||
|
|
||||||
|
t_type_info_enum_value = type_info_enum_value_entity->type;
|
||||||
|
t_type_info_enum_value_ptr = make_type_pointer(c->allocator, t_type_info_enum_value);
|
||||||
|
|
||||||
|
|
||||||
if (record->field_count != 18) {
|
if (record->field_count != 18) {
|
||||||
compiler_error("Invalid `Type_Info` layout");
|
compiler_error("Invalid `Type_Info` layout");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,9 +85,6 @@ struct Entity {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Entity *e_iota = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, Type *type) {
|
Entity *alloc_entity(gbAllocator a, EntityKind kind, Scope *scope, Token token, Type *type) {
|
||||||
Entity *entity = gb_alloc_item(a, Entity);
|
Entity *entity = gb_alloc_item(a, Entity);
|
||||||
entity->kind = kind;
|
entity->kind = kind;
|
||||||
|
|||||||
@@ -1051,6 +1051,12 @@ irValue *ir_make_const_i32(gbAllocator a, i64 i) {
|
|||||||
irValue *ir_make_const_i64(gbAllocator a, i64 i) {
|
irValue *ir_make_const_i64(gbAllocator a, i64 i) {
|
||||||
return ir_make_value_constant(a, t_i64, make_exact_value_integer(i));
|
return ir_make_value_constant(a, t_i64, make_exact_value_integer(i));
|
||||||
}
|
}
|
||||||
|
irValue *ir_make_const_f32(gbAllocator a, f32 f) {
|
||||||
|
return ir_make_value_constant(a, t_f32, make_exact_value_float(f));
|
||||||
|
}
|
||||||
|
irValue *ir_make_const_f64(gbAllocator a, f64 f) {
|
||||||
|
return ir_make_value_constant(a, t_f64, make_exact_value_float(f));
|
||||||
|
}
|
||||||
irValue *ir_make_const_bool(gbAllocator a, bool b) {
|
irValue *ir_make_const_bool(gbAllocator a, bool b) {
|
||||||
return ir_make_value_constant(a, t_bool, make_exact_value_bool(b != 0));
|
return ir_make_value_constant(a, t_bool, make_exact_value_bool(b != 0));
|
||||||
}
|
}
|
||||||
@@ -3743,6 +3749,48 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
ir_emit_store(proc, gep2, ir_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
|
ir_emit_store(proc, gep2, ir_make_const_int(proc->module->allocator, slice->ConstantSlice.count));
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case Type_Basic: {
|
||||||
|
GB_ASSERT(is_type_any(bt));
|
||||||
|
if (cl->elems.count > 0) {
|
||||||
|
ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, make_exact_value_compound(expr)));
|
||||||
|
String field_names[2] = {
|
||||||
|
str_lit("type_info"),
|
||||||
|
str_lit("data"),
|
||||||
|
};
|
||||||
|
Type *field_types[2] = {
|
||||||
|
t_type_info_ptr,
|
||||||
|
t_rawptr,
|
||||||
|
};
|
||||||
|
|
||||||
|
for_array(field_index, cl->elems) {
|
||||||
|
AstNode *elem = cl->elems.e[field_index];
|
||||||
|
|
||||||
|
irValue *field_expr = NULL;
|
||||||
|
isize index = field_index;
|
||||||
|
|
||||||
|
if (elem->kind == AstNode_FieldValue) {
|
||||||
|
ast_node(fv, FieldValue, elem);
|
||||||
|
Selection sel = lookup_field(proc->module->allocator, bt, fv->field->Ident.string, false);
|
||||||
|
index = sel.index.e[0];
|
||||||
|
elem = fv->value;
|
||||||
|
} else {
|
||||||
|
TypeAndValue *tav = type_and_value_of_expression(proc->module->info, elem);
|
||||||
|
Selection sel = lookup_field(proc->module->allocator, bt, field_names[field_index], false);
|
||||||
|
index = sel.index.e[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
field_expr = ir_build_expr(proc, elem);
|
||||||
|
|
||||||
|
GB_ASSERT(ir_type(field_expr)->kind != Type_Tuple);
|
||||||
|
|
||||||
|
Type *ft = field_types[index];
|
||||||
|
irValue *fv = ir_emit_conv(proc, field_expr, ft);
|
||||||
|
irValue *gep = ir_emit_struct_ep(proc, v, index);
|
||||||
|
ir_emit_store(proc, gep, fv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ir_make_addr(v, expr);
|
return ir_make_addr(v, expr);
|
||||||
@@ -5682,6 +5730,7 @@ void ir_gen_tree(irGen *s) {
|
|||||||
Entity **fields = t->Record.fields;
|
Entity **fields = t->Record.fields;
|
||||||
isize count = t->Record.field_count;
|
isize count = t->Record.field_count;
|
||||||
irValue *name_array = NULL;
|
irValue *name_array = NULL;
|
||||||
|
irValue *value_array = NULL;
|
||||||
|
|
||||||
{
|
{
|
||||||
Token token = {Token_Ident};
|
Token token = {Token_Ident};
|
||||||
@@ -5698,8 +5747,40 @@ void ir_gen_tree(irGen *s) {
|
|||||||
map_ir_value_set(&m->members, hash_string(token.string), name_array);
|
map_ir_value_set(&m->members, hash_string(token.string), name_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Token token = {Token_Ident};
|
||||||
|
i32 id = cast(i32)entry_index;
|
||||||
|
char name_base[] = "__$enum_values";
|
||||||
|
isize name_len = gb_size_of(name_base) + 10;
|
||||||
|
token.string.text = gb_alloc_array(a, u8, name_len);
|
||||||
|
token.string.len = gb_snprintf(cast(char *)token.string.text, name_len,
|
||||||
|
"%s-%d", name_base, id)-1;
|
||||||
|
Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, t_type_info_enum_value, count));
|
||||||
|
value_array = ir_make_value_global(a, e, NULL);
|
||||||
|
value_array->Global.is_private = true;
|
||||||
|
ir_module_add_value(m, e, value_array);
|
||||||
|
map_ir_value_set(&m->members, hash_string(token.string), value_array);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_value_int = is_type_integer(t->Record.enum_base_type);
|
||||||
|
|
||||||
for (isize i = 0; i < count; i++) {
|
for (isize i = 0; i < count; i++) {
|
||||||
irValue *name_ep = ir_emit_array_epi(proc, name_array, i);
|
irValue *name_ep = ir_emit_array_epi(proc, name_array, i);
|
||||||
|
irValue *value_ep = ir_emit_array_epi(proc, value_array, i);
|
||||||
|
|
||||||
|
ExactValue value = fields[i]->Constant.value;
|
||||||
|
|
||||||
|
if (is_value_int) {
|
||||||
|
i64 i = value.value_integer;
|
||||||
|
value_ep = ir_emit_conv(proc, value_ep, t_i64_ptr);
|
||||||
|
ir_emit_store(proc, value_ep, ir_make_const_i64(a, i));
|
||||||
|
} else {
|
||||||
|
GB_ASSERT(is_type_float(t->Record.enum_base_type));
|
||||||
|
f64 f = value.value_float;
|
||||||
|
value_ep = ir_emit_conv(proc, value_ep, t_f64_ptr);
|
||||||
|
ir_emit_store(proc, value_ep, ir_make_const_f64(a, f));
|
||||||
|
}
|
||||||
|
|
||||||
ir_emit_store(proc, name_ep, ir_make_const_string(a, fields[i]->token.string));
|
ir_emit_store(proc, name_ep, ir_make_const_string(a, fields[i]->token.string));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5711,6 +5792,13 @@ void ir_gen_tree(irGen *s) {
|
|||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, names, 0), name_array_elem);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, names, 0), name_array_elem);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, names, 1), v_count);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, names, 1), v_count);
|
||||||
ir_emit_store(proc, ir_emit_struct_ep(proc, names, 2), v_count);
|
ir_emit_store(proc, ir_emit_struct_ep(proc, names, 2), v_count);
|
||||||
|
|
||||||
|
irValue *values = ir_emit_struct_ep(proc, tag, 2);
|
||||||
|
irValue *value_array_elem = ir_array_elem(proc, value_array);
|
||||||
|
|
||||||
|
ir_emit_store(proc, ir_emit_struct_ep(proc, values, 0), value_array_elem);
|
||||||
|
ir_emit_store(proc, ir_emit_struct_ep(proc, values, 1), v_count);
|
||||||
|
ir_emit_store(proc, ir_emit_struct_ep(proc, values, 2), v_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
+30
-7
@@ -84,7 +84,10 @@ typedef struct TypeRecord {
|
|||||||
bool struct_is_ordered;
|
bool struct_is_ordered;
|
||||||
Entity **fields_in_src_order; // Entity_Variable
|
Entity **fields_in_src_order; // Entity_Variable
|
||||||
|
|
||||||
Type * enum_base_type;
|
Type * enum_base_type;
|
||||||
|
Entity *enum_count;
|
||||||
|
Entity *enum_min_value;
|
||||||
|
Entity *enum_max_value;
|
||||||
} TypeRecord;
|
} TypeRecord;
|
||||||
|
|
||||||
#define TYPE_KINDS \
|
#define TYPE_KINDS \
|
||||||
@@ -253,11 +256,15 @@ gb_global Type *t_rune = &basic_type_aliases[1];
|
|||||||
|
|
||||||
gb_global Type *t_u8_ptr = NULL;
|
gb_global Type *t_u8_ptr = NULL;
|
||||||
gb_global Type *t_int_ptr = NULL;
|
gb_global Type *t_int_ptr = NULL;
|
||||||
|
gb_global Type *t_i64_ptr = NULL;
|
||||||
|
gb_global Type *t_f64_ptr = NULL;
|
||||||
|
|
||||||
gb_global Type *t_type_info = NULL;
|
gb_global Type *t_type_info = NULL;
|
||||||
gb_global Type *t_type_info_ptr = NULL;
|
gb_global Type *t_type_info_member = NULL;
|
||||||
gb_global Type *t_type_info_member = NULL;
|
gb_global Type *t_type_info_enum_value = NULL;
|
||||||
gb_global Type *t_type_info_member_ptr = NULL;
|
gb_global Type *t_type_info_ptr = NULL;
|
||||||
|
gb_global Type *t_type_info_member_ptr = NULL;
|
||||||
|
gb_global Type *t_type_info_enum_value_ptr = NULL;
|
||||||
|
|
||||||
gb_global Type *t_type_info_named = NULL;
|
gb_global Type *t_type_info_named = NULL;
|
||||||
gb_global Type *t_type_info_integer = NULL;
|
gb_global Type *t_type_info_integer = NULL;
|
||||||
@@ -1043,11 +1050,27 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
|||||||
|
|
||||||
if (str_eq(field_name, str)) {
|
if (str_eq(field_name, str)) {
|
||||||
sel.entity = f;
|
sel.entity = f;
|
||||||
selection_add_index(&sel, i);
|
// selection_add_index(&sel, i);
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (is_type_enum(type)) {
|
} else if (is_type_enum(type)) {
|
||||||
|
// NOTE(bill): These may not have been added yet, so check in case
|
||||||
|
if (type->Record.enum_count != NULL) {
|
||||||
|
if (str_eq(field_name, str_lit("count"))) {
|
||||||
|
sel.entity = type->Record.enum_count;
|
||||||
|
return sel;
|
||||||
|
}
|
||||||
|
if (str_eq(field_name, str_lit("min_value"))) {
|
||||||
|
sel.entity = type->Record.enum_min_value;
|
||||||
|
return sel;
|
||||||
|
}
|
||||||
|
if (str_eq(field_name, str_lit("max_value"))) {
|
||||||
|
sel.entity = type->Record.enum_max_value;
|
||||||
|
return sel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (isize i = 0; i < type->Record.field_count; i++) {
|
for (isize i = 0; i < type->Record.field_count; i++) {
|
||||||
Entity *f = type->Record.fields[i];
|
Entity *f = type->Record.fields[i];
|
||||||
GB_ASSERT(f->kind == Entity_Constant);
|
GB_ASSERT(f->kind == Entity_Constant);
|
||||||
@@ -1055,7 +1078,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
|||||||
|
|
||||||
if (str_eq(field_name, str)) {
|
if (str_eq(field_name, str)) {
|
||||||
sel.entity = f;
|
sel.entity = f;
|
||||||
selection_add_index(&sel, i);
|
// selection_add_index(&sel, i);
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user