Files
kraken/stdlib/importer.krak

137 lines
6.0 KiB
Plaintext

import symbol:*
import tree:*
import vector:*
import stack:*
import map:*
import util:*
import string:*
import mem:*
import io:*
import ast_nodes:*
import ast_transformation:*
import parser:*
fun import(file_name: string, parsers: ref vector<parser>, ast_pass: ref ast_transformation, import_paths: vector<string>): map<string, pair<*tree<symbol>,*ast_node>> {
var name_ast_map = map<string, pair<*tree<symbol>,*ast_node>>()
// lambda closes over our fix-up list
var imports_to_fix = vector<*ast_node>()
var import_first_pass = fun(file_name_idx: pair<string,int>) {
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)
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: string, tree_pair: pair<*tree<symbol>, *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<symbol>, *ast_node>) ast_pass.third_pass(tree_pair.first, tree_pair.second);)
printlnerr("**Fourth Pass**")
name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree<symbol>, *ast_node>) ast_pass.fourth_pass(tree_pair.first, tree_pair.second);)
return name_ast_map
}
fun trim(parse_tree: *tree<symbol>): *tree<symbol> {
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)
return parse_tree
}
fun remove_node(remove: symbol, parse_tree: *tree<symbol>) {
var to_process = stack<*tree<symbol>>()
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<symbol>) {
var to_process = stack<*tree<symbol>>()
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])
}
}
}
}