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

284
ast.cpp
View File

@@ -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->name = name;
result->typespec = typespec; result->typespec = typespec;
result->expr = expr;
if(result->typespec) result->typespec->parent = result;
if(result->expr) result->expr->parent = result;
return 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; result->name = name;
if(result->expr) result->expr->parent = result; if(result->expr) result->expr->parent = result;
if(result->typespec) result->typespec->parent = result;
return result; return result;
} }
function Ast_Const * function Ast_Package
ast_const(Token *pos, Intern_String name, Ast_Expr *value){ ast_package(Allocator *allocator, Intern_String name, Array<Ast_Decl *> decls){
assert(is_flag_set(value->flags, AST_AGGREGATE) || is_flag_set(value->flags, AST_EXPR) ); Ast_Package result = {};
AST_NEW(Const, CONST, pos, AST_BINDING); result.kind = AST_PACKAGE;
result->value = value; result.decls = decls.copy(allocator);
result->name = name; result.resolved = {allocator};
result->value->parent = result; result.name = name;
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;
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;
}

View File

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

View File

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

View File

@@ -112,7 +112,7 @@ struct Token{
S64 indent; S64 indent;
}; };
String file; Intern_String file;
S32 line; S32 line;
U8 *line_begin; U8 *line_begin;
}; };
@@ -122,7 +122,7 @@ struct Lex_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);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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 &it;
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); }
Ast_Resolved_Type *func_type3 = type_lambda(0, types[0], types); return 0;
Ast_Resolved_Type *func_type4 = type_lambda(0, types[0], types2); }
assert(func_type1 != func_type3);
assert(func_type3 == func_type4); 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 // 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