context.cpp
No OneTemporary

File Metadata

Created
Thu, Jul 9, 12:33 AM

context.cpp

/*
* frame-context.cpp
*
* Created on: Dec 3, 2015
* Author: pgess
*/
#include "passmanager.h"
#include "query/context.h"
#include "gtest/gtest.h"
#include <iostream>
#include <boost/scoped_ptr.hpp>
using namespace xreate;
//TEST(Context, frame_Context1){
// PassManager* man = PassManager::prepareForCode(
// " import raw (\"core/control-context.lp\")\n"
// " testC = function::int {\n"
// " context:: testC.\n"
//
// " 0\n"
// " }\n"
//
// " testA = function:: int {\n"
// " context:: testA; test.\n"
//
// " testC()\n"
// " }\n"
//
// " testB = function:: int {\n"
// " context:: testB; test.\n"
//
// " testC()\n"
// " }\n"
// );
//
// ContextQuery* query = (ContextQuery*) man->clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery);
// man->runWithoutCompilation();
//
// CodeScope* scopeTestC = man->root->findFunction("testC")->getEntryScope();
// const ContextDomain& context = query->getContext(man->clasp->pack(scopeTestC));
//
// int contextSize = context.size();
// EXPECT_EQ(2, contextSize);
//}
//
//TEST(Context, full_ContextBasedFunctionSpecialization){
//
// PassManager* man = PassManager::prepareForCode(
// " case context::toMillimeters {\n"
// " convert = function(source:: num)::num {\n"
// " 10 * source \n"
// " }\n"
// " }\n"
//
// " case context::toInches {\n"
// " convert = function(source:: num)::num {\n"
// " 2 * source \n"
// " }\n"
// " }\n"
//
// "test = function(vrnt:: int)::int; entry {\n"
// " switch(vrnt):: int\n"
// " case 0 {\n"
// " context:: toMillimeters.\n"
// " convert(1)\n"
// " }\n"
// "\n"
// " case 1 {\n"
// " context:: toInches.\n"
// " convert(1)\n"
// " }\n"
// " case default {0}\n"
// " }" );
//
// int (*main)(int) = (int (*)(int)) man->run();
// ASSERT_EQ(10, main(0));
// ASSERT_EQ(2, main(1));
//}
//
//TEST(Context, full_LoopContext){
//
// PassManager* man = PassManager::prepareForCode("case context:: a {\n"
// " print = function:: string {\n"
// " \"a\"\n"
// " }}\n"
// "\n"
// " case context:: b {\n"
// " print = function:: string {\n"
// " \"b\"\n"
// " }}\n"
// "\n"
// " case context:: c {\n"
// " print = function:: string {\n"
// " \"c\"\n"
// " }}\n"
// "\n"
// " case context:: d {\n"
// " print = function:: string {\n"
// " \"d\"\n"
// " }}\n"
// "\n"
// " start = function(command::int)::string; entry {\n"
// " switch (command) :: string \n"
// " case 0 {\n"
// " context:: print(a); print(b); print(d).\n"
// "\n"
// " loop context (\"print\") {\n"
// " print()\n"
// " }\n"
// " }\n"
// "\n"
// " case default {\n"
// " context:: print(c).\n"
// " loop context (\"print\") {\n"
// " print()\n"
// " }\n"
// " }\n"
// " }");
//
//
// char* (*main)(int) =(char* (*)(int)) man->run();
// ASSERT_STREQ("c", main(1));
// ASSERT_STREQ("a", main(0));
//}
//
//TEST(Context, full_RuleContext){
// /*
// "rule context:: childs(Child)\n"
// " case artefact(Item)\n"
// " {\n"
// " artefact_depends(Item, Child)\n"
// " }";
// */
//
// PassManager* man = PassManager::prepareForCode(
// " case context:: toMilli {\n"
// " convert = function(length::int)::int{\n"
// " 10 * length\n"
// " }\n"
// " }\n"
// "\n"
// " case context:: toCenti {\n"
// " convert = function(length::int)::int{\n"
// " length\n"
// " }\n"
// " }\n"
// "\n"
// " main=function::int; entry {\n"
// " context:: output(milli).\n"
// "\n"
// " rule context::toMilli\n"
// " case output(milli) {true}\n"
// "\n"
// " convert(1)\n"
// " }" );
// man->clasp->addRawScript("true.");
//
// int (*entry)() = (int (*)()) man->run();
// ASSERT_EQ(10, entry());
//}
//
//TEST(Context, full_InheritedRuleContext){
// PassManager* man = PassManager::prepareForCode(
// " import raw (\"core/control-context.lp\") \n"
//
// " case context:: toMilli {\n"
// " convert = function(length::int)::int{\n"
// " 10 * length\n"
// " }\n"
// " }\n"
//
// " case context:: toCenti {\n"
// " convert = function(length::int)::int{\ n"
// " length\n"
// " }\n"
// " }\n"
// "\n"
//
// "main = function(comm:: num)::num; entry{\n"
// " rule context::X case output(X) {true}\n"
// "\n"
// " switch (comm)::num \n"
// " case 0 {\n"
// " context:: output(toMilli).\n"
// " convert(1)\n"
// " }\n"
// " case default {\n"
// " context:: output(toCenti).\n"
// " convert(1)\n"
// " }\n"
// " }");
//
// man->clasp->addRawScript("true.");
// int (*entry)(int) = (int (*)(int)) man->run();
// ASSERT_EQ(10, entry(0));
// ASSERT_EQ(1, entry(1));
//}
//
//
//
//TEST(Context, full_LateContext){
// PassManager* man = PassManager::prepareForCode(
// "import raw (\"core/control-context.lp\")\n"
//
// " convert = function(length:: num)::num{\n"
// " 0\n"
// " }\n"
//
// "case context:: milli {\n"
// " convert = function(length:: num)::num{\n"
// " 1000 * length\n"
// " }\n"
// "}\n"
// "\n"
// "case context:: centi {\n"
// " convert = function(length:: num)::num{\n"
// " 100 * length\n"
// " }\n"
// "}\n"
// "\n"
// "calculate = function(length:: num)::num {\n"
// " convert(length)\n"
// "}\n"
// "\n"
// "main = function(com:: num):: num; entry {\n"
// " switch (com):: num \n"
// " case 0 {\n"
// " context:: milli.\n"
// " calculate(1)\n"
// " }\n"
// "\n"
// " case default{\n"
// " context:: centi. \n"
// " calculate(1)\n"
// " }\n"
// "}");
//
// man->runWithoutCompilation();
// ContextQuery* queryContext = reinterpret_cast<ContextQuery*>(man->clasp->getQuery(QueryId::ContextQuery));
// Expression exprSwitch = man->root->findFunction("main")->__entry->__body;
// CodeScope* blockDefault = man->root->findFunction("main")->__entry->__body.operands[1].blocks.front();
// ScopePacked blockDefaultId = man->clasp->pack(blockDefault);
// const ContextDomain& domDefault = queryContext->getContext(blockDefaultId);
// ASSERT_EQ(1, domDefault.count(Expression(Atom<Identifier_t>("centi"))));
//
// std::list<ManagedFnPtr> variants = man->root->getFunctionVariants("convert");
// for (ManagedFnPtr f: variants){
// const Expression guard = f->guardContext;
// bool result = (guard.getValueString() == "centi" || guard.getValueString() == "milli" || !guard.isValid());
// ASSERT_TRUE(result);
// }
//
// const FunctionContextDemand& demMain = queryContext->getFunctionDemand("main");
// ASSERT_EQ(0, demMain.size());
//
// const FunctionContextDemand& demCalculate = queryContext->getFunctionDemand("calculate");
// ASSERT_EQ(1, demCalculate.size());
// ASSERT_EQ(1, demCalculate.right.count("convert"));
//
// int (*entry)(int) = (int (*)(int)) man->run();
// ASSERT_EQ(1000, entry(0));
// ASSERT_EQ(100, entry(1));
//}
TEST(Context, pathDependent_context){
std::string program =
R"CODE(
import raw("core/control-context.lp")
convert = function(length:: num) :: num {
0
}
case context:: convert(milli, meters) {
convert = function(length:: num) :: num {
1000 * length
}
}
case context:: convert(centi, meters) {
convert = function(length:: num) :: num {
100 * length
}
}
case context:: convert(centi, kilo) {
convert = function(length:: num) :: num {
100000 * length
}
}
case context:: convert(milli, kilo) {
convert = function(length:: num) :: num {
1000000 * length
}
}
main = function(value::num, unitsInput::num, unitsOutput::num)::num; entry{
switch (unitsInput)::num
case 0 {
test_fromMilli(value, unitsOutput)
}
case 1 {
test_fromCenti(value, unitsOutput)
}
case default {0}
}
test_fromCenti = function(value::num, output::num)::num{
context:: input(centi).
switch(output):: num
case 0 {
toMeters(value)
}
case 1 {
toKilo(value)
}
case default {0}
}
test_fromMilli = function(value::num, output::num)::num{
context:: input(milli).
switch(output):: num
case 0 {
toMeters(value)
}
case 1 {
toKilo(value)
}
case default {0}
}
toMeters = function(value::num)::num {
rule context:: convert(X, meters) case input(X) {true}
doConvert(value)
}
toKilo = function(value::num)::num {
rule context:: convert(X, kilo) case input(X) {true}
doConvert(value)
}
doConvert = function(value::num)::num{
convert(value)
})CODE";
boost::scoped_ptr<PassManager> man(PassManager::prepareForCode(move(program)));
man->runWithoutCompilation();
int (*test)(int, int, int) = (int (*)(int, int, int))man->run();
enum {INPUT_MILLI, INPUT_CENTI};
enum {OUTPUT_METERS, OUTPUT_KILO};
ASSERT_EQ(1000000, test(1, INPUT_MILLI, OUTPUT_KILO));
ASSERT_EQ(200, test(2, INPUT_CENTI, OUTPUT_METERS));
}

Event Timeline