More work on packages
This commit is contained in:
2
ast.cpp
2
ast.cpp
@@ -111,6 +111,8 @@ struct Ast_Binary: Ast_Expr{
|
|||||||
Token_Kind op;
|
Token_Kind op;
|
||||||
Ast_Expr *left;
|
Ast_Expr *left;
|
||||||
Ast_Expr *right;
|
Ast_Expr *right;
|
||||||
|
|
||||||
|
Ast_Resolved_Type *type;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Problem: We are parsing out of order, in the middle of parsing a function
|
// Problem: We are parsing out of order, in the middle of parsing a function
|
||||||
|
|||||||
63
ccodegen.cpp
63
ccodegen.cpp
@@ -4,6 +4,8 @@
|
|||||||
global S32 global_indent;
|
global S32 global_indent;
|
||||||
global S32 is_inside_struct;
|
global S32 is_inside_struct;
|
||||||
|
|
||||||
|
function void gen_ast(Ast *ast);
|
||||||
|
|
||||||
function void
|
function void
|
||||||
gen_indent(){
|
gen_indent(){
|
||||||
for(S32 i = 0; i < global_indent; i++) gen(" ");
|
for(S32 i = 0; i < global_indent; i++) gen(" ");
|
||||||
@@ -172,57 +174,13 @@ gen_expr(Ast_Expr *ast){
|
|||||||
// BREAK();
|
// BREAK();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
CASE(VAR, Decl){
|
||||||
|
gen_ast(node);
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
CASE(CALL, Call){
|
CASE(CALL, Call){
|
||||||
// @todo: Reach into map instead of direct lookup
|
unused(node);
|
||||||
if(is_struct(node->type) || is_array(node->type)){
|
|
||||||
if(is_array(node->type)){
|
|
||||||
gen("(Slice){%d, ", node->exprs.len);
|
|
||||||
}
|
|
||||||
gen("(");
|
|
||||||
gen_simple_decl(node->type, {});
|
|
||||||
gen(")");
|
|
||||||
|
|
||||||
gen("{");
|
|
||||||
For(node->exprs){
|
|
||||||
auto comp = it;
|
|
||||||
if(comp->name){
|
|
||||||
gen(".");
|
|
||||||
gen_expr(comp->name);
|
|
||||||
gen(" = ");
|
|
||||||
}
|
|
||||||
if(comp->index){
|
|
||||||
gen("[");
|
|
||||||
gen_expr(comp->index);
|
|
||||||
gen("] = ");
|
|
||||||
}
|
|
||||||
assert(comp->item);
|
|
||||||
gen_expr(comp->item);
|
|
||||||
|
|
||||||
if(!node->exprs.is_last(&it)) gen(", ");
|
|
||||||
}
|
|
||||||
gen("}");
|
|
||||||
if(is_array(node->type)){
|
|
||||||
gen("}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
gen_expr(node->name);
|
|
||||||
gen("(");
|
|
||||||
auto name_for_printf = (Ast_Atom *)node->name;
|
|
||||||
For(node->exprs){
|
|
||||||
// @special_case @todo in the future this should be replaced
|
|
||||||
// with []Any
|
|
||||||
if(intern_printf == name_for_printf->intern_val && &it == node->exprs.data){
|
|
||||||
Ast_Atom *atom = (Ast_Atom *)it->item;
|
|
||||||
assert(atom->kind == AST_VALUE);
|
|
||||||
assert(atom->type == untyped_string);
|
|
||||||
gen("\"%s\"", atom->intern_val.str);
|
|
||||||
}
|
|
||||||
else gen_expr(it->item);
|
|
||||||
if(!node->exprs.is_last(&it)) gen(", ");
|
|
||||||
}
|
|
||||||
gen(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
@@ -237,8 +195,6 @@ gen_line(Ast *node){
|
|||||||
genln("#line %d", node->pos->line+1);
|
genln("#line %d", node->pos->line+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
|
||||||
gen_ast(Ast *ast);
|
|
||||||
function void
|
function void
|
||||||
gen_stmt_scope(Ast_Scope *scope){
|
gen_stmt_scope(Ast_Scope *scope){
|
||||||
gen("{");
|
gen("{");
|
||||||
@@ -368,8 +324,7 @@ gen_ast(Ast *ast){
|
|||||||
gen(")");
|
gen(")");
|
||||||
|
|
||||||
if(lambda->scope) {
|
if(lambda->scope) {
|
||||||
// gen_stmt_scope(lambda->scope);
|
gen_stmt_scope(lambda->scope);
|
||||||
// @todo stmts
|
|
||||||
}
|
}
|
||||||
else gen(";");
|
else gen(";");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ struct Parse_Ctx:Lexer{
|
|||||||
U64 unique_ids;
|
U64 unique_ids;
|
||||||
Map type_map;
|
Map type_map;
|
||||||
|
|
||||||
Ast_Scope *current_scope;
|
Array<Ast_Scope *> scopes;
|
||||||
Ast_Package *resolving_package;
|
Ast_Package *resolving_package;
|
||||||
Array<Ast_Decl *> ordered_decls;
|
Array<Ast_Decl *> ordered_decls;
|
||||||
|
|
||||||
@@ -221,6 +221,7 @@ parse_init(Parse_Ctx *ctx, Allocator *perm_allocator, Allocator *heap_allocator)
|
|||||||
ctx->perm = perm_allocator;
|
ctx->perm = perm_allocator;
|
||||||
ctx->heap = heap_allocator;
|
ctx->heap = heap_allocator;
|
||||||
ctx->gen = {ctx->perm};
|
ctx->gen = {ctx->perm};
|
||||||
|
ctx->scopes = {ctx->heap};
|
||||||
ctx->ordered_decls = {ctx->heap};
|
ctx->ordered_decls = {ctx->heap};
|
||||||
ctx->type_map = {ctx->heap};
|
ctx->type_map = {ctx->heap};
|
||||||
bigint_allocator = ctx->perm;
|
bigint_allocator = ctx->perm;
|
||||||
|
|||||||
24
lambdas.kl
24
lambdas.kl
@@ -28,16 +28,16 @@ add_10 :: (size: S64): S64
|
|||||||
|
|
||||||
constant :: 20; result := constant + 10
|
constant :: 20; result := constant + 10
|
||||||
|
|
||||||
v3 := add(1,2)
|
// v3 := add(1,2)
|
||||||
v2 := add(a = 1, b = 2)
|
// v2 := add(a = 1, b = 2)
|
||||||
v1 := add(a = 1)
|
// v1 := add(a = 1)
|
||||||
// v_err := add([0] = 1)
|
// // v_err := add([0] = 1)
|
||||||
v4 := add(b = 1, a = 2)
|
// v4 := add(b = 1, a = 2)
|
||||||
// v_err := add([0] = 1, [1] = 2)
|
// // v_err := add([0] = 1, [1] = 2)
|
||||||
// v_err := add([0] = 1, 10) // illegal
|
// // v_err := add([0] = 1, 10) // illegal
|
||||||
// v_err := add([1] = 1) // illegal
|
// // v_err := add([1] = 1) // illegal
|
||||||
// v_err := add() // illegal
|
// // v_err := add() // illegal
|
||||||
|
v4 := constant
|
||||||
return v4
|
return v4
|
||||||
|
|
||||||
return_constant :: (): S64
|
return_constant :: (): S64
|
||||||
@@ -45,8 +45,8 @@ return_constant :: (): S64
|
|||||||
return constant
|
return constant
|
||||||
|
|
||||||
returning_void :: (insert: S64)
|
returning_void :: (insert: S64)
|
||||||
val1: S64 = return_constant()
|
// val1: S64 = return_constant()
|
||||||
val2: S64 = add_10(val1)
|
// val2: S64 = add_10(val1)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -542,9 +542,6 @@ lex_restream(Lexer *lexer, String istream, String file){
|
|||||||
lexer->stream.line_begin = istream.str;
|
lexer->stream.line_begin = istream.str;
|
||||||
lexer->stream.file = lexer->intern(file);
|
lexer->stream.file = lexer->intern(file);
|
||||||
|
|
||||||
|
|
||||||
lexer->tokens.clear();
|
|
||||||
lexer->token_iter = 0;
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
lexer->stream.indent_stack.allocator = scratch;
|
lexer->stream.indent_stack.allocator = scratch;
|
||||||
lexer->stream.indent_stack.add(&token_null);
|
lexer->stream.indent_stack.add(&token_null);
|
||||||
|
|||||||
@@ -15,4 +15,5 @@ val := CONSTANT_VAL
|
|||||||
DEPENDENCE :: CONSTANT_VAL
|
DEPENDENCE :: CONSTANT_VAL
|
||||||
CONSTANT_VAL :: 10
|
CONSTANT_VAL :: 10
|
||||||
|
|
||||||
|
thing: a_type = 10
|
||||||
|
|
||||||
|
|||||||
@@ -122,8 +122,6 @@ parse_init_stmt(Ast_Expr *expr){
|
|||||||
if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT)
|
if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT)
|
||||||
compiler_error(expr->pos, "Binding with [:=] to something that is not an identifier");
|
compiler_error(expr->pos, "Binding with [:=] to something that is not an identifier");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
else if(token_is_assign(token)){
|
else if(token_is_assign(token)){
|
||||||
token_next();
|
token_next();
|
||||||
Ast_Expr *value = parse_expr();
|
Ast_Expr *value = parse_expr();
|
||||||
@@ -131,10 +129,11 @@ parse_init_stmt(Ast_Expr *expr){
|
|||||||
if(token->kind == TK_ColonAssign){
|
if(token->kind == TK_ColonAssign){
|
||||||
Ast_Atom *name = (Ast_Atom *)expr;
|
Ast_Atom *name = (Ast_Atom *)expr;
|
||||||
result = (Ast_Expr *)ast_var(token, 0, name->intern_val, value);
|
result = (Ast_Expr *)ast_var(token, 0, name->intern_val, value);
|
||||||
|
set_flag(result->flags, AST_EXPR);
|
||||||
} else{
|
} else{
|
||||||
result = ast_expr_binary((Ast_Atom *)expr, value, token);
|
result = ast_expr_binary((Ast_Atom *)expr, value, token);
|
||||||
}
|
}
|
||||||
result->flags = set_flag(result->flags, AST_STMT);
|
set_flag(result->flags, AST_STMT);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
242
typechecking.cpp
242
typechecking.cpp
@@ -330,98 +330,6 @@ require_const_int(Ast_Expr *expr, B32 ast_can_be_null){
|
|||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Operand
|
|
||||||
resolve_and_require_bool(const char *error, Ast_Expr *expr, B32 ast_can_be_null = AST_CANT_BE_NULL){
|
|
||||||
if(!expr){
|
|
||||||
if(ast_can_be_null)
|
|
||||||
return {};
|
|
||||||
else compiler_error(0, "Compiler error: Null expression");
|
|
||||||
}
|
|
||||||
|
|
||||||
Operand op = resolve_expr(expr);
|
|
||||||
if(!is_bool(op.type)){
|
|
||||||
compiler_error(expr->pos, "Expected type [Bool] got instead type %s :: %s", docname(op.type), error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return op;
|
|
||||||
}
|
|
||||||
|
|
||||||
// @note: Ret is return value of function passed down the stack
|
|
||||||
// to check if type matches
|
|
||||||
function void
|
|
||||||
resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
|
||||||
if(!ast) return;
|
|
||||||
|
|
||||||
switch(ast->kind){
|
|
||||||
CASE(RETURN, Return){ // @todo: need to check if all paths return a value
|
|
||||||
Operand op = resolve_expr(node->expr);
|
|
||||||
if(!op.type && ret != type_void) compiler_error(node->pos, "Function expects a void return value but the returned value is %s", docname(op.type));
|
|
||||||
op.value = convert_untyped_to_typed(node->pos, op.value, ret);
|
|
||||||
if(op.type && op.type != ret) compiler_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(op.type));
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
CASE(VAR, Var){
|
|
||||||
Operand op = resolve_binding(node);
|
|
||||||
sym_var(node->name, op, node, INSERT_INTO_SCOPE);
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
CASE(CONST, Const){
|
|
||||||
Operand op = resolve_binding(node);
|
|
||||||
sym_const(node->name, op, node, INSERT_INTO_SCOPE);
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
CASE(PASS, Pass){
|
|
||||||
unused(node);
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
CASE(FOR, For){
|
|
||||||
if(node->init && node->cond == 0 && node->iter == 0){
|
|
||||||
if(!is_flag_set(node->init->flags, AST_STMT)){
|
|
||||||
node->cond = node->init;
|
|
||||||
node->init = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
S64 scope = scope_open();
|
|
||||||
{
|
|
||||||
resolve_expr(node->init, ret);
|
|
||||||
resolve_and_require_bool("Conditional in a for loop condition", node->cond, AST_CAN_BE_NULL);
|
|
||||||
resolve_expr(node->iter, ret);
|
|
||||||
For(node->block->stmts)
|
|
||||||
resolve_stmt(it, ret);
|
|
||||||
}
|
|
||||||
scope_close(scope);
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
CASE(IF, If){
|
|
||||||
For(node->ifs){
|
|
||||||
resolve_stmt(it->init, ret);
|
|
||||||
S64 scope = scope_open();
|
|
||||||
{
|
|
||||||
// @todo: maybe add else kind ?? and then make sure other then else are AST_CANT_BE_NULL
|
|
||||||
resolve_and_require_bool("Conditional in a if condition", it->expr, AST_CAN_BE_NULL);
|
|
||||||
For_It(it->block->stmts, jt)
|
|
||||||
resolve_stmt(jt, ret);
|
|
||||||
}
|
|
||||||
scope_close(scope);
|
|
||||||
}
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
default:{
|
|
||||||
if(is_flag_set(ast->flags, AST_EXPR)){
|
|
||||||
assert(is_flag_set(ast->flags, AST_STMT));
|
|
||||||
resolve_expr((Ast_Expr *)ast);
|
|
||||||
}
|
|
||||||
else invalid_codepath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){
|
resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){
|
||||||
@@ -924,18 +832,19 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
|
|
||||||
#define Enter_Scope(x) Enter_Scope_Defer package_scope(x)
|
#define Enter_Scope(x) Enter_Scope_Defer package_scope(x)
|
||||||
struct Enter_Scope_Defer{
|
struct Enter_Scope_Defer{
|
||||||
Ast_Scope *scope;
|
Ast_Scope *scope = 0;
|
||||||
Ast_Package *package;
|
Ast_Package *package = 0;
|
||||||
Enter_Scope_Defer(Ast_Scope *new_p){
|
Enter_Scope_Defer(Ast_Scope *new_p){
|
||||||
scope = pctx->current_scope;
|
pctx->scopes.add(new_p);
|
||||||
pctx->current_scope = new_p;
|
scope = new_p;
|
||||||
if(new_p->kind == AST_PACKAGE){
|
if(new_p->kind == AST_PACKAGE){
|
||||||
package = pctx->resolving_package;
|
package = pctx->resolving_package;
|
||||||
pctx->resolving_package = (Ast_Package *)new_p;
|
pctx->resolving_package = (Ast_Package *)new_p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
~Enter_Scope_Defer(){
|
~Enter_Scope_Defer(){
|
||||||
pctx->current_scope = scope;
|
Ast_Scope *poped = pctx->scopes.pop();
|
||||||
|
assert(poped == scope);
|
||||||
if(package){
|
if(package){
|
||||||
pctx->resolving_package = package;
|
pctx->resolving_package = package;
|
||||||
}
|
}
|
||||||
@@ -954,9 +863,15 @@ search_for_decl(Ast_Scope *scope, Intern_String name){
|
|||||||
|
|
||||||
function Ast_Decl *
|
function Ast_Decl *
|
||||||
search_for_decl_in_current_context(Intern_String name){
|
search_for_decl_in_current_context(Intern_String name){
|
||||||
Ast_Decl *result = search_for_decl(pctx->current_scope, name);
|
Ast_Decl *result = 0;
|
||||||
|
for(S64 i = pctx->scopes.len - 1; i >= 0; i--){
|
||||||
|
result = search_for_decl(pctx->scopes[i], name);
|
||||||
|
if(result) break;
|
||||||
|
}
|
||||||
|
|
||||||
if(!result)
|
if(!result)
|
||||||
result = search_for_decl(pctx->resolving_package, name);
|
result = search_for_decl(pctx->resolving_package, name);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -967,7 +882,7 @@ insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
insert_into_current_scope(Ast_Decl *decl){
|
insert_into_current_scope(Ast_Decl *decl){
|
||||||
insert_into_scope(pctx->current_scope, decl);
|
insert_into_scope(*pctx->scopes.last(), decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
@@ -1006,6 +921,22 @@ resolve_typespec(Ast_Expr *ast, B32 flags){
|
|||||||
return resolved.type_val;
|
return resolved.type_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Operand
|
||||||
|
resolve_and_require_bool(const char *error, Ast_Expr *expr, B32 flags){
|
||||||
|
if(!expr){
|
||||||
|
if(flags == AST_CAN_BE_NULL)
|
||||||
|
return {};
|
||||||
|
else compiler_error(0, "Compiler error: Null expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
Operand op = resolve_expr(expr, flags);
|
||||||
|
if(!is_bool(op.type)){
|
||||||
|
compiler_error(expr->pos, "Expected type [Bool] got instead type %s :: %s", docname(op.type), error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
require_const_int(Ast_Expr *expr, B32 flags){
|
require_const_int(Ast_Expr *expr, B32 flags){
|
||||||
Operand op = resolve_expr(expr, flags);
|
Operand op = resolve_expr(expr, flags);
|
||||||
@@ -1023,6 +954,15 @@ require_const_int(Ast_Expr *expr, B32 flags){
|
|||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
resolve_const(Ast_Decl *node){
|
||||||
|
Operand op = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
||||||
|
if(!op.is_const){
|
||||||
|
compiler_error(node->pos, "Assigning a value that is not constant to a constant declaration");
|
||||||
|
}
|
||||||
|
node->value = op.value;
|
||||||
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
resolve_var(Ast_Decl *node){
|
resolve_var(Ast_Decl *node){
|
||||||
Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL);
|
Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL);
|
||||||
@@ -1033,6 +973,83 @@ resolve_var(Ast_Decl *node){
|
|||||||
node->value = op.value;
|
node->value = op.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @note: Ret is return value of function passed down the stack
|
||||||
|
// to check if type matches
|
||||||
|
function void
|
||||||
|
resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
||||||
|
if(!ast) return;
|
||||||
|
|
||||||
|
switch(ast->kind){
|
||||||
|
CASE(RETURN, Return){ // @todo: need to check if all paths return a value
|
||||||
|
Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL);
|
||||||
|
if(!op.type && ret != type_void) compiler_error(node->pos, "Function expects a void return value but the returned value is %s", docname(op.type));
|
||||||
|
op.value = convert_untyped_to_typed(node->pos, op.value, ret);
|
||||||
|
if(op.type && op.type != ret) compiler_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(op.type));
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
|
// CASE(VAR, Decl){
|
||||||
|
// resolve_decl(node);
|
||||||
|
// insert_into_current_scope(node);
|
||||||
|
// BREAK();
|
||||||
|
// }
|
||||||
|
|
||||||
|
case AST_LAMBDA:
|
||||||
|
case AST_VAR:
|
||||||
|
CASE(CONST, Decl){
|
||||||
|
resolve_decl(node);
|
||||||
|
insert_into_current_scope(node);
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
|
CASE(PASS, Pass){
|
||||||
|
unused(node);
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
|
CASE(FOR, For){
|
||||||
|
if(node->init && node->cond == 0 && node->iter == 0){
|
||||||
|
if(!is_flag_set(node->init->flags, AST_STMT)){
|
||||||
|
node->cond = node->init;
|
||||||
|
node->init = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Enter_Scope(node->scope);
|
||||||
|
resolve_expr(node->init, AST_CAN_BE_NULL);
|
||||||
|
resolve_and_require_bool("Conditional in a for loop condition", node->cond, AST_CAN_BE_NULL);
|
||||||
|
resolve_expr(node->iter, AST_CAN_BE_NULL);
|
||||||
|
For(node->scope->stmts)
|
||||||
|
resolve_stmt(it, ret);
|
||||||
|
}
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
|
CASE(IF, If){
|
||||||
|
For(node->ifs){
|
||||||
|
resolve_stmt(it->init, ret);
|
||||||
|
{
|
||||||
|
Enter_Scope(it->scope);
|
||||||
|
// @todo: maybe add else kind ?? and then make sure other then else are AST_CANT_BE_NULL
|
||||||
|
resolve_and_require_bool("Conditional in a if condition", it->expr, AST_CAN_BE_NULL);
|
||||||
|
For_It(it->scope->stmts, jt)
|
||||||
|
resolve_stmt(jt, ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
|
default:{
|
||||||
|
if(is_flag_set(ast->flags, AST_EXPR)){
|
||||||
|
assert(is_flag_set(ast->flags, AST_STMT));
|
||||||
|
resolve_expr((Ast_Expr *)ast, AST_CANT_BE_NULL);
|
||||||
|
}
|
||||||
|
else invalid_codepath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
resolve_expr(Ast_Expr *ast, B32 flags){
|
resolve_expr(Ast_Expr *ast, B32 flags){
|
||||||
if(!ast && flags == AST_CAN_BE_NULL) return {};
|
if(!ast && flags == AST_CAN_BE_NULL) return {};
|
||||||
@@ -1046,6 +1063,12 @@ resolve_expr(Ast_Expr *ast, B32 flags){
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CASE(CALL, Call){
|
||||||
|
unused(node);
|
||||||
|
// return {};
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
CASE(IDENT, Atom){
|
CASE(IDENT, Atom){
|
||||||
Ast_Decl *decl = resolve_name(node->pos, node->intern_val);
|
Ast_Decl *decl = resolve_name(node->pos, node->intern_val);
|
||||||
|
|
||||||
@@ -1065,12 +1088,6 @@ resolve_expr(Ast_Expr *ast, B32 flags){
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(VAR, Decl){
|
|
||||||
resolve_var(node);
|
|
||||||
insert_into_current_scope(node);
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
CASE(BINARY, Binary){
|
CASE(BINARY, Binary){
|
||||||
if(token_is_assign(node->op)){
|
if(token_is_assign(node->op)){
|
||||||
assert(is_flag_set(node->flags, AST_STMT));
|
assert(is_flag_set(node->flags, AST_STMT));
|
||||||
@@ -1097,6 +1114,12 @@ resolve_expr(Ast_Expr *ast, B32 flags){
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CASE(VAR, Decl){
|
||||||
|
resolve_stmt(node, 0);
|
||||||
|
return {};
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
CASE(UNARY, Unary){
|
CASE(UNARY, Unary){
|
||||||
Operand value = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
Operand value = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
||||||
if(node->op == TK_Pointer){
|
if(node->op == TK_Pointer){
|
||||||
@@ -1177,8 +1200,7 @@ resolve_decl(Ast_Decl *ast){
|
|||||||
insert_into_current_scope(it);
|
insert_into_current_scope(it);
|
||||||
}
|
}
|
||||||
For(lambda->scope->stmts){
|
For(lambda->scope->stmts){
|
||||||
unused(it);
|
resolve_stmt(it, ret_type);
|
||||||
// resolve_stmt(it, ret_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = operand_lambda(lambda_type);
|
result = operand_lambda(lambda_type);
|
||||||
@@ -1190,11 +1212,7 @@ resolve_decl(Ast_Decl *ast){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CASE(CONST, Decl){
|
CASE(CONST, Decl){
|
||||||
Operand op = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
resolve_const(node);
|
||||||
if(!op.is_const){
|
|
||||||
compiler_error(node->pos, "Assigning a value that is not constant to a constant declaration");
|
|
||||||
}
|
|
||||||
node->value = op.value;
|
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user