import symbol:* import tree:* import vector:* import queue:* import map:* import util:* import string:* import mem:* import io:* import ast_nodes:* import ast_transformation:* import parser:* import thread:* obj importer (Object) { var parsers: vector var ast_pass: ast_transformation var name_ast_map: map,*ast_node>> var import_paths: vector fun construct(parsersIn: ref vector, ast_passIn: ref ast_transformation, import_paths_in: vector): *importer { parsers.copy_construct(&parsersIn) ast_pass.copy_construct(&ast_passIn) name_ast_map.construct() import_paths.copy_construct(&import_paths_in) return this } fun copy_construct(old: *importer) { parsers.copy_construct(&old->parsers) ast_pass.copy_construct(&old->ast_pass) name_ast_map.copy_construct(&old->name_ast_map) import_paths.copy_construct(&old->import_paths) } fun operator=(old: ref importer) { destruct() copy_construct(&old) } fun destruct() { parsers.destruct() ast_pass.destruct() name_ast_map.destruct() import_paths.destruct() } fun import(file_name: string) { // lambda closes over our fix-up list var imports_to_fix = vector<*ast_node>() var import_first_pass = fun(file_name_idx: pair) { var file_name = file_name_idx.first var file = string() import_paths.for_each(fun(path: string) { if (file_exists(path + file_name)) { file = read_file(path + file_name) } else { } }) printerr(file_name + ", ") var parse_tree = parsers[file_name_idx.second].parse_input(file, file_name) trim(parse_tree) var ast_and_imports = ast_pass.first_pass(file_name, parse_tree, this) imports_to_fix += ast_and_imports.second name_ast_map[file_name] = make_pair(parse_tree, ast_and_imports.first) } printlnerr("**First Pass**") printerr("parsing: ") import_first_pass(make_pair(file_name,0)) for (var i = 0; i < imports_to_fix.size; i++;) { /*println(string("iteration of imports to fix: ") + i)*/ var threads = vector<*ulong>() var num_threads = min(imports_to_fix.size - i, parsers.size) for (var j = i; j < i+num_threads; j++;) { var import_name = imports_to_fix[j]->import.name var file_name = import_name + ".krak" if (!name_ast_map.contains_key(file_name)) { /*import_first_pass(file_name)*/ /*join(run(import_first_pass, file_name))*/ if (num_threads > 1) threads.add(run(import_first_pass, make_pair(file_name, j-i))) else import_first_pass(make_pair(file_name,0)) } else { threads.add(null()) } } /*println(string("iteration of imports to fix: ") + i + " made")*/ for (var j = i; j < i+num_threads; j++;) { if (num_threads > 1) { if (threads[j-i]) join(threads[j-i]) } var im = imports_to_fix[j] var import_name = im->import.name var file_name = import_name + ".krak" im->import.translation_unit = name_ast_map[file_name].second add_to_scope(import_name, im->import.translation_unit, im->import.containing_translation_unit) } /*println(string("iteration of imports to fix: ") + i + " done")*/ i += num_threads-1 } printlnerr() printlnerr("**Second Pass**") name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree, *ast_node>) ast_pass.second_pass(tree_pair.first, tree_pair.second);) printlnerr("**Third Pass**") name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree, *ast_node>) ast_pass.third_pass(tree_pair.first, tree_pair.second);) // this needs to be modified to do chaotic iteration on instantiating template classes, based on what I see in the C++ version printlnerr("**Fourth Pass**") name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree, *ast_node>) ast_pass.fourth_pass(tree_pair.first, tree_pair.second);) } fun trim(parse_tree: *tree) { remove_node(symbol("$NULL$", false), parse_tree) remove_node(symbol("WS", false), parse_tree) // the terminals have " around them, which we have to escape remove_node(symbol("\"\\(\"", true), parse_tree) remove_node(symbol("\"\\)\"", true), parse_tree) remove_node(symbol("\"template\"", true), parse_tree) remove_node(symbol("\"return\"", true), parse_tree) remove_node(symbol("\"defer\"", true), parse_tree) remove_node(symbol("\";\"", true), parse_tree) remove_node(symbol("line_end", false), parse_tree) remove_node(symbol("\"{\"", true), parse_tree) remove_node(symbol("\"}\"", true), parse_tree) remove_node(symbol("\"(\"", true), parse_tree) remove_node(symbol("\")\"", true), parse_tree) remove_node(symbol("\"if\"", true), parse_tree) remove_node(symbol("\"while\"", true), parse_tree) remove_node(symbol("\"__if_comp__\"", true), parse_tree) remove_node(symbol("\"comp_simple_passthrough\"", true), parse_tree) /*remove_node(symbol("obj_nonterm", false), parse_tree)*/ remove_node(symbol("adt_nonterm", false), parse_tree) collapse_node(symbol("case_statement_list", false), parse_tree) collapse_node(symbol("opt_param_assign_list", false), parse_tree) collapse_node(symbol("param_assign_list", false), parse_tree) collapse_node(symbol("opt_typed_parameter_list", false), parse_tree) collapse_node(symbol("opt_parameter_list", false), parse_tree) collapse_node(symbol("intrinsic_parameter_list", false), parse_tree) collapse_node(symbol("identifier_list", false), parse_tree) collapse_node(symbol("adt_option_list", false), parse_tree) collapse_node(symbol("statement_list", false), parse_tree) collapse_node(symbol("parameter_list", false), parse_tree) collapse_node(symbol("typed_parameter_list", false), parse_tree) collapse_node(symbol("unorderd_list_part", false), parse_tree) collapse_node(symbol("if_comp_pred", false), parse_tree) collapse_node(symbol("declaration_block", false), parse_tree) collapse_node(symbol("type_list", false), parse_tree) collapse_node(symbol("opt_type_list", false), parse_tree) collapse_node(symbol("template_param_list", false), parse_tree) collapse_node(symbol("trait_list", false), parse_tree) collapse_node(symbol("dec_type", false), parse_tree) } fun remove_node(remove: symbol, parse_tree: *tree) { var to_process = queue<*tree>() to_process.push(parse_tree) while(!to_process.empty()) { var node = to_process.pop() for (var i = 0; i < node->children.size; i++;) { if (!node->children[i] || node->children[i]->data.equal_wo_data(remove)) { /* if (!node->children[i]) println("not because null") else { print("not because "); println(remove.name) } */ node->children.remove(i) i--; } else { /*println(remove.to_string() + " not equal " + node->children[i]->data.to_string())*/ to_process.push(node->children[i]) } } } } fun collapse_node(remove: symbol, parse_tree: *tree) { var to_process = queue<*tree>() to_process.push(parse_tree) while(!to_process.empty()) { var node = to_process.pop() for (var i = 0; i < node->children.size; i++;) { if (node->children[i]->data.equal_wo_data(remove)) { var add_children = node->children[i]->children; // stick child's children between the current children divided // on i, without including i node->children = node->children.slice(0,i) + add_children + node->children.slice(i+1,-1) i--; } else { to_process.push(node->children[i]) } } } } }