Struct field access. Damn, I coded for like 30 minutes and then it just worked on the first try
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
65
new_ast.cpp
65
new_ast.cpp
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
12
new_type.cpp
12
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_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);
|
||||||
|
|||||||
20
order2.kl
20
order2.kl
@@ -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,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user