Folding constant enum access into constant int value

This commit is contained in:
Krzosa Karol
2022-05-31 13:10:56 +02:00
parent 627e2bad88
commit 437a776d78
5 changed files with 71 additions and 17 deletions

View File

@@ -103,11 +103,16 @@ gen_expr(Ast_Expr *ast){
CASE(BINARY, Binary){ CASE(BINARY, Binary){
if(node->op == TK_Dot){ if(node->op == TK_Dot){
Sym *sym = resolved_get(node->left); Sym *sym = resolved_get(node->left);
if(sym->kind == SYM_CONST){
gen("%lld", sym->int_val);
}
else{
gen_expr(node->left); gen_expr(node->left);
if(sym->type->kind == TYPE_POINTER) gen("->"); if(sym->type->kind == TYPE_POINTER) gen("->");
else gen("."); else gen(".");
gen_expr(node->right); gen_expr(node->right);
} }
}
else{ else{
gen("("); gen("(");
gen_expr(node->left); gen_expr(node->left);
@@ -305,6 +310,9 @@ gen_ast(Ast *ast){
else if(sym->type == type_string){ else if(sym->type == type_string){
gen("String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str); gen("String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str);
} }
else if(sym->type->kind == TYPE_ENUM){
gen("enum { %s = %lld };", node->name.str, sym->int_val);
}
else if(sym->type == type_type){ else if(sym->type == type_type){
if(sym->type_val->kind == TYPE_STRUCT){ if(sym->type_val->kind == TYPE_STRUCT){
Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast; Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast;

View File

@@ -1,5 +1,15 @@
Thing :: struct
len: int
thing: Thing
access := thing.len
Allocator_Kind :: enum Allocator_Kind :: enum
Null Null
Arena Arena
Heap = Arena Heap
kind := Allocator_Kind.Heap

View File

@@ -594,3 +594,13 @@ query_struct(Ast_Struct *agg, Intern_String string){
} }
return 0; return 0;
} }
function Ast_Enum_Member *
query_enum(Ast_Enum *enu, Intern_String string){
For(enu->members){
if(it->name == string){
return it;
}
}
return 0;
}

View File

@@ -89,6 +89,12 @@ is_struct(Ast_Resolved_Type *type){
return result; return result;
} }
function B32
is_enum(Ast_Resolved_Type *type){
B32 result = type->kind == TYPE_ENUM;
return result;
}
function B32 function B32
is_pointer(Ast_Resolved_Type *type){ is_pointer(Ast_Resolved_Type *type){
B32 result = type->kind == TYPE_POINTER; B32 result = type->kind == TYPE_POINTER;
@@ -183,7 +189,6 @@ type_incomplete(Ast *ast){
return result; return result;
} }
//Array<Ast_Resolved_Member> members
function void function void
type_complete(Ast_Resolved_Type *type){ type_complete(Ast_Resolved_Type *type){
if(type->kind == TYPE_COMPLETING){ if(type->kind == TYPE_COMPLETING){

View File

@@ -607,21 +607,24 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
// second part requires searching through a struct // second part requires searching through a struct
// resolve.x.y // resolve.x.y
Operand resolved_ident = resolve_expr(node->left); Operand resolved_ident = resolve_expr(node->left);
// @copy_paste
Ast_Resolved_Type *type = resolved_ident.type; Ast_Resolved_Type *type = resolved_ident.type;
if(type == type_type){
type = resolved_ident.type_val;
}
// @copy_paste
if(is_pointer(type)){ if(is_pointer(type)){
type = type->base; type = type->base;
} }
type_complete(type); type_complete(type);
if(!is_struct(type)){ if(!(is_struct(type) || is_enum(type))){
parsing_error(node->pos, "Trying to access inside a value that is not a struct"); parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
} }
sym_new_resolved(SYM_VAR, {}, resolved_ident.type, {}, node->left); sym_new_resolved(SYM_VAR, {}, resolved_ident.type, {}, node->left);
// This happens only on binary nodes which further chain with dots and require lookups // This happens only on binary nodes which further chain with dots and require lookups
// x.resolve.y // x.resolve.y
Ast_Binary *binary = (Ast_Binary *)node->right; Ast_Binary *binary = (Ast_Binary *)node->right;
for(; !is_ident(binary); binary=(Ast_Binary *)binary->right){ for(;!is_ident(binary); binary=(Ast_Binary *)binary->right){
assert(is_ident(binary->left)); assert(is_ident(binary->left));
Ast_Atom *ident = (Ast_Atom *)binary->left; Ast_Atom *ident = (Ast_Atom *)binary->left;
assert(is_binary(binary)); assert(is_binary(binary));
@@ -648,13 +651,31 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
// x.y.resolve // x.y.resolve
// @copy_paste // @copy_paste
Ast_Atom *ident = (Ast_Atom *)binary; Ast_Atom *ident = (Ast_Atom *)binary;
if(is_enum(type)){
Ast_Enum *enu = (Ast_Enum *)type->ast;
Ast_Enum_Member *query = query_enum(enu, ident->intern_val);
if(query){
Sym *resolved = resolved_get(query);
assert(resolved);
// @warning: rewrite into a constant
{
sym_new_resolved(SYM_CONST, {}, resolved->type, resolved->value, node->left);
node->right = 0;
}
result = operand(resolved);
}
}
else if(is_struct(type)){
Ast_Struct *agg = (Ast_Struct *)type->ast; Ast_Struct *agg = (Ast_Struct *)type->ast;
Ast *query = query_struct(agg, ident->intern_val); Ast *query = query_struct(agg, ident->intern_val);
if(query){ if(query){
Sym *sym = resolved_get(query); Sym *sym = resolved_get(query);
assert(sym);
result = operand(sym); result = operand(sym);
sym_new_resolved(SYM_VAR, {}, sym->type, {}, ident); sym_new_resolved(SYM_VAR, {}, sym->type, {}, ident);
} else parsing_error(ident->pos, "No such member in struct"); } else parsing_error(ident->pos, "No such member in struct");
}
else parsing_error(ident->pos, "Trying to [.] access a value that is not [Enum] or [Struct]");
} }
else{ else{