import symbol:* import tree:* import vec:* import stack:* import map:* import util:* import str:* import mem:* import io:* import ast_nodes:* import ast_transformation:* import parser:* fun import(file_name: str, parsers: ref vec, ast_pass: ref ast_transformation, import_paths: vec): map,*ast_node>> { var name_ast_map = map,*ast_node>>() // lambda closes over our fix-up list var imports_to_fix = vec<*ast_node>() var import_first_pass = fun(file_name_idx: pair) { var file_name = file_name_idx.first var file = str() import_paths.for_each(fun(path: str) { 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) 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++;) { var import_name = imports_to_fix[i]->import.name var file_name = import_name + ".krak" if (!name_ast_map.contains_key(file_name)) { import_first_pass(make_pair(file_name,0)) } var im = imports_to_fix[i] 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) } printlnerr() printlnerr("**Second Pass**") name_ast_map.for_each(fun(name: str, 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: str, tree_pair: pair<*tree, *ast_node>) ast_pass.third_pass(tree_pair.first, tree_pair.second);) printlnerr("**Fourth Pass**") name_ast_map.for_each(fun(name: str, tree_pair: pair<*tree, *ast_node>) ast_pass.fourth_pass(tree_pair.first, tree_pair.second);) return name_ast_map } 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 = stack<*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)) { node->children.remove(i) i--; } else { to_process.push(node->children[i]) } } } } fun collapse_node(remove: symbol, parse_tree: *tree) { var to_process = stack<*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]) } } } }