From f29fdcd4631ec7b735953a301e9dcaa80f577204 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Tue, 5 Jan 2016 21:40:00 -0500 Subject: [PATCH] More skeleton, including a trivial second_pass_function, fix a bug with ADTs that have members with the same name (may still be a problem if the ADT itself has the same name) --- include/Type.h | 2 +- src/CGenerator.cpp | 24 ++++++++++------- stdlib/ast_transformation.krak | 34 ++++++++++++++++++++--- stdlib/importer.krak | 23 +++++++++++++--- stdlib/type.krak | 49 ++++++++++++++++++++++++++++++++++ tests/to_parse.krak | 7 +++++ 6 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 stdlib/type.krak diff --git a/include/Type.h b/include/Type.h index 9c04217..74876cd 100644 --- a/include/Type.h +++ b/include/Type.h @@ -56,7 +56,7 @@ class Type { std::set traits; std::vector parameterTypes; Type *returnType; - bool is_reference;; + bool is_reference; private: int indirection; }; diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 566b16c..033ea91 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -76,11 +76,13 @@ std::string CGenerator::generateTypeStruct(NodeTree* from) { // if this is not a plain no-data adt member (so if it is a primitive or doesn't have a reference back to) // wait a sec, this is easier if ( child->getDataRef()->valueType->typeDefinition != from) - structString += tabs() + ValueTypeToCType(child->getDataRef()->valueType, child->getDataRef()->symbol.getName()) + "; /* adt data member */\n"; + structString += tabs() + ValueTypeToCType(child->getDataRef()->valueType, prefixIfNeeded(scopePrefix(child), child->getDataRef()->symbol.getName())) + "; /* adt data member */\n"; } else { structString += tabs() + generate(child, nullptr).oneString() + "\n"; } - enumString += tabs() + data.symbol.getName() + "__" + generate(child, nullptr).oneString() + (data.type == adt_def ? ",\n" : "\n"); + //enumString += tabs() + data.symbol.getName() + "__" + generate(child, nullptr).oneString() + (data.type == adt_def ? ",\n" : "\n"); + // this was prefixing when it shouldn't have, since we prefix with the name of the adt anyway. Probs the entire thing should be prefixed, but we'll cross that bridge when we come to it + enumString += tabs() + data.symbol.getName() + "__" + child->getDataRef()->symbol.getName() + (data.type == adt_def ? ",\n" : "\n"); } } tabLevel--; @@ -335,6 +337,7 @@ std::pair CGenerator::generateTranslationUnit(std::str for (auto child : decChildren) { if (child->getName() != "function" && child->getDataRef()->valueType->typeDefinition != declaration) { std::string option_name = child->getDataRef()->symbol.getName(); + std::string prefixed_option_name = prefixIfNeeded(scopePrefix(declaration),option_name); functionDefinitions += " else if (this->flag == " + declarationData.symbol.getName() + "__" + option_name + ") {\n"; NodeTree* method = nullptr; if (method = getMethod(child->getDataRef()->valueType, "operator==", std::vector{*child->getDataRef()->valueType})) { @@ -345,17 +348,17 @@ std::pair CGenerator::generateTranslationUnit(std::str if (need_temporary) { functionDefinitions += " " + ValueTypeToCType(child->getDataRef()->valueType, "copy_constructTemporary") + ";\n"; functionDefinitions += " " + generateMethodIfExists(child->getDataRef()->valueType, "copy_construct", - "©_constructTemporary, &in->" + option_name, itemTypeVector) + ";\n"; + "©_constructTemporary, &in->" + prefixed_option_name, itemTypeVector) + ";\n"; } - std::string otherValue = (is_reference ? "&" : "") + (need_temporary ? "copy_constructTemporary" : "in->" + option_name); + std::string otherValue = (is_reference ? "&" : "") + (need_temporary ? "copy_constructTemporary" : "in->" + prefixed_option_name); functionDefinitions += " equal = " + generateMethodIfExists(child->getDataRef()->valueType, "operator==", - "&this->" + option_name + ", " + otherValue, + "&this->" + prefixed_option_name + ", " + otherValue, std::vector{*child->getDataRef()->valueType}) + ";\n"; // Remember, we don't destruct copy_constructTemporary because the function will do that functionDefinitions += "}\n"; } else { - functionDefinitions += " equal = this->" + option_name + " == in->" + option_name + ";\n}\n"; + functionDefinitions += " equal = this->" + prefixed_option_name + " == in->" + prefixed_option_name + ";\n}\n"; } } } @@ -380,15 +383,16 @@ std::pair CGenerator::generateTranslationUnit(std::str for (auto child : decChildren) { if (child->getName() != "function" && child->getDataRef()->valueType->typeDefinition != declaration) { std::string option_name = child->getDataRef()->symbol.getName(); + std::string prefixed_option_name = prefixIfNeeded(scopePrefix(declaration),option_name); functionDefinitions += " " + elsePrefix + " if (in->flag == " + declarationData.symbol.getName() + "__" + option_name + ") {\n"; elsePrefix = "else"; NodeTree* method = nullptr; auto itemTypeVector = std::vector{child->getDataRef()->valueType->withIncreasedIndirection()}; if (method = getMethod(child->getDataRef()->valueType, "copy_construct", itemTypeVector)) { functionDefinitions += " " + generateMethodIfExists(child->getDataRef()->valueType, "copy_construct", - "&this->" + option_name + ", &in->" + option_name, itemTypeVector) + ";\n"; + "&this->" + prefixed_option_name + ", &in->" + prefixed_option_name, itemTypeVector) + ";\n"; } else { - functionDefinitions += "this->" + option_name + " = in->" + option_name + ";\n"; + functionDefinitions += "this->" + prefixed_option_name + " = in->" + prefixed_option_name + ";\n"; } functionDefinitions += " }\n"; } @@ -421,9 +425,9 @@ std::pair CGenerator::generateTranslationUnit(std::str functionDefinitions += "/*" + ValueTypeToCType(paramType, "") + "*/\n"; if (method = getMethod(paramType, "copy_construct", itemTypeVector)) { functionDefinitions += " " + generateMethodIfExists(paramType, "copy_construct", - "&toRet." + orig_fun_name + ", &in", itemTypeVector) + ";\n"; + "&toRet." + prefixIfNeeded(scopePrefix(declaration),orig_fun_name) + ", &in", itemTypeVector) + ";\n"; } else { - functionDefinitions += " toRet." + orig_fun_name + " = in;\n"; + functionDefinitions += " toRet." + prefixIfNeeded(scopePrefix(declaration),orig_fun_name) + " = in;\n"; } if (method = getMethod(paramType, "destruct", std::vector())) { diff --git a/stdlib/ast_transformation.krak b/stdlib/ast_transformation.krak index b14c186..11c654e 100644 --- a/stdlib/ast_transformation.krak +++ b/stdlib/ast_transformation.krak @@ -9,6 +9,7 @@ import mem:* import io:* import importer:* import ast_nodes:* +import type:* /*Importer * importer;*/ /*NodeTree* builtin_trans_unit; // the top scope for language level stuff*/ @@ -29,7 +30,7 @@ obj ast_transformation (Object) { } fun destruct() { } - // first pass defines all type_defs (objects and aliases), ADTs, and top-level if/passthroughs + // first pass defines all type_defs (objects and aliases), ADTs, and top-level if-comps/passthroughs fun first_pass(file_name: string, parse_tree: *tree, importer: *importer): *ast_node { var translation_unit = ast_translation_unit_ptr(file_name) importer->register(file_name, parse_tree, translation_unit) @@ -48,12 +49,12 @@ obj ast_transformation (Object) { 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) + var if_comp_node = transform_if_comp(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, + // now do all imports (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) { if (child->data.name == "import") { @@ -62,13 +63,38 @@ obj ast_transformation (Object) { 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") + var outside_translation_unit = importer->import_first_pass(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):string return concat_symbol_tree(ident);)) } }) return translation_unit } + // defines inside of objects + ADTs, outside declaration statements, and function prototypes + fun second_pass(parse_tree: *tree, translation_unit: *ast_node) { + println(string("Second Pass for ") + translation_unit->translation_unit.name) + parse_tree->children.for_each(fun(child: *tree) { + if (child->data.name == "type_def") { + // second pass class stuff + // class insides calls into second_pass_declaration and second_pass_function... + } else if (child->data.name == "adt_def") { + // set up options and all the generated functions (operator==, operator!=, copy_construct, operator=, destruct) + } else if (child->data.name == "function") { + translation_unit->translation_unit.children.add(second_pass_function(child, translation_unit, map())) + } else if (child->data.name == "declaration_statement") { + // second pass declaration can actually just call a normal transform (but maybe should be it's own method to do so because typedef has to do it too?)... + } + }) + } + fun second_pass_function(parse_tree: *tree, translation_unit: *ast_node, template_replacements: map): *ast_node { + return ast_function_ptr() + } + fun third_pass(parse_tree: *tree, translation_unit: *ast_node) { + println(string("Third Pass for ") + translation_unit->translation_unit.name) + } + fun fourth_pass(parse_tree: *tree, translation_unit: *ast_node) { + println(string("Fourth Pass for ") + translation_unit->translation_unit.name) + } /*NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree* scope, std::vector types, bool limitToFunction, std::map templateTypeReplacements) {*/ fun transform(node: *tree, scope: *ast_node): *ast_node { var name = node->data.name diff --git a/stdlib/importer.krak b/stdlib/importer.krak index fb9adbb..69dc92a 100644 --- a/stdlib/importer.krak +++ b/stdlib/importer.krak @@ -36,6 +36,24 @@ obj importer (Object) { name_ast_map.destruct() } fun import(file_name: string): *ast_node { + println("**First Pass**") + var to_ret = import_first_pass(file_name) + println("**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);) + println("**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 + println("**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);) + + name_ast_map.for_each(fun(name: string, tree_pair: pair<*tree, *ast_node>) { + print("writing ast for: "); println(name) + write_file(name + ".ast.dot", ast_to_dot(tree_pair.second)) + }) + + return to_ret + } + fun import_first_pass(file_name: string): *ast_node { if (name_ast_map.contains_key(file_name)) return name_ast_map[file_name].second @@ -47,10 +65,9 @@ obj importer (Object) { trim(parse_tree) print("post-trim: "); println(file_name) write_file(file_name + ".trimmed_parse.dot", syntax_tree_to_dot(parse_tree)) - print("pre-ast: "); println(file_name) + print("pre-first-ast: "); println(file_name) var ast = ast_pass.first_pass(file_name, parse_tree, this) - print("post-ast: "); println(file_name) - write_file(file_name + ".ast.dot", ast_to_dot(ast)) + print("post-first-ast: "); println(file_name) return ast } fun register(file_name: string, parse_tree: *tree, translation_unit: *ast_node) { diff --git a/stdlib/type.krak b/stdlib/type.krak new file mode 100644 index 0000000..377c4d5 --- /dev/null +++ b/stdlib/type.krak @@ -0,0 +1,49 @@ + +// hmm, like the ast_node, this is another candadate for being fully an ADT +// one issue is that there are properties shared between most of the options (indirection, say) + +adt base_type { + none, + template, + template_type, + void_return, + boolean, + character, + integer, + floating, + double_precision, + function +} + +fun type(): type { + var to_ret.construct(): type + return to_ret +} +fun type(base: base_type): type { + var to_ret.construct(base): type + return to_ret +} + +obj type (Object) { + var base: base_type + fun construct(): *type { + base.copy_construct(&base_type::none()) + return this + } + fun construct(base_in: base_type): *type { + base.copy_construct(&base_in) + return this + } + fun copy_construct(old: *type) { + base = old->base + } + fun operator=(other: ref type) { + destruct() + copy_construct(&other) + } + fun destruct() { + base.destruct() + } +} + + diff --git a/tests/to_parse.krak b/tests/to_parse.krak index bc2cb0b..f79846e 100644 --- a/tests/to_parse.krak +++ b/tests/to_parse.krak @@ -1,5 +1,12 @@ import to_import: a,b +obj Something (ObjectTrait) { + var member: int + fun method():int { + return 5 + } +} + fun main(): int { return 0 }