No OneTemporary

File Metadata

Created
Sat, Mar 14, 4:31 AM
diff --git a/config/default.json b/config/default.json
index a73a43d..e7f99d6 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,73 +1,74 @@
{
"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",
"transcend": {
"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": "latereasoning",
+ "template": "intrinsic-query",
"templates": {
"current-fix":"*",
"default": "*-Adhoc.*:Containers.*:Compilation.full_IFStatementWithVariantType:Types.full_VariantType_Switch1:Context.full_LateContext:Context.pathDependentContext:CFA.testLoopContextExists",
"ast": "AST.*",
"effects": "Effects.*",
"basic": "Attachments.*",
"compilation": "Compilation.*-Compilation.full_IFStatementWithVariantType",
"communication": "Communication.*",
"cfa": "CFA.*",
"containers": "Containers.*",
"dfa": "DFA.*",
"diagnostic": "Diagnostic.*",
"dsl": "Association.*:Interpretation.*",
"exploitation": "Exploitation.*",
"ExpressionSerializer": "ExpressionSerializer.*",
"externc": "InterfaceExternC.*",
"loops": "Loop.*",
"latereasoning": "LateReasoning.Compilation2",
"modules": "Modules.*",
"polymorphs": "Polymorphs.*",
+ "intrinsic-query": "Types.SlaveTypes*:Association.TypedQuery*",
"types": "Types.*",
"virtualization": "Virtualization.test2",
"vendorsAPI/clang": "ClangAPI.*",
"vendorsAPI/xml2": "libxml2*"
}
}
}
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index f03ed0e..8fd4295 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -1,231 +1,232 @@
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(STATUS "LLVM DEFS: " ${LLVM_DEFINITIONS})
execute_process(
COMMAND llvm-config --libs
OUTPUT_VARIABLE LLVM_LIBS
OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "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}/../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_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
)
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
- compilation/latereasoning.cpp
+ compilation/interpretation-instructions.cpp
analysis/typeinference.cpp
+ compilation/latereasoning.cpp
aux/latereasoning.cpp
xreatemanager.cpp
transcendlayer.cpp
analysis/dfagraph.cpp
analysis/DominatorsTreeAnalysisProvider.cpp
llvmlayer.cpp
ExternLayer.cpp
pass/compilepass.cpp
query/polymorph.cpp
analysis/utils.cpp
pass/dfapass.cpp
compilation/targetinterpretation.cpp
pass/interpretationpass.cpp
ast.cpp
aux/xreatemanager-decorators.cpp
compilation/operators.cpp
compilation/transformations.cpp
compilation/transformersaturation.cpp
pass/versionspass.cpp
attachments.cpp
analysis/cfagraph.cpp
compilation/containers.cpp
compilation/advancedinstructions.cpp
utils.cpp
pass/abstractpass.cpp
pass/cfapass.cpp
contextrule.cpp
query/containers.cpp
aux/serialization/expressionserializer.cpp
modules.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 ${COCO_SOURCE_FILES} ${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 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/analysis/typeinference.cpp b/cpp/src/analysis/typeinference.cpp
index 38b3d5d..8d3992c 100644
--- a/cpp/src/analysis/typeinference.cpp
+++ b/cpp/src/analysis/typeinference.cpp
@@ -1,93 +1,185 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* typeinference.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on April 16, 2017, 10:13 AM
*/
/**
* \file typeinference.h
* \brief Type inference analysis
*/
#include "typeinference.h"
#include "llvmlayer.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/DerivedTypes.h"
#include "transcendlayer.h"
using namespace std;
-namespace xreate {namespace typeinference {
+namespace xreate{
+namespace typeinference{
//TODO type conversion:
//a) automatically expand types int -> bigger int; int -> floating
//b) detect exact type of `num` based on max used numeral / function type
//c) warning if need to truncate (allow/dissalow based on annotations)
llvm::Value*
-doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, llvm::IRBuilder<>& builder){
- if (tyTarget->isIntegerTy() && source->getType()->isIntegerTy())
- {
- llvm::IntegerType* tyTargetInt = llvm::dyn_cast<llvm::IntegerType>(tyTarget);
- llvm::IntegerType* tySourceInt = llvm::dyn_cast<llvm::IntegerType>(source->getType());
-
- if (tyTargetInt->getBitWidth() < tySourceInt->getBitWidth()){
- return builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
- }
-
- if (tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()){
- return builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
- }
+doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, llvm::IRBuilder<>& builder) {
+ if(tyTarget->isIntegerTy() && source->getType()->isIntegerTy()) {
+ llvm::IntegerType* tyTargetInt = llvm::dyn_cast<llvm::IntegerType>(tyTarget);
+ llvm::IntegerType* tySourceInt = llvm::dyn_cast<llvm::IntegerType>(source->getType());
+
+ if(tyTargetInt->getBitWidth() < tySourceInt->getBitWidth()) {
+ return builder.CreateCast(llvm::Instruction::Trunc, source, tyTarget);
+ }
+
+ if(tyTargetInt->getBitWidth() > tySourceInt->getBitWidth()) {
+ return builder.CreateCast(llvm::Instruction::SExt, source, tyTarget);
+ }
}
- if (source->getType()->isIntegerTy() && tyTarget->isFloatingPointTy()){
+ if(source->getType()->isIntegerTy() && tyTarget->isFloatingPointTy()) {
return builder.CreateCast(llvm::Instruction::SIToFP, source, tyTarget);
}
return source;
}
ExpandedType
-getType(const Expression& expression, const AST& ast){
- if (expression.type.isValid()){
- return ast.expandType(expression.type);
+getType(const Expression& expression, const AST& ast) {
+ if(expression.type.isValid()) {
+ return ast.expandType(expression.type);
}
- if (expression.__state == Expression::IDENT){
+ if(expression.__state == Expression::IDENT) {
Symbol s = Attachments::get<IdentifierSymbol>(expression);
return getType(CodeScope::getDefinition(s), ast);
}
- if (Attachments::exists<TypeInferred>(expression)){
+ if(Attachments::exists<TypeInferred>(expression)) {
return Attachments::get<TypeInferred>(expression);
}
- if(expression.__state==Expression::NUMBER){
- return ExpandedType (TypeAnnotation(TypePrimitive::I32));
+ if(expression.__state == Expression::NUMBER) {
+ return ExpandedType(TypeAnnotation(TypePrimitive::I32));
}
assert(false && "Type can't be determined for an expression");
}
-std::vector<Expression>
-getSlaveVariants(ExpandedType t, const TranscendLayer* transcend){
+TypeAnnotation collapseColumn(const std::list<Gringo::Symbol>& symbols);
+
+TypeAnnotation
+collapseFnGroup(const std::list<Gringo::Symbol>& symbols) {
+ Gringo::Symbol symbolAny = symbols.front();
+ size_t operandsCount = symbolAny.args().size;
+
+ TypeAnnotation resultT;
+ resultT.__operands.reserve(operandsCount);
+
+ for(size_t operandId = 0; operandId < operandsCount; ++operandId) {
+ std::list<Gringo::Symbol> column;
+
+ for(const Gringo::Symbol& row : symbols) {
+ column.push_back(row.args()[operandId]);
+ }
+
+ TypeAnnotation operandT = collapseColumn(column);
+ resultT.__operands.push_back(operandT);
+ }
+
+ if(resultT.__operands.size() == 1) {
+ return resultT.__operands.front();
+ }
+
+ if(resultT.__operands.size() > 1) {
+ resultT.__operator = TypeOperator::LIST_NAMED;
+ return resultT;
+ }
+
+ return resultT;
+}
+
+TypeAnnotation
+collapseColumn(const std::list<Gringo::Symbol>& symbols) {
+ TypeAnnotation resultT;
+ if(!symbols.size()) return resultT;
+
+ Gringo::Symbol symbolAny = symbols.front();
+
+ switch(symbolAny.type()) {
+ case Gringo::SymbolType::Num:
+ {
+ return TypeAnnotation(TypePrimitive::Num);
+ }
+
+ case Gringo::SymbolType::Str:
+ {
+ return TypeAnnotation(TypePrimitive::String);
+ }
+
+ case Gringo::SymbolType::Fun:
+ {
+ map<string, list < Gringo::Symbol>> fnGroups;
+
+ for(const Gringo::Symbol& row : symbols) {
+ fnGroups[row.name().c_str()].push_back(row);
+ }
+
+ TypeAnnotation resultT;
+ resultT.__operands.reserve(fnGroups.size());
+ resultT.bindings.reserve(fnGroups.size());
+
+ for(const auto& group : fnGroups) {
+ if(!group.second.size()) continue;
+
+ TypeAnnotation variantT = collapseFnGroup(group.second);
+ Gringo::Symbol symbolAny = group.second.front();
+ string variantName = symbolAny.name().c_str();
+ resultT.fields.push_back(variantName);
+ resultT.__operands.push_back(variantT);
+ }
+
+ resultT.__operator = TypeOperator::VARIANT;
+ if(resultT.__operands.size() == 1) {
+ return resultT.__operands.front();
+ }
+ return resultT;
+ }
+
+ case Gringo::SymbolType::Inf:
+ case Gringo::SymbolType::Special:
+ case Gringo::SymbolType::Sup:
+ {
+ break;
+ }
+ }
+
+ assert(false);
+ return TypeAnnotation();
+}
+
+ExpandedType
+dereferenceSlaveType(ExpandedType t, const TranscendLayer* transcend) {
assert(t->__operator == TypeOperator::SLAVE);
const string& domain = t->__valueCustom;
StaticModel model = transcend->query(domain);
+ if(!model.size()) return ExpandedType(TypeAnnotation());
- vector<Expression> result;
- result.reserve(model.size());
- for(auto entry: model){
- result.push_back(get<0>(TranscendLayer::parse<Expression>(entry.second)));
+ std::list<Gringo::Symbol> symbols;
+ for(auto row : model) {
+ symbols.push_back(row.second);
}
-
- return result;
+ return ExpandedType(collapseFnGroup(symbols));
}
-} } //end of namespace xreate::typeinference
+}
+} //end of namespace xreate::typeinference
diff --git a/cpp/src/analysis/typeinference.h b/cpp/src/analysis/typeinference.h
index aa956a3..500fc17 100644
--- a/cpp/src/analysis/typeinference.h
+++ b/cpp/src/analysis/typeinference.h
@@ -1,35 +1,37 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: typeinference.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on April 16, 2017, 10:17 AM
*/
#ifndef TYPEINFERENCE_H
#define TYPEINFERENCE_H
#include "ast.h"
#include "llvm/IR/IRBuilder.h"
-namespace llvm {
- class Value;
- class Type;
+namespace llvm{
+class Value;
+class Type;
};
-namespace xreate {
- class TranscendLayer;
+namespace xreate{
+class TranscendLayer;
};
-namespace xreate { namespace typeinference {
-
+namespace xreate{
+namespace typeinference{
+
llvm::Value* doAutomaticTypeConversion(llvm::Value* source, llvm::Type* tyTarget, llvm::IRBuilder<>& builder);
-ExpandedType getType(const Expression& expression, const AST& ast);
-std::vector<Expression> getSlaveVariants(ExpandedType t, const TranscendLayer* transcend);
+ExpandedType getType(const Expression& expression, const AST& ast);
+ExpandedType dereferenceSlaveType(ExpandedType t, const TranscendLayer* transcend);
-} }//namespace xreate::typeinference
+}
+}//namespace xreate::typeinference
#endif /* TYPEINFERENCE_H */
diff --git a/cpp/src/compilation/interpretation-instructions.cpp b/cpp/src/compilation/interpretation-instructions.cpp
new file mode 100644
index 0000000..97c2634
--- /dev/null
+++ b/cpp/src/compilation/interpretation-instructions.cpp
@@ -0,0 +1,167 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on June 15, 2018, 5:32 PM
+ *
+ */
+
+#include "compilation/interpretation-instructions.h"
+#include "analysis/typeinference.h"
+#include "transcendlayer.h"
+#include "targets.h"
+
+using namespace std;
+
+namespace xreate{
+namespace interpretation{
+
+Expression
+IntrinsicQueryInstruction::representTransExpression(const Gringo::Symbol& atom, ExpandedType schemaT) {
+ TranscendLayer* transcend = static_cast<TargetInterpretation*> (__scope->function->man)->pass->man->transcend;
+
+ switch(schemaT->__operator) {
+ case TypeOperator::NONE:
+ {
+ switch(schemaT->__value) {
+ case TypePrimitive::I8:
+ case TypePrimitive::I32:
+ case TypePrimitive::I64:
+ case TypePrimitive::Num:
+ case TypePrimitive::Int:
+ {
+ return Expression(Atom<Number_t>(atom.num()));
+ }
+
+ case TypePrimitive::String:
+ {
+ return Expression(Atom<String_t>(atom.string().c_str()));
+ }
+
+ case TypePrimitive::Invalid:
+ case TypePrimitive::Bool:
+ case TypePrimitive::Float:
+ {
+ assert(false);
+ return Expression();
+ }
+ }
+ break;
+ }
+
+ case TypeOperator::SLAVE:
+ {
+ ExpandedType contentT = typeinference::dereferenceSlaveType(schemaT, transcend);
+ return representTransExpression(atom, contentT);
+ }
+
+ case TypeOperator::VARIANT:
+ {
+ map<string, int> dictVariants;
+ for(size_t variantId = 0; variantId < schemaT->fields.size(); ++variantId) {
+ dictVariants.emplace(schemaT->fields.at(variantId), variantId);
+ }
+
+ string predicateName = atom.name().c_str();
+ assert(dictVariants.count(predicateName));
+
+ size_t predicateId = dictVariants.at(predicateName);
+ Expression result(Operator::VARIANT,{});
+ result.op = Operator::VARIANT;
+ result.setValueDouble(predicateId);
+
+ if(!schemaT->__operands.size()) return result;
+ ExpandedType contentT = schemaT->__operands.at(0).__operator == TypeOperator::SLAVE
+ ? typeinference::dereferenceSlaveType(ExpandedType(schemaT->__operands.at(0)), transcend)
+ : ExpandedType(schemaT->__operands.at(0));
+
+ //edge case, content's type is LIST_NAMED:
+ if (contentT->__operator == TypeOperator::LIST_NAMED) {
+ result.operands.push_back(representTransExpression(atom, contentT));
+
+ } else {
+ assert(atom.args().size);
+ result.operands.push_back(representTransExpression(atom.args()[0], contentT));
+ }
+
+ return result;
+ }
+
+ case TypeOperator::LIST_NAMED:
+ {
+ const Gringo::SymSpan& operandsRaw = atom.args();
+ size_t opCount = operandsRaw.size;
+ assert(opCount == schemaT->__operands.size());
+
+ size_t operandId = 0;
+ std::vector<Expression> operands;
+ operands.reserve(opCount);
+ for(const TypeAnnotation operandT : schemaT->__operands) {
+ operands.push_back(representTransExpression(operandsRaw[operandId], ExpandedType(operandT)));
+ ++operandId;
+ }
+
+ Expression result(Operator::LIST_NAMED,{});
+ result.operands = operands;
+ result.type = schemaT;
+ return result;
+ }
+
+ case TypeOperator::LIST:
+ case TypeOperator::CALL:
+ case TypeOperator::CUSTOM:
+ case TypeOperator::ACCESS:
+ case TypeOperator::LINK:
+ {
+ assert(false);
+ return Expression();
+ }
+ }
+
+ assert(false);
+ return Expression();
+}
+
+Expression
+IntrinsicQueryInstruction::process(const Expression& expression) {
+ AST* ast = static_cast<TargetInterpretation*> (__scope->function->man)->ast;
+ TranscendLayer* transcend = static_cast<TargetInterpretation*> (__scope->function->man)->pass->man->transcend;
+ InterpretationFunction* function = static_cast<InterpretationFunction*> (__scope->function);
+
+ ExpandedType targetT = ast->expandType(expression.type);
+ assert(expression.operands.size() == 1);
+ assert(expression.operands.front().__state == Expression::STRING);
+ assert(targetT->__operator == TypeOperator::LIST);
+
+ std::string namePredicate = expression.operands.front().getValueString();
+ StaticModel model = (static_cast<TargetInterpretation*> (function->man))->pass->man->transcend->query(namePredicate);
+
+ Expression result(Operator::LIST,{});
+ result.operands.reserve(model.size());
+
+ ExpandedType elementT = targetT->__operands.at(0).__operator == TypeOperator::SLAVE
+ ? typeinference::dereferenceSlaveType(ExpandedType(targetT->__operands.at(0)), transcend)
+ : ExpandedType(targetT->__operands.at(0));
+
+ if(model.size()) {
+ if (elementT->__operator == TypeOperator::LIST_NAMED) {
+ //edge case, content's type is LIST_NAMED:
+ for(const auto& row : model) {
+ result.operands.push_back(representTransExpression(row.second, elementT));
+ }
+ } else {
+ for (const auto& row : model) {
+ assert(row.second.args().size);
+ result.operands.push_back(representTransExpression(row.second.args()[0], elementT));
+ }
+ }
+ }
+
+ return result;
+}
+}
+} //end of xreate::interpretation
\ No newline at end of file
diff --git a/cpp/src/compilation/interpretation-instructions.h b/cpp/src/compilation/interpretation-instructions.h
new file mode 100644
index 0000000..2ff6c8c
--- /dev/null
+++ b/cpp/src/compilation/interpretation-instructions.h
@@ -0,0 +1,39 @@
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+/*
+ * Author: pgess <v.melnychenko@xreate.org>
+ * Created on June 15, 2018, 5:28 PM
+ *
+ * \file interpretation-instructions.h
+ * \brief Additional intepretation statements
+ */
+
+#ifndef INTERPRETATION_INSTRUCTIONS_H
+#define INTERPRETATION_INSTRUCTIONS_H
+
+#include "compilation/targetinterpretation.h"
+#include "ast.h"
+
+namespace xreate{
+namespace interpretation{
+
+class IntrinsicQueryInstruction{
+public:
+
+ IntrinsicQueryInstruction(InterpretationScope* scope): __scope(scope){ }
+ Expression process(const Expression& expression);
+
+private:
+ InterpretationScope* __scope;
+ Expression representTransExpression(const Gringo::Symbol& atom, ExpandedType schemaT);
+};
+
+}
+} //end of xreate::interpretation
+
+#endif /* INTERPRETATION_INSTRUCTIONS_H */
+
diff --git a/cpp/src/compilation/latereasoning.cpp b/cpp/src/compilation/latereasoning.cpp
index 97a7eb6..e62201f 100644
--- a/cpp/src/compilation/latereasoning.cpp
+++ b/cpp/src/compilation/latereasoning.cpp
@@ -1,79 +1,79 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* latereasoning.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on May 26, 2018, 3:54 PM
*/
#include "compilation/latereasoning.h"
#include "aux/latereasoning.h"
#include "compilation/scopedecorators.h"
#include "analysis/typeinference.h"
#include <vector>
using namespace xreate::compilation;
using namespace std;
namespace xreate{ namespace latereasoning {
llvm::Value*
LateReasoningCompiler::compile(const Expression& expr, const std::string& identHint){
#define HINT(x) (identHint.empty()? x : identHint)
LLVMLayer* llvm = context.pass->man->llvm;
compilation::ICodeScopeUnit* scope = context.scope;
AST* root = context.pass->man->root;
llvm::IRBuilder<>& builder = llvm->builder;
compilation::IFunctionUnit* function = context.function;
llvm::Type* typI8= llvm::Type::getInt8Ty(llvm->llvmContext);
CodeScope* scopeBody = expr.blocks.front();
Symbol guardS = Symbol{scopeBody->getSymbol(expr.bindings.front()), scopeBody};
- const ExpandedType& typCondition = root->getType(expr.operands.at(0));
- vector<Expression> guardVariants = typeinference::getSlaveVariants(typCondition, context.pass->man->transcend);
- const int countVariants = guardVariants.size();
+ const ExpandedType& conditionT = root->getType(expr.operands.at(0));
+ const ExpandedType& conditionTPlain = typeinference::dereferenceSlaveType(conditionT, context.pass->man->transcend);
+ const int countVariants = conditionTPlain->fields.size();
assert(countVariants);
llvm::Value * conditionRaw = scope->process(expr.operands.at(0));
llvm::Value* variantRaw = builder.CreateExtractValue(conditionRaw, llvm::ArrayRef<unsigned>({0}));
llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(variantRaw, nullptr, countVariants);
llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm->llvmContext, "switchLateAfter", function->raw);
builder.SetInsertPoint(blockEpilog);
llvm::Type* exprSwitchType = llvm->toLLVMType(root->getType(expr));
llvm::PHINode *ret = builder.CreatePHI(exprSwitchType, countVariants, HINT("switchLate"));
llvm::BasicBlock* blockDefault = nullptr;
bool flagFirstPass = true;
for (int variantId = 0; variantId<countVariants; ++variantId){
//Pass information to the late model
flagFirstPass?
- Attachments::put<LateBindingT>(guardS, guardVariants.at(variantId))
- : Attachments::update<LateBindingT>(guardS, guardVariants.at(variantId));
+ Attachments::put<LateBindingT>(guardS, Expression(Operator::CALL, {Expression(Atom<Identifier_t>(string(conditionTPlain->fields.at(variantId))))}))
+ : Attachments::update<LateBindingT>(guardS, Expression(Operator::CALL, {Expression(Atom<Identifier_t>(string(conditionTPlain->fields.at(variantId))))}));
flagFirstPass = false;
llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(
llvm->llvmContext,
"case" + std::to_string(variantId),
function->raw);
if(variantId == 0) blockDefault = blockCase;
builder.SetInsertPoint(blockCase);
auto scopeBody = Decorators<CachedScopeDecoratorTag>::getInterface<>(
function->getScopeUnit(expr.blocks.back()));
scopeBody->reset();
llvm::Value* resultCase = scopeBody->compile();
ret->addIncoming(resultCase, builder.GetInsertBlock());
instructionSwitch->addCase(llvm::dyn_cast<llvm::ConstantInt>(llvm::ConstantInt::get(typI8, variantId)), blockCase);
builder.CreateBr(blockEpilog);
}
instructionSwitch->setDefaultDest(blockDefault);
builder.SetInsertPoint(blockEpilog);
return ret;
}
}}
\ No newline at end of file
diff --git a/cpp/src/compilation/targetinterpretation.cpp b/cpp/src/compilation/targetinterpretation.cpp
index 9d7d29d..1658d2f 100644
--- a/cpp/src/compilation/targetinterpretation.cpp
+++ b/cpp/src/compilation/targetinterpretation.cpp
@@ -1,645 +1,593 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: targetinterpretation.cpp
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on June 29, 2016, 6:45 PM
*/
/**
* \file targetinterpretation.h
* \brief Interpretation support. See more [details on Interpretation](/w/concepts/dsl/)
*/
#include "compilation/targetinterpretation.h"
#include "pass/interpretationpass.h"
#include "analysis/typeinference.h"
#include "llvmlayer.h"
#include "compilation/scopedecorators.h"
+#include "compilation/interpretation-instructions.h"
#include <boost/scoped_ptr.hpp>
#include <iostream>
-#include <clang/AST/DeclBase.h>
#include <csignal>
using namespace std;
using namespace xreate::compilation;
namespace xreate{ namespace interpretation{
const Expression EXPRESSION_FALSE = Expression(Atom<Number_t>(0));
const Expression EXPRESSION_TRUE = Expression(Atom<Number_t>(1));
-Expression
-representAsAnnotation(const Gringo::Symbol& atom){
- switch (atom.type()) {
- case Gringo::SymbolType::Num: {
- Expression result(Operator::VARIANT, {Expression(atom.num())});
- result.setValueDouble(0);
- return result;
- }
-
- case Gringo::SymbolType::Str: {
- Expression result(Operator::VARIANT, {Expression(Atom<String_t>(std::string(atom.string().c_str())))});
- result.setValueDouble(1);
- return result;
- }
-
- case Gringo::SymbolType::Fun: {
- Expression fnDescription(Operator::LIST_NAMED, {});
- std::list<Atom<Identifier_t>> bindings{Atom<Identifier_t>("name"), Atom<Identifier_t>("arguments")};
- fnDescription.addBindings(bindings.begin(), bindings.end());
- fnDescription.addArg(Expression(Atom<String_t>(std::string(atom.name().c_str()))));
-
- Expression args(Operator::LIST, {});
- for (const Gringo::Symbol& arg : atom.args()) {
- args.addArg(representAsAnnotation(arg));
- }
-
- fnDescription.addArg(std::move(args));
-
- Expression result(Operator::VARIANT, {fnDescription});
- result.setValueDouble(2);
- return result;
- }
-
- default: {
- assert(false);
- }
- }
-}
-
CodeScope*
InterpretationScope::processOperatorIf(const Expression& expression){
const Expression& exprCondition = process(expression.getOperands()[0]);
if (exprCondition == EXPRESSION_TRUE){
return expression.blocks.front();
}
return expression.blocks.back();
}
CodeScope*
InterpretationScope::processOperatorSwitch(const Expression& expression) {
const Expression& exprCondition = process(expression.operands[0]);
bool flagHasDefault = expression.operands[1].op == Operator::CASE_DEFAULT;
//TODO check that one and only one case variant is appropriate
for (size_t size = expression.operands.size(), i= flagHasDefault? 2: 1; i<size; ++i){
const Expression& exprCase = process(expression.operands[i]);
if (function->getScope((const CodeScope*) exprCase.blocks.front())->processScope() == exprCondition){
return exprCase.blocks.back();
}
}
if (flagHasDefault){
const Expression& exprCaseDefault = expression.operands[1];
return exprCaseDefault.blocks.front();
}
assert(false && "Switch has no appropriate variant");
return nullptr;
}
CodeScope*
InterpretationScope::processOperatorSwitchVariant(const Expression& expression){
const Expression& condition = process(expression.operands.at(0));
assert(condition.op == Operator::VARIANT);
const string& identCondition = expression.bindings.front();
Expression opExpected(Atom<Number_t>(condition.getValueDouble()));
auto itFoundValue = std::find(++expression.operands.begin(), expression.operands.end(), opExpected);
assert(itFoundValue != expression.operands.end());
int indexBlock = itFoundValue - expression.operands.begin() -1;
auto blockFound = expression.blocks.begin();
std::advance(blockFound, indexBlock);
InterpretationScope* scopeI12n = function->getScope(*blockFound);
if(condition.operands.size()){
const Expression& value=condition.operands.at(0);
scopeI12n->overrideBindings({
{value, identCondition}});
}
return *blockFound;
}
llvm::Value*
InterpretationScope::compileHybrid(const InterpretationOperator& op, const Expression& expression, const Context& context){
switch(op){
case IF_INTERPRET_CONDITION: {
CodeScope* scopeResult = processOperatorIf(expression);
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case SWITCH_INTERPRET_CONDITION:{
CodeScope* scopeResult = processOperatorSwitch(expression);
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case SWITCH_VARIANT: {
CodeScope* scopeResult = processOperatorSwitchVariant(expression);
const Expression& condition = expression.operands.at(0);
const Expression& valueCondition = process(condition);
const string identCondition = expression.bindings.front();
auto scopeCompilation = Decorators<CachedScopeDecoratorTag>::getInterface(context.function->getScopeUnit(scopeResult));
if(valueCondition.operands.size()){
//override value
Symbol symbCondition{ScopedSymbol{scopeResult->__identifiers.at(identCondition), versions::VERSION_NONE}, scopeResult};
scopeCompilation->overrideDeclarations(
{{symbCondition, Expression(valueCondition.operands.at(0))}}
);
//set correct type for binding:
TypeAnnotation typeVariant = typeinference::getType(condition, *function->man->ast);
int conditionIndex = valueCondition.getValueDouble();
ScopedSymbol symbolInternal = scopeResult->getSymbol(identCondition);
scopeResult->__declarations[symbolInternal].bindType(typeVariant.__operands.at(conditionIndex));
}
llvm::Value* result = context.function->getScopeUnit(scopeResult)->compile();
return result;
}
case FOLD_INTERPRET_INPUT: {
//initialization
const Expression& exprInput = process(expression.getOperands()[0]);
assert(exprInput.op == Operator::LIST);
CodeScope* scopeBody = expression.blocks.front();
const string& nameEl = expression.bindings[0];
Symbol symbEl{ScopedSymbol{scopeBody->__identifiers.at(nameEl), versions::VERSION_NONE}, scopeBody};
const std::string& idAccum = expression.bindings[1];
llvm::Value* rawAccum = context.scope->process(expression.getOperands()[1]);
InterpretationScope* intrBody = function->getScope(scopeBody);
auto unitBody = Decorators<CachedScopeDecoratorTag>::getInterface(context.function->getScopeUnit(scopeBody));
const std::vector<Expression> elementsInput= exprInput.getOperands();
for(size_t i=0; i<elementsInput.size(); ++i) {
const Expression& exprElement=elementsInput[i];
intrBody->overrideBindings({
{exprElement, nameEl}});
unitBody->overrideDeclarations({
{symbEl, exprElement}}); //resets unitBody
unitBody->bindArg(rawAccum, string(idAccum));
rawAccum=unitBody->compile();
}
return rawAccum;
}
/*
case FOLD_INF_INTERPRET_INOUT{
}
*/
//TODO refactor as InterpretationCallStatement class
case CALL_INTERPRET_PARTIAL: {
const std::string &calleeName = expression.getValueString();
ICodeScopeUnit* scopeUnitSelf = context.scope;
ManagedFnPtr callee = this->function->man->ast->findFunction(calleeName);
const FunctionInterpretationData& calleeData = FunctionInterpretationHelper::getSignature(callee);
std::vector<llvm::Value *> argsActual;
PIFSignature sig;
sig.declaration = callee;
for(size_t no=0, size = expression.operands.size(); no < size; ++no){
const Expression& op = expression.operands[no];
if (calleeData.signature.at(no) == INTR_ONLY){
sig.bindings.push_back(process(op));
continue;
}
argsActual.push_back(scopeUnitSelf->process(op));
}
TargetInterpretation* man = dynamic_cast<TargetInterpretation*>(this->function->man);
PIFunction* pifunction = man->getFunction(move(sig));
llvm::Function* raw = pifunction->compile();
boost::scoped_ptr<CallStatementRaw> statement(new CallStatementRaw(raw, man->pass->man->llvm));
return (*statement)(move(argsActual));
}
default: break;
}
assert(false&& "Unknown hybrid operator");
return nullptr;
}
llvm::Value*
InterpretationScope::compile(const Expression& expression, const Context& context){
const InterpretationData& data = Attachments::get<InterpretationData>(expression);
if (data.op != InterpretationOperator::NONE){
return compileHybrid(data.op, expression, context);
}
Expression result = process(expression);
return context.scope->process(result);
}
Expression
InterpretationScope::process(const Expression& expression) {
#ifndef NDEBUG
if (expression.tags.count("bpoint")){
std::raise(SIGINT);
}
#endif
PassManager* man = (static_cast<TargetInterpretation*> (function->man))->pass->man;
switch (expression.__state){
case Expression::INVALID:
assert(false);
case Expression::NUMBER:
case Expression::STRING:
return expression;
case Expression::IDENT:{
Symbol s = Attachments::get<IdentifierSymbol>(expression);
return Parent::processSymbol(s);
}
case Expression::COMPOUND:
break;
default: assert(false);
}
switch (expression.op) {
case Operator::EQU: {
const Expression& left = process(expression.operands[0]);
const Expression& right = process(expression.operands[1]);
if (left == right) return EXPRESSION_TRUE;
return EXPRESSION_FALSE;
}
case Operator::NE: {
const Expression& left = process(expression.operands[0]);
const Expression& right = process(expression.operands[1]);
if (left == right) return EXPRESSION_FALSE;
return EXPRESSION_TRUE;
}
case Operator::LOGIC_AND: {
assert(expression.operands.size() == 1);
return process (expression.operands[0]);
}
// case Operator::LOGIC_OR:
case Operator::CALL: {
const std::string &fnName = expression.getValueString();
ManagedFnPtr fnAst = this->function->man->ast->findFunction(fnName);
InterpretationFunction* fnUnit = this->function->man->getFunction(fnAst);
vector<Expression> args;
args.reserve(expression.getOperands().size());
for(size_t i=0, size = expression.getOperands().size(); i<size; ++i) {
args.push_back(process(expression.getOperands()[i]));
}
return fnUnit->process(args);
}
case Operator::CALL_INTRINSIC: {
std::string nameFunction = expression.getValueString();
if(nameFunction=="query"){
- assert(expression.operands.size() == 1);
- assert(expression.operands.front().__state == Expression::STRING);
-
- std::string namePredicate = expression.operands.front().getValueString();
- StaticModel model = (static_cast<TargetInterpretation*>(function->man))->pass->man->transcend->query(namePredicate);
-
- Expression result(Operator::LIST, {});
-
- if(model.size())
- for (const auto& row: model) {
- result.addArg(representAsAnnotation(std::get<1>(row)));
- }
-
- return result;
+ return IntrinsicQueryInstruction(this).process(expression);
- } else if(nameFunction=="query_scope"){
- ScopePacked scopeId = man->transcend->pack(scope);
- Expression result(Operator::VARIANT, {Expression(scopeId)});
- result.setValueDouble(0);
- return result;
+ } else if(nameFunction=="query_scope"){
+ ScopePacked scopeId = man->transcend->pack(scope);
+ Expression result(Operator::VARIANT, {Expression(scopeId)});
+ result.setValueDouble(0);
+ return result;
} else {
- assert(false && "Unknown intrinsic");
+ assert(false && "Unknown intrinsic");
}
}
case Operator::IF:{
CodeScope* scopeResult = processOperatorIf(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::SWITCH: {
CodeScope* scopeResult = processOperatorSwitch(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::SWITCH_VARIANT: {
CodeScope* scopeResult = processOperatorSwitchVariant(expression);
return function->getScope(scopeResult)->processScope();
}
case Operator::VARIANT: {
if(!expression.operands.size()) return expression;
Expression variantData = process(expression.operands[0]);
Expression result{Operator::VARIANT, {variantData}};
result.setValueDouble(expression.getValueDouble());
return result;
}
case Operator::INDEX: {
Expression exprData = process(expression.operands[0]);
for (size_t keyId=1; keyId<expression.operands.size(); ++keyId){
const Expression& exprKey = process(expression.operands[keyId]);
if (exprKey.__state == Expression::STRING){
const string& key = exprKey.getValueString();
assert(exprData.__indexBindings.count(key));
size_t idxKey = exprData.__indexBindings.at(key);
exprData = Expression(exprData.operands.at(idxKey));
continue;
}
if (exprKey.__state == Expression::NUMBER){
int key = exprKey.getValueDouble();
exprData = Expression(exprData.operands[key]);
continue;
}
assert(false && "Inappropriate key");
}
return exprData;
}
case Operator::FOLD: {
const Expression& exprInput = process(expression.getOperands()[0]);
const Expression& exprInit = process(expression.getOperands()[1]);
const std::string& argEl = expression.bindings[0];
const std::string& argAccum = expression.bindings[1];
InterpretationScope* body = function->getScope(expression.blocks.front());
Expression accum = exprInit;
for(size_t size=exprInput.getOperands().size(), i=0; i<size; ++i){
body->overrideBindings({
{exprInput.getOperands()[i], argEl},
{accum, argAccum}
});
accum = body->processScope();
}
return accum;
}
case Operator::LIST:
case Operator::LIST_NAMED:
case Operator::LIST_RANGE:
{
Expression result(expression.op,{});
result.operands.resize(expression.operands.size());
result.bindings=expression.bindings;
result.__indexBindings=expression.__indexBindings;
int keyId=0;
for(const Expression& opCurrent : expression.operands) {
result.operands[keyId++]=process(opCurrent);
}
return result;
}
// case Operator::MAP: {
// break;
// }
default: break;
}
return expression;
}
InterpretationFunction*
TargetInterpretation::getFunction(IFunctionUnit* unit){
if (__dictFunctionsByUnit.count(unit)) {
return __dictFunctionsByUnit.at(unit);
}
InterpretationFunction* f = new InterpretationFunction(unit->function, this);
__dictFunctionsByUnit.emplace(unit, f);
assert(__functions.emplace(unit->function.id(), f).second);
return f;
}
PIFunction*
TargetInterpretation::getFunction(PIFSignature&& sig){
auto f = __pifunctions.find(sig);
if (f != __pifunctions.end()){
return f->second;
}
PIFunction* result = new PIFunction(PIFSignature(sig), __pifunctions.size(), this);
__pifunctions.emplace(move(sig), result);
assert(__dictFunctionsByUnit.emplace(result->functionUnit, result).second);
return result;
}
InterpretationScope*
TargetInterpretation::transformContext(const Context& c){
return this->getFunction(c.function)->getScope(c.scope->scope);
}
llvm::Value*
TargetInterpretation::compile(const Expression& expression, const Context& ctx){
return transformContext(ctx)->compile(expression, ctx);
}
InterpretationFunction::InterpretationFunction(const ManagedFnPtr& function, Target<TargetInterpretation>* target)
: Function<TargetInterpretation>(function, target)
{}
Expression
InterpretationFunction::process(const std::vector<Expression>& args){
InterpretationScope* body = getScope(__function->__entry);
list<pair<Expression, string>> bindings;
for(size_t i=0, size=args.size(); i<size; ++i) {
bindings.push_back(make_pair(args.at(i), body->scope->__bindings.at(i)));
}
body->overrideBindings(bindings);
return body->processScope();
}
// Partial function interpretation
typedef BasicFunctionUnit PIFunctionUnitParent;
class PIFunctionUnit : public PIFunctionUnitParent {
public:
PIFunctionUnit(ManagedFnPtr f, std::set<size_t>&& arguments, size_t id, CompilePass* p)
: PIFunctionUnitParent(f, p), argumentsActual(move(arguments)), __id(id) { }
protected:
std::vector<llvm::Type*> prepareArguments(){
LLVMLayer* llvm = PIFunctionUnitParent::pass->man->llvm;
AST* ast = PIFunctionUnitParent::pass->man->root;
CodeScope* entry = PIFunctionUnitParent::function->__entry;
std::vector<llvm::Type*> signature;
for(size_t no: argumentsActual){
VNameId argId = entry->__identifiers.at(entry->__bindings.at(no));
ScopedSymbol arg{argId, versions::VERSION_NONE};
signature.push_back(llvm->toLLVMType(ast->expandType(entry->__declarations.at(arg).type)));
}
return signature;
}
llvm::Function::arg_iterator prepareBindings(){
CodeScope* entry = PIFunctionUnitParent::function->__entry;
ICodeScopeUnit* entryCompilation = PIFunctionUnitParent::getScopeUnit(entry);
llvm::Function::arg_iterator fargsI = PIFunctionUnitParent::raw->arg_begin();
for(size_t no: argumentsActual){
ScopedSymbol arg{entry->__identifiers.at(entry->__bindings.at(no)), versions::VERSION_NONE};
entryCompilation->bindArg(&*fargsI, arg);
fargsI->setName(entry->__bindings.at(no));
++fargsI;
}
return fargsI;
}
virtual std::string prepareName(){
return PIFunctionUnitParent::prepareName() + "_" + std::to_string(__id);
}
private:
std::set<size_t> argumentsActual;
size_t __id;
};
PIFunction::PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target)
: InterpretationFunction(sig.declaration, target), signatureInstance(move(sig)) {
const FunctionInterpretationData& functionData = FunctionInterpretationHelper::getSignature(signatureInstance.declaration);
std::set<size_t> argumentsActual;
for (size_t no=0, size=functionData.signature.size(); no < size; ++no){
if (functionData.signature.at(no) != INTR_ONLY){
argumentsActual.insert(no);
}
}
functionUnit = new PIFunctionUnit(signatureInstance.declaration, move(argumentsActual), id, target->pass);
CodeScope* entry = signatureInstance.declaration->__entry;
auto entryUnit = Decorators<CachedScopeDecoratorTag>::getInterface<>(functionUnit->getEntry());
InterpretationScope* entryIntrp = InterpretationFunction::getScope(entry);
list<pair<Expression, std::string>> bindingsPartial;
list<pair<Symbol, Expression>> declsPartial;
for(size_t no=0, sigNo=0, size=entry->__bindings.size(); no<size; ++no) {
if(functionData.signature.at(no)==INTR_ONLY){
bindingsPartial.push_back({signatureInstance.bindings[sigNo], entry->__bindings[no]});
VNameId argId=entry->__identifiers.at(entry->__bindings[no]);
Symbol argSymbol{ScopedSymbol
{argId, versions::VERSION_NONE}, entry};
declsPartial.push_back({argSymbol, signatureInstance.bindings[sigNo]});
++sigNo;
}
}
entryIntrp->overrideBindings(bindingsPartial);
entryUnit->overrideDeclarations(declsPartial);
}
llvm::Function*
PIFunction::compile(){
llvm::Function* raw = functionUnit->compile();
return raw;
}
bool operator<(const PIFSignature& lhs, const PIFSignature& rhs){
if (lhs.declaration.id() != rhs.declaration.id()) {
return lhs.declaration.id() < rhs.declaration.id();
}
return lhs.bindings < rhs.bindings;
}
bool operator<(const PIFSignature& lhs, PIFunction* const rhs){
return lhs < rhs->signatureInstance;
}
bool operator<(PIFunction* const lhs, const PIFSignature& rhs){
return lhs->signatureInstance < rhs;
}
}}
/** \class xreate::interpretation::InterpretationFunction
*
* Holds list of xreate::interpretation::InterpretationScope 's focused on interpretation of individual code scopes
*
* There is particulat subclass PIFunction intended to represent partially interpreted functions
*\sa TargetInterpretation, [Interpretation Concept](/w/concepts/dfa)
*/
/** \class xreate::interpretation::TargetInterpretation
*
* Executed during compilation and intented to preprocess eligible parts of code.
* Established on [Targets Infrastructure](\ref compilation::Target)
*
* Holds list of InterpretationFunction / PIFunction to represent interpretation process for individual functions
*
* In order to be activated during compilation process there is
* InterpretationScopeDecorator implementation of ICodeScopeUnit
* \sa InterpretationPass, compilation::Target, [Interpretation Concept](/w/concepts/dfa)
*
*/
diff --git a/cpp/src/compilation/targetinterpretation.h b/cpp/src/compilation/targetinterpretation.h
index 7634199..ba03f34 100644
--- a/cpp/src/compilation/targetinterpretation.h
+++ b/cpp/src/compilation/targetinterpretation.h
@@ -1,132 +1,129 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: targetstatic.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 2, 2016, 1:25 PM
*/
#ifndef TARGETSTATIC_H
#define TARGETSTATIC_H
#include "ast.h"
#include "pass/compilepass.h"
#include "compilation/targets.h"
#include "pass/interpretationpass.h"
#include "transcendlayer.h"
namespace xreate{ namespace interpretation{
class TargetInterpretation;
class InterpretationScope;
class InterpretationFunction;
}}
namespace xreate{ namespace compilation{
template <>
struct TargetInfo<interpretation::TargetInterpretation> {
typedef Expression Result;
typedef interpretation::InterpretationScope Scope;
typedef interpretation::InterpretationFunction Function;
};
}}
namespace xreate{ namespace interpretation{
/** \brief Encapsulates interpretation of a single Code Scope */
class InterpretationScope: public compilation::Scope<TargetInterpretation>{
typedef Scope<TargetInterpretation> Parent;
public:
InterpretationScope(const CodeScope* scope, compilation::Function<TargetInterpretation>* f): Parent(scope, f) {}
Expression process(const Expression& expression) override;
llvm::Value* compile(const Expression& expression, const compilation::Context& context);
private:
llvm::Value* compileHybrid(const InterpretationOperator& op, const Expression& expression, const compilation::Context& context);
//llvm::Value* compilePartialFnCall(const Expression& expression, const Context& context);
CodeScope* processOperatorIf(const Expression& expression);
CodeScope* processOperatorSwitch(const Expression& expression);
CodeScope* processOperatorSwitchVariant(const Expression& expression);
};
/** \brief Encapsulates interpretation of a single %Function */
class InterpretationFunction: public compilation::Function<TargetInterpretation>{
public:
InterpretationFunction(const ManagedFnPtr& function, compilation::Target<TargetInterpretation>* target);
Expression process(const std::vector<Expression>& args);
};
/** \brief Signature of a partially interpreted function */
struct PIFSignature{
ManagedFnPtr declaration;
std::vector<Expression> bindings;
};
class PIFunctionUnit;
/** \brief Partially interpreted function */
class PIFunction: public InterpretationFunction{
public:
PIFunctionUnit* functionUnit;
PIFSignature signatureInstance;
PIFunction(PIFSignature&& sig, size_t id, TargetInterpretation* target);
llvm::Function* compile();
};
bool operator<(const PIFSignature& lhs, PIFunction* const rhs);
bool operator<(PIFunction* const lhs, const PIFSignature& rhs);
/** \brief Encapsulates actual [Interpretation](/w/concepts/dfa) based on InterpretationPass analysis results */
class TargetInterpretation: public compilation::Target<TargetInterpretation>{
public:
TargetInterpretation(AST* root, CompilePass* passCompilation): Target<TargetInterpretation>(root), pass(passCompilation){}
//target:
public:
InterpretationFunction* getFunction(compilation::IFunctionUnit* unit);
PIFunction* getFunction(PIFSignature&& sig);
private:
std::map<PIFSignature, PIFunction*> __pifunctions;
std::map<compilation::IFunctionUnit*, InterpretationFunction*> __dictFunctionsByUnit;
//self:
public:
CompilePass* pass;
llvm::Value* compile(const Expression& expression, const compilation::Context& ctx);
private:
InterpretationScope* transformContext(const compilation::Context& c);
};
/**\brief Interpretation-aware Code Scope decorator
* \extends xreate::compilation::ICodeScopeUnit
*/
template<class Parent>
class InterpretationScopeDecorator: public Parent{
public:
InterpretationScopeDecorator(const CodeScope* const codeScope, compilation::IFunctionUnit* f, CompilePass* compilePass): Parent(codeScope, f, compilePass){}
virtual llvm::Value* process(const Expression& expr, const std::string& hintVarDecl){
const InterpretationData& data = Attachments::get<InterpretationData>(expr, {ANY, NONE});
bool flagInterpretationEligible = (data.resolution == INTR_ONLY || data.op != InterpretationOperator::NONE);
if (flagInterpretationEligible){
compilation::Context ctx{this, this->function, this->pass};
return Parent::pass->targetInterpretation->compile(expr, ctx);
}
return Parent::process(expr, hintVarDecl);
}
};
-/** \brief translates Logic expression(Gringo::Symbol) into Xreate expression to support intrinsic function `query` */
-Expression representAsAnnotation(const Gringo::Symbol& symbol);
-
}} //end of xreate:: interpretation
#endif /* TARGETSTATIC_H */
\ No newline at end of file
diff --git a/cpp/src/compilation/targets.h b/cpp/src/compilation/targets.h
index dee23be..df281ca 100644
--- a/cpp/src/compilation/targets.h
+++ b/cpp/src/compilation/targets.h
@@ -1,198 +1,198 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* File: targetabstract.h
* Author: pgess <v.melnychenko@xreate.org>
*
* Created on July 2, 2016, 1:25 PM
*/
/**
* \file
* \brief Compilation targets infrastructure
*/
#ifndef TARGETABSTRACT_H
#define TARGETABSTRACT_H
#include "ast.h"
#include <boost/optional.hpp>
#include <map>
#include <list>
namespace xreate{ namespace compilation {
template <typename ConcreteTarget>
struct TargetInfo{
//typedef Result
//typedef Function
//typedef Scope
};
template<typename ConcreteTarget>
class Function;
template<typename ConcreteTarget>
class Target;
template<typename ConcreteTarget>
class Scope{
typedef typename TargetInfo<ConcreteTarget>::Scope Self;
public:
const CodeScope* scope;
+ Function<ConcreteTarget>* function=0;
typename TargetInfo<ConcreteTarget>::Result
processSymbol(const Symbol& s){
const CodeScope* scope = s.scope;
Self* self = function->getScope(scope);
if (self->__bindings.count(s.identifier)) {
return self->__bindings[s.identifier];
}
const Expression& declaration = CodeScope::getDefinition(s, true);
if (!declaration.isDefined()){
assert(false); //for bindings there should be result already
}
return self->__bindings[s.identifier] = self->process(declaration);
}
typename TargetInfo<ConcreteTarget>::Result
processScope() {
return process(scope->getBody());
}
// typename TargetInfo<ConcreteTarget>::Result
// processFunction(typename TargetInfo<ConcreteTarget>::Function* fnRemote, const std::vector<typename TargetInfo<ConcreteTarget>::Result>& args){
// Scope<ConcreteTarget> scopeRemote = fnRemote->getScope(fnRemote->__function->__entry);
//
// if (scopeRemote->raw){
// return scopeRemote->raw;
// }
//
// return fnRemote->process(args);
// }
virtual typename TargetInfo<ConcreteTarget>::Result
process(const Expression& expression)=0;
Scope(const CodeScope* codeScope, Function<ConcreteTarget>* f)
: scope(codeScope), function(f) {}
virtual ~Scope(){}
void
overrideBindings(std::list<std::pair<typename TargetInfo<ConcreteTarget>::Result, std::string>> bindings){
reset();
for (auto entry: bindings){
assert(scope->__identifiers.count(entry.second));
ScopedSymbol id{scope->__identifiers.at(entry.second), versions::VERSION_NONE};
__bindings[id] = entry.first;
}
}
void registerChildScope(std::shared_ptr<Self> scope){
__childScopes.push_back(scope);
}
void reset(){
__bindings.clear();
__childScopes.clear();
}
protected:
- Function<ConcreteTarget>* function=0;
std::map<ScopedSymbol, typename TargetInfo<ConcreteTarget>::Result> __bindings;
std::list<std::shared_ptr<Self>> __childScopes;
};
template<typename ConcreteTarget>
class Function{
typedef typename TargetInfo<ConcreteTarget>::Result Result;
typedef typename TargetInfo<ConcreteTarget>::Scope ConcreteScope;
public:
Function(const ManagedFnPtr& function, Target<ConcreteTarget>* target)
: man(target), __function(function) {}
virtual ~Function(){};
ConcreteScope*
getScope(const CodeScope* const scope){
if (__scopes.count(scope)) {
auto result = __scopes.at(scope).lock();
if (result){
return result.get();
}
}
std::shared_ptr<ConcreteScope> 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<Result>& args)=0;
Target<ConcreteTarget>* man=0;
ManagedFnPtr __function;
protected:
std::map<const CodeScope*, std::weak_ptr<ConcreteScope>> __scopes;
std::shared_ptr<ConcreteScope> __entryScope;
};
/** \brief Similar to xreate::IPass */
template<typename ConcreteTarget>
class Target {
typedef typename TargetInfo<ConcreteTarget>::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<unsigned int, ConcreteFunction*> __functions;
};
}}
#endif /* TARGETABSTRACT_H */
diff --git a/cpp/tests/association.cpp b/cpp/tests/association.cpp
index 23def6a..d97d2f3 100644
--- a/cpp/tests/association.cpp
+++ b/cpp/tests/association.cpp
@@ -1,129 +1,133 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* association.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on August 12, 2017, 9:28 PM
*/
#include "xreatemanager.h"
#include "transcendlayer.h"
#include <gtest/gtest.h>
using namespace xreate;
using namespace std;
-TEST(Association, test1){
-std::string controller=
-R"Code(
+TEST(Association, test1) {
+ std::string controller =
+ R"Code(
program(add).
)Code";
-std::string script=
-R"Code(
+ std::string script =
+ R"Code(
Annotation = type variant {
Num:: int,
String:: string,
Func:: {name::string, arguments::[Annotation]}
}.
extractCmd = function(program::Annotation):: Annotation; interpretation(force){
switch variant(program)::Annotation
case (Num){String("wrong expression")}
case (String){String("wrong expression")}
case (Func){program["arguments"][0]}
}
main= function:: int; entry{
x= 5::int.
y = 6::int.
program = intrinsic query("program")[0]::Annotation.
cmd = extractCmd(program)::Annotation; interpretation(force).
answer = switch variant(cmd)::int
case (Num) {0}
case (String){0}
case (Func){
switch(cmd["name"])::int
case("add"){x + y}
case default {0}
}.
answer
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(std::move(script)));
man->transcend->addRawScript(move(controller));
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(11, result);
}
-TEST(Association, QueryScope1){
-std::string script = R"Code(
+TEST(Association, QueryScope1) {
+ std::string script = R"Code(
Annotation = type variant {
Num:: int,
String:: string,
Func:: {name::string, arguments::[Annotation]}
}.
func = function::int{10} //aux func in order to have few scopes
main = function:: int; entry {
scope = intrinsic query_scope()::Annotation.
answer = switch variant(scope):: int
case (Num) {scope}
case (String){-1}
case (Func){-1}.
answer
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(std::move(script)));
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(1, result);
}
-//std::string script=
-//R"Code(
-//
-//case context:: test1 {
-//test= function::bool; registerTest {
-// x = 8:: int.
-//
-// x == 8
-//}}
-//
-//case context:: test2{
-//test= function::bool{
-// x = 3::int.
-// y = 12::int.,
-//
-// (x+y) <> 25
-//}}
-//
-//runTests= function::bool{
-// tests = intrinsic query (registeredTests)::[Expression].
-//
-// loop fold(tests->test::Expression, true->result):: bool {
-// shot = {
-// context:: make context (test)
-// test()
-// }
-//
-// result and shot
-// }
-//}
-//
-//main= function:: int; entry{
-// runTests()
-//}
-//)Code";
+TEST(Association, TypedQuery_1) {
+ auto man = details::tier1::XreateManager::prepare(R"Code(
+ AtomNumT = type slave atomNumT.
+ AtomStrT = type slave atomStrT.
+ CompListT = type slave compListT.
+ CompArithT = type slave compArithT.
+
+ test = function:: num; entry
+ {
+ query1 = intrinsic query("atomNumT")::[AtomNumT].
+ query2 = intrinsic query("atomStrT")::[AtomStrT].
+ query3 = intrinsic query("compListT")::[CompListT].
+ query4 = intrinsic query("compArithT")::[CompArithT].
+ test1 = query1[0] == 5:: bool.
+ test2 = query2[1] == "y":: bool.
+ test3 = query3[0, 1] == "x" :: bool.
+ test4 = query4[0, 0, 0] == 1:: bool.
+
+ test1 + test2 + test3 + test4
+ }
+ )Code");
+
+ man->transcend->addRawScript(R"RAW(
+ atomNumT(5; 8).
+ atomStrT("x"; "y").
+ compListT(5, "x").
+ compListT(8, "y").
+ compArithT(add(1, 2)).
+ compArithT(mul(5, 6)).
+ )RAW");
+
+ man->analyse();
+ int (*test)() = (int (*)())man->run();
+ int result = test();
+ ASSERT_EQ(4, result);
+}
+
+
+
diff --git a/cpp/tests/types.cpp b/cpp/tests/types.cpp
index 51facbf..5d3c9f5 100644
--- a/cpp/tests/types.cpp
+++ b/cpp/tests/types.cpp
@@ -1,181 +1,235 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* types.cpp
*
* Created on: Jun 4, 2015
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "gtest/gtest.h"
#include "xreatemanager.h"
#include "llvmlayer.h"
#include "main/Parser.h"
+#include "transcendlayer.h"
+#include "analysis/typeinference.h"
using namespace std;
using namespace xreate;
using namespace xreate::grammar::main;
TEST(Types, DependantTypes1) {
- string&& code = "XmlNode = type {\n"
- " tag:: string,\n"
- " attrs:: [string], \n"
- " content:: string\n"
- "}.\n";
-
- std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
- ExpandedType typeXmlNode = program->root->findType("XmlNode");
-
- ASSERT_EQ(TypeOperator::LIST_NAMED, typeXmlNode->__operator);
- ASSERT_EQ(3, typeXmlNode->__operands.size());
- ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(0).__value);
- ASSERT_EQ(TypeOperator::LIST, typeXmlNode->__operands.at(1).__operator);
- ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(2).__value);
+ string&& code = "XmlNode = type {\n"
+ " tag:: string,\n"
+ " attrs:: [string], \n"
+ " content:: string\n"
+ "}.\n";
+
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
+ ExpandedType typeXmlNode = program->root->findType("XmlNode");
+
+ ASSERT_EQ(TypeOperator::LIST_NAMED, typeXmlNode->__operator);
+ ASSERT_EQ(3, typeXmlNode->__operands.size());
+ ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(0).__value);
+ ASSERT_EQ(TypeOperator::LIST, typeXmlNode->__operands.at(1).__operator);
+ ASSERT_EQ(TypePrimitive::String, typeXmlNode->__operands.at(2).__value);
}
TEST(Types, ast_ParameterizedTypes_FeatureTypeIndex_1) {
- string&& code = "XmlNode = type {\n"
- " tag:: string,\n"
- " attrs:: [string],\n"
- " content:: string\n"
- "}.\n"
- ""
- "Template = type(Leaf) {Leaf, [Leaf[content]]}."
- "Concrete = type Template(XmlNode).";
-
- std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
- ExpandedType typeConcrete = program->root->findType("Concrete");
-
- ASSERT_EQ(TypeOperator::LIST_NAMED, typeConcrete->__operator);
- ASSERT_EQ(2, typeConcrete->__operands.size());
- ASSERT_EQ(TypeOperator::LIST_NAMED, typeConcrete->__operands.at(0).__operator);
-
- ASSERT_EQ(TypeOperator::LIST, typeConcrete->__operands.at(1).__operator);
- ASSERT_EQ(TypePrimitive::String, typeConcrete->__operands.at(1).__operands.at(0).__value);
+ string&& code = "XmlNode = type {\n"
+ " tag:: string,\n"
+ " attrs:: [string],\n"
+ " content:: string\n"
+ "}.\n"
+ ""
+ "Template = type(Leaf) {Leaf, [Leaf[content]]}."
+ "Concrete = type Template(XmlNode).";
+
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
+ ExpandedType typeConcrete = program->root->findType("Concrete");
+
+ ASSERT_EQ(TypeOperator::LIST_NAMED, typeConcrete->__operator);
+ ASSERT_EQ(2, typeConcrete->__operands.size());
+ ASSERT_EQ(TypeOperator::LIST_NAMED, typeConcrete->__operands.at(0).__operator);
+
+ ASSERT_EQ(TypeOperator::LIST, typeConcrete->__operands.at(1).__operator);
+ ASSERT_EQ(TypePrimitive::String, typeConcrete->__operands.at(1).__operands.at(0).__value);
}
TEST(Types, TreeType1) {
- string&& code = "XmlNode = type {\n"
- " tag:: string,\n"
- " attrs:: [string],\n"
- " content:: string\n"
- "}.\n"
- ""
- "Tree = type(Leaf) {Leaf, [Tree(Leaf)]}."
- "Concrete = type Tree(XmlNode).";
-
- std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
- ExpandedType typeConcrete = program->root->findType("Concrete");
-
- ASSERT_EQ(TypeOperator::LIST_NAMED, typeConcrete->__operator);
- ASSERT_EQ(2, typeConcrete->__operands.size());
- ASSERT_EQ(TypeOperator::LIST_NAMED, typeConcrete->__operands.at(0).__operator);
-
- ASSERT_EQ(TypeOperator::LIST, 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);
+ string&& code = "XmlNode = type {\n"
+ " tag:: string,\n"
+ " attrs:: [string],\n"
+ " content:: string\n"
+ "}.\n"
+ ""
+ "Tree = type(Leaf) {Leaf, [Tree(Leaf)]}."
+ "Concrete = type Tree(XmlNode).";
+
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
+ ExpandedType typeConcrete = program->root->findType("Concrete");
+
+ ASSERT_EQ(TypeOperator::LIST_NAMED, typeConcrete->__operator);
+ ASSERT_EQ(2, typeConcrete->__operands.size());
+ ASSERT_EQ(TypeOperator::LIST_NAMED, typeConcrete->__operands.at(0).__operator);
+
+ ASSERT_EQ(TypeOperator::LIST, 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 {\n"
- " tag:: string,\n"
- " /* attrs:: [string],*/\n"
- " content:: string\n"
- "}.\n"
- ""
- "Tree = type(Leaf) {Leaf, [Tree(Leaf)]}."
- "Concrete = type Tree(XmlNode).";
+TEST(Types, TreeType1LLvm) {
+ string&& code = "XmlNode = type {\n"
+ " tag:: string,\n"
+ " /* attrs:: [string],*/\n"
+ " content:: string\n"
+ "}.\n"
+ ""
+ "Tree = type(Leaf) {Leaf, [Tree(Leaf)]}."
+ "Concrete = type Tree(XmlNode).";
- std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
- ExpandedType typeConcrete = program->root->findType("Concrete");
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
+ ExpandedType typeConcrete = program->root->findType("Concrete");
- llvm::Type* raw = program->llvm->toLLVMType(typeConcrete);
+ llvm::Type* raw = program->llvm->toLLVMType(typeConcrete);
}
-TEST(Types, ArrayOfExternal1){
- FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r");
+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();
CodeScope* body = ast->findFunction("test")->getEntryScope();
const ExpandedType& t2 = ast->getType(body->getDefinition(body->getSymbol("childrenRaw")));
EXPECT_EQ(t2->__operator, TypeOperator::LIST);
}
-TEST(Types, ExternType1){
- FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r");
- assert(input != nullptr);
+TEST(Types, ExternType1) {
+ FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate", "r");
+ assert(input != nullptr);
- Scanner scanner(input);
- Parser parser(&scanner);
- parser.Parse();
+ Scanner scanner(input);
+ Parser parser(&scanner);
+ parser.Parse();
- AST* ast = parser.root->finalize();
- CodeScope* body = ast->findFunction("test")->getEntryScope();
+ AST* ast = parser.root->finalize();
+ CodeScope* body = ast->findFunction("test")->getEntryScope();
const ExpandedType& t2 = ast->getType(body->getDefinition(body->getSymbol("tree")));
EXPECT_EQ(t2->__operator, TypeOperator::CUSTOM);
}
-TEST(Types, ast_VariantType1){
- string&& code =
- " colors = type variant {RED, BLUE, GREEN}.\n"
- " test = function:: colors; entry {GREEN()}";
+TEST(Types, ast_VariantType1) {
+ string&& code =
+ " colors = type variant {RED, BLUE, GREEN}.\n"
+ " test = function:: colors; entry {GREEN()}";
- std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
+ std::unique_ptr<XreateManager> program(XreateManager::prepare(move(code)));
- ExpandedType typ = program->root->findType("colors");
- EXPECT_EQ(TypeOperator::VARIANT, typ->__operator);
+ ExpandedType typ = program->root->findType("colors");
+ EXPECT_EQ(TypeOperator::VARIANT, typ->__operator);
- Expression eRed = program->root->findFunction("test")->getEntryScope()->getBody();
- EXPECT_EQ(Operator::VARIANT, eRed.op);
+ Expression eRed = program->root->findFunction("test")->getEntryScope()->getBody();
+ EXPECT_EQ(Operator::VARIANT, eRed.op);
- const ExpandedType& typ2 = program->root->getType(eRed);
- EXPECT_EQ(TypeOperator::VARIANT, typ2->__operator);
+ const ExpandedType& typ2 = program->root->getType(eRed);
+ EXPECT_EQ(TypeOperator::VARIANT, typ2->__operator);
}
-TEST(Types, full_VariantType_Switch1){
- string&& code =
+TEST(Types, full_VariantType_Switch1) {
+ string&& code =
"colors = type variant{RED, BLUE, GREEN}. \n"
- " test = function:: colors {GREEN()} \n"
+ " test = function:: colors {GREEN()} \n"
- "main = function:: int; entry { \n"
- " switch(test()):: int \n"
- " case (GREEN()) {0} \n"
- " case default {1} \n"
- "}";
+ "main = function:: int; entry { \n"
+ " switch(test()):: int \n"
+ " case (GREEN()) {0} \n"
+ " case default {1} \n"
+ "}";
- XreateManager* man = XreateManager::prepare(move(code));
- int (*main)() = (int (*)()) man->run();
+ XreateManager* man = XreateManager::prepare(move(code));
+ int (*main)() = (int (*)()) man->run();
- EXPECT_EQ(0, main());
+ EXPECT_EQ(0, main());
}
-TEST(Types, ast_VariantType2){
- std::string script=
-R"Code(
+TEST(Types, ast_VariantType2) {
+ std::string script =
+ R"Code(
Annotation = type
variant {
Num:: int,
String:: string,
Func:: {name::string, arguments::[Expression]}
}.
)Code";
std::unique_ptr<XreateManager> program(XreateManager::prepare(move(script)));
ExpandedType typ = program->root->findType("Annotation");
ASSERT_EQ(3, typ.get().fields.size());
}
-//TEST(Types, A)
-
-
-//TOTEST string type
+TEST(Types, SlaveTypes_UnwrapSlaveType1) {
+ auto man = details::tier1::XreateManager::prepare(R"Code(
+ AtomNumT = type slave atomNumT.
+ AtomStrT = type slave atomStrT.
+ CmpndIntStrT = type slave cmpndIntStrT.
+
+ VariantT = type slave variantT.
+
+ VariantComplicatedT = type slave variantComplicatedT.
+ )Code");
+
+ man->transcend->addRawScript(R"RAW(
+ atomNumT(5). atomNumT(8).
+ atomStrT("a"). atomStrT("b").
+ cmpndIntStrT(1, "a").
+ cmpndIntStrT(2, "b").
+
+ variantT(first).
+ variantT(second).
+ variantT(third).
+
+ variantComplicatedT(first(1, "a")).
+ variantComplicatedT(second("b")).
+ )RAW");
+
+ man->analyse();
+ ExpandedType AtomNumT = man->root->findType("AtomNumT");
+ ASSERT_EQ(AtomNumT->__operator, TypeOperator::SLAVE);
+
+ ExpandedType ContentAtomNumT = typeinference::dereferenceSlaveType(AtomNumT, man->transcend);
+ ASSERT_EQ(TypePrimitive::Num, ContentAtomNumT->__value);
+
+ ExpandedType AtomStrT = man->root->findType("AtomStrT");
+ ExpandedType ContentAtomStrT = typeinference::dereferenceSlaveType(AtomStrT,
+ man->transcend);
+ ASSERT_EQ(TypePrimitive::String, ContentAtomStrT->__value);
+
+ ExpandedType CmpndIntStrT = man->root->findType("CmpndIntStrT");
+ ExpandedType ContentCmpndIntStrT = typeinference::dereferenceSlaveType(CmpndIntStrT,
+ man->transcend);
+ ASSERT_EQ(TypeOperator::LIST_NAMED, ContentCmpndIntStrT->__operator);
+ ASSERT_EQ(2, ContentCmpndIntStrT->__operands.size());
+
+ ExpandedType VariantT = man->root->findType("VariantT");
+ ExpandedType ContentVariantT = typeinference::dereferenceSlaveType(VariantT,
+ man->transcend);
+ ASSERT_EQ(TypeOperator::VARIANT, ContentVariantT->__operator);
+ ASSERT_EQ(3, ContentVariantT->fields.size());
+
+ ExpandedType VariantComplicatedT = man->root->findType("VariantComplicatedT");
+ ExpandedType ContentVariantComplicatedT = typeinference::dereferenceSlaveType(VariantComplicatedT,
+ man->transcend);
+ ASSERT_EQ(TypeOperator::VARIANT, ContentVariantComplicatedT->__operator);
+ ASSERT_EQ(2, ContentVariantComplicatedT->fields.size());
+ ASSERT_EQ(2, ContentVariantComplicatedT->__operands.at(0).__operands.size());
+}
\ No newline at end of file
diff --git a/git-commit-template b/git-commit-template
index 94da945..567e7b8 100644
--- a/git-commit-template
+++ b/git-commit-template
@@ -1,12 +1,12 @@
<Changeset description>
Syntax: <syntax changes>
Transcend: <any changes related to reasoning>
Compilation: <any changes on compilation side>
-Documentation: <...>
+Documentation: <note if requires any changes in documentation>
<component, AST, DFAPass etc>: <...>
Malfunctions: <what is broken after commit, broken/disabled tests>
Tests: <tests that cover commited changes>

Event Timeline