Complete rework, adding packages
This commit is contained in:
288
ast.cpp
288
ast.cpp
@@ -7,6 +7,7 @@ enum Ast_Kind: U32{
|
|||||||
|
|
||||||
AST_PACKAGE,
|
AST_PACKAGE,
|
||||||
|
|
||||||
|
AST_SCOPE,
|
||||||
AST_VALUE,
|
AST_VALUE,
|
||||||
AST_CAST,
|
AST_CAST,
|
||||||
AST_IDENT,
|
AST_IDENT,
|
||||||
@@ -16,6 +17,8 @@ enum Ast_Kind: U32{
|
|||||||
AST_CALL_ITEM,
|
AST_CALL_ITEM,
|
||||||
AST_CALL,
|
AST_CALL,
|
||||||
|
|
||||||
|
AST_VAR,
|
||||||
|
AST_CONST,
|
||||||
AST_POINTER,
|
AST_POINTER,
|
||||||
AST_ARRAY,
|
AST_ARRAY,
|
||||||
AST_FOR,
|
AST_FOR,
|
||||||
@@ -29,8 +32,6 @@ enum Ast_Kind: U32{
|
|||||||
AST_ENUM,
|
AST_ENUM,
|
||||||
AST_ENUM_MEMBER,
|
AST_ENUM_MEMBER,
|
||||||
AST_STRUCT,
|
AST_STRUCT,
|
||||||
AST_CONST,
|
|
||||||
AST_VAR,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef U32 Ast_Flag;
|
typedef U32 Ast_Flag;
|
||||||
@@ -43,6 +44,7 @@ enum{
|
|||||||
AST_ITEM_INCLUDED = bit_flag(6),
|
AST_ITEM_INCLUDED = bit_flag(6),
|
||||||
AST_ATOM = bit_flag(7),
|
AST_ATOM = bit_flag(7),
|
||||||
AST_FOREIGN = bit_flag(8),
|
AST_FOREIGN = bit_flag(8),
|
||||||
|
AST_DECL = bit_flag(9),
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast{
|
struct Ast{
|
||||||
@@ -161,16 +163,6 @@ struct Ast_Array: Ast_Expr{
|
|||||||
Ast_Expr *expr;
|
Ast_Expr *expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Named:Ast{
|
|
||||||
Intern_String name;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Ast_Decl_State{
|
|
||||||
DECL_NOT_RESOLVED,
|
|
||||||
DECL_RESOLVED,
|
|
||||||
DECL_RESOLVING,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
How does current declaration order resolver works:
|
How does current declaration order resolver works:
|
||||||
* First we put all the global declarations into the global scope (when parsing) all unresolved
|
* First we put all the global declarations into the global scope (when parsing) all unresolved
|
||||||
@@ -188,81 +180,43 @@ How does current declaration order resolver works:
|
|||||||
resolving, we got a circular dependency. That might happen when we have
|
resolving, we got a circular dependency. That might happen when we have
|
||||||
that struct without pointer inside itself.
|
that struct without pointer inside itself.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
We need a new algorithm to process structs
|
|
||||||
we probably want default values so constants
|
|
||||||
can be evaluated first, also it's pretty weird that
|
|
||||||
only top scope gets special treatment
|
|
||||||
|
|
||||||
Idea 1
|
|
||||||
New algorithm, at some point in a constant we might
|
|
||||||
see the struct inside which is the constant. struct is
|
|
||||||
unresolved so we probably call resolve_name on struct
|
|
||||||
and struct continues resolving omitting already resolved and
|
|
||||||
declaration that requires the struct size. Problem is what happens
|
|
||||||
when we meet a member that references a constant and that constant
|
|
||||||
has reference to struct.
|
|
||||||
|
|
||||||
Idea 2
|
|
||||||
We resolve first members without default values, we add to queue dependencies
|
|
||||||
then we resolve constants. And at the end we resolve the queued values.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct Ast_Scope{
|
enum Ast_Decl_State{
|
||||||
Array<Ast_Decl *> resolved;
|
DECL_NOT_RESOLVED,
|
||||||
Array<Ast *> children;
|
DECL_RESOLVED,
|
||||||
Array<Ast *> constants;
|
DECL_RESOLVING,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ast_Decl;
|
||||||
|
struct Ast_Scope: Ast{
|
||||||
|
Array<Ast_Decl *> resolved;
|
||||||
|
Array<Ast_Decl *> decls;
|
||||||
|
Array<Ast *> stmts;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Decl: Ast{
|
struct Ast_Decl: Ast{
|
||||||
Ast_Decl_State state;
|
Ast_Decl_State state;
|
||||||
// kind:AST_CONST: subkind:AST_STRUCT, AST_ENUM, AST_EXPR(can be TYPE_TYPE), AST_LAMBDA
|
// Kind: AST_STRUCT implied AST_DECL (should flag AST_CONST AST_DECL)
|
||||||
// kind:AST_VAR : subkind:AST_EXPR, AST_LAMBDA
|
|
||||||
Intern_String name;
|
Intern_String name;
|
||||||
Ast_Kind sub_kind;
|
|
||||||
Ast_Scope *scope;
|
Ast_Scope *scope;
|
||||||
Ast_Resolved_Type *type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Ast_Var: Ast_Named{
|
|
||||||
Ast_Expr *typespec;
|
|
||||||
Ast_Expr *expr;
|
Ast_Expr *expr;
|
||||||
};
|
|
||||||
|
|
||||||
struct Ast_Const;
|
|
||||||
struct Ast_Resolved_Type;
|
|
||||||
struct Ast_Struct: Ast{
|
|
||||||
// Required to be Ast_Struct or Ast_Var or Ast_Const
|
|
||||||
Array<Ast_Var *> members;
|
|
||||||
Array<Ast_Const *> const_members;
|
|
||||||
Ast_Resolved_Type *type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Ast_Enum_Member: Ast{
|
|
||||||
Intern_String name;
|
|
||||||
Ast_Expr *value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Ast_Enum: Ast{
|
|
||||||
Ast_Expr *typespec;
|
Ast_Expr *typespec;
|
||||||
Array<Ast_Enum_Member *> members;
|
|
||||||
|
INLINE_VALUE_FIELDS;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ast_Const: Ast_Named{
|
struct Ast_File{
|
||||||
union{
|
String filename;
|
||||||
Ast *ast;
|
String filecontent;
|
||||||
Ast_Expr *value;
|
|
||||||
Ast_Struct *agg;
|
|
||||||
Ast_Enum *enu;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Ast_Package:Ast{
|
|
||||||
Intern_String name;
|
Intern_String name;
|
||||||
Array<Ast_Named *> decls;
|
Array<Ast_Decl *> decls;
|
||||||
Array<Ast_Named *> ordered;
|
};
|
||||||
|
|
||||||
|
struct Ast_Package : Ast_Scope{
|
||||||
|
Intern_String name;
|
||||||
};
|
};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -482,76 +436,72 @@ ast_array(Token *pos, Ast_Expr *expr){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Enum_Member *
|
function Ast_Scope *
|
||||||
ast_enum_member(Token *pos, Intern_String name, Ast_Expr *default_value){
|
ast_decl_scope(Token *pos, Array<Ast_Decl *> decls){
|
||||||
AST_NEW(Enum_Member, ENUM_MEMBER, pos, AST_AGGREGATE_CHILD);
|
AST_NEW(Scope, SCOPE, pos, AST_DECL);
|
||||||
result->name = name;
|
result->decls = decls.tight_copy(pctx->perm);
|
||||||
result->value = default_value;
|
result->resolved = array_make<Ast_Decl *>(pctx->perm, result->decls.len);
|
||||||
if(result->value) result->value->parent = result;
|
For(result->decls){
|
||||||
|
it->parent = result;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Enum *
|
function Ast_Scope *
|
||||||
ast_enum(Token *pos, Ast_Expr *typespec, Array<Ast_Enum_Member *> members){
|
ast_stmt_scope(Token *pos, Array<Ast *> stmts){
|
||||||
AST_NEW(Enum, ENUM, pos, AST_AGGREGATE);
|
AST_NEW(Scope, SCOPE, pos, AST_STMT);
|
||||||
result->members = members.tight_copy(pctx->perm);
|
result->stmts = stmts.tight_copy(pctx->perm);
|
||||||
|
For(result->stmts){
|
||||||
|
it->parent = result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Ast_Decl *
|
||||||
|
ast_struct(Token *pos, Array<Ast_Decl *> decls){
|
||||||
|
AST_NEW(Decl, STRUCT, pos, AST_DECL | AST_AGGREGATE);
|
||||||
|
result->scope = ast_decl_scope(pos, decls);
|
||||||
|
result->scope->parent = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Ast_Decl *
|
||||||
|
ast_enum(Token *pos, Ast_Expr *typespec, Array<Ast_Decl *> decls){
|
||||||
|
AST_NEW(Decl, ENUM, pos, AST_DECL | AST_AGGREGATE);
|
||||||
|
result->scope = ast_decl_scope(pos, decls);
|
||||||
result->typespec = typespec;
|
result->typespec = typespec;
|
||||||
|
result->scope->parent = result;
|
||||||
if(result->typespec) result->typespec->parent = result;
|
if(result->typespec) result->typespec->parent = result;
|
||||||
For(result->members){
|
|
||||||
it->parent = result;
|
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Struct *
|
function Ast_Decl *
|
||||||
ast_struct(Token *pos, Array<Ast_Var *> members, Array<Ast_Const *> const_members){
|
|
||||||
AST_NEW(Struct, STRUCT, pos, AST_AGGREGATE);
|
|
||||||
result->members = members.tight_copy(pctx->perm);
|
|
||||||
result->const_members = const_members.tight_copy(pctx->perm);
|
|
||||||
For(result->members) {
|
|
||||||
assert(is_flag_set(it->flags, AST_BINDING));
|
|
||||||
assert(it->kind == AST_VAR);
|
|
||||||
it->parent = result;
|
|
||||||
}
|
|
||||||
For(result->const_members) {
|
|
||||||
assert(is_flag_set(it->flags, AST_BINDING));
|
|
||||||
assert(it->kind == AST_CONST);
|
|
||||||
it->parent = result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Declarations
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
function Ast_Var *
|
|
||||||
ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr){
|
ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr){
|
||||||
AST_NEW(Var, VAR, pos, AST_BINDING);
|
AST_NEW(Decl, VAR, pos, AST_DECL);
|
||||||
result->expr = expr;
|
|
||||||
result->typespec = typespec;
|
|
||||||
result->name = name;
|
|
||||||
if(result->expr) result->expr->parent = result;
|
|
||||||
if(result->typespec) result->typespec->parent = result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Ast_Const *
|
|
||||||
ast_const(Token *pos, Intern_String name, Ast_Expr *value){
|
|
||||||
assert(is_flag_set(value->flags, AST_AGGREGATE) || is_flag_set(value->flags, AST_EXPR) );
|
|
||||||
AST_NEW(Const, CONST, pos, AST_BINDING);
|
|
||||||
result->value = value;
|
|
||||||
result->name = name;
|
result->name = name;
|
||||||
result->value->parent = result;
|
result->typespec = typespec;
|
||||||
|
result->expr = expr;
|
||||||
|
if(result->typespec) result->typespec->parent = result;
|
||||||
|
if(result->expr) result->expr->parent = result;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Package *
|
function Ast_Decl *
|
||||||
ast_package(Token *pos, String name, Array<Ast_Named *> decls){
|
ast_const(Token *pos, Intern_String name, Ast_Expr *expr){
|
||||||
AST_NEW(Package, PACKAGE, pos, 0);
|
AST_NEW(Decl, CONST, pos, AST_DECL);
|
||||||
result->decls = decls.tight_copy(pctx->perm);
|
result->expr = expr;
|
||||||
result->ordered = array_make<Ast_Named *>(pctx->perm, decls.len);
|
result->name = name;
|
||||||
result->name = intern_string(&pctx->interns, name);
|
if(result->expr) result->expr->parent = result;
|
||||||
For(result->decls) it->parent = result;
|
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;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,61 +548,6 @@ value_float(BigInt a){
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// Utillities
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
function Ast_Struct *
|
|
||||||
const_try_getting_struct(Ast *ast){
|
|
||||||
assert(ast->kind == AST_CONST);
|
|
||||||
Ast_Const *constant = (Ast_Const *)ast;
|
|
||||||
if(constant->value->kind == AST_STRUCT){
|
|
||||||
return (Ast_Struct *)constant->value;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Ast_Struct *
|
|
||||||
const_get_struct(Ast *ast){
|
|
||||||
auto result = const_try_getting_struct(ast);
|
|
||||||
assert(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Ast_Lambda *
|
|
||||||
const_try_getting_lambda(Ast *ast){
|
|
||||||
assert(ast->kind == AST_CONST);
|
|
||||||
Ast_Const *constant = (Ast_Const *)ast;
|
|
||||||
if(constant->value->kind == AST_LAMBDA){
|
|
||||||
return (Ast_Lambda *)constant->value;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Ast_Lambda *
|
|
||||||
const_get_lambda(Ast *ast){
|
|
||||||
auto result = const_try_getting_lambda(ast);
|
|
||||||
assert(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Intern_String
|
|
||||||
ast_get_name(Ast *ast){
|
|
||||||
assert(is_flag_set(ast->flags, AST_BINDING));
|
|
||||||
auto constant = (Ast_Named *)ast;
|
|
||||||
return constant->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
function B32
|
|
||||||
ast_is_struct(Ast *ast){
|
|
||||||
if(ast->kind == AST_CONST){
|
|
||||||
auto a = (Ast_Const *)ast;
|
|
||||||
B32 result = a->agg->kind == AST_STRUCT;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function B32
|
function B32
|
||||||
is_ident(Ast *ast){
|
is_ident(Ast *ast){
|
||||||
B32 result = ast->kind == AST_IDENT;
|
B32 result = ast->kind == AST_IDENT;
|
||||||
@@ -670,28 +565,3 @@ is_atom(Ast *ast){
|
|||||||
B32 result = is_flag_set(ast->flags, AST_ATOM);
|
B32 result = is_flag_set(ast->flags, AST_ATOM);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast *
|
|
||||||
query_struct(Ast_Struct *agg, Intern_String string){
|
|
||||||
For(agg->members){
|
|
||||||
if(it->name == string){
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
For(agg->const_members){
|
|
||||||
if(it->name == string){
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Ast_Enum_Member *
|
|
||||||
query_enum(Ast_Enum *enu, Intern_String string){
|
|
||||||
For(enu->members){
|
|
||||||
if(it->name == string){
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
struct Token;
|
struct Token;
|
||||||
Allocator *bigint_allocator;
|
Allocator *bigint_allocator;
|
||||||
global S64 bigint_allocation_count;
|
global S64 bigint_allocation_count;
|
||||||
function void parsing_error(Token *token, const char *str, ...);
|
function void compiler_error(Token *token, const char *str, ...);
|
||||||
|
|
||||||
#define Set_BigInt_Allocator(x) BigInt_Allocator bigint_allocator(x)
|
#define Set_BigInt_Allocator(x) BigInt_Allocator bigint_allocator(x)
|
||||||
struct BigInt_Allocator{
|
struct BigInt_Allocator{
|
||||||
@@ -17,7 +17,7 @@ struct BigInt_Allocator{
|
|||||||
#define count_bigint_alloc() (bigint_allocator != thread_ctx.scratch ? bigint_allocation_count++ : 0)
|
#define count_bigint_alloc() (bigint_allocator != thread_ctx.scratch ? bigint_allocation_count++ : 0)
|
||||||
#define malloc_arena(x) (count_bigint_alloc(), exp_alloc(bigint_allocator, x, AF_ZeroMemory))
|
#define malloc_arena(x) (count_bigint_alloc(), exp_alloc(bigint_allocator, x, AF_ZeroMemory))
|
||||||
#define ALLOC_DIGITS(_digits) (uint64_t *)((_digits) ? malloc_arena(sizeof(uint64_t) * (_digits)) : NULL)
|
#define ALLOC_DIGITS(_digits) (uint64_t *)((_digits) ? malloc_arena(sizeof(uint64_t) * (_digits)) : NULL)
|
||||||
#define FATAL_ERROR(x) parsing_error(0, x)
|
#define FATAL_ERROR(x) compiler_error(0, x)
|
||||||
|
|
||||||
struct BigInt
|
struct BigInt
|
||||||
{
|
{
|
||||||
|
|||||||
14
ccodegen.cpp
14
ccodegen.cpp
@@ -468,7 +468,7 @@ gen_ast(Ast *ast){
|
|||||||
gen(";");
|
gen(";");
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
default: parsing_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(sym->type));
|
default: compiler_error(node->pos, "C_Codegen: Unhandled type %s of constant expression", docname(sym->type));
|
||||||
}
|
}
|
||||||
|
|
||||||
BREAK();
|
BREAK();
|
||||||
@@ -574,15 +574,3 @@ compile_file(String filename){
|
|||||||
String result = compile_string(filecontent, filename);
|
String result = compile_string(filecontent, filename);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct Custom_Data{
|
|
||||||
S32 thing;
|
|
||||||
}Custom_Data;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct Slice{
|
|
||||||
S64 len;
|
|
||||||
void *data;
|
|
||||||
}Slice;
|
|
||||||
|
|
||||||
Slice thing = (Slice){2, (Custom_Data []){(Custom_Data ){1}, (Custom_Data ){2}}};
|
|
||||||
31
compiler.h
31
compiler.h
@@ -112,19 +112,19 @@ struct Token{
|
|||||||
S64 indent;
|
S64 indent;
|
||||||
};
|
};
|
||||||
|
|
||||||
String file;
|
Intern_String file;
|
||||||
S32 line;
|
S32 line;
|
||||||
U8 *line_begin;
|
U8 *line_begin;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Lex_Stream{
|
struct Lex_Stream{
|
||||||
String stream;
|
String stream;
|
||||||
S64 iter;
|
S64 iter;
|
||||||
|
|
||||||
U8 *line_begin;
|
U8 *line_begin;
|
||||||
String file;
|
Intern_String file;
|
||||||
S32 line;
|
S32 line;
|
||||||
S32 inside_brace_paren;
|
S32 inside_brace_paren;
|
||||||
Array<Token *> indent_stack;
|
Array<Token *> indent_stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -154,6 +154,7 @@ Intern_String keyword_if;
|
|||||||
Intern_String keyword_else;
|
Intern_String keyword_else;
|
||||||
Intern_String keyword_true;
|
Intern_String keyword_true;
|
||||||
Intern_String keyword_false;
|
Intern_String keyword_false;
|
||||||
|
Intern_String keyword_package;
|
||||||
Intern_String keyword_for;
|
Intern_String keyword_for;
|
||||||
Intern_String keyword_pass;
|
Intern_String keyword_pass;
|
||||||
Intern_String keyword_cast;
|
Intern_String keyword_cast;
|
||||||
@@ -163,8 +164,10 @@ Intern_String intern_void;
|
|||||||
Intern_String intern_foreign;
|
Intern_String intern_foreign;
|
||||||
Intern_String intern_printf;
|
Intern_String intern_printf;
|
||||||
|
|
||||||
|
|
||||||
|
struct Ast_Scope;
|
||||||
|
struct Ast_Decl;
|
||||||
struct Ast_Package;
|
struct Ast_Package;
|
||||||
struct Sym;
|
|
||||||
struct Parse_Ctx:Lexer{
|
struct Parse_Ctx:Lexer{
|
||||||
Allocator *perm; // Stores: AST, tokens, interns
|
Allocator *perm; // Stores: AST, tokens, interns
|
||||||
Allocator *heap;
|
Allocator *heap;
|
||||||
@@ -172,15 +175,12 @@ struct Parse_Ctx:Lexer{
|
|||||||
U64 unique_ids;
|
U64 unique_ids;
|
||||||
Map type_map;
|
Map type_map;
|
||||||
|
|
||||||
|
Ast_Scope *current_scope;
|
||||||
Ast_Package *resolving_package;
|
Ast_Package *resolving_package;
|
||||||
Map resolved;
|
Array<Ast_Decl *> ordered_decls;
|
||||||
Map syms;
|
|
||||||
S32 scope;
|
|
||||||
Array<Sym *> local_syms;
|
|
||||||
|
|
||||||
Token empty_token;
|
Token empty_token;
|
||||||
S64 indent;
|
S64 indent;
|
||||||
|
|
||||||
String_Builder gen;
|
String_Builder gen;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -201,6 +201,7 @@ lex_init(Allocator *token_string_arena, Allocator *map_allocator, Lexer *l){
|
|||||||
keyword_cast = l->intern("cast"_s);
|
keyword_cast = l->intern("cast"_s);
|
||||||
keyword_true = l->intern("true"_s);
|
keyword_true = l->intern("true"_s);
|
||||||
keyword_false = l->intern("false"_s);
|
keyword_false = l->intern("false"_s);
|
||||||
|
keyword_package = l->intern("package"_s);
|
||||||
keyword_return = l->intern("return"_s);
|
keyword_return = l->intern("return"_s);
|
||||||
keyword_if = l->intern("if"_s);
|
keyword_if = l->intern("if"_s);
|
||||||
keyword_pass = l->intern("pass"_s);
|
keyword_pass = l->intern("pass"_s);
|
||||||
@@ -220,10 +221,8 @@ parse_init(Parse_Ctx *ctx, Allocator *perm_allocator, Allocator *heap_allocator)
|
|||||||
ctx->perm = perm_allocator;
|
ctx->perm = perm_allocator;
|
||||||
ctx->heap = heap_allocator;
|
ctx->heap = heap_allocator;
|
||||||
ctx->gen = {ctx->perm};
|
ctx->gen = {ctx->perm};
|
||||||
ctx->resolved = {ctx->heap};
|
ctx->ordered_decls = {ctx->heap};
|
||||||
ctx->syms = {ctx->heap};
|
|
||||||
ctx->type_map = {ctx->heap};
|
ctx->type_map = {ctx->heap};
|
||||||
ctx->local_syms = {ctx->heap};
|
|
||||||
bigint_allocator = ctx->perm;
|
bigint_allocator = ctx->perm;
|
||||||
|
|
||||||
lex_init(ctx->perm, ctx->heap, ctx);
|
lex_init(ctx->perm, ctx->heap, ctx);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
package lambdas
|
||||||
|
|
||||||
a_type :: S64
|
a_type :: S64
|
||||||
pointer_type :: *S64
|
pointer_type :: *S64
|
||||||
// null_pointer: pointer_type = null
|
// null_pointer: pointer_type = null
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ lex_parse_ident(Intern_Table *table, Lex_Stream *s, Token *t){
|
|||||||
break
|
break
|
||||||
|
|
||||||
function Token
|
function Token
|
||||||
token_make(Lexer *lexer, U8 *str, String file, int line, U8 *line_begin){
|
token_make(Lexer *lexer, U8 *str, Intern_String file, int line, U8 *line_begin){
|
||||||
Token t = {};
|
Token t = {};
|
||||||
t.str = str;
|
t.str = str;
|
||||||
t.file = file;
|
t.file = file;
|
||||||
@@ -540,7 +540,7 @@ lex_restream(Lexer *lexer, String istream, String file){
|
|||||||
lexer->stream = {};
|
lexer->stream = {};
|
||||||
lexer->stream.stream = istream;
|
lexer->stream.stream = istream;
|
||||||
lexer->stream.line_begin = istream.str;
|
lexer->stream.line_begin = istream.str;
|
||||||
lexer->stream.file = file;
|
lexer->stream.file = lexer->intern(file);
|
||||||
|
|
||||||
|
|
||||||
lexer->tokens.clear();
|
lexer->tokens.clear();
|
||||||
|
|||||||
16
main.cpp
16
main.cpp
@@ -164,10 +164,10 @@ 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"
|
||||||
|
|
||||||
int main(int argument_count, char **arguments){
|
int main(int argument_count, char **arguments){
|
||||||
// test_big_int();
|
|
||||||
|
|
||||||
test_os_memory();
|
test_os_memory();
|
||||||
thread_ctx_init();
|
thread_ctx_init();
|
||||||
@@ -180,7 +180,7 @@ int main(int argument_count, char **arguments){
|
|||||||
test_intern_table();
|
test_intern_table();
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
emit_line_directives = true;
|
emit_line_directives = true;
|
||||||
if(argument_count > 1){
|
if(argument_count > 1){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
@@ -211,12 +211,16 @@ int main(int argument_count, char **arguments){
|
|||||||
printf("%s", result.str);
|
printf("%s", result.str);
|
||||||
result = compile_file("order2.kl"_s);
|
result = compile_file("order2.kl"_s);
|
||||||
printf("%s", result.str);
|
printf("%s", result.str);
|
||||||
result = compile_file("lambdas.kl"_s);
|
|
||||||
printf("%s", result.str);
|
|
||||||
result = compile_file("new_types.kl"_s);
|
result = compile_file("new_types.kl"_s);
|
||||||
printf("%s", result.str);
|
printf("%s", result.str);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
Scratch scratch;
|
||||||
|
Array<String> files = {scratch};
|
||||||
|
files.add("lambdas.kl"_s);
|
||||||
|
files.add("order1.kl"_s);
|
||||||
|
compile_files(files);
|
||||||
__debugbreak();
|
__debugbreak();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
package lambdas
|
||||||
|
|
||||||
other_func :: ()
|
other_func :: ()
|
||||||
a_val := recursive_lambda
|
a_val := recursive_lambda
|
||||||
|
|||||||
68
parsing.cpp
68
parsing.cpp
@@ -1,6 +1,7 @@
|
|||||||
|
function Ast_Decl *parse_decl(B32 is_global);
|
||||||
|
|
||||||
function void
|
function void
|
||||||
parsing_error(Token *token, const char *str, ...){
|
compiler_error(Token *token, const char *str, ...){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
STRING_FMT(scratch, str, string);
|
STRING_FMT(scratch, str, string);
|
||||||
|
|
||||||
@@ -109,7 +110,7 @@ function Token *
|
|||||||
token_expect(Token_Kind kind){
|
token_expect(Token_Kind kind){
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
if(token->kind == kind) return token_next();
|
if(token->kind == kind) return token_next();
|
||||||
parsing_error(token, "Expected token of kind: [%s], got instead token of kind: [%s]", name(kind), name(token->kind));
|
compiler_error(token, "Expected token of kind: [%s], got instead token of kind: [%s]", name(kind), name(token->kind));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +120,7 @@ function Ast_Expr *
|
|||||||
parse_init_stmt(Ast_Expr *expr){
|
parse_init_stmt(Ast_Expr *expr){
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT)
|
if(token->kind == TK_ColonAssign && expr->kind != AST_IDENT)
|
||||||
parsing_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)){
|
if(token_is_assign(token)){
|
||||||
token_next();
|
token_next();
|
||||||
@@ -175,7 +176,6 @@ parse_optional_type(){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Named *parse_named(B32);
|
|
||||||
function Ast_Block *
|
function Ast_Block *
|
||||||
parse_block(){
|
parse_block(){
|
||||||
Ast_Block *block = 0;
|
Ast_Block *block = 0;
|
||||||
@@ -257,7 +257,7 @@ parse_block(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
Ast *result = parse_named(false);
|
Ast *result = parse_decl(false);
|
||||||
if(!result){
|
if(!result){
|
||||||
result = parse_expr();
|
result = parse_expr();
|
||||||
result = parse_init_stmt((Ast_Expr *)result);
|
result = parse_init_stmt((Ast_Expr *)result);
|
||||||
@@ -268,7 +268,7 @@ parse_block(){
|
|||||||
stmts.add(result);
|
stmts.add(result);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
parsing_error(token, "Unexpected token [%s] while parsing statement", name(token->kind));
|
compiler_error(token, "Unexpected token [%s] while parsing statement", name(token->kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -304,7 +304,7 @@ parse_lambda(Token *token){
|
|||||||
has_var_args = true;
|
has_var_args = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else parsing_error(name, "Expected [Identifier] or [...] when parsing lambda arguments");
|
else compiler_error(name, "Expected [Identifier] or [...] when parsing lambda arguments");
|
||||||
|
|
||||||
if(!token_match(TK_Comma))
|
if(!token_match(TK_Comma))
|
||||||
break;
|
break;
|
||||||
@@ -412,7 +412,7 @@ parse_expr(S64 min_bp){
|
|||||||
Ast_Expr *expr = 0;
|
Ast_Expr *expr = 0;
|
||||||
if(!token_is(TK_CloseBracket))
|
if(!token_is(TK_CloseBracket))
|
||||||
expr = parse_expr(0);
|
expr = parse_expr(0);
|
||||||
|
|
||||||
Ast_Array *result = ast_array(token, expr);
|
Ast_Array *result = ast_array(token, expr);
|
||||||
token_expect(TK_CloseBracket);
|
token_expect(TK_CloseBracket);
|
||||||
result->base = parse_expr(prefix_bp.right);
|
result->base = parse_expr(prefix_bp.right);
|
||||||
@@ -430,7 +430,7 @@ parse_expr(S64 min_bp){
|
|||||||
token_expect(TK_CloseParen);
|
token_expect(TK_CloseParen);
|
||||||
left = ast_expr_cast(token, expr, typespec);
|
left = ast_expr_cast(token, expr, typespec);
|
||||||
}
|
}
|
||||||
else parsing_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str);
|
else compiler_error(token, "Unexpected keyword: [%s], expected keyword [cast]", token->intern_val.str);
|
||||||
}break;
|
}break;
|
||||||
|
|
||||||
case TK_OpenParen: {
|
case TK_OpenParen: {
|
||||||
@@ -441,7 +441,7 @@ parse_expr(S64 min_bp){
|
|||||||
token_expect(TK_CloseParen);
|
token_expect(TK_CloseParen);
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
default: parsing_error(token, "Unexpected token of kind: [%s] in expression", name(token->kind)); return 0;
|
default: compiler_error(token, "Unexpected token of kind: [%s] in expression", name(token->kind)); return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
@@ -497,51 +497,45 @@ parse_assign_expr(){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Struct *
|
function Ast_Decl *
|
||||||
parse_struct(Token *pos){
|
parse_struct(Token *pos){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast_Var *> members = {scratch};
|
Array<Ast_Decl *> members = {scratch};
|
||||||
Array<Ast_Const *> members_const = {scratch};
|
|
||||||
|
|
||||||
token_match(OPEN_SCOPE);
|
token_match(OPEN_SCOPE);
|
||||||
do{
|
do{
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
|
|
||||||
Ast_Named *named = parse_named(false);
|
Ast_Decl *decl = parse_decl(false);
|
||||||
if(!named) parsing_error(token, "Failed to parse struct member");
|
if(!decl) compiler_error(token, "Failed to parse struct member");
|
||||||
named->flags = set_flag(named->flags, AST_AGGREGATE_CHILD);
|
|
||||||
|
|
||||||
if(named->kind == AST_CONST){
|
decl->flags = set_flag(decl->flags, AST_AGGREGATE_CHILD);
|
||||||
members_const.add((Ast_Const *)named);
|
members.add(decl);
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert(named->kind == AST_VAR);
|
|
||||||
members.add((Ast_Var *)named);
|
|
||||||
}
|
|
||||||
|
|
||||||
}while(token_match(SAME_SCOPE));
|
}while(token_match(SAME_SCOPE));
|
||||||
token_expect(CLOSE_SCOPE);
|
token_expect(CLOSE_SCOPE);
|
||||||
|
|
||||||
Ast_Struct *result = ast_struct(pos, members, members_const);
|
Ast_Decl *result = ast_struct(pos, members);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Enum *
|
function Ast_Decl *
|
||||||
parse_enum(Token *pos){
|
parse_enum(Token *pos){
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast_Enum_Member *> members = {scratch};
|
Array<Ast_Decl *> members = {scratch};
|
||||||
Ast_Expr *typespec = parse_optional_type();
|
Ast_Expr *typespec = parse_optional_type();
|
||||||
|
|
||||||
token_match(OPEN_SCOPE);
|
token_match(OPEN_SCOPE);
|
||||||
do{
|
do{
|
||||||
Token *name = token_expect(TK_Identifier);
|
Token *name = token_expect(TK_Identifier);
|
||||||
Ast_Expr *value = parse_assign_expr();
|
Ast_Expr *value = parse_assign_expr();
|
||||||
Ast_Enum_Member *member = ast_enum_member(name, name->intern_val, value);
|
Ast_Decl *member = ast_const(name, name->intern_val, value);
|
||||||
|
member->flags = set_flag(member->flags, AST_AGGREGATE_CHILD);
|
||||||
members.add(member);
|
members.add(member);
|
||||||
}while(token_match(SAME_SCOPE));
|
}while(token_match(SAME_SCOPE));
|
||||||
token_expect(CLOSE_SCOPE);
|
token_expect(CLOSE_SCOPE);
|
||||||
|
|
||||||
Ast_Enum *result = ast_enum(pos, typespec, members);
|
Ast_Decl *result = ast_enum(pos, typespec, members);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -550,13 +544,13 @@ Needs peeking only because I didn't want to duplicate code
|
|||||||
for parsing statements and it makes code nicer.
|
for parsing statements and it makes code nicer.
|
||||||
Statements can have named syntax i :=
|
Statements can have named syntax i :=
|
||||||
*/
|
*/
|
||||||
function Ast_Named *
|
function Ast_Decl *
|
||||||
parse_named(B32 is_global){
|
parse_decl(B32 is_global){
|
||||||
Ast_Named *result = 0;
|
Ast_Decl *result = 0;
|
||||||
if(is_global) {
|
if(is_global) {
|
||||||
token_match(SAME_SCOPE);
|
token_match(SAME_SCOPE);
|
||||||
if(pctx->indent != 0){
|
if(pctx->indent != 0){
|
||||||
parsing_error(token_get(), "Top level declarations shouldn't be indented");
|
compiler_error(token_get(), "Top level declarations shouldn't be indented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,15 +562,12 @@ parse_named(B32 is_global){
|
|||||||
Token *tname = token_get();
|
Token *tname = token_get();
|
||||||
if(token_match(TK_Identifier, TK_DoubleColon)){
|
if(token_match(TK_Identifier, TK_DoubleColon)){
|
||||||
// @note parse struct binding
|
// @note parse struct binding
|
||||||
Token *struct_pos = token_get();
|
|
||||||
if(token_match_keyword(keyword_struct)){
|
if(token_match_keyword(keyword_struct)){
|
||||||
Ast_Struct *struct_val = parse_struct(struct_pos);
|
result = parse_struct(tname);
|
||||||
result = ast_const(tname, tname->intern_val, (Ast_Expr *)struct_val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(token_match_keyword(keyword_enum)){
|
else if(token_match_keyword(keyword_enum)){
|
||||||
Ast_Enum *enum_val = parse_enum(struct_pos);
|
result = parse_enum(tname);
|
||||||
result = ast_const(tname, tname->intern_val, (Ast_Expr *)enum_val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @note parse constant expression
|
// @note parse constant expression
|
||||||
@@ -596,10 +587,11 @@ parse_named(B32 is_global){
|
|||||||
result = ast_var(tname, 0, tname->intern_val, expr);
|
result = ast_var(tname, 0, tname->intern_val, expr);
|
||||||
}
|
}
|
||||||
else if(is_global && tname->kind != TK_End){
|
else if(is_global && tname->kind != TK_End){
|
||||||
parsing_error(tname, "Unexpected token: [%s] when parsing a declaration", name(tname->kind));
|
compiler_error(tname, "Unexpected token: [%s] when parsing a declaration", name(tname->kind));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result){
|
if(result){
|
||||||
|
result->name = tname->intern_val;
|
||||||
result->flags = set_flag(result->flags, flags);
|
result->flags = set_flag(result->flags, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
431
typechecking.cpp
431
typechecking.cpp
@@ -1,32 +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
|
||||||
|
|
||||||
function void
|
|
||||||
type_error(Token *token, Ast_Resolved_Type *expected, Ast_Resolved_Type *actual, const char *str, ...){
|
|
||||||
Scratch scratch;
|
|
||||||
STRING_FMT(scratch, str, string);
|
|
||||||
|
|
||||||
// @Note(Krzosa): Print nice error message
|
|
||||||
printf("\nType error :: %s :: ", string.str);
|
|
||||||
printf("Expected %s, got instead %s", docname(expected), docname(actual));
|
|
||||||
if(token){
|
|
||||||
printf(" :: %s:%d\n", token->file.str, (S32)token->line + 1);
|
|
||||||
|
|
||||||
// @Note(Krzosa): Print error line
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
|
|
||||||
printf("%.*s\n", i, token->line_begin);
|
|
||||||
|
|
||||||
// @Note(Krzosa): Print error marker
|
|
||||||
int token_i = token->str - token->line_begin;
|
|
||||||
for(int i = 0; i < token_i-2; i++) printf(" ");
|
|
||||||
printf("^^^^^^\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__debugbreak();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Evaluating constant expressions
|
// Evaluating constant expressions
|
||||||
@@ -38,7 +12,7 @@ check_value_bounds(Token *pos, Value *a){
|
|||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
if(!bigint_fits_in_bits(&a->big_int_val, a->type->size*8, is_signed_int(a->type))){
|
if(!bigint_fits_in_bits(&a->big_int_val, a->type->size*8, is_signed_int(a->type))){
|
||||||
const char *string = bigint_to_error_string(scratch, &a->big_int_val, 10);
|
const char *string = bigint_to_error_string(scratch, &a->big_int_val, 10);
|
||||||
parsing_error(pos, "Value %s doesn't fit in type %s", string, docname(a->type));
|
compiler_error(pos, "Value %s doesn't fit in type %s", string, docname(a->type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +34,7 @@ convert_untyped_to_typed(Token *pos, Value a, Ast_Resolved_Type *new_type){
|
|||||||
; // nothing to do
|
; // nothing to do
|
||||||
else if(is_string(a.type) && is_string(new_type))
|
else if(is_string(a.type) && is_string(new_type))
|
||||||
; // nothing to do
|
; // nothing to do
|
||||||
else parsing_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type));
|
else compiler_error(pos, "Type mismatch when converting from %s to %s", docname(a.type), docname(new_type));
|
||||||
|
|
||||||
a.type = new_type;
|
a.type = new_type;
|
||||||
check_value_bounds(pos, &a);
|
check_value_bounds(pos, &a);
|
||||||
@@ -77,7 +51,7 @@ make_sure_types_are_compatible(Token *pos, Value *a, Value *b){
|
|||||||
}
|
}
|
||||||
else if(is_typed(a->type) && is_typed(b->type)){
|
else if(is_typed(a->type) && is_typed(b->type)){
|
||||||
if(a->type != b->type){
|
if(a->type != b->type){
|
||||||
fail: parsing_error(pos, "Type mismatch in make_sure_types_are_compatible - left: %s right: %s", docname(a->type), docname(b->type));
|
fail: compiler_error(pos, "Type mismatch in make_sure_types_are_compatible - left: %s right: %s", docname(a->type), docname(b->type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,7 +74,7 @@ make_sure_types_are_compatible(Token *pos, Value *a, Value *b){
|
|||||||
function Value
|
function Value
|
||||||
compare_values(Token *pos, Token_Kind op, Value a, Value b, bool is_const){
|
compare_values(Token *pos, Token_Kind op, Value a, Value b, bool is_const){
|
||||||
if(!(is_numeric(a.type) && is_numeric(b.type)))
|
if(!(is_numeric(a.type) && is_numeric(b.type)))
|
||||||
parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type));
|
compiler_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type));
|
||||||
|
|
||||||
make_sure_types_are_compatible(pos, &a, &b);
|
make_sure_types_are_compatible(pos, &a, &b);
|
||||||
|
|
||||||
@@ -154,7 +128,7 @@ eval_binary(Token *pos, Token_Kind op, Value a, Value b, bool is_const){
|
|||||||
return compare_values(pos, op, a, b, is_const);
|
return compare_values(pos, op, a, b, is_const);
|
||||||
|
|
||||||
if(!(is_numeric(a.type) && is_numeric(b.type)))
|
if(!(is_numeric(a.type) && is_numeric(b.type)))
|
||||||
parsing_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type));
|
compiler_error(pos, "Constant application of binary %s on values of type %s and %s is not allowed", name(op), docname(a.type), docname(b.type));
|
||||||
|
|
||||||
make_sure_types_are_compatible(pos, &a, &b);
|
make_sure_types_are_compatible(pos, &a, &b);
|
||||||
|
|
||||||
@@ -220,14 +194,14 @@ eval_unary(Token *pos, Token_Kind op, Operand *operand){
|
|||||||
Value *a = &operand->value;
|
Value *a = &operand->value;
|
||||||
Ast_Resolved_Type *type = a->type;
|
Ast_Resolved_Type *type = a->type;
|
||||||
if(!is_numeric(type))
|
if(!is_numeric(type))
|
||||||
parsing_error(pos, "Unary [%s] cant be applied to value of type %s", name(op), docname(type));
|
compiler_error(pos, "Unary [%s] cant be applied to value of type %s", name(op), docname(type));
|
||||||
|
|
||||||
if(op == TK_Not)
|
if(op == TK_Not)
|
||||||
a->type = untyped_bool;
|
a->type = untyped_bool;
|
||||||
|
|
||||||
if(op == TK_Increment || op == TK_Decrement || op == TK_PostIncrement || op == TK_PostDecrement)
|
if(op == TK_Increment || op == TK_Decrement || op == TK_PostIncrement || op == TK_PostDecrement)
|
||||||
if(!operand->is_lvalue)
|
if(!operand->is_lvalue)
|
||||||
parsing_error(pos, "Unary [%s] requires an assignable value(lvalue)", name(op));
|
compiler_error(pos, "Unary [%s] requires an assignable value(lvalue)", name(op));
|
||||||
|
|
||||||
if(!operand->is_const)
|
if(!operand->is_const)
|
||||||
return;
|
return;
|
||||||
@@ -269,7 +243,7 @@ eval_unary(Token *pos, Token_Kind op, Operand *operand){
|
|||||||
default:goto failure;
|
default:goto failure;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default: failure: parsing_error(pos, "Constant application of unary %s on values of type %s is not allowed", name(op), docname(a->type));
|
default: failure: compiler_error(pos, "Constant application of unary %s on values of type %s is not allowed", name(op), docname(a->type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,10 +293,11 @@ make_sure_value_is_compatible_with_type(Token *pos, Operand *expr, Ast_Resolved_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(type && expr->type != type){
|
if(type && expr->type != type){
|
||||||
parsing_error(pos, "Assigning but incompatible types, expression: %s expected var type: %s", docname(expr->type), docname(type));
|
compiler_error(pos, "Assigning but incompatible types, expression: %s expected var type: %s", docname(expr->type), docname(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
type_complete(expr->type);
|
// @todo
|
||||||
|
// type_complete(expr->type);
|
||||||
check_value_bounds(pos, &expr->value);
|
check_value_bounds(pos, &expr->value);
|
||||||
assert(expr->type);
|
assert(expr->type);
|
||||||
}
|
}
|
||||||
@@ -337,11 +312,7 @@ _rewrite_into_const(Ast *node, U64 ast_size, Value value){
|
|||||||
ast->value = value;
|
ast->value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
#if 0
|
||||||
_rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){
|
|
||||||
_rewrite_into_const(node, ast_size, sym->value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function Ast_Resolved_Type *
|
function Ast_Resolved_Type *
|
||||||
resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){
|
resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){
|
||||||
if(ast_can_be_null && ast == 0)
|
if(ast_can_be_null && ast == 0)
|
||||||
@@ -349,7 +320,7 @@ resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){
|
|||||||
|
|
||||||
Operand resolved = resolve_expr(ast);
|
Operand resolved = resolve_expr(ast);
|
||||||
if(resolved.type != type_type)
|
if(resolved.type != type_type)
|
||||||
parsing_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]);
|
compiler_error(ast->pos, "Expected [Type] got instead %s", type_names[resolved.type->kind]);
|
||||||
return resolved.type_val;
|
return resolved.type_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,12 +331,12 @@ require_const_int(Ast_Expr *expr, B32 ast_can_be_null){
|
|||||||
if(expr == 0 && ast_can_be_null)
|
if(expr == 0 && ast_can_be_null)
|
||||||
return op;
|
return op;
|
||||||
else if(expr == 0)
|
else if(expr == 0)
|
||||||
parsing_error(expr->pos, "This field cannot be null");
|
compiler_error(expr->pos, "This field cannot be null");
|
||||||
|
|
||||||
if(!op.is_const)
|
if(!op.is_const)
|
||||||
parsing_error(expr->pos, "Expected a const value");
|
compiler_error(expr->pos, "Expected a const value");
|
||||||
if(!is_int(op.type))
|
if(!is_int(op.type))
|
||||||
parsing_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type));
|
compiler_error(expr->pos, "Expected a constant integer got instead %s", docname(op.type));
|
||||||
|
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
@@ -375,12 +346,12 @@ resolve_and_require_bool(const char *error, Ast_Expr *expr, B32 ast_can_be_null
|
|||||||
if(!expr){
|
if(!expr){
|
||||||
if(ast_can_be_null)
|
if(ast_can_be_null)
|
||||||
return {};
|
return {};
|
||||||
else parsing_error(0, "Compiler error: Null expression");
|
else compiler_error(0, "Compiler error: Null expression");
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand op = resolve_expr(expr);
|
Operand op = resolve_expr(expr);
|
||||||
if(!is_bool(op.type)){
|
if(!is_bool(op.type)){
|
||||||
type_error(expr->pos, type_bool, op.type, "%s", error);
|
compiler_error(expr->pos, "Expected type [Bool] got instead type %s :: %s", docname(op.type), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return op;
|
return op;
|
||||||
@@ -395,9 +366,9 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
|||||||
switch(ast->kind){
|
switch(ast->kind){
|
||||||
CASE(RETURN, 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 = resolve_expr(node->expr);
|
Operand op = resolve_expr(node->expr);
|
||||||
if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is %s", docname(op.type));
|
if(!op.type && ret != type_void) compiler_error(node->pos, "Function expects a void return value but the returned value is %s", docname(op.type));
|
||||||
op.value = convert_untyped_to_typed(node->pos, op.value, ret);
|
op.value = convert_untyped_to_typed(node->pos, op.value, ret);
|
||||||
if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(op.type));
|
if(op.type && op.type != ret) compiler_error(node->pos, "Return statement has different type then returned value, expecting: %s got instead %s", docname(ret), docname(op.type));
|
||||||
BREAK();
|
BREAK();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -570,7 +541,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
CASE(ARRAY, Array){
|
CASE(ARRAY, Array){
|
||||||
// @todo: Arrays of inferred size []
|
// @todo: Arrays of inferred size []
|
||||||
Operand type = resolve_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) compiler_error(node->pos, "Prefix array operator is only allowed on types");
|
||||||
Operand expr = require_const_int(node->expr, AST_CAN_BE_NULL);
|
Operand expr = require_const_int(node->expr, AST_CAN_BE_NULL);
|
||||||
|
|
||||||
Ast_Resolved_Type *resolved = type_array(type.type_val, node->expr ? 1 : 0, bigint_as_unsigned(&expr.big_int_val));
|
Ast_Resolved_Type *resolved = type_array(type.type_val, node->expr ? 1 : 0, bigint_as_unsigned(&expr.big_int_val));
|
||||||
@@ -583,10 +554,11 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
Operand left = resolve_expr(node->expr);
|
Operand left = resolve_expr(node->expr);
|
||||||
Operand index = resolve_expr(node->index);
|
Operand index = resolve_expr(node->index);
|
||||||
if(!is_int(index.type)){
|
if(!is_int(index.type)){
|
||||||
type_error(node->pos, untyped_int, index.type,"Trying to index the array with invalid type, expected int");
|
|
||||||
|
compiler_error(node->pos, "Trying to index the array with invalid type, expected [Int] got instead %s", docname(index.type));
|
||||||
}
|
}
|
||||||
if(!is_array(left.type) && !is_pointer(left.type)){
|
if(!is_array(left.type) && !is_pointer(left.type)){
|
||||||
parsing_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %s instead", docname(left.type));
|
compiler_error(node->pos, "Indexing variable that is not an [Array] or [Pointer], it's of type %s instead", docname(left.type));
|
||||||
}
|
}
|
||||||
|
|
||||||
sym_new_resolved(SYM_VAR, {}, left.value, node);
|
sym_new_resolved(SYM_VAR, {}, left.value, node);
|
||||||
@@ -605,26 +577,26 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
if(name.type == type_type){
|
if(name.type == type_type){
|
||||||
type = name.type_val;
|
type = name.type_val;
|
||||||
if(expected_type && expected_type != type)
|
if(expected_type && expected_type != type)
|
||||||
parsing_error(node->pos, "Variable type different from explicit compound type");
|
compiler_error(node->pos, "Variable type different from explicit compound type");
|
||||||
if(type->kind == TYPE_LAMBDA)
|
if(type->kind == TYPE_LAMBDA)
|
||||||
parsing_error(node->pos, "Calling a lambda type");
|
compiler_error(node->pos, "Calling a lambda type");
|
||||||
}
|
}
|
||||||
type_complete(type);
|
type_complete(type);
|
||||||
node->type = type;
|
node->type = type;
|
||||||
|
|
||||||
if(type->kind == TYPE_ARRAY){
|
if(type->kind == TYPE_ARRAY){
|
||||||
if(node->exprs.len > type->arr.size && type->arr.size != ARRAY_SIZE_INFERRED)
|
if(node->exprs.len > type->arr.size && type->arr.size != ARRAY_SIZE_INFERRED)
|
||||||
parsing_error(node->pos, "compound statement has too many items for this type");
|
compiler_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;
|
||||||
|
|
||||||
For(node->exprs){
|
For(node->exprs){
|
||||||
Ast_Call_Item *i = (Ast_Call_Item *)it;
|
Ast_Call_Item *i = (Ast_Call_Item *)it;
|
||||||
assert(i->kind == AST_CALL_ITEM);
|
assert(i->kind == AST_CALL_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) compiler_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 = require_const_int(i->index, AST_CANT_BE_NULL);
|
Operand index_op = require_const_int(i->index, AST_CANT_BE_NULL);
|
||||||
U64 index = bigint_as_unsigned(&index_op.big_int_val);
|
U64 index = bigint_as_unsigned(&index_op.big_int_val);
|
||||||
if(index > (type->arr.size - 1)) parsing_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
if(index > (type->arr.size - 1)) compiler_error(i->pos, "Invalid index in compound expression, larger then type can store");
|
||||||
}
|
}
|
||||||
Operand expr = resolve_expr(i->item, item_type);
|
Operand expr = resolve_expr(i->item, item_type);
|
||||||
expr.value = convert_untyped_to_typed(i->pos, expr.value, item_type);
|
expr.value = convert_untyped_to_typed(i->pos, expr.value, item_type);
|
||||||
@@ -637,7 +609,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
|
|
||||||
S64 default_iter = 0;
|
S64 default_iter = 0;
|
||||||
For_It(node->exprs, expr){
|
For_It(node->exprs, expr){
|
||||||
if(expr->index) parsing_error(expr->index->pos, "Function call indexing is illegal");
|
if(expr->index) compiler_error(expr->index->pos, "Function call indexing is illegal");
|
||||||
Ast_Atom *name = expr->name;
|
Ast_Atom *name = expr->name;
|
||||||
S64 expr_index = node->exprs.get_index(&expr);
|
S64 expr_index = node->exprs.get_index(&expr);
|
||||||
|
|
||||||
@@ -647,7 +619,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
assert(name->kind == AST_IDENT);
|
assert(name->kind == AST_IDENT);
|
||||||
For_It(agg->members, member){
|
For_It(agg->members, member){
|
||||||
if(member->name.str == name->intern_val.str){
|
if(member->name.str == name->intern_val.str){
|
||||||
if(member->kind == AST_CONST) parsing_error(expr->pos, "Initializing a value that is a constant");
|
if(member->kind == AST_CONST) compiler_error(expr->pos, "Initializing a value that is a constant");
|
||||||
found = member;
|
found = member;
|
||||||
found_type = &type->agg.members[agg->members.get_index(&member)];
|
found_type = &type->agg.members[agg->members.get_index(&member)];
|
||||||
break;
|
break;
|
||||||
@@ -658,18 +630,18 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
S64 i = default_iter++;
|
S64 i = default_iter++;
|
||||||
found = agg->members[i];
|
found = agg->members[i];
|
||||||
found_type = &type->agg.members[i];
|
found_type = &type->agg.members[i];
|
||||||
if(i >= agg->members.len) parsing_error(expr->pos, "Too many arguments in compound constructor");
|
if(i >= agg->members.len) compiler_error(expr->pos, "Too many arguments in compound constructor");
|
||||||
}
|
}
|
||||||
else parsing_error(expr->pos, "Positional argument after named or indexed argument");
|
else compiler_error(expr->pos, "Positional argument after named or indexed argument");
|
||||||
|
|
||||||
if(!found) parsing_error(expr->pos, "Invalid argument in compound constructor");
|
if(!found) compiler_error(expr->pos, "Invalid argument in compound constructor");
|
||||||
if(is_flag_set(found->flags, AST_ITEM_INCLUDED)) parsing_error(found->pos, "Item included multiple times in compound constructor");
|
if(is_flag_set(found->flags, AST_ITEM_INCLUDED)) compiler_error(found->pos, "Item included multiple times in compound constructor");
|
||||||
found->flags = set_flag(found->flags, AST_ITEM_INCLUDED);
|
found->flags = set_flag(found->flags, AST_ITEM_INCLUDED);
|
||||||
|
|
||||||
Operand op = resolve_expr(expr->item, found_type->type);
|
Operand op = resolve_expr(expr->item, found_type->type);
|
||||||
|
|
||||||
op.value = convert_untyped_to_typed(node->pos, op.value, found_type->type);
|
op.value = convert_untyped_to_typed(node->pos, op.value, found_type->type);
|
||||||
if(found_type->type != op.type) parsing_error(expr->pos, "Invalid type of compound constructor item, expected %s got instead %s", type_names[found_type->type->kind], type_names[op.type->kind]);
|
if(found_type->type != op.type) compiler_error(expr->pos, "Invalid type of compound constructor item, expected %s got instead %s", type_names[found_type->type->kind], type_names[op.type->kind]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @note: cleanup, required?
|
// @note: cleanup, required?
|
||||||
@@ -691,7 +663,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
// there are three kinds of possible matches: indexed, named, default
|
// there are three kinds of possible matches: indexed, named, default
|
||||||
Ast_Call_Item *item = 0;
|
Ast_Call_Item *item = 0;
|
||||||
For_It(node->exprs, expr){
|
For_It(node->exprs, expr){
|
||||||
if(expr->index) parsing_error(expr->index->pos, "Function call indexing is illegal");
|
if(expr->index) compiler_error(expr->index->pos, "Function call indexing is illegal");
|
||||||
Ast_Atom *name = expr->name;
|
Ast_Atom *name = expr->name;
|
||||||
|
|
||||||
if(name){
|
if(name){
|
||||||
@@ -704,7 +676,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
item = expr;
|
item = expr;
|
||||||
}
|
}
|
||||||
else if(node->exprs.get_index(&expr) > default_iter){
|
else if(node->exprs.get_index(&expr) > default_iter){
|
||||||
parsing_error(expr->pos, "Positional argument after named argument");
|
compiler_error(expr->pos, "Positional argument after named argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(item)
|
if(item)
|
||||||
@@ -722,13 +694,13 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
Ast_Call_Item *item_default = ast_call_item(arg->default_value->pos, 0, 0, arg->default_value);
|
Ast_Call_Item *item_default = ast_call_item(arg->default_value->pos, 0, 0, arg->default_value);
|
||||||
items.add(item_default);
|
items.add(item_default);
|
||||||
}
|
}
|
||||||
else parsing_error(arg->pos, "Required value in lambda call was not passed");
|
else compiler_error(arg->pos, "Required value in lambda call was not passed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lambda->has_var_args){
|
if(lambda->has_var_args){
|
||||||
if(was_name_indexed)
|
if(was_name_indexed)
|
||||||
parsing_error(lambda->pos, "Cant name index a lambda with var args");
|
compiler_error(lambda->pos, "Cant name index a lambda with var args");
|
||||||
for(S64 i = lambda->args.len; i < node->exprs.len; i++){
|
for(S64 i = lambda->args.len; i < node->exprs.len; i++){
|
||||||
Ast_Call_Item *item = node->exprs.data[i];
|
Ast_Call_Item *item = node->exprs.data[i];
|
||||||
resolve_expr(item->item);
|
resolve_expr(item->item);
|
||||||
@@ -740,14 +712,14 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
// @note: check if all arguments are included and cleanup
|
// @note: check if all arguments are included and cleanup
|
||||||
For(node->exprs){
|
For(node->exprs){
|
||||||
if(!is_flag_set(it->flags, AST_ITEM_INCLUDED))
|
if(!is_flag_set(it->flags, AST_ITEM_INCLUDED))
|
||||||
parsing_error(it->pos, "Invalid argument to function call");
|
compiler_error(it->pos, "Invalid argument to function call");
|
||||||
else it->flags = unset_flag(it->flags, AST_ITEM_INCLUDED);
|
else it->flags = unset_flag(it->flags, AST_ITEM_INCLUDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
node->exprs = items.tight_copy(pctx->perm);
|
node->exprs = items.tight_copy(pctx->perm);
|
||||||
type = type->func.ret;
|
type = type->func.ret;
|
||||||
}
|
}
|
||||||
else parsing_error(node->pos, "Invalid function call type");
|
else compiler_error(node->pos, "Invalid function call type");
|
||||||
|
|
||||||
return operand_rvalue(type);
|
return operand_rvalue(type);
|
||||||
BREAK();
|
BREAK();
|
||||||
@@ -788,7 +760,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
expr.type = type;
|
expr.type = type;
|
||||||
} else goto failure;
|
} else goto failure;
|
||||||
} break;
|
} break;
|
||||||
default: failure: parsing_error(node->pos, "Failed to cast from %s to %s", docname(expr.type), docname(type));;
|
default: failure: compiler_error(node->pos, "Failed to cast from %s to %s", docname(expr.type), docname(type));;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(original_type != type) assert(expr.type == type);
|
if(original_type != type) assert(expr.type == type);
|
||||||
@@ -807,7 +779,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
sym_type(type, node);
|
sym_type(type, node);
|
||||||
return operand_type(type);
|
return operand_type(type);
|
||||||
}
|
}
|
||||||
else{ parsing_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; }
|
else{ compiler_error(node->pos, "Dereferencing expression %s that is not a [Pointer] or [Type]", type_names[value.type->kind]); return {}; }
|
||||||
}break;
|
}break;
|
||||||
case TK_Dereference:{
|
case TK_Dereference:{
|
||||||
return operand_lvalue(type_pointer(value.type));
|
return operand_lvalue(type_pointer(value.type));
|
||||||
@@ -846,11 +818,11 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
else if(token_is_assign(node->op)){
|
else if(token_is_assign(node->op)){
|
||||||
assert(is_flag_set(node->flags, AST_STMT));
|
assert(is_flag_set(node->flags, AST_STMT));
|
||||||
Operand left = resolve_expr(node->left);
|
Operand left = resolve_expr(node->left);
|
||||||
if(!left.is_lvalue) parsing_error(node->pos, "Assigning to rvalue");
|
if(!left.is_lvalue) compiler_error(node->pos, "Assigning to rvalue");
|
||||||
Operand right = resolve_expr(node->right);
|
Operand right = resolve_expr(node->right);
|
||||||
|
|
||||||
right.value = convert_untyped_to_typed(node->pos, right.value, left.type);
|
right.value = convert_untyped_to_typed(node->pos, right.value, left.type);
|
||||||
if(left.type != right.type) parsing_error(node->pos, "Can't assign value when left is %s and right is %s", docname(left.type), docname(right.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));
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -878,7 +850,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
type_complete(type);
|
type_complete(type);
|
||||||
if(!(is_struct(type) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
|
if(!(is_struct(type) || is_enum(type))) compiler_error(node->pos, "Trying to access inside a value that is not a struct or enum");
|
||||||
|
|
||||||
// This happens only on binary nodes which further chain with dots and require lookups
|
// This happens only on binary nodes which further chain with dots and require lookups
|
||||||
// This part cant happen on enums
|
// This part cant happen on enums
|
||||||
@@ -893,7 +865,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
Ast *query = query_struct(agg, ident->intern_val);
|
Ast *query = query_struct(agg, ident->intern_val);
|
||||||
if(query){
|
if(query){
|
||||||
Sym *sym = resolved_get(query);
|
Sym *sym = resolved_get(query);
|
||||||
if(required_to_be_const && sym->kind != SYM_CONST) parsing_error(ident->pos, "Required to be constant");
|
if(required_to_be_const && sym->kind != SYM_CONST) compiler_error(ident->pos, "Required to be constant");
|
||||||
type = sym->type;
|
type = sym->type;
|
||||||
// @copy_paste
|
// @copy_paste
|
||||||
if(type == type_type){
|
if(type == type_type){
|
||||||
@@ -902,10 +874,10 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
}
|
}
|
||||||
if(is_pointer(type)) type = type->base;
|
if(is_pointer(type)) type = type->base;
|
||||||
type_complete(type);
|
type_complete(type);
|
||||||
if(!(is_struct(type) || is_enum(type))) parsing_error(node->pos, "Trying to access inside a value that is not a struct or enum");
|
if(!(is_struct(type) || is_enum(type))) compiler_error(node->pos, "Trying to access inside a value that is not a struct or enum");
|
||||||
sym_associate(ident, sym);
|
sym_associate(ident, sym);
|
||||||
|
|
||||||
} else parsing_error(ident->pos, "No such member in struct");
|
} else compiler_error(ident->pos, "No such member in struct");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we can resolve the last part, this doesnt need to be a struct
|
// Here we can resolve the last part, this doesnt need to be a struct
|
||||||
@@ -932,9 +904,9 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
if(sym->kind == SYM_CONST) rewrite_into_const(node, Ast_Binary, sym);
|
if(sym->kind == SYM_CONST) rewrite_into_const(node, Ast_Binary, sym);
|
||||||
else sym_associate(ident, sym);
|
else sym_associate(ident, sym);
|
||||||
|
|
||||||
} else parsing_error(ident->pos, "No such member in struct");
|
} else compiler_error(ident->pos, "No such member in struct");
|
||||||
}
|
}
|
||||||
else parsing_error(ident->pos, "Trying to [.] access a value that is not [Enum] or [Struct]");
|
else compiler_error(ident->pos, "Trying to [.] access a value that is not [Enum] or [Struct]");
|
||||||
|
|
||||||
if(result.is_const == false && required_to_be_const){
|
if(result.is_const == false && required_to_be_const){
|
||||||
invalid_codepath;
|
invalid_codepath;
|
||||||
@@ -972,41 +944,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
|
|||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
resolve_const(Ast_Expr *ast, Sym *sym){
|
resolve_const(Ast_Expr *ast, Sym *sym){
|
||||||
switch(ast->kind){
|
|
||||||
CASE(LAMBDA, Lambda){
|
|
||||||
return resolve_lambda(node, sym);
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
CASE(ENUM, Enum){
|
|
||||||
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++);
|
|
||||||
}
|
|
||||||
|
|
||||||
sym_const(it->name, op, it, INSERT_INTO_SCOPE);
|
|
||||||
}
|
|
||||||
scope_close(scope_index);
|
|
||||||
return operand_type(type);
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
CASE(STRUCT, Struct){
|
|
||||||
Ast_Resolved_Type *type = type_struct(node);
|
|
||||||
return operand_type(type);
|
|
||||||
BREAK();
|
|
||||||
}
|
|
||||||
|
|
||||||
default: return resolve_expr(ast, 0, sym);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function Operand
|
function Operand
|
||||||
@@ -1024,7 +962,7 @@ resolve_binding(Ast *ast, Sym *sym){
|
|||||||
|
|
||||||
CASE(CONST, Const){
|
CASE(CONST, Const){
|
||||||
Operand expr = resolve_const((Ast_Expr *)node->value, sym);
|
Operand expr = resolve_const((Ast_Expr *)node->value, sym);
|
||||||
if(!expr.is_const) parsing_error(node->pos, "Value of constant variable is not a constant expression");
|
if(!expr.is_const) compiler_error(node->pos, "Value of constant variable is not a constant expression");
|
||||||
assert(expr.type);
|
assert(expr.type);
|
||||||
return expr;
|
return expr;
|
||||||
BREAK();
|
BREAK();
|
||||||
@@ -1033,50 +971,126 @@ resolve_binding(Ast *ast, Sym *sym){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
#endif
|
||||||
resolve_sym(Sym *sym){
|
|
||||||
if(sym->state == SYM_RESOLVED){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if(sym->state == SYM_RESOLVING){
|
|
||||||
parsing_error(sym->ast->pos, "Cyclic dependency");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
assert(sym->state == SYM_NOT_RESOLVED);
|
|
||||||
assert(sym->ast->kind == AST_VAR || sym->ast->kind == AST_CONST);
|
|
||||||
|
|
||||||
sym->state = SYM_RESOLVING;
|
#define Enter_Scope(x) Enter_Scope_Defer package_scope(x)
|
||||||
{
|
struct Enter_Scope_Defer{
|
||||||
Operand op = resolve_binding(sym->ast, sym);
|
Ast_Scope *scope;
|
||||||
sym->value = op.value;
|
Ast_Package *package;
|
||||||
|
Enter_Scope_Defer(Ast_Scope *new_p){
|
||||||
|
scope = pctx->current_scope;
|
||||||
|
pctx->current_scope = new_p;
|
||||||
|
if(new_p->kind == AST_PACKAGE){
|
||||||
|
package = pctx->resolving_package;
|
||||||
|
pctx->resolving_package = (Ast_Package *)new_p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sym->state = SYM_RESOLVED;
|
~Enter_Scope_Defer(){
|
||||||
|
pctx->current_scope = scope;
|
||||||
|
if(package){
|
||||||
|
pctx->resolving_package = package;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pctx->resolving_package->ordered.add((Ast_Named *)sym->ast);
|
function Ast_Decl *
|
||||||
|
search_for_decl(Ast_Scope *scope, Intern_String name){
|
||||||
|
For(scope->decls){
|
||||||
|
if(it->name == name){
|
||||||
|
return it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Sym *
|
function Ast_Decl *
|
||||||
|
search_for_decl_in_current_context(Intern_String name){
|
||||||
|
Ast_Decl *result = search_for_decl(pctx->current_scope, name);
|
||||||
|
if(!result)
|
||||||
|
result = search_for_decl(pctx->resolving_package, name);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
resolve_decl(Ast_Decl *ast){
|
||||||
|
if(ast->state == DECL_RESOLVED){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if(ast->state == DECL_RESOLVING){
|
||||||
|
compiler_error(ast->pos, "Cyclic dependency of %s", ast->name.str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(ast->state == DECL_NOT_RESOLVED);
|
||||||
|
|
||||||
|
ast->state = DECL_RESOLVING;
|
||||||
|
{
|
||||||
|
Operand result = {};
|
||||||
|
switch(ast->kind){
|
||||||
|
CASE(LAMBDA, Decl){
|
||||||
|
// return resolve_lambda(node, sym);
|
||||||
|
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++);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// sym_const(it->name, op, it, INSERT_INTO_SCOPE);
|
||||||
|
// }
|
||||||
|
// scope_close(scope_index);
|
||||||
|
// return operand_type(type);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Ast_Decl *
|
||||||
resolve_name(Token *pos, Intern_String name){
|
resolve_name(Token *pos, Intern_String name){
|
||||||
Sym *sym = sym_get(name);
|
Ast_Decl *decl = search_for_decl_in_current_context(name);
|
||||||
if(!sym) parsing_error(pos, "Unidentified name [%s]", name.str);
|
if(!decl) compiler_error(pos, "Unidentified name [%s]", name.str);
|
||||||
resolve_sym(sym);
|
resolve_decl(decl);
|
||||||
return sym;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
resolve_package(Ast_Package *package){
|
resolve_package(Ast_Package *package){
|
||||||
|
Enter_Scope(package);
|
||||||
For(package->decls){
|
For(package->decls){
|
||||||
resolve_name(it->pos, it->name);
|
resolve_name(it->pos, it->name);
|
||||||
if(ast_is_struct(it)){
|
if(it->kind == AST_STRUCT){
|
||||||
type_complete(const_get_struct(it)->type);
|
// type_complete(it->type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function Ast_Package *
|
function void
|
||||||
parse_file(){
|
parse_file(Ast_File *file){
|
||||||
Scratch scratch;
|
lex_restream(pctx, file->filecontent, file->filename);
|
||||||
|
|
||||||
|
Scratch scratch;
|
||||||
//
|
//
|
||||||
// @note: pop the first token with token_next() / token_expect()
|
// @note: pop the first token with token_next() / token_expect()
|
||||||
// which always should be an indentation token,
|
// which always should be an indentation token,
|
||||||
@@ -1085,66 +1099,91 @@ parse_file(){
|
|||||||
// the first line is properly updated
|
// the first line is properly updated
|
||||||
//
|
//
|
||||||
Token *token = token_get();
|
Token *token = token_get();
|
||||||
Array<Ast_Named *>decls = {scratch};
|
file->name = token->file;
|
||||||
while(!token_is(TK_End)){
|
file->decls = {scratch};
|
||||||
token_expect(SAME_SCOPE);
|
|
||||||
Ast_Named *decl = parse_named(true);
|
if(token_is(SAME_SCOPE) && token_is_keyword(keyword_package, 1)){
|
||||||
|
token_next(); token_next();
|
||||||
|
Token *package = token_expect(TK_Identifier);
|
||||||
|
file->name = package->intern_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(token_expect(SAME_SCOPE)){
|
||||||
|
Ast_Decl *decl = parse_decl(true);
|
||||||
if(!decl) break;
|
if(!decl) break;
|
||||||
|
|
||||||
Sym *sym = sym_new(SYM_VAR, decl->name, decl);
|
if(decl->kind == AST_STRUCT){
|
||||||
if(decl->kind == AST_CONST) {
|
decl->type = type_incomplete(decl);
|
||||||
sym->kind = SYM_CONST;
|
decl->state = DECL_RESOLVED;
|
||||||
Ast_Struct *s = const_try_getting_struct(decl);
|
|
||||||
if(s){
|
|
||||||
s->type = type_incomplete(s);
|
|
||||||
sym->type_val = s->type;
|
|
||||||
sym->type = type_type;
|
|
||||||
sym->state = SYM_RESOLVED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else assert(decl->kind == AST_VAR);
|
|
||||||
|
|
||||||
sym_insert(sym);
|
file->decls.add(decl);
|
||||||
decls.add(decl);
|
|
||||||
}
|
}
|
||||||
Ast_Package *result = ast_package(token, token->file, decls);
|
|
||||||
|
file->decls = file->decls.tight_copy(pctx->perm);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Ast_File
|
||||||
|
ast_file(String filename, String filecontent){
|
||||||
|
Ast_File result = {};
|
||||||
|
result.filecontent = filecontent;
|
||||||
|
result.filename = filename;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function Ast_Package *
|
||||||
test_types(){
|
find_package(Intern_String name, Array<Ast_Package> *packages){
|
||||||
Scratch scratch;
|
For(*packages){
|
||||||
Parse_Ctx ctx = {};
|
if(it.name == name){
|
||||||
parse_init(&ctx, scratch, scratch);
|
return ⁢
|
||||||
pctx = &ctx;
|
}
|
||||||
|
|
||||||
Ast_Resolved_Type *array_type1 = type_array(type_s64, 1, 32);
|
|
||||||
Ast_Resolved_Type *array_type2 = type_array(type_s64, 1, 32);
|
|
||||||
Ast_Resolved_Type *array_type3 = type_array(type_s64, 1, 48);
|
|
||||||
assert(array_type1 == array_type2);
|
|
||||||
assert(array_type2 != array_type3);
|
|
||||||
Ast_Resolved_Type *pointer_type1 = type_pointer(type_s64);
|
|
||||||
Ast_Resolved_Type *pointer_type2 = type_pointer(type_s64);
|
|
||||||
assert(pointer_type2 == pointer_type1);
|
|
||||||
Ast_Resolved_Type *pointer_type3 = type_pointer(pointer_type1);
|
|
||||||
Ast_Resolved_Type *pointer_type4 = type_pointer(pointer_type2);
|
|
||||||
assert(pointer_type3 != pointer_type1);
|
|
||||||
assert(pointer_type3 == pointer_type4);
|
|
||||||
|
|
||||||
Array<Ast_Resolved_Type*> types = {scratch};
|
|
||||||
types.add(type_array(type_s64, 1, 32));
|
|
||||||
Ast_Resolved_Type *func_type1 = type_lambda(0, types[0], types);
|
|
||||||
Ast_Resolved_Type *func_type2 = type_lambda(0, types[0], types);
|
|
||||||
assert(func_type1 == func_type2);
|
|
||||||
|
|
||||||
Array<Ast_Resolved_Type*> types2 = {scratch};
|
|
||||||
{
|
|
||||||
types2.add(type_array(type_s64, 1, 32));
|
|
||||||
types2.add(type_s64);
|
|
||||||
}
|
}
|
||||||
types.add(type_s64);
|
return 0;
|
||||||
Ast_Resolved_Type *func_type3 = type_lambda(0, types[0], types);
|
}
|
||||||
Ast_Resolved_Type *func_type4 = type_lambda(0, types[0], types2);
|
|
||||||
assert(func_type1 != func_type3);
|
function String
|
||||||
assert(func_type3 == func_type4);
|
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 {};
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
|
|
||||||
|
struct Operand{
|
||||||
|
INLINE_VALUE_FIELDS;
|
||||||
|
U8 is_const : 1;
|
||||||
|
U8 is_lvalue: 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Symbols
|
// Symbols
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -22,12 +30,6 @@ struct Sym{
|
|||||||
INLINE_VALUE_FIELDS;
|
INLINE_VALUE_FIELDS;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Operand{
|
|
||||||
INLINE_VALUE_FIELDS;
|
|
||||||
bool is_const: 1;
|
|
||||||
bool is_lvalue: 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum{AST_CANT_BE_NULL = 0, AST_CAN_BE_NULL = 1};
|
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);
|
||||||
@@ -42,7 +44,7 @@ function void
|
|||||||
sym_insert(Sym *sym){
|
sym_insert(Sym *sym){
|
||||||
U64 hash = hash_string(sym->name.s);
|
U64 hash = hash_string(sym->name.s);
|
||||||
Sym *is_sym = (Sym *)map_get(&pctx->syms, hash);
|
Sym *is_sym = (Sym *)map_get(&pctx->syms, hash);
|
||||||
if(is_sym) parsing_error(sym->ast->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str);
|
if(is_sym) compiler_error(sym->ast->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str);
|
||||||
if(pctx->scope > 0) pctx->local_syms.add(sym);
|
if(pctx->scope > 0) pctx->local_syms.add(sym);
|
||||||
map_insert(&pctx->syms, hash, sym);
|
map_insert(&pctx->syms, hash, sym);
|
||||||
}
|
}
|
||||||
@@ -254,7 +256,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
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -332,9 +334,11 @@ type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function Ast_Resolved_Type *
|
function Ast_Resolved_Type *
|
||||||
type_enum(Ast_Enum *ast){
|
type_enum(Ast_Decl *ast){
|
||||||
Ast_Resolved_Type *type = resolve_typespec(ast->typespec, AST_CAN_BE_NULL);
|
Ast_Resolved_Type *type = 0;
|
||||||
|
// Ast_Resolved_Type *type = resolve_typespec(ast->typespec, AST_CAN_BE_NULL);
|
||||||
if(!type){
|
if(!type){
|
||||||
type = untyped_int;
|
type = untyped_int;
|
||||||
}
|
}
|
||||||
@@ -362,16 +366,17 @@ type_incomplete(Ast *ast){
|
|||||||
result->ast = ast;
|
result->ast = ast;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
function void
|
function void
|
||||||
type_struct_complete(Ast_Resolved_Type *type, Ast_Struct *node){
|
type_struct_complete(Ast_Resolved_Type *type, Ast_Decl *node){
|
||||||
|
assert(node->kind == AST_STRUCT);
|
||||||
// @todo: compute size, alignement, offset !!!
|
// @todo: compute size, alignement, offset !!!
|
||||||
// @note: resolve all the struct members first
|
// @note: resolve all the struct members first
|
||||||
type->kind = TYPE_COMPLETING;
|
type->kind = TYPE_COMPLETING;
|
||||||
Scratch scratch;
|
Scratch scratch;
|
||||||
Array<Ast_Resolved_Member> members = {scratch};
|
Array<Ast_Resolved_Member> members = {scratch};
|
||||||
For(node->members){
|
For(node->scope->decls){
|
||||||
Operand op = resolve_binding(it);
|
Operand op = resolve_decl(it);
|
||||||
Intern_String name = ast_get_name(it);
|
Intern_String name = ast_get_name(it);
|
||||||
sym_var(name, op, it);
|
sym_var(name, op, it);
|
||||||
members.add({op.type, name});
|
members.add({op.type, name});
|
||||||
@@ -407,7 +412,7 @@ type_complete(Ast_Resolved_Type *type){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(type->kind == TYPE_COMPLETING){
|
if(type->kind == TYPE_COMPLETING){
|
||||||
parsing_error(type->ast->pos, "Cyclic type dependency");
|
compiler_error(type->ast->pos, "Cyclic type dependency");
|
||||||
}
|
}
|
||||||
else if(type->kind != TYPE_INCOMPLETE){
|
else if(type->kind != TYPE_INCOMPLETE){
|
||||||
return;
|
return;
|
||||||
@@ -417,3 +422,5 @@ type_complete(Ast_Resolved_Type *type){
|
|||||||
type_struct_complete(type, node);
|
type_struct_complete(type, node);
|
||||||
pctx->resolving_package->ordered.add((Ast_Named *)node->parent);
|
pctx->resolving_package->ordered.add((Ast_Named *)node->parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user