Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F2731380
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:44 AM
Size
182 KB
Mime Type
text/x-diff
Expires
Mon, Mar 16, 4:44 AM (1 d, 15 h)
Engine
blob
Format
Raw Data
Handle
244005
Attached To
rXR Xreate
View Options
diff --git a/config/default.json b/config/default.json
index 04ec9d5..a2522d6 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,69 +1,69 @@
{
"containers": {
"id": {
"implementations": "impl_fulfill_cluster",
"clusters": "var_cluster",
"prototypes": "proto_cluster",
"linkedlist": "linkedlist"
},
"impl": {
"solid": "solid",
"onthefly": "on_the_fly"
}
},
"logging": {
"id": "logging"
},
"function-entry": "entry",
"clasp": {
"bindings" : {
"variable": "bind",
"function": "bind_func",
"scope": "bind_scope",
"function_demand" : "bind_function_demand",
"scope_decision": "bind_scope_decision"
},
"context" : {
"decisions":{
"dependent": "resolution_dependency"
},
},
"nonevalue": "nonevalue",
"ret": {
"symbol": "retv",
"tag": "ret"
}
},
"tests": {
"template": "default",
"templates": {
- "default": "*-",
+ "default": "*-Adhoc.*:Compilation.full_IFStatementWithVariantType:Types.full_VariantType_Switch1",
"ast": "AST.*",
"adhocs": "Adhoc.*",
"effects": "Effects.*",
"basic": "Attachments.*",
"context": "Context.*",
"compilation": "Compilation.*",
"cfa": "CFA.*",
"containers": "Containers.*",
"dfa": "DFA.*",
"diagnostic": "Diagnostic.*",
- "dsl": "Interpretation.*:InterpretationExamples.*",
+ "dsl": "Interpretation.*",
"ExpressionSerializer": "ExpressionSerializer.*",
"externc": "InterfaceExternC.*",
"loops": "Loop.*",
"modules": "Modules.*",
- "types": "Types.*-",
+ "types": "Types.*",
"vendorsAPI/clang": "ClangAPI.*",
"vendorsAPI/xml2": "libxml2*"
}
}
}
diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt
index 9f4c71a..61049e9 100644
--- a/cpp/src/CMakeLists.txt
+++ b/cpp/src/CMakeLists.txt
@@ -1,229 +1,229 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate)
cmake_policy(SET CMP0022 NEW)
message("MODULES" ${CMAKE_MODULE_PATH})
# LLVM
#======================
FIND_PACKAGE (LLVM REQUIRED)
set(LLVM_VERSION ${LLVM_VERSION_MAJOR}.${LLVM_VERSION_MINOR})
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message("LLVM LIB PATH:" ${LLVM_LIBRARY_DIRS})
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS})
message(STATUS "INCLUDE DIR: ${LLVM_INCLUDE_DIRS}")
add_definitions(${LLVM_DEFINITIONS})
message("LLVM DEFS: " ${LLVM_DEFINITIONS})
llvm_map_components_to_libnames(LLVM_LIBS core nativecodegen native executionengine mcjit support option)
message("LLVM LIBS: " ${LLVM_LIBS})
# CLANG
#======================
set(CLANG_LIBS
clangCodeGen
clangASTMatchers
clangQuery
clangTooling
clangFrontend
clangSerialization
clangDriver
clangParse
clangSema
clangAnalysis
clangAST
clangEdit
clangLex
clangBasic
)
# POTASSCO
#======================
set(POTASSCO_PATH "/opt/potassco/clingo" CACHE PATH "Path to potassco sources")
set(POTASSCO_INCLUDE_PATH
${POTASSCO_PATH}/libgringo
${POTASSCO_PATH}/libclasp
${POTASSCO_PATH}/libclingo
${POTASSCO_PATH}/libprogram_opts
${POTASSCO_PATH}/liblp
)
INCLUDE_DIRECTORIES(${POTASSCO_INCLUDE_PATH})
set(LIBCLASP_LIBS
clingo
clasp
gringo
program_opts
reify
lp
)
message("CLASP LIBS: " ${LIBCLASP_LIBS})
# OTHER DEPENDENCIES
#===========================
set(JEAYESON_INCLUDE_PATH
${CMAKE_HOME_DIRECTORY}/../vendors/jeayeson/include/
)
INCLUDE_DIRECTORIES(${JEAYESON_INCLUDE_PATH})
# COCO
#===========================
set(COCO_EXECUTABLE "" CACHE PATH "Path to coco executable")
set(COCO_FRAMES_PATH "" CACHE PATH "Path to coco frames")
set(COCO_GRAMMAR_PATH ${CMAKE_HOME_DIRECTORY}/../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
- modules.cpp
+ compilation/targetinterpretation.cpp
+ pass/interpretationpass.cpp
ast.cpp
xreatemanager.cpp
analysis/typeinference.cpp
aux/xreatemanager-decorators.cpp
compilation/operators.cpp
compilation/transformations.cpp
compilation/transformersaturation.cpp
pass/compilepass.cpp
pass/dfapass.cpp
analysis/dfagraph.cpp
pass/versionspass.cpp
- compilation/targetinterpretation.cpp
attachments.cpp
ExternLayer.cpp
analysis/cfagraph.cpp
analysis/aux.cpp
compilation/containers.cpp
compilation/advanced.cpp
clasplayer.cpp
compilation/latecontextcompiler2.cpp
query/context.cpp
llvmlayer.cpp
utils.cpp
pass/abstractpass.cpp
pass/cfapass.cpp
pass/adhocpass.cpp
contextrule.cpp
query/containers.cpp
- pass/interpretationpass.cpp
analysis/DominatorsTreeAnalysisProvider.cpp
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 ${SOURCE_FILES} ${COCO_SOURCE_FILES})
+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/ast.cpp b/cpp/src/ast.cpp
index 87c974b..06cdd55 100644
--- a/cpp/src/ast.cpp
+++ b/cpp/src/ast.cpp
@@ -1,928 +1,951 @@
#include "ast.h"
#include "ExternLayer.h"
#include "analysis/typeinference.h"
#include <stdexcept>
#include <iostream>
//TODO BDecl. forbid multiple body declaration (ExprTyped)
-namespace std{
+namespace std {
+
std::size_t
- hash<xreate::ScopedSymbol>::operator()(xreate::ScopedSymbol const& s) const
- {return s.id ^ (s.version << 2);}
+ hash<xreate::ScopedSymbol>::operator()(xreate::ScopedSymbol const& s) const {
+ return s.id ^ (s.version << 2);
+ }
bool
- equal_to<xreate::ScopedSymbol>::operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const
- { return __x.id == __y.id && __x.version == __y.version; }
+ equal_to<xreate::ScopedSymbol>::operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const {
+ return __x.id == __y.id && __x.version == __y.version;
+ }
size_t
- hash<xreate::Symbol>::operator()(xreate::Symbol const& s) const{
+ hash<xreate::Symbol>::operator()(xreate::Symbol const& s) const {
return hash<xreate::ScopedSymbol>()(s.identifier) ^ ((long int) s.scope << 1);
}
bool
- equal_to<xreate::Symbol>::operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const{
- return __x == __y;
+ equal_to<xreate::Symbol>::operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const {
+ return __x == __y;
};
}
using namespace std;
namespace xreate {
Atom<Identifier_t>::Atom(const std::wstring& value) {
__value = wstring_to_utf8(value);
}
-Atom<Identifier_t>::Atom(std::string && name) : __value(name)
-{}
+Atom<Identifier_t>::Atom(std::string && name) : __value(name) {
+}
const std::string&
Atom<Identifier_t>::get() const {
return __value;
}
Atom<Number_t>::Atom(wchar_t* value) {
//DEBT reconsider number literal recognition
__value = wcstol(value, 0, 10);
}
Atom<Number_t>::Atom(int value)
: __value(value) {
}
double
Atom<Number_t>::get()const {
return __value;
}
Atom<String_t>::Atom(const std::wstring& value) {
- assert(value.size() >=2);
- __value = wstring_to_utf8(value.substr(1, value.size() -2));
+ assert(value.size() >= 2);
+ __value = wstring_to_utf8(value.substr(1, value.size() - 2));
}
const std::string&
Atom<String_t>::get() const {
return __value;
}
- class ExpressionHints {
- public:
+class ExpressionHints {
+public:
- static bool
- isStringValueValid(const Expression& e) {
- switch (e.__state) {
- case Expression::INVALID:
- assert(false);
+ static bool
+ isStringValueValid(const Expression& e) {
+ switch (e.__state) {
+ case Expression::INVALID:
+ assert(false);
- case Expression::IDENT:
- case Expression::STRING:
- return true;
+ case Expression::IDENT:
+ case Expression::STRING:
+ return true;
- case Expression::NUMBER:
- case Expression::BINDING:
- return false;
+ case Expression::NUMBER:
+ case Expression::BINDING:
+ return false;
- case Expression::COMPOUND:
- {
- switch (e.op) {
- case Operator::CALL:
- return true;
+ case Expression::COMPOUND:
+ {
+ switch (e.op) {
+ case Operator::CALL:
+ return true;
- default: return false;
- }
+ default: return false;
}
}
-
- return false;
}
- static bool
- isDoubleValueValid(const Expression& e) {
- switch (e.__state) {
- case Expression::NUMBER:
- return true;
-
- case Expression::INVALID:
- assert(false);
-
- case Expression::IDENT:
- case Expression::STRING:
- case Expression::BINDING:
- return false;
-
- case Expression::COMPOUND:{
- switch (e.op) {
- case Operator::VARIANT:
- return true;
- default: return false;
- }
+ return false;
+ }
+
+ static bool
+ isDoubleValueValid(const Expression& e) {
+ switch (e.__state) {
+ case Expression::NUMBER:
+ return true;
+
+ case Expression::INVALID:
+ assert(false);
+
+ case Expression::IDENT:
+ case Expression::STRING:
+ case Expression::BINDING:
+ return false;
+
+ case Expression::COMPOUND: {
+ switch (e.op) {
+ case Operator::VARIANT:
+ return true;
+ default: return false;
}
}
-
- return false;
}
- };
- class TypesResolver {
- private:
- const AST* ast;
- std::map<std::string, TypeAnnotation> scope;
- std::map<TypeAnnotation, int> signatures;
+ return false;
+ }
+};
- ExpandedType expandType(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
- return TypesResolver(ast, scope, signatures)(t, args);
- }
+class TypesResolver {
+private:
+ const AST* ast;
+ std::map<std::string, TypeAnnotation> scope;
+ std::map<TypeAnnotation, int> signatures;
- std::vector<TypeAnnotation>
- expandOperands(const std::vector<TypeAnnotation>& operands) {
- std::vector<TypeAnnotation> pack;
+ ExpandedType expandType(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
+ return TypesResolver(ast, scope, signatures)(t, args);
+ }
- pack.reserve(operands.size());
- std::transform(operands.begin(), operands.end(), std::inserter(pack, pack.end()),
- [this](const TypeAnnotation & t) {
- return expandType(t);
- });
+ std::vector<TypeAnnotation>
+ expandOperands(const std::vector<TypeAnnotation>& operands) {
+ std::vector<TypeAnnotation> pack;
- return pack;
- }
+ pack.reserve(operands.size());
+ std::transform(operands.begin(), operands.end(), std::inserter(pack, pack.end()),
+ [this](const TypeAnnotation & t) {
+ return expandType(t);
+ });
- public:
+ return pack;
+ }
- TypesResolver(const AST* root, const std::map<std::string, TypeAnnotation>& scopeOuter = std::map<std::string, TypeAnnotation>(),
- std::map<TypeAnnotation, int> signaturesOuter = std::map<TypeAnnotation, int>())
- : ast(root), scope(scopeOuter), signatures(signaturesOuter) {
- }
+public:
- ExpandedType
- operator()(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
- //assert(args.size() == t.bindings.size()); // invalid number of arguments
- for (size_t i = 0; i < args.size(); ++i) {
- scope[t.bindings.at(i)] = args.at(i);
- }
+ TypesResolver(const AST* root, const std::map<std::string, TypeAnnotation>& scopeOuter = std::map<std::string, TypeAnnotation>(),
+ std::map<TypeAnnotation, int> signaturesOuter = std::map<TypeAnnotation, int>())
+ : ast(root), scope(scopeOuter), signatures(signaturesOuter) {
+ }
- switch (t.__operator) {
- case TypeOperator::ARRAY:
- {
- assert(t.__operands.size() == 1);
+ ExpandedType
+ operator()(const TypeAnnotation &t, const std::vector<TypeAnnotation> &args = std::vector<TypeAnnotation>()) {
+ //assert(args.size() == t.bindings.size()); // invalid number of arguments
+ for (size_t i = 0; i < args.size(); ++i) {
+ scope[t.bindings.at(i)] = args.at(i);
+ }
- Expanded<TypeAnnotation> elTy = expandType(t.__operands.at(0));
- return ExpandedType(TypeAnnotation(tag_array, elTy, 0));
- }
+ switch (t.__operator) {
+ case TypeOperator::ARRAY:
+ {
+ assert(t.__operands.size() == 1);
- case TypeOperator::STRUCT:
- {
- assert(t.__operands.size());
+ Expanded<TypeAnnotation> elTy = expandType(t.__operands.at(0));
+ return ExpandedType(TypeAnnotation(tag_array, elTy, 0));
+ }
- std::vector<TypeAnnotation>&& packOperands = expandOperands(t.__operands);
- auto typNew = TypeAnnotation(TypeOperator::STRUCT, move(packOperands));
- typNew.fields = t.fields;
+ case TypeOperator::STRUCT:
+ {
+ assert(t.__operands.size());
- return ExpandedType(move(typNew));
- };
+ std::vector<TypeAnnotation>&& packOperands = expandOperands(t.__operands);
+ auto typNew = TypeAnnotation(TypeOperator::STRUCT, move(packOperands));
+ typNew.fields = t.fields;
- case TypeOperator::CALL:
- {
- std::string alias = t.__valueCustom;
+ return ExpandedType(move(typNew));
+ };
- //find in local scope:
- TypeAnnotation ty;
- if (scope.count(alias)) {
- ty = scope.at(alias);
+ case TypeOperator::CALL:
+ {
+ std::string alias = t.__valueCustom;
- } else if (ast->__indexTypeAliases.count(alias)) {
- ty = ast->__indexTypeAliases.at(alias);
+ //find in local scope:
+ TypeAnnotation ty;
+ if (scope.count(alias)) {
+ ty = scope.at(alias);
- } else {
- assert(false && "Undefined or external type");
- }
+ } else if (ast->__indexTypeAliases.count(alias)) {
+ ty = ast->__indexTypeAliases.at(alias);
- std::vector<TypeAnnotation>&& operands = expandOperands(t.__operands);
- TypeAnnotation signature(TypeOperator::CALL, move(operands));
- signature.__valueCustom = alias;
+ } else {
+ assert(false && "Undefined or external type");
+ }
- if (signatures.count(signature)) {
- auto link = TypeAnnotation(TypeOperator::LINK,{});
- link.conjuctionId = signatures.at(signature);
+ std::vector<TypeAnnotation>&& operands = expandOperands(t.__operands);
+ TypeAnnotation signature(TypeOperator::CALL, move(operands));
+ signature.__valueCustom = alias;
- return ExpandedType(move(link));
- }
+ if (signatures.count(signature)) {
+ auto link = TypeAnnotation(TypeOperator::LINK,{});
+ link.conjuctionId = signatures.at(signature);
- int cid = signatures.size();
- signatures[signature] = cid;
- TypeAnnotation tyResult = expandType(ty, operands);
- tyResult.conjuctionId = cid;
+ return ExpandedType(move(link));
+ }
- return ExpandedType(move(tyResult));
- };
+ int cid = signatures.size();
+ signatures[signature] = cid;
+ TypeAnnotation tyResult = expandType(ty, operands);
+ tyResult.conjuctionId = cid;
- case TypeOperator::CUSTOM:
- {
- std::string alias = t.__valueCustom;
+ return ExpandedType(move(tyResult));
+ };
- /*
- if (signatures.count(alias)) {
- return ExpandedType(TypeAnnotation(TypeOperator::LINK, {t}));
- }
- signatures[alias].emplace(t);
- */
+ case TypeOperator::CUSTOM:
+ {
+ std::string alias = t.__valueCustom;
- //find in local scope:
- if (scope.count(alias)) {
- return expandType(scope.at(alias));
- }
+ /*
+ if (signatures.count(alias)) {
+ return ExpandedType(TypeAnnotation(TypeOperator::LINK, {t}));
+ }
+ signatures[alias].emplace(t);
+ */
- // find in general scope:
- if (ast->__indexTypeAliases.count(alias)) {
- return expandType(ast->__indexTypeAliases.at(t.__valueCustom));
- }
+ //find in local scope:
+ if (scope.count(alias)) {
+ return expandType(scope.at(alias));
+ }
- //if type is unknown keep it as is.
- return ExpandedType(TypeAnnotation(t));
- };
+ // find in general scope:
+ if (ast->__indexTypeAliases.count(alias)) {
+ return expandType(ast->__indexTypeAliases.at(t.__valueCustom));
+ }
- case TypeOperator::ACCESS:
- {
- std::string alias = t.__valueCustom;
- ExpandedType tyAlias = ExpandedType(TypeAnnotation());
+ //if type is unknown keep it as is.
+ return ExpandedType(TypeAnnotation(t));
+ };
- //find in local scope:
- if (scope.count(alias)) {
- tyAlias = expandType(scope.at(alias));
+ case TypeOperator::ACCESS:
+ {
+ std::string alias = t.__valueCustom;
+ ExpandedType tyAlias = ExpandedType(TypeAnnotation());
- //find in global scope:
- } else if ((ast->__indexTypeAliases.count(alias))) {
- tyAlias = expandType(ast->__indexTypeAliases.at(alias));
+ //find in local scope:
+ if (scope.count(alias)) {
+ tyAlias = expandType(scope.at(alias));
- } else {
- assert(false && "Undefined or external type");
- }
+ //find in global scope:
+ } else if ((ast->__indexTypeAliases.count(alias))) {
+ tyAlias = expandType(ast->__indexTypeAliases.at(alias));
- assert(tyAlias->__operator == TypeOperator::STRUCT);
+ } else {
+ assert(false && "Undefined or external type");
+ }
- for (const string& field : t.fields) {
- auto fieldIt = std::find(tyAlias->fields.begin(), tyAlias->fields.end(), field);
- assert(fieldIt != tyAlias->fields.end() && "unknown field");
+ assert(tyAlias->__operator == TypeOperator::STRUCT);
- int fieldId = fieldIt - tyAlias->fields.begin();
- tyAlias = expandType(tyAlias->__operands.at(fieldId));
- }
+ for (const string& field : t.fields) {
+ auto fieldIt = std::find(tyAlias->fields.begin(), tyAlias->fields.end(), field);
+ assert(fieldIt != tyAlias->fields.end() && "unknown field");
- return tyAlias;
+ int fieldId = fieldIt - tyAlias->fields.begin();
+ tyAlias = expandType(tyAlias->__operands.at(fieldId));
}
- case TypeOperator::VARIANT:
- {
- return ExpandedType(TypeAnnotation(t));
- }
+ return tyAlias;
+ }
- case TypeOperator::NONE:
- {
- return ExpandedType(TypeAnnotation(t));
- }
+ case TypeOperator::VARIANT:
+ {
+ return ExpandedType(TypeAnnotation(t));
+ }
- default:
- assert(false);
+ case TypeOperator::NONE:
+ {
+ return ExpandedType(TypeAnnotation(t));
}
- assert(false);
- return ExpandedType(TypeAnnotation());
+ default:
+ assert(false);
}
- };
- TypeAnnotation::TypeAnnotation()
- : __operator(TypeOperator::NONE), __value(TypePrimitive::Invalid)
- {}
-
- TypeAnnotation::TypeAnnotation(TypePrimitive typ)
- : __value(typ) {
+ assert(false);
+ return ExpandedType(TypeAnnotation());
}
+};
- TypeAnnotation::TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands)
- : __operator(op), __operands(operands) {
+TypeAnnotation::TypeAnnotation()
+: __operator(TypeOperator::NONE), __value(TypePrimitive::Invalid) {
+}
- }
+TypeAnnotation::TypeAnnotation(TypePrimitive typ)
+: __value(typ) {
+}
- TypeAnnotation::TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands)
- : __operator(op), __operands(operands) {
- }
+TypeAnnotation::TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands)
+: __operator(op), __operands(operands) {
- TypeAnnotation::TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size)
- : TypeAnnotation(TypeOperator::ARRAY,{typ}) {
- __size = size;
- }
+}
- bool
- TypeAnnotation::isValid() const{
- return !(__value == TypePrimitive::Invalid && __operator == TypeOperator::NONE);
- }
+TypeAnnotation::TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands)
+: __operator(op), __operands(operands) {
+}
- bool
- TypeAnnotation::operator<(const TypeAnnotation& t) const {
- if (__operator != t.__operator) return __operator < t.__operator;
+TypeAnnotation::TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size)
+: TypeAnnotation(TypeOperator::ARRAY,{typ}) {
+ __size = size;
+}
+
+bool
+TypeAnnotation::isValid() const {
+ return !(__value == TypePrimitive::Invalid && __operator == TypeOperator::NONE);
+}
- if (__operator == TypeOperator::NONE)
- return __value < t.__value;
+bool
+TypeAnnotation::operator<(const TypeAnnotation& t) const {
+ if (__operator != t.__operator) return __operator < t.__operator;
- if (__operator == TypeOperator::CALL || __operator == TypeOperator::CUSTOM || __operator == TypeOperator::ACCESS) {
- if (__valueCustom != t.__valueCustom)
- return __valueCustom < t.__valueCustom;
- }
+ if (__operator == TypeOperator::NONE)
+ return __value < t.__value;
- return __operands < t.__operands;
+ if (__operator == TypeOperator::CALL || __operator == TypeOperator::CUSTOM || __operator == TypeOperator::ACCESS) {
+ if (__valueCustom != t.__valueCustom)
+ return __valueCustom < t.__valueCustom;
}
- /*
- TypeAnnotation (struct_tag, std::initializer_list<TypeAnnotation>)
- {}
- */
+ return __operands < t.__operands;
+}
- void
- TypeAnnotation::addBindings(std::vector<Atom<Identifier_t>>&& params) {
- bindings.reserve(bindings.size() + params.size());
+/*
+TypeAnnotation (struct_tag, std::initializer_list<TypeAnnotation>)
+{}
+ */
- std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()),
- [](const Atom<Identifier_t>& ident) {
- return ident.get(); });
- }
+void
+TypeAnnotation::addBindings(std::vector<Atom<Identifier_t>>&& params) {
+ bindings.reserve(bindings.size() + params.size());
- void
- TypeAnnotation::addFields(std::vector<Atom<Identifier_t>>&& listFields) {
- fields.reserve(fields.size() + listFields.size());
+ std::transform(params.begin(), params.end(), std::inserter(bindings, bindings.end()),
+ [](const Atom<Identifier_t>& ident) {
+ return ident.get(); });
+}
- std::transform(listFields.begin(), listFields.end(), std::inserter(fields, fields.end()),
- [](const Atom<Identifier_t>& ident) {
- return ident.get(); });
- }
+void
+TypeAnnotation::addFields(std::vector<Atom<Identifier_t>>&& listFields) {
+ fields.reserve(fields.size() + listFields.size());
- unsigned int Expression::nextVacantId = 0;
+ std::transform(listFields.begin(), listFields.end(), std::inserter(fields, fields.end()),
+ [](const Atom<Identifier_t>& ident) {
+ return ident.get(); });
+}
- Expression::Expression(const Atom<Number_t>& number)
- : Expression() {
- __state=NUMBER; op=Operator::NONE; __valueD=number.get();
- }
+unsigned int Expression::nextVacantId = 0;
- Expression::Expression(const Atom<String_t>& a)
- : Expression(){
- __state=STRING; op=Operator::NONE; __valueS=a.get();
- }
+Expression::Expression(const Atom<Number_t>& number)
+: Expression() {
+ __state = NUMBER;
+ op = Operator::NONE;
+ __valueD = number.get();
+}
- Expression::Expression(const Atom<Identifier_t> &ident)
- : Expression() {
- __state=IDENT; op=Operator::NONE; __valueS=ident.get();
- }
+Expression::Expression(const Atom<String_t>& a)
+: Expression() {
+ __state = STRING;
+ op = Operator::NONE;
+ __valueS = a.get();
+}
- Expression::Expression(const Operator &oprt, std::initializer_list<Expression> params)
- : Expression() {
- __state=COMPOUND; op=oprt;
+Expression::Expression(const Atom<Identifier_t> &ident)
+: Expression() {
+ __state = IDENT;
+ op = Operator::NONE;
+ __valueS = ident.get();
+}
- if (op == Operator::CALL) {
- assert(params.size() > 0);
- Expression arg = *params.begin();
+Expression::Expression(const Operator &oprt, std::initializer_list<Expression> params)
+: Expression() {
+ __state = COMPOUND;
+ op = oprt;
- assert(arg.__state == Expression::IDENT);
- __valueS = std::move(arg.__valueS);
+ if (op == Operator::CALL) {
+ assert(params.size() > 0);
+ Expression arg = *params.begin();
- operands.insert(operands.end(), params.begin() + 1, params.end());
- return;
- }
+ assert(arg.__state == Expression::IDENT);
+ __valueS = std::move(arg.__valueS);
- operands.insert(operands.end(), params.begin(), params.end());
+ operands.insert(operands.end(), params.begin() + 1, params.end());
+ return;
}
- void
- Expression::setOp(Operator oprt) {
- op = oprt;
+ operands.insert(operands.end(), params.begin(), params.end());
+}
- switch (op) {
- case Operator::NONE:
- __state = INVALID;
- break;
+void
+Expression::setOp(Operator oprt) {
+ op = oprt;
- default:
- __state = COMPOUND;
- break;
- }
- }
+ switch (op) {
+ case Operator::NONE:
+ __state = INVALID;
+ break;
- void
- Expression::addArg(Expression &&arg) {
- operands.push_back(arg);
+ default:
+ __state = COMPOUND;
+ break;
}
+}
+
+void
+Expression::addArg(Expression &&arg) {
+ operands.push_back(arg);
+}
- void
- Expression::addTags(const std::list<Expression> tags) const{
- std::transform(tags.begin(), tags.end(), std::inserter(this->tags, this->tags.end()),
- [](const Expression& tag){
+void
+Expression::addTags(const std::list<Expression> tags) const {
+ std::transform(tags.begin(), tags.end(), std::inserter(this->tags, this->tags.end()),
+ [](const Expression & tag) {
return make_pair(tag.getValueString(), tag);
- });
- }
+ });
+}
- void
- Expression::addBindings(std::initializer_list<Atom<Identifier_t>> params) {
- addBindings(params.begin(), params.end());
- }
+void
+Expression::addBindings(std::initializer_list<Atom<Identifier_t>> params) {
+ addBindings(params.begin(), params.end());
+}
- void
- Expression::bindType(TypeAnnotation t) {
- type = move(t);
- }
+void
+Expression::bindType(TypeAnnotation t) {
+ type = move(t);
+}
- void
- Expression::addBlock(ManagedScpPtr scope) {
- blocks.push_back(scope.operator->());
- }
+void
+Expression::addBlock(ManagedScpPtr scope) {
+ blocks.push_back(scope.operator->());
+}
- const std::vector<Expression>&
- Expression::getOperands() const {
- return operands;
- }
+const std::vector<Expression>&
+Expression::getOperands() const {
+ return operands;
+}
- double
- Expression::getValueDouble() const {
- return __valueD;
- }
+double
+Expression::getValueDouble() const {
+ return __valueD;
+}
- const std::string&
- Expression::getValueString() const {
- return __valueS;
- }
+const std::string&
+Expression::getValueString() const {
+ return __valueS;
+}
- void
- Expression::setValue(const Atom<Identifier_t>&& v) {
- __valueS = v.get();
- }
+void
+Expression::setValue(const Atom<Identifier_t>&& v) {
+ __valueS = v.get();
+}
- void Expression::setValueDouble(double value) {
- __valueD = value;
- }
+void Expression::setValueDouble(double value) {
+ __valueD = value;
+}
- bool
- Expression::isValid() const {
- return (__state != INVALID);
- }
+bool
+Expression::isValid() const {
+ return (__state != INVALID);
+}
- bool
- Expression::isDefined() const {
- return (__state != BINDING);
- }
+bool
+Expression::isDefined() const {
+ return (__state != BINDING);
+}
- Expression::Expression()
- : __state(INVALID), op(Operator::NONE), id(nextVacantId++)
- { }
+Expression::Expression()
+: __state(INVALID), op(Operator::NONE), id(nextVacantId++) {
+}
namespace details { namespace incomplete {
+
AST::AST() {
Attachments::init<versions::VariableVersion>();
Attachments::init<Symbol>();
}
void
AST::addInterfaceData(const ASTInterface& interface, Expression&& data) {
__interfacesData.emplace(interface, move(data));
}
void
AST::addDFAData(Expression &&data) {
__dfadata.push_back(data);
}
void
AST::addExternData(ExternData &&data) {
__externdata.insert(__externdata.end(), data.entries.begin(), data.entries.end());
}
void
AST::add(Function* f) {
__functions.push_back(f);
__indexFunctions.emplace(f->getName(), __functions.size() - 1);
}
void
AST::add(MetaRuleAbstract *r) {
__rules.push_back(r);
}
void
AST::add(TypeAnnotation t, Atom<Identifier_t> alias) {
if (t.__operator == TypeOperator::VARIANT) {
for (int i = 0, size = t.fields.size(); i < size; ++i) {
__dictVariants.emplace(t.fields[i], make_pair(t, i));
}
}
__indexTypeAliases.emplace(alias.get(), move(t));
}
ManagedScpPtr
AST::add(CodeScope* scope) {
this->__scopes.push_back(scope);
return ManagedScpPtr(this->__scopes.size() - 1, &this->__scopes);
}
std::string
AST::getModuleName() {
const std::string name = "moduleTest";
return name;
}
ManagedPtr<Function>
AST::findFunction(const std::string& name) {
int count = __indexFunctions.count(name);
if (!count) {
return ManagedFnPtr::Invalid();
}
assert(count == 1);
auto range = __indexFunctions.equal_range(name);
return ManagedPtr<Function>(range.first->second, &this->__functions);
}
std::list<ManagedFnPtr>
AST::getAllFunctions() const {
const size_t size = __functions.size();
std::list<ManagedFnPtr> result;
for (size_t i = 0; i < size; ++i) {
result.push_back(ManagedFnPtr(i, &this->__functions));
}
return result;
}
//TASK select default specializations
std::list<ManagedFnPtr>
AST::getFunctionVariants(const std::string& name) const {
auto functions = __indexFunctions.equal_range(name);
std::list<ManagedFnPtr> result;
std::transform(functions.first, functions.second, inserter(result, result.end()),
[this](auto f) {
return ManagedFnPtr(f.second, &this->__functions);
});
return result;
}
template<>
ManagedPtr<Function>
AST::begin<Function>() {
return ManagedPtr<Function>(0, &this->__functions);
}
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>() {
return ManagedPtr<CodeScope>(0, &this->__scopes);
}
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>() {
return ManagedPtr<MetaRuleAbstract>(0, &this->__rules);
}
void
AST::recognizeVariantConstructor(Expression& function) {
assert(function.op == Operator::CALL);
std::string variant = function.getValueString();
if (!__dictVariants.count(variant)) {
return;
}
auto record = __dictVariants.at(variant);
const TypeAnnotation& typ = record.first;
function.op = Operator::VARIANT;
function.setValueDouble(record.second);
function.type = typ;
}
+Atom<Number_t>
+AST::recognizeVariantConstructor(Atom<Identifier_t> ident) {
+ std::string variant = ident.get();
+ assert(__dictVariants.count(variant) && "Can't recognize variant constructor");
+ auto record = __dictVariants.at(variant);
+
+ return Atom<Number_t>(record.second);
+}
+
void
AST::postponeIdentifier(CodeScope* scope, const Expression& id) {
bucketUnrecognizedIdentifiers.emplace(scope, id);
}
void
AST::recognizePostponedIdentifiers() {
- for(const auto& identifier: bucketUnrecognizedIdentifiers){
- if (!identifier.first->recognizeIdentifier(identifier.second)){
+ for (const auto& identifier : bucketUnrecognizedIdentifiers) {
+ if (!identifier.first->recognizeIdentifier(identifier.second)) {
//exception: Ident not found
- std::cout << "Unknown symbol: "<< identifier.second.getValueString() << std::endl;
+ std::cout << "Unknown symbol: " << identifier.second.getValueString() << std::endl;
assert(false && "Symbol not found");
}
}
}
xreate::AST*
AST::finalize() {
//all finalization steps:
recognizePostponedIdentifiers();
- return reinterpret_cast<xreate::AST*>(this);
+ return reinterpret_cast<xreate::AST*> (this);
}
-}} //namespace details::incomplete
+
+} } //namespace details::incomplete
Expanded<TypeAnnotation>
AST::findType(const std::string& name) {
// find in general scope:
if (__indexTypeAliases.count(name))
return expandType(__indexTypeAliases.at(name));
//if type is unknown keep it as is.
TypeAnnotation t(TypeOperator::CUSTOM,{});
t.__valueCustom = name;
return ExpandedType(move(t));
}
Expanded<TypeAnnotation>
AST::expandType(const TypeAnnotation &t) const {
return TypesResolver(this)(t);
}
ExpandedType
-AST::getType(const Expression& expression){
+AST::getType(const Expression& expression) {
return typeinference::getType(expression, *this);
}
- Function::Function(const Atom<Identifier_t>& name)
- : __entry(new CodeScope(0)) {
- __name = name.get();
- }
-
- void
- Function::addTag(Expression&& tag, const TagModifier mod) {
- string name = tag.getValueString();
- __tags.emplace(move(name), move(tag));
- }
+Function::Function(const Atom<Identifier_t>& name)
+: __entry(new CodeScope(0)) {
+ __name = name.get();
+}
- const std::map<std::string, Expression>&
- Function::getTags() const {
- return __tags;
- }
+void
+Function::addTag(Expression&& tag, const TagModifier mod) {
+ string name = tag.getValueString();
+ __tags.emplace(move(name), move(tag));
+}
- CodeScope*
- Function::getEntryScope() const {
- return __entry;
- }
+const std::map<std::string, Expression>&
+Function::getTags() const {
+ return __tags;
+}
- void
- Function::addBinding(Atom <Identifier_t>&& name, Expression&& argument) {
- __entry->addBinding(move(name), move(argument));
- }
+CodeScope*
+Function::getEntryScope() const {
+ return __entry;
+}
- const std::string&
- Function::getName() const {
- return __name;
- }
+void
+Function::addBinding(Atom <Identifier_t>&& name, Expression&& argument) {
+ __entry->addBinding(move(name), move(argument));
+}
- ScopedSymbol
- CodeScope::registerIdentifier(const Expression& identifier) {
- versions::VariableVersion version = Attachments::get<versions::VariableVersion>(identifier, versions::VERSION_NONE);
+const std::string&
+Function::getName() const {
+ return __name;
+}
- auto result = __identifiers.emplace(identifier.getValueString(), __vCounter);
- if (result.second){
- ++__vCounter;
- return {__vCounter-1, version};
- }
+ScopedSymbol
+CodeScope::registerIdentifier(const Expression& identifier) {
+ versions::VariableVersion version = Attachments::get<versions::VariableVersion>(identifier, versions::VERSION_NONE);
- return {result.first->second, version};
+ auto result = __identifiers.emplace(identifier.getValueString(), __vCounter);
+ if (result.second) {
+ ++__vCounter;
+ return { __vCounter - 1, version };
}
- bool
- CodeScope::recognizeIdentifier(const Expression& identifier) const{
- versions::VariableVersion version = Attachments::get<versions::VariableVersion>(identifier, versions::VERSION_NONE);
- const std::string& name = identifier.getValueString();
-
- //search identifier in the current block
- if (__identifiers.count(name)){
- VNameId id = __identifiers.at(name);
+ return { result.first->second, version };
+}
- Symbol s;
- s.identifier = ScopedSymbol{id, version};
- s.scope = const_cast<CodeScope*>(this);
- Attachments::put<Symbol>(identifier, s);
+bool
+CodeScope::recognizeIdentifier(const Expression& identifier) const {
+ versions::VariableVersion version = Attachments::get<versions::VariableVersion>(identifier, versions::VERSION_NONE);
+ const std::string& name = identifier.getValueString();
- return true;
- }
+ //search identifier in the current block
+ if (__identifiers.count(name)) {
+ VNameId id = __identifiers.at(name);
- //search in the parent scope
- if (__parent)
- {
- return __parent->recognizeIdentifier(identifier);
- }
+ Symbol s;
+ s.identifier = ScopedSymbol{id, version};
+ s.scope = const_cast<CodeScope*> (this);
+ Attachments::put<Symbol>(identifier, s);
- return false;
+ return true;
}
- ScopedSymbol
- CodeScope::getSymbol(const std::string& alias){
- assert(__identifiers.count(alias));
- VNameId id = __identifiers.at(alias);
-
- return {id, versions::VERSION_NONE};
+ //search in the parent scope
+ if (__parent) {
+ return __parent->recognizeIdentifier(identifier);
}
- void
- CodeScope::addBinding(Expression&& var, Expression&& argument) {
- argument.__state = Expression::BINDING;
+ return false;
+}
- __bindings.push_back(var.getValueString());
- ScopedSymbol binding = registerIdentifier(var);
- __declarations[binding] = move(argument);
- }
+ScopedSymbol
+CodeScope::getSymbol(const std::string& alias) {
+ assert(__identifiers.count(alias));
+ VNameId id = __identifiers.at(alias);
- void
- CodeScope::addDeclaration(Expression&& var, Expression&& body) {
- ScopedSymbol s = registerIdentifier(var);
- __declarations[s] = move(body);
- }
+ return {id, versions::VERSION_NONE };
+}
- CodeScope::CodeScope(CodeScope* parent)
- : __parent(parent) {
- }
+void
+CodeScope::addBinding(Expression&& var, Expression&& argument) {
+ argument.__state = Expression::BINDING;
- CodeScope::~CodeScope() {
- }
+ __bindings.push_back(var.getValueString());
+ ScopedSymbol binding = registerIdentifier(var);
+ __declarations[binding] = move(argument);
+}
- void
- CodeScope::setBody(const Expression &body) {
- __declarations[ScopedSymbol::RetSymbol] = body;
- }
+void
+CodeScope::addDeclaration(Expression&& var, Expression&& body) {
+ ScopedSymbol s = registerIdentifier(var);
+ __declarations[s] = move(body);
+}
- Expression&
- CodeScope::getBody() {
- return __declarations[ScopedSymbol::RetSymbol];
- }
+CodeScope::CodeScope(CodeScope* parent)
+: __parent(parent) {
+}
- const Expression&
- CodeScope::getDeclaration(const Symbol& symbol) {
- CodeScope* self = symbol.scope;
- return self->getDeclaration(symbol.identifier);
- }
+CodeScope::~CodeScope() {
+}
- const Expression&
- CodeScope::getDeclaration(const ScopedSymbol& symbol){
- assert(__declarations.count(symbol) && "Symbol's declaration not found");
+void
+CodeScope::setBody(const Expression &body) {
+ __declarations[ScopedSymbol::RetSymbol] = body;
+}
- return __declarations.at(symbol);
- }
+Expression&
+CodeScope::getBody() {
+ return __declarations[ScopedSymbol::RetSymbol];
+}
- void
- RuleArguments::add(const Atom<Identifier_t> &arg, DomainAnnotation typ) {
- emplace_back(arg.get(), typ);
- }
+const Expression&
+CodeScope::getDeclaration(const Symbol& symbol) {
+ CodeScope* self = symbol.scope;
+ return self->getDeclaration(symbol.identifier);
+}
- void
- RuleGuards::add(Expression&& e) {
- push_back(e);
- }
+const Expression&
+CodeScope::getDeclaration(const ScopedSymbol& symbol) {
+ assert(__declarations.count(symbol) && "Symbol's declaration not found");
- MetaRuleAbstract::
- MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards)
- : __args(std::move(args)), __guards(std::move(guards)) {
- }
+ return __declarations.at(symbol);
+}
- MetaRuleAbstract::~MetaRuleAbstract() {
- }
+void
+RuleArguments::add(const Atom<Identifier_t> &arg, DomainAnnotation typ) {
+ emplace_back(arg.get(), typ);
+}
- RuleWarning::
- RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message)
- : MetaRuleAbstract(std::move(args), std::move(guards)), __message(message.get()), __condition(condition) {
- }
+void
+RuleGuards::add(Expression&& e) {
+ push_back(e);
+}
- RuleWarning::~RuleWarning() {
- }
+MetaRuleAbstract::
+MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards)
+: __args(std::move(args)), __guards(std::move(guards)) {
+}
- void
- RuleWarning::compile(ClaspLayer& layer) {
- //TODO restore addRuleWarning
- //layer.addRuleWarning(*this);
- }
+MetaRuleAbstract::~MetaRuleAbstract() {
+}
- bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2) {
- return (s1.id < s2.id) || (s1.id==s2.id && s1.version < s2.version);
- }
+RuleWarning::
+RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message)
+: MetaRuleAbstract(std::move(args), std::move(guards)), __message(message.get()), __condition(condition) {
+}
- bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2) {
- return (s1.id == s2.id) && (s1.version == s2.version);
- }
+RuleWarning::~RuleWarning() {
+}
- bool operator<(const Symbol& s1, const Symbol& s2) {
- return (s1.scope < s2.scope) || (s1.scope == s2.scope && s1.identifier < s2.identifier);
- }
+void
+RuleWarning::compile(ClaspLayer& layer) {
+ //TODO restore addRuleWarning
+ //layer.addRuleWarning(*this);
+}
- bool operator==(const Symbol& s1, const Symbol& s2) {
- return (s1.scope == s2.scope) && (s1.identifier == s2.identifier);
- }
+bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2) {
+ return (s1.id < s2.id) || (s1.id == s2.id && s1.version < s2.version);
+}
- bool operator<(const Expression&a, const Expression&b) {
- if (a.__state != b.__state) return a.__state < b.__state;
- assert(a.__state != Expression::INVALID);
- switch (a.__state) {
- case Expression::IDENT:
- case Expression::STRING:
- case Expression::NUMBER:
- return a.getValueDouble() < b.getValueDouble();
+bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2) {
+ return (s1.id == s2.id) && (s1.version == s2.version);
+}
- case Expression::COMPOUND:
- {
- assert(a.blocks.size() == 0);
- assert(b.blocks.size() == 0);
+bool operator<(const Symbol& s1, const Symbol& s2) {
+ return (s1.scope < s2.scope) || (s1.scope == s2.scope && s1.identifier < s2.identifier);
+}
- if (a.op != b.op){
- return a.op < b.op;
- }
+bool operator==(const Symbol& s1, const Symbol& s2) {
+ return (s1.scope == s2.scope) && (s1.identifier == s2.identifier);
+}
- bool flagAValid = ExpressionHints::isStringValueValid(a);
- bool flagBValid = ExpressionHints::isStringValueValid(b);
+bool operator<(const Expression&a, const Expression&b) {
+ if (a.__state != b.__state) return a.__state < b.__state;
+ assert(a.__state != Expression::INVALID);
+ switch (a.__state) {
+ case Expression::IDENT:
+ case Expression::STRING:
+ return a.getValueString() < b.getValueString();
+
+ case Expression::NUMBER:
+ return a.getValueDouble() < b.getValueDouble();
+
+ case Expression::COMPOUND:
+ {
+ assert(a.blocks.size() == 0);
+ assert(b.blocks.size() == 0);
- if (flagAValid != flagBValid) {
- return flagAValid < flagBValid;
- }
+ if (a.op != b.op) {
+ return a.op < b.op;
+ }
- if (flagAValid){
- if (a.getValueString() != b.getValueString()) {
- return a.getValueString() < b.getValueString();
- }
- }
+ bool flagAValid = ExpressionHints::isStringValueValid(a);
+ bool flagBValid = ExpressionHints::isStringValueValid(b);
- flagAValid = ExpressionHints::isDoubleValueValid(a);
- flagBValid = ExpressionHints::isDoubleValueValid(b);
+ if (flagAValid != flagBValid) {
+ return flagAValid < flagBValid;
+ }
- if (flagAValid != flagBValid) {
- return flagAValid < flagBValid;
+ if (flagAValid) {
+ if (a.getValueString() != b.getValueString()) {
+ return a.getValueString() < b.getValueString();
}
+ }
- if (flagAValid){
- if (a.getValueDouble() != b.getValueDouble()) {
- return a.getValueDouble() < b.getValueDouble();
- }
- }
+ flagAValid = ExpressionHints::isDoubleValueValid(a);
+ flagBValid = ExpressionHints::isDoubleValueValid(b);
- if (a.operands.size() != b.operands.size()) {
- return (a.operands.size() < b.operands.size());
- }
+ if (flagAValid != flagBValid) {
+ return flagAValid < flagBValid;
+ }
- for (size_t i = 0; i < a.operands.size(); ++i) {
- bool result = a.operands[i] < b.operands[i];
- if (result) return true;
+ if (flagAValid) {
+ if (a.getValueDouble() != b.getValueDouble()) {
+ return a.getValueDouble() < b.getValueDouble();
}
+ }
- return false;
+ if (a.operands.size() != b.operands.size()) {
+ return (a.operands.size() < b.operands.size());
}
- case Expression::BINDING:
- case Expression::INVALID:
- assert(false);
+ for (size_t i = 0; i < a.operands.size(); ++i) {
+ bool result = a.operands[i] < b.operands[i];
+ if (result) return true;
+ }
+
+ return false;
}
- return false;
+ case Expression::BINDING:
+ case Expression::INVALID:
+ assert(false);
}
- bool
- Expression::operator==(const Expression& other) const {
- if (this->__state != other.__state) return false;
-
- if (ExpressionHints::isStringValueValid(*this)) {
- if (this->__valueS != other.__valueS) return false;
- }
+ return false;
+}
- if (ExpressionHints::isDoubleValueValid(*this)) {
- if (this->__valueD != other.__valueD) return false;
- }
+bool
+Expression::operator==(const Expression& other) const {
+ if (this->__state != other.__state) return false;
- if (this->__state != Expression::COMPOUND) {
- return true;
- }
+ if (ExpressionHints::isStringValueValid(*this)) {
+ if (this->__valueS != other.__valueS) return false;
+ }
- if (this->op != other.op) {
- return false;
- }
+ if (ExpressionHints::isDoubleValueValid(*this)) {
+ if (this->__valueD != other.__valueD) return false;
+ }
- if (this->operands.size() != other.operands.size()) {
- return false;
- }
+ if (this->__state != Expression::COMPOUND) {
+ return true;
+ }
- for (size_t i = 0; i<this->operands.size(); ++i) {
- if (!(this->operands[i] == other.operands[i])) return false;
- }
+ if (this->op != other.op) {
+ return false;
+ }
- assert(!this->blocks.size());
- assert(!other.blocks.size());
+ if (this->operands.size() != other.operands.size()) {
+ return false;
+ }
- return true;
+ for (size_t i = 0; i<this->operands.size(); ++i) {
+ if (!(this->operands[i] == other.operands[i])) return false;
}
+ assert(!this->blocks.size());
+ assert(!other.blocks.size());
+
+ return true;
+}
+
const ScopedSymbol
ScopedSymbol::RetSymbol = ScopedSymbol{0, versions::VERSION_NONE};
-}
+
+} //end of namespace xreate
diff --git a/cpp/src/ast.h b/cpp/src/ast.h
index 5a71e8e..0a9e308 100644
--- a/cpp/src/ast.h
+++ b/cpp/src/ast.h
@@ -1,577 +1,576 @@
#ifndef AST_H
#define AST_H
#include "attachments.h"
#include <vector>
#include <stdlib.h>
#include <string>
#include <list>
#include <unordered_map>
#include <unordered_set>
#include <climits>
#include "utils.h"
#include <algorithm>
namespace llvm {
class Value;
}
-namespace xreate{
+namespace xreate {
struct ScopedSymbol;
struct Symbol;
}
-namespace std
-{
+namespace std {
+
template<>
- struct hash<xreate::ScopedSymbol>{
+ struct hash<xreate::ScopedSymbol> {
std::size_t operator()(xreate::ScopedSymbol const& s) const;
};
template<>
- struct equal_to<xreate::ScopedSymbol>{
- bool operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const;
+ struct equal_to<xreate::ScopedSymbol> {
+ bool operator()(const xreate::ScopedSymbol& __x, const xreate::ScopedSymbol& __y) const;
};
-
+
template<>
- struct hash<xreate::Symbol>{
+ struct hash<xreate::Symbol> {
size_t operator()(xreate::Symbol const& s) const;
};
template<>
- struct equal_to<xreate::Symbol>{
- bool operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const;
+ struct equal_to<xreate::Symbol> {
+ bool operator()(const xreate::Symbol& __x, const xreate::Symbol& __y) const;
};
}
namespace xreate {
struct String_t {
};
struct Identifier_t {
};
struct Number_t {
};
struct Type_t {
};
template<typename A>
class Atom {
};
//DEBT hold for all atoms/identifiers Parser::Token data, like line:col position
-template<> class
+template<> class
Atom<Identifier_t> {
public:
Atom(const std::wstring& value);
Atom(std::string && name);
const std::string& get() const;
-
+
private:
std::string __value;
};
-template<>
+template<>
class Atom<Number_t> {
public:
Atom(wchar_t* value);
Atom(int value);
double get()const;
-
+
private:
double __value;
};
-template<>
+template<>
class Atom<String_t> {
public:
Atom(const std::wstring& value);
const std::string& get() const;
private:
std::string __value;
};
enum class TypePrimitive {
Invalid, Bool, I8, I32, I64, Num, Int, Float, String
};
enum class TypeOperator {
- NONE, CALL, CUSTOM, VARIANT, ARRAY, STRUCT, ACCESS, LINK
+ NONE, CALL, CUSTOM, VARIANT, ARRAY, STRUCT, ACCESS, LINK
};
struct llvm_array_tag {
};
struct struct_tag {
};
const llvm_array_tag tag_array = llvm_array_tag();
const struct_tag tag_struct = struct_tag();
class TypeAnnotation {
public:
TypeAnnotation();
TypeAnnotation(const Atom<Type_t>& typ);
TypeAnnotation(TypePrimitive typ);
TypeAnnotation(llvm_array_tag, TypeAnnotation typ, int size);
TypeAnnotation(TypeOperator op, std::initializer_list<TypeAnnotation> operands);
TypeAnnotation(TypeOperator op, std::vector<TypeAnnotation>&& operands);
void addBindings(std::vector<Atom<Identifier_t>>&& params);
void addFields(std::vector<Atom<Identifier_t>>&& listFields);
bool operator<(const TypeAnnotation& t) const;
// TypeAnnotation (struct_tag, std::initializer_list<TypePrimitive>);
bool isValid() const;
TypeOperator __operator = TypeOperator::NONE;
std::vector<TypeAnnotation> __operands;
TypePrimitive __value;
std::string __valueCustom;
int conjuctionId = -1; //conjunction point id (relevant for recursive types)
uint64_t __size = 0;
std::vector<std::string> fields;
std::vector<std::string> bindings;
private:
};
enum class Operator {
ADD, SUB, MUL, DIV,
- EQU, NE, NEG, LSS,
- LSE, GTR, GTE, LIST,
- LIST_RANGE, LIST_NAMED,
- CALL, CALL_INTRINSIC, NONE,
- IMPL/* implication */, MAP,
- FOLD, FOLD_INF, LOOP_CONTEXT,
- INDEX, IF, SWITCH, SWITCH_ADHOC,
- CASE, CASE_DEFAULT, LOGIC_AND,
+ EQU, NE, NEG, LSS,
+ LSE, GTR, GTE, LIST,
+ LIST_RANGE, LIST_NAMED,
+ CALL, CALL_INTRINSIC, NONE,
+ IMPL/* implication */, MAP,
+ FOLD, FOLD_INF, LOOP_CONTEXT,
+ INDEX, IF, SWITCH, SWITCH_ADHOC, SWITCH_VARIANT,
+ CASE, CASE_DEFAULT, LOGIC_AND,
ADHOC, CONTEXT_RULE, VARIANT
};
class Function;
class AST;
class CodeScope;
class MetaRuleAbstract;
template<class Target>
struct ManagedPtr {
static ManagedPtr<Target> Invalid() {
return ManagedPtr<Target>();
}
ManagedPtr() : __storage(0) {
}
ManagedPtr(unsigned int id, const std::vector<Target*>* storage)
: __id(id), __storage(storage) {
}
Target&
operator*() const {
assert(isValid() && "Invalid Ptr");
return *__storage->at(__id);
}
void operator=(const ManagedPtr<Target>& other) {
__id = other.__id;
__storage = other.__storage;
}
bool
operator==(const ManagedPtr<Target>& other) {
return isValid() && (__id == other.__id);
}
Target*
operator->() const noexcept {
assert(isValid() && "Invalid Ptr");
return __storage->at(__id);
}
inline bool isValid() const {
return (__storage) && (0 <= __id) && (__id < __storage->size());
}
inline operator bool() const {
return isValid();
}
ManagedPtr<Target>& operator++() {
++__id;
return *this;
}
inline unsigned int id() const {
return __id;
}
private:
unsigned int __id = 0;
const std::vector<Target*> * __storage = 0;
};
typedef ManagedPtr<Function> ManagedFnPtr;
typedef ManagedPtr<CodeScope> ManagedScpPtr;
typedef ManagedPtr<MetaRuleAbstract> ManagedRulePtr;
const ManagedScpPtr NO_SCOPE = ManagedScpPtr(UINT_MAX, 0);
//To update ExpressionHints in case of any changes
struct Expression {
friend class CodeScope;
friend class ClaspLayer;
friend class CFAPass;
friend class ExpressionHints;
Expression(const Operator &oprt, std::initializer_list<Expression> params);
Expression(const Atom<Identifier_t>& ident);
Expression(const Atom<Number_t>& number);
Expression(const Atom<String_t>& a);
Expression();
void setOp(Operator oprt);
void addArg(Expression&& arg);
void addBindings(std::initializer_list<Atom<Identifier_t>> params);
void bindType(TypeAnnotation t);
template<class InputIt>
void addBindings(InputIt paramsBegin, InputIt paramsEnd);
void addTags(const std::list<Expression> tags) const;
void addBlock(ManagedScpPtr scope);
const std::vector<Expression>& getOperands() const;
double getValueDouble() const;
void setValueDouble(double value);
const std::string& getValueString() const;
void setValue(const Atom<Identifier_t>&& v);
bool isValid() const;
bool isDefined() const;
bool operator==(const Expression& other) const;
enum {
INVALID, COMPOUND, IDENT, NUMBER, STRING, BINDING
} __state = INVALID;
Operator op;
unsigned int id;
std::vector<std::string> bindings;
std::map<std::string, size_t> __indexBindings;
std::vector<Expression> operands;
TypeAnnotation type;
mutable std::map<std::string, Expression> tags;
std::list<CodeScope*> blocks;
private:
std::string __valueS;
double __valueD;
static unsigned int nextVacantId;
};
-bool operator< (const Expression&, const Expression&);
+bool operator<(const Expression&, const Expression&);
template<class InputIt>
void Expression::addBindings(InputIt paramsBegin, InputIt paramsEnd) {
size_t index = bindings.size();
std::transform(paramsBegin, paramsEnd, std::inserter(bindings, bindings.end()),
[&index, this] (const Atom<Identifier_t> atom) {
std::string key = atom.get();
this->__indexBindings[key] = index++;
return key;
});
}
typedef std::list<Expression> ExpressionList;
enum class TagModifier {
NONE, ASSERT, REQUIRE
};
enum class DomainAnnotation {
FUNCTION, VARIABLE
};
class RuleArguments : public std::vector<std::pair<std::string, DomainAnnotation>>
{
public:
void add(const Atom<Identifier_t>& name, DomainAnnotation typ);
};
class RuleGuards : public std::vector<Expression> {
public:
void add(Expression&& e);
};
class ClaspLayer;
class LLVMLayer;
class MetaRuleAbstract {
public:
MetaRuleAbstract(RuleArguments&& args, RuleGuards&& guards);
virtual ~MetaRuleAbstract();
virtual void compile(ClaspLayer& layer) = 0;
protected:
RuleArguments __args;
RuleGuards __guards;
};
class RuleWarning : public MetaRuleAbstract {
friend class ClaspLayer;
public:
RuleWarning(RuleArguments&& args, RuleGuards&& guards, Expression&& condition, Atom<String_t>&& message);
virtual void compile(ClaspLayer& layer);
~RuleWarning();
private:
std::string __message;
Expression __condition;
};
typedef unsigned int VNameId;
namespace versions {
typedef int VariableVersion;
const VariableVersion VERSION_NONE = -2;
const VariableVersion VERSION_INIT = 0;
}
template<>
-struct AttachmentsDict<versions::VariableVersion>
-{
+struct AttachmentsDict<versions::VariableVersion> {
typedef versions::VariableVersion Data;
static const unsigned int key = 6;
};
-struct ScopedSymbol{
+struct ScopedSymbol {
VNameId id;
versions::VariableVersion version;
static const ScopedSymbol RetSymbol;
};
struct Symbol {
ScopedSymbol identifier;
CodeScope * scope;
};
template<>
-struct AttachmentsDict<Symbol>
-{
+struct AttachmentsDict<Symbol> {
typedef Symbol Data;
static const unsigned int key = 7;
};
-
+
typedef std::pair<Expression, TagModifier> Tag;
bool operator<(const ScopedSymbol& s1, const ScopedSymbol& s2);
bool operator==(const ScopedSymbol& s1, const ScopedSymbol& s2);
bool operator<(const Symbol& s1, const Symbol& s2);
bool operator==(const Symbol& s1, const Symbol& s2);
class CodeScope {
friend class Function;
friend class PassManager;
public:
CodeScope(CodeScope* parent = 0);
void setBody(const Expression& body);
Expression& getBody();
void addDeclaration(Expression&& var, Expression&& body);
void addBinding(Expression&& var, Expression&& argument);
static const Expression& getDeclaration(const Symbol& symbol);
const Expression& getDeclaration(const ScopedSymbol& symbol);
~CodeScope();
std::vector<std::string> __bindings;
std::map<std::string, VNameId> __identifiers;
CodeScope* __parent;
//TODO move __definitions to SymbolsAttachments data
//NOTE: definition of return type has zero(0) variable index
std::unordered_map<ScopedSymbol, Expression> __declarations;
std::vector<Expression> tags;
std::vector<Expression> contextRules;
private:
VNameId __vCounter = 1;
ScopedSymbol registerIdentifier(const Expression& identifier);
public:
bool recognizeIdentifier(const Expression& identifier) const;
ScopedSymbol getSymbol(const std::string& alias);
};
class Function {
friend class Expression;
friend class CodeScope;
friend class AST;
public:
Function(const Atom<Identifier_t>& name);
void addBinding(Atom <Identifier_t>&& name, Expression&& argument);
void addTag(Expression&& tag, const TagModifier mod);
const std::string& getName() const;
const std::map<std::string, Expression>& getTags() const;
CodeScope* getEntryScope() const;
CodeScope* __entry;
std::string __name;
bool isPrefunction = false; //SECTIONTAG adhoc Function::isPrefunction flag
Expression guardContext;
private:
std::map<std::string, Expression> __tags;
};
class ExternData;
struct ExternEntry {
std::string package;
std::vector<std::string> headers;
};
typedef Expanded<TypeAnnotation> ExpandedType;
enum ASTInterface {
CFA, DFA, Extern, Adhoc
};
struct FunctionSpecialization {
std::string guard;
size_t id;
};
struct FunctionSpecializationQuery {
std::unordered_set<std::string> context;
};
template<>
struct AttachmentsId<Expression>{
static unsigned int getId(const Expression& expression){
return expression.id;
}
};
template<>
struct AttachmentsId<Symbol>{
static unsigned int getId(const Symbol& s){
return s.scope->__declarations.at(s.identifier).id;
}
};
template<>
struct AttachmentsId<ManagedFnPtr>{
static unsigned int getId(const ManagedFnPtr& f){
const Symbol symbolFunction{ScopedSymbol::RetSymbol, f->getEntryScope()};
-
+
return AttachmentsId<Symbol>::getId(symbolFunction);
}
};
namespace details { namespace incomplete {
class AST {
public:
AST();
//TASK extern and DFA interfaces move into addInterfaceData
/**
* DFA Interface
*/
void addDFAData(Expression&& data);
/**
* Extern Interface
*/
void addExternData(ExternData&& data);
void addInterfaceData(const ASTInterface& interface, Expression&& data);
void add(Function* f);
void add(MetaRuleAbstract* r);
ManagedScpPtr add(CodeScope* scope);
std::string getModuleName();
ManagedPtr<Function> findFunction(const std::string& name);
typedef std::multimap<std::string, unsigned int> FUNCTIONS_REGISTRY;
std::list<ManagedFnPtr> getAllFunctions() const;
std::list<ManagedFnPtr> getFunctionVariants(const std::string& name) const;
template<class Target>
ManagedPtr<Target> begin();
std::vector<ExternEntry> __externdata;
std::list<Expression> __dfadata; //TODO move to more appropriate place
std::list<std::string> __rawImports; //TODO move to more appropriate place
std::multimap<ASTInterface, Expression> __interfacesData; //TODO CFA data here.
private:
std::vector<MetaRuleAbstract*> __rules;
std::vector<Function*> __functions;
std::vector<CodeScope*> __scopes;
FUNCTIONS_REGISTRY __indexFunctions;
// ***** TYPES SECTION *****
public:
std::map<std::string, TypeAnnotation> __indexTypeAliases;
-
- ExpandedType getType(const Expression& expression);
+
void add(TypeAnnotation t, Atom<Identifier_t> alias);
-
+
// ***** SYMBOL RECOGNITION *****
//TODO revisit enums/variants, move to codescope
void recognizeVariantConstructor(Expression& function);
+ Atom<Number_t> recognizeVariantConstructor(Atom<Identifier_t> ident);
private:
std::map<std::string, std::pair<TypeAnnotation, int>> __dictVariants;
-
+
public:
std::set<std::pair<CodeScope*, Expression>> bucketUnrecognizedIdentifiers;
public:
void postponeIdentifier(CodeScope* scope, const Expression& id);
void recognizePostponedIdentifiers();
xreate::AST* finalize();
};
template<>
ManagedPtr<Function>
AST::begin<Function>();
template<>
ManagedPtr<CodeScope>
AST::begin<CodeScope>();
template<>
ManagedPtr<MetaRuleAbstract>
AST::begin<MetaRuleAbstract>();
} } // namespace details::incomplete
-class AST: public details::incomplete::AST{
-public:
- AST(): details::incomplete::AST() {}
+class AST : public details::incomplete::AST {
+public:
+
+ AST() : details::incomplete::AST() {}
ExpandedType expandType(const TypeAnnotation &t) const;
ExpandedType findType(const std::string& name);
ExpandedType getType(const Expression& expression);
};
}
#endif // AST_H
diff --git a/cpp/src/compilation/advanced.cpp b/cpp/src/compilation/advanced.cpp
index f4c64d2..e4f787c 100644
--- a/cpp/src/compilation/advanced.cpp
+++ b/cpp/src/compilation/advanced.cpp
@@ -1,399 +1,401 @@
/*
* File: InstructionsAdvanced.cpp
* Author: pgess
*
* Created on June 26, 2016, 6:00 PM
*/
//#include <compilation/transformations.h>
#include "compilation/advanced.h"
#include "compilation/containers.h"
#include "compilation/transformersaturation.h"
#include "query/context.h"
#include "query/containers.h"
#include "llvmlayer.h"
#include "ast.h"
using namespace std;
using namespace llvm;
using namespace xreate;
using namespace xreate::containers;
using namespace xreate::compilation;
#define NAME(x) (hintRetVar.empty()? x : hintRetVar)
#define UNUSED(x) (void)(x)
#define EXPAND_CONTEXT \
LLVMLayer* llvm = context.pass->man->llvm; \
compilation::ICodeScopeUnit* scope = context.scope; \
compilation::IFunctionUnit* function = context.function;
Advanced::Advanced(compilation::Context ctx)
: context(ctx), tyNum(static_cast<llvm::IntegerType*> (ctx.pass->man->llvm->toLLVMType(ExpandedType(TypeAnnotation(TypePrimitive::Num))))) {
}
llvm::Value*
Advanced::compileMapSolidOutput(const Expression &expr, const std::string hintRetVar) {
EXPAND_CONTEXT
+ UNUSED(scope);
//initialization
Symbol symbolIn = Attachments::get<Symbol>(expr.getOperands()[0]);
ImplementationRec<SOLID> implIn = containers::Query::queryImplementation(symbolIn).extract<SOLID>(); // impl of input list
size_t size = implIn.size;
CodeScope* scopeLoop = expr.blocks.front();
std::string varEl = scopeLoop->__bindings[0];
Iterator* it = Iterator::create(context, symbolIn);
llvm::Value *rangeFrom = it->begin();
llvm::Value *rangeTo = it->end();
//definitions
ArrayType* tyNumArray = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::Num, size))));
llvm::IRBuilder<> &builder = llvm->builder;
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "loop", function->raw);
llvm::BasicBlock *blockBeforeLoop = builder.GetInsertBlock();
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "postloop", function->raw);
Value* dataOut = llvm->builder.CreateAlloca(tyNumArray, ConstantInt::get(tyNum, size), NAME("map"));
// * initial check
Value* condBefore = builder.CreateICmpSLE(rangeFrom, rangeTo);
builder.CreateCondBr(condBefore, blockLoop, blockAfterLoop);
// create PHI:
builder.SetInsertPoint(blockLoop);
llvm::PHINode *stateLoop = builder.CreatePHI(tyNum, 2, "mapIt");
stateLoop->addIncoming(rangeFrom, blockBeforeLoop);
// loop body:
Value* elIn = it->get(stateLoop, varEl);
compilation::ICodeScopeUnit* scopeLoopUnit = function->getScopeUnit(scopeLoop);
scopeLoopUnit->bindArg(elIn, move(varEl));
Value* elOut = scopeLoopUnit->compile();
Value *pElOut = builder.CreateGEP(dataOut, ArrayRef<Value *>(std::vector<Value*>{ConstantInt::get(tyNum, 0), stateLoop}));
builder.CreateStore(elOut, pElOut);
//next iteration preparing
Value *stateLoopNext = builder.CreateAdd(stateLoop, llvm::ConstantInt::get(tyNum, 1));
stateLoop->addIncoming(stateLoopNext, builder.GetInsertBlock());
//next iteration checks:
Value* condAfter = builder.CreateICmpSLE(stateLoopNext, rangeTo);
builder.CreateCondBr(condAfter, blockLoop, blockAfterLoop);
//finalization:
builder.SetInsertPoint(blockAfterLoop);
return dataOut;
}
Value*
Advanced::compileArrayIndex(llvm::Value* aggregate, std::vector<llvm::Value *> indexes, std::string hintRetVar) {
EXPAND_CONTEXT
UNUSED(function);
+ UNUSED(scope);
indexes.insert(indexes.begin(), llvm::ConstantInt::get(tyNum, 0));
llvm::Value *pEl = llvm->builder.CreateGEP(aggregate, llvm::ArrayRef<llvm::Value *>(indexes));
return llvm->builder.CreateLoad(pEl, NAME("el"));
}
Value*
Advanced::compileStructIndex(llvm::Value* aggregate, const ExpandedType& t, const std::string& idx) {
EXPAND_CONTEXT
UNUSED(scope);
-
+ UNUSED(function);
TypeUtils types(llvm);
std::vector<std::string>&& fields = types.getStructFields(t);
for (unsigned i = 0, size = fields.size(); i < size; ++i) {
if (fields.at(i) == idx) {
//TODO DISABLEDFEATURE validptr
// TODO review safety check: validPtr for `aggregate`
// SECTIONTAG validptr exception
// std::vector<llvm::Value*> refs;
// llvm::BasicBlock *blockSafe = llvm::BasicBlock::Create(llvm::getGlobalContext(), "safe", function->raw);
// PointerType* tyAggr = dyn_cast<PointerType>(aggregate->getType());
// llvm::Value* null = llvm::ConstantPointerNull::get(tyAggr);
// Value* condNull = llvm->builder.CreateICmpNE(aggregate, null);
//
// llvm::BasicBlock *blockException = llvm::BasicBlock::Create(llvm::getGlobalContext(), "exception", function->raw);
// llvm->builder.CreateCondBr(condNull, blockSafe, blockException);
// llvm->initExceptionBlock(blockException);
//
// llvm->builder.SetInsertPoint(blockSafe);
//dereference pointer
if (types.isPointer(t)) {
llvm::Value* addr = llvm->builder.CreateConstGEP2_32(nullptr, aggregate, 0, i);
return llvm->builder.CreateLoad(addr);
}
aggregate->getType()->dump();
return llvm->builder.CreateExtractValue(aggregate, llvm::ArrayRef<unsigned>{i});
}
}
assert(false && "not found required struct field");
return nullptr;
}
llvm::Value*
Advanced::compileFold(const Expression& fold, const std::string& hintRetVar) {
EXPAND_CONTEXT
assert(fold.op == Operator::FOLD);
//initialization:
Symbol varInSymbol = Attachments::get<Symbol>(fold.getOperands()[0]);
Implementation info = Query::queryImplementation(varInSymbol);
Iterator* it = Iterator::create(context, varInSymbol);
llvm::Value* rangeBegin = it->begin();
llvm::Value* rangeEnd = it->end();
llvm::Value* accumInit = scope->process(fold.getOperands()[1]);
std::string varIn = fold.getOperands()[0].getValueString();
std::string varAccum = fold.bindings[1];
std::string varEl = fold.bindings[0];
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold", function->raw);
llvm::BasicBlock *blockLoopBody = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold_body", function->raw);
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold_after", function->raw);
llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm::getGlobalContext(), "fold_next", function->raw);
llvm->builder.CreateBr(blockLoop);
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, varAccum);
accum->addIncoming(accumInit, blockBeforeLoop);
llvm::PHINode *itLoop = llvm->builder.CreatePHI(rangeBegin->getType(), 2, "foldIt");
itLoop->addIncoming(rangeBegin, blockBeforeLoop);
// * loop checks
Value* condRange = llvm->builder.CreateICmpNE(itLoop, rangeEnd);
llvm->builder.CreateCondBr(condRange, blockLoopBody, blockAfterLoop);
// * loop body
llvm->builder.SetInsertPoint(blockLoopBody);
CodeScope* scopeLoop = fold.blocks.front();
compilation::ICodeScopeUnit* loopUnit = function->getScopeUnit(scopeLoop);
Value* elIn = it->get(itLoop);
loopUnit->bindArg(accum, move(varAccum));
loopUnit->bindArg(elIn, move(varEl));
Value* accumNext = loopUnit->compile();
// * Loop saturation checks
bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
llvm::BasicBlock* blockSaturation = llvm->builder.GetInsertBlock();
if (!flagSaturationTriggered){
llvm->builder.CreateBr(blockNext);
}
// * computing next iteration state
llvm->builder.SetInsertPoint(blockNext);
Value *itLoopNext = it->advance(itLoop);
accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
itLoop->addIncoming(itLoopNext, llvm->builder.GetInsertBlock());
llvm->builder.CreateBr(blockLoop);
// * finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
if (!flagSaturationTriggered){
return accum;
}
llvm::PHINode* result = llvm->builder.CreatePHI(accumInit->getType(), 2);
result->addIncoming(accum, blockLoop);
result->addIncoming(accumNext, blockSaturation);
return result;
}
llvm::Value*
Advanced::compileFoldInf(const Expression& fold, const std::string& hintRetVar) {
EXPAND_CONTEXT
assert(fold.op == Operator::FOLD_INF);
std::string accumName = fold.bindings[0];
llvm::Value* accumInit = scope->process(fold.getOperands()[0]);
llvm::BasicBlock *blockBeforeLoop = llvm->builder.GetInsertBlock();
llvm::BasicBlock *blockLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "foldinf", function->raw);
llvm::BasicBlock *blockNext = llvm::BasicBlock::Create(llvm::getGlobalContext(), "foldinf_next", function->raw);
llvm::BasicBlock *blockAfterLoop = llvm::BasicBlock::Create(llvm::getGlobalContext(), "foldinf_post", function->raw);
std::unique_ptr<TransformerSaturation> transformerSaturation(new TransformerSaturation(blockBeforeLoop, context.pass->managerTransformations));
llvm->builder.CreateBr(blockLoop);
// * create phi
llvm->builder.SetInsertPoint(blockLoop);
llvm::PHINode *accum = llvm->builder.CreatePHI(accumInit->getType(), 2, accumName);
accum->addIncoming(accumInit, blockBeforeLoop);
// * loop body
CodeScope* scopeLoop = fold.blocks.front();
compilation::ICodeScopeUnit* unitLoop = function->getScopeUnit(scopeLoop);
unitLoop->bindArg(accum, move(accumName));
Value* accumNext = unitLoop->compile();
// * Loop saturation checks
bool flagSaturationTriggered = transformerSaturation->insertSaturationChecks(blockNext, blockAfterLoop, context);
assert(flagSaturationTriggered);
// * computing next iteration state
llvm->builder.SetInsertPoint(blockNext);
accum->addIncoming(accumNext, llvm->builder.GetInsertBlock());
llvm->builder.CreateBr(blockLoop);
// finalization:
llvm->builder.SetInsertPoint(blockAfterLoop);
return accumNext;
}
llvm::Value*
Advanced::compileIf(const Expression& exprIf, const std::string& hintRetVar) {
EXPAND_CONTEXT
//initialization:
const Expression& condExpr = exprIf.getOperands()[0];
llvm::IRBuilder<>& builder = llvm->builder;
//llvm::Type* tyResultType = llvm->toLLVMType(llvm->ast->expandType(exprIf.type));
llvm::BasicBlock *blockAfter = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifAfter", function->raw);
llvm::BasicBlock *blockTrue = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifTrue", function->raw);
llvm::BasicBlock *blockFalse = llvm::BasicBlock::Create(llvm::getGlobalContext(), "ifFalse", function->raw);
llvm::Value* cond = scope->process(condExpr);
llvm->builder.CreateCondBr(cond, blockTrue, blockFalse);
builder.SetInsertPoint(blockTrue);
CodeScope* scopeTrue = exprIf.blocks.front();
llvm::Value* resultTrue = function->getScopeUnit(scopeTrue)->compile();
blockTrue = builder.GetInsertBlock();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockFalse);
CodeScope* scopeFalse = exprIf.blocks.back();
llvm::Value* resultFalse = function->getScopeUnit(scopeFalse)->compile();
blockFalse = builder.GetInsertBlock();
builder.CreateBr(blockAfter);
builder.SetInsertPoint(blockAfter);
llvm::PHINode *ret = builder.CreatePHI(resultTrue->getType(), 2, NAME("if"));
ret->addIncoming(resultTrue, blockTrue);
ret->addIncoming(resultFalse, blockFalse);
return ret;
}
//TODO Switch: default variant no needed when all possible conditions are considered
llvm::Value*
Advanced::compileSwitch(const Expression& exprSwitch, const std::string& hintRetVar) {
EXPAND_CONTEXT
AST* root = context.pass->man->root;
UNUSED(function);
assert(exprSwitch.operands.size() >= 2);
assert(exprSwitch.operands[1].op == Operator::CASE_DEFAULT && "No default case in Switch Statement");
int countCases = exprSwitch.operands.size() - 1;
llvm::IRBuilder<>& builder = llvm->builder;
llvm::BasicBlock* blockProlog = builder.GetInsertBlock();
llvm::BasicBlock *blockEpilog = llvm::BasicBlock::Create(llvm::getGlobalContext(), "switchAfter", function->raw);
builder.SetInsertPoint(blockEpilog);
llvm::Type* exprSwitchType = llvm->toLLVMType(root->getType(exprSwitch));
llvm::PHINode *ret = builder.CreatePHI(exprSwitchType, countCases, NAME("switch"));
builder.SetInsertPoint(blockProlog);
llvm::Value * conditionSwitch = scope->process(exprSwitch.operands[0]);
llvm::BasicBlock *blockDefault = llvm::BasicBlock::Create(llvm::getGlobalContext(), "caseDefault", function->raw);
llvm::SwitchInst * instructionSwitch = builder.CreateSwitch(conditionSwitch, blockDefault, countCases);
for (int size = exprSwitch.operands.size(), i = 2; i < size; ++i) {
llvm::BasicBlock *blockCase = llvm::BasicBlock::Create(llvm::getGlobalContext(), "case" + std::to_string(i), function->raw);
llvm::Value* condCase = function->getScopeUnit(exprSwitch.operands[i].blocks.front())->compile();
builder.SetInsertPoint(blockCase);
llvm::Value* resultCase = function->getScopeUnit(exprSwitch.operands[i].blocks.back())->compile();
builder.CreateBr(blockEpilog);
ret->addIncoming(resultCase, builder.GetInsertBlock());
builder.SetInsertPoint(blockProlog);
instructionSwitch->addCase(dyn_cast<llvm::ConstantInt>(condCase), blockCase);
}
//compile default block:
builder.SetInsertPoint(blockDefault);
CodeScope* scopeDefault = exprSwitch.operands[1].blocks.front();
llvm::Value* resultDefault = function->getScopeUnit(scopeDefault)->compile();
builder.CreateBr(blockEpilog);
ret->addIncoming(resultDefault, builder.GetInsertBlock());
builder.SetInsertPoint(blockEpilog);
return ret;
}
//TODO recognize cases to make const arrays/stored in global mem/stack alloced.
llvm::Value*
Advanced::compileListAsSolidArray(const Expression &expr, const std::string& hintRetVar) {
EXPAND_CONTEXT
UNUSED(scope);
UNUSED(function);
AST* root = context.pass->man->root;
const size_t& length = expr.getOperands().size();
const Expression& expression = expr;
llvm::Value* zero = ConstantInt::get(tyNum, 0);
llvm::Value* one = ConstantInt::get(tyNum, 1);
ExpandedType typAggrExpanded = root->getType(expression);
assert(typAggrExpanded->__operator == TypeOperator::ARRAY);
llvm::Type* typEl = llvm->toLLVMType(ExpandedType(typAggrExpanded->__operands[0]));
ArrayType* typAggr = (ArrayType*) llvm::ArrayType::get(typEl, length);
llvm::Value* list = llvm->builder.CreateAlloca(typAggr, ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), length, false), hintRetVar);
const std::vector<Expression>& operands = expression.getOperands();
llvm::Value* addrOperand = llvm->builder.CreateGEP(typAggr, list, ArrayRef<Value *>(std::vector<Value*>{zero, zero}));
llvm->builder.CreateStore(scope->process(operands.front()), addrOperand) ;
for (auto i=++operands.begin(); i!=operands.end(); ++i){
addrOperand = llvm->builder.CreateGEP(typEl, addrOperand, ArrayRef<Value *>(std::vector<Value*>{one}));
llvm->builder.CreateStore(scope->process(*i), addrOperand) ;
}
return list;
// Value* listDest = l.builder.CreateAlloca(typList, ConstantInt::get(typI32, __size), *hintRetVar);
// l.buil1der.CreateMemCpy(listDest, listSource, __size, 16);
}
llvm::Value*
Advanced::compileConstantStringAsPChar(const string& data, const std::string& hintRetVar) {
EXPAND_CONTEXT
UNUSED(function);
UNUSED(scope);
Type* typPchar = PointerType::getUnqual(Type::getInt8Ty(llvm::getGlobalContext()));
//ArrayType* typStr = (ArrayType*) (llvm->toLLVMType(ExpandedType(TypeAnnotation(tag_array, TypePrimitive::I8, size+1))));
/*
std::vector<Constant *> chars;
chars.reserve(size+1);
for (size_t i=0; i< size; ++i){
chars[i] = ConstantInt::get(typI8, (unsigned char) data[i]);
}
chars[size] = ConstantInt::get(typI8, 0);
*/
Value* rawData = ConstantDataArray::getString(llvm::getGlobalContext(), data);
Value* rawPtrData = llvm->builder.CreateAlloca(rawData->getType(), ConstantInt::get(Type::getInt32Ty(llvm::getGlobalContext()), 1, false));
llvm->builder.CreateStore(rawData, rawPtrData);
return llvm->builder.CreateCast(llvm::Instruction::BitCast, rawPtrData, typPchar, hintRetVar);
}
diff --git a/cpp/src/compilation/targetinterpretation.cpp b/cpp/src/compilation/targetinterpretation.cpp
index b47498c..a424e37 100644
--- a/cpp/src/compilation/targetinterpretation.cpp
+++ b/cpp/src/compilation/targetinterpretation.cpp
@@ -1,441 +1,495 @@
/*
* File: targetinterpretation.cpp
* Author: pgess
*
* Created on June 29, 2016, 6:45 PM
*/
#include "compilation/targetinterpretation.h"
#include "pass/interpretationpass.h"
+#include "analysis/typeinference.h"
#include "llvmlayer.h"
#include "compilation/scopedecorators.h"
#include <boost/scoped_ptr.hpp>
#include <iostream>
#include <clang/AST/DeclBase.h>
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
//InterpretationScope::compile(const Expression& expression){}
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(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.operands.at(0).getValueString();
+
+
+ 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->overrideBinding(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 = process(expression.operands.at(0));
+
+ const string identCondition = expression.operands.at(0).getValueString();
+ auto scopeCompilation = Decorators<CachedScopeDecoratorTag>::getInterface(context.function->getScopeUnit(scopeResult));
+
+ if(condition.operands.size()){
+ //override value
+ Symbol symbCondition{ScopedSymbol{scopeResult->__identifiers.at(identCondition), versions::VERSION_NONE}, scopeResult};
+ scopeCompilation->overrideDeclaration(symbCondition, Expression(condition.operands.at(0)));
+
+ //set correct type for binding:
+ TypeAnnotation typeVariant = typeinference::getType(condition, *function->man->ast);
+ int conditionIndex = condition.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){
intrBody->reset();
unitBody->reset();
Expression exprElement = elementsInput[i];
intrBody->overrideBinding(exprElement, nameEl);
unitBody->overrideDeclaration(symbEl, move(exprElement));
unitBody->bindArg(rawAccum, string(idAccum));
rawAccum = unitBody->compile();
}
return rawAccum;
}
/*
case FOLD_INF_INTERPRET_INOUT{
}
*/
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){
switch (expression.__state){
case Expression::INVALID:
assert(false);
case Expression::NUMBER:
case Expression::STRING:
return expression;
case Expression::IDENT:{
Symbol s = Attachments::get<Symbol>(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::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::INDEX: {
const Expression& exprKey = process(expression.operands[1]);
const Expression& exprData = process(expression.operands[0]);
if (exprKey.__state == Expression::STRING){
const string& key = exprKey.getValueString();
assert(exprData.__indexBindings.count(key));
return exprData.operands[exprData.__indexBindings.at(key)];
}
if (exprKey.__state == Expression::NUMBER){
int key = exprKey.getValueDouble();
return exprData.operands[key];
}
assert(false);
}
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->overrideBinding(exprInput.getOperands()[i], argEl);
body->overrideBinding(accum, argAccum);
accum = body->processScope();
}
return accum;
}
// 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);
for(size_t i=0, size = args.size(); i<size; ++i) {
body->overrideBinding(args.at(i), string(body->scope->__bindings.at(i)));
}
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);
for(size_t no=0, sigNo=0, size = entry->__bindings.size(); no < size; ++no){
if (functionData.signature.at(no) == INTR_ONLY){
entryIntrp->overrideBinding(signatureInstance.bindings[sigNo], entry->__bindings[no]);
VNameId argId = entry->__identifiers.at(entry->__bindings[no]);
Symbol argSymbol{ScopedSymbol{argId, versions::VERSION_NONE}, entry};
entryUnit->overrideDeclaration(argSymbol, Expression(signatureInstance.bindings[sigNo]));
++sigNo;
}
}
}
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;
}
}}
diff --git a/cpp/src/compilation/targetinterpretation.h b/cpp/src/compilation/targetinterpretation.h
index 3a47bdd..5223763 100644
--- a/cpp/src/compilation/targetinterpretation.h
+++ b/cpp/src/compilation/targetinterpretation.h
@@ -1,130 +1,131 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
/*
* File: targetstatic.h
* Author: pgess
*
* 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"
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{
class InterpretationScope: public compilation::Scope<TargetInterpretation>{
typedef Scope<TargetInterpretation> Parent;
public:
InterpretationScope(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);
};
class InterpretationFunction: public compilation::Function<TargetInterpretation>{
public:
InterpretationFunction(const ManagedFnPtr& function, compilation::Target<TargetInterpretation>* target);
Expression process(const std::vector<Expression>& args);
};
/*
* Partially interpreted function signature
*/
struct PIFSignature{
ManagedFnPtr declaration;
std::vector<Expression> bindings;
};
class PIFunctionUnit;
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);
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);
};
template<class Parent>
class InterpretationScopeDecorator: public Parent{
public:
InterpretationScopeDecorator(CodeScope* 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);
}
};
}} //end of xreate:: interpretation
#endif /* TARGETSTATIC_H */
//transformers:
// template<>
// struct TransformerInfo<TargetInterpretation> {
// static const int id = 1;
// };
\ No newline at end of file
diff --git a/cpp/src/pass/interpretationpass.cpp b/cpp/src/pass/interpretationpass.cpp
index b1bc4d4..09e7ac4 100644
--- a/cpp/src/pass/interpretationpass.cpp
+++ b/cpp/src/pass/interpretationpass.cpp
@@ -1,413 +1,448 @@
/*
* File: interpretationpass.cpp
* Author: pgess
*
* Created on July 5, 2016, 5:21 PM
*/
#include "pass/interpretationpass.h"
//#include "compilation/transformations.h"
#include <compilation/targetinterpretation.h>
+#include <bits/stl_vector.h>
#include "ast.h"
//DEBT implement InterpretationPass purely in clasp
//DEBT represent InterpretationPass as general type inference
using namespace std;
namespace xreate{
template<>
interpretation::InterpretationResolution
defaultValue<interpretation::InterpretationResolution>(){
return interpretation::CMPL_ONLY;
}
namespace interpretation{
enum InterpretationQuery{QUERY_INTR_ONLY, QUERY_CMPL_ONLY};
namespace details {
template<InterpretationQuery FLAG_REQUIRED>
bool checkConstraints(InterpretationResolution flag) {
return ( (flag==INTR_ONLY && FLAG_REQUIRED == QUERY_INTR_ONLY)
|| (flag==CMPL_ONLY && FLAG_REQUIRED == QUERY_CMPL_ONLY));
}
InterpretationResolution
recognizeTags(const map<std::string, Expression>& tags){
auto i = tags.find("interpretation");
if (i== tags.end()){
return ANY;
}
assert(i->second.op == Operator::CALL);
const string& cmd = i->second.operands.at(0).getValueString();
//TODO make consistent names of annotation and resolution
if (cmd == "force"){
return INTR_ONLY;
} else if (cmd == "suppress"){
return CMPL_ONLY;
}
return ANY;
}
}
InterpretationResolution
unify(InterpretationResolution flag) {
return flag;
}
template<typename FLAG_A, typename FLAG_B, typename... FLAGS>
InterpretationResolution
unify(FLAG_A flagA, FLAG_B flagB, FLAGS... flags) {
if (flagA== ANY){
return unify(flagB, flags...);
}
if (flagB == ANY) {
return unify(flagA, flags...);
}
assert(flagA == flagB);
return flagA;
}
template<InterpretationQuery FLAG_REQUIRED>
bool checkConstraints(std::vector<InterpretationResolution>&& flags) {
assert(flags.size());
InterpretationResolution flag = flags.front();
return details::checkConstraints<FLAG_REQUIRED>(flag);
}
template<InterpretationQuery FLAG_REQUIRED_A, InterpretationQuery FLAG_REQUIRED_B, InterpretationQuery... FLAGS>
bool checkConstraints(std::vector<InterpretationResolution>&& flags) {
assert(flags.size());
InterpretationResolution flag = flags.front();
flags.pop_back();
if (details::checkConstraints<FLAG_REQUIRED_A>(flag)){
return checkConstraints<FLAG_REQUIRED_B, FLAGS...>(move(flags));
}
return false;
}
bool
InterpretationData::isDefault() const{
return (resolution == ANY && op == NONE);
}
void
recognizeTags(const Expression& e){
InterpretationData tag{details::recognizeTags(e.tags), NONE};
if (!tag.isDefault())
Attachments::put<InterpretationData>(e, tag);
}
InterpretationResolution
recognizeTags(const ManagedFnPtr& f){
return details::recognizeTags(f->getTags());
}
InterpretationPass::InterpretationPass(PassManager* manager)
: AbstractPass(manager) {
Attachments::init<FunctionInterpretationData>();
Attachments::init<InterpretationData>();
}
void InterpretationPass::run(){
ManagedFnPtr f = man->root->begin<Function>();
auto& visitedSymbols = getSymbolCache();
while (f.isValid()) {
const Symbol& symbolFunction{ScopedSymbol::RetSymbol, f->getEntryScope()};
if (!visitedSymbols.isCached(symbolFunction)){
visitedSymbols.setCachedValue(symbolFunction, process(f));
}
++f;
}
}
InterpretationResolution
InterpretationPass::process(const Expression& expression, PassContext context, const std::string& decl){
recognizeTags(expression);
InterpretationResolution resolution = ANY;
InterpretationOperator op = NONE;
switch (expression.__state){
case Expression::NUMBER:
case Expression::STRING: {
break;
}
case Expression::IDENT: {
resolution = Parent::processSymbol(Attachments::get<Symbol>(expression), context);
break;
}
case Expression::COMPOUND:
break;
default: { resolution = CMPL_ONLY; break;}
}
if (expression.__state == Expression::COMPOUND)
switch(expression.op){
case Operator::EQU:
case Operator::NE: {
InterpretationResolution left = process(expression.operands[0], context);
InterpretationResolution right = process(expression.operands[1], context);
resolution = unify(left, right);
break;
}
case Operator::LOGIC_AND: {
assert(expression.operands.size() == 1);
resolution = process (expression.operands[0], context);
break;
}
case Operator::CALL: {
//TODO cope with static/dynamic context
//TODO BUG here: if several variants they all are processed as CMPL careless of signature
list<ManagedFnPtr> callees = man->root->getFunctionVariants(expression.getValueString());
if (callees.size()!=1){
resolution = CMPL_ONLY;
break;
}
ManagedFnPtr callee = callees.front();
const Symbol& symbCalleeFunc{ScopedSymbol::RetSymbol, callee->getEntryScope()};
//recursion-aware processing:
// - skip self recursion
const Symbol& symbSelfFunc{ScopedSymbol::RetSymbol, context.function->getEntryScope()};
if (!(symbSelfFunc == symbCalleeFunc)){
InterpretationResolution resCallee = processFnCall(callee, context);
assert(resCallee != FUNC_POSTPONED && "Indirect recursion detected: can't decide on interpretation resolution");
resolution = unify(resolution, resCallee);
}
//check arguments compatibility
const FunctionInterpretationData& calleeSignature = FunctionInterpretationHelper::getSignature(callee);
for (size_t op=0, size = expression.operands.size(); op < size; ++op){
const Expression &operand = expression.operands[op];
InterpretationResolution argActual = process(operand, context);
InterpretationResolution argExpected = calleeSignature.signature[op];
//TODO use args unification result to properly process function call
unify(argActual, argExpected);
}
if (FunctionInterpretationHelper::needPartialInterpretation(callee)){
op= CALL_INTERPRET_PARTIAL;
}
break;
}
case Operator::IF:{
InterpretationResolution flagCondition = process(expression.getOperands()[0], context);
InterpretationResolution flagScope1 = Parent::process(expression.blocks.front(), context);
InterpretationResolution flagScope2 = Parent::process(expression.blocks.back(), context);
//special case: IF_INTERPRET_CONDITION
if (checkConstraints<QUERY_INTR_ONLY>({flagCondition})){
op= IF_INTERPRET_CONDITION;
flagCondition = ANY;
}
resolution = unify(flagCondition, flagScope1, flagScope2);
break;
}
case Operator::FOLD: {
InterpretationResolution flagInput = process(expression.getOperands()[0], context);
InterpretationResolution flagAccumInit = process(expression.getOperands()[1], context);
CodeScope* scopeBody = expression.blocks.front();
const std::string& nameEl = expression.bindings[0];
Symbol symbEl{ScopedSymbol{scopeBody->__identifiers.at(nameEl), versions::VERSION_NONE}, scopeBody};
getSymbolCache().setCachedValue(symbEl, InterpretationResolution(flagInput));
const std::string& nameAccum = expression.bindings[1];
Symbol symbAccum{ScopedSymbol{scopeBody->__identifiers.at(nameAccum), versions::VERSION_NONE}, scopeBody};
getSymbolCache().setCachedValue(symbAccum, InterpretationResolution(flagAccumInit));
InterpretationResolution flagBody = Parent::process(expression.blocks.front(), context);
//special case: FOLD_INTERPRET_INPUT
if (checkConstraints<QUERY_INTR_ONLY>({flagInput})){
op= FOLD_INTERPRET_INPUT;
flagInput = ANY;
}
resolution = unify(flagInput, flagAccumInit, flagBody);
break;
}
case Operator::INDEX: {
resolution = unify(
process(expression.operands[0], context),
process(expression.operands[1], context)
);
break;
}
case Operator::SWITCH: {
InterpretationResolution flagCondition = process(expression.operands[0], context);
bool hasDefaultCase = expression.operands[1].op == Operator::CASE_DEFAULT;
//determine conditions resolution
InterpretationResolution flagHeaders = flagCondition;
for (size_t size = expression.operands.size(), i= hasDefaultCase? 2: 1; i<size; ++i){
const Expression& exprCase = expression.operands[i];
flagHeaders = unify(flagHeaders, Parent::process(exprCase.blocks.front(), context));
}
if (checkConstraints<QUERY_INTR_ONLY>({flagHeaders})){
op= SWITCH_INTERPRET_CONDITION;
flagHeaders = ANY;
}
//determine body resolutions
resolution = flagHeaders;
for (size_t size = expression.operands.size(), i= 1; i<size; ++i){
const Expression& exprCase = expression.operands[i];
resolution = unify(resolution, Parent::process(exprCase.blocks.back(), context));
}
break;
}
+ case Operator::SWITCH_VARIANT: {
+ InterpretationResolution resolutionCondition = process(expression.operands.at(0), context);
+ resolution= resolutionCondition;
+
+ if (checkConstraints<QUERY_INTR_ONLY>({resolution})){
+ op= SWITCH_VARIANT;
+ resolution = ANY;
+ }
+
+ const string identCondition = expression.operands.at(0).getValueString();
+ for(auto scope: expression.blocks){
+ //set binding resolution
+ ScopedSymbol symbolInternal = scope->getSymbol(identCondition);
+ getSymbolCache().setCachedValue(Symbol{symbolInternal, scope}, InterpretationResolution(resolutionCondition));
+
+ resolution = unify(resolution, Parent::process(scope, context));
+ }
+
+ for(auto scope: expression.blocks){
+ resolution = unify(resolution, Parent::process(scope, context));
+ }
+ break;
+ }
+
case Operator::LIST:
case Operator::LIST_NAMED: {
for (const Expression &op: expression.getOperands()) {
resolution = unify(resolution, process(op, context));
}
break;
}
+ case Operator::VARIANT: {
+ if(expression.getOperands().size()){
+ resolution = process(expression.getOperands().front(), context);
+ } else {
+ resolution = ANY;
+ }
+
+ break;
+ }
+
default: {
resolution = CMPL_ONLY;
for (const Expression &op: expression.getOperands()) {
process(op, context);
}
for (CodeScope* scope: expression.blocks) {
Parent::process(scope, context);
}
break;
}
}
InterpretationResolution resolutionExpected =
Attachments::get<InterpretationData>(expression, {ANY, NONE}).resolution;
resolution = unify(resolution, resolutionExpected);
if (resolution != resolutionExpected && (op!=NONE || resolution == INTR_ONLY)){
Attachments::put<InterpretationData>(expression, {resolution, op});
}
return resolution;
}
InterpretationResolution
InterpretationPass::processFnCall(ManagedFnPtr function, PassContext context){
return process(function);
}
InterpretationResolution
InterpretationPass::process(ManagedFnPtr function){
CodeScope* entry = function->getEntryScope();
std::vector<std::string> arguments = entry->__bindings;
const Symbol& symbSelfFunc{ScopedSymbol::RetSymbol, function->getEntryScope()};
auto& cache = getSymbolCache();
if (cache.isCached(symbSelfFunc))
return cache.getCachedValue(symbSelfFunc);
const FunctionInterpretationData& fnSignature = FunctionInterpretationHelper::getSignature(function);
InterpretationResolution fnResolutionExpected = details::recognizeTags(function->getTags());
//mark preliminary function resolution as expected
if (fnResolutionExpected != ANY){
cache.setCachedValue(symbSelfFunc, move(fnResolutionExpected));
} else {
// - in order to recognize indirect recursion mark this function resolution as POSTPONED
cache.setCachedValue(symbSelfFunc, FUNC_POSTPONED);
}
//set resolution for function arguments as expected
for (int argNo = 0, size = arguments.size(); argNo< size; ++argNo){
Symbol symbArg{ScopedSymbol{entry->__identifiers.at(arguments[argNo]), versions::VERSION_NONE}, entry};
cache.setCachedValue(symbArg, InterpretationResolution(fnSignature.signature[argNo]));
}
PassContext context;
context.function = function;
context.scope = entry;
InterpretationResolution resActual = process(CodeScope::getDeclaration(symbSelfFunc), context);
resActual = unify(resActual, fnResolutionExpected);
return cache.setCachedValue(symbSelfFunc, move(resActual));
}
const FunctionInterpretationData
FunctionInterpretationHelper::getSignature(ManagedFnPtr function){
if (Attachments::exists<FunctionInterpretationData>(function)){
return Attachments::get<FunctionInterpretationData>(function);
}
FunctionInterpretationData&& data = recognizeSignature(function);
Attachments::put<FunctionInterpretationData>(function, data);
return data;
}
FunctionInterpretationData
FunctionInterpretationHelper::recognizeSignature(ManagedFnPtr function){
CodeScope* entry = function->__entry;
FunctionInterpretationData result;
result.signature.reserve(entry->__bindings.size());
bool flagPartialInterpretation = false;
for(size_t no=0, size=entry->__bindings.size(); no < size; ++no){
const std::string& argName = entry->__bindings[no];
Symbol symbArg{ScopedSymbol{entry->__identifiers.at(argName), versions::VERSION_NONE}, entry};
const Expression& arg = CodeScope::getDeclaration(symbArg);
InterpretationResolution argResolution = details::recognizeTags(arg.tags);
flagPartialInterpretation |= (argResolution == INTR_ONLY);
result.signature.push_back(argResolution);
}
result.flagPartialInterpretation = flagPartialInterpretation;
return result;
}
bool FunctionInterpretationHelper::needPartialInterpretation(ManagedFnPtr function){
const FunctionInterpretationData& data = getSignature(function);
return data.flagPartialInterpretation;
}
}} //end of namespace xreate::interpretation
diff --git a/cpp/src/pass/interpretationpass.h b/cpp/src/pass/interpretationpass.h
index e418055..5a2b229 100644
--- a/cpp/src/pass/interpretationpass.h
+++ b/cpp/src/pass/interpretationpass.h
@@ -1,85 +1,87 @@
/*
* File: interpretationpass.h
* Author: pgess
*
* Created on July 5, 2016, 5:21 PM
*/
#ifndef INTERPRETATIONPASS_H
#define INTERPRETATIONPASS_H
#include "abstractpass.h"
#include <map>
#ifndef FRIENDS_INTERPRETATION_TESTS
#define FRIENDS_INTERPRETATION_TESTS
#endif
+//TODO refactor interpretation. Get rid of InterpretationOperator, put only one operator - Hybrid.
+
namespace xreate{ namespace interpretation{
enum InterpretationResolution{ANY, INTR_ONLY, CMPL_ONLY, FUNC_POSTPONED};
- enum InterpretationOperator{NONE, IF_INTERPRET_CONDITION, FOLD_INTERPRET_INPUT, SWITCH_INTERPRET_CONDITION, CALL_INTERPRET_PARTIAL};
+ enum InterpretationOperator{NONE, IF_INTERPRET_CONDITION, FOLD_INTERPRET_INPUT, SWITCH_INTERPRET_CONDITION, SWITCH_VARIANT, CALL_INTERPRET_PARTIAL};
struct InterpretationData{
InterpretationResolution resolution;
InterpretationOperator op;
bool isDefault() const;
};
struct FunctionInterpretationData{
typedef std::vector<InterpretationResolution> Signature;
Signature signature;
bool flagPartialInterpretation;
};
class FunctionInterpretationHelper {
public:
static const FunctionInterpretationData
getSignature(ManagedFnPtr function);
static bool needPartialInterpretation(ManagedFnPtr function);
private:
static FunctionInterpretationData recognizeSignature(ManagedFnPtr function);
};
class InterpretationPass: public AbstractPass<InterpretationResolution> {
typedef AbstractPass<InterpretationResolution> Parent;
public:
InterpretationResolution process(const Expression& expression, PassContext context, const std::string& varDecl="") override;
InterpretationResolution process(ManagedFnPtr function);
InterpretationResolution processFnCall(ManagedFnPtr function, PassContext context);
InterpretationPass(PassManager* manager);
void run();
};
namespace details {
InterpretationResolution recognizeTags(const std::map<std::string, Expression>& tags);
}
} //end of namespace interpretation
template<>
interpretation::InterpretationResolution
defaultValue<interpretation::InterpretationResolution>();
template<>
struct AttachmentsDict<interpretation::FunctionInterpretationData>
{
typedef interpretation::FunctionInterpretationData Data;
static const unsigned int key = 5;
};
template<>
struct AttachmentsDict<interpretation::InterpretationData>
{
typedef interpretation::InterpretationData Data;
static const unsigned int key = 3;
};
} //end of namespace xreate
#endif /* INTERPRETATIONPASS_H */
diff --git a/cpp/src/query/containers.cpp b/cpp/src/query/containers.cpp
index 1243cff..62a108e 100644
--- a/cpp/src/query/containers.cpp
+++ b/cpp/src/query/containers.cpp
@@ -1,165 +1,167 @@
//
// Created by pgess on 3/14/15.
//
#include <clasplayer.h>
#include "query/containers.h"
using namespace std;
using namespace xreate::containers;
using namespace xreate;
Implementation
Query::queryImplementation(xreate::Symbol const &s) {
if (Attachments::exists<Implementation>(s))
{
return Attachments::get<Implementation>(s);
}
return Implementation::create(s);
}
Query::Query(){
Attachments::init<Implementation>();
}
void
Query::init(ClaspLayer* clasp)
{
if (flagIsDataLoaded) return;
map<Symbol, Symbol> prototypes;
map<Symbol, string> roots;
//read all proto data
auto range = clasp->query(Config::get("containers.id.prototypes"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom) {
auto data = ClaspLayer::parse<SymbolPacked, SymbolPacked>(atom->second);
Symbol root = clasp->unpack(get<0> (data));
Symbol prototype = clasp->unpack(get<1> (data));
prototypes[root] = prototype;
}
// fill implementation data for a data sources:
range = clasp->query(Config::get("containers.id.implementations"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom)
{
auto data = ClaspLayer::parse<SymbolPacked, string>(atom->second);
Symbol var = clasp->unpack(get<0>(data));
string implSerialized = get<1>(data);
//data source, has no prototypes:
if (!prototypes.count(var))
{
Implementation impl = Implementation::create(var);
Attachments::put<Implementation>(var, move(impl));
continue;
}
roots.emplace(move(var), move(implSerialized));
}
//fill implementation data for a cluster roots
for (const pair<Symbol, string> & root: roots)
{
Symbol prototype = prototypes[root.first];
while (prototypes.count(prototype)) {
prototype = prototypes.at(prototype);
}
Attachments::put<Implementation>(root.first, Implementation(Attachments::get<Implementation>(prototype)));
}
// read cluster data and fill implementation data for cluster members
range = clasp->query(Config::get("containers.id.clusters"));
if (range)
for(ClaspLayer::ModelIterator atom = range->first; atom != range->second; ++atom)
{
auto info = ClaspLayer::parse<SymbolPacked, SymbolPacked>(atom->second);
Symbol root = clasp->unpack(get<0>(info));
Symbol child = clasp->unpack(get<1>(info));
if (!(child == root) && (Attachments::exists<Implementation>(root))) {
Implementation rootImpl = Attachments::get<Implementation>(root);
Attachments::put<Implementation>(child, move(rootImpl));
}
}
flagIsDataLoaded = true;
}
//static ImplementationData* create(Symbol var, std::string implSerialized, const ImplementationData* implPrototype);
Implementation
Implementation::create(const Symbol &var)
{
//TODO review implementation determination strategy
Expression varDecl = CodeScope::getDeclaration(var);
switch (varDecl.op)
{
case Operator::LIST_RANGE: {
ImplementationRec<ON_THE_FLY> rec{var};
return {ON_THE_FLY, rec};
}
case Operator::LIST: {
return {SOLID, ImplementationRec<SOLID> {varDecl.getOperands().size()}};
}
default: break;
};
ImplementationLinkedList ill(var);
if (ill){
return ill.getImplementationData();
}
assert(false && "Unable to determine proper implementation for the symbol");
+ return Implementation();
}
Implementation
Implementation::create(const Symbol& var, const std::string& implSerialized)
{
Expression varDecl = CodeScope::getDeclaration(var);
if (implSerialized == Config::get("containers.impl.solid"))
{
return {SOLID, ImplementationRec<SOLID>{varDecl.operands.size()}};
} else if (implSerialized == Config::get("containers.impl.onthefly")) {
return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{var}};
}
assert(false && "unable to determine proper implementation for the symbol");
+ return Implementation();
}
ImplementationLinkedList::ImplementationLinkedList(const Symbol& source)
: flagIsValid(false), s(source){
const Expression& sourceExpr = CodeScope::getDeclaration(source);
if (sourceExpr.tags.count(Config::get("containers.id.linkedlist"))){
flagIsValid = true;
Expression tagLinkedlist = sourceExpr.tags.at(Config::get("containers.id.linkedlist"));
assert(tagLinkedlist.operands.size() == 2);
fieldPointer = tagLinkedlist.operands.at(0).getValueString();
terminator = tagLinkedlist.operands.at(1);
}
}
ImplementationLinkedList:: operator bool () const{
return flagIsValid;
}
Implementation
ImplementationLinkedList::getImplementationData() const {
return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{s}};
}
diff --git a/cpp/src/query/containers.h b/cpp/src/query/containers.h
index 1991f66..b06b486 100644
--- a/cpp/src/query/containers.h
+++ b/cpp/src/query/containers.h
@@ -1,84 +1,84 @@
//
// Created by pgess on 3/14/15.
//
#ifndef _XREATE_CONTAINERSQUERY_H_
#define _XREATE_CONTAINERSQUERY_H_
#include "xreatemanager.h"
#include "clasplayer.h"
#include <boost/variant.hpp>
namespace xreate {
namespace containers {
enum ImplementationType {SOLID, ON_THE_FLY, LINKED_LIST};
template<ImplementationType I>
struct ImplementationRec;
template<>
struct ImplementationRec<SOLID> {
size_t size;
};
template<>
struct ImplementationRec<ON_THE_FLY>{
Symbol source;
};
struct Implementation;
struct ImplementationLinkedList {
bool flagIsValid;
std::string fieldPointer;
Expression terminator;
ImplementationLinkedList(const Symbol& source);
operator bool() const;
Implementation getImplementationData() const;
private:
Symbol s;
};
struct Implementation {
typedef boost::variant<ImplementationRec<SOLID>, ImplementationRec<ON_THE_FLY>> Variant;
- const ImplementationType impl;
+ ImplementationType impl;
Variant data;
static Implementation create(const Symbol &var);
static Implementation create(const Symbol& var, const std::string &implSerialized);
static Implementation create(const Symbol& var, const Implementation& proto);
template<ImplementationType I>
const ImplementationRec<I>& extract() const{
const ImplementationRec<I>& rec = boost::get<ImplementationRec<I>>(data);
return rec;
}
};
class Query : public xreate::IQuery {
public:
static Implementation queryImplementation(xreate::Symbol const &s);
void init(ClaspLayer* clasp);
Query();
~Query(){}
private:
bool flagIsDataLoaded = false;
PassManager *man;
};
}
template<>
struct AttachmentsDict<containers::Implementation> {
typedef containers::Implementation Data;
static const unsigned int key = 1;
};
}
#endif //_XREATE_CONTAINERSQUERY_H_
diff --git a/cpp/tests/ast.cpp b/cpp/tests/ast.cpp
index 193b68a..b6f3514 100644
--- a/cpp/tests/ast.cpp
+++ b/cpp/tests/ast.cpp
@@ -1,69 +1,88 @@
/*
* ast.cpp
*
* Created on: Jun 11, 2015
* Author: pgess
*/
#include "gtest/gtest.h"
#include "xreatemanager.h"
#include "main/Parser.h"
using namespace std;
using namespace xreate;
using namespace xreate::grammar::main;
TEST(AST, Containers1){
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r");
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
assert(!parser.errors->count && "Parser errors");
fclose(input);
}
TEST(AST, InterfacesDataCFA) {
XreateManager* man = XreateManager::prepare
("interface(cfa){\n"
" operator map :: annotation1.\n"
"}");
auto answer = man->root->__interfacesData.equal_range(CFA);
EXPECT_EQ(1, std::distance(answer.first, answer.second));
Expression&& scheme = move(answer.first->second);
EXPECT_EQ(Operator::MAP, scheme.op);
EXPECT_EQ("annotation1", scheme.getOperands().at(0).getValueString());
}
TEST(AST, syntax_recognizeIdentifiers){
XreateManager* man = XreateManager::prepare(R"Code(
test= function(a:: num):: num; entry {
a = b:: int.
b = 8:: int.
a
}
)Code");
}
TEST(AST, syntax_operatorIndex){
XreateManager* man = XreateManager::prepare(R"Code(
test= function(a:: num):: num; entry {
b = a[1].
b
}
)Code");
}
+TEST(AST, Variants_switch){
+XreateManager* man = XreateManager::prepare(R"Code(
+ Color = type variant{Blue, White, Green}.
+
+ main = function:: int {
+ x = White()::Color.
+
+ switch variant(x)::int
+ case (Green) {0}
+ case (White) {1}
+ case (Blue){2}
+ }
+)Code");
+
+ Expression e= man->root->findFunction("main")->getEntryScope()->getBody();
+ ASSERT_EQ(4, e.getOperands().size());
+ ASSERT_EQ(3, e.blocks.size());
+}
+
TEST(AST, DISABLED_InterfacesDataDFA){
}
TEST(AST, DISABLED_InterfacesDataExtern){
}
//TODO xreate.atg: replace all Type<> as ExprAnnotations<>
diff --git a/cpp/tests/compilation.cpp b/cpp/tests/compilation.cpp
index 18b8705..607e408 100644
--- a/cpp/tests/compilation.cpp
+++ b/cpp/tests/compilation.cpp
@@ -1,95 +1,95 @@
#include "xreatemanager.h"
#include "gtest/gtest.h"
using namespace xreate;
//DEBT implement no pkgconfig ways to link libs
//TOTEST FunctionUnit::compileInline
TEST(Compilation, DISABLED_functionInline1){
}
TEST(Compilation, functionEntry1){
std::unique_ptr<XreateManager> program(XreateManager::prepare(
"func1 = function(a:: int):: int {a+8} \
func2 = function::int; entry {12 + func1(4)} \
"));
void* entryPtr = program->run();
int (*entry)() = (int (*)())(intptr_t)entryPtr;
int answer = entry();
ASSERT_EQ(24, answer);
}
TEST(Compilation, full_IFStatementWithVariantType){
XreateManager* man = XreateManager::prepare(
- "Color = type variant (RED, BLUE, GREEN).\n"
+ "Color = type variant {RED, BLUE, GREEN}.\n"
"\n"
" main = function(x::int):: bool; entry {\n"
- " color = if (x == 0 )::Color {RED} else {BLUE}.\n"
- " if (color == BLUE)::bool {true} else {false}\n"
+ " color = if (x == 0 )::Color {RED()} else {BLUE()}.\n"
+ " if (color == BLUE())::bool {true} else {false}\n"
" }"
);
bool (*main)(int) = (bool (*)(int)) man->run();
ASSERT_FALSE(main(0));
ASSERT_TRUE(main(1));
}
TEST(Compilation, full_StructUpdate){
XreateManager* man = XreateManager::prepare(
R"Code(
- Rec = type alias {
+ Rec = type {
a :: int,
b:: int
}.
test= function:: int; entry {
a = {a = 18, b = 20}:: Rec.
b = a + {a = 11}:: Rec.
b["a"]
}
)Code");
int (*main)() = (int (*)()) man->run();
int result = main();
ASSERT_EQ(11, result);
}
TEST(Compilation, AnonymousStruct_init_index){
std::string code =
R"Code(
main = function:: int; entry {
x = {10, 15} :: {int, int}.
x[1]
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
int (*main)() = (int (*)()) man->run();
EXPECT_EQ(15, main());
}
TEST(Compilation, AnonymousStruct_init_update){
std::string code =
R"Code(
main = function:: int; entry {
x = {10, 15} :: {int, int}.
y = x + {6}:: {int, int}.
y[0]
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
int (*main)() = (int (*)()) man->run();
EXPECT_EQ(6, main());
}
diff --git a/cpp/tests/interpretation.cpp b/cpp/tests/interpretation.cpp
index 1eb60fc..5cc7e99 100644
--- a/cpp/tests/interpretation.cpp
+++ b/cpp/tests/interpretation.cpp
@@ -1,384 +1,411 @@
#include "attachments.h"
using namespace xreate;
#include "xreatemanager.h"
#include "compilation/targetinterpretation.h"
#include "gtest/gtest.h"
#include "boost/scoped_ptr.hpp"
//#define FRIENDS_INTERPRETATION_TESTS \
// friend class ::Modules_AST2_Test; \
// friend class ::Modules_Discovery1_Test; \
// friend class ::Modules_Solve1_Test;
#include "pass/interpretationpass.h"
using namespace xreate::grammar::main;
using namespace xreate::interpretation;
TEST(Interpretation, Analysis_StatementIF_1){
XreateManager* man = XreateManager::prepare(
R"Code(
main = function::bool {
x = "a":: string.
y = if (x=="b"):: bool; interpretation(force) {
true
} else {
false
}.
y
}
)Code" );
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
Symbol symbolY{scopeEntry->getSymbol("y"), scopeEntry};
InterpretationData& dataSymbolY = Attachments::get<InterpretationData>(symbolY);
ASSERT_EQ(INTR_ONLY, dataSymbolY.resolution);
}
TEST(Interpretation, Compilation_StatementIF_1){
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"Code(
main = function::int; entry {
x = "a":: string.
y = if (x=="b"):: string; interpretation(force) {
1
} else {
0
}.
y
}
)Code" );
man->analyse();
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(0, result);
}
TEST(Interpretation, Analysis_StatementIF_InterpretCondition_1){
XreateManager* man = XreateManager::prepare(
R"Code(
main = function(x:: int):: int {
comm= "inc":: string; interpretation(force).
y = if (comm == "inc")::int {x+1} else {x}.
y
}
)Code" );
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
CodeScope* scopeEntry = man->root->findFunction("main")->getEntryScope();
Symbol symbolY{scopeEntry->getSymbol("y"), scopeEntry};
InterpretationData& dataSymbolY = Attachments::get<InterpretationData>(symbolY);
ASSERT_EQ(CMPL_ONLY, dataSymbolY.resolution);
ASSERT_EQ(IF_INTERPRET_CONDITION, dataSymbolY.op);
}
TEST(Interpretation, Compilation_StatementIF_InterpretCondition_1){
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"Code(
main = function(x:: int):: int; entry {
comm= "inc":: string; interpretation(force).
y = if (comm == "inc")::int {x+1} else {x}.
y
}
)Code" );
man->analyse();
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
int (*main)(int) = (int (*)(int))man->run();
int result = main(1);
ASSERT_EQ(2, result);
}
TEST(Interpretation, Compilation_StatementFOLD_INTERPRET_INPUT_1){
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"Code(
main = function(x:: int):: int; entry {
commands = ["inc", "double", "dec"]:: [string]; interpretation(force).
loop fold(commands->comm::string, x->operand):: int{
switch(comm)::int
case ("inc"){
operand + 1
}
case ("dec"){
operand - 1
}
case ("double"){
operand * 2
}
}
}
)Code" );
man->analyse();
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
const ManagedFnPtr& funcMain = man->root->findFunction("main");
InterpretationData& dataBody = Attachments::get<InterpretationData>(funcMain);
ASSERT_EQ(FOLD_INTERPRET_INPUT, dataBody.op);
int (*main)(int) = (int (*)(int))man->run();
int result = main(10);
ASSERT_EQ(21, result);
}
TEST(Interpretation, StatementCall_RecursionNo_1){
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"Code(
unwrap = function(data::undef, keys::undef):: undef; interpretation(force){
loop fold(keys->key::string, data->a):: undef {
a[key]
}
}
start = function::num; entry{
result = unwrap(
{
a = {
b =
{
c = "core"
}
}
}, ["a", "b", "c"])::undef.
result == "core"
}
)Code" );
man->analyse();
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(1, result);
}
TEST(Interpretation, StatementCall_RecursionDirect_1){
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"Code(
unwrap = function(data:: X):: Y {
if (data[0] == "a")::Y {0} else {unwrap(data[0])}
}
entry = function:: i8; entry {
unwrap([[[["a"]]]]):: i8; interpretation(force)
}
)Code" );
man->analyse();
InterpretationPass* pass;
if (man->isPassRegistered(PassId::InterpretationPass)){
pass = (InterpretationPass*) man->getPassById(PassId::InterpretationPass);
} else {
pass = new InterpretationPass(man);
pass->run();
}
InterpretationResolution resolutionActual = pass->process(man->root->findFunction("unwrap"));
ASSERT_EQ(ANY, resolutionActual);
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(0, result);
}
TEST(Interpretation, StatementCall_RecursionIndirect_1){
XreateManager* man = XreateManager::prepare(
R"Code(
funcA = function(data:: X):: Y {
if (data == "a")::Y {0} else {funcB(data)}
}
funcB = function(data:: X):: Y {
if (data == "b")::Y {1} else {funcA(data)}
}
entry = function:: i8; entry {
funcA(""):: i8; interpretation(force)
}
)Code" );
InterpretationPass* pass = new InterpretationPass(man);
ASSERT_DEATH(pass->run(), "Indirect recursion detected");
}
TEST(Interpretation, PartialIntr_1){
XreateManager* man = XreateManager::prepare(
R"Code(
evaluate= function(argument:: num, code:: string; interpretation(force)):: num {
switch(code)::int
case ("inc") {argument + 1}
case ("dec") {argument - 1}
case ("double") {argument * 2}
}
main = function::int; entry {
commands= ["inc", "double", "dec"]:: [string]; interpretation(force).
loop fold(commands->comm::string, 10->operand):: int{
evaluate(operand, comm)
}
}
)Code" );
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
ManagedFnPtr fnEvaluate = man->root->findFunction("evaluate");
InterpretationResolution resFnEvaluate= pass->process(fnEvaluate);
ASSERT_EQ(CMPL_ONLY, resFnEvaluate);
ASSERT_TRUE(FunctionInterpretationHelper::needPartialInterpretation(fnEvaluate));
const Expression& exprLoop = man->root->findFunction("main")->__entry->getBody();
Symbol symbCallEv{{0, versions::VERSION_NONE}, exprLoop.blocks.front()};
InterpretationData dataCallEv = Attachments::get<InterpretationData>(symbCallEv);
ASSERT_EQ(CMPL_ONLY, dataCallEv.resolution);
ASSERT_EQ(CALL_INTERPRET_PARTIAL, dataCallEv.op);
}
TEST(Interpretation, Compilation_PartialIntr_2){
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"Code(
evaluate= function(argument:: num, code:: string; interpretation(force)):: num {
switch(code)::int
case ("inc") {argument + 1}
case ("dec") {argument - 1}
case ("double") {argument * 2}
case default {argument}
}
main = function::int; entry {
commands= ["inc", "double", "dec"]:: [string]; interpretation(force).
loop fold(commands->comm::string, 10->operand):: int{
evaluate(operand, comm)
}
}
)Code" );
man->analyse();
if (!man->isPassRegistered(PassId::InterpretationPass)){
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
}
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(21, result);
}
TEST(Interpretation, PartialIntr_3){
xreate::details::tier1::XreateManager* man = xreate::details::tier1::XreateManager::prepare(
R"Code(
- Command= type variant (INC, DEC, DOUBLE).
+ Command= type variant {INC, DEC, DOUBLE}.
evaluate= function(argument:: num, code:: Command; interpretation(force)):: num {
- switch(code)::int
+ switch variant(code)::int
case (INC) {argument + 1}
case (DEC) {argument - 1}
case (DOUBLE) {argument * 2}
- case default {argument}
}
main = function::int; entry {
- commands= [INC, DOUBLE, DEC]:: [Command]; interpretation(force).
+ commands= [INC(), DOUBLE(), DEC()]:: [Command]; interpretation(force).
loop fold(commands->comm::Command, 10->operand):: int{
evaluate(operand, comm)
}
}
)Code" );
man->analyse();
if (!man->isPassRegistered(PassId::InterpretationPass)){
InterpretationPass* pass = new InterpretationPass(man);
pass->run();
}
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(21, result);
}
+TEST(Interpretation, SwitchVariant){
+ xreate::XreateManager* man = xreate::XreateManager::prepare(
+R"Code(
+OneArgument = type{x::int}.
+TWoArgument = type {x::int, y::int}.
+
+Command= type variant {
+ ADD::TwoArguments,
+ DEC:: OneArgument,
+ DOUBLE::OneArgument
+}.
+
+main = function::int; entry{
+ program = ADD({x=2, y=3})::Command; interpretation(force).
+
+ switch variant(program)::int
+ case (ADD) {program["x"]+program["y"]}
+ case (DEC) {1}
+ case (DOUBLE) {2}
+}
+)Code" );
+
+ int (*main)() = (int (*)())man->run();
+ int result = main();
+ ASSERT_EQ(5, result);
+
+}
+
TEST(InterpretationExamples, Regexp1){
FILE* input = fopen("scripts/dsl/regexp.xreate","r");
assert(input != nullptr);
std::unique_ptr<XreateManager> man(XreateManager::prepare(input));
int (*main)() = (int (*)())man->run();
int result = main();
ASSERT_EQ(4, result);
}
//TOTEST call indirect recursion(w/o tags)
//TASk implement and test Loop Inf (fix acc types in coco grammar)
diff --git a/grammar/xreate.ATG b/grammar/xreate.ATG
index bdd885d..11b2fa1 100644
--- a/grammar/xreate.ATG
+++ b/grammar/xreate.ATG
@@ -1,626 +1,639 @@
//TODO add ListLiteral
//TODO ExprTyped: assign default(none) type
#include "ast.h"
#include "ExternLayer.h"
#include "pass/adhocpass.h"
#include <string>
#include <stack>
#define wprintf(format, ...) \
char __buffer[100]; \
wcstombs(__buffer, format, 100); \
fprintf(stderr, __buffer, __VA_ARGS__)
using namespace std;
COMPILER Xreate
details::incomplete::AST* root = nullptr; // current program unit
void ensureInitalizedAST(){
if (root == nullptr) root = new details::incomplete::AST();
}
struct {
std::stack<CodeScope*> scopesOld;
CodeScope* scope = nullptr;
} context;
void pushContextScope(CodeScope* scope){
context.scopesOld.push(context.scope);
context.scope = scope;
}
void popContextScope(){
context.scope = context.scopesOld.top();
context.scopesOld.pop();
}
int nextToken()
{
scanner->ResetPeek();
return scanner->Peek()->kind;
}
bool checkTokenAfterIdent(int key){
if (la->kind != _ident) return false;
return nextToken() == key;
}
bool checkParametersList()
{
return la->kind == _ident && nextToken() == _lparen;
}
bool checkInfix()
{
return la->kind == _ident && nextToken() == _ident;
}
bool checkIndex()
{
return la->kind == _ident && nextToken() == _lbrack;
}
bool checkFuncDecl()
{
if (la->kind != _ident) return false;
int token2 = nextToken();
int token3 = scanner->Peek()->kind;
return token2 == _assign && (token3 == _function || token3 == _pre);
}
bool checkAssignment()
{
if (la->kind != _ident) return false;
scanner->ResetPeek();
int token2 = scanner->Peek()->kind;
if (token2 == _lcurbrack) {
scanner->Peek();
int token3 = scanner->Peek()->kind;
if (token3 != _rcurbrack) return false;
int token4 = scanner->Peek()->kind;
return token4 == _assign;
}
return token2 == _assign;
}
void recognizeIdentifier(Expression& i){
if (!context.scope->recognizeIdentifier(i)){
root->postponeIdentifier(context.scope, i);
}
}
enum SwitchKind{SWITCH_NORMAL, SWITCH_META};
CHARACTERS
letter = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".
any = ANY - '"'.
digit = "0123456789".
cr = '\r'.
lf = '\n'.
tab = '\t'.
TOKENS
ident = (letter | '_') {letter | digit | '_'}.
number = (digit | '-' digit) {digit}.
string = '"' { any } '"'.
function = "function".
pre = "pre".
lparen = '('.
rparen = ')'.
lbrack = '['.
rbrack = ']'.
lcurbrack = '{'.
rcurbrack = '}'.
equal = "==".
assign = '='.
implic = '-' '>'.
colon = ':'.
context = "context".
tagcolon = "::".
lse = "<=".
lss = "<".
gte = ">=".
gtr = ">".
ne1 = "!=".
ne2= "<>".
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
IGNORE cr + lf + tab
PRODUCTIONS
Xreate = (. Function* function; ensureInitalizedAST(); .)
{( RuleDecl
| InterfaceData | Imprt | ContextSection
| IF(checkFuncDecl()) FDecl<function> (. root->add(function); .)
| TDecl
| SkipModulesSection
)} (. .)
.
Ident<std::wstring& name>
= ident (. name = t->val; .).
VarIdent<Expression& e>
= ident (. e = Expression(Atom<Identifier_t>(t->val)); .)
[ lcurbrack (
ident (. SemErr(coco_string_create("var version as ident is not implemented yet")); .)
| number (. Attachments::put<versions::VariableVersion>(e, Atom<Number_t>(t->val).get()); .)
- ) rcurbrack ] .
+ ) rcurbrack ]
+.
FDecl<Function*& f> = (. std::wstring fname; std::wstring argName; TypeAnnotation typIn; TypeAnnotation typOut; bool flagIsPrefunct = false; Expression binding; .)
Ident<fname> assign
[pre (. flagIsPrefunct = true; .)]
function (. f = new Function(fname); f->isPrefunction = flagIsPrefunct; CodeScope* entry = f->getEntryScope(); .)
['(' Ident<argName> tagcolon ExprAnnotations<binding> (. f->addBinding(Atom<Identifier_t>(argName), move(binding)); .)
{',' Ident<argName> tagcolon ExprAnnotations<binding> (. f->addBinding(Atom <Identifier_t>(argName), move(binding));.)
} ')']
[ tagcolon
( IF(flagIsPrefunct) FnTag<f>
| Type<typOut>
)
{';' FnTag<f> }]
BDecl<entry> (. entry->getBody().bindType(move(typOut));.)
.
ContextSection<>= (. Expression context; Function* f; .)
"case" "context" tagcolon MetaSimpExpr<context>
lcurbrack { FDecl<f> (. f->guardContext = context; root->add(f); .)
} rcurbrack.
/**
* TYPES
*
*/
TypeTerm<TypePrimitive& typ> = (. std::wstring tid; .)
("string" (. typ = TypePrimitive::String;.)
| "num" (. typ = TypePrimitive::Num;.)
| "int" (. typ = TypePrimitive::Int;.)
| "float" (. typ = TypePrimitive::Float;.)
| "bool" (. typ = TypePrimitive::Bool; .)
| "i8" (. typ = TypePrimitive::I8; .)
| "i32" (. typ = TypePrimitive::I32; .)
| "i64" (. typ = TypePrimitive::I64; .)
).
Type<TypeAnnotation& typ> = (. TypeAnnotation typ2; TypePrimitive typ3; std::wstring tid, field; .)
(
TList<typ>
| TStruct<typ>
| TVariant<typ>
| TypeTerm<typ3> (. typ = typ3; .)
| IF (checkIndex()) Ident<tid> lbrack
Ident<field> (. typ = TypeAnnotation(TypeOperator::ACCESS, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
{',' Ident<field> (. typ.fields.push_back(Atom<Identifier_t>(field).get()); .)
} rbrack
| Ident<tid> (. typ = TypeAnnotation(TypeOperator::CUSTOM, {}); typ.__valueCustom = Atom<Identifier_t>(tid).get(); .)
['(' Type<typ2> (. typ.__operator = TypeOperator::CALL; typ.__operands.push_back(typ2); .)
{',' Type<typ2> (. typ.__operands.push_back(typ2); .)
} ')']
) .
TList<TypeAnnotation& typ> = (. TypeAnnotation ty; .)
'[' Type<ty> ']' (. typ = TypeAnnotation(TypeOperator::ARRAY, {ty}); .)
.
TStruct<TypeAnnotation& typ> = (. TypeAnnotation t; std::wstring key; size_t keyCounter=0; .)
lcurbrack
(
IF(checkTokenAfterIdent(_tagcolon)) Ident<key> tagcolon Type<t>
| Type<t> (. key = to_wstring(keyCounter++); .)
) (. typ = TypeAnnotation(TypeOperator::STRUCT, {t}); typ.fields.push_back(Atom<Identifier_t>(key).get()); .)
{',' (
IF(checkTokenAfterIdent(_tagcolon)) Ident<key> tagcolon Type<t>
| Type<t> (. key = to_wstring(keyCounter++); .)
) (. typ.__operands.push_back(t); typ.fields.push_back(Atom<Identifier_t>(key).get()); .)
} rcurbrack.
TVariant<TypeAnnotation& typ>= (. TypeAnnotation t, typVoid(TypeOperator::STRUCT, {}); std::vector<TypeAnnotation> operands; std::vector<Atom<Identifier_t>> keys; std::wstring variant; .)
"variant" lcurbrack
Ident<variant> (. t=typVoid; .)
[tagcolon Type<t>] (. keys.push_back(Atom<Identifier_t>(variant)); operands.push_back(t); .)
{',' Ident<variant> (. t=typVoid; .)
[tagcolon Type<t>] (. keys.push_back(Atom<Identifier_t>(variant)); operands.push_back(t); .)
}
rcurbrack (. typ = TypeAnnotation(TypeOperator::VARIANT, {}); typ.__operands = operands; typ.addFields(std::move(keys)); .)
.
TDecl = (. TypeAnnotation t; std::wstring tname, arg; std::vector<Atom<Identifier_t>> args; .)
Ident<tname> assign "type"
['(' Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
{',' Ident<arg> (. args.push_back(Atom<Identifier_t>(arg)); .)
} ')']
Type<t>'.' (. t.addBindings(move(args)); root->add(move(t), Atom<Identifier_t>(tname)); .)
.
ContextDecl<CodeScope * scope> = (. Expression tag; .)
context tagcolon
MetaSimpExpr<tag> (. scope->tags.push_back(tag); .)
{';' MetaSimpExpr<tag> (. scope->tags.push_back(tag); .)
}.
VDecl<CodeScope* f> = (. std::wstring vname; Expression var, value;.)
VarIdent<var> assign ExprTyped<value> (. f->addDeclaration(move(var), move(value)); .)
.
BDecl<CodeScope* scope> = lcurbrack (. Expression body; pushContextScope(scope); .)
{(IF(checkAssignment()) VDecl<scope> '.'
| RuleContextDecl<scope>
| ContextDecl<scope>'.'
| ExprTyped<body> (. scope->setBody(body); .)
)}
rcurbrack (. popContextScope(); .)
.
IfDecl<Expression& e> = (. Expression cond; ManagedScpPtr blockTrue = root->add(new CodeScope(context.scope)); ManagedScpPtr blockFalse = root->add(new CodeScope(context.scope)); .)
"if" '(' Expr<cond> ')' (. e = Expression(Operator::IF, {cond}); .)
tagcolon ExprAnnotations<e>
BDecl<&*blockTrue> "else" BDecl<&*blockFalse> (. e.addBlock(blockTrue); e.addBlock(blockFalse); .)
.
LoopDecl<Expression& e> =
(. Expression eIn, eAcc, eFilters; std::wstring varEl, varAcc, contextClass; Expression tagsEl;
ManagedScpPtr block = root->add(new CodeScope(context.scope)); .)
"loop"
("map" '(' Expr<eIn> implic Ident<varEl> (. e = Expression(Operator::MAP, {eIn}); .)
tagcolon ExprAnnotations<tagsEl> ')' tagcolon ExprAnnotations<e> BDecl<&*block>
(.
e.addBindings({Atom<Identifier_t>(varEl)});
block->addBinding(Atom<Identifier_t>(varEl), move(tagsEl));
e.addBlock(block);
.)
|"fold"
("inf" '(' Expr<eAcc> implic Ident<varAcc> ')'
(.
e = Expression(Operator::FOLD_INF, {eAcc});
e.addBindings({Atom<Identifier_t>(varAcc)});
.)
tagcolon ExprAnnotations<e> BDecl<&*block>
(.
block->addBinding(Atom<Identifier_t>(varAcc), Expression());
e.addBlock(block);
.)
| '(' Expr<eIn> implic Ident<varEl> tagcolon ExprAnnotations<tagsEl> ['|' Expr<eFilters> ] ',' Expr<eAcc> implic Ident<varAcc>')'
(.
e = Expression(Operator::FOLD, {eIn, eAcc});
e.addBindings({Atom<Identifier_t>(varEl), Atom<Identifier_t>(varAcc)});
.)
- tagcolon ExprAnnotations<e> BDecl<&*block>
+ tagcolon ExprAnnotations<e>
(.
-
block->addBinding(Atom<Identifier_t>(varEl), move(tagsEl));
block->addBinding(Atom<Identifier_t>(varAcc), Expression());
- e.addBlock(block);
.)
+ BDecl<&*block>
+ (. e.addBlock(block); .)
)
| "context" '(' string (. contextClass = t->val; .)
')' BDecl<&*block>
(. e = Expression(Operator::LOOP_CONTEXT, {Expression(Atom<String_t>(std::move(contextClass)))});
e.addBlock(block);
.)
).
+// Switches
SwitchDecl<Expression& eSwitch, SwitchKind flagSwitchKind> = (. TypeAnnotation typ; eSwitch = Expression(Operator::SWITCH, {}); Expression eCondition; Expression tag;.)
-["switch"
- ( "ad" "hoc" lparen Expr<eCondition> tagcolon MetaSimpExpr<tag> rparen (. eSwitch.op = Operator::SWITCH_ADHOC;
- eSwitch.operands.push_back(eCondition);
- eSwitch.addTags({tag});
- flagSwitchKind = SWITCH_META; .)
+"switch"
+ (
+ SwitchVariantDecl<eSwitch>
| lparen Expr<eCondition> rparen tagcolon ExprAnnotations<eSwitch> (. eSwitch.operands.push_back(eCondition);.)
- )
-]
- CaseDecl<eSwitch, flagSwitchKind> {CaseDecl<eSwitch, flagSwitchKind>}
+ CaseDecl<eSwitch, flagSwitchKind> {CaseDecl<eSwitch, flagSwitchKind>}
+ )
.
CaseDecl<Expression& outer, SwitchKind flagSwitchKind> = (. ManagedScpPtr scope = root->add(new CodeScope(context.scope)); Expression condition; .)
"case"
( IF(flagSwitchKind == SWITCH_META)
lparen MetaSimpExpr<condition> rparen BDecl<&*scope> (. Expression exprCase(Operator::CASE, {}); exprCase.addTags({condition}); exprCase.addBlock(scope); outer.addArg(move(exprCase));.)
| "default" BDecl<&*scope> (. Expression exprCase(Operator::CASE_DEFAULT, {});
exprCase.addBlock(scope);
outer.operands.insert(++outer.operands.begin(), exprCase); .)
| lparen CaseParams<&*scope> rparen (. ManagedScpPtr scopeBody = root->add(new CodeScope(&*scope)); Expression exprCase(Operator::CASE, {}); .)
BDecl<&*scopeBody> (. exprCase.addBlock(scope); exprCase.addBlock(scopeBody); outer.addArg(move(exprCase)); .)
).
CaseParams<CodeScope* scope> = (. Expression condition; Expression guard(Operator::LOGIC_AND, {}); pushContextScope(scope); .)
ExprTyped<condition> (. guard.addArg(Expression(condition)); .)
{',' ExprTyped<condition> (. guard.addArg(Expression(condition)); .)
} (. scope->setBody(guard); popContextScope(); .)
.
+SwitchVariantDecl<Expression& expr> =
+ (. Expression varTested; expr = Expression(Operator::SWITCH_VARIANT, {}); .)
+
+ "variant" lparen VarIdent<varTested> rparen tagcolon ExprAnnotations<expr>
+ (. recognizeIdentifier(varTested); expr.addArg(std::move(varTested)); .)
+
+ CaseVariantDecl<expr> {CaseVariantDecl<expr>}
+.
+
+CaseVariantDecl<Expression& expr> = (. ManagedScpPtr scope = root->add(new CodeScope(context.scope)); std::wstring key; scope->addBinding(Expression(expr.operands.at(0)), Expression()); .)
+ "case" lparen Ident<key> rparen (. expr.addArg(root->recognizeVariantConstructor(Atom<Identifier_t>(std::move(key)))); .)
+ BDecl<&*scope> (. expr.addBlock(scope); .)
+.
+
IntrinsicDecl<Expression& outer>= (. std::wstring name; .)
"intrinsic" Ident< name> (. outer = Expression(Operator::CALL_INTRINSIC, {}); outer.setValue(Atom<Identifier_t>(name)); .)
lparen [CalleeParams<outer>] rparen .
/*============================ INTERFACES ===============================*/
Imprt<> =
"import" "raw" lparen string (. root->__rawImports.push_back(Atom<String_t>(t->val).get()); .)
rparen '.'.
InterfaceData<> = "interface" '('
( "dfa" ')' InterfaceDFA
| "extern-c" ')' InterfaceExternC
| "cfa" ')' InterfaceCFA
| "adhoc" ')' InterfaceAdhoc
).
InterfaceAdhoc<> =
'{' { PrefunctionSchemeDecl } '}'.
PrefunctionSchemeDecl<> = (. TypeAnnotation typReturn; std::wstring prefName; Expression exprCases; .)
pre function Ident<prefName> tagcolon Type<typReturn>
lcurbrack SwitchDecl<exprCases, SWITCH_META> rcurbrack
(. Expression prefData(Operator::CALL, {Atom<Identifier_t>(prefName), exprCases});
prefData.bindType(typReturn);
root->addInterfaceData(Adhoc, move(prefData));
.).
InterfaceExternC<> = (. ExternData data; .)
'{' {IncludeExternDecl<data> | LibExternDecl<data> } '}'
(. root->addExternData(move(data)); .)
.
LibExternDecl<ExternData& data> = (. std::wstring pkgname, libname; .)
Ident<libname> assign "library" tagcolon "pkgconfig"
'(' string (. pkgname = t->val; .)
')' '.' (. data.addLibrary(Atom<Identifier_t>(libname), Atom<String_t>(pkgname)); .)
.
IncludeExternDecl<ExternData& data> = (. Expression inc; .)
"include" StructLiteral<inc> '.' (. data.addIncludeDecl(move(inc)); .)
.
InterfaceDFA<> = '{' { InstructDecl } '}' .
InstructDecl = (.Operator op; Expression tag;
Expression scheme;
std::vector<Expression>& tags = scheme.operands;
tags.push_back(Expression()); /* return value */ .)
"operator" InstructAlias<op> tagcolon '(' (.scheme.setOp(op); .)
[
MetaSimpExpr<tag> (. tags.push_back(tag); .)
{
',' MetaSimpExpr<tag> (. tags.push_back(tag); .)
}
] ')' [ implic MetaSimpExpr<tag> (. tags[0] = tag; .)
] (. root->addDFAData(move(scheme)); .)
'.'.
InstructAlias<Operator& op> =
(
"map" (. op = Operator::MAP; .)
| "list_range" (. op = Operator::LIST_RANGE; .)
| "list" (. op = Operator::LIST; .)
| "fold" (. op = Operator::FOLD; .)
| "index" (. op = Operator::INDEX; .)
).
InterfaceCFA<> = '{' { InstructCFADecl } '}' .
InstructCFADecl<> = (.Operator op; Expression tag;
Expression scheme;
std::vector<Expression>& tags = scheme.operands; .)
"operator" InstructAlias<op> tagcolon (. scheme.setOp(op); .)
[
MetaSimpExpr<tag> (. tags.push_back(tag); .)
{
',' MetaSimpExpr<tag> (. tags.push_back(tag); .)
}
] '.' (. root->addInterfaceData(CFA, move(scheme)); .).
/*============================ METAPROGRAMMING ===============================*/
// TagsDecl<CodeScope* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
// ':' { MetaSimpExpr<tag> (. /*f.addTag(std::move(tag), mod); */ .)
// }.
FnTag<Function* f> = (. Expression tag; TagModifier mod = TagModifier::NONE; .)
MetaSimpExpr<tag>
['-' TagMod<mod>] (. f->addTag(std::move(tag), mod); .).
TagMod<TagModifier& mod> =
( "assert" (. mod = TagModifier::ASSERT; .)
| "require" (. mod = TagModifier::REQUIRE; .)
).
RuleDecl<> =
"rule" tagcolon (. RuleArguments args; RuleGuards guards; DomainAnnotation typ; std::wstring arg; .)
'(' Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
{',' Ident<arg> tagcolon Domain<typ> (. args.add(arg, typ); .)
} ')'
["case" RGuard<guards> {',' RGuard<guards>}]
'{' RBody<args, guards> '}' .
/* - TODO use RGuard for guards-*/
RuleContextDecl<CodeScope* scope> = (.Expression eHead, eGuards, eBody; .)
"rule" "context" tagcolon MetaSimpExpr<eHead>
"case" lparen MetaSimpExpr<eGuards> rparen
'{' MetaSimpExpr<eBody> '}' (.scope->contextRules.push_back(Expression(Operator::CONTEXT_RULE, {eHead, eGuards, eBody})); .).
Domain<DomainAnnotation& dom> =
(
"function" (. dom = DomainAnnotation::FUNCTION; .)
| "variable" (. dom = DomainAnnotation::VARIABLE; .)
).
RGuard<RuleGuards& guards>= (. Expression e; .)
MetaExpr<e> (. guards.add(std::move(e)); .).
MetaExpr<Expression& e>= (.Operator op; Expression e2; .)
MetaExpr2<e>
[MetaOp<op> MetaExpr2<e2> (. e = Expression(op, {e, e2}); .)
].
MetaExpr2<Expression& e>=
(
'(' MetaExpr<e> ')'
| MetaSimpExpr<e>
).
MetaSimpExpr<Expression& e>= (. std::wstring i1, infix; Expression e2; .)
( '-' MetaSimpExpr<e2> (. e = Expression(Operator::NEG, {e2}); .)
| IF(checkParametersList()) Ident<i1> (. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(i1))}); .)
'(' [ MetaCalleeParams<e> ] ')'
| IF(checkInfix()) Ident<i1> Ident<infix> MetaSimpExpr<e2>
(. e = Expression(Operator::CALL, {Expression(Atom<Identifier_t>(infix))});
e.addArg(Expression(Atom<Identifier_t>(i1)));
e.addArg(std::move(e2));
.)
| Ident<i1> (. e = Expression(Operator::CALL, {Atom<Identifier_t>(i1)}); .)
).
MetaCalleeParams<Expression& e> = (. Expression e2; .)
MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
{',' MetaSimpExpr<e2> (. e.addArg(Expression(e2)); .)
}.
RBody<const RuleArguments& args, const RuleGuards& guards> =
(. Expression e; std::wstring msg; .)
"warning" MetaExpr<e> ["message" string (. msg = t->val; .)
] (. root->add(new RuleWarning(RuleArguments(args), RuleGuards(guards), std::move(e), Atom<String_t>(msg))); .)
.
MetaOp< Operator& op> =
implic (. op = Operator::IMPL; .)
.
/*============================ Expressions ===============================*/
ExprAnnotations<Expression& e> = (. TypeAnnotation typ; std::list<Expression> tags; Expression tag; e.tags.clear();.)
Type<typ> (. e.bindType(move(typ)); .)
{';' MetaSimpExpr<tag> (. tags.push_back(tag); .)
} (. e.addTags(tags); .)
.
ExprTyped<Expression&e> = Expr<e> [tagcolon ExprAnnotations<e>].
Expr< Expression& e> (. Operator op; Expression e2; .)
= ExprArithmAdd<e>
[ RelOp<op>
ExprArithmAdd<e2> (. e = Expression(op, {e, e2}); .)
].
ExprArithmAdd< Expression& e>= (. Operator op; Expression e2; .)
ExprArithmMul< e>
[ AddOp< op>
ExprArithmAdd< e2> (. e = Expression(op, {e, e2});.)
].
ExprArithmMul< Expression& e> (. Operator op; Expression e2; .)
= ExprPostfix< e>
[ MulOp< op>
ExprArithmMul< e2> (. e = Expression(op, {e, e2}); .)
].
ExprPostfix<Expression& e>
= Term<e>
[lbrack (. e = Expression(Operator::INDEX, {e}); .)
CalleeParams<e> rbrack
].
Term< Expression& e> (. std::wstring name; e = Expression(); .)
=
(IF (checkParametersList()) Ident< name>
(. e = Expression(Operator::CALL, {Atom<Identifier_t>(name)}); root->recognizeVariantConstructor(e); .)
'(' [CalleeParams<e>] ')'
| VarIdent<e> (. recognizeIdentifier(e); .)
| ListLiteral<e> (. /* tuple */.)
| StructLiteral<e> (. /* struct */.)
| LoopDecl<e>
| IfDecl<e>
| SwitchDecl<e, SWITCH_NORMAL>
| AdhocDecl<e>
| IntrinsicDecl<e>
| number (. e = Expression(Atom<Number_t>(t->val)); .)
| string (. e = Expression(Atom<String_t>(t->val)); .)
| "true" (. e = Expression(Atom<Number_t>(1)); e.bindType(TypePrimitive::Bool); .)
| "false" (. e = Expression(Atom<Number_t>(0)); e.bindType(TypePrimitive::Bool); .)
| '-' Term<e> (. e = Expression(Operator::NEG, {e}); .)
| '(' ExprTyped<e> ')'
).
StructLiteral<Expression& e> = (. std::wstring key; Expression val; std::list<Atom<Identifier_t>> keys; size_t keyCounter=0; .)
lcurbrack
(IF(checkTokenAfterIdent(_assign)) Ident<key> '=' Expr<val>
| Expr<val> (. key = to_wstring(keyCounter++); .)
) (. keys.push_back(Atom<Identifier_t>(key)); e = Expression(Operator::LIST_NAMED, {val}); .)
{',' (IF(checkTokenAfterIdent(_assign)) Ident<key> '=' Expr<val>
| Expr<val> (. key = to_wstring(keyCounter++); .)
) (. e.addArg(Expression(val)); keys.push_back(Atom<Identifier_t>(key)); .)
} rcurbrack (. e.addBindings(keys.begin(), keys.end()); .)
.
ListLiteral<Expression& e> = (. Expression eFrom, eTo; .)
'['
[ Expr<eFrom> (. e.addArg(Expression(eFrom)); .)
(".." Expr<eTo> (. e.addArg(Expression(eTo)); e.setOp(Operator::LIST_RANGE); .)
|{',' Expr<eFrom> (. e.addArg(Expression(eFrom)); .)
} (. e.setOp(Operator::LIST); .)
) ] ']'.
AdhocDecl<Expression& e> = (. Expression command; .)
"ad" "hoc" MetaSimpExpr<command> (. adhoc::AdhocExpression exprAdhoc; exprAdhoc.setCommand(command); e = exprAdhoc; .).
CalleeParams<Expression& e> = (. Expression e2; .)
ExprTyped<e2> (. e.addArg(Expression(e2)); .)
{',' ExprTyped<e2> (. e.addArg(Expression(e2)); .)
}.
AddOp< Operator& op>
= (. op = Operator::ADD; .)
( '+'
| '-' (. op = Operator::SUB; .)
).
MulOp< Operator& op>
= (. op = Operator::MUL; .)
( '*'
| '/' (. op = Operator::DIV; .)
).
RelOp< Operator& op>
= (. op = Operator::EQU; .)
( equal
| (ne1 | ne2) (. op = Operator::NE; .)
| lse (. op = Operator::LSE; .)
| lss (. op = Operator::LSS; .)
| gte (. op = Operator::GTE; .)
| gtr (. op = Operator::GTR; .)
).
SkipModulesSection = "module" '{' {ANY} '}'.
END Xreate.
diff --git a/scripts/dsl/regexp.xreate b/scripts/dsl/regexp.xreate
index a313ccb..11d7299 100644
--- a/scripts/dsl/regexp.xreate
+++ b/scripts/dsl/regexp.xreate
@@ -1,72 +1,72 @@
interface(extern-c){
xml2 = library:: pkgconfig("libxml-2.0").
include {
xml2 = ["string.h"]
}.
}
-Matcher = type variant (Sequence, ZeroOrMore, Text).
+Matcher = type variant {Sequence, ZeroOrMore, Text}.
matchText = function(text::string, matcher::string, posStart::i64):: i64 {
textLength = strlen(text):: i64.
matcherLength = strlen(matcher):: i64.
if(textLength >= posStart + matcherLength):: i64{
if(strncmp(text + posStart, matcher, matcherLength) == 0):: i64 {
matcherLength
} else {-1:: i64}
} else {-2:: i64}
}
matchSequence = function(text::string, pattern::undef; interpretation(force), posStart::i64):: i64; interpretation(suppress){
textLength = length(text):: i64.
loop fold(pattern-> matcher:: undef, posStart->pos):: i64{
recognizedSymbols = match(text, matcher, pos):: i64.
if (recognizedSymbols > 0):: i64{
pos+recognizedSymbols
} else {
pos:: i64; break
}
}
}
matchZeroOrMore= function(text::string, matcher::undef; interpretation(force), posStart::i64):: i64; interpretation(suppress){
textLength = length(text):: i64.
loop fold inf(posStart->pos):: i64{
recognizedSymbols = match(text, matcher, pos):: i64.
if (recognizedSymbols > 0):: i64{
pos+recognizedSymbols
} else {
pos:: i64; break
}
}
}
match = function(text::string, pattern::undef; interpretation(force), posStart::i64)::i64; interpretation(suppress){
- switch (pattern[0]) :: int
+ key= pattern[0]::Matcher.
+ switch variant(key) :: int
case (Sequence) {matchSequence(text, pattern[1], posStart)}
case (ZeroOrMore) {matchZeroOrMore(text, pattern[1], posStart)}
case (Text) {matchText(text, pattern[1], posStart)}
- case default {-1}
}
main = function:: i64; entry {
patternAB =
- [Sequence,
- [[ZeroOrMore, [Text, "a"]],
- [Text, "b"]]] :: undef; interpretation(force).
+ [Sequence(),
+ [[ZeroOrMore(), [Text(), "a"]],
+ [Text(), "b"]]] :: undef; interpretation(force).
// matchers = ["The ", "only ", "way "] :: [string]; interpretation(force).
match("aaab", patternAB, 0):: i64
}
Event Timeline
Log In to Comment