From 58be1ebb919ad9a276aea677e78a5fde8bddfc1d Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Wed, 21 Sep 2016 21:37:20 +0100 Subject: Split compiler code away from runtime code --- slicer/slicer/Jamfile.jam | 5 - slicer/slicer/parser.cpp | 646 ------------------------------------------- slicer/slicer/parser.h | 75 ----- slicer/test/Jamfile.jam | 1 + slicer/test/preprocessor.cpp | 2 +- slicer/test/serializers.cpp | 2 +- slicer/tool/Jamfile.jam | 23 +- slicer/tool/parser.cpp | 646 +++++++++++++++++++++++++++++++++++++++++++ slicer/tool/parser.h | 75 +++++ slicer/tool/slicer.cpp | 2 +- 10 files changed, 746 insertions(+), 731 deletions(-) delete mode 100644 slicer/slicer/parser.cpp delete mode 100644 slicer/slicer/parser.h create mode 100644 slicer/tool/parser.cpp create mode 100644 slicer/tool/parser.h diff --git a/slicer/slicer/Jamfile.jam b/slicer/slicer/Jamfile.jam index 3d5fa77..7def868 100644 --- a/slicer/slicer/Jamfile.jam +++ b/slicer/slicer/Jamfile.jam @@ -1,20 +1,15 @@ -lib Slice ; lib IceUtil ; lib boost_system ; -lib boost_filesystem ; lib adhocutil : : : : /usr/include/adhocutil ; lib slicer : [ glob *.cpp ] : - Slice IceUtil boost_system - boost_filesystem adhocutil .. : : .. boost_system - boost_filesystem ; diff --git a/slicer/slicer/parser.cpp b/slicer/slicer/parser.cpp deleted file mode 100644 index 3d1c735..0000000 --- a/slicer/slicer/parser.cpp +++ /dev/null @@ -1,646 +0,0 @@ -#include "parser.h" -#include "metadata.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace fs = boost::filesystem; - -std::mutex slicePreprocessor; - -namespace Slicer { - Slicer::Slicer(FILE * c) : - components(0), - cpp(c), - classNo(0) - { - } - - void - Slicer::defineConversions(Slice::DataMemberPtr dm) const - { - if (!cpp) return; - - auto type = dm->type(); - auto c = Slice::ContainedPtr::dynamicCast(dm->container()); - auto conversions = getAllConversions(dm); - for (const auto & conversion : conversions) { - if (!AdHoc::containerContains(conversion.Options, "nodeclare")) { - if (!AdHoc::containerContains(conversion.Options, "nodeclareto")) { - fprintbf(cpp, "DLL_PUBLIC %s %s(const %s &);\n", - conversion.ExchangeType, - conversion.ConvertToExchangeFunc, - Slice::typeToString(type)); - } - if (!AdHoc::containerContains(conversion.Options, "nodeclarefrom")) { - fprintbf(cpp, "DLL_PUBLIC %s %s(const %s &);\n\n", - Slice::typeToString(type), - conversion.ConvertToModelFunc, - conversion.ExchangeType); - } - } - } - if (!conversions.empty()) { - fprintbf(cpp, "template<> DLL_PUBLIC\nvoid\n"); - fprintbf(cpp, "ModelPartForConverted< %s, %s, &%s >::SetValue(ValueSourcePtr vsp)\n", - Slice::typeToString(type), - c->scoped(), - dm->scoped()); - fprintbf(cpp, "{\n"); - - for (const auto & conversion : conversions) { - fprintbf(cpp, "\tif (auto vspt = dynamic_cast *>(vsp.get())) {\n", - conversion.ExchangeType); - fprintbf(cpp, "\t\t%s tmp;\n", - conversion.ExchangeType); - fprintbf(cpp, "\t\tvspt->set(tmp);\n"); - fprintbf(cpp, "\t\tMember = %s(tmp);\n", - conversion.ConvertToModelFunc); - fprintbf(cpp, "\t\treturn;\n"); - fprintbf(cpp, "\t}\n"); - } - // Default conversion - if (!dm->hasMetaData("slicer:nodefaultconversion")) { - fprintbf(cpp, "\tif (auto vspt = dynamic_cast *>(vsp.get())) {\n", - Slice::typeToString(type)); - fprintbf(cpp, "\t\tvspt->set(Member);\n"); - fprintbf(cpp, "\t\treturn;\n"); - fprintbf(cpp, "\t}\n"); - } - // Failed to convert - fprintbf(cpp, "\tthrow NoConversionFound(\"%s\");\n", - Slice::typeToString(type)); - fprintbf(cpp, "}\n\n"); - - fprintbf(cpp, "template<> DLL_PUBLIC\nvoid\n"); - fprintbf(cpp, "ModelPartForConverted< %s, %s, &%s >::GetValue(ValueTargetPtr vtp)\n", - Slice::typeToString(type), - c->scoped(), - dm->scoped()); - fprintbf(cpp, "{\n"); - - for (const auto & conversion : conversions) { - fprintbf(cpp, "\tif (auto vtpt = dynamic_cast *>(vtp.get())) {\n", - conversion.ExchangeType); - fprintbf(cpp, "\t\tvtpt->get(%s(Member));\n", - conversion.ConvertToExchangeFunc); - fprintbf(cpp, "\t\treturn;\n"); - fprintbf(cpp, "\t}\n"); - } - // Default conversion - if (!dm->hasMetaData("slicer:nodefaultconversion")) { - fprintbf(cpp, "\tif (auto vtpt = dynamic_cast *>(vtp.get())) {\n", - Slice::typeToString(type)); - fprintbf(cpp, "\t\tvtpt->get(Member);\n"); - fprintbf(cpp, "\t\treturn;\n"); - fprintbf(cpp, "\t}\n"); - } - // Failed to convert - fprintbf(cpp, "\tthrow NoConversionFound(\"%s\");\n", - Slice::typeToString(type)); - fprintbf(cpp, "}\n\n"); - } - } - - bool - Slicer::visitUnitStart(const Slice::UnitPtr & u) - { - fs::path topLevelFile(u->topLevelFile()); - if (!cpp) return true; - - fprintbf(cpp, "// Begin Slicer code\n\n"); - fprintbf(cpp, "#include <%s>\n\n", fs::change_extension(topLevelFile.filename(), ".h").string()); - fprintbf(cpp, "#include \n\n"); - fprintbf(cpp, "namespace Slicer {\n"); - return true; - } - - void - Slicer::visitUnitEnd(const Slice::UnitPtr&) - { - if (!cpp) return; - - fprintbf(cpp, "}\n\n"); - fprintbf(cpp, "// End Slicer code\n\n"); - } - - bool - Slicer::visitModuleStart(const Slice::ModulePtr & m) - { - if (!cpp) return true; - - fprintbf(cpp, "// Begin module %s\n\n", m->name()); - for (const auto & c : m->structs()) { - for (const auto & dm : c->dataMembers()) { - defineConversions(dm); - } - } - for (const auto & c : m->classes()) { - for (const auto & dm : c->dataMembers()) { - defineConversions(dm); - } - } - return true; - } - - - void - Slicer::defineRootName(const std::string & type, const std::string & name) const - { - fprintbf(cpp, "template<> DLL_PUBLIC\n"); - fprintbf(cpp, "const std::string ModelPartForRoot< %s >::rootName(\"%s\");\n\n", - type, name); - fprintbf(cpp, "template<> DLL_PUBLIC\n"); - fprintbf(cpp, "const std::string ModelPartForRoot< IceUtil::Optional< %s > >::rootName(\"Optional%s\");\n\n", - type, name); - - fprintbf(cpp, "template class ModelPartForRoot< %s >;\n\n", type); - fprintbf(cpp, "template class ModelPartForRoot< IceUtil::Optional< %s > >;\n\n", type); - } - - bool - Slicer::visitClassDefStart(const Slice::ClassDefPtr & c) - { - if (c->isInterface()) { return false; } - if (c->hasMetaData("slicer:ignore")) { return false; } - - components += 1; - - if (!cpp) return true; - - auto decl = c->declaration(); - fprintbf(cpp, "// Class %s\n", c->name()); - visitComplexDataMembers(decl, c->allDataMembers()); - - fprintbf(cpp, "template<> DLL_PUBLIC\n"); - auto typeId = metaDataValue("slicer:typeid:", c->getMetaData()); - fprintbf(cpp, "const std::string ModelPartForClass< %s >::typeIdProperty(\"%s\");\n\n", - typeToString(decl), - typeId ? *typeId : "slicer-typeid"); - - auto name = metaDataValue("slicer:root:", c->getMetaData()); - defineRootName(typeToString(decl), name ? *name : c->name()); - - auto typeName = metaDataValue("slicer:typename:", c->getMetaData()); - fprintbf(cpp, "static void registerClass_%u() __attribute__ ((constructor(210)));\n", classNo); - fprintbf(cpp, "static void registerClass_%u()\n{\n", classNo); - fprintbf(cpp, "\tSlicer::classRefMap()->insert({ \"%s\", [](void * p){ return new ModelPartForClass< %s >(*static_cast< %s *>(p)); } });\n", - c->scoped(), - typeToString(decl), - typeToString(decl)); - if (typeName) { - fprintbf(cpp, "\tSlicer::classNameMap()->insert({ \"%s\", \"%s\" });\n", - c->scoped(), - *typeName); - } - fprintbf(cpp, "}\n\n"); - fprintbf(cpp, "static void unregisterClass_%u() __attribute__ ((destructor(210)));\n", classNo); - fprintbf(cpp, "static void unregisterClass_%u()\n{\n", classNo); - fprintbf(cpp, "\tSlicer::classRefMap()->erase(\"%s\");\n", - c->scoped()); - if (typeName) { - fprintbf(cpp, "\tSlicer::classNameMap()->left.erase(\"%s\");\n", - c->scoped()); - } - fprintbf(cpp, "}\n\n"); - - fprintbf(cpp, "template<> DLL_PUBLIC\nTypeId\nModelPartForClass< %s >::GetTypeId() const\n{\n", - typeToString(decl)); - fprintbf(cpp, "\tauto id = ModelObject->ice_id();\n"); - fprintbf(cpp, "\treturn (id == \"%s\") ? TypeId() : ModelPart::ToExchangeTypeName(id);\n}\n\n", - c->scoped()); - - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForComplex< %s >::metadata ", - c->scoped()); - copyMetadata(c->getMetaData()); - - fprintbf(cpp, "MODELPARTFOR(::IceInternal::Handle< %s >, ModelPartForClass);\n\n", - c->scoped()); - - classNo += 1; - - return true; - } - - bool - Slicer::visitStructStart(const Slice::StructPtr & c) - { - if (c->hasMetaData("slicer:ignore")) { return false; } - - components += 1; - - if (!cpp) return true; - - fprintbf(cpp, "// Struct %s\n", c->name()); - visitComplexDataMembers(c, c->dataMembers()); - - auto name = metaDataValue("slicer:root:", c->getMetaData()); - defineRootName(c->scoped(), name ? *name : c->name()); - - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForComplex< %s >::metadata ", - c->scoped()); - copyMetadata(c->getMetaData()); - - fprintbf(cpp, "MODELPARTFOR(%s, ModelPartForStruct);\n\n", - c->scoped()); - - return true; - } - - void - Slicer::visitComplexDataMembers(Slice::ConstructedPtr it, const Slice::DataMemberList & dataMembers) const - { - if (!cpp) return; - - fprintbf(cpp, "template<> DLL_PUBLIC\n"); - fprintbf(cpp, "const ModelPartForComplex< %s >::Hooks ", - it->scoped()); - fprintbf(cpp, "ModelPartForComplex< %s >::hooks {\n", - it->scoped()); - for (const auto & dm : dataMembers) { - auto c = Slice::ContainedPtr::dynamicCast(dm->container()); - auto t = Slice::TypePtr::dynamicCast(dm->container()); - if (!t) { - t = Slice::ClassDefPtr::dynamicCast(dm->container())->declaration(); - } - auto name = metaDataValue("slicer:name:", dm->getMetaData()); - auto conversions = getAllConversions(dm); - fprintbf(cpp, "\t\tnew "); - auto type = dm->type(); - createNewModelPartPtrFor(t); - fprintbf(cpp, "< %s >::Hook< %s", - typeToString(it), - Slice::typeToString(type, dm->optional())); - fprintbf(cpp, ", %s, &%s, ", - boost::algorithm::trim_right_copy_if(dm->container()->thisScope(), ispunct), - dm->scoped()); - if (dm->optional()) { - fprintbf(cpp, "ModelPartForOptional< "); - } - if (!conversions.empty()) { - fprintbf(cpp, "ModelPartForConverted< %s, %s, &%s >", - Slice::typeToString(type), - boost::algorithm::trim_right_copy_if(dm->container()->thisScope(), ispunct), - dm->scoped()); - } - else { - createNewModelPartPtrFor(type); - fprintbf(cpp, "< %s >", - Slice::typeToString(type)); - } - if (dm->optional()) { - fprintbf(cpp, " > "); - } - if (!hasMetadata(dm->getMetaData())) { - fprintbf(cpp, ", HookBase"); - } - fprintbf(cpp, " >(\"%s\"),\n", - name ? *name : dm->name()); - } - fprintbf(cpp, "\t};\n\n"); - - for (const auto & dm : dataMembers) { - if (!hasMetadata(dm->getMetaData())) { - continue; - } - auto c = Slice::ContainedPtr::dynamicCast(dm->container()); - auto t = Slice::TypePtr::dynamicCast(dm->container()); - if (!t) { - t = Slice::ClassDefPtr::dynamicCast(dm->container())->declaration(); - } - auto type = dm->type(); - fprintbf(cpp, "template<>\ntemplate<> DLL_PUBLIC\nconst Metadata\n"); - createNewModelPartPtrFor(t); - fprintbf(cpp, "< %s >::HookMetadata< %s", - typeToString(it), - Slice::typeToString(type, dm->optional())); - fprintbf(cpp, ", %s, &%s >::metadata ", - boost::algorithm::trim_right_copy_if(dm->container()->thisScope(), ispunct), - dm->scoped()); - copyMetadata(dm->getMetaData()); - } - } - - void - Slicer::visitEnum(const Slice::EnumPtr & e) - { - if (e->hasMetaData("slicer:ignore")) { return; } - - components += 1; - - if (!cpp) return; - - fprintbf(cpp, "// Enumeration %s\n", e->name()); - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForEnum< %s >::metadata ", - e->scoped()); - copyMetadata(e->getMetaData()); - - fprintbf(cpp, "template<> DLL_PUBLIC\nconst ModelPartForEnum< %s >::Enumerations\nModelPartForEnum< %s >::enumerations([]() -> ModelPartForEnum< %s >::Enumerations\n", - e->scoped(), - e->scoped(), - e->scoped()); - fprintbf(cpp, "{\n\tModelPartForEnum< %s >::Enumerations e;\n", - e->scoped()); - for (const auto & ee : e->getEnumerators()) { - fprintbf(cpp, "\te.insert( { %s, \"%s\" } );\n", ee->scoped(), ee->name()); - } - fprintbf(cpp, "\treturn e;\n}());\n\n"); - - fprintbf(cpp, "template<> DLL_PUBLIC\nvoid ModelPartForEnum< %s >::SetValue(ValueSourcePtr s) {\n\ - std::string val;\n\ - s->set(val);\n\ - modelPart = lookup(val);\n\ -}\n\n", - e->scoped()); - fprintbf(cpp, "template<> DLL_PUBLIC\nvoid ModelPartForEnum< %s >::GetValue(ValueTargetPtr s) {\n\ - s->get(lookup(modelPart));\n\ -}\n\n", - e->scoped()); - - auto name = metaDataValue("slicer:root:", e->getMetaData()); - defineRootName(e->scoped(), name ? *name : e->name()); - - fprintbf(cpp, "MODELPARTFOR(%s, ModelPartForEnum);\n\n", - e->scoped()); - fprintbf(cpp, "template %s ModelPartForEnum< %s >::lookup(const std::string &);\n\n", - e->scoped(), e->scoped()); - fprintbf(cpp, "template const std::string & ModelPartForEnum< %s >::lookup(%s);\n\n", - e->scoped(), e->scoped()); - } - - void - Slicer::visitSequence(const Slice::SequencePtr & s) - { - if (s->hasMetaData("slicer:ignore")) { return; } - - components += 1; - - if (!cpp) return; - - fprintbf(cpp, "// Sequence %s\n", s->name()); - fprintbf(cpp, "template<> DLL_PUBLIC\n"); - fprintbf(cpp, "ChildRefPtr ModelPartForSequence< %s >::GetChildRef(const std::string & name, const HookFilter & flt)\n{\n", - s->scoped()); - auto iname = metaDataValue("slicer:item:", s->getMetaData()); - if (iname) { - fprintbf(cpp, "\tif (!name.empty() && name != \"%s\") { throw IncorrectElementName(); }\n", - *iname); - } - else { - fprintbf(cpp, "\t(void)name;\n"); - } - fprintbf(cpp, "\treturn GetAnonChildRef(flt);\n}\n\n"); - - fprintbf(cpp, "template<> DLL_PUBLIC\n"); - fprintbf(cpp, "ModelPartPtr\n"); - fprintbf(cpp, "ModelPartForSequence< %s >::elementModelPart(typename %s::value_type & e) const {\n", - s->scoped(), - s->scoped()); - fprintbf(cpp, "\treturn ModelPart::CreateFor(e);\n}\n\n"); - - fprintbf(cpp, "template<> DLL_PUBLIC\n"); - auto ename = metaDataValue("slicer:element:", s->getMetaData()); - fprintbf(cpp, "const std::string ModelPartForSequence< %s >::elementName(\"%s\");\n\n", - s->scoped(), - ename ? *ename : "element"); - - auto name = metaDataValue("slicer:root:", s->getMetaData()); - defineRootName(s->scoped(), name ? *name : s->name()); - - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForSequence< %s >::metadata ", - s->scoped()); - copyMetadata(s->getMetaData()); - - fprintbf(cpp, "MODELPARTFOR(%s, ModelPartForSequence);\n\n", - s->scoped()); - } - - void - Slicer::visitDictionary(const Slice::DictionaryPtr & d) - { - if (d->hasMetaData("slicer:ignore")) { return; } - - components += 1; - - if (!cpp) return; - - fprintbf(cpp, "// Dictionary %s\n", d->name()); - auto iname = metaDataValue("slicer:item:", d->getMetaData()); - fprintbf(cpp, "template<> DLL_PUBLIC\n"); - fprintbf(cpp, "const std::string ModelPartForDictionary< %s >::pairName(\"%s\");\n\n", - d->scoped(), - iname ? *iname : "element"); - - fprintbf(cpp, "template<> DLL_PUBLIC\n"); - fprintbf(cpp, "const ModelPartForComplex< %s::value_type >::Hooks ", - d->scoped()); - fprintbf(cpp, "ModelPartForComplex< %s::value_type >::hooks {\n", - d->scoped()); - auto kname = metaDataValue("slicer:key:", d->getMetaData()); - auto vname = metaDataValue("slicer:value:", d->getMetaData()); - fprintbf(cpp, "\t\t"); - auto ktype = d->keyType(); - fprintbf(cpp, "new ModelPartForComplex< %s::value_type >::Hook< const %s, %s::value_type, &%s::value_type::first, ", - d->scoped(), - Slice::typeToString(ktype), - d->scoped(), - d->scoped()); - createNewModelPartPtrFor(ktype); - fprintbf(cpp, "< %s >, HookBase >(\"%s\"),\n\t\t", - Slice::typeToString(ktype), - kname ? *kname : "key"); - auto vtype = d->valueType(); - fprintbf(cpp, "new ModelPartForComplex< %s::value_type >::Hook< %s, %s::value_type, &%s::value_type::second, ", - d->scoped(), - Slice::typeToString(vtype), - d->scoped(), - d->scoped()); - createNewModelPartPtrFor(vtype); - fprintbf(cpp, "< %s >, HookBase >(\"%s\"),\n", - Slice::typeToString(vtype), - vname ? *vname : "value"); - fprintbf(cpp, "\t};\n"); - fprintbf(cpp, "\n"); - - auto name = metaDataValue("slicer:root:", d->getMetaData()); - defineRootName(d->scoped(), name ? *name : d->name()); - - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForDictionary< %s >::metadata ", - d->scoped()); - copyMetadata(d->getMetaData()); - - fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForComplex<%s::value_type>::metadata ", - d->scoped()); - copyMetadata(d->getMetaData()); - - fprintbf(cpp, "MODELPARTFOR(%s, ModelPartForDictionary);\n\n", - d->scoped()); - } - - void - Slicer::visitModuleEnd(const Slice::ModulePtr & m) - { - if (cpp) { - fprintbf(cpp, "// End module %s\n\n", m->name()); - } - } - - void - Slicer::createNewModelPartPtrFor(const Slice::TypePtr & type) const - { - if (auto builtin = Slice::BuiltinPtr::dynamicCast(type)) { - fprintbf(cpp, "ModelPartForSimple"); - } - else if (auto complexClass = Slice::ClassDeclPtr::dynamicCast(type)) { - fprintbf(cpp, "ModelPartForClass"); - } - else if (auto complexStruct = Slice::StructPtr::dynamicCast(type)) { - fprintbf(cpp, "ModelPartForStruct"); - } - else if (auto sequence = Slice::SequencePtr::dynamicCast(type)) { - fprintbf(cpp, "ModelPartForSequence"); - } - else if (auto dictionary = Slice::DictionaryPtr::dynamicCast(type)) { - fprintbf(cpp, "ModelPartForDictionary"); - } - else if (auto enumeration = Slice::EnumPtr::dynamicCast(type)) { - fprintbf(cpp, "ModelPartForEnum"); - } - } - - bool - Slicer::hasMetadata(const std::list & metadata) const - { - for (const auto & md : metadata) { - if (boost::algorithm::starts_with(md, "slicer:")) { - return true; - } - } - return false; - } - - void - Slicer::copyMetadata(const std::list & metadata) const - { - fprintbf(cpp, "{\n"); - for (const auto & md : metadata) { - if (boost::algorithm::starts_with(md, "slicer:")) { - fprintbf(cpp, "\t\"%s\",\n", md.c_str() + 7); - } - } - fprintbf(cpp, "};\n\n"); - } - - Slicer::Conversions - Slicer::getAllConversions(Slice::DataMemberPtr dm) - { - auto conversions = getConversions(dm->getMetaData()); - auto typec = Slice::ContainedPtr::dynamicCast(dm->type()); - if (typec) { - if (auto cd = Slice::ClassDeclPtr::dynamicCast(typec)) { - typec = cd->definition(); - } - auto typeConversions = getConversions(typec->getMetaData()); - std::copy(typeConversions.begin(), typeConversions.end(), std::back_inserter(conversions)); - } - return conversions; - } - - Slicer::Conversions - Slicer::getConversions(const std::list & dm) - { - Conversions rtn; - auto conversions = metaDataValues("slicer:conversion:", dm); - for (const auto & conversion : conversions) { - auto split = metaDataSplit(conversion); - if (split.size() < 3) { - throw std::runtime_error("conversion needs at least 3 parts type:toModelFunc:toExchangeFunc[:options]"); - } - for (auto & pi : {0, 1, 2}) { - boost::algorithm::replace_all(split[pi], ".", "::"); - } - rtn.push_back(split); - } - return rtn; - } - - unsigned int - Slicer::Components() const - { - return components; - } - - unsigned int - Slicer::Apply(const boost::filesystem::path & ice, const boost::filesystem::path & cpp) - { - return Apply(ice, cpp, {}, false); - } - - unsigned int - Slicer::Apply(const boost::filesystem::path & ice, const boost::filesystem::path & cpp, const Args & args, bool allowIcePrefix) - { - FilePtr cppfile(fopen(cpp.string(), "a"), fclose); - if (!cppfile) { - throw std::runtime_error("failed to open code file"); - } - - return Apply(ice, cppfile.get(), args, allowIcePrefix); - } - - unsigned int - Slicer::Apply(const boost::filesystem::path & ice, FILE * cpp) - { - return Apply(ice, cpp, {}, false); - } - - unsigned int - Slicer::Apply(const boost::filesystem::path & ice, FILE * cpp, const Args & args, bool allowIcePrefix) - { - std::lock_guard lock(slicePreprocessor); - Slice::PreprocessorPtr icecpp = Slice::Preprocessor::create("slicer", ice.string(), args); - FILE * cppHandle = icecpp->preprocess(false); - - if (cppHandle == NULL) { - throw std::runtime_error("preprocess failed"); - } - - Slice::UnitPtr u = Slice::Unit::createUnit(false, false, allowIcePrefix, false); - - int parseStatus = u->parse(ice.string(), cppHandle, false); - - if (!icecpp->close()) { - throw std::runtime_error("preprocess close failed"); - } - - if (parseStatus == EXIT_FAILURE) { - throw std::runtime_error("unit parse failed"); - } - - Slicer s(cpp); - u->visit(&s, false); - - u->destroy(); - - return s.Components(); - } - - Slicer::ConversionSpec::ConversionSpec(const Slicer::Args & s) : - ExchangeType(s[0]), - ConvertToModelFunc(s[1]), - ConvertToExchangeFunc(s[2]) - { - if (s.size() >= 4) { - boost::algorithm::split(Options, s[3], boost::algorithm::is_any_of(","), boost::algorithm::token_compress_off); - } - } -}; - diff --git a/slicer/slicer/parser.h b/slicer/slicer/parser.h deleted file mode 100644 index 1193664..0000000 --- a/slicer/slicer/parser.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef SLICER_PARSER_H -#define SLICER_PARSER_H - -#include -#include -#include -#include - -namespace Slicer { - typedef boost::shared_ptr FilePtr; - - class DLL_PUBLIC Slicer : public Slice::ParserVisitor { - public: - typedef std::vector Args; - class ConversionSpec { - public: - ConversionSpec(const Args &); - - std::string ExchangeType; - std::string ConvertToModelFunc; - std::string ConvertToExchangeFunc; - Args Options; - }; - typedef std::vector Conversions; - - Slicer(FILE * c); - - static unsigned int Apply(const boost::filesystem::path & ice, const boost::filesystem::path & cpp); - static unsigned int Apply(const boost::filesystem::path & ice, FILE *); - static unsigned int Apply(const boost::filesystem::path & ice, const boost::filesystem::path & cpp, const Args &, bool); - static unsigned int Apply(const boost::filesystem::path & ice, FILE *, const Args &, bool); - - unsigned int Components() const; - -#pragma GCC visibility push(hidden) - virtual bool visitUnitStart(const Slice::UnitPtr&) override; - - virtual void visitUnitEnd(const Slice::UnitPtr&) override; - - virtual bool visitModuleStart(const Slice::ModulePtr & m) override; - - virtual bool visitClassDefStart(const Slice::ClassDefPtr & c) override; - - virtual bool visitStructStart(const Slice::StructPtr&) override; - - virtual void visitEnum(const Slice::EnumPtr &) override; - - virtual void visitSequence(const Slice::SequencePtr & s) override; - - virtual void visitDictionary(const Slice::DictionaryPtr & d) override; - - virtual void visitModuleEnd(const Slice::ModulePtr & m) override; - - private: - void createNewModelPartPtrFor(const Slice::TypePtr & type) const; - - void visitComplexDataMembers(Slice::ConstructedPtr t, const Slice::DataMemberList &) const; - - void defineConversions(Slice::DataMemberPtr dm) const; - void defineRootName(const std::string & type, const std::string & name) const; - - bool hasMetadata(const std::list & metadata) const; - void copyMetadata(const std::list & metadata) const; - static Conversions getAllConversions(Slice::DataMemberPtr dm); - static Conversions getConversions(const std::list & metadata); -#pragma GCC visibility pop - - unsigned int components; - FILE * cpp; - unsigned int classNo; - }; -} - -#endif - diff --git a/slicer/test/Jamfile.jam b/slicer/test/Jamfile.jam index e679a76..b6e2834 100644 --- a/slicer/test/Jamfile.jam +++ b/slicer/test/Jamfile.jam @@ -59,6 +59,7 @@ run preprocessor.cpp adhocutil .. ../slicer//slicer + ../tool//slicer-compiler ../tool//slicer : preprocess diff --git a/slicer/test/preprocessor.cpp b/slicer/test/preprocessor.cpp index e34632b..ae4f1b7 100644 --- a/slicer/test/preprocessor.cpp +++ b/slicer/test/preprocessor.cpp @@ -1,7 +1,7 @@ #define BOOST_TEST_MODULE preprocess #include -#include +#include #include #include #include diff --git a/slicer/test/serializers.cpp b/slicer/test/serializers.cpp index 7c5f252..8f569d8 100644 --- a/slicer/test/serializers.cpp +++ b/slicer/test/serializers.cpp @@ -1,7 +1,7 @@ #define BOOST_TEST_MODULE execute_serializers #include -#include +#include #include #include #include diff --git a/slicer/tool/Jamfile.jam b/slicer/tool/Jamfile.jam index 16942a0..d34828c 100644 --- a/slicer/tool/Jamfile.jam +++ b/slicer/tool/Jamfile.jam @@ -1,8 +1,27 @@ +lib Slice ; +lib IceUtil ; lib po : : boost_program_options ; +lib adhocutil : : : : /usr/include/adhocutil ; +lib boost_system ; +lib boost_filesystem ; -exe slicer : - [ glob *.cpp ] +lib slicer-compiler : + parser.cpp : + Slice + IceUtil + boost_system + boost_filesystem + adhocutil ../slicer//slicer + .. + : : + .. + ; + +exe slicer : + slicer.cpp + : + slicer-compiler po ; diff --git a/slicer/tool/parser.cpp b/slicer/tool/parser.cpp new file mode 100644 index 0000000..6d89719 --- /dev/null +++ b/slicer/tool/parser.cpp @@ -0,0 +1,646 @@ +#include "parser.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace fs = boost::filesystem; + +std::mutex slicePreprocessor; + +namespace Slicer { + Slicer::Slicer(FILE * c) : + components(0), + cpp(c), + classNo(0) + { + } + + void + Slicer::defineConversions(Slice::DataMemberPtr dm) const + { + if (!cpp) return; + + auto type = dm->type(); + auto c = Slice::ContainedPtr::dynamicCast(dm->container()); + auto conversions = getAllConversions(dm); + for (const auto & conversion : conversions) { + if (!AdHoc::containerContains(conversion.Options, "nodeclare")) { + if (!AdHoc::containerContains(conversion.Options, "nodeclareto")) { + fprintbf(cpp, "DLL_PUBLIC %s %s(const %s &);\n", + conversion.ExchangeType, + conversion.ConvertToExchangeFunc, + Slice::typeToString(type)); + } + if (!AdHoc::containerContains(conversion.Options, "nodeclarefrom")) { + fprintbf(cpp, "DLL_PUBLIC %s %s(const %s &);\n\n", + Slice::typeToString(type), + conversion.ConvertToModelFunc, + conversion.ExchangeType); + } + } + } + if (!conversions.empty()) { + fprintbf(cpp, "template<> DLL_PUBLIC\nvoid\n"); + fprintbf(cpp, "ModelPartForConverted< %s, %s, &%s >::SetValue(ValueSourcePtr vsp)\n", + Slice::typeToString(type), + c->scoped(), + dm->scoped()); + fprintbf(cpp, "{\n"); + + for (const auto & conversion : conversions) { + fprintbf(cpp, "\tif (auto vspt = dynamic_cast *>(vsp.get())) {\n", + conversion.ExchangeType); + fprintbf(cpp, "\t\t%s tmp;\n", + conversion.ExchangeType); + fprintbf(cpp, "\t\tvspt->set(tmp);\n"); + fprintbf(cpp, "\t\tMember = %s(tmp);\n", + conversion.ConvertToModelFunc); + fprintbf(cpp, "\t\treturn;\n"); + fprintbf(cpp, "\t}\n"); + } + // Default conversion + if (!dm->hasMetaData("slicer:nodefaultconversion")) { + fprintbf(cpp, "\tif (auto vspt = dynamic_cast *>(vsp.get())) {\n", + Slice::typeToString(type)); + fprintbf(cpp, "\t\tvspt->set(Member);\n"); + fprintbf(cpp, "\t\treturn;\n"); + fprintbf(cpp, "\t}\n"); + } + // Failed to convert + fprintbf(cpp, "\tthrow NoConversionFound(\"%s\");\n", + Slice::typeToString(type)); + fprintbf(cpp, "}\n\n"); + + fprintbf(cpp, "template<> DLL_PUBLIC\nvoid\n"); + fprintbf(cpp, "ModelPartForConverted< %s, %s, &%s >::GetValue(ValueTargetPtr vtp)\n", + Slice::typeToString(type), + c->scoped(), + dm->scoped()); + fprintbf(cpp, "{\n"); + + for (const auto & conversion : conversions) { + fprintbf(cpp, "\tif (auto vtpt = dynamic_cast *>(vtp.get())) {\n", + conversion.ExchangeType); + fprintbf(cpp, "\t\tvtpt->get(%s(Member));\n", + conversion.ConvertToExchangeFunc); + fprintbf(cpp, "\t\treturn;\n"); + fprintbf(cpp, "\t}\n"); + } + // Default conversion + if (!dm->hasMetaData("slicer:nodefaultconversion")) { + fprintbf(cpp, "\tif (auto vtpt = dynamic_cast *>(vtp.get())) {\n", + Slice::typeToString(type)); + fprintbf(cpp, "\t\tvtpt->get(Member);\n"); + fprintbf(cpp, "\t\treturn;\n"); + fprintbf(cpp, "\t}\n"); + } + // Failed to convert + fprintbf(cpp, "\tthrow NoConversionFound(\"%s\");\n", + Slice::typeToString(type)); + fprintbf(cpp, "}\n\n"); + } + } + + bool + Slicer::visitUnitStart(const Slice::UnitPtr & u) + { + fs::path topLevelFile(u->topLevelFile()); + if (!cpp) return true; + + fprintbf(cpp, "// Begin Slicer code\n\n"); + fprintbf(cpp, "#include <%s>\n\n", fs::change_extension(topLevelFile.filename(), ".h").string()); + fprintbf(cpp, "#include \n\n"); + fprintbf(cpp, "namespace Slicer {\n"); + return true; + } + + void + Slicer::visitUnitEnd(const Slice::UnitPtr&) + { + if (!cpp) return; + + fprintbf(cpp, "}\n\n"); + fprintbf(cpp, "// End Slicer code\n\n"); + } + + bool + Slicer::visitModuleStart(const Slice::ModulePtr & m) + { + if (!cpp) return true; + + fprintbf(cpp, "// Begin module %s\n\n", m->name()); + for (const auto & c : m->structs()) { + for (const auto & dm : c->dataMembers()) { + defineConversions(dm); + } + } + for (const auto & c : m->classes()) { + for (const auto & dm : c->dataMembers()) { + defineConversions(dm); + } + } + return true; + } + + + void + Slicer::defineRootName(const std::string & type, const std::string & name) const + { + fprintbf(cpp, "template<> DLL_PUBLIC\n"); + fprintbf(cpp, "const std::string ModelPartForRoot< %s >::rootName(\"%s\");\n\n", + type, name); + fprintbf(cpp, "template<> DLL_PUBLIC\n"); + fprintbf(cpp, "const std::string ModelPartForRoot< IceUtil::Optional< %s > >::rootName(\"Optional%s\");\n\n", + type, name); + + fprintbf(cpp, "template class ModelPartForRoot< %s >;\n\n", type); + fprintbf(cpp, "template class ModelPartForRoot< IceUtil::Optional< %s > >;\n\n", type); + } + + bool + Slicer::visitClassDefStart(const Slice::ClassDefPtr & c) + { + if (c->isInterface()) { return false; } + if (c->hasMetaData("slicer:ignore")) { return false; } + + components += 1; + + if (!cpp) return true; + + auto decl = c->declaration(); + fprintbf(cpp, "// Class %s\n", c->name()); + visitComplexDataMembers(decl, c->allDataMembers()); + + fprintbf(cpp, "template<> DLL_PUBLIC\n"); + auto typeId = metaDataValue("slicer:typeid:", c->getMetaData()); + fprintbf(cpp, "const std::string ModelPartForClass< %s >::typeIdProperty(\"%s\");\n\n", + typeToString(decl), + typeId ? *typeId : "slicer-typeid"); + + auto name = metaDataValue("slicer:root:", c->getMetaData()); + defineRootName(typeToString(decl), name ? *name : c->name()); + + auto typeName = metaDataValue("slicer:typename:", c->getMetaData()); + fprintbf(cpp, "static void registerClass_%u() __attribute__ ((constructor(210)));\n", classNo); + fprintbf(cpp, "static void registerClass_%u()\n{\n", classNo); + fprintbf(cpp, "\tSlicer::classRefMap()->insert({ \"%s\", [](void * p){ return new ModelPartForClass< %s >(*static_cast< %s *>(p)); } });\n", + c->scoped(), + typeToString(decl), + typeToString(decl)); + if (typeName) { + fprintbf(cpp, "\tSlicer::classNameMap()->insert({ \"%s\", \"%s\" });\n", + c->scoped(), + *typeName); + } + fprintbf(cpp, "}\n\n"); + fprintbf(cpp, "static void unregisterClass_%u() __attribute__ ((destructor(210)));\n", classNo); + fprintbf(cpp, "static void unregisterClass_%u()\n{\n", classNo); + fprintbf(cpp, "\tSlicer::classRefMap()->erase(\"%s\");\n", + c->scoped()); + if (typeName) { + fprintbf(cpp, "\tSlicer::classNameMap()->left.erase(\"%s\");\n", + c->scoped()); + } + fprintbf(cpp, "}\n\n"); + + fprintbf(cpp, "template<> DLL_PUBLIC\nTypeId\nModelPartForClass< %s >::GetTypeId() const\n{\n", + typeToString(decl)); + fprintbf(cpp, "\tauto id = ModelObject->ice_id();\n"); + fprintbf(cpp, "\treturn (id == \"%s\") ? TypeId() : ModelPart::ToExchangeTypeName(id);\n}\n\n", + c->scoped()); + + fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForComplex< %s >::metadata ", + c->scoped()); + copyMetadata(c->getMetaData()); + + fprintbf(cpp, "MODELPARTFOR(::IceInternal::Handle< %s >, ModelPartForClass);\n\n", + c->scoped()); + + classNo += 1; + + return true; + } + + bool + Slicer::visitStructStart(const Slice::StructPtr & c) + { + if (c->hasMetaData("slicer:ignore")) { return false; } + + components += 1; + + if (!cpp) return true; + + fprintbf(cpp, "// Struct %s\n", c->name()); + visitComplexDataMembers(c, c->dataMembers()); + + auto name = metaDataValue("slicer:root:", c->getMetaData()); + defineRootName(c->scoped(), name ? *name : c->name()); + + fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForComplex< %s >::metadata ", + c->scoped()); + copyMetadata(c->getMetaData()); + + fprintbf(cpp, "MODELPARTFOR(%s, ModelPartForStruct);\n\n", + c->scoped()); + + return true; + } + + void + Slicer::visitComplexDataMembers(Slice::ConstructedPtr it, const Slice::DataMemberList & dataMembers) const + { + if (!cpp) return; + + fprintbf(cpp, "template<> DLL_PUBLIC\n"); + fprintbf(cpp, "const ModelPartForComplex< %s >::Hooks ", + it->scoped()); + fprintbf(cpp, "ModelPartForComplex< %s >::hooks {\n", + it->scoped()); + for (const auto & dm : dataMembers) { + auto c = Slice::ContainedPtr::dynamicCast(dm->container()); + auto t = Slice::TypePtr::dynamicCast(dm->container()); + if (!t) { + t = Slice::ClassDefPtr::dynamicCast(dm->container())->declaration(); + } + auto name = metaDataValue("slicer:name:", dm->getMetaData()); + auto conversions = getAllConversions(dm); + fprintbf(cpp, "\t\tnew "); + auto type = dm->type(); + createNewModelPartPtrFor(t); + fprintbf(cpp, "< %s >::Hook< %s", + typeToString(it), + Slice::typeToString(type, dm->optional())); + fprintbf(cpp, ", %s, &%s, ", + boost::algorithm::trim_right_copy_if(dm->container()->thisScope(), ispunct), + dm->scoped()); + if (dm->optional()) { + fprintbf(cpp, "ModelPartForOptional< "); + } + if (!conversions.empty()) { + fprintbf(cpp, "ModelPartForConverted< %s, %s, &%s >", + Slice::typeToString(type), + boost::algorithm::trim_right_copy_if(dm->container()->thisScope(), ispunct), + dm->scoped()); + } + else { + createNewModelPartPtrFor(type); + fprintbf(cpp, "< %s >", + Slice::typeToString(type)); + } + if (dm->optional()) { + fprintbf(cpp, " > "); + } + if (!hasMetadata(dm->getMetaData())) { + fprintbf(cpp, ", HookBase"); + } + fprintbf(cpp, " >(\"%s\"),\n", + name ? *name : dm->name()); + } + fprintbf(cpp, "\t};\n\n"); + + for (const auto & dm : dataMembers) { + if (!hasMetadata(dm->getMetaData())) { + continue; + } + auto c = Slice::ContainedPtr::dynamicCast(dm->container()); + auto t = Slice::TypePtr::dynamicCast(dm->container()); + if (!t) { + t = Slice::ClassDefPtr::dynamicCast(dm->container())->declaration(); + } + auto type = dm->type(); + fprintbf(cpp, "template<>\ntemplate<> DLL_PUBLIC\nconst Metadata\n"); + createNewModelPartPtrFor(t); + fprintbf(cpp, "< %s >::HookMetadata< %s", + typeToString(it), + Slice::typeToString(type, dm->optional())); + fprintbf(cpp, ", %s, &%s >::metadata ", + boost::algorithm::trim_right_copy_if(dm->container()->thisScope(), ispunct), + dm->scoped()); + copyMetadata(dm->getMetaData()); + } + } + + void + Slicer::visitEnum(const Slice::EnumPtr & e) + { + if (e->hasMetaData("slicer:ignore")) { return; } + + components += 1; + + if (!cpp) return; + + fprintbf(cpp, "// Enumeration %s\n", e->name()); + fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForEnum< %s >::metadata ", + e->scoped()); + copyMetadata(e->getMetaData()); + + fprintbf(cpp, "template<> DLL_PUBLIC\nconst ModelPartForEnum< %s >::Enumerations\nModelPartForEnum< %s >::enumerations([]() -> ModelPartForEnum< %s >::Enumerations\n", + e->scoped(), + e->scoped(), + e->scoped()); + fprintbf(cpp, "{\n\tModelPartForEnum< %s >::Enumerations e;\n", + e->scoped()); + for (const auto & ee : e->getEnumerators()) { + fprintbf(cpp, "\te.insert( { %s, \"%s\" } );\n", ee->scoped(), ee->name()); + } + fprintbf(cpp, "\treturn e;\n}());\n\n"); + + fprintbf(cpp, "template<> DLL_PUBLIC\nvoid ModelPartForEnum< %s >::SetValue(ValueSourcePtr s) {\n\ + std::string val;\n\ + s->set(val);\n\ + modelPart = lookup(val);\n\ +}\n\n", + e->scoped()); + fprintbf(cpp, "template<> DLL_PUBLIC\nvoid ModelPartForEnum< %s >::GetValue(ValueTargetPtr s) {\n\ + s->get(lookup(modelPart));\n\ +}\n\n", + e->scoped()); + + auto name = metaDataValue("slicer:root:", e->getMetaData()); + defineRootName(e->scoped(), name ? *name : e->name()); + + fprintbf(cpp, "MODELPARTFOR(%s, ModelPartForEnum);\n\n", + e->scoped()); + fprintbf(cpp, "template %s ModelPartForEnum< %s >::lookup(const std::string &);\n\n", + e->scoped(), e->scoped()); + fprintbf(cpp, "template const std::string & ModelPartForEnum< %s >::lookup(%s);\n\n", + e->scoped(), e->scoped()); + } + + void + Slicer::visitSequence(const Slice::SequencePtr & s) + { + if (s->hasMetaData("slicer:ignore")) { return; } + + components += 1; + + if (!cpp) return; + + fprintbf(cpp, "// Sequence %s\n", s->name()); + fprintbf(cpp, "template<> DLL_PUBLIC\n"); + fprintbf(cpp, "ChildRefPtr ModelPartForSequence< %s >::GetChildRef(const std::string & name, const HookFilter & flt)\n{\n", + s->scoped()); + auto iname = metaDataValue("slicer:item:", s->getMetaData()); + if (iname) { + fprintbf(cpp, "\tif (!name.empty() && name != \"%s\") { throw IncorrectElementName(); }\n", + *iname); + } + else { + fprintbf(cpp, "\t(void)name;\n"); + } + fprintbf(cpp, "\treturn GetAnonChildRef(flt);\n}\n\n"); + + fprintbf(cpp, "template<> DLL_PUBLIC\n"); + fprintbf(cpp, "ModelPartPtr\n"); + fprintbf(cpp, "ModelPartForSequence< %s >::elementModelPart(typename %s::value_type & e) const {\n", + s->scoped(), + s->scoped()); + fprintbf(cpp, "\treturn ModelPart::CreateFor(e);\n}\n\n"); + + fprintbf(cpp, "template<> DLL_PUBLIC\n"); + auto ename = metaDataValue("slicer:element:", s->getMetaData()); + fprintbf(cpp, "const std::string ModelPartForSequence< %s >::elementName(\"%s\");\n\n", + s->scoped(), + ename ? *ename : "element"); + + auto name = metaDataValue("slicer:root:", s->getMetaData()); + defineRootName(s->scoped(), name ? *name : s->name()); + + fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForSequence< %s >::metadata ", + s->scoped()); + copyMetadata(s->getMetaData()); + + fprintbf(cpp, "MODELPARTFOR(%s, ModelPartForSequence);\n\n", + s->scoped()); + } + + void + Slicer::visitDictionary(const Slice::DictionaryPtr & d) + { + if (d->hasMetaData("slicer:ignore")) { return; } + + components += 1; + + if (!cpp) return; + + fprintbf(cpp, "// Dictionary %s\n", d->name()); + auto iname = metaDataValue("slicer:item:", d->getMetaData()); + fprintbf(cpp, "template<> DLL_PUBLIC\n"); + fprintbf(cpp, "const std::string ModelPartForDictionary< %s >::pairName(\"%s\");\n\n", + d->scoped(), + iname ? *iname : "element"); + + fprintbf(cpp, "template<> DLL_PUBLIC\n"); + fprintbf(cpp, "const ModelPartForComplex< %s::value_type >::Hooks ", + d->scoped()); + fprintbf(cpp, "ModelPartForComplex< %s::value_type >::hooks {\n", + d->scoped()); + auto kname = metaDataValue("slicer:key:", d->getMetaData()); + auto vname = metaDataValue("slicer:value:", d->getMetaData()); + fprintbf(cpp, "\t\t"); + auto ktype = d->keyType(); + fprintbf(cpp, "new ModelPartForComplex< %s::value_type >::Hook< const %s, %s::value_type, &%s::value_type::first, ", + d->scoped(), + Slice::typeToString(ktype), + d->scoped(), + d->scoped()); + createNewModelPartPtrFor(ktype); + fprintbf(cpp, "< %s >, HookBase >(\"%s\"),\n\t\t", + Slice::typeToString(ktype), + kname ? *kname : "key"); + auto vtype = d->valueType(); + fprintbf(cpp, "new ModelPartForComplex< %s::value_type >::Hook< %s, %s::value_type, &%s::value_type::second, ", + d->scoped(), + Slice::typeToString(vtype), + d->scoped(), + d->scoped()); + createNewModelPartPtrFor(vtype); + fprintbf(cpp, "< %s >, HookBase >(\"%s\"),\n", + Slice::typeToString(vtype), + vname ? *vname : "value"); + fprintbf(cpp, "\t};\n"); + fprintbf(cpp, "\n"); + + auto name = metaDataValue("slicer:root:", d->getMetaData()); + defineRootName(d->scoped(), name ? *name : d->name()); + + fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForDictionary< %s >::metadata ", + d->scoped()); + copyMetadata(d->getMetaData()); + + fprintbf(cpp, "template<> DLL_PUBLIC\nconst Metadata ModelPartForComplex<%s::value_type>::metadata ", + d->scoped()); + copyMetadata(d->getMetaData()); + + fprintbf(cpp, "MODELPARTFOR(%s, ModelPartForDictionary);\n\n", + d->scoped()); + } + + void + Slicer::visitModuleEnd(const Slice::ModulePtr & m) + { + if (cpp) { + fprintbf(cpp, "// End module %s\n\n", m->name()); + } + } + + void + Slicer::createNewModelPartPtrFor(const Slice::TypePtr & type) const + { + if (auto builtin = Slice::BuiltinPtr::dynamicCast(type)) { + fprintbf(cpp, "ModelPartForSimple"); + } + else if (auto complexClass = Slice::ClassDeclPtr::dynamicCast(type)) { + fprintbf(cpp, "ModelPartForClass"); + } + else if (auto complexStruct = Slice::StructPtr::dynamicCast(type)) { + fprintbf(cpp, "ModelPartForStruct"); + } + else if (auto sequence = Slice::SequencePtr::dynamicCast(type)) { + fprintbf(cpp, "ModelPartForSequence"); + } + else if (auto dictionary = Slice::DictionaryPtr::dynamicCast(type)) { + fprintbf(cpp, "ModelPartForDictionary"); + } + else if (auto enumeration = Slice::EnumPtr::dynamicCast(type)) { + fprintbf(cpp, "ModelPartForEnum"); + } + } + + bool + Slicer::hasMetadata(const std::list & metadata) const + { + for (const auto & md : metadata) { + if (boost::algorithm::starts_with(md, "slicer:")) { + return true; + } + } + return false; + } + + void + Slicer::copyMetadata(const std::list & metadata) const + { + fprintbf(cpp, "{\n"); + for (const auto & md : metadata) { + if (boost::algorithm::starts_with(md, "slicer:")) { + fprintbf(cpp, "\t\"%s\",\n", md.c_str() + 7); + } + } + fprintbf(cpp, "};\n\n"); + } + + Slicer::Conversions + Slicer::getAllConversions(Slice::DataMemberPtr dm) + { + auto conversions = getConversions(dm->getMetaData()); + auto typec = Slice::ContainedPtr::dynamicCast(dm->type()); + if (typec) { + if (auto cd = Slice::ClassDeclPtr::dynamicCast(typec)) { + typec = cd->definition(); + } + auto typeConversions = getConversions(typec->getMetaData()); + std::copy(typeConversions.begin(), typeConversions.end(), std::back_inserter(conversions)); + } + return conversions; + } + + Slicer::Conversions + Slicer::getConversions(const std::list & dm) + { + Conversions rtn; + auto conversions = metaDataValues("slicer:conversion:", dm); + for (const auto & conversion : conversions) { + auto split = metaDataSplit(conversion); + if (split.size() < 3) { + throw std::runtime_error("conversion needs at least 3 parts type:toModelFunc:toExchangeFunc[:options]"); + } + for (auto & pi : {0, 1, 2}) { + boost::algorithm::replace_all(split[pi], ".", "::"); + } + rtn.push_back(split); + } + return rtn; + } + + unsigned int + Slicer::Components() const + { + return components; + } + + unsigned int + Slicer::Apply(const boost::filesystem::path & ice, const boost::filesystem::path & cpp) + { + return Apply(ice, cpp, {}, false); + } + + unsigned int + Slicer::Apply(const boost::filesystem::path & ice, const boost::filesystem::path & cpp, const Args & args, bool allowIcePrefix) + { + FilePtr cppfile(fopen(cpp.string(), "a"), fclose); + if (!cppfile) { + throw std::runtime_error("failed to open code file"); + } + + return Apply(ice, cppfile.get(), args, allowIcePrefix); + } + + unsigned int + Slicer::Apply(const boost::filesystem::path & ice, FILE * cpp) + { + return Apply(ice, cpp, {}, false); + } + + unsigned int + Slicer::Apply(const boost::filesystem::path & ice, FILE * cpp, const Args & args, bool allowIcePrefix) + { + std::lock_guard lock(slicePreprocessor); + Slice::PreprocessorPtr icecpp = Slice::Preprocessor::create("slicer", ice.string(), args); + FILE * cppHandle = icecpp->preprocess(false); + + if (cppHandle == NULL) { + throw std::runtime_error("preprocess failed"); + } + + Slice::UnitPtr u = Slice::Unit::createUnit(false, false, allowIcePrefix, false); + + int parseStatus = u->parse(ice.string(), cppHandle, false); + + if (!icecpp->close()) { + throw std::runtime_error("preprocess close failed"); + } + + if (parseStatus == EXIT_FAILURE) { + throw std::runtime_error("unit parse failed"); + } + + Slicer s(cpp); + u->visit(&s, false); + + u->destroy(); + + return s.Components(); + } + + Slicer::ConversionSpec::ConversionSpec(const Slicer::Args & s) : + ExchangeType(s[0]), + ConvertToModelFunc(s[1]), + ConvertToExchangeFunc(s[2]) + { + if (s.size() >= 4) { + boost::algorithm::split(Options, s[3], boost::algorithm::is_any_of(","), boost::algorithm::token_compress_off); + } + } +}; + diff --git a/slicer/tool/parser.h b/slicer/tool/parser.h new file mode 100644 index 0000000..1193664 --- /dev/null +++ b/slicer/tool/parser.h @@ -0,0 +1,75 @@ +#ifndef SLICER_PARSER_H +#define SLICER_PARSER_H + +#include +#include +#include +#include + +namespace Slicer { + typedef boost::shared_ptr FilePtr; + + class DLL_PUBLIC Slicer : public Slice::ParserVisitor { + public: + typedef std::vector Args; + class ConversionSpec { + public: + ConversionSpec(const Args &); + + std::string ExchangeType; + std::string ConvertToModelFunc; + std::string ConvertToExchangeFunc; + Args Options; + }; + typedef std::vector Conversions; + + Slicer(FILE * c); + + static unsigned int Apply(const boost::filesystem::path & ice, const boost::filesystem::path & cpp); + static unsigned int Apply(const boost::filesystem::path & ice, FILE *); + static unsigned int Apply(const boost::filesystem::path & ice, const boost::filesystem::path & cpp, const Args &, bool); + static unsigned int Apply(const boost::filesystem::path & ice, FILE *, const Args &, bool); + + unsigned int Components() const; + +#pragma GCC visibility push(hidden) + virtual bool visitUnitStart(const Slice::UnitPtr&) override; + + virtual void visitUnitEnd(const Slice::UnitPtr&) override; + + virtual bool visitModuleStart(const Slice::ModulePtr & m) override; + + virtual bool visitClassDefStart(const Slice::ClassDefPtr & c) override; + + virtual bool visitStructStart(const Slice::StructPtr&) override; + + virtual void visitEnum(const Slice::EnumPtr &) override; + + virtual void visitSequence(const Slice::SequencePtr & s) override; + + virtual void visitDictionary(const Slice::DictionaryPtr & d) override; + + virtual void visitModuleEnd(const Slice::ModulePtr & m) override; + + private: + void createNewModelPartPtrFor(const Slice::TypePtr & type) const; + + void visitComplexDataMembers(Slice::ConstructedPtr t, const Slice::DataMemberList &) const; + + void defineConversions(Slice::DataMemberPtr dm) const; + void defineRootName(const std::string & type, const std::string & name) const; + + bool hasMetadata(const std::list & metadata) const; + void copyMetadata(const std::list & metadata) const; + static Conversions getAllConversions(Slice::DataMemberPtr dm); + static Conversions getConversions(const std::list & metadata); +#pragma GCC visibility pop + + unsigned int components; + FILE * cpp; + unsigned int classNo; + }; +} + +#endif + diff --git a/slicer/tool/slicer.cpp b/slicer/tool/slicer.cpp index 632ae03..8a4e764 100644 --- a/slicer/tool/slicer.cpp +++ b/slicer/tool/slicer.cpp @@ -1,4 +1,4 @@ -#include +#include #include namespace po = boost::program_options; -- cgit v1.2.3