Cleanup
This commit is contained in:
3
main.cpp
3
main.cpp
@@ -48,6 +48,7 @@ For now I don't thing it should be overloadable.
|
|||||||
[ ] - For loop
|
[ ] - For loop
|
||||||
[ ] - Switch
|
[ ] - Switch
|
||||||
[ ] - More basic types
|
[ ] - More basic types
|
||||||
|
[ ] - Array of inferred size
|
||||||
[ ] - Lexer: Need to insert scope endings when hitting End of file
|
[ ] - Lexer: Need to insert scope endings when hitting End of file
|
||||||
[ ] - Add single line lambda expressions
|
[ ] - Add single line lambda expressions
|
||||||
|
|
||||||
@@ -88,9 +89,9 @@ int main(){
|
|||||||
String result = {};
|
String result = {};
|
||||||
result = compile_file("globals.kl"_s);
|
result = compile_file("globals.kl"_s);
|
||||||
result = compile_file("enums.kl"_s);
|
result = compile_file("enums.kl"_s);
|
||||||
result = compile_file("order2.kl"_s);
|
|
||||||
result = compile_file("lambdas.kl"_s);
|
result = compile_file("lambdas.kl"_s);
|
||||||
result = compile_file("order1.kl"_s);
|
result = compile_file("order1.kl"_s);
|
||||||
|
result = compile_file("order2.kl"_s);
|
||||||
printf("%s", result.str);
|
printf("%s", result.str);
|
||||||
|
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ arena := Arena(
|
|||||||
cap = 1000,
|
cap = 1000,
|
||||||
)
|
)
|
||||||
|
|
||||||
// lambda_value := (val: int) // What to do with this???
|
// lambda_value := (val: int) // @todo
|
||||||
// return
|
// return
|
||||||
|
|
||||||
Arena :: struct
|
Arena :: struct
|
||||||
@@ -21,13 +21,13 @@ Arena :: struct
|
|||||||
len : int
|
len : int
|
||||||
cap : int
|
cap : int
|
||||||
|
|
||||||
get_len :: (s: *Arena): int
|
get_len :: (s: *Arena): int // @todo
|
||||||
return s.next.len
|
return s.next.len
|
||||||
|
|
||||||
|
|
||||||
constant_inside :: 10000
|
constant_inside :: 10000
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
string16: Str16
|
string16: Str16
|
||||||
|
|
||||||
String16 :: struct
|
String16 :: struct
|
||||||
|
|||||||
119
typechecking.cpp
119
typechecking.cpp
@@ -37,10 +37,6 @@ struct Operand{
|
|||||||
INLINE_VALUE_FIELDS;
|
INLINE_VALUE_FIELDS;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum{
|
|
||||||
AST_CANT_BE_NULL = 0,
|
|
||||||
AST_CAN_BE_NULL = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Typecheck_Ctx{ // @todo
|
struct Typecheck_Ctx{ // @todo
|
||||||
Ast_Resolved_Type *required_type;
|
Ast_Resolved_Type *required_type;
|
||||||
@@ -48,6 +44,7 @@ struct Typecheck_Ctx{ // @todo
|
|||||||
B32 expr_can_be_null;
|
B32 expr_can_be_null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum{AST_CANT_BE_NULL = 0, AST_CAN_BE_NULL = 1};
|
||||||
function Ast_Resolved_Type *resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null = AST_CANT_BE_NULL);
|
function Ast_Resolved_Type *resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null = AST_CANT_BE_NULL);
|
||||||
function Sym *resolve_name(Token *pos, Intern_String name);
|
function Sym *resolve_name(Token *pos, Intern_String name);
|
||||||
function Operand resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0, Sym *const_sym = 0);
|
function Operand resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0, Sym *const_sym = 0);
|
||||||
@@ -93,20 +90,26 @@ scope_close(S64 local_sym_count){
|
|||||||
pctx->local_syms.len = local_sym_count;
|
pctx->local_syms.len = local_sym_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
sym_associate(Ast *ast, Sym *sym){
|
||||||
|
assert(ast);
|
||||||
|
assert(sym);
|
||||||
|
map_insert(&pctx->resolved, ast, sym);
|
||||||
|
}
|
||||||
|
|
||||||
function Sym *
|
function Sym *
|
||||||
sym_new(Sym_Kind kind, Intern_String name, Ast *ast){
|
sym_new(Sym_Kind kind, Intern_String name, Ast *ast, B32 associate = true){
|
||||||
Sym *result = exp_alloc_type(pctx->perm, Sym, AF_ZeroMemory);
|
Sym *result = exp_alloc_type(pctx->perm, Sym, AF_ZeroMemory);
|
||||||
result->name = name;
|
result->name = name;
|
||||||
result->kind = kind;
|
result->kind = kind;
|
||||||
result->ast = ast;
|
result->ast = ast;
|
||||||
assert(ast);
|
if(associate) sym_associate(ast, result);
|
||||||
map_insert(&pctx->resolved, ast, result);
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Sym *
|
function Sym *
|
||||||
sym_new_resolved(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Value value, Ast *ast){
|
sym_new_resolved(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Value value, Ast *ast, B32 associate = true){
|
||||||
Sym *result = sym_new(kind, name, ast);
|
Sym *result = sym_new(kind, name, ast, associate);
|
||||||
result->type = type;
|
result->type = type;
|
||||||
result->state = SYM_RESOLVED;
|
result->state = SYM_RESOLVED;
|
||||||
result->value = value;
|
result->value = value;
|
||||||
@@ -129,11 +132,24 @@ resolved_type_get(Ast_Expr *ast){
|
|||||||
return result->type_val;
|
return result->type_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Sym *
|
||||||
|
sym_type(Ast *ast, Ast_Resolved_Type *type, Intern_String name = {}, B32 associate = true){
|
||||||
|
Value value; value.type_val = type;
|
||||||
|
Sym *result = sym_new_resolved(SYM_CONST, name, type_type, value, ast, associate);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Sym *
|
||||||
|
sym_insert(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Value value, Ast *ast){
|
||||||
|
Sym *sym = sym_new_resolved(kind, name, type, value, ast);
|
||||||
|
sym_insert(sym);
|
||||||
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
sym_insert_builtin_type(String name, Ast_Resolved_Type *type){
|
sym_insert_builtin_type(String name, Ast_Resolved_Type *type){
|
||||||
Intern_String string = intern_string(&pctx->interns, name);
|
Intern_String string = intern_string(&pctx->interns, name);
|
||||||
Value val; val.type_val = type;
|
Sym *sym = sym_type(&empty_decl, type, string, false);
|
||||||
Sym *sym = sym_new_resolved(SYM_CONST, string, type_type, val, &empty_decl);
|
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,21 +163,21 @@ sym_insert_builtins(){
|
|||||||
{
|
{
|
||||||
Intern_String string = intern_string(&pctx->interns, "true"_s);
|
Intern_String string = intern_string(&pctx->interns, "true"_s);
|
||||||
Value val; val.int_val = 1;
|
Value val; val.int_val = 1;
|
||||||
Sym *sym = sym_new_resolved(SYM_CONST, string, type_bool, val, &empty_decl);
|
Sym *sym = sym_new_resolved(SYM_CONST, string, type_bool, val, &empty_decl, false);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Intern_String string = intern_string(&pctx->interns, "false"_s);
|
Intern_String string = intern_string(&pctx->interns, "false"_s);
|
||||||
Value val; val.int_val = 0;
|
Value val; val.int_val = 0;
|
||||||
Sym *sym = sym_new_resolved(SYM_CONST, string, type_bool, val, &empty_decl);
|
Sym *sym = sym_new_resolved(SYM_CONST, string, type_bool, val, &empty_decl, false);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
Intern_String string = intern_string(&pctx->interns, "null"_s);
|
Intern_String string = intern_string(&pctx->interns, "null"_s);
|
||||||
Value val; val.int_val = 0;
|
Value val; val.int_val = 0;
|
||||||
Sym *sym = sym_new_resolved(SYM_CONST, string, type_null, val, &empty_decl);
|
Sym *sym = sym_new_resolved(SYM_CONST, string, type_null, val, &empty_decl, false);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,13 +210,13 @@ resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
||||||
|
if(!ast) return;
|
||||||
|
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
CASE(RETURN, Return){ // @todo: need to check if all paths return a value
|
CASE(RETURN, Return){ // @todo: need to check if all paths return a value
|
||||||
Operand op = {};
|
Operand op = resolve_expr(node->expr);
|
||||||
if(node->expr) op = resolve_expr(node->expr);
|
|
||||||
if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is [%s]", type_names[op.type->kind]);
|
if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is [%s]", type_names[op.type->kind]);
|
||||||
if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value");
|
if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value");
|
||||||
|
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,12 +248,10 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
|||||||
|
|
||||||
CASE(IF, If){
|
CASE(IF, If){
|
||||||
For(node->ifs){
|
For(node->ifs){
|
||||||
if(it->init) resolve_stmt(it->init, ret);
|
resolve_stmt(it->init, ret);
|
||||||
if(it->expr) resolve_expr(it->expr);
|
resolve_expr(it->expr); // @todo: typechecking
|
||||||
S64 scope_index = scope_open();
|
S64 scope_index = scope_open();
|
||||||
For_It(it->block->stmts, jt){
|
For_It(it->block->stmts, jt) resolve_stmt(jt, ret);
|
||||||
resolve_stmt(jt, ret);
|
|
||||||
}
|
|
||||||
scope_close(scope_index);
|
scope_close(scope_index);
|
||||||
}
|
}
|
||||||
BREAK();
|
BREAK();
|
||||||
@@ -266,18 +280,14 @@ operand_type(Ast_Resolved_Type *type){
|
|||||||
function Operand
|
function Operand
|
||||||
require_const_int(Ast_Expr *expr, B32 ast_can_be_null){
|
require_const_int(Ast_Expr *expr, B32 ast_can_be_null){
|
||||||
Operand op = resolve_expr(expr);
|
Operand op = resolve_expr(expr);
|
||||||
if(expr == 0 && ast_can_be_null){
|
if(expr == 0 && ast_can_be_null) return op;
|
||||||
return op;
|
|
||||||
}
|
|
||||||
else if(expr == 0) parsing_error(expr->pos, "This field cannot be null");
|
else if(expr == 0) parsing_error(expr->pos, "This field cannot be null");
|
||||||
|
|
||||||
if(!op.is_const) parsing_error(expr->pos, "Expected a const value");
|
if(!op.is_const) parsing_error(expr->pos, "Expected a const value");
|
||||||
if(op.type != type_int) parsing_error(expr->pos, "Expected a constant integer");
|
if(op.type != type_int) parsing_error(expr->pos, "Expected a constant integer");
|
||||||
|
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define rewrite_into_const(ast,T,sym) _rewrite_into_const(ast,sizeof(T),sym)
|
|
||||||
function void
|
function void
|
||||||
_rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){
|
_rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){
|
||||||
auto ast = (Ast_Atom *)node;
|
auto ast = (Ast_Atom *)node;
|
||||||
@@ -293,6 +303,7 @@ _rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){
|
|||||||
ast->int_val = sym->int_val;
|
ast->int_val = sym->int_val;
|
||||||
} else invalid_codepath;
|
} else invalid_codepath;
|
||||||
}
|
}
|
||||||
|
#define rewrite_into_const(ast,T,sym) _rewrite_into_const(ast,sizeof(T),sym)
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||||
@@ -315,8 +326,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
|||||||
|
|
||||||
CASE(IDENT, Atom){
|
CASE(IDENT, Atom){
|
||||||
Sym *sym = resolve_name(node->pos, node->intern_val);
|
Sym *sym = resolve_name(node->pos, node->intern_val);
|
||||||
// @note: check if null and rewrite the expression to match the expected type
|
|
||||||
Operand result = {};
|
Operand result = {};
|
||||||
|
// @note: check if null and rewrite the expression to match the expected type
|
||||||
if(sym->type->kind == TYPE_NULL){
|
if(sym->type->kind == TYPE_NULL){
|
||||||
if(!expected_type) parsing_error(node->pos, "Couldn't infer type of null");
|
if(!expected_type) parsing_error(node->pos, "Couldn't infer type of null");
|
||||||
result.type = expected_type;
|
result.type = expected_type;
|
||||||
@@ -328,7 +339,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
|||||||
}
|
}
|
||||||
else if(sym->kind == SYM_VAR || sym->kind == SYM_CONST){
|
else if(sym->kind == SYM_VAR || sym->kind == SYM_CONST){
|
||||||
result = operand(sym);
|
result = operand(sym);
|
||||||
sym_new_resolved(sym->kind, sym->name, sym->type, sym->value, node);
|
sym_associate(node, sym);
|
||||||
}
|
}
|
||||||
else invalid_codepath;
|
else invalid_codepath;
|
||||||
|
|
||||||
@@ -339,12 +350,10 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
|||||||
CASE(ARRAY, Array){
|
CASE(ARRAY, Array){
|
||||||
Operand type = resolve_expr(node->base);
|
Operand type = resolve_expr(node->base);
|
||||||
if(type.type != type_type) parsing_error(node->pos, "Prefix array operator is only allowed on types");
|
if(type.type != type_type) parsing_error(node->pos, "Prefix array operator is only allowed on types");
|
||||||
Operand expr = resolve_expr(node->expr);
|
Operand expr = require_const_int(node->expr, AST_CANT_BE_NULL); // @todo:
|
||||||
if(!expr.is_const) parsing_error(node->pos, "Array operator requires a constant value");
|
|
||||||
if(expr.type != type_int) parsing_error(node->pos, "Array index requires type [Int]");
|
|
||||||
|
|
||||||
type.type_val = type_array(type.type_val, expr.int_val);
|
type.type_val = type_array(type.type_val, expr.int_val);
|
||||||
sym_new_resolved(SYM_CONST, {}, type_type, type.value, node);
|
sym_type(node, type.type_val);
|
||||||
return type;
|
return type;
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
@@ -364,9 +373,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
|||||||
op.int_val = value++;
|
op.int_val = value++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sym_insert(SYM_CONST, it->name, op.type, op.value, it);
|
||||||
Sym *arg_sym = sym_new_resolved(SYM_CONST, it->name, op.type, op.value, it);
|
|
||||||
sym_insert(arg_sym);
|
|
||||||
}
|
}
|
||||||
scope_close(scope_index);
|
scope_close(scope_index);
|
||||||
|
|
||||||
@@ -390,9 +397,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
|||||||
lambda_type = type_lambda(node, ret_type, args);
|
lambda_type = type_lambda(node, ret_type, args);
|
||||||
|
|
||||||
{
|
{
|
||||||
assert(lambda_type);
|
sym_type(node, lambda_type);
|
||||||
Value val; val.type_val = lambda_type;
|
|
||||||
sym_new_resolved(SYM_CONST, {}, type_type, val, node);
|
|
||||||
if(const_sym){
|
if(const_sym){
|
||||||
const_sym->type = lambda_type;
|
const_sym->type = lambda_type;
|
||||||
const_sym->state = SYM_RESOLVED;
|
const_sym->state = SYM_RESOLVED;
|
||||||
@@ -408,9 +413,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
|||||||
For(node->args){
|
For(node->args){
|
||||||
S64 i = node->args.get_index(&it);
|
S64 i = node->args.get_index(&it);
|
||||||
Ast_Resolved_Type *type = args[i];
|
Ast_Resolved_Type *type = args[i];
|
||||||
|
sym_insert(SYM_VAR, it->name, type, {}, it);
|
||||||
Sym *arg_sym = sym_new_resolved(SYM_VAR, it->name, type, {}, it);
|
|
||||||
sym_insert(arg_sym);
|
|
||||||
}
|
}
|
||||||
For(node->block->stmts){
|
For(node->block->stmts){
|
||||||
resolve_stmt(it, ret_type);
|
resolve_stmt(it, ret_type);
|
||||||
@@ -633,16 +636,13 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
|||||||
required_to_be_const = true;
|
required_to_be_const = true;
|
||||||
}
|
}
|
||||||
// @copy_paste
|
// @copy_paste
|
||||||
if(is_pointer(type)){
|
if(is_pointer(type)) type = type->base;
|
||||||
type = type->base;
|
|
||||||
}
|
|
||||||
type_complete(type);
|
type_complete(type);
|
||||||
if(!(is_struct(type) || is_enum(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");
|
||||||
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);
|
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 happens only on binary nodes which further chain with dots and require lookups
|
||||||
|
// This part cant happen on enums
|
||||||
// x.resolve.y
|
// x.resolve.y
|
||||||
Ast_Binary *binary = (Ast_Binary *)node->right;
|
Ast_Binary *binary = (Ast_Binary *)node->right;
|
||||||
for(;!is_ident(binary); binary=(Ast_Binary *)binary->right){
|
for(;!is_ident(binary); binary=(Ast_Binary *)binary->right){
|
||||||
@@ -652,24 +652,20 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
|||||||
|
|
||||||
Ast_Struct *agg = (Ast_Struct *)type->ast;
|
Ast_Struct *agg = (Ast_Struct *)type->ast;
|
||||||
Ast *query = query_struct(agg, ident->intern_val);
|
Ast *query = query_struct(agg, ident->intern_val);
|
||||||
// @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");
|
if(required_to_be_const && sym->kind != SYM_CONST) parsing_error(ident->pos, "Required to be constant");
|
||||||
type = sym->type;
|
type = sym->type;
|
||||||
|
// @copy_paste
|
||||||
if(type == type_type){
|
if(type == type_type){
|
||||||
required_to_be_const = true;
|
required_to_be_const = true;
|
||||||
type = sym->type_val;
|
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) || is_enum(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");
|
||||||
parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
|
sym_associate(ident, sym);
|
||||||
}
|
|
||||||
|
|
||||||
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");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -694,13 +690,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
|||||||
Sym *sym = resolved_get(query);
|
Sym *sym = resolved_get(query);
|
||||||
result = operand(sym);
|
result = operand(sym);
|
||||||
assert(sym);
|
assert(sym);
|
||||||
// @warning rewriting nodes with constant values
|
if(sym->kind == SYM_CONST) rewrite_into_const(node, Ast_Binary, sym);
|
||||||
if(sym->kind == SYM_CONST){
|
else sym_associate(ident, sym);
|
||||||
rewrite_into_const(node, Ast_Binary, sym);
|
|
||||||
}
|
|
||||||
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");
|
||||||
}
|
}
|
||||||
@@ -746,7 +737,7 @@ resolve_binding(Ast *ast, Sym *sym){
|
|||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
CASE(VAR, Var){
|
CASE(VAR, Var){
|
||||||
Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL);
|
Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL);
|
||||||
Operand expr = node->expr ? resolve_expr(node->expr, type) : Operand{};
|
Operand expr = resolve_expr(node->expr, type);
|
||||||
expr.type = resolve_type_pair(node->pos, type, expr.type);
|
expr.type = resolve_type_pair(node->pos, type, expr.type);
|
||||||
type_complete(expr.type);
|
type_complete(expr.type);
|
||||||
return expr;
|
return expr;
|
||||||
|
|||||||
Reference in New Issue
Block a user