Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F2731273
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Mar 14, 4:31 AM
Size
81 KB
Mime Type
text/x-diff
Expires
Mon, Mar 16, 4:31 AM (1 d, 16 h)
Engine
blob
Format
Raw Data
Handle
243918
Attached To
rXR Xreate
View Options
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
Log In to Comment