This commit is contained in:
Krzosa Karol
2022-09-28 17:15:22 +02:00
parent 95400a0929
commit 681b3c1f95
8 changed files with 84 additions and 56 deletions

View File

@@ -65,28 +65,28 @@ Release :: (m: *Memory)
## What's missing ? ## What's missing ?
- [x] Constant evaluation and constant folding - Folding and precomputing every expression that can be calculated at compile time. Which allows to check if a given constant expression is actually something that can be computed at compile time. - [x] Constant evaluation and constant folding - Folding and precomputing every expression that can be calculated at compile time. Which allows to check if a given constant expression is actually something that can be computed at compile time
- [ ] Constant expressions with types specified by the user. - [ ] Constant expressions with concrete types
- [x] Untyped types - Context dependent type assignment of constant expressions, this is a feature I really loved in Go, it makes constants work very well with a very strict type system and it makes errors like overflow of constants in C due to bad size specifier impossible. - [x] Untyped types - Context dependent type assignment of constant expressions, this is a feature I really loved in Go, it makes constants work very well with a very strict type system and it makes errors like overflow of constants in C due to bad size specifier impossible
- [x] Infinite precision integers in constants. - [x] Infinite precision integers in constants
- [x] Resolution of all untyped types in the typechecking stage. - [x] Resolution of all untyped types in the typechecking stage
- [x] Special case of booleans and their type propagation. - [x] Special case of booleans and their type propagation
- [x] Module system - [x] Module system
- [x] Lazy evaluation of modules (unused code is not compiled or typechecked) - [x] Lazy evaluation of modules (unused code is not compiled or typechecked)
- [x] Import module, load project file distinction - [x] Import module, load project file distinction
- [x] Order independent declarations - The ordering of functions in code files or modules does not matter, compiler figures all that stuff out for you. "main" can be wherever you want it to be and all functions should be available without problems. - [x] Order independent declarations - The ordering of functions in code files or modules does not matter, compiler figures all that stuff out for you. "main" can be wherever you want it to be and all functions should be available without problems
- [x] Synchronize generated C code with original source using line directives so that debuggers work. - [x] Synchronize generated C code with original source using line directives so that debuggers work
- [ ] Expressions - [ ] Expressions
- [x] Compounds with named fields and numbered fields - [x] Compounds with named fields and numbered fields
- [x] Functions calls with named arguments - [x] Functions calls with named arguments
- [x] All the standard binary, unary expressions - [x] All the standard binary, unary expressions
- [x] Pointer arithmetic and pointer as array - [x] Pointer arithmetic and pointer as array
- [ ] Dot access expression needs a redesign - [ ] Dot access expression needs a redesign because it doesn't handle expressions after the dot it requires names instead
- [ ] Casting might need a redesign not sure - [ ] Casting might need a redesign not sure
- [x] Runtime reflection - [x] Runtime reflection

View File

