Basic resolving, codegen with packages
This commit is contained in:
96
ast.cpp
96
ast.cpp
@@ -17,6 +17,7 @@ enum Ast_Kind: U32{
|
|||||||
AST_CALL_ITEM,
|
AST_CALL_ITEM,
|
||||||
AST_CALL,
|
AST_CALL,
|
||||||
|
|
||||||
|
AST_TYPE,
|
||||||
AST_VAR,
|
AST_VAR,
|
||||||
AST_CONST,
|
AST_CONST,
|
||||||
AST_POINTER,
|
AST_POINTER,
|
||||||
@@ -73,6 +74,7 @@ struct Value{VALUE_FIELDS};
|
|||||||
// BigInt big_int_val;
|
// BigInt big_int_val;
|
||||||
|
|
||||||
struct Ast_Atom: Ast_Expr{
|
struct Ast_Atom: Ast_Expr{
|
||||||
|
Ast_Decl *resolved_decl;
|
||||||
INLINE_VALUE_FIELDS;
|
INLINE_VALUE_FIELDS;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -91,7 +93,8 @@ struct Ast_Call: Ast_Expr{
|
|||||||
struct Ast_Unary: Ast_Expr{
|
struct Ast_Unary: Ast_Expr{
|
||||||
Token_Kind op;
|
Token_Kind op;
|
||||||
Ast_Expr *expr;
|
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{
|
struct Ast_Cast: Ast_Expr{
|
||||||
@@ -116,19 +119,13 @@ struct Ast_Binary: Ast_Expr{
|
|||||||
// look into global scope and to the locals list.
|
// 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{
|
struct Ast_Return: Ast{
|
||||||
Ast_Expr *expr;
|
Ast_Expr *expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_If_Node: Ast{
|
struct Ast_If_Node: Ast{
|
||||||
Ast_Expr *expr ;
|
Ast_Expr *expr ;
|
||||||
Ast_Block *block;
|
Ast_Scope *scope;
|
||||||
Ast_Binary*init;
|
Ast_Binary*init;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -142,20 +139,14 @@ struct Ast_For: Ast{
|
|||||||
Ast_Expr *init;
|
Ast_Expr *init;
|
||||||
Ast_Expr *cond;
|
Ast_Expr *cond;
|
||||||
Ast_Expr *iter;
|
Ast_Expr *iter;
|
||||||
Ast_Block *block;
|
Ast_Scope *scope;
|
||||||
};
|
|
||||||
|
|
||||||
struct Ast_Lambda_Arg: Ast_Expr{
|
|
||||||
Intern_String name;
|
|
||||||
Ast_Expr *typespec;
|
|
||||||
Ast_Expr *default_value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Lambda : Ast_Expr {
|
struct Ast_Lambda : Ast_Expr {
|
||||||
Array<Ast_Lambda_Arg *> args;
|
Array<Ast_Decl *> args;
|
||||||
Ast_Expr *ret;
|
Ast_Expr *ret;
|
||||||
Ast_Block *block;
|
Ast_Scope *scope;
|
||||||
B32 has_var_args;
|
B32 has_var_args;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Array: Ast_Expr{
|
struct Ast_Array: Ast_Expr{
|
||||||
@@ -190,7 +181,6 @@ enum Ast_Decl_State{
|
|||||||
|
|
||||||
struct Ast_Decl;
|
struct Ast_Decl;
|
||||||
struct Ast_Scope: Ast{
|
struct Ast_Scope: Ast{
|
||||||
Array<Ast_Decl *> resolved;
|
|
||||||
Array<Ast_Decl *> decls;
|
Array<Ast_Decl *> decls;
|
||||||
Array<Ast *> stmts;
|
Array<Ast *> stmts;
|
||||||
};
|
};
|
||||||
@@ -201,8 +191,11 @@ struct Ast_Decl: Ast{
|
|||||||
Intern_String name;
|
Intern_String name;
|
||||||
|
|
||||||
Ast_Scope *scope;
|
Ast_Scope *scope;
|
||||||
Ast_Expr *expr;
|
|
||||||
Ast_Expr *typespec;
|
Ast_Expr *typespec;
|
||||||
|
union{
|
||||||
|
Ast_Expr *expr;
|
||||||
|
Ast_Lambda *lambda;
|
||||||
|
};
|
||||||
|
|
||||||
INLINE_VALUE_FIELDS;
|
INLINE_VALUE_FIELDS;
|
||||||
};
|
};
|
||||||
@@ -339,41 +332,21 @@ ast_expr_index(Token *pos, Ast_Expr *expr, Ast_Expr *index){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Lambda *
|
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);
|
AST_NEW(Lambda, LAMBDA, 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->block = block;
|
result->scope = scope;
|
||||||
result->ret = ret;
|
result->ret = ret;
|
||||||
result->has_var_args = has_var_args;
|
result->has_var_args = has_var_args;
|
||||||
if(!ret) result->ret = ast_ident(result->pos, intern_void);
|
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;
|
result->ret->parent = result;
|
||||||
For(result->args) it->parent = result;
|
For(result->args) it->parent = result;
|
||||||
return 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 *
|
function Ast_If *
|
||||||
ast_if(Token *pos, Array<Ast_If_Node *> ifs){
|
ast_if(Token *pos, Array<Ast_If_Node *> ifs){
|
||||||
AST_NEW(If, IF, pos, AST_STMT);
|
AST_NEW(If, IF, pos, AST_STMT);
|
||||||
@@ -383,16 +356,16 @@ ast_if(Token *pos, Array<Ast_If_Node *> ifs){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Ast_For *
|
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);
|
AST_NEW(For, FOR, pos, AST_STMT);
|
||||||
result->init = init;
|
result->init = init;
|
||||||
result->cond = cond;
|
result->cond = cond;
|
||||||
result->iter = iter;
|
result->iter = iter;
|
||||||
result->block = block;
|
result->scope = scope;
|
||||||
if(result->init) result->init->parent = result;
|
if(result->init) result->init->parent = result;
|
||||||
if(result->cond) result->cond->parent = result;
|
if(result->cond) result->cond->parent = result;
|
||||||
if(result->iter) result->iter->parent = result;
|
if(result->iter) result->iter->parent = result;
|
||||||
result->block->parent = result;
|
result->scope->parent = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,15 +387,15 @@ ast_return(Token *pos, Ast_Expr *expr){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Ast_If_Node *
|
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);
|
AST_NEW(If_Node, IF_NODE, pos, AST_STMT);
|
||||||
result->block = block;
|
result->scope = scope;
|
||||||
result->expr = expr;
|
result->expr = expr;
|
||||||
result->init = (Ast_Binary *)init;
|
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->expr) result->expr->parent = result;
|
||||||
if(result->init) {
|
if(result->init) {
|
||||||
assert(init->kind == AST_BINARY);
|
assert(init->kind == AST_VAR);
|
||||||
result->init->parent = result;
|
result->init->parent = result;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -440,7 +413,6 @@ function Ast_Scope *
|
|||||||
ast_decl_scope(Token *pos, Array<Ast_Decl *> decls){
|
ast_decl_scope(Token *pos, Array<Ast_Decl *> decls){
|
||||||
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
||||||
result->decls = decls.tight_copy(pctx->perm);
|
result->decls = decls.tight_copy(pctx->perm);
|
||||||
result->resolved = array_make<Ast_Decl *>(pctx->perm, result->decls.len);
|
|
||||||
For(result->decls){
|
For(result->decls){
|
||||||
it->parent = result;
|
it->parent = result;
|
||||||
}
|
}
|
||||||
@@ -451,6 +423,7 @@ function Ast_Scope *
|
|||||||
ast_stmt_scope(Token *pos, Array<Ast *> stmts){
|
ast_stmt_scope(Token *pos, Array<Ast *> stmts){
|
||||||
AST_NEW(Scope, SCOPE, pos, AST_STMT);
|
AST_NEW(Scope, SCOPE, pos, AST_STMT);
|
||||||
result->stmts = stmts.tight_copy(pctx->perm);
|
result->stmts = stmts.tight_copy(pctx->perm);
|
||||||
|
result->decls = {pctx->heap};
|
||||||
For(result->stmts){
|
For(result->stmts){
|
||||||
it->parent = result;
|
it->parent = result;
|
||||||
}
|
}
|
||||||
@@ -486,6 +459,14 @@ ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr){
|
|||||||
return result;
|
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 *
|
function Ast_Decl *
|
||||||
ast_const(Token *pos, Intern_String name, Ast_Expr *expr){
|
ast_const(Token *pos, Intern_String name, Ast_Expr *expr){
|
||||||
AST_NEW(Decl, CONST, pos, AST_DECL);
|
AST_NEW(Decl, CONST, pos, AST_DECL);
|
||||||
@@ -495,13 +476,22 @@ ast_const(Token *pos, Intern_String name, Ast_Expr *expr){
|
|||||||
return result;
|
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
|
function Ast_Package
|
||||||
ast_package(Allocator *allocator, Intern_String name, Array<Ast_Decl *> decls){
|
ast_package(Allocator *allocator, Intern_String name, Array<Ast_Decl *> decls){
|
||||||
Ast_Package result = {};
|
Ast_Package result = {};
|
||||||
result.kind = AST_PACKAGE;
|
result.kind = AST_PACKAGE;
|
||||||
result.decls = decls.copy(allocator);
|
result.decls = decls.copy(allocator);
|
||||||
result.resolved = {allocator};
|
|
||||||
result.name = name;
|
result.name = name;
|
||||||
|
For(result.decls) it->parent = &result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
371
ccodegen.cpp
371
ccodegen.cpp
@@ -26,7 +26,7 @@ gen_simple_decl_prefix(Ast_Resolved_Type *ast){
|
|||||||
case TYPE_LAMBDA:break;
|
case TYPE_LAMBDA:break;
|
||||||
case TYPE_ENUM:
|
case TYPE_ENUM:
|
||||||
case TYPE_STRUCT: {
|
case TYPE_STRUCT: {
|
||||||
auto constant = (Ast_Const *)ast->ast->parent;
|
auto constant = (Ast_Decl *)ast->ast;
|
||||||
auto name = constant->name;
|
auto name = constant->name;
|
||||||
gen("%s ", name.str);
|
gen("%s ", name.str);
|
||||||
}break;
|
}break;
|
||||||
@@ -98,60 +98,58 @@ gen_expr(Ast_Expr *ast){
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(INDEX, Index){
|
// CASE(INDEX, Index){
|
||||||
Sym *sym = resolved_get(node);
|
// Sym *sym = resolved_get(node);
|
||||||
if(is_array(sym->type)){
|
// if(is_array(sym->type)){
|
||||||
gen("(");
|
// gen("(");
|
||||||
gen("(");
|
// gen("(");
|
||||||
|
|
||||||
gen("(");
|
// gen("(");
|
||||||
gen_simple_decl(sym->type->arr.base, {});
|
// gen_simple_decl(sym->type->arr.base, {});
|
||||||
gen("*)");
|
// gen("*)");
|
||||||
gen_expr(node->expr);
|
// gen_expr(node->expr);
|
||||||
gen(".data)");
|
// gen(".data)");
|
||||||
|
|
||||||
|
|
||||||
gen("[");
|
// gen("[");
|
||||||
gen_expr(node->index);
|
// gen_expr(node->index);
|
||||||
gen("]");
|
// gen("]");
|
||||||
gen(")");
|
// gen(")");
|
||||||
} else{
|
// } else{
|
||||||
gen("(");
|
// gen("(");
|
||||||
gen_expr(node->expr);
|
// gen_expr(node->expr);
|
||||||
gen("[");
|
// gen("[");
|
||||||
gen_expr(node->index);
|
// gen_expr(node->index);
|
||||||
gen("]");
|
// gen("]");
|
||||||
gen(")");
|
// gen(")");
|
||||||
}
|
// }
|
||||||
BREAK();
|
// BREAK();
|
||||||
}
|
// }
|
||||||
|
|
||||||
CASE(BINARY, Binary){
|
CASE(BINARY, Binary){
|
||||||
if(node->op == TK_Dot){
|
// if(node->op == TK_Dot){
|
||||||
Sym *sym = resolved_get(node->left);
|
// Sym *sym = resolved_get(node->left);
|
||||||
gen_expr(node->left);
|
// gen_expr(node->left);
|
||||||
if(sym->type->kind == TYPE_POINTER) gen("->");
|
// if(sym->type->kind == TYPE_POINTER) gen("->");
|
||||||
else gen(".");
|
// else gen(".");
|
||||||
gen_expr(node->right);
|
// gen_expr(node->right);
|
||||||
}
|
// }
|
||||||
else if(node->op == TK_ColonAssign){
|
// else if(node->op == TK_ColonAssign){
|
||||||
|
|
||||||
Sym *sym = resolved_get(node);
|
// Sym *sym = resolved_get(node);
|
||||||
Ast_Atom *atom = (Ast_Atom *)node->left;
|
// Ast_Atom *atom = (Ast_Atom *)node->left;
|
||||||
assert(is_atom(atom));
|
// assert(is_atom(atom));
|
||||||
gen_simple_decl(sym->type, atom->intern_val);
|
// gen_simple_decl(sym->type, atom->intern_val);
|
||||||
if(node->right){
|
// if(node->right){
|
||||||
gen(" = ");
|
// gen(" = ");
|
||||||
gen_expr(node->right);
|
// gen_expr(node->right);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
else{
|
if(!token_is_assign(node->op)) gen("(");
|
||||||
if(!token_is_assign(node->op)) gen("(");
|
gen_expr(node->left);
|
||||||
gen_expr(node->left);
|
gen("%s", name(node->op));
|
||||||
gen("%s", name(node->op));
|
gen_expr(node->right);
|
||||||
gen_expr(node->right);
|
if(!token_is_assign(node->op)) gen(")");
|
||||||
if(!token_is_assign(node->op)) gen(")");
|
|
||||||
}
|
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,15 +162,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(resolved_type_get(node->typespec), {});
|
||||||
gen(")");
|
// gen(")");
|
||||||
gen_expr(node->expr);
|
// gen_expr(node->expr);
|
||||||
gen(")");
|
// gen(")");
|
||||||
BREAK();
|
// BREAK();
|
||||||
}
|
// }
|
||||||
|
|
||||||
CASE(CALL, Call){
|
CASE(CALL, Call){
|
||||||
// @todo: Reach into map instead of direct lookup
|
// @todo: Reach into map instead of direct lookup
|
||||||
@@ -242,10 +240,10 @@ gen_line(Ast *node){
|
|||||||
function void
|
function void
|
||||||
gen_ast(Ast *ast);
|
gen_ast(Ast *ast);
|
||||||
function void
|
function void
|
||||||
gen_block(Ast_Block *block){
|
gen_stmt_scope(Ast_Scope *scope){
|
||||||
gen("{");
|
gen("{");
|
||||||
global_indent++;
|
global_indent++;
|
||||||
For(block->stmts) {
|
For(scope->stmts) {
|
||||||
gen_line(it);
|
gen_line(it);
|
||||||
genln("");
|
genln("");
|
||||||
gen_ast(it);
|
gen_ast(it);
|
||||||
@@ -292,17 +290,6 @@ function void
|
|||||||
gen_ast(Ast *ast){
|
gen_ast(Ast *ast){
|
||||||
switch(ast->kind){
|
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){
|
CASE(RETURN, Return){
|
||||||
gen("return");
|
gen("return");
|
||||||
if(node->expr){
|
if(node->expr){
|
||||||
@@ -313,9 +300,8 @@ gen_ast(Ast *ast){
|
|||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(VAR, Var){
|
CASE(VAR, Decl){
|
||||||
Sym *sym = resolved_get(node);
|
gen_var(node->name, node->type, node->expr, is_inside_struct ? DONT_EMIT_VALUE : ALWAYS_EMIT_VALUE);
|
||||||
gen_var(sym->name, sym->type, node->expr, is_inside_struct ? DONT_EMIT_VALUE : ALWAYS_EMIT_VALUE);
|
|
||||||
gen(";");
|
gen(";");
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
@@ -327,7 +313,7 @@ gen_ast(Ast *ast){
|
|||||||
gen("if(");
|
gen("if(");
|
||||||
gen_expr(it->expr);
|
gen_expr(it->expr);
|
||||||
gen(")");
|
gen(")");
|
||||||
gen_block(it->block);
|
gen_stmt_scope(it->scope);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
genln("else");
|
genln("else");
|
||||||
@@ -336,7 +322,7 @@ gen_ast(Ast *ast){
|
|||||||
gen_expr(it->expr);
|
gen_expr(it->expr);
|
||||||
gen(")");
|
gen(")");
|
||||||
}
|
}
|
||||||
gen_block(it->block);
|
gen_stmt_scope(it->scope);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
BREAK();
|
BREAK();
|
||||||
@@ -362,113 +348,116 @@ gen_ast(Ast *ast){
|
|||||||
gen(";");
|
gen(";");
|
||||||
if(node->iter) gen_expr(node->iter);
|
if(node->iter) gen_expr(node->iter);
|
||||||
gen(")");
|
gen(")");
|
||||||
gen_block(node->block);
|
gen_stmt_scope(node->scope);
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(CONST, Const){
|
CASE(LAMBDA, Decl){
|
||||||
Sym *sym = resolved_get(node);
|
if(node->kind == AST_LAMBDA){
|
||||||
|
if(is_flag_set(node->flags, AST_FOREIGN)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Ast_Lambda *lambda = node->lambda;
|
||||||
|
Ast_Resolved_Type *ret = node->type->func.ret;
|
||||||
|
gen_simple_decl(ret, node->name);
|
||||||
|
gen("(");
|
||||||
|
For(lambda->args){
|
||||||
|
gen_var(it->name, it->type, 0, DONT_EMIT_VALUE);
|
||||||
|
if(&it != (lambda->args.end() - 1)) gen(", ");
|
||||||
|
}
|
||||||
|
gen(")");
|
||||||
|
|
||||||
switch(sym->type->kind){
|
if(lambda->scope) {
|
||||||
|
// gen_stmt_scope(lambda->scope);
|
||||||
|
// @todo stmts
|
||||||
|
}
|
||||||
|
else gen(";");
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
gen_simple_decl(node->type, node->name);
|
||||||
|
gen(" = ");
|
||||||
|
gen_expr((Ast_Expr *)node->expr);
|
||||||
|
gen(";");
|
||||||
|
}
|
||||||
|
BREAK();
|
||||||
|
}
|
||||||
|
|
||||||
|
CASE(CONST, Decl){
|
||||||
|
switch(node->type->kind){
|
||||||
CASE_FLOAT:{
|
CASE_FLOAT:{
|
||||||
gen("// F64 %s = ", node->name.str);
|
gen("// F64 %s = ", node->name.str);
|
||||||
gen_value(sym->value);
|
gen_value(node->value);
|
||||||
} break;
|
} break;
|
||||||
CASE_INT:{
|
CASE_INT:{
|
||||||
gen("// constant int %s = ", node->name.str);
|
gen("// constant int %s = ", node->name.str);
|
||||||
gen_value(sym->value);
|
gen_value(node->value);
|
||||||
}break;
|
}break;
|
||||||
CASE_STRING:{
|
CASE_STRING:{
|
||||||
gen("// const String %s = ", node->name.str);
|
gen("// const String %s = ", node->name.str);
|
||||||
gen_value(sym->value);
|
gen_value(node->value);
|
||||||
}break;
|
}break;
|
||||||
CASE_BOOL:{
|
CASE_BOOL:{
|
||||||
gen("// const Bool %s = ", node->name.str);
|
gen("// const Bool %s = ", node->name.str);
|
||||||
gen_value(sym->value);
|
gen_value(node->value);
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case TYPE_LAMBDA:{
|
case TYPE_LAMBDA:{
|
||||||
if(node->value->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);
|
|
||||||
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);
|
|
||||||
if(&it != (lambda->args.end() - 1)) gen(", ");
|
|
||||||
}
|
|
||||||
gen(")");
|
|
||||||
|
|
||||||
if(lambda->block) {
|
|
||||||
gen_block(lambda->block);
|
|
||||||
}
|
|
||||||
else gen(";");
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
gen_simple_decl(sym->type, node->name);
|
|
||||||
gen(" = ");
|
|
||||||
gen_expr((Ast_Expr *)node->value);
|
|
||||||
gen(";");
|
|
||||||
}
|
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case TYPE_TYPE:{
|
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;
|
}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();
|
BREAK();
|
||||||
@@ -482,6 +471,7 @@ gen_ast(Ast *ast){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
function String
|
function String
|
||||||
compile_string(String filecontent, String filename = "default_name"_s){
|
compile_string(String filecontent, String filename = "default_name"_s){
|
||||||
F64 total_time = os_time();
|
F64 total_time = os_time();
|
||||||
@@ -574,3 +564,64 @@ compile_file(String filename){
|
|||||||
String result = compile_string(filecontent, filename);
|
String result = compile_string(filecontent, filename);
|
||||||
return result;
|
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;
|
S32 line;
|
||||||
U8 *line_begin;
|
U8 *line_begin;
|
||||||
};
|
};
|
||||||
|
global Token null_token;
|
||||||
|
|
||||||
struct Lex_Stream{
|
struct Lex_Stream{
|
||||||
String stream;
|
String stream;
|
||||||
@@ -179,7 +180,6 @@ struct Parse_Ctx:Lexer{
|
|||||||
Ast_Package *resolving_package;
|
Ast_Package *resolving_package;
|
||||||
Array<Ast_Decl *> ordered_decls;
|
Array<Ast_Decl *> ordered_decls;
|
||||||
|
|
||||||
Token empty_token;
|
|
||||||
S64 indent;
|
S64 indent;
|
||||||
String_Builder gen;
|
String_Builder gen;
|
||||||
};
|
};
|
||||||
|
|||||||
5
main.cpp
5
main.cpp
@@ -164,7 +164,7 @@ Expr:
|
|||||||
#include "parsing.cpp"
|
#include "parsing.cpp"
|
||||||
#include "typechecking.h"
|
#include "typechecking.h"
|
||||||
#include "typechecking.cpp"
|
#include "typechecking.cpp"
|
||||||
// #include "ccodegen.cpp"
|
#include "ccodegen.cpp"
|
||||||
#include "tests.cpp"
|
#include "tests.cpp"
|
||||||
|
|
||||||
int main(int argument_count, char **arguments){
|
int main(int argument_count, char **arguments){
|
||||||
@@ -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);
|
||||||
compile_files(files);
|
String result = compile_files(files);
|
||||||
|
printf("%s", result.str);
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package lambdas
|
package lambdas
|
||||||
|
|
||||||
other_func :: ()
|
|
||||||
a_val := recursive_lambda
|
|
||||||
|
|
||||||
recursive_lambda :: (thing: S64)
|
recursive_lambda :: (thing: S64)
|
||||||
in_val := recursive_lambda
|
in_val := recursive_lambda
|
||||||
some_value := thing + const_in_lambda
|
some_value := thing + const_in_lambda
|
||||||
|
|
||||||
|
other_func :: ()
|
||||||
|
a_val := recursive_lambda
|
||||||
|
|
||||||
const_in_lambda :: 10
|
const_in_lambda :: 10
|
||||||
|
|
||||||
not_const := val + 10
|
not_const := val + 10
|
||||||
|
|||||||
49
parsing.cpp
49
parsing.cpp
@@ -33,7 +33,7 @@ function Token *
|
|||||||
token_get(S64 i = 0){
|
token_get(S64 i = 0){
|
||||||
i += pctx->token_iter;
|
i += pctx->token_iter;
|
||||||
if(i >= pctx->tokens.len){
|
if(i >= pctx->tokens.len){
|
||||||
return &pctx->empty_token;
|
return &null_token;
|
||||||
}
|
}
|
||||||
Token *result = &pctx->tokens[i];
|
Token *result = &pctx->tokens[i];
|
||||||
return result;
|
return result;
|
||||||
@@ -122,10 +122,18 @@ parse_init_stmt(Ast_Expr *expr){
|
|||||||
if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT)
|
if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT)
|
||||||
compiler_error(expr->pos, "Binding with [:=] to something that is not an identifier");
|
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();
|
token_next();
|
||||||
Ast_Expr *value = parse_expr();
|
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);
|
result->flags = set_flag(result->flags, AST_STMT);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -176,9 +184,9 @@ parse_optional_type(){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Block *
|
function Ast_Scope *
|
||||||
parse_block(){
|
parse_stmt_scope(){
|
||||||
Ast_Block *block = 0;
|
Ast_Scope *block = 0;
|
||||||
|
|
||||||
if(token_expect(OPEN_SCOPE)){ // @todo: Fix error message here, it doesn't show proper token context
|
if(token_expect(OPEN_SCOPE)){ // @todo: Fix error message here, it doesn't show proper token context
|
||||||
Token *token_block = token_get();
|
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));
|
stmts.add(ast_for(token, init, cond, iter, for_block));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +240,7 @@ parse_block(){
|
|||||||
}
|
}
|
||||||
if(init_val == expr) init_val = 0;
|
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);
|
Ast_If_Node *if_node = ast_if_node(token, init_val, expr, if_block);
|
||||||
if_nodes.add(if_node);
|
if_nodes.add(if_node);
|
||||||
|
|
||||||
@@ -241,12 +249,12 @@ parse_block(){
|
|||||||
token = token_next();
|
token = token_next();
|
||||||
if(token_match_keyword(keyword_if)){
|
if(token_match_keyword(keyword_if)){
|
||||||
Ast_Expr *expr = parse_expr();
|
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);
|
Ast_If_Node *if_node = ast_if_node(token, 0, expr, else_if_block);
|
||||||
if_nodes.add(if_node);
|
if_nodes.add(if_node);
|
||||||
}
|
}
|
||||||
else{
|
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);
|
Ast_If_Node *if_node = ast_if_node(token, 0, 0, else_block);
|
||||||
if_nodes.add(if_node);
|
if_nodes.add(if_node);
|
||||||
break;
|
break;
|
||||||
@@ -274,7 +282,7 @@ parse_block(){
|
|||||||
}
|
}
|
||||||
} while(token_match(SAME_SCOPE));
|
} while(token_match(SAME_SCOPE));
|
||||||
token_expect(CLOSE_SCOPE);
|
token_expect(CLOSE_SCOPE);
|
||||||
block = ast_block(token_block, stmts);
|
block = ast_stmt_scope(token_block, stmts);
|
||||||
}
|
}
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
@@ -284,7 +292,7 @@ parse_lambda(Token *token){
|
|||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
|
|
||||||
B32 has_var_args = false;
|
B32 has_var_args = false;
|
||||||
Array<Ast_Lambda_Arg *> params = {scratch};
|
Array<Ast_Decl *> params = {scratch};
|
||||||
if(!token_is(TK_CloseParen)){
|
if(!token_is(TK_CloseParen)){
|
||||||
for(;;){
|
for(;;){
|
||||||
Token *name = token_get();
|
Token *name = token_get();
|
||||||
@@ -297,7 +305,7 @@ parse_lambda(Token *token){
|
|||||||
default_value = parse_expr();
|
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);
|
params.add(param);
|
||||||
}
|
}
|
||||||
else if(token_match(TK_ThreeDots)){
|
else if(token_match(TK_ThreeDots)){
|
||||||
@@ -313,8 +321,8 @@ parse_lambda(Token *token){
|
|||||||
token_expect(TK_CloseParen);
|
token_expect(TK_CloseParen);
|
||||||
|
|
||||||
Ast_Expr *ret = parse_optional_type();
|
Ast_Expr *ret = parse_optional_type();
|
||||||
Ast_Block *block = token_is(OPEN_SCOPE) ? parse_block() : 0;
|
Ast_Scope *scope = token_is(OPEN_SCOPE) ? parse_stmt_scope() : 0;
|
||||||
Ast_Lambda *result = ast_lambda(token, params, has_var_args, ret, block);
|
Ast_Lambda *result = ast_lambda(token, params, has_var_args, ret, scope);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,10 +578,17 @@ parse_decl(B32 is_global){
|
|||||||
result = parse_enum(tname);
|
result = parse_enum(tname);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @note parse constant expression
|
|
||||||
else{
|
else{
|
||||||
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){
|
||||||
|
auto a = (Ast_Lambda *)expr;
|
||||||
|
if(a->scope){
|
||||||
|
result->kind = AST_LAMBDA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(token_match(TK_Identifier, TK_Colon)){
|
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 CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast;
|
||||||
#define BREAK() } break
|
#define BREAK() } break
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Evaluating constant expressions
|
// Evaluating constant expressions
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -313,16 +312,6 @@ _rewrite_into_const(Ast *node, U64 ast_size, Value value){
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#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
|
function Operand
|
||||||
require_const_int(Ast_Expr *expr, B32 ast_can_be_null){
|
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;
|
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
|
#endif
|
||||||
|
|
||||||
#define Enter_Scope(x) Enter_Scope_Defer package_scope(x)
|
#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;
|
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
|
function void
|
||||||
resolve_decl(Ast_Decl *ast){
|
resolve_decl(Ast_Decl *ast){
|
||||||
if(ast->state == DECL_RESOLVED){
|
if(ast->state == DECL_RESOLVED){
|
||||||
@@ -1024,47 +1145,90 @@ resolve_decl(Ast_Decl *ast){
|
|||||||
|
|
||||||
ast->state = DECL_RESOLVING;
|
ast->state = DECL_RESOLVING;
|
||||||
{
|
{
|
||||||
Operand result = {};
|
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
CASE(LAMBDA, Decl){
|
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();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(ENUM, Decl){
|
CASE(ENUM, Decl){
|
||||||
// Ast_Resolved_Type *type = type_enum(node);
|
node->type = type_enum(node);
|
||||||
// S64 scope_index = scope_open();
|
Enter_Scope(node->scope);
|
||||||
// S64 value = 0;
|
S64 value = 0;
|
||||||
// For(node->members){
|
For(node->scope->decls){
|
||||||
// Operand op = require_const_int(it->value, AST_CAN_BE_NULL);
|
Operand op = {};
|
||||||
// if(op.type){
|
if(it->expr){
|
||||||
// value = bigint_as_signed(&op.big_int_val) + 1;
|
op = require_const_int(it->expr, AST_CANT_BE_NULL);
|
||||||
// }
|
value = bigint_as_signed(&op.big_int_val) + 1;
|
||||||
// else{
|
} else{
|
||||||
// op.type = untyped_int;
|
op.type = untyped_int;
|
||||||
// bigint_init_signed(&op.big_int_val, value++);
|
bigint_init_signed(&op.big_int_val, value++);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// sym_const(it->name, op, it, INSERT_INTO_SCOPE);
|
it->value = op.value;
|
||||||
// }
|
}
|
||||||
// scope_close(scope_index);
|
|
||||||
// return operand_type(type);
|
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
CASE(STRUCT, Decl){
|
|
||||||
// Ast_Resolved_Type *type = type_struct(node);
|
|
||||||
// return operand_type(type);
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
}
|
}
|
||||||
// Operand op = resolve_binding(ast->ast, ast);
|
|
||||||
// ast->value = op.value;
|
|
||||||
}
|
}
|
||||||
ast->state = DECL_RESOLVED;
|
ast->state = DECL_RESOLVED;
|
||||||
|
|
||||||
pctx->resolving_package->resolved.add(ast);
|
pctx->ordered_decls.add(ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Decl *
|
function Ast_Decl *
|
||||||
@@ -1081,7 +1245,7 @@ resolve_package(Ast_Package *package){
|
|||||||
For(package->decls){
|
For(package->decls){
|
||||||
resolve_name(it->pos, it->name);
|
resolve_name(it->pos, it->name);
|
||||||
if(it->kind == AST_STRUCT){
|
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;
|
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;
|
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
|
#if 0
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Symbols
|
// Symbols
|
||||||
@@ -30,7 +34,7 @@ struct Sym{
|
|||||||
INLINE_VALUE_FIELDS;
|
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 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 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);
|
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;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
#endif
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Operands
|
// Operands
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
function Operand
|
function Operand
|
||||||
operand(Sym *sym){
|
operand(Ast_Decl *sym){
|
||||||
Operand result = {};
|
Operand result = {};
|
||||||
result.type = sym->type;
|
result.type = sym->type;
|
||||||
result.is_const = sym->kind == SYM_CONST ? true : false;
|
result.is_const = sym->kind == AST_CONST ? true : false;
|
||||||
result.is_lvalue= sym->kind == SYM_CONST ? false : true; // Cant assign to const values
|
result.is_lvalue= sym->kind == AST_CONST ? false : true; // Cant assign to const values
|
||||||
result.value = sym->value;
|
result.value = sym->value;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -256,7 +238,7 @@ operand_rvalue(Ast_Resolved_Type *type){
|
|||||||
result.is_lvalue = false;
|
result.is_lvalue = false;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Hash consed types
|
// Hash consed types
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -337,8 +319,7 @@ type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
|
|||||||
|
|
||||||
function Ast_Resolved_Type *
|
function Ast_Resolved_Type *
|
||||||
type_enum(Ast_Decl *ast){
|
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){
|
if(!type){
|
||||||
type = untyped_int;
|
type = untyped_int;
|
||||||
}
|
}
|
||||||
@@ -349,24 +330,13 @@ type_enum(Ast_Decl *ast){
|
|||||||
return result;
|
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 *
|
function Ast_Resolved_Type *
|
||||||
type_incomplete(Ast *ast){
|
type_incomplete(Ast *ast){
|
||||||
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0);
|
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_INCOMPLETE, 0, 0);
|
||||||
result->ast = ast;
|
result->ast = ast;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
function void
|
function void
|
||||||
type_struct_complete(Ast_Resolved_Type *type, Ast_Decl *node){
|
type_struct_complete(Ast_Resolved_Type *type, Ast_Decl *node){
|
||||||
assert(node->kind == AST_STRUCT);
|
assert(node->kind == AST_STRUCT);
|
||||||
@@ -376,34 +346,11 @@ type_struct_complete(Ast_Resolved_Type *type, Ast_Decl *node){
|
|||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast_Resolved_Member> members = {scratch};
|
Array<Ast_Resolved_Member> members = {scratch};
|
||||||
For(node->scope->decls){
|
For(node->scope->decls){
|
||||||
Operand op = resolve_decl(it);
|
resolve_decl(it);
|
||||||
Intern_String name = ast_get_name(it);
|
members.add({it->type, it->name});
|
||||||
sym_var(name, op, it);
|
|
||||||
members.add({op.type, name});
|
|
||||||
}
|
}
|
||||||
type->agg.members = members.tight_copy(pctx->perm);
|
type->agg.members = members.tight_copy(pctx->perm);
|
||||||
type->kind = TYPE_STRUCT;
|
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
|
function void
|
||||||
@@ -418,9 +365,7 @@ type_complete(Ast_Resolved_Type *type){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Struct *node = (Ast_Struct *)type->ast;
|
type_struct_complete(type, (Ast_Decl *)type->ast);
|
||||||
type_struct_complete(type, node);
|
pctx->ordered_decls.add((Ast_Decl *)type->ast);
|
||||||
pctx->resolving_package->ordered.add((Ast_Named *)node->parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
1
types.h
1
types.h
@@ -227,6 +227,7 @@ global Ast_Resolved_Type *untyped_float = &type__untyped_float;
|
|||||||
// Type constructors and utillities
|
// Type constructors and utillities
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
force_inline B32 is_struct(Ast_Resolved_Type *a){return a->kind == TYPE_STRUCT;}
|
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_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_enum(Ast_Resolved_Type *a){return a->kind == TYPE_ENUM;}
|
||||||
force_inline B32 is_pointer(Ast_Resolved_Type *a){return a->kind == TYPE_POINTER;}
|
force_inline B32 is_pointer(Ast_Resolved_Type *a){return a->kind == TYPE_POINTER;}
|
||||||
|
|||||||
Reference in New Issue
Block a user