Closer to old state
This commit is contained in:
7
ast.cpp
7
ast.cpp
@@ -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;
|
||||||
|
|||||||
51
ccodegen.cpp
51
ccodegen.cpp
@@ -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:{
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
1
main.cpp
1
main.cpp
@@ -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();
|
||||||
|
|||||||
25
order2.kl
25
order2.kl
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
541
typechecking.cpp
541
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));
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user