155 lines
7.3 KiB
Plaintext
155 lines
7.3 KiB
Plaintext
import symbol:*
|
|
import tree:*
|
|
import vector:*
|
|
import stack:*
|
|
import map:*
|
|
import util:*
|
|
import string:*
|
|
import mem:*
|
|
import io:*
|
|
import importer:*
|
|
import ast_nodes:*
|
|
|
|
/*Importer * importer;*/
|
|
/*NodeTree<ASTData>* builtin_trans_unit; // the top scope for language level stuff*/
|
|
/*std::map<std::string, std::vector<NodeTree<ASTData>*>> languageLevelReservedWords;*/
|
|
/*std::map<std::string, std::vector<NodeTree<ASTData>*>> languageLevelOperators;*/
|
|
/*std::map<NodeTree<ASTData>*, NodeTree<ASTData>*> this_map; // used to map implicit "this" variables to their type*/
|
|
/*NodeTree<ASTData>* topScope; //maintained for templates that need to add themselves to the top scope no matter where they are instantiated*/
|
|
/*int lambdaID = 0;*/
|
|
obj ast_transformation (Object) {
|
|
fun construct(): *ast_transformation {
|
|
return this
|
|
}
|
|
fun copy_construct(old: *ast_transformation) {
|
|
}
|
|
fun operator=(old: ref ast_transformation) {
|
|
destruct()
|
|
copy_construct(&old)
|
|
}
|
|
fun destruct() {
|
|
}
|
|
// first pass defines all type_defs (objects and aliases), ADTs, and top-level if/passthroughs
|
|
fun first_pass(file_name: string, parse_tree: *tree<symbol>, importer: *importer): *ast_node {
|
|
var translation_unit = ast_translation_unit_ptr(file_name)
|
|
importer->register(file_name, parse_tree, translation_unit)
|
|
parse_tree->children.for_each(fun(child: *tree<symbol>) {
|
|
if (child->data.name == "type_def") {
|
|
var name = concat_symbol_tree(get_node("identifier", child))
|
|
var type_def_node = ast_type_def_ptr(name)
|
|
translation_unit->translation_unit.children.add(type_def_node)
|
|
add_to_scope("~enclosing_scope", translation_unit, type_def_node)
|
|
add_to_scope(name, type_def_node, translation_unit)
|
|
// set up type - self-referential, traits, template, etc
|
|
} else if (child->data.name == "adt_def") {
|
|
var name = concat_symbol_tree(get_node("identifier", child))
|
|
var adt_def_node = ast_adt_def_ptr(name)
|
|
translation_unit->translation_unit.children.add(adt_def_node)
|
|
add_to_scope("~enclosing_scope", translation_unit, adt_def_node)
|
|
add_to_scope(name, adt_def_node, translation_unit)
|
|
} else if (child->data.name == "if_comp") {
|
|
var if_comp_node = transform(child, translation_unit)
|
|
translation_unit->translation_unit.children.add(if_comp_node)
|
|
}
|
|
})
|
|
|
|
// now do all inports (done second so that if it imports this translation_unit,
|
|
// this one already has all its types defined
|
|
parse_tree->children.for_each(fun(child: *tree<symbol>) {
|
|
if (child->data.name == "import") {
|
|
var import_identifier_children = get_nodes("identifier", child)
|
|
var name = concat_symbol_tree(import_identifier_children[0])
|
|
var import_node = ast_import_ptr(name)
|
|
translation_unit->translation_unit.children.add(import_node)
|
|
add_to_scope("~enclosing_scope", translation_unit, import_node)
|
|
var outside_translation_unit = importer->import(name + ".krak")
|
|
add_to_scope(name, outside_translation_unit, translation_unit)
|
|
import_node->import.imported = from_vector(import_identifier_children.slice(1,-1).map(fun(ident: *tree<symbol>):string return concat_symbol_tree(ident);))
|
|
}
|
|
})
|
|
return translation_unit
|
|
}
|
|
/*NodeTree<ASTData>* ASTTransformation::transform(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::vector<Type> types, bool limitToFunction, std::map<std::string, Type*> templateTypeReplacements) {*/
|
|
fun transform(node: *tree<symbol>, scope: *ast_node): *ast_node {
|
|
var name = node->data.name
|
|
if (name == "identifier" || name == "scoped_identifier") {
|
|
return transform_identifier(node, scope)
|
|
} else if (name == "code_block") {
|
|
return transform_code_block(node, scope)
|
|
} else if (name == "if_comp") {
|
|
return transform_if_comp(node, scope)
|
|
} else if (name == "simple_passthrough") {
|
|
return transform_simple_passthrough(node, scope)
|
|
}
|
|
print("FAILED TO TRANSFORM: "); println(concat_symbol_tree(node))
|
|
return null<ast_node>()
|
|
}
|
|
fun transform_all(nodes: vector<*tree<symbol>>, scope: *ast_node): vector<*ast_node> {
|
|
return nodes.map(fun(node: *tree<symbol>): *ast_node return transform(node, scope);)
|
|
}
|
|
fun transform_identifier(node: *tree<symbol>, scope: *ast_node): *ast_node {
|
|
// for identifier we have to do scope lookup, etc, and maybe limit to function
|
|
var name = concat_symbol_tree(node)
|
|
return ast_identifier_ptr(name)
|
|
}
|
|
fun transform_code_block(node: *tree<symbol>, scope: *ast_node): *ast_node {
|
|
var new_block = ast_code_block_ptr()
|
|
add_to_scope("~enclosing_scope", scope, new_block)
|
|
new_block->code_block.children = transform_all(node->children, new_block)
|
|
return new_block
|
|
}
|
|
fun transform_if_comp(node: *tree<symbol>, scope: *ast_node): *ast_node {
|
|
var new_if_comp = ast_if_comp_ptr()
|
|
new_if_comp->if_comp.wanted_generator = concat_symbol_tree(get_node("identifier", node))
|
|
new_if_comp->if_comp.statement = transform_statement(get_node("statement", node), scope)
|
|
return new_if_comp
|
|
}
|
|
fun transform_simple_passthrough(node: *tree<symbol>, scope: *ast_node): *ast_node {
|
|
var new_passthrough = ast_simple_passthrough_ptr()
|
|
// setup passthrough params and string
|
|
new_passthrough->simple_passthrough.passthrough_str = concat_symbol_tree(get_node("triple_quoted_string", node))
|
|
return new_passthrough
|
|
}
|
|
fun transform_statement(node: *tree<symbol>, scope: *ast_node): *ast_node {
|
|
var new_statement = ast_statement_ptr()
|
|
new_statement->statement.child = transform(node->children[0], scope)
|
|
return new_statement
|
|
}
|
|
}
|
|
|
|
fun concat_symbol_tree(node: *tree<symbol>): string {
|
|
var str.construct(): string
|
|
if (node->data.data != "no_value")
|
|
str += node->data.data
|
|
node->children.for_each(fun(child: *tree<symbol>) str += concat_symbol_tree(child);)
|
|
return str
|
|
}
|
|
fun get_node(lookup: *char, parent: *tree<symbol>): *tree<symbol> {
|
|
return get_node(string(lookup), parent)
|
|
}
|
|
fun get_node(lookup: string, parent: *tree<symbol>): *tree<symbol> {
|
|
var results = get_nodes(lookup, parent)
|
|
if (results.size > 1)
|
|
println("too many results!")
|
|
if (results.size)
|
|
return results[0]
|
|
return null<tree<symbol>>()
|
|
}
|
|
fun get_nodes(lookup: *char, parent: *tree<symbol>): vector<*tree<symbol>> {
|
|
return get_nodes(string(lookup), parent)
|
|
}
|
|
fun get_nodes(lookup: string, parent: *tree<symbol>): vector<*tree<symbol>> {
|
|
return parent->children.filter(fun(node: *tree<symbol>):bool return node->data.name == lookup;)
|
|
}
|
|
fun add_to_scope(name: *char, to_add: *ast_node, add_to: *ast_node) {
|
|
add_to_scope(string(name), to_add, add_to)
|
|
}
|
|
fun add_to_scope(name: string, to_add: *ast_node, add_to: *ast_node) {
|
|
var add_to_map = get_ast_scope(add_to)
|
|
if (add_to_map->contains_key(name))
|
|
(*add_to_map)[name].add(to_add)
|
|
else
|
|
add_to_map->set(name, vector(to_add))
|
|
}
|
|
|