aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGinger Bill <bill@gingerbill.org>2016-12-19 14:03:59 +0000
committerGinger Bill <bill@gingerbill.org>2016-12-19 14:03:59 +0000
commit478d63424fb99c368a0cfae88704b2c903956a1d (patch)
tree6e46bc62dd94772ff4fc07b84e93c7bf7d237681 /src
parentac1566762bdfea1e9cf27dfdad393352398bbab0 (diff)
Remove `enum` for favour of Go-style enumerations
Diffstat (limited to 'src')
-rw-r--r--src/checker/checker.c87
-rw-r--r--src/checker/decl.c22
-rw-r--r--src/checker/entity.c1
-rw-r--r--src/checker/expr.c263
-rw-r--r--src/checker/stmt.c93
-rw-r--r--src/checker/types.c101
-rw-r--r--src/parser.c51
-rw-r--r--src/ssa.c149
-rw-r--r--src/ssa_print.c3
9 files changed, 89 insertions, 681 deletions
diff --git a/src/checker/checker.c b/src/checker/checker.c
index 14cb62bdb..705fc54d9 100644
--- a/src/checker/checker.c
+++ b/src/checker/checker.c
@@ -127,8 +127,6 @@ typedef enum BuiltinProcId {
BuiltinProc_abs,
BuiltinProc_clamp,
- BuiltinProc_enum_to_string,
-
BuiltinProc_Count,
} BuiltinProcId;
typedef struct BuiltinProc {
@@ -171,8 +169,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
{STR_LIT("max"), 2, false, Expr_Expr},
{STR_LIT("abs"), 1, false, Expr_Expr},
{STR_LIT("clamp"), 3, false, Expr_Expr},
-
- {STR_LIT("enum_to_string"), 1, false, Expr_Expr},
};
typedef enum ImplicitValueId {
@@ -681,7 +677,9 @@ void add_untyped(CheckerInfo *i, AstNode *expression, bool lhs, AddressingMode m
}
void add_type_and_value(CheckerInfo *i, AstNode *expression, AddressingMode mode, Type *type, ExactValue value) {
- GB_ASSERT(expression != NULL);
+ if (expression == NULL) {
+ return;
+ }
if (mode == Addressing_Invalid) {
return;
}
@@ -864,10 +862,6 @@ void add_type_info_type(Checker *c, Type *t) {
case Type_Record: {
switch (bt->Record.kind) {
- case TypeRecord_Enum:
- add_type_info_type(c, bt->Record.enum_base);
- break;
-
case TypeRecord_Union:
add_type_info_type(c, t_int);
/* fallthrough */
@@ -1012,7 +1006,7 @@ void init_preload(Checker *c) {
t_type_info_member = type_info_member_entity->type;
t_type_info_member_ptr = make_type_pointer(c->allocator, t_type_info_member);
- if (record->field_count != 18) {
+ if (record->field_count != 17) {
compiler_error("Invalid `Type_Info` layout");
}
t_type_info_named = record->fields[ 1]->type;
@@ -1031,7 +1025,6 @@ void init_preload(Checker *c) {
t_type_info_struct = record->fields[14]->type;
t_type_info_union = record->fields[15]->type;
t_type_info_raw_union = record->fields[16]->type;
- t_type_info_enum = record->fields[17]->type;
}
if (t_allocator == NULL) {
@@ -1253,78 +1246,6 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
DelayedDecl di = {parent_scope, decl};
array_add(&c->delayed_foreign_libraries, di);
case_end;
- case_ast_node(vd, VarDecl, decl);
- if (!parent_scope->is_file) {
- // NOTE(bill): Within a procedure, variables must be in order
- continue;
- }
-
- // NOTE(bill): You need to store the entity information here unline a constant declaration
- isize entity_count = vd->names.count;
- isize entity_index = 0;
- Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
- DeclInfo *di = NULL;
- if (vd->values.count > 0) {
- di = make_declaration_info(heap_allocator(), parent_scope);
- di->entities = entities;
- di->entity_count = entity_count;
- di->type_expr = vd->type;
- di->init_expr = vd->values.e[0];
- }
-
- for_array(i, vd->names) {
- AstNode *name = vd->names.e[i];
- AstNode *value = NULL;
- if (i < vd->values.count) {
- value = vd->values.e[i];
- }
- if (name->kind != AstNode_Ident) {
- error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
- continue;
- }
- Entity *e = make_entity_variable(c->allocator, parent_scope, name->Ident, NULL);
- e->identifier = name;
- entities[entity_index++] = e;
-
- DeclInfo *d = di;
- if (d == NULL) {
- AstNode *init_expr = value;
- d = make_declaration_info(heap_allocator(), e->scope);
- d->type_expr = vd->type;
- d->init_expr = init_expr;
- d->var_decl_tags = vd->tags;
- }
-
- add_entity_and_decl_info(c, name, e, d);
- }
- case_end;
- case_ast_node(cd, ConstDecl, decl);
- for_array(i, cd->values) {
- AstNode *name = cd->names.e[i];
- AstNode *value = unparen_expr(cd->values.e[i]);
- if (name->kind != AstNode_Ident) {
- error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
- continue;
- }
-
- ExactValue v = {ExactValue_Invalid};
- Entity *e = make_entity_constant(c->allocator, parent_scope, name->Ident, NULL, v);
- e->identifier = name;
- DeclInfo *di = make_declaration_info(c->allocator, e->scope);
- di->type_expr = cd->type;
- di->init_expr = value;
- add_entity_and_decl_info(c, name, e, di);
- }
-
- isize lhs_count = cd->names.count;
- isize rhs_count = cd->values.count;
-
- if (rhs_count == 0 && cd->type == NULL) {
- error_node(decl, "Missing type or initial expression");
- } else if (lhs_count < rhs_count) {
- error_node(decl, "Extra initial expression");
- }
- case_end;
case_ast_node(td, TypeDecl, decl);
if (td->name->kind != AstNode_Ident) {
error_node(td->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[td->name->kind]));
diff --git a/src/checker/decl.c b/src/checker/decl.c
index 603d04c5d..5266a8bba 100644
--- a/src/checker/decl.c
+++ b/src/checker/decl.c
@@ -98,15 +98,14 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
gb_temp_arena_memory_end(tmp);
}
-
-void check_var_decl_node(Checker *c, AstNode *node) {
- ast_node(vd, VarDecl, node);
- isize entity_count = vd->names.count;
+void check_var_spec_node(Checker *c, AstNodeValueSpec *vs) {
+ GB_ASSERT(vs->keyword == Token_var);
+ isize entity_count = vs->names.count;
isize entity_index = 0;
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
- for_array(i, vd->names) {
- AstNode *name = vd->names.e[i];
+ for_array(i, vs->names) {
+ AstNode *name = vs->names.e[i];
Entity *entity = NULL;
if (name->kind == AstNode_Ident) {
Token token = name->Ident;
@@ -137,8 +136,8 @@ void check_var_decl_node(Checker *c, AstNode *node) {
}
Type *init_type = NULL;
- if (vd->type) {
- init_type = check_type_extra(c, vd->type, NULL);
+ if (vs->type) {
+ init_type = check_type_extra(c, vs->type, NULL);
if (init_type == NULL) {
init_type = t_invalid;
}
@@ -157,11 +156,12 @@ void check_var_decl_node(Checker *c, AstNode *node) {
e->type = init_type;
}
- check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration"));
- for_array(i, vd->names) {
+ check_init_variables(c, entities, entity_count, vs->values, str_lit("variable declaration"));
+
+ for_array(i, vs->names) {
if (entities[i] != NULL) {
- add_entity(c, c->context.scope, vd->names.e[i], entities[i]);
+ add_entity(c, c->context.scope, vs->names.e[i], entities[i]);
}
}
diff --git a/src/checker/entity.c b/src/checker/entity.c
index d02268837..3eb62db08 100644
--- a/src/checker/entity.c
+++ b/src/checker/entity.c
@@ -55,6 +55,7 @@ struct Entity {
ExactValue value;
} Constant;
struct {
+ b32 is_let;
i32 field_index;
i32 field_src_index;
} Variable;
diff --git a/src/checker/expr.c b/src/checker/expr.c
index 9562473ca..5b50e75a0 100644
--- a/src/checker/expr.c
+++ b/src/checker/expr.c
@@ -131,76 +131,6 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
}
}
case_end;
- case_ast_node(cd, ConstDecl, node);
- gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-
- isize entity_count = cd->names.count;
- isize entity_index = 0;
- Entity **entities = gb_alloc_array(c->tmp_allocator, Entity *, entity_count);
-
- for_array(i, cd->values) {
- AstNode *name = cd->names.e[i];
- AstNode *value = unparen_expr(cd->values.e[i]);
- if (name->kind != AstNode_Ident) {
- error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
- entities[entity_index++] = NULL;
- continue;
- }
-
- ExactValue v = {ExactValue_Invalid};
- Entity *e = make_entity_constant(c->allocator, c->context.scope, name->Ident, NULL, v);
- e->identifier = name;
- entities[entity_index++] = e;
- DeclInfo *d = make_declaration_info(c->allocator, e->scope);
- d->type_expr = cd->type;
- d->init_expr = value;
- add_entity_and_decl_info(c, name, e, d);
-
- DelayedEntity delay = {name, e, d};
- array_add(delayed_entities, delay);
- }
-
- isize lhs_count = cd->names.count;
- isize rhs_count = cd->values.count;
-
- // TODO(bill): Better error messages or is this good enough?
- if (rhs_count == 0 && cd->type == NULL) {
- error_node(node, "Missing type or initial expression");
- } else if (lhs_count < rhs_count) {
- error_node(node, "Extra initial expression");
- }
-
- if (dof != NULL) {
- // NOTE(bill): Within a record
- for_array(i, cd->names) {
- Entity *e = entities[i];
- if (e == NULL) {
- continue;
- }
- AstNode *name = cd->names.e[i];
- if (name->kind != AstNode_Ident) {
- continue;
- }
- Token name_token = name->Ident;
- if (str_eq(name_token.string, str_lit("_"))) {
- dof->other_fields[dof->other_field_index++] = e;
- } else {
- HashKey key = hash_string(name_token.string);
- if (map_entity_get(dof->entity_map, key) != NULL) {
- // TODO(bill): Scope checking already checks the declaration
- error(name_token, "`%.*s` is already declared in this record", LIT(name_token.string));
- } else {
- map_entity_set(dof->entity_map, key, e);
- dof->other_fields[dof->other_field_index++] = e;
- }
- add_entity(c, c->context.scope, name, e);
- }
- }
- }
-
- gb_temp_arena_memory_end(tmp);
- case_end;
-
#if 0
case_ast_node(pd, ProcDecl, node);
if (!ast_node_expect(pd->name, AstNode_Ident)) {
@@ -362,9 +292,6 @@ bool check_is_assignable_to(Checker *c, Operand *operand, Type *type) {
}
if (are_types_identical(dst, src) && (!is_type_named(dst) || !is_type_named(src))) {
- if (is_type_enum(dst) && is_type_enum(src)) {
- return are_types_identical(s, type);
- }
return true;
}
@@ -794,127 +721,6 @@ GB_COMPARE_PROC(cmp_enum_order) {
return i < j ? -1 : i > j;
}
-
-
-void check_enum_type(Checker *c, Type *enum_type, Type *named_type, AstNode *node) {
- GB_ASSERT(node->kind == AstNode_EnumType);
- GB_ASSERT(is_type_enum(enum_type));
- ast_node(et, EnumType, node);
-
- Type *base_type = t_int;
- if (et->base_type != NULL) {
- base_type = check_type(c, et->base_type);
- }
-
- if (base_type == NULL || !is_type_integer(base_type)) {
- error(et->token, "Base type for enumeration must be an integer");
- return;
- } else
- if (base_type == NULL) {
- base_type = t_int;
- }
- enum_type->Record.enum_base = base_type;
-
- Entity **fields = gb_alloc_array(c->allocator, Entity *, et->fields.count);
- isize field_index = 0;
- ExactValue iota = make_exact_value_integer(-1);
- i64 min_value = 0;
- i64 max_value = 0;
-
- Type *constant_type = enum_type;
- if (named_type != NULL) {
- constant_type = named_type;
- }
-
-
- gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&c->tmp_arena);
-
- MapEntity entity_map = {0};
- map_entity_init_with_reserve(&entity_map, c->tmp_allocator, 2*(et->fields.count));
-
- Entity *blank_entity = make_entity_constant(c->allocator, c->context.scope, blank_token, constant_type, make_exact_value_integer(0));;
-
- for_array(i, et->fields) {
- AstNode *field = et->fields.e[i];
-
- if (!ast_node_expect(field, AstNode_FieldValue)) {
- continue;
- }
-
- ast_node(f, FieldValue, field);
- Token name_token = f->field->Ident;
-
- if (str_eq(name_token.string, str_lit("count"))) {
- error(name_token, "`count` is a reserved identifier for enumerations");
- fields[field_index++] = blank_entity;
- continue;
- } else if (str_eq(name_token.string, str_lit("min_value"))) {
- error(name_token, "`min_value` is a reserved identifier for enumerations");
- fields[field_index++] = blank_entity;
- continue;
- } else if (str_eq(name_token.string, str_lit("max_value"))) {
- error(name_token, "`max_value` is a reserved identifier for enumerations");
- fields[field_index++] = blank_entity;
- continue;
- }
-
- Operand o = {0};
- if (f->value != NULL) {
- check_expr(c, &o, f->value);
- if (o.mode != Addressing_Constant) {
- error_node(f->value, "Enumeration value must be a constant integer %d");
- o.mode = Addressing_Invalid;
- }
- if (o.mode != Addressing_Invalid) {
- check_assignment(c, &o, constant_type, str_lit("enumeration"));
- }
- 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));
- }
-
-
- Entity *e = make_entity_constant(c->allocator, c->context.scope, name_token, constant_type, iota);
- if (min_value > iota.value_integer) {
- min_value = iota.value_integer;
- }
- if (max_value < iota.value_integer) {
- max_value = iota.value_integer;
- }
-
- HashKey key = hash_string(name_token.string);
- if (map_entity_get(&entity_map, key)) {
- // TODO(bill): Scope checking already checks the declaration
- error(name_token, "`%.*s` is already declared in this enumeration", LIT(name_token.string));
- } else {
- map_entity_set(&entity_map, key, e);
- add_entity(c, c->context.scope, NULL, e);
- fields[field_index++] = e;
- }
- add_entity_use(c, f->field, e);
- }
-
- GB_ASSERT(field_index <= et->fields.count);
-
- gb_sort_array(fields, field_index, cmp_enum_order);
-
- enum_type->Record.enum_values = fields;
- enum_type->Record.enum_value_count = field_index;
-
- enum_type->Record.enum_count = make_entity_constant(c->allocator, NULL,
- make_token_ident(str_lit("count")), t_int, make_exact_value_integer(enum_type->Record.enum_value_count));
- enum_type->Record.min_value = make_entity_constant(c->allocator, NULL,
- make_token_ident(str_lit("min_value")), constant_type, make_exact_value_integer(min_value));
- enum_type->Record.max_value = make_entity_constant(c->allocator, NULL,
- make_token_ident(str_lit("max_value")), constant_type, make_exact_value_integer(max_value));
-
- gb_temp_arena_memory_end(tmp);
-}
-
Type *check_get_params(Checker *c, Scope *scope, AstNodeArray params, bool *is_variadic_) {
if (params.count == 0) {
return NULL;
@@ -1165,6 +971,11 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
Type *type = NULL;
gbString err_str = NULL;
+ if (e == NULL) {
+ type = t_invalid;
+ goto end;
+ }
+
switch (e->kind) {
case_ast_node(i, Ident, e);
Operand o = {0};
@@ -1291,16 +1102,6 @@ Type *check_type_extra(Checker *c, AstNode *e, Type *named_type) {
goto end;
case_end;
- case_ast_node(et, EnumType, e);
- type = make_type_enum(c->allocator);
- set_base_type(named_type, type);
- check_open_scope(c, e);
- check_enum_type(c, type, named_type, e);
- check_close_scope(c);
- type->Record.node = e;
- goto end;
- case_end;
-
case_ast_node(pt, ProcType, e);
type = alloc_type(c->allocator, Type_Proc);
set_base_type(named_type, type);
@@ -1357,7 +1158,7 @@ end:
bool check_unary_op(Checker *c, Operand *o, Token op) {
// TODO(bill): Handle errors correctly
- Type *type = base_type(get_enum_base_type(base_vector_type(o->type)));
+ Type *type = base_type(base_vector_type(o->type));
gbString str = NULL;
switch (op.kind) {
case Token_Add:
@@ -1393,7 +1194,7 @@ bool check_unary_op(Checker *c, Operand *o, Token op) {
bool check_binary_op(Checker *c, Operand *o, Token op) {
// TODO(bill): Handle errors correctly
- Type *type = base_type(get_enum_base_type(base_vector_type(o->type)));
+ Type *type = base_type(base_vector_type(o->type));
switch (op.kind) {
case Token_Sub:
case Token_SubEq:
@@ -1470,8 +1271,6 @@ bool check_value_is_expressible(Checker *c, ExactValue in_value, Type *type, Exa
return true;
}
- type = get_enum_base_type(type);
-
if (is_type_boolean(type)) {
return in_value.kind == ExactValue_Bool;
} else if (is_type_string(type)) {
@@ -1554,8 +1353,8 @@ void check_is_expressible(Checker *c, Operand *o, Type *type) {
if (!check_value_is_expressible(c, o->value, type, &o->value)) {
gbString a = expr_to_string(o->expr);
gbString b = type_to_string(type);
- if (is_type_numeric(get_enum_base_type(o->type)) && is_type_numeric(get_enum_base_type(type))) {
- if (!is_type_integer(get_enum_base_type(o->type)) && is_type_integer(get_enum_base_type(type))) {
+ if (is_type_numeric(o->type) && is_type_numeric(type)) {
+ if (!is_type_integer(o->type) && is_type_integer(type)) {
error_node(o->expr, "`%s` truncated to `%s`", a, b);
} else {
error_node(o->expr, "`%s = %lld` overflows `%s`", a, o->value.value_integer, b);
@@ -1859,8 +1658,6 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) {
if (are_types_identical(xb, yb)) {
return true;
}
- xb = get_enum_base_type(x);
- yb = get_enum_base_type(y);
// Cast between booleans and integers
@@ -2460,7 +2257,7 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level
return;
}
- Type *t = get_enum_base_type(base_type(target_type));
+ Type *t = base_type(target_type);
switch (t->kind) {
case Type_Basic:
if (operand->mode == Addressing_Constant) {
@@ -2531,7 +2328,7 @@ bool check_index_value(Checker *c, AstNode *index_value, i64 max_count, i64 *val
return false;
}
- if (!is_type_integer(get_enum_base_type(operand.type))) {
+ if (!is_type_integer(operand.type)) {
gbString expr_str = expr_to_string(operand.expr);
error_node(operand.expr, "Index `%s` must be an integer", expr_str);
gb_string_free(expr_str);
@@ -3598,44 +3395,6 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
}
}
} break;
-
- case BuiltinProc_enum_to_string: {
- Type *type = base_type(operand->type);
- if (!is_type_enum(type)) {
- gbString type_str = type_to_string(operand->type);
- gb_string_free(type_str);
- error_node(call,
- "Expected an enum to `enum_to_string`, got `%s`",
- type_str);
- return false;
- }
-
- if (operand->mode == Addressing_Constant) {
- ExactValue value = make_exact_value_string(str_lit(""));
- if (operand->value.kind == ExactValue_Integer) {
- i64 index = operand->value.value_integer;
- for (isize i = 0; i < type->Record.enum_value_count; i++) {
- Entity *f = type->Record.enum_values[i];
- if (f->kind == Entity_Constant && f->Constant.value.kind == ExactValue_Integer) {
- i64 fv = f->Constant.value.value_integer;
- if (index == fv) {
- value = make_exact_value_string(f->token.string);
- break;
- }
- }
- }
- }
-
- operand->value = value;
- operand->type = t_string;
- return true;
- }
-
- add_type_info_type(c, operand->type);
-
- operand->mode = Addressing_Value;
- operand->type = t_string;
- } break;
}
return true;
diff --git a/src/checker/stmt.c b/src/checker/stmt.c
index 7e1578987..f9ac8cedb 100644
--- a/src/checker/stmt.c
+++ b/src/checker/stmt.c
@@ -279,6 +279,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
c->context.stmt_state_flags = prev_stmt_state_flags;
}
+
+
typedef struct TypeAndToken {
Type *type;
Token token;
@@ -907,19 +909,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
switch (e->kind) {
case Entity_TypeName: {
Type *t = base_type(e->type);
- if (is_type_enum(t)) {
- for (isize i = 0; i < t->Record.enum_value_count; i++) {
- Entity *f = t->Record.enum_values[i];
- Entity *found = scope_insert_entity(c->context.scope, f);
- if (found != NULL) {
- gbString expr_str = expr_to_string(expr);
- error(us->token, "Namespace collision while `using` `%s` of: %.*s", expr_str, LIT(found->token.string));
- gb_string_free(expr_str);
- return;
- }
- f->using_parent = e;
- }
- } else if (is_type_union(t)) {
+ if (is_type_union(t)) {
for (isize i = 0; i < t->Record.field_count; i++) {
Entity *f = t->Record.fields[i];
Entity *found = scope_insert_entity(c->context.scope, f);
@@ -931,6 +921,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
f->using_parent = e;
}
+ } else {
+ error(us->token, "`using` can be only applied to `union` type entities");
}
} break;
@@ -1008,40 +1000,52 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
case_end;
- case_ast_node(vd, VarDecl, us->node);
- if (vd->names.count > 1 && vd->type != NULL) {
- error(us->token, "`using` can only be applied to one variable of the same type");
- }
- check_var_decl_node(c, us->node);
+ case_ast_node(gd, GenericDecl, us->node);
+ for_array(spec_index, gd->specs) {
+ AstNode *spec = gd->specs.e[spec_index];
+ switch (spec->kind) {
+ case_ast_node(vs, ValueSpec, spec);
+ if (vs->keyword != Token_var) {
+ error_node(spec, "`using` can only be applied to a variable declaration");
+ return;
+ }
- for_array(name_index, vd->names) {
- AstNode *item = vd->names.e[name_index];
- ast_node(i, Ident, item);
- String name = i->string;
- Entity *e = scope_lookup_entity(c->context.scope, name);
- Type *t = base_type(type_deref(e->type));
- if (is_type_struct(t) || is_type_raw_union(t)) {
- Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
- GB_ASSERT(found != NULL);
- for_array(i, (*found)->elements.entries) {
- Entity *f = (*found)->elements.entries.e[i].value;
- if (f->kind == Entity_Variable) {
- Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
- Entity *prev = scope_insert_entity(c->context.scope, uvar);
- if (prev != NULL) {
- error(us->token, "Namespace collision while `using` `%.*s` of: %.*s", LIT(name), LIT(prev->token.string));
- return;
+ if (vs->names.count > 1 && vs->type != NULL) {
+ error(us->token, "`using` can only be applied to one variable of the same type");
+ }
+
+ check_var_spec_node(c, vs);
+
+ for_array(name_index, vs->names) {
+ AstNode *item = vs->names.e[name_index];
+ ast_node(i, Ident, item);
+ String name = i->string;
+ Entity *e = scope_lookup_entity(c->context.scope, name);
+ Type *t = base_type(type_deref(e->type));
+ if (is_type_struct(t) || is_type_raw_union(t)) {
+ Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
+ GB_ASSERT(found != NULL);
+ for_array(i, (*found)->elements.entries) {
+ Entity *f = (*found)->elements.entries.e[i].value;
+ if (f->kind == Entity_Variable) {
+ Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
+ Entity *prev = scope_insert_entity(c->context.scope, uvar);
+ if (prev != NULL) {
+ error(us->token, "Namespace collision while `using` `%.*s` of: %.*s", LIT(name), LIT(prev->token.string));
+ return;
+ }
+ }
}
+ } else {
+ error(us->token, "`using` can only be applied to variables of type struct or raw_union");
+ return;
}
}
- } else {
- error(us->token, "`using` can only be applied to variables of type struct or raw_union");
- return;
+ case_end;
}
}
case_end;
-
default:
error(us->token, "Invalid AST: Using Statement");
break;
@@ -1068,12 +1072,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
-
-
- case_ast_node(vd, VarDecl, node);
- check_var_decl_node(c, node);
- case_end;
-
case_ast_node(gd, GenericDecl, node);
for_array(spec_index, gd->specs) {
AstNode *spec = gd->specs.e[spec_index];
@@ -1136,6 +1134,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
if (e->type == NULL)
e->type = init_type;
}
+ check_arity_match(c, vs, NULL);
check_init_variables(c, entities, entity_count, vs->values, str_lit("variable declaration"));
@@ -1158,10 +1157,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
}
case_end;
- case_ast_node(cd, ConstDecl, node);
- // NOTE(bill): Handled elsewhere
- case_end;
-
case_ast_node(td, TypeDecl, node);
// NOTE(bill): Handled elsewhere
case_end;
diff --git a/src/checker/types.c b/src/checker/types.c
index a09254061..c3f3d2383 100644
--- a/src/checker/types.c
+++ b/src/checker/types.c
@@ -62,7 +62,6 @@ typedef enum TypeRecordKind {
TypeRecord_Invalid,
TypeRecord_Struct,
- TypeRecord_Enum,
TypeRecord_RawUnion,
TypeRecord_Union, // Tagged
@@ -78,23 +77,11 @@ typedef struct TypeRecord {
i32 field_count; // == offset_count is struct
AstNode *node;
- union { // NOTE(bill): Reduce size_of Type
- struct { // enum only
- Type * enum_base; // Default is `int`
- Entity * enum_count;
- Entity * min_value;
- Entity * max_value;
- Entity **enum_values;
- i32 enum_value_count;
- };
- struct { // struct only
- i64 * struct_offsets;
- bool struct_are_offsets_set;
- bool struct_is_packed;
- bool struct_is_ordered;
- Entity **fields_in_src_order; // Entity_Variable
- };
- };
+ i64 * struct_offsets;
+ bool struct_are_offsets_set;
+ bool struct_is_packed;
+ bool struct_is_ordered;
+ Entity **fields_in_src_order; // Entity_Variable
} TypeRecord;
#define TYPE_KINDS \
@@ -282,7 +269,6 @@ gb_global Type *t_type_info_tuple = NULL;
gb_global Type *t_type_info_struct = NULL;
gb_global Type *t_type_info_union = NULL;
gb_global Type *t_type_info_raw_union = NULL;
-gb_global Type *t_type_info_enum = NULL;
gb_global Type *t_allocator = NULL;
gb_global Type *t_allocator_ptr = NULL;
@@ -380,11 +366,6 @@ Type *make_type_raw_union(gbAllocator a) {
return t;
}
-Type *make_type_enum(gbAllocator a) {
- Type *t = alloc_type(a, Type_Record);
- t->Record.kind = TypeRecord_Enum;
- return t;
-}
@@ -437,15 +418,6 @@ Type *type_deref(Type *t) {
return t;
}
-Type *get_enum_base_type(Type *t) {
- Type *bt = base_type(t);
- if (bt->kind == Type_Record && bt->Record.kind == TypeRecord_Enum) {
- GB_ASSERT(bt->Record.enum_base != NULL);
- return bt->Record.enum_base;
- }
- return t;
-}
-
bool is_type_named(Type *t) {
if (t->kind == Type_Basic) {
return true;
@@ -508,7 +480,7 @@ bool is_type_untyped(Type *t) {
return false;
}
bool is_type_ordered(Type *t) {
- t = base_type(get_enum_base_type(t));
+ t = base_type(t);
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_Ordered) != 0;
}
@@ -522,9 +494,6 @@ bool is_type_constant_type(Type *t) {
if (t->kind == Type_Basic) {
return (t->Basic.flags & BasicFlag_ConstantType) != 0;
}
- if (t->kind == Type_Record) {
- return t->Record.kind == TypeRecord_Enum;
- }
return false;
}
bool is_type_float(Type *t) {
@@ -615,10 +584,6 @@ Type *base_vector_type(Type *t) {
}
-bool is_type_enum(Type *t) {
- t = base_type(t);
- return (t->kind == Type_Record && t->Record.kind == TypeRecord_Enum);
-}
bool is_type_struct(Type *t) {
t = base_type(t);
return (t->kind == Type_Record && t->Record.kind == TypeRecord_Struct);
@@ -656,20 +621,13 @@ bool type_has_nil(Type *t) {
case Type_Tuple:
return false;
-
- case Type_Record:
- switch (t->Record.kind) {
- case TypeRecord_Enum:
- return false;
- }
- break;
}
return true;
}
bool is_type_comparable(Type *t) {
- t = base_type(get_enum_base_type(t));
+ t = base_type(t);
switch (t->kind) {
case Type_Basic:
return t->kind != Basic_UntypedNil;
@@ -682,8 +640,6 @@ bool is_type_comparable(Type *t) {
if (!is_type_comparable(t->Record.fields[i]->type))
return false;
}
- } else if (is_type_enum(t)) {
- return is_type_comparable(t->Record.enum_base);
}
return false;
} break;
@@ -753,10 +709,6 @@ bool are_types_identical(Type *x, Type *y) {
return true;
}
break;
-
- case TypeRecord_Enum:
- // NOTE(bill): Each enum is unique
- return x == y;
}
}
}
@@ -981,33 +933,7 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
}
}
}
-
- if (is_type_enum(type)) {
- for (isize i = 0; i < type->Record.enum_value_count; i++) {
- Entity *f = type->Record.enum_values[i];
- GB_ASSERT(f->kind != Entity_Variable);
- String str = f->token.string;
-
- if (str_eq(field_name, str)) {
- sel.entity = f;
- selection_add_index(&sel, i);
- return sel;
- }
- }
-
- if (str_eq(field_name, str_lit("count"))) {
- sel.entity = type->Record.enum_count;
- return sel;
- } else if (str_eq(field_name, str_lit("min_value"))) {
- sel.entity = type->Record.min_value;
- return sel;
- } else if (str_eq(field_name, str_lit("max_value"))) {
- sel.entity = type->Record.max_value;
- return sel;
- }
- }
-
- } else if (!is_type_enum(type) && !is_type_union(type)) {
+ } else if (!is_type_union(type)) {
for (isize i = 0; i < type->Record.field_count; i++) {
Entity *f = type->Record.fields[i];
GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
@@ -1247,8 +1173,6 @@ i64 type_align_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, Type
}
return max;
} break;
- case TypeRecord_Enum:
- return type_align_of_internal(s, allocator, t->Record.enum_base, path);
}
} break;
}
@@ -1437,10 +1361,6 @@ i64 type_size_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypeP
// TODO(bill): Is this how it should work?
return align_formula(max, align);
} break;
-
- case TypeRecord_Enum: {
- return type_size_of_internal(s, allocator, t->Record.enum_base, path);
- } break;
}
} break;
}
@@ -1591,11 +1511,6 @@ gbString write_type_to_string(gbString str, Type *type) {
}
str = gb_string_appendc(str, "}");
break;
-
- case TypeRecord_Enum:
- str = gb_string_appendc(str, "enum ");
- str = write_type_to_string(str, type->Record.enum_base);
- break;
}
} break;
diff --git a/src/parser.c b/src/parser.c
index dd4f2a8c5..f502cc316 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -241,21 +241,6 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
u64 tags; \
bool is_using; \
}) \
- AST_NODE_KIND(VarDecl, "variable declaration", struct { \
- u64 tags; \
- bool is_using; \
- AstNodeArray names; \
- AstNode * type; \
- AstNodeArray values; \
- AstNode * note; \
- }) \
- AST_NODE_KIND(ConstDecl, "constant declaration", struct { \
- u64 tags; \
- AstNodeArray names; \
- AstNode * type; \
- AstNodeArray values; \
- AstNode * note; \
- }) \
AST_NODE_KIND(TypeDecl, "type declaration", struct { \
Token token; \
AstNode *name; \
@@ -480,10 +465,6 @@ Token ast_node_token(AstNode *node) {
return node->BadDecl.begin;
case AstNode_GenericDecl:
return node->GenericDecl.token;
- case AstNode_VarDecl:
- return ast_node_token(node->VarDecl.names.e[0]);
- case AstNode_ConstDecl:
- return ast_node_token(node->ConstDecl.names.e[0]);
case AstNode_ProcDecl:
return ast_node_token(node->ProcDecl.name);
case AstNode_TypeDecl:
@@ -917,22 +898,6 @@ AstNode *make_bad_decl(AstFile *f, Token begin, Token end) {
return result;
}
-AstNode *make_var_decl(AstFile *f, AstNodeArray names, AstNode *type, AstNodeArray values) {
- AstNode *result = make_node(f, AstNode_VarDecl);
- result->VarDecl.names = names;
- result->VarDecl.type = type;
- result->VarDecl.values = values;
- return result;
-}
-
-AstNode *make_const_decl(AstFile *f, AstNodeArray names, AstNode *type, AstNodeArray values) {
- AstNode *result = make_node(f, AstNode_ConstDecl);
- result->ConstDecl.names = names;
- result->ConstDecl.type = type;
- result->ConstDecl.values = values;
- return result;
-}
-
AstNode *make_parameter(AstFile *f, AstNodeArray names, AstNode *type, bool is_using) {
AstNode *result = make_node(f, AstNode_Parameter);
result->Parameter.names = names;
@@ -2814,8 +2779,8 @@ AstNode *parse_stmt(AstFile *f) {
valid = true;
}
} break;
- case AstNode_VarDecl:
- valid = true;
+ case AstNode_GenericDecl:
+ valid = node->GenericDecl.token.kind == Token_var;
break;
}
@@ -2952,9 +2917,8 @@ AstNode *parse_stmt(AstFile *f) {
return s;
} else if (str_eq(tag, str_lit("thread_local"))) {
AstNode *decl = parse_simple_stmt(f);
- if (decl->kind != AstNode_VarDecl &&
- (decl->kind == AstNode_GenericDecl &&
- decl->GenericDecl.token.kind != Token_var)) {
+ if (decl->kind == AstNode_GenericDecl &&
+ decl->GenericDecl.token.kind != Token_var) {
syntax_error(token, "#thread_local may only be applied to variable declarations");
return make_bad_decl(f, token, ast_node_token(decl));
}
@@ -2962,11 +2926,8 @@ AstNode *parse_stmt(AstFile *f) {
syntax_error(token, "#thread_local is only allowed at the file scope");
return make_bad_decl(f, token, ast_node_token(decl));
}
- if (decl->kind == AstNode_VarDecl) {
- decl->VarDecl.tags |= VarDeclTag_thread_local;
- } else if (decl->kind == AstNode_GenericDecl) {
- decl->GenericDecl.tags |= VarDeclTag_thread_local;
- }
+ GB_ASSERT(decl->kind == AstNode_GenericDecl);
+ decl->GenericDecl.tags |= VarDeclTag_thread_local;
return decl;
} else if (str_eq(tag, str_lit("bounds_check"))) {
s = parse_stmt(f);
diff --git a/src/ssa.c b/src/ssa.c
index bc5737676..cd09eaf11 100644
--- a/src/ssa.c
+++ b/src/ssa.c
@@ -1919,8 +1919,8 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
return value;
}
- Type *src = base_type(get_enum_base_type(src_type));
- Type *dst = base_type(get_enum_base_type(t));
+ Type *src = base_type(src_type);
+ Type *dst = base_type(t);
if (value->kind == ssaValue_Constant) {
if (is_type_any(dst)) {
@@ -2172,7 +2172,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
}
bool ssa_is_type_aggregate(Type *t) {
- t = base_type(get_enum_base_type(t));
+ t = base_type(t);
switch (t->kind) {
case Type_Basic:
switch (t->Basic.kind) {
@@ -3088,19 +3088,6 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
x = ssa_emit_select(proc, cond, max, x);
return x;
} break;
-
- case BuiltinProc_enum_to_string: {
- ssa_emit_comment(proc, str_lit("enum_to_string"));
- ssaValue *x = ssa_build_expr(proc, ce->args.e[0]);
- Type *t = ssa_type(x);
- ssaValue *ti = ssa_type_info(proc, t);
-
-
- ssaValue **args = gb_alloc_array(proc->module->allocator, ssaValue *, 2);
- args[0] = ti;
- args[1] = ssa_emit_conv(proc, x, t_i64);
- return ssa_emit_global_call(proc, "__enum_to_string", args, 2);
- } break;
}
}
}
@@ -3849,8 +3836,7 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
case_ast_node(us, UsingStmt, node);
AstNode *decl = unparen_expr(us->node);
- if (decl->kind == AstNode_VarDecl &&
- decl->kind == AstNode_GenericDecl) {
+ if (decl->kind == AstNode_GenericDecl) {
ssa_build_stmt(proc, decl);
}
case_end;
@@ -3928,61 +3914,6 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
}
case_end;
- case_ast_node(vd, VarDecl, node);
- ssaModule *m = proc->module;
- gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
-
- if (vd->values.count == 0) { // declared and zero-initialized
- for_array(i, vd->names) {
- AstNode *name = vd->names.e[i];
- if (!ssa_is_blank_ident(name)) {
- ssa_add_local_for_identifier(proc, name, true);
- }
- }
- } else { // Tuple(s)
- Array(ssaAddr) lvals;
- ssaValueArray inits;
- array_init_reserve(&lvals, m->tmp_allocator, vd->names.count);
- array_init_reserve(&inits, m->tmp_allocator, vd->names.count);
-
- for_array(i, vd->names) {
- AstNode *name = vd->names.e[i];
- ssaAddr lval = ssa_make_addr(NULL, NULL);
- if (!ssa_is_blank_ident(name)) {
- ssa_add_local_for_identifier(proc, name, false);
- lval = ssa_build_addr(proc, name);
- }
-
- array_add(&lvals, lval);
- }
-
- for_array(i, vd->values) {
- ssaValue *init = ssa_build_expr(proc, vd->values.e[i]);
- Type *t = ssa_type(init);
- if (t->kind == Type_Tuple) {
- for (isize i = 0; i < t->Tuple.variable_count; i++) {
- Entity *e = t->Tuple.variables[i];
- ssaValue *v = ssa_emit_struct_ev(proc, init, i);
- array_add(&inits, v);
- }
- } else {
- array_add(&inits, init);
- }
- }
-
-
- for_array(i, inits) {
- if (lvals.e[i].addr == NULL) {
- continue;
- }
- ssaValue *v = ssa_emit_conv(proc, inits.e[i], ssa_addr_type(lvals.e[i]));
- ssa_addr_store(proc, lvals.e[i], v);
- }
- }
-
- gb_temp_arena_memory_end(tmp);
- case_end;
-
case_ast_node(pd, ProcDecl, node);
if (pd->body != NULL) {
CheckerInfo *info = proc->module->info;
@@ -5472,78 +5403,6 @@ void ssa_gen_tree(ssaGen *s) {
ssa_emit_store(proc, len, field_count);
ssa_emit_store(proc, cap, field_count);
} break;
- case TypeRecord_Enum: {
- tag = ssa_add_local_generated(proc, t_type_info_enum);
- Type *enum_base = t->Record.enum_base;
- if (enum_base == NULL) {
- enum_base = t_int;
- }
- ssaValue *base = ssa_emit_struct_ep(proc, tag, 0);
- ssa_emit_store(proc, base, ssa_get_type_info_ptr(proc, type_info_data, enum_base));
-
- if (t->Record.enum_value_count > 0) {
- Entity **fields = t->Record.enum_values;
- isize count = t->Record.enum_value_count;
- ssaValue *value_array = NULL;
- ssaValue *name_array = NULL;
-
- {
- 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_i64, count));
- value_array = ssa_make_value_global(a, e, NULL);
- value_array->Global.is_private = true;
- ssa_module_add_value(m, e, value_array);
- map_ssa_value_set(&m->members, hash_string(token.string), value_array);
- }
- {
- Token token = {Token_Ident};
- i32 id = cast(i32)entry_index;
- char name_base[] = "__$enum_names";
- 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_string, count));
- name_array = ssa_make_value_global(a, e, NULL);
- name_array->Global.is_private = true;
- ssa_module_add_value(m, e, name_array);
- map_ssa_value_set(&m->members, hash_string(token.string), name_array);
- }
-
- for (isize i = 0; i < count; i++) {
- ssaValue *value_gep = ssa_emit_array_epi(proc, value_array, i);
- ssaValue *name_gep = ssa_emit_array_epi(proc, name_array, i);
-
- ssa_emit_store(proc, value_gep, ssa_make_const_i64(a, fields[i]->Constant.value.value_integer));
- ssa_emit_store(proc, name_gep, ssa_make_const_string(a, fields[i]->token.string));
- }
-
- ssaValue *v_count = ssa_make_const_int(a, count);
-
-
- ssaValue *values = ssa_emit_struct_ep(proc, tag, 1);
- ssaValue *names = ssa_emit_struct_ep(proc, tag, 2);
- ssaValue *value_slice = ssa_add_local_generated(proc, type_deref(t_i64_slice_ptr));
- ssaValue *name_slice = ssa_add_local_generated(proc, type_deref(t_string_slice_ptr));
-
- ssa_emit_store(proc, ssa_emit_struct_ep(proc, value_slice, 0), ssa_array_elem(proc, value_array));
- ssa_emit_store(proc, ssa_emit_struct_ep(proc, value_slice, 1), v_count);
- ssa_emit_store(proc, ssa_emit_struct_ep(proc, value_slice, 2), v_count);
-
- ssa_emit_store(proc, ssa_emit_struct_ep(proc, name_slice, 0), ssa_array_elem(proc, name_array));
- ssa_emit_store(proc, ssa_emit_struct_ep(proc, name_slice, 1), v_count);
- ssa_emit_store(proc, ssa_emit_struct_ep(proc, name_slice, 2), v_count);
-
- ssa_emit_store(proc, values, ssa_emit_load(proc, value_slice));
- ssa_emit_store(proc, names, ssa_emit_load(proc, name_slice));
- }
- } break;
}
} break;
diff --git a/src/ssa_print.c b/src/ssa_print.c
index 31463bd17..c6f55893a 100644
--- a/src/ssa_print.c
+++ b/src/ssa_print.c
@@ -225,9 +225,6 @@ void ssa_print_type(ssaFileBuffer *f, ssaModule *m, Type *t) {
i64 align_of_union = type_align_of(s, heap_allocator(), t);
ssa_fprintf(f, "{[0 x <%lld x i8>], [%lld x i8]}", align_of_union, size_of_union);
} break;
- case TypeRecord_Enum:
- ssa_print_type(f, m, t->Record.enum_base);
- break;
}
} break;