diff --git a/ast.cpp b/ast.cpp index 7bddd37..7abf607 100644 --- a/ast.cpp +++ b/ast.cpp @@ -111,6 +111,8 @@ struct Ast_Binary: Ast_Expr{ Token_Kind op; Ast_Expr *left; Ast_Expr *right; + + Ast_Resolved_Type *type; }; // Problem: We are parsing out of order, in the middle of parsing a function diff --git a/ccodegen.cpp b/ccodegen.cpp index a07f399..5e6b919 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -4,6 +4,8 @@ global S32 global_indent; global S32 is_inside_struct; +function void gen_ast(Ast *ast); + function void gen_indent(){ for(S32 i = 0; i < global_indent; i++) gen(" "); @@ -172,57 +174,13 @@ gen_expr(Ast_Expr *ast){ // BREAK(); // } + CASE(VAR, Decl){ + gen_ast(node); + BREAK(); + } + CASE(CALL, Call){ - // @todo: Reach into map instead of direct lookup - 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(")"); - } + unused(node); BREAK(); } @@ -237,8 +195,6 @@ gen_line(Ast *node){ genln("#line %d", node->pos->line+1); } -function void -gen_ast(Ast *ast); function void gen_stmt_scope(Ast_Scope *scope){ gen("{"); @@ -368,8 +324,7 @@ gen_ast(Ast *ast){ gen(")"); if(lambda->scope) { - // gen_stmt_scope(lambda->scope); - // @todo stmts + gen_stmt_scope(lambda->scope); } else gen(";"); } diff --git a/compiler.h b/compiler.h index 0dc6902..c79e656 100644 --- a/compiler.h +++ b/compiler.h @@ -176,7 +176,7 @@ struct Parse_Ctx:Lexer{ U64 unique_ids; Map type_map; - Ast_Scope *current_scope; + Array scopes; Ast_Package *resolving_package; Array ordered_decls; @@ -221,6 +221,7 @@ parse_init(Parse_Ctx *ctx, Allocator *perm_allocator, Allocator *heap_allocator) ctx->perm = perm_allocator; ctx->heap = heap_allocator; ctx->gen = {ctx->perm}; + ctx->scopes = {ctx->heap}; ctx->ordered_decls = {ctx->heap}; ctx->type_map = {ctx->heap}; bigint_allocator = ctx->perm; diff --git a/lambdas.kl b/lambdas.kl index 4b96c0d..aeb65c3 100644 --- a/lambdas.kl +++ b/lambdas.kl @@ -28,16 +28,16 @@ add_10 :: (size: S64): S64 constant :: 20; result := constant + 10 - v3 := add(1,2) - v2 := add(a = 1, b = 2) - v1 := add(a = 1) - // v_err := add([0] = 1) - v4 := add(b = 1, a = 2) - // v_err := add([0] = 1, [1] = 2) - // v_err := add([0] = 1, 10) // illegal - // v_err := add([1] = 1) // illegal - // v_err := add() // illegal - + // v3 := add(1,2) + // v2 := add(a = 1, b = 2) + // v1 := add(a = 1) + // // v_err := add([0] = 1) + // v4 := add(b = 1, a = 2) + // // v_err := add([0] = 1, [1] = 2) + // // v_err := add([0] = 1, 10) // illegal + // // v_err := add([1] = 1) // illegal + // // v_err := add() // illegal + v4 := constant return v4 return_constant :: (): S64 @@ -45,8 +45,8 @@ return_constant :: (): S64 return constant returning_void :: (insert: S64) - val1: S64 = return_constant() - val2: S64 = add_10(val1) + // val1: S64 = return_constant() + // val2: S64 = add_10(val1) return diff --git a/lexing.cpp b/lexing.cpp index 76cd08a..02ca865 100644 --- a/lexing.cpp +++ b/lexing.cpp @@ -542,9 +542,6 @@ lex_restream(Lexer *lexer, String istream, String file){ lexer->stream.line_begin = istream.str; lexer->stream.file = lexer->intern(file); - - lexer->tokens.clear(); - lexer->token_iter = 0; Scratch scratch; lexer->stream.indent_stack.allocator = scratch; lexer->stream.indent_stack.add(&token_null); diff --git a/order1.kl b/order1.kl index b8da11f..179c512 100644 --- a/order1.kl +++ b/order1.kl @@ -15,4 +15,5 @@ val := CONSTANT_VAL DEPENDENCE :: CONSTANT_VAL CONSTANT_VAL :: 10 +thing: a_type = 10 diff --git a/parsing.cpp b/parsing.cpp index 0943982..dbbd8b0 100644 --- a/parsing.cpp +++ b/parsing.cpp @@ -122,8 +122,6 @@ parse_init_stmt(Ast_Expr *expr){ if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT) compiler_error(expr->pos, "Binding with [:=] to something that is not an identifier"); - - else if(token_is_assign(token)){ token_next(); Ast_Expr *value = parse_expr(); @@ -131,10 +129,11 @@ parse_init_stmt(Ast_Expr *expr){ if(token->kind == TK_ColonAssign){ Ast_Atom *name = (Ast_Atom *)expr; result = (Ast_Expr *)ast_var(token, 0, name->intern_val, value); + set_flag(result->flags, AST_EXPR); } else{ 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; } diff --git a/typechecking.cpp b/typechecking.cpp index b16e09b..d34efe4 100644 --- a/typechecking.cpp +++ b/typechecking.cpp @@ -330,98 +330,6 @@ require_const_int(Ast_Expr *expr, B32 ast_can_be_null){ 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 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) struct Enter_Scope_Defer{ - Ast_Scope *scope; - Ast_Package *package; + Ast_Scope *scope = 0; + Ast_Package *package = 0; Enter_Scope_Defer(Ast_Scope *new_p){ - scope = pctx->current_scope; - pctx->current_scope = new_p; + pctx->scopes.add(new_p); + scope = new_p; if(new_p->kind == AST_PACKAGE){ package = pctx->resolving_package; pctx->resolving_package = (Ast_Package *)new_p; } } ~Enter_Scope_Defer(){ - pctx->current_scope = scope; + Ast_Scope *poped = pctx->scopes.pop(); + assert(poped == scope); if(package){ pctx->resolving_package = package; } @@ -954,9 +863,15 @@ search_for_decl(Ast_Scope *scope, Intern_String name){ function Ast_Decl * 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) result = search_for_decl(pctx->resolving_package, name); + return result; } @@ -967,7 +882,7 @@ insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){ function void insert_into_current_scope(Ast_Decl *decl){ - insert_into_scope(pctx->current_scope, decl); + insert_into_scope(*pctx->scopes.last(), decl); } function void @@ -1006,6 +921,22 @@ resolve_typespec(Ast_Expr *ast, B32 flags){ 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 require_const_int(Ast_Expr *expr, B32 flags){ Operand op = resolve_expr(expr, flags); @@ -1023,6 +954,15 @@ require_const_int(Ast_Expr *expr, B32 flags){ 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 resolve_var(Ast_Decl *node){ 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; } +// @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 resolve_expr(Ast_Expr *ast, B32 flags){ if(!ast && flags == AST_CAN_BE_NULL) return {}; @@ -1046,6 +1063,12 @@ resolve_expr(Ast_Expr *ast, B32 flags){ BREAK(); } + CASE(CALL, Call){ + unused(node); + // return {}; + BREAK(); + } + CASE(IDENT, Atom){ Ast_Decl *decl = resolve_name(node->pos, node->intern_val); @@ -1065,12 +1088,6 @@ resolve_expr(Ast_Expr *ast, B32 flags){ BREAK(); } - CASE(VAR, Decl){ - resolve_var(node); - insert_into_current_scope(node); - BREAK(); - } - CASE(BINARY, Binary){ if(token_is_assign(node->op)){ assert(is_flag_set(node->flags, AST_STMT)); @@ -1097,6 +1114,12 @@ resolve_expr(Ast_Expr *ast, B32 flags){ BREAK(); } + CASE(VAR, Decl){ + resolve_stmt(node, 0); + return {}; + BREAK(); + } + CASE(UNARY, Unary){ Operand value = resolve_expr(node->expr, AST_CANT_BE_NULL); if(node->op == TK_Pointer){ @@ -1177,8 +1200,7 @@ resolve_decl(Ast_Decl *ast){ insert_into_current_scope(it); } For(lambda->scope->stmts){ - unused(it); - // resolve_stmt(it, ret_type); + resolve_stmt(it, ret_type); } result = operand_lambda(lambda_type); @@ -1190,11 +1212,7 @@ resolve_decl(Ast_Decl *ast){ } CASE(CONST, Decl){ - 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; + resolve_const(node); BREAK(); }