Complete rework, adding packages

This commit is contained in:
Krzosa Karol
2022-06-09 21:30:52 +02:00
parent 4edd2a4799
commit fbe911d267
11 changed files with 399 additions and 497 deletions

288
ast.cpp
View File

@@ -7,6 +7,7 @@ enum Ast_Kind: U32{
AST_PACKAGE,
AST_SCOPE,
AST_VALUE,
AST_CAST,
AST_IDENT,
@@ -16,6 +17,8 @@ enum Ast_Kind: U32{
AST_CALL_ITEM,
AST_CALL,
AST_VAR,
AST_CONST,
AST_POINTER,
AST_ARRAY,
AST_FOR,
@@ -29,8 +32,6 @@ enum Ast_Kind: U32{
AST_ENUM,
AST_ENUM_MEMBER,
AST_STRUCT,
AST_CONST,
AST_VAR,
};
typedef U32 Ast_Flag;
@@ -43,6 +44,7 @@ enum{
AST_ITEM_INCLUDED = bit_flag(6),
AST_ATOM = bit_flag(7),
AST_FOREIGN = bit_flag(8),
AST_DECL = bit_flag(9),
};
struct Ast{
@@ -161,16 +163,6 @@ struct Ast_Array: Ast_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:
* 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
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{
Array<Ast_Decl *> resolved;
Array<Ast *> children;
Array<Ast *> constants;
enum Ast_Decl_State{
DECL_NOT_RESOLVED,
DECL_RESOLVED,
DECL_RESOLVING,
};
struct Ast_Decl;
struct Ast_Scope: Ast{
Array<Ast_Decl *> resolved;
Array<Ast_Decl *> decls;
Array<Ast *> stmts;
};
struct Ast_Decl: Ast{
Ast_Decl_State state;
// kind:AST_CONST: subkind:AST_STRUCT, AST_ENUM, AST_EXPR(can be TYPE_TYPE), AST_LAMBDA
// kind:AST_VAR : subkind:AST_EXPR, AST_LAMBDA
// Kind: AST_STRUCT implied AST_DECL (should flag AST_CONST AST_DECL)
Intern_String name;
Ast_Kind sub_kind;
Ast_Scope *scope;
Ast_Resolved_Type *type;
};
struct Ast_Var: Ast_Named{
Ast_Expr *typespec;
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;
Array<Ast_Enum_Member *> members;
INLINE_VALUE_FIELDS;
};
struct Ast_Const: Ast_Named{
union{
Ast *ast;
Ast_Expr *value;
Ast_Struct *agg;
Ast_Enum *enu;
};
};
struct Ast_File{
String filename;
String filecontent;
struct Ast_Package:Ast{
Intern_String name;
Array<Ast_Named *> decls;
Array<Ast_Named *> ordered;
Array<Ast_Decl *> decls;
};
struct Ast_Package : Ast_Scope{
Intern_String name;
};
//-----------------------------------------------------------------------------
@@ -482,76 +436,72 @@ ast_array(Token *pos, Ast_Expr *expr){
return result;
}
function Ast_Enum_Member *
ast_enum_member(Token *pos, Intern_String name, Ast_Expr *default_value){
AST_NEW(Enum_Member, ENUM_MEMBER, pos, AST_AGGREGATE_CHILD);
result->name = name;
result->value = default_value;
if(result->value) result->value->parent = result;
function Ast_Scope *
ast_decl_scope(Token *pos, Array<Ast_Decl *> decls){
AST_NEW(Scope, SCOPE, pos, AST_DECL);
result->decls = decls.tight_copy(pctx->perm);
result->resolved = array_make<Ast_Decl *>(pctx->perm, result->decls.len);
For(result->decls){
it->parent = result;
}
return result;
}
function Ast_Enum *
ast_enum(Token *pos, Ast_Expr *typespec, Array<Ast_Enum_Member *> members){
AST_NEW(Enum, ENUM, pos, AST_AGGREGATE);
result->members = members.tight_copy(pctx->perm);
function Ast_Scope *
ast_stmt_scope(Token *pos, Array<Ast *> stmts){
AST_NEW(Scope, SCOPE, pos, AST_STMT);
result->stmts = stmts.tight_copy(pctx->perm);
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->scope->parent = result;
if(result->typespec) result->typespec->parent = result;
For(result->members){
it->parent = result;
}
return result;
}
function Ast_Struct *
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 *
function Ast_Decl *
ast_var(Token *pos, Ast_Expr *typespec, Intern_String name, Ast_Expr *expr){
AST_NEW(Var, VAR, pos, AST_BINDING);
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;
AST_NEW(Decl, VAR, pos, AST_DECL);
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;
}
function Ast_Package *
ast_package(Token *pos, String name, Array<Ast_Named *> decls){
AST_NEW(Package, PACKAGE, pos, 0);
result->decls = decls.tight_copy(pctx->perm);
result->ordered = array_make<Ast_Named *>(pctx->perm, decls.len);
result->name = intern_string(&pctx->interns, name);
For(result->decls) it->parent = result;
function Ast_Decl *
ast_const(Token *pos, Intern_String name, Ast_Expr *expr){
AST_NEW(Decl, CONST, pos, AST_DECL);
result->expr = expr;
result->name = name;
if(result->expr) result->expr->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;
}
@@ -598,61 +548,6 @@ value_float(BigInt a){
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
is_ident(Ast *ast){
B32 result = ast->kind == AST_IDENT;
@@ -670,28 +565,3 @@ is_atom(Ast *ast){
B32 result = is_flag_set(ast->flags, AST_ATOM);
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;
}

View File

@@ -5,7 +5,7 @@
struct Token;
Allocator *bigint_allocator;
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)
struct BigInt_Allocator{
@@ -17,7 +17,7 @@ struct BigInt_Allocator{
#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 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
{

View File

@@ -468,7 +468,7 @@ gen_ast(Ast *ast){
gen(";");
}
}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();
@@ -574,15 +574,3 @@ compile_file(String filename){
String result = compile_string(filecontent, filename);
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}}};

View File

@@ -112,19 +112,19 @@ struct Token{
S64 indent;
};
String file;
S32 line;
U8 *line_begin;
Intern_String file;
S32 line;
U8 *line_begin;
};
struct Lex_Stream{
String stream;
S64 iter;
U8 *line_begin;
String file;
S32 line;
S32 inside_brace_paren;
U8 *line_begin;
Intern_String file;
S32 line;
S32 inside_brace_paren;
Array<Token *> indent_stack;
};
@@ -154,6 +154,7 @@ Intern_String keyword_if;
Intern_String keyword_else;
Intern_String keyword_true;
Intern_String keyword_false;
Intern_String keyword_package;
Intern_String keyword_for;
Intern_String keyword_pass;
Intern_String keyword_cast;
@@ -163,8 +164,10 @@ Intern_String intern_void;
Intern_String intern_foreign;
Intern_String intern_printf;
struct Ast_Scope;
struct Ast_Decl;
struct Ast_Package;
struct Sym;
struct Parse_Ctx:Lexer{
Allocator *perm; // Stores: AST, tokens, interns
Allocator *heap;
@@ -172,15 +175,12 @@ struct Parse_Ctx:Lexer{
U64 unique_ids;
Map type_map;
Ast_Scope *current_scope;
Ast_Package *resolving_package;
Map resolved;
Map syms;
S32 scope;
Array<Sym *> local_syms;
Array<Ast_Decl *> ordered_decls;
Token empty_token;
S64 indent;
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_true = l->intern("true"_s);
keyword_false = l->intern("false"_s);
keyword_package = l->intern("package"_s);
keyword_return = l->intern("return"_s);
keyword_if = l->intern("if"_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->heap = heap_allocator;
ctx->gen = {ctx->perm};
ctx->resolved = {ctx->heap};
ctx->syms = {ctx->heap};
ctx->ordered_decls = {ctx->heap};
ctx->type_map = {ctx->heap};
ctx->local_syms = {ctx->heap};
bigint_allocator = ctx->perm;
lex_init(ctx->perm, ctx->heap, ctx);

View File

@@ -1,3 +1,5 @@
package lambdas
a_type :: S64
pointer_type :: *S64
// null_pointer: pointer_type = null

View File

@@ -165,7 +165,7 @@ lex_parse_ident(Intern_Table *table, Lex_Stream *s, Token *t){
break
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 = {};
t.str = str;
t.file = file;
@@ -540,7 +540,7 @@ lex_restream(Lexer *lexer, String istream, String file){
lexer->stream = {};
lexer->stream.stream = istream;
lexer->stream.line_begin = istream.str;
lexer->stream.file = file;
lexer->stream.file = lexer->intern(file);
lexer->tokens.clear();

View File

@@ -164,10 +164,10 @@ Expr:
#include "parsing.cpp"
#include "typechecking.h"
#include "typechecking.cpp"
#include "ccodegen.cpp"
// #include "ccodegen.cpp"
#include "tests.cpp"
int main(int argument_count, char **arguments){
// test_big_int();
test_os_memory();
thread_ctx_init();
@@ -180,7 +180,7 @@ int main(int argument_count, char **arguments){
test_intern_table();
#if 0
emit_line_directives = true;
if(argument_count > 1){
Scratch scratch;
@@ -211,12 +211,16 @@ int main(int argument_count, char **arguments){
printf("%s", result.str);
result = compile_file("order2.kl"_s);
printf("%s", result.str);
result = compile_file("lambdas.kl"_s);
printf("%s", result.str);
result = compile_file("new_types.kl"_s);
printf("%s", result.str);
#endif
}
#endif
Scratch scratch;
Array<String> files = {scratch};
files.add("lambdas.kl"_s);
files.add("order1.kl"_s);
compile_files(files);
__debugbreak();
}

View File

@@ -1,3 +1,4 @@
package lambdas
other_func :: ()
a_val := recursive_lambda

View File

@@ -1,6 +1,7 @@
function Ast_Decl *parse_decl(B32 is_global);
function void
parsing_error(Token *token, const char *str, ...){
compiler_error(Token *token, const char *str, ...){
Scratch scratch;
STRING_FMT(scratch, str, string);
@@ -109,7 +110,7 @@ function Token *
token_expect(Token_Kind kind){
Token *token = token_get();
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;
}
@@ -119,7 +120,7 @@ function Ast_Expr *
parse_init_stmt(Ast_Expr *expr){
Token *token = token_get();
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)){
token_next();
@@ -175,7 +176,6 @@ parse_optional_type(){
return result;
}
function Ast_Named *parse_named(B32);
function Ast_Block *
parse_block(){
Ast_Block *block = 0;
@@ -257,7 +257,7 @@ parse_block(){
}
else{
Ast *result = parse_named(false);
Ast *result = parse_decl(false);
if(!result){
result = parse_expr();
result = parse_init_stmt((Ast_Expr *)result);
@@ -268,7 +268,7 @@ parse_block(){
stmts.add(result);
}
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;
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))
break;
@@ -412,7 +412,7 @@ parse_expr(S64 min_bp){
Ast_Expr *expr = 0;
if(!token_is(TK_CloseBracket))
expr = parse_expr(0);
Ast_Array *result = ast_array(token, expr);
token_expect(TK_CloseBracket);
result->base = parse_expr(prefix_bp.right);
@@ -430,7 +430,7 @@ parse_expr(S64 min_bp){
token_expect(TK_CloseParen);
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;
case TK_OpenParen: {
@@ -441,7 +441,7 @@ parse_expr(S64 min_bp){
token_expect(TK_CloseParen);
}
}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(;;){
@@ -497,51 +497,45 @@ parse_assign_expr(){
return result;
}
function Ast_Struct *
function Ast_Decl *
parse_struct(Token *pos){
Scratch scratch;
Array<Ast_Var *> members = {scratch};
Array<Ast_Const *> members_const = {scratch};
Array<Ast_Decl *> members = {scratch};
token_match(OPEN_SCOPE);
do{
Token *token = token_get();
Ast_Named *named = parse_named(false);
if(!named) parsing_error(token, "Failed to parse struct member");
named->flags = set_flag(named->flags, AST_AGGREGATE_CHILD);
Ast_Decl *decl = parse_decl(false);
if(!decl) compiler_error(token, "Failed to parse struct member");
if(named->kind == AST_CONST){
members_const.add((Ast_Const *)named);
}
else {
assert(named->kind == AST_VAR);
members.add((Ast_Var *)named);
}
decl->flags = set_flag(decl->flags, AST_AGGREGATE_CHILD);
members.add(decl);
}while(token_match(SAME_SCOPE));
token_expect(CLOSE_SCOPE);
Ast_Struct *result = ast_struct(pos, members, members_const);
Ast_Decl *result = ast_struct(pos, members);
return result;
}
function Ast_Enum *
function Ast_Decl *
parse_enum(Token *pos){
Scratch scratch;
Array<Ast_Enum_Member *> members = {scratch};
Array<Ast_Decl *> members = {scratch};
Ast_Expr *typespec = parse_optional_type();
token_match(OPEN_SCOPE);
do{
Token *name = token_expect(TK_Identifier);
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);
}while(token_match(SAME_SCOPE));
token_expect(CLOSE_SCOPE);
Ast_Enum *result = ast_enum(pos, typespec, members);
Ast_Decl *result = ast_enum(pos, typespec, members);
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.
Statements can have named syntax i :=
*/
function Ast_Named *
parse_named(B32 is_global){
Ast_Named *result = 0;
function Ast_Decl *
parse_decl(B32 is_global){
Ast_Decl *result = 0;
if(is_global) {
token_match(SAME_SCOPE);
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();
if(token_match(TK_Identifier, TK_DoubleColon)){
// @note parse struct binding
Token *struct_pos = token_get();
if(token_match_keyword(keyword_struct)){
Ast_Struct *struct_val = parse_struct(struct_pos);
result = ast_const(tname, tname->intern_val, (Ast_Expr *)struct_val);
result = parse_struct(tname);
}
else if(token_match_keyword(keyword_enum)){
Ast_Enum *enum_val = parse_enum(struct_pos);
result = ast_const(tname, tname->intern_val, (Ast_Expr *)enum_val);
result = parse_enum(tname);
}
// @note parse constant expression
@@ -596,10 +587,11 @@ parse_named(B32 is_global){
result = ast_var(tname, 0, tname->intern_val, expr);
}
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){
result->name = tname->intern_val;
result->flags = set_flag(result->flags, flags);
}

View File

@@ -1,32 +1,6 @@
#define CASE(kind,type) case AST_##kind: { Ast_##type *node = (Ast_##type *)ast;
#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
@@ -38,7 +12,7 @@ check_value_bounds(Token *pos, Value *a){
Scratch scratch;
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);
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
else if(is_string(a.type) && is_string(new_type))
; // 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;
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)){
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
compare_values(Token *pos, Token_Kind op, Value a, Value b, bool is_const){
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);
@@ -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);
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);
@@ -220,14 +194,14 @@ eval_unary(Token *pos, Token_Kind op, Operand *operand){
Value *a = &operand->value;
Ast_Resolved_Type *type = a->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)
a->type = untyped_bool;
if(op == TK_Increment || op == TK_Decrement || op == TK_PostIncrement || op == TK_PostDecrement)
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)
return;
@@ -269,7 +243,7 @@ eval_unary(Token *pos, Token_Kind op, Operand *operand){
default:goto failure;
}
} 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){
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);
assert(expr->type);
}
@@ -337,11 +312,7 @@ _rewrite_into_const(Ast *node, U64 ast_size, Value value){
ast->value = value;
}
function void
_rewrite_into_const(Ast *node, U64 ast_size, Sym *sym){
_rewrite_into_const(node, ast_size, sym->value);
}
#if 0
function Ast_Resolved_Type *
resolve_typespec(Ast_Expr *ast, B32 ast_can_be_null){
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);
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;
}
@@ -360,12 +331,12 @@ require_const_int(Ast_Expr *expr, B32 ast_can_be_null){
if(expr == 0 && ast_can_be_null)
return op;
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)
parsing_error(expr->pos, "Expected a const value");
compiler_error(expr->pos, "Expected a const value");
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;
}
@@ -375,12 +346,12 @@ resolve_and_require_bool(const char *error, Ast_Expr *expr, B32 ast_can_be_null
if(!expr){
if(ast_can_be_null)
return {};
else parsing_error(0, "Compiler error: Null expression");
else compiler_error(0, "Compiler error: Null expression");
}
Operand op = resolve_expr(expr);
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;
@@ -395,9 +366,9 @@ resolve_stmt(Ast *ast, Ast_Resolved_Type *ret){
switch(ast->kind){
CASE(RETURN, Return){ // @todo: need to check if all paths return a value
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);
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();
}
@@ -570,7 +541,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
CASE(ARRAY, Array){
// @todo: Arrays of inferred size []
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);
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 index = resolve_expr(node->index);
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)){
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);
@@ -605,26 +577,26 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
if(name.type == type_type){
type = name.type_val;
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)
parsing_error(node->pos, "Calling a lambda type");
compiler_error(node->pos, "Calling a lambda type");
}
type_complete(type);
node->type = type;
if(type->kind == TYPE_ARRAY){
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;
For(node->exprs){
Ast_Call_Item *i = (Ast_Call_Item *)it;
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){
Operand index_op = require_const_int(i->index, AST_CANT_BE_NULL);
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);
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;
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;
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);
For_It(agg->members, member){
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_type = &type->agg.members[agg->members.get_index(&member)];
break;
@@ -658,18 +630,18 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
S64 i = default_iter++;
found = 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(is_flag_set(found->flags, AST_ITEM_INCLUDED)) parsing_error(found->pos, "Item included multiple times in compound constructor");
if(!found) compiler_error(expr->pos, "Invalid argument 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);
Operand op = resolve_expr(expr->item, 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?
@@ -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
Ast_Call_Item *item = 0;
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;
if(name){
@@ -704,7 +676,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
item = expr;
}
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)
@@ -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);
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(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++){
Ast_Call_Item *item = node->exprs.data[i];
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
For(node->exprs){
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);
}
node->exprs = items.tight_copy(pctx->perm);
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);
BREAK();
@@ -788,7 +760,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
expr.type = type;
} else goto failure;
} 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);
@@ -807,7 +779,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
sym_type(type, node);
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;
case TK_Dereference:{
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)){
assert(is_flag_set(node->flags, AST_STMT));
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);
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{
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 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);
if(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;
// @copy_paste
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;
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);
} 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
@@ -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);
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){
invalid_codepath;
@@ -972,41 +944,7 @@ resolve_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_res
function Operand
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
@@ -1024,7 +962,7 @@ resolve_binding(Ast *ast, Sym *sym){
CASE(CONST, Const){
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);
return expr;
BREAK();
@@ -1033,50 +971,126 @@ resolve_binding(Ast *ast, Sym *sym){
}
}
function void
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);
#endif
sym->state = SYM_RESOLVING;
{
Operand op = resolve_binding(sym->ast, sym);
sym->value = op.value;
#define Enter_Scope(x) Enter_Scope_Defer package_scope(x)
struct Enter_Scope_Defer{
Ast_Scope *scope;
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){
Sym *sym = sym_get(name);
if(!sym) parsing_error(pos, "Unidentified name [%s]", name.str);
resolve_sym(sym);
return sym;
Ast_Decl *decl = search_for_decl_in_current_context(name);
if(!decl) compiler_error(pos, "Unidentified name [%s]", name.str);
resolve_decl(decl);
return decl;
}
function void
resolve_package(Ast_Package *package){
Enter_Scope(package);
For(package->decls){
resolve_name(it->pos, it->name);
if(ast_is_struct(it)){
type_complete(const_get_struct(it)->type);
if(it->kind == AST_STRUCT){
// type_complete(it->type);
}
}
}
function Ast_Package *
parse_file(){
Scratch scratch;
function void
parse_file(Ast_File *file){
lex_restream(pctx, file->filecontent, file->filename);
Scratch scratch;
//
// @note: pop the first token with token_next() / token_expect()
// which always should be an indentation token,
@@ -1085,66 +1099,91 @@ parse_file(){
// the first line is properly updated
//
Token *token = token_get();
Array<Ast_Named *>decls = {scratch};
while(!token_is(TK_End)){
token_expect(SAME_SCOPE);
Ast_Named *decl = parse_named(true);
file->name = token->file;
file->decls = {scratch};
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;
Sym *sym = sym_new(SYM_VAR, decl->name, decl);
if(decl->kind == AST_CONST) {
sym->kind = SYM_CONST;
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;
}
if(decl->kind == AST_STRUCT){
decl->type = type_incomplete(decl);
decl->state = DECL_RESOLVED;
}
else assert(decl->kind == AST_VAR);
sym_insert(sym);
decls.add(decl);
file->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;
}
function void
test_types(){
Scratch scratch;
Parse_Ctx ctx = {};
parse_init(&ctx, scratch, scratch);
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);
function Ast_Package *
find_package(Intern_String name, Array<Ast_Package> *packages){
For(*packages){
if(it.name == name){
return &it;
}
}
types.add(type_s64);
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);
assert(func_type3 == func_type4);
}
return 0;
}
function String
compile_files(Array<String> filename){
Scratch scratch(thread_ctx.scratch);
Array<Ast_File> files = {scratch};
For(filename){
String filecontent = os_read_file(scratch, it);
assert(filecontent.len);
files.add(ast_file(it, filecontent));
}
F64 total_time = os_time();
OS_Heap heap = win32_os_heap_create(false, mib(16), 0);
Parse_Ctx ctx = {};
parse_init(&ctx, scratch, &heap);
F64 parse_begin = os_time();
Array<Ast_Package> packages = {&heap};
For(files){
parse_file(&it);
Ast_Package *package = find_package(it.name, &packages);
if(package){
package->decls.add(it.decls);
} else {
packages.add(ast_package(&heap, it.name, it.decls));
}
}
F64 parse_end = os_time();
For(packages){
resolve_package(&it);
}
exp_destroy(&heap);
F64 flattening_end = os_time();
printf("\n//-------------------------------");
printf("\n// Parse : %f", parse_end - parse_begin);
printf("\n// Total : %f", flattening_end - total_time);
printf("\n//-------------------------------");
return {};
}

View File

@@ -1,4 +1,12 @@
struct Operand{
INLINE_VALUE_FIELDS;
U8 is_const : 1;
U8 is_lvalue: 1;
};
#if 0
//-----------------------------------------------------------------------------
// Symbols
//-----------------------------------------------------------------------------
@@ -22,12 +30,6 @@ struct Sym{
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};
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);
@@ -42,7 +44,7 @@ function void
sym_insert(Sym *sym){
U64 hash = hash_string(sym->name.s);
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);
map_insert(&pctx->syms, hash, sym);
}
@@ -254,7 +256,7 @@ operand_rvalue(Ast_Resolved_Type *type){
result.is_lvalue = false;
return result;
}
#endif
//-----------------------------------------------------------------------------
// Hash consed types
//-----------------------------------------------------------------------------
@@ -332,9 +334,11 @@ type_lambda(Ast *ast, Ast_Resolved_Type *ret, Array<Ast_Resolved_Type *> args){
return result;
}
function Ast_Resolved_Type *
type_enum(Ast_Enum *ast){
Ast_Resolved_Type *type = resolve_typespec(ast->typespec, AST_CAN_BE_NULL);
type_enum(Ast_Decl *ast){
Ast_Resolved_Type *type = 0;
// Ast_Resolved_Type *type = resolve_typespec(ast->typespec, AST_CAN_BE_NULL);
if(!type){
type = untyped_int;
}
@@ -362,16 +366,17 @@ type_incomplete(Ast *ast){
result->ast = ast;
return result;
}
#if 0
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 !!!
// @note: resolve all the struct members first
type->kind = TYPE_COMPLETING;
Scratch scratch;
Array<Ast_Resolved_Member> members = {scratch};
For(node->members){
Operand op = resolve_binding(it);
For(node->scope->decls){
Operand op = resolve_decl(it);
Intern_String name = ast_get_name(it);
sym_var(name, op, it);
members.add({op.type, name});
@@ -407,7 +412,7 @@ type_complete(Ast_Resolved_Type *type){
return;
}
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){
return;
@@ -417,3 +422,5 @@ type_complete(Ast_Resolved_Type *type){
type_struct_complete(type, node);
pctx->resolving_package->ordered.add((Ast_Named *)node->parent);
}
#endif