Page Menu
Home
Xreate
Search
Configure Global Search
Log In
Docs
Questions
Repository
Issues
Patches
Internal API
Files
F3995256
compilation.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Jul 6, 11:18 PM
Size
9 KB
Mime Type
text/x-c++
Expires
Wed, Jul 8, 11:18 PM (3 h, 50 m)
Engine
blob
Format
Raw Data
Handle
271523
Attached To
rXR Xreate
compilation.cpp
View Options
/* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/publicdomain/zero/1.0/
*
* compilation.cpp
*
* Created on: -
* Author: pgess <v.melnychenko@xreate.org>
*/
#include "xreatemanager.h"
#include "supplemental/basics.h"
#include "llvmlayer.h"
#include "pass/compilepass.h"
#include "compilation/lambdas.h"
#include "gtest/gtest.h"
using namespace xreate;
using namespace xreate::compilation;
using namespace std;
//DEBT implement no pkgconfig ways to link libs
//TOTEST FunctionUnit::compileInline
TEST(Compilation, functionEntry1){
std::unique_ptr<XreateManager> program(XreateManager::prepare(
"func1 = function(a:: int):: int {a+8} \
func2 = function::int; entry {12 + func1(4)} \
"));
void* entryPtr = program->run();
int (*entry)() = (int (*)())(intptr_t)entryPtr;
int answer = entry();
ASSERT_EQ(24, answer);
}
TEST(Compilation, full_IFStatementWithVariantType){
XreateManager* man = XreateManager::prepare(
"Color = type variant {RED, BLUE, GREEN}.\n"
"\n"
" main = function(x::int):: bool; entry {\n"
" color = if (x == 0 )::Color {RED()} else {BLUE()}.\n"
" if (color == BLUE())::bool {true} else {false}\n"
" }"
);
bool (*main)(int) = (bool (*)(int)) man->run();
ASSERT_FALSE(main(0));
ASSERT_TRUE(main(1));
}
TEST(Compilation, full_Variant1){
XreateManager* man = XreateManager::prepare(R"Code(
global = type predicate {
entry
}
Command= type variant{
Add(x::int, y::int),
Dec(x::int)
}.
main = function::Command; entry() {
Dec(2) ::Command
}
)Code");
void (*main)() = (void (*)()) man->run();
}
TEST(Compilation, full_SwitchVariant1){
XreateManager* man = XreateManager::prepare(R"Code(
Command= type variant{
Add(x::int, y::int),
Dec(x::int)
}.
main = function::int; entry {
command = Add(3, 5):: Command.
switch variant(command)::int
case(Add){command["x"] + command["y"]}
case(Dec){command["x"]}
}
)Code");
int (*mainFn)() = (int (*)()) man->run();
int result = mainFn();
ASSERT_EQ(8, result);
}
TEST(Compilation, full_SwitchVariantNoArguments2){
XreateManager* man = XreateManager::prepare(R"Code(
Command= type variant{Add, Dec}.
main = function::int; entry {
command = Dec():: Command.
switch variant(command)::int
case(Add){0}
case(Dec){1}
}
)Code");
int (*mainFn)() = (int (*)()) man->run();
int result = mainFn();
ASSERT_EQ(1, result);
}
TEST(Compilation, full_SwitchVariantMixedArguments3){
XreateManager* man = XreateManager::prepare(R"Code(
Command= type variant{
Add(x::int, y::int),
Dec
}.
main = function(arg::int):: int; entry {
command = if (arg > 0)::Command {Dec()} else {Add(1, 2)}.
switch variant(command)::int
case(Add){0}
case(Dec){1}
}
)Code");
int (*mainFn)(int) = (int (*)(int)) man->run();
int result = mainFn(5);
ASSERT_EQ(1, result);
}
TEST(Compilation, full_StructUpdate){
XreateManager* man = XreateManager::prepare(
R"Code(
Rec = type {
a :: int,
b:: int
}.
test= function:: int; entry {
a = {a = 18, b = 20}:: Rec.
b = a + {a = 11}:: Rec.
b["a"]
}
)Code");
int (*main)() = (int (*)()) man->run();
int result = main();
ASSERT_EQ(11, result);
}
TEST(Compilation, AnonymousStruct_init_index){
std::string code =
R"Code(
main = function:: int; entry {
x = {10, 15} :: {int, int}.
x[1]
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
int (*main)() = (int (*)()) man->run();
EXPECT_EQ(15, main());
}
TEST(Compilation, AnonymousStruct_init_update){
std::string code =
R"Code(
main = function:: int; entry {
x = {10, 15} :: {int, int}.
y = x + {6}:: {int, int}.
y[0]
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
int (*main)() = (int (*)()) man->run();
EXPECT_EQ(6, main());
}
TEST(Compilation, BugIncorrectScopes1){
std::string code =
R"Code(
init = function:: int {10}
main = function(cmd:: int):: int; entry {
x = init():: int.
if(cmd > 0):: int { x + 1 } else { x }
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
int (*mainFn)(int) = (int (*)(int)) man->run();
EXPECT_EQ(11, mainFn(1));
}
TEST(Compilation, Sequence1){
std::string code =
R"Code(
interface(extern-c){
libbsd = library:: pkgconfig("libbsd").
include {
libbsd = {"bsd/stdlib.h", "string.h"}
}.
}
start = function:: i32; entry {
seq {
nameNew = "TestingSequence":: string.
setprogname(nameNew)
} {strlen(getprogname())}::i32
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
int (*startFn)() = (int (*)()) man->run();
int nameNewLen = startFn();
ASSERT_EQ(15, nameNewLen);
}
TEST(Compilation, BoolInstructions1){
std::string code =
R"Code(
test = function (a:: bool, b:: bool):: bool; entry
{
-a
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
Fn2Args startFn = (Fn2Args) man->run();
}
TEST(Compilation, StructIndex1){
std::string code =
R"Code(
Anns = type predicate {
entry()
}
test = function:: int; entry()
{
x = {a = ({b = 3}::{b:: int})}:: {a:: {b:: int}}.
2 + x["a", "b"] + x["a"]["b"]
}
)Code";
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
FnNoArgs startFn = (FnNoArgs) man->run();
int result = startFn();
ASSERT_EQ(2, result);
}
TEST(Compilation, PreferredInt1){
std::unique_ptr<XreateManager> man(XreateManager::prepare(""));
TypesHelper utils(man->llvm);
int bitwidth = utils.getPreferredIntTy()->getBitWidth();
ASSERT_EQ(64, bitwidth);
}
TEST(Compilation, PredPredicates1){
string code = R"(
my-fn = function:: int; entry() {0}
)";
auto man = XreateManager::prepare(move(code));
FnNoArgs startFn = (FnNoArgs) man->run();
int result = startFn();
ASSERT_EQ(0, result);
}
typedef intmax_t (*FnI_I)(intmax_t);
TEST(Compilation, Lambda1){
string code = R"(
myfn = function:: int {
a = [1..5]:: [int].
loop map(a->x:: int):: [int] { x + 10:: int}
}
)";
auto man = details::tier1::XreateManager::prepare(move(code));
LLVMLayer* llvm = man->llvm;
man->analyse();
std::unique_ptr<CompilePass> compiler(new compilation::CompilePassCustomDecorators<>(man));
compiler->prepare();
LambdaIR compilerLambda(compiler.get());
CodeScope* scopeLoop = man->root->findFunction("myfn")->getEntryScope()->getBody().blocks.front();
auto fnRaw = compilerLambda.compile(scopeLoop, "loop");
llvm->initJit();
FnI_I fn = (FnI_I)llvm->getFunctionPointer(fnRaw);
ASSERT_EQ(20, fn(10));
}
TEST(Compilation, Lambda_BoundVars1){
string code = R"(
myfn = function:: int {
a = [1..5]:: [int].
offset = 10:: int.
loop map(a->x:: int):: [int] { x + offset:: int}
}
)";
auto man = details::tier1::XreateManager::prepare(move(code));
LLVMLayer* llvm = man->llvm;
man->analyse();
std::unique_ptr<CompilePass> compiler(new compilation::CompilePassCustomDecorators<>(man));
compiler->prepare();
LambdaIR compilerLambda(compiler.get());
CodeScope* scopeLoop = man->root->findFunction("myfn")->getEntryScope()->getBody().blocks.front();
auto fnRaw = compilerLambda.compile(scopeLoop, "loop");
llvm->print();
llvm->initJit();
Fn2Args fn = (Fn2Args)llvm->getFunctionPointer(fnRaw);
ASSERT_EQ(30, fn(10, 20));
}
struct Tuple3 {intmax_t a; intmax_t b; intmax_t c; };
typedef Tuple3 (*FnTuple3)();
intmax_t fn_BUG_Triple(FnTuple3 callee){
Tuple3 result = callee();
return result.a+ result.b + result.c;
}
TEST(Compilation, BUG_Triple){
std::unique_ptr<XreateManager> man(XreateManager::prepare(R"(
Tuple2 = type {int, int}.
Tuple3 = type {int, int, int}.
Tuple4 = type {int, int, int, int}.
main = function:: Tuple3; entry()
{
{1, 2, 3}
}
)"));
FnTuple3 mainFn = (FnTuple3) man->run();
intmax_t result = fn_BUG_Triple(mainFn);
ASSERT_EQ(6, result);
// ASSERT_EQ(2, result.b);
// ASSERT_EQ(3, result.c);
}
TEST(Compilation, ExteriorFns1){
std::unique_ptr<XreateManager> man(XreateManager::prepare(R"(
fn-a = function:: int; exterior() {1}
fn-b = function:: int; exterior() {2}
)"));
man->options.requireEntryFn = false;
man->run();
FnNoArgs fnA = (FnNoArgs) man->getExteriorFn("fn-a");
ASSERT_EQ(1, fnA());
FnNoArgs fnB = (FnNoArgs) man->getExteriorFn("fn-b");
ASSERT_EQ(2, fnB());
}
TEST(Compilation, LLVMAliases){
FILE* code = fopen("scripts/compilation/llvmaliases.xreate", "r");
assert(code != nullptr);
std::unique_ptr<XreateManager> man(XreateManager::prepare(move(code)));
man->run();
}
Event Timeline
Log In to Comment