checker: simplify generic fn post processing

pull/7078/head
joe-conigliaro 2020-12-01 16:43:10 +11:00
parent 0e54b9acb5
commit a7d917474d
No known key found for this signature in database
GPG Key ID: C12F7136C08206F1
2 changed files with 9 additions and 26 deletions

View File

@ -414,6 +414,7 @@ pub mut:
imports []Import imports []Import
errors []errors.Error errors []errors.Error
warnings []errors.Warning warnings []errors.Warning
generic_fns []&FnDecl
} }
pub struct IdentFn { pub struct IdentFn {

View File

@ -61,19 +61,12 @@ mut:
inside_sql bool // to handle sql table fields pseudo variables inside_sql bool // to handle sql table fields pseudo variables
cur_orm_ts table.TypeSymbol cur_orm_ts table.TypeSymbol
error_details []string error_details []string
generic_fn_queue []&ast.FnDecl
vmod_file_content string // needed for @VMOD_FILE, contents of the file, *NOT its path** vmod_file_content string // needed for @VMOD_FILE, contents of the file, *NOT its path**
vweb_gen_types []table.Type // vweb route checks vweb_gen_types []table.Type // vweb route checks
prevent_sum_type_unwrapping_once bool // needed for assign new values to sum type, stopping unwrapping then prevent_sum_type_unwrapping_once bool // needed for assign new values to sum type, stopping unwrapping then
loop_label string // set when inside a labelled for loop loop_label string // set when inside a labelled for loop
} }
struct GenericFnQueueInfo {
file_idx int
start int
end int
}
pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker { pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
return Checker{ return Checker{
table: table table: table
@ -134,8 +127,6 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
mut has_main_mod_file := false mut has_main_mod_file := false
mut has_main_fn := false mut has_main_fn := false
mut files_from_main_module := []&ast.File{} mut files_from_main_module := []&ast.File{}
mut generic_fn_count := 0
mut generic_fn_queue_info := []GenericFnQueueInfo{}
for i in 0 .. ast_files.len { for i in 0 .. ast_files.len {
file := unsafe {&ast_files[i]} file := unsafe {&ast_files[i]}
c.check(file) c.check(file)
@ -146,12 +137,6 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
has_main_fn = true has_main_fn = true
} }
} }
// add queue info for generic functions
if c.generic_fn_queue.len > 0 {
generic_fn_queue_info <<
GenericFnQueueInfo{i, generic_fn_count, c.generic_fn_queue.len}
generic_fn_count = c.generic_fn_queue.len
}
} }
if has_main_mod_file && !has_main_fn && files_from_main_module.len > 0 { if has_main_mod_file && !has_main_fn && files_from_main_module.len > 0 {
if c.pref.is_script && !c.pref.is_test { if c.pref.is_script && !c.pref.is_test {
@ -168,15 +153,13 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
// post process generic functions. must be done after all files have been // post process generic functions. must be done after all files have been
// checked, to eunsure all generic calls are processed as this information // checked, to eunsure all generic calls are processed as this information
// is needed when the generic type is auto inferred from the call argument // is needed when the generic type is auto inferred from the call argument
if c.generic_fn_queue.len > 0 { for i in 0 .. ast_files.len {
for queue_item in generic_fn_queue_info { file := unsafe {&ast_files[i]}
file := unsafe {&ast_files[queue_item.file_idx]} if file.generic_fns.len > 0 {
// set the context
c.file = file c.file = file
c.mod = file.mod.name c.mod = file.mod.name
c.post_process_generic_fns(queue_item.start, queue_item.end) c.post_process_generic_fns()
} }
c.generic_fn_queue = []
} }
c.verify_all_vweb_routes() c.verify_all_vweb_routes()
// Make sure fn main is defined in non lib builds // Make sure fn main is defined in non lib builds
@ -4512,15 +4495,15 @@ fn (mut c Checker) fetch_and_verify_orm_fields(info table.Struct, pos token.Posi
return fields return fields
} }
fn (mut c Checker) post_process_generic_fns(start int, end int) { fn (mut c Checker) post_process_generic_fns() {
// Loop thru each generic function concrete type. // Loop thru each generic function concrete type.
// Check each specific fn instantiation. // Check each specific fn instantiation.
for i in start .. end { for i in 0 .. c.file.generic_fns.len {
if c.table.fn_gen_types.len == 0 { if c.table.fn_gen_types.len == 0 {
// no concrete types, so just skip: // no concrete types, so just skip:
continue continue
} }
mut node := c.generic_fn_queue[i] mut node := c.file.generic_fns[i]
c.mod = node.mod c.mod = node.mod
for gen_type in c.table.fn_gen_types[node.name] { for gen_type in c.table.fn_gen_types[node.name] {
c.cur_generic_type = gen_type c.cur_generic_type = gen_type
@ -4530,7 +4513,6 @@ fn (mut c Checker) post_process_generic_fns(start int, end int) {
} }
} }
c.cur_generic_type = 0 c.cur_generic_type = 0
c.generic_fn_queue[i] = 0
} }
} }
@ -4543,7 +4525,7 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
// This is done so that all generic function calls can // This is done so that all generic function calls can
// have a chance to populate c.table.fn_gen_types with // have a chance to populate c.table.fn_gen_types with
// the correct concrete types. // the correct concrete types.
c.generic_fn_queue << node c.file.generic_fns << node
return return
} }
if node.language == .v && !c.is_builtin_mod { if node.language == .v && !c.is_builtin_mod {