Closer to old state

This commit is contained in:
Krzosa Karol
2022-06-10 14:08:27 +02:00
parent d5d9911f3e
commit 89b3e00ae4
8 changed files with 219 additions and 422 deletions

View File

@@ -29,6 +29,7 @@ enum Ast_Kind: U32{
AST_BLOCK, AST_BLOCK,
AST_PASS, AST_PASS,
AST_LAMBDA, AST_LAMBDA,
AST_LAMBDA_EXPR,
AST_LAMBDA_ARG, AST_LAMBDA_ARG,
AST_ENUM, AST_ENUM,
AST_ENUM_MEMBER, AST_ENUM_MEMBER,
@@ -100,11 +101,14 @@ struct Ast_Unary: Ast_Expr{
struct Ast_Cast: Ast_Expr{ struct Ast_Cast: Ast_Expr{
Ast_Expr *expr; Ast_Expr *expr;
Ast_Expr *typespec; Ast_Expr *typespec;
Ast_Resolved_Type *before_type;
Ast_Resolved_Type *after_type;
}; };
struct Ast_Index: Ast_Expr{ struct Ast_Index: Ast_Expr{
Ast_Expr *expr; Ast_Expr *expr;
Ast_Expr *index; Ast_Expr *index;
Ast_Resolved_Type *original_type;
}; };
struct Ast_Binary: Ast_Expr{ struct Ast_Binary: Ast_Expr{
@@ -154,6 +158,7 @@ struct Ast_Lambda : Ast_Expr {
struct Ast_Array: Ast_Expr{ struct Ast_Array: Ast_Expr{
Ast_Expr *base; Ast_Expr *base;
Ast_Expr *expr; 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 * function Ast_Lambda *
ast_lambda(Token *pos, Array<Ast_Decl *> params, B32 has_var_args, Ast_Expr *ret, Ast_Scope *scope){ ast_lambda(Token *pos, Array<Ast_Decl *> 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->flags = AST_EXPR;
result->args = params.tight_copy(pctx->perm); result->args = params.tight_copy(pctx->perm);
result->scope = scope; result->scope = scope;

View File

@@ -164,15 +164,15 @@ gen_expr(Ast_Expr *ast){
BREAK(); BREAK();
} }
// CASE(CAST, Cast){ CASE(CAST, Cast){
// gen("("); gen("(");
// gen("("); gen("(");
// gen_simple_decl(resolved_type_get(node->typespec), {}); gen_simple_decl(node->after_type, {});
// gen(")"); gen(")");
// gen_expr(node->expr); gen_expr(node->expr);
// gen(")"); gen(")");
// BREAK(); BREAK();
// } }
CASE(VAR, Decl){ CASE(VAR, Decl){
gen_ast(node); gen_ast(node);
@@ -180,8 +180,13 @@ gen_expr(Ast_Expr *ast){
} }
CASE(CALL, Call){ 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(); BREAK();
} }
@@ -215,11 +220,7 @@ enum {
function void function void
gen_var(Intern_String name, Ast_Resolved_Type *type, Ast_Expr *expr, B32 emit_value){ 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){ if(emit_value == DONT_EMIT_VALUE){
return; return;
@@ -228,11 +229,6 @@ gen_var(Intern_String name, Ast_Resolved_Type *type, Ast_Expr *expr, B32 emit_va
if(expr){ if(expr){
gen(" = "); gen(" = ");
gen_expr(expr); gen_expr(expr);
} else if(is_array(type)){
gen(" = (Slice){%d, (", type->arr.size);
gen_simple_decl(type, {});
gen("){}");
gen("}");
} else { // Default zero } else { // Default zero
if(is_numeric(type)){ if(is_numeric(type)){
gen(" = 0"); gen(" = 0");
@@ -337,6 +333,21 @@ gen_ast(Ast *ast){
BREAK(); 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){ CASE(CONST, Decl){
switch(node->type->kind){ switch(node->type->kind){
CASE_FLOAT:{ CASE_FLOAT:{

View File

@@ -28,7 +28,7 @@ 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)

View File

@@ -221,6 +221,7 @@ int main(int argument_count, char **arguments){
Array<String> files = {scratch}; Array<String> files = {scratch};
files.add("lambdas.kl"_s); files.add("lambdas.kl"_s);
files.add("order1.kl"_s); files.add("order1.kl"_s);
files.add("order2.kl"_s);
String result = compile_files(files); String result = compile_files(files);
printf("%s", result.str); printf("%s", result.str);
__debugbreak(); __debugbreak();

View File

@@ -1,37 +1,14 @@
Str16 :: String16 Str16 :: String16
// arena_pointer: *Arena = null arena_pointer: *Arena = 0
thing: Arena thing: Arena
no_type := thing 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 :: struct
// arena: Arena
next: *Arena next: *Arena
data: *S64 data: *S64
len : S64 len : S64
cap : 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: Str16
String16 :: struct String16 :: struct

View File

@@ -581,7 +581,7 @@ parse_decl(B32 is_global){
Ast_Expr *expr = parse_expr(); Ast_Expr *expr = parse_expr();
result = ast_const(tname, tname->intern_val, 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; auto a = (Ast_Lambda *)expr;
if(a->scope){ if(a->scope){
result->kind = AST_LAMBDA; result->kind = AST_LAMBDA;

View File

@@ -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)); 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); check_value_bounds(pos, &expr->value);
assert(expr->type); assert(expr->type);
} }
@@ -306,7 +305,7 @@ function void
_rewrite_into_const(Ast *node, U64 ast_size, Value value){ _rewrite_into_const(Ast *node, U64 ast_size, Value value){
auto ast = (Ast_Atom *)node; auto ast = (Ast_Atom *)node;
assert(ast_size >= sizeof(Ast_Atom)); 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->kind = AST_VALUE;
ast->value = 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<Ast_Resolved_Type *> 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 function Operand
resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_resolve){ 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)); assert(is_flag_set(ast->flags, AST_EXPR));
switch(ast->kind){ 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<Ast_Call_Item *> 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){ CASE(UNARY, Unary){
Operand value = resolve_expr(node->expr); Operand value = resolve_expr(node->expr);
@@ -912,10 +585,12 @@ insert_builtin_types_into_package(Ast_Package *p){
function Ast_Resolved_Type * function Ast_Resolved_Type *
resolve_typespec(Ast_Expr *ast, B32 flags){ 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; return 0;
Operand resolved = resolve_expr(ast, flags); Operand resolved = resolve_expr(ast, flags);
if(is_flag_set(flags, RESOLVE_TYPESPEC_COMPLETE))
type_complete(resolved.type);
if(resolved.type != type_type) if(resolved.type != type_type)
compiler_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]); compiler_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]);
return resolved.type_val; return resolved.type_val;
@@ -954,25 +629,6 @@ 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
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 // @note: Ret is return value of function passed down the stack
// to check if type matches // to check if type matches
function void function void
@@ -988,16 +644,10 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
BREAK(); BREAK();
} }
// CASE(VAR, Decl){
// resolve_decl(node);
// insert_into_current_scope(node);
// BREAK();
// }
case AST_LAMBDA: case AST_LAMBDA:
case AST_VAR: case AST_VAR:
CASE(CONST, Decl){ CASE(CONST, Decl){
resolve_decl(node); resolve_decl(node, IS_NOT_PACKAGE_GLOBAL);
insert_into_current_scope(node); insert_into_current_scope(node);
BREAK(); 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 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 && is_flag_set(flags, AST_CAN_BE_NULL)) return {};
assert(is_flag_set(ast->flags, AST_EXPR)); assert(is_flag_set(ast->flags, AST_EXPR));
@@ -1063,9 +758,30 @@ resolve_expr(Ast_Expr *ast, B32 flags){
BREAK(); BREAK();
} }
CASE(CALL, Call){ // Typespec array [32]int
unused(node); CASE(ARRAY, Array){
// return {}; // @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(); BREAK();
} }
@@ -1073,18 +789,21 @@ resolve_expr(Ast_Expr *ast, B32 flags){
Ast_Decl *decl = resolve_name(node->pos, node->intern_val); Ast_Decl *decl = resolve_name(node->pos, node->intern_val);
node->resolved_decl = decl; node->resolved_decl = decl;
if(decl->kind == AST_CONST){ Operand result = operand(decl);
if(decl->kind != AST_VAR){
// @note // @note
// There might be some problem with types getting rewritten // There might be some problem with types getting rewritten
// I would like decls to be resolved to be of AST_TYPE ?? // I would like decls to be resolved to be of AST_TYPE ??
// //
// assert(decl->value.type != type_type); // assert(decl->value.type != type_type);
// assert(!is_lambda(decl->value.type)); // assert(!is_lambda(decl->value.type));
if(decl->kind == AST_CONST){
rewrite_into_const(node, Ast_Atom, decl->value); rewrite_into_const(node, Ast_Atom, decl->value);
} }
result.is_const = 1;
}
return result;
return operand(decl);
BREAK(); BREAK();
} }
@@ -1149,6 +868,77 @@ resolve_expr(Ast_Expr *ast, B32 flags){
BREAK(); 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<Ast_Call_Item *> 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; invalid_default_case;
} }
@@ -1156,7 +946,7 @@ resolve_expr(Ast_Expr *ast, B32 flags){
} }
function void function void
resolve_decl(Ast_Decl *ast){ resolve_decl(Ast_Decl *ast, B32 flags){
if(ast->state == DECL_RESOLVED){ if(ast->state == DECL_RESOLVED){
return; return;
} }
@@ -1208,21 +998,32 @@ resolve_decl(Ast_Decl *ast){
else if(is_flag_set(lambda->parent->flags, AST_FOREIGN)){ else if(is_flag_set(lambda->parent->flags, AST_FOREIGN)){
result = operand_lambda(lambda_type); result = operand_lambda(lambda_type);
} }
node->value = result.value;
BREAK(); BREAK();
} }
CASE(CONST, Decl){ 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(); BREAK();
} }
CASE(VAR, Decl){ 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(); BREAK();
} }
CASE(ENUM, Decl){ CASE(ENUM, Decl){
node->type = type_enum(node); node->type = type_type;
node->type_val = type_enum(node);
Enter_Scope(node->scope); Enter_Scope(node->scope);
S64 value = 0; S64 value = 0;
For(node->scope->decls){ For(node->scope->decls){
@@ -1246,6 +1047,7 @@ resolve_decl(Ast_Decl *ast){
} }
ast->state = DECL_RESOLVED; ast->state = DECL_RESOLVED;
if(!is_flag_set(flags, IS_NOT_PACKAGE_GLOBAL))
pctx->ordered_decls.add(ast); pctx->ordered_decls.add(ast);
} }
@@ -1295,7 +1097,8 @@ parse_file(Ast_File *file){
if(!decl) break; if(!decl) break;
if(decl->kind == AST_STRUCT){ if(decl->kind == AST_STRUCT){
decl->type = type_incomplete(decl); decl->type = type_type;
decl->type_val = type_incomplete(decl);
decl->state = DECL_RESOLVED; decl->state = DECL_RESOLVED;
} }

View File

@@ -5,9 +5,9 @@ struct Operand{
U8 is_lvalue: 1; 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 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_Decl *resolve_name(Token *pos, Intern_String name);
function Ast_Resolved_Type *resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null); function Ast_Resolved_Type *resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null);
#if 0 #if 0