@@ -23,45 +23,6 @@ destroy_compiler(){
exp_destroy(&pctx->stage_arena); exp_destroy(&pctx->stage_arena);
} }
function void
parse_file(Ast_File *file){
assert(file);
Scratch scratch;
file->filecontent = os_read_file(pctx->perm, file->absolute_file_path);
if(file->filecontent.len == 0){
compiler_error(file->pos, "Failed to open file \"%Q\"", file->absolute_file_path);
}
pctx->currently_parsed_file = file;
pctx->currently_parsed_scope = file;
lex_restream(pctx, file->filecontent, file->absolute_file_path);
while(token_expect(SAME_SCOPE)){
if(token_match_pound(pctx->intern("load"_s))){
parse_load(true);
continue;
} else if(token_match_pound(pctx->intern("import"_s))){
parse_import(true);
continue;
}
Ast_Decl *decl = parse_decl(true);
if(!decl) break;
set_flag(decl->flags, AST_GLOBAL);
if(decl->kind == AST_STRUCT){
decl->type = type_type;
decl->type_val = type_incomplete(decl);
decl->state = DECL_RESOLVED;
}
insert_into_scope(file, decl);
}
pctx->currently_parsed_scope = 0;
pctx->currently_parsed_file = 0;
}
function void function void
insert_builtin_into_scope(Ast_Scope *p, String name, Ast_Type *type){ insert_builtin_into_scope(Ast_Scope *p, String name, Ast_Type *type){
Intern_String string = pctx->intern(name); Intern_String string = pctx->intern(name);

View File

@@ -1,6 +1,9 @@
/* /*
- [ ] Basic - [ ] Basic
- [ ] Idea to fix overshoot when debugging and it goes to the
close bracket and there is not enough line directives.
- Store the last outputed line and propagate it on the close brace etc.
- [ ] Detecting if return was called - [ ] Detecting if return was called
- [ ] Fix . operator lookups - [ ] Fix . operator lookups
- [ ] Combining casts with . operator - [ ] Combining casts with . operator

View File

@@ -736,8 +736,7 @@ register_ast_file(Token *pos, String absolute_file_path, Ast_Module *module, B32
break; break;
} }
print_token_context(it->pos); compiler_error(it->pos, pos, "This file is already loaded by module: %Q, try importing that module to get access to it", module->absolute_file_path);
compiler_error(pos, "This file is already loaded by module: %Q, try importing that module to get access to it", module->absolute_file_path);
} }
} }
@@ -866,3 +865,44 @@ parse_decl(B32 is_global){
return result; return result;
} }
function void insert_into_scope(Ast_Scope *scope, Ast_Decl *decl);
function Ast_Type *type_incomplete(Ast *ast);
function void
parse_file(Ast_File *file){
assert(file);
Scratch scratch;
file->filecontent = os_read_file(pctx->perm, file->absolute_file_path);
if(file->filecontent.len == 0){
compiler_error(file->pos, "Failed to open file \"%Q\"", file->absolute_file_path);
}
pctx->currently_parsed_file = file;
pctx->currently_parsed_scope = file;
lex_restream(pctx, file->filecontent, file->absolute_file_path);
while(token_expect(SAME_SCOPE)){
if(token_match_pound(pctx->intern("load"_s))){
parse_load(true);
continue;
} else if(token_match_pound(pctx->intern("import"_s))){
parse_import(true);
continue;
}
Ast_Decl *decl = parse_decl(true);
if(!decl) break;
set_flag(decl->flags, AST_GLOBAL);
if(decl->kind == AST_STRUCT){
decl->type = type_type;
decl->type_val = type_incomplete(decl);
decl->state = DECL_RESOLVED;
}
insert_into_scope(file, decl);
}
pctx->currently_parsed_scope = 0;
pctx->currently_parsed_file = 0;
}

View File

@@ -445,19 +445,26 @@ search_for_decl(Ast_Scope *scope, Intern_String name, Search_Flag flags = 0){
function Ast_Decl * function Ast_Decl *
resolve_name(Ast_Scope *scope, Token *pos, Intern_String name, Search_Flag search_flags){ resolve_name(Ast_Scope *scope, Token *pos, Intern_String name, Search_Flag search_flags){
Ast_Decl *decl = search_for_decl(scope, name, search_flags); Ast_Decl *decl = search_for_decl(scope, name, search_flags);
if(!decl) compiler_error(pos, "Unidentified name [%s]", name.str); if(!decl) {
compiler_error(pos, "Unidentified name [%s]", name.str);
}
resolve_decl(decl); resolve_decl(decl);
return decl; return decl;
} }
function void function void
insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){ insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){
// This function is called when resolving statements
// inside code blocks, inserting lambda arguments into scope
//
// It's also called when scanning top level declarations of a module
// as such we probably don't want to call any resolve stuff here
Ast_Decl *find = search_for_decl(scope, decl->name); Ast_Decl *find = search_for_decl(scope, decl->name);
if(find){ if(find){
print_token_context(find->pos); // if(find->kind != AST_LAMBDA)
compiler_error(decl->pos, "[%s] is already defined", decl->name.str); compiler_error(find->pos, decl->pos, "[%s] is already defined", decl->name.str);
} }
scope->decls.add(decl); scope->decls.add(decl);
} }

View File

@@ -224,8 +224,9 @@ type_array(Ast_Type *base, S64 size){
function Ast_Type * function Ast_Type *
type_lambda(Ast *ast, Array<Ast_Type *> return_vals, Array<Ast_Type *> args){ type_lambda(Ast *ast, Array<Ast_Type *> return_vals, Array<Ast_Type *> args){
Ast_Type *ret = type_try_tupling(return_vals, ast); Ast_Type *ret = type_try_tupling(return_vals, ast);
U64 hash = hash_ptr(ret); U64 hash_without_ret = 13; // @function_overloading scrap this if we changed course
For(args) hash = hash_mix(hash, hash_ptr(it)); For(args) hash_without_ret = hash_mix(hash_without_ret, hash_ptr(it));
U64 hash = hash_mix(hash_ptr(ret), hash_without_ret);
Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash); Ast_Type *result = (Ast_Type *)map_get(&pctx->type_map, hash);
if(result){ if(result){
@@ -238,6 +239,7 @@ type_lambda(Ast *ast, Array<Ast_Type *> return_vals, Array<Ast_Type *> args){
result->ast = ast; result->ast = ast;
result->func.ret = ret; result->func.ret = ret;
result->func.args = args.tight_copy(pctx->perm); result->func.args = args.tight_copy(pctx->perm);
result->func.hash_without_ret = hash_without_ret; // @function_overloading scrap this if we changed course
map_insert(&pctx->type_map, hash, result); map_insert(&pctx->type_map, hash, result);
return result; return result;

View File

@@ -101,6 +101,7 @@ struct Ast_Type{
struct{ struct{
Ast_Type * ret; Ast_Type * ret;
Array<Ast_Type *> args; Array<Ast_Type *> args;
U64 hash_without_ret; // @function_overloading scrap this if we changed course
}func; }func;
}; };
}; };

View File

@@ -50,6 +50,20 @@ Vec3_Add :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x+b.x, a.y+b.y, a.z+b.
Vec3_Div :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x/b.x, a.y/b.y, a.z/b.z} Vec3_Div :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x/b.x, a.y/b.y, a.z/b.z}
Vec3_Sub :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x-b.x, a.y-b.y, a.z-b.z} Vec3_Sub :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x-b.x, a.y-b.y, a.z-b.z}
/*
@todo: Add function overloading
Current plan:
* allow insert_into_scope to insert multiple lambdas
* change resolve_name and search_for_decl to something
that can seek multiple lambda declarations
resolve them and return a match to hash or type
* change the order of lambda call resolution, probably would have to
hash the arguments first to match the lambda call
*/
// Add :: (a: Vec3, b: Vec3): Vec3 ;; return Vec3{a.x+b.x, a.y+b.y, a.z+b.z}
// Add :: (a: Vec2, b: Vec2): Vec2 ;; return Vec2{a.x+b.x, a.y+b.y}
F32_Clamp :: (min: F32, value: F32, max: F32): F32 F32_Clamp :: (min: F32, value: F32, max: F32): F32
if value > max;; return max if value > max;; return max
if value < min;; return min if value < min;; return min