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){ gen_expr(Ast_Expr *ast){
switch(ast->kind){ switch(ast->kind){
CASE(IDENT, Atom){ 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(); BREAK();
} }
@@ -305,13 +318,10 @@ gen_ast(Ast *ast){
} }
} }
else if(sym->type == type_int){ 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){ 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){
@@ -339,7 +349,7 @@ gen_ast(Ast *ast){
Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast; Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast;
assert(enu->kind == AST_ENUM); assert(enu->kind == AST_ENUM);
if(node->value->kind == AST_ENUM){ if(node->value->kind == AST_ENUM){
gen("enum %s{", node->name.str); gen("/*enum %s{", node->name.str);
// @todo add typespec // @todo add typespec
global_indent++; global_indent++;
For(enu->members){ For(enu->members){
@@ -350,7 +360,7 @@ gen_ast(Ast *ast){
gen(","); gen(",");
} }
global_indent--; global_indent--;
genln("};"); genln("};*/");
} }
else{ else{
// Type alias // Type alias

View File

@@ -2,9 +2,16 @@
Thing :: struct Thing :: struct
len: int len: int
Constant :: 10
Thing_Kind :: enum
None
Thing_Not
thing: Thing thing: Thing
access := thing.len access := thing.len
test := Thing.Thing_Kind.Thing_Not
test_const := Thing.Constant
Allocator_Kind :: enum Allocator_Kind :: enum
Null 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_bool = &type__bool;
global Ast_Resolved_Type *type_null = &type__null; 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 function B32
is_struct(Ast_Resolved_Type *type){ is_struct(Ast_Resolved_Type *type){
B32 result = type->kind == TYPE_STRUCT; 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){ CASE(BINARY, Binary){
Operand result = {}; Operand result = {};
if(node->op == TK_Dot){ if(node->op == TK_Dot){
B32 required_to_be_const = false;
// @note: resolve first chunk which involves querying global map // @note: resolve first chunk which involves querying global map
// second part requires searching through a struct // second part requires searching through a struct
// resolve.x.y // 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; Ast_Resolved_Type *type = resolved_ident.type;
if(type == type_type){ if(type == type_type){
type = resolved_ident.type_val; type = resolved_ident.type_val;
required_to_be_const = true;
} }
// @copy_paste // @copy_paste
if(is_pointer(type)){ if(is_pointer(type)){
@@ -634,16 +636,21 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
// @copy_paste // @copy_paste
if(query){ if(query){
Sym *sym = resolved_get(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; type = sym->type;
if(type == type_type){
required_to_be_const = true;
type = sym->type_val;
}
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, {}, sym->type, {}, ident);
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, "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); Ast_Enum_Member *query = query_enum(enu, ident->intern_val);
if(query){ if(query){
Sym *resolved = resolved_get(query); Sym *resolved = resolved_get(query);
assert(resolved); 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); sym_new_resolved(SYM_CONST, {}, resolved->type, resolved->value, node->left);
node->right = 0; 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); 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); 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, "No such member in struct");
} }
else parsing_error(ident->pos, "Trying to [.] access a value that is not [Enum] or [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{ else{
Operand left = resolve_expr(node->left); Operand left = resolve_expr(node->left);