Basic resolving, codegen with packages

This commit is contained in:
Krzosa Karol
2022-06-10 10:35:10 +02:00
parent fbe911d267
commit b0077fe9df
9 changed files with 553 additions and 433 deletions

96
ast.cpp
View File

@@ -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,20 +139,14 @@ 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;
Ast_Expr *ret;
Ast_Block *block;
B32 has_var_args;
Array<Ast_Decl *> args;
Ast_Expr *ret;
Ast_Scope *scope;
B32 has_var_args;
};
struct Ast_Array: Ast_Expr{
@@ -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;
}

View File

@@ -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{
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(")");
}
// 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);
CASE(LAMBDA, Decl){
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:{
gen("// F64 %s = ", node->name.str);
gen_value(sym->value);
gen_value(node->value);
} break;
CASE_INT:{
gen("// constant int %s = ", node->name.str);
gen_value(sym->value);
gen_value(node->value);
}break;
CASE_STRING:{
gen("// const String %s = ", node->name.str);
gen_value(sym->value);
gen_value(node->value);
}break;
CASE_BOOL:{
gen("// const Bool %s = ", node->name.str);
gen_value(sym->value);
gen_value(node->value);
}break;
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;
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;
}

View File

@@ -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;
};

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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 *value = parse_expr();
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)){

View File

@@ -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 {};
}

View File

@@ -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

View File

@@ -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;}