From 437a776d78bda8ab9143ff3785af178c07820f72 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Tue, 31 May 2022 13:10:56 +0200 Subject: [PATCH] Folding constant enum access into constant int value --- ccodegen.cpp | 16 ++++++++++++---- enums.kl | 12 +++++++++++- new_ast.cpp | 10 ++++++++++ new_type.cpp | 7 ++++++- typechecking.cpp | 43 ++++++++++++++++++++++++++++++++----------- 5 files changed, 71 insertions(+), 17 deletions(-) diff --git a/ccodegen.cpp b/ccodegen.cpp index e3f1ad8..f1caa9f 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -103,10 +103,15 @@ gen_expr(Ast_Expr *ast){ CASE(BINARY, Binary){ if(node->op == TK_Dot){ Sym *sym = resolved_get(node->left); - gen_expr(node->left); - if(sym->type->kind == TYPE_POINTER) gen("->"); - else gen("."); - gen_expr(node->right); + if(sym->kind == SYM_CONST){ + gen("%lld", sym->int_val); + } + else{ + gen_expr(node->left); + if(sym->type->kind == TYPE_POINTER) gen("->"); + else gen("."); + gen_expr(node->right); + } } else{ gen("("); @@ -305,6 +310,9 @@ gen_ast(Ast *ast){ else if(sym->type == type_string){ 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){ if(sym->type_val->kind == TYPE_STRUCT){ Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast; diff --git a/enums.kl b/enums.kl index 8678ad0..79cf7c5 100644 --- a/enums.kl +++ b/enums.kl @@ -1,5 +1,15 @@ +Thing :: struct + len: int + +thing: Thing +access := thing.len + + Allocator_Kind :: enum Null Arena - Heap = Arena + Heap + + +kind := Allocator_Kind.Heap \ No newline at end of file diff --git a/new_ast.cpp b/new_ast.cpp index 6b08660..88b0fb9 100644 --- a/new_ast.cpp +++ b/new_ast.cpp @@ -593,4 +593,14 @@ query_struct(Ast_Struct *agg, Intern_String string){ } } 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; } \ No newline at end of file diff --git a/new_type.cpp b/new_type.cpp index 3cf1404..542593f 100644 --- a/new_type.cpp +++ b/new_type.cpp @@ -89,6 +89,12 @@ is_struct(Ast_Resolved_Type *type){ return result; } +function B32 +is_enum(Ast_Resolved_Type *type){ + B32 result = type->kind == TYPE_ENUM; + return result; +} + function B32 is_pointer(Ast_Resolved_Type *type){ B32 result = type->kind == TYPE_POINTER; @@ -183,7 +189,6 @@ type_incomplete(Ast *ast){ return result; } -//Array members function void type_complete(Ast_Resolved_Type *type){ if(type->kind == TYPE_COMPLETING){ diff --git a/typechecking.cpp b/typechecking.cpp index c0b678a..905b6f7 100644 --- a/typechecking.cpp +++ b/typechecking.cpp @@ -607,21 +607,24 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ // second part requires searching through a struct // resolve.x.y Operand resolved_ident = resolve_expr(node->left); - // @copy_paste Ast_Resolved_Type *type = resolved_ident.type; + if(type == type_type){ + type = resolved_ident.type_val; + } + // @copy_paste if(is_pointer(type)){ type = type->base; } type_complete(type); - if(!is_struct(type)){ - parsing_error(node->pos, "Trying to access inside a value that is not a struct"); + if(!(is_struct(type) || is_enum(type))){ + 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); // This happens only on binary nodes which further chain with dots and require lookups // x.resolve.y 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)); Ast_Atom *ident = (Ast_Atom *)binary->left; assert(is_binary(binary)); @@ -648,13 +651,31 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ // x.y.resolve // @copy_paste Ast_Atom *ident = (Ast_Atom *)binary; - Ast_Struct *agg = (Ast_Struct *)type->ast; - Ast *query = query_struct(agg, ident->intern_val); - if(query){ - Sym *sym = resolved_get(query); - result = operand(sym); - sym_new_resolved(SYM_VAR, {}, sym->type, {}, ident); - } else parsing_error(ident->pos, "No such member in struct"); + 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 *query = query_struct(agg, ident->intern_val); + if(query){ + Sym *sym = resolved_get(query); + assert(sym); + result = operand(sym); + sym_new_resolved(SYM_VAR, {}, sym->type, {}, ident); + } 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{