Change the decl searching api while figuring out how to implement

function overloading
This commit is contained in:
Krzosa Karol
2022-09-29 12:04:21 +02:00
parent a7524a0071
commit 5f11a11f0f
9 changed files with 113 additions and 53 deletions

View File

@@ -38,7 +38,9 @@ api F32 absolute(F32 value) {
return value;
}
api S32 square(S32 val) { return val * val; }
api S32 square(S32 val) {
return val * val;
}
api S32 clamp01(S32 val) {
S32 result = clamp(0, val, 1);

View File

@@ -227,10 +227,12 @@ How does current declaration order resolver works:
*/
struct Ast_Scope: Ast{
String debug_name; // Dont use
Array<Ast_Scope *> implicit_imports;
Array<Ast_Decl *> decls;
Array<Ast *> stmts;
U32 visit_id;
U32 scope_id;
Ast_Scope *file; // Self referential for scope and module
Ast_Module *module;
@@ -264,7 +266,7 @@ enum Ast_Decl_State{
struct Ast_Decl: Ast{
Ast_Decl_State state;
Intern_String name;
Intern_String unique_name; // For code generation
Intern_String unique_name; // For code generation, currently only present on lambdas
Ast_Scope *scope;
Ast_Expr *typespec;
@@ -463,6 +465,7 @@ begin_decl_scope(Allocator *scratch, Token *pos){
result->file = pctx->currently_parsed_file;
result->module = pctx->currently_parsed_file->module;
result->scope_id = pctx->scope_ids++;
result->debug_name = pos->string;
assert(result->file);
pctx->currently_parsed_scope = result;
return result;
@@ -482,6 +485,7 @@ begin_stmt_scope(Allocator *scratch, Token *pos){
result->file = pctx->currently_parsed_file;
result->module = pctx->currently_parsed_file->module;
result->scope_id = pctx->scope_ids++;
result->debug_name = pos->string;
assert(result->file);
pctx->currently_parsed_scope = result;
return result;
@@ -547,6 +551,7 @@ ast_decl_scope(Token *pos, Allocator *allocator, Ast_File *file){
AST_NEW(Scope, SCOPE, pos, AST_DECL);
result->decls = {allocator};
result->file = file;
result->scope_id = pctx->scope_ids++;
assert(result->file);
return result;

View File

@@ -123,6 +123,7 @@ add_module(Token *pos, Intern_String filename, B32 command_line_module){
Ast_Module *result = ast_new(Ast_Module, AST_MODULE, pos, 0);
result->absolute_file_path = string_copy(pctx->perm, absolute_file_path);
result->absolute_base_folder = string_copy(pctx->perm, absolute_base_folder);
result->debug_name = string_skip_to_last_slash(result->absolute_file_path);
// log_info("Adding module: %Q\n", filename);
result->module = result; // @warning: self referential
result->file = result; // @warning: self referential
@@ -170,7 +171,7 @@ compile_file_to_string(String filename){
// @note: language stuff needs to be declared before type_info data
// so we mark where it ends
pctx->base_language_ordered_decl_len = pctx->ordered_decls.len;
Ast_Decl *any_decl = search_for_decl(module, pctx->intern("Any"_s));
Ast_Decl *any_decl = search_for_single_decl(module, pctx->intern("Any"_s));
assert(any_decl->type == type_type);
type_any = any_decl->type_val;
}

View File

@@ -201,6 +201,7 @@ struct Parse_Ctx:Lexer{
Ast_Scope *currently_parsed_scope;
Ast_File *currently_parsed_file;
U32 scope_ids;
U32 scope_visit_id;
Array<String> module_folders;
String module_folder;

View File

@@ -1,15 +1,12 @@
/*
- [ ] 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.
- [ ] Introduce List to reduce heap allocations and make it more arena friendly, can we get rid of heap completly?
- [ ] Detecting if return was called
- [ ] Fix . operator lookups
- [ ] '.' Operator doesn't handle expressions inside the dot chain, no good, so casts don't work
- [ ] Combining casts with . operator
- [ ] Builtin data structures
- [ ] Fix Length etc. they should be function calls not operators
- [ ] Strings probably should have len() instead of string.len
- [ ] Slices
- [ ] Some way to take slice of data
@@ -18,7 +15,6 @@
- [ ] Hash tables
- [ ] C Codegen
- [ ] Function renaming to prevent colissions, we can't really touch other stuff cause I want it to be easily debuggable
- [ ] Programming constructs
- [ ] Defer statement
@@ -135,6 +131,9 @@ For modules it's a bit different cause they should be distributed as valid.
## Done
- [x] Function renaming to prevent colissions, we can't really touch other stuff cause I want it to be easily debuggable
- [x] Fix Length etc. they should be function calls not operators
- [x] 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.
- [x] Disable .len for Strings, are there other things that use this convention?
- [x] Calculate size and alignment of struct data types
- [x] Consider changing syntax of scopes to use braces { } NO

View File

@@ -751,6 +751,7 @@ register_ast_file(Token *pos, String absolute_file_path, Ast_Module *module, B32
file->decls = {pctx->heap};
file->implicit_imports = {pctx->heap};
file->pos = pos;
file->debug_name = string_skip_to_last_slash(absolute_file_path);
file->module->all_loaded_files.add(file);
file->scope_id = pctx->scope_ids++;
pctx->files.add(file);
@@ -891,6 +892,10 @@ parse_file(Ast_File *file){
continue;
}
if(!file->pos){
file->pos = token_get();
}
Ast_Decl *decl = parse_decl(true);
if(!decl) break;

View File

@@ -409,46 +409,104 @@ _rewrite_into_const(Ast *node, U64 ast_size, Value value){
ast->resolved_type = value.type;
}
function Ast_Decl *
_search_for_decl(Ast_Scope *scope, Intern_String name, S32 level){
struct Scope_Search {
Array<Ast_Decl *> results;
Intern_String name;
Ast_Scope *scope;
bool exit_on_find;
bool search_only_current_scope;
U32 scope_visit_id;
};
function void
inside_scope_search(Scope_Search *search, Ast_Scope *scope, int level){
if(scope->visit_id == search->scope_visit_id) return;
scope->visit_id = search->scope_visit_id;
// Search for declarations in current scope
For(scope->decls){
if(it->name == name){
return it;
if(it->name == search->name){
search->results.add(it);
if(search->exit_on_find){
return;
}
}
}
// Search for declarations in imported implicitly scopes
if(level < 2 || scope->kind != AST_FILE){
For(scope->implicit_imports){
Ast_Decl *result = 0;
if(scope->kind != AST_MODULE || level < 2)
result = _search_for_decl(it, name, level+1);
if(result) return result;
}
inside_scope_search(search, it, level + 1);
return 0;
if(search->exit_on_find && search->results.len){
return;
}
}
}
}
function Ast_Decl *
search_for_decl(Ast_Scope *scope, Intern_String name, Search_Flag flags = 0){
Ast_Decl *result = 0;
function void
scope_search(Scope_Search *search){
// Climb the scope tree and search each scope in module and also
// search in implicitly imported scopes
Ast_Scope *scope = search->scope;
for(Ast_Scope *it = scope; it; it=it->parent_scope){
result = _search_for_decl(it, name, 0);
if(result) break;
if(is_flag_set(flags, SEARCH_ONLY_CURRENT_SCOPE)) break;
inside_scope_search(search, it, 0);
if(search->exit_on_find && search->results.len){
return;
}
if(!result && !is_flag_set(flags, SEARCH_ONLY_CURRENT_SCOPE)){
result = _search_for_decl(scope->module, name, 0);
if(search->search_only_current_scope){
return;
}
}
inside_scope_search(search, scope->module, 0);
}
function Scope_Search
make_scope_search(Arena *arena, Ast_Scope *scope, Intern_String name){
Scope_Search result = {};
result.results.allocator = arena;
result.name = name;
result.scope_visit_id = ++pctx->scope_visit_id;
result.scope = scope;
result.exit_on_find = true;
return result;
}
function Ast_Decl *
resolve_name(Ast_Scope *scope, Token *pos, Intern_String name, Search_Flag search_flags){
Ast_Decl *decl = search_for_decl(scope, name, search_flags);
if(!decl) {
compiler_error(pos, "Unidentified name [%s]", name.str);
search_for_single_decl(Ast_Scope *scope, Intern_String name){
Scratch scratch;
Scope_Search search = make_scope_search(scratch, scope, name);
scope_search(&search);
if(search.results.len == 0){
compiler_error(0, "Unidentified name [%s]", name.str);
}
if(search.results.len > 1){
compiler_error(0, "Found multiple definitions of name [%s]", name.str);
}
return search.results.data[0];
}
function Ast_Decl *
resolve_name(Ast_Scope *scope, Token *pos, Intern_String name, Search_Flag search_flags){
Scratch scratch;
Scope_Search search = make_scope_search(scratch, scope, name);
search.search_only_current_scope = search_flags & SEARCH_ONLY_CURRENT_SCOPE;
scope_search(&search);
if(search.results.len == 0){
compiler_error(pos, "Unidentified name [%s]", name.str);
}
if(search.results.len > 1){
compiler_error(pos, "Found multiple definitions of name [%s]", name.str);
}
Ast_Decl *decl = *search.results.data;
resolve_decl(decl);
return decl;
}
@@ -460,11 +518,14 @@ insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){
//
// 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);
if(find){
// if(find->kind != AST_LAMBDA)
compiler_error(find->pos, decl->pos, "[%s] is already defined", decl->name.str);
Scratch scratch;
Scope_Search search = make_scope_search(scratch, scope, decl->name);
search.search_only_current_scope = true;
scope_search(&search);
if(search.results.len != 0){
compiler_error(search.results.data[0]->pos, decl->pos, "[%s] is already defined", decl->name.str);
}
scope->decls.add(decl);
}

View File

@@ -3,7 +3,7 @@ struct Operand{
INLINE_VALUE_FIELDS;
Ast_Decl *resolved_decl;
U8 is_const : 1;
U8 is_lvalue: 1;
U8 is_lvalue : 1;
U8 pound_strict: 1;
};

View File

@@ -50,20 +50,6 @@ 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_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
if value > max;; return max
if value < min;; return min