diff --git a/coco/gen-grammar b/coco/gen-grammar deleted file mode 100755 index ed6c115..0000000 --- a/coco/gen-grammar +++ /dev/null @@ -1,6 +0,0 @@ -COCO_EXECUTABLE=${1:-cococpp} -COCO_FRAMES_PATH=${2:-/usr/share/coco-cpp/} - -echo "Run coco generator: " -$COCO_EXECUTABLE ./xreate.ATG -frames $COCO_FRAMES_PATH - diff --git a/config/default.json b/config/default.json index 807e420..33f43d3 100644 --- a/config/default.json +++ b/config/default.json @@ -1,69 +1,70 @@ { "containers": { "id": { "implementations": "impl_fulfill_cluster", "clusters": "var_cluster", "prototypes": "proto_cluster", "linkedlist": "linkedlist" }, "impl": { "solid": "solid", "onthefly": "on_the_fly" } }, "logging": { "id": "logging" }, "function-entry": "entry", "clasp": { "bindings" : { "variable": "bind", "function": "bind_func", "scope": "bind_scope", "function_demand" : "bind_function_demand", "scope_decision": "bind_scope_decision" }, "context" : { "decisions":{ "dependent": "resolution_dependency" }, }, "nonevalue": "nonevalue", "ret": { "symbol": "retv", "tag": "ret" } }, "tests": { "template": "default", "templates": { "default": "*-", "adhocs": "Adhoc.*", "effects": "Effects.*", "basic": "Attachments.*", "ast": "AST.*", "cfa": "CFA.*", "dfa": "DFA.*", "compilation": "Compilation.functionEntry1*", "diagnostic": "Diagnostic.*", "ExpressionSerializer": "ExpressionSerializer.*", "externc": "InterfaceExternC.*", "types": "Types.*-", "vendorsAPI/clang": "ClangAPI.*", "vendorsAPI/xml2": "libxml2*", "dsl": "Interpretation.*:InterpretationExamples.*", "context": "Context.*", "containers": "Containers.*", - "loops": "Loop.*" + "loops": "Loop.*", + "modules": "Modules.*" } } } diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index 78a19cc..2f998dd 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -1,219 +1,228 @@ cmake_minimum_required(VERSION 2.8.11) project(xreate) cmake_policy(SET CMP0022 NEW) message("MODULES" ${CMAKE_MODULE_PATH}) # LLVM #====================== FIND_PACKAGE (LLVM REQUIRED) set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR}) message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS}) message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS}) message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}") add_definitions(${LLVM_DEFINITIONS}) message("LLVM DEFS: " ${LLVM_DEFINITIONS}) llvm_map_components_to_libnames(LLVM_LIBS core nativecodegen native executionengine mcjit support option) message("LLVM LIBS: " ${LLVM_LIBS}) # CLANG #====================== set(CLANG_LIBS clangCodeGen clangASTMatchers clangQuery clangTooling clangFrontend clangSerialization clangDriver clangParse clangSema clangAnalysis clangAST clangEdit clangLex clangBasic ) # POTASSCO #====================== set(POTASSCO_PATH "/opt/potassco/clingo" CACHE PATH "Path to potassco sources") set(POTASSCO_INCLUDE_PATH ${POTASSCO_PATH}/libgringo ${POTASSCO_PATH}/libclasp ${POTASSCO_PATH}/libclingo ${POTASSCO_PATH}/libprogram_opts ${POTASSCO_PATH}/liblp ) INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH}) set(LIBCLASP_LIBS clingo clasp gringo program_opts reify lp ) message("CLASP LIBS: " ${LIBCLASP_LIBS}) # OTHER DEPENDENCIES #=========================== set(JEAYESON_INCLUDE_PATH ${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/ ) INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH}) # COCO #=========================== set(COCO_EXECUTABLE "" CACHE PATH "Path to coco executable") set(COCO_FRAMES_PATH "" CACHE PATH "Path to coco frames") -set(COCO_GRAMMAR_PATH ${CMAKE_HOME_DIRECTORY}/../coco/) -set(COCO_SOURCE_FILES - ${COCO_GRAMMAR_PATH}/Parser.cpp - ${COCO_GRAMMAR_PATH}/Scanner.cpp) +set(COCO_GRAMMAR_PATH ${CMAKE_HOME_DIRECTORY}/../grammar/) +set(COCO_SOURCE_FILES_MAIN + ${COCO_GRAMMAR_PATH}/main/Parser.cpp + ${COCO_GRAMMAR_PATH}/main/Scanner.cpp +) + +set(COCO_SOURCE_FILES_MODULES + ${COCO_GRAMMAR_PATH}/modules/Parser.cpp + ${COCO_GRAMMAR_PATH}/modules/Scanner.cpp +) + +set(COCO_SOURCE_FILES ${COCO_SOURCE_FILES_MODULES} ${COCO_SOURCE_FILES_MAIN}) + INCLUDE_DIRECTORIES(${COCO_GRAMMAR_PATH}) -add_custom_command(OUTPUT ${COCO_SOURCE_FILES} - COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH} +add_custom_command(OUTPUT ${COCO_SOURCE_FILES_MAIN} + COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar main ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH} WORKING_DIRECTORY ${COCO_GRAMMAR_PATH} - MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/xreate.ATG + MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/xreate.ATG ) + +add_custom_command(OUTPUT ${COCO_SOURCE_FILES_MODULES} + COMMAND ${COCO_GRAMMAR_PATH}/gen-grammar modules ${COCO_EXECUTABLE} ${COCO_FRAMES_PATH} + WORKING_DIRECTORY ${COCO_GRAMMAR_PATH} + MAIN_DEPENDENCY ${COCO_GRAMMAR_PATH}/modules.ATG +) + message(STATUS "COCO GRAMMAR BUILD STATUS:" ${COCO_OUTPUT}) # XREATE #====================== set(SOURCE_FILES + modules.cpp + ast.cpp + xreatemanager.cpp + misc/xreatemanager-decorators.cpp compilation/pointerarithmetic.cpp compilation/transformations.cpp compilation/transformersaturation.cpp pass/compilepass.cpp pass/dfapass.cpp analysis/dfagraph.cpp - pass/versionspass.cpp compilation/targetinterpretation.cpp - attachments.cpp - ast.cpp - - ExternLayer.cpp - - analysis/cfagraph.cpp - - analysis/aux.cpp - compilation/containers.cpp - compilation/advanced.cpp - - clasplayer.cpp - compilation/latecontextcompiler2.cpp - query/context.cpp - - llvmlayer.cpp - utils.cpp - passmanager-bare.cpp - passmanager-full.cpp - pass/abstractpass.cpp - - pass/cfapass.cpp - pass/adhocpass.cpp - contextrule.cpp - query/containers.cpp - pass/interpretationpass.cpp - analysis/DominatorsTreeAnalysisProvider.cpp - serialization/expressionserializer.cpp + ExternLayer.cpp + analysis/cfagraph.cpp + analysis/aux.cpp + compilation/containers.cpp + compilation/advanced.cpp + clasplayer.cpp + compilation/latecontextcompiler2.cpp + query/context.cpp + llvmlayer.cpp + utils.cpp + pass/abstractpass.cpp + pass/cfapass.cpp + pass/adhocpass.cpp + contextrule.cpp + query/containers.cpp + pass/interpretationpass.cpp + analysis/DominatorsTreeAnalysisProvider.cpp + misc/serialization/expressionserializer.cpp ) set(XREATE_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/ ) INCLUDE_DIRECTORIES(${XREATE_INCLUDE_DIRS}) set(XREATE_PRIVATE_INCLUDE_DIRS ${XREATE_INCLUDE_DIRS} ${COCO_GRAMMAR_PATH} ${JEAYESON_INCLUDE_PATH} ${LLVM_INCLUDE_DIRS} ${POTASSCO_INCLUDE_PATH} ) add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${COCO_SOURCE_FILES}) target_link_libraries(${PROJECT_NAME}) target_include_directories(${PROJECT_NAME} INTERFACE ${XREATE_INCLUDE_DIRS} ${COCO_GRAMMAR_PATH} ${JEAYESON_INCLUDE_PATH} ${LLVM_INCLUDE_DIRS} ${POTASSCO_INCLUDE_PATH} ) get_directory_property(DEFINITIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_DEFINITIONS) message("definitions all: " ${DEFINITIONS_ALL}) target_compile_definitions(${PROJECT_NAME} INTERFACE ${DEFINITIONS_ALL}) get_directory_property(COMPILATION_OPTIONS_ALL DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMPILE_OPTIONS) message("compilations all: " ${COMPILATION_OPTIONS_ALL}) target_compile_options(${PROJECT_NAME} INTERFACE ${COMPILATION_OPTIONS_ALL}) SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY - INTERFACE_LINK_LIBRARIES ${LIBCLASP_LIBS} ${CLANG_LIBS} ${LLVM_LIBS} tbb + INTERFACE_LINK_LIBRARIES ${LIBCLASP_LIBS} ${CLANG_LIBS} ${LLVM_LIBS} tbb boost_system boost_filesystem ) #${CLANG_LIBS} #set (LINK_INTERFACE_LIBRARIES "") # FUNCTION(PREPEND var prefix) # SET(listVar "") # FOREACH(f ${ARGN}) # LIST(APPEND listVar "${prefix}/${f}") # ENDFOREACH(f) # SET(${var} "${listVar}" PARENT_SCOPE) # ENDFUNCTION(PREPEND) #set(COTIRE_UNITY_SOURCE_MAXIMUM_NUMBER_OF_INCLUDES "-j4") #cotire(xreate) # MACRO (ADD_PCH_RULE _header_filename _src_list) # SET(_gch_filename "${_header_filename}.gch") # LIST(APPEND ${_src_list} ${_gch_filename}) # SET (_args ${CMAKE_CXX_FLAGS}) # LIST(APPEND _args -c ${_header_filename} -o ${_gch_filename}) # GET_DIRECTORY_PROPERTY(DIRINC INCLUDE_DIRECTORIES) # foreach (_inc ${DIRINC}) # LIST(APPEND _args "-I" ${_inc}) # endforeach(_inc ${DIRINC}) # SEPARATE_ARGUMENTS(_args) # add_custom_command(OUTPUT ${_gch_filename} # COMMAND rm -f ${_gch_filename} # COMMAND ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1} ${_args} # DEPENDS ${_header_filename}) # ENDMACRO(ADD_PCH_RULE _header_filename _src_list) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/ast.h SOURCE_FILES) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/llvmlayer.h SOURCE_FILES) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/clasplayer.h SOURCE_FILES) # ADD_PCH_RULE (${CMAKE_HOME_DIRECTORY}/src/pass/abstractpass.h SOURCE_FILES) diff --git a/cpp/src/ast.cpp b/cpp/src/ast.cpp index 6a6cccf..f50b3d3 100644 --- a/cpp/src/ast.cpp +++ b/cpp/src/ast.cpp @@ -1,915 +1,925 @@ #include "ast.h" #include "ExternLayer.h" #include #include namespace std{ std::size_t hash::operator()(xreate::ScopedSymbol const& s) const {return s.id ^ (s.version << 2);} bool equal_to::operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const { return __x.id == __y.id && __x.version == __y.version; } } using namespace std; namespace xreate { Atom::Atom(const std::wstring& value) { __value = wstring_to_utf8(value); } Atom::Atom(std::string && name) : __value(name) {} const std::string& Atom::get() const { return __value; } Atom::Atom(wchar_t* value) { //DEBT reconsider number literal recognition __value = wcstol(value, 0, 10); } Atom::Atom(int value) : __value(value) { } double Atom::get()const { return __value; } Atom::Atom(const std::wstring& value) { assert(value.size() >=2); __value = wstring_to_utf8(value.substr(1, value.size() -2)); } const std::string& Atom::get() const { return __value; } class ExpressionHints { public: static bool isStringValueValid(const Expression& e) { switch (e.__state) { case Expression::INVALID: assert(false); case Expression::IDENT: case Expression::STRING: return true; case Expression::NUMBER: case Expression::BINDING: case Expression::VARIANT: return false; case Expression::COMPOUND: { switch (e.op) { case Operator::CALL: return true; default: return false; } } } return false; } static bool isDoubleValueValid(const Expression& e) { switch (e.__state) { case Expression::NUMBER: case Expression::VARIANT: return true; case Expression::INVALID: assert(false); case Expression::IDENT: case Expression::STRING: case Expression::COMPOUND: case Expression::BINDING: return false; } return false; } }; class TypesResolver { private: const AST* ast; std::map scope; std::map signatures; ExpandedType expandType(const TypeAnnotation &t, const std::vector &args = std::vector()) { return TypesResolver(ast, scope, signatures)(t, args); } std::vector expandOperands(const std::vector& operands) { std::vector pack; pack.reserve(operands.size()); std::transform(operands.begin(), operands.end(), std::inserter(pack, pack.end()), [this](const TypeAnnotation & t) { return expandType(t); }); return pack; } public: TypesResolver(const AST* root, const std::map& scopeOuter = std::map(), std::map signaturesOuter = std::map()) : ast(root), scope(scopeOuter), signatures(signaturesOuter) { } ExpandedType operator()(const TypeAnnotation &t, const std::vector &args = std::vector()) { //assert(args.size() == t.bindings.size()); // invalid number of arguments for (size_t i = 0; i < args.size(); ++i) { scope[t.bindings.at(i)] = args.at(i); } switch (t.__operator) { case TypeOperator::ARRAY: { assert(t.__operands.size() == 1); Expanded elTy = expandType(t.__operands.at(0)); return ExpandedType(TypeAnnotation(tag_array, elTy, 0)); } case TypeOperator::STRUCT: { assert(t.__operands.size()); std::vector&& pack = expandOperands(t.__operands); auto tnew = TypeAnnotation(TypeOperator::STRUCT, move(pack)); tnew.fields = t.fields; return ExpandedType(move(tnew)); }; case TypeOperator::CALL: { std::string alias = t.__valueCustom; //find in local scope: TypeAnnotation ty; if (scope.count(alias)) { ty = scope.at(alias); } else if (ast->__indexTypeAliases.count(alias)) { ty = ast->__indexTypeAliases.at(alias); } else { assert(false && "Undefined or external type"); } std::vector&& operands = expandOperands(t.__operands); TypeAnnotation signature(TypeOperator::CALL, move(operands)); signature.__valueCustom = alias; if (signatures.count(signature)) { auto link = TypeAnnotation(TypeOperator::LINK,{}); link.conjuctionId = signatures.at(signature); return ExpandedType(move(link)); } int cid = signatures.size(); signatures[signature] = cid; TypeAnnotation tyResult = expandType(ty, operands); tyResult.conjuctionId = cid; return ExpandedType(move(tyResult)); }; case TypeOperator::CUSTOM: { std::string alias = t.__valueCustom; /* if (signatures.count(alias)) { return ExpandedType(TypeAnnotation(TypeOperator::LINK, {t})); } signatures[alias].emplace(t); */ //find in local scope: if (scope.count(alias)) { return expandType(scope.at(alias)); } // find in general scope: if (ast->__indexTypeAliases.count(alias)) { return expandType(ast->__indexTypeAliases.at(t.__valueCustom)); } //if type is unknown keep it as is. return ExpandedType(TypeAnnotation(t)); }; case TypeOperator::ACCESS: { std::string alias = t.__valueCustom; ExpandedType tyAlias = ExpandedType(TypeAnnotation()); //find in local scope: if (scope.count(alias)) { tyAlias = expandType(scope.at(alias)); //find in global scope: } else if ((ast->__indexTypeAliases.count(alias))) { tyAlias = expandType(ast->__indexTypeAliases.at(alias)); } else { assert(false && "Undefined or external type"); } assert(tyAlias->__operator == TypeOperator::STRUCT); for (const string& field : t.fields) { auto fieldIt = std::find(tyAlias->fields.begin(), tyAlias->fields.end(), field); assert(fieldIt != tyAlias->fields.end() && "unknown field"); int fieldId = fieldIt - tyAlias->fields.begin(); tyAlias = expandType(tyAlias->__operands.at(fieldId)); } return tyAlias; } case TypeOperator::TUPLE: { assert(t.__operands.size()); std::vector pack; pack.reserve(t.__operands.size()); std::transform(t.__operands.begin(), t.__operands.end(), std::inserter(pack, pack.end()), [this](const TypeAnnotation & t) { return expandType(t); }); return ExpandedType(TypeAnnotation(TypeOperator::TUPLE, move(pack))); } case TypeOperator::VARIANT: { return ExpandedType(TypeAnnotation(t)); } case TypeOperator::NONE: { return ExpandedType(TypeAnnotation(t)); } default: assert(false); } assert(false); return ExpandedType(TypeAnnotation()); } }; TypeAnnotation::TypeAnnotation() : __operator(TypeOperator::NONE), __value(TypePrimitive::Invalid) {} TypeAnnotation::TypeAnnotation(TypePrimitive typ) : __value(typ) { } TypeAnnotation::TypeAnnotation(TypeOperator op, std::initializer_list operands) : __operator(op), __operands(operands) { } TypeAnnotation::TypeAnnotation(TypeOperator op, std::vector&& operands) : __operator(op), __operands(operands) { } TypeAnnotation::TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size) : TypeAnnotation(TypeOperator::ARRAY,{typ}) { __size = size; } bool TypeAnnotation::isValid() const{ return !(__value == TypePrimitive::Invalid && __operator == TypeOperator::NONE); } bool TypeAnnotation::operator<(const TypeAnnotation& t) const { if (__operator != t.__operator) return __operator < t.__operator; if (__operator == TypeOperator::NONE) return __value < t.__value; if (__operator == TypeOperator::CALL || __operator == TypeOperator::CUSTOM || __operator == TypeOperator::ACCESS) { if (__valueCustom != t.__valueCustom) return __valueCustom < t.__valueCustom; } return __operands < t.__operands; } /* TypeAnnotation (struct_tag, std::initializer_list) {} */ void TypeAnnotation::addBindings(std::vector>&& params) { bindings.reserve(bindings.size() + params.size()); std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()), [](const Atom& ident) { return ident.get(); }); } void TypeAnnotation::addFields(std::vector>&& listFields) { fields.reserve(fields.size() + listFields.size()); std::transform(listFields.begin(), listFields.end(), std::inserter(fields, fields.end()), [](const Atom& ident) { return ident.get(); }); } unsigned int Expression::nextVacantId = 0; Expression::Expression(const Atom& number) : Expression() { __state=NUMBER; op=Operator::NONE; __valueD=number.get(); } Expression::Expression(const Atom& a) : Expression(){ __state=STRING; op=Operator::NONE; __valueS=a.get(); } Expression::Expression(const Atom &ident) : Expression() { __state=IDENT; op=Operator::NONE; __valueS=ident.get(); } Expression::Expression(const Operator &oprt, std::initializer_list params) : Expression() { __state=COMPOUND; op=oprt; if (op == Operator::CALL) { assert(params.size() > 0); Expression arg = *params.begin(); assert(arg.__state == Expression::IDENT); __valueS = std::move(arg.__valueS); operands.insert(operands.end(), params.begin() + 1, params.end()); return; } operands.insert(operands.end(), params.begin(), params.end()); } void Expression::setOp(Operator oprt) { op = oprt; switch (op) { case Operator::NONE: __state = INVALID; break; default: __state = COMPOUND; break; } } void Expression::addArg(Expression &&arg) { operands.push_back(arg); } void Expression::addTags(const std::list tags) const{ std::transform(tags.begin(), tags.end(), std::inserter(this->tags, this->tags.end()), [](const Expression& tag){ return make_pair(tag.getValueString(), tag); }); } void Expression::addBindings(std::initializer_list> params) { addBindings(params.begin(), params.end()); } void Expression::bindType(TypeAnnotation t) { type = move(t); } void Expression::addBlock(ManagedScpPtr scope) { blocks.push_back(scope.operator->()); } const std::vector& Expression::getOperands() const { return operands; } double Expression::getValueDouble() const { return __valueD; } const std::string& Expression::getValueString() const { return __valueS; } void Expression::setValue(const Atom&& v) { __valueS = v.get(); } void Expression::setValueDouble(double value) { __valueD = value; } bool Expression::isValid() const { return (__state != INVALID); } bool Expression::isDefined() const { return (__state != BINDING); } Expression::Expression() : __state(INVALID), op(Operator::NONE), id(nextVacantId++) { } - AST::AST() { - Attachments::init(); - Attachments::init(); - } +namespace details { namespace incomplete { +AST::AST() { + Attachments::init(); + Attachments::init(); +} - void - AST::addInterfaceData(const ASTInterface& interface, Expression&& data) { - __interfacesData.emplace(interface, move(data)); - } +void +AST::addInterfaceData(const ASTInterface& interface, Expression&& data) { + __interfacesData.emplace(interface, move(data)); +} - void - AST::addDFAData(Expression &&data) { - __dfadata.push_back(data); - } +void +AST::addDFAData(Expression &&data) { + __dfadata.push_back(data); +} - void - AST::addExternData(ExternData &&data) { - __externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end()); - } +void +AST::addExternData(ExternData &&data) { + __externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end()); +} - void - AST::add(Function* f) { - __functions.push_back(f); - __indexFunctions.emplace(f->getName(), __functions.size() - 1); - } +void +AST::add(Function* f) { + __functions.push_back(f); + __indexFunctions.emplace(f->getName(), __functions.size() - 1); +} - void - AST::add(MetaRuleAbstract *r) { - __rules.push_back(r); - } +void +AST::add(MetaRuleAbstract *r) { + __rules.push_back(r); +} - void - AST::add(TypeAnnotation t, Atom alias) { - if (t.__operator == TypeOperator::VARIANT) { - for (int i = 0, size = t.fields.size(); i < size; ++i) { - __dictVariants.emplace(t.fields[i], make_pair(t, i)); - } +void +AST::add(TypeAnnotation t, Atom alias) { + if (t.__operator == TypeOperator::VARIANT) { + for (int i = 0, size = t.fields.size(); i < size; ++i) { + __dictVariants.emplace(t.fields[i], make_pair(t, i)); } - - __indexTypeAliases.emplace(alias.get(), move(t)); } - ManagedScpPtr - AST::add(CodeScope* scope) { - this->__scopes.push_back(scope); - return ManagedScpPtr(this->__scopes.size() - 1, &this->__scopes); - } + __indexTypeAliases.emplace(alias.get(), move(t)); +} + +ManagedScpPtr +AST::add(CodeScope* scope) { + this->__scopes.push_back(scope); + return ManagedScpPtr(this->__scopes.size() - 1, &this->__scopes); +} - std::string - AST::getModuleName() { - const std::string name = "moduleTest"; +std::string +AST::getModuleName() { + const std::string name = "moduleTest"; - return name; + return name; +} + +ManagedPtr +AST::findFunction(const std::string& name) { + int count = __indexFunctions.count(name); + if (!count) { + return ManagedFnPtr::Invalid(); } - ManagedPtr - AST::findFunction(const std::string& name) { - int count = __indexFunctions.count(name); - if (!count) { - return ManagedFnPtr::Invalid(); - } + assert(count == 1); - assert(count == 1); + auto range = __indexFunctions.equal_range(name); + return ManagedPtr(range.first->second, &this->__functions); +} - auto range = __indexFunctions.equal_range(name); - return ManagedPtr(range.first->second, &this->__functions); +std::list +AST::getAllFunctions() const { + const size_t size = __functions.size(); + + std::list result; + for (size_t i = 0; i < size; ++i) { + result.push_back(ManagedFnPtr(i, &this->__functions)); } - std::list - AST::getAllFunctions() const { - const size_t size = __functions.size(); + return result; +} - std::list result; - for (size_t i = 0; i < size; ++i) { - result.push_back(ManagedFnPtr(i, &this->__functions)); - } +//TASK select default specializations - return result; - } +std::list +AST::getFunctionVariants(const std::string& name) const { + auto functions = __indexFunctions.equal_range(name); - //TASK select default specializations + std::list result; + std::transform(functions.first, functions.second, inserter(result, result.end()), + [this](auto f) { + return ManagedFnPtr(f.second, &this->__functions); + }); - std::list - AST::getFunctionVariants(const std::string& name) const { - auto functions = __indexFunctions.equal_range(name); + return result; +} - std::list result; - std::transform(functions.first, functions.second, inserter(result, result.end()), - [this](auto f) { - return ManagedFnPtr(f.second, &this->__functions); - }); +template<> +ManagedPtr +AST::begin() { + return ManagedPtr(0, &this->__functions); +} - return result; - } +template<> +ManagedPtr +AST::begin() { + return ManagedPtr(0, &this->__scopes); +} - template<> - ManagedPtr - AST::begin() { - return ManagedPtr(0, &this->__functions); - } +template<> +ManagedPtr +AST::begin() { + return ManagedPtr(0, &this->__rules); +} - template<> - ManagedPtr - AST::begin() { - return ManagedPtr(0, &this->__scopes); - } +bool +AST::recognizeVariantIdentifier(Expression& identifier) { + assert(identifier.__state == Expression::IDENT); - template<> - ManagedPtr - AST::begin() { - return ManagedPtr(0, &this->__rules); + std::string variant = identifier.getValueString(); + if (!__dictVariants.count(variant)) { + return false; } - Expanded - AST::expandType(const TypeAnnotation &t) const { - return TypesResolver(this)(t); - } + auto record = __dictVariants.at(variant); + const TypeAnnotation& typ = record.first; - Expanded - AST::findType(const std::string& name) { - // find in general scope: - if (__indexTypeAliases.count(name)) - return expandType(__indexTypeAliases.at(name)); + identifier.__state = Expression::VARIANT; + identifier.setValueDouble(record.second); + identifier.type = typ; - //if type is unknown keep it as is. - TypeAnnotation t(TypeOperator::CUSTOM,{}); - t.__valueCustom = name; - return ExpandedType(move(t)); - } + return true; +} - bool - AST::recognizeVariantIdentifier(Expression& identifier) { - assert(identifier.__state == Expression::IDENT); +void +AST::postponeIdentifier(CodeScope* scope, const Expression& id) { + bucketUnrecognizedIdentifiers.emplace(scope, id); +} - std::string variant = identifier.getValueString(); - if (!__dictVariants.count(variant)) { - return false; +void +AST::recognizePostponedIdentifiers() { + for(const auto& identifier: bucketUnrecognizedIdentifiers){ + if (!identifier.first->recognizeIdentifier(identifier.second)){ + //exception: Ident not found + std::cout << "Unknown symbol: "<< identifier.second.getValueString() << std::endl; + assert(false && "Symbol not found"); } + } +} - auto record = __dictVariants.at(variant); - const TypeAnnotation& typ = record.first; +xreate::AST* +AST::finalize() { + //all finalization steps: + recognizePostponedIdentifiers(); - identifier.__state = Expression::VARIANT; - identifier.setValueDouble(record.second); - identifier.type = typ; + return reinterpret_cast(this); +} +}} //namespace details::incomplete + +Expanded +AST::findType(const std::string& name) { + // find in general scope: + if (__indexTypeAliases.count(name)) + return expandType(__indexTypeAliases.at(name)); + + //if type is unknown keep it as is. + TypeAnnotation t(TypeOperator::CUSTOM,{}); + t.__valueCustom = name; + return ExpandedType(move(t)); +} - return true; - } +Expanded +AST::expandType(const TypeAnnotation &t) const { + return TypesResolver(this)(t); +} Function::Function(const Atom& name) : __entry(new CodeScope(0)) { __name = name.get(); } void Function::addTag(Expression&& tag, const TagModifier mod) { string name = tag.getValueString(); __tags.emplace(move(name), move(tag)); } const std::map& Function::getTags() const { return __tags; } CodeScope* Function::getEntryScope() const { return __entry; } void Function::addBinding(Atom && name, Expression&& argument) { __entry->addBinding(move(name), move(argument)); } const std::string& Function::getName() const { return __name; } ScopedSymbol CodeScope::registerIdentifier(const Expression& identifier) { VariableVersion version = Attachments::get(identifier, VERSION_NONE); auto result = __identifiers.emplace(identifier.getValueString(), __vCounter); if (result.second){ ++__vCounter; return {__vCounter-1, version}; } return {result.first->second, version}; } bool CodeScope::recognizeIdentifier(const Expression& identifier) const{ VariableVersion version = Attachments::get(identifier, VERSION_NONE); const std::string& name = identifier.getValueString(); //search identifier in the current block if (__identifiers.count(name)){ VNameId id = __identifiers.at(name); Symbol s; s.identifier = ScopedSymbol{id, version}; s.scope = const_cast(this); Attachments::put(identifier, s); return true; } //search in the parent scope if (__parent) { return __parent->recognizeIdentifier(identifier); } return false; } ScopedSymbol CodeScope::getSymbol(const std::string& alias){ assert(__identifiers.count(alias)); VNameId id = __identifiers.at(alias); return {id, VERSION_NONE}; } - void - AST::postponeIdentifier(CodeScope* scope, const Expression& id) { - binUnrecognizedIdentifiers.emplace(scope, id); - } - - void - AST::recognizePostponedIdentifiers() { - for(const auto& identifier: binUnrecognizedIdentifiers){ - if (!identifier.first->recognizeIdentifier(identifier.second)){ - //exception: Ident not found - std::cout << "Unknown symbol: "<< identifier.second.getValueString() << std::endl; - assert(false && "Symbol not found"); - } - } - } - void CodeScope::addBinding(Expression&& var, Expression&& argument) { argument.__state = Expression::BINDING; __bindings.push_back(var.getValueString()); ScopedSymbol binding = registerIdentifier(var); __declarations[binding] = move(argument); } void CodeScope::addDeclaration(Expression&& var, Expression&& body) { ScopedSymbol s = registerIdentifier(var); __declarations[s] = move(body); } CodeScope::CodeScope(CodeScope* parent) : __parent(parent) { } CodeScope::~CodeScope() { } void CodeScope::setBody(const Expression &body) { __declarations[ScopedSymbol::RetSymbol] = body; } Expression& CodeScope::getBody() { return __declarations[ScopedSymbol::RetSymbol]; } const Expression& CodeScope::getDeclaration(const Symbol& symbol) { CodeScope* self = symbol.scope; return self->getDeclaration(symbol.identifier); } const Expression& CodeScope::getDeclaration(const ScopedSymbol& symbol){ assert(__declarations.count(symbol) && "Symbol's declaration not found"); return __declarations.at(symbol); } void RuleArguments::add(const Atom &arg, DomainAnnotation typ) { emplace_back(arg.get(), typ); } void RuleGuards::add(Expression&& e) { push_back(e); } MetaRuleAbstract:: MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards) : __args(std::move(args)), __guards(std::move(guards)) { } MetaRuleAbstract::~MetaRuleAbstract() { } RuleWarning:: RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom&& message) : MetaRuleAbstract(std::move(args), std::move(guards)), __message(message.get()), __condition(condition) { } RuleWarning::~RuleWarning() { } void RuleWarning::compile(ClaspLayer& layer) { //TODO restore addRuleWarning //layer.addRuleWarning(*this); } bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2) { return (s1.id < s2.id) || (s1.id==s2.id && s1.version < s2.version); } bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2) { return (s1.id == s2.id) && (s1.version == s2.version); } bool operator<(const Symbol& s1, const Symbol& s2) { return (s1.scope < s2.scope) || (s1.scope == s2.scope && s1.identifier < s2.identifier); } bool operator==(const Symbol& s1, const Symbol& s2) { return (s1.scope == s2.scope) && (s1.identifier == s2.identifier); } bool operator<(const Expression&a, const Expression&b) { if (a.__state != b.__state) return a.__state < b.__state; assert(a.__state != Expression::INVALID); switch (a.__state) { case Expression::IDENT: case Expression::STRING: case Expression::VARIANT: return a.getValueString() < b.getValueString(); case Expression::NUMBER: return a.getValueDouble() < b.getValueDouble(); case Expression::COMPOUND: { assert(a.blocks.size() == 0); assert(b.blocks.size() == 0); if (a.op != b.op){ return a.op < b.op; } bool flagAValid = ExpressionHints::isStringValueValid(a); bool flagBValid = ExpressionHints::isStringValueValid(b); if (flagAValid != flagBValid) { return flagAValid < flagBValid; } if (flagAValid){ if (a.getValueString() != b.getValueString()) { return a.getValueString() < b.getValueString(); } } flagAValid = ExpressionHints::isDoubleValueValid(a); flagBValid = ExpressionHints::isDoubleValueValid(b); if (flagAValid != flagBValid) { return flagAValid < flagBValid; } if (flagAValid){ if (a.getValueDouble() != b.getValueDouble()) { return a.getValueDouble() < b.getValueDouble(); } } if (a.operands.size() != b.operands.size()) { return (a.operands.size() < b.operands.size()); } for (size_t i = 0; i < a.operands.size(); ++i) { bool result = a.operands[i] < b.operands[i]; if (result) return true; } return false; } case Expression::BINDING: case Expression::INVALID: assert(false); } return false; } bool Expression::operator==(const Expression& other) const { if (this->__state != other.__state) return false; if (ExpressionHints::isStringValueValid(*this)) { if (this->__valueS != other.__valueS) return false; } if (ExpressionHints::isDoubleValueValid(*this)) { if (this->__valueD != other.__valueD) return false; } if (this->__state != Expression::COMPOUND) { return true; } if (this->op != other.op) { return false; } if (this->operands.size() != other.operands.size()) { return false; } for (size_t i = 0; ioperands.size(); ++i) { if (!(this->operands[i] == other.operands[i])) return false; } assert(!this->blocks.size()); assert(!other.blocks.size()); return true; } const ScopedSymbol ScopedSymbol::RetSymbol = ScopedSymbol{0, VERSION_NONE}; } diff --git a/cpp/src/ast.h b/cpp/src/ast.h index 8c24e48..87dbecc 100644 --- a/cpp/src/ast.h +++ b/cpp/src/ast.h @@ -1,556 +1,562 @@ #ifndef AST_H #define AST_H #include "attachments.h" #include #include #include #include #include #include #include #include "utils.h" #include namespace llvm { class Value; } namespace xreate { struct String_t { }; struct Identifier_t { }; struct Number_t { }; struct Type_t { }; template class Atom { }; //DEBT hold for all atoms/identifiers Parser::Token data, like line:col position template<> class Atom { public: Atom(const std::wstring& value); Atom(std::string && name); const std::string& get() const; private: std::string __value; }; template<> class Atom { public: Atom(wchar_t* value); Atom(int value); double get()const; private: double __value; }; template<> class Atom { public: Atom(const std::wstring& value); const std::string& get() const; private: std::string __value; }; enum class TypePrimitive { Invalid, Bool, I8, I32, I64, Num, Int, Float, String }; enum class TypeOperator { NONE, CALL, CUSTOM, VARIANT, ARRAY, TUPLE, STRUCT, ACCESS, LINK }; struct llvm_array_tag { }; struct struct_tag { }; const llvm_array_tag tag_array = llvm_array_tag(); const struct_tag tag_struct = struct_tag(); class TypeAnnotation { public: TypeAnnotation(); TypeAnnotation(const Atom& typ); TypeAnnotation(TypePrimitive typ); TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size); TypeAnnotation(TypeOperator op, std::initializer_list operands); TypeAnnotation(TypeOperator op, std::vector&& operands); void addBindings(std::vector>&& params); void addFields(std::vector>&& listFields); bool operator<(const TypeAnnotation& t) const; // TypeAnnotation (struct_tag, std::initializer_list); bool isValid() const; TypeOperator __operator = TypeOperator::NONE; std::vector __operands; TypePrimitive __value; std::string __valueCustom; int conjuctionId = -1; //conjunction point id (relevant for recursive types) uint64_t __size = 0; std::vector fields; std::vector bindings; private: }; enum class Operator { ADD, SUB, MUL, DIV, EQU, NE, NEG, LSS, LSE, GTR, GTE, LIST, LIST_RANGE, LIST_NAMED, CALL, CALL_INTRINSIC, NONE, IMPL/* implication */, MAP, FOLD, FOLD_INF, LOOP_CONTEXT, INDEX, IF, SWITCH, SWITCH_ADHOC, CASE, CASE_DEFAULT, LOGIC_AND, ADHOC, CONTEXT_RULE }; class Function; class AST; class CodeScope; class MetaRuleAbstract; template struct ManagedPtr { static ManagedPtr Invalid() { return ManagedPtr(); } ManagedPtr() : __storage(0) { } ManagedPtr(unsigned int id, const std::vector* storage) : __id(id), __storage(storage) { } Target& operator*() const { assert(isValid() && "Invalid Ptr"); return *__storage->at(__id); } void operator=(const ManagedPtr& other) { __id = other.__id; __storage = other.__storage; } bool operator==(const ManagedPtr& other) { return isValid() && (__id == other.__id); } Target* operator->() const noexcept { assert(isValid() && "Invalid Ptr"); return __storage->at(__id); } inline bool isValid() const { return (__storage) && (0 <= __id) && (__id < __storage->size()); } inline operator bool() const { return isValid(); } ManagedPtr& operator++() { ++__id; return *this; } inline unsigned int id() const { return __id; } private: unsigned int __id = 0; const std::vector * __storage = 0; }; typedef ManagedPtr ManagedFnPtr; typedef ManagedPtr ManagedScpPtr; typedef ManagedPtr ManagedRulePtr; const ManagedScpPtr NO_SCOPE = ManagedScpPtr(UINT_MAX, 0); //To update ExpressionHints in case of any changes struct Expression { friend class CodeScope; friend class ClaspLayer; friend class CFAPass; friend class ExpressionHints; Expression(const Operator &oprt, std::initializer_list params); Expression(const Atom& ident); Expression(const Atom& number); Expression(const Atom& a); Expression(); void setOp(Operator oprt); void addArg(Expression&& arg); void addBindings(std::initializer_list> params); void bindType(TypeAnnotation t); template void addBindings(InputIt paramsBegin, InputIt paramsEnd); void addTags(const std::list tags) const; void addBlock(ManagedScpPtr scope); const std::vector& getOperands() const; double getValueDouble() const; void setValueDouble(double value); const std::string& getValueString() const; void setValue(const Atom&& v); bool isValid() const; bool isDefined() const; bool operator==(const Expression& other) const; enum { INVALID, COMPOUND, IDENT, NUMBER, STRING, VARIANT, BINDING } __state = INVALID; Operator op; unsigned int id; std::vector bindings; std::map __indexBindings; std::vector operands; TypeAnnotation type; mutable std::map tags; std::list blocks; private: std::string __valueS; double __valueD; static unsigned int nextVacantId; }; bool operator< (const Expression&, const Expression&); template void Expression::addBindings(InputIt paramsBegin, InputIt paramsEnd) { size_t index = bindings.size(); std::transform(paramsBegin, paramsEnd, std::inserter(bindings, bindings.end()), [&index, this] (const Atom atom) { std::string key = atom.get(); this->__indexBindings[key] = index++; return key; }); } typedef std::list ExpressionList; enum class TagModifier { NONE, ASSERT, REQUIRE }; enum class DomainAnnotation { FUNCTION, VARIABLE }; class RuleArguments : public std::vector> { public: void add(const Atom& name, DomainAnnotation typ); }; class RuleGuards : public std::vector { public: void add(Expression&& e); }; class ClaspLayer; class LLVMLayer; class MetaRuleAbstract { public: MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards); virtual ~MetaRuleAbstract(); virtual void compile(ClaspLayer& layer) = 0; protected: RuleArguments __args; RuleGuards __guards; }; class RuleWarning : public MetaRuleAbstract { friend class ClaspLayer; public: RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom&& message); virtual void compile(ClaspLayer& layer); ~RuleWarning(); private: std::string __message; Expression __condition; }; typedef unsigned int VNameId; typedef int VariableVersion; const VariableVersion VERSION_NONE = -2; const VariableVersion VERSION_INIT = 0; template<> struct AttachmentsDict { typedef VariableVersion Data; static const unsigned int key = 6; }; struct ScopedSymbol{ VNameId id; VariableVersion version; static const ScopedSymbol RetSymbol; }; struct Symbol { ScopedSymbol identifier; CodeScope * scope; }; template<> struct AttachmentsDict { typedef Symbol Data; static const unsigned int key = 7; }; } namespace std { template<> struct hash{ std::size_t operator()(xreate::ScopedSymbol const& s) const; }; template<> struct equal_to{ bool operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const; }; } namespace xreate { typedef std::pair Tag; bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2); bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2); bool operator<(const Symbol& s1, const Symbol& s2); bool operator==(const Symbol& s1, const Symbol& s2); class CodeScope { friend class Function; friend class PassManager; public: CodeScope(CodeScope* parent = 0); void setBody(const Expression& body); Expression& getBody(); void addDeclaration(Expression&& var, Expression&& body); void addBinding(Expression&& var, Expression&& argument); static const Expression& getDeclaration(const Symbol& symbol); const Expression& getDeclaration(const ScopedSymbol& symbol); ~CodeScope(); std::vector __bindings; std::map __identifiers; CodeScope* __parent; //TODO move __definitions to SymbolsAttachments data //NOTE: definition of return type has zero(0) variable index std::unordered_map __declarations; std::vector tags; std::vector contextRules; private: VNameId __vCounter = 1; ScopedSymbol registerIdentifier(const Expression& identifier); public: bool recognizeIdentifier(const Expression& identifier) const; ScopedSymbol getSymbol(const std::string& alias); }; class Function { friend class Expression; friend class CodeScope; friend class AST; public: Function(const Atom& name); void addBinding(Atom && name, Expression&& argument); void addTag(Expression&& tag, const TagModifier mod); const std::string& getName() const; const std::map& getTags() const; CodeScope* getEntryScope() const; CodeScope* __entry; std::string __name; bool isPrefunction = false; //SECTIONTAG adhoc Function::isPrefunction flag Expression guardContext; private: std::map __tags; }; class ExternData; struct ExternEntry { std::string package; std::vector headers; }; typedef Expanded ExpandedType; enum ASTInterface { CFA, DFA, Extern, Adhoc }; struct FunctionSpecialization { std::string guard; size_t id; }; struct FunctionSpecializationQuery { std::unordered_set context; }; template<> struct AttachmentsId{ static unsigned int getId(const Expression& expression){ return expression.id; } }; template<> struct AttachmentsId{ static unsigned int getId(const Symbol& s){ return s.scope->__declarations.at(s.identifier).id; } }; template<> struct AttachmentsId{ static unsigned int getId(const ManagedFnPtr& f){ const Symbol symbolFunction{ScopedSymbol::RetSymbol, f->getEntryScope()}; return AttachmentsId::getId(symbolFunction); } }; +namespace details { namespace incomplete { class AST { public: AST(); //TASK extern and DFA interfaces move into addInterfaceData /** * DFA Interface */ void addDFAData(Expression&& data); /** * Extern Interface */ void addExternData(ExternData&& data); void addInterfaceData(const ASTInterface& interface, Expression&& data); void add(Function* f); void add(MetaRuleAbstract* r); ManagedScpPtr add(CodeScope* scope); std::string getModuleName(); ManagedPtr findFunction(const std::string& name); typedef std::multimap FUNCTIONS_REGISTRY; std::list getAllFunctions() const; std::list getFunctionVariants(const std::string& name) const; template ManagedPtr begin(); std::vector __externdata; std::list __dfadata; //TODO move to more appropriate place std::list __rawImports; //TODO move to more appropriate place std::multimap __interfacesData; //TODO CFA data here. private: std::vector __rules; std::vector __functions; std::vector __scopes; FUNCTIONS_REGISTRY __indexFunctions; // ***** TYPES SECTION ***** public: std::map __indexTypeAliases; - ExpandedType expandType(const TypeAnnotation &t) const; - ExpandedType findType(const std::string& name); + void add(TypeAnnotation t, Atom alias); - + + // ***** SYMBOL RECOGNITION ***** //TODO revisit enums/variants, move to codescope bool recognizeVariantIdentifier(Expression& identifier); - private: std::map> __dictVariants; - ExpandedType expandType(const TypeAnnotation &t, std::map scope, - const std::vector &args = std::vector()) const; - - // ***** SYMBOL RECOGNITION ***** + public: - std::set> binUnrecognizedIdentifiers; + std::set> bucketUnrecognizedIdentifiers; public: void postponeIdentifier(CodeScope* scope, const Expression& id); void recognizePostponedIdentifiers(); + xreate::AST* finalize(); }; template<> ManagedPtr AST::begin(); template<> ManagedPtr AST::begin(); template<> ManagedPtr AST::begin(); +} } // namespace details::incomplete + +class AST: public details::incomplete::AST{ +public: + AST(): details::incomplete::AST() {} + ExpandedType expandType(const TypeAnnotation &t) const; + ExpandedType findType(const std::string& name); +}; } #endif // AST_H diff --git a/cpp/src/attachments.h b/cpp/src/attachments.h index 1fd3e48..5964ebe 100644 --- a/cpp/src/attachments.h +++ b/cpp/src/attachments.h @@ -1,158 +1,163 @@ // // Created by pgess on 3/15/15. // #ifndef _XREATE_ATTACHMENTS_H_ #define _XREATE_ATTACHMENTS_H_ #include #include #include #include namespace xreate { //Attachments dictionary template struct AttachmentsDict { // typedef void Data; // static const unsigned int key (current unreserved - 9); }; template struct AttachmentsId{ //static unsigned int getId(const Object& object); }; template class IAttachmentsContainer{ protected: virtual bool __exists(const unsigned int object)=0; virtual Data& __get(const unsigned int object)=0; virtual void __put(const unsigned int object, Data data)=0; public: template bool exists(const Id& object){ unsigned int id = AttachmentsId::getId(object); return __exists(id); } template Data& get(const Id& object){ unsigned int id = AttachmentsId::getId(object); return __get(id); } template Data get(const Id& object, const Data& dataDefault){ unsigned int id = AttachmentsId::getId(object); if (! __exists(id)){ return dataDefault; } return __get(id); } template void put(const Id& object, Data data){ unsigned int id = AttachmentsId::getId(object); __put(id, data); } virtual ~IAttachmentsContainer(){}; }; template class AttachmentsContainerDefault: public IAttachmentsContainer{ private: std::unordered_map __data; virtual bool __exists(const unsigned int id){ return __data.count(id); } virtual Data& __get(const unsigned int id){ return __data.at(id); } virtual void __put(const unsigned int id, Data data){ auto result = __data.emplace(id, data); assert(result.second); } + +public: + std::unordered_map& getRawStorage() { + return __data; + } }; class Attachments{ private: static std::vector __storage; template using Data = typename AttachmentsDict::Data; public: template static bool exists(const Id& object) { assert(AttachmentsDict::key < __storage.size()); assert(__storage.at(AttachmentsDict::key)); IAttachmentsContainer>* self = reinterpret_cast>*>(__storage.at(AttachmentsDict::key)); return self->exists(object); } template static Data& get(const Id& object){ assert(AttachmentsDict::key < __storage.size()); assert(__storage.at(AttachmentsDict::key)); IAttachmentsContainer>* self = reinterpret_cast>*>(__storage.at(AttachmentsDict::key)); return self->get(object); } template static Data get(const Id& object, const Data& dataDefault){ assert(AttachmentsDict::key < __storage.size()); assert(__storage.at(AttachmentsDict::key)); IAttachmentsContainer>* self = reinterpret_cast>*>(__storage.at(AttachmentsDict::key)); return self->get(object, dataDefault); } template static void put(const Id& object, Data data){ assert(AttachmentsDict::key < __storage.size()); assert(__storage.at(AttachmentsDict::key)); IAttachmentsContainer>* self = reinterpret_cast>*>(__storage.at(AttachmentsDict::key)); self->put(object, data); } template static void init(){ unsigned int keyStorage = AttachmentsDict::key; if (keyStorage+1 > __storage.size()){ __storage.resize(keyStorage + 1, nullptr); } __storage[keyStorage] = new AttachmentsContainerDefault>(); } template static void init(IAttachmentsContainer>* container){ unsigned int keyStorage = AttachmentsDict::key; if (keyStorage+1 > __storage.size()){ __storage.resize(keyStorage + 1, nullptr); } __storage[keyStorage] = container; } }; } #endif //_XREATE_ATTACHMENTS_H_ \ No newline at end of file diff --git a/cpp/src/clasplayer.cpp b/cpp/src/clasplayer.cpp index 65ff3fb..4073851 100644 --- a/cpp/src/clasplayer.cpp +++ b/cpp/src/clasplayer.cpp @@ -1,275 +1,275 @@ #include "clasplayer.h" #include #include "utils.h" #include #include #include #include "analysis/aux.h" #include "analysis/DominatorsTreeAnalysisProvider.h" #include "analysis/cfagraph.h" #include "analysis/dfagraph.h" using namespace std; -//TODO escape identifiers started from upper case symbol +//TODO escape identifiers started with upper case symbol namespace xreate { void ClaspLayer::printWarnings(std::ostream& out) { const std::string warningTag = "warning"; auto warningsRange = __model.equal_range(warningTag); for (auto warning=warningsRange.first; warning!= warningsRange.second; ++warning) { unsigned int warningId; Gringo::Symbol params; std::tie(warningId, params) = parse(warning->second); cout << "Warning: " << __warnings.at(warningId) << " "; params.print(out); out< warnings; cout << "Model: " << endl; const string& atomBindVar = Config::get("clasp.bindings.variable"); const string& atomBindFunc = Config::get("clasp.bindings.function"); const string& atomBindScope = Config::get("clasp.bindings.scope"); for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) { atom.print(cout); cout <<" | "<< endl; string atomName(atom.name().c_str()); if (atomName == atomBindVar || atomName == atomBindFunc || atomName == atomBindScope){ string name = std::get<1>(parse(atom)).name().c_str(); __model.emplace(move(name), move(atom)); } __model.emplace(atomName, move(atom)); } return true; } void ClaspLayer::setCFAData(xreate::analysis::CFAGraph* graph) { dataCFA.reset(graph); } void ClaspLayer::setDFAData(xreate::analysis::DFAGraph* graph){ dataDFA.reset(graph); } void ClaspLayer::addRuleWarning(const RuleWarning &rule) { //__partGeneral << rule << endl; list domains; boost::format formatDef("%1%(%2%)"); std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(domains, domains.begin()), [&formatDef](const std::pair &argument) { string domain; switch (argument.second) { case DomainAnnotation::FUNCTION: domain = "function"; break; case DomainAnnotation::VARIABLE: domain = "variable"; break; } return boost::str(formatDef % domain % argument.first); }); list vars; std::transform(rule.__args.begin(), rule.__args.end(), std::inserter(vars, vars.begin()), [](const std::pair &argument) { return argument.first.c_str(); }); list> guardsRaw; std::transform(rule.__guards.begin(), rule.__guards.end(), std::inserter(guardsRaw, guardsRaw.begin()), [this](const Expression &guard) { return xreate::analysis::compile(guard); }); const list& guards = xreate::analysis::multiplyLists(std::move(guardsRaw)); list &&branches = xreate::analysis::compileNeg(rule.__condition); boost::format formatWarning("warning(%1%, (%2%)):- %3%, %4%, %5%."); for (const string &guardsJoined: guards) for (const string &branch: branches) { unsigned int hook = registerWarning(string(rule.__message)); __partGeneral << formatWarning %(hook) %(boost::algorithm::join(vars, ", ")) %(branch) %(guardsJoined) %(boost::algorithm::join(domains, ", ")) <__rawImports) { std::ifstream file(fn); if (!file) continue; while(!file.eof()){ string line; std::getline(file, line); out << line << endl; } } } void ClaspLayer::addRawScript(std::string&& script){ __partGeneral << script; } void ClaspLayer::run() { involveImports(); if (this->dataDFA){ this->dataDFA->print(__partGeneral); } if (this->dataCFA){ this->dataCFA->print(__partGeneral); } DominatorsTreeAnalysisProvider providerDominators; providerDominators.run(this); providerDominators.print(__partGeneral); ostringstream program; program << __partTags.str() << __partGeneral.str(); cout << FYEL(program.str()) << endl; std::vector args{"clingo", nullptr}; DefaultGringoModule moduleDefault; Gringo::Scripts scriptsDefault(moduleDefault); ClingoLib ctl(scriptsDefault, 0, args.data(), {}, 0); ctl.add("base", {}, program.str()); ctl.ground({{"base", {}}}, nullptr); // solve Gringo::SolveResult result = ctl.solve([this](Gringo::Model const &model) { this->handleSolution(model); return true; }, {}); if (result.satisfiable() == Gringo::SolveResult::Satisfiable) { cout << FGRN("SUCCESSFULLY") << endl; } else { cout << FRED("UNSUCCESSFULLY") << endl; } // invoke all query plugins to process clasp data for (auto q: __queries) { q.second->init(this); } } ClaspLayer::ClaspLayer() { } ClaspLayer::ModelFragment ClaspLayer::query(const std::string& atom) { if (! __model.count(atom)){ return boost::none; } return ModelFragment(__model.equal_range(atom)); } ScopePacked ClaspLayer::pack(CodeScope* const scope) { auto pos = __indexScopes.emplace(scope, __indexScopes.size()); if (pos.second) __registryScopes.push_back(scope); return pos.first->second; } size_t ClaspLayer::getScopesCount() const{ return __registryScopes.size(); } SymbolPacked ClaspLayer::pack(const Symbol& symbol, std::string hintSymbolName) { SymbolPacked result(symbol.identifier.id, symbol.identifier.version, pack(symbol.scope)); __indexSymbolNameHints.emplace(result, hintSymbolName); return result; } Symbol ClaspLayer::unpack(const SymbolPacked& symbol) { return Symbol{ScopedSymbol{symbol.identifier, symbol.version}, __registryScopes[symbol.scope]}; }; std::string ClaspLayer::getHintForPackedSymbol(const SymbolPacked& symbol){ if (!symbol.categoryTransient) { auto result = __indexSymbolNameHints.find(symbol); return (result == __indexSymbolNameHints.end())? "" : result->second; } else { return "anonym(" + to_string(symbol.identifier) + ")"; } } bool operator==(const SymbolPacked& s1, const SymbolPacked& s2) { return s1.identifier == s2.identifier && s1.scope == s2.scope; } bool operator<(const SymbolPacked& s1, const SymbolPacked& s2) { return s1.scope < s2.scope || (s1.scope == s2.scope && s1.identifier < s2.identifier); } IQuery* ClaspLayer::registerQuery(IQuery *query, const QueryId& id) { return __queries.emplace(id, query).first->second; } IQuery* ClaspLayer::getQuery(const QueryId& id){ assert(__queries.count(id) && "Undefined query"); return __queries.at(id); } } \ No newline at end of file diff --git a/cpp/src/compilation/targets.h b/cpp/src/compilation/targets.h index 2ec48eb..6b891c7 100644 --- a/cpp/src/compilation/targets.h +++ b/cpp/src/compilation/targets.h @@ -1,191 +1,191 @@ /* * File: targetabstract.h * Author: pgess * * Created on July 2, 2016, 1:25 PM */ #ifndef TARGETABSTRACT_H #define TARGETABSTRACT_H #include "ast.h" #include #include namespace xreate{ namespace compilation { template struct TargetInfo{ //typedef Result //typedef Function //typedef Scope }; template class Function; template class Target; template class Scope{ typedef typename TargetInfo::Scope Self; public: CodeScope* scope; typename TargetInfo::Result processSymbol(const Symbol& s){ CodeScope* scope = s.scope; Self* self = function->getScope(scope); if (self->__bindings.count(s.identifier)) { return self->__bindings[s.identifier]; } const Expression& declaration = CodeScope::getDeclaration(s); if (!declaration.isDefined()){ assert(false); //for bindings there should be result already } return self->__bindings[s.identifier] = self->process(declaration); } typename TargetInfo::Result processScope() { if (raw) return *raw; raw = process(scope->getBody()); return *raw; } // typename TargetInfo::Result // processFunction(typename TargetInfo::Function* fnRemote, const std::vector::Result>& args){ // Scope scopeRemote = fnRemote->getScope(fnRemote->__function->__entry); // // if (scopeRemote->raw){ // return scopeRemote->raw; // } // // return fnRemote->process(args); // } virtual typename TargetInfo::Result process(const Expression& expression)=0; Scope(CodeScope* codeScope, Function* f) : scope(codeScope), function(f) {} virtual ~Scope(){} void overrideBinding(typename TargetInfo::Result arg, const std::string& name){ assert(scope->__identifiers.count(name)); ScopedSymbol id{scope->__identifiers.at(name), VERSION_NONE}; __bindings[id] = arg; //reset the result if any: raw.reset(); } void registerChildScope(std::shared_ptr scope){ __childScopes.push_back(scope); } void reset(){ __bindings.clear(); __childScopes.clear(); - raw == nullptr; + raw.reset(); } protected: Function* function=0; std::map::Result> __bindings; std::list> __childScopes; typename boost::optional::Result> raw; }; template class Function{ typedef typename TargetInfo::Result Result; typedef typename TargetInfo::Scope ConcreteScope; public: Function(const ManagedFnPtr& function, Target* target) : man(target), __function(function) {} virtual ~Function(){}; ConcreteScope* getScope(CodeScope* scope){ if (__scopes.count(scope)) { auto result = __scopes.at(scope).lock(); if (result){ return result.get(); } } std::shared_ptr unit(new ConcreteScope(scope, this)); if (scope->__parent != nullptr){ getScope(scope->__parent)->registerChildScope(unit); } else { assert(!__entryScope); __entryScope = unit; } if (!__scopes.emplace(scope, unit).second){ __scopes[scope] = unit; } return unit.get(); } virtual Result process(const std::vector& args)=0; Target* man=0; ManagedFnPtr __function; protected: std::map> __scopes; std::shared_ptr __entryScope; }; template class Target { typedef typename TargetInfo::Function ConcreteFunction; public: Target(AST* root): ast(root){} ConcreteFunction* getFunction(const ManagedFnPtr& function){ unsigned int id = function.id(); if (!__functions.count(id)){ ConcreteFunction* unit = new ConcreteFunction(function, this); __functions.emplace(id, unit); return unit; } return __functions.at(id); } AST* ast; virtual ~Target(){ for (const auto& entry: __functions){ delete entry.second; } } protected: std::map __functions; }; }} #endif /* TARGETABSTRACT_H */ diff --git a/cpp/src/serialization/expressionserializer.cpp b/cpp/src/misc/serialization/expressionserializer.cpp similarity index 99% rename from cpp/src/serialization/expressionserializer.cpp rename to cpp/src/misc/serialization/expressionserializer.cpp index 447c7d1..d62a1cc 100644 --- a/cpp/src/serialization/expressionserializer.cpp +++ b/cpp/src/misc/serialization/expressionserializer.cpp @@ -1,318 +1,318 @@ /* * expressionserializer.cpp * * Created on: Jan 4, 2016 * Author: pgess */ -#include "serialization/expressionserializer.h" +#include "misc/serialization/expressionserializer.h" #include #include #include using namespace std; //using namespace boost::bimaps; namespace xreate { struct Index { string name; size_t degree; //count of parameters unsigned char level; //level in expression tree (depth of tree layer) bool operator< (const Index other) const{ if (name != other.name) return name < other.name; if (degree != other.degree) return degree < other.degree; if (name != other.name) return level < other.level; return false; } }; class ExpressionSerializerPrivate { //boost::bimap> __registry; struct { map left; } __registry; map __range; public: void pack(const Expression& e, unsigned char level, OptionalPackedExpression& target){ if (!target) return; switch (e.op){ case Operator::NONE: { switch (e.__state) { case Expression::NUMBER: case Expression::STRING: case Expression::IDENT : { Index index; if ((e.__state == Expression::NUMBER)) index = {std::to_string(e.getValueDouble()), 0, level}; else index = {e.getValueString(), 0, level}; if (!__registry.left.count(index)){ target = boost::none; return; } size_t id = __registry.left.at(index); size_t range = __range[level]; (*target) << make_pair(id, range); return; } default: break; } break; } case Operator::CALL: { Index index{e.getValueString(), e.operands.size(), level}; if(!__registry.left.count(index)){ target = boost::none; return; } size_t id = __registry.left.at(index); size_t range = __range[level]; (*target) << make_pair(id, range); for (const Expression& operand: e.operands){ pack(operand, level+1, target); } return; } default: break; } assert(false && "Expression too complicate for serialization"); } void registerExpression(const Expression&e, unsigned char level){ switch (e.op){ case Operator::CALL: { Index index{e.getValueString(), e.operands.size(), level}; if (__registry.left.insert(make_pair(index, __range[level])).second){ __range[level]++; } for (const Expression& operand: e.operands){ registerExpression(operand, level+1); } return; } case Operator::NONE: { Index index; switch (e.__state) { case Expression::STRING: case Expression::IDENT: { index = {e.getValueString(), 0, level}; if (__registry.left.insert(make_pair(index, __range[level])).second){ __range[level]++; } return; } case Expression::NUMBER: { index = {std::to_string(e.getValueDouble()), 0, level}; if (__registry.left.insert(make_pair(index, __range[level])).second){ __range[level]++; } return; } default: break; } break; } default: break; } assert(false && "Expression too complicate for serialization"); } }; ExpressionSerializer::ExpressionSerializer() : strategy(new ExpressionSerializerPrivate()){ } ExpressionSerializer::~ExpressionSerializer() { delete strategy; } void ExpressionSerializer::registerExpression(const Expression&e){ if (e.isValid()) strategy->registerExpression(e, 0); } PackedExpression ExpressionSerializer::getId(const Expression& e){ OptionalPackedExpression result(boost::in_place()); //move(PackedExpression()) strategy->pack(e, 0, result); assert(result); return move(*result); } OptionalPackedExpression ExpressionSerializer::getIdOptional(const Expression& e) const{ OptionalPackedExpression result(boost::in_place()); //move(PackedExpression()) strategy->pack(e, 0, result); return result; } ExpressionSerializerIntegral::ExpressionSerializerIntegral():serializer(*this){} ExpressionSerializerIntegral::ExpressionSerializerIntegral(const std::vector&& expressions) : std::vector(move(expressions)), serializer(*this){ size_t id =0; for (const Expression& e: expressions){ __registry.emplace(serializer.getId(e), id++); } } size_t ExpressionSerializerIntegral::size() const{ return PARENT::size(); } size_t ExpressionSerializerIntegral::count(const Expression& e) const { return (getIdOptional(e)? 1: 0); } ExpressionSerializerIntegral::const_iterator ExpressionSerializerIntegral::begin() const { return PARENT::begin(); } ExpressionSerializerIntegral::const_iterator ExpressionSerializerIntegral::end() const { return PARENT::end(); } size_t ExpressionSerializerIntegral::getId(const Expression& e) const{ const OptionalPackedExpression exprPacked = serializer.getIdOptional(e); assert(exprPacked); return __registry.at(*exprPacked); } boost::optional ExpressionSerializerIntegral::getIdOptional(const Expression& e) const{ const OptionalPackedExpression exprPacked = serializer.getIdOptional(e); if (!exprPacked){ return boost::none; } return __registry.at(*exprPacked); } const Expression& ExpressionSerializerIntegral::get(size_t id) const{ return at(id); } void PackedExpression::operator<< (const std::pair& value){ static const size_t sizeSizeT = sizeof(size_t); const size_t& id = value.first; const size_t& range = value.second; int countSufficientBits = range <=1? 0 : ceil(log2(range)); if (0 < countRemainedBits && countRemainedBits < countSufficientBits) { size_t* tail = reinterpret_cast(__storage + size- sizeSizeT); (*tail) += id >> (countSufficientBits - countRemainedBits); countSufficientBits-=countRemainedBits; countRemainedBits = 0; } if (countRemainedBits == 0) { if (countSufficientBits == 0) return; char* __storageNew = new char[size+sizeSizeT]; std::memcpy (__storageNew, __storage, size); std::memset(__storageNew + size, 0, sizeSizeT); delete[] __storage; __storage = __storageNew; size += sizeSizeT; countRemainedBits = 8 * sizeSizeT; } if (countRemainedBits >= countSufficientBits) { size_t* tail = reinterpret_cast(__storage + size- sizeSizeT); (*tail) += id << (countRemainedBits - countSufficientBits); countRemainedBits -= countSufficientBits; return; } assert("Unreachable block"); } #if BOOST_VERSION <= 105500 PackedExpression::PackedExpression(const PackedExpression& other){ __storage = other.__storage; size = other.size; countRemainedBits = other.countRemainedBits; } #endif PackedExpression::PackedExpression(PackedExpression&& other){ __storage = other.__storage; size = other.size; countRemainedBits = other.countRemainedBits; other.__storage = nullptr; } bool PackedExpression::operator==(const PackedExpression& other) const{ if (size == other.size && countRemainedBits == other.countRemainedBits){ return std::memcmp(__storage, other.__storage, size) == 0 ; } return false; } bool PackedExpression::operator<(const PackedExpression& other) const{ if (size < other.size) { return true; } if (countRemainedBits < other.countRemainedBits) return true; if (size == other.size && countRemainedBits == other.countRemainedBits){ return std::memcmp(__storage, other.__storage, size) < 0 ; } return false; } bool PackedExpression::operator!=(const PackedExpression& other) const{ return ! ((*this) == other); } PackedExpression::~PackedExpression() { delete[] __storage; } //PackedExpression::PackedExpression (const PackedExpression& other) // : size(other.size), countRemainedBits(other.countRemainedBits) //{ // __storage = new char[size]; // std::memcpy (__storage, other.__storage, size); //} } /* namespace xreate */ \ No newline at end of file diff --git a/cpp/src/serialization/expressionserializer.h b/cpp/src/misc/serialization/expressionserializer.h similarity index 100% rename from cpp/src/serialization/expressionserializer.h rename to cpp/src/misc/serialization/expressionserializer.h diff --git a/cpp/src/misc/xreatemanager-decorators.cpp b/cpp/src/misc/xreatemanager-decorators.cpp new file mode 100644 index 0000000..242d45e --- /dev/null +++ b/cpp/src/misc/xreatemanager-decorators.cpp @@ -0,0 +1,67 @@ +/* + * xreatemanager-decorators.cpp + * + * Author: pgess + * Created on July 16, 2017, 4:40 PM + */ + +#include "misc/xreatemanager-decorators.h" +#include "main/Parser.h" +#include "pass/compilepass.h" +#include "pass/adhocpass.h" +#include "pass/cfapass.h" +#include "pass/dfapass.h" +#include "pass/interpretationpass.h" +#include "pass/versionspass.h" + +namespace xreate { + +void +XreateManagerDecoratorBase::prepareCode(std::string&& code){ + grammar::main::Scanner scanner(reinterpret_cast(code.c_str()), code.size()); + grammar::main::Parser parser(&scanner); + parser.Parse(); + assert(!parser.errors->count && "Parser errors"); + + PassManager::prepare(parser.root->finalize()); +} + +void +XreateManagerDecoratorBase::prepareCode(FILE* code){ + grammar::main::Scanner scanner(code); + grammar::main::Parser parser(&scanner); + parser.Parse(); + assert(!parser.errors->count && "Parser errors"); + + PassManager::prepare(parser.root->finalize()); +} + +void +XreateManagerDecoratorBase::analyse(){ + CompilePass::prepareQueries(clasp); + clasp->run(); +} + +void +XreateManagerDecoratorFull::initPasses(){ + CFAPass* passCFG = new CFAPass(this); + + //TODO is it really DFGPass needs CFGpass? + registerPass(new DFAPass(this), PassId::DFGPass, passCFG); + registerPass(passCFG, PassId::CFGPass); + this->registerPass(new AdhocPass(this), PassId::AdhocPass); + this->registerPass(new InterpretationPass(this), PassId::InterpretationPass); + this->registerPass(new VersionsPass(this), PassId::VersionsPass); +} + +void* +XreateManagerDecoratorFull::run() { + std::unique_ptr compiler(new CompilePass(this)); + compiler->run(); + + llvm->print(); + llvm->initJit(); + return llvm->getFunctionPointer(compiler->getEntryFunction()); +} + +} //namespace xreate diff --git a/cpp/src/misc/xreatemanager-decorators.h b/cpp/src/misc/xreatemanager-decorators.h new file mode 100644 index 0000000..942f23b --- /dev/null +++ b/cpp/src/misc/xreatemanager-decorators.h @@ -0,0 +1,33 @@ +/* + * File: xreatemanager-decorators.h + * Author: pgess + * + * Created on July 16, 2017, 4:37 PM + */ + +#ifndef XREATEMANAGER_DECORATORS_H +#define XREATEMANAGER_DECORATORS_H + +#include "xreatemanager.h" + +namespace xreate { + +class XreateManagerDecoratorBase: public details::tier2::XreateManager{ +public: + void analyse(); + +public: + virtual void prepareCode(std::string&& code); + virtual void prepareCode(FILE* code); +}; + +class XreateManagerDecoratorFull: public XreateManagerDecoratorBase { +public: + void initPasses() override; + void* run(); +}; + +} + +#endif /* XREATEMANAGER_DECORATORS_H */ + diff --git a/cpp/src/misc/xreatemanager-modules.h b/cpp/src/misc/xreatemanager-modules.h new file mode 100644 index 0000000..bff07cf --- /dev/null +++ b/cpp/src/misc/xreatemanager-modules.h @@ -0,0 +1,110 @@ +/* + * File: PassManagerModular.h + * Author: pgess + * + * Created on June 22, 2017, 5:32 PM + */ + +#ifndef PASSMANAGERMODULAR_H +#define PASSMANAGERMODULAR_H + +#include "ast.h" +#include "modules.h" +#include "modules/Parser.h" +#include "main/Parser.h" + +namespace xreate{ + +template +class XreateManagerDecoratorModules: public Parent{ +public: + XreateManagerDecoratorModules(): __registry(new ModulesRegistry()){} + + void prepareCode(std::string&& code) override { + grammar::modules::Scanner scannerModules(reinterpret_cast(code.c_str()), code.size()); + std::list listIncludedFiles; + parseModulesGrammar(scannerModules, listIncludedFiles); + + grammar::main::Scanner scannerMain(reinterpret_cast(code.c_str()), code.size()); + parseMainGrammar(scannerMain, listIncludedFiles); + } + + void prepareCode(FILE* code) override { + grammar::modules::Scanner scannerModules(code); + std::list listIncludedFiles; + parseModulesGrammar(scannerModules, listIncludedFiles); + + grammar::main::Scanner scannerMain(code); + parseMainGrammar(scannerMain, listIncludedFiles); + } + +private: + ModulesRegistry* __registry; + + void parseModulesGrammar(grammar::modules::Scanner& scanner, std::list& listIncludedFiles){ + ModulesSolver solver(__registry); + + grammar::modules::Parser parser(&scanner); + parser.Parse(); + parser.module.__path = ""; + + solver.init("", parser.module); + + std::list modulesExternal = solver.run(parser.module); + std::string programBase = solver.__program.str(); + + for (const std::string module: modulesExternal){ + parseModulesGrammar(module, programBase, listIncludedFiles); + } + } + + void parseModulesGrammar(const std::string& path, std::string base, std::list& listIncludedFiles){ + FILE* input = fopen(path.c_str(), "r"); + assert(input != nullptr); + grammar::modules::Scanner scanner(input); + grammar::modules::Parser parser(&scanner); + parser.Parse(); + parser.module.__path = path; + fclose(input); + + ModulesSolver solver(__registry); + solver.init(base, parser.module); + + std::list&& modulesExternal = solver.run(parser.module); + std::string programBase = solver.__program.str(); + + for (const std::string module: modulesExternal){ + parseModulesGrammar(module, programBase, listIncludedFiles); + } + + listIncludedFiles.push_back(path); + } + + void parseMainGrammar(grammar::main::Scanner& scanner, std::list& listIncludedFiles){ + details::incomplete::AST* ast = new AST; + + grammar::main::Parser parser(&scanner); + parser.root = ast; + parser.Parse(); + assert(!parser.errors->count && "Parser errors"); + + for (auto file: listIncludedFiles){ + FILE* fileContent = fopen(file.c_str(), "r"); + grammar::main::Scanner scanner(fileContent); + grammar::main::Parser parser(&scanner); + parser.root = ast; + parser.Parse(); + fclose(fileContent); + + assert(!parser.errors->count && "Parser errors"); + } + + PassManager::prepare(ast->finalize()); + } +}; + +} //end namespace xreate + + +#endif /* PASSMANAGERMODULAR_H */ + diff --git a/cpp/src/modules.cpp b/cpp/src/modules.cpp new file mode 100644 index 0000000..5866c8a --- /dev/null +++ b/cpp/src/modules.cpp @@ -0,0 +1,164 @@ +/* + * modules.cpp + * + * Author: pgess + * Created on July 22, 2017, 5:13 PM + */ + +#include "modules.h" +#include "modules/Parser.h" +#include "analysis/aux.h" +#include +#include +#include +#include +#include + +namespace fs = boost::filesystem; + +namespace xreate { +void +ModuleRecord::addModuleQuery(const Expression& query){ + __queries.push_back(query); +} + +void +ModuleRecord::addControllerPath(const std::string& path){ + __controllers.push_back(path); +} + +void +ModuleRecord::addDiscoveryPath(const std::string& path){ + __discoveries.push_back(path); +} + +void +ModuleRecord::addProperty(const Expression& prop){ + __properties.push_back(prop); +} + +void +ModulesSolver::loadControllers(const ModuleRecord& module){ + for (const std::string& pathController: module.__controllers){ + std::fstream fileContent(pathController); + __program << fileContent.rdbuf(); + } +} + +void +ModulesSolver::extractProperties(const ModuleRecord& module){ + unsigned int moduleId = __registry->getModuleHash(module.__path); + const std::string atomProperty = "bind_module"; + boost::format formatProperty(atomProperty + "(%1%, %2%)."); + + for (const Expression& property: module.__properties){ + std::list reprProp = xreate::analysis::compile(property); + assert(reprProp.size()== 1); + + __program << (formatProperty % moduleId % reprProp.front()) + << std::endl; + } +} + +void +ModulesSolver::discoverModules(const ModuleRecord& moduleClient){ + std::regex extXreate("\\.xreate$", std::regex::basic); + + for(const std::string& path: moduleClient.__discoveries){ + for(fs::directory_entry e: fs::recursive_directory_iterator(path)) { + if (fs::is_regular_file(e.status())){ + if (!std::regex_search(e.path().string(), extXreate)) continue; + + FILE* script = fopen(e.path().c_str(), "r"); + grammar::modules::Scanner scanner(script); + grammar::modules::Parser parser(&scanner); + parser.Parse(); + assert(!parser.errors->count && "Discovery errors"); + parser.module.__path = e.path().c_str(); + + extractProperties(parser.module); + fclose(script); + } + } + } +} + +void +ModulesSolver::extractRequirements(const ModuleRecord& module){ + const std::string atomQuery = "module_require"; + boost::format formatProperty(atomQuery + "(%1%, %2%)."); + unsigned int moduleId = __registry->getModuleHash(module.__path); + + for (const Expression& query: module.__queries){ + std::list reprQuery = xreate::analysis::compile(query); + assert(reprQuery.size()== 1); + + __program << (formatProperty % moduleId % reprQuery.front()) + << std::endl; + } +} + +void +ModulesSolver::add(const std::string& base){ + __program << base; +} + +void +ModulesSolver::init(const std::string& programBase, const ModuleRecord& module){ + add(programBase); + extractRequirements(module); + extractProperties(module); + loadControllers(module); + discoverModules(module); + + std::cout << __program.str() << std::endl; +} + +std::list +ModulesSolver::run(const ModuleRecord& module){ + const std::string atomDecision = "module_include"; + unsigned int moduleId = __registry->getModuleHash(module.__path); + + std::list result; + std::vector args{"clingo", nullptr}; + DefaultGringoModule moduleDefault; + Gringo::Scripts scriptsDefault(moduleDefault); + ClingoLib ctl(scriptsDefault, 0, args.data(), {}, 0); + + ctl.add("base", {}, __program.str()); + ctl.ground({{"base", {}}}, nullptr); + ctl.solve([&atomDecision, this, &result, moduleId](Gringo::Model const &model) { + for (Gringo::Symbol atom : model.atoms(clingo_show_type_atoms)) { + atom.print(std::cout); + + if (std::strcmp(atom.name().c_str(), atomDecision.c_str())==0){ + auto rowDecision = ClaspLayer::parse(atom); + + unsigned int moduleIdActual = std::get<0>(rowDecision); + if (moduleIdActual == moduleId){ + result.push_back(__registry->getModuleNameByHash(std::get<1>(rowDecision))); + } + } + } + return true; + }, {}); + + return result; +} + +const std::string& +ModulesRegistry::getModuleNameByHash(unsigned int hash){ + auto result = __registry.right.find(hash); + assert(result != __registry.right.end()); + + return result->second; +} + +unsigned int +ModulesRegistry::getModuleHash(const std::string& moduleName){ + auto result = __registry.left.insert(Hash::left_value_type(moduleName, __registry.size())); + + return result.first->second; +} + +} //namespace xreate diff --git a/cpp/src/modules.h b/cpp/src/modules.h new file mode 100644 index 0000000..39c2e97 --- /dev/null +++ b/cpp/src/modules.h @@ -0,0 +1,76 @@ +/* + * File: modules.h + * Author: pgess + * + * Created on July 22, 2017, 5:11 PM + */ + +#ifndef MODULES_H +#define MODULES_H + +#include "ast.h" +#include + +#ifndef FRIENDS_MODULES_TESTS +#define FRIENDS_MODULES_TESTS +#endif + +namespace xreate { +class ModulesRegistry{ +public: + const std::string& getModuleNameByHash(unsigned int hash); + unsigned int getModuleHash(const std::string& moduleName); + +private: + typedef boost::bimap Hash; + Hash __registry; +}; + +class ModulesSolver; + +class ModuleRecord { + FRIENDS_MODULES_TESTS + friend class ModulesSolver; + +public: + void addModuleQuery(const Expression& query); + void addControllerPath(const std::string& path); + void addDiscoveryPath(const std::string& path); + void addProperty(const Expression& prop); + +private: + std::list __queries; + std::list __controllers; + std::list __discoveries; + std::list __properties; + +public: + std::string __path; +}; + +class ModulesSolver{ + FRIENDS_MODULES_TESTS + +public: + ModulesSolver(ModulesRegistry *registry): __registry(registry) {} + + void loadControllers(const ModuleRecord& module); + void discoverModules(const ModuleRecord& moduleClient); + + void extractProperties(const ModuleRecord& module); + void extractRequirements(const ModuleRecord& module); + + void add(const std::string& base); + + void init(const std::string& programBase, const ModuleRecord& module); + std::list run(const ModuleRecord& module); + +private: + ModulesRegistry* __registry; + +public: + std::ostringstream __program; +}; +} //end namespace xreate + +#endif /* MODULES_H */ \ No newline at end of file diff --git a/cpp/src/pass/abstractpass.cpp b/cpp/src/pass/abstractpass.cpp index ca6190a..18a7ed9 100644 --- a/cpp/src/pass/abstractpass.cpp +++ b/cpp/src/pass/abstractpass.cpp @@ -1,58 +1,58 @@ #include "abstractpass.h" #include "attachments.h" -#include "passmanager.h" +#include "xreatemanager.h" using namespace std; namespace xreate { template<> void defaultValue(){} void AbstractPassBase::finish(){} AbstractPassBase::AbstractPassBase(PassManager *manager) : man(manager) { } template<> void AbstractPass::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol) { if (__visitedSymbols.isCached(symbol)) return; __visitedSymbols.setCachedValue(symbol); const Expression& declaration = CodeScope::getDeclaration(symbol); if (declaration.isDefined()){ PassContext context2 = context.updateScope(symbol.scope); process(declaration, context2, hintSymbol); } } template<> void AbstractPass::process(const Expression& expression, PassContext context, const std::string& varDecl){ if (expression.__state == Expression::COMPOUND){ for (const Expression &op: expression.getOperands()) { process(op, context); } for (CodeScope* scope: expression.blocks) { process(scope, context); } if (expression.op == Operator::CALL){ processExpressionCall(expression, context); } return; } if (expression.__state == Expression::IDENT){ assert(context.scope); processSymbol(Attachments::get(expression), context, expression.getValueString()); } } -} \ No newline at end of file +} diff --git a/cpp/src/pass/abstractpass.h b/cpp/src/pass/abstractpass.h index dfefc06..39c28de 100644 --- a/cpp/src/pass/abstractpass.h +++ b/cpp/src/pass/abstractpass.h @@ -1,194 +1,194 @@ #ifndef ABSTRACTPASS_H #define ABSTRACTPASS_H #include "ast.h" -#include "passmanager.h" +#include "xreatemanager.h" #include namespace xreate { struct PassContext { CodeScope* scope = 0; ManagedFnPtr function; ManagedRulePtr rule; std::string varDecl; PassContext() {} PassContext updateScope(CodeScope* scopeNew) { PassContext context2{*this}; context2.scope = scopeNew; return context2; } ~PassContext(){} }; class AbstractPassBase { public: AbstractPassBase(PassManager* manager); virtual void run()=0; virtual void finish(); PassManager* man; }; template Output defaultValue(); template<> void defaultValue(); template class SymbolCache: private std::map{ public: bool isCached(const Symbol& symbol){ return this->count(symbol); } Output setCachedValue(const Symbol& symbol, Output&& value){ (*this)[symbol] = value; return value; } Output getCachedValue(const Symbol& symbol){ assert(this->count(symbol)); return this->at(symbol); } }; template<> class SymbolCache: private std::set{ public: bool isCached(const Symbol& symbol){ bool result = this->count(symbol) > 0; return result; } void setCachedValue(const Symbol& symbol){ this->insert(symbol); } void getCachedValue(const Symbol& symbol){ } }; template class AbstractPass: public AbstractPassBase { SymbolCache __visitedSymbols; protected: virtual Output processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol=""){ if (__visitedSymbols.isCached(symbol)) return __visitedSymbols.getCachedValue(symbol); const Expression& declaration = CodeScope::getDeclaration(symbol); if (declaration.isDefined()){ PassContext context2 = context.updateScope(symbol.scope); Output&& result = process(declaration, context2, hintSymbol); return __visitedSymbols.setCachedValue(symbol, std::move(result)); } return defaultValue(); } Output processExpressionCall(const Expression& expression, PassContext context){ const std::string &calleeName = expression.getValueString(); std::list callees = man->root->getFunctionVariants(calleeName); if (callees.size() == 1 && callees.front()){ return processFnCall(callees.front(), context); } else { for (const ManagedFnPtr& callee: callees){ processFnCallUncertain(callee, context); } return defaultValue(); } } SymbolCache& getSymbolCache(){ return __visitedSymbols; } public: AbstractPass(PassManager* manager) : AbstractPassBase(manager){} virtual Output processFnCall(ManagedFnPtr function, PassContext context){ return defaultValue(); } virtual void processFnCallUncertain(ManagedFnPtr function, PassContext context) {} virtual void process(ManagedRulePtr rule) {} virtual Output process(ManagedFnPtr function) { PassContext context; context.function = function; return process(function->getEntryScope(), context); } virtual Output process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl=""){ context.scope = scope; return processSymbol(Symbol{ScopedSymbol::RetSymbol, scope}, context); } virtual Output process(const Expression& expression, PassContext context, const std::string& varDecl=""){ if (expression.__state == Expression::IDENT){ assert(context.scope); return processSymbol(Attachments::get(expression), context, expression.getValueString()); } assert(false); return defaultValue(); } void run() { ManagedRulePtr rule = man->root->begin(); while (rule.isValid()) { process(rule); ++rule; } ManagedFnPtr f = man->root->begin(); while (f.isValid()) { process(f); ++f; } } }; template<> void AbstractPass::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol); template<> void AbstractPass::process(const Expression& expression, PassContext context, const std::string& hintSymbol); } #endif //PROCESS FUNCTION: // const Symbol& symbolFunction{0, function->getEntryScope()}; // // if (__visitedSymbols.isCached(symbolFunction)) // return __visitedSymbols.getCachedValue(symbolFunction); // // PassContext context; // context.function = function; // // Output&& result = process(function->getEntryScope(), context); -// return __visitedSymbols.setCachedValue(symbolFunction, std::move(result)); \ No newline at end of file +// return __visitedSymbols.setCachedValue(symbolFunction, std::move(result)); diff --git a/cpp/src/pass/cfapass.cpp b/cpp/src/pass/cfapass.cpp index 07801b6..80f3034 100644 --- a/cpp/src/pass/cfapass.cpp +++ b/cpp/src/pass/cfapass.cpp @@ -1,100 +1,100 @@ #include "cfapass.h" #include "analysis/cfagraph.h" #include using namespace std; using namespace xreate; void CFAPass::initSignatures(){ auto range = man->root->__interfacesData.equal_range(CFA); for (auto i = range.first; i!= range.second; ++i){ __signatures.emplace(i->second.op, i->second); } } void CFAPass::run(){ initSignatures(); return AbstractPass::run(); } void CFAPass::finish() { man->clasp->setCFAData(move(__context.graph)); return AbstractPass::finish(); } void CFAPass::processFnCall(ManagedFnPtr function, PassContext context) { ClaspLayer* clasp = man->clasp; __context.graph->addCallConnection(clasp->pack(context.scope), function->getName()); return AbstractPass::processFnCall(function, context); } void CFAPass::processFnCallUncertain(ManagedFnPtr function, PassContext context){ ClaspLayer* clasp = man->clasp; __context.graph->addCallConnection(clasp->pack(context.scope), function->getName()); return AbstractPass::processFnCallUncertain(function, context); } void CFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl){ ClaspLayer* clasp = man->clasp; CodeScope* scopeParent = context.scope; ScopePacked scopeId = clasp->pack(scope); if (scopeParent){ __context.graph->addParentConnection(scopeId, clasp->pack(scopeParent)); } else { __context.graph->addParentConnection(scopeId, context.function->getName()); } //TOTEST scope annotations //SECTIONTAG context gather scope annotations __context.graph->addScopeAnnotations(scopeId, scope->tags); __context.graph->addContextRules(scopeId, scope->contextRules); return AbstractPass::process(scope, context, hintBlockDecl); } //TOTEST scope annotations via scheme void CFAPass::process(const Expression& expression, PassContext context, const std::string& varDecl){ ClaspLayer* clasp = man->clasp; if (expression.__state == Expression::COMPOUND){ Operator op= expression.op; if (__signatures.count(op)) { assert(expression.blocks.size()); for (const auto& scheme: boost::make_iterator_range(__signatures.equal_range(expression.op))) { __context.graph->addScopeAnnotations(clasp->pack(expression.blocks.front()), scheme.second.getOperands()); } } } return AbstractPass::process(expression, context, varDecl); } void CFAPass::process(ManagedFnPtr function) { __context.graph->addFunctionAnnotations(function->getName(), function->getTags()); return AbstractPass::process(function); } CFAPass::CFAPass(PassManager* manager) : AbstractPass(manager) , __context{new xreate::analysis::CFAGraph(manager->clasp)} -{} \ No newline at end of file +{} diff --git a/cpp/src/pass/cfapass.h b/cpp/src/pass/cfapass.h index a064c6d..b63e6a6 100644 --- a/cpp/src/pass/cfapass.h +++ b/cpp/src/pass/cfapass.h @@ -1,38 +1,38 @@ // Control Flow Graph determination pass #ifndef CFGPASS_H #define CFGPASS_H -#include "passmanager.h" +#include "xreatemanager.h" #include "clasplayer.h" #include "abstractpass.h" namespace xreate{namespace analysis { class CFAGraph; }} namespace xreate { class CFAPass : public AbstractPass { public: void process(ManagedFnPtr function) override; void processFnCall(ManagedFnPtr function, PassContext context) override; void processFnCallUncertain(ManagedFnPtr function, PassContext context) override; void process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl="") override; void process(const Expression& expression, PassContext context, const std::string& varDecl="") override; CFAPass(PassManager* manager); void finish() override; void run() override; private: struct { xreate::analysis::CFAGraph* graph; } __context; std::multimap __signatures; //CFA data for particular operators void initSignatures(); }; } #endif // CFGPASS_H diff --git a/cpp/src/pass/dfapass.cpp b/cpp/src/pass/dfapass.cpp index 49a957a..bee36eb 100644 --- a/cpp/src/pass/dfapass.cpp +++ b/cpp/src/pass/dfapass.cpp @@ -1,262 +1,262 @@ #include "pass/dfapass.h" #include "analysis/dfagraph.h" -#include "passmanager.h" +#include "xreatemanager.h" #include "clasplayer.h" #include using namespace std; using namespace xreate::analysis; namespace xreate { class DfaExpressionProcessor { std::vector operands; std::vector blocks; const Expression expression; xreate::analysis::SymbolNode result; DFAPass * const pass; const PassContext context; public: DfaExpressionProcessor(const Expression& expr, SymbolNode resInitial, DFAPass * const p, const PassContext c) : expression(expr), result(resInitial), pass(p), context(c) { operands.reserve(expression.getOperands().size()); for (const Expression &op : expression.getOperands()) { SymbolAnonymous symbOp(op.id); operands.push_back(DfaExpressionProcessor(op, symbOp, pass, context).process()); } blocks.reserve(expression.blocks.size()); for (CodeScope* scope : expression.blocks) { blocks.push_back(pass->process(scope, context)); } } SymbolNode process() { if (expression.__state == Expression::COMPOUND) { processCompoundOp(); } else { processElementaryOp(); } applySignatureAnnotations(); applyInPlaceAnnotations(); return result; } private: void processElementaryOp() { switch (expression.__state) { case Expression::IDENT: { SymbolPacked symbFrom = pass->processSymbol(Attachments::get(expression), context, expression.getValueString()); SymbolPacked* symbTo = boost::get(&result); if (symbTo) { pass->__context.graph->addConnection(*symbTo, SymbolNode(symbFrom), DFGConnection::STRONG); } else { result = SymbolNode(symbFrom); } break; } default: break; } } void processCompoundOp() { switch (expression.op) { //DEBT provide CALL processing // case Operator::CALL: { // const string &nameCalleeFunction = expression.getValueString(); // // //TODO implement processFnCall/Uncertain // list variantsCalleeFunction = man->root->getFunctionVariants(nameCalleeFunction); // if (variantsCalleeFunction.size()!=1) return; // ManagedFnPtr function= variantsCalleeFunction.front(); // // // set calling relations: // CodeScope *scopeRemote = function->getEntryScope(); // std::vector::iterator nodeActual = cache.operands.begin(); // for (const std::string &identFormal: scopeRemote->__bindings){ // const ScopedSymbol symbolFormal{scopeRemote->__identifiers.at(identFormal), VERSION_NONE}; // // __context.graph->addConnection(clasp->pack(Symbol{symbolFormal, scopeRemote}, nameCalleeFunction + ":" + identFormal), *nodeActual, DFGConnection::WEAK); // ++nodeActual; // } // // //TODO add RET connection // break; // } //MAP processing: apply PROTOTYPE relation case Operator::MAP: { SymbolNode nodeFrom = operands.front(); SymbolPacked* nodeTo = boost::get(&result); assert(nodeTo); pass->__context.graph->addConnection(*nodeTo, nodeFrom, DFGConnection::PROTOTYPE); break; } default: break; } } void applySignatureAnnotations() { if (pass->__signatures.count(expression.op)) { const Expression &scheme = pass->__signatures.at(expression.op); std::vector::iterator arg = operands.begin(); std::vector::const_iterator tag = scheme.getOperands().begin(); //Assign scheme RET annotation Expression retTag = *scheme.getOperands().begin(); if (retTag.__state != Expression::INVALID) { pass->__context.graph->addAnnotation(result, move(retTag)); } ++tag; while (tag != scheme.getOperands().end()) { if (tag->__state != Expression::INVALID) { pass->__context.graph->addAnnotation(*arg, Expression(*tag)); } ++arg; ++tag; } // TODO add possibility to have specific signature for a particular function // if (expression.op == Operator::CALL || expression.op == Operator::INDEX){ // string caption = expression.getValueString(); // operands.push_back(process(Expression(move(caption)), context, "")); // } } } void applyInPlaceAnnotations() { // write down in-place expression tags: for (pair tag : expression.tags) { pass->__context.graph->addAnnotation(result, Expression(tag.second)); } } }; DFAPass::DFAPass(PassManager* manager) : AbstractPass(manager) , __context{new xreate::analysis::DFAGraph(manager->clasp)} , clasp(manager->clasp) {} SymbolPacked DFAPass::process(CodeScope* scope, PassContext context, const std::string& hintBlockDecl) { const SymbolPacked& symbRet = AbstractPass::process(scope, context, hintBlockDecl); return symbRet; } SymbolPacked DFAPass::processSymbol(const Symbol& symbol, PassContext context, const std::string& hintSymbol) { const Expression& declaration = CodeScope::getDeclaration(symbol); const SymbolPacked& symbPacked = clasp->pack(symbol, hintSymbol); DfaExpressionProcessor(declaration, symbPacked, this, context).process(); return symbPacked; } void DFAPass::run() { init(); return AbstractPass::run(); } void DFAPass::init() { for (const Expression& scheme : man->root->__dfadata) { __signatures.emplace(scheme.op, scheme); } } void DFAPass::finish() { clasp->setDFAData(move(__context.graph)); } template<> SymbolPacked defaultValue(){ assert(false); } } //xreate namespace //DEBT represent VersionaPass in declarative form using applyDependencies // applyDependencies(expression, context, cache, decl); //DEBT prepare static annotations and represent InterpretationPass in declarative form // applyStaticAnnotations(expression, context, cache, decl); //TODO Null ad hoc DFG implementation/None symbol //DISABLEDFEATURE None value // if (expression.isNone()){ // return SymbolTransient{{Atom(Config::get("clasp.nonevalue"))}}; // } // non initialized(SymbolInvalid) value //void //DFAPass::applyDependencies(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){ // for (SymbolNode &op: cache.operands) { // __context.graph->addDependencyConnection(cache.result, op); // } // // for (SymbolNode &block: cache.blocks) { // __context.graph->addDependencyConnection(cache.result, block); // } // // switch(expression.__state) { // case Expression::IDENT: { // SymbolNode identSymbol = clasp->pack(Attachments::get(expression), context.function->getName() + ":" + expression.getValueString()); // __context.graph->addDependencyConnection(cache.result, identSymbol); // } // // default: break; // } //} //void //DFAPass::applyStaticAnnotations(const Expression& expression, PassContext context, ExpressionCache& cache, const std::string& decl){ // // switch(expression.__state) { // case Expression::NUMBER: // case Expression::STRING: // __context.graph->addAnnotation(cache.result, Expression(Atom("static"))); // break; // // default: break; // } - //} \ No newline at end of file + //} diff --git a/cpp/src/passmanager-bare.cpp b/cpp/src/passmanager-bare.cpp deleted file mode 100644 index 48c2715..0000000 --- a/cpp/src/passmanager-bare.cpp +++ /dev/null @@ -1,84 +0,0 @@ - -#include "passmanager.h" -#include -#include "Parser.h" -#include "clasplayer.h" - -#include -#include - -using namespace xreate; -using namespace std; - -PassManager* -PassManager::prepareForCode(std::string&& code){ - Scanner scanner(reinterpret_cast(code.c_str()), code.size()); - return prepareForCode(&scanner); -} - -PassManager* -PassManager::prepareForCode(FILE* code){ - Scanner scanner(code); - return prepareForCode(&scanner); -} - -PassManager* -PassManager::prepareForCode(Scanner* code){ - Parser parser(code); - parser.Parse(); - assert(!parser.errors->count && "Parser errors"); - - PassManager* man = new PassManager; - AST* ast = new AST(parser.root); - - man->root = ast; - man->clasp = new ClaspLayer(); - - man->clasp->ast = man->root; - man->llvm = new LLVMLayer(man->root); - - return man; -} - -void -PassManager::registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* parent) -{ - __passes.emplace(id, pass); - __passDependencies.emplace(parent, pass); -} - -AbstractPassBase* -PassManager::getPassById(const PassId& id){ - assert(__passes.count(id)); - return __passes[id]; -} - -bool -PassManager::isPassRegistered(const PassId& id){ - return __passes.count(id); -} - -void -PassManager::executePasses(){ - std::list passes{nullptr}; - while (passes.size()){ - AbstractPassBase* parent = passes.front(); - - auto range = __passDependencies.equal_range(parent); - - for (auto i=range.first; i!=range.second; ++i){ - AbstractPassBase* pass = i->second; - - pass->run(); - pass->finish(); - - passes.push_back(pass); - } - - passes.pop_front(); - } -} - - - -PassManager::~PassManager(){} diff --git a/cpp/src/passmanager-full.cpp b/cpp/src/passmanager-full.cpp deleted file mode 100644 index 5bb70b2..0000000 --- a/cpp/src/passmanager-full.cpp +++ /dev/null @@ -1,49 +0,0 @@ -/* - * passmanager-full.cpp - * - * Author: Volodymyr Melnychenko - * Created on January 27, 2017, 7:10 PM - */ - -#include "passmanager.h" -#include "llvmlayer.h" -#include "pass/compilepass.h" -#include "pass/adhocpass.h" -#include "pass/cfapass.h" -#include "pass/dfapass.h" -#include "pass/interpretationpass.h" -#include "pass/versionspass.h" - -using namespace xreate; - -void PassManager::runWithoutCompilation(){ - if (flagIsProcessed) return; - - CFAPass* passCFG = new CFAPass(this); - - //TODO is it really DFGPass needs CFGpass? - this->registerPass(new DFAPass(this), PassId::DFGPass, passCFG); - this->registerPass(passCFG, PassId::CFGPass); - this->registerPass(new AdhocPass(this), PassId::AdhocPass); - this->registerPass(new InterpretationPass(this), PassId::InterpretationPass); - this->registerPass(new VersionsPass(this), PassId::VersionsPass); - - this->executePasses(); - - CompilePass::prepareQueries(clasp); - clasp->run(); - flagIsProcessed = true; -} - -void* -PassManager::run() -{ - runWithoutCompilation(); - - CompilePass* compiler = new CompilePass(this); - compiler->run(); - - llvm->print(); - llvm->initJit(); - return llvm->getFunctionPointer(compiler->getEntryFunction()); -} \ No newline at end of file diff --git a/cpp/src/passmanager.h b/cpp/src/passmanager.h deleted file mode 100644 index 0e67ba0..0000000 --- a/cpp/src/passmanager.h +++ /dev/null @@ -1,57 +0,0 @@ -#ifndef PASSMANAGER_H -#define PASSMANAGER_H - -#include -#include - -//stdio external -struct _IO_FILE; -typedef struct _IO_FILE FILE; - -class Scanner; - -namespace xreate { -class AbstractPassBase; -class ClaspLayer; -class LLVMLayer; -class AST; - -enum class PassId { - CFGPass, - CompilePass, - DFGPass, - EnvironmentTestsPass, - LoggerPass, - AdhocPass, - RulesPass, - InterpretationPass, - VersionsPass -}; - -class PassManager -{ -public: - ~PassManager(); - void*run(); - void runWithoutCompilation(); - void executePasses(); - void registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* prerequisite=nullptr); - AbstractPassBase* getPassById(const PassId& id); - bool isPassRegistered(const PassId& id); - static PassManager* prepareForCode(std::string&& code); - static PassManager* prepareForCode(FILE* code); - - ClaspLayer* clasp; - LLVMLayer* llvm; - AST* root; -private: - //typedef std::multimap FILTERS_STORAGE; - //FILTERS_STORAGE __filters; - std::map __passes; - std::multimap __passDependencies; - bool flagIsProcessed = false; - - static PassManager* prepareForCode(Scanner* code); -}; } - -#endif diff --git a/cpp/src/query/containers.h b/cpp/src/query/containers.h index 35db039..1991f66 100644 --- a/cpp/src/query/containers.h +++ b/cpp/src/query/containers.h @@ -1,84 +1,84 @@ // // Created by pgess on 3/14/15. // #ifndef _XREATE_CONTAINERSQUERY_H_ #define _XREATE_CONTAINERSQUERY_H_ -#include "passmanager.h" +#include "xreatemanager.h" #include "clasplayer.h" #include namespace xreate { namespace containers { enum ImplementationType {SOLID, ON_THE_FLY, LINKED_LIST}; template struct ImplementationRec; template<> struct ImplementationRec { size_t size; }; template<> struct ImplementationRec{ Symbol source; }; struct Implementation; struct ImplementationLinkedList { bool flagIsValid; std::string fieldPointer; Expression terminator; ImplementationLinkedList(const Symbol& source); operator bool() const; Implementation getImplementationData() const; private: Symbol s; }; struct Implementation { typedef boost::variant, ImplementationRec> Variant; const ImplementationType impl; Variant data; static Implementation create(const Symbol &var); static Implementation create(const Symbol& var, const std::string &implSerialized); static Implementation create(const Symbol& var, const Implementation& proto); template const ImplementationRec& extract() const{ const ImplementationRec& rec = boost::get>(data); return rec; } }; class Query : public xreate::IQuery { public: static Implementation queryImplementation(xreate::Symbol const &s); void init(ClaspLayer* clasp); Query(); ~Query(){} private: bool flagIsDataLoaded = false; PassManager *man; }; } template<> struct AttachmentsDict { typedef containers::Implementation Data; static const unsigned int key = 1; }; } #endif //_XREATE_CONTAINERSQUERY_H_ diff --git a/cpp/src/serialization.h b/cpp/src/serialization.h index 08425af..af74e11 100644 --- a/cpp/src/serialization.h +++ b/cpp/src/serialization.h @@ -1,30 +1,30 @@ /* * serialization.h * * Created on: 13 февр. 2016 * Author: pgess */ #ifndef SRC_SERIALIZATION_SERIALIZATION_H_ #define SRC_SERIALIZATION_SERIALIZATION_H_ -#include "serialization/expressionserializer.h" +#include "misc/serialization/expressionserializer.h" namespace xreate { struct RequirementIntegralCode{}; template struct ExpressionSerialization { typedef PackedExpression Code; typedef ExpressionSerializer Serializer; }; template<> struct ExpressionSerialization{ typedef size_t Code; typedef ExpressionSerializerIntegral Serializer; }; } #endif /* SRC_SERIALIZATION_SERIALIZATION_H_ */ diff --git a/cpp/src/xreatemanager.cpp b/cpp/src/xreatemanager.cpp new file mode 100644 index 0000000..b7029c4 --- /dev/null +++ b/cpp/src/xreatemanager.cpp @@ -0,0 +1,123 @@ +/* + * xreatemanager.cpp + * + * Author: pgess + * Created on July 3, 2017, 6:03 PM + */ + +#include "xreatemanager.h" +#include "clasplayer.h" +#include "misc/xreatemanager-decorators.h" +#include "llvmlayer.h" +#include "main/Parser.h" +#include +#include + +namespace xreate { +void +PassManager::registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* parent) +{ + __passes.emplace(id, pass); + __passDependencies.emplace(parent, pass); +} + +AbstractPassBase* +PassManager::getPassById(const PassId& id){ + assert(__passes.count(id)); + return __passes[id]; +} + +bool +PassManager::isPassRegistered(const PassId& id){ + return __passes.count(id); +} + +void +PassManager::executePasses(){ + std::list passes{nullptr}; + while (passes.size()){ + AbstractPassBase* parent = passes.front(); + + auto range = __passDependencies.equal_range(parent); + + for (auto i=range.first; i!=range.second; ++i){ + AbstractPassBase* pass = i->second; + + pass->run(); + pass->finish(); + + passes.push_back(pass); + } + + passes.pop_front(); + } +} + +void +PassManager::prepare(AST* ast){ + root = ast; + clasp = new ClaspLayer(); + clasp->ast = ast; + llvm = new LLVMLayer(ast); +} + +PassManager::~PassManager(){} + +typedef XreateManagerDecoratorFull XreateManagerDecoratorDefault; + +namespace details{ namespace tier2{ + +XreateManager* +XreateManager::prepare(std::string&& code){ + auto man = new XreateManagerImpl; + + man->prepareCode(std::move(code)); + return man; +} + +XreateManager* +XreateManager::prepare(FILE* code){ + auto man = new XreateManagerImpl; + + man->prepareCode(code); + return man; +} +}} + +namespace details { namespace tier1 { + +XreateManager* +XreateManager::prepare(std::string&& code){ + auto man = new XreateManagerImpl; + + man->prepareCode(std::move(code)); + return man; +} + +XreateManager* +XreateManager::prepare(FILE* code){ + auto man = new XreateManagerImpl; + + man->prepareCode(code); + return man; +} + +}} + +XreateManager* +XreateManager::prepare(std::string&& code) { + auto man = new XreateManagerImpl; + + man->prepareCode(std::move(code)); + return man; +} + +XreateManager* +XreateManager::prepare(FILE* code){ + auto man = new XreateManagerImpl; + + man->prepareCode(code); + return man; +} + +} diff --git a/cpp/src/xreatemanager.h b/cpp/src/xreatemanager.h new file mode 100644 index 0000000..7ffb3c3 --- /dev/null +++ b/cpp/src/xreatemanager.h @@ -0,0 +1,122 @@ +#ifndef PASSMANAGER_H +#define PASSMANAGER_H + +#include +#include + +//stdio external +struct _IO_FILE; +typedef struct _IO_FILE FILE; + +namespace xreate { namespace grammar { namespace main { + class Scanner; +}}} + +namespace xreate { +class AbstractPassBase; +class ClaspLayer; +class LLVMLayer; +class AST; + +enum class PassId { + CFGPass, + CompilePass, + DFGPass, + EnvironmentTestsPass, + LoggerPass, + AdhocPass, + RulesPass, + InterpretationPass, + VersionsPass +}; + +class PassManager{ +public: + void prepare(AST* ast); + void registerPass(AbstractPassBase* pass, const PassId& id, AbstractPassBase* prerequisite=nullptr); + AbstractPassBase* getPassById(const PassId& id); + bool isPassRegistered(const PassId& id); + void executePasses(); + + virtual ~PassManager(); + + ClaspLayer* clasp; + LLVMLayer* llvm; + AST* root; + +private: + std::map __passes; + std::multimap __passDependencies; +}; + +namespace details{ namespace tier2{ +class XreateManager: public virtual PassManager{ +public: + virtual ~XreateManager(){}; + + virtual void initPasses()=0; +// virtual void executePasses()=0; + virtual void analyse()=0; + virtual void* run()=0; + + static XreateManager* prepare(std::string&& code); + static XreateManager* prepare(FILE* code); +}; + +template +class XreateManagerImpl: public Decorator { +public: +}; + +}} //namespace details::tier2 + +namespace details{ namespace tier1{ +class XreateManager: public virtual PassManager{ +public: + virtual void analyse()=0; + virtual void* run()=0; + + static XreateManager* prepare(std::string&& code); + static XreateManager* prepare(FILE* code); +}; + +template +class XreateManagerImpl: public XreateManager, public details::tier2::XreateManagerImpl { + typedef details::tier2::XreateManagerImpl PARENT; + + public: + void analyse(){ + PARENT::initPasses(); + PARENT::executePasses(); + PARENT::analyse(); + } + + void* run(){ + return PARENT::run(); + } +}; + +}} //namespace details::tier1 + +class XreateManager: public virtual PassManager{ +public: + virtual void* run()=0; + + static XreateManager* prepare(std::string&& code); + static XreateManager* prepare(FILE* code); +}; + +template +class XreateManagerImpl: public XreateManager, public details::tier1::XreateManagerImpl{ + typedef details::tier1::XreateManagerImpl PARENT; + +public: + void* run(){ + PARENT::analyse(); + return PARENT::run(); + } +}; + +} //namespace xreate + +#endif diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt index ac038d2..8611af2 100644 --- a/cpp/tests/CMakeLists.txt +++ b/cpp/tests/CMakeLists.txt @@ -1,50 +1,51 @@ cmake_minimum_required(VERSION 2.8.11) project(xreate-tests) find_package(GTest REQUIRED) INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS}) INCLUDE_DIRECTORIES("/usr/include/libxml2") INCLUDE_DIRECTORIES($) # TESTS #========================= FIND_PACKAGE (LLVM REQUIRED) message("LLVM_LIBRARY_DIRS: " ${LLVM_LIBRARY_DIRS}) link_directories(${LLVM_LIBRARY_DIRS}) set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug) link_directories(${LIBCLASP_PATH}) #aux_source_directory(. TEST_FILES) set(TEST_FILES main.cpp + modules.cpp adhoc.cpp attachments.cpp ast.cpp cfa.cpp dfa.cpp compilation.cpp ExpressionSerializer.cpp externc.cpp context.cpp types.cpp vendorAPI/clangAPI.cpp vendorAPI/xml2.cpp vendorAPI/json.cpp containers.cpp context.cpp interpretation.cpp loops.cpp #supplemental/versions-algorithm-data_dependency.cpp effects-versions.cpp ) add_executable(${PROJECT_NAME} ${TEST_FILES}) target_link_libraries(${PROJECT_NAME} xreate ${GTEST_LIBRARIES} pthread xml2 gcov) add_custom_target (coverage COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/code-coverage.sh WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) diff --git a/cpp/tests/ExpressionSerializer.cpp b/cpp/tests/ExpressionSerializer.cpp index c5dc128..dae45e5 100644 --- a/cpp/tests/ExpressionSerializer.cpp +++ b/cpp/tests/ExpressionSerializer.cpp @@ -1,65 +1,65 @@ /* * testExpressionSerializer.cpp * * Created on: Jan 4, 2016 * Author: pgess */ -#include "serialization/expressionserializer.h" +#include "misc/serialization/expressionserializer.h" #include "serialization.h" #include "ast.h" #include "gtest/gtest.h" using namespace xreate; using namespace std; TEST(ExpressionSerializer, pack1){ PackedExpression x; x << std::make_pair(0xA1, 0x100); size_t* storage = reinterpret_cast (*x); ASSERT_EQ(0xA100000000000000, *storage); x << std::make_pair(0x23456, 0x100000); ASSERT_EQ(0xA123456000000000, *storage); x << std::make_pair(0x7654321, 0x10000000); ASSERT_EQ(0xA123456765432100, *storage); x << std::make_pair(0xABBA, 0x10000); storage = reinterpret_cast (*x); ASSERT_EQ(0xA1234567654321AB, *storage); ASSERT_EQ(0xBA00000000000000, *(storage+1)); } TEST(ExpressionSerializer, serialize1){ Expression a(Operator::CALL, {Expression(string("a")), Expression(string("a"))}); Expression b(Operator::CALL, {Expression(string("a")), Expression(string("b"))}); ExpressionSerializer serializer(vector{a, b}); PackedExpression packA = serializer.getId(a); PackedExpression packB = serializer.getId(b); PackedExpression packA2 = serializer.getId(a); ASSERT_EQ(packA, packA2); ASSERT_NE(packA, packB); } TEST(ExpressionSerializer, serialize2){ Expression a(Operator::CALL, {Expression(string("a")), Expression(string("a"))}); Expression b(Operator::CALL, {Expression(string("a")), Expression(string("b"))}); Expression c(Atom("c")); typedef ExpressionSerialization::Serializer Serializer; Serializer serializer(vector{a, b}); ASSERT_EQ(2, serializer.size()); ASSERT_EQ(1, serializer.count(a)); ASSERT_EQ(1, serializer.count(b)); ASSERT_EQ(0, serializer.count(c)); Serializer serializer2(move(serializer)); ASSERT_EQ(1, serializer2.count(a)); } diff --git a/cpp/tests/adhoc.cpp b/cpp/tests/adhoc.cpp index 55b586e..710fd4e 100644 --- a/cpp/tests/adhoc.cpp +++ b/cpp/tests/adhoc.cpp @@ -1,196 +1,194 @@ /* * adhoc-exceptions.cpp * * Created on: Nov 19, 2015 * Author: pgess */ class Adhoc_pass_Adhoc1_Test; #define FRIENDS_ADHOC \ friend class ::Adhoc_pass_Adhoc1_Test; #include "ast.h" -#include "passmanager.h" +#include "xreatemanager.h" #include "gtest/gtest.h" #include #include #include #include #include "pass/adhocpass.h" #include "pass/compilepass.h" #include "llvmlayer.h" using namespace xreate; using namespace std; TEST(Adhoc, ast_operatorAdhoc1){ - PassManager* man = PassManager::prepareForCode ( + XreateManager* man = XreateManager::prepare ( "test = function:: int {\n" " ad hoc exception(nonImplemented)\n" "}"); Expression subject = man->root->findFunction("test")->getEntryScope()->getBody(); ASSERT_EQ(Operator::ADHOC, subject.op); Expression exception = AdhocExpression(subject).getCommand(); ASSERT_EQ("exception", exception.getValueString()); } TEST(Adhoc, ast_schemeAdhoc1){ - PassManager* man = PassManager::prepareForCode ( + XreateManager* man = XreateManager::prepare ( "interface(adhoc){\n" " pre function expectNoErrors:: bool {\n" " case (Error) {false}\n" " case (Success) {true}\n" " }\n" " }"); assert(man->root->__interfacesData.count(ASTInterface::Adhoc)); Expression adhocData = man->root->__interfacesData.find(ASTInterface::Adhoc)->second; ASSERT_EQ(Operator::SWITCH, adhocData.operands[0].op); } TEST(Adhoc, pass_Adhoc1){ - PassManager* man = PassManager::prepareForCode ( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare ( "interface(adhoc){\n" " pre function expectNoErrors:: bool {\n" " case (Error) {false}\n" " case (Success) {true}\n" " }\n" "}\n" "main = function::int; entry {0} \n" ); - man->runWithoutCompilation(); + man->analyse(); AdhocPass* pass = reinterpret_cast(man->getPassById(PassId::AdhocPass)); EXPECT_TRUE(pass->__schemes.size() > 0); AdhocScheme* scheme = pass->__schemes.begin()->second; EXPECT_EQ("expectNoErrors", scheme->getName()); } TEST(Adhoc, full_1){ - PassManager* man = PassManager::prepareForCode ( - " import raw (\"core/control-context.lp\")\n" + XreateManager* man = XreateManager::prepare ( + " import raw (\"core/control-context.lp\").\n" " interface(adhoc){\n" " pre function expectNoErrors:: bool {\n" " case (error) {false}\n" " case (success) {true}\n" " }\n" " }\n" " test1 = pre function {\n" " context:: expectNoErrors." " ad hoc success\n" " }" "main = function::bool;entry {\n" " test1()\n" " }"); bool (*main)() = (bool (*)()) man->run(); bool result = main(); ASSERT_EQ(true, result); } TEST(Adhoc, full_2){ - PassManager* man = PassManager::prepareForCode ( - " import raw (\"core/control-context.lp\")\n" + XreateManager* man = XreateManager::prepare ( + " import raw (\"core/control-context.lp\").\n" " interface(adhoc){\n" " pre function expectNoErrors:: bool {\n" " case (error) {false}\n" " case (success) {true}\n" " }\n" " pre function expectErrors:: bool {\n" " case (error) {true}\n" " case (success) {false}\n" " }\n" " }\n" " test1 = pre function {\n" " context:: expectNoErrors." " ad hoc success\n" " }\n" " test2 = pre function {\n" " context:: expectErrors." " ad hoc success\n" " }" "main = function::bool;entry {\n" " test1() != test2()\n" "}"); bool (*main)() = (bool (*)()) man->run(); bool result = main(); ASSERT_EQ(true, result); } //TODO adhoc type. FDecl sets wrong type in prefunc case(invalid type)) TEST(Adhoc, full_contextExpectNoErrrors){ - PassManager* man = PassManager::prepareForCode ( - "import raw (\"core/control-context.lp\")\n" + XreateManager* man = XreateManager::prepare ( + "import raw (\"core/control-context.lp\").\n" "interface(extern-c){\n" " xml2 = library:: pkgconfig(\"libxml-2.0\").\n" " \n" " include {\n" " xml2 = [\"stdlib.h\"]\n" " }.\n" "}" "interface(adhoc){\n" " pre function expectNoErrors:: bool {\n" " case (error) {false}\n" " case (success) {true}\n" " }\n" "}\n" "expectErrorCode = pre function(x::int){\n" " if (x==0)::undef {ad hoc success}\n" " else {ad hoc error}\n" "}\n" "main = function::bool; entry {\n" " context:: expectNoErrors." " expectErrorCode(system(\"ls -la\"))\n" "}" ); int (*main)() = (int (*)()) man->run(); ASSERT_EQ(1, main()); } //DEBT Implement compilation of switch adhoc TEST(Adhoc, ast_switchAdhoc1){ - PassManager* man = PassManager::prepareForCode ( + XreateManager* man = XreateManager::prepare ( "test1 = function:: bool {\n" " x = 0. \n" " switch ad hoc (x:: errors)\n" " case (error) {0}\n" " case (success) {1}\n" "\n" "}" ); Expression eSwitch = man->root->findFunction("test1")->getEntryScope()->getBody(); EXPECT_EQ(Operator::SWITCH_ADHOC, eSwitch.op); EXPECT_EQ(3, eSwitch.operands.size()); EXPECT_EQ(1, eSwitch.tags.size()); EXPECT_EQ("errors", eSwitch.tags.begin()->first); Expression eCondition = eSwitch.getOperands()[0]; EXPECT_EQ("x", eCondition.getValueString()); -} - - +} \ No newline at end of file diff --git a/cpp/tests/ast.cpp b/cpp/tests/ast.cpp index d1fb31f..0720184 100644 --- a/cpp/tests/ast.cpp +++ b/cpp/tests/ast.cpp @@ -1,68 +1,68 @@ /* * ast.cpp * * Created on: Jun 11, 2015 * Author: pgess */ #include "gtest/gtest.h" -#include "passmanager.h" -#include "Parser.h" +#include "xreatemanager.h" +#include "main/Parser.h" using namespace std; -using namespace xreate; +using namespace xreate::grammar::main; TEST(AST, Containers1){ FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r"); Scanner scanner(input); Parser parser(&scanner); parser.Parse(); assert(!parser.errors->count && "Parser errors"); fclose(input); } TEST(AST, InterfacesDataCFA) { - PassManager* man = PassManager::prepareForCode + XreateManager* man = XreateManager::prepare ("interface(cfa){\n" " operator map :: annotation1.\n" "}"); auto answer = man->root->__interfacesData.equal_range(CFA); EXPECT_EQ(1, std::distance(answer.first, answer.second)); Expression&& scheme = move(answer.first->second); EXPECT_EQ(Operator::MAP, scheme.op); EXPECT_EQ("annotation1", scheme.getOperands().at(0).getValueString()); } TEST(AST, syntax_recognizeIdentifiers){ - PassManager* man = PassManager::prepareForCode(R"Code( + XreateManager* man = XreateManager::prepare(R"Code( test= function(a:: num):: num; entry { a = b:: int. b = 8:: int. a } )Code"); } TEST(AST, syntax_operatorIndex){ - PassManager* man = PassManager::prepareForCode(R"Code( + XreateManager* man = XreateManager::prepare(R"Code( test= function(a:: num):: num; entry { b = a[1]. b } )Code"); } TEST(AST, DISABLED_InterfacesDataDFA){ } TEST(AST, DISABLED_InterfacesDataExtern){ } //TODO xreate.atg: replace all Type<> as ExprAnnotations<> diff --git a/cpp/tests/cfa.cpp b/cpp/tests/cfa.cpp index 42f7c4f..5d4f84a 100644 --- a/cpp/tests/cfa.cpp +++ b/cpp/tests/cfa.cpp @@ -1,119 +1,119 @@ /* * testsCFG.cpp * * Created on: Jul 17, 2015 * Author: pgess */ -#include "passmanager.h" +#include "xreatemanager.h" #include "pass/dfapass.h" #include "pass/cfapass.h" #include "analysis/DominatorsTreeAnalysisProvider.h" #include "gtest/gtest.h" #include #include using namespace xreate; using namespace std; TEST(CFA, testFunctionAnnotationsClasp){ string&& program = "f2 = function::int; annotationF2 {\n" " 0\n" "}\n" "\n" "f1 = function:: int; entry; annotationF1 {\n" " f2() + 10\n" "}"; - PassManager* man = PassManager::prepareForCode(move(program)); - man->runWithoutCompilation(); + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare(move(program)); + man->analyse(); ClaspLayer::ModelFragment answer = man->clasp->query("annotationF1"); int countNoneValue = 0; if (answer) countNoneValue = std::distance(answer->first, answer->second); EXPECT_EQ(1, countNoneValue); answer = man->clasp->query("annotationF2"); countNoneValue = 0; if (answer) countNoneValue = std::distance(answer->first, answer->second); EXPECT_EQ(1, countNoneValue); } TEST(CFA, testLoopContextExists){ - PassManager* man = PassManager::prepareForCode ( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare ( "interface(cfa){\n" " operator fold:: annotation1.\n" "}\n" "\n" "main = function:: int; entry {\n" " x = [1..10]:: [int].\n" " sum = loop fold (x->el:: int, 0->sum):: int {\n" " el + sum + f1()\n" " }. \n" " sum\n" "}" "case context:: annotation1 {" " f1 = function::int {\n" " x = 0:: int. " " x\n" " }" "}" ); - man->runWithoutCompilation(); + man->analyse(); ClaspLayer::ModelFragment model = man->clasp->query("annotation1"); ScopePacked scopeIdActual = std::get<0>(ClaspLayer::parse(model->first->second)); CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope(); const Expression& exprSum = scopeEntry->getDeclaration(scopeEntry->getSymbol("sum")); CodeScope* scopeExpected = exprSum.blocks.front(); ScopePacked scopeIdExpected = man->clasp->pack(scopeExpected); ASSERT_EQ(scopeIdExpected, scopeIdActual); } TEST(CFA, CFGRoots){ std::string program = R"CODE( main = function::int{a()+ b()} a= function::int {c1() + c2()} b= function::int {c2()} c1=function::int{0} c2=function::int{0} )CODE"; - boost::scoped_ptr manager - (PassManager::prepareForCode(move(program))); + boost::scoped_ptr manager + (XreateManager::prepare(move(program))); manager->registerPass(new CFAPass(manager.get()) , PassId::CFGPass); manager->executePasses(); manager->clasp->run(); DominatorsTreeAnalysisProvider domProvider; domProvider.run(manager->clasp); DominatorsTreeAnalysisProvider::Dominators expectedFDom= { {0, {0, 9}} ,{1, {1, 4}} ,{2, {7, 8}} ,{3, {2, 3}} ,{4, {5, 6}} }; DominatorsTreeAnalysisProvider::Dominators expectedPostDom= { {0, {5, 6}} ,{1, {3, 4}} ,{2, {8, 9}} ,{3, {1, 2}} ,{4, {7, 10}} }; ASSERT_EQ(expectedFDom, domProvider.getForwardDominators()); ASSERT_EQ(expectedPostDom, domProvider.getPostDominators()); } diff --git a/cpp/tests/compilation.cpp b/cpp/tests/compilation.cpp index 95b96b6..8c00e14 100644 --- a/cpp/tests/compilation.cpp +++ b/cpp/tests/compilation.cpp @@ -1,37 +1,37 @@ -#include "passmanager.h" +#include "xreatemanager.h" #include "gtest/gtest.h" using namespace xreate; //DEBT implement no pkgconfig ways to link libs //TOTEST FunctionUnit::compileInline TEST(Compilation, DISABLED_functionInline1){ } TEST(Compilation, functionEntry1){ - std::unique_ptr program(PassManager::prepareForCode( + std::unique_ptr program(XreateManager::prepare( "func1 = function(a:: int):: int {a+8} \ func2 = function::int; entry {12 + func1(4)} \ ")); void* entryPtr = program->run(); int (*entry)() = (int (*)())(intptr_t)entryPtr; int answer = entry(); ASSERT_EQ(24, answer); } TEST(Compilation, full_IFStatementWithVariantType){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( "Color = type variant (RED, BLUE, GREEN).\n" "\n" " main = function(x::int):: bool; entry {\n" " color = if (x == 0 )::Color {RED} else {BLUE}.\n" " if (color == BLUE)::bool {true} else {false}\n" " }" ); bool (*main)(int) = (bool (*)(int)) man->run(); ASSERT_FALSE(main(0)); ASSERT_TRUE(main(1)); } diff --git a/cpp/tests/containers.cpp b/cpp/tests/containers.cpp index 7037a8d..75fbfc5 100644 --- a/cpp/tests/containers.cpp +++ b/cpp/tests/containers.cpp @@ -1,109 +1,109 @@ /* * containers.cpp * * Created on: Jun 9, 2015 * Author: pgess */ -#include "passmanager.h" +#include "xreatemanager.h" #include "query/containers.h" -#include "Parser.h" +#include "main/Parser.h" #include "gtest/gtest.h" using namespace std; -using namespace xreate; -using namespace containers; +using namespace xreate::grammar::main; +using namespace xreate::containers; TEST(Containers, ListAsArray){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( R"Code( main = function(x:: int):: int;entry { a = [1, 2, 3]:: [int]. a[x] } )Code" ); void* mainPtr = man->run(); int (*main)(int) = (int (*)(int))mainPtr; ASSERT_EQ(2, main(1)); delete man; } TEST(Containers, ListAsArray2){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( R"Code( // CONTAINERS interface(dfa) { operator map:: (op(seqaccess)) -> impl(solid). operator list_range:: ()->impl(on_the_fly). operator list:: ()->impl(solid). operator fold:: (op(seqaccess)). operator index:: (op(randaccess)). } - import raw("core/containers.lp") + import raw("core/containers.lp"). main = function:: int;entry { a= [1, 2, 3]:: [int]. b= loop map(a->el:: int):: [int]{ 2 * el }. sum = loop fold(b->el:: int, 0->acc):: int { acc + el }. sum } )Code" ); void* mainPtr = man->run(); int (*main)() = (int (*)())mainPtr; ASSERT_EQ(12, main()); delete man; } TEST(Containers, ContanierLinkedList1){ FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r"); assert(input != nullptr); Scanner scanner(input); Parser parser(&scanner); parser.Parse(); - AST& ast = parser.root; - CodeScope* body = ast.findFunction("test")->getEntryScope(); + AST* ast = parser.root->finalize(); + CodeScope* body = ast->findFunction("test")->getEntryScope(); const Symbol symb_chilrenRaw{body->getSymbol("childrenRaw"), body}; containers::ImplementationLinkedList iLL(symb_chilrenRaw); ASSERT_EQ(true, static_cast(iLL)); ASSERT_EQ("next", iLL.fieldPointer); Implementation impl = Implementation::create(symb_chilrenRaw); ASSERT_NO_FATAL_FAILURE(impl.extract()); ImplementationRec recOnthefly = impl.extract(); ASSERT_EQ(symb_chilrenRaw, recOnthefly.source); } TEST(Containers, Implementation_LinkedListFull){ FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r"); assert(input != nullptr); - std::unique_ptr program(PassManager::prepareForCode(input)); + std::unique_ptr program(XreateManager::prepare(input)); void* mainPtr = program->run(); int (*main)() = (int (*)())(intptr_t)mainPtr; int answer = main(); ASSERT_EQ(17, answer); fclose(input); } diff --git a/cpp/tests/context.cpp b/cpp/tests/context.cpp index 796fee1..92b19fc 100644 --- a/cpp/tests/context.cpp +++ b/cpp/tests/context.cpp @@ -1,496 +1,494 @@ /* * frame-context.cpp * * Created on: Dec 3, 2015 * Author: pgess */ -#include "passmanager.h" +#include "xreatemanager.h" #include "query/context.h" #include "gtest/gtest.h" #include #include using namespace xreate; TEST(Context, frame_Context1){ - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( + " import raw (\"core/control-context.lp\").\n" " compute = function::int {\n" " 0\n" " }\n" " computeFast = function:: int {\n" " context:: computation(fast).\n" " compute()\n" " }\n" " computePrecisely = function:: int {\n" " context:: computation(precise). \n" " compute()\n" " }\n" "test = function(cmnd:: int):: int; entry {\n" " context:: arithmetic(iee754). \n" " if (cmnd > 0)::int {computePrecisely()} else {computeFast()} \n" "}\n" ); ContextQuery* query = (ContextQuery*) man->clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery); - man->runWithoutCompilation(); + man->analyse(); CodeScope* scopeTestC = man->root->findFunction("compute")->getEntryScope(); const Domain& context = query->getContext(man->clasp->pack(scopeTestC)); int contextSize = context.size(); EXPECT_EQ(1, contextSize); //arithmetic(iee754) } TEST(Context, contextAsRequirementSuccessful1){ - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" + XreateManager* man = XreateManager::prepare( + " import raw (\"core/control-context.lp\").\n" " case context::safe {\n" " funcSensitive = function::int {\n" " 0\n" " }}\n" " test = function:: int; entry {\n" " context:: safe; test.\n" " funcSensitive()\n" " }\n" ); int (*main)() = (int (*)()) man->run(); ASSERT_EQ(0, main()); } TEST(Context, contextAsRequirementFailed){ - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" + XreateManager* man = XreateManager::prepare( + " import raw (\"core/control-context.lp\").\n" " case context::safe {\n" " funcSensitive = function::int {\n" " 0\n" " }}\n" " test = function:: int; entry {\n" " context:: non_safe; test.\n" " funcSensitive()\n" " }\n" ); ASSERT_DEATH(man->run(), "findFunction"); } TEST(Context, ContextPropagationNested){ - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" + XreateManager* man = XreateManager::prepare( + " import raw (\"core/control-context.lp\").\n" " case context::safe {\n" " square = function(x:: int) ::int {\n" " x * x\n" " }}\n" " test = function:: int; entry {\n" " context:: safe; test.\n" " range = [1..10]:: [int]. \n" " loop fold(range->x::int, 0->acc):: int { \n" " acc + square(x) \n" " } \n" " }\n" ); int (*main)() = (int (*)()) man->run(); ASSERT_EQ(385, main()); } TEST(Context, ContextPropagationNestedInterfunction){ - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" + XreateManager* man = XreateManager::prepare( + " import raw (\"core/control-context.lp\").\n" " case context::toMillimeters {\n" " convertConcrete = function(source:: num)::num {\n" " 10 * source \n" " }\n" " }\n" " case context::toInches {\n" " convertConcrete = function(source:: num)::num {\n" " 2 * source \n" " }\n" " }\n" "convert= function(source:: num):: num { \n" "convertConcrete(source) \n" "} \n" "test = function(source:: num):: num; entry {\n" " context:: toMillimeters.\n" " convert(1)\n" "}\n" ); int (*main)(int) = (int (*)(int)) man->run(); ASSERT_EQ(10, main(1)); } TEST(Context, full_ContextBasedFunctionSpecialization){ - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" + XreateManager* man = XreateManager::prepare( + " import raw (\"core/control-context.lp\").\n" " case context::toMillimeters {\n" " convert = function(source:: num)::num {\n" " 10 * source \n" " }\n" " }\n" " case context::toInches {\n" " convert = function(source:: num)::num {\n" " 2 * source \n" " }\n" " }\n" "test = function(vrnt:: int)::int; entry {\n" " switch(vrnt):: int\n" " case (0) {\n" " context:: toMillimeters.\n" " convert(1)\n" " }\n" "\n" " case (1) {\n" " context:: toInches.\n" " convert(1)\n" " }\n" " case default {0}\n" " }" ); int (*main)(int) = (int (*)(int)) man->run(); ASSERT_EQ(10, main(0)); ASSERT_EQ(2, main(1)); } TEST(Context, full_RuleContext){ /* "rule context:: childs(Child)\n" " case artefact(Item)\n" " {\n" " artefact_depends(Item, Child)\n" " }"; */ - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" + XreateManager* man = XreateManager::prepare( + " import raw (\"core/control-context.lp\").\n" " case context:: toMilli {\n" " convert = function(length::int)::int{\n" " 10 * length\n" " }\n" " }\n" "\n" " case context:: toCenti {\n" " convert = function(length::int)::int{\n" " length\n" " }\n" " }\n" "\n" " main=function::int; entry {\n" " context:: output(milli).\n" "\n" " rule context::toMilli\n" " case (output(milli)) {truth}\n" "\n" " convert(1)\n" " }" ); man->clasp->addRawScript("truth."); int (*entry)() = (int (*)()) man->run(); ASSERT_EQ(10, entry()); } TEST(Context, full_InheritedRuleContext){ - PassManager* man = PassManager::prepareForCode( -" import raw (\"core/control-context.lp\") \n" + XreateManager* man = XreateManager::prepare( +" import raw (\"core/control-context.lp\"). \n" " case context:: toMilli {\n" " convert = function(length::int)::int{\n" " 10 * length\n" " }\n" " }\n" " case context:: toCenti {\n" " convert = function(length::int)::int{\n" " length\n" " }\n" " }\n" "\n" "main = function(comm:: num)::num; entry{\n" " rule context::X case (output(X)) {truth}\n" "\n" " switch (comm)::num \n" " case (0) {\n" " context:: output(toMilli).\n" " convert(1)\n" " }\n" " case default {\n" " context:: output(toCenti).\n" " convert(1)\n" " }\n" " }"); man->clasp->addRawScript("truth."); int (*entry)(int) = (int (*)(int)) man->run(); ASSERT_EQ(10, entry(0)); ASSERT_EQ(1, entry(1)); } TEST(Context, full_LateContext){ - PassManager* man = PassManager::prepareForCode( - "import raw (\"core/control-context.lp\")\n" - - " convert = function(length:: num)::num{\n" - " 0\n" - " }\n" - - "case context:: milli {\n" - " convert = function(length:: num)::num{\n" - " 1000 * length\n" - " }\n" - "}\n" - "\n" - "case context:: centi {\n" - " convert = function(length:: num)::num{\n" - " 100 * length\n" - " }\n" - "}\n" - "\n" - "calculate = function(length:: num)::num {\n" - " convert(length)\n" - "}\n" - "\n" - "main = function(com:: num):: num; entry {\n" - " switch (com):: num \n" - " case (0) {\n" - " context:: milli.\n" - " calculate(1)\n" - " }\n" - "\n" - " case default{\n" - " context:: centi. \n" - " calculate(1)\n" - " }\n" - "}"); - - man->runWithoutCompilation(); - ContextQuery* queryContext = reinterpret_cast(man->clasp->getQuery(QueryId::ContextQuery)); - Expression exprSwitch = man->root->findFunction("main")->__entry->getBody(); - CodeScope* blockDefault = man->root->findFunction("main")->__entry->getBody().operands[1].blocks.front(); - ScopePacked blockDefaultId = man->clasp->pack(blockDefault); - const Domain& domDefault = queryContext->getContext(blockDefaultId); - ASSERT_EQ(1, domDefault.count(Expression(Atom("centi")))); - - std::list variants = man->root->getFunctionVariants("convert"); - for (ManagedFnPtr f: variants){ - const Expression guard = f->guardContext; - bool result = (guard.getValueString() == "centi" || guard.getValueString() == "milli" || !guard.isValid()); - ASSERT_TRUE(result); - } - - const FunctionDemand& demMain = queryContext->getFunctionDemand("main"); - ASSERT_EQ(0, demMain.size()); - - const FunctionDemand& demCalculate = queryContext->getFunctionDemand("calculate"); - ASSERT_EQ(1, demCalculate.size()); - - int (*entry)(int) = (int (*)(int)) man->run(); - ASSERT_EQ(1000, entry(0)); - ASSERT_EQ(100, entry(1)); + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( + "import raw (\"core/control-context.lp\").\n" + + " convert = function(length:: num)::num{\n" + " 0\n" + " }\n" + + "case context:: milli {\n" + " convert = function(length:: num)::num{\n" + " 1000 * length\n" + " }\n" + "}\n" + "\n" + "case context:: centi {\n" + " convert = function(length:: num)::num{\n" + " 100 * length\n" + " }\n" + "}\n" + "\n" + "calculate = function(length:: num)::num {\n" + " convert(length)\n" + "}\n" + "\n" + "main = function(com:: num):: num; entry {\n" + " switch (com):: num \n" + " case (0) {\n" + " context:: milli.\n" + " calculate(1)\n" + " }\n" + "\n" + " case default{\n" + " context:: centi. \n" + " calculate(1)\n" + " }\n" + "}"); + + man->analyse(); + ContextQuery* queryContext = reinterpret_cast(man->clasp->getQuery(QueryId::ContextQuery)); + Expression exprSwitch = man->root->findFunction("main")->__entry->getBody(); + CodeScope* blockDefault = man->root->findFunction("main")->__entry->getBody().operands[1].blocks.front(); + ScopePacked blockDefaultId = man->clasp->pack(blockDefault); + const Domain& domDefault = queryContext->getContext(blockDefaultId); + ASSERT_EQ(1, domDefault.count(Expression(Atom("centi")))); + + std::list variants = man->root->getFunctionVariants("convert"); + for (ManagedFnPtr f: variants){ + const Expression guard = f->guardContext; + bool result = (guard.getValueString() == "centi" || guard.getValueString() == "milli" || !guard.isValid()); + ASSERT_TRUE(result); + } + + const FunctionDemand& demMain = queryContext->getFunctionDemand("main"); + ASSERT_EQ(0, demMain.size()); + + const FunctionDemand& demCalculate = queryContext->getFunctionDemand("calculate"); + ASSERT_EQ(1, demCalculate.size()); + + int (*entry)(int) = (int (*)(int)) man->run(); + ASSERT_EQ(1000, entry(0)); + ASSERT_EQ(100, entry(1)); } TEST(Context, loopContextExists){ - PassManager* man = PassManager::prepareForCode ( - "import raw (\"core/control-context.lp\")\n" + XreateManager* man = XreateManager::prepare ( + "import raw (\"core/control-context.lp\").\n" "interface(cfa){\n" " operator fold:: annotation1.\n" "}\n" "\n" "main = function:: int; entry {\n" " x = [1..10]:: [int].\n" " sum = loop fold (x->el:: int, 0->sum):: int {\n" " el + sum + f1()\n" " }. \n" " sum\n" "}" "case context:: annotation1 {" " f1 = function::int {\n" " x = 0:: int. " " x\n" " }" "}" ); man->run(); } TEST(Context, pathDependentContext){ std::string program = R"CODE( -import raw("core/control-context.lp") +import raw("core/control-context.lp"). convert = function(length:: num) :: num { 0 } case context:: convert(milli, meters) { convert = function(length:: num) :: num { 1000 * length } } case context:: convert(centi, meters) { convert = function(length:: num) :: num { 100 * length } } case context:: convert(centi, kilo) { convert = function(length:: num) :: num { 100000 * length } } case context:: convert(milli, kilo) { convert = function(length:: num) :: num { 1000000 * length } } main = function(value::num, unitsInput::num, unitsOutput::num)::num; entry{ switch (unitsInput)::num case (0) { test_fromMilli(value, unitsOutput) } case (1) { test_fromCenti(value, unitsOutput) } case default {0} } test_fromCenti = function(value::num, output::num)::num{ context:: input(centi). switch(output):: num case (0) { toMeters(value) } case (1) { toKilo(value) } case default {0} } test_fromMilli = function(value::num, output::num)::num{ context:: input(milli). switch(output):: num case (0) { toMeters(value) } case (1) { toKilo(value) } case default {0} } toMeters = function(value::num)::num { rule context:: convert(X, meters) case (input(X)) {truth} doConvert(value) } toKilo = function(value::num)::num { rule context:: convert(X, kilo) case (input(X)) {truth} doConvert(value) } doConvert = function(value::num)::num{ convert(value) })CODE"; - boost::scoped_ptr man(PassManager::prepareForCode(move(program))); + boost::scoped_ptr man(details::tier1::XreateManager::prepare(move(program))); man->clasp->addRawScript("truth."); - man->runWithoutCompilation(); + man->analyse(); int (*test)(int, int, int) = (int (*)(int, int, int))man->run(); enum {INPUT_MILLI, INPUT_CENTI}; enum {OUTPUT_METERS, OUTPUT_KILO}; ASSERT_EQ(1000000, test(1, INPUT_MILLI, OUTPUT_KILO)); ASSERT_EQ(200, test(2, INPUT_CENTI, OUTPUT_METERS)); } //TODO recover context loop and enable the test TEST(Context, DISABLED_full_LoopContext){ - - PassManager* man = PassManager::prepareForCode( - " import raw (\"core/control-context.lp\")\n" - " case context:: a {\n" - " print = function:: string {\n" - " \"a\"\n" - " }}\n" - "\n" - " case context:: b {\n" - " print = function:: string {\n" - " \"b\"\n" - " }}\n" - "\n" - " case context:: c {\n" - " print = function:: string {\n" - " \"c\"\n" - " }}\n" - "\n" - " case context:: d {\n" - " print = function:: string {\n" - " \"d\"\n" - " }}\n" - "\n" - " start = function(command::int)::string; entry {\n" - " switch (command) :: string \n" - " case (0) {\n" - " context:: print(a); print(b); print(d).\n" - "\n" - " loop context (\"print\") {\n" - " print()\n" - " }\n" - " }\n" - "\n" - " case default {\n" - " context:: print(c).\n" - " loop context (\"print\") {\n" - " print()\n" - " }\n" - " }\n" - " }"); - - - char* (*main)(int) =(char* (*)(int)) man->run(); - ASSERT_STREQ("c", main(1)); - ASSERT_STREQ("a", main(0)); -} - + XreateManager* man = XreateManager::prepare( + " import raw (\"core/control-context.lp\")\n" + " case context:: a {\n" + " print = function:: string {\n" + " \"a\"\n" + " }}\n" + "\n" + " case context:: b {\n" + " print = function:: string {\n" + " \"b\"\n" + " }}\n" + "\n" + " case context:: c {\n" + " print = function:: string {\n" + " \"c\"\n" + " }}\n" + "\n" + " case context:: d {\n" + " print = function:: string {\n" + " \"d\"\n" + " }}\n" + "\n" + " start = function(command::int)::string; entry {\n" + " switch (command) :: string \n" + " case (0) {\n" + " context:: print(a); print(b); print(d).\n" + "\n" + " loop context (\"print\") {\n" + " print()\n" + " }\n" + " }\n" + "\n" + " case default {\n" + " context:: print(c).\n" + " loop context (\"print\") {\n" + " print()\n" + " }\n" + " }\n" + " }"); + + + char* (*main)(int) =(char* (*)(int)) man->run(); + ASSERT_STREQ("c", main(1)); + ASSERT_STREQ("a", main(0)); +} \ No newline at end of file diff --git a/cpp/tests/dfa.cpp b/cpp/tests/dfa.cpp index c8bc714..53deb4e 100644 --- a/cpp/tests/dfa.cpp +++ b/cpp/tests/dfa.cpp @@ -1,14 +1,14 @@ /* * DFGtests.cpp * * Created on: Jul 23, 2015 * Author: pgess */ -#include "passmanager.h" +#include "xreatemanager.h" #include "pass/dfapass.h" #include "gtest/gtest.h" using namespace xreate; using namespace std; //DEBT dfa tests: dfa scheme, dfa scheme + return value annoation (example: script/testpass/containers...) diff --git a/cpp/tests/effects-versions.cpp b/cpp/tests/effects-versions.cpp index 3ca9fb4..95e22c7 100644 --- a/cpp/tests/effects-versions.cpp +++ b/cpp/tests/effects-versions.cpp @@ -1,276 +1,276 @@ /* * Created on: Dec 16, 2016 * Author: pgess */ #include "pass/versionspass.h" -#include "passmanager.h" +#include "xreatemanager.h" #include "gtest/gtest.h" using namespace xreate; TEST(Effects, syntax_versions_1){ - PassManager* man = PassManager::prepareForCode(R"Code( + XreateManager* man = XreateManager::prepare(R"Code( test= function(a:: num):: num; entry { x= b[8]. b = 5:: num. x{1} = a:: num. x{1} + a } )Code"); } TEST(Effects, analysis_versions_1){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( R"Code( test= function:: num; entry { x{0}= 3:: int. x{1} = x{0} + 1. x{1} } )Code"); VersionsPass* pass = new VersionsPass(man); pass->run(); VersionsGraph graph = pass->getResultGraph(); ASSERT_TRUE(graph.validate()); } TEST(Effects, analysis_versions_2){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( R"Code( test= function(a:: num):: num; entry { x{0}= 3:: int. b = [1, 2, x{0}]. x{1} = b[2]. x{1} + a } )Code"); VersionsPass* pass = new VersionsPass(man); pass->run(); VersionsGraph graph = pass->getResultGraph(); ASSERT_TRUE(graph.validate()); } TEST(Effects, analysis_versions_2_1_fail){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( R"Code( test= function(a:: num):: num; entry { x{0}= 5:: int. b = x{0}. x{1} = 2. b + x{1} } )Code"); VersionsPass* pass = new VersionsPass(man); pass->run(); VersionsGraph graph = pass->getResultGraph(); graph.__debug_print(std::cout); ASSERT_FALSE(graph.validate()); } TEST(Effects, analysis_versions_2_2){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( R"Code( test= function(a:: num):: num; entry { x{0}= 5:: int. b = intrinsic copy(x{0}). x{1} = 2. b + x{1} } )Code"); VersionsPass* pass = new VersionsPass(man); pass->run(); VersionsGraph graph = pass->getResultGraph(); graph.__debug_print(std::cout); ASSERT_TRUE(graph.validate()); } TEST(Effects, analysis_versions_3){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( R"Code( test= function:: num; entry { x{0}= 3:: int. a = x{0}:: int. b = a :: int. x{1} = b. x{1} } )Code"); VersionsPass* pass = new VersionsPass(man); pass->run(); VersionsGraph graph = pass->getResultGraph(); graph.__debug_print(std::cout); ASSERT_TRUE(graph.validate()); std::cout << "========================\n"; graph.__debug_print(std::cout); AttachmentsContainerDefault>* attachmentsDependency = graph.representAsAttachments(); CodeScope* scope = man->root->findFunction("test")->getEntryScope(); const std::list& dependenciesX1 = attachmentsDependency->get(Symbol{ScopedSymbol{1, 1}, scope}); ASSERT_EQ(3, dependenciesX1.size()); } TEST(Effects, compilation_versions_1){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( test= function:: num; entry { x{1} = b. b = a :: int. a = x{0}:: int. x{0}= 3:: int. x{1} } )Code"); - man->runWithoutCompilation(); + man->analyse(); if (!man->isPassRegistered(PassId::VersionsPass)){ VersionsPass* pass = new VersionsPass(man); pass->run(); pass->finish(); } int (*body)() = (int (*)())man->run(); int answer = body(); ASSERT_EQ(3, answer); } TEST(Effects, compilation_versions_versionInit1){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( test= function:: num; entry { x{0} = 3. x{0} } )Code"); - man->runWithoutCompilation(); + man->analyse(); if (!man->isPassRegistered(PassId::VersionsPass)){ VersionsPass* pass = new VersionsPass(man); pass->run(); pass->finish(); } int (*body)() = (int (*)())man->run(); int answer = body(); ASSERT_EQ(3, answer); } TEST(Effects, compilation_versions_versionNext1){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( test= function:: num; entry { x{0} = 5. x{1} = x{0} - 2. x{1} } )Code"); - man->runWithoutCompilation(); + man->analyse(); if (!man->isPassRegistered(PassId::VersionsPass)){ VersionsPass* pass = new VersionsPass(man); pass->run(); pass->finish(); } int (*body)() = (int (*)())man->run(); int answer = body(); ASSERT_EQ(3, answer); } TEST(Effects, compilation_versions_IntrinsicCopy1){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( test= function:: num; entry { x{0} = 5. b = intrinsic copy (x{0}). x{1} = 2. b - x{1} } )Code"); - man->runWithoutCompilation(); + man->analyse(); if (!man->isPassRegistered(PassId::VersionsPass)){ VersionsPass* pass = new VersionsPass(man); pass->run(); pass->finish(); } int (*body)() = (int (*)())man->run(); int answer = body(); ASSERT_EQ(3, answer); } TEST(Effects, compilation_versions_varexchange){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( test= function:: num; entry { a{0} = 3. b{0} = 5. tmp = intrinsic copy (a{0}). a{1} = b{0}. b{1} = tmp. b{1} } )Code"); - man->runWithoutCompilation(); + man->analyse(); if (!man->isPassRegistered(PassId::VersionsPass)){ VersionsPass* pass = new VersionsPass(man); pass->run(); pass->finish(); } int (*body)() = (int (*)())man->run(); int answer = body(); ASSERT_EQ(3, answer); } /* TEST(Effects, analysis_versions_copy){ } TEST(Effects, syntax_references1){ } TEST(Effects, syntax_scope_versions1){ } TEST(Effects, DynamicVersions_analysis){ } */ diff --git a/cpp/tests/externc.cpp b/cpp/tests/externc.cpp index 4aa5d7e..2057d42 100644 --- a/cpp/tests/externc.cpp +++ b/cpp/tests/externc.cpp @@ -1,106 +1,106 @@ #include "gtest/gtest.h" -#include "passmanager.h" -#include "Scanner.h" -#include "Parser.h" +#include "xreatemanager.h" +#include "main/Scanner.h" +#include "main/Parser.h" #include #include using namespace std; TEST(InterfaceExternC, testAST) { std::string code = " \ interface(extern-c){ \ xml2 = library:: pkgconfig(\"libxml-2.0\"). \ \ include { \ xml2 = [\"libxml/tree.h\"] \ }. \ } \ "; - Scanner scanner(reinterpret_cast (code.c_str()), code.size()); - Parser parser(&scanner); + xreate::grammar::main::Scanner scanner(reinterpret_cast (code.c_str()), code.size()); + xreate::grammar::main::Parser parser(&scanner); parser.Parse(); - ASSERT_EQ(1, parser.root.__externdata.size()); + ASSERT_EQ(1, parser.root->__externdata.size()); - for (const ExternEntry& lib : parser.root.__externdata) { + for (const ExternEntry& lib : parser.root->__externdata) { ASSERT_EQ("libxml-2.0", lib.package); ASSERT_EQ(1, lib.headers.size()); ASSERT_EQ("libxml/tree.h", lib.headers.at(0)); } } TEST(InterfaceExternC, testfetchPackageHeaders) { ExternEntry entry{"libxml-2.0", {}}; vector args = ExternLayer::fetchPackageFlags(entry); ASSERT_EQ(1, args.size()); ASSERT_EQ("-I/usr/include/libxml2", args.at(0)); } TEST(InterfaceExternC, testfetchPackageLibs) { ExternEntry entry{"libxml-2.0", {}}; vector args = ExternLayer::fetchPackageLibs(entry); ASSERT_EQ(1, args.size()); ASSERT_EQ("xml2", args.at(0)); } TEST(InterfaceExternC, testLoadLib) { std::string msgErr; if (!llvm::sys::DynamicLibrary::LoadLibraryPermanently("-lpcre -lxml2", &msgErr)) { cout << msgErr; ASSERT_EQ("", msgErr); } ASSERT_TRUE(true); } TEST(InterfaceExternC, testBSD1) { std::string code = " \n\ interface(extern-c){ \n\ libbsd = library:: pkgconfig(\"libbsd\"). \n\ \n\ include { \n\ libbsd = [\"bsd/stdlib.h\"] \n\ }. \n\ } \n" "main= function:: int; entry{arc4random_uniform(24) }"; - std::unique_ptr program(PassManager::prepareForCode(move(code))); + std::unique_ptr program(XreateManager::prepare(move(code))); void* entryPtr = program->run(); int (*entry)() = (int (*)())(intptr_t) entryPtr; int answer = 24; answer = entry(); cout << answer; ASSERT_LT(answer, 24); } TEST(InterfaceExternC, testStructFields1) { FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate", "r"); assert(input != nullptr); - Scanner scanner(input); - Parser parser(&scanner); + xreate::grammar::main::Scanner scanner(input); + xreate::grammar::main::Parser parser(&scanner); parser.Parse(); - AST& ast = parser.root; - CodeScope* body = ast.findFunction("test")->getEntryScope(); + AST* ast = parser.root->finalize(); + CodeScope* body = ast->findFunction("test")->getEntryScope(); const TypeAnnotation& tTree = body->getDeclaration(body->getSymbol("tree")).type; - const ExpandedType& t2Tree = ast.expandType(tTree); - LLVMLayer llvm(&ast); + const ExpandedType& t2Tree = ast->expandType(tTree); + LLVMLayer llvm(ast); TypeUtils utils(&llvm); std::vectorfields = utils.getStructFields(t2Tree); auto field = std::find(fields.begin(), fields.end(), "children"); ASSERT_TRUE(field != fields.end()); } diff --git a/cpp/tests/interpretation.cpp b/cpp/tests/interpretation.cpp index 21cdc9f..abb3606 100644 --- a/cpp/tests/interpretation.cpp +++ b/cpp/tests/interpretation.cpp @@ -1,381 +1,380 @@ #include "attachments.h" using namespace xreate; -#include "passmanager.h" +#include "xreatemanager.h" #include "compilation/targetinterpretation.h" #include "gtest/gtest.h" #include "boost/scoped_ptr.hpp" #define private public -#include "Parser.h" #include "pass/interpretationpass.h" -using namespace xreate; +using namespace xreate::grammar::main; using namespace xreate::compilation; TEST(Interpretation, Analysis_StatementIF_1){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( R"Code( main = function::bool { x = "a":: string. y = if (x=="b"):: bool; interpretation(force) { true } else { false }. y } )Code" ); InterpretationPass* pass = new InterpretationPass(man); pass->run(); CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope(); Symbol symbolY{scopeEntry->getSymbol("y"), scopeEntry}; InterpretationData& dataSymbolY = Attachments::get(symbolY); ASSERT_EQ(INTR_ONLY, dataSymbolY.resolution); } TEST(Interpretation, Compilation_StatementIF_1){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( main = function::int; entry { x = "a":: string. y = if (x=="b"):: string; interpretation(force) { 1 } else { 0 }. y } )Code" ); - man->runWithoutCompilation(); + man->analyse(); InterpretationPass* pass; if (man->isPassRegistered(PassId::InterpretationPass)){ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass); } else { pass = new InterpretationPass(man); pass->run(); } int (*main)() = (int (*)())man->run(); int result = main(); ASSERT_EQ(0, result); } TEST(Interpretation, Analysis_StatementIF_InterpretCondition_1){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( R"Code( main = function(x:: int):: int { comm= "inc":: string; interpretation(force). y = if (comm == "inc")::int {x+1} else {x}. y } )Code" ); InterpretationPass* pass = new InterpretationPass(man); pass->run(); CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope(); Symbol symbolY{scopeEntry->getSymbol("y"), scopeEntry}; InterpretationData& dataSymbolY = Attachments::get(symbolY); ASSERT_EQ(CMPL_ONLY, dataSymbolY.resolution); ASSERT_EQ(IF_INTERPRET_CONDITION, dataSymbolY.op); } TEST(Interpretation, Compilation_StatementIF_InterpretCondition_1){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( main = function(x:: int):: int; entry { comm= "inc":: string; interpretation(force). y = if (comm == "inc")::int {x+1} else {x}. y } )Code" ); - man->runWithoutCompilation(); + man->analyse(); InterpretationPass* pass; if (man->isPassRegistered(PassId::InterpretationPass)){ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass); } else { pass = new InterpretationPass(man); pass->run(); } int (*main)(int) = (int (*)(int))man->run(); int result = main(1); ASSERT_EQ(2, result); } TEST(Interpretation, Compilation_StatementFOLD_INTERPRET_INPUT_1){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( main = function(x:: int):: int; entry { commands = ["inc", "double", "dec"]:: [string]; interpretation(force). loop fold(commands->comm::string, x->operand):: int{ switch(comm)::int case ("inc"){ operand + 1 } case ("dec"){ operand - 1 } case ("double"){ operand * 2 } } } )Code" ); - man->runWithoutCompilation(); + man->analyse(); InterpretationPass* pass; if (man->isPassRegistered(PassId::InterpretationPass)){ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass); } else { pass = new InterpretationPass(man); pass->run(); } const ManagedFnPtr& funcMain = man->root->findFunction("main"); InterpretationData& dataBody = Attachments::get(funcMain); ASSERT_EQ(FOLD_INTERPRET_INPUT, dataBody.op); int (*main)(int) = (int (*)(int))man->run(); int result = main(10); ASSERT_EQ(21, result); } TEST(Interpretation, StatementCall_RecursionNo_1){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( unwrap = function(data::undef, keys::undef):: undef; interpretation(force){ loop fold(keys->key::string, data->a):: undef { a[key] } } start = function::num; entry{ result = unwrap( { a = { b = { c = "core" } } }, ["a", "b", "c"])::undef. result == "core" } )Code" ); - man->runWithoutCompilation(); + man->analyse(); InterpretationPass* pass; if (man->isPassRegistered(PassId::InterpretationPass)){ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass); } else { pass = new InterpretationPass(man); pass->run(); } int (*main)() = (int (*)())man->run(); int result = main(); ASSERT_EQ(1, result); } TEST(Interpretation, StatementCall_RecursionDirect_1){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( unwrap = function(data:: X):: Y { if (data[0] == "a")::Y {0} else {unwrap(data[0])} } entry = function:: i8; entry { unwrap([[[["a"]]]]):: i8; interpretation(force) } )Code" ); - man->runWithoutCompilation(); + man->analyse(); InterpretationPass* pass; if (man->isPassRegistered(PassId::InterpretationPass)){ pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass); } else { pass = new InterpretationPass(man); pass->run(); } InterpretationResolution resolutionActual = pass->process(man->root->findFunction("unwrap")); ASSERT_EQ(ANY, resolutionActual); int (*main)() = (int (*)())man->run(); int result = main(); ASSERT_EQ(0, result); } TEST(Interpretation, StatementCall_RecursionIndirect_1){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( R"Code( funcA = function(data:: X):: Y { if (data == "a")::Y {0} else {funcB(data)} } funcB = function(data:: X):: Y { if (data == "b")::Y {1} else {funcA(data)} } entry = function:: i8; entry { funcA(""):: i8; interpretation(force) } )Code" ); InterpretationPass* pass = new InterpretationPass(man); ASSERT_DEATH(pass->run(), "Indirect recursion detected"); } TEST(Interpretation, PartialIntr_1){ - PassManager* man = PassManager::prepareForCode( + XreateManager* man = XreateManager::prepare( R"Code( evaluate= function(argument:: num, code:: string; interpretation(force)):: num { switch(code)::int case ("inc") {argument + 1} case ("dec") {argument - 1} case ("double") {argument * 2} } main = function::int; entry { commands= ["inc", "double", "dec"]:: [string]; interpretation(force). loop fold(commands->comm::string, 10->operand):: int{ evaluate(operand, comm) } } )Code" ); InterpretationPass* pass = new InterpretationPass(man); pass->run(); ManagedFnPtr fnEvaluate = man->root->findFunction("evaluate"); InterpretationResolution resFnEvaluate= pass->process(fnEvaluate); ASSERT_EQ(CMPL_ONLY, resFnEvaluate); ASSERT_TRUE(FunctionInterpretationHelper::needPartialInterpretation(fnEvaluate)); const Expression& exprLoop = man->root->findFunction("main")->__entry->getBody(); Symbol symbCallEv{{0, VERSION_NONE}, exprLoop.blocks.front()}; InterpretationData dataCallEv = Attachments::get(symbCallEv); ASSERT_EQ(CMPL_ONLY, dataCallEv.resolution); ASSERT_EQ(CALL_INTERPRET_PARTIAL, dataCallEv.op); } TEST(Interpretation, Compilation_PartialIntr_2){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( evaluate= function(argument:: num, code:: string; interpretation(force)):: num { switch(code)::int case ("inc") {argument + 1} case ("dec") {argument - 1} case ("double") {argument * 2} case default {argument} } main = function::int; entry { commands= ["inc", "double", "dec"]:: [string]; interpretation(force). loop fold(commands->comm::string, 10->operand):: int{ evaluate(operand, comm) } } )Code" ); - man->runWithoutCompilation(); + man->analyse(); if (!man->isPassRegistered(PassId::InterpretationPass)){ InterpretationPass* pass = new InterpretationPass(man); pass->run(); } int (*main)() = (int (*)())man->run(); int result = main(); ASSERT_EQ(21, result); } TEST(Interpretation, PartialIntr_3){ - PassManager* man = PassManager::prepareForCode( + details::tier1::XreateManager* man = details::tier1::XreateManager::prepare( R"Code( Command= type variant (INC, DEC, DOUBLE). evaluate= function(argument:: num, code:: Command; interpretation(force)):: num { switch(code)::int case (INC) {argument + 1} case (DEC) {argument - 1} case (DOUBLE) {argument * 2} case default {argument} } main = function::int; entry { commands= [INC, DOUBLE, DEC]:: [Command]; interpretation(force). loop fold(commands->comm::Command, 10->operand):: int{ evaluate(operand, comm) } } )Code" ); - man->runWithoutCompilation(); + man->analyse(); if (!man->isPassRegistered(PassId::InterpretationPass)){ InterpretationPass* pass = new InterpretationPass(man); pass->run(); } int (*main)() = (int (*)())man->run(); int result = main(); ASSERT_EQ(21, result); } TEST(InterpretationExamples, Regexp1){ FILE* input = fopen("scripts/dsl/regexp.xreate","r"); assert(input != nullptr); - std::unique_ptr man(PassManager::prepareForCode(input)); + std::unique_ptr man(XreateManager::prepare(input)); int (*main)() = (int (*)())man->run(); int result = main(); ASSERT_EQ(4, result); } //TOTEST call indirect recursion(w/o tags) //TASk implement and test Loop Inf (fix acc types in coco grammar) diff --git a/cpp/tests/loops.cpp b/cpp/tests/loops.cpp index be08250..6947ae6 100644 --- a/cpp/tests/loops.cpp +++ b/cpp/tests/loops.cpp @@ -1,178 +1,178 @@ -#include "passmanager.h" +#include "xreatemanager.h" #include "gtest/gtest.h" using namespace std; TEST(Loop, SimpleLoop1){ string code = R"CODE( main = function:: int; entry { input = [1..5]:: [int]. loop fold(input->el::int, 0->sum)::int { sum + el } } )CODE"; - xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code)); + xreate::XreateManager* man = xreate::XreateManager::prepare(move(code)); int (*funcMain)() = (int (*)()) man->run(); int answerActual = funcMain(); ASSERT_EQ(15, answerActual); } TEST(Loop, Break1){ string code = R"CODE( main = function:: int; entry { input = [1..10]:: [int]. loop fold(input->el::int, 0->sum)::int { if (sum>5)::int { sum:: int; break } else {sum+el} } } )CODE"; - xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code)); + xreate::XreateManager* man = xreate::XreateManager::prepare(move(code)); int (*funcMain)() = (int (*)()) man->run(); int answerActual = funcMain(); ASSERT_EQ(6, answerActual); } TEST(Loop, NestedLoopsSimple1){ string code = R"CODE( main = function:: int; entry { listX = [1..5]:: [int]. loop fold(listX->x::int, 0->acc)::int { listY = [1..5]:: [int]. row = loop fold(listY->y::int, 1->acc):: int { acc * ( y + x) }. acc + row } } )CODE"; - xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code)); + xreate::XreateManager* man = xreate::XreateManager::prepare(move(code)); int (*funcMain)() = (int (*)()) man->run(); int answerActual = funcMain(); ASSERT_EQ(55320, answerActual); } TEST(Loop, NestedLoopsBreak1){ string code = R"CODE( main = function:: int; entry { listX = [1..5]:: [int]. loop fold(listX->x::int, 0->acc)::int { listY = [1..5]:: [int]. row = loop fold(listY->y::int, 1->acc):: int { res = acc * ( y + x) :: int. if (res > 20):: int { 20:: int; break } else { res } }. acc + row } } )CODE"; - xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code)); + xreate::XreateManager* man = xreate::XreateManager::prepare(move(code)); int (*funcMain)() = (int (*)()) man->run(); int answerActual = funcMain(); ASSERT_EQ(100, answerActual); } TEST(Loop, NestedLoopsBreak2){ string code = R"CODE( main = function:: int; entry { listX = [1..3]:: [int]. loop fold(listX->x::int, 0->acc)::int { listY = [1..5]:: [int]. row = loop fold(listY->y::int, 1->acc):: int { res = acc * y :: int. if (res > 24):: int { 24:: int; break } else { res } }. if (x==3)::int{ acc:: int; break } else { acc + row } } } )CODE"; - xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code)); + xreate::XreateManager* man = xreate::XreateManager::prepare(move(code)); int (*funcMain)() = (int (*)()) man->run(); int answerActual = funcMain(); ASSERT_EQ(48, answerActual); } //TEST nested loop breaks. //TEST 2 breaks^ outer loop break, inner loop break TEST(Loop, InfiniteLoop1){ string code = R"Code( fac = function(x:: int):: int{ range = [2..x] :: [int]. loop fold(range->i::int, 1->acc)::int { acc * i } } main = function:: int; entry { loop fold inf(2->state) :: int { if (fac(state)==120)::int { state::int; break } else {state + 1} } } )Code" ; - xreate::PassManager* man = xreate::PassManager::prepareForCode(move(code)); + xreate::XreateManager* man = xreate::XreateManager::prepare(move(code)); int (*funcMain)() = (int (*)()) man->run(); int answerActual = funcMain(); ASSERT_EQ(5, answerActual); } \ No newline at end of file diff --git a/cpp/tests/main.cpp b/cpp/tests/main.cpp index 2385205..0e1f7de 100644 --- a/cpp/tests/main.cpp +++ b/cpp/tests/main.cpp @@ -1,15 +1,14 @@ #include "utils.h" #include using namespace std; using namespace xreate; -int main(int argc, char **argv) { - testing::GTEST_FLAG(color) = "yes"; +int main(int argc, char **argv) { testing::GTEST_FLAG(color) = "yes"; string testsTemplate = Config::get("tests.template"); string testsFilter = Config::get(string("tests.templates.") + testsTemplate); testing::GTEST_FLAG(filter) = testsFilter; testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } diff --git a/cpp/tests/modules.cpp b/cpp/tests/modules.cpp new file mode 100644 index 0000000..10c1ead --- /dev/null +++ b/cpp/tests/modules.cpp @@ -0,0 +1,271 @@ +/* + * modules.cpp + * + * Author: pgess + * Created on June 18, 2017, 8:25 PM + */ + +class Modules_AST2_Test; +class Modules_Discovery1_Test; +class Modules_Solve1_Test; + +#define FRIENDS_MODULES_TESTS \ + friend class ::Modules_AST2_Test; \ + friend class ::Modules_Discovery1_Test; \ + friend class ::Modules_Solve1_Test; + +#include "modules.h" +#include "misc/xreatemanager-decorators.h" +#include "misc/xreatemanager-modules.h" +#include "xreatemanager.h" +#include "modules/Parser.h" +#include "gtest/gtest.h" +#include +#include +#include + +namespace fs = boost::filesystem; + +using namespace std; +using namespace xreate::grammar::modules; + +TEST(Modules, AST1) { + FILE* input = fopen("scripts/dsl/regexp.xreate","r"); + assert(input != nullptr); + + Scanner scanner(input); + Parser parser(&scanner); + parser.Parse(); + ASSERT_EQ(parser.errors->count, 0); +} + +TEST(Modules, AST2){ + string code = R"Code( + module { + name(test1). + status(untested). + + require provides(logging). + include controller("/tmp/test-controller.ls"). + discover("/tmp/root/"). + } + )Code"; + + Scanner scanner(reinterpret_cast(code.c_str()), code.size()); + Parser parser(&scanner); + parser.Parse(); + + xreate::ModuleRecord module = parser.module; + + ASSERT_EQ(2, module.__properties.size()); + ASSERT_EQ("name", module.__properties.front().getValueString()); + ASSERT_EQ("status", module.__properties.back().getValueString()); + + ASSERT_EQ(1, module.__queries.size()); + ASSERT_EQ("provides", module.__queries.front().getValueString()); + + ASSERT_EQ(1, module.__controllers.size()); + ASSERT_EQ("/tmp/test-controller.ls", module.__controllers.front()); + + ASSERT_EQ(1, module.__discoveries.size()); + ASSERT_EQ("/tmp/root/", module.__discoveries.front()); +} + +TEST(Modules, Discovery1){ + const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54723/"; + + string codeA = +R"Code(module { + name(testA). + status(needToTestMore). +})Code"; + + string codeB = +R"Code(module { + name(testB). + status(needToTestEvenMore). +})Code"; + + string codeMain = string("module{discover \"") + dirModulesRoot + "\".}"; + + fs::create_directories(dirModulesRoot); + fs::ofstream fileA(dirModulesRoot + "a.xreate"); + fileA << codeA; + fileA.close(); + + fs::ofstream fileB(dirModulesRoot + "b.xreate"); + fileB << codeB; + fileB.close(); + + Scanner scanner(reinterpret_cast(codeMain.c_str()), codeMain.size()); + Parser parser(&scanner); + parser.Parse(); + + xreate::ModulesRegistry registry; + xreate::ModulesSolver solver(®istry); + solver.discoverModules(parser.module); + fs::remove_all(dirModulesRoot); + + std::string output = solver.__program.str(); + cout << output << endl; + ASSERT_NE(string::npos, output.find("bind_module(0, name(testA)).")); + ASSERT_NE(string::npos, output.find("bind_module(1, status(needToTestEvenMore)).")); +} + +TEST(Modules, Requests1){ + +} + +TEST(Modules, Solve1){ + const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54724/"; + + string codeA = +R"Code(module { + name(testA). + provide(superService). + status(needToTestMore). +})Code"; + + string codeB = +R"Code(module { + name(testB). + provide(superService). + status(needToTestEvenMore). +})Code"; + + string codeMain = +R"Code(module { + discover("/tmp/testModulesDiscovery1_t54724/") + include controller ("/tmp/testModulesDiscovery1_t54724/controller") + + require (superService) +})Code"; + + string codeController = +R"Code( +status_score(0, needToTestEvenMore). +status_score(1, needToTestMore). + +module_include_candidate(X, Y, Request):- + module_require(X, Request); bind_module(Y, provide(Request)). + +module_include_winner(X, Request, MaxScore) :- + MaxScore = #max{Score: module_include_candidate(X, Y, Request), bind_module(Y, status(Status)), status_score(Score, Status)}; + module_require(X, Request). + +module_include(X, Y) :- + module_include_winner(X, Request, MaxScore); + bind_module(Y, provide(Request)); + bind_module(Y, status(Status)); + status_score(MaxScore, Status). +)Code"; + + fs::create_directories(dirModulesRoot); + fs::ofstream fileA(dirModulesRoot + "a.xreate"); + fileA << codeA; + fileA.close(); + + fs::ofstream fileB(dirModulesRoot + "b.xreate"); + fileB << codeB; + fileB.close(); + + fs::ofstream fileController(dirModulesRoot + "controller"); + fileController << codeController; + fileController.close(); + + Scanner scanner(reinterpret_cast(codeMain.c_str()), codeMain.size()); + Parser parser(&scanner); + parser.Parse(); + + xreate::ModulesRegistry registry; + xreate::ModulesSolver solver(®istry); + solver.init("", parser.module); + fs::remove_all(dirModulesRoot); + + cout << solver.__program.str() << endl; + std::list modulesRequired = solver.run(parser.module); + + ASSERT_EQ(1, modulesRequired.size()); + string moduleActualRequired = modulesRequired.front(); + + string moduleExpected = dirModulesRoot + "a.xreate"; + ASSERT_EQ(moduleExpected, moduleActualRequired); +} + +TEST(Modules, Compilation1){ + const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54725/"; + + string codeMain = +R"Code( +module { + discover("/tmp/testModulesDiscovery1_t54725/") + include controller("/tmp/testModulesDiscovery1_t54725/controller") + + require (superService) +} + +test = function:: int; entry { + getYourNumber() +} +)Code"; + + string codeA = +R"Code(module { + name(testA). + provide(superService). + status(needToTestEvenMore). +} + +getYourNumber= function:: int {0} +)Code"; + + string codeB = +R"Code(module { + name(testB). + provide(superService). + status(needToTestMore). +} + +getYourNumber= function:: int {1} +)Code"; + +string codeController = +R"Code( +status_score(0, needToTestEvenMore). +status_score(1, needToTestMore). + +module_include_candidate(X, Y, Request):- + module_require(X, Request); bind_module(Y, provide(Request)). + +module_include_winner(X, Request, MaxScore) :- + MaxScore = #max{Score: module_include_candidate(X, Y, Request), bind_module(Y, status(Status)), status_score(Score, Status)}; + module_require(X, Request). + +module_include(X, Y) :- + module_include_winner(X, Request, MaxScore); + bind_module(Y, provide(Request)); + bind_module(Y, status(Status)); + status_score(MaxScore, Status). +)Code"; + + fs::create_directories(dirModulesRoot); + fs::ofstream fileA(dirModulesRoot + "a.xreate"); + fileA << codeA; + fileA.close(); + + fs::ofstream fileB(dirModulesRoot + "b.xreate"); + fileB << codeB; + fileB.close(); + + fs::ofstream fileController(dirModulesRoot + "controller"); + fileController << codeController; + fileController.close(); + + auto man = new XreateManagerImpl>(); + man->prepareCode(std::move(codeMain)); + fs::remove_all(dirModulesRoot); + + int (*funcMain)() = (int (*)()) man->run(); + int result = funcMain(); + ASSERT_EQ(1, result); +} diff --git a/cpp/tests/types.cpp b/cpp/tests/types.cpp index 5ff99b6..30ea9a0 100644 --- a/cpp/tests/types.cpp +++ b/cpp/tests/types.cpp @@ -1,163 +1,164 @@ /* * types.cpp * * Created on: Jun 4, 2015 * Author: pgess */ #include "gtest/gtest.h" -#include "passmanager.h" +#include "xreatemanager.h" #include "llvmlayer.h" -#include "Parser.h" +#include "main/Parser.h" using namespace std; -using namespace xreate; +using namespace xreate::grammar::main; TEST(Types, DependantTypes1) { string&& code = "XmlNode = type alias {\n" " tag:: string,\n" " /* attrs:: [string],*/\n" " content:: string\n" "}.\n"; - std::unique_ptr program(PassManager::prepareForCode(move(code))); + std::unique_ptr program(XreateManager::prepare(move(code))); ExpandedType typeXmlNode = program->root->findType("XmlNode"); ASSERT_EQ(TypeOperator::STRUCT, typeXmlNode->__operator); ASSERT_EQ(2, typeXmlNode->__operands.size()); ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(0).__value); ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(1).__value); } TEST(Types, DependantTypes2) { string&& code = "XmlNode = type alias {\n" " tag:: string,\n" " /* attrs:: [string],*/\n" " content:: string\n" "}.\n" "" "Template = type Template(Leaf) [Leaf, [Leaf[content]]]." "Concrete = type alias Template(XmlNode)."; - std::unique_ptr program(PassManager::prepareForCode(move(code))); + std::unique_ptr program(XreateManager::prepare(move(code))); ExpandedType typeConcrete = program->root->findType("Concrete"); ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator); ASSERT_EQ(2, typeConcrete->__operands.size()); ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator); ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator); ASSERT_EQ(TypePrimitive::String, typeConcrete->__operands.at(1).__operands.at(0).__value); } TEST(Types, TreeType1) { string&& code = "XmlNode = type alias {\n" " tag:: string,\n" " /* attrs:: [string],*/\n" " content:: string\n" "}.\n" "" "Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]." "Concrete = type alias Tree(XmlNode)."; - std::unique_ptr program(PassManager::prepareForCode(move(code))); + std::unique_ptr program(XreateManager::prepare(move(code))); ExpandedType typeConcrete = program->root->findType("Concrete"); ASSERT_EQ(TypeOperator::TUPLE, typeConcrete->__operator); ASSERT_EQ(2, typeConcrete->__operands.size()); ASSERT_EQ(TypeOperator::STRUCT, typeConcrete->__operands.at(0).__operator); ASSERT_EQ(TypeOperator::ARRAY, typeConcrete->__operands.at(1).__operator); auto typeLink = typeConcrete->__operands.at(1).__operands.at(0); ASSERT_EQ(TypeOperator::LINK, typeLink.__operator); ASSERT_EQ(typeConcrete->conjuctionId,typeLink.conjuctionId); } TEST(Types, TreeType1LLvm){ string&& code = "XmlNode = type alias {\n" " tag:: string,\n" " /* attrs:: [string],*/\n" " content:: string\n" "}.\n" "" "Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]." "Concrete = type alias Tree(XmlNode)."; - std::unique_ptr program(PassManager::prepareForCode(move(code))); + std::unique_ptr program(XreateManager::prepare(move(code))); ExpandedType typeConcrete = program->root->findType("Concrete"); llvm::Type* raw = program->llvm->toLLVMType(typeConcrete); } TEST(Types, ArrayOfExternal1){ FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r"); assert(input != nullptr); Scanner scanner(input); Parser parser(&scanner); + parser.Parse(); + AST* ast = parser.root->finalize(); - AST& ast = parser.root; - CodeScope* body = ast.findFunction("test")->getEntryScope(); + CodeScope* body = ast->findFunction("test")->getEntryScope(); const TypeAnnotation& t = body->getDeclaration(body->getSymbol("childrenRaw")).type; - const ExpandedType& t2 = ast.expandType(t); + const ExpandedType& t2 = ast->expandType(t); EXPECT_EQ(t2->__operator, TypeOperator::ARRAY); } TEST(Types, ExternType1){ FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r"); assert(input != nullptr); Scanner scanner(input); Parser parser(&scanner); parser.Parse(); - AST& ast = parser.root; - CodeScope* body = ast.findFunction("test")->getEntryScope(); + AST* ast = parser.root->finalize(); + CodeScope* body = ast->findFunction("test")->getEntryScope(); const TypeAnnotation& t = body->getDeclaration(body->getSymbol("tree")).type; - const ExpandedType& t2 = ast.expandType(t); + const ExpandedType& t2 = ast->expandType(t); EXPECT_EQ(t2->__operator, TypeOperator::CUSTOM); } TEST(Types, ast_VariantType1){ string&& code = " colors = type variant (RED, BLUE, GREEN).\n" " test = function:: colors; entry {GREEN}"; - std::unique_ptr program(PassManager::prepareForCode(move(code))); + std::unique_ptr program(XreateManager::prepare(move(code))); ExpandedType typ = program->root->findType("colors"); EXPECT_EQ(TypeOperator::VARIANT, typ->__operator); Expression eRed = program->root->findFunction("test")->getEntryScope()->getBody(); EXPECT_EQ(Expression::VARIANT, eRed.__state); const ExpandedType& typ2 = program->root->expandType(eRed.type); EXPECT_EQ(TypeOperator::VARIANT, typ2->__operator); program->run(); } TEST(Types, full_VariantType_Switch1){ string&& code = " colors = type variant (RED, BLUE, GREEN). \n" " test = function:: colors {GREEN} \n" "main = function:: int; entry { \n" " switch(test()):: int \n" " case (GREEN) {0} \n" " case default {1} \n" "}"; - PassManager* man = PassManager::prepareForCode(move(code)); + XreateManager* man = XreateManager::prepare(move(code)); int (*main)() = (int (*)()) man->run(); EXPECT_EQ(0, main()); } //TOTEST string type diff --git a/grammar/gen-grammar b/grammar/gen-grammar new file mode 100755 index 0000000..237f5b5 --- /dev/null +++ b/grammar/gen-grammar @@ -0,0 +1,9 @@ +COCO_EXECUTABLE=${2:-cococpp} +COCO_FRAMES_PATH=${3:-/usr/share/coco-cpp/} + +echo "Run coco generator: " + +case $1 in + main) $COCO_EXECUTABLE ./xreate.ATG -frames $COCO_FRAMES_PATH -o main -namespace xreate::grammar::main;; + modules) $COCO_EXECUTABLE ./modules.ATG -frames $COCO_FRAMES_PATH -o modules -namespace xreate::grammar::modules;; +esac diff --git a/grammar/modules.ATG b/grammar/modules.ATG new file mode 100644 index 0000000..43aaacf --- /dev/null +++ b/grammar/modules.ATG @@ -0,0 +1,96 @@ +#include "modules.h" + +COMPILER Modules + +ModuleRecord module; + +int nextToken() +{ + scanner->ResetPeek(); + return scanner->Peek()->kind; +} + +bool checkParametersList() +{ + return la->kind == _ident && nextToken() == _lparen; +} + +CHARACTERS + letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz". + digit = "0123456789". + any = ANY - '"'. + cr = '\r'. + lf = '\n'. + tab = '\t'. + + +TOKENS + string = '"' { any } '"'. + ident = (letter | '_') {letter | digit | '_'}. + lparen = '('. + + +COMMENTS FROM "/*" TO "*/" NESTED +COMMENTS FROM "//" TO lf + +IGNORE cr + lf + tab + +PRODUCTIONS + +Block = +'{' + { string + | Block + | ANY + } +'}'. + +Modules = +{ + ModulesInterface + | SkipXreateOperators +}. + +ModulesInterface = "module" '{' + {ModulesStatement} +'}'. + +ModulesStatement = (. std::wstring path; Expression query; .) +( "require" '(' MetaSimpExpr ')' '.' (. module.addModuleQuery(query); .) + + | "include" "controller" '(' string (. module.addControllerPath(Atom(t->val).get()); .) + ')' '.' + | "discover" '(' string (. module.addDiscoveryPath(Atom(t->val).get()); .) + ')' '.' + | MetaSimpExpr '.' (. module.addProperty(query); .) +). + +MetaSimpExpr= (. Expression e2; .) +( '-' MetaSimpExpr (. e = Expression(Operator::NEG, {e2}); .) +| IF(checkParametersList()) ident (. e = Expression(Operator::CALL, {Expression(Atom(t->val))}); .) + '(' [ MetaCalleeParams ] ')' +| ident (. e = Expression(Atom(t->val)); .) +). + +MetaCalleeParams = (. Expression e2; .) + MetaSimpExpr (. e.addArg(Expression(e2)); .) + {',' MetaSimpExpr (. e.addArg(Expression(e2)); .) + }. + + + +SkipXreateOperators = +{ "rule" {ANY} Block + | "interface" {ANY} Block + | "import" {ANY} '.' + | "case" "context" {ANY} Block + | {ANY} '=' + ( + "function" {ANY} Block + | "type" {ANY} '.' + ) +}. + + + +END Modules. diff --git a/coco/xreate.ATG b/grammar/xreate.ATG similarity index 93% rename from coco/xreate.ATG rename to grammar/xreate.ATG index 66e8ad4..ac15f56 100644 --- a/coco/xreate.ATG +++ b/grammar/xreate.ATG @@ -1,600 +1,607 @@ //TODO add ListLiteral //TODO ExprTyped: assign default(none) type #include "ast.h" #include "ExternLayer.h" #include "pass/adhocpass.h" #include #include #define wprintf(format, ...) \ char __buffer[100]; \ wcstombs(__buffer, format, 100); \ fprintf(stderr, __buffer, __VA_ARGS__) using namespace xreate; using namespace std; COMPILER Xreate - xreate::AST root; // current program unit + xreate::details::incomplete::AST* root = nullptr; // current program unit + + void ensureInitalizedAST(){ + if (root == nullptr) root = new xreate::details::incomplete::AST(); + } struct { std::stack scopesOld; xreate::CodeScope* scope = nullptr; } context; void pushContextScope(CodeScope* scope){ context.scopesOld.push(context.scope); context.scope = scope; } void popContextScope(){ context.scope = context.scopesOld.top(); context.scopesOld.pop(); } int nextToken() { scanner->ResetPeek(); return scanner->Peek()->kind; } bool checkParametersList() { return la->kind == _ident && nextToken() == _lparen; } bool checkInfix() { return la->kind == _ident && nextToken() == _ident; } bool checkIndex() { return la->kind == _ident && nextToken() == _lbrack; } bool checkFuncDecl() { if (la->kind != _ident) return false; int token2 = nextToken(); int token3 = scanner->Peek()->kind; return token2 == _assign && (token3 == _function || token3 == _pre); } bool checkAssignment() { if (la->kind != _ident) return false; scanner->ResetPeek(); int token2 = scanner->Peek()->kind; if (token2 == _lcurbrack) { scanner->Peek(); int token3 = scanner->Peek()->kind; if (token3 != _rcurbrack) return false; int token4 = scanner->Peek()->kind; return token4 == _assign; } return token2 == _assign; } void recognizeIdentifier(Expression& i){ if (!context.scope->recognizeIdentifier(i)){ - if (!root.recognizeVariantIdentifier(i)){ - root.postponeIdentifier(context.scope, i); + if (!root->recognizeVariantIdentifier(i)){ + root->postponeIdentifier(context.scope, i); } } } enum SwitchKind{SWITCH_NORMAL, SWITCH_META}; CHARACTERS letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz". any = ANY - '"'. digit = "0123456789". cr = '\r'. lf = '\n'. tab = '\t'. TOKENS ident = (letter | '_') {letter | digit | '_'}. number = (digit | '-' digit) {digit}. string = '"' { any } '"'. function = "function". pre = "pre". lparen = '('. rparen = ')'. lbrack = '['. rbrack = ']'. lcurbrack = '{'. rcurbrack = '}'. equal = "==". assign = '='. implic = '-' '>'. colon = ':'. context = "context". tagcolon = "::". lse = "<=". lss = "<". gte = ">=". gtr = ">". ne1 = "!=". ne2= "<>". COMMENTS FROM "/*" TO "*/" NESTED COMMENTS FROM "//" TO lf IGNORE cr + lf + tab PRODUCTIONS -Xreate = (. Function* function; .) +Xreate = (. Function* function; ensureInitalizedAST(); .) {( RuleDecl | InterfaceData | Imprt | ContextSection - | IF(checkFuncDecl()) FDecl (. root.add(function); .) + | IF(checkFuncDecl()) FDecl (. root->add(function); .) | TDecl -)} (. root.recognizePostponedIdentifiers(); .) + | SkipModulesSection +)} (. .) . Ident = ident (. name = t->val; .). VarIdent = ident (. e = Expression(Atom(t->val)); .) [ lcurbrack ( ident (. SemErr(coco_string_create("var version as ident is not implemented yet")); .) | number (. Attachments::put(e, Atom(t->val).get()); .) ) rcurbrack ] . FDecl = (. std::wstring fname; std::wstring argName; TypeAnnotation typIn; TypeAnnotation typOut; bool flagIsPrefunct = false; Expression binding; .) Ident assign [pre (. flagIsPrefunct = true; .)] function (. f = new Function(fname); f->isPrefunction = flagIsPrefunct; CodeScope* entry = f->getEntryScope(); .) ['(' Ident tagcolon ExprAnnotations (. f->addBinding(Atom(argName), move(binding)); .) {',' Ident tagcolon ExprAnnotations (. f->addBinding(Atom (argName), move(binding));.) } ')'] [ tagcolon ( IF(flagIsPrefunct) FnTag | Type ) {';' FnTag }] BDecl (. entry->getBody().bindType(move(typOut));.) . ContextSection<>= (. Expression context; Function* f; .) "case" "context" tagcolon MetaSimpExpr -lcurbrack { FDecl (. f->guardContext = context; root.add(f); .) +lcurbrack { FDecl (. f->guardContext = context; root->add(f); .) } rcurbrack. /** * TYPES * */ TypeTerm = (. std::wstring tid; .) ("string" (. typ = TypePrimitive::String;.) | "num" (. typ = TypePrimitive::Num;.) | "int" (. typ = TypePrimitive::Int;.) | "float" (. typ = TypePrimitive::Float;.) | "bool" (. typ = TypePrimitive::Bool; .) | "i8" (. typ = TypePrimitive::I8; .) | "i32" (. typ = TypePrimitive::I32; .) | "i64" (. typ = TypePrimitive::I64; .) ). Type = (. TypeAnnotation typ2; TypePrimitive typ3; std::wstring tid, field; .) ( TList | TStruct | TypeTerm (. typ = typ3; .) | IF (checkIndex()) Ident lbrack Ident (. typ = TypeAnnotation(TypeOperator::ACCESS, {}); typ.__valueCustom = Atom(tid).get(); typ.fields.push_back(Atom(field).get()); .) {',' Ident (. typ.fields.push_back(Atom(field).get()); .) } rbrack | Ident (. typ = TypeAnnotation(TypeOperator::CUSTOM, {}); typ.__valueCustom = Atom(tid).get(); .) ['(' Type (. typ.__operator = TypeOperator::CALL; typ.__operands.push_back(typ2); .) {',' Type (. typ.__operands.push_back(typ2); .) } ')'] ) . TList = (. TypeAnnotation ty; .) '[' Type (. typ = TypeAnnotation(TypeOperator::ARRAY, {ty}); .) {',' Type (. typ.__operator = TypeOperator::TUPLE; typ.__operands.push_back(ty); .) }']' . TStruct = (. TypeAnnotation t; std::wstring field; .) lcurbrack Ident tagcolon Type (. typ = TypeAnnotation(TypeOperator::STRUCT, {t}); typ.fields.push_back(Atom(field).get()); .) {',' Ident tagcolon Type} (. typ.__operands.push_back(t); typ.fields.push_back(Atom(field).get()); .) rcurbrack. TDecl = (. std::wstring ttag; TypeAnnotation t, t1; std::wstring tname, arg; std::vector> args; .) Ident assign "type" ( - "alias" Type (. root.add(move(t), Atom(tname)); .) + "alias" Type (. root->add(move(t), Atom(tname)); .) | "variant" lparen Ident (. t = TypeAnnotation(TypeOperator::VARIANT, {}); args.push_back(Atom(arg)); .) {',' Ident (. args.push_back(Atom(arg)); .) - } rparen (. t.addFields(move(args)); root.add(move(t), Atom(tname)); .) + } rparen (. t.addFields(move(args)); root->add(move(t), Atom(tname)); .) | Ident ['(' Ident (. args.push_back(Atom(arg)); .) {',' Ident (. args.push_back(Atom(arg)); .) } ')'] - Type (. t.addBindings(move(args)); root.add(move(t), Atom(tname)); .) + Type (. t.addBindings(move(args)); root->add(move(t), Atom(tname)); .) ) '.' . ContextDecl = (. Expression tag; .) context tagcolon MetaSimpExpr (. scope->tags.push_back(tag); .) {';' MetaSimpExpr (. scope->tags.push_back(tag); .) }. VDecl = (. std::wstring vname; Expression var, value;.) VarIdent assign ExprTyped (. f->addDeclaration(move(var), move(value)); .) . //TODO forbid multiple body declaration (ExprTyped) BDecl = lcurbrack (. Expression body; pushContextScope(scope); .) {(IF(checkAssignment()) VDecl '.' | RuleContextDecl | ContextDecl'.' | ExprTyped (. scope->setBody(body); .) )} (. popContextScope(); .) rcurbrack . -IfDecl = (. Expression cond; ManagedScpPtr blockTrue = root.add(new xreate::CodeScope(context.scope)); ManagedScpPtr blockFalse = root.add(new xreate::CodeScope(context.scope)); .) +IfDecl = (. Expression cond; ManagedScpPtr blockTrue = root->add(new xreate::CodeScope(context.scope)); ManagedScpPtr blockFalse = root->add(new xreate::CodeScope(context.scope)); .) "if" '(' Expr ')' (. e = Expression(Operator::IF, {cond}); .) tagcolon ExprAnnotations BDecl<&*blockTrue> "else" BDecl<&*blockFalse> (. e.addBlock(blockTrue); e.addBlock(blockFalse); .) . LoopDecl = (. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc, contextClass; Expression tagsEl; - ManagedScpPtr block = root.add(new xreate::CodeScope(context.scope)); .) + ManagedScpPtr block = root->add(new xreate::CodeScope(context.scope)); .) "loop" ("map" '(' Expr implic Ident (. e = Expression(Operator::MAP, {eIn}); .) tagcolon ExprAnnotations ')' tagcolon ExprAnnotations BDecl<&*block> (. e.addBindings({Atom(varEl)}); block->addBinding(Atom(varEl), move(tagsEl)); e.addBlock(block); .) |"fold" ("inf" '(' Expr implic Ident ')' (. e = Expression(Operator::FOLD_INF, {eAcc}); e.addBindings({Atom(varAcc)}); .) tagcolon ExprAnnotations BDecl<&*block> (. block->addBinding(Atom(varAcc), Expression()); e.addBlock(block); .) | '(' Expr implic Ident tagcolon ExprAnnotations ['|' Expr ] ',' Expr implic Ident')' (. e = Expression(Operator::FOLD, {eIn, eAcc}); e.addBindings({Atom(varEl), Atom(varAcc)}); .) tagcolon ExprAnnotations BDecl<&*block> (. block->addBinding(Atom(varEl), move(tagsEl)); block->addBinding(Atom(varAcc), Expression()); e.addBlock(block); .) ) | "context" '(' string (. contextClass = t->val; .) ')' BDecl<&*block> (. e = Expression(Operator::LOOP_CONTEXT, {Expression(Atom(std::move(contextClass)))}); e.addBlock(block); .) ). SwitchDecl = (. TypeAnnotation typ; eSwitch = Expression(Operator::SWITCH, {}); Expression eCondition; Expression tag;.) ["switch" ( "ad" "hoc" lparen Expr tagcolon MetaSimpExpr rparen (. eSwitch.op = Operator::SWITCH_ADHOC; eSwitch.operands.push_back(eCondition); eSwitch.addTags({tag}); flagSwitchKind = SWITCH_META; .) | lparen Expr rparen tagcolon ExprAnnotations (. eSwitch.operands.push_back(eCondition);.) ) ] CaseDecl {CaseDecl} . -CaseDecl = (. ManagedScpPtr scope = root.add(new xreate::CodeScope(context.scope)); Expression condition; .) +CaseDecl = (. ManagedScpPtr scope = root->add(new xreate::CodeScope(context.scope)); Expression condition; .) "case" ( IF(flagSwitchKind == SWITCH_META) lparen MetaSimpExpr rparen BDecl<&*scope> (. Expression exprCase(Operator::CASE, {}); exprCase.addTags({condition}); exprCase.addBlock(scope); outer.addArg(move(exprCase));.) | "default" BDecl<&*scope> (. Expression exprCase(Operator::CASE_DEFAULT, {}); exprCase.addBlock(scope); outer.operands.insert(++outer.operands.begin(), exprCase); .) - | lparen CaseParams<&*scope> rparen (. ManagedScpPtr scopeBody = root.add(new xreate::CodeScope(&*scope)); Expression exprCase(Operator::CASE, {}); .) + | lparen CaseParams<&*scope> rparen (. ManagedScpPtr scopeBody = root->add(new xreate::CodeScope(&*scope)); Expression exprCase(Operator::CASE, {}); .) BDecl<&*scopeBody> (. exprCase.addBlock(scope); exprCase.addBlock(scopeBody); outer.addArg(move(exprCase)); .) ). CaseParams = (. Expression condition; Expression guard(Operator::LOGIC_AND, {}); pushContextScope(scope); .) ExprTyped (. guard.addArg(Expression(condition)); .) {',' ExprTyped (. guard.addArg(Expression(condition)); .) } (. scope->setBody(guard); popContextScope(); .) . IntrinsicDecl= (. std::wstring name; .) "intrinsic" Ident< name> (. outer = Expression(Operator::CALL_INTRINSIC, {}); outer.setValue(Atom(name)); .) lparen [CalleeParams] rparen . /*============================ INTERFACES ===============================*/ Imprt<> = -"import" "raw" lparen string (. root.__rawImports.push_back(Atom(t->val).get()); .) -rparen . +"import" "raw" lparen string (. root->__rawImports.push_back(Atom(t->val).get()); .) +rparen '.'. InterfaceData<> = "interface" '(' ( "dfa" ')' InterfaceDFA | "extern-c" ')' InterfaceExternC | "cfa" ')' InterfaceCFA | "adhoc" ')' InterfaceAdhoc ). InterfaceAdhoc<> = '{' { PrefunctionSchemeDecl } '}'. PrefunctionSchemeDecl<> = (. TypeAnnotation typReturn; std::wstring prefName; Expression exprCases; .) pre function Ident tagcolon Type lcurbrack SwitchDecl rcurbrack (. Expression prefData(Operator::CALL, {Atom(prefName), exprCases}); prefData.bindType(typReturn); - root.addInterfaceData(Adhoc, move(prefData)); + root->addInterfaceData(Adhoc, move(prefData)); .). InterfaceExternC<> = (.xreate::ExternData data; .) '{' {IncludeExternDecl | LibExternDecl } '}' - (. root.addExternData(move(data)); .) + (. root->addExternData(move(data)); .) . LibExternDecl = (. std::wstring pkgname, libname; .) Ident assign "library" tagcolon "pkgconfig" '(' string (. pkgname = t->val; .) ')' '.' (. data.addLibrary(Atom(libname), Atom(pkgname)); .) . IncludeExternDecl = (. Expression inc; .) "include" StructLiteral '.' (. data.addIncludeDecl(move(inc)); .) . InterfaceDFA<> = '{' { InstructDecl } '}' . InstructDecl = (.Operator op; Expression tag; Expression scheme; std::vector& tags = scheme.operands; tags.push_back(Expression()); /* return value */ .) "operator" InstructAlias tagcolon '(' (.scheme.setOp(op); .) [ MetaSimpExpr (. tags.push_back(tag); .) { ',' MetaSimpExpr (. tags.push_back(tag); .) } ] ')' [ implic MetaSimpExpr (. tags[0] = tag; .) - ] (. root.addDFAData(move(scheme)); .) + ] (. root->addDFAData(move(scheme)); .) '.'. InstructAlias = ( "map" (. op = Operator::MAP; .) | "list_range" (. op = Operator::LIST_RANGE; .) | "list" (. op = Operator::LIST; .) | "fold" (. op = Operator::FOLD; .) | "index" (. op = Operator::INDEX; .) ). InterfaceCFA<> = '{' { InstructCFADecl } '}' . InstructCFADecl<> = (.Operator op; Expression tag; Expression scheme; std::vector& tags = scheme.operands; .) "operator" InstructAlias tagcolon (. scheme.setOp(op); .) [ MetaSimpExpr (. tags.push_back(tag); .) { ',' MetaSimpExpr (. tags.push_back(tag); .) } -] '.' (. root.addInterfaceData(CFA, move(scheme)); .). +] '.' (. root->addInterfaceData(CFA, move(scheme)); .). /*============================ METAPROGRAMMING ===============================*/ // TagsDecl = (. Expression tag; TagModifier mod = TagModifier::NONE; .) // ':' { MetaSimpExpr (. /*f.addTag(std::move(tag), mod); */ .) // }. FnTag = (. Expression tag; TagModifier mod = TagModifier::NONE; .) MetaSimpExpr ['-' TagMod] (. f->addTag(std::move(tag), mod); .). TagMod = ( "assert" (. mod = TagModifier::ASSERT; .) | "require" (. mod = TagModifier::REQUIRE; .) ). RuleDecl<> = "rule" tagcolon (. RuleArguments args; RuleGuards guards; DomainAnnotation typ; std::wstring arg; .) '(' Ident tagcolon Domain (. args.add(arg, typ); .) {',' Ident tagcolon Domain (. args.add(arg, typ); .) } ')' ["case" RGuard {',' RGuard}] '{' RBody '}' . /* - TODO use RGuard for guards-*/ RuleContextDecl = (.Expression eHead, eGuards, eBody; .) "rule" "context" tagcolon MetaSimpExpr "case" lparen MetaSimpExpr rparen '{' MetaSimpExpr '}' (.scope->contextRules.push_back(Expression(Operator::CONTEXT_RULE, {eHead, eGuards, eBody})); .). Domain = ( "function" (. dom = DomainAnnotation::FUNCTION; .) | "variable" (. dom = DomainAnnotation::VARIABLE; .) ). RGuard= (. Expression e; .) MetaExpr (. guards.add(std::move(e)); .). MetaExpr= (.Operator op; Expression e2; .) MetaExpr2 [MetaOp MetaExpr2 (. e = Expression(op, {e, e2}); .) ]. MetaExpr2= ( '(' MetaExpr ')' | MetaSimpExpr ). MetaSimpExpr= (. std::wstring i1, infix; Expression e2; .) ( '-' MetaSimpExpr (. e = Expression(Operator::NEG, {e2}); .) | IF(checkParametersList()) Ident (. e = Expression(Operator::CALL, {Expression(Atom(i1))}); .) '(' [ MetaCalleeParams ] ')' | IF(checkInfix()) Ident Ident MetaSimpExpr (. e = Expression(Operator::CALL, {Expression(Atom(infix))}); e.addArg(Expression(Atom(i1))); e.addArg(std::move(e2)); .) | Ident (. e = Expression(Atom(i1)); .) ). MetaCalleeParams = (. Expression e2; .) MetaSimpExpr (. e.addArg(Expression(e2)); .) {',' MetaSimpExpr (. e.addArg(Expression(e2)); .) }. RBody = (. Expression e; std::wstring msg; .) "warning" MetaExpr ["message" string (. msg = t->val; .) -] (. root.add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom(msg))); .) +] (. root->add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom(msg))); .) . MetaOp< Operator& op> = implic (. op = Operator::IMPL; .) . /*============================ Expressions ===============================*/ ExprAnnotations = (. TypeAnnotation typ; std::list tags; Expression tag; e.tags.clear();.) Type (. e.bindType(move(typ)); .) {';' MetaSimpExpr (. tags.push_back(tag); .) } (. e.addTags(tags); .) . ExprTyped = Expr [tagcolon ExprAnnotations]. Expr< Expression& e> (. Operator op; Expression e2; .) = ExprArithmAdd [ RelOp ExprArithmAdd (. e = Expression(op, {e, e2}); .) ]. ExprArithmAdd< Expression& e>= (. Operator op; Expression e2; .) ExprArithmMul< e> [ AddOp< op> ExprArithmAdd< e2> (. e = Expression(op, {e, e2});.) ]. ExprArithmMul< Expression& e> (. Operator op; Expression e2; .) = ExprPostfix< e> [ MulOp< op> ExprArithmMul< e2> (. e = Expression(op, {e, e2}); .) ]. ExprPostfix = Term [lbrack (. e = Expression(Operator::INDEX, {e}); .) CalleeParams rbrack ]. Term< Expression& e> (. std::wstring name; e = Expression(); .) = (IF (checkParametersList()) Ident< name> (. e = Expression(Operator::CALL, {Atom(name)}); .) '(' [CalleeParams] ')' | VarIdent (. recognizeIdentifier(e); .) | ListLiteral (. /* tuple */.) | StructLiteral (. /* struct */.) | LoopDecl | IfDecl | SwitchDecl | AdhocDecl | IntrinsicDecl | "true" (. e = Expression(Atom(1)); e.bindType(TypePrimitive::Bool); .) | "false" (. e = Expression(Atom(0)); e.bindType(TypePrimitive::Bool); .) | number (. e = Expression(Atom(t->val)); .) | string (. e = Expression(Atom(t->val)); .) | '-' Term (. e = Expression(Operator::NEG, {e}); .) | '(' ExprTyped ')' ). StructLiteral = (. std::wstring key; Expression val; std::list> keys; .) '{' Ident '=' Expr (. keys.push_back(Atom(key)); e = Expression(Operator::LIST_NAMED, {val}); .) {',' Ident '=' Expr (.e.addArg(Expression(val)); keys.push_back(Atom(key)); .) } '}' (. e.addBindings(keys.begin(), keys.end()); .) . ListLiteral = (. Expression eFrom, eTo; .) '[' [ Expr (. e.addArg(Expression(eFrom)); .) (".." Expr (. e.addArg(Expression(eTo)); e.setOp(Operator::LIST_RANGE); .) |{',' Expr (. e.addArg(Expression(eFrom)); .) } (. e.setOp(Operator::LIST); .) ) ] ']'. AdhocDecl = (. Expression command; .) "ad" "hoc" MetaSimpExpr (. AdhocExpression exprAdhoc; exprAdhoc.setCommand(command); e = exprAdhoc; .). CalleeParams = (. Expression e2; .) ExprTyped (. e.addArg(Expression(e2)); .) {',' ExprTyped (. e.addArg(Expression(e2)); .) }. AddOp< Operator& op> = (. op = Operator::ADD; .) ( '+' | '-' (. op = Operator::SUB; .) ). MulOp< Operator& op> = (. op = Operator::MUL; .) ( '*' | '/' (. op = Operator::DIV; .) ). RelOp< Operator& op> = (. op = Operator::EQU; .) ( equal | (ne1 | ne2) (. op = Operator::NE; .) | lse (. op = Operator::LSE; .) | lss (. op = Operator::LSS; .) | gte (. op = Operator::GTE; .) | gtr (. op = Operator::GTR; .) ). +SkipModulesSection = "module" '{' {ANY} '}'. + END Xreate. diff --git a/scripts/containers/Containers_Implementation_LinkedList1.xreate b/scripts/containers/Containers_Implementation_LinkedList1.xreate index a645574..c1998de 100644 --- a/scripts/containers/Containers_Implementation_LinkedList1.xreate +++ b/scripts/containers/Containers_Implementation_LinkedList1.xreate @@ -1,47 +1,47 @@ // EXTERN INCLUDES interface(extern-c){ xml2 = library:: pkgconfig("libxml-2.0"). include { xml2 = ["libxml/tree.h"] }. } // CONTAINERS interface(dfa) { operator map:: (op(seqaccess)) -> impl(solid). operator list_range:: ()->impl(on_the_fly). operator list:: ()->impl(solid). operator fold:: (op(seqaccess)). /* operator index:: (op(randaccess)). - BREAKS THE ANALYSIS. MAKE tree VIEWED AS COLLECTION */ /* operator map: (op(seqaccess)) -> impl(llvm_array | on_the_fly); */ } -import raw("core/containers.lp") +import raw("core/containers.lp"). // PROGRAM XmlNode = type alias { tag:: string, /* attrs:: [string],*/ content:: string }. Tree = type Tree(Leaf) [Leaf, [Tree(Leaf)]]. XmlTree = type alias Tree(XmlNode). test= function:: num; entry { filename = "scripts/containers/Containers_Implementation_LinkedList1-data.xml" :: string. docRaw = xmlParseFile(filename) :: xmlDocPtr. tree= xmlDocGetRootElement(docRaw) :: xmlNodePtr. childrenRaw = tree["children"]:: [xmlNodePtr]; linkedlist(next, null). size = loop fold(childrenRaw->child:: xmlNodePtr, 0->count):: int { count +1::int }. size }