From 89b3e00ae4d3389f51c43a92db3825a276186255 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 10 Jun 2022 14:08:27 +0200 Subject: [PATCH] Closer to old state --- ast.cpp | 7 +- ccodegen.cpp | 53 +++-- lambdas.kl | 2 +- main.cpp | 1 + order2.kl | 25 +-- parsing.cpp | 2 +- typechecking.cpp | 547 +++++++++++++++-------------------------------- typechecking.h | 4 +- 8 files changed, 219 insertions(+), 422 deletions(-) diff --git a/ast.cpp b/ast.cpp index 7abf607..95b42ac 100644 --- a/ast.cpp +++ b/ast.cpp @@ -29,6 +29,7 @@ enum Ast_Kind: U32{ AST_BLOCK, AST_PASS, AST_LAMBDA, + AST_LAMBDA_EXPR, AST_LAMBDA_ARG, AST_ENUM, AST_ENUM_MEMBER, @@ -100,11 +101,14 @@ struct Ast_Unary: Ast_Expr{ struct Ast_Cast: Ast_Expr{ Ast_Expr *expr; Ast_Expr *typespec; + Ast_Resolved_Type *before_type; + Ast_Resolved_Type *after_type; }; struct Ast_Index: Ast_Expr{ Ast_Expr *expr; Ast_Expr *index; + Ast_Resolved_Type *original_type; }; struct Ast_Binary: Ast_Expr{ @@ -154,6 +158,7 @@ struct Ast_Lambda : Ast_Expr { struct Ast_Array: Ast_Expr{ Ast_Expr *base; Ast_Expr *expr; + Ast_Resolved_Type *type; }; /* @@ -335,7 +340,7 @@ ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){ function Ast_Lambda * ast_lambda(Token *pos, Array params, B32 has_var_args, Ast_Expr *ret, Ast_Scope *scope){ - AST_NEW(Lambda, LAMBDA, pos, AST_EXPR); + AST_NEW(Lambda, LAMBDA_EXPR, pos, AST_EXPR); result->flags = AST_EXPR; result->args = params.tight_copy(pctx->perm); result->scope = scope; diff --git a/ccodegen.cpp b/ccodegen.cpp index 5e6b919..a7a1388 100644 --- a/ccodegen.cpp +++ b/ccodegen.cpp @@ -164,15 +164,15 @@ gen_expr(Ast_Expr *ast){ BREAK(); } - // CASE(CAST, Cast){ - // gen("("); - // gen("("); - // gen_simple_decl(resolved_type_get(node->typespec), {}); - // gen(")"); - // gen_expr(node->expr); - // gen(")"); - // BREAK(); - // } + CASE(CAST, Cast){ + gen("("); + gen("("); + gen_simple_decl(node->after_type, {}); + gen(")"); + gen_expr(node->expr); + gen(")"); + BREAK(); + } CASE(VAR, Decl){ gen_ast(node); @@ -180,8 +180,13 @@ gen_expr(Ast_Expr *ast){ } CASE(CALL, Call){ - unused(node); - + gen_expr(node->name); + gen("("); + For(node->exprs){ + gen_expr(it->item); + if(!node->exprs.is_last(&it)) gen(", "); + } + gen(")"); BREAK(); } @@ -215,11 +220,7 @@ enum { function void gen_var(Intern_String name, Ast_Resolved_Type *type, Ast_Expr *expr, B32 emit_value){ - if(is_array(type)){ - gen("Slice %s", name.str); - } else{ - gen_simple_decl(type, name); - } + gen_simple_decl(type, name); if(emit_value == DONT_EMIT_VALUE){ return; @@ -228,11 +229,6 @@ gen_var(Intern_String name, Ast_Resolved_Type *type, Ast_Expr *expr, B32 emit_va if(expr){ gen(" = "); gen_expr(expr); - } else if(is_array(type)){ - gen(" = (Slice){%d, (", type->arr.size); - gen_simple_decl(type, {}); - gen("){}"); - gen("}"); } else { // Default zero if(is_numeric(type)){ gen(" = 0"); @@ -337,6 +333,21 @@ gen_ast(Ast *ast){ BREAK(); } + CASE(STRUCT, Decl){ + gen("typedef struct %s{", node->name.str); + global_indent++; + is_inside_struct++; + For(node->scope->decls){ + genln(""); + gen_ast(it); + } + + is_inside_struct--; + global_indent--; + genln("}%s;", node->name.str); + BREAK(); + } + CASE(CONST, Decl){ switch(node->type->kind){ CASE_FLOAT:{ diff --git a/lambdas.kl b/lambdas.kl index aeb65c3..6b8b14a 100644 --- a/lambdas.kl +++ b/lambdas.kl @@ -28,7 +28,7 @@ add_10 :: (size: S64): S64 constant :: 20; result := constant + 10 - // v3 := add(1,2) + v3 := add(1,2) // v2 := add(a = 1, b = 2) // v1 := add(a = 1) // // v_err := add([0] = 1) diff --git a/main.cpp b/main.cpp index 2c5453c..c3230bd 100644 --- a/main.cpp +++ b/main.cpp @@ -221,6 +221,7 @@ int main(int argument_count, char **arguments){ Array files = {scratch}; files.add("lambdas.kl"_s); files.add("order1.kl"_s); + files.add("order2.kl"_s); String result = compile_files(files); printf("%s", result.str); __debugbreak(); diff --git a/order2.kl b/order2.kl index 47196cc..71cf613 100644 --- a/order2.kl +++ b/order2.kl @@ -1,37 +1,14 @@ Str16 :: String16 -// arena_pointer: *Arena = null +arena_pointer: *Arena = 0 thing: Arena no_type := thing -constant_access := Arena.constant_inside - -arena := Arena( -// next = null, -// data = null, - len = 1000, - cap = 1000, -) - -// lambda_value := (val: S64) // @todo - // return Arena :: struct - // arena: Arena next: *Arena data: *S64 len : S64 cap : S64 - Sub :: struct - len: S64 - Sub_Sub :: struct - len: S64 - - get_len :: (s: *Arena): S64 // @todo - return s.next.len - - constant_inside :: 10000 - -// subarena: Arena.Sub // @todo string16: Str16 String16 :: struct diff --git a/parsing.cpp b/parsing.cpp index dbbd8b0..1e3669d 100644 --- a/parsing.cpp +++ b/parsing.cpp @@ -581,7 +581,7 @@ parse_decl(B32 is_global){ Ast_Expr *expr = parse_expr(); result = ast_const(tname, tname->intern_val, expr); - if(expr->kind == AST_LAMBDA){ + if(expr->kind == AST_LAMBDA_EXPR){ auto a = (Ast_Lambda *)expr; if(a->scope){ result->kind = AST_LAMBDA; diff --git a/typechecking.cpp b/typechecking.cpp index d34efe4..67a3f62 100644 --- a/typechecking.cpp +++ b/typechecking.cpp @@ -295,8 +295,7 @@ make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Resolved_ compiler_error(pos, "Assigning but incompatible types, expression: %s expected var type: %s", docname(expr->type), docname(type)); } - // @todo - // type_complete(expr->type); + type_complete(expr->type); check_value_bounds(pos, &expr->value); assert(expr->type); } @@ -306,7 +305,7 @@ function void _rewrite_into_const(Ast *node, U64 ast_size, Value value){ auto ast = (Ast_Atom *)node; assert(ast_size >= sizeof(Ast_Atom)); - ast->flags = set_flag(ast->flags, AST_ATOM); + set_flag(ast->flags, AST_ATOM); ast->kind = AST_VALUE; ast->value = value; } @@ -331,82 +330,6 @@ require_const_int(Ast_Expr *expr, B32 ast_can_be_null){ } -function Operand -resolve_lambda(Ast_Lambda *lambda, Sym *sym = 0){ - Scratch scratch; - Ast_Resolved_Type *lambda_type = 0; - Ast_Resolved_Type *ret_type = resolve_typespec(lambda->ret); - Array args = {scratch}; - For(lambda->args){ - Ast_Resolved_Type *type = - resolve_typespec(it->typespec, AST_CANT_BE_NULL); - Operand default_value = resolve_expr(it->default_value, type); - make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL); - args.add(type); - } - - lambda_type = type_lambda(lambda, ret_type, args); - sym_type(lambda_type, lambda); - Operand result = operand_type(lambda_type); - - // @note: top level lambda needs to get marked as resolved - // so that the cyclic dependency wont trigger - if(sym){ - sym->type = lambda_type; - sym->state = SYM_RESOLVED; - } - - // @todo: We also need to make sure there is a return value when ret type is not void - // @note: then try resolving the block of lambda - if(lambda->block){ - S64 scope_index = scope_open(); - For(lambda->args){ - S64 i = lambda->args.get_index(&it); - Ast_Resolved_Type *type = args[i]; - sym_var(it->name, type, it, INSERT_INTO_SCOPE); - } - For(lambda->block->stmts){ - resolve_stmt(it, ret_type); - } - scope_close(scope_index); - - result = operand_lambda(lambda_type); - } - else if(is_flag_set(lambda->parent->flags, AST_FOREIGN)){ - result = operand_lambda(lambda_type); - } - - - return result; -} - -function Operand -field_access_builtin_string(Ast_Expr *right){ - if(right->kind == AST_BINARY) invalid_codepath; // @todo entire field access needs a rework - assert(right->kind == AST_IDENT); - - auto a = (Ast_Atom *)right; - if(a->intern_val == pctx->intern("len"_s)){ - return operand_lvalue(type_s64); - } - else if(a->intern_val == pctx->intern("str"_s)){ - return operand_lvalue(type_pointer(type_u8)); - } - else invalid_return; -} - -function Operand -field_access_builtin_array(Ast_Expr *right){ - if(right->kind == AST_BINARY) invalid_codepath; // @todo entire field access needs a rework - assert(right->kind == AST_IDENT); - - auto a = (Ast_Atom *)right; - if(a->intern_val == pctx->intern("len"_s)){ - return operand_lvalue(type_s64); - } - else invalid_return; -} - function Operand resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_resolve){ @@ -414,257 +337,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res assert(is_flag_set(ast->flags, AST_EXPR)); switch(ast->kind){ - CASE(VALUE, Atom){ - return operand_const_rvalue(node->value); - BREAK(); - } - CASE(IDENT, Atom){ - Sym *sym = resolve_name(node->pos, node->intern_val); - if(sym->kind == SYM_CONST && sym->type != type_type && sym->type->kind != TYPE_LAMBDA){ - rewrite_into_const(node, Ast_Atom, sym); - return operand(sym); - } - else if(sym->kind == SYM_VAR || sym->kind == SYM_CONST){ - sym_associate(node, sym); - return operand(sym); - } - - invalid_return; - BREAK(); - } - - // Typespec array [32]int - CASE(ARRAY, Array){ - // @todo: Arrays of inferred size [] - Operand type = resolve_expr(node->base); - if(type.type != type_type) compiler_error(node->pos, "Prefix array operator is only allowed on types"); - Operand expr = require_const_int(node->expr, AST_CAN_BE_NULL); - - Ast_Resolved_Type *resolved = type_array(type.type_val, node->expr ? 1 : 0, bigint_as_unsigned(&expr.big_int_val)); - sym_type(resolved, node); - return operand_type(resolved); - BREAK(); - } - - CASE(INDEX, Index){ - Operand left = resolve_expr(node->expr); - Operand index = resolve_expr(node->index); - if(!is_int(index.type)){ - - compiler_error(node->pos, "Trying to index the array with invalid type, expected [Int] got instead %s", docname(index.type)); - } - if(!is_array(left.type) && !is_pointer(left.type)){ - compiler_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %s instead", docname(left.type)); - } - - sym_new_resolved(SYM_VAR, {}, left.value, node); - return operand_lvalue(left.type->arr.base); - BREAK(); - } - - CASE(LAMBDA, Lambda){ - return resolve_lambda(node); - BREAK(); - } - - CASE(CALL, Call){ - Operand name = resolve_expr(node->name); - Ast_Resolved_Type *type = name.type; - if(name.type == type_type){ - type = name.type_val; - if(expected_type && expected_type != type) - compiler_error(node->pos, "Variable type different from explicit compound type"); - if(type->kind == TYPE_LAMBDA) - compiler_error(node->pos, "Calling a lambda type"); - } - type_complete(type); - node->type = type; - - if(type->kind == TYPE_ARRAY){ - if(node->exprs.len > type->arr.size && type->arr.size != ARRAY_SIZE_INFERRED) - compiler_error(node->pos, "compound statement has too many items for this type"); - Ast_Resolved_Type *item_type = type->arr.base; - - For(node->exprs){ - Ast_Call_Item *i = (Ast_Call_Item *)it; - assert(i->kind == AST_CALL_ITEM); - if(i->name) compiler_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]); - if(i->index){ - Operand index_op = require_const_int(i->index, AST_CANT_BE_NULL); - U64 index = bigint_as_unsigned(&index_op.big_int_val); - if(index > (type->arr.size - 1)) compiler_error(i->pos, "Invalid index in compound expression, larger then type can store"); - } - Operand expr = resolve_expr(i->item, item_type); - expr.value = convert_untyped_to_typed(i->pos, expr.value, item_type); - // @todo I don't think this detects when types are different - } - } - - else if(type->kind == TYPE_STRUCT){ - auto agg = (Ast_Struct *)type->ast; - - S64 default_iter = 0; - For_It(node->exprs, expr){ - if(expr->index) compiler_error(expr->index->pos, "Function call indexing is illegal"); - Ast_Atom *name = expr->name; - S64 expr_index = node->exprs.get_index(&expr); - - Ast_Named *found = 0; - Ast_Resolved_Member *found_type = 0; - if(name){ - assert(name->kind == AST_IDENT); - For_It(agg->members, member){ - if(member->name.str == name->intern_val.str){ - if(member->kind == AST_CONST) compiler_error(expr->pos, "Initializing a value that is a constant"); - found = member; - found_type = &type->agg.members[agg->members.get_index(&member)]; - break; - } - } - } - else if(expr_index == default_iter){ - S64 i = default_iter++; - found = agg->members[i]; - found_type = &type->agg.members[i]; - if(i >= agg->members.len) compiler_error(expr->pos, "Too many arguments in compound constructor"); - } - else compiler_error(expr->pos, "Positional argument after named or indexed argument"); - - if(!found) compiler_error(expr->pos, "Invalid argument in compound constructor"); - if(is_flag_set(found->flags, AST_ITEM_INCLUDED)) compiler_error(found->pos, "Item included multiple times in compound constructor"); - found->flags = set_flag(found->flags, AST_ITEM_INCLUDED); - - Operand op = resolve_expr(expr->item, found_type->type); - - op.value = convert_untyped_to_typed(node->pos, op.value, found_type->type); - if(found_type->type != op.type) compiler_error(expr->pos, "Invalid type of compound constructor item, expected %s got instead %s", type_names[found_type->type->kind], type_names[op.type->kind]); - } - - // @note: cleanup, required? - For(agg->members) it->flags = unset_flag(it->flags, AST_ITEM_INCLUDED); - } - else if(type->kind == TYPE_LAMBDA){ - Scratch scratch; - Array items = {scratch}; - - S64 was_name_indexed = false; - S64 default_iter = 0; - auto lambda = (Ast_Lambda *)type->ast; - For(lambda->args){ - S64 i = lambda->args.get_index(&it); - Ast_Resolved_Type *resolved = type->func.args[i]; - Ast_Lambda_Arg *arg = it; - - // @note: match any in list of call items, if none matched then we have a problem - // there are three kinds of possible matches: indexed, named, default - Ast_Call_Item *item = 0; - For_It(node->exprs, expr){ - if(expr->index) compiler_error(expr->index->pos, "Function call indexing is illegal"); - Ast_Atom *name = expr->name; - - if(name){ - assert(name->kind == AST_IDENT); - was_name_indexed = true; - if(name->intern_val.str == arg->name.str) item = expr; - } - else if(node->exprs.get_index(&expr) == default_iter){ - default_iter++; - item = expr; - } - else if(node->exprs.get_index(&expr) > default_iter){ - compiler_error(expr->pos, "Positional argument after named argument"); - } - - if(item) - break; - } - - if(item){ - item->flags = set_flag(item->flags, AST_ITEM_INCLUDED); - Operand expr = resolve_expr(item->item); - make_sure_value_is_compatible_with_type(node->pos, &expr, resolved, TYPE_AND_EXPR_REQUIRED); - items.add(item); - } - else{ - if(arg->default_value){ - Ast_Call_Item *item_default = ast_call_item(arg->default_value->pos, 0, 0, arg->default_value); - items.add(item_default); - } - else compiler_error(arg->pos, "Required value in lambda call was not passed"); - } - } - - if(lambda->has_var_args){ - if(was_name_indexed) - compiler_error(lambda->pos, "Cant name index a lambda with var args"); - for(S64 i = lambda->args.len; i < node->exprs.len; i++){ - Ast_Call_Item *item = node->exprs.data[i]; - resolve_expr(item->item); - item->flags = set_flag(item->flags, AST_ITEM_INCLUDED); - items.add(item); - } - } - - // @note: check if all arguments are included and cleanup - For(node->exprs){ - if(!is_flag_set(it->flags, AST_ITEM_INCLUDED)) - compiler_error(it->pos, "Invalid argument to function call"); - else it->flags = unset_flag(it->flags, AST_ITEM_INCLUDED); - } - - node->exprs = items.tight_copy(pctx->perm); - type = type->func.ret; - } - else compiler_error(node->pos, "Invalid function call type"); - - return operand_rvalue(type); - BREAK(); - } - - CASE(CAST, Cast){ - Operand expr = resolve_expr(node->expr); - Ast_Resolved_Type *type = resolve_typespec(node->typespec); - Ast_Resolved_Type *original_type = expr.type; - - // @todo: cleanup, probably just want one big if - // @todo: factor this into a function for easier search - - switch(expr.type->kind){ - case TYPE_POINTER:{ - if(is_pointer(type)) - expr = operand_rvalue(type); - else goto failure; - } break; - CASE_UNTYPED: { - expr.value = convert_untyped_to_typed(node->pos, expr.value, type); - } break; - CASE_UINT: - CASE_SINT:{ - if(is_int(type)) - expr.type = type; - else if(is_float(type)){ - expr.value.type = type; - if(expr.is_const) expr.value.f64_val = bigint_as_float(&expr.big_int_val); // @leak - } else goto failure; - } break; - case TYPE_F32: case TYPE_F64: { - if(is_float(type)){ - expr.type = type; - } - else if(is_int(type)){ - if(expr.is_const) expr.value.big_int_val = bigint_s64((S64)expr.value.f64_val); // @todo: What to do here??? - expr.type = type; - } else goto failure; - } break; - default: failure: compiler_error(node->pos, "Failed to cast from %s to %s", docname(expr.type), docname(type));; - } - - if(original_type != type) assert(expr.type == type); - if(expr.is_const) check_value_bounds(node->pos, &expr.value); - return expr; - BREAK(); - } CASE(UNARY, Unary){ Operand value = resolve_expr(node->expr); @@ -912,10 +585,12 @@ insert_builtin_types_into_package(Ast_Package *p){ function Ast_Resolved_Type * resolve_typespec(Ast_Expr *ast, B32 flags){ - if(!ast && flags == AST_CAN_BE_NULL) + if(!ast && is_flag_set(flags, AST_CAN_BE_NULL)) return 0; Operand resolved = resolve_expr(ast, flags); + if(is_flag_set(flags, RESOLVE_TYPESPEC_COMPLETE)) + type_complete(resolved.type); if(resolved.type != type_type) compiler_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]); return resolved.type_val; @@ -954,25 +629,6 @@ 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); - Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL); - assert(op.type != 0 || type != 0); - - make_sure_value_is_compatible_with_type(node->pos, &op, type, EXPR_CAN_BE_NULL|TYPE_CAN_BE_NULL); - node->value = op.value; -} - // @note: Ret is return value of function passed down the stack // to check if type matches function void @@ -988,16 +644,10 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ 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); + resolve_decl(node, IS_NOT_PACKAGE_GLOBAL); insert_into_current_scope(node); BREAK(); } @@ -1050,9 +700,54 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){ } } +function Operand +resolve_cast(Ast_Cast *node){ + Operand expr = resolve_expr(node->expr, AST_CANT_BE_NULL); + Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CANT_BE_NULL); + Ast_Resolved_Type *original_type = expr.type; + node->before_type = expr.type; + + // @todo: cleanup, probably just want one big if + switch(expr.type->kind){ + case TYPE_POINTER:{ + if(is_pointer(type)) + expr = operand_rvalue(type); + else goto failure; + } break; + CASE_UNTYPED: { + expr.value = convert_untyped_to_typed(node->pos, expr.value, type); + } break; + CASE_UINT: + CASE_SINT:{ + if(is_int(type)) + expr.type = type; + else if(is_float(type)){ + expr.value.type = type; + if(expr.is_const) expr.value.f64_val = bigint_as_float(&expr.big_int_val); // @leak + } else goto failure; + } break; + case TYPE_F32: case TYPE_F64: { + if(is_float(type)){ + expr.type = type; + } + else if(is_int(type)){ + if(expr.is_const) expr.value.big_int_val = bigint_s64((S64)expr.value.f64_val); // @todo: What to do here??? + expr.type = type; + } else goto failure; + } break; + default: failure: compiler_error(node->pos, "Failed to cast from %s to %s", docname(expr.type), docname(type));; + } + + assert(original_type != type ? expr.type == type : 1); + if(expr.is_const) check_value_bounds(node->pos, &expr.value); + + node->after_type = expr.type; + return expr; +} + function Operand resolve_expr(Ast_Expr *ast, B32 flags){ - if(!ast && flags == AST_CAN_BE_NULL) return {}; + if(!ast && is_flag_set(flags, AST_CAN_BE_NULL)) return {}; assert(is_flag_set(ast->flags, AST_EXPR)); @@ -1063,9 +758,30 @@ resolve_expr(Ast_Expr *ast, B32 flags){ BREAK(); } - CASE(CALL, Call){ - unused(node); - // return {}; + // Typespec array [32]int + CASE(ARRAY, Array){ + // @todo: Arrays of inferred size [] + Operand type = resolve_expr(node->base, AST_CANT_BE_NULL); + Operand expr = require_const_int(node->expr, AST_CAN_BE_NULL); + if(type.type != type_type) compiler_error(node->pos, "Prefix array operator is only allowed on types"); + + node->type = type_array(type.type_val, node->expr ? 1 : 0, bigint_as_unsigned(&expr.big_int_val)); + return operand_type(node->type); + BREAK(); + } + + CASE(INDEX, Index){ + Operand left = resolve_expr(node->expr, AST_CANT_BE_NULL); + Operand index = resolve_expr(node->index, AST_CANT_BE_NULL); + if(!is_int(index.type)){ + compiler_error(node->pos, "Trying to index the array with invalid type, expected [Int] got instead %s", docname(index.type)); + } + if(!is_array(left.type) && !is_pointer(left.type)){ + compiler_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %s instead", docname(left.type)); + } + + node->original_type = left.type; + return operand_lvalue(left.type->arr.base); BREAK(); } @@ -1073,18 +789,21 @@ resolve_expr(Ast_Expr *ast, B32 flags){ Ast_Decl *decl = resolve_name(node->pos, node->intern_val); node->resolved_decl = decl; - if(decl->kind == AST_CONST){ + Operand result = operand(decl); + if(decl->kind != AST_VAR){ // @note // There might be some problem with types getting rewritten // I would like decls to be resolved to be of AST_TYPE ?? // // assert(decl->value.type != type_type); // assert(!is_lambda(decl->value.type)); - rewrite_into_const(node, Ast_Atom, decl->value); + if(decl->kind == AST_CONST){ + rewrite_into_const(node, Ast_Atom, decl->value); + } + result.is_const = 1; } - - return operand(decl); + return result; BREAK(); } @@ -1149,6 +868,77 @@ resolve_expr(Ast_Expr *ast, B32 flags){ BREAK(); } + CASE(CAST, Cast){ + return resolve_cast(node); + BREAK(); + } + + CASE(CALL, Call){ + Operand name = resolve_expr(node->name, AST_CANT_BE_NULL); + if(name.type->kind != TYPE_LAMBDA) + compiler_error(node->pos, "Calling %s which is not a [Lambda]", docname(name.type)); + + Scratch scratch; + Array items = {scratch}; + S64 was_name_indexed = false; + S64 default_iter = 0; + + Ast_Decl *decl = (Ast_Decl *)name.type->ast; + Ast_Lambda *lambda = decl->lambda; + for(S64 i = 0; i < lambda->args.len; i++){ + Ast_Decl *lambda_arg = lambda->args[i]; + assert(lambda_arg->type); + + Ast_Call_Item *item = 0; + For(node->exprs){ + if(it->index) compiler_error(it->index->pos, "Function call indexing is illegal"); + + if(it->name){ + Ast_Atom *name = it->name; + assert(name->kind == AST_IDENT); + was_name_indexed = true; + if(name->intern_val.str == lambda_arg->name.str) + item = it; + } + else if(node->exprs.get_index(&it) == default_iter){ + default_iter++; + item = it; + } + else if(node->exprs.get_index(&it) > default_iter){ + compiler_error(it->pos, "Positional argument after named argument"); + } + + if(item) break; + } + + if(item){ + set_flag(item->flags, AST_ITEM_INCLUDED); + Operand expr = resolve_expr(item->item, AST_CANT_BE_NULL); + make_sure_value_is_compatible_with_type(node->pos, &expr, lambda_arg->type, TYPE_AND_EXPR_REQUIRED); + items.add(item); + } + else{ + // default values are typechecked when they get resolved + if(lambda_arg->expr){ + Ast_Call_Item *item_default = ast_call_item(lambda_arg->expr->pos, 0, 0, lambda_arg->expr); + items.add(item_default); + } + else compiler_error(lambda_arg->pos, "Required value in lambda call was not passed"); + } + + } + + // @note: check if all arguments are included and cleanup + For(node->exprs){ + if(!is_flag_set(it->flags, AST_ITEM_INCLUDED)) + compiler_error(it->pos, "Invalid argument to function call"); + else unset_flag(it->flags, AST_ITEM_INCLUDED); + } + + return operand_rvalue(name.type); + BREAK(); + } + invalid_default_case; } @@ -1156,7 +946,7 @@ resolve_expr(Ast_Expr *ast, B32 flags){ } function void -resolve_decl(Ast_Decl *ast){ +resolve_decl(Ast_Decl *ast, B32 flags){ if(ast->state == DECL_RESOLVED){ return; } @@ -1208,21 +998,32 @@ resolve_decl(Ast_Decl *ast){ else if(is_flag_set(lambda->parent->flags, AST_FOREIGN)){ result = operand_lambda(lambda_type); } + + node->value = result.value; BREAK(); } CASE(CONST, Decl){ - resolve_const(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; BREAK(); } - CASE(VAR, Decl){ - resolve_var(node); + Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL | RESOLVE_TYPESPEC_COMPLETE); + Operand op = resolve_expr(node->expr, AST_CAN_BE_NULL); + assert(op.type != 0 || type != 0); + + make_sure_value_is_compatible_with_type(node->pos, &op, type, EXPR_CAN_BE_NULL|TYPE_CAN_BE_NULL); + node->value = op.value; BREAK(); } CASE(ENUM, Decl){ - node->type = type_enum(node); + node->type = type_type; + node->type_val = type_enum(node); Enter_Scope(node->scope); S64 value = 0; For(node->scope->decls){ @@ -1246,7 +1047,8 @@ resolve_decl(Ast_Decl *ast){ } ast->state = DECL_RESOLVED; - pctx->ordered_decls.add(ast); + if(!is_flag_set(flags, IS_NOT_PACKAGE_GLOBAL)) + pctx->ordered_decls.add(ast); } function Ast_Decl * @@ -1295,8 +1097,9 @@ parse_file(Ast_File *file){ if(!decl) break; if(decl->kind == AST_STRUCT){ - decl->type = type_incomplete(decl); - decl->state = DECL_RESOLVED; + decl->type = type_type; + decl->type_val = type_incomplete(decl); + decl->state = DECL_RESOLVED; } file->decls.add(decl); diff --git a/typechecking.h b/typechecking.h index bc81222..ac7abbc 100644 --- a/typechecking.h +++ b/typechecking.h @@ -5,9 +5,9 @@ struct Operand{ U8 is_lvalue: 1; }; -enum{AST_CANT_BE_NULL = 0, AST_CAN_BE_NULL = 1}; +enum{AST_CANT_BE_NULL = 0, AST_CAN_BE_NULL = 1, IS_NOT_PACKAGE_GLOBAL=2, RESOLVE_TYPESPEC_COMPLETE = bit_flag(3)}; function Operand resolve_expr(Ast_Expr *ast, B32 flags); -function void resolve_decl(Ast_Decl *ast); +function void resolve_decl(Ast_Decl *ast, B32 flags = 0); function Ast_Decl *resolve_name(Token *pos, Intern_String name); function Ast_Resolved_Type *resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null); #if 0