More work on order independent bindings, A bit more cleanup, Delete some of the null code, no longer valid c code
This commit is contained in:
98
ccodegen.cpp
98
ccodegen.cpp
@@ -20,15 +20,15 @@ gen_indent(){
|
|||||||
function void
|
function void
|
||||||
gen_simple_decl_prefix(Ast_Resolved_Type *ast){
|
gen_simple_decl_prefix(Ast_Resolved_Type *ast){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
case TYPE_Int: gen("int "); break;
|
case TYPE_INT: gen("int "); break;
|
||||||
case TYPE_Bool: gen("bool "); break;
|
case TYPE_BOOL: gen("bool "); break;
|
||||||
case TYPE_Unsigned: gen("unsigned "); break;
|
case TYPE_UNSIGNED: gen("unsigned "); break;
|
||||||
case TYPE_String: gen("String "); break;
|
case TYPE_STRING: gen("String "); break;
|
||||||
case TYPE_Void: gen("void "); break;
|
case TYPE_VOID: gen("void "); break;
|
||||||
case TYPE_Pointer:{gen_simple_decl_prefix(ast->base); gen("*");} break;
|
case TYPE_POINTER:{gen_simple_decl_prefix(ast->base); gen("*");} break;
|
||||||
case TYPE_Array: gen_simple_decl_prefix(ast->base); break;
|
case TYPE_ARRAY: gen_simple_decl_prefix(ast->base); break;
|
||||||
case TYPE_Lambda:break;
|
case TYPE_LAMBDA:break;
|
||||||
case TYPE_Struct: {
|
case TYPE_STRUCT: {
|
||||||
auto name = ast->sym->name;
|
auto name = ast->sym->name;
|
||||||
gen("%s ", name.str);
|
gen("%s ", name.str);
|
||||||
}break;
|
}break;
|
||||||
@@ -39,22 +39,22 @@ gen_simple_decl_prefix(Ast_Resolved_Type *ast){
|
|||||||
function void
|
function void
|
||||||
gen_simple_decl_postfix(Ast_Resolved_Type *ast){
|
gen_simple_decl_postfix(Ast_Resolved_Type *ast){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
case TYPE_Int: break;
|
case TYPE_INT: break;
|
||||||
case TYPE_Bool: break;
|
case TYPE_BOOL: break;
|
||||||
case TYPE_Unsigned: break;
|
case TYPE_UNSIGNED: break;
|
||||||
case TYPE_String: break;
|
case TYPE_STRING: break;
|
||||||
case TYPE_Void: break;
|
case TYPE_VOID: break;
|
||||||
case TYPE_Pointer: gen_simple_decl_postfix(ast->base); break;
|
case TYPE_POINTER: gen_simple_decl_postfix(ast->base); break;
|
||||||
case TYPE_Array: gen("[%d]", (int)ast->arr.size); gen_simple_decl_postfix(ast->arr.base); break;
|
case TYPE_ARRAY: gen("[%d]", (int)ast->arr.size); gen_simple_decl_postfix(ast->arr.base); break;
|
||||||
case TYPE_Lambda:break;
|
case TYPE_LAMBDA:break;
|
||||||
case TYPE_Struct:break;
|
case TYPE_STRUCT:break;
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){
|
gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){
|
||||||
if(ast->kind == TYPE_Lambda) {
|
if(ast->kind == TYPE_LAMBDA) {
|
||||||
gen_simple_decl_prefix(ast->func.ret);
|
gen_simple_decl_prefix(ast->func.ret);
|
||||||
gen("(*%s)(", name.str);
|
gen("(*%s)(", name.str);
|
||||||
For(ast->func.args){
|
For(ast->func.args){
|
||||||
@@ -75,39 +75,39 @@ gen_simple_decl(Ast_Resolved_Type *ast, Intern_String name){
|
|||||||
function void
|
function void
|
||||||
gen_expr(Ast_Expr *ast){
|
gen_expr(Ast_Expr *ast){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
Ast_Begin(AST_IDENT, Ast_Atom){
|
CASE(IDENT, Atom){
|
||||||
gen("%s", node->intern_val.str);
|
gen("%s", node->intern_val.str);
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_INT, Ast_Atom){
|
CASE(INT, Atom){
|
||||||
gen("%lld", node->int_val);
|
gen("%lld", node->int_val);
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_STR, Ast_Atom){
|
CASE(STR, Atom){
|
||||||
gen("LIT(\"%s\")", node->intern_val.str);
|
gen("LIT(\"%s\")", node->intern_val.str);
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_INDEX, Ast_Index){
|
CASE(INDEX, Index){
|
||||||
gen_expr(node->expr);
|
gen_expr(node->expr);
|
||||||
gen("[");
|
gen("[");
|
||||||
gen_expr(node->index);
|
gen_expr(node->index);
|
||||||
gen("]");
|
gen("]");
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_BINARY, Ast_Binary){
|
CASE(BINARY, Binary){
|
||||||
gen("(");
|
gen("(");
|
||||||
gen_expr(node->left);
|
gen_expr(node->left);
|
||||||
gen("%s", token_kind_string(node->op).str);
|
gen("%s", token_kind_string(node->op).str);
|
||||||
gen_expr(node->right);
|
gen_expr(node->right);
|
||||||
gen(")");
|
gen(")");
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_UNARY, Ast_Unary){
|
CASE(UNARY, Unary){
|
||||||
switch(node->op){
|
switch(node->op){
|
||||||
case TK_Pointer: {
|
case TK_Pointer: {
|
||||||
gen("(*");
|
gen("(*");
|
||||||
@@ -121,20 +121,20 @@ gen_expr(Ast_Expr *ast){
|
|||||||
} break;
|
} break;
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
}
|
}
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_CAST, Ast_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(")");
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_COMPOUND, Ast_Compound){
|
CASE(COMPOUND, Compound){
|
||||||
gen("(");
|
gen("(");
|
||||||
gen_simple_decl(node->type, {});
|
gen_simple_decl(node->type, {});
|
||||||
gen(")");
|
gen(")");
|
||||||
@@ -159,7 +159,7 @@ gen_expr(Ast_Expr *ast){
|
|||||||
}
|
}
|
||||||
gen("}");
|
gen("}");
|
||||||
|
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
@@ -184,25 +184,25 @@ function void
|
|||||||
gen_ast(Ast *ast){
|
gen_ast(Ast *ast){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
|
|
||||||
Ast_Begin(AST_PACKAGE, Ast_Package){
|
CASE(PACKAGE, Package){
|
||||||
For(node->ordered) {
|
For(node->ordered) {
|
||||||
genln("");
|
genln("");
|
||||||
gen_ast(*it);
|
gen_ast(*it);
|
||||||
}
|
}
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_RETURN, Ast_Return){
|
CASE(RETURN, Return){
|
||||||
gen("return");
|
gen("return");
|
||||||
if(node->expr){
|
if(node->expr){
|
||||||
gen(" ");
|
gen(" ");
|
||||||
gen_expr(node->expr);
|
gen_expr(node->expr);
|
||||||
}
|
}
|
||||||
gen(";");
|
gen(";");
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_VAR, Ast_Var){
|
CASE(VAR, Var){
|
||||||
Sym *sym = resolved_get(node);
|
Sym *sym = resolved_get(node);
|
||||||
gen_simple_decl(sym->type, node->name);
|
gen_simple_decl(sym->type, node->name);
|
||||||
if(node->expr){
|
if(node->expr){
|
||||||
@@ -210,10 +210,10 @@ gen_ast(Ast *ast){
|
|||||||
gen_expr(node->expr);
|
gen_expr(node->expr);
|
||||||
}
|
}
|
||||||
gen(";");
|
gen(";");
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_INIT, Ast_Init){
|
CASE(INIT, Init){
|
||||||
Sym *sym = resolved_get(node);
|
Sym *sym = resolved_get(node);
|
||||||
gen_simple_decl(sym->type, node->ident->intern_val);
|
gen_simple_decl(sym->type, node->ident->intern_val);
|
||||||
if(node->expr){
|
if(node->expr){
|
||||||
@@ -221,10 +221,10 @@ gen_ast(Ast *ast){
|
|||||||
gen_expr(node->expr);
|
gen_expr(node->expr);
|
||||||
}
|
}
|
||||||
gen(";");
|
gen(";");
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_IF, Ast_If){
|
CASE(IF, If){
|
||||||
For(node->ifs){
|
For(node->ifs){
|
||||||
if(it[0]->init) gen_ast(it[0]->init);
|
if(it[0]->init) gen_ast(it[0]->init);
|
||||||
if(node->ifs.is_first(it)){
|
if(node->ifs.is_first(it)){
|
||||||
@@ -243,13 +243,13 @@ gen_ast(Ast *ast){
|
|||||||
gen_block(it[0]->block);
|
gen_block(it[0]->block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_CONST, Ast_Const){
|
CASE(CONST, Const){
|
||||||
Sym *sym = resolved_get(node);
|
Sym *sym = resolved_get(node);
|
||||||
|
|
||||||
if(sym->type->kind == TYPE_Lambda){
|
if(sym->type->kind == TYPE_LAMBDA){
|
||||||
if(node->value->kind == AST_LAMBDA){
|
if(node->value->kind == AST_LAMBDA){
|
||||||
Ast_Lambda *lambda = (Ast_Lambda *)node->value;
|
Ast_Lambda *lambda = (Ast_Lambda *)node->value;
|
||||||
gen("static ");
|
gen("static ");
|
||||||
@@ -283,7 +283,7 @@ gen_ast(Ast *ast){
|
|||||||
gen("String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str);
|
gen("String %s = LIT(\"%s\");", node->name.str, sym->intern_val.str);
|
||||||
}
|
}
|
||||||
else if(sym->type == type_type){
|
else if(sym->type == type_type){
|
||||||
if(sym->type_val->kind == TYPE_Struct){
|
if(sym->type_val->kind == TYPE_STRUCT){
|
||||||
Ast_Struct *agg = const_get_struct(sym->type_val->sym->ast);
|
Ast_Struct *agg = const_get_struct(sym->type_val->sym->ast);
|
||||||
if(node->value->kind == AST_STRUCT){
|
if(node->value->kind == AST_STRUCT){
|
||||||
gen("struct %s{", node->name.str);
|
gen("struct %s{", node->name.str);
|
||||||
@@ -309,7 +309,7 @@ gen_ast(Ast *ast){
|
|||||||
parsing_error(node->pos, "C_Codegen: Unhandled type of constant expression");
|
parsing_error(node->pos, "C_Codegen: Unhandled type of constant expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
|
|||||||
1
main.cpp
1
main.cpp
@@ -3,7 +3,6 @@
|
|||||||
#include "new_lex.cpp"
|
#include "new_lex.cpp"
|
||||||
#include "new_ast.cpp"
|
#include "new_ast.cpp"
|
||||||
#include "new_parse.cpp"
|
#include "new_parse.cpp"
|
||||||
#include "new_type.cpp"
|
|
||||||
#include "new_resolve.cpp"
|
#include "new_resolve.cpp"
|
||||||
#include "ccodegen.cpp"
|
#include "ccodegen.cpp"
|
||||||
|
|
||||||
|
|||||||
24
new_ast.cpp
24
new_ast.cpp
@@ -226,7 +226,11 @@ struct Ast_Var: Ast_Named{
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Const: Ast_Named{
|
struct Ast_Const: Ast_Named{
|
||||||
Ast_Expr *value;
|
union{
|
||||||
|
Ast *ast;
|
||||||
|
Ast_Expr *value;
|
||||||
|
Ast_Struct *agg;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Package:Ast{
|
struct Ast_Package:Ast{
|
||||||
@@ -460,3 +464,21 @@ ast_package(Token *pos, String name, Array<Ast_Named *> decls){
|
|||||||
For(result->decls) it[0]->parent = result;
|
For(result->decls) it[0]->parent = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Utillities
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
function Ast_Struct *
|
||||||
|
const_get_struct(Ast *ast){
|
||||||
|
assert(ast->kind == AST_CONST);
|
||||||
|
Ast_Const *constant = (Ast_Const *)ast;
|
||||||
|
assert(constant->value->kind == AST_STRUCT);
|
||||||
|
return (Ast_Struct *)constant->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Intern_String
|
||||||
|
ast_get_name(Ast *ast){
|
||||||
|
assert(is_flag_set(ast->flags, AST_BINDING));
|
||||||
|
auto constant = (Ast_Named *)ast;
|
||||||
|
return constant->name;
|
||||||
|
}
|
||||||
|
|||||||
241
new_resolve.cpp
241
new_resolve.cpp
@@ -1,5 +1,5 @@
|
|||||||
#define Ast_Begin(kind,type) case kind: { type *node = (type *)ast;
|
#define CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast;
|
||||||
#define Ast_End() } break
|
#define BREAK() } break
|
||||||
|
|
||||||
enum Sym_Kind{
|
enum Sym_Kind{
|
||||||
SYM_NONE,
|
SYM_NONE,
|
||||||
@@ -37,6 +37,14 @@ struct Operand{
|
|||||||
INLINE_VALUE_FIELDS;
|
INLINE_VALUE_FIELDS;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum{
|
||||||
|
AST_CANT_BE_NULL = 0,
|
||||||
|
AST_CAN_BE_NULL = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
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_binding(Ast *ast, Sym *sym = 0);
|
||||||
global Ast_Named empty_decl = {};
|
global Ast_Named empty_decl = {};
|
||||||
|
|
||||||
function void
|
function void
|
||||||
@@ -104,6 +112,7 @@ resolved_get(Ast *ast){
|
|||||||
assert(result);
|
assert(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#include "new_type.cpp"
|
||||||
|
|
||||||
function Ast_Resolved_Type *
|
function Ast_Resolved_Type *
|
||||||
resolved_type_get(Ast_Expr *ast){
|
resolved_type_get(Ast_Expr *ast){
|
||||||
@@ -150,18 +159,10 @@ sym_insert_builtins(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Sym *resolve_name(Token *pos, Intern_String name);
|
|
||||||
function Operand eval_expr(Ast_Expr *ast, Ast_Resolved_Type *compound_required_type = 0, Sym *lambda_to_complete = 0);
|
|
||||||
|
|
||||||
enum{
|
|
||||||
AST_CANT_BE_NULL = 0,
|
|
||||||
AST_CAN_BE_NULL = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
function Ast_Resolved_Type *
|
function Ast_Resolved_Type *
|
||||||
eval_typespec(Ast_Expr *ast, B32 ast_can_be_null = AST_CANT_BE_NULL){
|
resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null = AST_CANT_BE_NULL){
|
||||||
if(ast_can_be_null && ast == 0) return 0;
|
if(ast_can_be_null && ast == 0) return 0;
|
||||||
Operand resolved = eval_expr(ast);
|
Operand resolved = resolve_expr(ast);
|
||||||
if(resolved.type != type_type) parsing_error(ast->pos, "Expected [Type] got instead %s", resolved.type->kind);
|
if(resolved.type != type_type) parsing_error(ast->pos, "Expected [Type] got instead %s", resolved.type->kind);
|
||||||
return resolved.type_val;
|
return resolved.type_val;
|
||||||
}
|
}
|
||||||
@@ -173,67 +174,66 @@ resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){
|
|||||||
else if(a && !b) result = a;
|
else if(a && !b) result = a;
|
||||||
else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are [Null]");
|
else if(!a && !b) parsing_error(pos, "Trying to resolve a type pair where both types are [Null]");
|
||||||
else{ // a && b
|
else{ // a && b
|
||||||
if(b->kind == TYPE_Null) result = a;
|
if(b->kind == TYPE_NULL) result = a;
|
||||||
else if(a->kind == TYPE_Null) result = b;
|
else if(a->kind == TYPE_NULL) result = b;
|
||||||
else if(a != b) parsing_error(pos, "Expression and type specification are differing %s %s", type_names[a->kind], type_names[b->kind]);
|
else if(a != b) parsing_error(pos, "Expression and type specification are differing %s %s", type_names[a->kind], type_names[b->kind]);
|
||||||
else result = a; // Types are the same
|
else result = a; // Types are the same
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result->kind == TYPE_Null) parsing_error(pos, "Couldn't infer type of null value");
|
if(result->kind == TYPE_NULL) parsing_error(pos, "Couldn't infer type of null value");
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Operand eval_binding(Ast *ast, Sym *sym = 0);
|
|
||||||
function void
|
function void
|
||||||
eval_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
Ast_Begin(AST_RETURN, Ast_Return){ // @todo: need to check if all paths return a value
|
CASE(RETURN, Return){ // @todo: need to check if all paths return a value
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
if(node->expr) op = eval_expr(node->expr);
|
if(node->expr) op = resolve_expr(node->expr);
|
||||||
if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is [x]");
|
if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is [x]");
|
||||||
if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value");
|
if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value");
|
||||||
|
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_VAR, Ast_Var){
|
CASE(VAR, Var){
|
||||||
Operand op = eval_binding(node);
|
Operand op = resolve_binding(node);
|
||||||
Sym *sym = sym_new_resolved(SYM_VAR, node->name, op.type, op.value, node);
|
Sym *sym = sym_new_resolved(SYM_VAR, node->name, op.type, op.value, node);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_CONST, Ast_Const){
|
CASE(CONST, Const){
|
||||||
Operand op = eval_binding(node);
|
Operand op = resolve_binding(node);
|
||||||
Sym *sym = sym_new_resolved(SYM_CONST, node->name, op.type, op.value, node);
|
Sym *sym = sym_new_resolved(SYM_CONST, node->name, op.type, op.value, node);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_INIT, Ast_Init){
|
CASE(INIT, Init){
|
||||||
switch(node->op){
|
switch(node->op){
|
||||||
case TK_Comma:{
|
case TK_Comma:{
|
||||||
Operand op = eval_expr(node->expr);
|
Operand op = resolve_expr(node->expr);
|
||||||
Sym *sym = sym_new_resolved(SYM_VAR, node->ident->intern_val, op.type, op.value, node);
|
Sym *sym = sym_new_resolved(SYM_VAR, node->ident->intern_val, op.type, op.value, node);
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
}break;
|
}break;
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
}
|
}
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_IF, Ast_If){
|
CASE(IF, If){
|
||||||
For(node->ifs){
|
For(node->ifs){
|
||||||
if(it[0]->init) eval_stmt(it[0]->init, ret);
|
if(it[0]->init) resolve_stmt(it[0]->init, ret);
|
||||||
if(it[0]->expr) eval_expr(it[0]->expr);
|
if(it[0]->expr) resolve_expr(it[0]->expr);
|
||||||
S64 scope_index = scope_open();
|
S64 scope_index = scope_open();
|
||||||
For_It(it[0]->block->stmts, jt){
|
For_It(it[0]->block->stmts, jt){
|
||||||
eval_stmt(jt[0], ret);
|
resolve_stmt(jt[0], ret);
|
||||||
}
|
}
|
||||||
scope_close(scope_index);
|
scope_close(scope_index);
|
||||||
}
|
}
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
@@ -241,29 +241,29 @@ eval_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_complete){
|
resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *const_sym){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
Ast_Begin(AST_INT, Ast_Atom){
|
CASE(INT, Atom){
|
||||||
Operand result = {type_int, true};
|
Operand result = {type_int, true};
|
||||||
result.int_val = node->int_val;
|
result.int_val = node->int_val;
|
||||||
return result;
|
return result;
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_STR, Ast_Atom){
|
CASE(STR, Atom){
|
||||||
Operand result = {type_string, true};
|
Operand result = {type_string, true};
|
||||||
result.intern_val = node->intern_val;
|
result.intern_val = node->intern_val;
|
||||||
return result;
|
return result;
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_IDENT, Ast_Atom){
|
CASE(IDENT, Atom){
|
||||||
Sym *sym = resolve_name(node->pos, node->intern_val);
|
Sym *sym = resolve_name(node->pos, node->intern_val);
|
||||||
|
|
||||||
// @cleanup: due to Value being a union this portion probably can get cleaned
|
// @cleanup: due to Value being a union this portion probably can get cleaned
|
||||||
// @note: check if null and rewrite the expression to match the expected type
|
// @note: check if null and rewrite the expression to match the expected type
|
||||||
Operand result = {};
|
Operand result = {};
|
||||||
if(sym->type->kind == TYPE_Null){
|
if(sym->type->kind == TYPE_NULL){
|
||||||
if(!expected_type) parsing_error(node->pos, "Couldn't infer type of null");
|
if(!expected_type) parsing_error(node->pos, "Couldn't infer type of null");
|
||||||
result.type = expected_type;
|
result.type = expected_type;
|
||||||
result.is_const = true;
|
result.is_const = true;
|
||||||
@@ -277,30 +277,30 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple
|
|||||||
else invalid_codepath;
|
else invalid_codepath;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_ARRAY, Ast_Array){
|
CASE(ARRAY, Array){
|
||||||
Operand type = eval_expr(node->base);
|
Operand type = resolve_expr(node->base);
|
||||||
if(type.type != type_type) parsing_error(node->pos, "Prefix array operator is only allowed on types");
|
if(type.type != type_type) parsing_error(node->pos, "Prefix array operator is only allowed on types");
|
||||||
Operand expr = eval_expr(node->expr);
|
Operand expr = resolve_expr(node->expr);
|
||||||
if(!expr.is_const) parsing_error(node->pos, "Array operator requires a constant value");
|
if(!expr.is_const) parsing_error(node->pos, "Array operator requires a constant value");
|
||||||
if(expr.type != type_int) parsing_error(node->pos, "Array index requires type [Int]");
|
if(expr.type != type_int) parsing_error(node->pos, "Array index requires type [Int]");
|
||||||
|
|
||||||
type.type_val = type_array(type.type_val, expr.int_val);
|
type.type_val = type_array(type.type_val, expr.int_val);
|
||||||
sym_new_resolved(SYM_CONST, {}, type_type, type.value, node);
|
sym_new_resolved(SYM_CONST, {}, type_type, type.value, node);
|
||||||
return type;
|
return type;
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_LAMBDA, Ast_Lambda){
|
CASE(LAMBDA, Lambda){
|
||||||
// @note: first resolve type of lambda
|
// @note: first resolve type of lambda
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Ast_Resolved_Type *lambda_type = 0;
|
Ast_Resolved_Type *lambda_type = 0;
|
||||||
Ast_Resolved_Type *ret_type = eval_typespec(node->ret);
|
Ast_Resolved_Type *ret_type = resolve_typespec(node->ret);
|
||||||
Array<Ast_Resolved_Type *> args = {scratch};
|
Array<Ast_Resolved_Type *> args = {scratch};
|
||||||
For(node->args){
|
For(node->args){
|
||||||
Operand type = eval_expr(it[0]->typespec);
|
Operand type = resolve_expr(it[0]->typespec);
|
||||||
if(type.type != type_type) parsing_error(it[0]->pos, "Required expression of kind [type]");
|
if(type.type != type_type) parsing_error(it[0]->pos, "Required expression of kind [type]");
|
||||||
args.add(type.type_val);
|
args.add(type.type_val);
|
||||||
}
|
}
|
||||||
@@ -309,9 +309,9 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple
|
|||||||
assert(lambda_type);
|
assert(lambda_type);
|
||||||
Value val; val.type_val = lambda_type;
|
Value val; val.type_val = lambda_type;
|
||||||
sym_new_resolved(SYM_CONST, {}, type_type, val, node);
|
sym_new_resolved(SYM_CONST, {}, type_type, val, node);
|
||||||
if(lambda_to_complete){
|
if(const_sym){
|
||||||
lambda_to_complete->type = lambda_type;
|
const_sym->type = lambda_type;
|
||||||
lambda_to_complete->state = SYM_RESOLVED;
|
const_sym->state = SYM_RESOLVED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,34 +329,34 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple
|
|||||||
sym_insert(arg_sym);
|
sym_insert(arg_sym);
|
||||||
}
|
}
|
||||||
For(node->block->stmts){
|
For(node->block->stmts){
|
||||||
eval_stmt(it[0], ret_type);
|
resolve_stmt(it[0], ret_type);
|
||||||
}
|
}
|
||||||
scope_close(scope_index);
|
scope_close(scope_index);
|
||||||
result.type = lambda_type;
|
result.type = lambda_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_INDEX, Ast_Index){
|
CASE(INDEX, Index){
|
||||||
Operand left = eval_expr(node->expr);
|
Operand left = resolve_expr(node->expr);
|
||||||
Operand index = eval_expr(node->index);
|
Operand index = resolve_expr(node->index);
|
||||||
if(left.type->kind != TYPE_Array) parsing_error(node->pos, "Indexing variable that is not an array");
|
if(left.type->kind != TYPE_ARRAY) parsing_error(node->pos, "Indexing variable that is not an array");
|
||||||
if(index.type != type_int) parsing_error(node->pos, "Trying to index the array with invalid type, expected int");
|
if(index.type != type_int) parsing_error(node->pos, "Trying to index the array with invalid type, expected int");
|
||||||
Operand result = {left.type->arr.base};
|
Operand result = {left.type->arr.base};
|
||||||
return result;
|
return result;
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_COMPOUND, Ast_Compound){
|
CASE(COMPOUND, Compound){
|
||||||
Ast_Resolved_Type *type = eval_typespec(node->typespec, AST_CAN_BE_NULL);
|
Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL);
|
||||||
if(!type && expected_type) type = expected_type;
|
if(!type && expected_type) type = expected_type;
|
||||||
else if(!expected_type && type);
|
else if(!expected_type && type);
|
||||||
else if(expected_type != type) parsing_error(node->pos, "Variable type different from explicit compound type");
|
else if(expected_type != type) parsing_error(node->pos, "Variable type different from explicit compound type");
|
||||||
node->type = type;
|
node->type = type;
|
||||||
|
|
||||||
if(type->kind == TYPE_Array){
|
if(type->kind == TYPE_ARRAY){
|
||||||
if(node->exprs.len > type->arr.size) parsing_error(node->pos, "compound statement has too many items for this type");
|
if(node->exprs.len > type->arr.size) parsing_error(node->pos, "compound statement has too many items for this type");
|
||||||
Ast_Resolved_Type *item_type = type->arr.base;
|
Ast_Resolved_Type *item_type = type->arr.base;
|
||||||
|
|
||||||
@@ -366,12 +366,12 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple
|
|||||||
assert(i->kind == AST_COMPOUND_ITEM);
|
assert(i->kind == AST_COMPOUND_ITEM);
|
||||||
if(i->name) parsing_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]);
|
if(i->name) parsing_error(i->pos, "Invalid indexing kind in a compound expression of type %s", type_names[type->kind]);
|
||||||
if(i->index){
|
if(i->index){
|
||||||
Operand index_op = eval_expr(i->index);
|
Operand index_op = resolve_expr(i->index);
|
||||||
if(!index_op.is_const) parsing_error(i->pos, "Index in a compound expression is not a constant");
|
if(!index_op.is_const) parsing_error(i->pos, "Index in a compound expression is not a constant");
|
||||||
if(index_op.type != type_int) parsing_error(i->pos, "Index should be of type int");
|
if(index_op.type != type_int) parsing_error(i->pos, "Index should be of type int");
|
||||||
if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
if(index_op.int_val > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
||||||
}
|
}
|
||||||
Operand expr = eval_expr(i->item, item_type);
|
Operand expr = resolve_expr(i->item, item_type);
|
||||||
resolve_type_pair(i->pos, expr.type, item_type);
|
resolve_type_pair(i->pos, expr.type, item_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -379,12 +379,12 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple
|
|||||||
|
|
||||||
Operand result = {type, false};
|
Operand result = {type, false};
|
||||||
return result;
|
return result;
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_CAST, Ast_Cast){
|
CASE(CAST, Cast){
|
||||||
Operand expr = eval_expr(node->expr);
|
Operand expr = resolve_expr(node->expr);
|
||||||
Ast_Resolved_Type *type = eval_typespec(node->typespec);
|
Ast_Resolved_Type *type = resolve_typespec(node->typespec);
|
||||||
|
|
||||||
if(type == expr.type) return expr;
|
if(type == expr.type) return expr;
|
||||||
|
|
||||||
@@ -405,18 +405,18 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple
|
|||||||
|
|
||||||
else parsing_error(node->pos, "Failed to cast, incompatible types");
|
else parsing_error(node->pos, "Failed to cast, incompatible types");
|
||||||
|
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_UNARY, Ast_Unary){
|
CASE(UNARY, Unary){
|
||||||
Operand value = eval_expr(node->expr);
|
Operand value = resolve_expr(node->expr);
|
||||||
switch(node->op){
|
switch(node->op){
|
||||||
case TK_Pointer:{
|
case TK_Pointer:{
|
||||||
if(value.type->kind == TYPE_Pointer){
|
if(value.type->kind == TYPE_POINTER){
|
||||||
Operand result = {value.type->base};
|
Operand result = {value.type->base};
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
else if(value.type->kind == TYPE_Type){
|
else if(value.type->kind == TYPE_TYPE){
|
||||||
Operand result = {type_type, true};
|
Operand result = {type_type, true};
|
||||||
result.type_val = type_pointer(value.type_val);
|
result.type_val = type_pointer(value.type_val);
|
||||||
return result;
|
return result;
|
||||||
@@ -430,12 +430,12 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple
|
|||||||
invalid_default_case; return {};
|
invalid_default_case; return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_BINARY, Ast_Binary){
|
CASE(BINARY, Binary){
|
||||||
Operand left = eval_expr(node->left);
|
Operand left = resolve_expr(node->left);
|
||||||
Operand right = eval_expr(node->right);
|
Operand right = resolve_expr(node->right);
|
||||||
Operand result = {};
|
Operand result = {};
|
||||||
result.type = resolve_type_pair(node->pos, left.type, right.type);
|
result.type = resolve_type_pair(node->pos, left.type, right.type);
|
||||||
if(left.is_const && right.is_const){
|
if(left.is_const && right.is_const){
|
||||||
@@ -453,17 +453,17 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo: add const prepass? expecting only structs, exprs, lambdas
|
// @todo: add const prepass? expecting only structs, exprs, lambdas
|
||||||
Ast_Begin(AST_STRUCT, Ast_Struct){
|
CASE(STRUCT, Struct){
|
||||||
assert(lambda_to_complete);
|
assert(const_sym);
|
||||||
|
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast_Resolved_Type_Field> members = {scratch};
|
Array<Ast_Resolved_Member> members = {scratch};
|
||||||
For(node->members){
|
For(node->members){
|
||||||
Operand op = eval_binding(it[0]);
|
Operand op = resolve_binding(it[0]);
|
||||||
|
|
||||||
Intern_String name = {};
|
Intern_String name = {};
|
||||||
if(is_flag_set(it[0]->flags, AST_BINDING)){
|
if(is_flag_set(it[0]->flags, AST_BINDING)){
|
||||||
@@ -474,11 +474,10 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple
|
|||||||
sym_new_resolved(SYM_VAR, name, op.type, {}, it[0]);
|
sym_new_resolved(SYM_VAR, name, op.type, {}, it[0]);
|
||||||
members.add({op.type, name});
|
members.add({op.type, name});
|
||||||
}
|
}
|
||||||
Ast_Resolved_Type *resolved = type_struct(lambda_to_complete, members);
|
Ast_Resolved_Type *resolved = type_struct(const_sym, members);
|
||||||
Operand result = {type_type, true}; result.type_val = resolved;
|
Operand result = {type_type, true}; result.type_val = resolved;
|
||||||
return result;
|
return result;
|
||||||
|
BREAK();
|
||||||
Ast_End();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid_default_case;
|
invalid_default_case;
|
||||||
@@ -488,54 +487,47 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
eval_binding(Ast *ast, Sym *sym){
|
resolve_binding(Ast *ast, Sym *sym){
|
||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
|
CASE(VAR, Var){
|
||||||
Ast_Begin(AST_VAR, Ast_Var){
|
Ast_Resolved_Type *type = resolve_typespec(node->typespec, AST_CAN_BE_NULL);
|
||||||
Ast_Resolved_Type *type = eval_typespec(node->typespec, AST_CAN_BE_NULL);
|
Operand expr = node->expr ? resolve_expr(node->expr, type) : Operand{};
|
||||||
Operand expr = node->expr ? eval_expr(node->expr, type) : Operand{};
|
|
||||||
expr.type = resolve_type_pair(node->pos, type, expr.type);
|
expr.type = resolve_type_pair(node->pos, type, expr.type);
|
||||||
return expr;
|
return expr;
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ast_Begin(AST_CONST, Ast_Const){
|
CASE(CONST, Const){
|
||||||
Operand expr = eval_expr((Ast_Expr *)node->value, 0, sym);
|
Operand expr = resolve_expr((Ast_Expr *)node->value, 0, sym);
|
||||||
if(!expr.type) parsing_error(node->pos, "Constant value without expression");
|
|
||||||
if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression");
|
if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression");
|
||||||
|
assert(expr.type);
|
||||||
return expr;
|
return expr;
|
||||||
Ast_End();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid_default_case; return {};
|
invalid_default_case; return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Struct *
|
|
||||||
const_get_struct(Ast *ast){
|
|
||||||
assert(ast->kind == AST_CONST);
|
|
||||||
Ast_Const *constant = (Ast_Const *)ast;
|
|
||||||
assert(constant->value->kind == AST_STRUCT);
|
|
||||||
return (Ast_Struct *)constant->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
function void
|
function void
|
||||||
resolve_sym(Sym *sym){
|
resolve_sym(Sym *sym){
|
||||||
if(sym->state == SYM_RESOLVED) return;
|
if(sym->state == SYM_RESOLVED){
|
||||||
else if(sym->state == SYM_RESOLVING){ parsing_error(sym->ast->pos, "Cyclic dependency"); return; }
|
return;
|
||||||
|
}
|
||||||
|
else if(sym->state == SYM_RESOLVING){
|
||||||
|
parsing_error(sym->ast->pos, "Cyclic dependency");
|
||||||
|
return;
|
||||||
|
}
|
||||||
assert(sym->state == SYM_NOT_RESOLVED);
|
assert(sym->state == SYM_NOT_RESOLVED);
|
||||||
|
|
||||||
assert(sym->ast->kind == AST_VAR || sym->ast->kind == AST_CONST);
|
assert(sym->ast->kind == AST_VAR || sym->ast->kind == AST_CONST);
|
||||||
sym->state = SYM_RESOLVING;
|
|
||||||
|
|
||||||
Operand op = eval_binding(sym->ast, sym);
|
sym->state = SYM_RESOLVING;
|
||||||
sym->type = op.type;
|
{
|
||||||
if(sym->kind == SYM_CONST){
|
Operand op = resolve_binding(sym->ast, sym);
|
||||||
assert(op.is_const);
|
sym->type = op.type;
|
||||||
sym->value = op.value;
|
sym->value = op.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
sym->state = SYM_RESOLVED;
|
sym->state = SYM_RESOLVED;
|
||||||
|
|
||||||
pctx->resolving_package->ordered.add((Ast_Named *)sym->ast);
|
pctx->resolving_package->ordered.add((Ast_Named *)sym->ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -572,21 +564,18 @@ parse_file(){
|
|||||||
Ast_Named *decl = parse_named(true);
|
Ast_Named *decl = parse_named(true);
|
||||||
if(!decl) break;
|
if(!decl) break;
|
||||||
|
|
||||||
Sym_Kind kind = SYM_VAR;
|
Sym *sym = sym_new(SYM_VAR, decl->name, decl);
|
||||||
if(decl->kind == AST_CONST) kind = SYM_CONST;
|
if(decl->kind == AST_CONST) {
|
||||||
else if(decl->kind == AST_VAR) kind = SYM_VAR;
|
sym->kind = SYM_CONST;
|
||||||
else invalid_codepath;
|
auto constant = (Ast_Const *)decl;
|
||||||
|
if(constant->value->kind == AST_STRUCT){
|
||||||
|
sym->type = type_incomplete(sym);
|
||||||
|
sym->state = SYM_RESOLVED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else assert(decl->kind == AST_VAR);
|
||||||
|
|
||||||
Sym *sym = sym_new(kind, decl->name, decl);
|
|
||||||
// if(kind == SYM_CONST){
|
|
||||||
// auto constant = (Ast_Const *)decl;
|
|
||||||
// if(constant->value->kind == AST_STRUCT) {
|
|
||||||
// sym->type = type_incomplete(sym);
|
|
||||||
// sym->state = SYM_RESOLVED;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
sym_insert(sym);
|
sym_insert(sym);
|
||||||
|
|
||||||
decls.add(decl);
|
decls.add(decl);
|
||||||
}
|
}
|
||||||
Ast_Package *result = ast_package(token, token->file, decls);
|
Ast_Package *result = ast_package(token, token->file, decls);
|
||||||
|
|||||||
100
new_type.cpp
100
new_type.cpp
@@ -1,24 +1,26 @@
|
|||||||
enum Ast_Resolved_Type_Kind{
|
enum Ast_Resolved_Type_Kind{
|
||||||
TYPE_None,
|
TYPE_NONE,
|
||||||
TYPE_Null,
|
TYPE_NULL,
|
||||||
TYPE_Incomplete,
|
TYPE_COMPLETING,
|
||||||
TYPE_Int,
|
TYPE_INCOMPLETE,
|
||||||
TYPE_Bool,
|
TYPE_INT,
|
||||||
TYPE_Unsigned,
|
TYPE_BOOL,
|
||||||
TYPE_String,
|
TYPE_UNSIGNED,
|
||||||
TYPE_Void,
|
TYPE_STRING,
|
||||||
TYPE_Pointer,
|
TYPE_VOID,
|
||||||
TYPE_Array,
|
TYPE_POINTER,
|
||||||
TYPE_Lambda,
|
TYPE_ARRAY,
|
||||||
TYPE_Struct,
|
TYPE_LAMBDA,
|
||||||
TYPE_Union,
|
TYPE_STRUCT,
|
||||||
TYPE_Enum,
|
TYPE_UNION,
|
||||||
TYPE_Type,
|
TYPE_ENUM,
|
||||||
|
TYPE_TYPE,
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *type_names[] = {
|
const char *type_names[] = {
|
||||||
"[Invalid Ast_Resolved_Type]",
|
"[Invalid Ast_Resolved_Type]",
|
||||||
"[Null]",
|
"[Null]",
|
||||||
|
"[Completing]",
|
||||||
"[Incomplete]",
|
"[Incomplete]",
|
||||||
"[Int]",
|
"[Int]",
|
||||||
"[Bool]",
|
"[Bool]",
|
||||||
@@ -34,7 +36,7 @@ const char *type_names[] = {
|
|||||||
"[Type]",
|
"[Type]",
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Resolved_Type_Field{
|
struct Ast_Resolved_Member{
|
||||||
Ast_Resolved_Type *type;
|
Ast_Resolved_Type *type;
|
||||||
Intern_String name;
|
Intern_String name;
|
||||||
U64 offset;
|
U64 offset;
|
||||||
@@ -53,7 +55,7 @@ struct Ast_Resolved_Type{
|
|||||||
SizeU size;
|
SizeU size;
|
||||||
}arr;
|
}arr;
|
||||||
struct{
|
struct{
|
||||||
Array<Ast_Resolved_Type_Field> fields;
|
Array<Ast_Resolved_Member> members;
|
||||||
}agg;
|
}agg;
|
||||||
struct{
|
struct{
|
||||||
Ast_Resolved_Type *ret;
|
Ast_Resolved_Type *ret;
|
||||||
@@ -65,13 +67,13 @@ struct Ast_Resolved_Type{
|
|||||||
const SizeU pointer_size = sizeof(SizeU);
|
const SizeU pointer_size = sizeof(SizeU);
|
||||||
const SizeU pointer_align = __alignof(SizeU);
|
const SizeU pointer_align = __alignof(SizeU);
|
||||||
|
|
||||||
global Ast_Resolved_Type type__null = {TYPE_Null};
|
global Ast_Resolved_Type type__null = {TYPE_NULL};
|
||||||
global Ast_Resolved_Type type__void = {TYPE_Void};
|
global Ast_Resolved_Type type__void = {TYPE_VOID};
|
||||||
global Ast_Resolved_Type type__int = {TYPE_Int, sizeof(int), __alignof(int)};
|
global Ast_Resolved_Type type__int = {TYPE_INT, sizeof(int), __alignof(int)};
|
||||||
global Ast_Resolved_Type type__unsigned = {TYPE_Int, sizeof(unsigned), __alignof(unsigned)};
|
global Ast_Resolved_Type type__unsigned = {TYPE_INT, sizeof(unsigned), __alignof(unsigned)};
|
||||||
global Ast_Resolved_Type type__string = {TYPE_String, sizeof(String), __alignof(String)};
|
global Ast_Resolved_Type type__string = {TYPE_STRING, sizeof(String), __alignof(String)};
|
||||||
global Ast_Resolved_Type type__bool = {TYPE_Bool, sizeof(bool), __alignof(bool)};
|
global Ast_Resolved_Type type__bool = {TYPE_BOOL, sizeof(bool), __alignof(bool)};
|
||||||
global Ast_Resolved_Type type__type = {TYPE_Type};
|
global Ast_Resolved_Type type__type = {TYPE_TYPE};
|
||||||
|
|
||||||
global Ast_Resolved_Type *type_type = &type__type;
|
global Ast_Resolved_Type *type_type = &type__type;
|
||||||
global Ast_Resolved_Type *type_void = &type__void;
|
global Ast_Resolved_Type *type_void = &type__void;
|
||||||
@@ -101,11 +103,11 @@ function Ast_Resolved_Type *
|
|||||||
type_pointer(Ast_Resolved_Type *base){
|
type_pointer(Ast_Resolved_Type *base){
|
||||||
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, (void *)base);
|
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, (void *)base);
|
||||||
if(!result){
|
if(!result){
|
||||||
result = type_new(pctx->perm, TYPE_Pointer, pointer_size, pointer_align);
|
result = type_new(pctx->perm, TYPE_POINTER, pointer_size, pointer_align);
|
||||||
result->base = base;
|
result->base = base;
|
||||||
map_insert(&pctx->type_map, base, result);
|
map_insert(&pctx->type_map, base, result);
|
||||||
}
|
}
|
||||||
assert(result->kind == TYPE_Pointer);
|
assert(result->kind == TYPE_POINTER);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,13 +116,13 @@ type_array(Ast_Resolved_Type *base, SizeU size){
|
|||||||
U64 hash = hash_mix(hash_ptr(base), hash_u64(size));
|
U64 hash = hash_mix(hash_ptr(base), hash_u64(size));
|
||||||
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, hash);
|
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, hash);
|
||||||
if(result){
|
if(result){
|
||||||
assert(result->kind == TYPE_Array);
|
assert(result->kind == TYPE_ARRAY);
|
||||||
assert(result->arr.size == size);
|
assert(result->arr.size == size);
|
||||||
assert(result->arr.base == base);
|
assert(result->arr.base == base);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = type_new(pctx->perm, TYPE_Array, pointer_size, pointer_align);
|
result = type_new(pctx->perm, TYPE_ARRAY, pointer_size, pointer_align);
|
||||||
result->arr.base = base;
|
result->arr.base = base;
|
||||||
result->arr.size = size;
|
result->arr.size = size;
|
||||||
map_insert(&pctx->type_map, hash, result);
|
map_insert(&pctx->type_map, hash, result);
|
||||||
@@ -134,13 +136,13 @@ type_lambda(Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
|
|||||||
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, hash);
|
Ast_Resolved_Type *result = (Ast_Resolved_Type *)map_get(&pctx->type_map, hash);
|
||||||
|
|
||||||
if(result){
|
if(result){
|
||||||
assert(result->kind == TYPE_Lambda);
|
assert(result->kind == TYPE_LAMBDA);
|
||||||
assert(result->func.ret == ret);
|
assert(result->func.ret == ret);
|
||||||
assert(result->func.args.len == args.len);
|
assert(result->func.args.len == args.len);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = type_new(pctx->perm, TYPE_Lambda, pointer_size, pointer_align);
|
result = type_new(pctx->perm, TYPE_LAMBDA, pointer_size, pointer_align);
|
||||||
result->func.ret = ret;
|
result->func.ret = ret;
|
||||||
result->func.args = args.tight_copy(pctx->perm);
|
result->func.args = args.tight_copy(pctx->perm);
|
||||||
map_insert(&pctx->type_map, hash, result);
|
map_insert(&pctx->type_map, hash, result);
|
||||||
@@ -150,21 +152,45 @@ type_lambda(Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
|
|||||||
|
|
||||||
function Ast_Resolved_Type *
|
function Ast_Resolved_Type *
|
||||||
type_incomplete(Sym *sym){
|
type_incomplete(Sym *sym){
|
||||||
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->sym = sym;
|
result->sym = sym;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Array<Ast_Resolved_Member> members
|
||||||
function void
|
function void
|
||||||
type_complete_struct(Ast_Resolved_Type *type, Array<Ast_Resolved_Type_Field> fields){
|
type_complete(Ast_Resolved_Type *type){
|
||||||
type->agg.fields = fields.tight_copy(pctx->perm);
|
if(type->kind == TYPE_COMPLETING){
|
||||||
type->kind = TYPE_Struct;
|
parsing_error(0, "Cyclic type dependency");
|
||||||
|
}
|
||||||
|
else if(type->kind != TYPE_INCOMPLETE){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Ast_Struct *node = const_get_struct(type->sym->ast);
|
||||||
|
|
||||||
|
// @note: resolve all the struct members
|
||||||
|
type->kind = TYPE_COMPLETING;
|
||||||
|
{
|
||||||
|
Scratch scratch;
|
||||||
|
Array<Ast_Resolved_Member> members = {scratch};
|
||||||
|
For(node->members){
|
||||||
|
Operand op = resolve_binding(it[0]);
|
||||||
|
Intern_String name = ast_get_name(it[0]);
|
||||||
|
sym_new_resolved(SYM_VAR, name, op.type, {}, it[0]);
|
||||||
|
members.add({op.type, name});
|
||||||
|
}
|
||||||
|
type->agg.members = members.tight_copy(pctx->perm);
|
||||||
|
}
|
||||||
|
|
||||||
|
// @note: complete struct
|
||||||
|
type->kind = TYPE_STRUCT;
|
||||||
|
// @todo: compute size, alignement, offset
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Resolved_Type *
|
function Ast_Resolved_Type *
|
||||||
type_struct(Sym *sym, Array<Ast_Resolved_Type_Field> fields){
|
type_struct(Sym *sym, Array<Ast_Resolved_Member> members){
|
||||||
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_Struct, 0, 0); // @todo: align,size
|
Ast_Resolved_Type *result = type_new(pctx->perm, TYPE_STRUCT, 0, 0); // @todo: align,size
|
||||||
result->agg.fields = fields.tight_copy(pctx->perm);
|
result->agg.members = members.tight_copy(pctx->perm);
|
||||||
result->sym = sym;
|
result->sym = sym;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user