Cleanup
This commit is contained in:
3
main.cpp
3
main.cpp
@@ -48,6 +48,7 @@ For now I don't thing it should be overloadable.
|
||||
[ ] - For loop
|
||||
[ ] - Switch
|
||||
[ ] - More basic types
|
||||
[ ] - Array of inferred size
|
||||
[ ] - Lexer: Need to insert scope endings when hitting End of file
|
||||
[ ] - Add single line lambda expressions
|
||||
|
||||
@@ -88,9 +89,9 @@ int main(){
|
||||
String result = {};
|
||||
result = compile_file("globals.kl"_s);
|
||||
result = compile_file("enums.kl"_s);
|
||||
result = compile_file("order2.kl"_s);
|
||||
result = compile_file("lambdas.kl"_s);
|
||||
result = compile_file("order1.kl"_s);
|
||||
result = compile_file("order2.kl"_s);
|
||||
printf("%s", result.str);
|
||||
|
||||
__debugbreak();
|
||||
|
||||
@@ -11,7 +11,7 @@ arena := Arena(
|
||||
cap = 1000,
|
||||
)
|
||||
|
||||
// lambda_value := (val: int) // What to do with this???
|
||||
// lambda_value := (val: int) // @todo
|
||||
// return
|
||||
|
||||
Arena :: struct
|
||||
@@ -21,13 +21,13 @@ Arena :: struct
|
||||
len : int
|
||||
cap : int
|
||||
|
||||
get_len :: (s: *Arena): int
|
||||
get_len :: (s: *Arena): int // @todo
|
||||
return s.next.len
|
||||
|
||||
|
||||
constant_inside :: 10000
|
||||
|
||||
|
||||
|
||||
string16: Str16
|
||||
|
||||
String16 :: struct
|
||||
|
||||
119
typechecking.cpp
119
typechecking.cpp
@@ -37,10 +37,6 @@ struct Operand{
|
||||
INLINE_VALUE_FIELDS;
|
||||
};
|
||||
|
||||
enum{
|
||||
AST_CANT_BE_NULL = 0,
|
||||
AST_CAN_BE_NULL = 1
|
||||
};
|
||||
|
||||
struct Typecheck_Ctx{ // @todo
|
||||
Ast_Resolved_Type *required_type;
|
||||
@@ -48,6 +44,7 @@ struct Typecheck_Ctx{ // @todo
|
||||
B32 expr_can_be_null;
|
||||
};
|
||||
|
||||
enum{AST_CANT_BE_NULL = 0, AST_CAN_BE_NULL = 1};
|
||||
function Ast_Resolved_Type *resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null = AST_CANT_BE_NULL);
|
||||
function Sym *resolve_name(Token *pos, Intern_String name);
|
||||
function Operand resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0, Sym *const_sym = 0);
|
||||
@@ -93,20 +90,26 @@ scope_close(S64 local_sym_count){
|
||||
pctx->local_syms.len = local_sym_count;
|
||||
}
|
||||
|
||||
function void
|
||||
sym_associate(Ast *ast, Sym *sym){
|
||||
assert(ast);
|
||||
assert(sym);
|
||||
map_insert(&pctx->resolved, ast, sym);
|
||||
}
|
||||
|
||||
function Sym *
|
||||
sym_new(Sym_Kind kind, Intern_String name, Ast *ast){
|
||||
sym_new(Sym_Kind kind, Intern_String name, Ast *ast, B32 associate = true){
|
||||
Sym *result = exp_alloc_type(pctx->perm, Sym, AF_ZeroMemory);
|
||||
result->name = name;
|
||||
result->kind = kind;
|
||||
result->ast = ast;
|
||||
assert(ast);
|
||||
map_insert(&pctx->resolved, ast, result);
|
||||
if(associate) sym_associate(ast, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function Sym *
|
||||
sym_new_resolved(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Value value, Ast *ast){
|
||||
Sym *result = sym_new(kind, name, ast);
|
||||
sym_new_resolved(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Value value, Ast *ast, B32 associate = true){
|
||||
Sym *result = sym_new(kind, name, ast, associate);
|
||||
result->type = type;
|
||||
result->state = SYM_RESOLVED;
|
||||
result->value = value;
|
||||
@@ -129,11 +132,24 @@ resolved_type_get(Ast_Expr *ast){
|
||||
return result->type_val;
|
||||
}
|
||||
|
||||
function Sym *
|
||||
sym_type(Ast *ast, Ast_Resolved_Type *type, Intern_String name = {}, B32 associate = true){
|
||||
Value value; value.type_val = type;
|
||||
Sym *result = sym_new_resolved(SYM_CONST, name, type_type, value, ast, associate);
|
||||
return result;
|
||||
}
|
||||
|
||||
function Sym *
|
||||
sym_insert(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Value value, Ast *ast){
|
||||
Sym *sym = sym_new_resolved(kind, name, type, value, ast);
|
||||
sym_insert(sym);
|
||||
return sym;
|
||||
}
|
||||
|
||||
function void
|
||||
sym_insert_builtin_type(String name, Ast_Resolved_Type *type){
|
||||
Intern_String string = intern_string(&pctx->interns, name);
|
||||
Value val; val.type_val = type;
|
||||
Sym *sym = sym_new_resolved(SYM_CONST, string, type_type, val, &empty_decl);
|
||||
Sym *sym = sym_type(&empty_decl, type, string, false);
|
||||
sym_insert(sym);
|
||||
}
|
||||
|
||||
@@ -147,21 +163,21 @@ sym_insert_builtins(){
|
||||
{
|
||||
Intern_String string = intern_string(&pctx->interns, "true"_s);
|
||||
Value val; val.int_val = 1;
|
||||
Sym *sym = sym_new_resolved(SYM_CONST, string, type_bool, val, &empty_decl);
|
||||
Sym *sym = sym_new_resolved(SYM_CONST, string, type_bool, val, &empty_decl, false);
|
||||
sym_insert(sym);
|
||||
}
|
||||
|
||||
{
|
||||
Intern_String string = intern_string(&pctx->interns, "false"_s);
|
||||
Value val; val.int_val = 0;
|
||||
Sym *sym = sym_new_resolved(SYM_CONST, string, type_bool, val, &empty_decl);
|
||||
Sym *sym = sym_new_resolved(SYM_CONST, string, type_bool, val, &empty_decl, false);
|
||||
sym_insert(sym);
|
||||
}
|
||||
|
||||
{
|
||||
Intern_String string = intern_string(&pctx->interns, "null"_s);
|
||||
Value val; val.int_val = 0;
|
||||
Sym *sym = sym_new_resolved(SYM_CONST, string, type_null, val, &empty_decl);
|
||||
Sym *sym = sym_new_resolved(SYM_CONST, string, type_null, val, &empty_decl, false);
|
||||
sym_insert(sym);
|
||||
}
|
||||
}
|
||||
@@ -194,13 +210,13 @@ resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){
|
||||
|
||||
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 = {};
|
||||
if(node->expr) op = resolve_expr(node->expr);
|
||||
Operand op = resolve_expr(node->expr);
|
||||
if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is [%s]", type_names[op.type->kind]);
|
||||
if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value");
|
||||
|
||||
BREAK();
|
||||
}
|
||||
|
||||
@@ -232,12 +248,10 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
||||
|
||||
CASE(IF, If){
|
||||
For(node->ifs){
|
||||
if(it->init) resolve_stmt(it->init, ret);
|
||||
if(it->expr) resolve_expr(it->expr);
|
||||
resolve_stmt(it->init, ret);
|
||||
resolve_expr(it->expr); // @todo: typechecking
|
||||
S64 scope_index = scope_open();
|
||||
For_It(it->block->stmts, jt){
|
||||
resolve_stmt(jt, ret);
|
||||
}
|
||||
For_It(it->block->stmts, jt) resolve_stmt(jt, ret);
|
||||
scope_close(scope_index);
|
||||
}
|
||||
BREAK();
|
||||
@@ -266,18 +280,14 @@ operand_type(Ast_Resolved_Type *type){
|
||||
function Operand
|
||||
require_const_int(Ast_Expr *expr, B32 ast_can_be_null){
|
||||
Operand op = resolve_expr(expr);
|
||||
if(expr == 0 && ast_can_be_null){
|
||||
return op;
|
||||
}
|
||||
if(expr == 0 && ast_can_be_null) return op;
|
||||
else if(expr == 0) parsing_error(expr->pos, "This field cannot be null");
|
||||
|
||||
if(!op.is_const) parsing_error(expr->pos, "Expected a const value");
|
||||
if(op.type != type_int) parsing_error(expr->pos, "Expected a constant integer");
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
#define rewrite_into_const(ast,T,sym) _rewrite_into_const(ast,sizeof(T),sym)
|
||||
function void
|
||||
_rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){
|
||||
auto ast = (Ast_Atom *)node;
|
||||
@@ -293,6 +303,7 @@ _rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){
|
||||
ast->int_val = sym->int_val;
|
||||
} else invalid_codepath;
|
||||
}
|
||||
#define rewrite_into_const(ast,T,sym) _rewrite_into_const(ast,sizeof(T),sym)
|
||||
|
||||
function Operand
|
||||
resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||
@@ -315,8 +326,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||
|
||||
CASE(IDENT, Atom){
|
||||
Sym *sym = resolve_name(node->pos, node->intern_val);
|
||||
// @note: check if null and rewrite the expression to match the expected type
|
||||
Operand result = {};
|
||||
// @note: check if null and rewrite the expression to match the expected type
|
||||
if(sym->type->kind == TYPE_NULL){
|
||||
if(!expected_type) parsing_error(node->pos, "Couldn't infer type of null");
|
||||
result.type = expected_type;
|
||||
@@ -328,7 +339,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||
}
|
||||
else if(sym->kind == SYM_VAR || sym->kind == SYM_CONST){
|
||||
result = operand(sym);
|
||||
sym_new_resolved(sym->kind, sym->name, sym->type, sym->value, node);
|
||||
sym_associate(node, sym);
|
||||
}
|
||||
else invalid_codepath;
|
||||
|
||||
@@ -339,12 +350,10 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||
CASE(ARRAY, Array){
|
||||
Operand type = resolve_expr(node->base);
|
||||
if(type.type != type_type) parsing_error(node->pos, "Prefix array operator is only allowed on types");
|
||||
Operand expr = resolve_expr(node->expr);
|
||||
if(!expr.is_const) parsing_error(node->pos, "Array operator requires a constant value");
|
||||
if(expr.type != type_int) parsing_error(node->pos, "Array index requires type [Int]");
|
||||
Operand expr = require_const_int(node->expr, AST_CANT_BE_NULL); // @todo:
|
||||
|
||||
type.type_val = type_array(type.type_val, expr.int_val);
|
||||
sym_new_resolved(SYM_CONST, {}, type_type, type.value, node);
|
||||
sym_type(node, type.type_val);
|
||||
return type;
|
||||
BREAK();
|
||||
}
|
||||
@@ -364,9 +373,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||
op.int_val = value++;
|
||||
}
|
||||
|
||||
|
||||
Sym *arg_sym = sym_new_resolved(SYM_CONST, it->name, op.type, op.value, it);
|
||||
sym_insert(arg_sym);
|
||||
sym_insert(SYM_CONST, it->name, op.type, op.value, it);
|
||||
}
|
||||
scope_close(scope_index);
|
||||
|
||||
@@ -390,9 +397,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||
lambda_type = type_lambda(node, ret_type, args);
|
||||
|
||||
{
|
||||
assert(lambda_type);
|
||||
Value val; val.type_val = lambda_type;
|
||||
sym_new_resolved(SYM_CONST, {}, type_type, val, node);
|
||||
sym_type(node, lambda_type);
|
||||
if(const_sym){
|
||||
const_sym->type = lambda_type;
|
||||
const_sym->state = SYM_RESOLVED;
|
||||
@@ -408,9 +413,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||
For(node->args){
|
||||
S64 i = node->args.get_index(&it);
|
||||
Ast_Resolved_Type *type = args[i];
|
||||
|
||||
Sym *arg_sym = sym_new_resolved(SYM_VAR, it->name, type, {}, it);
|
||||
sym_insert(arg_sym);
|
||||
sym_insert(SYM_VAR, it->name, type, {}, it);
|
||||
}
|
||||
For(node->block->stmts){
|
||||
resolve_stmt(it, ret_type);
|
||||
@@ -633,16 +636,13 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||
required_to_be_const = true;
|
||||
}
|
||||
// @copy_paste
|
||||
if(is_pointer(type)){
|
||||
type = type->base;
|
||||
}
|
||||
if(is_pointer(type)) type = type->base;
|
||||
type_complete(type);
|
||||
if(!(is_struct(type) || is_enum(type))){
|
||||
parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
|
||||
}
|
||||
if(!(is_struct(type) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
|
||||
sym_new_resolved(SYM_VAR, {}, resolved_ident.type, {}, node->left);
|
||||
|
||||
// This happens only on binary nodes which further chain with dots and require lookups
|
||||
// This part cant happen on enums
|
||||
// x.resolve.y
|
||||
Ast_Binary *binary = (Ast_Binary *)node->right;
|
||||
for(;!is_ident(binary); binary=(Ast_Binary *)binary->right){
|
||||
@@ -652,24 +652,20 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||
|
||||
Ast_Struct *agg = (Ast_Struct *)type->ast;
|
||||
Ast *query = query_struct(agg, ident->intern_val);
|
||||
// @copy_paste
|
||||
if(query){
|
||||
Sym *sym = resolved_get(query);
|
||||
if(required_to_be_const && sym->kind != SYM_CONST) parsing_error(ident->pos, "Required to be constant");
|
||||
type = sym->type;
|
||||
// @copy_paste
|
||||
if(type == type_type){
|
||||
required_to_be_const = true;
|
||||
type = sym->type_val;
|
||||
}
|
||||
if(is_pointer(type)){
|
||||
type = type->base;
|
||||
}
|
||||
if(is_pointer(type)) type = type->base;
|
||||
type_complete(type);
|
||||
if(!(is_struct(type) || is_enum(type))){
|
||||
parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
|
||||
}
|
||||
if(!(is_struct(type) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
|
||||
sym_associate(ident, sym);
|
||||
|
||||
sym_new_resolved(sym->kind, {}, sym->type, sym->value, ident);
|
||||
} else parsing_error(ident->pos, "No such member in struct");
|
||||
}
|
||||
|
||||
@@ -694,13 +690,8 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||
Sym *sym = resolved_get(query);
|
||||
result = operand(sym);
|
||||
assert(sym);
|
||||
// @warning rewriting nodes with constant values
|
||||
if(sym->kind == SYM_CONST){
|
||||
rewrite_into_const(node, Ast_Binary, sym);
|
||||
}
|
||||
else{
|
||||
sym_new_resolved(sym->kind, {}, sym->type, sym->value, ident);
|
||||
}
|
||||
if(sym->kind == SYM_CONST) rewrite_into_const(node, Ast_Binary, sym);
|
||||
else sym_associate(ident, sym);
|
||||
|
||||
} else parsing_error(ident->pos, "No such member in struct");
|
||||
}
|
||||
@@ -746,7 +737,7 @@ resolve_binding(Ast *ast, Sym *sym){
|
||||
switch(ast->kind){
|
||||
CASE(VAR, Var){
|
||||
Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL);
|
||||
Operand expr = node->expr ? resolve_expr(node->expr, type) : Operand{};
|
||||
Operand expr = resolve_expr(node->expr, type);
|
||||
expr.type = resolve_type_pair(node->pos, type, expr.type);
|
||||
type_complete(expr.type);
|
||||
return expr;
|
||||
|
||||
Reference in New Issue
Block a user