No OneTemporary

File Metadata

Created
Sun, Feb 15, 7:49 PM
diff --git a/config/default.json b/config/default.json
index baf997f..a4c45db 100644
--- a/config/default.json
+++ b/config/default.json
@@ -1,74 +1,74 @@
{
"containers": {
"id": {
"implementations": "containers_impl",
"linkedlist": "linkedlist"
},
"impl": {
"solid": "solid",
- "onthefly": "on_the_fly"
+ "onthefly": "onthefly"
}
},
"logging": {
"id": "logging"
},
"function-entry": "entry",
"transcend": {
"bindings" : {
"variable": "bind",
"function": "bind_func",
"scope": "bind_scope",
"function_demand" : "bind_function_demand",
"scope_decision": "bind_scope_decision"
},
"context" : {
"decisions":{
"dependent": "resolution_dependency"
}
},
"nonevalue": "nonevalue",
"ret": {
"symbol": "retv",
"tag": "ret"
}
},
"tests": {
"template": "troubleshooting",
"templates": {
- "troubleshooting":"Virtualization.Doc_*:Exploitation.Doc_*:Communication.Doc_*",
- "documentation":"Modules.Doc_*:Interpretation.Doc_*:AST.Doc_*:Loop.Doc_*:LateReasoning.Doc_*:Latex.Doc_*:Polymorphs.Doc_*:Transcend.Doc_*:ASTCorrespondence.Doc_*:Virtualization.Doc_*:Exploitation.Doc_*:Communication.Doc_*",
+ "troubleshooting":"*.Doc_*:-Latex.*",
+ "documentation":"Modules.Doc_*:Modules_API.Doc_*:Interpretation.Doc_*:AST.Doc_*:Loop.Doc_*:LateReasoning.Doc_*:Latex.Doc_*:Polymorphs.Doc_*:Transcend.Doc_*:ASTCorrespondence.Doc_*:Virtualization.Doc_*:Exploitation.Doc_*:Communication.Doc_*:Introduction.*",
"default": "*",
"ast": "AST.*",
"effects": "Effects.*",
"basic": "Attachments.*",
"compilation": "Compilation.*",
"communication": "Communication.*",
"cfa": "CFA.*",
"containers": "Containers.*",
"dfa": "DFA.*",
"diagnostic": "Diagnostic.*",
"dsl": "Association.*:Interpretation.*",
"exploitation": "Exploitation.*",
"ExpressionSerializer": "ExpressionSerializer.*",
"externc": "InterfaceExternC.*",
"loops": "Loop.*",
"latereasoning": "LateReasoning.*",
"latex": "Latex.*",
"modules": "Modules.*",
"polymorphs": "Polymorphs.*",
"intrinsic-query": "Types.SlaveTypes*:Association.TypedQuery*",
"types": "Types.*",
"virtualization": "Virtualization.*",
"vendorsAPI/clang": "ClangAPI.*",
"vendorsAPI/xml2": "libxml2.*"
}
}
}
diff --git a/cpp/src/pass/compilepass.cpp b/cpp/src/pass/compilepass.cpp
index a101e3b..7cf3994 100644
--- a/cpp/src/pass/compilepass.cpp
+++ b/cpp/src/pass/compilepass.cpp
@@ -1,771 +1,775 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* compilepass.cpp
*/
/**
* \file compilepass.h
* \brief Compilation pass
*/
#include "compilepass.h"
#include "transcendlayer.h"
#include <ast.h>
#include "llvmlayer.h"
#include "query/containers.h"
#include "compilation/containers.h"
#include "ExternLayer.h"
#include "compilation/targetinterpretation.h"
#include "pass/versionspass.h"
#include "compilation/scopedecorators.h"
#include "compilation/operators.h"
#include "compilation/latex.h"
#include "analysis/typeinference.h"
#include <boost/optional.hpp>
#include <memory>
#include <iostream>
using namespace std;
using namespace llvm;
namespace xreate{
namespace compilation{
std::string
BasicFunctionUnit::prepareName() {
AST* ast = IFunctionUnit::pass->man->root;
string name = ast->getFunctionSpecializations(IFunctionUnit::function->__name).size() > 1 ?
IFunctionUnit::function->__name + std::to_string(IFunctionUnit::function.id()) :
IFunctionUnit::function->__name;
return name;
}
std::vector<llvm::Type*>
BasicFunctionUnit::prepareSignature() {
LLVMLayer* llvm = IFunctionUnit::pass->man->llvm;
AST* ast = IFunctionUnit::pass->man->root;
CodeScope* entry = IFunctionUnit::function->__entry;
std::vector<llvm::Type*> signature;
std::transform(entry->__bindings.begin(), entry->__bindings.end(), std::inserter(signature, signature.end()),
[llvm, ast, entry](const std::string & arg)->llvm::Type* {
assert(entry->__identifiers.count(arg));
ScopedSymbol argid{entry->__identifiers.at(arg), versions::VERSION_NONE};
return llvm->toLLVMType(ast->expandType(entry->__declarations.at(argid).type));
});
return signature;
}
llvm::Type*
BasicFunctionUnit::prepareResult() {
LLVMLayer* llvm = IFunctionUnit::pass->man->llvm;
AST* ast = IFunctionUnit::pass->man->root;
CodeScope* entry = IFunctionUnit::function->__entry;
return llvm->toLLVMType(ast->expandType(entry->__declarations.at(ScopedSymbol::RetSymbol).type));
}
llvm::Function::arg_iterator
BasicFunctionUnit::prepareBindings() {
CodeScope* entry = IFunctionUnit::function->__entry;
ICodeScopeUnit* entryCompilation = IFunctionUnit::getScopeUnit(entry);
llvm::Function::arg_iterator fargsI = IFunctionUnit::raw->arg_begin();
for (std::string &arg : entry->__bindings) {
ScopedSymbol argid{entry->__identifiers[arg], versions::VERSION_NONE};
entryCompilation->bindArg(&*fargsI, argid);
fargsI->setName(arg);
++fargsI;
}
return fargsI;
}
//DEBT compiler rigidly depends on exact definition of DefaultFunctionUnit
typedef latex::LatexBruteFunctionDecorator<
compilation::BasicFunctionUnit>
BruteFunctionDefault;
ICodeScopeUnit::ICodeScopeUnit(const CodeScope * const codeScope, IFunctionUnit* f, CompilePass* compilePass)
: pass(compilePass), function(f), scope(codeScope), currentBlockRaw(nullptr) { }
llvm::Value*
BruteFnInvocation::operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
llvm::Function* calleeInfo = dyn_cast<llvm::Function>(__callee);
if (calleeInfo) {
auto argsFormal = calleeInfo->args();
size_t sizeArgsF = std::distance(argsFormal.begin(), argsFormal.end());
assert(args.size() >= sizeArgsF);
assert(calleeInfo->isVarArg() || args.size() == sizeArgsF);
auto argFormal = argsFormal.begin();
for(size_t argId = 0; argId < args.size(); ++argId){
if(argFormal != argsFormal.end()){
args[argId] = typeinference::doAutomaticTypeConversion(
args.at(argId), argFormal->getType(), llvm->builder);
++argFormal;
}
}
}
//Do not name function call that returns Void.
std::string nameStatement = hintDecl;
if (calleeInfo->getReturnType()->isVoidTy()) {
nameStatement.clear();
}
return llvm->builder.CreateCall(__calleeTy, __callee, args, nameStatement);
}
//DESABLEDFEATURE implement inlining
class CallStatementInline : public IFnInvocation{
public:
CallStatementInline(IFunctionUnit* caller, IFunctionUnit* callee, LLVMLayer* l)
: __caller(caller), __callee(callee), llvm(l) { }
llvm::Value* operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
//TOTEST inlining
// CodeScopeUnit* entryCompilation = outer->getScopeUnit(function->__entry);
// for(int i=0, size = args.size(); i<size; ++i) {
// entryCompilation->bindArg(args.at(i), string(entryCompilation->scope->__bindings.at(i)));
// }
//
//
// return entryCompilation->compile();
return nullptr;
}
private:
IFunctionUnit* __caller;
IFunctionUnit* __callee;
LLVMLayer* llvm;
bool
isInline() {
// Symbol ret = Symbol{0, function->__entry};
// bool flagOnTheFly = SymbolAttachments::get<IsImplementationOnTheFly>(ret, false);
//TODO consider inlining
return false;
}
} ;
BasicCodeScopeUnit::BasicCodeScopeUnit(const CodeScope * const codeScope, IFunctionUnit* f, CompilePass* compilePass)
: ICodeScopeUnit(codeScope, f, compilePass) { }
llvm::Value*
BasicCodeScopeUnit::processSymbol(const Symbol& s, std::string hintRetVar) {
Expression declaration = CodeScope::getDefinition(s);
const CodeScope* scopeExternal = s.scope;
ICodeScopeUnit* scopeBruteExternal = ICodeScopeUnit::function->getScopeUnit(scopeExternal);
assert(scopeBruteExternal->currentBlockRaw);
llvm::Value* resultRaw;
llvm::BasicBlock* blockOwn = pass->man->llvm->builder.GetInsertBlock();
if (scopeBruteExternal->currentBlockRaw == blockOwn) {
resultRaw = scopeBruteExternal->process(declaration, hintRetVar);
scopeBruteExternal->currentBlockRaw = currentBlockRaw =
pass->man->llvm->builder.GetInsertBlock();
} else {
pass->man->llvm->builder.SetInsertPoint(scopeBruteExternal->currentBlockRaw);
resultRaw = scopeBruteExternal->processSymbol(s, hintRetVar);
pass->man->llvm->builder.SetInsertPoint(blockOwn);
}
return resultRaw;
}
IFnInvocation*
BasicCodeScopeUnit::findFunction(const Expression& opCall) {
const std::string& calleeName = opCall.getValueString();
LLVMLayer* llvm = pass->man->llvm;
const std::list<ManagedFnPtr>& specializations = pass->man->root->getFunctionSpecializations(calleeName);
//if no specializations registered - check external function
if (specializations.size() == 0) {
llvm::Function* external = llvm->layerExtern->lookupFunction(calleeName);
llvm::outs() << "Debug/External function: " << calleeName;
external->getType()->print(llvm::outs(), true);
llvm::outs() << "\n";
return new BruteFnInvocation(external, llvm);
}
//There should be only one specialization without any valid guards at this point
return new BruteFnInvocation(pass->getFunctionUnit(
pass->man->root->findFunction(calleeName))->compile(),
llvm);
}
//DISABLEDFEATURE transformations
// if (pass->transformations->isAcceptable(expr)){
// return pass->transformations->transform(expr, result, ctx);
// }
llvm::Value*
BasicCodeScopeUnit::process(const Expression& expr, const std::string& hintVarDecl) {
#define DEFAULT(x) (hintVarDecl.empty()? x: hintVarDecl)
llvm::Value *left;
llvm::Value *right;
LLVMLayer& l = *pass->man->llvm;
xreate::compilation::AdvancedInstructions instructions = xreate::compilation::AdvancedInstructions({this, function, pass});
switch (expr.op) {
case Operator::SUB: case Operator::MUL:
case Operator::DIV: case Operator::EQU: case Operator::LSS:
case Operator::GTR: case Operator::NE: case Operator::LSE:
case Operator::GTE:
assert(expr.__state == Expression::COMPOUND);
assert(expr.operands.size() == 2);
left = process(expr.operands[0]);
right = process(expr.operands[1]);
break;
default:;
}
switch (expr.op) {
case Operator::ADD:
{
left = process(expr.operands[0]);
Context context{this, function, pass};
llvm::Value* resultSU = StructUpdate::add(expr.operands[0], left, expr.operands[1], context, DEFAULT("tmp_add"));
if (resultSU) return resultSU;
right = process(expr.operands[1]);
llvm::Value* resultAddPA = pointerarithmetic::PointerArithmetic::add(left, right, context, DEFAULT("tmp_add"));
if (resultAddPA) {
return resultAddPA;
}
return l.builder.CreateAdd(left, right, DEFAULT("tmp_add"));
break;
}
case Operator::SUB:
return l.builder.CreateSub(left, right, DEFAULT("tmp_sub"));
break;
case Operator::MUL:
return l.builder.CreateMul(left, right, DEFAULT("tmp_mul"));
break;
case Operator::DIV:
- return l.builder.CreateSDiv(left, right, DEFAULT("tmp_div"));
+ if (left->getType()->isIntegerTy()) return l.builder.CreateSDiv(left, right, DEFAULT("tmp_div"));
+ if (left->getType()->isFloatingPointTy()) return l.builder.CreateFDiv(left, right, DEFAULT("tmp_div"));
break;
case Operator::EQU: {
if (left->getType()->isIntegerTy()) return l.builder.CreateICmpEQ(left, right, DEFAULT("tmp_equ"));
if (left->getType()->isFloatingPointTy()) return l.builder.CreateFCmpOEQ(left, right, DEFAULT("tmp_equ"));
const ExpandedType& leftT = pass->man->root->getType(expr.operands[0]);
const ExpandedType& rightT = pass->man->root->getType(expr.operands[0]);
if(leftT->__operator == TypeOperator::VARIANT && rightT->__operator == TypeOperator::VARIANT){
llvm::Type* selectorT = llvm::cast<llvm::StructType>(left->getType())->getElementType(0);
llvm::Value* leftUnwapped = typeinference::doAutomaticTypeConversion(left, selectorT, l.builder);
llvm::Value* rightUnwapped = typeinference::doAutomaticTypeConversion(right, selectorT, l.builder);
return l.builder.CreateICmpEQ(leftUnwapped, rightUnwapped, DEFAULT("tmp_equ"));
}
break;
}
case Operator::NE:
return l.builder.CreateICmpNE(left, right, DEFAULT("tmp_ne"));
break;
case Operator::LSS:
return l.builder.CreateICmpSLT(left, right, DEFAULT("tmp_lss"));
break;
case Operator::LSE:
return l.builder.CreateICmpSLE(left, right, DEFAULT("tmp_lse"));
break;
case Operator::GTR:
return l.builder.CreateICmpSGT(left, right, DEFAULT("tmp_gtr"));
break;
case Operator::GTE:
return l.builder.CreateICmpSGE(left, right, DEFAULT("tmp_gte"));
break;
case Operator::NEG:
left = process(expr.operands[0]);
return l.builder.CreateNeg(left, DEFAULT("tmp_neg"));
break;
case Operator::CALL:
{
assert(expr.__state == Expression::COMPOUND);
shared_ptr<IFnInvocation> callee(findFunction(expr));
const std::string& nameCallee = expr.getValueString();
//prepare arguments
std::vector<llvm::Value *> args;
args.reserve(expr.operands.size());
std::transform(expr.operands.begin(), expr.operands.end(), std::inserter(args, args.end()),
[this](const Expression & operand) {
return process(operand);
}
);
return (*callee)(move(args), DEFAULT("res_" + nameCallee));
}
case Operator::IF:
{
return instructions.compileIf(expr, DEFAULT("tmp_if"));
}
case Operator::SWITCH:
{
return instructions.compileSwitch(expr, DEFAULT("tmp_switch"));
}
case Operator::LOGIC_AND:
{
assert(expr.operands.size() == 1);
return process(expr.operands[0]);
}
case Operator::LIST:
{
ExpandedType exprT = l.ast->getType(expr);
bool flagIsArray;
do {
if (exprT->__operator == TypeOperator::CUSTOM){
if (l.layerExtern->isArrayType(exprT->__valueCustom)){
flagIsArray = true;
break;
}
if (l.layerExtern->isRecordType(exprT->__valueCustom)){
flagIsArray = false;
break;
}
assert(false && "Inapproriate external type");
}
if (exprT->__operator != TypeOperator::LIST_ARRAY && exprT->__operator != TypeOperator::LIST_RECORD){
assert(false && "Inapproriate type");
}
flagIsArray = exprT->__operator == TypeOperator::LIST_ARRAY;
} while(false);
if(flagIsArray){
return instructions.compileListAsSolidArray(expr, DEFAULT("tmp_list"));
}
const std::vector<string> fieldsFormal = (exprT.get().__operator == TypeOperator::CUSTOM) ?
l.layerExtern->getStructFields(l.layerExtern->lookupType(exprT.get().__valueCustom))
: exprT.get().fields;
std::map<std::string, size_t> indexFields;
for (size_t i = 0, size = fieldsFormal.size(); i < size; ++i) {
indexFields.emplace(fieldsFormal[i], i);
}
llvm::StructType* tyLiteralRaw = llvm::cast<llvm::StructType>(l.toLLVMType(exprT));
llvm::Value* record = llvm::UndefValue::get(tyLiteralRaw);
for (size_t i = 0; i < expr.operands.size(); ++i) {
const Expression& operand = expr.operands.at(i);
unsigned int fieldId = indexFields.at(expr.bindings.at(i));
llvm::Value* result = process(operand);
assert(result);
record = l.builder.CreateInsertValue(record, result, llvm::ArrayRef<unsigned>({fieldId}));
}
return record;
};
case Operator::LIST_RANGE:
{
assert(false); //no compilation phase for a range list
// return InstructionList(this).compileConstantArray(expr, l, hintRetVar);
};
case Operator::MAP:
{
assert(expr.blocks.size());
return instructions.compileMapSolidOutput(expr, DEFAULT("map"));
};
case Operator::FOLD:
{
return instructions.compileFold(expr, DEFAULT("fold"));
};
case Operator::INF:
{
return instructions.compileFoldInf(expr, DEFAULT("fold"));
};
case Operator::INDEX:
{
//TASK allow multiindex compilation
assert(expr.operands.size() == 2);
assert(expr.operands[0].__state == Expression::IDENT);
const std::string& hintIdent = expr.operands[0].getValueString();
Symbol s = Attachments::get<IdentifierSymbol>(expr.operands[0]);
const ExpandedType& t2 = pass->man->root->getType(expr.operands[0]);
llvm::Value* aggr = processSymbol(s, hintIdent);
switch (t2.get().__operator) {
case TypeOperator::LIST_RECORD: case TypeOperator::CUSTOM:
{
std::string idxField;
const Expression& idx = expr.operands.at(1);
switch (idx.__state) {
//named struct field
case Expression::STRING:
idxField = idx.getValueString();
break;
//anonymous struct field
case Expression::NUMBER:
idxField = to_string((int) idx.getValueDouble());
break;
default:
assert(false && "Wrong index for a struct");
}
return instructions.compileStructIndex(aggr, t2, idxField);
};
case TypeOperator::LIST_ARRAY:
{
std::vector<llvm::Value*> indexes;
std::transform(++expr.operands.begin(), expr.operands.end(), std::inserter(indexes, indexes.end()),
[this] (const Expression & op) {
return process(op);
}
);
return instructions.compileArrayIndex(aggr, indexes, DEFAULT(string("el_") + hintIdent));
};
default:
assert(false);
}
};
case Operator::CALL_INTRINSIC:
{
const std::string op = expr.getValueString();
if (op == "copy") {
llvm::Value* result = process(expr.getOperands().at(0));
auto decoratorVersions = Decorators<VersionsScopeDecoratorTag>::getInterface(this);
llvm::Value* storage = decoratorVersions->processIntrinsicInit(result->getType());
decoratorVersions->processIntrinsicCopy(result, storage);
return l.builder.CreateLoad(storage, hintVarDecl);
}
assert(false && "undefined intrinsic");
}
case Operator::QUERY:
case Operator::QUERY_LATE:
{
assert(false && "Should be processed by interpretation");
}
case Operator::VARIANT:
{
const ExpandedType& typVariant = pass->man->root->getType(expr);
llvm::Type* typVariantRaw = l.toLLVMType(typVariant);
llvm::Type* typIdRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(0);
uint64_t id = expr.getValueDouble();
llvm::Value* variantRaw = llvm::UndefValue::get(typVariantRaw);
variantRaw = l.builder.CreateInsertValue(variantRaw, llvm::ConstantInt::get(typIdRaw, id), llvm::ArrayRef<unsigned>({0}));
const bool flagDoReference = expr.operands.size();
if (flagDoReference) {
const ExpandedType& subtyp = ExpandedType(typVariant->__operands.at(id));
llvm::Type* subtypRaw = l.toLLVMType(subtyp);
Attachments::put<TypeInferred>(expr.operands.at(0), subtyp);
llvm::Value* subtypValue = process(expr.operands.at(0));
llvm::Type* typStorageRaw = llvm::cast<llvm::StructType>(typVariantRaw)->getElementType(1);
llvm::Value* addrAsStorage = l.builder.CreateAlloca(typStorageRaw);
llvm::Value* addrAsSubtyp = l.builder.CreateBitOrPointerCast(addrAsStorage, subtypRaw->getPointerTo());
l.builder.CreateStore(subtypValue, addrAsSubtyp);
llvm::Value* storageRaw = l.builder.CreateLoad(typStorageRaw, addrAsStorage);
variantRaw = l.builder.CreateInsertValue(variantRaw, storageRaw, llvm::ArrayRef<unsigned>({1}));
}
return variantRaw;
}
case Operator::SWITCH_VARIANT:
{
return instructions.compileSwitchVariant(expr, DEFAULT("tmpswitch"));
}
case Operator::SWITCH_LATE:
{
assert(false && "Instruction's compilation should've been redirected to interpretation");
return nullptr;
}
case Operator::SEQUENCE:
{
return instructions.compileSequence(expr);
}
case Operator::UNDEF:
{
llvm::Type* typExprUndef = l.toLLVMType(typeinference::getType(expr, *pass->man->root));
return llvm::UndefValue::get(typExprUndef);
}
case Operator::INVALID:
assert(expr.__state != Expression::COMPOUND);
switch (expr.__state) {
case Expression::IDENT:
{
Symbol s = Attachments::get<IdentifierSymbol>(expr);
return processSymbol(s, expr.getValueString());
}
case Expression::NUMBER:
{
- llvm::Type* typConst = l.toLLVMType(typeinference::getType(expr, *pass->man->root));
- int literal = expr.getValueDouble();
+ llvm::Type* typConst = l.toLLVMType(typeinference::getType(expr, *pass->man->root));
+ int literal = expr.getValueDouble();
- return llvm::ConstantInt::get(typConst, literal);
+ if (typConst->isFloatingPointTy()) return llvm::ConstantFP::get(typConst, literal);
+ if (typConst->isIntegerTy()) return llvm::ConstantInt::get(typConst, literal);
+
+ assert(false && "Can't compile literal");
}
case Expression::STRING:
{
return instructions.compileConstantStringAsPChar(expr.getValueString(), DEFAULT("tmp_str"));
};
default:
{
break;
}
};
break;
default: break;
}
assert(false && "Can't compile expression");
return 0;
}
llvm::Value*
BasicCodeScopeUnit::compile(const std::string& hintBlockDecl) {
LLVMLayer* llvm = pass->man->llvm;
if (!hintBlockDecl.empty()) {
llvm::BasicBlock *block = llvm::BasicBlock::Create(llvm->llvmContext, hintBlockDecl, function->raw);
pass->man->llvm->builder.SetInsertPoint(block);
}
currentBlockRaw = pass->man->llvm->builder.GetInsertBlock();
Symbol symbScope = Symbol{ScopedSymbol::RetSymbol, scope};
return processSymbol(symbScope);
}
ICodeScopeUnit::~ICodeScopeUnit() { }
IFunctionUnit::~IFunctionUnit() { }
llvm::Function*
IFunctionUnit::compile() {
if (raw != nullptr) return raw;
LLVMLayer* llvm = pass->man->llvm;
llvm::IRBuilder<>& builder = llvm->builder;
string&& functionName = prepareName();
std::vector<llvm::Type*>&& types = prepareSignature();
llvm::Type* expectedResultType = prepareResult();
llvm::FunctionType *ft = llvm::FunctionType::get(expectedResultType, types, false);
raw = llvm::cast<llvm::Function>(llvm->module->getOrInsertFunction(functionName, ft));
prepareBindings();
const std::string&blockName = "entry";
llvm::BasicBlock* blockCurrent = builder.GetInsertBlock();
llvm::Value* result = getScopeUnit(function->__entry)->compile(blockName);
assert(result);
//SECTIONTAG types/convert function ret value
builder.CreateRet(typeinference::doAutomaticTypeConversion(result, expectedResultType, llvm->builder));
if (blockCurrent) {
builder.SetInsertPoint(blockCurrent);
}
llvm->moveToGarbage(ft);
return raw;
}
ICodeScopeUnit*
IFunctionUnit::getScopeUnit(const CodeScope * const scope) {
if (__scopes.count(scope)) {
auto result = __scopes.at(scope).lock();
if (result) {
return result.get();
}
}
std::shared_ptr<ICodeScopeUnit> unit(pass->buildCodeScopeUnit(scope, this));
if (scope->__parent != nullptr) {
auto parentUnit = Decorators<CachedScopeDecoratorTag>::getInterface(getScopeUnit(scope->__parent));
parentUnit->registerChildScope(unit);
} else {
__orphanedScopes.push_back(unit);
}
if (!__scopes.emplace(scope, unit).second) {
__scopes[scope] = unit;
}
return unit.get();
}
ICodeScopeUnit*
IFunctionUnit::getScopeUnit(ManagedScpPtr scope) {
return getScopeUnit(&*scope);
}
ICodeScopeUnit*
IFunctionUnit::getEntry() {
return getScopeUnit(function->getEntryScope());
}
template<>
compilation::IFunctionUnit*
CompilePassCustomDecorators<void, void>
::buildFunctionUnit(const ManagedFnPtr& function) {
return new BruteFunctionDefault(function, this);
}
template<>
compilation::ICodeScopeUnit*
CompilePassCustomDecorators<void, void>
::buildCodeScopeUnit(const CodeScope * const scope, IFunctionUnit* function) {
return new DefaultCodeScopeUnit(scope, function, this);
}
} // end of compilation
compilation::IFunctionUnit*
CompilePass::getFunctionUnit(const ManagedFnPtr& function) {
unsigned int id = function.id();
if (!functions.count(id)) {
compilation::IFunctionUnit* unit = buildFunctionUnit(function);
functions.emplace(id, unit);
return unit;
}
return functions.at(id);
}
void
CompilePass::run() {
//Initialization:
managerTransformations = new xreate::compilation::TransformationsManager();
targetInterpretation = new interpretation::TargetInterpretation(this->man->root, this);
//Determine entry function:
StaticModel model = man->transcend->query(Config::get("function-entry"));
assert(model.size() && "Error: No entry function found");
assert(model.size() == 1 && "Error: Ambiguous entry function");
string nameMain = std::get<0>(TranscendLayer::parse<std::string>(model.begin()->second));
compilation::IFunctionUnit* unitMain = getFunctionUnit(man->root->findFunction(nameMain));
//Compilation itself:
entry = unitMain->compile();
}
llvm::Function*
CompilePass::getEntryFunction() {
assert(entry);
return entry;
}
void
CompilePass::prepareQueries(TranscendLayer* transcend) {
transcend->registerQuery(new containers::Query(), QueryId::ContainersQuery);
transcend->registerQuery(new polymorph::PolymorphQuery(), QueryId::PolymorphQuery);
transcend->registerQuery(new latex::LatexQuery(), QueryId::LatexQuery);
}
} //end of namespace xreate
/**
* \class xreate::CompilePass
* \brief Encapsulates all compilation activities
*
* xreate::CompilePass iterates over xreate::AST tree and produces executable code fed by data(via xreate::Attachments) gathered by previous passes as well as data via queries(xreate::IQuery) from xreate:TranscendLayer reasoner.
* Compilation's done using xreate::LLVMLayer(wrapper over LLVM toolchain) and based on following aspects:
* - Containers support. See \ref compilation/containers.h
* - Late Conext compilation. See xreate::context::LateContextCompiler2
* - Interpretation support. See xreate::interpretation::TargetInterpretation
* - Loop saturation support. See xreate::compilation::TransformerSaturation
* - External Code access. See xreate::ExternLayer(wrapper over Clang library)
*
* \section adaptability_sect Adaptability
* xreate::CompilePass's architecture provides adaptability by employing:
* - %Function Decorators to alter function-level compilation. See xreate::compilation::IFunctionUnit
* - Code Block Decorators to alter code block level compilation. See xreate::compilation::ICodeScopeUnit
* Default functionality defined by \ref xreate::compilation::DefaultCodeScopeUnit
* - Targets to allow more versitile extensions.
* Currently only xreate::interpretation::TargetInterpretation use Targets infrastructure. See xreate::compilation::Target
* - %Altering Function invocation. xreate::compilation::ICallStatement
*
* Client able to construct compiler with desired decorators using xreate::compilation::CompilePassCustomDecorators.
* As a handy alias, `CompilePassCustomDecorators<void, void>` constructs default compiler
*
*/
diff --git a/cpp/src/query/containers.cpp b/cpp/src/query/containers.cpp
index 543fc00..a95fe9c 100644
--- a/cpp/src/query/containers.cpp
+++ b/cpp/src/query/containers.cpp
@@ -1,119 +1,116 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Author: pgess <v.melnychenko@xreate.org>
*
* containers.cpp
* Created on 3/14/15.
*/
/**
* \file query/containers.h
* \brief Represents reasoner's solution on [Container implementations](/w/concepts/containers)
*/
#include <transcendlayer.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);
- }
+ if (Attachments::exists<Implementation>(s)) {
+ return Attachments::get<Implementation>(s);
+ }
- return Implementation::create(s);
+ return Implementation::create(s);
}
-
-Query::Query(){
- Attachments::init<Implementation>();
+Query::Query() {
+ Attachments::init<Implementation>();
}
void
-Query::init(TranscendLayer* transcend)
-{
- if (flagDataIsLoaded) return;
-
- //Fill implementation data for a data sources:
- auto range = transcend->query(Config::get("containers.id.implementations"));
- if (range.size())
- for(auto atom: range)
- {
- auto data = TranscendLayer::parse<SymbolPacked, Gringo::Symbol>(atom.second);
-
- Symbol var = transcend->unpack(get<0>(data));
- string implStr = get<1>(data).name().c_str();
-
- if (implStr == Config::get("containers.impl.solid"))
- {
- auto size = TranscendLayer::parse<int>(get<1>(data));
- Attachments::put<Implementation>(var, {SOLID, ImplementationRec<SOLID>{get<0>(size)}});
-
- } else if (implStr == Config::get("containers.impl.onthefly")) {
- Attachments::put<Implementation>(var, {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{var}});
-
- } else {
- assert(false && "Unable to determine proper implementation for the symbol");
- }
+Query::init(TranscendLayer* transcend) {
+ if (flagDataIsLoaded) return;
+
+ //Fill implementation data for a data sources:
+ auto range = transcend->query(Config::get("containers.id.implementations"));
+ if (range.size())
+ for(auto atom : range) {
+ auto data = TranscendLayer::parse<SymbolPacked, Gringo::Symbol>(atom.second);
+
+ Symbol var = transcend->unpack(get<0>(data));
+ string implStr = get<1>(data).name().c_str();
+
+ if (implStr == Config::get("containers.impl.solid")) {
+ auto size = TranscendLayer::parse<int>(get<1>(data));
+ Attachments::put<Implementation>(var,{SOLID, ImplementationRec<SOLID>
+ {get<0>(size)}});
+
+ } else if (implStr == Config::get("containers.impl.onthefly")) {
+ Attachments::put<Implementation>(var,{ON_THE_FLY, ImplementationRec<ON_THE_FLY>
+ {var}});
+
+ } else {
+ assert(false && "Unable to determine proper implementation for the symbol");
+ }
}
- flagDataIsLoaded = true;
+ flagDataIsLoaded = true;
}
Implementation
-Implementation::create(const Symbol &var)
-{
- //TODO review implementation determination strategy
- Expression varDecl = CodeScope::getDefinition(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::create(const Symbol &var) {
+ //TODO review implementation determination strategy
+ Expression varDecl = CodeScope::getDefinition(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();
}
ImplementationLinkedList::ImplementationLinkedList(const Symbol& source)
- : flagIsValid(false), s(source){
+: flagIsValid(false), s(source) {
- const Expression& sourceExpr = CodeScope::getDefinition(source);
+ const Expression& sourceExpr = CodeScope::getDefinition(source);
- if (sourceExpr.tags.count(Config::get("containers.id.linkedlist"))){
- flagIsValid = true;
+ 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);
- }
+ 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;
+ImplementationLinkedList::operator bool () const {
+ return flagIsValid;
}
Implementation
ImplementationLinkedList::getImplementationData() const {
- return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{s}};
+ return {ON_THE_FLY, ImplementationRec<ON_THE_FLY>{s}};
}
diff --git a/cpp/tests/CMakeLists.txt b/cpp/tests/CMakeLists.txt
index a178bcc..8d6a2e4 100644
--- a/cpp/tests/CMakeLists.txt
+++ b/cpp/tests/CMakeLists.txt
@@ -1,58 +1,59 @@
cmake_minimum_required(VERSION 2.8.11)
project(xreate-tests)
find_package(GTest REQUIRED)
INCLUDE_DIRECTORIES(${GTEST_INCLUDE_DIRS})
INCLUDE_DIRECTORIES("/usr/include/libxml2")
INCLUDE_DIRECTORIES($<TARGET_PROPERTY:xreate,INCLUDE_DIRECTORIES>)
# TESTS
#=========================
FIND_PACKAGE (LLVM REQUIRED)
message("LLVM_LIBRARY_DIRS: " ${LLVM_LIBRARY_DIRS})
link_directories(${LLVM_LIBRARY_DIRS})
set (LIBCLASP_PATH ${POTASSCO_PATH}/build/debug)
link_directories(${LIBCLASP_PATH})
#aux_source_directory(. TEST_FILES)
set(TEST_FILES
+ introduction.cpp
transcend-ast.cpp
supplemental/docutils
latetranscend.cpp
cfa.cpp
latex.cpp
polymorph.cpp
transcend.cpp
virtualization.cpp
exploitation.cpp
effects-communication.cpp
association.cpp
main.cpp
modules.cpp
attachments.cpp
ast.cpp
dfa.cpp
compilation.cpp
ExpressionSerializer.cpp
externc.cpp
types.cpp
#vendorsAPI/clangAPI.cpp
#vendorsAPI/xml2.cpp
#vendorsAPI/json.cpp
containers.cpp
interpretation.cpp
loops.cpp
#supplemental/versions-algorithm-data_dependency.cpp
effects-versions.cpp
)
add_executable(${PROJECT_NAME} ${TEST_FILES})
target_link_libraries(${PROJECT_NAME} xreate ${GTEST_LIBRARIES} pthread xml2 gcov)
add_custom_target (coverage
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/code-coverage.sh
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
diff --git a/cpp/tests/containers.cpp b/cpp/tests/containers.cpp
index 8d0ba20..0e7482d 100644
--- a/cpp/tests/containers.cpp
+++ b/cpp/tests/containers.cpp
@@ -1,103 +1,155 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* containers.cpp
*
* Created on: Jun 9, 2015
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "xreatemanager.h"
#include "query/containers.h"
#include "main/Parser.h"
+#include "supplemental/docutils.h"
#include "gtest/gtest.h"
using namespace std;
using namespace xreate::grammar::main;
using namespace xreate::containers;
using namespace xreate;
+typedef int (*IntFn)();
+
TEST(Containers, ListAsArray){
XreateManager* man = XreateManager::prepare(
R"Code(
main = function(x:: int):: int;entry {
a = {1, 2, 3}:: [int].
a[x]
}
)Code" );
void* mainPtr = man->run();
int (*main)(int) = (int (*)(int))mainPtr;
ASSERT_EQ(2, main(1));
delete man;
}
TEST(Containers, ListAsArray2){
XreateManager* man = XreateManager::prepare(
R"Code(
// CONTAINERS
import raw("scripts/dfa/ast-attachments.lp").
import raw("scripts/containers/containers.lp").
main = function:: int;entry {
a= {1, 2, 3}:: [int].
b= loop map(a->el:: int):: [int]{
2 * el
}.
sum = loop fold(b->el:: int, 0->acc):: int {
acc + el
}.
sum
}
)Code");
void* mainPtr = man->run();
int (*main)() = (int (*)())mainPtr;
ASSERT_EQ(12, main());
delete man;
}
TEST(Containers, ContanierLinkedList1){
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
AST* ast = parser.root->finalize();
CodeScope* body = ast->findFunction("test")->getEntryScope();
const Symbol symb_chilrenRaw{body->getSymbol("childrenRaw"), body};
containers::ImplementationLinkedList iLL(symb_chilrenRaw);
ASSERT_EQ(true, static_cast<bool>(iLL));
ASSERT_EQ("next", iLL.fieldPointer);
Implementation impl = Implementation::create(symb_chilrenRaw);
ASSERT_NO_FATAL_FAILURE(impl.extract<ON_THE_FLY>());
ImplementationRec<ON_THE_FLY> recOnthefly = impl.extract<ON_THE_FLY>();
ASSERT_EQ(symb_chilrenRaw, recOnthefly.source);
}
TEST(Containers, Implementation_LinkedListFull){
FILE* input = fopen("scripts/containers/Containers_Implementation_LinkedList1.xreate","r");
assert(input != nullptr);
std::unique_ptr<XreateManager> program(XreateManager::prepare(input));
void* mainPtr = program->run();
int (*main)() = (int (*)())(intptr_t)mainPtr;
int answer = main();
ASSERT_EQ(17, answer);
fclose(input);
}
+TEST(Containers, Doc_Intr_1){
+ string example = R"Code(
+ import raw("scripts/containers/containers.lp").
+
+ test = function:: int; entry
+ {
+ <BODY>
+ x
+ }
+ )Code";
+ string body = getDocumentationExampleById("documentation/Concepts/containers.xml", "Intr_1");
+ replace(example, "<BODY>", body);
+
+ XreateManager* xreate = XreateManager::prepare(move(example));
+ IntFn program = (IntFn) xreate->run();
+
+ int result = program();
+ ASSERT_EQ(1, result);
+}
+
+TEST(Containers, Doc_OpAccessSeq_1){
+ string example = getDocumentationExampleById("documentation/Concepts/containers.xml", "OpAccessSeq_1");
+ XreateManager* xreate = XreateManager::prepare(move(example));
+ IntFn program = (IntFn) xreate->run();
+
+ int result = program();
+ ASSERT_EQ(15, result);
+}
+
+TEST(Containers, Doc_OpAccessRand_1){
+ string example = getDocumentationExampleById("documentation/Concepts/containers.xml", "OpAccessRand_1");
+ XreateManager* xreate = XreateManager::prepare(move(example));
+ IntFn program = (IntFn) xreate->run();
+
+ int result = program();
+ ASSERT_EQ(2, result);
+}
+
+TEST(Containers, Doc_ASTAttach_1){
+ string example = getDocumentationExampleById("documentation/Concepts/containers.xml", "ASTAttach_1");
+ string outputExpected = "containers_impl(s(1,-2,0),onthefly)";
+ XreateManager* xreate = XreateManager::prepare(move(example));
+
+ testing::internal::CaptureStdout();
+ xreate->run();
+ std::string outputActual = testing::internal::GetCapturedStdout();
+
+ ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
+}
diff --git a/cpp/tests/introduction.cpp b/cpp/tests/introduction.cpp
new file mode 100644
index 0000000..64f4d2b
--- /dev/null
+++ b/cpp/tests/introduction.cpp
@@ -0,0 +1,25 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ *
+ * Introduction.cpp
+ *
+ * Created on: March 2019
+ * Author: pgess <v.melnychenko@xreate.org>
+ */
+
+#include "xreatemanager.h"
+#include "transcendlayer.h"
+#include "supplemental/docutils.h"
+#include <gtest/gtest.h>
+
+using namespace xreate;
+using namespace std;
+
+TEST(Introduction, Doc_Example_1){
+ string example = getDocumentationExampleById("documentation/index.xml", "Example_1");
+ string rules = getDocumentationExampleById("documentation/index.xml", "Transcend_Example_1");
+ std::unique_ptr<XreateManager> man(XreateManager::prepare(move(example)));
+ man->transcend->addRawScript(move(rules));
+
+ int (* main)() = (int (*)()) man->run();
+}
\ No newline at end of file
diff --git a/cpp/tests/modules.cpp b/cpp/tests/modules.cpp
index e9820aa..cc8e7c4 100644
--- a/cpp/tests/modules.cpp
+++ b/cpp/tests/modules.cpp
@@ -1,371 +1,404 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* modules.cpp
*
* Author: pgess <v.melnychenko@xreate.org>
* Created on June 18, 2017, 8:25 PM
*/
class Modules_AST2_Test;
class Modules_Discovery1_Test;
class Modules_Solve1_Test;
#define FRIENDS_MODULES_TESTS \
friend class ::Modules_AST2_Test; \
friend class ::Modules_Discovery1_Test; \
friend class ::Modules_Solve1_Test;
#include "modules.h"
#include "aux/xreatemanager-decorators.h"
#include "aux/xreatemanager-modules.h"
#include "xreatemanager.h"
#include "modules/Parser.h"
#include "supplemental/docutils.h"
#include "gtest/gtest.h"
#include <boost/filesystem.hpp>
#include <regex>
#include <clingo/clingocontrol.hh>
namespace fs = boost::filesystem;
using namespace std;
using namespace xreate;
using namespace xreate::modules;
TEST(Modules, AST1) {
FILE* input = fopen("scripts/dsl/regexp.xreate","r");
assert(input != nullptr);
Scanner scanner(input);
Parser parser(&scanner);
parser.Parse();
ASSERT_EQ(parser.errors->count, 0);
}
TEST(Modules, AST2){
string code = R"Code(
module:: name(test1); status(untested)
{
require(provides(logging)).
controller("/tmp/test-controller.ls").
discover("/tmp/root/").
}
)Code";
Scanner scanner(reinterpret_cast<const unsigned char*>(code.c_str()), code.size());
Parser parser(&scanner);
parser.Parse();
ModuleRecord module = parser.module;
ASSERT_EQ(2, module.__properties.size());
ASSERT_EQ("name", module.__properties.front().getValueString());
ASSERT_EQ("status", module.__properties.back().getValueString());
ASSERT_EQ(1, module.__requests.size());
ASSERT_EQ("provides", module.__requests.front().getValueString());
ASSERT_EQ(1, module.__controllers.size());
ASSERT_EQ("/tmp/test-controller.ls", module.__controllers.front());
ASSERT_EQ(1, module.__discoveryPaths.size());
ASSERT_EQ("/tmp/root/", module.__discoveryPaths.front());
}
TEST(Modules, Discovery1){
const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54723/";
string codeA =
R"Code(
module::name(testA); status(needToTestMore).
)Code";
string codeB =
R"Code(
module:: name(testB); status(needToTestEvenMore).
)Code";
string codeMain = string("module{discover (\"") + dirModulesRoot + "\").}";
fs::create_directories(dirModulesRoot);
fs::ofstream fileA(dirModulesRoot + "a.xreate");
fileA << codeA;
fileA.close();
fs::ofstream fileB(dirModulesRoot + "b.xreate");
fileB << codeB;
fileB.close();
Scanner scanner(reinterpret_cast<const unsigned char*>(codeMain.c_str()), codeMain.size());
Parser parser(&scanner);
parser.Parse();
ModulesSolver solver;
solver.discoverModules(parser.module);
fs::remove_all(dirModulesRoot);
std::string output = solver.__program.str();
cout << output << endl;
ASSERT_NE(string::npos, output.find("bind_module(\"/tmp/testModulesDiscovery1_t54723/a.xreate\", name(testA))."));
ASSERT_NE(string::npos, output.find("bind_module(\"/tmp/testModulesDiscovery1_t54723/b.xreate\", status(needToTestEvenMore))."));
}
TEST(Modules, Requests1){
}
TEST(Modules, Compilation1){
const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54726/";
string codeMain =
R"Code(
module {
discover("/tmp/testModulesDiscovery1_t54726/").
controller("/tmp/testModulesDiscovery1_t54726/controller").
require (superService).
}
test = function:: int; entry {
getYourNumber()
}
)Code";
string codeA =
R"Code(
module:: name(testA); provide(superService); status(needToTestEvenMore).
getYourNumber= function:: int {0}
)Code";
string codeB =
R"Code(
module :: name(testB); provide(superService); status(needToTestMore).
getYourNumber= function:: int {1}
)Code";
string codeController =
R"Code(
status_score(0, needToTestEvenMore).
status_score(1, needToTestMore).
module_include_candidate(Request, Y):-
bind_module(Y, provide(Request)).
module_include_winner(Request, MaxScore) :-
MaxScore = #max{Score: module_include_candidate(Request, Y), bind_module(Y, status(Status)), status_score(Score, Status)};
modules_require(_, Request).
modules_resolution(Request, Y) :-
module_include_winner(Request, MaxScore);
bind_module(Y, provide(Request));
bind_module(Y, status(Status));
status_score(MaxScore, Status).
)Code";
fs::create_directories(dirModulesRoot);
fs::ofstream fileA(dirModulesRoot + "a.xreate");
fileA << codeA;
fileA.close();
fs::ofstream fileB(dirModulesRoot + "b.xreate");
fileB << codeB;
fileB.close();
fs::ofstream fileController(dirModulesRoot + "controller");
fileController << codeController;
fileController.close();
auto man = new XreateManagerImpl<XreateManagerDecoratorModules<XreateManagerDecoratorFull>>();
man->prepareCode(std::move(codeMain));
fs::remove_all(dirModulesRoot);
int (*funcMain)() = (int (*)()) man->run();
int result = funcMain();
ASSERT_EQ(1, result);
}
TEST(Modules, Compilation_AssignModulePath1){
const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54725/";
string codeMain =
R"Code(
module {
discover("/tmp/testModulesDiscovery1_t54725/").
controller("/tmp/testModulesDiscovery1_t54725/controller").
require (superService).
}
test = function:: int; entry {
getYourNumber()
}
)Code";
string codeA =
R"Code(
module:: name(testA); provide(superService); status(needToTestEvenMore).
getYourNumber= function:: int {0}
)Code";
string codeController =
R"Code(
modules_resolution(superService, "/tmp/testModulesDiscovery1_t54725/a.xreate").
)Code";
fs::create_directories(dirModulesRoot);
fs::ofstream fileA(dirModulesRoot + "a.xreate");
fileA << codeA;
fileA.close();
fs::ofstream fileController(dirModulesRoot + "controller");
fileController << codeController;
fileController.close();
auto man = new XreateManagerImpl<XreateManagerDecoratorModules<XreateManagerDecoratorFull>>();
man->prepareCode(std::move(codeMain));
fs::remove_all(dirModulesRoot);
int (*funcMain)() = (int (*)()) man->run();
int result = funcMain();
ASSERT_EQ(0, result);
}
TEST(Modules, Doc_Requesting_Modules_1){
string codeExcerpt = getDocumentationExampleById("documentation/Syntax/modules.xml", "Requesting_Modules_1");
string codeController = R"Code(
modules_resolution(logger, "/tmp/logger").
)Code";
Scanner scanner(reinterpret_cast<const unsigned char*>(codeExcerpt.c_str()), codeExcerpt.size());
Parser parser(&scanner);
parser.Parse();
ModulesSolver solver;
solver.init(move(codeController), parser.module);
std::list<string> result = solver.run(parser.module);
ASSERT_EQ(1, result.size());
ASSERT_STREQ("/tmp/logger", result.front().c_str());
}
TEST(Modules, Doc_Requesting_Modules_2){
string codeExcerpt = getDocumentationExampleById("documentation/Syntax/modules.xml", "Requesting_Modules_2");
string codeController = R"Code(
modules_resolution(stringslib, "/tmp/stringslib").
modules_resolution(mathlib, "/tmp/mathlib").
)Code";
Scanner scanner(reinterpret_cast<const unsigned char*>(codeExcerpt.c_str()), codeExcerpt.size());
Parser parser(&scanner);
parser.Parse();
ModulesSolver solver;
solver.init(move(codeController), parser.module);
std::list<string> result = solver.run(parser.module);
ASSERT_EQ(2, result.size());
ASSERT_STREQ("/tmp/stringslib", result.front().c_str());
ASSERT_STREQ("/tmp/mathlib", result.back().c_str());
}
TEST(Modules, Doc_ModuleAnnotations_1){
string codeExcerpt = getDocumentationExampleById("documentation/Syntax/modules.xml", "ModuleAnnotations_1");
Scanner scanner(reinterpret_cast<const unsigned char*>(codeExcerpt.c_str()), codeExcerpt.size());
Parser parser(&scanner);
parser.Parse();
ModulesSolver solver;
solver.init("", parser.module);
string program = solver.__program.str();
ASSERT_NE(string::npos, program.find("bind_module(\"\", status(obsolete))."));
}
TEST(Modules, Doc_ModulesResolution_1){
string codeExcerpt = getDocumentationExampleById("documentation/Syntax/modules.xml", "ModulesResolution_1");
string codeModule = R"Code(
module {require(numlib). require(strings)}
)Code";
//use ModuleA as a current module
codeExcerpt.replace(codeExcerpt.find("moduleA"), 7, "");
Scanner scanner(reinterpret_cast<const unsigned char*>(codeModule.c_str()), codeModule.size());
Parser parser(&scanner);
parser.Parse();
ModulesSolver solver;
solver.init(codeExcerpt, parser.module);
std::list<string> result = solver.run(parser.module);
ASSERT_EQ(2, result.size());
ASSERT_STREQ("/path/to/numlib", result.front().c_str());
ASSERT_STREQ("/path/to/ansi-lib", result.back().c_str());
}
TEST(Modules, Doc_AdvModRes_1){
string code = getDocumentationExampleById("documentation/Syntax/modules.xml", "AdvModRes_1");
size_t posCodeA = code.find("//First Module");
size_t posCodeB = code.find("//Second Module");
size_t posCodeMain = code.find("//Third Module");
string codeA = code.substr(posCodeA, posCodeB - posCodeA);
string codeB = code.substr(posCodeB, posCodeMain - posCodeB);
string codeMain = code.substr(posCodeMain);
const std::string dirModulesRoot = "/tmp/testModulesDiscovery1_t54724/";
replace(codeMain, string("/modules/path/"), dirModulesRoot);
replace(codeMain, string("/path/to/controller"), dirModulesRoot + "controller");
cout << codeMain << endl;
string codeController =
R"Code(
status_score(0, needToTestEvenMore).
status_score(1, needToTest).
module_include_candidate(Request, Y):-
bind_module(Y, provide(Request)).
module_include_winner(Request, MaxScore) :-
MaxScore = #max{Score: module_include_candidate(Request, Y), bind_module(Y, status(Status)), status_score(Score, Status)};
modules_require(_, Request).
modules_resolution(Request, Y) :-
module_include_winner(Request, MaxScore);
bind_module(Y, provide(Request));
bind_module(Y, status(Status));
status_score(MaxScore, Status).
)Code";
fs::create_directories(dirModulesRoot);
fs::ofstream fileA(dirModulesRoot + "a.xreate");
fileA << codeA;
fileA.close();
fs::ofstream fileB(dirModulesRoot + "b.xreate");
fileB << codeB;
fileB.close();
fs::ofstream fileController(dirModulesRoot + "controller");
fileController << codeController;
fileController.close();
Scanner scanner(reinterpret_cast<const unsigned char*>(codeMain.c_str()), codeMain.size());
Parser parser(&scanner);
parser.Parse();
ModulesSolver solver;
solver.init("", parser.module);
fs::remove_all(dirModulesRoot);
cout << solver.__program.str() << endl;
std::list<std::string> modulesRequired = solver.run(parser.module);
ASSERT_EQ(1, modulesRequired.size());
string moduleActualRequired = modulesRequired.front();
string moduleExpected = dirModulesRoot + "b.xreate";
ASSERT_EQ(moduleExpected, moduleActualRequired);
+}
+
+TEST(Modules_API, Doc_ModAnn_1){
+ string program = getDocumentationExampleById("documentation/Transcend/modules-api.xml", "ModAnn_1");
+ string outputExpected = getDocumentationExampleById("documentation/Transcend/modules-api.xml", "Output_ModAnn_1");
+ replace(outputExpected, "/path/to/module", "");
+
+ auto xreate = new xreate::details::tier1::XreateManagerImpl<XreateManagerDecoratorModules<XreateManagerDecoratorFull>>();
+ testing::internal::CaptureStdout();
+
+ xreate->prepareCode(std::move(program));
+ xreate->analyse();
+
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
+}
+
+TEST(Modules_API, Doc_ReqMod_1){
+ string program = getDocumentationExampleById("documentation/Transcend/modules-api.xml", "ReqMod_1");
+ string outputExpected = getDocumentationExampleById("documentation/Transcend/modules-api.xml", "Output_ReqMod_1");
+ replace(outputExpected, "/path/to/module", "");
+
+ Scanner scanner(reinterpret_cast<const unsigned char*>(program.c_str()), program.size());
+ Parser parser(&scanner);
+ parser.Parse();
+
+ ModulesSolver solver;
+ testing::internal::CaptureStdout();
+
+ solver.init("", parser.module);
+
+ std::string outputActual = testing::internal::GetCapturedStdout();
+ ASSERT_NE(std::string::npos, outputActual.find(outputExpected));
}
\ No newline at end of file
diff --git a/cpp/tests/supplemental/docutils.cpp b/cpp/tests/supplemental/docutils.cpp
index 6fac2ad..a4f70f6 100644
--- a/cpp/tests/supplemental/docutils.cpp
+++ b/cpp/tests/supplemental/docutils.cpp
@@ -1,81 +1,95 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* \file docutils.cpp
* \brief Documentation processing
*
*/
#include "docutils.h"
#include <iostream>
#include <fstream>
#include <assert.h>
#include <libxml/parser.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>
using namespace std;
std::string
getDocumentationExampleById(std::string filename, std::string id) {
string query = string("(//db:programlisting | //db:code | //db:screen)[@xml:id='") + id + "']";
xmlDocPtr doc = xmlParseFile(filename.c_str());
if(!doc) {
cout << "Can't find documentation file: " << filename << endl;
assert(false);
return "";
}
xmlXPathContextPtr context = xmlXPathNewContext(doc);
xmlXPathRegisterNs(context, BAD_CAST "db", BAD_CAST "http://docbook.org/ns/docbook");
xmlXPathObjectPtr response = xmlXPathEvalExpression((xmlChar*) query.c_str(), context);
xmlXPathFreeContext(context);
xmlNodeSetPtr nodeset = response->nodesetval;
if(nodeset->nodeNr != 1) {
cout << "Can't find specified example " << id << endl;
assert(false);
return "";
}
string tag = (char*) nodeset->nodeTab[0]->name;
bool flagIsPrgListing = tag == "programlisting";
xmlChar* contentC = xmlNodeListGetString(doc, nodeset->nodeTab[0]->xmlChildrenNode, 1);
string content = (char*) contentC;
xmlFree(contentC);
xmlXPathFreeObject(response);
- if(flagIsPrgListing){
- //skip first line(used as header)
- content = content.substr(content.find('\n')+1);
+ //skip first line(used as header)
+ if(flagIsPrgListing) {
+ content = content.substr(content.find('\n') + 1);
}
+
+ //replace no break spaces
+ replaceAll(content, "\u00A0", " ");
+
assert(content.size() && "Empty example");
return content;
}
std::string
getDocumentationExampleFromFile(std::string filename) {
std::ifstream stream(filename);
std::string result;
stream.seekg(0, std::ios::end);
result.reserve(stream.tellg());
stream.seekg(0, std::ios::beg);
result.assign((std::istreambuf_iterator<char>(stream)),
- std::istreambuf_iterator<char>());
+ std::istreambuf_iterator<char>());
assert(result.size() && "Empty example");
return result;
}
void
replace(std::string &str, const std::string &subA, const std::string &subB) {
size_t posA = str.find(subA);
assert(posA != string::npos);
str.replace(posA, subA.size(), subB);
+}
+
+void
+replaceAll(std::string &str, const std::string &subA, const std::string &subB) {
+ size_t posA = str.find(subA);
+
+ while(posA != string::npos) {
+ str.replace(posA, subA.size(), subB);
+ posA = str.find(subA);
+ }
}
\ No newline at end of file
diff --git a/cpp/tests/supplemental/docutils.h b/cpp/tests/supplemental/docutils.h
index 3f17d8f..0e47d69 100644
--- a/cpp/tests/supplemental/docutils.h
+++ b/cpp/tests/supplemental/docutils.h
@@ -1,24 +1,27 @@
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* File: docuils.h
* Author: pgess
*
* Created on November 29, 2018, 3:58 PM
*
* \brief Documentation processing
*/
#ifndef DOC_H
#define DOC_H
#include <string>
std::string getDocumentationExampleById (std::string filename, std::string id);
std::string getDocumentationExampleFromFile (std::string filename);
void replace (std::string& str,
const std::string& subA,
const std::string& subB);
+void replaceAll (std::string& str,
+ const std::string& subA,
+ const std::string& subB);
#endif /* DOC_H */
diff --git a/documentation/Concepts/containers.xml b/documentation/Concepts/containers.xml
new file mode 100644
index 0000000..c6e8384
--- /dev/null
+++ b/documentation/Concepts/containers.xml
@@ -0,0 +1,336 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:trans="http://docbook.org/ns/transclusion"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:m="http://www.w3.org/1998/Math/MathML"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns:db="http://docbook.org/ns/docbook">
+ <?xxe-sn 2ahi4rjnvuo 2h?>
+
+ <title><?xxe-sn 2ahi4rjnvuo 2i?>Containers</title>
+
+ <section>
+ <?xxe-sn 2alsjvonojk 1g?>
+
+ <title><?xxe-sn 2alsjvonojk 1h?>Syntax</title>
+
+ <para><?xxe-sn 2alsjvonojk 1z?>Container operations:</para>
+
+ <itemizedlist>
+ <?xxe-sn 2alsjvonojk 20?>
+
+ <listitem>
+ <?xxe-sn 2alsjvonojk 21?>
+
+ <para><?xxe-sn 2alsjvonojk 22?><code><?xxe-sn 2alsjvonojk 23?>access(serial)</code>
+ Denotes operation's type as a sequential access. <link
+ xlink:href="#operation-access-serial"><?xxe-sn 2alsjvonojk 41?>More</link>...</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 2alsjvonojk 24?>
+
+ <para><?xxe-sn 2alsjvonojk 25?><code><?xxe-sn 2alsjvonojk 26?>access(rand)</code>
+ Denotes operation's type as a random access. <link
+ xlink:href="#operation-access-rand"><?xxe-sn 2alsjvonojk 42?>More</link>...</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 2alsjvonojk 1i?>Container implementations:</para>
+
+ <itemizedlist>
+ <?xxe-sn 2alsjvonojk 1j?>
+
+ <listitem>
+ <?xxe-sn 2alsjvonojk 1k?>
+
+ <para><?xxe-sn 2alsjvonojk 1l?><code><?xxe-sn 2alsjvonojk 1y?>container(onthefly)</code>
+ Lazy data structure that generates elements on the fly when needed.
+ <link xlink:href="#implementation-container"><?xxe-sn 2alsjvonojk 27?>More</link>...</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 2alsjvonojk 1n?>
+
+ <para><?xxe-sn 2alsjvonojk 1o?><code><?xxe-sn 2alsjvonojk 28?>container(solid)</code>
+ Array or data structure that occupies contiguous memory region <link
+ xlink:href="#implementation-container-1"><?xxe-sn 2alsjvonojk 29?>More</link>...</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <?xxe-sn 2ahi4rjnvuo 2j?>
+
+ <title><?xxe-sn 2ahi4rjnvuo 2k?>Introduction</title>
+
+ <para><?xxe-sn 2ahi4rjnvuo 2m?><emphasis><?xxe-sn 2ahi4rjnvuo 4g?>Containers</emphasis>
+ is a general term referring to the data structures that contain a group of
+ elements of certain type.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 2n?>Considering that virtually every program
+ use containers to store, retrieve, search or otherwise process aggregate
+ data, obviously efficiency of containers implementation is a priority for
+ Xreate design.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 2p?>There are many different data structures
+ invented to serve as a containers, each of them having different
+ characteristics and peculiarities with no obvious winner but rather each
+ one suits the best in appropriate situations. Usually it is software
+ developer's knowledge and responsibility to be able to select the most
+ appropriate container's implementation for a particular use case. That
+ said, Xreate goes further and gathers information on <emphasis><?xxe-sn 2ahi4rjnvuo 4h?>how
+ containers are used</emphasis>, by analysing the program sources. On this
+ ground it's possible to choose semi-automatically the most appropriate
+ data structure for container implementation to efficiently fulfil
+ particular needs in a particular situation.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 2q?>In order to do this, the following approach
+ is used. The way a container is defined is associated with one or more
+ possible implementations it supports. On the other side, operations over
+ container demand certain "good" implementations to efficiently process
+ container data. Viewing it as <emphasis><?xxe-sn 2ahi4rjnvuo 53?>supply
+ and demand</emphasis> setting, with a list of several acceptable
+ implementations from either side, the most appropriate tradeoff is chosen
+ as implementation for a given container to fulfill both sides with regard
+ to defaults, preferences, constraints and other ways to guide inference
+ process.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 2r?>In short example below</para>
+
+ <programlisting xml:id="Intr_1"><?xxe-sn 2ahi4rjnvuo 2s?>name = "tests/containers.cpp: Containers.Doc_Intr_1"
+//container definition:
+a= {1, 2, 3, 4, 5}:: [num]; container(solid).
+
+
+//container's operation
+x= a[0]:: num; access(rand). </programlisting>
+
+ <para><?xxe-sn 2ahi4rjnvuo 2t?>container's <emphasis><?xxe-sn 2ahi4rjnvuo 4i?>offer</emphasis>
+ <code><?xxe-sn 2apiasqubk0 c?>container(solid)</code> and operation's
+ <emphasis><?xxe-sn 2ahi4rjnvuo 4j?>demand</emphasis> <code><?xxe-sn 2apiasqubk0 d?>access(rand)</code>
+ are explicitly expressed by annotations for clarity purposes.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 2u?>Annotation <code><?xxe-sn 2alsjvonojk 2p?>container(solid)</code>
+ depicts that container <code><?xxe-sn 2ahi4rjnvuo 4l?>a</code> supports
+ implementation <code><?xxe-sn 2ahi4rjnvuo 4m?>solid</code>, that is plain
+ contiguous memory region or array. On the other side, annotation
+ <code><?xxe-sn 2ahi4rjnvuo 4n?>access(rand)</code> expresses nature of
+ <emphasis><?xxe-sn 2ahi4rjnvuo 54?>retrieving by index</emphasis>
+ operation (variable <code><?xxe-sn 2ahi4rjnvuo 4p?>x</code>) and it
+ requires selected data structure to support <emphasis><?xxe-sn 2ahi4rjnvuo 55?>random
+ access</emphasis> to be efficiently executed.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 2v?>Obviously, implementation <code><?xxe-sn 2ahi4rjnvuo 4r?>solid</code>
+ allows efficient random access and so it's assumed as a container
+ <code><?xxe-sn 2ahi4rjnvuo 4s?>a</code>'s implementation by inference
+ process.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 4t?>Semi-automatic, guided container's
+ implementation selection has some advantages, such as:</para>
+
+ <itemizedlist>
+ <?xxe-sn 2ahi4rjnvuo 4u?>
+
+ <listitem>
+ <?xxe-sn 2ahi4rjnvuo 4v?>
+
+ <para><?xxe-sn 2ahi4rjnvuo 4w?><emphasis><?xxe-sn 2ahi4rjnvuo 4x?>Less
+ manual work</emphasis>. Inferring adequate implementations with little
+ to no additional input from developer saves time to concentrate on
+ more important aspects. Other approach to achieve the same, namely to
+ assign default one-size-fits-all implementation with an average
+ performance, is simpler but can not compete with more careful
+ strategy.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 2ahi4rjnvuo 4y?>
+
+ <para><?xxe-sn 2ahi4rjnvuo 4z?><emphasis><?xxe-sn 2ahi4rjnvuo 50?>Rapid
+ development and optimization antagonism</emphasis>. It is important to
+ keep in mind, that rapid development and frequent code changes
+ somewhat contradict optimization efforts. Each round of optimization
+ is leveraged by relying on concrete and particular program properties,
+ overt or hidden connections and other observations. Once program
+ undergo further development most of the previously sound optimization
+ techniques became obsolete, irrelevant or plainly wrong. Selecting(as
+ often as needed) the most efficient data structures keeps reasonable
+ efficiency level automatically and does not impede possibly fast
+ development pace.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 2ahi4rjnvuo 56?>
+
+ <para><?xxe-sn 2ahi4rjnvuo 57?><emphasis><?xxe-sn 2ahi4rjnvuo 58?>Regression
+ resistance</emphasis>. Xreate encourages frequent changes, adjusting
+ and recombination in software components, libraries and modules by
+ automatically reevaluating and reassigning most appropriate data
+ structures in the new conditions or signalling error if it's
+ impossible. This somewhat alleviates problem of <emphasis><?xxe-sn 2apiasqubk0 g?>fragile
+ software</emphasis> and gives more confidence for refactoring.</para>
+ </listitem>
+ </itemizedlist>
+ </section>
+
+ <section>
+ <?xxe-sn 2ahi4rjnvuo 32?>
+
+ <title><?xxe-sn 2ahi4rjnvuo 33?>Container Implementations</title>
+
+ <para><?xxe-sn 2ahi4rjnvuo 35?>Xreate supports container implementations
+ presented below:</para>
+
+ <section>
+ <?xxe-sn 2ahi4rjnvuo 5g?>
+
+ <title><?xxe-sn 2ahi4rjnvuo 5h?>Implementation
+ 'container(onthefly)'</title>
+
+ <para><?xxe-sn 2alsjvonojk 2f?>Source: range list operator
+ <code><?xxe-sn 2alsjvonojk 2i?>[from .. to]</code>.</para>
+
+ <para><?xxe-sn 2alsjvonojk 2g?>Supported operations: <code><?xxe-sn 2alsjvonojk 2h?>access(serial)</code>.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 5j?>This is elementary implementation that
+ represents <emphasis><?xxe-sn 2ahi4rjnvuo 5k?>lazy</emphasis> data
+ structure — sequence of elements is generated by recurrence equation
+ applied to a current element to compute next element of the sequence. It
+ does not keep actual data in the memory, but instead computes necessary
+ elements when accessed. This kind of implementation is rather memory
+ efficient since occupied memory does not depend on count of
+ elements.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 5l?>For example, range list <code><?xxe-sn 2alsjvonojk 2a?>[1..10]</code>
+ supports <code><?xxe-sn 2alsjvonojk 2b?>onthefly</code> implementation
+ by using internally recurrent function <code><?xxe-sn 2alsjvonojk 2c?>x[i+1] = x[i] + 1, 1&lt;= x &lt;= 10</code>,
+ that generates successive element <code><?xxe-sn 2alsjvonojk 2d?>x[i+1]</code>
+ given <code><?xxe-sn 2alsjvonojk 2e?>x[i]</code>.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 5p?>Recurrent elements generation is suited
+ for sequential access and can't serve random access operations.</para>
+ </section>
+
+ <section>
+ <?xxe-sn 2ahi4rjnvuo 5q?>
+
+ <title><?xxe-sn 2ahi4rjnvuo 5r?>Implementation
+ 'container(solid)'</title>
+
+ <para><?xxe-sn 2alsjvonojk 2l?>Source: list operator.</para>
+
+ <para><?xxe-sn 2alsjvonojk 2m?>Supported operations: <code><?xxe-sn 2alsjvonojk 2n?>access(serial)</code>,
+ <code><?xxe-sn 2alsjvonojk 2o?>access(rand)</code>.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 5t?>This is implementation from the opposite
+ side of the memory/computation space. It stores all the container's data
+ in memory occupying contiguous region, known as <emphasis><?xxe-sn 2alsjvonojk 2j?>array</emphasis>.
+ As opposed to the implementation <code><?xxe-sn 2alsjvonojk 2k?>onthefly</code>,
+ it's computationally efficient for there is no need for any additional
+ computations apart from simple offset calculation to get an element
+ requested by an index.</para>
+
+ <para><?xxe-sn 2ahi4rjnvuo 5u?>Due to the fact that all elements are
+ present in the memory, the implementation supports sequential access as
+ well as random access operations.</para>
+ </section>
+ </section>
+
+ <section>
+ <?xxe-sn 2ahi4rjnvuo 3f?>
+
+ <title><?xxe-sn 2ahi4rjnvuo 3g?>Container Operations</title>
+
+ <para><?xxe-sn 2ahi4rjnvuo 3i?>In order to describe requirements for a
+ container all the operations are broken down into several categories as
+ presented below.</para>
+
+ <section>
+ <?xxe-sn 2alsjvonojk 2q?>
+
+ <title><?xxe-sn 2alsjvonojk 2r?>Operation 'access(serial)'</title>
+
+ <para><?xxe-sn 2alsjvonojk 2s?>Operators: <code><?xxe-sn 2alsjvonojk 3e?>loop map</code>,
+ <code><?xxe-sn 2alsjvonojk 3f?>loop fold</code>.</para>
+
+ <para><?xxe-sn 2alsjvonojk 3s?>Annotation denotes sequential access
+ operation, such as <code><?xxe-sn 2alsjvonojk 3t?>map loop</code> or
+ <code><?xxe-sn 2alsjvonojk 3u?>map fold</code>.</para>
+
+ <para><?xxe-sn 2alsjvonojk 43?>Example:</para>
+
+ <programlisting xml:id="OpAccessSeq_1"><?xxe-sn 2alsjvonojk 44?>name = "tests/containers.cpp: Containers.Doc_OpAccessSeq_1"
+import raw("scripts/containers/containers.lp").
+
+test = function :: int; entry
+{
+ range = [1..5] :: [int]; container(onthefly).
+ sum = loop fold(range-&gt;el:: int, 0-&gt;acc):: [int]; access(serial)
+ {
+ acc + el
+ }.
+
+ sum
+}</programlisting>
+ </section>
+
+ <section>
+ <?xxe-sn 2alsjvonojk 2t?>
+
+ <title><?xxe-sn 2alsjvonojk 2u?>Operation 'access(rand)'</title>
+
+ <para><?xxe-sn 2alsjvonojk 2v?>Operators: index</para>
+
+ <para><?xxe-sn 2alsjvonojk 3v?>Annotation denotes random access
+ operation.</para>
+
+ <para><?xxe-sn 2apiasqubk0 1?>Example:</para>
+
+ <programlisting xml:id="OpAccessRand_1"><?xxe-sn 2apiasqubk0 2?>name = "tests/containers.cpp: Containers.Doc_OpAccessRand_1"
+import raw("scripts/containers/containers.lp").
+
+test = function:: num; entry
+{
+ a = {1, 2, 3, 4, 5}:: [num]; container(solid).
+ a[1]:: num; access(rand)
+}</programlisting>
+ </section>
+ </section>
+
+ <section>
+ <?xxe-sn 2apiasqubk0 5?>
+
+ <title><?xxe-sn 2apiasqubk0 6?>AST Attachments</title>
+
+ <para><?xxe-sn 2apiasqubk0 7?>In order to bypass tedious writing of
+ necessary annotations for each line of code that works with containers
+ there are appropriate annotations already defined for common operations.
+ All it takes for a client's code is to include transcend script
+ <code><?xxe-sn 2apiasqubk0 8?>scripts/dfa/ast-attachments.lp</code> that
+ allows to assign predefined annotations for syntactic constructs and
+ operators.</para>
+
+ <para><?xxe-sn 2apiasqubk0 9?>Example below includes <code><?xxe-sn 2apiasqubk0 e?>ast-attachments.lp</code>
+ that feeds compiler with default annotations sparing developer of
+ specifying them manually. </para>
+
+ <programlisting xml:id="ASTAttach_1"><?xxe-sn 2apiasqubk0 a?>name = "tests/containers.cpp: Containers.Doc_ASTAttach_1"
+import raw("scripts/containers/containers.lp").
+import raw("scripts/dfa/ast-attachments.lp").
+
+test = function :: int; entry
+{
+ range = [1..5] :: [int].
+ sum = loop fold(range-&gt;el:: int, 0-&gt;acc):: [int]
+ {
+ acc + el
+ }.
+
+ sum
+}</programlisting>
+ </section>
+</chapter>
diff --git a/documentation/Concepts/context.xml b/documentation/Concepts/context.xml
index 3762cb8..020b673 100644
--- a/documentation/Concepts/context.xml
+++ b/documentation/Concepts/context.xml
@@ -1,365 +1,304 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<?xxe-sn 2ahi4rjnvuo 1?>
<title><?xxe-sn 2ahi4rjnvuo 2?>Context</title>
- <para><?xxe-sn 2ahi4rjnvuo 3?>Computer program and its internal states and
+ <para><?xxe-sn 2ahi4rjnvuo 3?>Computer program, its internal states and
transitions between them can be looked at from two different points of view:
- control flow and data flow. Any information that can be derived from control
- flow is called <emphasis><?xxe-sn 2ahi4rjnvuo 4?>context</emphasis> in
- Xreate.</para>
+ control flow and data flow. In order to express and employ control flow
+ related program's properties Xreate supports mechanism called
+ <emphasis><?xxe-sn 2axopn9e3uo 1?>context</emphasis> — ability to assign
+ transcend data to a code blocks in a way that related blocks in the CFG have
+ related contexts. </para>
- <para><?xxe-sn 2ahi4rjnvuo 5?>Data that can be captured from analysing
- control flow consists of two parts as follows:</para>
+ <para><?xxe-sn 2ahi4rjnvuo 5?>Code block's context is exhaustingly defined
+ as follows:</para>
<itemizedlist>
<?xxe-sn 2ahi4rjnvuo 6?>
<listitem>
<?xxe-sn 2ahi4rjnvuo 7?>
- <para><?xxe-sn 2ahi4rjnvuo 8?>Instantaneous state or current place
- within the code. It's fully determined by current code block as well as
- hierarchy of all its respective parents</para>
+ <para><?xxe-sn 2ahi4rjnvuo 8?>Block's place within the code in terms of
+ hierarchy of all its respective parents.</para>
</listitem>
<listitem>
<?xxe-sn 2ahi4rjnvuo 9?>
- <para><?xxe-sn 2ahi4rjnvuo a?>Historical data determined by all previous
- visited code blocks</para>
+ <para><?xxe-sn 2ahi4rjnvuo a?>Historical data determined by previous
+ visited code blocks in terms of "caller-callee" relation graph.</para>
</listitem>
</itemizedlist>
- <para><?xxe-sn 2ahi4rjnvuo b?>Xreate allows to express Context and reason
- about it by employing block level annotations. See <link
+ <para><?xxe-sn 2ahi4rjnvuo b?>Block level annotations are used to define
+ context and reason about it. See <link
xlink:href="/w/transcend#code-blocks-and-context"><?xxe-sn 2ahi4rjnvuo c?>syntax</link>.</para>
<section>
<?xxe-sn 2ahi4rjnvuo d?>
<title><?xxe-sn 2ahi4rjnvuo e?>Examples of Context Usage: Suggestions and
Requirements</title>
<programlisting xml:id="Examples_1"><?xxe-sn 2ahi4rjnvuo f?>//someStringFn = function:: string {...}
main = function:: string; entry
{
context:: env(utf8).
someStringFn()
}</programlisting>
- <para><?xxe-sn 2ahi4rjnvuo g?>Example shows annotation <code><?xxe-sn 2ahi4rjnvuo h?>env(utf8)</code>
- which conveys some information about the block thus distinguishing it from
- the others. It allows compiler to apply specific compilation rules for
- this block. Suppose <code><?xxe-sn 2ahi4rjnvuo i?>someStringFn</code> has
- different specializations for different environments. Now it's possible to
- invoke specialization tailored for UTF8 environment.</para>
+ <para><?xxe-sn 2ahi4rjnvuo g?>In this example the annotation
+ <code><?xxe-sn 2ahi4rjnvuo h?>env(utf8)</code> conveys some information
+ about the block thus distinguishing it from the others, which allows to
+ apply specific compilation rules for this block. Suppose <code><?xxe-sn 2ahi4rjnvuo i?>someStringFn</code>
+ has different specializations for different environments. Now it's
+ possible to invoke specialization tailored for UTF8 environment. In this
+ case context can be viewed as a <emphasis><?xxe-sn 2axopn9e3uo 2?>suggestion</emphasis>
+ to pick up appropriate specialization. </para>
- <para><?xxe-sn 2ahi4rjnvuo j?>Different story with the next example. Here
- we want to stipulate context properties:</para>
+ <para><?xxe-sn 2ahi4rjnvuo j?>Also there is possibility to define expected
+ context properties:</para>
<programlisting xml:id="Examples_2"><?xxe-sn 2ahi4rjnvuo k?>name - "...."
guard:: safe
{
crucialOperation = function:: int
{0}
}
main = function:: int; entry
{
context:: env(safe).
crucialOperation()
}</programlisting>
<para><?xxe-sn 2ahi4rjnvuo l?>Function <code><?xxe-sn 2ahi4rjnvuo m?>crucialOperation</code>
has only one specialization <code><?xxe-sn 2ahi4rjnvuo n?>safe</code> in
- the example. If context does not provide required environment
+ the example. If the context does not provide required environment
<code><?xxe-sn 2ahi4rjnvuo o?>env(safe)</code>compiler can't find
- appropriate specialization and halts with compilation error. This is a way
- for function to express requirements or <emphasis><?xxe-sn 2ahi4rjnvuo p?>contract</emphasis>
- to a context it works within.</para>
+ appropriate specialization and reports compilation error. This is a way
+ for function to express <emphasis><?xxe-sn 2axopn9e3uo 3?>requirements</emphasis>
+ or contract to a context it works within.</para>
</section>
<section>
<?xxe-sn 2ahi4rjnvuo q?>
<title><?xxe-sn 2ahi4rjnvuo r?>Context Propagation</title>
- <para><?xxe-sn 2ahi4rjnvuo s?>Context of a particular code block contains
- not only its own annotations but also reflects parent blocks as well as
- previously executed blocks. It's achieved by <emphasis><?xxe-sn 2ahi4rjnvuo t?>context
- propagation</emphasis>.</para>
+ <para><?xxe-sn 2ahi4rjnvuo s?><emphasis><?xxe-sn 2axopn9e3uo 4?>Context
+ propagation</emphasis> means that contexts of different blocks are
+ connected reflecting control flow. Context of a particular code block is
+ gathered from following sources: </para>
- <para><?xxe-sn 2ahi4rjnvuo u?>Context propagation means that nested blocks
- <emphasis><?xxe-sn 2ahi4rjnvuo v?>inherit</emphasis> context of parents.
- Moreover callee function's context inherits caller's one. Example:</para>
+ <itemizedlist>
+ <?xxe-sn 2axopn9e3uo 5?>
+
+ <listitem>
+ <?xxe-sn 2axopn9e3uo 6?>
+
+ <para><?xxe-sn 2axopn9e3uo 7?>Local context — annotations that are
+ defined within the block</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 2axopn9e3uo 8?>
+
+ <para><?xxe-sn 2axopn9e3uo 9?>Parent context. Block's context inherits
+ context of its parent reflecting block's place within a
+ program.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 2axopn9e3uo a?>
+
+ <para><?xxe-sn 2axopn9e3uo b?>Client context. Blocks context also
+ includes caller's context reflecting control flow. It allows taking
+ into account in which context a given code is used.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 2ahi4rjnvuo u?>Example below</para>
<programlisting xml:id="ContextPropagation1"><?xxe-sn 2ahi4rjnvuo w?>name = "..."
//requires 'safe' context
-guard:: safe
+guard:: safe
{
crucialOperation = function(a:: int, b::int):: int
{ 0 }
}
test = function:: int; entry {
//blockA
context:: env(safe).
range = [1..10]:: [int].
loop fold(range-&gt;x::int, 0-&gt;acc):: int {
//blockB
crucialOperation(x, acc) // In the nested scope env(safe) context still accessible
}
} </programlisting>
- <para><?xxe-sn 2ahi4rjnvuo x?>This is example of <emphasis><?xxe-sn 2ahi4rjnvuo y?>nested
- scope context propagation</emphasis>. It demonstrates availability of a
- <code><?xxe-sn 2ahi4rjnvuo z?>env(safe)</code> annotation in the context
- of the nested block <code><?xxe-sn 2ahi4rjnvuo 10?>blockB</code> despite
- being declared in <code><?xxe-sn 2ahi4rjnvuo 11?>blockA</code>.</para>
+ <para><?xxe-sn 2ahi4rjnvuo x?>demonstrates context propagation to a nested
+ block which is exhibited by availability of a <code><?xxe-sn 2ahi4rjnvuo z?>env(safe)</code>
+ annotation in the context of the nested block <code><?xxe-sn 2ahi4rjnvuo 10?>blockB</code>
+ despite being defined in the <code><?xxe-sn 2ahi4rjnvuo 11?>blockA</code>.</para>
- <para><?xxe-sn 2ahi4rjnvuo 12?>More complicated case is
- <emphasis><?xxe-sn 2ahi4rjnvuo 13?>inter-function context
- propagation</emphasis>. It means context propagates through
- "caller/callee" relation: callee inherits caller context. The example
- below demonstrates this:</para>
+ <para><?xxe-sn 2ahi4rjnvuo 12?>Another case is propagation from caller to
+ a callee. It means context propagates through "caller/callee" relation —
+ callee inherits caller context. The example below demonstrates
+ this:</para>
<programlisting xml:id="ContextPropagation2"><?xxe-sn 2ahi4rjnvuo 14?>name = "..."
toSI = function(x:: int):: int
{ 0 }
calculate = function(x:: int):: int
{
y = toSI(x):: int.
y
}
test = function:: int; entry
{
- context:: units(millimeters).
+ context:: units(mm).
calculate(10)
} </programlisting>
<para><?xxe-sn 2ahi4rjnvuo 15?>Suppose <code><?xxe-sn 2ahi4rjnvuo 16?>calculate()</code>works
with values measured in different units. It normalizes each value by
invoking <code><?xxe-sn 2ahi4rjnvuo 17?>toSI()</code> conversion. One
approach is to keep unit information for each variable independently. But
if we know that entire program or a part of it works only with specific
- unit we can register it in a context, <code><?xxe-sn 2ahi4rjnvuo 18?>units(millimeters)</code>in
- this example, and <code><?xxe-sn 2ahi4rjnvuo 19?>calculate()</code> and
- its callees inherit context allowing compiler to generate code tailored
- for specific units only.</para>
-
- <para><?xxe-sn 2ahi4rjnvuo 1a?>Context is determined by reasoning over
- control flow graph of a program during compilation. Let's consider
- example:</para>
-
- <programlisting xml:id="ContextPropagation3"><?xxe-sn 2ahi4rjnvuo 1b?>name = "..."
-calcInches = function:: int
-{
- context:: precision(accurate); units(inches).
- calculate()
-}
-
-calcMillis = function:: int
-{
- context:: precision(accurate); units(millimeters).
- calculate()
-}
-
-calculate = function:: int
- { 0 }</programlisting>
-
- <para><?xxe-sn 2ahi4rjnvuo 1c?>Client functions <code><?xxe-sn 2ahi4rjnvuo 1d?>calcInches()</code>
- and <code><?xxe-sn 2ahi4rjnvuo 1e?>calcMillis()</code> each define context
- with a configuration options for a main routine <code><?xxe-sn 2ahi4rjnvuo 1f?>calculate()</code>.
- Unlike in previous example, there are several callers with different
- context here.</para>
-
- <para><?xxe-sn 2ahi4rjnvuo 1g?>In case with several possible control flow
- paths each introducing different context, only path invariant context
- annotations could be determined at compile time. Obviously, annotations
- that are the same for each possible alternative are part of context in any
- case. It's <code><?xxe-sn 2ahi4rjnvuo 1h?>precision(accurate)</code> in
- the example above, since both client function define it. More formally,
- statically determined context is a conjunction of all possible contexts of
- a given code block.</para>
-
- <para><?xxe-sn 2ahi4rjnvuo 1i?>However the other annotation
- <code><?xxe-sn 2ahi4rjnvuo 1j?>units(...)</code> differs from path to path
- and can be determined only during runtime. Late Transcend functionality is
- used for this. Context reasoning employing Late Transcend called
- <emphasis><?xxe-sn 2ahi4rjnvuo 1k?>Late Context</emphasis> or
- <emphasis><?xxe-sn 2ahi4rjnvuo 1l?>Latex</emphasis> for short.</para>
+ unit we can register it in a context, <code><?xxe-sn 2ahi4rjnvuo 18?>units(mm)</code>in
+ this example, letting functions <code><?xxe-sn 2ahi4rjnvuo 19?>calculate()</code>
+ and its callees inherit context allowing compiler to generate code
+ tailored for specific units only.</para>
</section>
<section>
<?xxe-sn 2ahi4rjnvuo 1m?>
<title><?xxe-sn 2ahi4rjnvuo 1n?>Latex (Late Context)</title>
<para><?xxe-sn 2ahi4rjnvuo 1o?>Static(compile-time) context reasoning is
<emphasis><?xxe-sn 2ahi4rjnvuo 1p?>weak</emphasis> since it's able to
infer only partial context, consisting of properties that are true for all
- possible paths leading in a CFG to a given block. Other part consists of
- set of possible properties that depends on exact path in CFG. Such
- uncertainty possible to resolve during runtime once it's known which path
- is chosen.</para>
-
- <para><?xxe-sn 2ahi4rjnvuo 1q?>It leads to a necessity of having //late
- context// - context data gathered on relevant occasion at runtime to
- determine right decisions.</para>
+ possible paths leading in a CFG to a given block. Beyond that are entries
+ that depend on exact path in CFG. Such uncertainty is possible to resolve
+ during runtime once it's known which path exactly is chosen.</para>
- <para><?xxe-sn 2ahi4rjnvuo 1r?>However, for any cases it's crucial to
- consider //possible contexts// that is, contexts valid only under certain
- conditions.</para>
+ <para><?xxe-sn 2ahi4rjnvuo 1q?>To solve this problem <emphasis><?xxe-sn 2axopn9e3uo 11?>late
+ context</emphasis> is introduced - embedding into compiled code certain
+ instructions to gathered data on relevant occasion at runtime to determine
+ exact or <emphasis><?xxe-sn 2axopn9e3uo 12?>strong</emphasis>,
+ context.</para>
<para><?xxe-sn 2ahi4rjnvuo 1s?>Latex approach can be described as
follows:</para>
<itemizedlist>
<?xxe-sn 2ahi4rjnvuo 1t?>
<listitem>
<?xxe-sn 2ahi4rjnvuo 1u?>
- <para><?xxe-sn 2ahi4rjnvuo 1v?>All possible alternative contexts for
- the given scope computed during compile time used as input for
- Latex</para>
+ <para><?xxe-sn 2ahi4rjnvuo 1v?>Set of all possible context facts for
+ the given block is computed during compile time. Each such fact is
+ associated with code paths it holds for. </para>
</listitem>
<listitem>
- <?xxe-sn 2ahi4rjnvuo 1w?>
+ <?xxe-sn 2axopn9e3uo 13?>
- <para><?xxe-sn 2ahi4rjnvuo 1x?>All possible paths are numerated and
- specific latex parameter created to keep data about current
- path.</para>
+ <para><?xxe-sn 2axopn9e3uo 14?>During execution the information is
+ gathered which facts are hold depending on actual code path.
+ Information stored in the late parameters. To convey late context data
+ the latex parameter is injected into function signature as hidden
+ parameter.</para>
</listitem>
<listitem>
<?xxe-sn 2ahi4rjnvuo 1y?>
- <para><?xxe-sn 2ahi4rjnvuo 1z?>Late parameter used as guard for Late
- Transcend facts context consists of.</para>
+ <para><?xxe-sn 2ahi4rjnvuo 1z?>Late parameter is used as guard for
+ late transcend facts context consists of.</para>
</listitem>
</itemizedlist>
- <para><?xxe-sn 2ahi4rjnvuo 20?>As of now, to convey late context data
- latex parameter injected into function signature as hidden
- parameter.</para>
-
<programlisting xml:id="Latex1"><?xxe-sn 2ahi4rjnvuo 21?>name = "..."
import raw ("core/control-context.lp").
compute = function:: int
{ 0 }
computeFast = function:: int {
context:: computation(fast).
compute()
}
computePrecisely = function:: int {
context:: computation(precise).
compute()
}
test = function(cmnd:: int):: int; entry {
context:: arithmetic(iee754).
if (cmnd &gt; 0)::int {computePrecisely()} else {computeFast()}
}</programlisting>
<para><?xxe-sn 2ahi4rjnvuo 22?>Static scope</para>
<para><?xxe-sn 2ahi4rjnvuo 23?></para>
<programlisting><?xxe-sn 2ahi4rjnvuo 24?>name = "..."
import raw ("core/control-context.lp")
case context:: computation(fast) {
compute = function:: num {
0
}
}
case context:: computation(precise) {
compute = function:: num {
0
}
}
executeComputation= function:: num {
compute()
}
test = function(cmnd:: num):: num; entry {
if (cmnd &gt; 0)::num {
context:: computation(fast).
executeComputation()
} else {
context:: computation(precise).
executeComputation()
}
}</programlisting>
- <para><?xxe-sn 2ahi4rjnvuo 25?>To sum up, context consists of two
- complements parts: on the one hand //static(early) context// denotes
- compile time inferences,</para>
-
- <para><?xxe-sn 2ahi4rjnvuo 26?>and on the other hand, //late(dynamic)
- context// denotes annotations decided upon at runtime.</para>
-
- <note>
- <?xxe-sn 2ahi4rjnvuo 27?>
-
- <para><?xxe-sn 2ahi4rjnvuo 28?>Since it is possible to determine number
- of possible contexts with diffent outcome decisions, it is possible to
- determine least size for late context data enough to identify each
- possible variant. (In example above, since there are only two
- specializons of `compute`, 1 bit is enough to convey late context
- data)</para>
- </note>
- </section>
-
- <section>
- <?xxe-sn 2ahi4rjnvuo 29?>
-
- <title><?xxe-sn 2ahi4rjnvuo 2a?>Remarks on late context
- implementation</title>
-
- <para><?xxe-sn 2ahi4rjnvuo 2b?></para>
-
- <para><?xxe-sn 2ahi4rjnvuo 2c?>To return to a last example, in order to
- correcly determine `compute`'s context it's necessary:</para>
-
- <para><?xxe-sn 2ahi4rjnvuo 2d?>After such transformation signature of
- `executeComputation` looks like
- `executeComputation(__hidden_context_data__)`,</para>
-
- <para><?xxe-sn 2ahi4rjnvuo 2e?>where `hidden_context_data` holds data
- enough to determine within `executeComputation` which one of possible
- contexts it encountered with.</para>
-
- <para><?xxe-sn 2ahi4rjnvuo 2f?>Consequently, `executeComputation` decides
- which specialization of `compute` should be called based on
- `hidden_context_data` value.</para>
-
- <para><?xxe-sn 2ahi4rjnvuo 2g?>Only at run-time there is enough
- information for `executeComputation` to decide what specialization of
- `compute` to call.</para>
+ <para><?xxe-sn 2ahi4rjnvuo 25?>To sum it up, context consists of two
+ complements parts: on the one hand <emphasis><?xxe-sn 2axopn9e3uo 15?>static(early)
+ context</emphasis>, that denotes compile time inference's result and on
+ the other hand, <emphasis><?xxe-sn 2axopn9e3uo 16?>late(dynamic)
+ context</emphasis> denotes annotations decided upon at runtime.</para>
</section>
</chapter>
diff --git a/documentation/Concepts/polymorphism.xml b/documentation/Concepts/polymorphism.xml
index c453c27..e757c58 100644
--- a/documentation/Concepts/polymorphism.xml
+++ b/documentation/Concepts/polymorphism.xml
@@ -1,224 +1,229 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<?xxe-sn 26n42fz1reo 1?>
<title><?xxe-sn 26n42fz1reo 2?>Polymorphism</title>
<para><?xxe-sn 26n42fz1reo 3?><emphasis><?xxe-sn 26n42fz1reo 4?>Polymorphism</emphasis>
is an umbrella term to denote number of techniques across different
programing paradigms. They all share the same intention to provide ability
easily recombine software components in a different way with as little as
possible manual work on developer's side. It serves two major goals:
<emphasis><?xxe-sn 26n42fz1reo 5?>specialization</emphasis>, when software,
initially designed to support wide range of use cases, is configured for
concrete particular case and <emphasis><?xxe-sn 26n42fz1reo 6?>extension</emphasis>
- adapting software to an environment and conditions it was not specifically
designed for.</para>
<para><?xxe-sn 26n42fz1reo 7?>In course of software engineering evolution,
number of polymorphism techniques was proposed and experimented with, all
suited for different use-cases. Xreate presents generalized and elegant
approach that exhaustively covers wide landscape of polymorphism
variations.</para>
<para><?xxe-sn 26n42fz1reo 8?>Polymorphism in Xreate can be applied on two
levels:</para>
<itemizedlist>
<?xxe-sn 26n42fz1reo 9?>
<listitem>
<?xxe-sn 26n42fz1reo a?>
<para><?xxe-sn 26n42fz1reo b?><emphasis><?xxe-sn 26n42fz1reo c?>Functions
level</emphasis>. Function in Xreate can have a multiple
<emphasis><?xxe-sn 26n42fz1reo d?>specializations</emphasis> and
polymorphism is compiler's ability to decide which exactly
specialization to use depending on various factors</para>
</listitem>
<listitem>
<?xxe-sn 26n42fz1reo e?>
<para><?xxe-sn 26n42fz1reo f?><emphasis><?xxe-sn 26n42fz1reo g?>Modules
level</emphasis>. Multiple modules can provide the same service for
users. <link
xlink:href="/w/syntax/modules/#modules-resolution"><?xxe-sn 26n42fz1reo h?>Modules
Resolution</link> is a process to decide which exactly module to
use</para>
</listitem>
</itemizedlist>
<section>
<?xxe-sn 26n42fz1reo i?>
<title><?xxe-sn 26n42fz1reo j?>Function Level Polymorphism</title>
<para><?xxe-sn 26n42fz1reo k?>Basic idea is to allow developer to define
several functions with the same name or, in other words, several
<emphasis><?xxe-sn 26n42fz1reo l?>specializations</emphasis>. Caller code
then invokes necessary function by its shared name but can't directly
specify particular specialization. Exact specialization to be invoked is
decided later by decision process called <emphasis><?xxe-sn 26n42fz1reo m?>polymorphism
resolution</emphasis> carried out by Transcend. This indirect invocation
approach gives enough flexibility to use or replace different
specializations depending on various conditions during compile time as
well as at runtime.</para>
<para><?xxe-sn 26n42fz1reo n?>Please refer to <link
xlink:href="/w/syntax#function-specializations"><?xxe-sn 26n42fz1reo o?>syntax</link>
for details about function specializations. Each specialization must have
unique <emphasis><?xxe-sn 26n42fz1reo p?>guard</emphasis>(among all
specializations with the same name) to be discernible from others. To
summarize, function invocation is a two layered process, in which client
code specifies callee function's shared name, and polymorphism resolution
specifies specialization guard if needed.</para>
<para><?xxe-sn 26n42fz1reo q?>For an example, assume that we develop
program to operate under specified time constraints. To model
implementation suitable for real time environment, one specialization of
<code><?xxe-sn 26n42fz1reo r?>crucialOperation</code> is defined with
<code><?xxe-sn 26n42fz1reo s?>env(realtime)</code> guard i.e. satisfies
some fixed execution time constraints. Caller <code><?xxe-sn 26n42fz1reo t?>main</code>
specifies only function name <code><?xxe-sn 26n42fz1reo u?>crucialOperation</code>
thus delegating decision on guard to a polymorphism resolution done
elsewhere, based on environment's constraints the code is executed
in.</para>
- <programlisting xml:id="FnLvlPoly_1"><?xxe-sn 26n42fz1reo v?>guard:: env(realtime)
+ <programlisting xml:id="FnLvlPoly_1"><?xxe-sn 26n42fz1reo v?>name="tests/polymorph.cpp: Polymorphs.Doc_FnLvlPoly_1"
+guard:: env(realtime)
{
crucialOperation = function:: int
{ 0 }
}
main = function:: int; entry
{
crucialOperation()
} </programlisting>
</section>
<section>
<?xxe-sn 26n42fz1reo w?>
<title><?xxe-sn 26n42fz1reo x?>Polymorphism Resolution</title>
<synopsis><?xxe-sn 26n42fz1reo y?>SYNTAX:
**dfa_callguard**(//call-site-ref//, //guard//)</synopsis>
<itemizedlist>
<?xxe-sn 26n42fz1reo z?>
<listitem>
<?xxe-sn 26n42fz1reo 10?>
<para><?xxe-sn 26n42fz1reo 11?><emphasis><?xxe-sn 26n42fz1reo 12?>call-site-ref</emphasis>
reference to a call site in AST</para>
</listitem>
<listitem>
<?xxe-sn 26n42fz1reo 13?>
<para><?xxe-sn 26n42fz1reo 14?><emphasis><?xxe-sn 26n42fz1reo 15?>guard</emphasis>
resolved function specialization guard</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26n42fz1reo 16?>When compiler encounters function
invocation that has several specialization it refers to the table
<code><?xxe-sn 26n42fz1reo 17?>dfa_callguard</code> to find out which
specialization to call. It must have entry with appropriate
<code><?xxe-sn 26n42fz1reo 18?>guard</code> for every invocation site
<code><?xxe-sn 26n42fz1reo 19?>call-site-ref</code> of a polymorphic
function. Polymorphism resolution is a process of filling out
<code><?xxe-sn 26n42fz1reo 1a?>dfa_callguard</code> for a compiler based
on custom Transcend rules reflecting one or another polymorphism
strategy.</para>
</section>
<section>
<?xxe-sn 26n42fz1reo 1b?>
<title><?xxe-sn 26n42fz1reo 1c?>Late Polymorphism</title>
<para><?xxe-sn 26n42fz1reo 1d?>Late Polymorphism is an extension to allow
polymorphism resolution to be based on data known only at runtime, i.e.
resolve function specializations dynamically. The Idea is to use Late
Transcend to access runtime data. See <link
xlink:href="/w/transcend/latetranscend"><?xxe-sn 26n42fz1reo 1e?>Late
Transcend</link> for details.</para>
<para><?xxe-sn 26n42fz1reo 1f?>Example below demonstrates <code><?xxe-sn 26n42fz1reo 1g?>test</code>
invoking polymorphic function <code><?xxe-sn 26n42fz1reo 1h?>compute</code>:</para>
- <programlisting xml:id="LatePoly_1"><?xxe-sn 26n42fz1reo 1i?>Strategy = type variant {fast, precise}.
+ <programlisting xml:id="LatePoly_1"><?xxe-sn 26n42fz1reo 1i?>name="tests/polymorph.cpp: Polymorphs.Doc_LatePoly_1"
+Strategy = type variant {fast, precise}.
guard:: fast
{
compute = function:: int
{0}
}
guard:: precise
{
compute = function:: int
{1}
}
test = function(s:: Strategy; alias(strategy)):: int; entry
{
switch late (s):: int
{
compute():: int; guardalias(strategy)
}
}</programlisting>
<para><?xxe-sn 26n42fz1reo 1j?>Function <code><?xxe-sn 26n42fz1reo 1k?>compute</code>
has two specializations, <code><?xxe-sn 26n42fz1reo 1l?>fast</code> and
<code><?xxe-sn 26n42fz1reo 1m?>precise</code>. We see that <code><?xxe-sn 26n42fz1reo 1n?>test</code>
gets parameter <code><?xxe-sn 26n42fz1reo 1o?>s</code> that dictates exact
strategy to use. Clearly, resolution should work dynamically to cope with
cases like this, for value of parameter <code><?xxe-sn 26n42fz1reo 1p?>s</code>
not only is unknown at compile time, but it can change with each
<code><?xxe-sn 26n42fz1reo 1q?>test</code> execution.</para>
<para><?xxe-sn 26n42fz1reo 1r?>Operation Switch Late is compiled into
several branches, two in this case, each branch executing appropriate
<code><?xxe-sn 26n42fz1reo 1s?>compute</code> specialization. Correct
branch executed depending on current <code><?xxe-sn 26n42fz1reo 1t?>s</code>
value. Custom annotations <code><?xxe-sn 26n42fz1reo 1u?>alias(Alias)</code>
and <code><?xxe-sn 26n42fz1reo 1v?>guardalias(Alias)</code> used to assign
an alias in order to specify which parameter to use for as basis for
resolution</para>
</section>
<section>
<?xxe-sn 26n42fz1reo 1w?>
<title><?xxe-sn 26n42fz1reo 1x?>Auto Expansion of Late Parameters</title>
<para><?xxe-sn 26n42fz1reo 1y?>In previous example, switch late operation
was used to facilitate calling of polymorphic function with late
polymorphism resolution. It's not that convenient to wrap each invocation
by switch late whenever there is need to call late polymorphic function.
Specifically to handle cases like this, compiler uses late parameter auto
expansion technique.</para>
<para><?xxe-sn 26n42fz1reo 1z?>If compiler discovers that <code><?xxe-sn 26n42fz1reo 20?>late(dfa_callguard())</code>
entry exists for current invocation and it does not have enclosing switch
late already, compiler automatically generates different branches that
invoke relevant specializations and transfers control to a branch
depending on late parameter value. In other words invocation implicitly
wrapped into switch late instruction if needed.</para>
</section>
</chapter>
<?xxe-revisions
+#2 2019-02-20T12:19:58Z pgess
#1 2018-12-12T21:49:13Z pgess
+1sPEAAAByDQAGMdHAAALB3OicBMFQ5B0U5NeAJpsiECRKg==
+
?>
\ No newline at end of file
diff --git a/documentation/Syntax/modules.xml b/documentation/Syntax/modules.xml
index c08f132..649dfa8 100644
--- a/documentation/Syntax/modules.xml
+++ b/documentation/Syntax/modules.xml
@@ -1,325 +1,335 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<?xxe-sn 26n42fz1reo 21?>
<title><?xxe-sn 26n42fz1reo 22?>Modules</title>
<para><?xxe-sn 26n42fz1reo 23?>Xreate offers <emphasis><?xxe-sn 26n42fz1reo 24?>modules</emphasis>
as a way to organize and reuse source code. For simplicity, it's implemented
as one file—one module.</para>
<para><?xxe-sn 26n42fz1reo 25?>Modules often require prior compilation of
other modules for correct work. It leads to a problem of a
<emphasis><?xxe-sn 26n42fz1reo 26?>resolution</emphasis> where required
module is located. Especially since modern software products usually have
complicated and volatile file structure depending on exact configuration and
platform to build. Common practice is to rely on build configuration tools
to provide exact path for each module.</para>
<para><?xxe-sn 26n42fz1reo 27?>For this reason Xreate interferes as little
as possible with resolution. Language does not support for module to
directly specify any path be it relative or absolute of other required
modules. Also compiler does not search modules in some predefined list of
directories and does not assume anything about project's file structure. It
expects resolution information already fully defined before
compilation.</para>
<para><?xxe-sn 26n42fz1reo 28?>However compiler has optional built-in
functionality to facilitate resolution. It is the very kind of problems the
transcend level suited excellently for. It is modeled as <emphasis><?xxe-sn 26n42fz1reo 29?>supply
and demand</emphasis> approach and lets modules to declare what they
<emphasis><?xxe-sn 26n42fz1reo 2a?>provide</emphasis> and what
<emphasis><?xxe-sn 26n42fz1reo 2b?>require</emphasis> expressed by
annotations. Compiler then tries to satisfy requirements and find a match.
Alternatively, external tools always can be used.</para>
<section>
<?xxe-sn 26n42fz1reo 2c?>
<title><?xxe-sn 26n42fz1reo 2d?>Module Headers</title>
<synopsis><?xxe-sn 26n42fz1reo 2e?>SYNTAX:
**module** [:: //annotations-list// ] (Full form)
{
//module-statement//...
}</synopsis>
<synopsis><?xxe-sn 26n42fz1reo 2f?>**module** :: //annotations-list// . (Simplified form)</synopsis>
<synopsis><?xxe-sn 26n42fz1reo 2g?>//module-statement// ::=
| **require** ( //annotation// ). (1)
| **discover** ( //path// ). (2)
| **controller** (//path//). (3)</synopsis>
<itemizedlist>
<?xxe-sn 26n42fz1reo 2h?>
<listitem>
<?xxe-sn 26n42fz1reo 2i?>
<para><?xxe-sn 26n42fz1reo 2j?><code><?xxe-sn 26n42fz1reo 2k?>annotations-list</code>
List of annotations delimited by semicolon</para>
</listitem>
<listitem>
<?xxe-sn 26n42fz1reo 2l?>
<para><?xxe-sn 26n42fz1reo 2m?><code><?xxe-sn 26n42fz1reo 2n?>annotation</code>
Any valid transcend expression</para>
</listitem>
<listitem>
<?xxe-sn 26n42fz1reo 2o?>
<para><?xxe-sn 26n42fz1reo 2p?><code><?xxe-sn 26n42fz1reo 2q?>path</code>
Absolute or relative path to controller</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26n42fz1reo 2r?>Xreate recognizes number of module
management statements. Those statements should be located in specific
section <code><?xxe-sn 26n42fz1reo 2s?>module {...}</code> of a source
code which is called <emphasis><?xxe-sn 26n42fz1reo 2t?>module
header</emphasis>. Module can have several headers. All headers gathered
from a whole file are combined into one before actual processing.</para>
<note>
<?xxe-sn 26n42fz1reo 2u?>
<para><?xxe-sn 26n42fz1reo 2v?>Modules processing happens before
compilation. It means any data produced in course of compilation is
inaccessible at this stage</para>
</note>
</section>
<section>
<?xxe-sn 26n42fz1reo 2w?>
<title><?xxe-sn 26n42fz1reo 2x?>Requesting Modules</title>
<para><?xxe-sn 26n42fz1reo 2y?>Statement <code><?xxe-sn 26n42fz1reo 2z?>require(..)</code>
expresses which modules are required for correct compilation.</para>
- <programlisting xml:id="Requesting_Modules_1"><?xxe-sn 26n42fz1reo 30?>module {
+ <programlisting xml:id="Requesting_Modules_1"><?xxe-sn 26n42fz1reo 30?>name="tests/modules.cpp: Modules.Doc_Requesting_Modules_1"
+module {
require(logger).
}</programlisting>
<para><?xxe-sn 26n42fz1reo 31?>In this example module in question requires
some other module that <emphasis><?xxe-sn 26n42fz1reo 32?>provides</emphasis>
feature called <code><?xxe-sn 26n42fz1reo 33?>logger</code>. There is no
way to specify direct external module location. Instead, module expresses
requirement in abstract form as propositional expression which is later
used by resolution to find exact match.</para>
- <programlisting xml:id="Requesting_Modules_2"><?xxe-sn 26n42fz1reo 34?>module{require(stringslib).}
+ <programlisting xml:id="Requesting_Modules_2"><?xxe-sn 26n42fz1reo 34?>name="tests/modules.cpp: Modules.Doc_Requesting_Modules_2"
+module{require(stringslib).}
processString = function(a:: string):: string
{
someStrFunc(a)
}
module{require(mathlib).}
processNumber = function(a:: num):: num
{
someMathFunc(a)
}</programlisting>
<para><?xxe-sn 26n42fz1reo 35?>Example above demonstrates using several
headers in one file. It's particularly useful if developer finds it
convenient to put requirements near the actual code that uses it. This way
it can be easily spotted when requirements are no more needed. After all,
code locality improves readability.</para>
</section>
<section>
<?xxe-sn 26n42fz1reo 36?>
<title><?xxe-sn 26n42fz1reo 37?>Module Annotations</title>
<para><?xxe-sn 26n42fz1reo 38?>Module can declare additional information
for various uses. This is expressed by annotations located in the header.
They are called module annotations. For instance, module annotations can
be used by module resolution to find modules that satisfy requirements of
others.</para>
- <programlisting xml:id="ModuleAnnotations_1"><?xxe-sn 26n42fz1reo 39?>module:: status(obsolete).</programlisting>
+ <programlisting xml:id="ModuleAnnotations_1"><?xxe-sn 26n42fz1reo 39?>name="tests/modules.cpp: Modules.Doc_ModuleAnnotations_1"
+module:: status(obsolete).</programlisting>
<para><?xxe-sn 26n42fz1reo 3a?>The example shows module that declares its
status. It can be used by resolution to choose most appropriate module out
of number of candidates. One way to view annotations used by resolution is
to treat them as something that module <emphasis><?xxe-sn 26n42fz1reo 3b?>provides</emphasis>.</para>
<note>
<?xxe-sn 26n42fz1reo 3c?>
<para><?xxe-sn 26n42fz1reo 3d?>There are no predefined module
annotations and developer can put arbitrary information there.</para>
</note>
</section>
<section>
<?xxe-sn 26n42fz1reo 3e?>
<title><?xxe-sn 26n42fz1reo 3f?>Modules Resolution</title>
<para><?xxe-sn 26n42fz1reo 3g?>Modules resolution is a process to find
exact modules locations that match requests. Compiler does not search
modules in predefined directories and does not assume anything about
project's file structure. In order to allow developer to determine it
themselves the compiler refers to two transcend tables</para>
<synopsis><?xxe-sn 26n42fz1reo 3h?>SYNTAX:
**modules_resolution**(//request//, //module-resolved//). (1)
**modules_resolution**(//request//, //module-resolved//, //module-context//). (2)</synopsis>
<itemizedlist>
<?xxe-sn 26n42fz1reo 3i?>
<listitem>
<?xxe-sn 26n42fz1reo 3j?>
<para><?xxe-sn 26n42fz1reo 3k?><emphasis><?xxe-sn 26n42fz1reo 3l?>request</emphasis>
annotation used in statement <code><?xxe-sn 26n42fz1reo 3m?>request(...)</code></para>
</listitem>
<listitem>
<?xxe-sn 26n42fz1reo 3n?>
<para><?xxe-sn 26n42fz1reo 3o?><emphasis><?xxe-sn 26n42fz1reo 3p?>module-resolved</emphasis>
Path or identifier of a module that matches request</para>
</listitem>
<listitem>
<?xxe-sn 26n42fz1reo 3q?>
<para><?xxe-sn 26n42fz1reo 3r?><emphasis><?xxe-sn 26n42fz1reo 3s?>module-context</emphasis>
Path or identifier of a module that requires other module</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26n42fz1reo 3t?>These tables contain resolved modules for
all possible requests. Form (1) contains requests that should always be
resolved to the same module. Form (2) contains such requests for which
resolution depends on requesting module <emphasis><?xxe-sn 26n42fz1reo 3u?>module-context</emphasis>.</para>
- <programlisting xml:id="ModulesResolution_1"><?xxe-sn 26n42fz1reo 3v?> modules_resolution(numlib, "/path/to/numlib").
- modules_resolution(strings, "/path/to/ansi-lib", "moduleA").
- modules_resolution(strings, "/path/to/utf8-lib", "moduleB"). </programlisting>
+ <programlisting xml:id="ModulesResolution_1"><?xxe-sn 26n42fz1reo 3v?>name="tests/modules.cpp: Modules.Doc_ModulesResolution_1"
+modules_resolution(numlib, "/path/to/numlib").
+modules_resolution(strings, "/path/to/ansi-lib", "moduleA").
+modules_resolution(strings, "/path/to/utf8-lib", "moduleB"). </programlisting>
<para><?xxe-sn 26n42fz1reo 3w?>For the example above the compiler would
always resolve path to numerical lib(<code><?xxe-sn 26n42fz1reo 3x?>numlib</code>)
as "/path/to/numlib" (line 1). However <code><?xxe-sn 26n42fz1reo 3y?>strings</code>
library would be resolved as "/path/to/ansi-lib" if requested in
<code><?xxe-sn 26n42fz1reo 3z?>moduleA</code>(line 2) and as
"/path/to/utf8-lib" if requested in <code><?xxe-sn 26n42fz1reo 40?>moduleB</code>(line
3).</para>
<para><?xxe-sn 26n42fz1reo 41?>When compiler encounters module request it
looks up table <code><?xxe-sn 26n42fz1reo 42?>modules_resolution</code>
(first or second form) to find path of the requested module. Tables can be
populated by any means be it either transcend reasoning or external
tools.</para>
<note>
<?xxe-sn 26n42fz1reo 43?>
<para><?xxe-sn 26n42fz1reo 44?>There is no defined order or priority or
fall back behavior while looking into tables. If the same request occurs
in both tables they are considered to be ill-formed</para>
</note>
</section>
<section>
<?xxe-sn 26n42fz1reo 45?>
<title><?xxe-sn 26n42fz1reo 46?>Advanced Modules Resolution</title>
<para><?xxe-sn 26n42fz1reo 47?>Xreate provide additional layer, optional
helper to simplify modules management. It introduces two more built-in
statements that can be used in module header: <emphasis><?xxe-sn 26n42fz1reo 48?>Discover</emphasis>
statement and <emphasis><?xxe-sn 26n42fz1reo 49?>Controller</emphasis>
Statement.</para>
<itemizedlist>
<?xxe-sn 26n42fz1reo 4a?>
<listitem>
<?xxe-sn 26n42fz1reo 4b?>
<para><?xxe-sn 26n42fz1reo 4c?><emphasis><?xxe-sn 26n42fz1reo 4d?>Discover
Statement</emphasis> has the form <code><?xxe-sn 26n42fz1reo 4e?>discover
(<emphasis><?xxe-sn 26n42fz1reo 4f?>path</emphasis>)</code>.It allows
to specify directory where compiler would recursively search for all
xreate files and extract module header annotations. It gathers info
about all found source files.</para>
</listitem>
<listitem>
<?xxe-sn 26n42fz1reo 4g?>
<para><?xxe-sn 26n42fz1reo 4h?><emphasis><?xxe-sn 26n42fz1reo 4i?>Controller
Statement</emphasis> has the form <code><?xxe-sn 26n42fz1reo 4j?>controller
(<emphasis><?xxe-sn 26n42fz1reo 4k?>path</emphasis>)</code> and
specifies path to modules resolution controller. Controller is a file
that contains transcend rules in order to process data gathered by
discovery and populate resolution tables as its result of work.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26n42fz1reo 4l?>Example below shows 3 modules:</para>
- <programlisting xml:id="AdvModRes_1"><?xxe-sn 26n42fz1reo 4m?>//First Module
+ <programlisting xml:id="AdvModRes_1"><?xxe-sn 26n42fz1reo 4m?>name="tests/modules.cpp: Modules.Doc_AdvModRes_1"
+
+//First Module
module::
- name(testA);
- provide(superService);
- status(needToTestEvenMore).
+ name(testA);
+ provide(superService);
+ status(needToTestEvenMore).
//Second Module
module::
- name(testB);
- provide(superService);
- status(needToTest).
+ name(testB);
+ provide(superService);
+ status(needToTest).
//Third Module
module {
- require(superService).
- discover("/modules/path/").
- controller("/path/to/controller").
+ require(superService).
+ discover("/modules/path/").
+ controller("/path/to/controller").
}</programlisting>
<para><?xxe-sn 26n42fz1reo 4n?>Two modules offer the same feature
<code><?xxe-sn 26n42fz1reo 4o?>provide(superSerivce)</code>. Third module
requires it and specifies directory where to look up for needed files.
Controller's task is to populate resolution table if needed module is
found and choose appropriate candidate, if more than one module offer this
service.</para>
<para><?xxe-sn 26n42fz1reo 4p?>One way to decide what to choose in this
example is to look at status of both modules. Let score be assigned to
each possible status. Let's say <code><?xxe-sn 26n42fz1reo 4q?>0</code>
for <code><?xxe-sn 26n42fz1reo 4r?>status(needToTestEvenMore)</code>,
<code><?xxe-sn 26n42fz1reo 4s?>1</code> for <code><?xxe-sn 26n42fz1reo 4t?>status(needToTest)</code>.
Then controller would proceed with the best scoring module,
<code><?xxe-sn 26n42fz1reo 4u?>Second Module</code> in this case.</para>
</section>
<section>
<?xxe-sn 26n42fz1reo 4v?>
<title><?xxe-sn 26n42fz1reo 4w?>See Also</title>
<para><?xxe-sn 26n42fz1reo 4x?>Transcend: <link
xlink:href="/w/transcend/modules-api"><?xxe-sn 26n42fz1reo 4y?>Modules
API</link></para>
</section>
</chapter>
<?xxe-revisions
+#2 2019-02-20T12:15:04Z pgess
#1 2018-12-12T21:49:18Z pgess
+1sPEAAAB41YAZ+FRAAE8JCBzoWsThB8jBkOHeGOSBwEBUwgzKCMVEwdTI3MVgwdDlFkzGkMRUxtj
+OpMLMwaTG1MxEwpjDSMEMyAziUUAoiauc4RgiDKDQJJIMacPQuWPPZUMGA8ZI0MyHaIvCpZrSB4=
+
?>
\ No newline at end of file
diff --git a/documentation/Syntax/syntax.xml b/documentation/Syntax/syntax.xml
index 95f2184..209abbb 100644
--- a/documentation/Syntax/syntax.xml
+++ b/documentation/Syntax/syntax.xml
@@ -1,956 +1,959 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<?xxe-sn 26yv439af40 59?>
<title><?xxe-sn 26yv439af40 5a?>Syntax</title>
<para><?xxe-sn 26yv439af40 5b?><informaltable>
<?xxe-sn 26yv439af40 5c?>
<tgroup cols="3">
<?xxe-sn 26yv439af40 5d?>
<tbody>
<?xxe-sn 26yv439af40 5e?>
<row>
<?xxe-sn 26yv439af40 5f?>
<entry><?xxe-sn 26yv439af40 5g?>Literals, Expressions, Basic
Statements</entry>
<entry><?xxe-sn 26yv439af40 5h?>Annotations</entry>
<entry><?xxe-sn 26yv439af40 5i?>Intrinsics: query</entry>
</row>
<row>
<?xxe-sn 26yv439af40 5j?>
<entry><?xxe-sn 26yv439af40 5k?>Identifiers, Code Blocks</entry>
<entry><?xxe-sn 26yv439af40 5l?>Branch Statements</entry>
<entry><?xxe-sn 26yv439af40 5m?>Interfaces: Extern-C</entry>
</row>
<row>
<?xxe-sn 26yv439af40 5n?>
<entry><?xxe-sn 26yv439af40 5o?>Functions</entry>
<entry><?xxe-sn 26yv439af40 5p?>Loops</entry>
<entry><?xxe-sn 26yv439af40 5q?>Other: Transcend, Versions</entry>
</row>
<row>
<?xxe-sn 26yv439af40 5r?>
<entry><?xxe-sn 26yv439af40 5s?>Types</entry>
<entry><?xxe-sn 26yv439af40 5t?>Variants</entry>
<entry><?xxe-sn 26yv439af40 5u?></entry>
</row>
</tbody>
</tgroup>
</informaltable></para>
<para><?xxe-sn 26yv439af40 5v?>There are number of principles Xreate syntax
based on:</para>
<itemizedlist>
<?xxe-sn 26yv439af40 5w?>
<listitem>
<?xxe-sn 26yv439af40 5x?>
<para><?xxe-sn 26yv439af40 5y?>Follows SSA form: each identifier is
defined only once and no redefinitions allowed</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 5z?>
<para><?xxe-sn 26yv439af40 60?>Order in which identifiers are defined
does not influence computation order. Identifiers are computed in order
based on dependencies between expressions. Order in which identifiers
are defines reflects personal preferences and what is convenient for a
developer.</para>
</listitem>
</itemizedlist>
<section>
<?xxe-sn 26yv439af40 61?>
<title><?xxe-sn 26yv439af40 62?>Literals and expressions</title>
<para><?xxe-sn 26yv439af40 63?>Xreate expressions have a form:</para>
<synopsis><?xxe-sn 26yv439af40 64?>SYNTAX:
//expression// [:: //type//; //annotations-list// ]</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 fd?>
<listitem>
<?xxe-sn 26yv439af40 fe?>
<para><?xxe-sn 26yv439af40 ff?><emphasis><?xxe-sn 26yv439af40 fg?>annotation-list</emphasis>
is a list of annotations delimited by semicolon.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 67?>Expressions consist of literals and various
operations as follows:</para>
<informaltable>
<?xxe-sn 26yv439af40 68?>
<tgroup cols="2">
<?xxe-sn 26yv439af40 69?>
<colspec colwidth="115*"><?xxe-sn 26yv439af40 6a?></colspec>
<colspec colwidth="885*"><?xxe-sn 26yv439af40 6b?></colspec>
<tbody>
<?xxe-sn 26yv439af40 6c?>
<row>
<?xxe-sn 26yv439af40 6d?>
<entry><?xxe-sn 26yv439af40 6e?>Literals</entry>
<entry><?xxe-sn 26yv439af40 6f?>numbers, strings: <code><?xxe-sn 26yv439af40 6g?>5,
"Nimefurahi kukujua"</code></entry>
</row>
<row>
<?xxe-sn 26yv439af40 6h?>
<entry><?xxe-sn 26yv439af40 6i?>Lists, records</entry>
<entry><?xxe-sn 26yv439af40 6j?>Record is a collection of elements
- of different types - <code><?xxe-sn 26yv439af40 6k?>{year = 1934,
+ of different types — <code><?xxe-sn 26yv439af40 6k?>{year = 1934,
month = "april"}</code>. List is a collection of elements of the
- same type without keys - <code><?xxe-sn 26yv439af40 6l?>{16, 8,
- 3}</code></entry>
+ same type without keys — <code><?xxe-sn 26yv439af40 6l?>{16, 8,
+ 3}</code>. Range of elements — <code><?xxe-sn 2apiasqubk0 4?>[1..18]</code>.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 6m?>
<entry><?xxe-sn 26yv439af40 6n?>Arithmetic operations</entry>
<entry><?xxe-sn 26yv439af40 6o?>Basic arithmetic operations:
<code><?xxe-sn 26yv439af40 6p?>+, -, *, /</code></entry>
</row>
<row>
<?xxe-sn 26yv439af40 6q?>
<entry><?xxe-sn 26yv439af40 6r?>Relations</entry>
<entry><?xxe-sn 26yv439af40 6s?><code><?xxe-sn 26yv439af40 6t?>==,
!=, &lt;&gt;, &lt;, &lt;=, &gt;, &gt;=</code>. Both
<code><?xxe-sn 26yv439af40 6u?>!=, &lt;&gt;</code> mean
<emphasis><?xxe-sn 26yv439af40 6v?>not equal</emphasis> relation.
Examples: <code><?xxe-sn 26yv439af40 6w?>8&gt;=3, "Blue" &lt;&gt;
"Green"</code></entry>
</row>
<row>
<?xxe-sn 26yv439af40 6x?>
<entry><?xxe-sn 26yv439af40 6y?>List and struct operations</entry>
<entry><?xxe-sn 26yv439af40 6z?><emphasis><?xxe-sn 26yv439af40 70?>index</emphasis>
operation to access individual elements of a list or a record.
Example: <code><?xxe-sn 26yv439af40 71?>colors = {"Green",
"Blue"}::[string]. color = colors[0]:: string.</code> Record's
element access: <code><?xxe-sn 26yv439af40 72?>date = {year =
1934, month = "april"}. year = date["year"]</code></entry>
</row>
<row>
<?xxe-sn 26yv439af40 73?>
<entry><?xxe-sn 26yv439af40 74?>Identifiers</entry>
<entry><?xxe-sn 26yv439af40 75?>Example: <code><?xxe-sn 26yv439af40 76?>a
- b</code></entry>
</row>
<row>
<?xxe-sn 26yv439af40 77?>
<entry><?xxe-sn 26yv439af40 78?>Functions</entry>
<entry><?xxe-sn 26yv439af40 79?>Example: <code><?xxe-sn 26yv439af40 7a?>result
= isOdd(6).</code></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section>
<?xxe-sn 26yv439af40 7b?>
<title><?xxe-sn 26yv439af40 7c?>Code Blocks</title>
<para><?xxe-sn 26yv439af40 7d?>Block is a list of expressions delimited by
period. It has a <emphasis><?xxe-sn 26yv439af40 7e?>body</emphasis> - main
expression and optionally some identifier definitions.</para>
<synopsis><?xxe-sn 26yv439af40 7f?>SYNTAX:
{
[//ident// = //expression// . | //body-expression// . ]..
}</synopsis>
<para><?xxe-sn 26yv439af40 7g?>Code block consists of <emphasis><?xxe-sn 26yv439af40 7h?>body
expression</emphasis> and optional set of assignments to define
identifiers used in body expression. Block's computation is defined as a
result of associated body expression's computation. Identifiers are
computed before expressions they are used in.</para>
<programlisting xml:id="CodeBlocks1"><?xxe-sn 26yv439af40 7i?>name="tests/ast.cpp: AST.Doc_CodeBlocks1"
test = function:: int
{
a = 10:: int.
b = 2:: int.
a + b:: int
}</programlisting>
<para><?xxe-sn 26yv439af40 7j?>Above is an example of code block which
have <code><?xxe-sn 26yv439af40 7k?>a+b</code> as a body expression. In
this case body depends on identifiers <code><?xxe-sn 26yv439af40 7l?>a</code>,
<code><?xxe-sn 26yv439af40 7m?>b</code> so compiler computes both of them
beforehand.</para>
<para><?xxe-sn 26yv439af40 7n?>Computation order depends only on
dependencies between expressions. This approach has properties as
follows:</para>
<itemizedlist>
<?xxe-sn 26yv439af40 7o?>
<listitem>
<?xxe-sn 26yv439af40 7p?>
<para><?xxe-sn 26yv439af40 7q?>Mutually independent identifiers can be
evaluated in any order</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 7r?>
<para><?xxe-sn 26yv439af40 7s?>Identifier gets computed only if it's
required(even transitively) by block's body expression.</para>
</listitem>
</itemizedlist>
</section>
<section>
<?xxe-sn 26yv439af40 7t?>
<title><?xxe-sn 26yv439af40 7u?>Functions</title>
<synopsis><?xxe-sn 26yv439af40 7v?>SYNTAX:
//function-name// = **function** ([//argument//:: //type//[; //annotation-list//]]...):: //return-type// [; //annotations//]...
//function-block//</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 7w?>
<listitem>
<?xxe-sn 26yv439af40 7x?>
<para><?xxe-sn 26yv439af40 7y?><emphasis><?xxe-sn 26yv439af40 7z?>function-name</emphasis>
name of function</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 80?>
<para><?xxe-sn 26yv439af40 81?><emphasis><?xxe-sn 26yv439af40 82?>argument</emphasis>
formal parameter. Arguments are delimited by comma.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 83?>
<para><?xxe-sn 26yv439af40 84?><emphasis><?xxe-sn 26yv439af40 85?>type</emphasis>,
<emphasis><?xxe-sn 26yv439af40 86?>return-type</emphasis> formal
parameter and returning value types</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 87?>
<para><?xxe-sn 26yv439af40 88?><emphasis><?xxe-sn 26yv439af40 89?>function-block</emphasis>
code block that acts as a function's definition</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 8a?>
<para><?xxe-sn 26yv439af40 8b?><emphasis><?xxe-sn 26yv439af40 8c?>annotations</emphasis>
list of annotations delimited by semicolon</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 8d?>Below is an example of a function
<code><?xxe-sn 26yv439af40 8e?>sum</code>. It takes two arguments and
returns their sum. Also it defines several annotations. First annotation
<code><?xxe-sn 26yv439af40 8f?>entry</code> has a special meaning — it
depicts entry point or main function in a program. Second annotation
<code><?xxe-sn 26yv439af40 8g?>status(needs_review)</code> is a
demonstration that developers can annotate function using custom
annotations to express different properties.</para>
<programlisting xml:id="Functions1"><?xxe-sn 26yv439af40 8h?>name="tests/ast.cpp: AST.Doc_Functions1"
sum = function(x:: int, y:: int):: int; entry; status(needs_review)
{
x+y
}</programlisting>
</section>
<section>
<?xxe-sn 26yv439af40 8i?>
<title><?xxe-sn 26yv439af40 8j?>Function Specializations</title>
<synopsis><?xxe-sn 26yv439af40 8k?>SYNTAX:
**guard**:: //annotation//
{
//functions-list//
}</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 8l?>
<listitem>
<?xxe-sn 26yv439af40 8m?>
<para><?xxe-sn 26yv439af40 8n?><emphasis><?xxe-sn 26yv439af40 8o?>annotation</emphasis>
Guard expressed by annotation</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 8p?>
<para><?xxe-sn 26yv439af40 8q?><emphasis><?xxe-sn 26yv439af40 8r?>functions-list</emphasis>
one or more function that share the same guard</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 8s?>Xreate allows several functions to share
the same name. In which case they are called <emphasis><?xxe-sn 26yv439af40 fk?>
specializations</emphasis>. This is syntactic foundation for
<emphasis><?xxe-sn 26yv439af40 8u?>function level polymorphism</emphasis>,
i.e. ability for compiler to decide which exactly function is called out
of several options. Polymorphism resolution can happen during compilation
or at run-time.</para>
<para><?xxe-sn 26yv439af40 8v?>Functions with the same name, i.e.
different specializations should have additional unique identifiers called
<emphasis><?xxe-sn 26yv439af40 8w?>guards</emphasis>. When function is
actually called it's expected that resolution is already done at some
point before and supplies correct guard to uniquely specify which exactly
specialization to call.</para>
<para><?xxe-sn 26yv439af40 8x?>Example:</para>
<programlisting xml:id="FunctionSpecialization1"><?xxe-sn 26yv439af40 8y?>name="tests/ast.cpp: AST.Doc_FunctionSpecializations1"
guard:: safe_enviroment
{
sum = function (a::int, b::int) :: int
{
a + b
}
}</programlisting>
<note>
<?xxe-sn 26yv439af40 8z?>
<para><?xxe-sn 26yv439af40 90?>See <link
xlink:href="/w/transcend/ast-api#function-s-specializatio"><?xxe-sn 26yv439af40 91?>API</link>
to get more information on how guards are processed</para>
</note>
</section>
<section>
<?xxe-sn 26yv439af40 92?>
<title><?xxe-sn 26yv439af40 93?>Branch Statements</title>
<section>
<?xxe-sn 26yv439af40 94?>
<title><?xxe-sn 26yv439af40 95?>IF Statement</title>
<synopsis><?xxe-sn 26yv439af40 96?>SYNTAX:
**if** (//condition//):: //type// [; //annotations// ]..
//block-true//
**else**
//block-false//</synopsis>
<para><?xxe-sn 26yv439af40 97?><code><?xxe-sn 26yv439af40 fh?>IF</code>
statement executes <emphasis><?xxe-sn 26yv439af40 98?>block-true</emphasis>
or <emphasis><?xxe-sn 26yv439af40 99?>block-false</emphasis> depending
on <emphasis><?xxe-sn 26yv439af40 9a?>condition</emphasis> evaluation
result.</para>
<para><?xxe-sn 26yv439af40 9b?>Example:</para>
<programlisting xml:id="IfStatement1"><?xxe-sn 26yv439af40 9c?>name="tests/ast.cpp: AST.Doc_BranchStatements"
answer = if (question == "Favorite color?"):: string
{"Yellow"} else {"Don't know"}.</programlisting>
</section>
<section>
<?xxe-sn 26yv439af40 9d?>
<title><?xxe-sn 26yv439af40 9e?>SWITCH Statement</title>
<synopsis><?xxe-sn 26yv439af40 9f?>SYNTAX:
**switch** ( //condition// ) :: //type// [; //annotations//]..
[**case** ( //guard// ) code-block]..
**case default** //default-code-block//
</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 9g?>
<listitem>
<?xxe-sn 26yv439af40 9h?>
<para><?xxe-sn 26yv439af40 9i?><emphasis><?xxe-sn 26yv439af40 9j?>condition</emphasis>'s
result is used to decide which branch to execute next</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 9k?>
<para><?xxe-sn 26yv439af40 9l?><emphasis><?xxe-sn 26yv439af40 9m?>guard</emphasis>
value to match against <emphasis><?xxe-sn 26yv439af40 9n?>condition</emphasis></para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 9o?>
<para><?xxe-sn 26yv439af40 9p?><emphasis><?xxe-sn 26yv439af40 9q?>default-code-block</emphasis>
executed if no appropriate case found</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 9r?>SWITCH statement evaluation's result is
that of branch whose <emphasis><?xxe-sn 26yv439af40 9s?>guard</emphasis>
matches <emphasis><?xxe-sn 26yv439af40 9t?>condition</emphasis>.</para>
<para><?xxe-sn 26yv439af40 9u?>Example:</para>
<programlisting xml:id="SwitchStatement1"><?xxe-sn 26yv439af40 9v?>name="tests/ast.cpp: AST.Doc_BranchStatements"
monthName = switch(monthNum) :: string
case (1) {"Jan"}
case (2) {"Feb"}
case default {"Strange.. Don't know this month"}.</programlisting>
</section>
</section>
<section>
<?xxe-sn 26yv439af40 9w?>
<title><?xxe-sn 26yv439af40 9x?>Loop Statements</title>
<section>
<?xxe-sn 26yv439af40 9y?>
<title><?xxe-sn 26yv439af40 9z?>LOOP Statement</title>
<synopsis><?xxe-sn 26yv439af40 a0?>SYNTAX:
**loop** ( //init-value// -&gt; //accumulator// ):: //type// [; //annotations//] //loop-body//</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 a1?>
<listitem>
<?xxe-sn 26yv439af40 a2?>
<para><?xxe-sn 26yv439af40 a3?><emphasis><?xxe-sn 26yv439af40 a4?>init-value</emphasis>
initial value loop starts from</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 a5?>
<para><?xxe-sn 26yv439af40 a6?><emphasis><?xxe-sn 26yv439af40 a7?>accumulator</emphasis>
identifier which holds loop's result after each iteration</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 a8?>For each iteration <emphasis><?xxe-sn 26yv439af40 a9?>accumulator</emphasis>
assumes result of previous iteration or <emphasis><?xxe-sn 26yv439af40 aa?>init-value</emphasis>
during first iteration. Result of the <emphasis><?xxe-sn 26yv439af40 ab?>loop-body</emphasis>
evaluation is used as <emphasis><?xxe-sn 26yv439af40 ac?>accumulator</emphasis>'s
next iteration value and as overall loop statement result after the last
iteration.</para>
<para><?xxe-sn 26yv439af40 ad?>This notation does not have termination
condition. Compiler relies on loop body's fixed point in order to decide
when to interrupt loop. Let's consider example:</para>
<programlisting xml:id="LoopStatement1"><?xxe-sn 26yv439af40 ae?>COUNTEREXAMPLE, name="tests/ast.cpp: AST.Doc_LoopStatements"
//infinite loop
answer = loop (2-&gt;x) :: int
{
if(IsPerfect(x)):: int {x} else {x+1}
}.</programlisting>
<para><?xxe-sn 26yv439af40 af?>The example tests numbers for being
perfect(sum of all proper divisors equals to the number itself). While
iterating accumulator <code><?xxe-sn 26yv439af40 ag?>x</code> assumes
values as follows: 2, 3, 4, 5, 6, 6 ... After it founds first perfect
number any further iteration do not change result anymore since there is
no increment and it continues to test the same number again and again.
Obviously, <code><?xxe-sn 26yv439af40 ah?>x=6</code> is a fixed point in
this example. There is no point to continue going through further
iterations once fixed point is evaluated and hence loop can be safely
interrupted.</para>
<para><?xxe-sn 26yv439af40 ai?>Compiler relies on manually provided
annotations to recognize when fixed point is reached. There is special
annotation <code><?xxe-sn 26yv439af40 aj?>final</code> to specify fixed
point for loops. Once expression marked as <code><?xxe-sn 26yv439af40 ak?>final</code>
gets evaluated it's assumed to be a fixed point or in other words
compiler knows it's the very last iteration after which loop ends.
Correct code for the example above is:</para>
<programlisting xml:id="LoopStatement2"><?xxe-sn 26yv439af40 al?>name="tests/ast.cpp: AST.Doc_LoopStatements"
//loop exits after first perfect number is found
answer2 = loop (2-&gt;x) :: int
{
if(IsPerfect(x))::int {x:: int; final} else {x+1}
}.</programlisting>
<para><?xxe-sn 26yv439af40 am?>In this case compiler able to recognize
when fixed point is reached to exit loop. After loops is done
<code><?xxe-sn 26yv439af40 an?>answer</code> is <code><?xxe-sn 26yv439af40 ao?>6</code>.</para>
</section>
<section>
<?xxe-sn 26yv439af40 ap?>
<title><?xxe-sn 26yv439af40 aq?>LOOP FOLD Statement</title>
<synopsis><?xxe-sn 26yv439af40 ar?>SYNTAX:
**loop fold** (//list// **-&gt;** //element//:: //type// [; //annotations//], //init-value// **-&gt;** //accumulator//):: //type// [; //annotations//]
//loop-body//</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 as?>
<listitem>
<?xxe-sn 26yv439af40 at?>
<para><?xxe-sn 26yv439af40 au?><emphasis><?xxe-sn 26yv439af40 av?>list</emphasis>
to iterate through</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 aw?>
<para><?xxe-sn 26yv439af40 ax?><emphasis><?xxe-sn 26yv439af40 ay?>element</emphasis>
identifier that assumes value of currently processed list
element</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 az?>
<para><?xxe-sn 26yv439af40 b0?><emphasis><?xxe-sn 26yv439af40 b1?>type</emphasis>,
<emphasis><?xxe-sn 26yv439af40 b2?>annotations</emphasis> expression
types and optional annotations delimited by semicolon</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 b3?>
<para><?xxe-sn 26yv439af40 b4?><emphasis><?xxe-sn 26yv439af40 b5?>init-value</emphasis>
accumulator's initial value loop starts with</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 b6?>
<para><?xxe-sn 26yv439af40 b7?><emphasis><?xxe-sn 26yv439af40 b8?>accumulator</emphasis>
identifier assumes loop-body evaluation result after each
iteration</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 b9?>Iterates over <emphasis><?xxe-sn 26yv439af40 ba?>list</emphasis>
in order to accumulate result by applying <emphasis><?xxe-sn 26yv439af40 bb?>loop-body</emphasis>
transformation to each <emphasis><?xxe-sn 26yv439af40 bc?>element</emphasis>
and intermediate <emphasis><?xxe-sn 26yv439af40 bd?>accumulator</emphasis>.
Overall loop value is a accumulator's value after the last iteration. If
fixed point is found an execution terminates earlier.</para>
<para><?xxe-sn 26yv439af40 be?>Example shows code excerpt that looks for
a minimal element in the given list(and less then initial value
<code><?xxe-sn 26yv439af40 bf?>10</code>).</para>
<programlisting xml:id="FoldStatement1"><?xxe-sn 26yv439af40 bg?>name="tests/ast.cpp: AST.Doc_LoopStatements"
numbers = {4, 8, 7, 1, 5}:: [int].
min = loop fold(numbers-&gt;x:: int, 10-&gt;acc):: int
{
if (acc &gt; x):: int {x} else {acc}
}.</programlisting>
</section>
<section>
<?xxe-sn 26yv439af40 bh?>
<title><?xxe-sn 26yv439af40 bi?>LOOP MAP Statement</title>
<synopsis><?xxe-sn 26yv439af40 bj?>SYNTAX:
**loop map** (//list// **-&gt;** //element// :: //type// [; //annotations// ] ) :: //type// [; //annotations// ]
//loop-body//</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 bk?>
<listitem>
<?xxe-sn 26yv439af40 bl?>
<para><?xxe-sn 26yv439af40 bm?><emphasis><?xxe-sn 26yv439af40 bn?>list</emphasis>
to iterate through</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 bo?>
<para><?xxe-sn 26yv439af40 bp?><emphasis><?xxe-sn 26yv439af40 bq?>element</emphasis>
identifier that assumes value of currently processed list
element</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 br?>
<para><?xxe-sn 26yv439af40 bs?><emphasis><?xxe-sn 26yv439af40 bt?>type</emphasis>,
<emphasis><?xxe-sn 26yv439af40 bu?>annotations</emphasis> type and
optional annotations delimited by semicolon.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 bv?>
<para><?xxe-sn 26yv439af40 bw?><emphasis><?xxe-sn 26yv439af40 bx?>loop-body</emphasis></para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 by?>Iterates over input <emphasis><?xxe-sn 26yv439af40 bz?>list</emphasis>
and applies <emphasis><?xxe-sn 26yv439af40 c0?>loop-body</emphasis>
transformation to each element. Result is a list that consists of all
transformed elements.</para>
<programlisting xml:id="MapStatement1"><?xxe-sn 26yv439af40 c1?>name="tests/ast.cpp: AST.Doc_LoopStatements"
odd_numbers = {1, 3, 5}:: [int].
even_numbers = loop map(odd_numbers-&gt;number::int) :: [int]
{ 2 * number }.</programlisting>
<para><?xxe-sn 26yv439af40 c2?>Example demonstrates creating
<code><?xxe-sn 26yv439af40 c3?>even_number</code> list by multiplying by
2 every element of <code><?xxe-sn 26yv439af40 c4?>odd_numbers</code>.</para>
</section>
</section>
<section>
<?xxe-sn 26yv439af40 c5?>
<title><?xxe-sn 26yv439af40 c6?>Types</title>
<para><?xxe-sn 26yv439af40 c7?>Primitive Types</para>
<informaltable>
<?xxe-sn 26yv439af40 c8?>
<tgroup cols="2">
<?xxe-sn 26yv439af40 c9?>
<colspec colwidth="173*"><?xxe-sn 26yv439af40 ca?></colspec>
<colspec colwidth="827*"><?xxe-sn 26yv439af40 cb?></colspec>
<tbody>
<?xxe-sn 26yv439af40 cc?>
<row>
<?xxe-sn 26yv439af40 cd?>
<entry><?xxe-sn 26yv439af40 ce?><code><?xxe-sn 26yv439af40 cf?>num</code></entry>
<entry><?xxe-sn 26yv439af40 cg?><code><?xxe-sn 26yv439af40 ch?>i32</code>
- alias. Reserved for auto detected most appropriate either integral
- of floating-point number type</entry>
+ alias. Reserved as a placeholder for auto detected appropriate
+ either integral of floating-point type</entry>
</row>
<row>
<?xxe-sn 26yv439af40 ci?>
<entry><?xxe-sn 26yv439af40 cj?><code><?xxe-sn 26yv439af40 ck?>int</code></entry>
<entry><?xxe-sn 26yv439af40 cl?><code><?xxe-sn 26yv439af40 cm?>i32</code>
- alias. Reserved for auto detected most appropriate integral number
- type</entry>
+ alias. Reserved as a placeholder for auto detected appropriate
+ integral type</entry>
</row>
<row>
<?xxe-sn 26yv439af40 cn?>
<entry><?xxe-sn 26yv439af40 co?><code><?xxe-sn 26yv439af40 cp?>float</code></entry>
<entry><?xxe-sn 26yv439af40 cq?>Double precision floating-point
number</entry>
</row>
<row>
<?xxe-sn 26yv439af40 cr?>
<entry><?xxe-sn 26yv439af40 cs?><code><?xxe-sn 26yv439af40 ct?>bool</code></entry>
<entry><?xxe-sn 26yv439af40 cu?>Boolean type</entry>
</row>
<row>
<?xxe-sn 26yv439af40 cv?>
<entry><?xxe-sn 26yv439af40 cw?><code><?xxe-sn 26yv439af40 cx?>i8,
i32, i64</code></entry>
<entry><?xxe-sn 26yv439af40 cy?>Signed integers. 8, 32, 64 bit
wide respectively</entry>
</row>
<row>
<?xxe-sn 26yv439af40 cz?>
<entry><?xxe-sn 26yv439af40 d0?><code><?xxe-sn 26yv439af40 d1?>string</code></entry>
<entry><?xxe-sn 26yv439af40 d2?>Pointer to a null terminated ANSI
char string. Reserved for auto detected most appropriate string
type.</entry>
</row>
<row>
<?xxe-sn 26yv439af40 d3?>
<entry><?xxe-sn 26yv439af40 d4?><code><?xxe-sn 26yv439af40 d5?>*</code></entry>
<entry><?xxe-sn 26yv439af40 d6?>Unspecified type. Example
<code><?xxe-sn 26yv439af40 d7?>x = {amount=200,
currency="USD"}::*.</code></entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para><?xxe-sn 26yv439af40 d8?>Compound types:</para>
<informaltable>
<?xxe-sn 26yv439af40 d9?>
<tgroup cols="2">
<?xxe-sn 26yv439af40 da?>
<colspec colwidth="312*"><?xxe-sn 26yv439af40 db?></colspec>
<colspec colwidth="688*"><?xxe-sn 26yv439af40 dc?></colspec>
<tbody>
<?xxe-sn 26yv439af40 dd?>
<row>
<?xxe-sn 26yv439af40 de?>
<entry><?xxe-sn 26yv439af40 df?><code><?xxe-sn 26yv439af40 dg?>[
<emphasis><?xxe-sn 26yv439af40 dh?>element-type</emphasis>
]</code></entry>
<entry><?xxe-sn 26yv439af40 di?>List of elements of the same type
<emphasis><?xxe-sn 26yv439af40 dj?>element-type</emphasis>.
Example: <code><?xxe-sn 26yv439af40 dk?>[int]</code> - list of
<code><?xxe-sn 26yv439af40 dl?>int</code>'s</entry>
</row>
<row>
<?xxe-sn 26yv439af40 dm?>
<entry><?xxe-sn 26yv439af40 dn?><code><?xxe-sn 26yv439af40 do?>{<emphasis><?xxe-sn 26yv439af40 dp?>key</emphasis>::
<emphasis><?xxe-sn 26yv439af40 dq?>type</emphasis>,
...}</code></entry>
<entry><?xxe-sn 26yv439af40 dr?>List of elements of different type
possibly with named keys. Examples: <code><?xxe-sn 26yv439af40 ds?>{int,
string}</code>, <code><?xxe-sn 26yv439af40 dt?>{name::string,
age::int}</code></entry>
</row>
<row>
<?xxe-sn 26yv439af40 du?>
<entry><?xxe-sn 26yv439af40 dv?><code><?xxe-sn 26yv439af40 dw?>variant
{<emphasis><?xxe-sn 26yv439af40 dx?>option</emphasis> ::
(<emphasis><?xxe-sn 26yv439af40 dy?>type</emphasis>, ...},
...}</code></entry>
<entry><?xxe-sn 26yv439af40 dz?>Holds a single element of type of
one out of number of options. Examples: <code><?xxe-sn 26yv439af40 e0?>variant
{FullAddress:: {string, string, string}, ShortAddress::
{string}}</code></entry>
</row>
<row>
<?xxe-sn 26yv439af40 e1?>
<entry><?xxe-sn 26yv439af40 e2?><code><?xxe-sn 26yv439af40 e3?>slave
<emphasis><?xxe-sn 26yv439af40 e4?>identifier</emphasis></code></entry>
<entry><?xxe-sn 26yv439af40 e5?>Type determined by Transcend.
Example: <code><?xxe-sn 26yv439af40 e6?>slave
unit_test</code></entry>
</row>
<row>
<?xxe-sn 26yv439af40 e7?>
<entry><?xxe-sn 26yv439af40 e8?><code><?xxe-sn 26yv439af40 e9?><emphasis><?xxe-sn 26yv439af40 ea?>compound-type</emphasis>
[ <emphasis><?xxe-sn 26yv439af40 eb?>key</emphasis>
]</code></entry>
<entry><?xxe-sn 26yv439af40 ec?>Accessing elements of compound
type. Example: <code><?xxe-sn 26yv439af40 ed?>Bio = type
{birth_year:: int, name:: string}. Year = type
Bio[birth_year].</code></entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para><?xxe-sn 26yv439af40 ee?>New types defined as:</para>
<synopsis><?xxe-sn 26yv439af40 ef?>SYNTAX:
//type-name// = **type** (//parameters//...) //type-definition// .</synopsis>
<para><?xxe-sn 26yv439af40 eg?>Example:</para>
<programlisting xml:id="Types1"><?xxe-sn 26yv439af40 eh?>name="tests/ast.cpp: AST.Doc_Types"
Tuple = type {string, int}.
Int = type Tuple[1]. //accessing by index</programlisting>
</section>
<section>
<?xxe-sn 26yv439af40 ei?>
<title><?xxe-sn 26yv439af40 ej?>Variants and SWITCH VARIANT
Instruction</title>
<synopsis><?xxe-sn 26yv439af40 ek?>SYNTAX:
**switch variant** ( //condition// [-&gt; //alias// ] [:: //type// [; //annotations//... ] ] ) :: type [; annotations... ]
[ **case** ( //guard// ) //case-branch// ]...</synopsis>
<itemizedlist>
<?xxe-sn 26yv439af40 el?>
<listitem>
<?xxe-sn 26yv439af40 em?>
<para><?xxe-sn 26yv439af40 en?><emphasis><?xxe-sn 26yv439af40 eo?>condition</emphasis>
expression of variant type</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 ep?>
<para><?xxe-sn 26yv439af40 eq?><emphasis><?xxe-sn 26yv439af40 er?>alias</emphasis>
identifier to denote unwrapped content of condition withing case
branches.</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 es?>
<para><?xxe-sn 26yv439af40 et?><emphasis><?xxe-sn 26yv439af40 eu?>guard</emphasis>
name of variant to match against actual condition's variant</para>
</listitem>
<listitem>
<?xxe-sn 26yv439af40 ev?>
<para><?xxe-sn 26yv439af40 ew?><emphasis><?xxe-sn 26yv439af40 ex?>case-branch</emphasis>
block of code to execute in case of matched variant. Content is
accessible by using alias Within the branch .</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 26yv439af40 ey?>Sometimes it is useful for a variable to
have value of different types depending on some conditions, in other words
it has <emphasis><?xxe-sn 26yv439af40 ez?>variant type</emphasis>.</para>
<para><?xxe-sn 26yv439af40 f0?>Let's consider example with variable
<code><?xxe-sn 26yv439af40 fi?>month</code> of variant type
<code><?xxe-sn 26yv439af40 fj?>Month</code>:</para>
<programlisting xml:id="Variants1"><?xxe-sn 26yv439af40 f3?>name="tests/ast.cpp: AST.Doc_Variants"
Month = type variant {
MonName :: {string},
MonNumber:: {int}
}.
test = function:: Month
{
month = MonName("April"):: Month.
month
}</programlisting>
<para><?xxe-sn 26yv439af40 f4?>Variable <code><?xxe-sn 26yv439af40 f5?>month</code>
holds value of either <code><?xxe-sn 26yv439af40 f6?>string</code> or
<code><?xxe-sn 26yv439af40 f7?>int</code> type. Value is not accessible
directly. It should be <emphasis><?xxe-sn 26yv439af40 f8?>unwrapped</emphasis>
before using. Xreate supports <code><?xxe-sn 26yv439af40 f9?>switch variant</code>
instruction for this operation.</para>
<para><?xxe-sn 26yv439af40 fa?>As an example below is function
<code><?xxe-sn 26yv439af40 fb?>nextMonth</code>'s definition:</para>
<programlisting><?xxe-sn 26yv439af40 fc?>nextMonth = function(month:: Month):: Month
{
switch variant(month):: Month
case (MonName)
{
//
}
case (MonNumber)
}</programlisting>
</section>
</chapter>
<?xxe-revisions
+#3 2019-02-23T12:37:01Z pgess
#2 2018-12-18T15:50:51Z pgess
+1sPEAAABgeMqAFCB4lUAASggLXObCwEBE4EIIx9DFRMsY4GNb0MjQyITB1MEY4FhcyNTBBMFIzdD
+tF4Amw6BCYEpmU2BCIGXHoGOHowjjkUmXYgkgatoghiCZA==
+
#1 2018-12-18T15:11:23Z pgess
1sPEAAABgeJVADCB4lkAABkQc+xgE5kzQ5JQgwhTshozg19DkFhTCmODEwDsX5kyEZJXshmDXoYP
ilQ=
-
?>
\ No newline at end of file
diff --git a/documentation/Transcend/modules-api.xml b/documentation/Transcend/modules-api.xml
index fb780af..dc2d68e 100644
--- a/documentation/Transcend/modules-api.xml
+++ b/documentation/Transcend/modules-api.xml
@@ -1,116 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
- <title>Modules API</title>
+ <?xxe-sn 2ahy8s1pw5c 7f?>
- <para>Modules Resolution is a process of finding out which modules should be
- preloaded for a correct compilation of a given module.</para>
+ <title><?xxe-sn 2ahy8s1pw5c 7g?>Modules API</title>
- <para>Resolution expected to use <code>bind_module</code>,
- <code>modules_require</code> as an input and produce results in form of
- <code>modules_resolution</code> data table.</para>
+ <para><?xxe-sn 2ahy8s1pw5c 7h?>Modules Resolution is a process of finding
+ out which modules should be preloaded for a correct compilation of a given
+ module.</para>
+
+ <para><?xxe-sn 2ahy8s1pw5c 7i?>Resolution expected to use <code><?xxe-sn 2ahy8s1pw5c 7j?>bind_module</code>,
+ <code><?xxe-sn 2ahy8s1pw5c 7k?>modules_require</code> as an input and
+ produce results in form of <code><?xxe-sn 2ahy8s1pw5c 7l?>modules_resolution</code>
+ data table.</para>
<section>
- <title>Module Annotations: 'bind_module'</title>
+ <?xxe-sn 2ahy8s1pw5c 7m?>
+
+ <title><?xxe-sn 2ahy8s1pw5c 7n?>Module Annotations: 'bind_module'</title>
- <synopsis>SYNTAX:
+ <synopsis><?xxe-sn 2ahy8s1pw5c 7o?>SYNTAX:
**bind_module**(//module-ref//, //annotation//)</synopsis>
<itemizedlist>
+ <?xxe-sn 2ahy8s1pw5c 7p?>
+
<listitem>
- <para><emphasis>module-ref</emphasis> module's path</para>
+ <?xxe-sn 2ahy8s1pw5c 7q?>
+
+ <para><?xxe-sn 2ahy8s1pw5c 7r?><emphasis><?xxe-sn 2ahy8s1pw5c 7s?>module-ref</emphasis>
+ module's path</para>
</listitem>
</itemizedlist>
- <para>Declares module annotations.</para>
+ <para><?xxe-sn 2ahy8s1pw5c 7t?>Declares module annotations.</para>
- <para>Example:</para>
+ <para><?xxe-sn 2ahy8s1pw5c 7u?>Example:</para>
- <programlisting>module:: status(obsolete).</programlisting>
+ <programlisting xml:id="ModAnn_1"><?xxe-sn 2ahy8s1pw5c 7v?>name="tests/modules.cpp: Modules_API.Doc_ModAnn_1"
+module:: status(obsolete).</programlisting>
- <para>Produced fact:
- <code>bind_module(path/to/module, status(obsolete))</code></para>
+ <para><?xxe-sn 2ahy8s1pw5c 7w?>Produced fact: <code
+ xml:id="Output_ModAnn_1"><?xxe-sn 2ahy8s1pw5c 7x?>bind_module("/path/to/module",status(obsolete))</code></para>
</section>
<section>
- <title>Requesting Modules: 'modules_require'</title>
+ <?xxe-sn 2ahy8s1pw5c 7y?>
- <synopsis>SYNTAX:
+ <title><?xxe-sn 2ahy8s1pw5c 7z?>Requesting Modules:
+ 'modules_require'</title>
+
+ <synopsis><?xxe-sn 2ahy8s1pw5c 80?>SYNTAX:
**modules_require**(//module-ref//, //request//)</synopsis>
<itemizedlist>
+ <?xxe-sn 2ahy8s1pw5c 81?>
+
<listitem>
- <para><emphasis>module-ref</emphasis> module's path</para>
+ <?xxe-sn 2ahy8s1pw5c 82?>
+
+ <para><?xxe-sn 2ahy8s1pw5c 83?><emphasis><?xxe-sn 2ahy8s1pw5c 84?>module-ref</emphasis>
+ module's path</para>
</listitem>
<listitem>
- <para><emphasis>request</emphasis> expressed by annotation</para>
+ <?xxe-sn 2ahy8s1pw5c 85?>
+
+ <para><?xxe-sn 2ahy8s1pw5c 86?><emphasis><?xxe-sn 2ahy8s1pw5c 87?>request</emphasis>
+ expressed by annotation</para>
</listitem>
</itemizedlist>
- <para>Module can request other modules necessary for correct work.
- Declared requests can be processed to find a resolution.</para>
+ <para><?xxe-sn 2ahy8s1pw5c 88?>Module can request other modules necessary
+ for correct work. Declared requests can be processed to find a
+ resolution.</para>
- <para>Example:</para>
+ <para><?xxe-sn 2ahy8s1pw5c 89?>Example:</para>
- <programlisting>module
+ <programlisting xml:id="ReqMod_1"><?xxe-sn 2ahy8s1pw5c 8a?>name="tests/modules.cpp: Modules_API.Doc_ReqMod_1"
+module
{
require(logger).
}</programlisting>
- <para>Produced declaration:
- <code>modules_require(/path/to/module, logger)</code></para>
+ <para><?xxe-sn 2ahy8s1pw5c 8b?>Produced declaration: <code
+ xml:id="Output_ReqMod_1"><?xxe-sn 2ahy8s1pw5c 8c?>modules_require("/path/to/module", logger)</code></para>
</section>
<section>
- <title>Modules Resolution: 'modules_resolution'</title>
+ <?xxe-sn 2ahy8s1pw5c 8d?>
+
+ <title><?xxe-sn 2ahy8s1pw5c 8e?>Modules Resolution:
+ 'modules_resolution'</title>
- <synopsis>SYNTAX:
+ <synopsis><?xxe-sn 2ahy8s1pw5c 8f?>SYNTAX:
**modules_resolution**(//request//, //module-resolved-ref//) (1)
**modules_resolution**(//request//, //module-resolved-ref//, //module-context-ref//) (2)
</synopsis>
<itemizedlist>
+ <?xxe-sn 2ahy8s1pw5c 8g?>
+
<listitem>
- <para><emphasis>request</emphasis> expressed by annotation</para>
+ <?xxe-sn 2ahy8s1pw5c 8h?>
+
+ <para><?xxe-sn 2ahy8s1pw5c 8i?><emphasis><?xxe-sn 2ahy8s1pw5c 8j?>request</emphasis>
+ expressed by annotation</para>
</listitem>
<listitem>
- <para><emphasis>module-resolved-ref</emphasis> resolved module's
- path</para>
+ <?xxe-sn 2ahy8s1pw5c 8k?>
+
+ <para><?xxe-sn 2ahy8s1pw5c 8l?><emphasis><?xxe-sn 2ahy8s1pw5c 8m?>module-resolved-ref</emphasis>
+ resolved module's path</para>
</listitem>
<listitem>
- <para><emphasis>module-context-ref</emphasis> context module's
- path</para>
+ <?xxe-sn 2ahy8s1pw5c 8n?>
+
+ <para><?xxe-sn 2ahy8s1pw5c 8o?><emphasis><?xxe-sn 2ahy8s1pw5c 8p?>module-context-ref</emphasis>
+ context module's path</para>
</listitem>
</itemizedlist>
- <para>Xreate uses the data table to find correspondent modules for each
- request.</para>
+ <para><?xxe-sn 2ahy8s1pw5c 8q?>Xreate uses the data table to find
+ correspondent modules for each request.</para>
- <para>Form (1) assigns resolved module to a request and assumes that
- assignment is valid in all cases, i.e. whenever compiler encounters
- request it loads associated module.</para>
+ <para><?xxe-sn 2ahy8s1pw5c 8r?>Form (1) assigns resolved module to a
+ request and assumes that assignment is valid in all cases, i.e. whenever
+ compiler encounters request it loads associated module.</para>
- <para>Form (2) assigns resolution valid only in a specific context.
- Compiler uses particular resolution only for requests that came from a
- module specified in a context. In other words, form (2) allows to resolve
- the same request differently for different modules depending on resolution
- strategy, thus implementing <emphasis>polymorphism on module
- level</emphasis>.</para>
+ <para><?xxe-sn 2ahy8s1pw5c 8s?>Form (2) assigns resolution valid only in a
+ specific context. Compiler uses particular resolution only for requests
+ that came from a module specified in a context. In other words, form (2)
+ allows to resolve the same request differently for different modules
+ depending on resolution strategy, thus implementing <emphasis><?xxe-sn 2ahy8s1pw5c 8t?>polymorphism
+ on module level</emphasis>.</para>
</section>
<section>
- <title>See Also</title>
+ <?xxe-sn 2ahy8s1pw5c 8u?>
+
+ <title><?xxe-sn 2ahy8s1pw5c 8v?>See Also</title>
- <para>Syntax: <link xlink:href="/w/syntax/modules">Modules</link></para>
+ <para><?xxe-sn 2ahy8s1pw5c 8w?>Syntax: <link
+ xlink:href="/w/syntax/modules"><?xxe-sn 2ahy8s1pw5c 8x?>Modules</link></para>
</section>
</chapter>
diff --git a/documentation/Transcend/transcend.xml b/documentation/Transcend/transcend.xml
index 743c93c..ad02e52 100644
--- a/documentation/Transcend/transcend.xml
+++ b/documentation/Transcend/transcend.xml
@@ -1,337 +1,443 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
- <title>Transcend</title>
+ <?xxe-sn 2ajela3ur5s 7q?>
- <para>Transcend is a compilation phase and process of reasoning about
- program in order to influence compilation.</para>
+ <title><?xxe-sn 2ajela3ur5s 7r?>Transcend</title>
- <para>First, compiler extracts <emphasis>annotations</emphasis> from source
- code and other facts from number of sources to form a complete
- <emphasis>logic program</emphasis>. Then, solver processes logic program and
- outputs decisions that affect and control compilation process in a number of
- ways.</para>
+ <para><?xxe-sn 2ajela3ur5s 7s?>Transcend is a compilation phase and process
+ of reasoning about program in order to influence compilation.</para>
+
+ <para><?xxe-sn 2ajela3ur5s 7t?>First, compiler extracts <emphasis><?xxe-sn 2ajela3ur5s 7u?>annotations</emphasis>
+ from source code and other facts from number of sources to form a complete
+ <emphasis><?xxe-sn 2ajela3ur5s 7v?>logic program</emphasis>. Then, solver
+ processes logic program and outputs decisions that affect and control
+ compilation process in a number of ways.</para>
<section>
- <title>Annotations' Syntax</title>
+ <?xxe-sn 2ajela3ur5s 7w?>
+
+ <title><?xxe-sn 2ajela3ur5s 7x?>Annotations' Syntax</title>
- <para>Xreate's annotations comprise optional supplementary information
- that is processed by compiler along with a source code proper and able to
- affect compilation process. Annotations have form of expressions that
- consist of following elements:</para>
+ <para><?xxe-sn 2ajela3ur5s 7y?>Xreate's annotations comprise optional
+ supplementary information that is processed by compiler along with a
+ source code proper and able to affect compilation process. Annotations
+ have form of expressions that consist of following elements:</para>
<informaltable>
+ <?xxe-sn 2ajela3ur5s 7z?>
+
<tgroup cols="2">
- <colspec colwidth="183*"/>
+ <?xxe-sn 2ajela3ur5s 80?>
- <colspec colwidth="817*"/>
+ <colspec colwidth="183*"><?xxe-sn 2ajela3ur5s 81?></colspec>
+
+ <colspec colwidth="817*"><?xxe-sn 2ajela3ur5s 82?></colspec>
<tbody>
+ <?xxe-sn 2ajela3ur5s 83?>
+
<row>
- <entry>Literals</entry>
+ <?xxe-sn 2ajela3ur5s 84?>
+
+ <entry><?xxe-sn 2ajela3ur5s 85?>Literals</entry>
- <entry>Strings, numbers. Example:
- <code>5, "success"</code></entry>
+ <entry><?xxe-sn 2ajela3ur5s 86?>Strings, numbers. Example:
+ <code><?xxe-sn 2ajela3ur5s 87?>5, "success"</code></entry>
</row>
<row>
- <entry>Predicates</entry>
+ <?xxe-sn 2ajela3ur5s 88?>
- <entry>Predicates have zero or more arguments. Example:
- <code>final, status(broken), version("12.0.3", unstable)</code></entry>
+ <entry><?xxe-sn 2ajela3ur5s 89?>Predicates</entry>
+
+ <entry><?xxe-sn 2ajela3ur5s 8a?>Predicates have zero or more
+ arguments. Example: <code><?xxe-sn 2ajela3ur5s 8b?>final, status(broken), version("12.0.3", unstable)</code></entry>
</row>
<row>
- <entry>Negation</entry>
+ <?xxe-sn 2ajela3ur5s 8c?>
+
+ <entry><?xxe-sn 2ajela3ur5s 8d?>Negation</entry>
- <entry>Example: <code>-i12n, -access(allowed)</code></entry>
+ <entry><?xxe-sn 2ajela3ur5s 8e?>Example: <code><?xxe-sn 2ajela3ur5s 8f?>-i12n, -access(allowed)</code></entry>
</row>
</tbody>
</tgroup>
</informaltable>
- <para>Various Xreate's entities can be annotated. At the time following
- entities are supported:</para>
+ <para><?xxe-sn 2ajela3ur5s 8g?>Various Xreate's entities can be annotated.
+ At the time following entities are supported:</para>
<informaltable>
+ <?xxe-sn 2ajela3ur5s 8h?>
+
<tgroup cols="4">
+ <?xxe-sn 2ajela3ur5s 8i?>
+
<tbody>
+ <?xxe-sn 2ajela3ur5s 8j?>
+
<row>
- <entry><link xlink:href="#expression-and-identifiers">Expressions
+ <?xxe-sn 2ajela3ur5s 8k?>
+
+ <entry><?xxe-sn 2ajela3ur5s 8l?><link
+ xlink:href="#expression-and-identifiers"><?xxe-sn 2ajela3ur5s 8m?>Expressions
and Identifiers</link></entry>
- <entry><link xlink:href="#code-blocks-and-context">Code blocks and
- context</link></entry>
+ <entry><?xxe-sn 2ajela3ur5s 8n?><link
+ xlink:href="#code-blocks-and-context"><?xxe-sn 2ajela3ur5s 8o?>Code
+ blocks and context</link></entry>
- <entry><link xlink:href="/w/syntax#functions">Functions</link> and
- <link xlink:href="/w/syntax#function-guards">Function
+ <entry><?xxe-sn 2ajela3ur5s 8p?><link
+ xlink:href="/w/syntax#functions"><?xxe-sn 2ajela3ur5s 8q?>Functions</link>
+ and <link xlink:href="/w/syntax#function-guards"><?xxe-sn 2ajela3ur5s 8r?>Function
Guards</link></entry>
- <entry><link
- xlink:href="/w/syntax/modules#module-annotations">Modules</link></entry>
+ <entry><?xxe-sn 2ajela3ur5s 8s?><link
+ xlink:href="/w/syntax/modules#module-annotations"><?xxe-sn 2ajela3ur5s 8t?>Modules</link></entry>
</row>
</tbody>
</tgroup>
</informaltable>
<section>
- <title>Expression and Identifiers</title>
+ <?xxe-sn 2ajela3ur5s 8u?>
- <synopsis>SYNTAX:
+ <title><?xxe-sn 2ajela3ur5s 8v?>Expression and Identifiers</title>
+
+ <synopsis><?xxe-sn 2ajela3ur5s 8w?>SYNTAX:
//expression// **::** //type//**;** //annotation-list//.</synopsis>
<itemizedlist>
+ <?xxe-sn 2ajela3ur5s 8x?>
+
<listitem>
- <para><emphasis>type</emphasis> expression's type</para>
+ <?xxe-sn 2ajela3ur5s 8y?>
+
+ <para><?xxe-sn 2ajela3ur5s 8z?><emphasis><?xxe-sn 2ajela3ur5s 90?>type</emphasis>
+ expression's type</para>
</listitem>
<listitem>
- <para><emphasis>annotation-list</emphasis> one or more annotation
- attached to the expression. Annotations are delimited by
- semicolon</para>
+ <?xxe-sn 2ajela3ur5s 91?>
+
+ <para><?xxe-sn 2ajela3ur5s 92?><emphasis><?xxe-sn 2ajela3ur5s 93?>annotation-list</emphasis>
+ one or more annotation attached to the expression. Annotations are
+ delimited by semicolon</para>
</listitem>
</itemizedlist>
- <para>Example:</para>
+ <para><?xxe-sn 2ajela3ur5s 94?>Example:</para>
- <programlisting xml:id="Expressions1">test = function:: int
+ <programlisting xml:id="Expressions1"><?xxe-sn 2ajela3ur5s 95?>name="tests/transcend.cpp: Transcend.Doc_Expressions1"
+test = function:: int
{
x = 5:: int; arithmetic(fast). //annotation applied to an identifier
y = (x - 8:: int; arithm_optimization(off)) * 2:: float. //annotation applied to a nested expression
x+y
}</programlisting>
<note>
- <para>For readability sake compound statements(e.g. <link
- xlink:href="/w/syntax#loop-statements">loops</link>) have different
- syntax for an annotations. See particular statement's <link
- xlink:href="/w/syntax">syntax</link> for details</para>
+ <?xxe-sn 2ajela3ur5s 96?>
+
+ <para><?xxe-sn 2ajela3ur5s 97?>For readability sake compound
+ statements(e.g. <link xlink:href="/w/syntax#loop-statements"><?xxe-sn 2ajela3ur5s 98?>loops</link>)
+ have different syntax for an annotations. See particular statement's
+ <link xlink:href="/w/syntax"><?xxe-sn 2ajela3ur5s 99?>syntax</link>
+ for details</para>
</note>
</section>
<section>
- <title>Code Blocks and Context</title>
+ <?xxe-sn 2ajela3ur5s 9a?>
- <synopsis>SYNTAX:
+ <title><?xxe-sn 2ajela3ur5s 9b?>Code Blocks and Context</title>
+
+ <synopsis><?xxe-sn 2ajela3ur5s 9c?>SYNTAX:
**context** :: //annotations-list//.</synopsis>
<itemizedlist>
+ <?xxe-sn 2ajela3ur5s 9d?>
+
<listitem>
- <para><emphasis>annotations-list</emphasis> List of annotation
- delimited by semicolon</para>
+ <?xxe-sn 2ajela3ur5s 9e?>
+
+ <para><?xxe-sn 2ajela3ur5s 9f?><emphasis><?xxe-sn 2ajela3ur5s 9g?>annotations-list</emphasis>
+ List of annotation delimited by semicolon</para>
</listitem>
</itemizedlist>
- <para>Code block annotations called <emphasis>context</emphasis>.
- Keyword <code>context</code> used to declare annotation within enclosing
- code block.</para>
+ <para><?xxe-sn 2ajela3ur5s 9h?>Code block annotations called
+ <emphasis><?xxe-sn 2ajela3ur5s 9i?>context</emphasis>. Keyword
+ <code><?xxe-sn 2ajela3ur5s 9j?>context</code> used to declare annotation
+ within enclosing code block.</para>
- <para>Example:</para>
+ <para><?xxe-sn 2ajela3ur5s 9k?>Example:</para>
- <programlisting xml:id="Codeblocks1">test = function:: int
+ <programlisting xml:id="Codeblocks1"><?xxe-sn 2ajela3ur5s 9l?>name="tests/transcend.cpp: Transcend.Doc_Codeblocks1"
+test = function:: int
{
context:: arithm_optimization(off).
x = 10 :: int.
2 * x - 16
}</programlisting>
</section>
<section>
- <title>Special Annotations</title>
+ <?xxe-sn 2ajela3ur5s 9m?>
+
+ <title><?xxe-sn 2ajela3ur5s 9n?>Special Annotations</title>
- <para>There are some annotations in Xreate that have special
- meaning</para>
+ <para><?xxe-sn 2ajela3ur5s 9o?>There are some annotations in Xreate that
+ have special meaning</para>
<informaltable>
+ <?xxe-sn 2ajela3ur5s 9p?>
+
<tgroup cols="2">
- <colspec colwidth="201*"/>
+ <?xxe-sn 2ajela3ur5s 9q?>
+
+ <colspec colwidth="201*"><?xxe-sn 2ajela3ur5s 9r?></colspec>
- <colspec colwidth="799*"/>
+ <colspec colwidth="799*"><?xxe-sn 2ajela3ur5s 9s?></colspec>
<tbody>
+ <?xxe-sn 2ajela3ur5s 9t?>
+
<row>
- <entry><code>entry</code></entry>
+ <?xxe-sn 2ajela3ur5s 9u?>
- <entry>Specifies entry point of a program. See <link
- xlink:href="/w/syntax#functions">Function Syntax</link></entry>
+ <entry><?xxe-sn 2ajela3ur5s 9v?><code><?xxe-sn 2ajela3ur5s 9w?>entry</code></entry>
+
+ <entry><?xxe-sn 2ajela3ur5s 9x?>Specifies entry point of a
+ program. See <link xlink:href="/w/syntax#functions"><?xxe-sn 2ajela3ur5s 9y?>Function
+ Syntax</link></entry>
</row>
<row>
- <entry><code>final</code></entry>
+ <?xxe-sn 2ajela3ur5s 9z?>
+
+ <entry><?xxe-sn 2ajela3ur5s a0?><code><?xxe-sn 2ajela3ur5s a1?>final</code></entry>
- <entry>Specifies fixed point of loop statements. See <link
- xlink:href="/w/syntax#loop-statement">Loop
+ <entry><?xxe-sn 2ajela3ur5s a2?>Specifies fixed point of loop
+ statements. See <link
+ xlink:href="/w/syntax#loop-statement"><?xxe-sn 2ajela3ur5s a3?>Loop
Statement</link></entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
</section>
<section>
- <title>Annotations and Reasoning</title>
-
- <para>Annotations is a mechanism to express an additional pieces of
- information and can occur in source code or accompanying files. They are
- of declarative nature in a sense that they express specific properties of
- and relations between different entities, such as: identifiers,
- statements, code blocks, functions, modules or even a whole
- program.</para>
-
- <para>Annotations are <emphasis>facts</emphasis> about source code
- provided by developer in explicit form. Beside annotations there are other
- sources of information, e.g. implicit facts that are automatically
- inferred by various analysis phases to express useful insights regarding
- analysed code. Such pieces aren't exposed directly to a developer but
- accessed and used internally at reasoning phase along with annotations.
- All types of input are summed up below:</para>
+ <?xxe-sn 2ajela3ur5s a4?>
+
+ <title><?xxe-sn 2ajela3ur5s a5?>Annotations and Reasoning</title>
+
+ <para><?xxe-sn 2ajela3ur5s a6?>Annotations is a mechanism to express an
+ additional pieces of information and can occur in source code or
+ accompanying files. They are of declarative nature in a sense that they
+ express specific properties of and relations between different entities,
+ such as: identifiers, statements, code blocks, functions, modules or even
+ a whole program.</para>
+
+ <para><?xxe-sn 2ajela3ur5s a7?>Annotations are <emphasis><?xxe-sn 2ajela3ur5s a8?>facts</emphasis>
+ about source code provided by developer in explicit form. Beside
+ annotations there are other sources of information, e.g. implicit facts
+ that are automatically inferred by various analysis phases to express
+ useful insights regarding analysed code. Such pieces aren't exposed
+ directly to a developer but accessed and used internally at reasoning
+ phase along with annotations. All types of input are summed up
+ below:</para>
<informaltable>
+ <?xxe-sn 2ajela3ur5s a9?>
+
<tgroup cols="2">
- <colspec colwidth="287*"/>
+ <?xxe-sn 2ajela3ur5s aa?>
- <colspec colwidth="713*"/>
+ <colspec colwidth="287*"><?xxe-sn 2ajela3ur5s ab?></colspec>
+
+ <colspec colwidth="713*"><?xxe-sn 2ajela3ur5s ac?></colspec>
<tbody>
+ <?xxe-sn 2ajela3ur5s ad?>
+
<row>
- <entry>Explicit annotations in source files</entry>
+ <?xxe-sn 2ajela3ur5s ae?>
+
+ <entry><?xxe-sn 2ajela3ur5s af?>Explicit annotations in source
+ files</entry>
- <entry>Annotations provided by developer in order to explicitly
- affect compilation</entry>
+ <entry><?xxe-sn 2ajela3ur5s ag?>Annotations provided by developer
+ in order to explicitly affect compilation</entry>
</row>
<row>
- <entry>Code Analysis</entry>
+ <?xxe-sn 2ajela3ur5s ah?>
- <entry>Different code analyses during compilation provide
- information implicitly inferred from source code</entry>
+ <entry><?xxe-sn 2ajela3ur5s ai?>Code Analysis</entry>
+
+ <entry><?xxe-sn 2ajela3ur5s aj?>Different code analyses during
+ compilation provide information implicitly inferred from source
+ code</entry>
</row>
<row>
- <entry>Supervision</entry>
-
- <entry>External facts that reflect requirements, describe hardware
- and/or environment where compilation takes place or program is
- supposed to work. There are many supervision layers possible, from
- custom compiler's mode, to OS- or computer- or even network-wide
- level. On other words, supervision covers local or client supplied
- annotations</entry>
+ <?xxe-sn 2ajela3ur5s ak?>
+
+ <entry><?xxe-sn 2ajela3ur5s al?>Supervision</entry>
+
+ <entry><?xxe-sn 2ajela3ur5s am?>External facts that reflect
+ requirements, describe hardware and/or environment where
+ compilation takes place or program is supposed to work. There are
+ many supervision layers possible, from custom compiler's mode, to
+ OS- or computer- or even network-wide level. On other words,
+ supervision covers local or client supplied annotations</entry>
</row>
<row>
- <entry>Audit</entry>
+ <?xxe-sn 2ajela3ur5s an?>
+
+ <entry><?xxe-sn 2ajela3ur5s ao?>Audit</entry>
- <entry>Third party supplied external information that reflect
- additional software properties, e.g. results of security
- audit</entry>
+ <entry><?xxe-sn 2ajela3ur5s ap?>Third party supplied external
+ information that reflect additional software properties, e.g.
+ results of security audit</entry>
</row>
<row>
- <entry>Reasoning rules</entry>
+ <?xxe-sn 2ajela3ur5s aq?>
+
+ <entry><?xxe-sn 2ajela3ur5s ar?>Reasoning rules</entry>
- <entry>Reasoning infers additional facts from pool of previously
- gathered information. It is done by using <emphasis>resoning
- rules</emphasis> that govern reasoning process</entry>
+ <entry><?xxe-sn 2ajela3ur5s as?>Reasoning infers additional facts
+ from pool of previously gathered information. It is done by using
+ <emphasis><?xxe-sn 2ajela3ur5s at?>resoning rules</emphasis> that
+ govern reasoning process</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section>
- <title>Why Annotations Matter</title>
+ <?xxe-sn 2ajela3ur5s au?>
- <para>This section goes through differences that annotations have over
- traditional statements.</para>
+ <title><?xxe-sn 2ajela3ur5s av?>Why Annotations Matter</title>
+
+ <para><?xxe-sn 2ajela3ur5s aw?>This section goes through differences that
+ annotations have over traditional statements.</para>
<section>
- <title>Extensible</title>
+ <?xxe-sn 2ajela3ur5s ax?>
+
+ <title><?xxe-sn 2ajela3ur5s ay?>Extensible</title>
- <para>Annotations are not a part of language syntax and there is no
- predefined set of allowed annotations. Developer is free to define and
- use custom annotations to express desired properties without prior
- changes to compiler.</para>
+ <para><?xxe-sn 2ajela3ur5s az?>Annotations are not a part of language
+ syntax and there is no predefined set of allowed annotations. Developer
+ is free to define and use custom annotations to express desired
+ properties without prior changes to compiler.</para>
<note>
- <para>Yet there are several reserved annotations that have specific
- meaning in Xreate. See <link xlink:href="#special-annotations">special
+ <?xxe-sn 2ajela3ur5s b0?>
+
+ <para><?xxe-sn 2ajela3ur5s b1?>Yet there are several reserved
+ annotations that have specific meaning in Xreate. See <link
+ xlink:href="#special-annotations"><?xxe-sn 2ajela3ur5s b2?>special
annotations</link> for details.</para>
</note>
</section>
<section>
- <title>Indicative Nature</title>
+ <?xxe-sn 2ajela3ur5s b3?>
- <para>Unlike language statements that have well defined compilation
- output, annotation do not. They are rather of suggestive nature and
- actual impact depends on many factors. Annotations comprise an input for
- a reasoning procedure that ultimately determines how exactly influence
- compilation.</para>
+ <title><?xxe-sn 2ajela3ur5s b4?>Indicative Nature</title>
+
+ <para><?xxe-sn 2ajela3ur5s b5?>Unlike language statements that have well
+ defined compilation output, annotation do not. They are rather of
+ suggestive nature and actual impact depends on many factors. Annotations
+ comprise an input for a reasoning procedure that ultimately determines
+ how exactly influence compilation.</para>
</section>
<section>
- <title>Cooperation</title>
+ <?xxe-sn 2ajela3ur5s b6?>
+
+ <title><?xxe-sn 2ajela3ur5s b7?>Cooperation</title>
- <para>Annotations are gathered from different sources and this enables
- annotations to complement themselves. Compiler blends in annotations
- originated from various sources seamlessly and this allows to improve
- decisions quality.</para>
+ <para><?xxe-sn 2ajela3ur5s b8?>Annotations are gathered from different
+ sources and this enables annotations to complement themselves. Compiler
+ blends in annotations originated from various sources seamlessly and
+ this allows to improve decisions quality.</para>
</section>
<section>
- <title>External Sources and Adaptability</title>
-
- <para>Annotations able to express not only properties of program itself
- but also properties of local environment(OS, computer, local network)
- where program is supposed to run. Thus compiler operates information
- inaccessible during software development and can't be reflected in the
- code otherwise. Compilation can be adjusted to a particular environment
- and functioning mode.</para>
+ <?xxe-sn 2ajela3ur5s b9?>
+
+ <title><?xxe-sn 2ajela3ur5s ba?>External Sources and
+ Adaptability</title>
+
+ <para><?xxe-sn 2ajela3ur5s bb?>Annotations able to express not only
+ properties of program itself but also properties of local
+ environment(OS, computer, local network) where program is supposed to
+ run. Thus compiler operates information inaccessible during software
+ development and can't be reflected in the code otherwise. Compilation
+ can be adjusted to a particular environment and functioning mode.</para>
</section>
<section>
- <title>Feedback</title>
-
- <para>Traditionally software has a rigid strictly defined hierarchical
- structure and interaction between components. More precisely, let's look
- at client-service code model. Service is done independently in order to
- work well with as wide as possible set of different clients. Thus
- service is unaware of exact characteristics of particular client code it
- works with. All burden of complying with interaction specification lies
- on a client.</para>
-
- <para>However client may use only small subset of service functionality
- or use it in specific and predictable order. Generally speaking, service
- by having additional information on particular client able to serve
- requests more efficiently in many cases.</para>
-
- <para>It can be conceptualized as a <emphasis>feedback</emphasis> from a
- client. Annotations is good candidate to express feedback to improve
- interaction quality.</para>
+ <?xxe-sn 2ajela3ur5s bc?>
+
+ <title><?xxe-sn 2ajela3ur5s bd?>Feedback</title>
+
+ <para><?xxe-sn 2ajela3ur5s be?>Traditionally software has a rigid
+ strictly defined hierarchical structure and interaction between
+ components. More precisely, let's look at client-service code model.
+ Service is done independently in order to work well with as wide as
+ possible set of different clients. Thus service is unaware of exact
+ characteristics of particular client code it works with. All burden of
+ complying with interaction specification lies on a client.</para>
+
+ <para><?xxe-sn 2ajela3ur5s bf?>However client may use only small subset
+ of service functionality or use it in specific and predictable order.
+ Generally speaking, service by having additional information on
+ particular client able to serve requests more efficiently in many
+ cases.</para>
+
+ <para><?xxe-sn 2ajela3ur5s bg?>It can be conceptualized as a
+ <emphasis><?xxe-sn 2ajela3ur5s bh?>feedback</emphasis> from a client.
+ Annotations is good candidate to express feedback to improve interaction
+ quality.</para>
</section>
<section>
- <title>Resiliency</title>
+ <?xxe-sn 2ajela3ur5s bi?>
+
+ <title><?xxe-sn 2ajela3ur5s bj?>Resiliency</title>
- <para>As code grows and goes through multiple reworks and rewrites many
- initial assumptions about the code and relation between different parts
- change accordingly. Some implementation details and approaches became
- outdated and code quality deteriorates.</para>
+ <para><?xxe-sn 2ajela3ur5s bk?>As code grows and goes through multiple
+ reworks and rewrites many initial assumptions about the code and
+ relation between different parts change accordingly. Some implementation
+ details and approaches became outdated and code quality
+ deteriorates.</para>
- <para>DIfferent picture in case if code uses annotations to express
- important properties. Any changes in underlying code lead to a restart
- of reasoning procedure which adjust implementation decisions to be still
- optimal in changed environment.</para>
+ <para><?xxe-sn 2ajela3ur5s bl?>DIfferent picture in case if code uses
+ annotations to express important properties. Any changes in underlying
+ code lead to a restart of reasoning procedure which adjust
+ implementation decisions to be still optimal in changed
+ environment.</para>
</section>
</section>
</chapter>
diff --git a/documentation/communication.xml b/documentation/communication.xml
index 8c945f9..f4293f6 100644
--- a/documentation/communication.xml
+++ b/documentation/communication.xml
@@ -1,440 +1,440 @@
<?xml version="1.0" encoding="UTF-8"?>
<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:trans="http://docbook.org/ns/transclusion"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:m="http://www.w3.org/1998/Math/MathML"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:db="http://docbook.org/ns/docbook">
<?xxe-sn 29tvny21340 1?>
<title><?xxe-sn 29tvny21340 2?>Communication</title>
<para><?xxe-sn 2abbls7nbb4 2?>The chapter discusses safe usage of non-local
variables, that is variables accessible by different components or threads
with global variables as a particular case.</para>
<section>
<?xxe-sn 29xq7jt0wzk 1?>
<title><?xxe-sn 29xq7jt0wzk 2?>Syntax</title>
<para><?xxe-sn 29xq7jt0wzk 3?>Annotations:</para>
<synopsis><?xxe-sn 2afyauuaxvk d?>SYNTAX:
**commop(send)** (1)
**commop(receive)** (2)</synopsis>
<itemizedlist>
<?xxe-sn 2afyauuaxvk e?>
<listitem>
<?xxe-sn 2afyauuaxvk f?>
<para><?xxe-sn 2afyauuaxvk g?>annotation <code><?xxe-sn 2afyauuaxvk h?>(1)</code>
marks <code><?xxe-sn 2afyauuaxvk i?>SEND</code> communication
event.</para>
</listitem>
<listitem>
<?xxe-sn 2afyauuaxvk j?>
<para><?xxe-sn 2afyauuaxvk k?>annotation <code><?xxe-sn 2afyauuaxvk l?>(2)</code>
marks <code><?xxe-sn 2afyauuaxvk m?>RECEIVE</code> communication
event.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 2afyauuaxvk n?>Specializations:</para>
<synopsis><?xxe-sn 2afyauuaxvk o?>SYNTAX:
**commDirect**
**commGuarded**</synopsis>
<para><?xxe-sn 2afyauuaxvk p?>Communication reasoning able to assign
following specializations:</para>
<itemizedlist>
<?xxe-sn 2afyauuaxvk q?>
<listitem>
<?xxe-sn 2afyauuaxvk r?>
<para><?xxe-sn 2afyauuaxvk s?><code><?xxe-sn 2afyauuaxvk t?>commDirect</code>
— specialization is expected to provide direct access to raw
variable's content.</para>
</listitem>
<listitem>
<?xxe-sn 2afyauuaxvk u?>
<para><?xxe-sn 2afyauuaxvk v?><code><?xxe-sn 2afyauuaxvk w?>commGaurded</code>
— specialization is expected to do internal consistency checks at run
time.</para>
</listitem>
</itemizedlist>
</section>
<section>
<?xxe-sn 29tvny21340 3?>
<title><?xxe-sn 29tvny21340 4?>Background</title>
<para><?xxe-sn 29tvny21340 5?>One of the major concepts that support
writing of safe programs is a notion of <emphasis><?xxe-sn 2abbls7nbb4 1?>immutability</emphasis>.
Immutability tremendously simplifies many kinds of analyses; using
immutable structures is a practical way to write multithreaded
applications and has many other benefits beyond that. However in its most
basic form it comes with a price of disastrous, in many cases, memory
overhead, since property of immutability stipulates for each change of
variable to make an independent copy of it occupying different memory
region. Unwise using of immutable structures lead to the situation such
that CPU is mostly occupied with unnecessary variables copying to and fro
as well as with extensive garbage collection, irrelevant of actual
algorithm's complexity at hand. Thus it is one of the central highlights
of proper programming language design to provide techniques to overcome
the shortcomings by relaxing immutability requirements keeping
nevertheless safety benefits. There are many ways to approach the problem,
and one such technique, namely <emphasis><?xxe-sn 2abbls7nbb4 3?>communication
model</emphasis> is discussed next.</para>
</section>
<section>
<?xxe-sn 29xq7jt0wzk 5?>
<title><?xxe-sn 29xq7jt0wzk 6?>Communication Model</title>
<para><?xxe-sn 29xq7jt0wzk 7?><emphasis><?xxe-sn 2abizkj6e4g 1?>Communication
model</emphasis> is a way to capture and express what's going on with
variables in a program as well as to define rules that describe valid
operations over variables. Within the framework writing value to a
variable is viewed as <emphasis><?xxe-sn 29xq7jt0wzk 8?>sending</emphasis>,
and conversely reading variable's value is viewed as <emphasis><?xxe-sn 29xq7jt0wzk 9?>receiving</emphasis>.</para>
<para><?xxe-sn 2abizkj6e4g 2?>Variables that are accessed from different
components or threads are referred to as non-local variables. This chapter
is focused on a on-local variables, global variables particularly, since
exactly for them it's hard to manually check exhaustively where and how
they are used in order to catch any errors. It is natural to view them as
the means of interaction between different parts of a program, in other
words, interaction between sender and receiver, where sender and receiver
are different components. The same terms comprise rules that express valid
ways of interacting. The abstraction is named <emphasis><?xxe-sn 29xq7jt0wzk a?>communication
model</emphasis> due to similarity with the network communication.</para>
<para><?xxe-sn 29xq7jt0wzk b?>Reasoning based on working with a
<emphasis><?xxe-sn 2abizkj6e4g 3?>communication path</emphasis>, i.e chain
of <emphasis><?xxe-sn 29xq7jt0wzk c?>communication events</emphasis>(e.g.
sending/receiving) occurred during program execution.</para>
<para><?xxe-sn 2abizkj6e4g 4?>Let's consider small example:</para>
- <programlisting><?xxe-sn 2abizkj6e4g 5?>a = init():: int; comm(send). //(1)
-b = a + 1 :: int; comm(receive). //(2)</programlisting>
+ <programlisting><?xxe-sn 2abizkj6e4g 5?>a = init():: int; commop(send). //(1)
+b = a + 1 :: int; commop(receive). //(2)</programlisting>
<para><?xxe-sn 2abizkj6e4g 6?>It shows computing of variable
<code><?xxe-sn 2abizkj6e4g 7?>b</code>. Variable <code><?xxe-sn 2abizkj6e4g 8?>b</code>
depends on <code><?xxe-sn 2abizkj6e4g 9?>a</code> so <code><?xxe-sn 2abizkj6e4g a?>a</code>
is calculated first. Variables <code><?xxe-sn 2abizkj6e4g b?>a</code>,
<code><?xxe-sn 2abizkj6e4g c?>b</code> are annotated with <code><?xxe-sn 2abizkj6e4g d?>comm(send)</code>
and <code><?xxe-sn 2abizkj6e4g e?>comm(receive)</code>, denoting
<emphasis><?xxe-sn 2abizkj6e4g f?>sending</emphasis> and
<emphasis><?xxe-sn 2abizkj6e4g g?>receiving</emphasis> events,
respectively. Communication path in this case is an ordered list
<code><?xxe-sn 2abizkj6e4g h?>{&lt;begin&gt;, SEND, RECEIVE,
&lt;end&gt;}</code> where <code><?xxe-sn 2abizkj6e4g i?>&lt;begin&gt;,
&lt;end&gt;</code> — are special events that denote first and last events
in the path, respectively.</para>
<para><?xxe-sn 2abizkj6e4g k?>The gist of using communication model is to
ensure that <emphasis><?xxe-sn 2abizkj6e4g l?>every sent value is properly
received</emphasis>. It relies on the compiler to gather all possible
communication paths in the program as an input for processing. There are
two supported modes of reasoning:</para>
<itemizedlist>
<?xxe-sn 29xq7jt0wzk d?>
<listitem>
<?xxe-sn 29xq7jt0wzk e?>
<para><?xxe-sn 29xq7jt0wzk f?>Validation. In this mode all
communication paths are checked against communication rules to confirm
that the program is valid. Otherwise compilation error is
raised.</para>
</listitem>
<listitem>
<?xxe-sn 29xq7jt0wzk g?>
<para><?xxe-sn 29xq7jt0wzk h?>Planning. In this mode reasoning assigns
proper implementation for variables in efforts to ensure
validity.</para>
</listitem>
</itemizedlist>
</section>
<section>
<?xxe-sn 29xq7jt0wzk j?>
<title><?xxe-sn 29xq7jt0wzk k?>Validation</title>
<para><?xxe-sn 29xq7jt0wzk l?>To perform validation, every communication
path is checked against number of communication rules that express which
communication path are valid. Default behaviour expressed by "every sent
value being properly received" produce next possible cases:</para>
<itemizedlist>
<?xxe-sn 29xq7jt0wzk 1w?>
<listitem>
<?xxe-sn 29xq7jt0wzk 1x?>
<para><?xxe-sn 29xq7jt0wzk 1y?>Valid. Path that consists of pairs of
events <code><?xxe-sn 29xq7jt0wzk 1z?>{SEND, RECEIVE}</code> are
<emphasis><?xxe-sn 29xq7jt0wzk 20?>valid</emphasis> meaning that each
sent value is properly received.</para>
</listitem>
<listitem>
<?xxe-sn 29xq7jt0wzk 21?>
<para><?xxe-sn 29xq7jt0wzk 22?>Undefined and expired value. Paths that
have parts <code><?xxe-sn 2abizkj6e4g m?>{&lt;begin&gt;,
RECEIVE}</code> or <code><?xxe-sn 2abizkj6e4g n?>{RECEIVE,
RECEIVE}</code> are invalid meaning possibly undefined value is
received in the first case or duplication i.e. expired value is used
in the second's one.</para>
</listitem>
<listitem>
<?xxe-sn 2a3uy8rr2f4 5?>
<para><?xxe-sn 2a3uy8rr2f4 6?>Lost value. Paths that have parts
<code><?xxe-sn 2abizkj6e4g o?>{SEND, SEND}</code> or <code><?xxe-sn 2abizkj6e4g p?>{SEND,
&lt;end&gt;}</code> indicate possibly lost change since consequent
sender replaces value in the former case and sent value is not used at
all in the latter case.</para>
</listitem>
</itemizedlist>
<para><?xxe-sn 29xq7jt0wzk 28?>Traditional immutability validation is
based on the idea that once valid value is valid as long it is unmodified.
In this regards communication model can be viewed as an extension and more
expressive tool since it also captures <emphasis><?xxe-sn 2afyauuaxvk 3?>value
expiration</emphasis> after it was used as well as <emphasis><?xxe-sn 2afyauuaxvk 4?>value</emphasis>
<emphasis><?xxe-sn 2afyauuaxvk 5?>loss</emphasis>, if it was not used at
all.</para>
</section>
<section>
<?xxe-sn 29xq7jt0wzk 29?>
<title><?xxe-sn 29xq7jt0wzk 2a?>Planning</title>
<para><?xxe-sn 2abizkj6e4g s?>Reasoning in the communication model aside
of performing validation, also assigns appropriate specialization for
sending and receiving operations, as appropriate. At the moment there are
two specializations the operations are expected to support:</para>
<itemizedlist>
<?xxe-sn 2abizkj6e4g t?>
<listitem>
<?xxe-sn 2abizkj6e4g u?>
<para><?xxe-sn 2abizkj6e4g v?>Direct. Direct specialization
<code><?xxe-sn 2abizkj6e4g w?>commDirect</code> is expected to provide
direct access to variable's value. This specialization is assigned in
case of fully statically validated communication path.</para>
</listitem>
<listitem>
<?xxe-sn 2abizkj6e4g x?>
<para><?xxe-sn 2abizkj6e4g y?>Guarded. In case if there are possible
communication path inconsistencies that can not be completely ruled
out at compile time, checking logic should be embedded into compiled
code. Specialization <code><?xxe-sn 2abizkj6e4g z?>commGaurded</code>
is expected to hold variable state and check usage consistency.</para>
</listitem>
</itemizedlist>
</section>
<section>
<?xxe-sn 2a3uy8rr2f4 8?>
<title><?xxe-sn 2a3uy8rr2f4 9?>Planning Horizon</title>
<para><?xxe-sn 2a3uy8rr2f4 a?>Reasoning implements algorithm that is
bounded by the maximal path length it can process. The parameter is called
<emphasis><?xxe-sn 2a3uy8rr2f4 b?>planning horizon</emphasis>. Any
variable that it can not check due to exceedingly large path's length is
assigned default implementation <code><?xxe-sn 2abizkj6e4g 10?>commGaurded</code>
that performs necessary checks during runtime. Thus the parameter
regulates trade off between static analysis extensiveness and runtime
checks overhead.</para>
</section>
<section>
<?xxe-sn 2a7t1hxqqyo 1?>
<title><?xxe-sn 2a7t1hxqqyo 2?>Example: Direct Implementation</title>
<programlisting xml:id="DirImpl_1"><?xxe-sn 2a7t1hxqqyo 3?>name="tests/effects-communication.cpp: Doc_DirImpl", lines=15
import raw("scripts/dfa/propagation.lp").
import raw("scripts/dfa/polymorphism.lp").
import raw("scripts/effects-communication/communication.lp").
import raw("scripts/effects-communication/config.lp").
CommDirect = type {
value:: int
}.
guard:: commDirect {
init = function::CommDirect
{
{value = 0}
}
read = function(vault1:: CommDirect):: int
{
(vault1:: *;commop(receive))["value"]
}
write = function(vault2:: CommDirect, valueNew:: int)::CommDirect
{
(vault2:: *; dfa_pseudo(vault2)) + {value = valueNew}:: int; commop(send); dfa_uppy(vault2)
}
}
main = function::int; entry {
x1 = init()::*; dfa_polym(ret).
x2 = write(x1, 1)::*; dfa_polym(arg).
val = read(x2)::int; dfa_polym(arg).
val
}</programlisting>
<para><?xxe-sn 2a7t1hxqqyo 4?>In this example, basic workflow is presented
in <code><?xxe-sn 2afyauuaxvk 1?>main</code> — the function
<code><?xxe-sn 2a7t1hxqqyo 5?>write(x1, 1)</code> is invoked following by
invocation of <code><?xxe-sn 2a7t1hxqqyo 6?>read(x2)</code>. Functions
<code><?xxe-sn 2afyauuaxvk 9?>write()</code> and <code><?xxe-sn 2afyauuaxvk a?>read()</code>
are annotated with <code><?xxe-sn 2afyauuaxvk b?>commop(send)</code> and
<code><?xxe-sn 2afyauuaxvk c?>commop(receive)</code> respectively in order
to enable communication reasoning. Analyzer gathers and validates observed
communication path and since there is no ambiguity, it's possible to
assign specialization <code><?xxe-sn 2a7t1hxqqyo 7?>CommDirect</code>
allowing direct access to the variables avoiding any additional overhead.
Note, there are no any other specializations defined and if reasoning was
not enable to conclude that it is the case the compilation error would be
raised.</para>
</section>
<section>
<?xxe-sn 2a7t1hxqqyo 9?>
<title><?xxe-sn 2a7t1hxqqyo a?>Example: Guarded Implementation</title>
<programlisting xml:id="GuardedImpl_1"><?xxe-sn 2a7t1hxqqyo b?>name="tests/effects-communication.cpp: Doc_GuardedImpl", lines=15
import raw ("scripts/effects-communication/communication.lp").
import raw ("scripts/dfa/propagation.lp").
import raw ("scripts/dfa/polymorphism.lp").
import raw ("scripts/effects-communication/config.lp").
CommState = type variant{Invalid, Valid, Outdated}.
CommDirect = type {
value:: int
}.
CommGuarded = type {
value:: int,
state:: CommState
}.
guard:: commDirect {
init=function::CommDirect{
{value = 0}
}
read= function(vault1:: CommDirect):: int{
(vault1::CommDirect; commop(receive))["value"]
}
write= function(vault2:: CommDirect, valueNew1:: int)::CommDirect{
(vault2::CommDirect;dfa_pseudo(vault2)) + {value = valueNew1}:: int; commop(send); dfa_uppy(vault2)
}
}
errorRead = function:: int { -1 }
errorWrite = function:: CommGuarded{
{
value = -1,
state = Invalid()
}
}
guard:: commGuarded{
init=function::CommGuarded{
{
value = 0,
state = Invalid()
}
}
read=function(vault3:: CommGuarded):: int {
switch variant (vault3["state"]-&gt;whatever::CommState;commop(receive)):: int
case (Invalid) { errorRead() }
case (Outdated) { errorRead() }
case (Valid) { vault3["value"] }
}
write=function(vault4:: CommGuarded, valueNew2:: int)::CommGuarded{
switch variant (vault4["state"]-&gt;whatever::CommState;commop(send); dfa_pseudo(vault4))::int
case (Invalid) {
{value = valueNew2, state = Valid()}:: CommGuarded; dfa_uppy(vault4)
}
case (Outdated) {
{value = valueNew2, state = Valid()}:: CommGuarded; dfa_uppy(vault4)
}
case (Valid) { errorWrite():: CommGuarded; dfa_uppy(vault4) }
}
}
main=function(cmd:: num)::int; entry {
x1 = init():: *; dfa_polym(ret).
x2 = write(x1, 1)::*; dfa_polym(arg).
x3 = if (cmd &gt; 0)::int {
y = read(x2):: int; dfa_polym(arg).
y
} else {
z = write(x2, 2)::*; dfa_polym(arg).
a = read(z):: int; dfa_polym(arg).
a
}.
x3
}</programlisting>
<para><?xxe-sn 2a7t1hxqqyo d?>Here example of slightly more complicated
workflow. Function <code><?xxe-sn 2afyauuaxvk 2?>main</code> contains
branching that depends on argument known at run time only. Analyzer is
presented with two possible communication paths and one of them(false
branch) leads to a possibly lost value for it contains two consequent
<code><?xxe-sn 2afyauuaxvk 6?>SEND</code> events. In this situation the
analyzer unable to statically validate correctness and assigns
specialization <code><?xxe-sn 2afyauuaxvk 7?>commGuarded</code> to embed
checking logic into compiled code as an intermediary layer between
variable's content and client's code. Implementation <code><?xxe-sn 2afyauuaxvk 8?>commGuarded</code>
along with a variable access also tracks the variable status and returns
- error if the value is inconsistent. </para>
+ error if the value is inconsistent.</para>
</section>
</chapter>
diff --git a/documentation/index.xml b/documentation/index.xml
new file mode 100644
index 0000000..a1db8a3
--- /dev/null
+++ b/documentation/index.xml
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<chapter version="5.1" xmlns="http://docbook.org/ns/docbook"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:xila="http://www.w3.org/2001/XInclude/local-attributes"
+ xmlns:xi="http://www.w3.org/2001/XInclude"
+ xmlns:trans="http://docbook.org/ns/transclusion"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:m="http://www.w3.org/1998/Math/MathML"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns:db="http://docbook.org/ns/docbook">
+ <?xxe-sn 2b06cb2u4g0 1?>
+
+ <title><?xxe-sn 2b06cb2u4g0 2?>Xreate Manual</title>
+
+ <para><?xxe-sn 2b06cb2u4g0 6?>Xreate is an open source general purpose high
+ level programming language designed to write efficient and safe computer
+ programs.</para>
+
+ <para><?xxe-sn 2b06cb2u4g0 8?>Here "high level" has very specific meaning as
+ an ability to easily write, read, as well as adapt software to a constantly
+ changing environment or business goals. In this respect, any software
+ product can be evaluated on the basis of the three dimensions: efficiency,
+ safety and adaptability. Unfortunately, those properties are proved to be
+ largely contradictory for it is manageable to write either efficient(still
+ unsafe) or safe(and impractical) code, but not both. Thus, the ultimate goal
+ of the language is to allow developers to produce code with all these
+ properties at the same time. Xreate's design principles allow to adopt any
+ programming technique as long as it does not improve one dimension at the
+ expense of another.</para>
+
+ <para><?xxe-sn 2b06cb2u4g0 7?>To achieve aforementioned design goals Xreate
+ has tree distinctive layers:</para>
+
+ <itemizedlist>
+ <?xxe-sn 2b06cb2u4g0 e?>
+
+ <listitem>
+ <?xxe-sn 2b06cb2u4g0 f?>
+
+ <para><?xxe-sn 2b06cb2u4g0 g?><link xlink:href="/w/syntax"><?xxe-sn 2b06cb2u4g0 o?>Brute</link>.
+ Lowest layer is called <emphasis><?xxe-sn 2b06cb2u4g0 p?>Brute</emphasis>—
+ this is code that is indented to be actually compiled. Code on this
+ level implements actual software functionality. It resembles the usual
+ imperative languages' apparatus and consists of executable instructions
+ such as arithmetic, branching, input/output, etc.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 2b06cb2u4g0 i?>
+
+ <para><?xxe-sn 2b06cb2u4g0 j?><link xlink:href="/w/transcend"><?xxe-sn 2b06cb2u4g0 q?>Transcend</link>.
+ Brute level alone is not enough to constitute full fledged language
+ since a code requires various non executable metadata to express
+ developer's intents, check correctness, validity and perform other types
+ of analyses. In Xreate everything of this sort belongs to a layer called
+ <emphasis><?xxe-sn 2b06cb2u4g0 s?>Transcend</emphasis>. Transcend
+ features declarative nature that is appropriate to do management kind of
+ work — it analyzes, oversees and controls brute by guiding compilation
+ process. Everything that is on this level — logic or transcend facts and
+ rules are gathered and sent to an external logic solver to make
+ solutions that are brought back in order to guide compilation.</para>
+ </listitem>
+
+ <listitem>
+ <?xxe-sn 2b06cb2u4g0 l?>
+
+ <para><?xxe-sn 2b06cb2u4g0 m?><link
+ xlink:href="/w/concepts/interpretation/"><?xxe-sn 2b06cb2u4g0 r?>Interpretation</link>.
+ And there is also <emphasis><?xxe-sn 2b06cb2u4g0 t?>Interpretation</emphasis>
+ — intermediate level resembling features of dynamically typed languages
+ that is used as a contact point and interpreter between brute and
+ transcend and their low level and high level constructs and structures
+ respectively.</para>
+ </listitem>
+ </itemizedlist>
+
+ <para><?xxe-sn 2b06cb2u4g0 u?>On a syntactic level Xreate is procedural
+ language with extensive use of <emphasis><?xxe-sn 2b06cb2u4g0 v?><link
+ xlink:href="/w/transcend"><?xxe-sn 2b06cb2u4g0 w?>annotations</link></emphasis>
+ — arbitrary unconstrained metadata that software developer can attach to a
+ different language constructs, variables and code blocks. Annotations are
+ completely invisible for the compiler proper and used by transcend rather as
+ suggestions conveying additional information.</para>
+
+ <para xlink:href="w/virtualization/"><?xxe-sn 2b3f3osfk74 g?>Most severe and
+ hard to resolve problems in software development stem from interaction of
+ different components on a different levels. Each individual component often
+ is thoroughly tested and works reliably. But combining them with complex
+ interaction and extensive IO to build end-user software usually leads to a
+ range of runtime errors, security vulnerabilities and performance
+ degradation. Thus key emphasis of Xreate is on domain specific component
+ level improvements and joint use of external resources. This aspect is
+ covered in <link xlink:href="/w/exploitation/"><?xxe-sn 2b3f3osfk74 h?>exploitation</link>
+ and <link xlink:href="/w/concepts/containers/"><?xxe-sn 2b3f3osfk74 i?>containers</link>
+ chapters. Unlike academic languages, Xreate targets safe and reliable usage
+ of effectful computations, such as IO, covered in <link
+ xlink:href="/w/virtualization"><?xxe-sn 2b3f3osfk74 j?>virtualization</link>,
+ <link xlink:href="/w/exploitation/"><?xxe-sn 2b3f3osfk74 k?>exploitation</link>
+ chapters and mutable structures covered in <link
+ xlink:href="/w/communication/"><?xxe-sn 2b3f3osfk74 l?>communication</link>.</para>
+
+ <section>
+ <?xxe-sn 2b06cb2u4g0 3?>
+
+ <title><?xxe-sn 2b06cb2u4g0 4?>Basic Example</title>
+
+ <para><?xxe-sn 2b06cb2u4g0 5?>To demonstrate what Xreate is all about,
+ basic example is given below:</para>
+
+ <programlisting xml:id="Example_1"><?xxe-sn 2b06cb2u4g0 x?>name="tests/introduction.cpp: Introduction.Doc_Example_1", lines=15
+guard:: iAmVeryFast
+{
+ div = function(a:: float, b:: float):: float
+ {
+ a / b
+ }
+}
+
+guard:: iAmVerySafe
+{
+ div = function(a:: float, b:: float):: float
+ {
+ if ( b == (0::float)):: float {0::float} else {a / b}
+ }
+}
+
+test = function:: float; entry; iAmVerySecure
+{
+ div(10, 5)
+}</programlisting>
+
+ <para><?xxe-sn 2b06cb2u4g0 y?>Here entry point of the program is a
+ function <code><?xxe-sn 2b06cb2u4g0 z?>test</code> recognized so by the
+ compiler because of annotation <code><?xxe-sn 2b06cb2u4g0 10?>entry</code>
+ in its signature. There are also two functions <code><?xxe-sn 2b06cb2u4g0 11?>div</code>
+ called <emphasis><?xxe-sn 2b06cb2u4g0 12?>specializations</emphasis>. Each
+ specialization has a guard that defines condition that has to be met in
+ order to invoke this particular specialization. In the example,
+ specializations of <code><?xxe-sn 2b06cb2u4g0 13?>div</code> have
+ <code><?xxe-sn 2b06cb2u4g0 14?>iAmVeryFast</code> and <code><?xxe-sn 2b06cb2u4g0 15?>iAmVerySafe</code>
+ guards respectively. Let's say, developer provides two specializations
+ where first is a very fast division implementation and second one is a
+ very safe since it checks division by zero but at the same time is
+ unbearably slow due to extra check instruction. This is a basis of <link
+ xlink:href="/w/concepts/polymorphism/"><?xxe-sn 2b3f3osfk74 2?>polymorphism</link>
+ — client's code <code><?xxe-sn 2b3f3osfk74 3?>test</code> is able to work
+ with any specialization, and compiler should decide which one to invoke
+ with the only hint it has — annotation <code><?xxe-sn 2b3f3osfk74 5?>iAmVerySecure</code>
+ in the function <code><?xxe-sn 2b3f3osfk74 7?>test</code>'s signature.
+ </para>
+
+ <note>
+ <?xxe-sn 2b3f3osfk74 n?>
+
+ <para><?xxe-sn 2b3f3osfk74 o?>All annotations(except <code><?xxe-sn 2b3f3osfk74 m?>entry</code>)
+ are custom defined by developer itself.</para>
+ </note>
+
+ <para><?xxe-sn 2b3f3osfk74 6?>This is when transcend comes into play. By
+ adding transcend rule as shown below it is possible to associate
+ annotation <code><?xxe-sn 2b3f3osfk74 8?>iAmVerySecure</code> with
+ invocation of specialization guarded by <code><?xxe-sn 2b3f3osfk74 9?>iAmVerySafe:</code></para>
+
+ <programlisting xml:id="Transcend_Example_1"><?xxe-sn 2b3f3osfk74 a?>name="tests/introduction.cpp: Introduction.Doc_Example_1", lines=15
+dfa_callguard(SiteInv, iAmVerySafe):-
+ dfa_callfn(SiteInv, div);
+ SiteInv = s(_, _, ScopeInv);
+ cfa_parent(ScopeInv, function(FnInv));
+ bind_func(FnInv, iAmVerySecure).</programlisting>
+
+ <para><?xxe-sn 2b3f3osfk74 b?>Transcend rules are written in ASP syntax —
+ common syntax to write logic programs. This particular rule reads that for
+ any function annotated with <code><?xxe-sn 2b3f3osfk74 c?>iAmVerySecure</code>,
+ certain specialization <code><?xxe-sn 2b3f3osfk74 d?>iAmVerySafe</code> is
+ chosen for <code><?xxe-sn 2b3f3osfk74 e?>div</code> invocation. </para>
+
+ <note>
+ <?xxe-sn 2b3f3osfk74 p?>
+
+ <para><?xxe-sn 2b3f3osfk74 q?>In this example an appropriate
+ specialization is statically resolved, so other specialization isn't
+ even compiled. </para>
+ </note>
+
+ <para><?xxe-sn 2b3f3osfk74 f?>By providing custom rules it is possible to
+ implement any polymorphism strategy, be it statically performed or
+ dynamically. The example demonstrates basic workflow: transcend gathers
+ available information about a program, such as annotations and using
+ custom rules makes decisions to guide compilation process particularly by
+ selecting appropriate specializations as in this example. </para>
+ </section>
+</chapter>
diff --git a/git-commit-template b/git-commit-template
index 567e7b8..38a341e 100644
--- a/git-commit-template
+++ b/git-commit-template
@@ -1,12 +1,14 @@
-<Changeset description>
+**REMEMBER TO UPDATE DOCUMENTATION ON THE SITE**
-Syntax: <syntax changes>
-Transcend: <any changes related to reasoning>
-Compilation: <any changes on compilation side>
+ <Changeset description>
+
+Syntax: <syntax changes>
Documentation: <note if requires any changes in documentation>
-<component, AST, DFAPass etc>: <...>
+Transcend: <any changes related to reasoning>
+Compilation: <any changes on compilation side>
-Malfunctions: <what is broken after commit, broken/disabled tests>
+<component, AST, DFAPass etc>: <...>
-Tests: <tests that cover commited changes>
+Malfunctions: <what is broken after commit, broken/disabled tests>
+Tests: <tests that cover commited changes>
diff --git a/installation/docker/patches/potassco-patch-95cc11 b/installation/docker/patches/potassco-patch-95cc11
new file mode 100644
index 0000000..391b1b5
--- /dev/null
+++ b/installation/docker/patches/potassco-patch-95cc11
@@ -0,0 +1,81 @@
+diff --git a/SConscript b/SConscript
+index 0ab4e7a..8341dd8 100644
+--- a/SConscript
++++ b/SConscript
+@@ -183,21 +183,21 @@ DEFS = {}
+ failure = False
+
+ if not conf.CheckBison():
+- print 'error: no usable bison version found'
++ print ('error: no usable bison version found')
+ failure = True
+
+ if not conf.CheckRe2c():
+- print 'error: no usable re2c version found'
++ print ('error: no usable re2c version found')
+ failure = True
+
+ if not conf.CheckCXX():
+- print 'error: no usable C++ compiler found'
+- print "Please check the log file for further information: " + log_file
++ print ('error: no usable C++ compiler found')
++ print ("Please check the log file for further information: " + log_file)
+ Exit(1)
+
+ if not conf.CheckSHCXX():
+- print 'error: no usable (shared) C++ compiler found'
+- print "Please check the log file for further information: " + log_file
++ print ('error: no usable (shared) C++ compiler found')
++ print ("Please check the log file for further information: " + log_file)
+ Exit(1)
+
+ if not conf.CheckThreadLocal():
+@@ -211,7 +211,7 @@ if env['WITH_PYTHON'] == "auto":
+ DEFS["WITH_PYTHON"] = 1
+ elif env['WITH_PYTHON']:
+ if not conf.CheckLibs("python", env['WITH_PYTHON'], "Python.h"):
+- print 'error: python library not found'
++ print ('error: python library not found')
+ failure = True
+ else:
+ with_python = True
+@@ -224,7 +224,7 @@ if env['WITH_LUA'] == "auto":
+ DEFS["WITH_LUA"] = 1
+ elif env['WITH_LUA']:
+ if not conf.CheckLibs("lua", env['WITH_LUA'], "lua.hpp"):
+- print 'error: lua library not found'
++ print ('error: lua library not found')
+ failure = True
+ else:
+ with_lua = True
+@@ -263,7 +263,7 @@ if env['WITH_THREADS'] is not None:
+ elif env['WITH_THREADS'] == "windows":
+ pass # nohing to do
+ else:
+- print 'error: unknown thread model'
++ print ('error: unknown thread model')
+ failure = True
+
+
+@@ -273,7 +273,7 @@ claspEnv.Append(CPPDEFINES=DEFS)
+ # {{{1 Check configuration
+
+ if failure:
+- print "Please check the log file for further information: " + log_file
++ print ("Please check the log file for further information: " + log_file)
+ Exit(1)
+
+ # {{{1 Opts: Library
+diff --git a/libprogram_opts/src/string_convert.cpp b/libprogram_opts/src/string_convert.cpp
+index 5e35424..16217de 100644
+--- a/libprogram_opts/src/string_convert.cpp
++++ b/libprogram_opts/src/string_convert.cpp
+@@ -53,7 +53,7 @@ typedef _locale_t locale_t;
+ #define freelocale _free_locale
+ inline locale_t default_locale() { return _create_locale(LC_ALL, "C"); }
+ #else
+-#include <xlocale.h>
++#include <locale.h>
+ inline locale_t default_locale() { return newlocale(LC_ALL_MASK, "C", 0); }
+ #endif
+ static struct LocaleHolder {
diff --git a/installation/prepare-opensuse-leap15 b/installation/prepare-opensuse-leap15
new file mode 100644
index 0000000..9100666
--- /dev/null
+++ b/installation/prepare-opensuse-leap15
@@ -0,0 +1,65 @@
+#!/bin/bash
+
+# VERSIONS OF MAJOR DEPENDENCIES:
+# OPENSUSE LEAP 15
+# LLVM: 5.0.1
+# CLANG: 5.0.1
+# GCC: 7.3.1
+
+CLINGO_PATH=/opt/potassco/clingo
+COCO_PATH=/opt/coco
+XREATE_PATH=/opt/xreate
+
+CLASP_VERSION=95cc1182f
+
+# PREREQUISITES
+#
+sudo zypper in \
+ git wget unzip make \
+ gcc7-c++ scons bison re2c\
+ llvm5-devel libboost_headers1_66_0-devel \
+ cmake gtest tbb-devel clang5-devel \
+ libxml2-devel libboost_system1_66_0-devel libboost_filesystem1_66_0-devel
+
+
+# COCO CPP
+# The Compiler Generator Coco/R
+# http://www.ssw.uni-linz.ac.at/coco/#CPP
+#
+mkdir $COCO_PATH
+cd $COCO_PATH
+wget http://www.ssw.uni-linz.ac.at/coco/CPP/CocoSourcesCPP.zip
+unzip ./CocoSourcesCPP.zip
+make
+
+
+# CLINGO
+# A grounder and solver for logic programs.
+# https://github.com/potassco/clingo
+#
+mkdir -p $CLINGO_PATH
+cd $CLINGO_PATH
+git clone https://github.com/potassco/clingo.git ./ &&\
+git reset --hard $CLASP_VERSION
+git apply $XREATE_PATH/installation/docker/patches/potassco-patch-95cc11
+scons configure --build-dir=debug &&\
+ sed -i "s/, '-fvisibility=hidden'//" build/debug.py &&\
+ sed -i "s/CXXFLAGS = \[\(.*\)\]/CXXFLAGS = \['-fPIC', \1\]/" build/debug.py &&\
+ sed -i "s/WITH_LUA = 'auto'/WITH_LUA = None/" build/debug.py &&\
+ sed -i "s/WITH_PYTHON = 'auto'/WITH_PYTHON = None/" build/debug.py &&\
+ sed -i "s/'-std=c++11'/'-std=c++14'/" build/debug.py &&\
+ cat build/debug.py &&\
+ scons --build-dir=debug
+
+
+# XREATE
+#
+cd $XREATE_PATH/vendors/jeayeson
+./configure
+mkdir ../../build
+cd ../../build
+ln -s $COCO_PATH/Copyright.frame $XREATE_PATH/vendors/coco/generator/Copyright.frame
+ln -s $COCO_PATH/Scanner.frame $XREATE_PATH/vendors/coco/generator/Scanner.frame
+mkdir $XREATE_PATH/grammar/main $XREATE_PATH/grammar/modules
+cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_XREATE_TESTS=1 -DCOCO_EXECUTABLE=$COCO_PATH/Coco -DCOCO_FRAMES_PATH=$XREATE_PATH/vendors/coco/generator/ -DCMAKE_CXX_COMPILER=g++ ../cpp
+
diff --git a/scripts/containers/containers.lp b/scripts/containers/containers.lp
index 2a05f4d..4d1b17a 100644
--- a/scripts/containers/containers.lp
+++ b/scripts/containers/containers.lp
@@ -1,87 +1,93 @@
% This Source Code Form is subject to the terms of the Mozilla Public
% License, v. 2.0. If a copy of the MPL was not distributed with this
% file, You can obtain one at http://mozilla.org/MPL/2.0/.
-%defines
- impl(solid; llvm_const_array; on_the_fly).
- op(seqaccess). op(randaccess).
-
- relation(recommends; satisfied; unsupported).
- relation_score(satisfied, 0).
- relation_score(recommends, 1).
- relation_score(unsupported, -1).
- score(-1..1).
+ %DEFINES
+container(solid; onthefly; llvm_const_array).
+access(serial; rand).
+relation(recommends; satisfied; unsupported).
+score(-1..1).
+
- %domain facts:
-relation_op(seqaccess, on_the_fly, recommends).
-relation_op(randaccess, llvm_const_array, recommends).
-relation_op(randaccess, on_the_fly, unsupported).
+ %DOMAIN FACTS
+relation_score(
+ unsupported, -1;
+ satisfied, 0;
+ recommends, 1
+).
+
+relation_access(
+ serial, onthefly, recommends;
+ rand, llvm_const_array, recommends;
+ rand, onthefly, unsupported
+).
+
%AST ATTACHMENTS
-attach_operator_map(none, op(seqaccess)).
-attach_operator_fold(none, op(seqaccess), none).
+attach_operator_map(none, access(serial)).
+attach_operator_fold(none, access(serial), none).
-attach_operator_list_range(impl(on_the_fly)).
-attach_operator_list(impl(solid)).
-attach_operator_index(op(randaccess)).
+attach_operator_list_range(container(onthefly)).
+attach_operator_list(container(solid)).
+attach_operator_index(access(rand)).
%CLUSTERS
cluster_link(VTo, VFrom):- %aliases
dfa_connection(VTo, VFrom, strong).
cluster_link(VResult, VSource):- %Operator MAP
ast_op_map(VResult, VSource, _).
cluster_root(V):-
not cluster_link(V, _);
v(V).
var_cluster(V, V):- %self referencing
cluster_root(V).
var_cluster(VRoot, VTo):- %propagation down the tree
cluster_link(VTo, VFrom);
var_cluster(VRoot, VFrom).
%ALGORITHM
-impl_fulfill(OP, IMPL):-
relation_op(OP, IMPL, unsupported).
impl_fulfill(OP, IMPL, SCORE):-
SCORE = #sum{SCORE1, (OP, IMPL, RL): relation_op(OP, IMPL, RL), relation_score(RL, SCORE1)};
not -impl_fulfill(OP, IMPL);
- op(OP); impl(IMPL).
+ access(OP); container(IMPL).
-impl_fulfill_cluster(Var0, Impl):-
var_cluster(Var0, Var_Any);
- bind(Var_Any, op(Op));
+ bind(Var_Any, access(Op));
-impl_fulfill(Op, Impl).
impl_fulfill_cluster(VAR0, IMPL, Score):-
- Score = #sum{SCORE, (OP, IMPL, VAR_ANY): impl_fulfill(OP, IMPL, SCORE), var_cluster(VAR0, VAR_ANY), bind(VAR_ANY, op(OP))};
- bind(VAR0, impl(IMPL));
+ Score = #sum{SCORE, (OP, IMPL, VAR_ANY): impl_fulfill(OP, IMPL, SCORE), var_cluster(VAR0, VAR_ANY), bind(VAR_ANY, access(OP))};
+ bind(VAR0, container(IMPL));
cluster_root(VAR0);
not -impl_fulfill_cluster(VAR0, IMPL).
%OUTPUT
containers_impl(V, Impl):-
containers_impl(VRoot, Impl);
var_cluster(VRoot, V).
containers_impl(V, solid(Size)):-
impl_fulfill_cluster(V, solid, _);
ast_op_list(V, Size);
cluster_root(V).
-containers_impl(V, on_the_fly):-
- impl_fulfill_cluster(V, on_the_fly, _);
+containers_impl(V, onthefly):-
+ impl_fulfill_cluster(V, onthefly, _);
ast_op_list_range(V);
cluster_root(V).
%optimization
% #maximize {SCORE, (VAR0, IMPL) : impl_fulfill_cluster(VAR0, IMPL, SCORE)}.
#show var_cluster/2.
#show impl_fulfill_cluster/3.
diff --git a/vendors/coco/generator/Copyright.frame b/vendors/coco/generator/Copyright.frame
deleted file mode 120000
index 708b5d5..0000000
--- a/vendors/coco/generator/Copyright.frame
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/coco-cpp/Copyright.frame
\ No newline at end of file
diff --git a/vendors/coco/generator/Scanner.frame b/vendors/coco/generator/Scanner.frame
deleted file mode 120000
index d1ee132..0000000
--- a/vendors/coco/generator/Scanner.frame
+++ /dev/null
@@ -1 +0,0 @@
-/usr/share/coco-cpp/Scanner.frame
\ No newline at end of file

Event Timeline