From 1168965ba47bc6ad78bf0de0dc9df4223b3b492c Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Tue, 31 May 2022 13:27:21 +0200 Subject: [PATCH] Accessing constant values in structs --- ccodegen.cpp | 26 ++++++++++++++++++-------- enums.kl | 9 ++++++++- new_type.cpp | 12 ++++++++++++ typechecking.cpp | 32 ++++++++++++++++++++++++++------ 4 files changed, 64 insertions(+), 15 deletions(-) diff --git a/ccodegen.cpp b/ccodegen.cpp index f1caa9f..d6a333e 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -78,7 +78,20 @@ function void gen_expr(Ast_Expr *ast){ switch(ast->kind){ CASE(IDENT, Atom){ - gen("%s", node->intern_val.str); + Sym *sym = resolved_get(node); + if(sym){ + if(sym->kind == SYM_CONST){ + if(sym->type == type_int){ + gen("%lld", sym->int_val); + } + else if(sym->type == type_string){ + gen("LIT(\"%s\")", sym->intern_val.str); + } + else gen("%s", node->intern_val.str); + } + else gen("%s", node->intern_val.str); + } + else gen("%s", node->intern_val.str); BREAK(); } @@ -305,13 +318,10 @@ gen_ast(Ast *ast){ } } else if(sym->type == type_int){ - gen("enum { %s = %lld };", node->name.str, sym->int_val); + gen("// constant int %s = %lld;", node->name.str, sym->int_val); } 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); + gen("// String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str); } else if(sym->type == type_type){ if(sym->type_val->kind == TYPE_STRUCT){ @@ -339,7 +349,7 @@ gen_ast(Ast *ast){ Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast; assert(enu->kind == AST_ENUM); if(node->value->kind == AST_ENUM){ - gen("enum %s{", node->name.str); + gen("/*enum %s{", node->name.str); // @todo add typespec global_indent++; For(enu->members){ @@ -350,7 +360,7 @@ gen_ast(Ast *ast){ gen(","); } global_indent--; - genln("};"); + genln("};*/"); } else{ // Type alias diff --git a/enums.kl b/enums.kl index 79cf7c5..2be3531 100644 --- a/enums.kl +++ b/enums.kl @@ -2,9 +2,16 @@ Thing :: struct len: int + + Constant :: 10 + Thing_Kind :: enum + None + Thing_Not + thing: Thing access := thing.len - +test := Thing.Thing_Kind.Thing_Not +test_const := Thing.Constant Allocator_Kind :: enum Null diff --git a/new_type.cpp b/new_type.cpp index 542593f..f4b1dce 100644 --- a/new_type.cpp +++ b/new_type.cpp @@ -83,6 +83,18 @@ global Ast_Resolved_Type *type_string = &type__string; global Ast_Resolved_Type *type_bool = &type__bool; global Ast_Resolved_Type *type_null = &type__null; +function B32 +is_string(Ast_Resolved_Type *type){ + B32 result = type->kind == TYPE_STRING; + return result; +} + +function B32 +is_int(Ast_Resolved_Type *type){ + B32 result = type->kind == TYPE_INT; + return result; +} + function B32 is_struct(Ast_Resolved_Type *type){ B32 result = type->kind == TYPE_STRUCT; diff --git a/typechecking.cpp b/typechecking.cpp index 905b6f7..e5585f3 100644 --- a/typechecking.cpp +++ b/typechecking.cpp @@ -603,6 +603,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ CASE(BINARY, Binary){ Operand result = {}; if(node->op == TK_Dot){ + B32 required_to_be_const = false; // @note: resolve first chunk which involves querying global map // second part requires searching through a struct // resolve.x.y @@ -610,6 +611,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ Ast_Resolved_Type *type = resolved_ident.type; if(type == type_type){ type = resolved_ident.type_val; + required_to_be_const = true; } // @copy_paste if(is_pointer(type)){ @@ -634,16 +636,21 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ // @copy_paste if(query){ Sym *sym = resolved_get(query); + if(required_to_be_const && sym->kind != SYM_CONST) parsing_error(ident->pos, "Required to be constant"); type = sym->type; + if(type == type_type){ + required_to_be_const = true; + type = sym->type_val; + } 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, {}, sym->type, {}, ident); + sym_new_resolved(sym->kind, {}, sym->type, sym->value, ident); } else parsing_error(ident->pos, "No such member in struct"); } @@ -656,8 +663,9 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ Ast_Enum_Member *query = query_enum(enu, ident->intern_val); if(query){ Sym *resolved = resolved_get(query); + assert(resolved); - // @warning: rewrite into a constant + // @warning: rewrite entire node into a constant { sym_new_resolved(SYM_CONST, {}, resolved->type, resolved->value, node->left); node->right = 0; @@ -670,13 +678,25 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){ 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); + assert(sym); + // @note: warning rewriting nodes with constant values + if(sym->kind == SYM_CONST){ + sym_new_resolved(sym->kind, {}, sym->type, sym->value, node->left); + node->right = 0; + } + else{ + sym_new_resolved(sym->kind, {}, sym->type, sym->value, 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]"); + if(result.is_const == false && required_to_be_const){ + invalid_codepath; + } + } else{ Operand left = resolve_expr(node->left);