Struct field access. Damn, I coded for like 30 minutes and then it just worked on the first try

This commit is contained in:
Krzosa Karol
2022-05-30 18:27:06 +02:00
parent 0e0b95ab52
commit 980a3b68b9
6 changed files with 186 additions and 41 deletions

View File

@@ -100,11 +100,20 @@ gen_expr(Ast_Expr *ast){
} }
CASE(BINARY, Binary){ 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);
}
else{
gen("("); gen("(");
gen_expr(node->left); gen_expr(node->left);
gen("%s", token_kind_string(node->op).str); gen("%s", token_kind_string(node->op).str);
gen_expr(node->right); gen_expr(node->right);
gen(")"); gen(")");
}
BREAK(); BREAK();
} }

View File

@@ -217,18 +217,20 @@ struct Ast_Named:Ast{
Intern_String name; Intern_String name;
}; };
struct Ast_Resolved_Type;
struct Ast_Struct: Ast_Expr{
// Required to be Ast_Struct or Ast_Var or Ast_Const
Array<Ast_Named *> members;
Ast_Resolved_Type *type;
};
struct Ast_Var: Ast_Named{ struct Ast_Var: Ast_Named{
Ast_Expr *typespec; Ast_Expr *typespec;
Ast_Expr *expr; Ast_Expr *expr;
}; };
struct Ast_Const;
struct Ast_Resolved_Type;
struct Ast_Struct: Ast_Expr{
// Required to be Ast_Struct or Ast_Var or Ast_Const
Array<Ast_Var *> members;
Array<Ast_Const *> const_members;
Ast_Resolved_Type *type;
};
struct Ast_Const: Ast_Named{ struct Ast_Const: Ast_Named{
union{ union{
Ast *ast; Ast *ast;
@@ -281,7 +283,7 @@ ast_expr_binary(Ast_Expr *left, Ast_Expr *right, Token *op){
result->left = left; result->left = left;
result->right = right; result->right = right;
result->left->parent = result; result->left->parent = result;
result->right->parent = result; if(result->right) result->right->parent = result;
return result; return result;
} }
@@ -426,12 +428,18 @@ ast_array(Token *pos, Ast_Expr *expr){
} }
function Ast_Struct * function Ast_Struct *
ast_struct(Token *pos, Array<Ast_Named *> members){ ast_struct(Token *pos, Array<Ast_Var *> members, Array<Ast_Const *> const_members){
AST_NEW(Struct, STRUCT, pos, AST_AGGREGATE); AST_NEW(Struct, STRUCT, pos, AST_AGGREGATE);
result->members = members.tight_copy(pctx->perm); result->members = members.tight_copy(pctx->perm);
result->const_members = const_members.tight_copy(pctx->perm);
For(result->members) { For(result->members) {
assert(is_flag_set(it->flags, AST_BINDING)); assert(is_flag_set(it->flags, AST_BINDING));
assert(it->kind == AST_VAR || it->kind == AST_CONST); assert(it->kind == AST_VAR);
it->parent = result;
}
For(result->const_members) {
assert(is_flag_set(it->flags, AST_BINDING));
assert(it->kind == AST_CONST);
it->parent = result; it->parent = result;
} }
return result; return result;
@@ -525,3 +533,40 @@ ast_is_struct(Ast *ast){
} }
return false; return false;
} }
function B32
is_ident(Ast *ast){
B32 result = ast->kind == AST_IDENT;
return result;
}
function B32
is_binary(Ast *ast){
B32 result = ast->kind == AST_BINARY;
return result;
}
function B32
is_atom(Ast *ast){
B32 result = is_flag_set(ast->flags, AST_ATOM);
return result;
}
function Ast *
query_struct(Ast_Struct *agg, Intern_String string){
For(agg->members){
if(it->name == string){
return it;
}
}
For(agg->const_members){
if(it->name == string){
return it;
}
}
return 0;
}

View File

@@ -353,7 +353,7 @@ left_denotation(Token *op, Ast_Expr *left){
function S64 function S64
postfix_binding_power(Token_Kind kind){ postfix_binding_power(Token_Kind kind){
switch(kind){ switch(kind){
case TK_Decrement: case TK_Increment: case TK_OpenBracket: case TK_OpenParen: return 1; case TK_Dot: case TK_Decrement: case TK_Increment: case TK_OpenBracket: case TK_OpenParen: return 1;
default: return 0; default: return 0;
} }
} }
@@ -369,6 +369,12 @@ parse_expr(S64 rbp){
if(postfix_binding_power(token->kind) > rbp){ if(postfix_binding_power(token->kind) > rbp){
token_next(); token_next();
switch(token->kind){ switch(token->kind){
case TK_Dot: {
// @note: making sure that we always get a configuration where
// Identifier is in left node
Ast_Expr *right = parse_expr();
left = ast_expr_binary(left, right, token);
}break;
case TK_OpenBracket:{ case TK_OpenBracket:{
Ast_Expr *index = parse_expr(); Ast_Expr *index = parse_expr();
left = ast_expr_index(token, left, index); left = ast_expr_index(token, left, index);
@@ -406,18 +412,25 @@ parse_assign_expr(){
function Ast_Struct * function Ast_Struct *
parse_struct(Token *pos){ parse_struct(Token *pos){
Scratch scratch; Scratch scratch;
Array<Ast_Named *> members = {scratch}; Array<Ast_Var *> members = {scratch};
Array<Ast_Const *> members_const = {scratch};
token_match(OPEN_SCOPE); token_match(OPEN_SCOPE);
do{ do{
Token *token = token_get(); Token *token = token_get();
Ast_Named *named = parse_named(false); Ast_Named *named = parse_named(false);
if(!named) parsing_error(token, "Failed to parse struct member"); if(!named) parsing_error(token, "Failed to parse struct member");
members.add(named); if(named->kind == AST_CONST){
members_const.add((Ast_Const *)named);
} else {
assert(named->kind == AST_VAR);
members.add((Ast_Var *)named);
}
}while(token_match(SAME_SCOPE)); }while(token_match(SAME_SCOPE));
token_expect(CLOSE_SCOPE); token_expect(CLOSE_SCOPE);
Ast_Struct *result = ast_struct(pos, members); Ast_Struct *result = ast_struct(pos, members, members_const);
return result; return result;
} }

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_struct(Ast_Resolved_Type *type){
B32 result = type->kind == TYPE_STRUCT;
return result;
}
function B32
is_pointer(Ast_Resolved_Type *type){
B32 result = type->kind == TYPE_POINTER;
return result;
}
function Ast_Resolved_Type * function Ast_Resolved_Type *
type_new(Allocator *allocator, Ast_Resolved_Type_Kind kind, SizeU size, SizeU align){ type_new(Allocator *allocator, Ast_Resolved_Type_Kind kind, SizeU size, SizeU align){
Ast_Resolved_Type *result = exp_alloc_type(allocator, Ast_Resolved_Type, AF_ZeroMemory); Ast_Resolved_Type *result = exp_alloc_type(allocator, Ast_Resolved_Type, AF_ZeroMemory);

View File

@@ -4,6 +4,14 @@ arena_pointer: *Arena = null
thing: Arena thing: Arena
no_type := thing no_type := thing
arena := Arena(
next = null,
data = null,
len = 1000,
cap = 1000,
// constant_inside = 10,
)
Arena :: struct Arena :: struct
// arena: Arena // arena: Arena
next: *Arena next: *Arena
@@ -11,8 +19,12 @@ Arena :: struct
len : int len : int
cap : int cap : int
constant_inside :: 10000
constant_outside :: 10000
get_len :: (s: *Arena): int get_len :: (s: *Arena): int
return s.len return s.next.len
string16: Str16 string16: Str16
@@ -24,10 +36,4 @@ with_type: Arena = thing
pointer := &with_type pointer := &with_type
deref := *pointer deref := *pointer
arena := Arena(
next = null,
data = null,
len = 1000,
cap = 1000,
)

View File

@@ -363,6 +363,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
CASE(CALL, Call){ CASE(CALL, Call){
Operand name = resolve_expr(node->name); Operand name = resolve_expr(node->name);
Ast_Resolved_Type *type = name.type; Ast_Resolved_Type *type = name.type;
type_complete(type);
if(name.type == type_type){ if(name.type == type_type){
type = name.type_val; type = name.type_val;
if(expected_type && expected_type != type) parsing_error(node->pos, "Variable type different from explicit compound type"); if(expected_type && expected_type != type) parsing_error(node->pos, "Variable type different from explicit compound type");
@@ -530,6 +531,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
else if(value.type->kind == TYPE_TYPE){ else if(value.type->kind == TYPE_TYPE){
Operand result = {type_type, true}; Operand result = {type_type, true};
result.type_val = type_pointer(value.type_val); result.type_val = type_pointer(value.type_val);
sym_new_resolved(SYM_CONST, {}, type_type, result.value, node);
return result; return result;
} }
else{ parsing_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; } else{ parsing_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; }
@@ -545,9 +547,65 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
} }
CASE(BINARY, Binary){ CASE(BINARY, Binary){
Operand result = {};
if(node->op == TK_Dot){
// @note: resolve first chunk which involves querying global map
// 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(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");
}
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){
assert(is_ident(binary->left));
Ast_Atom *ident = (Ast_Atom *)binary->left;
assert(is_binary(binary));
Ast_Struct *agg = (Ast_Struct *)type->ast;
Ast *query = query_struct(agg, ident->intern_val);
// @copy_paste
if(query){
Sym *sym = resolved_get(query);
type = sym->type;
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");
}
sym_new_resolved(SYM_VAR, {}, sym->type, {}, ident);
} else parsing_error(ident->pos, "No such member in struct");
}
// Here we can resolve the last part, this doesnt need to be a struct
// 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.type = sym->type;
sym_new_resolved(SYM_VAR, {}, sym->type, {}, ident);
} else parsing_error(ident->pos, "No such member in struct");
}
else{
Operand left = resolve_expr(node->left); Operand left = resolve_expr(node->left);
Operand right = resolve_expr(node->right); Operand right = resolve_expr(node->right);
Operand result = {};
result.type = resolve_type_pair(node->pos, left.type, right.type); result.type = resolve_type_pair(node->pos, left.type, right.type);
if(left.is_const && right.is_const){ if(left.is_const && right.is_const){
result.is_const = true; result.is_const = true;
@@ -562,6 +620,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
} }
else parsing_error(node->pos, "Arithmetic on type [%s] is not supported", type_names[result.type->kind]); else parsing_error(node->pos, "Arithmetic on type [%s] is not supported", type_names[result.type->kind]);
} }
}
return result; return result;
BREAK(); BREAK();