Basic resolving, codegen with packages
This commit is contained in:
92
ast.cpp
92
ast.cpp
@@ -17,6 +17,7 @@ enum Ast_Kind: U32{
|
||||
AST_CALL_ITEM,
|
||||
AST_CALL,
|
||||
|
||||
AST_TYPE,
|
||||
AST_VAR,
|
||||
AST_CONST,
|
||||
AST_POINTER,
|
||||
@@ -73,6 +74,7 @@ struct Value{VALUE_FIELDS};
|
||||
// BigInt big_int_val;
|
||||
|
||||
struct Ast_Atom: Ast_Expr{
|
||||
Ast_Decl *resolved_decl;
|
||||
INLINE_VALUE_FIELDS;
|
||||
};
|
||||
|
||||
@@ -91,7 +93,8 @@ struct Ast_Call: Ast_Expr{
|
||||
struct Ast_Unary: Ast_Expr{
|
||||
Token_Kind op;
|
||||
Ast_Expr *expr;
|
||||
U64 padding[3]; // For folding constants into atoms
|
||||
Ast_Resolved_Type *type;
|
||||
U64 padding[2]; // For folding constants into atoms
|
||||
};
|
||||
|
||||
struct Ast_Cast: Ast_Expr{
|
||||
@@ -116,19 +119,13 @@ struct Ast_Binary: Ast_Expr{
|
||||
// look into global scope and to the locals list.
|
||||
//
|
||||
|
||||
struct Ast_Block : Ast {
|
||||
// Stmts for global scope
|
||||
Array<Ast *> stmts;
|
||||
// Array<Ast_Named *> members;
|
||||
};
|
||||
|
||||
struct Ast_Return: Ast{
|
||||
Ast_Expr *expr;
|
||||
};
|
||||
|
||||
struct Ast_If_Node: Ast{
|
||||
Ast_Expr *expr ;
|
||||
Ast_Block *block;
|
||||
Ast_Scope *scope;
|
||||
Ast_Binary*init;
|
||||
};
|
||||
|
||||
@@ -142,19 +139,13 @@ struct Ast_For: Ast{
|
||||
Ast_Expr *init;
|
||||
Ast_Expr *cond;
|
||||
Ast_Expr *iter;
|
||||
Ast_Block *block;
|
||||
};
|
||||
|
||||
struct Ast_Lambda_Arg: Ast_Expr{
|
||||
Intern_String name;
|
||||
Ast_Expr *typespec;
|
||||
Ast_Expr *default_value;
|
||||
Ast_Scope *scope;
|
||||
};
|
||||
|
||||
struct Ast_Lambda : Ast_Expr {
|
||||
Array<Ast_Lambda_Arg *> args;
|
||||
Array<Ast_Decl *> args;
|
||||
Ast_Expr *ret;
|
||||
Ast_Block *block;
|
||||
Ast_Scope *scope;
|
||||
B32 has_var_args;
|
||||
};
|
||||
|
||||
@@ -190,7 +181,6 @@ enum Ast_Decl_State{
|
||||
|
||||
struct Ast_Decl;
|
||||
struct Ast_Scope: Ast{
|
||||
Array<Ast_Decl *> resolved;
|
||||
Array<Ast_Decl *> decls;
|
||||
Array<Ast *> stmts;
|
||||
};
|
||||
@@ -201,8 +191,11 @@ struct Ast_Decl: Ast{
|
||||
Intern_String name;
|
||||
|
||||
Ast_Scope *scope;
|
||||
Ast_Expr *expr;
|
||||
Ast_Expr *typespec;
|
||||
union{
|
||||
Ast_Expr *expr;
|
||||
Ast_Lambda *lambda;
|
||||
};
|
||||
|
||||
INLINE_VALUE_FIELDS;
|
||||
};
|
||||
@@ -339,41 +332,21 @@ ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){
|
||||
}
|
||||
|
||||
function Ast_Lambda *
|
||||
ast_lambda(Token *pos, Array<Ast_Lambda_Arg *> params, B32 has_var_args, Ast_Expr *ret, Ast_Block *block){
|
||||
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);
|
||||
result->flags = AST_EXPR;
|
||||
result->args = params.tight_copy(pctx->perm);
|
||||
result->block = block;
|
||||
result->scope = scope;
|
||||
result->ret = ret;
|
||||
result->has_var_args = has_var_args;
|
||||
if(!ret) result->ret = ast_ident(result->pos, intern_void);
|
||||
|
||||
if(result->block) result->block->parent = result;
|
||||
if(result->scope) result->scope->parent = result;
|
||||
result->ret->parent = result;
|
||||
For(result->args) it->parent = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Lambda_Arg *
|
||||
ast_expr_lambda_arg(Token *pos, Intern_String name, Ast_Expr *typespec, Ast_Expr *default_value){
|
||||
AST_NEW(Lambda_Arg, LAMBDA_ARG, pos, AST_EXPR);
|
||||
result->flags = AST_EXPR;
|
||||
result->name = name;
|
||||
result->typespec = typespec;
|
||||
result->default_value = default_value;
|
||||
result->typespec->parent = result;
|
||||
if(result->default_value) result->default_value->parent = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Block *
|
||||
ast_block(Token *pos, Array<Ast *> stmts){
|
||||
AST_NEW(Block, BLOCK, pos, AST_STMT);
|
||||
result->stmts = stmts.tight_copy(pctx->perm);
|
||||
For(result->stmts) it->parent = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_If *
|
||||
ast_if(Token *pos, Array<Ast_If_Node *> ifs){
|
||||
AST_NEW(If, IF, pos, AST_STMT);
|
||||
@@ -383,16 +356,16 @@ ast_if(Token *pos, Array<Ast_If_Node *> ifs){
|
||||
}
|
||||
|
||||
function Ast_For *
|
||||
ast_for(Token *pos, Ast_Expr *init, Ast_Expr *cond, Ast_Expr *iter, Ast_Block *block){
|
||||
ast_for(Token *pos, Ast_Expr *init, Ast_Expr *cond, Ast_Expr *iter, Ast_Scope *scope){
|
||||
AST_NEW(For, FOR, pos, AST_STMT);
|
||||
result->init = init;
|
||||
result->cond = cond;
|
||||
result->iter = iter;
|
||||
result->block = block;
|
||||
result->scope = scope;
|
||||
if(result->init) result->init->parent = result;
|
||||
if(result->cond) result->cond->parent = result;
|
||||
if(result->iter) result->iter->parent = result;
|
||||
result->block->parent = result;
|
||||
result->scope->parent = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -414,15 +387,15 @@ ast_return(Token *pos, Ast_Expr *expr){
|
||||
}
|
||||
|
||||
function Ast_If_Node *
|
||||
ast_if_node(Token *pos, Ast_Expr *init, Ast_Expr *expr, Ast_Block *block){
|
||||
ast_if_node(Token *pos, Ast_Expr *init, Ast_Expr *expr, Ast_Scope *scope){
|
||||
AST_NEW(If_Node, IF_NODE, pos, AST_STMT);
|
||||
result->block = block;
|
||||
result->scope = scope;
|
||||
result->expr = expr;
|
||||
result->init = (Ast_Binary *)init;
|
||||
if(result->block) result->block->parent = result;
|
||||
if(result->scope) result->scope->parent = result;
|
||||
if(result->expr) result->expr->parent = result;
|
||||
if(result->init) {
|
||||
assert(init->kind == AST_BINARY);
|
||||
assert(init->kind == AST_VAR);
|
||||
result->init->parent = result;
|
||||
}
|
||||
return result;
|
||||
@@ -440,7 +413,6 @@ function Ast_Scope *
|
||||
ast_decl_scope(Token *pos, Array<Ast_Decl *> decls){
|
||||
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
||||
result->decls = decls.tight_copy(pctx->perm);
|
||||
result->resolved = array_make<Ast_Decl *>(pctx->perm, result->decls.len);
|
||||
For(result->decls){
|
||||
it->parent = result;
|
||||
}
|
||||
@@ -451,6 +423,7 @@ function Ast_Scope *
|
||||
ast_stmt_scope(Token *pos, Array<Ast *> stmts){
|
||||
AST_NEW(Scope, SCOPE, pos, AST_STMT);
|
||||
result->stmts = stmts.tight_copy(pctx->perm);
|
||||
result->decls = {pctx->heap};
|
||||
For(result->stmts){
|
||||
it->parent = result;
|
||||
}
|
||||
@@ -486,6 +459,14 @@ ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr){
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Decl *
|
||||
ast_const(Token *pos, Intern_String name, Value value){
|
||||
AST_NEW(Decl, CONST, pos, AST_DECL);
|
||||
result->value = value;
|
||||
result->name = name;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Decl *
|
||||
ast_const(Token *pos, Intern_String name, Ast_Expr *expr){
|
||||
AST_NEW(Decl, CONST, pos, AST_DECL);
|
||||
@@ -495,13 +476,22 @@ ast_const(Token *pos, Intern_String name, Ast_Expr *expr){
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Decl *
|
||||
ast_type(Token *pos, Intern_String name, Ast_Resolved_Type *type){
|
||||
AST_NEW(Decl, CONST, pos, AST_DECL);
|
||||
result->type = type_type;
|
||||
result->type_val = type;
|
||||
result->name = name;
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Package
|
||||
ast_package(Allocator *allocator, Intern_String name, Array<Ast_Decl *> decls){
|
||||
Ast_Package result = {};
|
||||
result.kind = AST_PACKAGE;
|
||||
result.decls = decls.copy(allocator);
|
||||
result.resolved = {allocator};
|
||||
result.name = name;
|
||||
For(result.decls) it->parent = &result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
359
ccodegen.cpp
359
ccodegen.cpp
@@ -26,7 +26,7 @@ gen_simple_decl_prefix(Ast_Resolved_Type *ast){
|
||||
case TYPE_LAMBDA:break;
|
||||
case TYPE_ENUM:
|
||||
case TYPE_STRUCT: {
|
||||
auto constant = (Ast_Const *)ast->ast->parent;
|
||||
auto constant = (Ast_Decl *)ast->ast;
|
||||
auto name = constant->name;
|
||||
gen("%s ", name.str);
|
||||
}break;
|
||||
@@ -98,60 +98,58 @@ gen_expr(Ast_Expr *ast){
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(INDEX, Index){
|
||||
Sym *sym = resolved_get(node);
|
||||
if(is_array(sym->type)){
|
||||
gen("(");
|
||||
gen("(");
|
||||
// CASE(INDEX, Index){
|
||||
// Sym *sym = resolved_get(node);
|
||||
// if(is_array(sym->type)){
|
||||
// gen("(");
|
||||
// gen("(");
|
||||
|
||||
gen("(");
|
||||
gen_simple_decl(sym->type->arr.base, {});
|
||||
gen("*)");
|
||||
gen_expr(node->expr);
|
||||
gen(".data)");
|
||||
// gen("(");
|
||||
// gen_simple_decl(sym->type->arr.base, {});
|
||||
// gen("*)");
|
||||
// gen_expr(node->expr);
|
||||
// gen(".data)");
|
||||
|
||||
|
||||
gen("[");
|
||||
gen_expr(node->index);
|
||||
gen("]");
|
||||
gen(")");
|
||||
} else{
|
||||
gen("(");
|
||||
gen_expr(node->expr);
|
||||
gen("[");
|
||||
gen_expr(node->index);
|
||||
gen("]");
|
||||
gen(")");
|
||||
}
|
||||
BREAK();
|
||||
}
|
||||
// gen("[");
|
||||
// gen_expr(node->index);
|
||||
// gen("]");
|
||||
// gen(")");
|
||||
// } else{
|
||||
// gen("(");
|
||||
// gen_expr(node->expr);
|
||||
// gen("[");
|
||||
// gen_expr(node->index);
|
||||
// gen("]");
|
||||
// gen(")");
|
||||
// }
|
||||
// BREAK();
|
||||
// }
|
||||
|
||||
CASE(BINARY, Binary){
|
||||
if(node->op == TK_Dot){
|
||||
Sym *sym = resolved_get(node->left);
|
||||
gen_expr(node->left);
|
||||
if(sym->type->kind == TYPE_POINTER) gen("->");
|
||||
else gen(".");
|
||||
gen_expr(node->right);
|
||||
}
|
||||
else if(node->op == TK_ColonAssign){
|
||||
// if(node->op == TK_Dot){
|
||||
// Sym *sym = resolved_get(node->left);
|
||||
// gen_expr(node->left);
|
||||
// if(sym->type->kind == TYPE_POINTER) gen("->");
|
||||
// else gen(".");
|
||||
// gen_expr(node->right);
|
||||
// }
|
||||
// else if(node->op == TK_ColonAssign){
|
||||
|
||||
Sym *sym = resolved_get(node);
|
||||
Ast_Atom *atom = (Ast_Atom *)node->left;
|
||||
assert(is_atom(atom));
|
||||
gen_simple_decl(sym->type, atom->intern_val);
|
||||
if(node->right){
|
||||
gen(" = ");
|
||||
gen_expr(node->right);
|
||||
}
|
||||
}
|
||||
else{
|
||||
// Sym *sym = resolved_get(node);
|
||||
// Ast_Atom *atom = (Ast_Atom *)node->left;
|
||||
// assert(is_atom(atom));
|
||||
// gen_simple_decl(sym->type, atom->intern_val);
|
||||
// if(node->right){
|
||||
// gen(" = ");
|
||||
// gen_expr(node->right);
|
||||
// }
|
||||
// }
|
||||
if(!token_is_assign(node->op)) gen("(");
|
||||
gen_expr(node->left);
|
||||
gen("%s", name(node->op));
|
||||
gen_expr(node->right);
|
||||
if(!token_is_assign(node->op)) gen(")");
|
||||
}
|
||||
BREAK();
|
||||
}
|
||||
|
||||
@@ -164,15 +162,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(resolved_type_get(node->typespec), {});
|
||||
// gen(")");
|
||||
// gen_expr(node->expr);
|
||||
// gen(")");
|
||||
// BREAK();
|
||||
// }
|
||||
|
||||
CASE(CALL, Call){
|
||||
// @todo: Reach into map instead of direct lookup
|
||||
@@ -242,10 +240,10 @@ gen_line(Ast *node){
|
||||
function void
|
||||
gen_ast(Ast *ast);
|
||||
function void
|
||||
gen_block(Ast_Block *block){
|
||||
gen_stmt_scope(Ast_Scope *scope){
|
||||
gen("{");
|
||||
global_indent++;
|
||||
For(block->stmts) {
|
||||
For(scope->stmts) {
|
||||
gen_line(it);
|
||||
genln("");
|
||||
gen_ast(it);
|
||||
@@ -292,17 +290,6 @@ function void
|
||||
gen_ast(Ast *ast){
|
||||
switch(ast->kind){
|
||||
|
||||
CASE(PACKAGE, Package){
|
||||
if(emit_line_directives)
|
||||
genln("#line 0 \"%s\"", node->name.str);
|
||||
For(node->ordered) {
|
||||
gen_line(it);
|
||||
genln("");
|
||||
gen_ast(it);
|
||||
}
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(RETURN, Return){
|
||||
gen("return");
|
||||
if(node->expr){
|
||||
@@ -313,9 +300,8 @@ gen_ast(Ast *ast){
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(VAR, Var){
|
||||
Sym *sym = resolved_get(node);
|
||||
gen_var(sym->name, sym->type, node->expr, is_inside_struct ? DONT_EMIT_VALUE : ALWAYS_EMIT_VALUE);
|
||||
CASE(VAR, Decl){
|
||||
gen_var(node->name, node->type, node->expr, is_inside_struct ? DONT_EMIT_VALUE : ALWAYS_EMIT_VALUE);
|
||||
gen(";");
|
||||
BREAK();
|
||||
}
|
||||
@@ -327,7 +313,7 @@ gen_ast(Ast *ast){
|
||||
gen("if(");
|
||||
gen_expr(it->expr);
|
||||
gen(")");
|
||||
gen_block(it->block);
|
||||
gen_stmt_scope(it->scope);
|
||||
}
|
||||
else{
|
||||
genln("else");
|
||||
@@ -336,7 +322,7 @@ gen_ast(Ast *ast){
|
||||
gen_expr(it->expr);
|
||||
gen(")");
|
||||
}
|
||||
gen_block(it->block);
|
||||
gen_stmt_scope(it->scope);
|
||||
}
|
||||
}
|
||||
BREAK();
|
||||
@@ -362,113 +348,116 @@ gen_ast(Ast *ast){
|
||||
gen(";");
|
||||
if(node->iter) gen_expr(node->iter);
|
||||
gen(")");
|
||||
gen_block(node->block);
|
||||
gen_stmt_scope(node->scope);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(CONST, Const){
|
||||
Sym *sym = resolved_get(node);
|
||||
|
||||
switch(sym->type->kind){
|
||||
CASE_FLOAT:{
|
||||
gen("// F64 %s = ", node->name.str);
|
||||
gen_value(sym->value);
|
||||
} break;
|
||||
CASE_INT:{
|
||||
gen("// constant int %s = ", node->name.str);
|
||||
gen_value(sym->value);
|
||||
}break;
|
||||
CASE_STRING:{
|
||||
gen("// const String %s = ", node->name.str);
|
||||
gen_value(sym->value);
|
||||
}break;
|
||||
CASE_BOOL:{
|
||||
gen("// const Bool %s = ", node->name.str);
|
||||
gen_value(sym->value);
|
||||
}break;
|
||||
|
||||
case TYPE_LAMBDA:{
|
||||
if(node->value->kind == AST_LAMBDA){
|
||||
CASE(LAMBDA, Decl){
|
||||
if(node->kind == AST_LAMBDA){
|
||||
if(is_flag_set(node->flags, AST_FOREIGN)){
|
||||
return;
|
||||
}
|
||||
Ast_Lambda *lambda = (Ast_Lambda *)node->value;
|
||||
Ast_Resolved_Type *ret = resolved_type_get(lambda->ret);
|
||||
Ast_Lambda *lambda = node->lambda;
|
||||
Ast_Resolved_Type *ret = node->type->func.ret;
|
||||
gen_simple_decl(ret, node->name);
|
||||
gen("(");
|
||||
For(lambda->args){
|
||||
assert(it->kind == AST_LAMBDA_ARG);
|
||||
Ast_Resolved_Type *type = resolved_type_get(it->typespec);
|
||||
gen_var(it->name, type, 0, DONT_EMIT_VALUE);
|
||||
gen_var(it->name, it->type, 0, DONT_EMIT_VALUE);
|
||||
if(&it != (lambda->args.end() - 1)) gen(", ");
|
||||
}
|
||||
gen(")");
|
||||
|
||||
if(lambda->block) {
|
||||
gen_block(lambda->block);
|
||||
if(lambda->scope) {
|
||||
// gen_stmt_scope(lambda->scope);
|
||||
// @todo stmts
|
||||
}
|
||||
else gen(";");
|
||||
}
|
||||
else{
|
||||
gen_simple_decl(sym->type, node->name);
|
||||
gen_simple_decl(node->type, node->name);
|
||||
gen(" = ");
|
||||
gen_expr((Ast_Expr *)node->value);
|
||||
gen_expr((Ast_Expr *)node->expr);
|
||||
gen(";");
|
||||
}
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(CONST, Decl){
|
||||
switch(node->type->kind){
|
||||
CASE_FLOAT:{
|
||||
gen("// F64 %s = ", node->name.str);
|
||||
gen_value(node->value);
|
||||
} break;
|
||||
CASE_INT:{
|
||||
gen("// constant int %s = ", node->name.str);
|
||||
gen_value(node->value);
|
||||
}break;
|
||||
CASE_STRING:{
|
||||
gen("// const String %s = ", node->name.str);
|
||||
gen_value(node->value);
|
||||
}break;
|
||||
CASE_BOOL:{
|
||||
gen("// const Bool %s = ", node->name.str);
|
||||
gen_value(node->value);
|
||||
}break;
|
||||
|
||||
case TYPE_LAMBDA:{
|
||||
|
||||
}break;
|
||||
|
||||
case TYPE_TYPE:{
|
||||
if(sym->type_val->kind == TYPE_STRUCT){
|
||||
Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast;
|
||||
if(node->value->kind == AST_STRUCT){
|
||||
gen("typedef struct %s{", node->name.str);
|
||||
global_indent++;
|
||||
is_inside_struct++;
|
||||
For(agg->members){
|
||||
genln("");
|
||||
gen_ast(it);
|
||||
}
|
||||
|
||||
For(agg->const_members){
|
||||
genln("");
|
||||
gen_ast(it);
|
||||
}
|
||||
is_inside_struct--;
|
||||
global_indent--;
|
||||
genln("}%s;", node->name.str);
|
||||
}
|
||||
else{
|
||||
// Type alias
|
||||
}
|
||||
}
|
||||
else if(sym->type_val->kind == TYPE_ENUM){
|
||||
Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast;
|
||||
assert(enu->kind == AST_ENUM);
|
||||
if(node->value->kind == AST_ENUM){
|
||||
gen("/*enum %s{", node->name.str);
|
||||
// @todo add typespec
|
||||
global_indent++;
|
||||
For(enu->members){
|
||||
genln("%s", it->name.str);
|
||||
gen(" = ");
|
||||
Sym *value_sym = resolved_get(it);
|
||||
gen("%d", bigint_as_signed(&value_sym->big_int_val));
|
||||
gen(",");
|
||||
}
|
||||
global_indent--;
|
||||
genln("};*/");
|
||||
}
|
||||
else{
|
||||
// Type alias
|
||||
}
|
||||
}
|
||||
else{
|
||||
gen("// typedef ");
|
||||
gen_simple_decl(sym->type_val, node->name);
|
||||
gen(";");
|
||||
}
|
||||
}break;
|
||||
default: compiler_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(sym->type));
|
||||
// if(sym->type_val->kind == TYPE_STRUCT){
|
||||
// Ast_Struct *agg = (Ast_Struct *)sym->type_val->ast;
|
||||
// if(node->value->kind == AST_STRUCT){
|
||||
// gen("typedef struct %s{", node->name.str);
|
||||
// global_indent++;
|
||||
// is_inside_struct++;
|
||||
// For(agg->members){
|
||||
// genln("");
|
||||
// gen_ast(it);
|
||||
// }
|
||||
|
||||
// For(agg->const_members){
|
||||
// genln("");
|
||||
// gen_ast(it);
|
||||
// }
|
||||
// is_inside_struct--;
|
||||
// global_indent--;
|
||||
// genln("}%s;", node->name.str);
|
||||
// }
|
||||
// else{
|
||||
// // Type alias
|
||||
// }
|
||||
// }
|
||||
// else if(sym->type_val->kind == TYPE_ENUM){
|
||||
// Ast_Enum *enu = (Ast_Enum *)sym->type_val->ast;
|
||||
// assert(enu->kind == AST_ENUM);
|
||||
// if(node->value->kind == AST_ENUM){
|
||||
// gen("/*enum %s{", node->name.str);
|
||||
// // @todo add typespec
|
||||
// global_indent++;
|
||||
// For(enu->members){
|
||||
// genln("%s", it->name.str);
|
||||
// gen(" = ");
|
||||
// Sym *value_sym = resolved_get(it);
|
||||
// gen("%d", bigint_as_signed(&value_sym->big_int_val));
|
||||
// gen(",");
|
||||
// }
|
||||
// global_indent--;
|
||||
// genln("};*/");
|
||||
// }
|
||||
// else{
|
||||
// // Type alias
|
||||
// }
|
||||
// }
|
||||
// else{
|
||||
// gen("// typedef ");
|
||||
// gen_simple_decl(sym->type_val, node->name);
|
||||
// gen(";");
|
||||
// }
|
||||
// }break;
|
||||
default: compiler_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(node->type));
|
||||
}
|
||||
|
||||
BREAK();
|
||||
@@ -482,6 +471,7 @@ gen_ast(Ast *ast){
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
function String
|
||||
compile_string(String filecontent, String filename = "default_name"_s){
|
||||
F64 total_time = os_time();
|
||||
@@ -574,3 +564,64 @@ compile_file(String filename){
|
||||
String result = compile_string(filecontent, filename);
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
function String
|
||||
compile_files(Array<String> filename){
|
||||
Scratch scratch(thread_ctx.scratch);
|
||||
Array<Ast_File> files = {scratch};
|
||||
|
||||
For(filename){
|
||||
String filecontent = os_read_file(scratch, it);
|
||||
assert(filecontent.len);
|
||||
files.add(ast_file(it, filecontent));
|
||||
}
|
||||
|
||||
F64 total_time = os_time();
|
||||
OS_Heap heap = win32_os_heap_create(false, mib(16), 0);
|
||||
|
||||
Parse_Ctx ctx = {};
|
||||
parse_init(&ctx, scratch, &heap);
|
||||
|
||||
F64 parse_begin = os_time();
|
||||
Array<Ast_Package> packages = {&heap};
|
||||
For(files){
|
||||
parse_file(&it);
|
||||
|
||||
Ast_Package *package = find_package(it.name, &packages);
|
||||
if(package){
|
||||
package->decls.add(it.decls);
|
||||
} else {
|
||||
Ast_Package p = ast_package(&heap, it.name, it.decls);
|
||||
insert_builtin_types_into_package(&p);
|
||||
packages.add(p);
|
||||
}
|
||||
|
||||
}
|
||||
F64 parse_end = os_time();
|
||||
|
||||
For(packages){
|
||||
resolve_package(&it);
|
||||
}
|
||||
|
||||
For(pctx->ordered_decls){
|
||||
genln("");
|
||||
gen_ast(it);
|
||||
}
|
||||
|
||||
exp_destroy(&heap);
|
||||
|
||||
|
||||
F64 flattening_begin = os_time();
|
||||
String string_result = string_flatten(scratch, &pctx->gen);
|
||||
F64 flattening_end = os_time();
|
||||
|
||||
printf("\n//-------------------------------");
|
||||
printf("\n// Parse : %f", parse_end - parse_begin);
|
||||
printf("\n// Flattening : %f", flattening_end - flattening_begin);
|
||||
printf("\n// Total : %f", flattening_end - total_time);
|
||||
printf("\n//-------------------------------");
|
||||
|
||||
return string_result;
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ struct Token{
|
||||
S32 line;
|
||||
U8 *line_begin;
|
||||
};
|
||||
global Token null_token;
|
||||
|
||||
struct Lex_Stream{
|
||||
String stream;
|
||||
@@ -179,7 +180,6 @@ struct Parse_Ctx:Lexer{
|
||||
Ast_Package *resolving_package;
|
||||
Array<Ast_Decl *> ordered_decls;
|
||||
|
||||
Token empty_token;
|
||||
S64 indent;
|
||||
String_Builder gen;
|
||||
};
|
||||
|
||||
5
main.cpp
5
main.cpp
@@ -164,7 +164,7 @@ Expr:
|
||||
#include "parsing.cpp"
|
||||
#include "typechecking.h"
|
||||
#include "typechecking.cpp"
|
||||
// #include "ccodegen.cpp"
|
||||
#include "ccodegen.cpp"
|
||||
#include "tests.cpp"
|
||||
|
||||
int main(int argument_count, char **arguments){
|
||||
@@ -221,6 +221,7 @@ int main(int argument_count, char **arguments){
|
||||
Array<String> files = {scratch};
|
||||
files.add("lambdas.kl"_s);
|
||||
files.add("order1.kl"_s);
|
||||
compile_files(files);
|
||||
String result = compile_files(files);
|
||||
printf("%s", result.str);
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package lambdas
|
||||
|
||||
other_func :: ()
|
||||
a_val := recursive_lambda
|
||||
|
||||
recursive_lambda :: (thing: S64)
|
||||
in_val := recursive_lambda
|
||||
some_value := thing + const_in_lambda
|
||||
|
||||
other_func :: ()
|
||||
a_val := recursive_lambda
|
||||
|
||||
const_in_lambda :: 10
|
||||
|
||||
not_const := val + 10
|
||||
|
||||
47
parsing.cpp
47
parsing.cpp
@@ -33,7 +33,7 @@ function Token *
|
||||
token_get(S64 i = 0){
|
||||
i += pctx->token_iter;
|
||||
if(i >= pctx->tokens.len){
|
||||
return &pctx->empty_token;
|
||||
return &null_token;
|
||||
}
|
||||
Token *result = &pctx->tokens[i];
|
||||
return result;
|
||||
@@ -122,10 +122,18 @@ parse_init_stmt(Ast_Expr *expr){
|
||||
if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT)
|
||||
compiler_error(expr->pos, "Binding with [:=] to something that is not an identifier");
|
||||
|
||||
if(token_is_assign(token)){
|
||||
|
||||
|
||||
else if(token_is_assign(token)){
|
||||
token_next();
|
||||
Ast_Expr *value = parse_expr();
|
||||
Ast_Expr *result = ast_expr_binary((Ast_Atom *)expr, value, token);
|
||||
Ast_Expr *result = 0;
|
||||
if(token->kind == TK_ColonAssign){
|
||||
Ast_Atom *name = (Ast_Atom *)expr;
|
||||
result = (Ast_Expr *)ast_var(token, 0, name->intern_val, value);
|
||||
} else{
|
||||
result = ast_expr_binary((Ast_Atom *)expr, value, token);
|
||||
}
|
||||
result->flags = set_flag(result->flags, AST_STMT);
|
||||
return result;
|
||||
}
|
||||
@@ -176,9 +184,9 @@ parse_optional_type(){
|
||||
return result;
|
||||
}
|
||||
|
||||
function Ast_Block *
|
||||
parse_block(){
|
||||
Ast_Block *block = 0;
|
||||
function Ast_Scope *
|
||||
parse_stmt_scope(){
|
||||
Ast_Scope *block = 0;
|
||||
|
||||
if(token_expect(OPEN_SCOPE)){ // @todo: Fix error message here, it doesn't show proper token context
|
||||
Token *token_block = token_get();
|
||||
@@ -218,7 +226,7 @@ parse_block(){
|
||||
}
|
||||
}
|
||||
|
||||
Ast_Block *for_block = parse_block();
|
||||
Ast_Scope *for_block = parse_stmt_scope();
|
||||
stmts.add(ast_for(token, init, cond, iter, for_block));
|
||||
}
|
||||
|
||||
@@ -232,7 +240,7 @@ parse_block(){
|
||||
}
|
||||
if(init_val == expr) init_val = 0;
|
||||
|
||||
Ast_Block *if_block = parse_block();
|
||||
Ast_Scope *if_block = parse_stmt_scope();
|
||||
Ast_If_Node *if_node = ast_if_node(token, init_val, expr, if_block);
|
||||
if_nodes.add(if_node);
|
||||
|
||||
@@ -241,12 +249,12 @@ parse_block(){
|
||||
token = token_next();
|
||||
if(token_match_keyword(keyword_if)){
|
||||
Ast_Expr *expr = parse_expr();
|
||||
Ast_Block *else_if_block = parse_block();
|
||||
Ast_Scope *else_if_block = parse_stmt_scope();
|
||||
Ast_If_Node *if_node = ast_if_node(token, 0, expr, else_if_block);
|
||||
if_nodes.add(if_node);
|
||||
}
|
||||
else{
|
||||
Ast_Block *else_block = parse_block();
|
||||
Ast_Scope *else_block = parse_stmt_scope();
|
||||
Ast_If_Node *if_node = ast_if_node(token, 0, 0, else_block);
|
||||
if_nodes.add(if_node);
|
||||
break;
|
||||
@@ -274,7 +282,7 @@ parse_block(){
|
||||
}
|
||||
} while(token_match(SAME_SCOPE));
|
||||
token_expect(CLOSE_SCOPE);
|
||||
block = ast_block(token_block, stmts);
|
||||
block = ast_stmt_scope(token_block, stmts);
|
||||
}
|
||||
return block;
|
||||
}
|
||||
@@ -284,7 +292,7 @@ parse_lambda(Token *token){
|
||||
Scratch scratch;
|
||||
|
||||
B32 has_var_args = false;
|
||||
Array<Ast_Lambda_Arg *> params = {scratch};
|
||||
Array<Ast_Decl *> params = {scratch};
|
||||
if(!token_is(TK_CloseParen)){
|
||||
for(;;){
|
||||
Token *name = token_get();
|
||||
@@ -297,7 +305,7 @@ parse_lambda(Token *token){
|
||||
default_value = parse_expr();
|
||||
}
|
||||
|
||||
Ast_Lambda_Arg *param = ast_expr_lambda_arg(name, name->intern_val, typespec, default_value);
|
||||
Ast_Decl *param = ast_var(name, typespec, name->intern_val, default_value);
|
||||
params.add(param);
|
||||
}
|
||||
else if(token_match(TK_ThreeDots)){
|
||||
@@ -313,8 +321,8 @@ parse_lambda(Token *token){
|
||||
token_expect(TK_CloseParen);
|
||||
|
||||
Ast_Expr *ret = parse_optional_type();
|
||||
Ast_Block *block = token_is(OPEN_SCOPE) ? parse_block() : 0;
|
||||
Ast_Lambda *result = ast_lambda(token, params, has_var_args, ret, block);
|
||||
Ast_Scope *scope = token_is(OPEN_SCOPE) ? parse_stmt_scope() : 0;
|
||||
Ast_Lambda *result = ast_lambda(token, params, has_var_args, ret, scope);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -570,10 +578,17 @@ parse_decl(B32 is_global){
|
||||
result = parse_enum(tname);
|
||||
}
|
||||
|
||||
// @note parse constant expression
|
||||
else{
|
||||
Ast_Expr *expr = parse_expr();
|
||||
result = ast_const(tname, tname->intern_val, expr);
|
||||
|
||||
if(expr->kind == AST_LAMBDA){
|
||||
auto a = (Ast_Lambda *)expr;
|
||||
if(a->scope){
|
||||
result->kind = AST_LAMBDA;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if(token_match(TK_Identifier, TK_Colon)){
|
||||
|
||||
367
typechecking.cpp
367
typechecking.cpp
@@ -1,7 +1,6 @@
|
||||
#define CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast;
|
||||
#define BREAK() } break
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Evaluating constant expressions
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -313,16 +312,6 @@ _rewrite_into_const(Ast *node, U64 ast_size, Value value){
|
||||
}
|
||||
|
||||
#if 0
|
||||
function Ast_Resolved_Type *
|
||||
resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){
|
||||
if(ast_can_be_null && ast == 0)
|
||||
return 0;
|
||||
|
||||
Operand resolved = resolve_expr(ast);
|
||||
if(resolved.type != type_type)
|
||||
compiler_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]);
|
||||
return resolved.type_val;
|
||||
}
|
||||
|
||||
function Operand
|
||||
require_const_int(Ast_Expr *expr, B32 ast_can_be_null){
|
||||
@@ -916,18 +905,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
else{
|
||||
Operand left = resolve_expr(node->left);
|
||||
Operand right = resolve_expr(node->right);
|
||||
B32 is_const = left.is_const && right.is_const;
|
||||
Value value = eval_binary(node->pos, node->op, left.value, right.value, is_const);
|
||||
if(is_const){
|
||||
rewrite_into_const(node, Ast_Binary, value);
|
||||
result = operand_const_rvalue(value);
|
||||
}
|
||||
else result = operand_rvalue(value.type);
|
||||
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -942,35 +920,6 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
||||
invalid_return;
|
||||
}
|
||||
|
||||
function Operand
|
||||
resolve_const(Ast_Expr *ast, Sym *sym){
|
||||
|
||||
}
|
||||
|
||||
function Operand
|
||||
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 = resolve_expr(node->expr, type);
|
||||
assert(expr.type != 0 || type != 0);
|
||||
make_sure_value_is_compatible_with_type(node->pos, &expr, type, EXPR_CAN_BE_NULL|TYPE_CAN_BE_NULL);
|
||||
assert(expr.type);
|
||||
return expr;
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(CONST, Const){
|
||||
Operand expr = resolve_const((Ast_Expr *)node->value, sym);
|
||||
if(!expr.is_const) compiler_error(node->pos, "Value of constant variable is not a constant expression");
|
||||
assert(expr.type);
|
||||
return expr;
|
||||
BREAK();
|
||||
}
|
||||
invalid_default_case; return {};
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#define Enter_Scope(x) Enter_Scope_Defer package_scope(x)
|
||||
@@ -1011,6 +960,178 @@ search_for_decl_in_current_context(Intern_String name){
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){
|
||||
scope->decls.add(decl);
|
||||
}
|
||||
|
||||
function void
|
||||
insert_into_current_scope(Ast_Decl *decl){
|
||||
insert_into_scope(pctx->current_scope, decl);
|
||||
}
|
||||
|
||||
function void
|
||||
insert_type_into_package(Ast_Package *p, String name, Ast_Resolved_Type *type){
|
||||
Intern_String string = pctx->intern(name);
|
||||
Ast_Decl *decl = ast_type(&null_token, string, type);
|
||||
decl->state = DECL_RESOLVED;
|
||||
insert_into_scope(p, decl);
|
||||
}
|
||||
|
||||
function void
|
||||
insert_builtin_types_into_package(Ast_Package *p){
|
||||
insert_type_into_package(p, "void"_s , type_void);
|
||||
insert_type_into_package(p, "Bool"_s , type_bool);
|
||||
insert_type_into_package(p, "String"_s, type_string);
|
||||
insert_type_into_package(p, "S8"_s, type_s8);
|
||||
insert_type_into_package(p, "S16"_s, type_s16);
|
||||
insert_type_into_package(p, "S32"_s, type_s32);
|
||||
insert_type_into_package(p, "S64"_s, type_s64);
|
||||
insert_type_into_package(p, "U8"_s, type_u8);
|
||||
insert_type_into_package(p, "U16"_s, type_u16);
|
||||
insert_type_into_package(p, "U32"_s, type_u32);
|
||||
insert_type_into_package(p, "U64"_s, type_u64);
|
||||
insert_type_into_package(p, "F32"_s, type_f32);
|
||||
insert_type_into_package(p, "F64"_s, type_f64);
|
||||
}
|
||||
|
||||
function Ast_Resolved_Type *
|
||||
resolve_typespec(Ast_Expr *ast, B32 flags){
|
||||
if(!ast && flags == AST_CAN_BE_NULL)
|
||||
return 0;
|
||||
|
||||
Operand resolved = resolve_expr(ast, flags);
|
||||
if(resolved.type != type_type)
|
||||
compiler_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]);
|
||||
return resolved.type_val;
|
||||
}
|
||||
|
||||
function Operand
|
||||
require_const_int(Ast_Expr *expr, B32 flags){
|
||||
Operand op = resolve_expr(expr, flags);
|
||||
|
||||
if(expr == 0 && flags)
|
||||
return op;
|
||||
else if(expr == 0)
|
||||
compiler_error(expr->pos, "This field cannot be null");
|
||||
|
||||
if(!op.is_const)
|
||||
compiler_error(expr->pos, "Expected a const value");
|
||||
if(!is_int(op.type))
|
||||
compiler_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type));
|
||||
|
||||
return op;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function Operand
|
||||
resolve_expr(Ast_Expr *ast, B32 flags){
|
||||
if(!ast && flags == AST_CAN_BE_NULL) return {};
|
||||
assert(is_flag_set(ast->flags, AST_EXPR));
|
||||
|
||||
|
||||
switch(ast->kind){
|
||||
|
||||
CASE(VALUE, Atom){
|
||||
return operand_const_rvalue(node->value);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(IDENT, Atom){
|
||||
Ast_Decl *decl = resolve_name(node->pos, node->intern_val);
|
||||
|
||||
node->resolved_decl = decl;
|
||||
if(decl->kind == AST_CONST){
|
||||
// @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);
|
||||
}
|
||||
|
||||
|
||||
return operand(decl);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(VAR, Decl){
|
||||
resolve_var(node);
|
||||
insert_into_current_scope(node);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(BINARY, Binary){
|
||||
if(token_is_assign(node->op)){
|
||||
assert(is_flag_set(node->flags, AST_STMT));
|
||||
Operand left = resolve_expr(node->left, AST_CANT_BE_NULL);
|
||||
if(!left.is_lvalue) compiler_error(node->pos, "Assigning to rvalue");
|
||||
Operand right = resolve_expr(node->right, AST_CANT_BE_NULL);
|
||||
|
||||
right.value = convert_untyped_to_typed(node->pos, right.value, left.type);
|
||||
if(left.type != right.type) compiler_error(node->pos, "Can't assign value when left is %s and right is %s", docname(left.type), docname(right.type));
|
||||
return {};
|
||||
}
|
||||
else{
|
||||
Operand left = resolve_expr(node->left, AST_CANT_BE_NULL);
|
||||
Operand right = resolve_expr(node->right, AST_CANT_BE_NULL);
|
||||
B32 is_const = left.is_const && right.is_const;
|
||||
Value value = eval_binary(node->pos, node->op, left.value, right.value, is_const);
|
||||
if(is_const){
|
||||
rewrite_into_const(node, Ast_Binary, value);
|
||||
return operand_const_rvalue(value);
|
||||
}
|
||||
else return operand_rvalue(value.type);
|
||||
|
||||
}
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(UNARY, Unary){
|
||||
Operand value = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
||||
if(node->op == TK_Pointer){
|
||||
if(value.type->kind == TYPE_POINTER){
|
||||
node->type = value.type->base;
|
||||
return operand_lvalue(node->type);
|
||||
}
|
||||
else if(value.type->kind == TYPE_TYPE){
|
||||
node->type = type_pointer(value.type_val);
|
||||
return operand_type(node->type);
|
||||
}
|
||||
else{ compiler_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; }
|
||||
}
|
||||
else if(node->op == TK_Dereference){
|
||||
node->type = type_pointer(value.type);
|
||||
return operand_lvalue(node->type);
|
||||
}
|
||||
else{
|
||||
eval_unary(node->pos, node->op, &value);
|
||||
if(value.is_const){
|
||||
rewrite_into_const(node, Ast_Unary, value.value);
|
||||
return operand_const_rvalue(value.value);
|
||||
}
|
||||
return operand_rvalue(value.value.type);
|
||||
}
|
||||
|
||||
BREAK();
|
||||
}
|
||||
|
||||
invalid_default_case;
|
||||
}
|
||||
|
||||
invalid_return;
|
||||
}
|
||||
|
||||
function void
|
||||
resolve_decl(Ast_Decl *ast){
|
||||
if(ast->state == DECL_RESOLVED){
|
||||
@@ -1024,47 +1145,90 @@ resolve_decl(Ast_Decl *ast){
|
||||
|
||||
ast->state = DECL_RESOLVING;
|
||||
{
|
||||
Operand result = {};
|
||||
switch(ast->kind){
|
||||
CASE(LAMBDA, Decl){
|
||||
// return resolve_lambda(node, sym);
|
||||
Ast_Lambda *lambda = node->lambda;
|
||||
|
||||
Scratch scratch;
|
||||
Ast_Resolved_Type *lambda_type = 0;
|
||||
Ast_Resolved_Type *ret_type = resolve_typespec(lambda->ret, AST_CANT_BE_NULL);
|
||||
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->expr, AST_CAN_BE_NULL);
|
||||
make_sure_value_is_compatible_with_type(it->pos, &default_value, type, EXPR_CAN_BE_NULL);
|
||||
it->type = type;
|
||||
args.add(type);
|
||||
}
|
||||
|
||||
lambda_type = type_lambda(lambda, ret_type, args);
|
||||
Operand result = operand_type(lambda_type);
|
||||
|
||||
// @note: top level lambda needs to get marked as resolved
|
||||
// so that the cyclic dependency wont trigger
|
||||
node->type = lambda_type;
|
||||
node->state = DECL_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->scope){
|
||||
Enter_Scope(lambda->scope);
|
||||
For(lambda->args){
|
||||
insert_into_current_scope(it);
|
||||
}
|
||||
For(lambda->scope->stmts){
|
||||
unused(it);
|
||||
// resolve_stmt(it, ret_type);
|
||||
}
|
||||
|
||||
result = operand_lambda(lambda_type);
|
||||
}
|
||||
else if(is_flag_set(lambda->parent->flags, AST_FOREIGN)){
|
||||
result = operand_lambda(lambda_type);
|
||||
}
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(CONST, Decl){
|
||||
Operand op = resolve_expr(node->expr, AST_CANT_BE_NULL);
|
||||
if(!op.is_const){
|
||||
compiler_error(node->pos, "Assigning a value that is not constant to a constant declaration");
|
||||
}
|
||||
node->value = op.value;
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(VAR, Decl){
|
||||
resolve_var(node);
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(ENUM, Decl){
|
||||
// Ast_Resolved_Type *type = type_enum(node);
|
||||
// S64 scope_index = scope_open();
|
||||
// S64 value = 0;
|
||||
// For(node->members){
|
||||
// Operand op = require_const_int(it->value, AST_CAN_BE_NULL);
|
||||
// if(op.type){
|
||||
// value = bigint_as_signed(&op.big_int_val) + 1;
|
||||
// }
|
||||
// else{
|
||||
// op.type = untyped_int;
|
||||
// bigint_init_signed(&op.big_int_val, value++);
|
||||
// }
|
||||
node->type = type_enum(node);
|
||||
Enter_Scope(node->scope);
|
||||
S64 value = 0;
|
||||
For(node->scope->decls){
|
||||
Operand op = {};
|
||||
if(it->expr){
|
||||
op = require_const_int(it->expr, AST_CANT_BE_NULL);
|
||||
value = bigint_as_signed(&op.big_int_val) + 1;
|
||||
} else{
|
||||
op.type = untyped_int;
|
||||
bigint_init_signed(&op.big_int_val, value++);
|
||||
}
|
||||
|
||||
// sym_const(it->name, op, it, INSERT_INTO_SCOPE);
|
||||
// }
|
||||
// scope_close(scope_index);
|
||||
// return operand_type(type);
|
||||
it->value = op.value;
|
||||
}
|
||||
BREAK();
|
||||
}
|
||||
|
||||
CASE(STRUCT, Decl){
|
||||
// Ast_Resolved_Type *type = type_struct(node);
|
||||
// return operand_type(type);
|
||||
BREAK();
|
||||
}
|
||||
invalid_default_case;
|
||||
}
|
||||
// Operand op = resolve_binding(ast->ast, ast);
|
||||
// ast->value = op.value;
|
||||
|
||||
}
|
||||
ast->state = DECL_RESOLVED;
|
||||
|
||||
pctx->resolving_package->resolved.add(ast);
|
||||
pctx->ordered_decls.add(ast);
|
||||
}
|
||||
|
||||
function Ast_Decl *
|
||||
@@ -1081,7 +1245,7 @@ resolve_package(Ast_Package *package){
|
||||
For(package->decls){
|
||||
resolve_name(it->pos, it->name);
|
||||
if(it->kind == AST_STRUCT){
|
||||
// type_complete(it->type);
|
||||
type_complete(it->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1140,50 +1304,3 @@ find_package(Intern_String name, Array<Ast_Package> *packages){
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function String
|
||||
compile_files(Array<String> filename){
|
||||
Scratch scratch(thread_ctx.scratch);
|
||||
Array<Ast_File> files = {scratch};
|
||||
|
||||
For(filename){
|
||||
String filecontent = os_read_file(scratch, it);
|
||||
assert(filecontent.len);
|
||||
files.add(ast_file(it, filecontent));
|
||||
}
|
||||
|
||||
F64 total_time = os_time();
|
||||
OS_Heap heap = win32_os_heap_create(false, mib(16), 0);
|
||||
|
||||
Parse_Ctx ctx = {};
|
||||
parse_init(&ctx, scratch, &heap);
|
||||
|
||||
F64 parse_begin = os_time();
|
||||
Array<Ast_Package> packages = {&heap};
|
||||
For(files){
|
||||
parse_file(&it);
|
||||
|
||||
Ast_Package *package = find_package(it.name, &packages);
|
||||
if(package){
|
||||
package->decls.add(it.decls);
|
||||
} else {
|
||||
packages.add(ast_package(&heap, it.name, it.decls));
|
||||
}
|
||||
|
||||
}
|
||||
F64 parse_end = os_time();
|
||||
|
||||
For(packages){
|
||||
resolve_package(&it);
|
||||
}
|
||||
|
||||
exp_destroy(&heap);
|
||||
F64 flattening_end = os_time();
|
||||
printf("\n//-------------------------------");
|
||||
printf("\n// Parse : %f", parse_end - parse_begin);
|
||||
printf("\n// Total : %f", flattening_end - total_time);
|
||||
printf("\n//-------------------------------");
|
||||
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -5,7 +5,11 @@ struct Operand{
|
||||
U8 is_lvalue: 1;
|
||||
};
|
||||
|
||||
|
||||
enum{AST_CANT_BE_NULL = 0, AST_CAN_BE_NULL = 1};
|
||||
function Operand resolve_expr(Ast_Expr *ast, B32 flags);
|
||||
function void resolve_decl(Ast_Decl *ast);
|
||||
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
|
||||
//-----------------------------------------------------------------------------
|
||||
// Symbols
|
||||
@@ -30,7 +34,7 @@ struct Sym{
|
||||
INLINE_VALUE_FIELDS;
|
||||
};
|
||||
|
||||
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);
|
||||
@@ -155,39 +159,17 @@ sym_insert(Sym_Kind kind, Intern_String name, Value value, Ast *ast){
|
||||
return sym;
|
||||
}
|
||||
|
||||
function void
|
||||
sym_insert_builtin_type(String name, Ast_Resolved_Type *type){
|
||||
Intern_String string = intern_string(&pctx->interns, name);
|
||||
Sym *sym = sym_type(type, &empty_decl, string, false);
|
||||
sym_insert(sym);
|
||||
}
|
||||
|
||||
function void
|
||||
sym_insert_builtins(){
|
||||
sym_insert_builtin_type("void"_s , type_void);
|
||||
sym_insert_builtin_type("Bool"_s , type_bool);
|
||||
sym_insert_builtin_type("String"_s, type_string);
|
||||
sym_insert_builtin_type("S8"_s, type_s8);
|
||||
sym_insert_builtin_type("S16"_s, type_s16);
|
||||
sym_insert_builtin_type("S32"_s, type_s32);
|
||||
sym_insert_builtin_type("S64"_s, type_s64);
|
||||
sym_insert_builtin_type("U8"_s, type_u8);
|
||||
sym_insert_builtin_type("U16"_s, type_u16);
|
||||
sym_insert_builtin_type("U32"_s, type_u32);
|
||||
sym_insert_builtin_type("U64"_s, type_u64);
|
||||
sym_insert_builtin_type("F32"_s, type_f32);
|
||||
sym_insert_builtin_type("F64"_s, type_f64);
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Operands
|
||||
//-----------------------------------------------------------------------------
|
||||
function Operand
|
||||
operand(Sym *sym){
|
||||
operand(Ast_Decl *sym){
|
||||
Operand result = {};
|
||||
result.type = sym->type;
|
||||
result.is_const = sym->kind == SYM_CONST ? true : false;
|
||||
result.is_lvalue= sym->kind == SYM_CONST ? false : true; // Cant assign to const values
|
||||
result.is_const = sym->kind == AST_CONST ? true : false;
|
||||
result.is_lvalue= sym->kind == AST_CONST ? false : true; // Cant assign to const values
|
||||
result.value = sym->value;
|
||||
return result;
|
||||
}
|
||||
@@ -256,7 +238,7 @@ operand_rvalue(Ast_Resolved_Type *type){
|
||||
result.is_lvalue = false;
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Hash consed types
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -337,8 +319,7 @@ type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
|
||||
|
||||
function Ast_Resolved_Type *
|
||||
type_enum(Ast_Decl *ast){
|
||||
Ast_Resolved_Type *type = 0;
|
||||
// Ast_Resolved_Type *type = resolve_typespec(ast->typespec, AST_CAN_BE_NULL);
|
||||
Ast_Resolved_Type *type = resolve_typespec(ast->typespec, AST_CAN_BE_NULL);
|
||||
if(!type){
|
||||
type = untyped_int;
|
||||
}
|
||||
@@ -349,24 +330,13 @@ type_enum(Ast_Decl *ast){
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
2022.05.31 - Global scope structs vs nested structs
|
||||
Structs exist in 2 variants, the global scope structs are a bit different
|
||||
then scoped structs. They startout incomplete and when some operation
|
||||
requires the actual struct size, alignment, field access etc. then it
|
||||
should call complete_type. It resolves all the children, calculates the
|
||||
size and makes sure there are no cyclic dependencies. This is require for
|
||||
correct behaviour of order independent structs. If someone just wants a pointer
|
||||
to that struct we don't need to complete the type, we know how large a pointer is.
|
||||
This allows us to have cyclic dependency that is a pointer. Cause we know how large pointer is.
|
||||
*/
|
||||
function Ast_Resolved_Type *
|
||||
type_incomplete(Ast *ast){
|
||||
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0);
|
||||
result->ast = ast;
|
||||
return result;
|
||||
}
|
||||
#if 0
|
||||
|
||||
function void
|
||||
type_struct_complete(Ast_Resolved_Type *type, Ast_Decl *node){
|
||||
assert(node->kind == AST_STRUCT);
|
||||
@@ -376,34 +346,11 @@ type_struct_complete(Ast_Resolved_Type *type, Ast_Decl *node){
|
||||
Scratch scratch;
|
||||
Array<Ast_Resolved_Member> members = {scratch};
|
||||
For(node->scope->decls){
|
||||
Operand op = resolve_decl(it);
|
||||
Intern_String name = ast_get_name(it);
|
||||
sym_var(name, op, it);
|
||||
members.add({op.type, name});
|
||||
resolve_decl(it);
|
||||
members.add({it->type, it->name});
|
||||
}
|
||||
type->agg.members = members.tight_copy(pctx->perm);
|
||||
type->kind = TYPE_STRUCT;
|
||||
|
||||
/*
|
||||
@note: resolve constant members after the struct got resolved
|
||||
this way we avoid a problem where we start resolving the function
|
||||
and this function has parameter of type parent struct
|
||||
which is being resolved right now, cyclic dependency happens.
|
||||
constants arent required to make struct work
|
||||
*/
|
||||
For(node->const_members){
|
||||
Operand op = resolve_binding(it);
|
||||
Intern_String name = ast_get_name(it);
|
||||
sym_const(name, op, it);
|
||||
}
|
||||
}
|
||||
|
||||
function Ast_Resolved_Type *
|
||||
type_struct(Ast_Struct *agg){
|
||||
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_STRUCT, 0, 0);
|
||||
result->ast = agg;
|
||||
type_struct_complete(result, agg);
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
@@ -418,9 +365,7 @@ type_complete(Ast_Resolved_Type *type){
|
||||
return;
|
||||
}
|
||||
|
||||
Ast_Struct *node = (Ast_Struct *)type->ast;
|
||||
type_struct_complete(type, node);
|
||||
pctx->resolving_package->ordered.add((Ast_Named *)node->parent);
|
||||
type_struct_complete(type, (Ast_Decl *)type->ast);
|
||||
pctx->ordered_decls.add((Ast_Decl *)type->ast);
|
||||
}
|
||||
|
||||
#endif
|
||||
1
types.h
1
types.h
@@ -227,6 +227,7 @@ global Ast_Resolved_Type *untyped_float = &type__untyped_float;
|
||||
// Type constructors and utillities
|
||||
//-----------------------------------------------------------------------------
|
||||
force_inline B32 is_struct(Ast_Resolved_Type *a){return a->kind == TYPE_STRUCT;}
|
||||
force_inline B32 is_lambda(Ast_Resolved_Type *a){return a->kind == TYPE_LAMBDA;}
|
||||
force_inline B32 is_array(Ast_Resolved_Type *a){return a->kind == TYPE_ARRAY;}
|
||||
force_inline B32 is_enum(Ast_Resolved_Type *a){return a->kind == TYPE_ENUM;}
|
||||
force_inline B32 is_pointer(Ast_Resolved_Type *a){return a->kind == TYPE_POINTER;}
|
||||
|
||||
Reference in New Issue
Block a user