More cleanup
This commit is contained in:
@@ -145,7 +145,7 @@ parse_init_stmt(Ast_Expr *expr){
|
||||
result->flags = set_flag(result->flags, AST_STMT);
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
return expr;
|
||||
}
|
||||
|
||||
function Ast_Call *
|
||||
@@ -215,7 +215,6 @@ parse_block(){
|
||||
else if(token_match_keyword(keyword_for)){
|
||||
Ast_Expr *expr_first = parse_expr();
|
||||
Ast_Expr *init = parse_init_stmt(expr_first);
|
||||
Ast_Expr *actual_init = init ? init : expr_first;
|
||||
|
||||
Ast_Expr *cond = 0;
|
||||
Ast_Expr *iter = 0;
|
||||
@@ -223,18 +222,19 @@ parse_block(){
|
||||
cond = parse_expr();
|
||||
if(token_match(TK_Comma)){
|
||||
iter = parse_expr();
|
||||
iter = parse_init_stmt(iter);
|
||||
}
|
||||
}
|
||||
|
||||
Ast_Block *for_block = parse_block();
|
||||
stmts.add(ast_for(token, actual_init, cond, iter, for_block));
|
||||
stmts.add(ast_for(token, init, cond, iter, for_block));
|
||||
}
|
||||
|
||||
else if(token_match_keyword(keyword_if)){
|
||||
Array<Ast_If_Node *> if_nodes = {scratch};
|
||||
Ast_Expr *expr = parse_expr();
|
||||
Ast_Expr *init_val = parse_init_stmt(expr);
|
||||
if(init_val){
|
||||
if(init_val != expr){
|
||||
if(token_match(TK_Comma)) expr = parse_expr();
|
||||
else expr = 0;
|
||||
}
|
||||
|
||||
190
typecheck.cpp
190
typecheck.cpp
@@ -85,10 +85,10 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
||||
|
||||
CASE(FOR, For){
|
||||
// @todo: I think we need to bring back the Ast_Init, it was not an expression
|
||||
resolve_stmt(node->init, ret);
|
||||
resolve_expr(node->init, ret);
|
||||
Operand cond = resolve_expr(node->cond); // @todo: typechecking
|
||||
Operand iter = resolve_expr(node->iter);
|
||||
unused(cond); unused(iter);
|
||||
resolve_expr(node->iter, ret);
|
||||
unused(cond);
|
||||
resolve_stmt_block(node->block, ret);
|
||||
BREAK();
|
||||
}
|
||||
@@ -430,100 +430,110 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
||||
|
||||
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
|
||||
Operand resolved_ident = resolve_expr(node->left);
|
||||
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)) type = type->base;
|
||||
type_complete(type);
|
||||
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, {}, resolved_ident.type, {}, node->left);
|
||||
|
||||
// This happens only on binary nodes which further chain with dots and require lookups
|
||||
// This part cant happen on enums
|
||||
// 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);
|
||||
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;
|
||||
switch(node->op){
|
||||
case TK_ColonAssign:{
|
||||
assert(is_flag_set(node->flags, AST_STMT));
|
||||
// Operand left = resolve_expr(node->left); // needs to be lvalue
|
||||
Operand right = resolve_expr(node->right);
|
||||
assert(node->left->kind == AST_IDENT);
|
||||
Ast_Atom *atom = (Ast_Atom *)node->left; // @todo use left operand
|
||||
Sym *sym = sym_new_resolved(SYM_VAR, atom->intern_val, right.type, right.value, node);
|
||||
sym_insert(sym);
|
||||
}break;
|
||||
case 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
|
||||
Operand resolved_ident = resolve_expr(node->left);
|
||||
Ast_Resolved_Type *type = resolved_ident.type;
|
||||
if(type == type_type){
|
||||
type = resolved_ident.type_val;
|
||||
required_to_be_const = true;
|
||||
}
|
||||
// @copy_paste
|
||||
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) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
|
||||
sym_associate(ident, sym);
|
||||
if(is_pointer(type)) type = type->base;
|
||||
type_complete(type);
|
||||
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, {}, resolved_ident.type, {}, node->left);
|
||||
|
||||
} else parsing_error(ident->pos, "No such member in struct");
|
||||
}
|
||||
// This happens only on binary nodes which further chain with dots and require lookups
|
||||
// This part cant happen on enums
|
||||
// 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));
|
||||
|
||||
// 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;
|
||||
if(is_enum(type)){
|
||||
Ast_Enum *enu = (Ast_Enum *)type->ast;
|
||||
Ast_Enum_Member *query = query_enum(enu, ident->intern_val);
|
||||
if(query){
|
||||
Sym *resolved = resolved_get(query);
|
||||
assert(resolved);
|
||||
rewrite_into_const(node, Ast_Binary, resolved);
|
||||
result = operand(resolved);
|
||||
Ast_Struct *agg = (Ast_Struct *)type->ast;
|
||||
Ast *query = query_struct(agg, ident->intern_val);
|
||||
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;
|
||||
// @copy_paste
|
||||
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) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
|
||||
sym_associate(ident, sym);
|
||||
|
||||
} else parsing_error(ident->pos, "No such member in struct");
|
||||
}
|
||||
}
|
||||
else if(is_struct(type)){
|
||||
Ast_Struct *agg = (Ast_Struct *)type->ast;
|
||||
Ast *query = query_struct(agg, ident->intern_val);
|
||||
if(query){
|
||||
Sym *sym = resolved_get(query);
|
||||
result = operand(sym);
|
||||
assert(sym);
|
||||
if(sym->kind == SYM_CONST) rewrite_into_const(node, Ast_Binary, sym);
|
||||
else sym_associate(ident, sym);
|
||||
|
||||
} 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);
|
||||
Operand right = resolve_expr(node->right);
|
||||
result.type = resolve_type_pair(node->pos, left.type, right.type);
|
||||
if(left.is_const && right.is_const){
|
||||
result.is_const = true;
|
||||
if(result.type == type_int){
|
||||
switch(node->op){
|
||||
case TK_Add: result.int_val = left.int_val + right.int_val; break;
|
||||
case TK_Sub: result.int_val = left.int_val - right.int_val; break;
|
||||
case TK_Mul: result.int_val = left.int_val * right.int_val; break;
|
||||
case TK_Div: result.int_val = left.int_val / right.int_val; break;
|
||||
invalid_default_case;
|
||||
// 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;
|
||||
if(is_enum(type)){
|
||||
Ast_Enum *enu = (Ast_Enum *)type->ast;
|
||||
Ast_Enum_Member *query = query_enum(enu, ident->intern_val);
|
||||
if(query){
|
||||
Sym *resolved = resolved_get(query);
|
||||
assert(resolved);
|
||||
rewrite_into_const(node, Ast_Binary, resolved);
|
||||
result = operand(resolved);
|
||||
}
|
||||
}
|
||||
else parsing_error(node->pos, "Arithmetic on type [%s] is not supported", type_names[result.type->kind]);
|
||||
else if(is_struct(type)){
|
||||
Ast_Struct *agg = (Ast_Struct *)type->ast;
|
||||
Ast *query = query_struct(agg, ident->intern_val);
|
||||
if(query){
|
||||
Sym *sym = resolved_get(query);
|
||||
result = operand(sym);
|
||||
assert(sym);
|
||||
if(sym->kind == SYM_CONST) rewrite_into_const(node, Ast_Binary, sym);
|
||||
else sym_associate(ident, sym);
|
||||
|
||||
} 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;
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
Operand left = resolve_expr(node->left);
|
||||
Operand right = resolve_expr(node->right);
|
||||
result.type = resolve_type_pair(node->pos, left.type, right.type);
|
||||
if(left.is_const && right.is_const){
|
||||
result.is_const = true;
|
||||
if(result.type == type_int){
|
||||
switch(node->op){
|
||||
case TK_Add: result.int_val = left.int_val + right.int_val; break;
|
||||
case TK_Sub: result.int_val = left.int_val - right.int_val; break;
|
||||
case TK_Mul: result.int_val = left.int_val * right.int_val; break;
|
||||
case TK_Div: result.int_val = left.int_val / right.int_val; break;
|
||||
invalid_default_case;
|
||||
}
|
||||
}
|
||||
else parsing_error(node->pos, "Arithmetic on type [%s] is not supported", type_names[result.type->kind]);
|
||||
}break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user