Accessing constant values in structs

This commit is contained in:
Krzosa Karol
2022-05-31 13:27:21 +02:00
parent 437a776d78
commit 1168965ba4
4 changed files with 64 additions and 15 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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);