From e8db81b062649fa6c927b8a1183d224faacecf9a Mon Sep 17 00:00:00 2001 From: ctaylor Date: Sun, 7 May 2023 22:50:19 -0400 Subject: [PATCH] adding module support --- backend/include/hpx/codegenvisitor.hpp | 7 +- backend/include/hpx/programtree.hpp | 25 +- backend/include/hpx/symboltypes.hpp | 32 +- backend/src/codegenvisitor.cpp | 404 ++++++++++++++++++--- backend/src/driver.cpp | 10 +- backend/src/programtree.cpp | 22 +- backend/src/programtreebuildingvisitor.cpp | 133 ++++++- backend/src/symbolbuildingvisitor.cpp | 242 +++++++++++- 8 files changed, 776 insertions(+), 99 deletions(-) diff --git a/backend/include/hpx/codegenvisitor.hpp b/backend/include/hpx/codegenvisitor.hpp index 00b31448..d8885556 100644 --- a/backend/include/hpx/codegenvisitor.hpp +++ b/backend/include/hpx/codegenvisitor.hpp @@ -18,7 +18,6 @@ #include "symboltypes.hpp" #include "programtree.hpp" -#include #include #include #include @@ -72,13 +71,12 @@ struct CodegenVisitor { ProgramTree & prgmTree, chpl::uast::BuilderResult const& chapelBr, std::string const& cppFilePathStr, - std::string const& chapelFilePathStr, - std::ostream & fstrm + std::string const& chapelFilePathStr ); ~CodegenVisitor() = default; - void generateApplicationHeader(std::filesystem::path const& chplpth); + void generateApplicationHeader(std::string const& chplpth, std::string const& prefix, std::fstream & os); //template //void addSymbolEntry(char const* type); @@ -110,7 +108,6 @@ struct CodegenVisitor { std::size_t indent; std::size_t scope; std::string identifier; - std::ostream & fstrm_; std::string cppFilePathStr; std::string chplFilePathStr; std::vector headers; diff --git a/backend/include/hpx/programtree.hpp b/backend/include/hpx/programtree.hpp index c6948232..2628ec0a 100644 --- a/backend/include/hpx/programtree.hpp +++ b/backend/include/hpx/programtree.hpp @@ -116,6 +116,10 @@ struct CoforallLoopExpression; struct StatementList; struct ScalarDeclarationExprExpression; +struct RecordDeclarationExpression; +struct ClassDeclarationExpression; +struct ModuleDeclarationExpression; + using Statement = std::variant< std::monostate, std::shared_ptr, @@ -139,7 +143,10 @@ using Statement = std::variant< std::shared_ptr, std::shared_ptr, std::shared_ptr, - std::shared_ptr + std::shared_ptr, + std::shared_ptr, + std::shared_ptr, + std::shared_ptr >; struct StatementList { @@ -242,6 +249,22 @@ struct CoforallLoopExpression : public ScopeExpression { void emit(std::ostream & os) const; }; +struct RecordDeclarationExpression : public ScopeExpression { + Symbol symbol; + std::vector statements; + std::string chplLine; + + void emit(std::ostream & os) const; +}; + +struct ClassDeclarationExpression : public RecordDeclarationExpression { + void emit(std::ostream & os) const; +}; + +struct ModuleDeclarationExpression : public RecordDeclarationExpression { + void emit(std::ostream & os) const; +}; + struct ProgramTree { std::vector statements; diff --git a/backend/include/hpx/symboltypes.hpp b/backend/include/hpx/symboltypes.hpp index da9190b5..abdd5cac 100644 --- a/backend/include/hpx/symboltypes.hpp +++ b/backend/include/hpx/symboltypes.hpp @@ -102,6 +102,7 @@ struct tuple_kind; struct kind_node_type; struct kind_node_term_type {}; struct expr_kind {}; +struct module_kind; using kind_types = std::variant< std::monostate, @@ -127,6 +128,7 @@ using kind_types = std::variant< std::shared_ptr, std::shared_ptr, std::shared_ptr, + std::shared_ptr, kind_node_term_type, expr_kind >; @@ -161,15 +163,27 @@ struct tuple_kind { std::vector kinds; }; +enum class ScopeKind : std::uint8_t { + Module = 0, + ForLoop = 1, + ForallLoop = 2, + CoforallLoop = 3, + Loop = 4, + Function = 5, + Lambda = 6, + Record = 7, + Class = 8 +}; + struct SymbolBase { kind_types kind; std::string identifier; std::vector literal; int kindqualifier; bool isConfig; -// std::size_t parentModule; std::size_t scopeId; }; +// std::size_t parentModule; struct Symbol : public SymbolBase { }; @@ -204,6 +218,7 @@ struct SymbolTable { struct SymbolTableNode { std::size_t id; + // ScopeKind kind; std::map entries; std::vector children; SymbolTableNodeImpl parent; @@ -292,15 +307,16 @@ struct itrfunc_kind : public func_kind { }; struct record_kind { - std::vector identifiers; - std::vector kinds; - SymbolTable symbolTable; + std::uint64_t lutId; + std::string symbolTableSignature; + std::vector members; }; -struct class_kind { - std::vector identifiers; - std::vector kinds; - SymbolTable symbolTable; +struct class_kind : record_kind { + std::vector lineage; +}; + +struct module_kind : funcbase_kind { }; } /* namespace hpx */ } /* namespace visitors */ } /* namespace ast */ } /* namespace chpl */ diff --git a/backend/src/codegenvisitor.cpp b/backend/src/codegenvisitor.cpp index a00dff22..2a890035 100644 --- a/backend/src/codegenvisitor.cpp +++ b/backend/src/codegenvisitor.cpp @@ -34,11 +34,9 @@ CodegenVisitor::CodegenVisitor( ProgramTree & prgmTree, chpl::uast::BuilderResult const& chapelBr, std::string const& cppFilePath, - std::string const& chapelFilePath, - std::ostream & fstrm) + std::string const& chapelFilePath) : symbolTable(st), cfgVars(configVars), programTree(prgmTree), br(chapelBr), indent(0), scope(0), - fstrm_(fstrm), cppFilePathStr(cppFilePath), chplFilePathStr(chapelFilePath), headers(static_cast(HeaderEnum::HeaderCount), false) @@ -51,20 +49,18 @@ static void upper(std::string & s) { ); } -void CodegenVisitor::generateApplicationHeader(std::filesystem::path const& chplpth) { - const auto pos = chplFilePathStr.find("."); - std::string prefix = chplFilePathStr.substr(0, pos); - - std::fstream os(prefix + ".hpp", std::ios_base::out); +void CodegenVisitor::generateApplicationHeader(std::string const& chplpth, std::string const& Prefix, std::fstream & os) { + std::string prefix{Prefix}; upper(prefix); os << "// This program file was generated by the chplx compiler." << std::endl - << "// The original Chapel program file can be found here: " << chplpth.filename() << std::endl + << "// The original Chapel program file can be found here: " << chplpth << std::endl << "//" << std::endl << "#pragma once" << std::endl << std::endl << "#ifndef __" << prefix << "_HPP__" << std::endl << "#define __" << prefix << "_HPP__" << std::endl << std::endl - << "#include " << std::endl; + << "#include " << std::endl + << "#include \"" << Prefix << ".hpp\"" << std::endl; for(std::size_t i = 0; i < static_cast(HeaderEnum::HeaderCount); ++i) { if(headers[i]) { @@ -174,6 +170,122 @@ struct ExprVisitor { std::ostream & os; }; +struct HppStatementVisitor { + void emitIndent() const { + for(std::size_t i = 0; i < indent; ++i) { + os << INDENT; + } + } + + template + constexpr void operator()(T const& kind) {} + + void prologue(std::shared_ptr const& node) { + if(node->symbol.identifier.size() < 1) { std::cerr << "codegenvisitor.cpp FunctionDeclarationExpression " << node->symbol.identifier << " not found" << std::endl; } + + if(std::holds_alternative>(node->symbol.kind)) { + std::shared_ptr const& fk = + std::get>(node->symbol.kind); + + std::string prefix{fk->symbolTableSignature}; + upper(prefix); + + os << "// This program file was generated by the chplx compiler." << std::endl + << "// The original Chapel program file can be found here: " << fk->symbolTableSignature << ".chpl" << std::endl + << "//" << std::endl + << "#pragma once" << std::endl << std::endl + << "#ifndef __" << prefix << "_HPP__" << std::endl + << "#define __" << prefix << "_HPP__" << std::endl << std::endl + << "#include " << std::endl; + + for(std::size_t i = 0; i < static_cast(HeaderEnum::HeaderCount); ++i) { + if(headers[i]) { + if(i == static_cast(HeaderEnum::std_vector)) { + os << "#include " << std::endl; + } + else if(i == static_cast(HeaderEnum::std_complex)) { + os << "#include " << std::endl; + } + else if(i == static_cast(HeaderEnum::std_string)) { + os << "#include " << std::endl; + } + else if(i == static_cast(HeaderEnum::std_iostream)) { + os << "#include " << std::endl; + } + else if(i == static_cast(HeaderEnum::std_functional)) { + os << "#include " << std::endl; + } + } + } + + if(printChplLine) { + os << node->chplLine; + } + + os << "namespace " << fk->symbolTableSignature << " {" << std::endl; + } + } + + void epilogue() { + os << std::endl << "} // end namespace" << std::endl << std::endl << "#endif" << std::endl; + } + + void operator()(std::shared_ptr const& node) { + if(node->symbol.identifier.size() < 1) { std::cerr << "codegenvisitor.cpp FunctionDeclarationExpression " << node->symbol.identifier << " not found" << std::endl; } + + if(printChplLine) { + emitIndent(); + os << node->chplLine; + emitIndent(); + } + + if(std::holds_alternative>(node->symbol.kind)) { + std::shared_ptr const& fk = + std::get>(node->symbol.kind); + + FuncDeclArgVisitor fdav{os}; + const std::size_t args_sz = fk->args.size()-1; + + std::visit(fdav, fk->retKind); + std::string const& fn_sig_ref = + node->symbol.identifier; + + const std::size_t pos = + fn_sig_ref.find("|"); + + os << ' ' << fn_sig_ref.substr(0, (pos != std::string::npos) ? pos : fn_sig_ref.size() ) << "("; + + if(0 < args_sz) { + std::visit(fdav, fk->args[0].kind); + os << ' ' << fk->args[0].identifier; + + for(std::size_t i = 1; i < args_sz; ++i) { + os << ','; + std::visit(fdav, fk->args[i].kind ); + os << ' ' << fk->args[i].identifier; + } + } + + if(std::holds_alternative(fk->retKind)) { + os << ")"; + } + else { + os << ")"; + } + + os << ";" << std::endl; + } + } + + SymbolTable & symbolTable; + chpl::uast::BuilderResult const& br; + std::ostream & os; + std::size_t indent; + std::vector & headers; + bool printChplLine; + bool arg; +}; + struct StatementVisitor { void emitIndent() const { @@ -232,13 +344,7 @@ struct StatementVisitor { node.emit(os); os << " = "; if( 0 < node.literalValue.size() ) { - if(s->isConfig) { - os << "config_" << s->identifier; - } - else { - std::visit(ScalarDeclarationLiteralExpressionVisitor{s->literal[0], os}, node.kind); - } - + std::visit(ScalarDeclarationLiteralExpressionVisitor{s->literal[0], os}, node.kind); os << ";" << std::endl; } } @@ -374,33 +480,64 @@ struct StatementVisitor { FuncDeclArgVisitor fdav{os}; const std::size_t args_sz = fk->args.size()-1; - os << "auto "; - std::string const& fn_sig_ref = - node->symbol.identifier; + if(moduleLevel) { + std::visit(fdav, fk->retKind); + std::string const& fn_sig_ref = + node->symbol.identifier; - const std::size_t pos = - fn_sig_ref.find("|"); + const std::size_t pos = + fn_sig_ref.find("|"); - os << fn_sig_ref.substr(0, (pos != std::string::npos) ? pos : fn_sig_ref.size() ) << " = [&]("; + os << ' ' << fn_sig_ref.substr(0, (pos != std::string::npos) ? pos : fn_sig_ref.size() ) << "("; - if(0 < args_sz) { - std::visit(fdav, fk->args[0].kind); - os << ' ' << fk->args[0].identifier; + if(0 < args_sz) { + std::visit(fdav, fk->args[0].kind); + os << ' ' << fk->args[0].identifier; - for(std::size_t i = 1; i < args_sz; ++i) { - os << ','; - std::visit(fdav, fk->args[i].kind ); - os << ' ' << fk->args[i].identifier; + for(std::size_t i = 1; i < args_sz; ++i) { + os << ','; + std::visit(fdav, fk->args[i].kind ); + os << ' ' << fk->args[i].identifier; + } } - } - if(std::holds_alternative(fk->retKind)) { - os << ")"; + if(std::holds_alternative(fk->retKind)) { + os << ")"; + } + else { + os << ")"; + } } else { - os << ") -> "; - std::visit(fdav, fk->retKind); + os << "auto "; + std::string const& fn_sig_ref = + node->symbol.identifier; + + const std::size_t pos = + fn_sig_ref.find("|"); + + os << fn_sig_ref.substr(0, (pos != std::string::npos) ? pos : fn_sig_ref.size() ) << " = [&]("; + + if(0 < args_sz) { + std::visit(fdav, fk->args[0].kind); + os << ' ' << fk->args[0].identifier; + + for(std::size_t i = 1; i < args_sz; ++i) { + os << ','; + std::visit(fdav, fk->args[i].kind ); + os << ' ' << fk->args[i].identifier; + } + } + + if(std::holds_alternative(fk->retKind)) { + os << ")"; + } + else { + os << ") -> "; + std::visit(fdav, fk->retKind); + } } + os << " {"; os << std::endl; ++indent; @@ -455,6 +592,111 @@ struct StatementVisitor { os << ';' << std::endl; } } + void operator()(std::shared_ptr const& node) { + // populate prologue of template + os << "record " << node->symbol.identifier << " {" << std::endl; + for(Statement const& stmt : node->statements) { + std::visit(*this, stmt); + } + // populate epilogue of template + os << std::endl << "}" << std::endl; + } + void operator()(std::shared_ptr const& node) { + // populate prologue of template + os << "class " << node->symbol.identifier << " {" << std::endl; + for(Statement const& stmt : node->statements) { + std::visit(*this, stmt); + } + // populate epilogue of template + os << std::endl << "}" << std::endl; + } + void operator()(std::shared_ptr const& node) { + // needs to open a file and generate the module template provided by HK + // + std::fstream cppofs(node->symbol.identifier + ".cpp", std::ios_base::out); + StatementVisitor cppv{symbolTable, br, cppofs, indent, headers, true, false, true}; + + // populate prologue of template + + const std::size_t statements_size = node->statements.size(); + std::vector main_scoped_statements{}; + { + cppofs << "// This program file was generated by the chplx compiler." << std::endl + << "// The original Chapel program file can be found here: " << node->symbol.identifier << ".chpl" << std::endl + << "//" << std::endl + << "#include<" << node->symbol.identifier << ".hpp>" << std::endl << std::endl + << "namespace " << node->symbol.identifier << " {" << std::endl << std::endl; + + cppv.emitIndent(); + cppofs << "struct __thisModule *_this = nullptr;" << std::endl << std::endl; + cppv.emitIndent(); + cppofs << "struct __thisModule {" << std::endl << std::endl; + + for(std::size_t i = 0; i < statements_size; ++i) { + auto const& stmt = node->statements[i]; + if( + std::holds_alternative>(stmt) || + std::holds_alternative>(stmt) || + std::holds_alternative>(stmt) + ) { + std::visit(cppv, stmt); + } + else { + main_scoped_statements.push_back(i); + } + } + + cppofs << std::endl; + } + + // populate main scope of module + // + cppv.emitIndent(); + + cppofs << "void __main() {" << std::endl << std::endl; + + for(const std::size_t i : main_scoped_statements) { + auto const& stmt = node->statements[i]; + std::visit(cppv, stmt); + } + + cppofs << std::endl << std::endl; + cppv.emitIndent(); + cppofs << '}' << std::endl << std::endl; + cppv.emitIndent(); + cppofs << "static void __construct() { __thisModule = new __thisModule(); }" << std::endl << std::endl; + cppv.emitIndent(); + cppofs << "static void __destruct() noexcept {" << std::endl; + cppv.emitIndent(); cppv.emitIndent(); + cppofs << "auto *m = __thisModule;" << std::endl; + cppv.emitIndent(); cppv.emitIndent(); + cppofs << "__thisModule = nullptr;" << std::endl; + cppv.emitIndent(); cppv.emitIndent(); + cppofs << "delete m;" << std::endl; + cppv.emitIndent(); + cppofs << "}" << std::endl << std::endl; + cppv.emitIndent(); + cppofs << "}; // end of module struct" << std::endl; + cppofs << "} // end namespace"; + + // populate hpp + // + std::fstream hppofs(node->symbol.identifier + ".hpp", std::ios_base::out); + HppStatementVisitor hppv{symbolTable, br, hppofs, indent, headers, true, false}; + hppv.prologue(node); + for(std::size_t i = 0; i < statements_size; ++i) { + auto const& stmt = node->statements[i]; + if( + std::holds_alternative>(stmt) || + std::holds_alternative>(stmt) || + std::holds_alternative>(stmt) + ) { + std::visit(hppv, stmt); + } + } + hppv.epilogue(); + } + void emitChapelLine(std::ostream & os, uast::AstNode const* ast) const { auto const fp = br.filePath(); os << chplx::util::emitLineDirective(fp.c_str(), br.idToLocation(ast->id(), fp).line()); @@ -467,6 +709,7 @@ struct StatementVisitor { std::vector & headers; bool printChplLine; bool arg; + bool moduleLevel; }; template<> @@ -476,26 +719,62 @@ void CodegenVisitor::visit(StatementVisitor && v) { } } +void VisitQualifierPrefix(std::ostream & os, const int qualifier) { + if(qualifier == 1) { + os << "const "; + } + else if(qualifier == 4) { + os << "const "; + } +} + +void VisitQualifierSuffix(std::ostream & os, const int qualifier) { + if(qualifier == 2) { + os << " const&"; + } + else if(qualifier == 3) { + os << "&"; + } + else if(qualifier == 6) { + os << "&"; + } + else if(qualifier == 7) { + os << " const&"; + } + else if(qualifier == 8) { + os << "&"; + } + else if(qualifier == 9) { + os << "&"; + } +} + static void generateSourceHeader(std::vector & cfgVars, std::ostream & fos, std::string const& fps, std::string const& chplFile) { fos << "// This program file was generated by the chplx compiler." << std::endl; fos << "// The original Chapel program file can be found here: " << chplFile << std::endl; fos << "//" << std::endl; - fos << "#include " << std::endl << std::endl; - + fos << "#include " << std::endl; + if(0 < cfgVars.size()) { + fos << "#include " << std::endl; + } + fos << std::endl; + { const auto pos = fps.find("."); const std::string prefix = fps.substr(0, pos); - fos << "#include \"" << prefix << ".hpp\"" << std::endl; + fos << "#include \"" << prefix << "_driver.hpp\"" << std::endl; } if(0 < cfgVars.size()) { fos << std::endl; fos << "// global `config` variables" << std::endl << "//" << std::endl; for(auto & opt : cfgVars) { + VisitQualifierPrefix(fos, opt.kindqualifier); FuncDeclArgVisitor v{fos}; std::visit(v, opt.kind); - fos << ' ' << "config_" << opt.identifier; + VisitQualifierSuffix(fos, opt.kindqualifier); + fos << ' ' << opt.identifier; if(opt.isConfig && 0 < opt.literal.size()) { fos << " = "; std::visit(ScalarDeclarationLiteralExpressionVisitor{opt.literal[0], fos}, opt.kind); @@ -505,9 +784,10 @@ static void generateSourceHeader(std::vector & cfgVars, std::ostream & f } } -static void generateSourceFooter(std::vector & cfgVars, std::ostream & fos) { +static void generateSourceFooter(std::string const& modStr, std::vector & cfgVars, std::ostream & fos) { fos << std::endl - << "int main(int argc, char * argv[]) {" << std::endl; + << "int main(int argc, char * argv[]) {" << std::endl + << " chplx::registerModule<" << modStr << "::__thisModule>();" << std::endl; if(0 < cfgVars.size()) { fos << " hpx::program::options::options::options_description options;\n options.add_options()"; @@ -516,7 +796,9 @@ static void generateSourceFooter(std::vector & cfgVars, std::ostream & f FuncDeclArgVisitor v{fos}; fos << " hpx::program_options::value<"; std::visit(v, opt.kind); - fos << ">(&" << "config_" << opt.identifier << "), " << "\"config var " << opt.identifier << " : "; + fos << ">(&" << "config_" << opt.identifier << "), " << "\"config "; + if(0 < opt.kindqualifier) { VisitQualifierPrefix(fos, opt.kindqualifier); } else { fos << "var "; } + fos << opt.identifier << " : "; std::visit(v, opt.kind); fos << "\")"; } @@ -528,29 +810,43 @@ static void generateSourceFooter(std::vector & cfgVars, std::ostream & f << "}" << std::endl; } -static void generateHpxMainBeg(std::ostream & fos) { +static void generateHpxMain(std::ostream & fos, std::string const& moduleStr) { fos << std::endl << "int hpx_main(int argc, char * argv[]) {" << std::endl - << std::endl; -} - -static void generateHpxMainEnd(std::ostream & fos) { - fos << std::endl + << " " << moduleStr << "::__thisModule->__main();" << std::endl << " return hpx::finalize();" << std::endl << "}" << std::endl; } - void CodegenVisitor::visit() { - generateSourceHeader(cfgVars, fstrm_, cppFilePathStr, chplFilePathStr); + // generate cpp code `filename_driver.cpp` + // - figure this out... + // + const auto pos = chplFilePathStr.find("."); + std::string prefix = chplFilePathStr.substr(0, pos); + { + std::fstream ofs(prefix + "_driver.hpp", std::ios_base::out); + generateApplicationHeader(cppFilePathStr, prefix, ofs); + } + + { + std::fstream ofs(prefix + "_driver.cpp", std::ios_base::out); + generateSourceHeader(cfgVars, ofs, cppFilePathStr, chplFilePathStr); + generateHpxMain(ofs, prefix); + generateSourceFooter(prefix, cfgVars, ofs); + } - generateHpxMainBeg(fstrm_); + { + // rootos is intentionally empty/null + // + std::ostream rootos{0}; - visit(StatementVisitor{symbolTable, br, fstrm_, indent, headers, true, false}); + // generate cpp code for each module from the program tree + // + visit(StatementVisitor{symbolTable, br, rootos, indent, headers, true, false}); + } - generateHpxMainEnd(fstrm_); - generateSourceFooter(cfgVars, fstrm_); } } /* namespace hpx */ } /* namespace visitors */ } /* namespace ast */ } /* namespace chpl */ diff --git a/backend/src/driver.cpp b/backend/src/driver.cpp index 18e387d4..04ce23cc 100644 --- a/backend/src/driver.cpp +++ b/backend/src/driver.cpp @@ -183,16 +183,10 @@ int main(int argc, char ** argv) { std::cout << "[ProgramTreeBuildingVisitor] Exit" << std::endl; } - std::ofstream ofs(ofilePath); - - chpl::ast::visitors::hpx::CodegenVisitor cgv{sbv.symbolTable, sbv.configVars, program, br, ofilePath, chplFilePth.filename().string(), ofs}; + chpl::ast::visitors::hpx::CodegenVisitor cgv{sbv.symbolTable, sbv.configVars, program, br, ofilePath, chplFilePth.filename().string()}; cgv.indent += 1; - cgv.visit(); - cgv.generateApplicationHeader(chplFilePth); - - ofs.flush(); - ofs.close(); + cgv.visit(); CMakeGenerator gen{}; gen.generate(chplFilePth); diff --git a/backend/src/programtree.cpp b/backend/src/programtree.cpp index 9cf4ff70..99126159 100644 --- a/backend/src/programtree.cpp +++ b/backend/src/programtree.cpp @@ -77,6 +77,10 @@ void VisitQualifierSuffix(std::ostream & os, const int qualifier) { } void ScalarDeclarationExpression::emit(std::ostream & os) const { + if(config) { + os << "// "; + } + if(-1 < qualifier) { VisitQualifierPrefix(os, qualifier); } @@ -87,13 +91,7 @@ void ScalarDeclarationExpression::emit(std::ostream & os) const { VisitQualifierSuffix(os, qualifier); } - os << " " << identifier; - - if(config) { - os << " = config_" << identifier; - } - - os << ";" << std::endl; + os << " " << identifier << ";" << std::endl; } void ScalarDeclarationLiteralExpressionVisitor::operator()(bool_kind const&) { @@ -117,6 +115,10 @@ void ScalarDeclarationLiteralExpressionVisitor::operator()(string_kind const&) { } void ScalarDeclarationLiteralExpression::emit(std::ostream & os) const { + if(config) { + os << "// "; + } + if(-1 < qualifier) { VisitQualifierPrefix(os, qualifier); } @@ -435,4 +437,10 @@ void TernaryOpExpression::emit(std::ostream & os) const { void ForLoopExpression::emit(std::ostream & os) const { } +void RecordDeclarationExpression::emit(std::ostream & os) const { +} + +void ClassDeclarationExpression::emit(std::ostream & os) const { +} + } /* namespace hpx */ } /* namespace ast */ } /* namespace chpl */ diff --git a/backend/src/programtreebuildingvisitor.cpp b/backend/src/programtreebuildingvisitor.cpp index 69fdbac9..be5a9388 100644 --- a/backend/src/programtreebuildingvisitor.cpp +++ b/backend/src/programtreebuildingvisitor.cpp @@ -339,6 +339,9 @@ bool ProgramTreeBuildingVisitor::enter(const uast::AstNode * ast) { break; case asttags::Return: { + // check to see if the function symbol has a 'kind' set; + // if not set, set it to something + std::vector * cStmts = curStmts.back(); if(std::holds_alternative>(curStmts[curStmts.size()-2]->back())) { @@ -959,6 +962,9 @@ bool ProgramTreeBuildingVisitor::enter(const uast::AstNode * ast) { std::string lookup; }; + // check to see if the function symbol has a 'kind' set; + // if not set, set it to something (unknown is OK) + // if(node.has_value() && ast != (*node)) { ProgramTreeFunctionVisitor v{false, {}}; ast->traverse(v); @@ -1006,12 +1012,135 @@ bool ProgramTreeBuildingVisitor::enter(const uast::AstNode * ast) { case asttags::Interface: break; case asttags::Module: + { + std::string lookup = static_cast(ast)->name().str(); + +std::cout << symbolTableRef->id << ' ' << lookup << std::endl; + std::optional sym = + symbolTable.find(symbolTableRef->id, lookup); + + if(sym) { + std::shared_ptr & fk = std::get>(sym->kind); + symbolTableRef = symbolTable.lut[fk->lutId]; + + std::vector * cStmts = curStmts.back(); + + cStmts->emplace_back( + std::make_shared( + ModuleDeclarationExpression{{{{fk->lutId}, ast, {}}, *sym, {}, emitChapelLine(ast)}} + )); + + auto & fndecl = std::get>(cStmts->back()); + curStmts.emplace_back(&(fndecl->statements)); + } + else { + std::optional< std::pair< std::map::iterator, std::map::iterator > > fnsym + = symbolTable.findPrefix(symbolTableRef->id, lookup); + assert(fnsym.has_value()); + + std::map::iterator val = fnsym->second; + for(std::map::iterator itr = fnsym->first; itr != fnsym->second; ++itr) { + if(lookup == itr->first) { + val = itr; + } + } + + if(val == fnsym->second) { return false; } + + //Symbol & fsym = val->second; + + std::shared_ptr & fk = std::get>(sym->kind); + symbolTableRef = symbolTable.lut[fk->lutId]; + } + } break; case asttags::START_AggregateDecl: break; - case asttags::Class: - break; case asttags::Record: + { + std::string lookup = static_cast(ast)->name().str(); + + std::optional sym = + symbolTable.find(symbolTableRef->id, lookup); + + if(sym) { + std::shared_ptr & fk = std::get>(sym->kind); + symbolTableRef = symbolTable.lut[fk->lutId]; + + std::vector * cStmts = curStmts.back(); + + cStmts->emplace_back( + std::make_shared( + RecordDeclarationExpression{{{fk->lutId}, ast, {}}, *sym, {}, emitChapelLine(ast)} + )); + + auto & fndecl = std::get>(cStmts->back()); + curStmts.emplace_back(&(fndecl->statements)); + } + else { + std::optional< std::pair< std::map::iterator, std::map::iterator > > fnsym + = symbolTable.findPrefix(symbolTableRef->id, lookup); + + assert(fnsym.has_value()); + + std::map::iterator val = fnsym->second; + for(std::map::iterator itr = fnsym->first; itr != fnsym->second; ++itr) { + if(lookup == itr->first) { + val = itr; + } + } + + if(val == fnsym->second) { return false; } + + //Symbol & fsym = val->second; + + std::shared_ptr & fk = std::get>(sym->kind); + symbolTableRef = symbolTable.lut[fk->lutId]; + } + } + break; + case asttags::Class: + { + std::string lookup = static_cast(ast)->name().str(); + + std::optional sym = + symbolTable.find(symbolTableRef->id, lookup); + + if(sym) { + std::shared_ptr & fk = std::get>(sym->kind); + symbolTableRef = symbolTable.lut[fk->lutId]; + + std::vector * cStmts = curStmts.back(); + + cStmts->emplace_back( + std::make_shared( + ClassDeclarationExpression{{{{fk->lutId}, ast, {}}, *sym, {}, emitChapelLine(ast)}} + )); + + auto & fndecl = std::get>(cStmts->back()); + curStmts.emplace_back(&(fndecl->statements)); + } + else { + std::optional< std::pair< std::map::iterator, std::map::iterator > > fnsym + = symbolTable.findPrefix(symbolTableRef->id, lookup); + + assert(fnsym.has_value()); + + std::map::iterator val = fnsym->second; + for(std::map::iterator itr = fnsym->first; itr != fnsym->second; ++itr) { + if(lookup == itr->first) { + val = itr; + } + } + + if(val == fnsym->second) { return false; } + + //Symbol & fsym = val->second; + + std::shared_ptr & fk = std::get>(sym->kind); + symbolTableRef = symbolTable.lut[fk->lutId]; + } + } break; case asttags::Union: break; diff --git a/backend/src/symbolbuildingvisitor.cpp b/backend/src/symbolbuildingvisitor.cpp index c66ef48a..09e6a622 100644 --- a/backend/src/symbolbuildingvisitor.cpp +++ b/backend/src/symbolbuildingvisitor.cpp @@ -542,6 +542,7 @@ bool SymbolBuildingVisitor::enter(const uast::AstNode * ast) { sym->get().kind = expr_kind{}; } } +std::cout << "SYMSTACKSZ\t" << symstack.size() << ' ' << symstack.back().kind.index() << ' ' << symstack.back().identifier << std::endl; } break; case asttags::OpCall: @@ -684,7 +685,7 @@ bool SymbolBuildingVisitor::enter(const uast::AstNode * ast) { break; case asttags::Conditional: { - if(!(sym && 0 < sym->get().kind.index())) { + if(!(sym && !std::holds_alternative>(sym->get().kind))) { // symbol.scopePtr = the scope where the function is defined (equivalent to a lutId) // symstack.emplace_back( @@ -755,6 +756,7 @@ bool SymbolBuildingVisitor::enter(const uast::AstNode * ast) { symnode = const_cast(ast); } +std::cout << "SYMSTACKSZ\t" << symstack.size() << ' ' << symstack.back().kind.index() << ' ' << symstack.back().identifier << std::endl; } break; case asttags::Implements: @@ -773,7 +775,7 @@ bool SymbolBuildingVisitor::enter(const uast::AstNode * ast) { break; case asttags::Block: { - if(sym && 0 < sym->get().kind.index()) { + if(sym && !std::holds_alternative>(sym->get().kind)) { //0 < sym->get().kind.index()) { if(std::holds_alternative>(sym->get().kind)) { std::shared_ptr & fk = std::get>(sym->get().kind); @@ -818,6 +820,7 @@ bool SymbolBuildingVisitor::enter(const uast::AstNode * ast) { symbolTable.parentSymbolTableId = parScope; symbolTable.symbolTableRef->parent = prevSymbolTableRef; } +std::cout << "SYMSTACKSZ\t" << symstack.size() << ' ' << symstack.back().kind.index() << ' ' << symstack.back().identifier << std::endl; } break; case asttags::Defer: @@ -851,7 +854,7 @@ bool SymbolBuildingVisitor::enter(const uast::AstNode * ast) { break; case asttags::Coforall: { - if(!(sym && 0 < sym->get().kind.index())) { + if(!(sym && !std::holds_alternative>(sym->get().kind))) { //)0 < sym->get().kind.index())) { // symbol.scopePtr = the scope where the function is defined (equivalent to a lutId) // symstack.emplace_back( @@ -1015,7 +1018,8 @@ bool SymbolBuildingVisitor::enter(const uast::AstNode * ast) { std::string lookup; }; - if(!(sym && 0 < sym->get().kind.index())) { + //if(!(sym && std::holds_alternative>(sym->get().kind))) { // 0 < sym->get().kind.index())) { + { ProgramTreeFunctionVisitor v{false}; ast->traverse(v); @@ -1054,12 +1058,109 @@ bool SymbolBuildingVisitor::enter(const uast::AstNode * ast) { case asttags::Interface: break; case asttags::Module: + { + std::string lookup = static_cast(ast)->name().str(); + // symbol.scopePtr = the scope where the function is defined (equivalent to a lutId) + // + symstack.emplace_back( + Symbol{{ + std::make_shared(module_kind{{ + symbolTable.symbolTableRef->id, lookup, {}, {}}}), + lookup, + {}, -1, false, symbolTable.symbolTableRef->id + }}); + + std::shared_ptr prevSymbolTableRef = symbolTable.symbolTableRef; + const std::size_t parScope = symbolTable.symbolTableRef->id; + symbolTable.pushScope(); + sym.reset(); + sym = symstack.back(); + + std::shared_ptr & mk = + std::get>(sym->get().kind); + + //fk->symbolTableSignature = std::string{v.lookup}; + // func_kind.lutId = the scope where the function's symboltable references + // + mk->lutId = symbolTable.symbolTableRef->id; + + symbolTable.parentSymbolTableId = parScope; + symbolTable.symbolTableRef->parent = prevSymbolTableRef; + + symnode = const_cast(ast); + } break; case asttags::START_AggregateDecl: break; - case asttags::Class: - break; case asttags::Record: + { + std::string lookup = static_cast(ast)->name().str(); + + // symbol.scopePtr = the scope where the function is defined (equivalent to a lutId) + // + symstack.emplace_back( + Symbol{{ + std::make_shared(record_kind{ + symbolTable.symbolTableRef->id, lookup, {}}), + lookup, + {}, -1, false, symbolTable.symbolTableRef->id + }}); + + std::shared_ptr prevSymbolTableRef = symbolTable.symbolTableRef; + const std::size_t parScope = symbolTable.symbolTableRef->id; + symbolTable.pushScope(); + sym.reset(); + sym = symstack.back(); + + std::shared_ptr & rk = + std::get>(sym->get().kind); + + //fk->symbolTableSignature = std::string{lookup}; + // func_kind.lutId = the scope where the function's symboltable references + // + + rk->lutId = symbolTable.symbolTableRef->id; + + symbolTable.parentSymbolTableId = parScope; + symbolTable.symbolTableRef->parent = prevSymbolTableRef; + + symnode = const_cast(ast); + } + break; + case asttags::Class: + { + std::string lookup = static_cast(ast)->name().str(); + + // symbol.scopePtr = the scope where the function is defined (equivalent to a lutId) + // + symstack.emplace_back( + Symbol{{ + std::make_shared(class_kind{{ + symbolTable.symbolTableRef->id, lookup, {}}, {}}), + lookup, + {}, -1, false, symbolTable.symbolTableRef->id + }}); + + std::shared_ptr prevSymbolTableRef = symbolTable.symbolTableRef; + const std::size_t parScope = symbolTable.symbolTableRef->id; + symbolTable.pushScope(); + sym.reset(); + sym = symstack.back(); + + std::shared_ptr & ck = + std::get>(sym->get().kind); + + //fk->symbolTableSignature = std::string{lookup}; + // func_kind.lutId = the scope where the function's symboltable references + // + + ck->lutId = symbolTable.symbolTableRef->id; + + symbolTable.parentSymbolTableId = parScope; + symbolTable.symbolTableRef->parent = prevSymbolTableRef; + + symnode = const_cast(ast); + } break; case asttags::Union: break; @@ -1306,10 +1407,10 @@ void SymbolBuildingVisitor::exit(const uast::AstNode * ast) { case asttags::Block: { if(sym) { +std::cout << "SYMSTACKSZ\t" << symstack.size() << ' ' << symstack.back().kind.index() << ' ' << symstack.back().identifier << std::endl; assert( 0 < sym->get().identifier.size() ); auto lusym = symbolTable.find(sym->get().scopeId, sym->get().identifier); const bool is_func = std::holds_alternative>(sym->get().kind); - if(!lusym && is_func) { std::shared_ptr & fk = std::get>(sym->get().kind); @@ -1322,11 +1423,11 @@ void SymbolBuildingVisitor::exit(const uast::AstNode * ast) { sym.reset(); symnode = nullptr; - if(1 < symstack.size()) { + if(2 < symstack.size()) { symstack.pop_back(); sym = symstack.back(); } - else if(0 < symstack.size()) { + else if(1 < symstack.size()) { symstack.pop_back(); } @@ -1357,7 +1458,8 @@ void SymbolBuildingVisitor::exit(const uast::AstNode * ast) { case asttags::Function: { if(sym) { - assert( 0 < sym->get().identifier.size() ); +std::cout << "FN\t" << sym.has_value() << ' ' << sym->get().identifier << ' ' << sym->get().kind.index() << std::endl; + assert( sym.has_value() && std::holds_alternative>(sym->get().kind)); auto lusym = symbolTable.find(sym->get().scopeId, sym->get().identifier); if(!lusym) { std::shared_ptr & fk = @@ -1371,10 +1473,11 @@ void SymbolBuildingVisitor::exit(const uast::AstNode * ast) { sym.reset(); symnode = nullptr; - if(0 < symstack.size()) { + if(1 < symstack.size()) { symstack.pop_back(); } - if(1 < symstack.size()) { + + if(2 < symstack.size()) { sym = symstack.back(); } @@ -1397,12 +1500,123 @@ void SymbolBuildingVisitor::exit(const uast::AstNode * ast) { case asttags::Interface: break; case asttags::Module: + { + if(0 < symstack.size()) { + sym.reset(); + sym = symstack.back(); + } + + if(sym) { + assert( 0 < sym->get().identifier.size() ); + auto lusym = symbolTable.find(sym->get().scopeId, sym->get().identifier); + if(!lusym) { + std::shared_ptr & fk = + std::get>(sym->get().kind); + + if(fk->retKind.index() < 1) { + fk->retKind = nil_kind{}; + } + + symbolTable.addEntry(sym->get().scopeId, fk->symbolTableSignature, *sym); + sym.reset(); + symnode = nullptr; + + if(1 < symstack.size()) { + symstack.pop_back(); + } + if(2 < symstack.size()) { + sym = symstack.back(); + } + + symbolTable.popScope(); + } + else if (0 < sym->get().kind.index() && std::holds_alternative>(sym->get().kind)) { + std::shared_ptr & fk = + std::get>(sym->get().kind); + + std::cerr << "chplx : " << fk->symbolTableSignature << " identifier already defined in current scope" << std::endl; + return; + } + else { + std::cerr << "chplx : " << sym->get().identifier << " identifier already defined in current scope" << std::endl; + return; + } + } + } break; case asttags::START_AggregateDecl: break; - case asttags::Class: - break; case asttags::Record: + { + if(sym) { + assert( 0 < sym->get().identifier.size() ); + auto lusym = symbolTable.find(sym->get().scopeId, sym->get().identifier); + if(!lusym) { + std::shared_ptr & rk = + std::get>(sym->get().kind); + + symbolTable.addEntry(sym->get().scopeId, rk->symbolTableSignature, *sym); + sym.reset(); + symnode = nullptr; + + if(1 < symstack.size()) { + symstack.pop_back(); + } + if(2 < symstack.size()) { + sym = symstack.back(); + } + + symbolTable.popScope(); + } + else if (0 < sym->get().kind.index() && std::holds_alternative>(sym->get().kind)) { + std::shared_ptr & rk = + std::get>(sym->get().kind); + + std::cerr << "chplx : " << rk->symbolTableSignature << " identifier already defined in current scope" << std::endl; + return; + } + else { + std::cerr << "chplx : " << sym->get().identifier << " identifier already defined in current scope" << std::endl; + return; + } + } + } + break; + case asttags::Class: + { + if(sym) { + assert( 0 < sym->get().identifier.size() ); + auto lusym = symbolTable.find(sym->get().scopeId, sym->get().identifier); + if(!lusym) { + std::shared_ptr & ck = + std::get>(sym->get().kind); + + symbolTable.addEntry(sym->get().scopeId, ck->symbolTableSignature, *sym); + sym.reset(); + symnode = nullptr; + + if(1 < symstack.size()) { + symstack.pop_back(); + } + if(2 < symstack.size()) { + sym = symstack.back(); + } + + symbolTable.popScope(); + } + else if (0 < sym->get().kind.index() && std::holds_alternative>(sym->get().kind)) { + std::shared_ptr & ck = + std::get>(sym->get().kind); + + std::cerr << "chplx : " << ck->symbolTableSignature << " identifier already defined in current scope" << std::endl; + return; + } + else { + std::cerr << "chplx : " << sym->get().identifier << " identifier already defined in current scope" << std::endl; + return; + } + } + } break; case asttags::Union: break;