enum_to_string

This commit is contained in:
Ginger Bill
2016-09-19 21:33:52 +01:00
parent bbc9739f5c
commit 9561dc33ce
17 changed files with 660 additions and 214 deletions
+25 -7
View File
@@ -159,6 +159,8 @@ enum BuiltinProcId {
BuiltinProc_max,
BuiltinProc_abs,
BuiltinProc_enum_to_string,
BuiltinProc_Count,
};
@@ -200,6 +202,8 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
{STR_LIT("max"), 2, false, Expr_Expr},
{STR_LIT("abs"), 1, false, Expr_Expr},
{STR_LIT("enum_to_string"), 1, false, Expr_Expr},
};
struct CheckerContext {
@@ -358,6 +362,9 @@ void scope_lookup_parent_entity(Scope *scope, String name, Scope **scope_, Entit
// Do not return imported entities even #load ones
continue;
}
if (!is_entity_exported(e)) {
continue;
}
if (entity_) *entity_ = e;
if (scope_) *scope_ = shared;
return;
@@ -409,7 +416,7 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
void check_scope_usage(Checker *c, Scope *scope) {
// TODO(bill): Use this?
#if 0
#if 1
gb_for_array(i, scope->elements.entries) {
auto *entry = scope->elements.entries + i;
Entity *e = entry->value;
@@ -445,7 +452,7 @@ void add_global_entity(Entity *entity) {
return; // NOTE(bill): `untyped thing`
}
if (scope_insert_entity(universal_scope, entity)) {
GB_PANIC("Compiler error: double declaration");
compiler_error("double declaration");
}
}
@@ -492,10 +499,6 @@ void init_universal_scope(void) {
entity->Builtin.id = id;
add_global_entity(entity);
}
// Custom Runtime Types
{
}
}
@@ -1112,12 +1115,27 @@ void check_parsed_files(Checker *c) {
ExpressionInfo *info = &entry->value;
if (info != NULL && expr != NULL) {
if (is_type_typed(info->type)) {
GB_PANIC("%s (type %s) is typed!", expr_to_string(expr), info->type);
compiler_error("%s (type %s) is typed!", expr_to_string(expr), info->type);
}
add_type_and_value(&c->info, expr, info->mode, info->type, info->value);
}
}
#endif
gb_for_array(i, c->parser->files) {
AstFile *f = &c->parser->files[i];
Scope *scope = f->scope;
gb_for_array(j, scope->elements.entries) {
Entity *e = scope->elements.entries[j].value;
switch (e->kind) {
case Entity_ImportName: {
if (!e->ImportName.used) {
warning(e->token, "Unused import name: %.*s", LIT(e->ImportName.name));
}
} break;
}
}
}
}
+64 -10
View File
@@ -385,25 +385,34 @@ void check_fields(Checker *c, AstNode *node, AstNodeArray decls,
// TODO(bill): Cleanup struct field reordering
// TODO(bill): Inline sorting procedure?
gb_global BaseTypeSizes __checker_sizes = {};
gb_global gbAllocator __checker_allocator = {};
GB_COMPARE_PROC(cmp_struct_entity_size) {
// Rule: Biggest to smallest
// if same size, order by order in source
// Rule:
// Biggest to smallest alignment
// if same alignment: biggest to smallest size
// if same size: order by source order
Entity *x = *(Entity **)a;
Entity *y = *(Entity **)b;
GB_ASSERT(x != NULL);
GB_ASSERT(y != NULL);
GB_ASSERT(x->kind == Entity_Variable);
GB_ASSERT(y->kind == Entity_Variable);
i64 xa = type_align_of(__checker_sizes, __checker_allocator, x->type);
i64 ya = type_align_of(__checker_sizes, __checker_allocator, y->type);
i64 xs = type_size_of(__checker_sizes, __checker_allocator, x->type);
i64 ys = type_size_of(__checker_sizes, __checker_allocator, y->type);
if (xs == ys) {
i32 diff = x->Variable.field_index - y->Variable.field_index;
return diff < 0 ? -1 : diff > 0;
if (xa == ya) {
if (xs == ys) {
i32 diff = x->Variable.field_index - y->Variable.field_index;
return diff < 0 ? -1 : diff > 0;
}
return xs > ys ? -1 : xs < ys;
}
return xs > ys ? -1 : xs < ys;
return xa > ya ? -1 : xa < ya;
}
void check_struct_type(Checker *c, Type *struct_type, AstNode *node, CycleChecker *cycle_checker) {
@@ -746,6 +755,11 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
error(n->Ident,
"Undeclared name: %.*s", LIT(n->Ident.string));
}
o->type = t_invalid;
o->mode = Addressing_Invalid;
if (named_type != NULL) {
set_base_type(named_type, t_invalid);
}
return;
}
add_entity_use(&c->info, n, e);
@@ -761,7 +775,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
check_entity_decl(c, e, NULL, named_type, cycle_checker);
if (e->type == NULL) {
GB_PANIC("Compiler error: How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(n->Ident.string));
compiler_error("Compiler error: How did this happen? type: %s; identifier: %.*s\n", type_to_string(e->type), LIT(n->Ident.string));
return;
}
@@ -820,7 +834,7 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
return;
default:
GB_PANIC("Compiler error: Unknown EntityKind");
compiler_error("Compiler error: Unknown EntityKind");
break;
}
@@ -2785,6 +2799,44 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
operand->type = type;
} break;
case BuiltinProc_enum_to_string: {
Type *type = get_base_type(operand->type);
if (!is_type_enum(type)) {
gbString type_str = type_to_string(operand->type);
defer (gb_string_free(type_str));
error(ast_node_token(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(make_string(""));
if (operand->value.kind == ExactValue_Integer) {
i64 index = operand->value.value_integer;
for (isize i = 0; i < type->Record.other_field_count; i++) {
Entity *f = type->Record.other_fields[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;
@@ -2832,8 +2884,10 @@ void check_call_arguments(Checker *c, Operand *operand, Type *proc_type, AstNode
Entity **sig_params = proc_type->Proc.params->Tuple.variables;
gb_for_array(arg_index, ce->args) {
check_multi_expr(c, operand, ce->args[arg_index]);
if (operand->mode == Addressing_Invalid)
if (operand->mode == Addressing_Invalid) {
param_index++;
continue;
}
if (operand->type->kind != Type_Tuple) {
check_not_tuple(c, operand);
isize index = param_index;
@@ -3083,7 +3137,7 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
case Type_Record: {
if (!is_type_struct(t))
break;
if (gb_array_count(cl->elems) == 0) {
if (cl->elems == NULL || gb_array_count(cl->elems) == 0) {
break; // NOTE(bill): No need to init
}
{ // Checker values
+32 -12
View File
@@ -8,9 +8,12 @@ enum StmtFlag : u32 {
void check_stmt(Checker *c, AstNode *node, u32 flags);
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later);
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d);
void check_stmt_list(Checker *c, AstNodeArray stmts, u32 flags) {
// TODO(bill): Allow declaration (expect variable) in any order
// even within a procedure
b32 ft_ok = (flags & Stmt_FallthroughAllowed) != 0;
u32 f = flags & (~Stmt_FallthroughAllowed);
@@ -321,7 +324,7 @@ void check_init_constant(Checker *c, Entity *e, Operand *operand) {
}
if (!is_type_constant_type(operand->type)) {
// NOTE(bill): no need to free string as it's panicking
GB_PANIC("Compiler error: Type `%s` not constant!!!", type_to_string(operand->type));
compiler_error("Type `%s` not constant!!!", type_to_string(operand->type));
}
if (e->type == NULL) // NOTE(bill): type inference
@@ -482,7 +485,7 @@ b32 are_signatures_similar_enough(Type *a_, Type *b_) {
return true;
}
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
void check_proc_decl(Checker *c, Entity *e, DeclInfo *d) {
GB_ASSERT(e->type == NULL);
Type *proc_type = make_type_proc(c->allocator, e->scope, NULL, 0, NULL, 0, false);
@@ -494,6 +497,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
b32 is_foreign = (pd->tags & ProcTag_foreign) != 0;
b32 is_link_name = (pd->tags & ProcTag_link_name) != 0;
b32 is_inline = (pd->tags & ProcTag_inline) != 0;
b32 is_no_inline = (pd->tags & ProcTag_no_inline) != 0;
@@ -527,11 +531,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
d->scope = c->context.scope;
GB_ASSERT(pd->body->kind == AstNode_BlockStmt);
if (check_body_later) {
check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pd->body);
} else {
check_proc_body(c, e->token, d, proc_type, pd->body);
}
check_procedure_later(c, c->curr_ast_file, e->token, d, proc_type, pd->body);
}
if (is_foreign) {
@@ -557,6 +557,23 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
} else {
map_set(fp, key, e);
}
} else if (is_link_name) {
auto *fp = &c->info.foreign_procs;
auto *proc_decl = &d->proc_decl->ProcDecl;
String name = proc_decl->link_name;
HashKey key = hash_string(name);
auto *found = map_get(fp, key);
if (found) {
Entity *f = *found;
TokenPos pos = f->token.pos;
error(ast_node_token(d->proc_decl),
"Non unique #link_name for procedure `%.*s`\n"
"\tother at %.*s(%td:%td)",
LIT(name), LIT(pos.file), pos.line, pos.column);
} else {
map_set(fp, key, e);
}
}
}
@@ -610,7 +627,9 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
if (found) {
d = *found;
} else {
GB_PANIC("`%.*s` should been declared!", LIT(e->token.string));
e->type = t_invalid;
return;
// GB_PANIC("`%.*s` should been declared!", LIT(e->token.string));
}
}
@@ -620,7 +639,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
// defer (c->context.scope = prev);
if (e->kind == Entity_Procedure) {
check_proc_decl(c, e, d, true);
check_proc_decl(c, e, d);
return;
}
@@ -644,7 +663,7 @@ void check_entity_decl(Checker *c, Entity *e, DeclInfo *d, Type *named_type, Cyc
} break;
case Entity_Procedure: {
check_proc_decl(c, e, d, true);
check_proc_decl(c, e, d);
} break;
@@ -1261,6 +1280,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
// NOTE(bill): Dummy type
Type *tag_ptr_type = make_type_pointer(c->allocator, tag_type);
Entity *tag_var = make_entity_variable(c->allocator, c->context.scope, ms->var->Ident, tag_ptr_type);
tag_var->Variable.used = true;
add_entity(c, c->context.scope, ms->var, tag_var);
add_entity_use(&c->info, ms->var, tag_var);
}
@@ -1481,7 +1501,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
DeclInfo *decl = make_declaration_info(c->allocator, e->scope);
decl->proc_decl = node;
check_proc_decl(c, e, decl, false);
check_proc_decl(c, e, decl);
case_end;
case_ast_node(td, TypeDecl, node);
+8 -10
View File
@@ -7,12 +7,10 @@ enum BasicKind {
Basic_i16,
Basic_i32,
Basic_i64,
Basic_i128,
Basic_u8,
Basic_u16,
Basic_u32,
Basic_u64,
Basic_u128,
Basic_f32,
Basic_f64,
Basic_int,
@@ -296,12 +294,10 @@ gb_global Type basic_types[] = {
{0, Type_Basic, {Basic_i16, BasicFlag_Integer, STR_LIT("i16")}},
{0, Type_Basic, {Basic_i32, BasicFlag_Integer, STR_LIT("i32")}},
{0, Type_Basic, {Basic_i64, BasicFlag_Integer, STR_LIT("i64")}},
{0, Type_Basic, {Basic_i128, BasicFlag_Integer, STR_LIT("i128")}},
{0, Type_Basic, {Basic_u8, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u8")}},
{0, Type_Basic, {Basic_u16, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u16")}},
{0, Type_Basic, {Basic_u32, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u32")}},
{0, Type_Basic, {Basic_u64, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u64")}},
{0, Type_Basic, {Basic_u128, BasicFlag_Integer | BasicFlag_Unsigned, STR_LIT("u128")}},
{0, Type_Basic, {Basic_f32, BasicFlag_Float, STR_LIT("f32")}},
{0, Type_Basic, {Basic_f64, BasicFlag_Float, STR_LIT("f64")}},
{0, Type_Basic, {Basic_int, BasicFlag_Integer, STR_LIT("int")}},
@@ -328,12 +324,10 @@ gb_global Type *t_i8 = &basic_types[Basic_i8];
gb_global Type *t_i16 = &basic_types[Basic_i16];
gb_global Type *t_i32 = &basic_types[Basic_i32];
gb_global Type *t_i64 = &basic_types[Basic_i64];
gb_global Type *t_i128 = &basic_types[Basic_i128];
gb_global Type *t_u8 = &basic_types[Basic_u8];
gb_global Type *t_u16 = &basic_types[Basic_u16];
gb_global Type *t_u32 = &basic_types[Basic_u32];
gb_global Type *t_u64 = &basic_types[Basic_u64];
gb_global Type *t_u128 = &basic_types[Basic_u128];
gb_global Type *t_f32 = &basic_types[Basic_f32];
gb_global Type *t_f64 = &basic_types[Basic_f64];
gb_global Type *t_int = &basic_types[Basic_int];
@@ -602,7 +596,12 @@ b32 are_types_identical(Type *x, Type *y) {
break;
case TypeRecord_Enum:
return are_types_identical(x->Record.enum_base, y->Record.enum_base);
if (are_types_identical(x->Record.enum_base, y->Record.enum_base)) {
if (x->Record.field_count == y->Record.field_count) {
return x->Record.fields == y->Record.fields;
}
}
return false;
}
}
}
@@ -679,12 +678,10 @@ gb_global i64 basic_type_sizes[] = {
2, // Basic_i16
4, // Basic_i32
8, // Basic_i64
16, // Basic_i128
1, // Basic_u8
2, // Basic_u16
4, // Basic_u32
8, // Basic_u64
16, // Basic_u128
4, // Basic_f32
8, // Basic_f64
};
@@ -954,7 +951,8 @@ i64 type_align_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
} break;
}
return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.max_align);
// return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.max_align);
return gb_clamp(next_pow2(type_size_of(s, allocator, t)), 1, s.word_size);
}
i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields, isize field_count, b32 is_packed) {