This commit is contained in:
Yatao Li 2018-09-04 22:48:18 +08:00
Родитель d5728c6d11
Коммит f7a8bf547d
219 изменённых файлов: 36 добавлений и 17712 удалений

Просмотреть файл

@ -21,11 +21,9 @@ SET_OUTPUT_DIRECTORY(${CMAKE_BINARY_DIR})
DOTNET_REGISTER_LOCAL_REPOSITORY("Graph Engine OSS Local" "${CMAKE_BINARY_DIR}")
IF(WIN32)
SET(CMAKE_CXX_FLAGS "/volatile:iso /EHa /fp:except- /Zi /Gy /MP /W3 /nologo")
SET(CMAKE_CXX_FLAGS_RELEASE "/Oi /Ot /Ob2 /Oy /O2 /MT /GS- /GL")
SET(CMAKE_CXX_FLAGS_DEBUG "/Od /MTd /GS")
SET(CMAKE_SHARED_LINKER_FLAGS "/LTCG /OPT:REF /OPT:ICF /SUBSYSTEM:WINDOWS /INCREMENTAL /DEBUG:FULL")
SET(CMAKE_EXE_LINKER_FLAGS "/LTCG /OPT:REF /OPT:ICF /INCREMENTAL /DEBUG:FULL")
ADD_COMPILE_OPTIONS(/volatile:iso /EHa /fp:except- /Zi /Gy /W3 /nologo /MP)
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /DEBUG:FULL")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /DEBUG:FULL")
ELSEIF(UNIX)
ADD_COMPILE_OPTIONS(-fpermissive -Wall -Wno-write-strings -Wno-unknown-pragmas -pthread)
ELSE()
@ -36,8 +34,6 @@ ADD_SUBDIRECTORY(src/GraphEngine)
ADD_SUBDIRECTORY(src/Trinity.TSL)
ADD_SUBDIRECTORY(src/Trinity.C)
ADD_SUBDIRECTORY(src/Trinity.Core)
ADD_SUBDIRECTORY(src/Modules/GraphEngine.Jit)
ADD_SUBDIRECTORY(src/Modules/Trinity.FFI)
ADD_SUBDIRECTORY(src/Modules/LIKQ)
ADD_SUBDIRECTORY(src/Modules/GraphEngine.Storage.Composite)
ADD_SUBDIRECTORY(src/Modules/GraphEngine.Client)

Просмотреть файл

@ -124,7 +124,7 @@ FUNCTION(DOTNET_GET_DEPS _DN_PROJECT arguments)
ENDIF()
IF(NOT _DN_CONFIG)
SET(_DN_CONFIG Release)
SET(_DN_CONFIG $<CONFIG>)
ENDIF()
# If platform is not specified, do not pass the Platform property.
@ -215,7 +215,7 @@ FUNCTION(ADD_DOTNET DOTNET_PROJECT)
SET(_DOTNET_BUILD_NUPKGS "")
FOREACH(pkg ${DOTNET_PACKAGES})
LIST(APPEND _DOTNET_BUILD_NUPKGS ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${pkg}.${DOTNET_PACKAGE_VERSION}.nupkg)
LIST(APPEND _DOTNET_BUILD_NUPKGS ${pkg}.${DOTNET_PACKAGE_VERSION}.nupkg)
ENDFOREACH()
ADD_CUSTOM_COMMAND(

Двоичные данные
lib/GraphEngine.Jit.Native.dll

Двоичный файл не отображается.

Двоичные данные
lib/GraphEngine.Jit.Native.lib

Двоичный файл не отображается.

Двоичные данные
lib/libGraphEngine.Jit.Native.so

Двоичный файл не отображается.

Двоичные данные
lib/libtrinity_ffi.so

Двоичный файл не отображается.

Двоичные данные
lib/libtrinity_host.so

Двоичный файл не отображается.

Двоичные данные
lib/trinity_ffi.dll

Двоичный файл не отображается.

Двоичные данные
lib/trinity_ffi.lib

Двоичный файл не отображается.

Двоичные данные
lib/trinity_host.dll

Двоичный файл не отображается.

Двоичные данные
lib/trinity_host.lib

Двоичный файл не отображается.

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<RootNamespace>Trinity.Client</RootNamespace>
<AssemblyName>Trinity.Client</AssemblyName>
<OutputType>library</OutputType>

Просмотреть файл

@ -5,7 +5,7 @@
</PropertyGroup>
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<RootNamespace>Trinity.Azure.Storage</RootNamespace>
<AssemblyName>Trinity.Azure.Storage</AssemblyName>
<OutputTypeEx>library</OutputTypeEx>

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<AssemblyName>Trinity.DynamicCluster</AssemblyName>
<RootNamespace>Trinity.DynamicCluster</RootNamespace>
<OutputPath>..\..\..\..\bin</OutputPath>

Просмотреть файл

@ -1,17 +0,0 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0)
PROJECT(GraphEngine.Jit)
ADD_SUBDIRECTORY(GraphEngine.Jit.Native)
# dotnet build does not generate fsproj.metaproj
# workaround: build fsproj instead of sln
# see: https://github.com/Microsoft/msbuild/issues/2275
ADD_DOTNET(GraphEngine.Jit/GraphEngine.Jit.fsproj
PACKAGE GraphEngine.Jit
VERSION ${TRINITY_VERSION}
DEPENDS GraphEngine.Core)
# TODO unit test
ADD_DEPENDENCIES(BUILD_GraphEngine.Jit GraphEngine.Jit.Native)

Просмотреть файл

@ -1,13 +0,0 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0)
FIND_PACKAGE(AsmJit)
FILE(GLOB_RECURSE jit_src ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -DUNICODE -D_UNICODE)
ADD_LIBRARY(GraphEngine.Jit.Native SHARED ${jit_src})
TARGET_INCLUDE_DIRECTORIES(GraphEngine.Jit.Native PRIVATE ${ASMJIT_SOURCE_DIR})
TARGET_COMPILE_DEFINITIONS(GraphEngine.Jit.Native PRIVATE -DGRAPHENGINEJITNATIVE_EXPORTS)
TARGET_LINK_LIBRARIES(GraphEngine.Jit.Native PRIVATE Trinity asmjit)
POSTBUILD_XPLAT_OUTPUT(GraphEngine.Jit.Native ${XPLAT_LIB_DIR})

Просмотреть файл

@ -1,32 +0,0 @@
#pragma once
#include <cstdint>
#include "Trinity.h"
#pragma pack(push,1)
struct CellAccessor
{
int64_t cellPtr;
int64_t cellId;
int32_t size;
int32_t entryIndex;
uint16_t type;
uint8_t isCell;
uint8_t malloced;
CellAccessor() {}
inline void Release()
{
if (malloced)
{
free((void*)cellPtr);
}
else if(isCell)
{
::CReleaseCellLock(cellId, entryIndex);
}
}
};
#pragma pack(pop)

Просмотреть файл

@ -1,148 +0,0 @@
#include "Common.h"
#include "Trinity.h"
#include "CellAccessor.h"
#include <map>
#include <codecvt>
#include "Trinity/Hash/NonCryptographicHash.h"
using namespace asmjit;
static std::map<TypeCode, TypeId::Id> s_atom_typemap{
{TypeCode::TC_U8 , TypeId::kU8 },
{TypeCode::TC_U16 , TypeId::kU16 },
{TypeCode::TC_U32 , TypeId::kU32 },
{TypeCode::TC_U64 , TypeId::kU64 },
{TypeCode::TC_I8 , TypeId::kI8 },
{TypeCode::TC_I16 , TypeId::kI16 },
{TypeCode::TC_I32 , TypeId::kI32 },
{TypeCode::TC_I64 , TypeId::kI64 },
{TypeCode::TC_F32 , TypeId::kF32 },
{TypeCode::TC_F64 , TypeId::kF64 },
{TypeCode::TC_BOOL , TypeId::kU8 },
{TypeCode::TC_CHAR , TypeId::kU16 },
};
TypeId::Id GetTypeId(IN TypeDescriptor* const type)
{
auto c = static_cast<TypeCode>(type->get_TypeCode());
auto i = s_atom_typemap.find(c);
return i != s_atom_typemap.cend() ? i->second : TypeId::kUIntPtr;
}
u16char* tsl_getstring(int32_t* trinity_string_ptr)
{
print(__FUNCTION__);
debug((int64_t)trinity_string_ptr);
auto len = *trinity_string_ptr;
u16char* buf = (u16char*)malloc(len + 2);
memcpy(buf, trinity_string_ptr + 1, len);
buf[len / 2] = 0;
debug(len);
// wprintf(L"tsl_getstring = %s\n", buf);
return buf;
}
u16char* tsl_getu8string(int32_t* trinity_string_ptr)
{
auto arr = Trinity::String::Utf8ToUtf16((char*)(trinity_string_ptr + 1), *trinity_string_ptr);
return arr.detach_data();
}
void* tsl_dup(char* ptr, int32_t size)
{
auto buf = malloc(size);
return memcpy(buf, ptr, size);
}
void* tsl_dup_dynamic(int32_t* ptr)
{
auto len = sizeof(int) + *ptr;
return tsl_dup((char*)ptr, len);
}
u16char* tsl_utf8_utf16(char* str, int32_t* len)
{
print(__FUNCTION__);
debug(str);
debug(strlen(str));
auto arr = Trinity::String::Utf8ToUtf16(str, strlen(str));
debug(arr.Length());
*len = (arr.Length() - 1) * sizeof(u16char); // exclude trailing 0
debug(*len);
return arr.detach_data();
}
char* tsl_utf16_utf8(const u16char* str, int32_t* len)
{
auto s = Trinity::String::FromWcharArray(str, -1);
*len = s.Length();
return _strdup(s.c_str());
}
void* tsl_resize(CellAccessor* accessor, void* where, int32_t delta)
{
print(__FUNCTION__);
char* cellPtr;
auto offset = (int64_t)where - accessor->cellPtr;
debug(offset);
debug(delta);
debug((int64_t)where);
if (accessor->malloced)
{
// TODO reservation
if (delta > 0)
{
cellPtr = (char*)realloc((void*)accessor->cellPtr, accessor->size + delta);
if (cellPtr == nullptr) throw;
memmove(
cellPtr + offset + delta,
cellPtr + offset,
(uint64_t)(accessor->size - offset));
}
else if (delta < 0)
{
cellPtr = (char*)accessor->cellPtr;
memmove(
cellPtr + offset,
cellPtr + offset - delta,
(uint64_t)(accessor->size - offset + delta));
cellPtr = (char*)realloc((void*)accessor->cellPtr, accessor->size + delta);
if (cellPtr == nullptr) throw;
}
else
{
cellPtr = (char*)accessor->cellPtr;
}
}
else { ::CResizeCell(accessor->cellId, accessor->entryIndex, offset, delta, cellPtr); }
accessor->cellPtr = reinterpret_cast<int64_t>(cellPtr);
accessor->size += delta;
auto ret = cellPtr + offset;
debug((int64_t)ret);
return ret;
}
int32_t tsl_newaccessor(CellAccessor* paccessor, int32_t len, uint16_t type, uint8_t is_cell)
{
auto buf = calloc(1, len);
if (buf == nullptr) return TrinityErrorCode::E_NOMEM;
paccessor->cellPtr = (int64_t)buf;
paccessor->size = len;
paccessor->malloced = 1;
paccessor->type = type;
paccessor->isCell = is_cell;
return TrinityErrorCode::E_SUCCESS;
}
uint64_t tsl_hash(void* ptr, int32_t len)
{
uint64_t ret;
Trinity::Hash::hash_64(&ret, (uint8_t*)ptr, len);
return ret;
}

Просмотреть файл

@ -1,37 +0,0 @@
#pragma once
#include <iostream>
#include <asmjit.h>
#include "TypeSystem.h"
#include "CellAccessor.h"
#include "Trinity.h"
#include <io>
using namespace asmjit;
#define print(x)
// std::wcout << x << std::endl
#define debug(x)
// std::wcout << #x << " = " << (x) << std::endl
class ErrHandler : public ErrorHandler
{
public:
bool handleError(asmjit::Error err, const char* message, CodeEmitter* origin)
{
debug(message);
return false;
}
};
asmjit::TypeId::Id GetTypeId(IN TypeDescriptor* const type);
u16char* tsl_getstring(int32_t* trinity_string_ptr);
u16char* tsl_getu8string(int32_t* trinity_string_ptr);
u16char* tsl_utf8_utf16(char* str, int32_t* len);
char* tsl_utf16_utf8(const u16char* str, int32_t* len);
void* tsl_dup(char* ptr, int32_t size);
void* tsl_dup_dynamic(int32_t* ptr);
uint64_t tsl_hash(void* ptr, int32_t len);
int32_t tsl_newaccessor(CellAccessor* ptr, int32_t len, uint16_t type, uint8_t is_cell);
void* tsl_resize(CellAccessor* accessor, void* where, int32_t delta);

Просмотреть файл

@ -1,79 +0,0 @@
#include "x86.h"
#include "Common.h"
#include "FuncCtx.h"
#include "VerbSequence.h"
#include "VerbMixins.h"
#include "Trinity.h"
typedef void(*JitProc)(X86Compiler&, FuncCtx&, VerbSequence&);
static JitRuntime s_runtime;
DLL_EXPORT void* CompileFunctionToNative(FunctionDescriptor* fdesc)
{
print(L"In CompileFunctionToNative");
asmjit::Error eresult;
CodeHolder code;
CodeInfo ci = s_runtime.getCodeInfo();
CallConv::Id ccId = CallConv::kIdHost;
void* ret = nullptr;
FuncSignature fsig;
TypeId::Id retId;
bool wresize;
uint8_t* pargs;
int32_t nargs;
CCFunc* func;
ErrHandler handler;
StringLogger logger;
if (eresult = code.init(ci)) return nullptr;
code.setErrorHandler(&handler);
code.setLogger(&logger);
X86Compiler cc(&code);
print(L"Code initialized");
retId = Mixin::GetReturnId(fdesc);
debug(retId);
Mixin::GetArgument(fdesc, pargs, nargs);
debug(nargs);
wresize = Mixin::WouldResize(fdesc);
print(L"Initializing func");
fsig.init(ccId, retId, pargs, nargs);
func = cc.addFunc(fsig);
print(L"Jit dispatching");
// 1st arg is always CellAccessor* cellAccessor
FuncCtx fctx(cc, retId, wresize);
VerbSequence seq(fdesc);
Mixin::DoDispatch(cc, fctx, seq);
print(L"Jit dispatched");
if (eresult = fctx.finalize()) {
debug(eresult);
return nullptr;
}
print(L"Finalized");
if (eresult = s_runtime.add(&ret, &code)) {
debug(eresult);
return nullptr;
}
print(L"added");
debug(logger.getString());
cc.resetLastError();
fdesc->~FunctionDescriptor();
free(fdesc);
return ret;
}

Просмотреть файл

@ -1,77 +0,0 @@
#include "FuncCtx.h"
#include "Common.h"
FuncCtx::FuncCtx(X86Compiler& compiler, TypeId::Id ret, bool w) : cc(compiler), argIndex(0), returned(false), retId(ret), wresize(w)
{
cellAccessor = cc.newGpq("cellAccessor");
cellPtr = cc.newGpq("cellPtr");
addArg(cellAccessor);
// prolog: we always load the cell pointer into a gp register "cellPtr"
// void* cellPtr = cellAccessor->cellPtr;
cc.mov(cellPtr, x86::qword_ptr(cellAccessor));
}
void FuncCtx::pushResizeChain()
{
if (!wresize)return;
auto p = cc.newGpq("resize_point");
cc.mov(p, cellPtr);
cc.sub(p, x86::qword_ptr(cellAccessor));
resizeChain.push_back(p);
}
void FuncCtx::addArg(const Reg& reg)
{
cc.setArg(argIndex++, reg);
}
void FuncCtx::ret()
{
cc.ret();
returned = true;
}
void FuncCtx::ret(const X86Gp& gp)
{
cc.ret(gp);
returned = true;
}
void FuncCtx::ret(const X86Xmm& xmm)
{
cc.ret(xmm);
returned = true;
}
asmjit::Error FuncCtx::finalize()
{
if (!returned) //assume ret value in reg cellPtr
{
auto size = asmjit::TypeId::sizeOf(retId);
switch (size)
{
case 0:
ret();
break;
case 1:
ret(cellPtr.r8());
break;
case 2:
ret(cellPtr.r16());
break;
case 4:
ret(cellPtr.r32());
break;
case 8:
ret(cellPtr);
break;
default:
print(__FUNCTION__);
print("unsupported default return size");
debug(size);
throw;
}
}
return cc.finalize();
}

Просмотреть файл

@ -1,27 +0,0 @@
#pragma once
#include "asmjit.h"
#include <vector>
using namespace asmjit;
struct FuncCtx
{
public:
TypeId::Id retId;
bool returned;
int argIndex;
X86Compiler& cc;
X86Gp cellAccessor;
X86Gp cellPtr;
std::vector<X86Gp> resizeChain;
bool wresize;
public:
FuncCtx(X86Compiler& compiler, TypeId::Id, bool);
void pushResizeChain();
void addArg(const Reg& reg);
void ret();
void ret(const X86Gp& gp);
void ret(const X86Xmm& gp);
asmjit::Error finalize();
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,24 +0,0 @@
#include "TypeSystem.h"
void __deepcopy(char* &dst, char* const &src)
{
if (src) { dst = _strdup(src); }
else { dst = nullptr; }
}
TypeDescriptor::~TypeDescriptor()
{
for (int i = 0; i < ElementArity; ++i) { ElementType[i].~TypeDescriptor(); }
for (int i = 0; i < NrMember; ++i) { Members[i].~MemberDescriptor(); }
for (int i = 0; i < NrTSLAttribute; ++i) { TSLAttributes[i].~AttributeDescriptor(); }
if (TypeName) free(TypeName);
if (ElementType) free(ElementType);
if (Members) free(Members);
if (TSLAttributes) free(TSLAttributes);
TypeName = nullptr;
ElementType = nullptr;
Members = nullptr;
TSLAttributes = nullptr;
}

Просмотреть файл

@ -1,193 +0,0 @@
#pragma once
#include "TrinityCommon.h"
#include <cstring>
#include <algorithm>
#include <vector>
#define pdebug // printf("%s, line %d, this=%llx\n", __FUNCTION__, __LINE__, this);
#define pdebug_ // printf("%s, line %d\n", __FUNCTION__, __LINE__);
#pragma pack(push, 1)
template<typename T> void __deepcopy(T* &dst, T* const &src)
{
if (src) { dst = (T*)malloc(sizeof(T)); *dst = *src; }
else { dst = nullptr; }
}
void __deepcopy(char* &dst, char* const &src);
template<typename T, typename S> void __deepcopy_arr(T* &dst, S &dst_size, T* const &src, S const &src_size)
{
if (src && src_size) {
dst_size = src_size;
dst = (T*)malloc(sizeof(T) * src_size);
for (int i = 0; i < src_size; ++i) { dst[i] = src[i]; }
}
else { dst = nullptr; dst_size = 0; }
}
template<typename T> std::vector<T*>* __get_ptrs(T* arr, int len)
{
std::vector<T*>* vec = new std::vector<T*>();
for (T* p = arr; p < arr + len; ++p) { vec->push_back(p); }
return vec;
}
struct AttributeDescriptor
{
char* Key;
char* Value;
AttributeDescriptor() { Key = nullptr; Value = nullptr; }
~AttributeDescriptor()
{
if (Key) free(Key);
if (Value) free(Value);
Key = nullptr;
Value = nullptr;
}
};
struct MemberDescriptor;
struct TypeDescriptor
{
TypeDescriptor() { memset(this, 0, sizeof(TypeDescriptor)); }
TypeDescriptor(TypeDescriptor&& other) {
memcpy(this, &other, sizeof(TypeDescriptor));
memset(&other, 0, sizeof(TypeDescriptor));
}
TypeDescriptor(const TypeDescriptor& other) { *this = other; }
TypeDescriptor& operator = (TypeDescriptor &&other) {
memcpy(this, &other, sizeof(TypeDescriptor));
memset(&other, 0, sizeof(TypeDescriptor));
return *this;
}
TypeDescriptor& operator = (const TypeDescriptor &other) {
__deepcopy(TypeName, other.TypeName);
__deepcopy(QualifiedName, other.QualifiedName);
TypeCode = other.TypeCode;
CellType = other.CellType;
__deepcopy_arr(ElementType, ElementArity, other.ElementType, other.ElementArity);
__deepcopy_arr(Members, NrMember, other.Members, other.NrMember);
__deepcopy_arr(TSLAttributes, NrTSLAttribute, other.TSLAttributes, other.NrTSLAttribute);
return *this;
}
~TypeDescriptor();
char* get_TypeName()
{
return _strdup(TypeName);
}
char* get_QualifiedName()
{
return _strdup(QualifiedName);
}
std::vector<TypeDescriptor*>* get_ElementType()
{
return __get_ptrs(ElementType, ElementArity);
}
std::vector<MemberDescriptor*>* get_Members()
{
return __get_ptrs(Members, NrMember);
}
std::vector<AttributeDescriptor*>* get_TSLAttributes()
{
return __get_ptrs(TSLAttributes, NrTSLAttribute);
}
int16_t get_TypeCode()
{
return TypeCode;
}
uint16_t get_CellType()
{
return CellType;
}
private:
char* TypeName;
char* QualifiedName; // AssemblyQualifiedName
TypeDescriptor* ElementType; // non-null for container types
MemberDescriptor* Members; // null for non-struct
AttributeDescriptor* TSLAttributes; // non-null for cell/field with attributes
int32_t NrMember;
int32_t NrTSLAttribute;
int32_t ElementArity; // 1 for list
int16_t TypeCode;
uint16_t CellType;
};
struct MemberDescriptor
{
MemberDescriptor() { memset(this, 0, sizeof(MemberDescriptor)); }
MemberDescriptor(MemberDescriptor&& other)
{
memcpy(this, &other, sizeof(MemberDescriptor));
memset(&other, 0, sizeof(MemberDescriptor));
}
MemberDescriptor(const MemberDescriptor &other)
{
__deepcopy(Name, other.Name);
Type = other.Type;
Optional = other.Optional;
}
MemberDescriptor& operator = (const MemberDescriptor &other)
{
__deepcopy(Name, other.Name);
Type = other.Type;
Optional = other.Optional;
return *this;
}
MemberDescriptor& operator = (MemberDescriptor &&other)
{
memcpy(this, &other, sizeof(MemberDescriptor));
memset(&other, 0, sizeof(MemberDescriptor));
return *this;
}
char* Name;
TypeDescriptor Type;
uint8_t Optional; //non-zero for optional fields
~MemberDescriptor()
{
if (Name) free(Name);
Name = nullptr;
}
};
// !Keep in sync with TypeSystem.fs
enum TypeCode : int16_t {
TC_NULL
, TC_U8, TC_U16, TC_U32, TC_U64
, TC_I8, TC_I16, TC_I32, TC_I64
, TC_F32, TC_F64
, TC_BOOL
, TC_CHAR, TC_STRING, TC_U8STRING
, TC_LIST
, TC_STRUCT, TC_CELL
};
#pragma pack(pop)

Просмотреть файл

@ -1,14 +0,0 @@
#include "Verb.h"
Verb::~Verb()
{
if (Code == VerbCode::VC_GSGet || Code == VerbCode::VC_GSSet)
{
Data.GenericTypeArgument->~TypeDescriptor();
free(Data.GenericTypeArgument);
}
else if (Code == VerbCode::VC_SGet || Code == VerbCode::VC_SGet)
{
free(Data.MemberName);
}
}

Просмотреть файл

@ -1,85 +0,0 @@
#pragma once
#pragma pack(push, 1)
#include "Common.h"
// !Keep in sync with Verbs.fs
enum VerbCode : int32_t {
/* BasicVerb */
VC_BNew,
VC_BGet,
VC_BSet,
VC_BCmp,
VC_BLe,
VC_BLt,
VC_BGe,
VC_BGt,
VC_BRefEq,
VC_BHash,
VC_BCount, // Nr. elements, e.g. wcstrlen
VC_BSize, // Size in bytes
/* ListVerb */
VC_LInlineGet, // VerbData :: int64_t
VC_LInlineSet, // VerbData :: int64_t
VC_LGet,
VC_LSet,
VC_LContains,
VC_LCount,
VC_LInsertAt,
VC_LRemoveAt,
VC_LAppend,
VC_LConv, // converts TSL list to native list
/* StructVerb */
VC_SGet, // VerbData :: char*
VC_SSet, // VerbData :: char*
/* GenericStructVerb */
VC_GSGet, // VerbData :: TypeDescriptor*
VC_GSSet, // VerbData :: TypeDescriptor*
/* Enumerable */
VC_EAlloc ,
VC_EFree ,
VC_ENext ,
VC_ECurrent ,
// below invalid for native
VC_ComposedVerb
};
union VerbData
{
char* MemberName;
int64_t Index;
TypeDescriptor* GenericTypeArgument;
};
struct Verb
{
VerbCode Code;
VerbData Data;
~Verb();
};
struct FunctionDescriptor
{
TypeDescriptor Type; // embedded
Verb* Verbs;
int32_t NrVerbs;
~FunctionDescriptor()
{
for (auto p = Verbs, pend = Verbs + NrVerbs; p != pend; ++p)
{
p->~Verb();
}
if (Verbs) free(Verbs);
}
};
#pragma pack(pop)

Просмотреть файл

@ -1,87 +0,0 @@
#include "VerbMixins.h"
namespace Mixin
{
#define MIXIN(x) {VerbCode::VC_##x, new x()}
static std::map<VerbCode, VerbMixin*> s_mixins =
{
MIXIN(BNew),
MIXIN(BGet),
MIXIN(BSet),
MIXIN(BCmp),
MIXIN(BLe),
MIXIN(BLt),
MIXIN(BGe),
MIXIN(BGt),
MIXIN(BRefEq),
MIXIN(LGet),
MIXIN(LSet),
MIXIN(LContains),
MIXIN(LCount),
MIXIN(LInsertAt),
MIXIN(LAppend),
MIXIN(LRemoveAt),
MIXIN(SGet),
MIXIN(SSet),
};
VerbMixin* Make(VerbCode code)
{
auto i = s_mixins.find(code);
if (i == s_mixins.cend())
{
print("Mixin::Make: unexpected verb code");
debug(code);
throw;
}
return i->second;
}
static VerbMixin* Make(Verb* v)
{
return Make(v->Code);
}
TypeId::Id GetReturnId(FunctionDescriptor* fdesc)
{
TypeId::Id ret = TypeId::Id::kVoid;
VerbSequence seq(fdesc);
while (seq.Next()) { if (Make(seq.pcurrent)->GetRetId(seq, ret)) break; }
return ret;
}
void GetArgument(IN FunctionDescriptor* fdesc, OUT uint8_t* &pargs, OUT int32_t& nargs)
{
/* 1st argument is always CellAccessor* */
std::vector<uint8_t> vec{ TypeId::kUIntPtr };
VerbSequence seq(fdesc);
while (seq.Next()) { if (Make(seq.pcurrent)->GetArgs(seq, vec)) break; }
nargs = vec.size();
pargs = (uint8_t*)malloc(nargs * sizeof(uint8_t));
std::copy(vec.begin(), vec.end(), pargs);
}
bool WouldResize(FunctionDescriptor* fdesc)
{
VerbSequence seq(fdesc);
while (seq.Next()) { if (Make(seq.pcurrent)->WouldResize(seq)) return true; }
return false;
}
void DoDispatch(X86Compiler &cc, FuncCtx& ctx, VerbSequence& seq)
{
while (seq.Next() && !ctx.returned) { Make(seq.pcurrent)->Dispatch(cc, ctx, seq); }
}
bool SequenceNext(VerbSequence& seq)
{
if (++seq.pcurrent == seq.pend) return false;
debug(seq.pcurrent->Code);
debug(seq.ptype->get_QualifiedName());
Make(seq.pcurrent)->SequenceNext(seq);
return true;
}
}

Просмотреть файл

@ -1,368 +0,0 @@
#pragma once
#include <map>
#include <functional>
#include "Common.h"
#include "Verb.h"
#include "VerbSequence.h"
#include "FuncCtx.h"
#define CONCRETE_MIXIN_DECLARE(v) \
void Dispatch(asmjit::X86Compiler &cc, FuncCtx& ctx, const VerbSequence& seq) override; \
bool WouldResize(VerbSequence&) override;
#define CONCRETE_MIXIN_DEFINE(v) \
void v::Dispatch(asmjit::X86Compiler &cc, FuncCtx& ctx, const VerbSequence& seq)
namespace Mixin
{
struct VerbMixin
{
virtual bool GetArgs(const VerbSequence& seq, std::vector<uint8_t> &args) { return false; }
virtual bool GetRetId(const VerbSequence& seq, OUT TypeId::Id &retId) { return false; }
virtual void SequenceNext(VerbSequence& seq) {}
virtual void Dispatch(X86Compiler &cc, FuncCtx& ctx, const VerbSequence& seq) = 0;
virtual bool WouldResize(VerbSequence&) { return false; }
};
TypeId::Id GetReturnId(FunctionDescriptor* fdesc);
void GetArgument(IN FunctionDescriptor* fdesc, OUT uint8_t* &pargs, OUT int32_t& nargs);
void DoDispatch(X86Compiler &cc, FuncCtx& ctx, VerbSequence& seq);
bool WouldResize(FunctionDescriptor* fdesc);
bool SequenceNext(VerbSequence& seq);
VerbMixin* Make(VerbCode code);
#pragma region traits
#define HAS(x) \
class HAS_##x \
{ \
typedef struct { char onechar[1]; } good; \
typedef struct { char twochar[2]; } bad; \
template<typename U, U u> struct Check; \
struct Fallback { int x; }; \
\
template <typename U> static bad& test(Check<int Fallback::*, &U::x>*); \
template <typename U> static bad& test(Check<decltype(&VerbMixin::x), &U::x>*); \
template <typename U> static good& test(...); \
\
public: \
template <typename T> static constexpr bool value() \
{ \
return sizeof(test<T>(0)) == sizeof(good); \
} \
};
HAS(GetArgs);
HAS(GetRetId);
HAS(Dispatch);
HAS(SequenceNext);
template <typename K, typename T> static constexpr bool any()
{
return K::template value<T>();
}
template <typename K, typename T1, typename ... TS>
static constexpr typename std::enable_if<(sizeof...(TS) > 0), bool>::type any()
{
return any<K, T1>() || any<K, TS...>();
}
#pragma endregion
#pragma region helper mixins
template <class B1, class ... BRest>
struct M : virtual B1, virtual BRest...
{
private:
template <typename K>
using TSeq = std::conditional<(any<K, B1, BRest...>()), VerbSequence, void*>;
template <typename K, typename ... T>
using CSeq = std::conditional<(any<K, T...>()), VerbSequence, void*>;
template <typename T>
bool _GetArgs(...)
{
return false;
}
template <typename T>
bool _GetArgs(const typename CSeq<HAS_GetArgs, T>::type & seq, std::vector<uint8_t> &args)
{
return T::GetArgs(seq, args);
}
template <typename T1, typename ... TS>
typename std::enable_if< (sizeof...(TS) > 0), bool>::type _GetArgs(const typename CSeq<HAS_GetArgs, T1, TS...>::type & seq, std::vector<uint8_t> &args)
{
if (_GetArgs<T1>(seq, args)) return true;
return _GetArgs<TS...>(seq, args);
}
template <typename T>
bool _GetRetId(...)
{
return false;
}
template <typename T>
bool _GetRetId(const typename CSeq<HAS_GetRetId, T>::type & seq, TypeId::Id &id)
{
return T::GetRetId(seq, id);
}
template <typename T1, typename ... TS>
typename std::enable_if< (sizeof...(TS) > 0), bool>::type _GetRetId(const typename CSeq<HAS_GetRetId, T1, TS...>::type & seq, TypeId::Id &id)
{
if (_GetRetId<T1>(seq, id)) return true;
else return _GetRetId<TS...>(seq, id);
}
template <typename T>
void _SequenceNext(VerbSequence& seq)
{
if (HAS_SequenceNext::value<T>()) T::SequenceNext(seq);
}
template <typename T1, typename ... TS>
typename std::enable_if< (sizeof...(TS) > 0), void>::type _SequenceNext(VerbSequence& seq)
{
_SequenceNext<T1>(seq);
_SequenceNext<TS...>(seq);
}
//template <typename T>
//typename void _SequenceNext(...)
//{
//}
//template <typename T>
//typename void _SequenceNext(typename CSeq<HAS_SequenceNext, T>::type & seq)
//{
// T::SequenceNext(seq);
//}
//template <typename T1, typename ... TS>
//typename std::enable_if< (sizeof...(TS) > 0), void>::type _SequenceNext(typename CSeq<HAS_SequenceNext, T1, TS...>::type& seq)
//{
// _SequenceNext<T1>(seq);
// _SequenceNext<TS...>(seq);
//}
public:
//template <typename Q1 = B1, typename QRest = BRest>
//typename std::enable_if<any<HAS_GetArgs, Q1, QRest...>(), bool >::type GetArgs(const VerbSequence& seq, std::vector<uint8_t> &args)
typename std::conditional<any<HAS_GetArgs, B1, BRest...>(), bool, void* >::type
GetArgs(const typename TSeq<HAS_GetArgs>::type &seq, std::vector<uint8_t> &args)
{
print(__FUNCTION__);
return _GetArgs<B1, BRest...>(seq, args);
}
//bool GetRetId(const VerbSequence& seq, OUT TypeId::Id &retId)
//typename std::conditional<any<HAS_GetRetId, B1, BRest...>(), bool, void* >::type
//bool GetRetId(typename const TSeq<HAS_GetRetId>::type &seq, TypeId::Id &retId)
template <typename Q1 = B1>
typename std::enable_if<any<HAS_GetRetId, Q1, BRest...>(), bool >::type
GetRetId(const VerbSequence& seq, TypeId::Id &retId)
//typename std::conditional<any<HAS_GetRetId, B1, BRest...>(), bool, void* >::type
// GetRetId(typename const TSeq<HAS_GetRetId>::type &seq, TypeId::Id &retId)
{
print(__FUNCTION__);
return _GetRetId<Q1, BRest...>(seq, retId);
//return _GetRetId<B1, BRest...>(seq, retId);
}
//virtual void Dispatch(X86Compiler &cc, FuncCtx& ctx, const VerbSequence& seq) {}
//template <typename Q1 = B1, typename QRest = BRest>
//typename std::enable_if<any<HAS_SequenceNext, Q1, QRest...>(), void >::type SequenceNext(VerbSequence& seq)
typename std::conditional<any<HAS_SequenceNext, B1, BRest...>(), void, void* >::type
SequenceNext(typename TSeq<HAS_SequenceNext>::type &seq)
//void SequenceNext(VerbSequence& seq)
{
print(__FUNCTION__);
_SequenceNext<B1, BRest...>(seq);
}
};
//template <typename B> struct M<B> : virtual B {};
struct IndexInlined : virtual VerbMixin
{
void SequenceNext(VerbSequence& seq) override
{
seq.iidx = seq.pcurrent->Data.Index;
}
// cancel the index parameter so as to inline
bool GetArgs(const VerbSequence& seq, std::vector<uint8_t> &args) override
{
args.pop_back(); return false;
}
};
template<TypeId::Id tid, bool intercept = true>
struct Ret : virtual VerbMixin
{
bool GetRetId(const VerbSequence& seq, OUT TypeId::Id &retId) override
{ retId = tid; return intercept; }
};
struct NoRet : Ret<TypeId::kVoid> {};
template <bool intercept = true>
struct RetT : virtual VerbMixin
{
bool GetRetId(const VerbSequence& seq, OUT TypeId::Id &retId) override
{ retId = GetTypeId(seq.ptype); return intercept; }
};
template <bool intercept = true>
struct RetRef : Ret<TypeId::kUIntPtr, intercept> {};
template <bool intercept = true>
struct NoArgs : virtual VerbMixin
{
// simply interrupt inference
bool GetArgs(const VerbSequence& seq, std::vector<uint8_t> &args) override
{ return intercept; }
};
template <bool intercept = true>
struct ArgT : virtual VerbMixin
{
bool GetArgs(const VerbSequence& seq, std::vector<uint8_t> &args) override
{ args.push_back(seq.CurrentTypeId()); return intercept; }
};
template <TypeId::Id tid, bool intercept = true>
struct Arg : virtual VerbMixin
{
bool GetArgs(const VerbSequence& seq, std::vector<uint8_t> &args) override
{ args.push_back(tid); return intercept; }
};
#pragma endregion
struct Basic : virtual VerbMixin {};
struct BNew : M<Basic, NoArgs<true>>, Ret<TypeId::kI32> { CONCRETE_MIXIN_DECLARE(BNew); };
struct BGet : M<Basic, NoArgs<true>>, RetT<true> { CONCRETE_MIXIN_DECLARE(BGet); };
struct BSet : M<Basic, ArgT<true>>, NoRet { CONCRETE_MIXIN_DECLARE(BSet); };
struct BCmp : M<Basic, ArgT<true>, Ret<TypeId::kI32>> { CONCRETE_MIXIN_DECLARE(BCmp); };
struct BLt : M<Basic, ArgT<true>, Ret<TypeId::kU32>> { CONCRETE_MIXIN_DECLARE(BLt); };
struct BLe : M<Basic, ArgT<true>, Ret<TypeId::kU32>> { CONCRETE_MIXIN_DECLARE(BLe); };
struct BGt : M<Basic, ArgT<true>, Ret<TypeId::kU32>> { CONCRETE_MIXIN_DECLARE(BGt); };
struct BGe : M<Basic, ArgT<true>, Ret<TypeId::kU32>> { CONCRETE_MIXIN_DECLARE(BGe); };
struct BRefEq : M<Basic, ArgT<true>, Ret<TypeId::kU32>> { CONCRETE_MIXIN_DECLARE(BRefEq); };
struct BHash : M<Basic, NoArgs<true>, Ret<TypeId::kU64>> { CONCRETE_MIXIN_DECLARE(BHash); };
struct BCount : M<Basic, NoArgs<true>, Ret<TypeId::kI32>> { CONCRETE_MIXIN_DECLARE(BCount); };
struct BSize : M<Basic, NoArgs<true>, Ret<TypeId::kI32>> { CONCRETE_MIXIN_DECLARE(BSize); };
struct List : Arg<TypeId::kI32, false>
{
void SequenceNext(VerbSequence& seq)
{
auto vec = seq.ptype->get_ElementType();
seq.parent = seq.ptype;
seq.ptype = vec->at(0);
delete vec;
}
};
struct LGet : M<List, NoArgs<false>>, RetRef<false> { CONCRETE_MIXIN_DECLARE(LGet); };
struct LSet : M<List, ArgT<true>>, NoRet { CONCRETE_MIXIN_DECLARE(LSet); };
struct LContains : M<List, ArgT<true>, Ret<TypeId::kU32>> { CONCRETE_MIXIN_DECLARE(LContains); };
struct LCount : M<List, NoArgs<true>, Ret<TypeId::kI32>> { CONCRETE_MIXIN_DECLARE(LCount); };
struct LInsertAt : M<List, ArgT<true>, Ret<TypeId::kU32>> { CONCRETE_MIXIN_DECLARE(LInsertAt); };
struct LRemoveAt : M<List, NoArgs<true>, Ret<TypeId::kU32>> { CONCRETE_MIXIN_DECLARE(LRemoveAt); };
struct LAppend : M<ArgT<true>, /*Intercepts Arg chain*/ List, Ret<TypeId::kU32>> { CONCRETE_MIXIN_DECLARE(LAppend); };
struct LConv : M<NoArgs<true>, /*Intercepts Arg chain */ List, Ret<TypeId::kUIntPtr>> { CONCRETE_MIXIN_DECLARE(LConv); };
struct InlinedList : M<List, IndexInlined> {};
struct LInlineGet : M<InlinedList, NoArgs<false>, RetRef<false>> { CONCRETE_MIXIN_DECLARE(InlinedLGet); };
struct LInlineSet : M<InlinedList, ArgT<true>, NoRet> { CONCRETE_MIXIN_DECLARE(InlinedLSet); };
struct Struct : virtual VerbMixin
{
void SequenceNext(VerbSequence& seq)
{
auto members = seq.ptype->get_Members();
auto i = std::find_if(members->begin(), members->end(), [=](auto m) { return !strcmp(m->Name, seq.pcurrent->Data.MemberName); });
seq.pmember = *i;
seq.imember = i - members->begin();
delete members;
seq.parent = seq.ptype;
seq.ptype = &seq.pmember->Type;
}
};
struct SGet : M<Struct, NoArgs<false>, RetRef<false>> { CONCRETE_MIXIN_DECLARE(SGet); };
struct SSet : M<Struct, ArgT<true>, NoRet> { CONCRETE_MIXIN_DECLARE(SSet); };
struct GenericStruct : Arg<TypeId::kUIntPtr, false>
{
void SequenceNext(VerbSequence& seq)
{
seq.ptype = seq.pcurrent->Data.GenericTypeArgument;
}
};
struct GSGet : M<GenericStruct, NoArgs<false>, RetRef<false>> { CONCRETE_MIXIN_DECLARE(GSGet); };
struct GSSet : M<GenericStruct, ArgT<true>, NoRet> { CONCRETE_MIXIN_DECLARE(GSSet); };
// =========================== static tests ==================================
struct BBB : Basic
{
void Dispatch(X86Compiler& cc, FuncCtx& ctx, const VerbSequence& seq)
{
BBB b1;
}
};
struct RRR : RetT<true>
{
void Dispatch(X86Compiler& cc, FuncCtx& ctx, const VerbSequence& seq)
{
RRR r1;
static_assert(!HAS_GetArgs::value<RRR>(), "RRR should not have GetArgs");
}
};
struct ILIL : M<List, IndexInlined>
{
void Dispatch(X86Compiler& cc, FuncCtx& ctx, const VerbSequence& seq)
{
ILIL il;
static_assert(HAS_SequenceNext::value<ILIL>(), "ILIL should have SequenceNext");
static_assert(HAS_GetArgs::value<ILIL>(), "ILIL should have GetArgs");
}
};
struct MMM : M<Basic, NoArgs<true>>
{
void Dispatch(X86Compiler& cc, FuncCtx& ctx, const VerbSequence& seq)
{
MMM m1;
static_assert(HAS_GetArgs::value<List>(), "List should have GetArgs");
//static_assert(!HAS_GetRetId::value<List>(), "List should not have GetRetId");
static_assert(!HAS_GetArgs::value<Basic>(), "Basic should not have GetArgs");
static_assert(HAS_GetArgs::value<NoArgs>(), "NoArgs should have GetArgs");
static_assert(any<HAS_GetArgs, Basic, NoArgs>(), "should pass any<Has_GetArgs, Basic, NoArgs>");
static_assert(!HAS_GetArgs::value<Ret<TypeId::kVoid>>(), "Ret<> should not have GetArgs");
static_assert(!HAS_GetArgs::value<RetT<>>(), "RetT<> should not have GetArgs");
static_assert(!any<HAS_GetArgs, Ret<TypeId::kVoid>, RetT<>>(), "should not pass any<HAS_GetArgs, Ret<TypeId::kVoid>, RetT<>>");
static_assert(!HAS_GetRetId::value<Basic>(), "Basic should have GetArgs");
static_assert(!HAS_GetRetId::value<NoArgs>(), "NoArgs should have GetArgs");
static_assert(!any<HAS_GetRetId, Basic, NoArgs>(), "should not pass any<Has_GetRetId, Basic, NoArgs>");
static_assert(HAS_GetRetId::value<Ret<TypeId::kVoid>>(), "Ret<> should have GetRetId");
static_assert(HAS_GetRetId::value<RetT<>>(), "RetT<> should have GetRetId");
static_assert(any<HAS_GetRetId, Ret<TypeId::kVoid>, RetT<>>(), "should pass any<HAS_GetRetId, Ret<TypeId::kVoid>, RetT<>>");
static_assert(std::is_same<std::conditional<any<HAS_GetRetId, Basic, NoArgs>(), bool, void* >::type, void*>::value, "conditional type branch");
//static_assert(std::is_same<std::conditional<any<HAS_GetRetId, MMM>(), bool, void* >::type, void*>::value, "conditional type branch");
static_assert(HAS_GetArgs::value<MMM>(), "MMM should have GetArgs");
//static_assert(!HAS_GetRetId::value<MMM>(), "MMM should not have GetRetId");
}
};
}

Просмотреть файл

@ -1,25 +0,0 @@
#include "VerbSequence.h"
#include "VerbMixins.h"
#include "Common.h"
VerbSequence::VerbSequence(FunctionDescriptor* f)
{
ptype = &f->Type;
pstart = f->Verbs;
pend = pstart + f->NrVerbs;
pcurrent = pstart - 1;
pmember = nullptr;
imember = -1;
parent = nullptr;
iidx = -1;
debug(f->NrVerbs);
}
// for all setters, lcontains, lcount and bget, we allow no further sub-verbs.
bool VerbSequence::Next()
{
return Mixin::SequenceNext(*this);
}

Просмотреть файл

@ -1,22 +0,0 @@
#pragma once
#include "TypeSystem.h"
#include "Verb.h"
struct VerbSequence
{
TypeDescriptor* parent;
TypeDescriptor* ptype;
Verb* pstart;
Verb* pend;
Verb* pcurrent;
MemberDescriptor* pmember;
int32_t imember;
int64_t iidx; //inline integer index
VerbSequence(FunctionDescriptor* f);
bool Next();
TypeId::Id CurrentTypeId() const { return GetTypeId(ptype); }
TypeCode CurrentTypeCode() const { return (TypeCode)ptype->get_TypeCode(); }
};

Просмотреть файл

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>

Просмотреть файл

@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<RootNamespace>GraphEngine.Jit.Playground</RootNamespace>
<AssemblyName>GraphEngine.Jit.Playground</AssemblyName>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GraphEngine.Core" Version="2.0.9328" />
<ProjectReference Include="..\GraphEngine.Jit.TSL\GraphEngine.Jit.TSL.csproj" />
<ProjectReference Include="..\GraphEngine.Jit.UnitTest\GraphEngine.Jit.UnitTest.fsproj" />
<ProjectReference Include="..\GraphEngine.Jit\GraphEngine.Jit.fsproj" />
<TslCodegen Include="**/*.tsl" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Trinity;
using static GraphEngine.Jit.Verbs;
using static GraphEngine.Jit.JitCompiler;
using static GraphEngine.Jit.TypeSystem;
using static GraphEngine.Jit.JitNativeInterop;
using GraphEngine.Jit.TSL;
using static GraphEngine.Jit.Basic;
namespace GraphEngine.Jit.Playground
{
delegate void Setter(NativeCellAccessor p0, int p1);
delegate int Getter(NativeCellAccessor p0);
unsafe class Program
{
static void Main(string[] args)
{
//Console.ReadLine();
IntegerBGetBSet();
FloatBGetBSet();
StringBGetBSet();
IntegerSGetSet();
StringSGetSet();
IntegerSLGetSet();
StringSLGetSet();
IntegerSLCount();
IntegerCompare();
IntegerSLOps();
FloatSLOps();
StringSLOps();
//byte[] buf = new byte[16];
//int val = int.Parse(Console.ReadLine());
//fixed(byte* p = buf)
//{
// *(long*)p += val;
//}
}
}
}

Просмотреть файл

@ -1,12 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GraphEngine.Core" Version="2.0.9328" />
<TslCodegen Include="**/*.tsl" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,33 +0,0 @@
cell C1
{
int F1;
string F2;
}
cell S1
{
int f1;
string f2;
int f3;
}
cell S2
{
List<int64> f1;
double f2;
int f3;
}
cell S3
{
int f1;
List<string> f2;
int f3;
}
cell S4
{
string f1;
List<float> f2;
int f3;
}

Просмотреть файл

@ -1,713 +0,0 @@
module GraphEngine.Jit.Basic
#nowarn "9"
open Xunit
open Verbs
open TypeSystem
open Utils
open Trinity.Storage
open System.Collections.Generic
open System
open JitCompiler
open Trinity.Core.Lib
open Microsoft.FSharp.NativeInterop
open GraphEngine.Jit
open GraphEngine.Jit.Helper
open GraphEngine.Jit.TSL
open Trinity
[<Fact>]
let ``Verb allocation`` () =
Verb.BGet
[<Theory>]
[<InlineData("U16")>]
[<InlineData("I32")>]
[<InlineData("F64")>]
let ``TypeDescriptor allocation`` (tcode: string) =
{ TypeDescriptor.ElementType = []
TypeName = "Type"
QualifiedName = "QType"
Members = []
TSLAttributes = []
TypeCode = ParseCase tcode }
[<Theory>]
[<InlineData(typeof<int32>, 4, "I32")>]
[<InlineData(typeof<string>, 0, "STRING")>]
[<InlineData(typeof<System.DateTime>, 0, "S")>]
[<InlineData(typeof<System.Collections.Generic.List<int>>, 0, "L")>]
let ``TypeDescriptor allocation from Type`` (t: System.Type) (w: int32) (tt: string) =
let desc = MakeFromType t
if w > 0 then Assert.Equal(w, (TryGetTypeWidth desc).Value)
match t with
| PrimitiveType tcode -> Assert.Equal(tt, ToStringCase tcode)
| ListType _ -> Assert.Equal(tt, "L")
| StructType _ -> Assert.Equal(tt, "S")
desc
let attrs_empty() =
{ new IAttributeCollection with
member this.Attributes: System.Collections.Generic.IReadOnlyDictionary<string,string> =
new Dictionary<string, string>() :> IReadOnlyDictionary<string, string>
member this.GetAttributeValue(attributeKey: string): string =
failwith "???" }
let celldesc (name: string, fields: seq<IFieldDescriptor>, ct) =
{ new ICellDescriptor with
member this.Attributes: System.Collections.Generic.IReadOnlyDictionary<string,string> =
attrs_empty().Attributes
member this.CellType: uint16 =
ct
member this.GetAttributeValue(attributeKey: string): string =
attrs_empty().GetAttributeValue attributeKey
member this.GetFieldAttributes(fieldName: string): IAttributeCollection =
attrs_empty()
member this.GetFieldDescriptors(): System.Collections.Generic.IEnumerable<IFieldDescriptor> =
fields
member this.GetFieldNames(): System.Collections.Generic.IEnumerable<string> =
raise (System.NotImplementedException())
member this.IsList(): bool =
false
member this.IsOfType(): bool =
false
member this.Type: System.Type =
this.GetType()
member this.TypeName: string =
name }
let ICellDescriptorGen() =
let _seq: obj array seq = seq {
yield [|"C1"; new List<IFieldDescriptor>(); 0us|]
yield! (Global.StorageSchema.CellDescriptors |> Seq.map<ICellDescriptor, obj array>
(fun x -> [| x.TypeName; x.GetFieldDescriptors(); x.CellType |]))
}
Array.ofSeq _seq
let TypeDescriptorCollection() : obj array array =
[|
[| ``TypeDescriptor allocation`` "U32" |]
[| ``TypeDescriptor allocation`` "I16" |]
[| ``TypeDescriptor allocation`` "U8" |]
|]
[<Theory>]
[<MemberData("ICellDescriptorGen")>]
let ``TypeDescriptor allocation from ICellDescriptor`` (a,b,c) = (a,b,c) |> celldesc |> Make
[<Theory>]
[<MemberData("ICellDescriptorGen")>]
let ``NativeTypeDescriptor allocation from ICellDescriptor`` (a,b,c) = (a,b,c) |> celldesc |> Make |> JitNativeInterop.TypeDescriptorToNative
[<Theory>]
[<MemberData("TypeDescriptorCollection")>]
let ``FunctionDescriptor allocation``(tdesc: TypeDescriptor) =
{ DeclaringType = tdesc
Verb = BGet }
open JitNativeInterop
open System.Runtime.InteropServices
open Trinity.Diagnostics
open System.Runtime.InteropServices.ComTypes
let _AllocAccessor allocsize =
let p = Memory.malloc (uint64 allocsize) |> IntPtr
{
CellPtr = p
CellId = 0L
Size = allocsize
EntryIndex = 0
Type = 0us
IsMalloc = 1uy
IsCell = 0uy
}
let _AllocAccessorWithHeader allocsize =
let p = Memory.malloc (uint64 (allocsize + 4)) |> IntPtr
NativePtr.write (NativePtr.ofNativeInt<int> p) allocsize
{
CellPtr = p
CellId = 0L
Size = allocsize + 4
EntryIndex = 0
Type = 0us
IsMalloc = 1uy
IsCell = 0uy
}
let _Compile (tdesc: TypeDescriptor) (vs: Verb list) =
let fs = vs |> List.map (fun v -> {DeclaringType = tdesc; Verb = v} |> CompileFunction )
for f in fs do
Assert.NotEqual(IntPtr.Zero, f.CallSite)
fs
let _AllocAccessorWithBNew (tdesc: TypeDescriptor) =
let [bnew] = _Compile tdesc [BNew]
let mutable accessor: NativeCellAccessor = {
CellPtr = IntPtr.Zero
CellId = 0L
Type = 0us
EntryIndex = -1
Size = 0
IsMalloc = 0uy
IsCell = 1uy
}
let paccessor = &&accessor |> NativePtr.toNativeInt
let ret = CallHelper.CallByVal<int32>(bnew.CallSite, paccessor)
if ret <> 0 then
failwith "nomem"
accessor
let _BTest (getaccessor) (fn) =
let mutable accessor = getaccessor()
let paccessor = &&accessor |> NativePtr.toNativeInt
try
fn accessor paccessor
finally
Memory.free(accessor.CellPtr.ToPointer())
let _Set (value: 'a) (site: IntPtr) (acc: IntPtr) = CallHelper.CallByVal(site, acc, value)
// !Assume accessor.CellPtr is malloc'ed
let _BGetSet(tdesc: TypeDescriptor) (getaccessor) (set) (assert1) (assert2) =
let [nfget; nfset] = _Compile tdesc [BGet; BSet]
_BTest getaccessor (fun accessor paccessor ->
set nfset.CallSite paccessor // setter invoke
assert1 accessor.CellPtr // manual inspect
assert2 nfget.CallSite paccessor)// getter inspect
let _AtomAssignTest (value: 'a) fn =
fn (_Set value)
(fun p -> Assert.Equal<'a>(value, NativePtr.read <| NativePtr.ofNativeInt<'a> p))
(fun site acc -> Assert.Equal<'a>(value, CallHelper.CallByVal<'a>(site, acc)))
let _AtomBGetSet (tdesc: TypeDescriptor) (value: 'a) =
_AtomAssignTest value <| _BGetSet tdesc (fun () -> _AllocAccessor sizeof<'a>)
_AtomAssignTest value <| _BGetSet tdesc (fun () -> _AllocAccessorWithBNew tdesc)
// string setter expect "real" string
// string getter return "real" string
// but the accessor should contain a "tsl string"
let _StrTest (value: string) (strlen: int) (prawstr: nativeint) (ptslstr: nativeint) fn =
fn
(fun () -> _AllocAccessorWithHeader strlen )
(fun site acc -> CallHelper.CallByPtr(site, acc, prawstr))
(fun (p:nativeint) -> Assert.Equal(0, Memory.memcmp(p.ToPointer(), ptslstr.ToPointer(), uint64 (strlen + 4))))
(fun site acc -> Assert.Equal(value, CallHelper.CallByVal<string>(site, acc)))
let _StringBGetSet (tdesc: TypeDescriptor) (value: string) =
let mutable _val = value
use _pu16str = fixed _val
let lu16str = value.Length * 2
let pu16str = AddTslHead (NativePtr.toNativeInt _pu16str) lu16str
try
_StrTest value lu16str (NativePtr.toNativeInt _pu16str) pu16str <| _BGetSet tdesc
finally
Memory.free(pu16str.ToPointer())
let _U8StrTest (value: string) (strlen: int) (prawstr: nativeint) (ptslstr: nativeint) fn =
let mutable _val = value
use _pu16str = fixed _val
fn
(fun () -> _AllocAccessorWithHeader strlen )
(fun site acc -> CallHelper.CallByPtr(site, acc, (NativePtr.toNativeInt _pu16str)))
(fun (p:nativeint) -> Assert.Equal(0, Memory.memcmp(p.ToPointer(), ptslstr.ToPointer(), uint64 (strlen + 4))))
(fun site acc -> Assert.Equal(value, CallHelper.CallByVal<string>(site, acc)))
let _U8StringBGetSet (tdesc: TypeDescriptor) (value: string) =
let _pu8str = ToUtf8 value
let lu8str = strlen _pu8str
let pu8str = AddTslHead _pu8str lu8str
try
_U8StrTest value lu8str _pu8str pu8str <| _BGetSet tdesc
finally
Memory.free(_pu8str.ToPointer())
Memory.free(pu8str.ToPointer())
[<Fact>]
let IntegerBGetBSet () =
_AtomBGetSet (``TypeDescriptor allocation`` "U8") 255uy
_AtomBGetSet (``TypeDescriptor allocation`` "I8") -71y
_AtomBGetSet (``TypeDescriptor allocation`` "U16") 46131us
_AtomBGetSet (``TypeDescriptor allocation`` "I16") -516s
_AtomBGetSet (``TypeDescriptor allocation`` "U32") 123u
_AtomBGetSet (``TypeDescriptor allocation`` "I32") 5108346
_AtomBGetSet (``TypeDescriptor allocation`` "U64") 4968173491UL
_AtomBGetSet (``TypeDescriptor allocation`` "I64") 6924560298457134L
[<Fact>]
let FloatBGetBSet () =
_AtomBGetSet (``TypeDescriptor allocation`` "F32") 3.14f
_AtomBGetSet (``TypeDescriptor allocation`` "F64") 12345678.90123
[<Fact>]
let StringBGetBSet () =
_StringBGetSet (``TypeDescriptor allocation`` "STRING") "hello"
_StringBGetSet (``TypeDescriptor allocation`` "STRING") "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
_StringBGetSet (``TypeDescriptor allocation`` "STRING") "UTF8"
_U8StringBGetSet (``TypeDescriptor allocation`` "U8STRING") "hello"
_U8StringBGetSet (``TypeDescriptor allocation`` "U8STRING") "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"
_U8StringBGetSet (``TypeDescriptor allocation`` "U8STRING") "UTF8"
let Dump size p =
printfn "========="
printfn "Size: %X (%A)" size size
printfn "Content:"
printf " 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F"
for i in 0..(size-1) do
if i % 16 = 0 then
printfn ""
printf "%02X " i
if i % 8 = 0 then printf " "
if i % 4 = 0 then printf " "
printf " %02X" (NativePtr.read (NativePtr.add p i))
printfn ""
printfn "Content End"
printfn "========="
// !All cell-tests go through this routine instead of _BGetSet
let _CellGetSet (cell: ICell) action =
let cdesc = cell :> ICellDescriptor
let tdesc = TypeSystem.Make cdesc
let mutable accessor: NativeCellAccessor = {
CellPtr = IntPtr.Zero
CellId = 0L
Type = 0us
EntryIndex = -1
Size = 0
IsMalloc = 0uy
IsCell = 1uy
}
let mutable p: nativeptr<byte> = NativePtr.ofNativeInt (nativeint 0)
Global.LocalStorage.SaveGenericCell(cell) |> ignore
let mutable arr = [| 0uy |]
Global.LocalStorage.LoadCell(0L, &arr) |> ignore
Global.LocalStorage.GetLockedCellInfo(0L, &accessor.Size, &accessor.Type, &p, &accessor.EntryIndex) |> ignore
try
Dump accessor.Size p
accessor.CellPtr <- NativePtr.toNativeInt p
let paccessor = &&accessor |> NativePtr.toNativeInt
action tdesc accessor paccessor
finally
Global.LocalStorage.ReleaseCellLock(0L, accessor.EntryIndex)
let _SGetSet (cell: ICell) field (set) (assert1) (assert2) =
_CellGetSet cell (fun (tdesc: TypeDescriptor) (accessor: NativeCellAccessor) (paccessor: nativeint) ->
let [nfbget; nfget; nfset] = _Compile tdesc [ ComposedVerb(SGet field, BGet)
SGet field
SSet field ]
printfn "paccessor = %X" paccessor
printfn "pcell = %X" accessor.CellPtr
printfn "pushed = %X" (CallHelper.GetPushedPtr(nfget.CallSite, paccessor))
printfn "set"
set nfset.CallSite paccessor // setter invoke
printfn "assert1"
let p = CallHelper.GetPushedPtr(nfget.CallSite, paccessor)
assert1 (p) // manual inspect
printfn "assert2"
assert2 nfbget.CallSite paccessor // getter inspect
)
let _IntegerSGetSet (cell: ICell) field (value: 'a) =
_SGetSet cell field
(fun site acc -> CallHelper.CallByVal(site, acc, value) )
(fun p -> Assert.Equal<'a>(value, NativePtr.read <| NativePtr.ofNativeInt<'a> p))
(fun site acc -> Assert.Equal<'a>(value, CallHelper.CallByVal<'a>(site, acc)))
let _StringSGetSet (cell: ICell) field (value: string) =
let mutable _val = value
use _pu16str = fixed _val
let lu16str = value.Length * 2
let pu16str = AddTslHead (NativePtr.toNativeInt _pu16str) lu16str
try
_SGetSet cell field
(fun site acc -> CallHelper.CallByPtr(site, acc, NativePtr.toNativeInt _pu16str))
(fun p -> Assert.Equal(0, Memory.memcmp(p.ToPointer(), pu16str.ToPointer(), uint64 (lu16str + 4))))
(fun site acc -> Assert.Equal(value, CallHelper.CallByVal<string>(site, acc)))
finally
Memory.free(pu16str.ToPointer())
[<Fact>]
let IntegerSGetSet () =
let mutable s1 = S1(0L, 641934, "", 123)
_IntegerSGetSet s1 "f1" 465912345
_IntegerSGetSet s1 "f3" 13451
s1 <- S1(0L, 56256, "yargaaiawrguaw", 56892651)
_IntegerSGetSet s1 "f1" 652634
_IntegerSGetSet s1 "f3" 461371
let mutable s2 = S2(0L, new System.Collections.Generic.List<int64>(seq [1L; 2L; 3L]), 123.456, 0)
_IntegerSGetSet s2 "f3" 451
[<Fact>]
let StringSGetSet () =
let mutable s1 = S1(0L, 641934, "", 123)
//_StringSGetSet s1 "f2" "hello"
//_StringSGetSet s1 "f2" "world"
s1 <- S1(0L, 56256, "yargaaiawrguaw", 56892651)
_StringSGetSet s1 "f2" "hello"
_StringSGetSet s1 "f2" "world"
let _SLGetSet (cell: ICell) field index (set) (assert1) (assert2) =
_CellGetSet cell (fun (tdesc: TypeDescriptor) (accessor: NativeCellAccessor) (paccessor: nativeint) ->
let [nfbget; nfget; nfset] = _Compile tdesc [ ComposedVerb(SGet field, ComposedVerb(LGet, BGet))
ComposedVerb(SGet field, LGet)
ComposedVerb(SGet field, LSet) ]
printfn "paccessor = %X" paccessor
printfn "pcell = %X" accessor.CellPtr
printfn "pushed = %X" (CallHelper.GetPushedPtr(nfget.CallSite, paccessor, index))
printfn "set"
set nfset.CallSite paccessor // setter invoke
printfn "assert1"
assert1 (CallHelper.GetPushedPtr(nfget.CallSite, paccessor, index)) // manual inspect
printfn "assert2"
assert2 nfbget.CallSite paccessor // getter inspect
)
let _IntegerSLGetSet (cell: ICell) field (index: int32) (value: 'a) =
_SLGetSet cell field index
(fun site acc -> CallHelper.CallByVal(site, acc, index, value) )
(fun p -> Assert.Equal<'a>(value, NativePtr.read <| NativePtr.ofNativeInt<'a> p))
(fun site acc -> Assert.Equal<'a>(value, CallHelper.CallByVal<'a>(site, acc, index)))
let _StringSLGetSet (cell: ICell) field (index: int32) (value: string) =
let mutable _val = value
use _pu16str = fixed _val
let lu16str = value.Length * 2
let pu16str = AddTslHead (NativePtr.toNativeInt _pu16str) lu16str
try
_SLGetSet cell field index
(fun site acc -> CallHelper.CallByPtr(site, acc, index, NativePtr.toNativeInt _pu16str))
(fun (p: nativeint) -> Assert.Equal(0, Memory.memcmp(p.ToPointer(), pu16str.ToPointer(), uint64 (lu16str + 4))))
(fun site acc -> Assert.Equal(value, CallHelper.CallByVal<string>(site, acc, index)))
finally
Memory.free(pu16str.ToPointer())
[<Fact>]
let IntegerSLGetSet () =
let mutable s2 = S2(0L, new System.Collections.Generic.List<int64>(seq [1L; 2L; 3L]), 123.456, 0)
_IntegerSLGetSet s2 "f1" 0 4L
_IntegerSLGetSet s2 "f1" 1 5L
_IntegerSLGetSet s2 "f1" 2 6L
_IntegerSLGetSet s2 "f1" 0 7L
_IntegerSLGetSet s2 "f1" 1 8L
_IntegerSLGetSet s2 "f1" 2 9L
[<Fact>]
let StringSLGetSet () =
let mutable s3 = S3(0L, 0, new System.Collections.Generic.List<string>(seq [""; ""]), 0)
_StringSLGetSet s3 "f2" 0 "hello"
_StringSLGetSet s3 "f2" 1 "world!"
let _SLCount (cell: ICell) field (assert_len) =
_CellGetSet cell (fun (tdesc: TypeDescriptor) (accessor: NativeCellAccessor) (paccessor: nativeint) ->
let fcnt = { DeclaringType = tdesc
Verb = ComposedVerb(SGet field, LCount) }
let nfcnt = CompileFunction fcnt
Assert.NotEqual(IntPtr.Zero, nfcnt.CallSite)
printfn "paccessor = %X" paccessor
printfn "pcell = %X" accessor.CellPtr
printfn "length assertion"
Assert.Equal(assert_len, (CallHelper.CallByVal<int>(nfcnt.CallSite, paccessor)))
)
[<Fact>]
let IntegerSLCount () =
let mutable s2 = S2(0L, new System.Collections.Generic.List<int64>(seq [1L; 2L; 3L]), 123.456, 0)
_SLCount s2 "f1" 3
s2 <- S2(0L, new System.Collections.Generic.List<int64>(seq [1L; 2L; 3L; 5L; 8L]), 2333.33333, 0)
_SLCount s2 "f1" 5
let _ListOpsTest
(index : int32)
(verbs : Verb list)
(get : nativeint -> nativeint -> int32 -> 'b)
(insert: nativeint -> nativeint -> int32 -> bool)
(append: nativeint -> nativeint -> unit)
(remove: nativeint -> nativeint -> int32 -> bool)
(inspect: 'b -> bool)
(cmp: 'b -> 'b -> bool)
(tdesc: TypeDescriptor)
(accessor: NativeCellAccessor)
(paccessor: nativeint) =
let [fget; finsert; fcnt; fappend; fremove] = _Compile tdesc verbs
printfn "paccessor = %X" paccessor
printfn "pcell = %X" accessor.CellPtr
printfn "index = %d" index
let mutable _accessor = NativePtr.read (NativePtr.ofNativeInt<NativeCellAccessor> paccessor)
let mutable _size = _accessor.Size
Dump _size (NativePtr.ofNativeInt<byte> _accessor.CellPtr)
let len1 = CallHelper.CallByVal<int32>(fcnt.CallSite, paccessor)
printfn "list len = %d" len1
printfn "e[0] = %A" (CallHelper.CallByVal<'b>(fget.CallSite, paccessor, 0))
printfn "e[1] = %A" (CallHelper.CallByVal<'b>(fget.CallSite, paccessor, 1))
printfn "e[2] = %A" (CallHelper.CallByVal<'b>(fget.CallSite, paccessor, 2))
//printfn "e[3] = %A" (CallHelper.CallByVal<string>(fget.CallSite, paccessor, 3))
//printfn "e[4] = %A" (CallHelper.CallByVal<string>(fget.CallSite, paccessor, 4))
let e = if len1 = 0
then Unchecked.defaultof<'b>
else printfn "get original"
let v = get fget.CallSite paccessor index
printfn "Original = %A" v
v
printfn "insert"
Assert.True(insert finsert.CallSite paccessor index)
_accessor <- NativePtr.read (NativePtr.ofNativeInt<NativeCellAccessor> paccessor)
_size <- _accessor.Size
Dump _size (NativePtr.ofNativeInt<byte> _accessor.CellPtr)
printfn "inspect insert"
let v = get fget.CallSite paccessor index
printfn "v = %A" v
Assert.True(inspect <| v)
if len1 <> 0
then printfn "cmp"
Assert.True(cmp e (get fget.CallSite paccessor (index + 1)))
printfn "append"
append fappend.CallSite paccessor
_accessor <- NativePtr.read (NativePtr.ofNativeInt<NativeCellAccessor> paccessor)
_size <- _accessor.Size
Dump _size (NativePtr.ofNativeInt<byte> _accessor.CellPtr)
let len2 = CallHelper.CallByVal<int32>(fcnt.CallSite, paccessor)
Assert.Equal(len1 + 2, len2)
_accessor <- NativePtr.read (NativePtr.ofNativeInt<NativeCellAccessor> paccessor)
_size <- _accessor.Size
Dump _size (NativePtr.ofNativeInt<byte> _accessor.CellPtr)
printfn "inspect append"
Assert.True(inspect <| get fget.CallSite paccessor (len1 + 1))
printfn "remove at end"
Assert.True(remove fremove.CallSite paccessor (len1 + 1))
let len3 = CallHelper.CallByVal<int32>(fcnt.CallSite, paccessor)
Assert.Equal(len1 + 1, len3)
printfn "remove at index"
Assert.True(remove fremove.CallSite paccessor index)
let len4 = CallHelper.CallByVal<int32>(fcnt.CallSite, paccessor)
Assert.Equal(len1, len4)
if len1 <> 0
then printfn "cmp again"
Assert.True(cmp e (get fget.CallSite paccessor index))
let _SLOps cell field index get insert append remove inspect cmp =
let verbs = [ ComposedVerb(SGet field, ComposedVerb(LGet, BGet))
ComposedVerb(SGet field, LInsertAt)
ComposedVerb(SGet field, LCount)
ComposedVerb(SGet field, LAppend)
ComposedVerb(SGet field, LRemoveAt) ]
let test = _ListOpsTest index verbs
get insert append remove inspect cmp
_CellGetSet cell test
let inline __SLOps (cell: ICell) field (index: int32) (value: 'a) =
_SLOps cell field index
(fun site acc i -> CallHelper.CallByVal<'a>(site, acc, i) ) // SLGet
(fun site acc i -> CallHelper.CallByValBool<'a>(site, acc, i, value) ) // LInsert
(fun site acc -> CallHelper.CallByVal<'a>(site, acc, value) ) // LAppend
(fun site acc i -> CallHelper.CallByValBool<'a>(site, acc, i) ) // LRemove
(fun v -> v = value ) // inspect
(fun a b -> a = b)
[<Fact>]
let IntegerSLOps () =
let mutable s2 = S2(0L, new System.Collections.Generic.List<int64>(seq [1L; 2L; 3L]), 123.456, 0)
__SLOps s2 "f1" 0 4L
__SLOps s2 "f1" 1 5L
__SLOps s2 "f1" 2 6L
__SLOps s2 "f1" 0 7L
__SLOps s2 "f1" 1 8L
__SLOps s2 "f1" 2 9L
[<Fact>]
let FloatSLOps () =
let mutable s4 = S4(0L, "S4 header", new System.Collections.Generic.List<float32>(seq [1.0f; 2.0f; 3.0f]), 123)
__SLOps s4 "f2" 0 4.0f
__SLOps s4 "f2" 1 5.0f
__SLOps s4 "f2" 2 6.0f
__SLOps s4 "f2" 0 7.0f
__SLOps s4 "f2" 1 8.0f
__SLOps s4 "f2" 2 9.0f
[<Fact>]
let StringSLOps () =
let mutable s3 = S3(0L, 0xDEADBEEF, new System.Collections.Generic.List<string>(seq ["hello"; "world"; "people"]), 0x78563412)
__SLOps s3 "f2" 0 "Trinity"
__SLOps s3 "f2" 1 "Graph"
__SLOps s3 "f2" 2 "Engine"
__SLOps s3 "f2" 0 "Gets"
__SLOps s3 "f2" 1 "JIT"
__SLOps s3 "f2" 2 ""
let _BCompare (tdesc: TypeDescriptor) (getaccessor) (small: 'a) (mid: 'a) (large: 'a) =
printfn "BCompare %A: %A - %A - %A" typeof<'a> small mid large
let [set; cmp; lt; le; gt; ge] = _Compile tdesc [BSet; BCmp; BLt; BLe; BGt; BGe]
printfn "Functions compiled"
_BTest getaccessor (fun accessor paccessor ->
let test = fun expect vv nf ->
printfn "Test %A %A" expect vv
Assert.Equal(expect, CallHelper.CallCmp<'a>(nf.CallSite, paccessor, vv))
printfn "Set small"
CallHelper.CallByVal<'a>(set.CallSite, paccessor, small)
test -1 large cmp
test -1 mid cmp
test 0 small cmp
test 1 large lt
test 1 mid lt
test 0 small lt
test 1 large le
test 1 mid le
test 1 small le
test 0 large gt
test 0 mid gt
test 0 small gt
test 0 large ge
test 0 mid ge
test 1 small ge
printfn "Set mid"
CallHelper.CallByVal<'a>(set.CallSite, paccessor, mid)
test -1 large cmp
test 0 mid cmp
test 1 small cmp
test 1 large lt
test 0 mid lt
test 0 small lt
test 1 large le
test 1 mid le
test 0 small le
test 0 large gt
test 0 mid gt
test 1 small gt
test 0 large ge
test 1 mid ge
test 1 small ge
printfn "Set large"
CallHelper.CallByVal<'a>(set.CallSite, paccessor, large)
test 0 large cmp
test 1 mid cmp
test 1 small cmp
test 0 large lt
test 0 mid lt
test 0 small lt
test 1 large le
test 0 mid le
test 0 small le
test 0 large gt
test 1 mid gt
test 1 small gt
test 1 large ge
test 1 mid ge
test 1 small ge
)
let inline _NumericBCompare (tdesc: TypeDescriptor) (value: 'a) (delta: 'a) =
_BCompare tdesc (fun () -> _AllocAccessor sizeof<'a>) (value-delta) (value) (value+delta)
[<Fact>]
let IntegerCompare() =
let t_int32 = MakeFromType typeof<int32>
let t_uint32 = MakeFromType typeof<uint32>
let t_float32 = MakeFromType typeof<float32>
let t_float = MakeFromType typeof<float>
let inline disturb (d: 'a) (fn: 'a -> unit) = fun () -> fn d
let tests = List.collect id [
[ _NumericBCompare t_int32 0
_NumericBCompare t_int32 405923845
_NumericBCompare t_int32 -20514305
] |> List.map (disturb 1)
[ _NumericBCompare t_uint32 1u
_NumericBCompare t_uint32 49401345u
_NumericBCompare t_uint32 90071u
] |> List.map (disturb 1u)
[ _NumericBCompare t_float32 0.0f
_NumericBCompare t_float32 3.14f
_NumericBCompare t_float32 -45103.04352f
] |> List.map (disturb 1.0f)
[ _NumericBCompare t_float 0.0
_NumericBCompare t_float 2.54160571
_NumericBCompare t_float -62039145.51201235
] |> List.map (disturb 1.0)
]
for t in tests do
t()

Просмотреть файл

@ -1,29 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<RuntimeFrameworkVersion>2.0.0</RuntimeFrameworkVersion>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GraphEngine.Core" Version="2.0.9328" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GraphEngine.Jit.TSL\GraphEngine.Jit.TSL.csproj" />
<ProjectReference Include="..\GraphEngine.Jit\GraphEngine.Jit.fsproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="Helper.fs" />
<Compile Include="Basic.fs" />
</ItemGroup>
<ItemGroup />
</Project>

Просмотреть файл

@ -1,291 +0,0 @@
module GraphEngine.Jit.Helper
open System.Runtime.InteropServices
// B-Series
type i8setter = delegate of nativeint * int8 -> unit
type i8getter = delegate of nativeint -> int8
type i8cmp = delegate of nativeint * int8 -> int32
type i16setter = delegate of nativeint * int16 -> unit
type i16getter = delegate of nativeint -> int16
type i16cmp = delegate of nativeint * int16 -> int32
type i32setter = delegate of nativeint * int32 -> unit
type i32getter = delegate of nativeint -> int32
type i32cmp = delegate of nativeint * int32 -> int32
type i64setter = delegate of nativeint * int64 -> unit
type i64getter = delegate of nativeint -> int64
type i64cmp = delegate of nativeint * int64 -> int32
type u8setter = delegate of nativeint * uint8 -> unit
type u8getter = delegate of nativeint -> uint8
type u8cmp = delegate of nativeint * uint8 -> int32
type u16setter = delegate of nativeint * uint16 -> unit
type u16getter = delegate of nativeint -> uint16
type u16cmp = delegate of nativeint * uint16 -> int32
type u32setter = delegate of nativeint * uint32 -> unit
type u32getter = delegate of nativeint -> uint32
type u32cmp = delegate of nativeint * uint32 -> int32
type u64setter = delegate of nativeint * uint64 -> unit
type u64getter = delegate of nativeint -> uint64
type u64cmp = delegate of nativeint * uint64 -> int32
type f32setter = delegate of nativeint * float32 -> unit
type f32getter = delegate of nativeint -> float32
type f32cmp = delegate of nativeint * float32 -> int32
type f64setter = delegate of nativeint * double -> unit
type f64getter = delegate of nativeint -> double
type f64cmp = delegate of nativeint * double -> int32
[<UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet=CharSet.Unicode)>]
type strsetter = delegate of nativeint * string -> unit
[<UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet=CharSet.Unicode)>]
type strgetter = delegate of nativeint -> string
[<UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet=CharSet.Unicode)>]
type strcmp = delegate of nativeint * string -> int32
type psetter = delegate of nativeint * nativeint -> unit
type pgetter = delegate of nativeint -> nativeint
type pcmp = delegate of nativeint * nativeint -> int32
// L-Series
type li8setter = delegate of nativeint * int32 * int8 -> unit
type li8getter = delegate of nativeint * int32 -> int8
type li8boolop = delegate of nativeint * int32 -> bool
type li8boolop2 = delegate of nativeint * int32 * int8 -> bool
type li16setter = delegate of nativeint * int32 * int16 -> unit
type li16getter = delegate of nativeint * int32 -> int16
type li16boolop = delegate of nativeint * int32 * int16 -> bool
type li16boolop2= delegate of nativeint * int32 -> bool
type li32setter = delegate of nativeint * int32 * int32 -> unit
type li32getter = delegate of nativeint * int32 -> int32
type li32boolop = delegate of nativeint * int32 * int32 -> bool
type li32boolop2= delegate of nativeint * int32 -> bool
type li64setter = delegate of nativeint * int32 * int64 -> unit
type li64getter = delegate of nativeint * int32 -> int64
type li64boolop = delegate of nativeint * int32 * int64 -> bool
type li64boolop2= delegate of nativeint * int32 -> bool
type lu8setter = delegate of nativeint * int32 * uint8 -> unit
type lu8getter = delegate of nativeint * int32 -> uint8
type lu8boolop = delegate of nativeint * int32 * uint8 -> bool
type lu8boolop2 = delegate of nativeint * int32 -> bool
type lu16setter = delegate of nativeint * int32 * uint16 -> unit
type lu16getter = delegate of nativeint * int32 -> uint16
type lu16boolop = delegate of nativeint * int32 * uint16 -> bool
type lu16boolop2 = delegate of nativeint * int32 -> bool
type lu32setter = delegate of nativeint * int32 * uint32 -> unit
type lu32getter = delegate of nativeint * int32 -> uint32
type lu32boolop = delegate of nativeint * int32 * uint32 -> bool
type lu32boolop2 = delegate of nativeint * int32 -> bool
type lu64setter = delegate of nativeint * int32 * uint64 -> unit
type lu64getter = delegate of nativeint * int32 -> uint64
type lu64boolop = delegate of nativeint * int32 * uint64 -> bool
type lu64boolop2 = delegate of nativeint * int32 -> bool
type lf32setter = delegate of nativeint * int32 * float32 -> unit
type lf32getter = delegate of nativeint * int32 -> float32
type lf32boolop = delegate of nativeint * int32 * float32 -> bool
type lf32boolop2 = delegate of nativeint * int32 -> bool
type lf64setter = delegate of nativeint * int32 * double -> unit
type lf64getter = delegate of nativeint * int32 -> double
type lf64boolop = delegate of nativeint * int32 * double -> bool
type lf64boolop2 = delegate of nativeint * int32 -> bool
[<UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet=CharSet.Unicode)>]
type lstrsetter = delegate of nativeint * int32 * string -> unit
[<UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet=CharSet.Unicode)>]
type lstrgetter = delegate of nativeint * int32 -> string
[<UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet=CharSet.Unicode)>]
type lstrboolop = delegate of nativeint * int32 * string -> bool
type lstrboolop2 = delegate of nativeint * int32 -> bool
type lpsetter = delegate of nativeint * int32 * nativeint -> unit
type lpgetter = delegate of nativeint * int32 -> nativeint
type lpboolop = delegate of nativeint * int32 * nativeint -> bool
type lpboolop2 = delegate of nativeint * int32 -> bool
let cmp<'a>() =
match typeof<'a> with
| x when x = typeof<int8> -> typeof<i8cmp>
| x when x = typeof<int16> -> typeof<i16cmp>
| x when x = typeof<int32> -> typeof<i32cmp>
| x when x = typeof<int64> -> typeof<i64cmp>
| x when x = typeof<uint8> -> typeof<u8cmp>
| x when x = typeof<uint16> -> typeof<u16cmp>
| x when x = typeof<uint32> -> typeof<u32cmp>
| x when x = typeof<uint64> -> typeof<u64cmp>
| x when x = typeof<float32>-> typeof<f32cmp>
| x when x = typeof<double> -> typeof<f64cmp>
| x when x = typeof<string> -> typeof<strcmp>
| _ -> typeof<pcmp>
let getter<'a>() =
match typeof<'a> with
| x when x = typeof<int8> -> typeof<i8getter>
| x when x = typeof<int16> -> typeof<i16getter>
| x when x = typeof<int32> -> typeof<i32getter>
| x when x = typeof<int64> -> typeof<i64getter>
| x when x = typeof<uint8> -> typeof<u8getter>
| x when x = typeof<uint16> -> typeof<u16getter>
| x when x = typeof<uint32> -> typeof<u32getter>
| x when x = typeof<uint64> -> typeof<u64getter>
| x when x = typeof<float32>-> typeof<f32getter>
| x when x = typeof<double> -> typeof<f64getter>
| x when x = typeof<string> -> typeof<strgetter>
| _ -> typeof<pgetter>
let setter<'a>() =
match typeof<'a> with
| x when x = typeof<int8> -> typeof<i8setter>
| x when x = typeof<int16> -> typeof<i16setter>
| x when x = typeof<int32> -> typeof<i32setter>
| x when x = typeof<int64> -> typeof<i64setter>
| x when x = typeof<uint8> -> typeof<u8setter>
| x when x = typeof<uint16> -> typeof<u16setter>
| x when x = typeof<uint32> -> typeof<u32setter>
| x when x = typeof<uint64> -> typeof<u64setter>
| x when x = typeof<float32>-> typeof<f32setter>
| x when x = typeof<double> -> typeof<f64setter>
| x when x = typeof<string> -> typeof<strsetter>
| _ -> typeof<psetter>
let lgetter<'a>() =
match typeof<'a> with
| x when x = typeof<int8> -> typeof<li8getter>
| x when x = typeof<int16> -> typeof<li16getter>
| x when x = typeof<int32> -> typeof<li32getter>
| x when x = typeof<int64> -> typeof<li64getter>
| x when x = typeof<uint8> -> typeof<lu8getter>
| x when x = typeof<uint16> -> typeof<lu16getter>
| x when x = typeof<uint32> -> typeof<lu32getter>
| x when x = typeof<uint64> -> typeof<lu64getter>
| x when x = typeof<float32>-> typeof<lf32getter>
| x when x = typeof<double> -> typeof<lf64getter>
| x when x = typeof<string> -> typeof<lstrgetter>
| _ -> typeof<lpgetter>
let lsetter<'a>() =
match typeof<'a> with
| x when x = typeof<int8> -> typeof<li8setter>
| x when x = typeof<int16> -> typeof<li16setter>
| x when x = typeof<int32> -> typeof<li32setter>
| x when x = typeof<int64> -> typeof<li64setter>
| x when x = typeof<uint8> -> typeof<lu8setter>
| x when x = typeof<uint16> -> typeof<lu16setter>
| x when x = typeof<uint32> -> typeof<lu32setter>
| x when x = typeof<uint64> -> typeof<lu64setter>
| x when x = typeof<float32>-> typeof<lf32setter>
| x when x = typeof<double> -> typeof<lf64setter>
| x when x = typeof<string> -> typeof<lstrsetter>
| _ -> typeof<lpsetter>
let lboolop<'a>() =
match typeof<'a> with
| x when x = typeof<int8> -> typeof<li8boolop>
| x when x = typeof<int16> -> typeof<li16boolop>
| x when x = typeof<int32> -> typeof<li32boolop>
| x when x = typeof<int64> -> typeof<li64boolop>
| x when x = typeof<uint8> -> typeof<lu8boolop>
| x when x = typeof<uint16> -> typeof<lu16boolop>
| x when x = typeof<uint32> -> typeof<lu32boolop>
| x when x = typeof<uint64> -> typeof<lu64boolop>
| x when x = typeof<float32>-> typeof<lf32boolop>
| x when x = typeof<double> -> typeof<lf64boolop>
| x when x = typeof<string> -> typeof<lstrboolop>
| _ -> typeof<lpboolop>
let lboolop2<'a>() =
match typeof<'a> with
| x when x = typeof<int8> -> typeof<li8boolop2>
| x when x = typeof<int16> -> typeof<li16boolop2>
| x when x = typeof<int32> -> typeof<li32boolop2>
| x when x = typeof<int64> -> typeof<li64boolop2>
| x when x = typeof<uint8> -> typeof<lu8boolop2>
| x when x = typeof<uint16> -> typeof<lu16boolop2>
| x when x = typeof<uint32> -> typeof<lu32boolop2>
| x when x = typeof<uint64> -> typeof<lu64boolop2>
| x when x = typeof<float32>-> typeof<lf32boolop2>
| x when x = typeof<double> -> typeof<lf64boolop2>
| x when x = typeof<string> -> typeof<lstrboolop2>
| _ -> typeof<lpboolop2>
type setter<'a> = delegate of nativeint * 'a -> unit
type CallHelper =
static member CallByVal(callsite: nativeint, paccessor: nativeint, arg0: 'a) =
Marshal.GetDelegateForFunctionPointer(callsite, setter<'a>()).DynamicInvoke(paccessor, arg0) |> ignore
static member CallByVal<'a> (callsite: nativeint, paccessor: nativeint) =
Marshal.GetDelegateForFunctionPointer(callsite, getter<'a>()).DynamicInvoke(paccessor) :?> 'a
static member CallByVal(callsite: nativeint, paccessor: nativeint, arg0: int, arg1: 'a) =
Marshal.GetDelegateForFunctionPointer(callsite, lsetter<'a>()).DynamicInvoke(paccessor, arg0, arg1) |> ignore
static member CallByVal<'a> (callsite: nativeint, paccessor: nativeint, arg0: int) =
Marshal.GetDelegateForFunctionPointer(callsite, lgetter<'a>()).DynamicInvoke(paccessor, arg0) :?> 'a
static member CallByValBool(callsite: nativeint, paccessor: nativeint, arg0: int, arg1: 'a) =
Marshal.GetDelegateForFunctionPointer(callsite, lboolop<'a>()).DynamicInvoke(paccessor, arg0, arg1) :?> bool
static member CallByValBool<'a>(callsite: nativeint, paccessor: nativeint, arg0: int) =
Marshal.GetDelegateForFunctionPointer(callsite, lboolop2<'a>()).DynamicInvoke(paccessor, arg0) :?> bool
static member CallByPtr(callsite: nativeint, paccessor: nativeint, arg0: nativeint) =
Marshal.GetDelegateForFunctionPointer(callsite, setter<nativeint>()).DynamicInvoke(paccessor, arg0) |> ignore
static member CallByPtr<'a> (callsite: nativeint, paccessor: nativeint) =
Marshal.GetDelegateForFunctionPointer(callsite, getter<nativeint>()).DynamicInvoke(paccessor) :?> nativeint
static member CallByPtr(callsite: nativeint, paccessor: nativeint, arg0: int, arg1: nativeint) =
Marshal.GetDelegateForFunctionPointer(callsite, typeof<lpsetter>).DynamicInvoke(paccessor, arg0, arg1) |> ignore
static member CallByPtr<'a> (callsite: nativeint, paccessor: nativeint, arg0: int) =
Marshal.GetDelegateForFunctionPointer(callsite, typeof<lpgetter>).DynamicInvoke(paccessor, arg0) :?> nativeint
static member CallByPtrBool(callsite: nativeint, paccessor: nativeint, arg0: int, arg1: nativeint) =
Marshal.GetDelegateForFunctionPointer(callsite, lboolop<nativeint>()).DynamicInvoke(paccessor, arg0, arg1) :?> bool
static member CallByPtrBool<'a>(callsite: nativeint, paccessor: nativeint, arg0: int) =
Marshal.GetDelegateForFunctionPointer(callsite, lboolop2<nativeint>()).DynamicInvoke(paccessor, arg0) :?> bool
static member GetPushedPtr (callsite: nativeint, paccessor: nativeint): nativeint =
Marshal.GetDelegateForFunctionPointer(callsite, typeof<pgetter>).DynamicInvoke(paccessor) :?> nativeint
static member GetPushedPtr (callsite: nativeint, paccessor: nativeint, arg0: int): nativeint =
Marshal.GetDelegateForFunctionPointer(callsite, typeof<lpgetter>).DynamicInvoke(paccessor, arg0) :?> nativeint
static member CallCmp(callsite: nativeint, paccessor: nativeint, arg0: 'a) =
Marshal.GetDelegateForFunctionPointer(callsite, cmp<'a>()).DynamicInvoke(paccessor, arg0) :?> int32

Просмотреть файл

@ -1,81 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "GraphEngine.Jit", "GraphEngine.Jit\GraphEngine.Jit.fsproj", "{0F48A2AB-7BEE-45E1-955B-A938086EBA11}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Trinity.Core", "..\..\Trinity.Core\Trinity.Core.csproj", "{C527257C-8FEC-495A-A98E-38597D9E22B9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Dependencies", "Dependencies", "{0CB52B42-DEA7-4014-8109-DCF7295D59AF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GraphEngine.Jit.Playground", "GraphEngine.Jit.Playground\GraphEngine.Jit.Playground.csproj", "{F1BE24FA-C020-4DC9-9E36-20443D156CFD}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GraphEngine.Jit.TSL", "GraphEngine.Jit.TSL\GraphEngine.Jit.TSL.csproj", "{AD455239-3DFF-4F5D-A7AB-E4574229C30B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release-CoreCLR|Any CPU = Release-CoreCLR|Any CPU
Release-CoreCLR|x64 = Release-CoreCLR|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Debug|x64.ActiveCfg = Debug|Any CPU
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Debug|x64.Build.0 = Debug|Any CPU
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Release|Any CPU.Build.0 = Release|Any CPU
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Release|x64.ActiveCfg = Release|Any CPU
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Release|x64.Build.0 = Release|Any CPU
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Release-CoreCLR|Any CPU.ActiveCfg = Release|Any CPU
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Release-CoreCLR|Any CPU.Build.0 = Release|Any CPU
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Release-CoreCLR|x64.ActiveCfg = Release|Any CPU
{0F48A2AB-7BEE-45E1-955B-A938086EBA11}.Release-CoreCLR|x64.Build.0 = Release|Any CPU
{C527257C-8FEC-495A-A98E-38597D9E22B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C527257C-8FEC-495A-A98E-38597D9E22B9}.Debug|x64.ActiveCfg = Debug|Any CPU
{C527257C-8FEC-495A-A98E-38597D9E22B9}.Debug|x64.Build.0 = Debug|Any CPU
{C527257C-8FEC-495A-A98E-38597D9E22B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C527257C-8FEC-495A-A98E-38597D9E22B9}.Release|x64.ActiveCfg = Release|Any CPU
{C527257C-8FEC-495A-A98E-38597D9E22B9}.Release|x64.Build.0 = Release|Any CPU
{C527257C-8FEC-495A-A98E-38597D9E22B9}.Release-CoreCLR|Any CPU.ActiveCfg = Release|Any CPU
{C527257C-8FEC-495A-A98E-38597D9E22B9}.Release-CoreCLR|x64.ActiveCfg = Release|Any CPU
{C527257C-8FEC-495A-A98E-38597D9E22B9}.Release-CoreCLR|x64.Build.0 = Release|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Debug|x64.ActiveCfg = Debug|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Debug|x64.Build.0 = Debug|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Release|Any CPU.Build.0 = Release|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Release|x64.ActiveCfg = Release|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Release|x64.Build.0 = Release|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Release-CoreCLR|Any CPU.ActiveCfg = Release|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Release-CoreCLR|Any CPU.Build.0 = Release|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Release-CoreCLR|x64.ActiveCfg = Release|Any CPU
{F1BE24FA-C020-4DC9-9E36-20443D156CFD}.Release-CoreCLR|x64.Build.0 = Release|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Debug|x64.ActiveCfg = Debug|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Debug|x64.Build.0 = Debug|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Release|Any CPU.Build.0 = Release|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Release|x64.ActiveCfg = Release|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Release|x64.Build.0 = Release|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Release-CoreCLR|Any CPU.ActiveCfg = Release|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Release-CoreCLR|Any CPU.Build.0 = Release|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Release-CoreCLR|x64.ActiveCfg = Release|Any CPU
{AD455239-3DFF-4F5D-A7AB-E4574229C30B}.Release-CoreCLR|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{C527257C-8FEC-495A-A98E-38597D9E22B9} = {0CB52B42-DEA7-4014-8109-DCF7295D59AF}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A8A767BA-DA4D-4693-8BA5-4C0F7868A97B}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -1,64 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<AssemblyName>GraphEngine.Jit</AssemblyName>
<RootNamespace>GraphEngine.Jit</RootNamespace>
<OutputTypeEx>library</OutputTypeEx>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<ServerGarbageCollection>true</ServerGarbageCollection>
<ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
<IsPackable>true</IsPackable>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<!-- NuGet package metadata -->
<PropertyGroup>
<Authors>Microsoft Graph Engine Team</Authors>
<Description>GraphEngine Jit code generator.</Description>
<Copyright>Copyright 2018</Copyright>
<Company>Microsoft Corporation</Company>
<Version>2.0.9328</Version>
<AssemblyVersion>2.0.9328.0</AssemblyVersion>
<FileVersion>2.0.9328.0</FileVersion>
<PackageVersion>2.0.9328</PackageVersion>
<PackageId>GraphEngine.Jit</PackageId>
<PackageTags>Graph Engine Trinity Core Runtime Jit Compiler</PackageTags>
<PackageRequireLicenseAcceptance>True</PackageRequireLicenseAcceptance>
<PackageIconUrl>https://www.graphengine.io/img/logo-64x64.png</PackageIconUrl>
<PackageProjectUrl>https://www.graphengine.io</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/Microsoft/GraphEngine/blob/master/LICENSE.md</PackageLicenseUrl>
<RepositoryUrl>https://github.com/Microsoft/GraphEngine</RepositoryUrl>
<RepositoryType>git</RepositoryType>
</PropertyGroup>
<ItemGroup>
<Compile Include="TypeSystem.fs" />
<Compile Include="Utils.fs" />
<Compile Include="Verbs.fs" />
<Compile Include="JitNativeInterop.fs" />
<Compile Include="JitCompiler.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="GraphEngine.Core" Version="2.0.9328" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<Content Include="$(OutputPath)\GraphEngine.Jit.Native.dll">
<PackagePath>runtimes\win-x64\native</PackagePath>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="$(OutputPath)\libGraphEngine.Jit.Native.so">
<PackagePath>runtimes\linux-x64\native</PackagePath>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

Просмотреть файл

@ -1,28 +0,0 @@
module GraphEngine.Jit.JitCompiler
#nowarn "9"
open TypeSystem
open Verbs
open JitNativeInterop
open System.Collections.Generic
open System
open System.Runtime.InteropServices
open Utils
open Microsoft.FSharp.NativeInterop
type NativeFunction = { CallSite: nativeint; Descriptor: FunctionDescriptor }
let s_types = new Dictionary<TypeDescriptor, NativeFunction [] >()
[<DllImport("GraphEngine.Jit.Native.dll")>]
extern nativeint CompileFunctionToNative (nativeint)
let CompileFunction (f: FunctionDescriptor): NativeFunction =
let p = f |> FunctionDescriptorToNative |> Alloc |> NativePtr.toNativeInt
//printf "NativeFunctionDescriptor = %d" p
//let callsite = CompileFunctionToNative p
//printf "CallSite = %d" callsite
{ NativeFunction.CallSite = (CompileFunctionToNative p)
Descriptor = f }

Просмотреть файл

@ -1,120 +0,0 @@
module GraphEngine.Jit.JitNativeInterop
#nowarn "9"
open Microsoft.FSharp.Reflection
open System.Runtime.InteropServices
open System.Linq
open Trinity.Storage
open TypeSystem
open Utils
open Verbs
open System.Xml.Linq
open System
open Microsoft.FSharp.NativeInterop
[<StructLayout(LayoutKind.Sequential, Pack = 1)>]
[<Struct>]
type NativeAttributeDescriptor =
{ Name : nativeint
Value : nativeint }
[<StructLayout(LayoutKind.Sequential, Pack = 1)>]
[<Struct>]
type NativeTypeDescriptor =
{ TypeName : nativeint
QualifiedName : nativeint // Full clr type name
ElementType : nativeint
Members : nativeint
TSLAttributes : nativeint
NrMember : int32
NrTSLAttribute : int32
ElementArity : int32
TypeCode : int16
CellType : uint16 }
[<StructLayout(LayoutKind.Sequential, Pack = 1)>]
[<Struct>]
type NativeMemberDescriptor =
{ Name : nativeint
Type : NativeTypeDescriptor
Optional : uint8 }
[<StructLayout(LayoutKind.Sequential, Pack = 1)>]
[<Struct>]
type NativeVerb =
{ Code : int32 // tag of Verb
Data : nativeint }
[<StructLayout(LayoutKind.Sequential, Pack = 1)>]
[<Struct>]
type NativeFunctionDescriptor =
{ Type : NativeTypeDescriptor
Verbs : nativeint
NrVerbs : int32 }
[<StructLayout(LayoutKind.Sequential, Pack = 1)>]
[<Struct>]
type NativeCellAccessor =
{ mutable CellPtr : nativeint
mutable CellId : int64
mutable Size : int32
mutable EntryIndex : int32
mutable Type : uint16
mutable IsCell : uint8
mutable IsMalloc : uint8 }
let AttributeDescriptorToNative(desc: AttributeDescriptor) =
{ Name = desc.Name |> ToUtf8
Value = desc.Value |> ToUtf8 }
let rec MemberDescriptorToNative(mdesc: MemberDescriptor) =
{ Name = ToUtf8 mdesc.Name
Type = TypeDescriptorToNative mdesc.Type
Optional = if mdesc.Optional then 1uy else 0uy }
and TypeDescriptorToNative(desc: TypeDescriptor) =
{ TypeName = desc.TypeName |> ToUtf8
QualifiedName = desc.QualifiedName |> ToUtf8
TypeCode = desc.TypeCode |> ToUnionTag |> int16
CellType = match desc.TypeCode with | CELL ct -> ct; | _ -> 0us
NrMember = desc.Members |> Seq.length
NrTSLAttribute = desc.TSLAttributes |> Seq.length
ElementArity = desc.ElementType |> Seq.length
ElementType = desc.ElementType |> Seq.map TypeDescriptorToNative |> SeqToNative
Members = desc.Members |> Seq.map MemberDescriptorToNative |> SeqToNative
TSLAttributes = desc.TSLAttributes |> Seq.map AttributeDescriptorToNative |> SeqToNative }
let rec VerbsCount = function
| ComposedVerb(_, x) -> 1 + (VerbsCount x)
| _ -> 1
let rec VerbsToSeq (v: Verb) = seq {
match v with
| ComposedVerb(x, y) ->
yield x
yield! VerbsToSeq y
| _ -> yield v
}
let VerbToNative (v: Verb) =
let data =
match v with
| LInlineGet i | LInlineSet i -> i |> nativeint
| SGet s | SSet s -> s |> ToUtf8
| GSGet t | GSSet t -> t |> TypeDescriptorToNative |> Alloc |> NativePtr.toNativeInt
// TODO forbid EAlloc etc.
| ComposedVerb _ -> failwith "Cannot convert ComposedVerb to native"
| _ -> 0 |> nativeint
{ Code = v |> ToUnionTag; Data = data }
let VerbsToNative (v: Verb) =
VerbsToSeq v |> Seq.map VerbToNative |> SeqToNative
let FunctionDescriptorToNative (fdesc: FunctionDescriptor) =
{ Type = fdesc.DeclaringType |> TypeDescriptorToNative
Verbs = fdesc.Verb |> VerbsToNative
NrVerbs = fdesc.Verb |> VerbsCount}
let Make(desc: seq<ICellDescriptor>) =
desc |> Seq.map (Make >> TypeDescriptorToNative)
|> Seq.toArray

Просмотреть файл

@ -1,125 +0,0 @@
module GraphEngine.Jit.TypeSystem
open System
open System.Collections.Generic
open Trinity.Storage
open System.Reflection
(*
The integer tags of a DU behave exactly
as if they are enum cases
*)
type TypeCode =
NULL
| U8 | U16 | U32 | U64
| I8 | I16 | I32 | I64
| F32 | F64
| BOOL
| CHAR | STRING | U8STRING
| LIST
| STRUCT | CELL of CellType: uint16
let AtomWidthMap =
[ (U8, 1);
(U16, 2);
(U32, 4);
(U64, 8);
(I8, 1);
(I16, 2);
(I32, 4);
(I64, 8);
(F32, 4);
(F64, 8);
(BOOL, 1);
(CHAR, 2); ] |> Map.ofList
type AttributeDescriptor = {
Name : string
Value : string
}
type MemberDescriptor = {
Name : string
Type : TypeDescriptor
Optional : bool
}
and TypeDescriptor = {
TypeName : string
QualifiedName : string
ElementType : seq<TypeDescriptor> // non-empty for container types
Members : seq<MemberDescriptor> // non-empty for structs
TSLAttributes : seq<AttributeDescriptor> // non-empty for cell/field with attributes
TypeCode : TypeCode
}
let IsStruct (T: Type) = T.IsAnsiClass && not T.IsClass
let (|PrimitiveType|ListType|StructType|) (T: Type) =
match T with
| x when x = typeof<Unit> -> PrimitiveType NULL
| x when x = typeof<byte> -> PrimitiveType U8
| x when x = typeof<uint16> -> PrimitiveType U16
| x when x = typeof<uint32> -> PrimitiveType U32
| x when x = typeof<uint64> -> PrimitiveType U64
| x when x = typeof<sbyte> -> PrimitiveType I8
| x when x = typeof<int16> -> PrimitiveType I16
| x when x = typeof<int32> -> PrimitiveType I32
| x when x = typeof<int64> -> PrimitiveType I64
| x when x = typeof<float32> -> PrimitiveType F32
| x when x = typeof<double> -> PrimitiveType F64
| x when x = typeof<bool> -> PrimitiveType BOOL
| x when x = typeof<char> -> PrimitiveType CHAR
| x when x = typeof<string> -> PrimitiveType STRING
| x when x.IsConstructedGenericType &&
x.GetGenericTypeDefinition() =
typedefof<System.Collections.Generic.List<_>>
-> ListType (x.GetGenericArguments() |> Array.head)
| x when x |> IsStruct -> StructType (x.GetFields(BindingFlags.Public ||| BindingFlags.Instance))
| _ -> failwith "Unexpected type"
let rec MakeFromType(T: Type) =
match T with
| PrimitiveType tcode -> { TypeDescriptor.TypeName = T.Name
QualifiedName = T.AssemblyQualifiedName
TSLAttributes = Seq.empty
ElementType = Seq.empty
Members = Seq.empty
TypeCode = tcode }
| ListType elem -> { TypeDescriptor.TypeName = T.Name
QualifiedName = T.AssemblyQualifiedName
TSLAttributes = Seq.empty
ElementType = seq [ elem |> MakeFromType ]
Members = Seq.empty
TypeCode = TypeCode.LIST }
| StructType members -> { TypeDescriptor.TypeName = T.Name
QualifiedName = T.AssemblyQualifiedName
TSLAttributes = Seq.empty
ElementType = Seq.empty
Members = members |> Seq.map (fun m ->
{ MemberDescriptor.Name = m.Name
Type = MakeFromType(m.FieldType)
Optional = false }) // XXX
TypeCode = TypeCode.STRUCT }
let isPrimitive = AtomWidthMap.ContainsKey
let MakeAttr (attr: KeyValuePair<string, string>) =
{ AttributeDescriptor.Name = attr.Key
Value = attr.Value }
let MakeMember (fieldDesc: IFieldDescriptor) =
{ MemberDescriptor.Name = fieldDesc.Name
Type = MakeFromType(fieldDesc.Type)
Optional = fieldDesc.Optional }
let Make (cellDesc: ICellDescriptor) =
{ TypeDescriptor.TypeName = cellDesc.TypeName
QualifiedName = cellDesc.Type.AssemblyQualifiedName
ElementType = Seq.empty
Members = Seq.map MakeMember <| cellDesc.GetFieldDescriptors()
TSLAttributes = cellDesc.Attributes |> Seq.map MakeAttr
TypeCode = TypeCode.CELL cellDesc.CellType }
let TryGetTypeWidth(T: TypeDescriptor) = AtomWidthMap.TryFind T.TypeCode

Просмотреть файл

@ -1,63 +0,0 @@
module GraphEngine.Jit.Utils
#nowarn "9"
open Microsoft.FSharp.Reflection
open Microsoft.FSharp.NativeInterop
open Trinity.Core.Lib
open System.Text
open System
open System.Linq
open System
open System.Runtime.InteropServices
let DebugDump x =
printfn "========="
printfn "%A" x
printfn "========="
x
let ParseCase<'a> (value: string) =
match FSharpType.GetUnionCases typeof<'a> |> Array.filter (fun x -> x.Name = value) with
| [| case |] -> (FSharpValue.MakeUnion(case, [||]) :?> 'a)
| _ -> failwith "Cannot parse union case"
let ToStringCase (value: 'a) =
let caseInfo, _ = FSharpValue.GetUnionFields(value, typeof<'a>)
caseInfo.Name
[<DllImport("msvcrt")>]
extern int strlen(IntPtr)
let Malloc = uint64 >> Memory.malloc >> IntPtr
// Copy a value type to unmanaged heap
let Alloc (v: 'a) =
let buf = Malloc sizeof<'a> |> NativePtr.ofNativeInt<'a>
NativePtr.write buf v
buf
let AddTslHead (p: IntPtr) len =
let buf = Malloc (sizeof<int> + len)
NativePtr.ofNativeInt<int>(buf) |> NativePtr.write <| len
let pcontent = NativePtr.add (NativePtr.ofNativeInt<uint8>(buf)) (sizeof<int>) |> NativePtr.toNativeInt
Memory.memcpy(pcontent.ToPointer(), p.ToPointer(), uint64 len) |> ignore
buf
let ToUtf8 (str: string) =
let buf = Encoding.UTF8.GetBytes(str)
let ret = buf.Length + 1 |> Malloc
let bp = NativePtr.ofNativeInt<uint8> ret
Memory.Copy(buf, ret.ToPointer(), buf.Length)
NativePtr.write (NativePtr.add bp buf.Length) 0uy
ret
let SeqToNative (s: seq<'a>) =
let arr = Seq.toArray s
let buflen = arr.Count() * sizeof<'a> |> uint64
if buflen = 0UL then IntPtr.Zero
else let p = buflen |> Memory.malloc
use buf = fixed arr
Memory.memcpy(p, (NativePtr.toNativeInt buf).ToPointer(), buflen) |> IntPtr
let ToUnionTag (c: 'a) =
c |> box |> FSharpValue.PreComputeUnionTagReader typeof<'a>

Просмотреть файл

@ -1,124 +0,0 @@
module GraphEngine.Jit.Verbs
open System
open TypeSystem
// !Note, only BGet should generate code to extract data from Trinity;
// Other getters should only be interpreted as "getting the accessor of a type"
// For example, let t denote a type descriptor of a struct.
// SGet t "field" will yield the accessor of the field type, and another BGet on
// the type should then yield the real value.
// Further getters can be applied to the result to build up complex getter without
// actually getting the whole value out into the runtime.
// !Note, keep in sync with Verb.h
type Verb =
(** BasicVerb **)
| BNew
| BGet
| BSet
| BCmp
| BLe
| BLt
| BGe
| BGt
| BRefEq
| BHash
| BCount
| BSize
(** ListVerb **)
| LInlineGet of int // get value at a constant index
| LInlineSet of int // set value at a constant index
| LGet
| LSet
| LContains
| LCount
| LInsertAt
| LRemoveAt
| LAppend
| LConv
(** StructVerb **)
| SGet of string
| SSet of string
(** GenericStructVerb **)
| GSGet of TypeDescriptor
| GSSet of TypeDescriptor
(** EnumeratorVerb **)
| EAlloc
| EFree
| ENext
| ECurrent
(** ComposedVerb **)
| ComposedVerb of Verb * Verb
type FunctionDescriptor = {
DeclaringType : TypeDescriptor
Verb : Verb
}
type FunctionSignature(fdesc: FunctionDescriptor) =
let listElem = fdesc.DeclaringType.ElementType |> Seq.tryHead
let tUnit = MakeFromType(typeof<Unit>)
let tInt = MakeFromType(typeof<int32>)
let tBool = MakeFromType(typeof<bool>)
let tString = MakeFromType(typeof<string>)
let tX = fdesc.DeclaringType
member private x.MemberType name = fdesc.DeclaringType.Members |> Seq.find(fun m -> m.Name = name ) |> (fun m -> m.Type)
member x.Input : seq<TypeDescriptor> =
let listElem = fdesc.DeclaringType.ElementType |> Seq.tryHead
match fdesc.Verb with
| BGet -> seq []
| BSet -> seq [ fdesc.DeclaringType ]
| LGet -> seq [ MakeFromType(typeof<int32>) ]
| LSet -> seq [ MakeFromType(typeof<int32>); listElem.Value ]
| LInlineGet _ -> seq []
| LInlineSet _ -> seq [ listElem.Value ]
| LContains -> seq [ listElem.Value ]
| LCount -> seq [ MakeFromType(typeof<int32>); listElem.Value ]
| SGet _ -> seq []
| SSet name -> seq [ x.MemberType name ]
| GSGet _ -> seq [ MakeFromType(typeof<string>) ]
| GSSet t -> seq [ MakeFromType(typeof<string>); t ]
| EAlloc -> seq []
| EFree -> seq []
| ENext -> seq []
| ECurrent -> seq []
member x.Output: TypeDescriptor =
match fdesc.Verb with
| BGet -> tX
| BSet -> tUnit
| LGet -> listElem.Value
| LSet -> tUnit
| LInlineGet i -> listElem.Value
| LInlineSet i -> tUnit
| LContains -> tBool
| LCount -> tInt
| SGet name -> x.MemberType name
| SSet _ -> tUnit
| GSGet t -> t
| GSSet _ -> tUnit
| EAlloc -> tUnit // XXX
| EFree -> tUnit
| ENext -> tBool
| ECurrent -> tUnit // XXX
| ComposedVerb _ -> failwith "notimplemented"

Просмотреть файл

@ -1,24 +0,0 @@
#include "TypeSystem.h"
void __deepcopy(char* &dst, char* const &src)
{
if (src) { dst = _strdup(src); }
else { dst = nullptr; }
}
TypeDescriptor::~TypeDescriptor()
{
for (int i = 0; i < ElementArity; ++i) { ElementType[i].~TypeDescriptor(); }
for (int i = 0; i < NrMember; ++i) { Members[i].~MemberDescriptor(); }
for (int i = 0; i < NrTSLAttribute; ++i) { TSLAttributes[i].~AttributeDescriptor(); }
if (TypeName) free(TypeName);
if (ElementType) free(ElementType);
if (Members) free(Members);
if (TSLAttributes) free(TSLAttributes);
TypeName = nullptr;
ElementType = nullptr;
Members = nullptr;
TSLAttributes = nullptr;
}

Просмотреть файл

@ -1,191 +0,0 @@
#pragma once
#include <algorithm>
#include <vector>
#define pdebug printf("%s, line %d, this=%llx\n", __FUNCTION__, __LINE__, this);
#define pdebug_ printf("%s, line %d\n", __FUNCTION__, __LINE__);
#pragma pack(push, 1)
template<typename T> void __deepcopy(T* &dst, T* const &src)
{
if (src) { dst = (T*)malloc(sizeof(T)); *dst = *src; }
else { dst = nullptr; }
}
void __deepcopy(char* &dst, char* const &src);
template<typename T, typename S> void __deepcopy_arr(T* &dst, S &dst_size, T* const &src, S const &src_size)
{
if (src && src_size) {
dst_size = src_size;
dst = (T*)malloc(sizeof(T) * src_size);
for (int i = 0; i < src_size; ++i) { dst[i] = src[i]; }
}
else { dst = nullptr; dst_size = 0; }
}
template<typename T> std::vector<T*>* __get_ptrs(T* arr, int len)
{
std::vector<T*>* vec = new std::vector<T*>();
for (T* p = arr; p < arr + len; ++p) { vec->push_back(p); }
return vec;
}
struct AttributeDescriptor
{
char* Key;
char* Value;
AttributeDescriptor() { Key = nullptr; Value = nullptr; }
~AttributeDescriptor()
{
if (Key) free(Key);
if (Value) free(Value);
Key = nullptr;
Value = nullptr;
}
};
struct MemberDescriptor;
struct TypeDescriptor
{
TypeDescriptor() { memset(this, 0, sizeof(TypeDescriptor)); }
TypeDescriptor(TypeDescriptor&& other) {
memcpy(this, &other, sizeof(TypeDescriptor));
memset(&other, 0, sizeof(TypeDescriptor));
}
TypeDescriptor(const TypeDescriptor& other) { *this = other; }
TypeDescriptor& operator = (TypeDescriptor &&other) {
memcpy(this, &other, sizeof(TypeDescriptor));
memset(&other, 0, sizeof(TypeDescriptor));
return *this;
}
TypeDescriptor& operator = (const TypeDescriptor &other) {
__deepcopy(TypeName, other.TypeName);
__deepcopy(QualifiedName, other.QualifiedName);
TypeCode = other.TypeCode;
CellType = other.CellType;
__deepcopy_arr(ElementType, ElementArity, other.ElementType, other.ElementArity);
__deepcopy_arr(Members, NrMember, other.Members, other.NrMember);
__deepcopy_arr(TSLAttributes, NrTSLAttribute, other.TSLAttributes, other.NrTSLAttribute);
return *this;
}
~TypeDescriptor();
char* get_TypeName()
{
return _strdup(TypeName);
}
char* get_QualifiedName()
{
return _strdup(QualifiedName);
}
std::vector<TypeDescriptor*>* get_ElementType()
{
return __get_ptrs(ElementType, ElementArity);
}
std::vector<MemberDescriptor*>* get_Members()
{
return __get_ptrs(Members, NrMember);
}
std::vector<AttributeDescriptor*>* get_TSLAttributes()
{
return __get_ptrs(TSLAttributes, NrTSLAttribute);
}
int16_t get_TypeCode()
{
return TypeCode;
}
uint16_t get_CellType()
{
return CellType;
}
private:
char* TypeName;
char* QualifiedName; // AssemblyQualifiedName
TypeDescriptor* ElementType; // non-null for container types
MemberDescriptor* Members; // null for non-struct
AttributeDescriptor* TSLAttributes; // non-null for cell/field with attributes
int32_t NrMember;
int32_t NrTSLAttribute;
int32_t ElementArity; // 1 for list
int16_t TypeCode;
uint16_t CellType;
};
struct MemberDescriptor
{
MemberDescriptor() { memset(this, 0, sizeof(MemberDescriptor)); }
MemberDescriptor(MemberDescriptor&& other)
{
memcpy(this, &other, sizeof(MemberDescriptor));
memset(&other, 0, sizeof(MemberDescriptor));
}
MemberDescriptor(const MemberDescriptor &other)
{
__deepcopy(Name, other.Name);
Type = other.Type;
Optional = other.Optional;
}
MemberDescriptor& operator = (const MemberDescriptor &other)
{
__deepcopy(Name, other.Name);
Type = other.Type;
Optional = other.Optional;
return *this;
}
MemberDescriptor& operator = (MemberDescriptor &&other)
{
memcpy(this, &other, sizeof(MemberDescriptor));
memset(&other, 0, sizeof(MemberDescriptor));
return *this;
}
char* Name;
TypeDescriptor Type;
uint8_t Optional; //non-zero for optional fields
~MemberDescriptor()
{
if (Name) free(Name);
Name = nullptr;
}
};
// !Keep in sync with TypeSystem.fs
enum TypeCode : int16_t {
TC_NULL
, TC_U8, TC_U16, TC_U32, TC_U64
, TC_I8, TC_I16, TC_I32, TC_I64
, TC_F32, TC_F64
, TC_BOOL
, TC_CHAR, TC_STRING, TC_U8STRING
, TC_LIST
, TC_STRUCT, TC_CELL
};
#pragma pack(pop)

Просмотреть файл

@ -1,23 +0,0 @@
MIT License
Copyright (c) 2018 - present Z.Shang
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

Просмотреть файл

@ -1,40 +0,0 @@
> # *C++! THIS IS THE LAST OF MY PARENTHESES! TAKE IT FROM MEEEEEEE!*
# LICPP
[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](http://perso.crans.org/besson/LICENSE.html)
[![Open Source Love svg2](https://badges.frapsoft.com/os/v2/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badges/)
[![Made with Secret Alien Technology](https://img.shields.io/badge/Made%20with-Secret%20Alien%20Technology-green.svg?longCache=true&style=for-the-badge&colorB=82ce82)](https://common-lisp.net/)
[![Knights of the Lambda Calculus](https://img.shields.io/badge/Knights%20of-the%20lambda%20Calculus-brightgreen.svg?longCache=true&style=for-the-badge)](http://catb.org/jargon/html/K/Knights-of-the-Lambda-Calculus.html)
A Lisp Flavoured C++
An Visual Studio specified version is in the branch `ms`, licensed under MIT.
## About
A tiny library that implements some basic Lisp (mainly Common Lisp) utilities as a DSL, currently just a toy, beware of dirty hacks and low performance.
This has been tested with Clang 9.0, GCC 7.1, and Visual Studio Community 2017.
## Usage
At least C++ 14 is required.
You may expect everything to work similarly to what you know in Common Lisp (although there will be limitation because of the differences between C++ and Lisp).
For the details of symbols defined in LICPP, check out [SYMBOLS.md](SYMBOLS.md).
If you want some extra features, please use the latest version of GCC with the flags mentioned below:
- Type Constraints, enable with flag `-fconcepts` (GCC only)
## Note
`tlist` stands for the type `List<T>` which does not have an equivalance in Common Lisp, you may think this is `(type t) => [t]` in Haskell.
## Contributing
All functions should be (preferably) implemented in the same way as its corresponding definition in [CLHS](http://www.lispworks.com/documentation/lw70/CLHS/Front/X_AllSym.htm).
## License
MIT

Просмотреть файл

@ -1,31 +0,0 @@
/*
* This file is a part of the LICPP project,
* licensed under MIT liense.
* Please read LICENSE.TXT and README.MKD for more information.
*/
#ifndef __BASE_HACKS_HPP__
#define __BASE_HACKS_HPP__
#include <type_traits>
#include <functional>
#include <utility>
#include "core.hpp"
namespace licpp {
template <typename R, typename C, bool cp, typename ... As>
struct _lambda_type {
static const bool constp = cp;
enum { arity = sizeof...(As) };
using return_type = R;
using arg_type = typename _list_t<As...>::type;
};
template <typename L>
struct lambda_type : lambda_type<decltype(&L::operator())> {};
template <typename R, typename C, typename ... As>
struct lambda_type<R(C::*)(As...)> : _lambda_type<R, C, false, As...> {};
template <typename R, typename C, typename ... As>
struct lambda_type<R(C::*)(As...) const> : _lambda_type<R, C, true, As...> {};
};
#endif

Просмотреть файл

@ -1,384 +0,0 @@
/*
* This file is a part of the LICPP project,
* licensed under MIT liense.
* Please read LICENSE.TXT and README.MKD for more information.
*/
#ifdef _MSC_VER
#if _MSC_VER < 1900
#error At least Visual Studio 2015 is required
#endif
#else
#if __cplusplus <= 201103L
#error At least C++ 14 is required
#endif
#endif // _MSC_VER
#ifndef __LICPP_CORE_HPP__
#define __LICPP_CORE_HPP__
#include <cstdlib>
#include <vector>
#include <functional>
#include <string>
#include <sstream>
#include <type_traits>
using std::nullptr_t;
namespace licpp {
#define caar(X) car(car(X))
#define cadr(X) car(cdr(X))
#define cdar(X) cdr(car(X))
#define caaar(X) car(car(car(X)))
#define caadr(X) car(car(cdr(X)))
#define cadar(X) car(cdr(car(X)))
#define cdaar(X) cdr(car(car(X)))
#define caddr(X) car(cdr(cdr(X)))
#define cdadr(X) cdr(car(cdr(X)))
#define cddar(X) cdr(cdr(car(X)))
#define caaaar(X) car(car(car(car(X))))
#define caaadr(X) car(car(car(cdr(X))))
#define caadar(X) car(car(cdr(car(X))))
#define cadaar(X) car(cdr(car(car(X))))
#define cdaaar(X) cdr(car(car(car(X))))
#define caaddr(X) car(car(cdr(cdr(X))))
#define cadadr(X) car(cdr(car(cdr(X))))
#define cdaadr(X) cdr(car(car(cdr(X))))
#define caddar(X) car(cdr(cdr(car(X))))
#define cdadar(X) cdr(car(cdr(car(X))))
#define cddaar(X) cdr(cdr(car(car(X))))
#define cadddr(X) car(cdr(cdr(cdr(X))))
#define cdaddr(X) cdr(car(cdr(cdr(X))))
#define cddadr(X) cdr(cdr(car(cdr(X))))
#define cdddar(X) cdr(cdr(cdr(car(X))))
#define cddddr(X) cdr(cdr(cdr(cdr(X))))
#define var auto
// A 2-Element Pair Structure That Holds Arbitary Types
template <typename T, typename U> class Cons;
using nil_t = Cons<nullptr_t, nullptr_t> *;
static const nil_t nil = nullptr;
template <typename T, typename U>
class Cons {
private:
T _car;
U _cdr;
public:
Cons(T car) :_car(car), _cdr(nil) {}
Cons(T car, U cdr) :_car(car), _cdr(cdr) {}
T car() const {
return _car;
}
U cdr() const {
return _cdr;
}
Cons<T, U> * set_car(T car) {
_car = car;
return this;
}
Cons<T, U> * set_cdr(U cdr) {
_cdr = cdr;
return this;
}
};
template<typename T, typename U>
inline auto cons(T car, U cdr) {
return new Cons<T, U>(car, cdr);
}
template <typename T>
inline auto list(T car) {
return cons(car, nil);
}
template <typename T, typename U>
inline auto list(T car, U cadr) {
return cons(car, cons(cadr, nil));
}
template<typename T, typename... Us>
inline auto list(T car, Us... rest) {
auto tmp = list(rest...);
return cons(car, tmp);
}
template<typename T, typename U>
inline T car(Cons<T, U> * c) {
return c->car();
}
template<typename T, typename U>
inline U cdr(Cons<T, U> * c) {
return c->cdr();
}
template <typename T>
struct _consp : std::false_type {};
template <typename T, typename U>
struct _consp<Cons<T, U> * >: std::true_type {};
template <typename T>
inline bool consp(T) {
return _consp<T>::value;
}
template <typename T> constexpr bool consp_v = _consp<T>::value;
template <typename ... T>
struct _list_t {
using type = nullptr_t;
};
template <>
struct _list_t<nullptr_t> {
using type = nil_t;
};
template <typename T>
struct _list_t<T> {
using type = Cons<T, nil_t> *;
};
template <typename T, typename ... U>
struct _list_t<T, U... > {
using type = Cons<T, typename _list_t<U ... >::type> *;
};
template <typename T>
struct _car_t {};
template <>
struct _car_t<nil_t> {
using type = nil_t;
};
template <typename T, typename U>
struct _car_t<Cons<T, U> * > {
using type = T;
};
template <typename T>
struct _cdr_t {};
template <>
struct _cdr_t<nil_t> {
using type = nil_t;
};
template <typename T, typename U>
struct _cdr_t<Cons<T, U> * > {
using type = U;
};
template <typename T>
struct _listp : std::false_type {};
template <>
struct _listp<nil_t> : std::true_type {};
template <typename T, typename U>
struct _listp<Cons<T, U> *> : _listp<U> {
// static const bool value = _listp<U>::value;
};
template <typename T>
inline bool listp(T) {
return _listp<T>::value;
}
template <typename T> constexpr bool listp_v = _listp<T>::value;
template <typename T>
struct _list_len {
static const int value = 0;
};
template <>
struct _list_len<nil_t> {
static const int value = 0;
};
template <typename T>
struct _list_len<Cons<T, nil_t> * > {
static const int value = 1;
};
template <typename T, typename U>
struct _list_len<Cons<T, U> * > {
static const int value = 1 + _list_len<U>::value;
};
//template <typename T, typename U>
//inline int length(Cons<T, U> * l) {
//if (!(listp(l))) {
//throw "LENGTH only works on proper list.";
//}
//return _list_len<Cons<T, U> * >::value;
//}
template <typename T, typename U, typename IsProperList = std::enable_if_t<listp_v<Cons<T, U>*>>>
constexpr int length(Cons<T, U> * l) {
return _list_len<Cons<T, U> * >::value;
}
template <std::size_t N, typename T>
struct _nth_t {};
template <typename T, typename U>
struct _nth_t <0, Cons<T, U> *> {
using type = T;
};
template <std::size_t N, typename T, typename U>
struct _nth_t <N, Cons<T, U> *> {
using type = typename _nth_t<N - 1, U>::type;
};
template <std::size_t N>
struct _nth;
template <>
struct _nth<0>{
template <typename T, typename U>
T operator() (Cons<T, U>* lst) const {
return car(lst);
}
};
template <std::size_t N>
struct _nth{
template <typename T, typename U>
typename _nth_t<N, Cons<T, U>*>::type
operator() (Cons<T, U>* lst) const {
return _nth<N - 1>()(cdr(lst));
}
};
template <std::size_t N, typename T, typename U,
typename WithInListRange = std::enable_if_t<(N < _list_len<Cons<T, U> *>::value) && listp_v<Cons<T, U> *>>>
auto nth(Cons<T, U> * lst) -> typename _nth_t<N, Cons<T, U> * >::type {
return _nth<N>()(lst);
}
template <typename T>
struct _nullp : std::false_type {};
template <>
struct _nullp<nil_t> : std::true_type {};
template <typename T>
inline bool nullp(T) {
return _nullp<T>::value;
}
template <typename T> constexpr bool nullp_v = _nullp<T>::value;
inline std::ostream & operator<<(std::ostream& os, Cons<nullptr_t, nullptr_t> *) {
os << "nil";
return os;
}
template <typename T>
inline std::ostream & operator<<(std::ostream& os, Cons<T, nil_t> * c) {
os << "(";
os << car(c);
os << ". nil)";
return os;
}
template <typename T, typename U>
inline std::ostream & operator<<(std::ostream& os, Cons<T, U> * c) {
os << "(";
os << car(c);
if (cdr(c)) {
os << " . ";
os << cdr(c);
}
os << ")";
return os;
}
template <typename T, typename U>
inline std::string to_string(Cons<T, U> * c) {
std::stringstream ss;
ss << c;
return ss.str();
}
template <typename T>
inline bool equals(T a, T b) {
return a == b;
}
template <typename T, typename U>
inline bool equals(Cons<T, U> * lhs, Cons<T, U> * rhs) {
if (car(lhs) == car(rhs)) {
if (consp(cdr(lhs)) && consp(cdr(rhs))) {
return equals(cdr(lhs), cdr(lhs));
}
return cdr(lhs) == cdr(rhs);
}
return false;
}
// A List Type That Holds Dynamic Number Of Element Of One Type
template <typename T>
class List {
private:
T _head;
List<T> * _tail;
public:
T head() const { return _head; }
List<T> * tail() const { return _tail; }
List() :
_head(nullptr),
_tail(nullptr)
{}
List(T hd) :
_head(hd),
_tail(nullptr)
{}
List(T hd, T tl) :
_head(hd),
_tail(new List(tl))
{}
List(T hd, List<T> * lst) :
_head(hd),
_tail(lst)
{}
// A Trick To Use nullptr In The Places Require A Type Of List<T>*
static List<T> *
Nil() {
return nullptr;
}
// Determine Whether Two Lists are Identical, Order Matters
bool
equals(List<T> & b, std::function<bool(T, T)> pred = [](T a, T b) { return a == b; }) {
if (length(this) != length(b)) {
return false;
}
if (pred(_head, b->head())) {
if (_tail != nullptr) {
return _tail->equals(b->tail(), pred);
}
else {
return true;
}
}
return false;
}
};
// Some Handy Sugars
template <typename T>
inline T
car(List<T> * lst) {
return lst->head();
}
template <typename T>
inline List<T> *
cdr(List<T> * lst) {
return lst->tail();
}
template <typename T>
inline List<T> *
lcons(T ele, List<T> * lst) {
return new List<T>(ele, lst);
}
template <typename T>
inline List<T> *
tlist(T head) {
return new List<T>(head, nullptr);
}
template <typename T, typename ...Ts>
inline List<T> *
tlist(T head, Ts... rest) {
return lcons(head, list(rest...));
}
};
#endif

Просмотреть файл

@ -1,107 +0,0 @@
/*
* This file is a part of the LICPP project,
* licensed under MIT liense.
* Please read LICENSE.TXT and README.MKD for more information.
*/
#ifndef __LICPP_HACKS__
#define __LICPP_HACKS__
#include "core.hpp"
#include "base_hacks.hpp"
#include <type_traits>
namespace licpp{
// MULTIPLE-VALUE-BIND
template <typename T>
struct _values_t {
using type = nullptr_t;
};
template <typename T>
struct _values_t <Cons<T, nil_t> * >{
using type = Cons<T * , nil_t> *;
};
template <typename T, typename U>
struct _values_t <Cons<T, U> * > {
using type = Cons<T * , typename _values_t<U>::type> * ;
};
template <typename T, typename S = typename _values_t<Cons<T, nil_t> * >::type>
void _mvb(Cons<T, nil_t> * lst, S sym){
*(car(sym)) = car(lst);
}
template <typename T, typename U, typename S = typename _values_t<Cons<T, U> * >::type>
void _mvb(Cons<T, U> * lst, S sym){
*(car(sym)) = car(lst);
_mvb(cdr(lst), cdr(sym));
}
template <typename L>
struct get_return : get_return<decltype(&L::operator())>
{};
template <typename C, typename ...A>
struct get_return <void (C::*)(A...)>{
template <typename L>
Cons<bool, nullptr_t> * operator()(L fn){
fn();
return cons(false, nullptr);
}
};
template <typename R, typename C, typename ...A>
struct get_return <R (C::*)(A...)>{
template <typename L>
Cons<bool, R> * operator()(L fn){
return cons(true, fn());
}
};
template <typename C, typename ...A>
struct get_return <void (C::*)(A...) const>{
template <typename L>
Cons<bool, nullptr_t> * operator()(L fn){
fn();
return cons(false, nullptr);
}
};
template <typename R, typename C, typename ...A>
struct get_return <R (C::*)(A...) const>{
template <typename L>
Cons<bool, R> * operator()(L fn){
return cons(true, fn());
}
};
template <typename T, typename U, typename IsProperList = std::enable_if_t<listp_v<Cons<T, U>*>>, typename ... Ss>
auto multiple_value_bind(Cons<T, U> * c, Ss ... sym){
if(!std::is_same<typename _values_t<Cons<T, U> * >::type,
typename _list_t<Ss ...>::type>::value){
throw "The type of Pointer-List does not match the type of the given List";
}
using sym_lst_t = typename _values_t<Cons<T, U> * >::type;
sym_lst_t sym_lst = list(sym...);
auto orig = mapcar([](auto p){ return *p; }, sym_lst);
_mvb(c, sym_lst);
return [orig, sym_lst](auto fn){
auto retval = get_return<decltype(fn)>()(fn);
_mvb(orig, sym_lst);
if(car(retval)){
return cdr(retval);
}
typename _cdr_t<decltype(retval)>::type ret = 0;
return ret;
};
}
// APPLY
template <typename T, typename U, typename F, std::size_t ... A>
auto _apply(F fn, Cons<T, U> * lst, std::index_sequence<A...>){
return fn(nth<A>(lst)...);
}
template <typename T, typename U, typename F,
typename ArgTypesMatch = std::enable_if_t<std::is_same_v<lambda_type<F>::arg_type, Cons<T, U> *>>>
auto apply(F fn, Cons<T, U> * lst) -> typename lambda_type<F>::return_type {
return _apply(fn, lst, std::make_index_sequence<lambda_type<F>::arity>());
}
};
#endif

Просмотреть файл

@ -1,177 +0,0 @@
/*
* This file is a part of the LICPP project,
* licensed under MIT liense.
* Please read LICENSE.TXT and README.MKD for more information.
*/
#ifndef __LICPP_LIST_UTILS__
#define __LICPP_LIST_UTILS__
#include "core.hpp"
#include <type_traits>
#include <iostream>
namespace licpp{
// List-of
template <typename T, typename U>
struct _list_of : std::false_type {};
template <typename T>
struct _list_of<T, Cons<T, nil_t> * > : std::true_type {};
template <typename T, typename S>
struct _list_of<T, Cons<T, S> *> : _list_of<T, S> {};
template <typename T, typename U>
constexpr bool list_of_v = _list_of<T, U>::value;
// M-List-Of : Multiple-level list-of, e.g.: [[T], [[T]]] gives true
template <typename T, typename U>
struct _m_list_of : std::false_type {};
template <typename T>
struct _m_list_of<T, Cons<T, nil_t> * > : std::true_type {};
template <typename T, typename U>
struct _m_list_of<T, Cons<U, nil_t> * > : _m_list_of<T, U> {};
template <typename T, typename S>
struct _m_list_of<T, Cons<T, S> * > : _m_list_of<T, S> {};
template <typename T, typename U, typename S>
struct _m_list_of<T, Cons<U, S> * > {
static const bool value = _m_list_of<T, U>::value && _m_list_of<T, S>::value;
};
template <typename T, typename U>
constexpr bool m_list_of_v = _m_list_of<T, U>::value;
// APPEND
template <typename T, typename U>
struct _append_t{
using type = nullptr_t;
};
template <typename T, typename U>
struct _append_t<nil_t, Cons<T, U> * >{
using type = Cons<T, U> *;
};
template <typename T, typename U>
struct _append_t<Cons<T, U> *, nil_t>{
using type = Cons<T, U> *;
};
template <typename T, typename S, typename Y>
struct _append_t<T, Cons<S, Y> * >{
using type = Cons<T, Cons<S, Y> * > * ;
};
template <typename T, typename S, typename Y>
struct _append_t<Cons<T, nil_t> * , Cons<S, Y> * >{
using type = Cons<T, Cons<S, Y> * > * ;
};
template <typename T, typename U, typename S, typename Y>
struct _append_t<Cons<T, U> *, Cons<S, Y> * >{
using type = Cons<T, typename _append_t<U, Cons<S, Y> * >::type> *;
};
template <typename S, typename Y>
inline Cons<S, Y> * _append(nil_t, Cons<S, Y> * b){
return b;
}
template <typename T, typename U>
inline Cons<T, U> * _append(Cons<T, U> * a, nil_t){
return a;
}
template <typename T, typename U, typename S, typename Y,
typename R = typename _append_t<Cons<T, U> *, Cons<S, Y> *>::type>
R _append(Cons<T, U> * a, Cons<S, Y> * b){
return cons(car(a), _append(cdr(a), b));
}
template <typename T, typename U, typename S, typename Y,
typename BothProperLists = std::enable_if_t<listp_v<Cons<T, U>*> && listp_v<Cons<S, Y>*>>>
auto append(Cons<T, U> * a, Cons<S, Y> * b){
return _append(a, b);
}
// REVERSE
template <typename T>
struct _reverse_t {
using type = nullptr_t;
};
template <>
struct _reverse_t <nil_t> {
using type = nil_t;
};
template <typename T>
struct _reverse_t <Cons<T, nil_t> *>{
using type = Cons<T, nil_t> *;
};
template <typename T, typename U>
struct _reverse_t <Cons<T, Cons<U, nil_t> * > *>{
using type = Cons<U, Cons<T, nil_t> *> *;
};
template <typename T, typename U>
struct _reverse_t <Cons<T, U> *>{
using type = typename _append_t<typename _reverse_t<U>::type, Cons<T, nil_t> * >::type;
};
inline nil_t _reverse(nil_t){
return nil;
}
template <typename T, typename U, typename R = typename _reverse_t<Cons<T, U> *>::type>
R _reverse(Cons<T, U> * lst){
return append(_reverse(cdr(lst)), list(car(lst)));
}
template <typename T, typename U,
typename IsProperList = std::enable_if_t<listp_v<Cons<T, U>*>>>
auto reverse(Cons<T, U> * lst){
return _reverse(lst);
}
// MAPCAR
template <typename T, typename U, typename ...Us>
struct _mapcar_t {};
template <typename F>
struct _mapcar_t<F, nil_t>{
using type = nil_t;
};
template <typename F, typename T>
struct _mapcar_t<F, Cons<T, nil_t> *>{
using type = Cons<typename std::result_of<F&(T)>::type, nil_t> *;
};
template <typename F, typename T, typename U>
struct _mapcar_t<F, Cons<T, U> *>{
using type = Cons<typename std::result_of<F&(T)>::type, typename _mapcar_t<F, U>::type> * ;
};
template <typename F, typename ...S>
struct _packed_result_t{
using type = typename std::result_of<F&(S...)>::type;
};
template <typename F, typename T, typename ...S>
struct _mapcar_t<F, Cons<T, nil_t> *, S...>{
using type = Cons<typename _packed_result_t<F, T, typename _car_t<S>::type ...>::type,
nil_t> * ;
};
template <typename F, typename T, typename U, typename ...S>
struct _mapcar_t<F, Cons<T, U> *, S...>{
using type = Cons<typename _packed_result_t<F, T, typename _car_t<S>::type ...>::type,
typename _mapcar_t<F, U, typename _cdr_t<S>::type ...>::type> *;
};
template <typename F, typename T>
auto _mapcar(F fn, Cons<T, nil_t> * lst){
return list(fn(car(lst)));
}
template <typename F, typename T, typename U,
typename R = typename _mapcar_t<Cons<T, U>*, F>::type>
R _mapcar(F fn, Cons<T, U> * lst){
return cons(fn(car(lst)), _mapcar(fn, cdr(lst)));
}
template <typename F, typename T, typename ...S>
auto _mapcar(F fn, Cons<T, nil_t> * lst, S... rest){
return list(fn(car(lst), car(rest)...));
}
template <typename F, typename T, typename U, typename ...S>
auto _mapcar(F fn, Cons<T, U> * lst, S... rest){
return cons(fn(car(lst), car(rest)...), _mapcar(fn, cdr(lst), cdr(rest)...));
}
template <typename F, typename T, typename U,
typename IsProperList = std::enable_if_t<listp_v<Cons<T, U>*>>>
auto mapcar(F fn, Cons<T, U> * lst){
return _mapcar(fn, lst);
}
template <typename F, typename T, typename U,
typename IsProperList = std::enable_if_t<listp_v<Cons<T, U>*>>, typename ...S>
auto mapcar(F fn, Cons<T, U> * lst, S... rest){
return _mapcar(fn, lst, rest...);
}
};
#endif

Просмотреть файл

@ -1,38 +0,0 @@
#include <iostream>
#include "xsecd.hpp"
using namespace std;
using namespace xsecd;
using namespace licpp;
int main(){
auto l1 = licpp::list(1, 2, 3);
cout << (licpp::m_list_of_v<int, decltype(l1)> ? "true" : "false") << endl;
auto l2 = licpp::list(1, licpp::list(2, 4), 3);
cout << (licpp::m_list_of_v<int, decltype(l2)> ? "true" : "false") << endl;
auto stk = new_stack(10);
alloc_prim<T_U32>(stk, 1234);
cout << stk << endl;
saddr_t a = 1;
saddr_t b = 2;
saddr_t c = 3;
saddr_t d = 4;
saddr_t e = 5;
saddr_t f = 6;
saddr_t g = 7;
auto test_lst = licpp::list(licpp::list(a, b, c), d, licpp::list(f, g), e);
cout << (licpp::m_list_of_v<saddr_t, decltype(test_lst)> ? "true" : "false") << endl;
cout << list_size_v<decltype(test_lst)> << endl;
cout << list_size(test_lst) << endl;
// sizeof(a) = 1, sizeof(b) = 2
xsecd::xalloc(stk, licpp::list(a, b));
cout << stk << endl;
return 0;
}

Просмотреть файл

@ -1,202 +0,0 @@
#include <iostream>
#include <string>
#include "xsecd.hpp"
using namespace std;
namespace l = licpp;
namespace xsecd {
saddr_t salloc(XStack * stack, saddr_t size){
if(stack->sop + size >= stack->capacity){
cerr << "Stack Overflow" << endl;
return 0;
}
auto res = stack->sop; // return the very first address of the allocated block
for(saddr_t i = 0; i < size; i++){
stack->nil[stack->sop].tid = T_NULL;
stack->nil[stack->sop].type_desc = 0;
stack->sop ++;
}
return res;
}
XStack * new_stack(size_t cap){
auto res = (XStack *) malloc (2 * sizeof(saddr_t) + cap * sizeof(XObj32));
res->capacity = cap;
res->nil[0].tid = T_NULL;
res->sop = 1; // The stack starts from 1, and 0 will always be NIL
return res;
}
void operator<< (XStack * stack, XObj32& o){
if(stack->sop + 1 >= stack->capacity){
cerr << "Stack Overflow" << endl;
// Or should we do auto resize here?
return;
}
memcpy(&(stack->nil[stack->sop]), &o, sizeof(XObj32));
stack->sop += 1;
}
template <TypeId tid>
void alloc_prim(XStack *, prim_t_t<tid>){}
template <>
void alloc_prim<T_NULL>(XStack *, std::nullptr_t){}
template <>
void alloc_prim<T_U8>(XStack * stack, uint8_t v){
XObj32 o;
o.tid = T_U8;
o._u8 = v;
stack << o;
}
template <>
void alloc_prim<T_U16>(XStack * stack, uint16_t v){
XObj32 o;
o.tid = T_U16;
o._u16 = v;
stack << o;
}
template <>
void alloc_prim<T_U32>(XStack * stack, uint32_t v){
XObj32 o;
o.tid = T_U32;
o._u32 = v;
stack << o;
}
template <>
void alloc_prim<T_U64>(XStack * stack, uint64_t v){
XObj32 o;
o.tid = T_U64;
o._u64 = v;
stack << o;
}
template <>
void alloc_prim<T_I8>(XStack * stack, int8_t v){
XObj32 o;
o.tid = T_I8;
o._i8 = v;
stack << o;
}
template <>
void alloc_prim<T_I16>(XStack * stack, int16_t v){
XObj32 o;
o.tid = T_I16;
o._i16 = v;
stack << o;
}
template <>
void alloc_prim<T_I32>(XStack * stack, int32_t v){
XObj32 o;
o.tid = T_I32;
o._i32 = v;
stack << o;
}
template <>
void alloc_prim<T_I64>(XStack * stack, int64_t v){
XObj32 o;
o.tid = T_I64;
o._i64 = v;
stack << o;
}
template <>
void alloc_prim<T_F32>(XStack * stack, float v){
XObj32 o;
o.tid = T_F32;
o._f32 = v;
stack << o;
}
template <>
void alloc_prim<T_F64>(XStack * stack, double v){
XObj32 o;
o.tid = T_F64;
o._f64= v;
stack << o;
}
template <>
void alloc_prim<T_BOOL>(XStack * stack, bool v){
XObj32 o;
o.tid = T_BOOL;
o._bool = v;
stack << o;
}
template <>
void alloc_prim<T_CHAR>(XStack * stack, u16char_t v){
XObj32 o;
o.tid = T_CHAR;
o._char = v;
stack << o;
}
void XStack::operator>> (XObj32*& o){
// Dummy
(void)o;
}
ostream& operator<< (ostream& s, XStack * stack){
s << "[" << endl;
for(saddr_t i = 0; i < stack->sop; ++i){
s << " " << i << "\t| " << stack->nil[i];
s << endl;
}
s << "SOP: " << stack->sop << endl;
s << "]" << endl;
return s;
}
ostream& operator<< (ostream& s, XObj32 o){
switch(o.tid){
case T_NULL:
s << "NIL";
break;
case T_U8:
s << "U8:\t " << o._u8;
break;
case T_U16:
s << "U16:\t " << o._u16;
break;
case T_U32:
s << "U32:\t " << o._u32;
break;
case T_U64:
s << "U64:\t " << o._u64;
break;
case T_I8:
s << "I8:\t " << o._i8;
break;
case T_I16:
s << "I16:\t " << o._i16;
break;
case T_I32:
s << "I32:\t " << o._i32;
break;
case T_I64:
s << "I64:\t " << o._i64;
break;
case T_F32:
s << "F32:\t " << o._f32;
break;
case T_F64:
s << "F64:\t " << o._f64;
break;
case T_BOOL:
s << "BOOL:\t " << (o._bool ? "#t" : "#f");
break;
case T_CHAR:
s << "CHAR:\t #\\" << o._char;
break;
case T_LIST:
s << "LIST:\t";
s << "CAR: " << o._list.car;
s << " | CDR: " << o._list.cdr;
break;
default:
s << "Non Prim";
break;
}
return s;
}
};

Просмотреть файл

@ -1,257 +0,0 @@
#ifndef __XSECD_HPP__
#define __XSECD_HPP__
#include "licpp/includes/core.hpp"
#include "licpp/includes/base_hacks.hpp"
#include "licpp/includes/hacks.hpp"
#include "licpp/includes/list_utils.hpp"
//#include "TypeSystem.h"
#include <type_traits>
#include <string>
#include <limits>
#include <unordered_map>
namespace xsecd {
namespace l = licpp;
using saddr_t = uint32_t;
#ifdef _MSC_VER
using u16char_t = wchar_t;
#else
using u16char_t = char16_t;
#endif
const size_t default_stack_size = 1024;
enum TypeId : int16_t {
T_NULL
, T_U8, T_U16, T_U32, T_U64
, T_I8, T_I16, T_I32, T_I64
, T_F32, T_F64
, T_BOOL
, T_CHAR, T_STRING, T_U8STRING
, T_LIST
, T_STRUCT, T_CELL
};
template <TypeId>
struct prim_t {};
template <>
struct prim_t<T_NULL> { using type = std::nullptr_t; };
template <>
struct prim_t<T_U8> { using type = uint8_t; };
template <>
struct prim_t<T_U16> { using type = uint16_t; };
template <>
struct prim_t<T_U32> { using type = uint32_t; };
template <>
struct prim_t<T_U64> { using type = uint64_t; };
template <>
struct prim_t<T_I8> { using type = int8_t; };
template <>
struct prim_t<T_I16> { using type = int16_t; };
template <>
struct prim_t<T_I32> { using type = int32_t; };
template <>
struct prim_t<T_I64> { using type = int64_t; };
template <>
struct prim_t<T_F32> { using type = float; };
template <>
struct prim_t<T_F64> { using type = double; };
template <>
struct prim_t<T_BOOL> { using type = bool; };
template <>
struct prim_t<T_CHAR> { using type = u16char_t; };
template <TypeId i>
using prim_t_t = typename prim_t<i>::type;
enum TypeCat {
PRIM, DYN, LST
};
constexpr TypeCat type_cat(TypeId t){
switch(t){
case T_LIST:
return LST;
case T_STRING:
case T_U8STRING:
case T_STRUCT:
case T_CELL:
return DYN;
default:
return PRIM;
}
}
struct XObj32 {
TypeId tid : 8;
uint32_t type_desc : 24;
union {
uint8_t _u8;
uint16_t _u16;
uint32_t _u32;
uint64_t _u64;
int8_t _i8;
int16_t _i16;
int32_t _i32;
int64_t _i64;
float _f32;
double _f64;
bool _bool;
u16char_t _char;
// S_Addr is the offset on the stack
saddr_t _string;
saddr_t _u8string;
saddr_t _struct;
saddr_t _cell;
struct {
saddr_t car;
saddr_t cdr;
} _list;
};
};
template <typename T>
struct is_prim : std::false_type {};
template <>
struct is_prim<std::nullptr_t> : std::true_type {};
template <>
struct is_prim<uint8_t> : std::true_type {};
template <>
struct is_prim<uint16_t> : std::true_type {};
template <>
struct is_prim<uint32_t> : std::true_type {};
template <>
struct is_prim<uint64_t> : std::true_type {};
template <>
struct is_prim<int8_t> : std::true_type {};
template <>
struct is_prim<int16_t> : std::true_type {};
template <>
struct is_prim<int32_t> : std::true_type {};
template <>
struct is_prim<int64_t> : std::true_type {};
template <>
struct is_prim<float> : std::true_type {};
template <>
struct is_prim<double> : std::true_type {};
template <>
struct is_prim<bool> : std::true_type {};
template <>
struct is_prim<char> : std::true_type {};
template <typename T>
constexpr bool is_prim_v = is_prim<T>::value;
std::ostream & operator<< (std::ostream&, XObj32);
struct XStack {
saddr_t capacity;
saddr_t sop; // Top of stack....SOP stands for sopra: [it.] n. top
XObj32 nil[0]; // Bottom of stack
void operator>>(XObj32*&);
};
XStack * new_stack(size_t);
saddr_t salloc(XStack *, saddr_t size); // S Alloc, S stands for Stack
template <typename T>
saddr_t _xalloc(XStack *, T);
template <>
inline saddr_t _xalloc(XStack *, l::nil_t){
return 0;
}
template <typename U, typename = std::enable_if_t<!std::is_same_v<U, std::nullptr_t>>>
inline saddr_t _xalloc(XStack * stack, l::Cons<saddr_t, U> * lst){
auto p = stack->sop;
stack->sop++;
stack->nil[p].tid = T_LIST;
stack->nil[p]._list.car = salloc(stack, car(lst));
stack->nil[p]._list.cdr = _xalloc(stack, cdr(lst));
return p;
}
template <typename T, typename U, typename = std::enable_if_t<!std::is_same_v<U, std::nullptr_t>>>
inline saddr_t _xalloc(XStack * stack, l::Cons<T, U> * lst){
auto p = stack->sop;
stack->sop++;
stack->nil[p].tid = T_LIST;
stack->nil[p]._list.car = _xalloc(stack, car(lst));
stack->nil[p]._list.cdr = _xalloc(stack, cdr(lst));
return p;
}
template <typename T, typename U, typename MListOfSaddr = std::enable_if_t<l::m_list_of_v<saddr_t, l::Cons<T, U> *>>>
//template <typename T, typename U>
// saddr_t xalloc(XStack *, l::Cons<T, U> *); // X Alloc, X stands for eXtension
saddr_t xalloc(XStack * stack, l::Cons<T, U> * lst){
auto lsize = list_size(lst);
if(stack->sop + lsize >= stack->capacity){
cerr << "Stack Overflow" << endl;
return 0;
}
return _xalloc(stack, lst);
}
template <typename T>
struct _list_size {
static const saddr_t value = 0;
};
template <>
struct _list_size<l::nil_t> {
static const saddr_t value = 0;
};
template <typename T>
struct _list_size<l::Cons<T, l::nil_t> *> {
static const saddr_t value = 1 + _list_size<T>::value;
};
template <typename T, typename U>
struct _list_size<l::Cons<T, U> *> {
static const saddr_t value = 1 + _list_size<T>::value + _list_size<U>::value;
};
template <typename T> // This computes the extra (List-structure) size of a list
constexpr saddr_t list_size_v = _list_size<T>::value;
//template <typename T, typename U>
//unsigned int list_size(l::Cons<T, U> *);
template <typename T>
saddr_t __list_size(T);
template <>
inline saddr_t __list_size(l::Cons<std::nullptr_t, std::nullptr_t> *){
return 0;
}
template <>
inline saddr_t __list_size(saddr_t v){
return v;
}
template <typename T, typename U, typename = std::enable_if_t<!std::is_same_v<T, std::nullptr_t>>>
inline saddr_t __list_size(l::Cons<T, U> * l){
return __list_size(car(l)) + __list_size(cdr(l));
}
template <typename T, typename U,
typename IsListOfSAddr = std::enable_if_t<l::m_list_of_v<saddr_t, l::Cons<T, U> *>>>
inline saddr_t list_size(l::Cons<T, U> * lst){
return __list_size(car(lst)) + __list_size(cdr(lst)) + list_size_v<l::Cons<T, U>*>;
}
template <TypeId tid>
void alloc_prim(XStack *, prim_t_t<tid>);
void operator<<(XStack *, XObj32&);
std::ostream & operator<<(std::ostream&, XStack *);
//struct XTypeDesc {
//// This is the struct for storing user defined structural types
//static uint32_t type_id;
//static std::unordered_map<uint32_t, TypeDescriptor *> types;
//};
};
#endif

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<OutputType>library</OutputType>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>

Просмотреть файл

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<Version>2.0.9328.0</Version>
<FileVersion>2.0.9328.0</FileVersion>

Просмотреть файл

@ -1,18 +0,0 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0)
ADD_SUBDIRECTORY(Trinity.FFI.Native)
ADD_SUBDIRECTORY(Trinity.FFI.Python)
ADD_DOTNET(Trinity.FFI.Metagen/Trinity.FFI.Metagen.fsproj
PACKAGE GraphEngine.FFI.Metagen
VERSION ${TRINITY_VERSION}
DEPENDS GraphEngine.Core GraphEngine.Jit)
ADD_DOTNET(Trinity.FFI/Trinity.FFI.csproj
PACKAGE GraphEngine.FFI
VERSION ${TRINITY_VERSION}
DEPENDS GraphEngine.Core GraphEngine.Jit GraphEngine.FFI.Metagen)
#TODO unittest
ADD_DEPENDENCIES(BUILD_Trinity.FFI Trinity trinity_ffi trinity_host)

Просмотреть файл

@ -1,422 +0,0 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version: 15.0.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
namespace Trinity.FFI.AutoCode
{
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
using System;
/// <summary>
/// Class to produce the template output
/// </summary>
#line 1 "C:\Users\v-wazhao\github\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Cpp.tt"
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "15.0.0.0")]
public partial class Cpp : CppBase
{
#line hidden
/// <summary>
/// Create the template output
/// </summary>
public virtual string TransformText()
{
#line 7 "C:\Users\v-wazhao\github\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Cpp.tt"
Assembly ffi_asm = typeof(FFIExportAttribute).Assembly;
var export_methods = from type in ffi_asm.GetTypes()
select type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) into method
from m in method
where m.GetCustomAttribute<FFIExportAttribute>() != null
select m;
#line default
#line hidden
this.Write(@"
/***********************************
Auto-generated from Cpp.tt
***********************************/
#pragma once
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the TRINITYFFINATIVE_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// TRINITYFFINATIVE_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef TRINITYFFINATIVE_EXPORTS
#include <cstdint>
#include <os/os.h>
#define TRINITYFFINATIVE_API extern ""C"" __declspec(dllexport)
#else
#define TRINITYFFINATIVE_API extern ""C"" __declspec(dllimport)
#endif
#include <TrinityErrorCode.h>
#include ""Trinity.h""
typedef char* (*TRINITY_FFI_SYNC_HANDLER)(char*);
typedef void (*TRINITY_FFI_ASYNC_HANDLER)(char*);
");
#line 42 "C:\Users\v-wazhao\github\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Cpp.tt"
foreach(var m in export_methods)
{
#line default
#line hidden
this.Write("typedef ");
#line 45 "C:\Users\v-wazhao\github\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Cpp.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(Helper.GenerateReturnTypeCpp(m)));
#line default
#line hidden
this.Write(" (*TRINITY_FFI_");
#line 45 "C:\Users\v-wazhao\github\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Cpp.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(Helper.GenerateName(m).ToUpper()));
#line default
#line hidden
this.Write(")(");
#line 45 "C:\Users\v-wazhao\github\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Cpp.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(Helper.GenerateParameterListCpp(m)));
#line default
#line hidden
this.Write(");\r\n");
#line 46 "C:\Users\v-wazhao\github\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Cpp.tt"
}
#line default
#line hidden
this.Write("\r\nextern \"C\" struct TRINITY_INTERFACES\r\n{\r\n");
#line 51 "C:\Users\v-wazhao\github\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Cpp.tt"
foreach(var m in export_methods)
{
#line default
#line hidden
this.Write(" TRINITY_FFI_");
#line 54 "C:\Users\v-wazhao\github\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Cpp.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(Helper.GenerateName(m).ToUpper()));
#line default
#line hidden
this.Write(" ");
#line 54 "C:\Users\v-wazhao\github\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Cpp.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(Helper.GenerateName(m)));
#line default
#line hidden
this.Write(";\r\n");
#line 55 "C:\Users\v-wazhao\github\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Cpp.tt"
}
#line default
#line hidden
this.Write("};\r\n\r\nTRINITYFFINATIVE_API TrinityErrorCode TRINITY_FFI_INITIALIZE(int n_apppa" +
"ths, wchar_t** lp_apppaths, char* config_path, char* storage_root);\r\nTRINITYFFIN" +
"ATIVE_API TRINITY_INTERFACES* TRINITY_FFI_GET_INTERFACES();\r\n");
return this.GenerationEnvironment.ToString();
}
}
#line default
#line hidden
#region Base class
/// <summary>
/// Base class for this transformation
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "15.0.0.0")]
public class CppBase
{
#region Fields
private global::System.Text.StringBuilder generationEnvironmentField;
private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
private global::System.Collections.Generic.List<int> indentLengthsField;
private string currentIndentField = "";
private bool endsWithNewline;
private global::System.Collections.Generic.IDictionary<string, object> sessionField;
#endregion
#region Properties
/// <summary>
/// The string builder that generation-time code is using to assemble generated output
/// </summary>
protected System.Text.StringBuilder GenerationEnvironment
{
get
{
if ((this.generationEnvironmentField == null))
{
this.generationEnvironmentField = new global::System.Text.StringBuilder();
}
return this.generationEnvironmentField;
}
set
{
this.generationEnvironmentField = value;
}
}
/// <summary>
/// The error collection for the generation process
/// </summary>
public System.CodeDom.Compiler.CompilerErrorCollection Errors
{
get
{
if ((this.errorsField == null))
{
this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
}
return this.errorsField;
}
}
/// <summary>
/// A list of the lengths of each indent that was added with PushIndent
/// </summary>
private System.Collections.Generic.List<int> indentLengths
{
get
{
if ((this.indentLengthsField == null))
{
this.indentLengthsField = new global::System.Collections.Generic.List<int>();
}
return this.indentLengthsField;
}
}
/// <summary>
/// Gets the current indent we use when adding lines to the output
/// </summary>
public string CurrentIndent
{
get
{
return this.currentIndentField;
}
}
/// <summary>
/// Current transformation session
/// </summary>
public virtual global::System.Collections.Generic.IDictionary<string, object> Session
{
get
{
return this.sessionField;
}
set
{
this.sessionField = value;
}
}
#endregion
#region Transform-time helpers
/// <summary>
/// Write text directly into the generated output
/// </summary>
public void Write(string textToAppend)
{
if (string.IsNullOrEmpty(textToAppend))
{
return;
}
// If we're starting off, or if the previous text ended with a newline,
// we have to append the current indent first.
if (((this.GenerationEnvironment.Length == 0)
|| this.endsWithNewline))
{
this.GenerationEnvironment.Append(this.currentIndentField);
this.endsWithNewline = false;
}
// Check if the current text ends with a newline
if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
{
this.endsWithNewline = true;
}
// This is an optimization. If the current indent is "", then we don't have to do any
// of the more complex stuff further down.
if ((this.currentIndentField.Length == 0))
{
this.GenerationEnvironment.Append(textToAppend);
return;
}
// Everywhere there is a newline in the text, add an indent after it
textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
// If the text ends with a newline, then we should strip off the indent added at the very end
// because the appropriate indent will be added when the next time Write() is called
if (this.endsWithNewline)
{
this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
}
else
{
this.GenerationEnvironment.Append(textToAppend);
}
}
/// <summary>
/// Write text directly into the generated output
/// </summary>
public void WriteLine(string textToAppend)
{
this.Write(textToAppend);
this.GenerationEnvironment.AppendLine();
this.endsWithNewline = true;
}
/// <summary>
/// Write formatted text directly into the generated output
/// </summary>
public void Write(string format, params object[] args)
{
this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
}
/// <summary>
/// Write formatted text directly into the generated output
/// </summary>
public void WriteLine(string format, params object[] args)
{
this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
}
/// <summary>
/// Raise an error
/// </summary>
public void Error(string message)
{
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
error.ErrorText = message;
this.Errors.Add(error);
}
/// <summary>
/// Raise a warning
/// </summary>
public void Warning(string message)
{
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
error.ErrorText = message;
error.IsWarning = true;
this.Errors.Add(error);
}
/// <summary>
/// Increase the indent
/// </summary>
public void PushIndent(string indent)
{
if ((indent == null))
{
throw new global::System.ArgumentNullException("indent");
}
this.currentIndentField = (this.currentIndentField + indent);
this.indentLengths.Add(indent.Length);
}
/// <summary>
/// Remove the last indent that was added with PushIndent
/// </summary>
public string PopIndent()
{
string returnValue = "";
if ((this.indentLengths.Count > 0))
{
int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
if ((indentLength > 0))
{
returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
}
}
return returnValue;
}
/// <summary>
/// Remove any indentation
/// </summary>
public void ClearIndent()
{
this.indentLengths.Clear();
this.currentIndentField = "";
}
#endregion
#region ToString Helpers
/// <summary>
/// Utility class to produce culture-oriented representation of an object as a string.
/// </summary>
public class ToStringInstanceHelper
{
private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
/// <summary>
/// Gets or sets format provider to be used by ToStringWithCulture method.
/// </summary>
public System.IFormatProvider FormatProvider
{
get
{
return this.formatProviderField ;
}
set
{
if ((value != null))
{
this.formatProviderField = value;
}
}
}
/// <summary>
/// This is called from the compile/run appdomain to convert objects within an expression block to a string
/// </summary>
public string ToStringWithCulture(object objectToConvert)
{
if ((objectToConvert == null))
{
throw new global::System.ArgumentNullException("objectToConvert");
}
System.Type t = objectToConvert.GetType();
System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
typeof(System.IFormatProvider)});
if ((method == null))
{
return objectToConvert.ToString();
}
else
{
return ((string)(method.Invoke(objectToConvert, new object[] {
this.formatProviderField })));
}
}
}
private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
/// <summary>
/// Helper to produce culture-oriented representation of an object as a string
/// </summary>
public ToStringInstanceHelper ToStringHelper
{
get
{
return this.toStringHelperField;
}
}
#endregion
}
#endregion
}

Просмотреть файл

@ -1,60 +0,0 @@
<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Reflection" #>
<#
Assembly ffi_asm = typeof(FFIExportAttribute).Assembly;
var export_methods = from type in ffi_asm.GetTypes()
select type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) into method
from m in method
where m.GetCustomAttribute<FFIExportAttribute>() != null
select m;
#>
/***********************************
Auto-generated from Cpp.tt
***********************************/
#pragma once
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the TRINITYFFINATIVE_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// TRINITYFFINATIVE_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef TRINITYFFINATIVE_EXPORTS
#include <cstdint>
#include <os/os.h>
#define TRINITYFFINATIVE_API extern "C" __declspec(dllexport)
#else
#define TRINITYFFINATIVE_API extern "C" __declspec(dllimport)
#endif
#include <TrinityErrorCode.h>
#include "Trinity.h"
typedef char* (*TRINITY_FFI_SYNC_HANDLER)(char*);
typedef void (*TRINITY_FFI_ASYNC_HANDLER)(char*);
<#
foreach(var m in export_methods)
{#>
typedef <#=Helper.GenerateReturnTypeCpp(m)#> (*TRINITY_FFI_<#=Helper.GenerateName(m).ToUpper()#>)(<#=Helper.GenerateParameterListCpp(m)#>);
<#
}#>
extern "C" struct TRINITY_INTERFACES
{
<#
foreach(var m in export_methods)
{#>
TRINITY_FFI_<#=Helper.GenerateName(m).ToUpper()#> <#=Helper.GenerateName(m)#>;
<#
}#>
};
TRINITYFFINATIVE_API TrinityErrorCode TRINITY_FFI_INITIALIZE(int n_apppaths, wchar_t** lp_apppaths, char* config_path, char* storage_root);
TRINITYFFINATIVE_API TRINITY_INTERFACES* TRINITY_FFI_GET_INTERFACES();

Просмотреть файл

@ -1,368 +0,0 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version: 15.0.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
namespace Trinity.FFI.AutoCode
{
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
using System;
/// <summary>
/// Class to produce the template output
/// </summary>
#line 1 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\FFIMethods.tt"
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "15.0.0.0")]
public partial class FFIMethods : FFIMethodsBase
{
#line hidden
/// <summary>
/// Create the template output
/// </summary>
public virtual string TransformText()
{
#line 7 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\FFIMethods.tt"
Assembly ffi_asm = typeof(FFIExportAttribute).Assembly;
var export_methods = from type in ffi_asm.GetTypes()
select type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) into method
from m in method
where m.GetCustomAttribute<FFIExportAttribute>() != null
select m;
#line default
#line hidden
this.Write(@"/***********************************
Auto-generated from FFIMethods.tt
***********************************/
using Trinity.Diagnostics;
using Trinity.FFI.Interop;
namespace Trinity.FFI
{
public static class FFIMethods
{
private static TRINITY_INTERFACES s_interfaces = new TRINITY_INTERFACES
{
");
#line 30 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\FFIMethods.tt"
foreach(var m in export_methods)
{
#line default
#line hidden
this.Write("\t\t\t");
#line 33 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\FFIMethods.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(Helper.GenerateName(m) + " = " + m.DeclaringType.Name + "." + m.Name + ","));
#line default
#line hidden
this.Write("\r\n");
#line 34 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\FFIMethods.tt"
}
#line default
#line hidden
this.Write(" };\r\n\r\n public static void Initialize()\r\n {\r\n Log" +
".WriteLine(LogLevel.Info, $\"{nameof(FFIMethods)}: Initializing FFI methods\");\r\n " +
" Native.TRINITY_FFI_SET_INTERFACES(ref s_interfaces);\r\n }\r\n " +
"}\r\n}");
return this.GenerationEnvironment.ToString();
}
}
#line default
#line hidden
#region Base class
/// <summary>
/// Base class for this transformation
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "15.0.0.0")]
public class FFIMethodsBase
{
#region Fields
private global::System.Text.StringBuilder generationEnvironmentField;
private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
private global::System.Collections.Generic.List<int> indentLengthsField;
private string currentIndentField = "";
private bool endsWithNewline;
private global::System.Collections.Generic.IDictionary<string, object> sessionField;
#endregion
#region Properties
/// <summary>
/// The string builder that generation-time code is using to assemble generated output
/// </summary>
protected System.Text.StringBuilder GenerationEnvironment
{
get
{
if ((this.generationEnvironmentField == null))
{
this.generationEnvironmentField = new global::System.Text.StringBuilder();
}
return this.generationEnvironmentField;
}
set
{
this.generationEnvironmentField = value;
}
}
/// <summary>
/// The error collection for the generation process
/// </summary>
public System.CodeDom.Compiler.CompilerErrorCollection Errors
{
get
{
if ((this.errorsField == null))
{
this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
}
return this.errorsField;
}
}
/// <summary>
/// A list of the lengths of each indent that was added with PushIndent
/// </summary>
private System.Collections.Generic.List<int> indentLengths
{
get
{
if ((this.indentLengthsField == null))
{
this.indentLengthsField = new global::System.Collections.Generic.List<int>();
}
return this.indentLengthsField;
}
}
/// <summary>
/// Gets the current indent we use when adding lines to the output
/// </summary>
public string CurrentIndent
{
get
{
return this.currentIndentField;
}
}
/// <summary>
/// Current transformation session
/// </summary>
public virtual global::System.Collections.Generic.IDictionary<string, object> Session
{
get
{
return this.sessionField;
}
set
{
this.sessionField = value;
}
}
#endregion
#region Transform-time helpers
/// <summary>
/// Write text directly into the generated output
/// </summary>
public void Write(string textToAppend)
{
if (string.IsNullOrEmpty(textToAppend))
{
return;
}
// If we're starting off, or if the previous text ended with a newline,
// we have to append the current indent first.
if (((this.GenerationEnvironment.Length == 0)
|| this.endsWithNewline))
{
this.GenerationEnvironment.Append(this.currentIndentField);
this.endsWithNewline = false;
}
// Check if the current text ends with a newline
if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
{
this.endsWithNewline = true;
}
// This is an optimization. If the current indent is "", then we don't have to do any
// of the more complex stuff further down.
if ((this.currentIndentField.Length == 0))
{
this.GenerationEnvironment.Append(textToAppend);
return;
}
// Everywhere there is a newline in the text, add an indent after it
textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
// If the text ends with a newline, then we should strip off the indent added at the very end
// because the appropriate indent will be added when the next time Write() is called
if (this.endsWithNewline)
{
this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
}
else
{
this.GenerationEnvironment.Append(textToAppend);
}
}
/// <summary>
/// Write text directly into the generated output
/// </summary>
public void WriteLine(string textToAppend)
{
this.Write(textToAppend);
this.GenerationEnvironment.AppendLine();
this.endsWithNewline = true;
}
/// <summary>
/// Write formatted text directly into the generated output
/// </summary>
public void Write(string format, params object[] args)
{
this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
}
/// <summary>
/// Write formatted text directly into the generated output
/// </summary>
public void WriteLine(string format, params object[] args)
{
this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
}
/// <summary>
/// Raise an error
/// </summary>
public void Error(string message)
{
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
error.ErrorText = message;
this.Errors.Add(error);
}
/// <summary>
/// Raise a warning
/// </summary>
public void Warning(string message)
{
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
error.ErrorText = message;
error.IsWarning = true;
this.Errors.Add(error);
}
/// <summary>
/// Increase the indent
/// </summary>
public void PushIndent(string indent)
{
if ((indent == null))
{
throw new global::System.ArgumentNullException("indent");
}
this.currentIndentField = (this.currentIndentField + indent);
this.indentLengths.Add(indent.Length);
}
/// <summary>
/// Remove the last indent that was added with PushIndent
/// </summary>
public string PopIndent()
{
string returnValue = "";
if ((this.indentLengths.Count > 0))
{
int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
if ((indentLength > 0))
{
returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
}
}
return returnValue;
}
/// <summary>
/// Remove any indentation
/// </summary>
public void ClearIndent()
{
this.indentLengths.Clear();
this.currentIndentField = "";
}
#endregion
#region ToString Helpers
/// <summary>
/// Utility class to produce culture-oriented representation of an object as a string.
/// </summary>
public class ToStringInstanceHelper
{
private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
/// <summary>
/// Gets or sets format provider to be used by ToStringWithCulture method.
/// </summary>
public System.IFormatProvider FormatProvider
{
get
{
return this.formatProviderField ;
}
set
{
if ((value != null))
{
this.formatProviderField = value;
}
}
}
/// <summary>
/// This is called from the compile/run appdomain to convert objects within an expression block to a string
/// </summary>
public string ToStringWithCulture(object objectToConvert)
{
if ((objectToConvert == null))
{
throw new global::System.ArgumentNullException("objectToConvert");
}
System.Type t = objectToConvert.GetType();
System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
typeof(System.IFormatProvider)});
if ((method == null))
{
return objectToConvert.ToString();
}
else
{
return ((string)(method.Invoke(objectToConvert, new object[] {
this.formatProviderField })));
}
}
}
private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
/// <summary>
/// Helper to produce culture-oriented representation of an object as a string
/// </summary>
public ToStringInstanceHelper ToStringHelper
{
get
{
return this.toStringHelperField;
}
}
#endregion
}
#endregion
}

Просмотреть файл

@ -1,45 +0,0 @@
<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Reflection" #>
<#
Assembly ffi_asm = typeof(FFIExportAttribute).Assembly;
var export_methods = from type in ffi_asm.GetTypes()
select type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) into method
from m in method
where m.GetCustomAttribute<FFIExportAttribute>() != null
select m;
#>
/***********************************
Auto-generated from FFIMethods.tt
***********************************/
using Trinity.Diagnostics;
using Trinity.FFI.Interop;
namespace Trinity.FFI
{
public static class FFIMethods
{
private static TRINITY_INTERFACES s_interfaces = new TRINITY_INTERFACES
{
<#
foreach(var m in export_methods)
{
#> <#= Helper.GenerateName(m) + " = " + m.DeclaringType.Name + "." + m.Name + "," #>
<#
}
#>
};
public static void Initialize()
{
Log.WriteLine(LogLevel.Info, $"{nameof(FFIMethods)}: Initializing FFI methods");
Native.TRINITY_FFI_SET_INTERFACES(ref s_interfaces);
}
}
}

Просмотреть файл

@ -1,85 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Trinity.TSL.Lib;
namespace Trinity.FFI.AutoCode
{
static class Helper
{
internal static string GenerateName(MethodInfo m)
{
var name = m.Name;
var prefix = m.DeclaringType.GetCustomAttribute<FFIPrefixAttribute>();
if (prefix == null) throw new ArgumentException($"No prefix found for method {name}");
return prefix.Prefix + name;
}
internal static string GenerateReturnType(MethodInfo m)
=> (m.ReturnType == typeof(void)) ? "void" : m.ReturnType.Name;
internal static string GenerateParameterList(MethodInfo m)
=> string.Join(", ", m.GetParameters().Select(GenerateParameter));
internal static string GenerateParameter(ParameterInfo p)
{
string ret = "";
var t = p.ParameterType;
if (t == typeof(CellAccessOptions)) ret += "[MarshalAs(UnmanagedType.I4)]";
ret += _signature(t, p.IsOut);
ret += " p" + p.Position;
return ret;
}
internal static string GenerateReturnTypeCpp(MethodInfo m)
=> _signature_cpp(m.ReturnType);
internal static string GenerateParameterListCpp(MethodInfo m)
=> string.Join(", ", m.GetParameters().Select(GenerateParameterCpp));
internal static string GenerateParameterCpp(ParameterInfo p)
{
return _signature_cpp(p.ParameterType);
}
private static string _signature(Type t, bool isout = false)
{
var e = t.GetElementType();
if (isout) return "out " + _signature(e);
if (t.IsByRef) return "ref " + _signature(e);
if (t.IsArray) return _signature(e) + "[]";
if (t.IsPointer) throw new NotSupportedException();
if (t.IsGenericType) throw new NotSupportedException();
if (t.HasElementType) throw new NotSupportedException();
return t.Name;
}
private static string _signature_cpp(Type t)
{
var e = t.GetElementType();
if (t.IsByRef) { return _signature_cpp(e) + "*"; }
else if (t.IsPointer) throw new NotSupportedException();
else if (t.IsArray) { return "void*"; }
else if (t.IsGenericType) throw new NotSupportedException();
else if (t.HasElementType) throw new NotSupportedException();
// go through conversion map
switch (t.Name)
{
case "IntPtr": return "void*";
case "String": return "char*";
case "Int64": return "long long";
case "Int32": return "long";
case "Void": return "void";
default: return t.Name;
}
}
}
}

Просмотреть файл

@ -1,413 +0,0 @@
// ------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version: 15.0.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
// ------------------------------------------------------------------------------
namespace Trinity.FFI.AutoCode
{
using System.Linq;
using System.Text;
using System.Collections.Generic;
using System.Reflection;
using System;
/// <summary>
/// Class to produce the template output
/// </summary>
#line 1 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Native.tt"
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "15.0.0.0")]
public partial class Native : NativeBase
{
#line hidden
/// <summary>
/// Create the template output
/// </summary>
public virtual string TransformText()
{
#line 7 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Native.tt"
Assembly ffi_asm = typeof(FFIExportAttribute).Assembly;
var export_methods = from type in ffi_asm.GetTypes()
select type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) into method
from m in method
where m.GetCustomAttribute<FFIExportAttribute>() != null
select m;
#line default
#line hidden
this.Write(@"/***********************************
Auto-generated from Native.tt
***********************************/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Trinity.TSL.Lib;
using Trinity.FFI.Interop;
using static GraphEngine.Jit.JitNativeInterop;
namespace Trinity.FFI
{
internal unsafe delegate string TRINITY_FFI_SYNC_HANDLER(string content);
internal unsafe delegate void TRINITY_FFI_ASYNC_HANDLER(string content);
");
#line 34 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Native.tt"
foreach(var m in export_methods)
{
#line default
#line hidden
this.Write(" internal unsafe delegate ");
#line 37 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Native.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(Helper.GenerateReturnType(m)));
#line default
#line hidden
this.Write(" TRINITY_FFI_");
#line 37 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Native.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(Helper.GenerateName(m).ToUpper()));
#line default
#line hidden
this.Write("(");
#line 37 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Native.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(Helper.GenerateParameterList(m)));
#line default
#line hidden
this.Write(");\r\n");
#line 38 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Native.tt"
}
#line default
#line hidden
this.Write("\r\n internal struct TRINITY_INTERFACES\r\n {\r\n");
#line 43 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Native.tt"
foreach(var m in export_methods)
{
#line default
#line hidden
this.Write(" [MarshalAs(UnmanagedType.FunctionPtr)]\r\n public TRINITY_FFI_");
#line 47 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Native.tt"
this.Write(this.ToStringHelper.ToStringWithCulture(Helper.GenerateName(m).ToUpper() + " " + Helper.GenerateName(m)));
#line default
#line hidden
this.Write(";\r\n");
#line 48 "D:\git\GraphEngine\src\Modules\Trinity.FFI\Trinity.FFI.AutoCode\Native.tt"
}
#line default
#line hidden
this.Write(@" };
internal static unsafe class Native
{
[DllImport(""trinity_ffi"", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
internal static extern void TRINITY_FFI_SET_INTERFACES(ref TRINITY_INTERFACES interfaces);
}
}
");
return this.GenerationEnvironment.ToString();
}
}
#line default
#line hidden
#region Base class
/// <summary>
/// Base class for this transformation
/// </summary>
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "15.0.0.0")]
public class NativeBase
{
#region Fields
private global::System.Text.StringBuilder generationEnvironmentField;
private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
private global::System.Collections.Generic.List<int> indentLengthsField;
private string currentIndentField = "";
private bool endsWithNewline;
private global::System.Collections.Generic.IDictionary<string, object> sessionField;
#endregion
#region Properties
/// <summary>
/// The string builder that generation-time code is using to assemble generated output
/// </summary>
protected System.Text.StringBuilder GenerationEnvironment
{
get
{
if ((this.generationEnvironmentField == null))
{
this.generationEnvironmentField = new global::System.Text.StringBuilder();
}
return this.generationEnvironmentField;
}
set
{
this.generationEnvironmentField = value;
}
}
/// <summary>
/// The error collection for the generation process
/// </summary>
public System.CodeDom.Compiler.CompilerErrorCollection Errors
{
get
{
if ((this.errorsField == null))
{
this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
}
return this.errorsField;
}
}
/// <summary>
/// A list of the lengths of each indent that was added with PushIndent
/// </summary>
private System.Collections.Generic.List<int> indentLengths
{
get
{
if ((this.indentLengthsField == null))
{
this.indentLengthsField = new global::System.Collections.Generic.List<int>();
}
return this.indentLengthsField;
}
}
/// <summary>
/// Gets the current indent we use when adding lines to the output
/// </summary>
public string CurrentIndent
{
get
{
return this.currentIndentField;
}
}
/// <summary>
/// Current transformation session
/// </summary>
public virtual global::System.Collections.Generic.IDictionary<string, object> Session
{
get
{
return this.sessionField;
}
set
{
this.sessionField = value;
}
}
#endregion
#region Transform-time helpers
/// <summary>
/// Write text directly into the generated output
/// </summary>
public void Write(string textToAppend)
{
if (string.IsNullOrEmpty(textToAppend))
{
return;
}
// If we're starting off, or if the previous text ended with a newline,
// we have to append the current indent first.
if (((this.GenerationEnvironment.Length == 0)
|| this.endsWithNewline))
{
this.GenerationEnvironment.Append(this.currentIndentField);
this.endsWithNewline = false;
}
// Check if the current text ends with a newline
if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
{
this.endsWithNewline = true;
}
// This is an optimization. If the current indent is "", then we don't have to do any
// of the more complex stuff further down.
if ((this.currentIndentField.Length == 0))
{
this.GenerationEnvironment.Append(textToAppend);
return;
}
// Everywhere there is a newline in the text, add an indent after it
textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
// If the text ends with a newline, then we should strip off the indent added at the very end
// because the appropriate indent will be added when the next time Write() is called
if (this.endsWithNewline)
{
this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
}
else
{
this.GenerationEnvironment.Append(textToAppend);
}
}
/// <summary>
/// Write text directly into the generated output
/// </summary>
public void WriteLine(string textToAppend)
{
this.Write(textToAppend);
this.GenerationEnvironment.AppendLine();
this.endsWithNewline = true;
}
/// <summary>
/// Write formatted text directly into the generated output
/// </summary>
public void Write(string format, params object[] args)
{
this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
}
/// <summary>
/// Write formatted text directly into the generated output
/// </summary>
public void WriteLine(string format, params object[] args)
{
this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
}
/// <summary>
/// Raise an error
/// </summary>
public void Error(string message)
{
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
error.ErrorText = message;
this.Errors.Add(error);
}
/// <summary>
/// Raise a warning
/// </summary>
public void Warning(string message)
{
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
error.ErrorText = message;
error.IsWarning = true;
this.Errors.Add(error);
}
/// <summary>
/// Increase the indent
/// </summary>
public void PushIndent(string indent)
{
if ((indent == null))
{
throw new global::System.ArgumentNullException("indent");
}
this.currentIndentField = (this.currentIndentField + indent);
this.indentLengths.Add(indent.Length);
}
/// <summary>
/// Remove the last indent that was added with PushIndent
/// </summary>
public string PopIndent()
{
string returnValue = "";
if ((this.indentLengths.Count > 0))
{
int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
if ((indentLength > 0))
{
returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
}
}
return returnValue;
}
/// <summary>
/// Remove any indentation
/// </summary>
public void ClearIndent()
{
this.indentLengths.Clear();
this.currentIndentField = "";
}
#endregion
#region ToString Helpers
/// <summary>
/// Utility class to produce culture-oriented representation of an object as a string.
/// </summary>
public class ToStringInstanceHelper
{
private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
/// <summary>
/// Gets or sets format provider to be used by ToStringWithCulture method.
/// </summary>
public System.IFormatProvider FormatProvider
{
get
{
return this.formatProviderField ;
}
set
{
if ((value != null))
{
this.formatProviderField = value;
}
}
}
/// <summary>
/// This is called from the compile/run appdomain to convert objects within an expression block to a string
/// </summary>
public string ToStringWithCulture(object objectToConvert)
{
if ((objectToConvert == null))
{
throw new global::System.ArgumentNullException("objectToConvert");
}
System.Type t = objectToConvert.GetType();
System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
typeof(System.IFormatProvider)});
if ((method == null))
{
return objectToConvert.ToString();
}
else
{
return ((string)(method.Invoke(objectToConvert, new object[] {
this.formatProviderField })));
}
}
}
private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
/// <summary>
/// Helper to produce culture-oriented representation of an object as a string
/// </summary>
public ToStringInstanceHelper ToStringHelper
{
get
{
return this.toStringHelperField;
}
}
#endregion
}
#endregion
}

Просмотреть файл

@ -1,57 +0,0 @@
<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Reflection" #>
<#
Assembly ffi_asm = typeof(FFIExportAttribute).Assembly;
var export_methods = from type in ffi_asm.GetTypes()
select type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) into method
from m in method
where m.GetCustomAttribute<FFIExportAttribute>() != null
select m;
#>
/***********************************
Auto-generated from Native.tt
***********************************/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Trinity.TSL.Lib;
using Trinity.FFI.Interop;
using static GraphEngine.Jit.JitNativeInterop;
namespace Trinity.FFI
{
internal unsafe delegate string TRINITY_FFI_SYNC_HANDLER(string content);
internal unsafe delegate void TRINITY_FFI_ASYNC_HANDLER(string content);
<#
foreach(var m in export_methods)
{#>
internal unsafe delegate <#=Helper.GenerateReturnType(m)#> TRINITY_FFI_<#=Helper.GenerateName(m).ToUpper()#>(<#=Helper.GenerateParameterList(m)#>);
<#
}#>
internal struct TRINITY_INTERFACES
{
<#
foreach(var m in export_methods)
{#>
[MarshalAs(UnmanagedType.FunctionPtr)]
public TRINITY_FFI_<#=Helper.GenerateName(m).ToUpper() + " " + Helper.GenerateName(m)#>;
<#
}#>
};
internal static unsafe class Native
{
[DllImport("trinity_ffi", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
internal static extern void TRINITY_FFI_SET_INTERFACES(ref TRINITY_INTERFACES interfaces);
}
}

Просмотреть файл

@ -1,21 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Trinity.Utilities;
namespace Trinity.FFI.AutoCode
{
class Program
{
static void Main(string[] args)
{
File.WriteAllText("../Trinity.FFI/FFIMethods.cs", new FFIMethods().TransformText());
File.WriteAllText("../Trinity.FFI/Native.cs", new Native().TransformText());
File.WriteAllText("../Trinity.FFI.Native/Trinity.FFI.Native.h", new Cpp().TransformText());
}
}
}

Просмотреть файл

@ -1,8 +0,0 @@
{
"profiles": {
"Trinity.FFI.AutoCode": {
"commandName": "Project",
"workingDirectory": "."
}
}
}

Просмотреть файл

@ -1,77 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461</TargetFrameworks>
<AssemblyName>Trinity.FFI.AutoCode</AssemblyName>
<RootNamespace>Trinity.FFI.AutoCode</RootNamespace>
<AllowUnsafe>true</AllowUnsafe>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<ApplicationIcon />
<OutputType>Exe</OutputType>
<StartupObject />
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net461|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net461|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GraphEngine.Core" Version="2.0.9328" />
<ProjectReference Include="..\Trinity.FFI\Trinity.FFI.csproj" />
</ItemGroup>
<ItemGroup>
<TslCodegen Include="**/*.tsl" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib" />
</ItemGroup>
<ItemGroup>
<None Update="Cpp.tt">
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>Cpp.cs</LastGenOutput>
</None>
<None Update="FFIMethods.tt">
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>FFIMethods.cs</LastGenOutput>
</None>
<None Update="Native.tt">
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>Native.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
</ItemGroup>
<ItemGroup>
<Compile Update="Cpp.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Cpp.tt</DependentUpon>
</Compile>
<Compile Update="FFIMethods.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>FFIMethods.tt</DependentUpon>
</Compile>
<Compile Update="Native.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Native.tt</DependentUpon>
</Compile>
</ItemGroup>
</Project>

Просмотреть файл

@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using Trinity.Core.Lib;
using static GraphEngine.Jit.JitNativeInterop;
using static GraphEngine.Jit.Utils;
namespace Trinity.FFI.Metagen.UnitTests
{
internal static unsafe class Helper
{
internal static IntPtr LockCell(long cellId)
{
Global.LocalStorage.GetLockedCellInfo(cellId, out var Size, out var Type, out var CellPtr, out var EntryIndex);
return Alloc(new NativeCellAccessor((IntPtr)CellPtr, cellId, Size, EntryIndex, Type, 0, 0));
}
internal static T ListToNativeAndThen<T>(List<int> lst, Func<IntPtr, T> andthen)
{
var arr = lst.ToArray();
var buflen = arr.Length * sizeof(int);
IntPtr i = IntPtr.Zero;
if (buflen != 0L)
{
var p = (byte*)Memory.malloc((ulong)buflen + 4);
*(int*)p = buflen;
fixed(void* buf = arr)
{
Memory.memcpy(p + sizeof(int), buf, (ulong)buflen);
i = Alloc(new NativeCellAccessor((IntPtr) p, 0, 0, buflen, 0, 0, 0));
}
}
return andthen(i);
}
}
}

Просмотреть файл

@ -1,291 +0,0 @@
using System;
using Xunit;
using Xunit.Abstractions;
using Trinity.FFI.Metagen;
using Trinity.FFI;
using Trinity.Utilities;
using Trinity.Storage.Composite;
using System.Linq;
using Trinity.Storage;
using GraphEngine.Jit;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using Microsoft.FSharp.Collections;
namespace Trinity.FFI.Metagen.UnitTests
{
public delegate int SBGet(IntPtr cell);
public delegate int LBGet(IntPtr list, int idx);
public delegate int LCount(IntPtr list);
public unsafe class Test : IDisposable
{
readonly ITestOutputHelper Output;
readonly char ManglingCode = '_';
static IStorageSchema Schema;
public Test(ITestOutputHelper output)
{
Global.Initialize();
Output = output;
Schema = CompositeStorage.AddStorageExtension(@"..\..\..\tsl", "Some");
}
public void Disp(ICellAccessor c)
{
c.ToByteArray().By(_ => String.Join(" ", _)).By(Output.WriteLine);
Output.WriteLine("");
}
[Fact]
public void TestTSLBytes()
{
var c = Trinity.Global.LocalStorage.UseGenericCell(10, TSL.Lib.CellAccessOptions.CreateNewOnCellNotFound, "C");
//c.SetField<int>("i", 1);
//c.SetField<double>("x", 500.0);
Disp(c);
//var c2 = Trinity.Global.LocalStorage.UseGenericCell(12, TSL.Lib.CellAccessOptions.CreateNewOnCellNotFound, "C2");
//c2.AppendToField<int>("ls", 2);
//Disp(c2);
//var c3 = Trinity.Global.LocalStorage.UseGenericCell(14, TSL.Lib.CellAccessOptions.CreateNewOnCellNotFound, "C3");
//Disp(c3);
}
[Fact]
public void TestNewSwigGen()
{
var ty_descs = Schema.CellDescriptors.Select(TypeSystem.Make);
var all_type_collected = FFI.MetaGen.analyzer.collect_type(ty_descs);
foreach (var e in all_type_collected)
{
Output.WriteLine(e.TypeName);
}
Output.WriteLine("=====================");
var all_verbs = FFI.MetaGen.analyzer.generate_chaining_verb(all_type_collected);
//var num = 0;
//foreach (var e in all_verbs)
//{
// //var len = e.Item2.Length;
// //Output.WriteLine($"{e.Item1.TypeName}, method num: {len}");
// //num += len;
// e.Item2.Select(_ => _.ToString()).By(_ => String.Join("\n", _)).By(Output.WriteLine);
// Output.WriteLine("=====================");
//}
//Output.WriteLine($"Total method num: {num}");
var swig_code = FFI.MetaGen.code_gen.code_gen("", all_verbs);
Output.WriteLine(swig_code);
}
[Fact]
public void TestOnlyCellRootSwigGen()
{
var ty_descs = Schema.CellDescriptors.Select(TypeSystem.Make);
var all_type_collected = FFI.MetaGen.analyzer.collect_type(ty_descs);
foreach (var e in all_type_collected)
{
Output.WriteLine(e.TypeName);
}
Output.WriteLine("=====================");
var all_verbs = FFI.MetaGen.analyzer.generate_chaining_verb(all_type_collected);
//var num = 0;
//foreach (var e in all_verbs)
//{
// //var len = e.Item2.Length;
// //Output.WriteLine($"{e.Item1.TypeName}, method num: {len}");
// //num += len;
// e.Item2.Select(_ => _.ToString()).By(_ => String.Join("\n", _)).By(Output.WriteLine);
// Output.WriteLine("=====================");
//}
//Output.WriteLine($"Total method num: {num}");
var swig_code = FFI.MetaGen.Factory.code_gen("", all_verbs);
Output.WriteLine(swig_code);
}
public void Dispose()
{
Global.Uninitialize();
}
[Fact]
public void TestSwigGen()
{
var swig = MetaGen.GenerateSwig(ManglingCode).Invoke(Schema);
swig
.Each(_ =>
_.Item2
.Each(swigCodeGetter =>
swigCodeGetter
.Item2
.Invoke("0x00")
.By(Output.WriteLine)));
}
[Fact]
public void TestCSharpGen()
{
var csharp = MetaGen.GenerateCSharp(ManglingCode).Invoke(Schema);
csharp
.Take(2)
.Each(
_ => _.Item2.Take(2).Each(nested =>
{
var (fnName, Code) = nested;
Output.WriteLine($"Get function address by calling this one: {fnName}");
Output.WriteLine(Code);
}));
}
[Fact]
public void TestJitGen()
{
var jit = MetaGen.GenerateJit(ManglingCode).Invoke(Schema);
jit
.Take(2)
.Each(
for_each_type =>
for_each_type.Item2
.Take(2)
.Each(x => $"{{Type: {x.DeclaringType.TypeName}; Verb: {x.Verb.ToString()}}}".By(Output.WriteLine))
);
}
[Fact]
public void TestJitRun()
{
int _foo, foo = 1;
var c1 = Global.LocalStorage.NewGenericCell(1, "C1");
c1.SetField("foo", foo);
Global.LocalStorage.SaveGenericCell(c1.CellId, c1);
using (var s = Global.LocalStorage.UseGenericCell(c1.CellId))
{
Output.WriteLine(s.GetField<string>("foo"));
}
{
var acc = Helper.LockCell(c1.CellId);
var jit = MetaGen.GenerateJit(ManglingCode).Invoke(Schema);
jit.Each(x =>
Output.WriteLine(
$"{x.Item1.TypeName}: {x.Item2.Select(fnDesc => fnDesc.Verb.ToString()).By(all => String.Join('\n', all))}"));
var fnDescs =
jit
.Where(_ => _.Item1.TypeName.Equals("C1"))
.First()
.By(type_and_fields => type_and_fields.Item2);
var get_foo_from_c1 =
fnDescs
.Where(v => v.Verb is Verbs.Verb.ComposedVerb)
.First()
.By(JitCompiler.CompileFunction)
.By(native =>
Marshal.GetDelegateForFunctionPointer(
native.CallSite, typeof(SBGet)));
_foo = (int) get_foo_from_c1.DynamicInvoke(acc);
Output.WriteLine(_foo.ToString());
}
Assert.Equal(_foo, foo);
}
[Fact]
public void TestSwigFileGen()
{
var codeGenerators = MetaGen.CodeGenSwigJit(ManglingCode, Schema);
codeGenerators.Invoke("moduleName").By(Output.WriteLine);
}
[Fact]
public void TestList()
{
var lst = new List<int> { 1, 2, 3 };
var jit = MetaGen.GenerateJit(ManglingCode).Invoke(Schema);
var fnDescs = jit.First(_ => _.Item1.TypeName.StartsWith("List"))
.By(type_and_fields => type_and_fields.Item2);
var get_from_lst_int =
fnDescs
.First(v => v.Verb.Equals(Verbs.Verb.NewComposedVerb(Verbs.Verb.LGet, Verbs.Verb.BGet)))
.By(_ => {
Output.WriteLine(_.Verb.ToString());
return JitCompiler.CompileFunction(_); })
.By(native =>
Marshal.GetDelegateForFunctionPointer(
native.CallSite, typeof(LBGet)));
var count_lst_int =
fnDescs
.First(v => v.Verb.Equals(Verbs.Verb.LCount))
.By(_ => {
Output.WriteLine(_.Verb.ToString());
return JitCompiler.CompileFunction(_);
})
.By(native =>
Marshal.GetDelegateForFunctionPointer(
native.CallSite, typeof(LCount)));
Helper.ListToNativeAndThen(
lst,
subject =>
{
var list_1 = (int)get_from_lst_int.DynamicInvoke(subject, 1);
var list_len = (int)count_lst_int.DynamicInvoke(subject);
Output.WriteLine("list[1]=" + list_1.ToString());
Output.WriteLine("list length =" + list_len.ToString());
Assert.Equal(list_1, lst[1]);
Assert.Equal(list_len, lst.Count());
return 0;
});
}
}
}

Просмотреть файл

@ -1,27 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GraphEngine.Core" Version="2.0.9328" />
<PackageReference Include="GraphEngine.Jit" Version="2.0.9328" />
<PackageReference Include="GraphEngine.Storage.Composite" Version="2.0.9328" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
<PackageReference Include="xunit" Version="2.3.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Trinity.FFI.Metagen\Trinity.FFI.Metagen.fsproj" />
</ItemGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,11 +0,0 @@
struct S
{
int32 i;
string s;
}
cell C
{
int32 i;
List<S> ls;
S s;
}

Просмотреть файл

@ -1,256 +0,0 @@
namespace Trinity.FFI.Metagen
module CSharpGen =
open Trinity.FFI.Metagen.CommonForRender
open Trinity.FFI.Metagen.Operator
open GraphEngine.Jit.Verbs
open GraphEngine.Jit.TypeSystem
open System
type Name = string
type Code = string
type FunctionAddrGetterName = string
type ManglingCode = char
let render (manglingCode : ManglingCode)
(name'maker : ManglingCode -> TypeDescriptor -> Name)
(subject : TypeDescriptor)
(verb : Verb) : FunctionAddrGetterName * Code =
let subject'name = name'maker manglingCode subject
let subject'type = subject |> TypeName
let getObjectInfo (object: TypeDescriptor) =
let object'name = name'maker manglingCode object
let object'type = object |> TypeName
let Pritimive = isPrimitive object.TypeCode
let arg'type = if Pritimive then object'type else "void*"
let operationSig = PString.format "{subject name}{_}{object name}"
[
"subject name" ->> subject'name;
"_" ->> manglingCode;
"object name" ->> object'name
]
(object'name, object'type, Pritimive, arg'type, operationSig)
(** Although do pattern matching twice when it's a struct, the code is less.
CodeGen doesn't cost much so we just try a more readable way.
**)
let (object'name, object'type, Pritimive, arg'type, operationSig) =
if
subject.TypeCode = LIST
then
subject |> getElemTypeFromSubject |> getObjectInfo
else
match verb with
| SGet fieldName
| SSet fieldName ->
subject |> getMemberTypeFromSubject fieldName |> getObjectInfo
| _ -> failwith "Impossible."
match verb with
| LGet ->
let toFnName = fun head ->
PString.format "{0}{_}{1}{_}{2}"
["_" ->> manglingCode; "0" ->> head; "1" ->> operationSig; "2" ->> "Get"]
let RHS = if Pritimive then "src[idx]" else "GCHandle.ToIntPtr(GCHandle.Alloc(src[idx])).ToPointer()"
let RET = sprintf "@object = %s" RHS
"
public delegate void {DELE}(void* subject, int idx, out {arg type} @object);
public static void {FUNC}(void* subject, int idx, out {arg type} @object)
{{
var src = ({subject type}) GCHandle.FromIntPtr((IntPtr)subject).Target;
{RET};
}}
public static {DELE} {INST} = {FUNC};
public static int {ADDR} => Marshal.GetFunctionPointerForDelegate({INST}).ToInt32();
"
|> fun it -> (it, toFnName, RET)
| LSet ->
let toFnName = fun head ->
PString.format "{0}{_}{1}{_}{2}"
["_" ->> manglingCode; "0" ->> head; "1" ->> operationSig; "2" ->> "Set"]
let RHS = if Pritimive then "@object" else sprintf "((%s)GCHandle.FromIntPtr((IntPtr)@object).Target)" object'type
let RET = sprintf "src[idx] = %s" RHS
"
public delegate void {DELE}(void* subject, int idx, {arg type} @object);
public static void {FUNC}(void* subject, int idx, {arg type} @object)
{{
var src = ({subject type}) GCHandle.FromIntPtr((IntPtr)subject).Target;
{RET};
}}
public static {DELE} {INST} = {FUNC};
public static int {ADDR} => Marshal.GetFunctionPointerForDelegate({INST}).ToInt32();
"
|> fun it -> (it, toFnName, RET)
| LInlineGet idx ->
let toFnName = fun head ->
PString.format "{0}{_}{1}{_}{2}"
["_" ->> manglingCode; "0" ->> head; "1" ->> operationSig; "2" ->> "Get"]
let RHS = sprintf (if Pritimive then "src[%d]" else "GCHandle.ToIntPtr(GCHandle.Alloc(src[%d])).ToPointer()") idx
let RET = sprintf "@object = %s" RHS
"
public delegate void {DELE}(void* subject, out {arg type} @object);
public static void {FUNC}(void* subject, out {arg type} @object)
{{
var src = ({subject type}) GCHandle.FromIntPtr((IntPtr)subject).Target;
{RET};
}}
public static {DELE} {INST} = {FUNC};
public static int {ADDR} => Marshal.GetFunctionPointerForDelegate({INST}).ToInt32();
"
|> fun it -> (it, toFnName, RET)
| LInlineSet idx ->
let toFnName = fun head ->
PString.format "{0}{_}{1}{_}{2}"
["_" ->> manglingCode; "0" ->> head; "1" ->> operationSig; "2" ->> "Set"]
let LHS = sprintf "src[%d]" idx
let RHS = if Pritimive then "@object" else sprintf "((%s)GCHandle.FromIntPtr((IntPtr)@object).Target)" object'type
let RET = sprintf "%s = %s" LHS RHS;
"
public delegate void {DELE}(void* subject, {arg type} @object);
public static void {FUNC}(void* subject, {arg type} @object)
{{
var src = ({subject type}) GCHandle.FromIntPtr((IntPtr)subject).Target;
{RET};
}}
public static {DELE} {INST} = {FUNC};
public static int {ADDR} => Marshal.GetFunctionPointerForDelegate({INST}).ToInt32();
"
|> fun it -> (it, toFnName, RET)
| LCount ->
let toFnName = fun head ->
PString.format "{0}{_}{1}{_}{2}"
["_" ->> manglingCode; "0" ->> head; "1" ->> operationSig; "2" ->> "LCount"]
let RET = "return src.Count()"
"
public delegate int {DELE}(void* subject);
public static int {FUNC}(void* subject)
{{
var src = ({subject type}) GCHandle.FromIntPtr((IntPtr)subject).Target;
{RET};
}}
public static {DELE} {INST} = {FUNC};
public static int {ADDR} => Marshal.GetFunctionPointerForDelegate({INST}).ToInt32();
"
|> fun it -> (it, toFnName, RET)
| LContains ->
let toFnName = fun head ->
PString.format "{0}{_}{1}{_}{2}"
["_" ->> manglingCode; "0" ->> head; "1" ->> operationSig; "2" ->> "Contains"]
let ELEM = if Pritimive then "@object" else sprintf "((%s)GCHandle.FromIntPtr((IntPtr)@object).Target)" object'type
let RET = sprintf "return src.Contains(%s)? 1 : 0" ELEM
"
public delegate int {DELE}(void* subject, {arg type} @object);
public static int {FUNC}(void* subject, {arg type} @object)
{{
var src = ({subject type}) GCHandle.FromIntPtr((IntPtr)subject).Target;
{RET};
}}
public static {DELE} {INST} = {FUNC};
public static int {ADDR} => Marshal.GetFunctionPointerForDelegate({INST}).ToInt32();
"
|> fun it -> (it, toFnName, RET)
| SGet fieldName ->
let toFnName = fun head -> PString.format "{0}{_}{1}{_}{2}_{3}"
[
"_" ->> manglingCode;
"0" ->> head;
"1" ->> operationSig;
"2" ->> "Get";
"3" ->> fieldName
]
let LHS = "@object"
let RHS = sprintf (if Pritimive then "src.%s" else "GCHandle.ToIntPtr(GCHandle.Alloc(src.%s)).ToPointer()") fieldName
let RET = sprintf "%s = %s" LHS RHS;
"
public delegate void {DELE}(void* subject, out {arg type} @object);
public static void {FUNC}(void* subject, out {arg type} @object)
{{
var src = ({subject type}) GCHandle.FromIntPtr((IntPtr)subject).Target;
{RET};
}}
public static {DELE} {INST} = {FUNC};
public static int {ADDR} => Marshal.GetFunctionPointerForDelegate({INST}).ToInt32();
"
|> fun it -> (it, toFnName, RET)
| SSet fieldName ->
let toFnName = fun head -> PString.format "{0}{_}{1}{_}{2}_{3}"
[
"_" ->> manglingCode;
"0" ->> head;
"1" ->> operationSig;
"2" ->> "Set";
"3" ->> fieldName
]
let LHS = sprintf "src.%s" fieldName
let RHS = if Pritimive then "@object" else sprintf "((%s)GCHandle.FromIntPtr((IntPtr)@object).Target)" object'type
let RET = sprintf "%s = %s" LHS RHS;
"
public delegate void {DELE}(void* subject, out {arg type} @object);
public static void {FUNC}(void* subject, out {arg type} @object)
{{
var src = ({subject type}) GCHandle.FromIntPtr((IntPtr)subject).Target;
{RET};
}}
public static {DELE} {INST} = {FUNC};
public static int {ADDR} => Marshal.GetFunctionPointerForDelegate({INST}).ToInt32();
"
|> fun it -> (it, toFnName, RET)
| _ -> raise (NotImplementedException())
|>fun(template, toFnName, RET) ->
let FUNC = toFnName "FUNC"
let DELE = toFnName "DELE"
let INST = toFnName "INST"
let ADDR = toFnName "ADDR"
let renderMap =
[
"FUNC" ->> FUNC
"DELE" ->> DELE
"INST" ->> INST
"ADDR" ->> ADDR
"RET" ->> RET
"arg type" ->> arg'type
"subject type" ->> subject'type
]
(ADDR, PString.format template renderMap)

Просмотреть файл

@ -1,143 +0,0 @@
namespace Trinity.FFI.Metagen
module CodeGen =
open Trinity.FFI.Metagen.CommonForRender
open Trinity.FFI.Metagen.Operator
open GraphEngine.Jit.Verbs
open GraphEngine.Jit.TypeSystem
open GraphEngine.Jit.JitCompiler
open System
type Path = string // Path implementation might be changed
type Code = string
type FunctionAddr = uint32
type FunctionIdentity = string
type Name = string
type FunctionId = string
type TypeStr = string
type ManglingChar = char
type FunctionDecl = string
//let ProjectGenerate (namespace': Path)
// (referencePaths: seq<Path>)
// (projectDirector: Path)
// (operationCodes: Code) : Map<FunctionIdentity, FunctionAddr> =
// (**
// <Description>
// After loading some TSL extensions, vast operation generators are generated
// in memory storage in case of users' applications.
// Once a user call an operation(exported lazily as a function),
// a. if this operation has not been generated yet,
// - we will build the corresponding operation generator and give the generated one(an operation) to that user.
// - goto b
// b. if this operation has already been generated,
// - call the generated operation as the user expected.
// </Description>
// <Params>
// namespace' : the namespace of generated c# proj.
// referencePath : dll references of current TSL extension.
// projectDirector : the root dir of generated dll.
// operationCodes : codes for data manipulations. => Target
// </Params>
// **)
//raise (NotImplementedException())
let generateSwigFile
(manglingCode : ManglingChar)
(name'maker : ManglingChar -> TypeDescriptor -> Name)
(spec : seq<TypeDescriptor * seq<FunctionDescriptor*(FunctionDecl * (FunctionId -> Code))>>) =
let use_newobj = new System.Collections.Generic.List<string>()
let rec reducer (seqs) (definitions: list<FunctionDecl>) (sources: list<Code>) =
match seqs with
| (subject: TypeDescriptor, fields: seq<FunctionDescriptor*(FunctionDecl * (FunctionId -> Code))>) :: tail ->
let (defs, srcs) = fields |> Seq.map (fun (toCompile, (fnDecl, codeMaker)) ->
//let concrete_verb =
// match toCompile.Verb with
// | SGet x -> ComposedVerb(SGet x, BGet)
// | SSet x -> ComposedVerb(SSet x, BSet)
// | x -> x
sprintf "0x%xll" ((CompileFunction toCompile).CallSite.ToInt64())
|> codeMaker
|> fun it -> (fnDecl, it))
|> List.ofSeq
|> List.unzip
let extended'definitions = definitions|> List.append defs
let extended'sources = sources |> List.append srcs
let subject'name = name'maker manglingCode subject
match subject.TypeCode with
| CELL _ ->
let func_name = sprintf "Use%c%s" manglingCode subject'name
let decl_head = sprintf "CellAccessor* %s(int64_t cellid, int32_t options)" func_name
use_newobj.Add("%newobject " + func_name + ";")
let src = sprintf "
%s
{
CellAccessor* accessor = new CellAccessor();
accessor->cellId = cellid;
auto errCode = LockCell(*accessor, options);
if (errCode)
throw errCode;
return accessor;
}
" decl_head
reducer tail ((sprintf "%s;" decl_head)::extended'definitions) (src::extended'sources)
| _ ->
reducer tail extended'definitions extended'sources
| _ ->
List.rev definitions, List.rev sources
let (decls, srcs) = reducer (List.ofSeq spec) [] []
fun (moduleName: Name) ->
"
%module {moduleName}
%include <stdint.i>
%{{
#include \"swig_accessor.h\"
#include \"CellAccessor.h\"
#define SWIG_FILE_WITH_INIT
typedef void* (*Inst{_}Constructor)(CellAccessor*);
{source}
%}}
{decl}
{use_newobj}
"
|> fun template ->
PString.format template
[
"_" ->> manglingCode
"moduleName" ->> moduleName
"source" ->> (srcs |> PString.str'concatBy "\n" )
"decl" ->> (decls |> PString.str'concatBy "\n")
"use_newobj" ->> (use_newobj |> PString.str'concatBy "\n")
]

Просмотреть файл

@ -1,33 +0,0 @@
namespace Trinity.FFI.Metagen
open GraphEngine.Jit.Verbs
open GraphEngine.Jit.TypeSystem
open Trinity.FFI.Metagen.Operator
module CommonForRender =
let rec TypeName (t: TypeDescriptor) =
match t.TypeCode with
| LIST -> sprintf "List<%s>" (t.ElementType |> Seq.head |> TypeName)
| _ -> t.TypeName
let getMemberTypeFromSubject (memberName: string) (subject: TypeDescriptor) =
subject.Members
|> Seq.filter (fun it -> it.Name.Equals memberName)
|> Seq.head
|> fun it -> it.Type
let getElemTypeFromSubject (subject: TypeDescriptor) =
subject.ElementType |> Seq.head
let getObjectFromSubjectAndVerb (subject: TypeDescriptor) (verb: Verb) =
if
subject.TypeCode = LIST
then
subject |> getElemTypeFromSubject
else
match verb with
| ComposedVerb (SGet fieldName, BGet)
| SGet fieldName
| SSet fieldName ->
subject |> getMemberTypeFromSubject fieldName
| _ -> failwith "Impossible."

Просмотреть файл

@ -1,26 +0,0 @@
namespace Trinity.FFI.Metagen
module JitGen =
open GraphEngine.Jit.Verbs
open GraphEngine.Jit.TypeSystem
open GraphEngine.Jit.JitNativeInterop
open Trinity.Storage
open System
open Trinity.FFI.Metagen.Operator
open GraphEngine.Jit
open Microsoft.FSharp.NativeInterop
type ManglingCode = char
type Name = string
let render (manglingCode : ManglingCode)
(name'maker : ManglingCode -> TypeDescriptor -> Name)
(subject : TypeDescriptor)
(verb : Verb) : FunctionDescriptor =
{DeclaringType=subject; Verb=verb}

Просмотреть файл

@ -1,116 +0,0 @@
namespace Trinity.FFI.Metagen
open Trinity.FFI.Metagen
module MetaGen =
open GraphEngine.Jit
open GraphEngine.Jit.Verbs
open GraphEngine.Jit.TypeSystem
open System
open Trinity.Storage
open Trinity.FFI.Metagen.Operator
type SwigCode = string
type CodeGenerator = (string -> string)
let mangling (manglingCode: char) (name: string) = name.Replace(manglingCode, manglingCode + manglingCode)
let rec make'name (manglingCode: char) (desc: TypeDescriptor) =
(** transform a typedescriptor into a name signature
eg. List<List<int>> ->
List_List_int (if `_` is the mangling code
List<My_Struct> ->
List_My__Struct(if `_` is the mangling code
**)
let m_mangling = mangling manglingCode
match desc with
| {TypeCode=LIST; ElementType=elemType} ->
let elemTypeName = elemType |> Seq.head |> (make'name manglingCode)
PString.format "List{_}{elem}" ["_" ->> manglingCode; "elem" ->> elemTypeName]
| {TypeCode=CELL _; TypeName=cellName} ->
PString.format "Cell{_}{cellName}" ["_" ->> manglingCode; "cellName" ->> m_mangling cellName]
| {TypeCode=STRUCT; TypeName=structName} ->
PString.format "Struct{_}{structName}" ["_" ->> manglingCode; "structName" ->> m_mangling structName]
| _ ->
desc.TypeName.ToLower() // primitive type
let render'operations (render : TypeDescriptor -> Verb -> 'T ) (type': TypeDescriptor) : seq<'T> =
match type' with
| {TypeCode=CELL _; Members=members}
| {TypeCode=STRUCT; Members=members} ->
members
|> Seq.collect (
fun (member': MemberDescriptor) ->
let fieldName = member'.Name
SGet fieldName
|> fun it -> if isPrimitive member'.Type.TypeCode then ComposedVerb(it, BGet) else it
|> fun it -> [it; SSet fieldName;]
|> Seq.map (render type'))
| {TypeCode=LIST;ElementType=elemTypes} ->
LGet
|> fun it -> if (elemTypes |> Seq.head |> fun x -> isPrimitive x.TypeCode) then ComposedVerb (it, BGet) else it
|> fun it -> it::[LSet; LContains; LCount; LInsertAt; LRemoveAt; LAppend;]
|> Seq.map (render type')
| _ ->
(** primitive type **)
raise (NotImplementedException())
|> fun tail -> [BGet; BSet; BNew] |> Seq.map (render type') |> Seq.append tail
let rec TypeInfer(anyType: TypeDescriptor): seq<TypeDescriptor> =
(** inference out the descriptors of struct types and generic list types in a cell descriptor.**)
match anyType with
| {TypeCode=LIST; ElementType = elemType} ->
anyType >>> TypeInfer (Seq.head elemType)
| {TypeCode=CELL _; Members=members}
| {TypeCode=STRUCT; Members=members} ->
members
|> Seq.collect (fun field -> field.Type |> TypeInfer)
|> fun tail -> anyType >>> tail
| _ ->
(** primitive type **)
Seq.empty
let Generate (render : TypeDescriptor -> Verb -> 'T)
(schema : IStorageSchema)
: seq<TypeDescriptor * seq<'T>> =
schema.CellDescriptors
|> Seq.map Make
|> Seq.collect TypeInfer
|> Seq.distinctBy (fun typeDesc -> typeDesc.QualifiedName)
|> Seq.map (fun typeDesc ->
typeDesc
|> render'operations render
|> fun methods -> (typeDesc, methods))
let GenerateSwig (manglingCode: char) = SwigGen.render manglingCode make'name |> Generate
let GenerateCSharp (manglingCode: char) = CSharpGen.render manglingCode make'name |> Generate
let GenerateJit (manglingCode: char) = JitGen.render manglingCode make'name |> Generate
let GenerateSwigJit (manglingCode: char) =
let swig = SwigGen.render manglingCode make'name
let jit = JitGen.render manglingCode make'name
let new'render (type': TypeDescriptor) (verb: Verb) =
let swig'result = swig type' verb
let jit'result = jit type' verb
jit'result, swig'result
Generate new'render
open Trinity.FFI.Metagen.CodeGen
let CodeGenSwigJit (manglingCode: char) (schema: IStorageSchema)=
GenerateSwigJit manglingCode schema
|> CodeGen.generateSwigFile manglingCode make'name

Просмотреть файл

@ -1,194 +0,0 @@
namespace Trinity.FFI.Metagen
module SwigGen =
open Trinity.FFI.Metagen.CommonForRender
open Trinity.FFI.Metagen.Operator
open GraphEngine.Jit.Verbs
open GraphEngine.Jit.TypeSystem
open System
type Name = string
type Code = string
type FunctionId = string
type TypeStr = string
type ManglingChar = char
type FunctionDecl = string
let swig'typestr'mapper (typeDesc: TypeDescriptor) =
match typeDesc.TypeCode with
| NULL -> "void"
| U8 -> "uint8_t"
| U16 -> "uint16_t"
| U32 -> "uint32_t"
| U64 -> "uint64_t"
| I8 -> "int8_t"
| I16 -> "int16_t"
| I32 -> "int32_t"
| I64 -> "int64_t"
| F32 -> "float"
| F64 -> "double"
| BOOL -> "bool"
| CHAR -> "char"
| STRING -> "char*"
| U8STRING -> "wchar*"
| _ -> "void*"
let render (manglingCode : ManglingChar)
(name'maker : ManglingChar -> TypeDescriptor -> Name)
(subject : TypeDescriptor)
(verb : Verb)
: FunctionDecl * (FunctionId -> Code) =
let mutable decl: string = null
let subject'name = name'maker manglingCode subject
let object'type =
match verb with
| BNew
| BSet
| BGet -> String.Empty
| _ -> swig'typestr'mapper (getObjectFromSubjectAndVerb subject verb)
let TemplateArgs = ["object type" ->> object'type; "subject name" ->> subject'name; "_" ->> manglingCode]
let render'filter = fun (lst: list<char>) -> lst.Head <> '!'
match verb with
| BNew ->
decl <- "static void* New{_}{subject name}();"
"static Inst{_}Constructor {_}New{_}{subject name} = (Inst{_}Constructor) {!fn addr};" +/
"static void* New{_}{subject name}()" +/
"{{" +/
" CellAccessor* accessor = new CellAccessor();" +/
" auto errCode = {_}New{_}{subject name}(accessor);"+/
" if(errCode)" +/
" throw errCode;"+/
" return accessor;" +/
"}}"
(** BSet/BGet works for cell **)
| BGet ->
decl <- "static void* Get{_}{subject name}(void *);"
"static void* (* {_}Get{_}{subject name})(void*) = (void* (*)(void*)){!fn addr};" +/
"static void* Get{_}{subject name}(void *subject)" +/
"{{" +/
" return {_}Get{_}{subject name}(subject);" +/
"}}"
| BSet ->
decl <- "static void Set{_}{subject name}(void*, void*);"
"static void (* {_}Set{_}{subject name})(void*, void*) = (void (*)(void*, void*)){!fn addr};" +/
"static void Set{_}{subject name}(void* subject, void* object)" +/
"{{" +/
" return {_}Set{_}{subject name}(subject, cast_object(object));" +/
"}}"
| ComposedVerb (LGet, BGet)
| LGet ->
decl <- PString.format "static {object type} {subject name}{_}Get(void*, int);" TemplateArgs
"static {object type} (* {_}{subject name}{_}Get)(void*, int) = ({object type} (*)(void*, int)){!fn addr};" +/
"static {object type} {subject name}{_}Get(void* subject, int idx)" +/
"{{" +/
" return {_}{subject name}{_}Get(subject, idx);" +/
"}}"
| LSet ->
decl <- PString.format "static void {subject name}{_}Set(void*, int, {object type});" TemplateArgs
"static void (* {_}{subject name}{_}Set)(void*, int, {object type}) = (void (*)(void*, int, {object type} object)){!fn addr};" +/
"static void {subject name}{_}Set(void* subject, int idx, {object type} object)" +/
"{{" +/
"return {_}{subject name}{_}Set(subject, idx, cast_object(object));" +/
"}}"
| LCount ->
decl <- PString.format "static int Count{_}{subject name}(void* subject);" TemplateArgs;
"static int (* {_}Count{_}{subject name})(void*) = (int (*)(void* )) {!fn addr};" +/
"static int Count{_}{subject name}(void* subject)" +/
"{{" +/
" return {_}Count{_}{subject name}(subject);"+/
"}}"
| LContains ->
decl <- PString.format "static bool Contains{_}{subject name}(void*, {object type});" TemplateArgs;
"static bool (* {_}Contains{_}{subject name})(void*, {object type}) = (bool (*)(void*, {object type})) {!fn addr};" +/
"static bool Contains{_}{subject name}(void* subject, {object type} object)" +/
"{{" +/
" return {_}Contains{_}{subject name}(subject, cast_object(object));" +/
"}}"
| LInsertAt ->
decl <- PString.format "static bool Insert{_}{subject name}(void*, int, {object type});" TemplateArgs
"static bool (* {_}Insert{_}{subject name})(void*, int, {object type}) = (bool (*)(void*, int, {object type})) {!fn addr};"+/
"static bool Insert{_}{subject name}(void* subject, int idx, {object type} object)" +/
"{{" +/
" return {_}Insert{_}{subject name}(subject, idx, cast_object(object));"+/
"}}"
| LRemoveAt ->
decl <- PString.format "static bool Remove{_}{subject name}(void*, int);" TemplateArgs
"static bool (* {_}Remove{_}{subject name})(void*, int) = (bool (*)(void*, int)) {!fn addr};" +/
"static bool Remove{_}{subject name}(void* subject, int idx)"+/
"{{"+/
" return {_}Remove{_}{subject name}(subject, idx);"+/
"}}"
| LAppend ->
decl <- PString.format "static void Append{_}{subject name}(void*, {object type});" TemplateArgs
"static void (* {_}Append{_}{subject name})(void*, {object type}) = (void (*)(void*, {object type})) {!fn addr};"+/
"static void Append{_}{subject name}(void* subject, {object type} object)"+/
"{{"+/
" return {_}Append{_}{subject name}(subject, cast_object(object));"+/
"}}"
| ComposedVerb (SGet fieldName, BGet)
| SGet fieldName ->
let fnName = sprintf "{subject name}{_}Get{_}%s" fieldName
decl <- PString.format "static {object type} {fnName}(void*);" ("fnName" ->> fnName ::TemplateArgs);
"static {object type} (* {_}{:fnName})(void*) = ({object type} (*)(void*)){!fn addr};" +/
"static {object type} {:fnName}(void* subject)" +/
"{{" +/
" return {_}{:fnName}(subject);" +/
"}}"
|> fun template -> PString.format'cond (fun lst -> lst.Head = ':') template [":fnName" ->> fnName]
| SSet fieldName ->
let fnName = sprintf "{subject name}{_}Set{_}%s" fieldName
decl <- PString.format "static void {fnName}(void*, {object type});" ("fnName" ->> fnName ::TemplateArgs);
"static void (* {_}{:fnName})(void*, {object type}) = (void (*)(void*, {object type})){!fn addr};" +/
"static void {:fnName}(void* subject, {object type} object)" +/
"{{" +/
" return {_}{:fnName}(subject, cast_object(object));" +/
"}}"
|> fun template -> PString.format'cond (fun lst -> lst.Head = ':') template [":fnName" ->> fnName]
| _ -> raise (NotImplementedException())
|> fun template -> PString.format'cond render'filter template TemplateArgs
|> fun template -> (PString.format decl TemplateArgs, fun fnAddr -> PString.format template ["!fn addr" ->> fnAddr])

Просмотреть файл

@ -1,53 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netstandard2.0;net461</TargetFrameworks>
</PropertyGroup>
<PropertyGroup>
<AssemblyName>Trinity.FFI.Metagen</AssemblyName>
<RootNamespace>Trinity.FFI.Metagen</RootNamespace>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<IsPackable>true</IsPackable>
<OutputType>Library</OutputType>
<NoWarn>62</NoWarn>
<PackageId>GraphEngine.FFI.Metagen</PackageId>
<Authors>Microsoft Graph Engine Team</Authors>
<Company>Microsoft Corporation</Company>
<Product>GraphEngine.FFI.Metagen</Product>
<Description>Dynamically generate GraphEngine foreign function interfaces for various runtimes and programming languages.</Description>
<PackageRequireLicenseAcceptance>true</PackageRequireLicenseAcceptance>
<PackageProjectUrl>https://www.graphengine.io</PackageProjectUrl>
<PackageIconUrl>https://www.graphengine.io/img/logo-64x64.png</PackageIconUrl>
<PackageLicenseUrl>https://github.com/Microsoft/GraphEngine/blob/master/LICENSE.md</PackageLicenseUrl>
<Copyright>Copyright 2018</Copyright>
<Version>2.0.9328</Version>
<RepositoryUrl>https://github.com/Microsoft/GraphEngine/</RepositoryUrl>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<Compile Include="Utils.fs" />
<!-- Generation -->
<Compile Include="CommonForRender.fs" />
<Compile Include="SwigGen.fs" />
<Compile Include="CSharpGen.fs" />
<Compile Include="JitGen.fs" />
<Compile Include="CodeGen.fs" />
<Compile Include="MetaGen.fs" />
<Compile Include="analyzer.fs" />
<Compile Include="code_gen.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="GraphEngine.Core" Version="2.0.9328" />
<PackageReference Include="GraphEngine.Jit" Version="2.0.9328" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,208 +0,0 @@
namespace Trinity.FFI.Metagen
open System.IO
module Operator =
let (->>) (key: string) (value: 'T) = (key, value.ToString())
let (>>>) (head: 'T) (tail: seq<'T>) = Seq.append (head |> Seq.singleton) tail
let (<^.^^>) (left: 'T) (right: 'G) = (left, right)
let (<^^.^>) (right: 'T) (left: 'G) = (left, right)
let inline (+/) (left: string) (right: string) = left + "\n" + right
module PString =
(** python like string utilities **)
open System
let (|Prefix|_|) (p : string) (s : string) =
if s.StartsWith(p) then Some(s.Substring(p.Length))
else None
type StrOrChr =
| Chr of char
| Str of string
let str'concat (xs : seq<'T>) = String.Join("", xs)
let str'concatBy (sep: string) (xs: seq<'T>) = String.Join(sep, xs)
let rev'concat (xs : seq<'T>) =
xs
|> Seq.rev
|> str'concat
let rec format'root (template : List<char>) (result : List<string>) (kvpairs : Map<string, string>)
(cache : List<char>) : string =
match template with
| '{' :: '{' :: tail -> format'root tail result kvpairs ('{' :: cache)
| '{' :: tail ->
if cache.IsEmpty
then
format'render tail result kvpairs []
else
format'render tail ((cache |> rev'concat) :: result) kvpairs []
| '\\' :: chr :: tail -> format'root tail result kvpairs (chr :: cache)
| '}' :: '}' :: tail -> format'root tail result kvpairs ('}' :: cache)
| '}' :: _ -> failwith "missing pair parentheses."
| chr :: tail -> format'root tail result kvpairs (chr :: cache)
| [] ->
if cache.IsEmpty
then
result |> rev'concat
else
(cache |> rev'concat) :: result |> rev'concat
and format'render (chrs : List<char>) (result : List<string>) (kvpairs : Map<string, string>) (name : List<char>) =
match chrs with
| '}' :: tail ->
if name.IsEmpty
then
failwith "empty name cannot be render."
else
name
|> rev'concat
|> kvpairs.TryFind
|> (fun some ->
if some.IsNone
then
failwith (sprintf "unexpected keyword args (%s)" (name |> rev'concat))
else
some.Value)
|> (fun value -> format'root tail (value :: result) kvpairs [])
| chr :: tail -> format'render tail result kvpairs (chr :: name)
| _ -> failwith "unsolved error."
let rec format'root'cond (predicate: list<char> -> bool) (template : List<char>) (result : List<string>) (kvpairs : Map<string, string>)
(cache : List<char>) : string =
match template with
| '{' :: '{' :: tail -> format'root'cond predicate tail result kvpairs ('{' :: '{' :: cache)
| '{' :: tail ->
if cache.IsEmpty
then
format'render'cond predicate tail result kvpairs []
else
format'render'cond predicate tail ((cache |> rev'concat) :: result) kvpairs []
| '\\' :: chr :: tail -> format'root'cond predicate tail result kvpairs ('\\' :: chr :: cache)
| '}' :: '}' :: tail -> format'root'cond predicate tail result kvpairs ('}' :: '}' :: cache)
| '}' :: _ -> failwith "missing pair parentheses."
| chr :: tail -> format'root'cond predicate tail result kvpairs (chr :: cache)
| [] ->
if cache.IsEmpty
then
result |> rev'concat
else
(cache |> rev'concat) :: result |> rev'concat
and format'render'cond (predicate: list<char> -> bool) (chrs : List<char>) (result : List<string>) (kvpairs : Map<string, string>) (name : List<char>) =
match chrs with
| '}' :: tail ->
if name.IsEmpty
then
failwith "empty name cannot be render."
elif name |> List.rev |> predicate
then
name
|> rev'concat
|> kvpairs.TryFind
|> (fun some ->
if some.IsNone
then
failwith (sprintf "unexpected keyword args (%s)" (name |> rev'concat))
else
some.Value)
|> (fun value -> format'root'cond predicate tail (value :: result) kvpairs [])
else
let value = "{" + (name |> rev'concat) + "}"
format'root'cond predicate tail (value :: result) kvpairs []
| chr :: tail -> format'render'cond predicate tail result kvpairs (chr :: name)
| _ -> failwith "unsolved error."
let format (template : string) (kvpairs : seq<string * string>) : string =
format'root (template.ToCharArray() |> List.ofArray) [] (Map.ofSeq kvpairs) []
let format'cond (predicate: list<char> -> bool) (template : string) (kvpairs : seq<string *string>) : string =
format'root'cond predicate (template.ToCharArray() |> List.ofArray) [] (Map.ofSeq kvpairs) []
module Command =
(**
A default implementation of Command Line Parser.
**)
open PString
type Argument =
| Optional of string
| KeyValue of string * string
| Varadic of List<string>
type ArgInfo =
| On
| Off
| Varargs of List<string>
| Value of string
let rec extract (args : List<string>) : List<Argument> =
match args with
| (Prefix "--" head) :: tail -> optionalExtract (head :: tail)
| (Prefix "-" head) :: tail -> keyValueExtract (head :: tail)
| head :: tail -> varadicExtract tail (Varadic [ head ])
| [] -> []
and optionalExtract (head :: tail) : List<Argument> = (Optional head) :: (extract tail)
(**
The pattern must match `head::tail`
because `optionalExtract` is called within only this case.
**)
and keyValueExtract args : List<Argument> =
match args with
| key :: value :: tail -> (KeyValue(key, value)) :: (extract tail)
| _ -> failwith "unrecognized keyvalue argument"
and varadicExtract (args : List<string>) ((Varadic lst) as varargs) : List<Argument> =
(**
Just like `optionalExtract`,
the pattern must match `Varadic lst`. It's only called in this case.
**)
match args with
| (Prefix "--" head) :: tail -> varargs :: (optionalExtract (head :: tail))
| (Prefix "-" head) :: tail -> varargs :: (keyValueExtract (head :: tail))
| arg :: tail -> varadicExtract tail (Varadic(arg :: lst))
| [] -> [ varargs ]
| _ -> failwith "unknown exception"
let parse (args : string []) : Map<string, ArgInfo> =
Map.ofList (List.map (fun arg ->
match arg with
| Optional str -> (str, On)
| KeyValue(k, v) -> (k, Value v)
| Varadic many -> ("varadic", Varargs many)) (extract (args |> List.ofArray)))
module IO =
let exists filename = filename |> File.Exists
let write filename content = File.WriteAllText(filename, content)
let readlines filename = File.ReadAllLines(filename)
let read filename = File.ReadAllText(filename)
//
//module Main =
//
// [<EntryPoint>]
// let main (argv: string[]) =
// let myMap = Map.ofList [("1", "number1") ; ("2", "number2"); ("qwe???", "")]
// let s = PString.format "{1} some some some; {qwe???} some some some \\{ {2} {{{1}}} some " myMap
// System.Console.WriteLine(s)
// 0

Просмотреть файл

@ -1,183 +0,0 @@
module Trinity.FFI.MetaGen.analyzer
open GraphEngine.Jit.TypeSystem
open GraphEngine.Jit.Verbs
open System
open FSharp.NativeInterop
open FSharp.Data
// ml style naming
type ('k, 'v) hashmap = System.Collections.Generic.Dictionary<'k, 'v>
let _distinctByRef (lst: 'a list) =
(**
for our using case requires nested list comparison by memory address,
but fsharp list module hasn't implemented it yet.
and after a simple test our implementation is much more faster.
- using a list `List.chunkBySize 50 1000`applying
both `List.distinct` and `_distinctByRef`,
```
benchmark (fun () -> List.distinct chunks |> ignore);;
val it : float = 40.3861
benchmark (fun () -> dt chunks |> ignore);;
val it : float = 0.9669
```
where
```
let benchmark (test : unit -> unit) =
let stopWatch = System.Diagnostics.Stopwatch.StartNew()
for i = 1 to 1000 do
test()
stopWatch.Stop()
stopWatch.Elapsed.TotalMilliseconds
```
*)
let rec recur l1 l2 =
match l1 with
| [] -> l2
| x :: xs ->
if l2 |> List.exists (fun it -> obj.ReferenceEquals(it, x))
then recur xs l2
else recur xs (x::l2)
in recur lst []
type 'a List with
static member distinctByRef(this: 'a List) = _distinctByRef this
let find (tb: ('k, 'v) hashmap) (k: 'k) : 'v option =
if tb.ContainsKey(k)
then Some(tb.[k])
else None
let member_type mem = mem.Type
let collect_type (tydescs: TypeDescriptor seq): TypeDescriptor list =
let tb = hashmap() in
let rec recur tydesc =
match find tb tydesc.QualifiedName with
| Some v -> v
| _ ->
let (is_primitive, tail) =
match tydesc with
| {TypeCode = LIST; ElementType = elems} ->
false, elems |> List.ofSeq |> List.collect recur
| {TypeCode = CELL _; Members = membs }
| {TypeCode = STRUCT; Members = membs } ->
false, membs |> List.ofSeq |> List.collect (member_type >> recur)
| _ -> true, []
in if is_primitive then []
else
if tail |> List.contains tydesc
then raise (Exception(tydesc.TypeName |> sprintf "found recursive type `%s`."))
else
let result = tydesc :: tail
tb.[tydesc.QualifiedName] <- result
result
in
Seq.collect recur tydescs |> List.ofSeq |> List.distinctByRef
let generate_chaining_verb(tydescs: TypeDescriptor seq): (TypeDescriptor * (Verb list)) list =
(**
generate the methods for a type owning relationship chain:
e.g
```
cell C{
S s;
int b;
}
struct S{
int a;
int c;
}
```
for [C, S, int]:
we generate following methods:
- for S
* BSet
* BGet
* SSet "a"
* SSet "c"
* ComposedVerb(SGet "a", BGet)
* ComposedVerb(SGet "c", BGet)
- for C
* BSet
* BGet
* SSet "s"
* SGet "s"
* Composed(SGet "s", Composed(SGet "a", BGet))
* Composed(SGet "s", SSet "a")
* Composed(SGet "s", Composed(SGet "c", BGet))
* Composed(SGet "s", SSet "c")
*)
let tb = hashmap() in
let rec recur (tydesc: TypeDescriptor) : Verb list =
match find tb tydesc.QualifiedName with
| Some v -> v
| _ ->
let chaining_methods =
match tydesc with
| {TypeCode = LIST; ElementType = elem} ->
let subs = recur <| Seq.head elem in
LSet ::
LContains::
LCount ::
LInsertAt::
LRemoveAt::
LAppend ::
LGet :: [for sub_verb in subs -> ComposedVerb(LGet, sub_verb)]
| {TypeCode = CELL _; Members = membs}
| {TypeCode = STRUCT; Members = membs} ->
membs |> List.ofSeq
|> List.collect(
fun memb ->
let field = memb.Name
in
let subs = recur memb.Type
in
let sget = SGet field
in
SSet field::sget::
[for sub_verb in subs
-> ComposedVerb(sget, sub_verb)])
| _ -> []
in
let result = BGet::BSet::chaining_methods in
tb.[tydesc.QualifiedName] <- result
result
in
tydescs
|> Seq.map(fun each ->
(each, BNew :: recur each))
|> List.ofSeq

Просмотреть файл

@ -1,335 +0,0 @@

module Trinity.FFI.MetaGen.code_gen
open GraphEngine.Jit.JitCompiler
open GraphEngine.Jit.TypeSystem
open GraphEngine.Jit.Verbs
open System
open Trinity.FFI.Metagen.PString
open Trinity.FFI.Metagen
type hashmap<'k, 'v> = System.Collections.Generic.Dictionary<'k, 'v>
let find (tb : ('k, 'v)hashmap) (k : 'k) : 'v option =
if tb.ContainsKey(k) then Some(tb.[k])
else None
type method_generator = Int64 -> string
type method_declaration = string
type method_code = string
let mangling (name : string) = name.Replace("_", "__")
let rec ty_to_name (recursive_structure : bool) =
function
| { TypeCode = LIST; ElementType = elem } ->
if recursive_structure then
let elem = ty_to_name recursive_structure <| Seq.head elem
sprintf "list_%s" <| elem
else "list"
| { TypeCode = CELL _; TypeName = name } -> sprintf "cell_%s" <| mangling name
| { TypeCode = STRUCT; TypeName = name } -> sprintf "struct_%s" <| mangling name
| { TypeCode = code} -> code.ToString()
let null_type_string = "void"
let ty_to_string tydesc =
match tydesc.TypeCode with
| NULL -> null_type_string
| U8 -> "uint8_t"
| U16 -> "uint16_t"
| U32 -> "uint32_t"
| U64 -> "uint64_t"
| I8 -> "int8_t"
| I16 -> "int16_t"
| I32 -> "int32_t"
| I64 -> "int64_t"
| F32 -> "float"
| F64 -> "double"
| BOOL -> "bool"
| CHAR -> "char"
| STRING -> "wchar_t*"
| U8STRING -> "char*"
| _ -> "void*"
let chaining_verb_to_name (verb : Verb) =
match verb with
| ComposedVerb(l, r) -> sprintf "compose_%A_%A" l r
| SGet field -> sprintf "SGet_%s" field
| SSet field -> sprintf "SSet_%s" field
| _ -> sprintf "%A" verb
type FuncInfo =
{ name_sig : string
pos_arg_types : string list
ret_type : string
verb_str_lst : string list }
let single_method'code_gen (tb : ((string * string), FuncInfo)hashmap) (tydesc : TypeDescriptor) (verb : Verb) : method_declaration * method_generator =
let no_recur_name = ty_to_name false
let recur_name = ty_to_name true
let rec collect (tydesc : TypeDescriptor) verb : FuncInfo =
let name_sig : string = no_recur_name tydesc
let mutable name_sig_lsts : string list option = None
let get_elem_type = fun () -> Seq.head <| tydesc.ElementType
let get_member_type =
fun (field : string) ->
let memb = tydesc.Members |> Seq.find (fun it -> it.Name = field)
memb.Type
match find tb (tydesc.QualifiedName, verb.ToString()) with
| Some looked_up -> looked_up
| _ ->
match verb with
| ComposedVerb(l, r) ->
(** composed *)
match l, r with
| SGet field, _ ->
let memb_ty = get_member_type field
collect memb_ty r
| LGet, _ ->
let elem_ty = get_elem_type()
let { pos_arg_types = pos_arg_types } as info = collect elem_ty r
{ info with pos_arg_types = "int" :: pos_arg_types }
| _ -> failwith "Only SGet/LGet requires method chaining composition."
|> function
| { verb_str_lst = verb_str_lst; pos_arg_types = pos_arg_types; ret_type = ret_type } ->
let verb_str = chaining_verb_to_name l
verb_str :: verb_str_lst, pos_arg_types, ret_type
| _ ->
(** in the final node of a method chain *)
match verb with
(** argnum 1 *)
| SSet field ->
let memb_ty = get_member_type field
[ ty_to_string memb_ty ], null_type_string
| BSet ->
let arg_type = ty_to_string tydesc
[ arg_type ], null_type_string
| LGet ->
let elem_ty = get_elem_type()
[ "int" ], ty_to_string elem_ty
| LRemoveAt -> [ "int" ], "bool"
| LContains ->
let elem_ty = get_elem_type()
[ ty_to_string elem_ty ], "bool"
| LAppend ->
let elem_ty = get_elem_type()
[ ty_to_string elem_ty ], null_type_string
| LSet ->
let elem_ty = get_elem_type()
[ "int"
ty_to_string elem_ty ], null_type_string
| LInsertAt ->
let elem_ty = get_elem_type()
[ "int"
ty_to_string elem_ty ], "bool"
| (** argnum 0 *)
BGet -> [], ty_to_string tydesc
| LCount -> [], "int"
| SGet field ->
let memb_ty = get_member_type field
[], "void*" // SGet always get
(** BNew takes no subject argument. **)
| BNew -> [], "int32_t"
| info -> failwith <| sprintf "NotImplemented verb %A on %s" info tydesc.TypeName
|> function
| pos_arg_types, ret_type ->
let verb_str = chaining_verb_to_name verb
[ verb_str ], pos_arg_types, ret_type
|> function
| verb_str_lst, pos_arg_types, ret_type ->
let result =
{ name_sig = recur_name tydesc
verb_str_lst = verb_str_lst
pos_arg_types = pos_arg_types
ret_type = ret_type }
tb.[(tydesc.QualifiedName, verb.ToString())] <- result
result
in
let { name_sig = name_sig; verb_str_lst = verb_str_lst; pos_arg_types = pos_arg_types; ret_type = ret_type } = collect tydesc verb
let name_sig = sprintf "%s_%s" name_sig <| String.Join("_", verb_str_lst)
let pos_arg_types = "void*" :: pos_arg_types
let join (lst : string list) = String.Join(", ", lst)
let parameters =
[ for i in 1..(pos_arg_types.Length) -> sprintf "arg%d" i ]
// reversed
let rev_typed_parameters =
List.zip pos_arg_types parameters |> List.rev |> List.map (fun (ty_str, parameter) -> sprintf "%s %s" ty_str parameter)
let args_string : string = join parameters
let typed_args_string : string = join rev_typed_parameters
let private_fn_type = sprintf "%s (*)(%s)" ret_type <| join pos_arg_types
let decl = sprintf "static %s %s(%s);" ret_type name_sig <| join (List.rev pos_arg_types)
let generator addr =
sprintf ("static %s %s(%s){\nreturn reinterpret_cast<%s>(0x%xll)(%s);\n}") ret_type name_sig typed_args_string private_fn_type addr args_string
in (decl, generator)
let code_gen (module_name) (tsl_specs : (TypeDescriptor * Verb list) list) =
let tb = hashmap() (** for caching *)
let generate = single_method'code_gen tb
let ty_recur_naming = ty_to_name true
let (decls, defs) =
[
for (ty, verb_lst) in tsl_specs do
// for specific types
let ty_name = ty_recur_naming ty
for verb in verb_lst do
let (decl, generator) = generate ty verb
let native_fn =
CompileFunction { DeclaringType = ty; Verb = verb }
let addr = native_fn.CallSite.ToInt64()
yield (decl, generator addr)
match ty.TypeCode with
| CELL typeid ->
// for cells
let lock_cell_from_existed_decl = sprintf "static void reuse_%s(void*, int32_t);" ty_name
let lock_cell_from_existed_body =
sprintf "\n
static void reuse_%s(void* subject, int32_t options)
{
auto accessor = static_cast<CellAccessor*>(subject);
accessor -> Release();
auto errCode = LockCell(*accessor, options, %s_BNew);
if (errCode)
throw errCode;
} " ty_name ty_name
yield (lock_cell_from_existed_decl, lock_cell_from_existed_body)
let lock_cell_decl = sprintf "static void* use_%s(int64_t, int32_t);" ty_name
let lock_cell_body =
sprintf "\n
static void* use_%s(int64_t cellid, int32_t options)
{
CellAccessor* accessor = new CellAccessor();
accessor -> cellId = cellid;
accessor -> type = %u;
auto errCode = LockCell(*accessor, options, %s_BNew);
if (errCode)
throw errCode;
return accessor;
} " ty_name typeid ty_name
yield (lock_cell_decl, lock_cell_body)
let load_cell_decl = sprintf "static void* load_%s(int64_t cellid);" ty_name
let load_cell_body =
sprintf "\n
static void* load_%s(int64_t cellid)
{
CellAccessor* accessor = new CellAccessor();
accessor -> cellId = cellid;
accessor -> type = %u;
auto errCode = LoadCell(*accessor);
if (errCode)
throw errCode;
return accessor;
} " ty_name typeid
yield (load_cell_decl, load_cell_body)
| _ -> ()
let default_initializer_decl = sprintf "static void* create_%s();" ty_name
let default_initializer_body =
sprintf "\n
static void* create_%s()
{
CellAccessor* accessor = new CellAccessor();
auto errCode = %s_BNew(accessor);
if(errCode)
throw errCode;
return accessor;
} " ty_name ty_name
yield (default_initializer_decl, default_initializer_body)
let valued_initializer_decl = sprintf "static void* create_%s_with_data(char*);" ty_name
let valued_initializer_body =
sprintf "
static void* create_%s_with_data(char* content)
{
void* accessor = create_%s();
void* buf = reinterpret_cast<void*>(content);
%s_BSet(buf, accessor);
return accessor;
}
" ty_name ty_name ty_name
yield (valued_initializer_decl, valued_initializer_body)
// not for specific types
let basic_ref_get_decl = "static void* Unbox(void*);"
let basic_ref_get_body = "\n
static void* Unbox(void* object)
{
return cast_object(object);
}
"
yield (basic_ref_get_decl, basic_ref_get_body)
let unlock_decl = "static void unlock(void*);"
let unlock_body =
"
static void unlock(void* subject)
{
auto accessor = static_cast<CellAccessor*>(subject);
UnlockCell(*accessor);
}
"
yield (unlock_decl, unlock_body)
let save_cell_decl = "static void save_cell(void*);";
let save_cell_body = "
static void save_cell(void* subject)
{
auto accessor = static_cast<CellAccessor*>(subject);
auto errCode = SaveCell(*accessor);
if(errCode)
throw errCode;
}
"
yield (save_cell_decl, save_cell_body)
// TODO:
// 1. load and save cell. load cell might not require cellAcc.type(done)
// 2. link json deserialization method to init data
// 3. python method binding of above unfinished items(done).
] |> List.unzip
let (=>) a b = (a, b)
let swig_template =
"
%module {moduleName}
%include <stdint.i>
%include <std_wstring.i>
%begin %{{
#include \"swig_accessor.h\"
#include \"CellAccessor.h\"
#include \"stdio.h\"
#define SWIG_FILE_WITH_INIT
#define SWIG_PYTHON_STRICT_BYTE_CHAR
{decl}
{source}
%}}
{decl}
"
in PString.format swig_template
["moduleName" => module_name
"source" => (defs |> PString.str'concatBy "\n" )
"decl" => (decls |> PString.str'concatBy "\n")
]

Просмотреть файл

@ -1,13 +0,0 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0)
PROJECT(Trinity.FFI.Native)
SET(GRAPHENGINE_JIT_DIR ${TRINITY_SRC_DIR}/Modules/GraphEngine.Jit)
FILE(GLOB SRCS *.cpp)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS -DUNICODE -D_UNICODE)
ADD_LIBRARY(trinity_ffi SHARED ${SRCS})
TARGET_COMPILE_DEFINITIONS(trinity_ffi PRIVATE -DTRINITYFFINATIVE_EXPORTS)
TARGET_LINK_LIBRARIES(trinity_ffi PUBLIC Trinity trinity_host)
TARGET_INCLUDE_DIRECTORIES(trinity_ffi PUBLIC ${GRAPHENGINE_JIT_DIR}/GraphEngine.Jit.Native ${CMAKE_CURRENT_SOURCE_DIR})
POSTBUILD_XPLAT_OUTPUT(trinity_ffi ${XPLAT_LIB_DIR})

Просмотреть файл

@ -1,94 +0,0 @@
// Trinity.FFI.Native.cpp : Defines the exported functions for the DLL application.
//
#include "Trinity.FFI.Native.h"
#include "GraphEngine.Hosting.h"
#include "io"
#include <cstring>
static struct TRINITY_INTERFACES g_interfaces;
static bool g_init = false;
static void* g_lp_clr_runtime = nullptr;
using Trinity::IO::Console::WriteLine;
TRINITYFFINATIVE_API void TRINITY_FFI_SET_INTERFACES(const TRINITY_INTERFACES* interfaces)
{
memcpy(&g_interfaces, interfaces, sizeof(TRINITY_INTERFACES));
g_init = true;
}
TRINITYFFINATIVE_API TRINITY_INTERFACES* TRINITY_FFI_GET_INTERFACES()
{
if (!g_init)
{
return nullptr;
}
return &g_interfaces;
}
TRINITYFFINATIVE_API TrinityErrorCode TRINITY_FFI_INITIALIZE(int n_apppaths, char** lp_apppaths, char* config_path, char* storage_root)
{
/*
1. Find the coreclr assembly location, load it
- Raise if hosting environment is not installed
2. Commence coreclr initialization sequence.
- If success, we will have ExecutionEngine (EE) provider standby.
3. With EE provider, initialize an AppDomain (EE)
- Let's call it "runtime".
4. Load appropriate assemblies
- i. System assemblies (System.IO, etc.)
- ii. For each GraphEngine package, we will have a language-specific package mapped to it.
These language-specific packages will then proceed to handle loading logic of .NET assemblies.
- iii. The main entry is written in a master Reisen package. Plugin-packages extend the loading routine.
- iv. For example: GE -> Reisen (python) -> HA (azure) + CompositeStorage
On the Reisen+Python side, it would be Reisen.Core, Reisen.HA, Reisen.CompositeStorage;
Reisen.Core might trigger loading of essential packages.
5. Fire up init routines (set trinity ffi interfaces etc. ;)
- At this moment, Trinity and related assemblies (HA etc.) should be initialized.
- We have initialization routines and attributes at .NET side.
6. Start executing user logic.
- Defaults to an 'Application' with an 'Entry Point'.
For Python, it's the current file, or the one marked as '__MAIN__'
- A Reisen extension package may alter how user logic should be executed.
It might turn the proactive execution into callbacks, event handlers, etc.
For example, a High-Availability program will have a main event loop, a startup handler,
a termination handler etc. The main event loop may be re-entered after the program recovers
from a crash. How this is coordinated is defined by a Reisen package.
*/
TrinityErrorCode eresult = TrinityErrorCode::E_SUCCESS;
TrinityErrorCode(*lpfunc)(char*, char*);
if (g_lp_clr_runtime != nullptr)
{
eresult = GraphEngineUninit(g_lp_clr_runtime);
if (eresult != TrinityErrorCode::E_SUCCESS)
{
return eresult;
}
}
eresult = GraphEngineInit(n_apppaths, lp_apppaths, g_lp_clr_runtime);
if (eresult != TrinityErrorCode::E_SUCCESS)
{
return eresult;
}
eresult = GraphEngineGetFunction(g_lp_clr_runtime, "Trinity.FFI", "Trinity.FFI.Initializer", "Initialize", (void**)&lpfunc);
if (eresult != TrinityErrorCode::E_SUCCESS)
{
return eresult;
}
eresult = lpfunc(config_path, storage_root);
if (eresult != TrinityErrorCode::E_SUCCESS)
{
return eresult;
}
return TrinityErrorCode::E_SUCCESS;
}

Просмотреть файл

@ -1,100 +0,0 @@
/***********************************
Auto-generated from Cpp.tt
***********************************/
#pragma once
// The following ifdef block is the standard way of creating macros which make exporting
// from a DLL simpler. All files within this DLL are compiled with the TRINITYFFINATIVE_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see
// TRINITYFFINATIVE_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef TRINITYFFINATIVE_EXPORTS
#include <cstdint>
#include <os/os.h>
#define TRINITYFFINATIVE_API DLL_EXPORT
#else
#define TRINITYFFINATIVE_API DLL_IMPORT
#endif
#include <TrinityErrorCode.h>
#include "Trinity.h"
typedef char* (*TRINITY_FFI_SYNC_HANDLER)(char*);
typedef void (*TRINITY_FFI_ASYNC_HANDLER)(char*);
typedef char* (*TRINITY_FFI_JITSWIGGEN)(char*, char*);
typedef char* (*TRINITY_FFI_JITSWIGGENFORSERVER)(char*, char*);
typedef TrinityErrorCode (*TRINITY_FFI_ACCESSOR_USE_1)(long long, void**);
typedef TrinityErrorCode (*TRINITY_FFI_ACCESSOR_USE_2)(long long, CellAccessOptions, void**);
typedef TrinityErrorCode (*TRINITY_FFI_ACCESSOR_USE_3)(long long, CellAccessOptions, void**, char*);
typedef TrinityErrorCode (*TRINITY_FFI_CELL_NEW_1)(char*, void**);
typedef TrinityErrorCode (*TRINITY_FFI_CELL_NEW_2)(long long, char*, void**);
typedef TrinityErrorCode (*TRINITY_FFI_CELL_NEW_3)(char*, char*, void**);
typedef char* (*TRINITY_FFI_CELL_TOSTRING)(void*);
typedef TrinityErrorCode (*TRINITY_FFI_CELL_TOBINARY)(char*, char*, long long*, long long*);
typedef long long (*TRINITY_FFI_CELL_GETID)(void*);
typedef void (*TRINITY_FFI_CELL_SETID)(void*, long long);
typedef char* (*TRINITY_FFI_CELL_GET)(void*, char*);
typedef long (*TRINITY_FFI_CELL_HAS)(void*, char*);
typedef void (*TRINITY_FFI_CELL_SET)(void*, char*, char*);
typedef void (*TRINITY_FFI_CELL_APPEND)(void*, char*, char*);
typedef void (*TRINITY_FFI_CELL_DELETE)(void*, char*);
typedef TrinityErrorCode (*TRINITY_FFI_CLOUD_LOADCELL)(long long, void**);
typedef TrinityErrorCode (*TRINITY_FFI_CLOUD_SAVECELL)(long long, void*);
typedef TrinityErrorCode (*TRINITY_FFI_ENUM_NEXT)(void*);
typedef TrinityErrorCode (*TRINITY_FFI_GC_FREE)(void*);
typedef TrinityErrorCode (*TRINITY_FFI_GC_DISPOSE)(void*);
typedef TrinityErrorCode (*TRINITY_FFI_LOCAL_LOADCELL)(long long, void**);
typedef TrinityErrorCode (*TRINITY_FFI_LOCAL_SAVECELL_1)(long long, void*);
typedef TrinityErrorCode (*TRINITY_FFI_LOCAL_SAVECELL_2)(long long, CellAccessOptions, void*);
typedef TrinityErrorCode (*TRINITY_FFI_LOCAL_SAVECELL_3)(void*);
typedef TrinityErrorCode (*TRINITY_FFI_LOCAL_SAVECELL_4)(CellAccessOptions, void*);
typedef TrinityErrorCode (*TRINITY_FFI_LOCAL_REMOVECELL)(long long);
typedef TrinityErrorCode (*TRINITY_FFI_LOCAL_SAVESTORAGE)();
typedef TrinityErrorCode (*TRINITY_FFI_LOCAL_LOADSTORAGE)();
typedef TrinityErrorCode (*TRINITY_FFI_LOCAL_RESETSTORAGE)();
typedef TrinityErrorCode (*TRINITY_FFI_RT_GETFUNCTION)(char*, char*, char*, void**);
typedef TrinityErrorCode (*TRINITY_FFI_SCHEMA_GET)(void**, long*);
extern "C" struct TRINITY_INTERFACES
{
TRINITY_FFI_JITSWIGGEN jitSwigGen;
TRINITY_FFI_JITSWIGGENFORSERVER jitSwigGenForServer;
TRINITY_FFI_ACCESSOR_USE_1 accessor_use_1;
TRINITY_FFI_ACCESSOR_USE_2 accessor_use_2;
TRINITY_FFI_ACCESSOR_USE_3 accessor_use_3;
TRINITY_FFI_CELL_NEW_1 cell_new_1;
TRINITY_FFI_CELL_NEW_2 cell_new_2;
TRINITY_FFI_CELL_NEW_3 cell_new_3;
TRINITY_FFI_CELL_TOSTRING cell_tostring;
TRINITY_FFI_CELL_TOBINARY cell_tobinary;
TRINITY_FFI_CELL_GETID cell_getid;
TRINITY_FFI_CELL_SETID cell_setid;
TRINITY_FFI_CELL_GET cell_get;
TRINITY_FFI_CELL_HAS cell_has;
TRINITY_FFI_CELL_SET cell_set;
TRINITY_FFI_CELL_APPEND cell_append;
TRINITY_FFI_CELL_DELETE cell_delete;
TRINITY_FFI_CLOUD_LOADCELL cloud_loadcell;
TRINITY_FFI_CLOUD_SAVECELL cloud_savecell;
TRINITY_FFI_ENUM_NEXT enum_next;
TRINITY_FFI_GC_FREE gc_free;
TRINITY_FFI_GC_DISPOSE gc_dispose;
TRINITY_FFI_LOCAL_LOADCELL local_loadcell;
TRINITY_FFI_LOCAL_SAVECELL_1 local_savecell_1;
TRINITY_FFI_LOCAL_SAVECELL_2 local_savecell_2;
TRINITY_FFI_LOCAL_SAVECELL_3 local_savecell_3;
TRINITY_FFI_LOCAL_SAVECELL_4 local_savecell_4;
TRINITY_FFI_LOCAL_REMOVECELL local_removecell;
TRINITY_FFI_LOCAL_SAVESTORAGE local_savestorage;
TRINITY_FFI_LOCAL_LOADSTORAGE local_loadstorage;
TRINITY_FFI_LOCAL_RESETSTORAGE local_resetstorage;
TRINITY_FFI_RT_GETFUNCTION rt_getfunction;
TRINITY_FFI_SCHEMA_GET schema_get;
};
TRINITYFFINATIVE_API TrinityErrorCode TRINITY_FFI_INITIALIZE(int n_apppaths, char** lp_apppaths, char* config_path, char* storage_root);
TRINITYFFINATIVE_API TRINITY_INTERFACES* TRINITY_FFI_GET_INTERFACES();

Просмотреть файл

@ -1,285 +0,0 @@
#pragma once
#include <vector>
#include "Trinity.FFI.Native.h"
#include "TypeSystem.h"
#include <CellAccessor.h>
TRINITY_INTERFACES* g_TrinityInterfaces;
int InitCLR(int n_apppaths, const std::vector<std::string> & lp_apppaths, char* config_path, char* storage_root)
{
char** _paths = new char*[lp_apppaths.size()];
char** _ppath = _paths;
for (const auto &p : lp_apppaths)
{
*_ppath++ = _strdup(p.c_str());
}
return TRINITY_FFI_INITIALIZE(n_apppaths, _paths, config_path, storage_root);
}
void InitInterfaces()
{
g_TrinityInterfaces = TRINITY_FFI_GET_INTERFACES();
}
class Cell
{
private:
void* m_cell;
public:
Cell(void* cell) : m_cell(cell) {}
friend Cell* LoadCell(long long);
friend bool SaveCell_1(long long, Cell*);
friend bool SaveCell_2(long long, Cell*, CellAccessOptions);
friend Cell* NewCell_1(char*);
friend Cell* NewCell_2(long long, char*);
friend Cell* NewCell_3(char*, char*);
char* GetField(char* field)
{
return g_TrinityInterfaces->cell_get(m_cell, field);
}
//TODO errno
void SetField(char* field, char* content)
{
g_TrinityInterfaces->cell_set(m_cell, field, content);
}
void AppendField(char* field, char* content)
{
g_TrinityInterfaces->cell_append(m_cell, field, content);
}
void RemoveField(char* field)
{
g_TrinityInterfaces->cell_delete(m_cell, field);
}
int HasField(char* field)
{
return g_TrinityInterfaces->cell_has(m_cell, field);
}
long long GetID() {
return g_TrinityInterfaces->cell_getid(m_cell);
}
void SetID() {
g_TrinityInterfaces->cell_setid(m_cell, GetID());
}
~Cell()
{
//printf("====================== dtor %llX\n", m_cell);
g_TrinityInterfaces->gc_free(m_cell);
}
};
template<typename T, typename F> std::vector<T> __getarray(F f) {
long size = 0;
T* pelem = nullptr;
std::vector<T> vec;
if (TrinityErrorCode::E_SUCCESS == f((void**)&pelem, &size)) {
while (size-- > 0) {
vec.push_back(std::move(*pelem++));
}
}
return vec;
}
std::vector<TypeDescriptor> GetCellDescriptors() {
return __getarray<TypeDescriptor>(g_TrinityInterfaces->schema_get);
}
int LocalStorage_Load()
{
return g_TrinityInterfaces->local_loadstorage();
}
int LocalStorage_Save()
{
return g_TrinityInterfaces->local_savestorage();
}
int LocalStorage_Reset()
{
return g_TrinityInterfaces->local_resetstorage();
}
Cell* LoadCell(long long cellId) {
void* pcell = nullptr;
if (TrinityErrorCode::E_SUCCESS == g_TrinityInterfaces->local_loadcell(cellId, &pcell)) {
return new Cell(pcell);
}
else {
return nullptr;
}
}
bool SaveCell_1(long long cellId, Cell* pcell)
{
return (TrinityErrorCode::E_SUCCESS == g_TrinityInterfaces->local_savecell_1(cellId, pcell->m_cell));
}
bool SaveCell_2(long long cellId, Cell* pcell, CellAccessOptions options)
{
return (TrinityErrorCode::E_SUCCESS == g_TrinityInterfaces->local_savecell_2(cellId, options, pcell->m_cell));
}
Cell* NewCell_1(char* cellType)
{
Cell* pcell = new Cell(0);
if (TrinityErrorCode::E_SUCCESS == g_TrinityInterfaces->cell_new_1(cellType, &pcell->m_cell))
return pcell;
else
{
delete pcell;
return nullptr;
}
}
Cell* NewCell_2(long long cellId, char* cellType)
{
Cell* pcell = new Cell(0);
if (TrinityErrorCode::E_SUCCESS == g_TrinityInterfaces->cell_new_2(cellId, cellType, &pcell->m_cell))
return pcell;
else
{
delete pcell;
return nullptr;
}
}
Cell* NewCell_3(char* cellType, char* cellContent)
{
Cell* pcell = new Cell(0);
if (TrinityErrorCode::E_SUCCESS == g_TrinityInterfaces->cell_new_3(cellType, cellContent, &pcell->m_cell))
return pcell;
else
{
delete pcell;
return nullptr;
}
}
void json_cons_fn_ptr(char* cellType, char* cellContent, long long& cellId, long long& cellPtr) {
auto errCode = g_TrinityInterfaces->cell_tobinary(cellType, cellContent, &cellId, &cellPtr);
if (TrinityErrorCode::E_SUCCESS != errCode) {
throw errCode;
}
}
void test_it(char* cellType, char* cellContent) {
long long cellId = 0;
long long cellPtr = 0;
json_cons_fn_ptr(cellType, cellContent, cellId, cellPtr);
}
long long _json_cons_fn_ptr_getter() {
return (long long) &json_cons_fn_ptr;
}
char* Jit_SwigGenInProcess(char* directory, char* moduleName)
{
return g_TrinityInterfaces->jitSwigGen(directory, moduleName);
}
char* Jit_SwigGenForServer(char* directory, char* moduleName)
{
return g_TrinityInterfaces->jitSwigGenForServer(directory, moduleName);
}
/*
IKeyValueStore
C1 c1(1, 2, 3);
Global.LocalStorage.SaveC1(123, c1);
C:
struct C1
{
int a;
char* b;
int c;
}
Jit'ed:
C1:
[ 4B a | 8B b | 4B c ]
C1_Accessor
[ 4B a | 4B b.Length xB b.Content | 4B c ]
struct C1
{
int a;
std::string b;
std::vector<std::string> list_of_string;
int c;
}
class C1Accessor:
...
CellAccessor UseC1(cellid_t cellid, CellAccessOptions options)
{
CellAccessor accessor;
auto errcode = LockCell(accessor, options);
if (errcode)
throw errcode;
return accessor;
}
SaveC1(C1* c1)
{
char* ptr = nullptr;
ptr += 4;
ptr += b.length();
ptr += 4;
ptr += 4;
char* buf = malloc(ptr);
ptr = 0;
*(int*)ptr = c1->a;
ptr += 4;
*(int*)ptr = c1->b.length();
ptr += 4;
memcpy(ptr, c1->b.c_str());
ptr += b.length();
*(int*)ptr = c1->c;
::CSaveCell(Types::C1Type, buf, ptr);
}
c1 = C1() # new
storage.SaveC1(c1)
==================================
serialize :: C1 -> nativeptr * int
FFI: generate python interface like new C1()... ---> hooked to Cell::New_Cell, update deferred
Accessor: Jit'ed strong type, generate python interface like UseC1(id) ---> CellAccessor
LoadCell: runtime object ---- C# runtime obj
`--- python runtime obj
`--- C++ runtime obj
^
============================|===========
Trinity Storage:
[Serialized cell 1] [Serialized cell 2]
*/

Просмотреть файл

@ -1,37 +0,0 @@
%module ffi
%include <stdint.i>
%include <pybuffer.i>
%pybuffer_mutable_string(char *str);
%{
#define SWIG_FILE_WITH_INIT
#define SWIG_PYTHON_STRICT_BYTE_CHAR
#include "Trinity.FFI.SWIG.h"
%}
%include "attribute.i"
%include "std_vector.i"
%include "std_string.i"
namespace std {
%template(tdesc_vec) vector<TypeDescriptor>;
%template(ptdesc_vec) vector<TypeDescriptor*>;
%template(pmdesc_vec) vector<MemberDescriptor*>;
%template(padesc_vec) vector<AttributeDescriptor*>;
%template(string_vec) vector<string>;
};
%newobject NewCell;
%newobject LoadCell;
%attribute(TypeDescriptor, char*, TypeName, get_TypeName)
%attribute(TypeDescriptor, char*, QualifiedName, get_QualifiedName)
%attribute(TypeDescriptor, int16_t, TypeCode, get_TypeCode)
%attribute(TypeDescriptor, uint16_t, CellType, get_CellType)
%attribute(TypeDescriptor, std::vector<TypeDescriptor*>, ElementType, get_ElementType)
%attribute(TypeDescriptor, std::vector<MemberDescriptor*>, Members, get_Members)
%attribute(TypeDescriptor, std::vector<AttributeDescriptor*>, TSLAttributes, get_TSLAttributes)
%include "../../GraphEngine.Jit/GraphEngine.Jit.Native/TypeSystem.h"
%include "Trinity.FFI.SWIG.h"

Просмотреть файл

@ -1,101 +0,0 @@
#include "Trinity.h"
#include <vector>
#include <stdint.h>
#include "CellAccessor.h"
typedef TrinityErrorCode(*construct_fp_t) (CellAccessor*);
DLL_EXPORT TrinityErrorCode LockCell(IN OUT CellAccessor& accessor, IN const int32_t options, IN construct_fp_t construct)
{
char* ptr;
auto type = accessor.type;
auto ret = ::CGetLockedCellInfo4CellAccessor(accessor.cellId, accessor.size, accessor.type, ptr, accessor.entryIndex);
switch (ret)
{
case TrinityErrorCode::E_SUCCESS:
if (type != accessor.type)
{
::CReleaseCellLock(accessor.cellId, accessor.entryIndex);
ret = TrinityErrorCode::E_WRONG_CELL_TYPE;
}
break;
case TrinityErrorCode::E_CELL_NOT_FOUND:
if (options & CellAccessOptions::CreateNewOnCellNotFound)
{
ret = construct(&accessor);
if (ret != TrinityErrorCode::E_SUCCESS)
{
break;
}
ptr = (char*)accessor.cellPtr;
ret = ::CGetLockedCellInfo4AddOrUseCell(accessor.cellId, accessor.size, accessor.type, ptr, accessor.entryIndex);
if (ret == TrinityErrorCode::E_CELL_FOUND || ret == TrinityErrorCode::E_CELL_NOT_FOUND)
{
ret = TrinityErrorCode::E_SUCCESS;
}
free((char*)accessor.cellPtr);
}
break;
}
accessor.cellPtr = (int64_t)ptr;
accessor.isCell = 1;
accessor.malloced = 0;
finish:
return ret;
}
DLL_EXPORT void UnlockCell(IN const CellAccessor& accessor)
{
if (accessor.malloced) { free((void*)accessor.cellPtr); }
else { ::CReleaseCellLock(accessor.cellId, accessor.entryIndex); }
}
DLL_EXPORT TrinityErrorCode SaveCell(IN CellAccessor& accessor)
{
if (!accessor.isCell) return TrinityErrorCode::E_WRONG_CELL_TYPE;
if (!accessor.malloced) return TrinityErrorCode::E_INVALID_ARGUMENTS;
return ::CSaveCell(accessor.cellId, (char*)accessor.cellPtr, accessor.size, accessor.type);
}
// !note, accessor.type is examined against storage cell type
// error code:
//
// - E_SUCCESS ok
// - E_DEADLOCK storage deadlock
// - E_NOMEM malloc failure
// - E_WRONG_CELL_TYPE cell type mismatch
DLL_EXPORT TrinityErrorCode LoadCell(IN OUT CellAccessor& accessor)
{
char* ptr;
auto type = accessor.type;
auto ret = ::CGetLockedCellInfo4CellAccessor(accessor.cellId, accessor.size, accessor.type, ptr, accessor.entryIndex);
if (ret != TrinityErrorCode::E_SUCCESS) return ret;
if (type != accessor.type)
{
ret = TrinityErrorCode::E_WRONG_CELL_TYPE;
goto cleanup;
}
accessor.cellPtr = (int64_t)malloc(accessor.size);
if (!accessor.cellPtr)
{
ret = TrinityErrorCode::E_NOMEM;
goto cleanup;
}
accessor.malloced = 1;
accessor.isCell = 1;
memcpy((void*)accessor.cellPtr, ptr, accessor.size);
cleanup:
::CReleaseCellLock(accessor.cellId, accessor.entryIndex);
return ret;
}

Просмотреть файл

@ -1,27 +0,0 @@
#pragma once
// User swig code shall include this file
#include "CellAccessor.h"
#include <type_traits>
typedef int32_t(*construct_rawfp_t)(void*);
DLL_IMPORT int32_t LockCell(CellAccessor&, const int32_t, construct_rawfp_t);
DLL_IMPORT void UnlockCell(const CellAccessor&);
DLL_IMPORT int32_t SaveCell(CellAccessor&);
DLL_IMPORT int32_t LoadCell(CellAccessor&);
constexpr char* cast_object(char* object) {
return object;
}
template<typename T>
constexpr typename std::enable_if<std::is_fundamental<T>::value, T>::type cast_object(T x) {
return x;
}
constexpr void* cast_object(void* object) {
return (void*) ((CellAccessor*)object)->cellPtr;
}

Просмотреть файл

@ -1,5 +0,0 @@
cell MyCell
{
int a;
List<string> b;
}

Просмотреть файл

@ -1,39 +0,0 @@
using Python.Runtime;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using Trinity.Network;
using Trinity.Utilities;
using Xunit;
namespace Trinity.FFI.Python.UnitTests
{
public class PythonFFITest
{
[Fact]
public void LoadPythonFFI_Success()
{
// The test engine may trigger the initialization
Global.Initialize();
FileUtility.CompletePath(FFIConfig.Instance.ProgramDirectory, create_nonexistent: true);
// try to invoke trinity-specific python code here
var fp = Path.Combine(FFIConfig.Instance.ProgramDirectory, "test.py");
File.WriteAllText(fp, @"
with open('MyCell.txt', 'w') as f:
a = ge.NewCell('MyCell')
print(a)
f.write(a)
");
TrinityServer server = new TrinityServer();
server.Start();
Global.Uninitialize();
Assert.True(File.Exists("MyCell.txt"));
Debug.WriteLine(File.ReadAllText("MyCell.txt"));
}
}
}

Просмотреть файл

@ -1,97 +0,0 @@
using System;
using Xunit;
using Python.Runtime;
using System.Collections.Generic;
namespace Trinity.FFI.Python.UnitTests
{
public class PythonNetTests
{
public bool ApproxEqual(double a, double b)
{
return Math.Abs(a - b) < 0.00001;
}
[Fact]
void pythonToNETCallback()
{
using (Py.GIL())
{
//new PyObject()
}
}
[Fact]
public void inlinePythonCode_persistent()
{
string pcode = @"
import numpy as np
a = np.array([1,2,3])
print(a.tolist())
";
string pcode2 = @"
b = np.array([1,2,3])
print(b.tolist())";
using (Py.GIL())
{
PythonEngine.Exec(pcode);
PythonEngine.Exec(pcode2);
}
string pcode3 = @"
c = np.array([1,2,3])
print(c.tolist())";
using (Py.GIL())
{
PythonEngine.Exec(pcode3);
}
}
[Fact]
public void inlinePythonCode()
{
string pcode = @"
import numpy as np
a = np.array([1,2,3])
print(a.tolist())
";
using (Py.GIL())
{
PythonEngine.Exec(pcode);
}
}
[Fact]
public void PythonNetWorksHere()
{
using (Py.GIL())
{
dynamic np = Py.Import("numpy");
Assert.True(ApproxEqual((double)np.cos(np.pi * 2), 1.0));
dynamic sin = np.sin;
Assert.True(ApproxEqual((double)sin(5), Math.Sin(5.0)));
double c = np.cos(5) + sin(5);
Assert.True(ApproxEqual(c, Math.Sin(5.0) + Math.Cos(5.0)));
dynamic a = np.array(new List<float> { 1, 2, 3 });
Assert.Equal(np.float64, a.dtype);
dynamic b = np.array(new List<float> { 6, 5, 4 }, dtype: np.int32);
Assert.Equal(np.float64, a.dtype);
dynamic elementwise_product = (a * b).tolist();
Assert.True(ApproxEqual(6, (double)elementwise_product[0]));
Assert.True(ApproxEqual(10, (double)elementwise_product[1]));
Assert.True(ApproxEqual(12, (double)elementwise_product[2]));
}
}
}
}

Просмотреть файл

@ -1,22 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>
<NoWarn>MSB4018</NoWarn>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="GraphEngine.FFI.Python" Version="2.0.9328" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
<PackageReference Include="GraphEngine.Core" Version="2.0.9328" />
</ItemGroup>
<ItemGroup>
<TslCodegen Include="**/*.tsl" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,50 +0,0 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0)
PROJECT(Trinity.FFI.Python)
FIND_PACKAGE(PythonInterp 3)
FIND_PACKAGE(SWIG 3.0.10)
FIND_PACKAGE(TrinityC)
SET(TRINITY_FFI_NATIVE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../Trinity.FFI.Native")
SET(GRAPHENGINE_JIT_NATIVE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../GraphEngine.Jit/GraphEngine.Jit.Native")
SET(TRINITY_C_INCLUDE_DIR "${TRINITY_C_DIR}/include")
SET(PYPACKAGE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/GraphEngine")
FILE(GLOB_RECURSE pysrc "${PYPACKAGE_DIR}/*.py")
FILE(GLOB swigi "${TRINITY_FFI_NATIVE_DIR}/Trinity.FFI.SWIG.i")
FILE(GLOB swigh "${TRINITY_FFI_NATIVE_DIR}/Trinity.FFI.SWIG.h"
"${TRINITY_FFI_NATIVE_DIR}/Trinity.FFI.Schema.h"
"${TRINITY_FFI_NATIVE_DIR}/Trinity.FFI.Native.h")
SET(SETUP_PY_IN "${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in")
SET(SETUP_PY "${CMAKE_CURRENT_BINARY_DIR}/setup.py")
SET(swigpy "${CMAKE_CURRENT_BINARY_DIR}/ffi.py")
SET(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/build/timestamp")
SET(typesys "${GRAPHENGINE_JIT_NATIVE_DIR}/TypeSystem.cpp")
SET(swigcxx "${CMAKE_CURRENT_BINARY_DIR}/Trinity.FFI.SWIG_wrap.cxx")
SET(DEPS ${pysrc} ${swigi} ${typesys} ${swigh} Trinity GraphEngine.Jit.Native trinity_ffi)
IF (PYTHONINTERP_FOUND AND SWIG_FOUND)
IF(WIN32)
SET(ext_cxx_flags "['/Zi', '/D_CRT_SECURE_NO_WARNINGS', '/DUNICODE', '/D_UNICODE']")
SET(ext_linker_flags "['/DEBUG']")
ELSE()
SET(ext_cxx_flags "['--std=c++14', '-fpermissive', '-D_CRT_SECURE_NO_WARNINGS', '-DUNICODE', '-D_UNICODE']")
SET(ext_linker_flags "[]")
ENDIF()
CONFIGURE_FILE(${SETUP_PY_IN} ${SETUP_PY})
ADD_CUSTOM_COMMAND(OUTPUT ${OUTPUT}
COMMAND ${SWIG_EXECUTABLE} -modern -c++ -builtin -outcurrentdir -python "${swigi}"
COMMAND ${CMAKE_COMMAND} -E copy ${swigpy} ${PYPACKAGE_DIR}
COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} bdist_wheel
COMMAND ${CMAKE_COMMAND} -E touch ${OUTPUT}
DEPENDS ${DEPS} trinity_ffi)
ADD_CUSTOM_TARGET(REISEN_PY ALL DEPENDS ${OUTPUT})
INSTALL(CODE "execute_process(COMMAND ${PYTHON_EXECUTABLE} ${SETUP_PY} install)")
ELSE()
MESSAGE("Python environment not setup, skipping build")
ENDIF()

Просмотреть файл

@ -1,19 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="FSharp.Core" Version="4.5.1"/>
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
<PackageReference Include="GraphEngine.Core" Version="2.0.9328" />
<PackageReference Include="GraphEngine.Storage.Composite" Version="2.0.9328" />
<PackageReference Include="GraphEngine.Jit" Version="2.0.9328" />
<PackageReference Include="GraphEngine.FFI" Version="2.0.9328" />
<PackageReference Include="GraphEngine.FFI.Metagen" Version="2.0.9328" />
<PackageReference Include="Microsoft.Extensions.ObjectPool" Version="2.0.0" />
</ItemGroup>
</Project>

Просмотреть файл

Просмотреть файл

@ -1,64 +0,0 @@
from Redy.Magic.Classic import singleton, template, cast
from Redy.Tools.Version import Version as _Version
from typing import Tuple, Callable
from .env import Env
import operator
@singleton
class Version:
def __init__(self, fns=()):
self._fns: Tuple[Callable[[_Version], bool], ...] = fns
def __call__(self, version):
if not self._fns:
return True
elif not isinstance(version, _Version):
version = _Version(version)
for each in self._fns:
if not each(version):
return False
return True
@template
def compare(self, version, op):
if not isinstance(version, _Version):
version = _Version(version)
return self.__class__(self._fns + (lambda x: op(x, version),))
@compare(op=operator.lt)
def __lt__(self, other):
...
@compare(op=operator.eq)
def __eq__(self, other):
...
@compare(op=operator.gt)
def __gt__(self, other):
...
@compare(op=operator.le)
def __le__(self, other):
...
@compare(op=operator.ge)
def __ge__(self, other):
...
class Dependency:
def __init__(self, package_name, version, target_framework_check=None):
self.package_name = package_name
self.version = version
self.target_framework_check = target_framework_check if target_framework_check else Env.target_framework
def all(self):
for each in Env.nuget_root.into("{}/{}/lib".format(self.package_name, self.version)).list_dir():
if each.is_dir() and self.target_framework_check(each[-1]):
return each.list_dir()

Просмотреть файл

@ -1,98 +0,0 @@
from Redy.Tools.PathLib import Path
from Redy.Magic.Classic import singleton, cast
from Redy.Tools.TypeInterface import Module
from subprocess import call
from time import time
import getpass, sys
@singleton
class Env:
nuget_root = Path('~/.nuget/packages')
graph_engine_config_path = Path("~", ".graphengine")
ffi: Module
# TODO is_netstandard
@staticmethod
def target_framework(name: str) -> bool:
return name.startswith('netstandard')
@property
@cast(str)
def include_path(self):
return self.nuget_root.into('graphengine.ffi/2.0.9328/content/include')
@property
@cast(str)
def lib_path(self):
platform = 'win-x64' #TODO
# note, linux links to .so, no .lib needed
# in the setup invocation, we specify lib name only
return self.nuget_root.into(f'graphengine.ffi/2.0.9328/runtime/{platform}/native')
@property
def current_offset(self):
return self.Trinity.Storage.Composite.CompositeStorage.CurrentCellTypeOffset
Env: Env
def build_module(tsl_code, namespace: str):
new_path = Env.graph_engine_config_path.into("versions/{}.{}".format(namespace, str(time()).replace('.', '')))
new_path.mkdir()
directory = str(new_path)
# tsl gen
with open(str(new_path.into('def.tsl')), 'w') as tsl_file:
tsl_file.write(tsl_code)
# swig gen
swig_code = Env.ffi.Jit_SwigGenInProcess(directory.encode(), namespace.encode())
swig_interface_filename = str(new_path.into('{namespace}.i'.format(namespace=namespace)))
with open(swig_interface_filename, 'wb') as swig_file:
swig_file.write(swig_code)
# swig build
call([
"swig",
"-modern",
"-c++",
"-builtin",
"-python",
"-outdir",
directory,
"-o",
"{}/{}_wrap.cxx".format(directory, namespace),
str(swig_interface_filename)])
# py setup
py_setup_file = new_path.into('setup.py')
with open(str(py_setup_file), 'w') as py_file:
py_file.write(
"from setuptools import setup, find_packages\n"
"from setuptools.extension import Extension\n"
f"ext = Extension('_{namespace}',\n"
f" sources=[r'{directory}/{namespace}_wrap.cxx'],\n"
f" include_dirs=[r'{Env.include_path}'],\n"
" libraries=['trinity_ffi', 'Trinity'],\n"
f" library_dirs=[r'{Env.lib_path}'])\n"
"\n"
f"setup(name='{namespace}',\n"
"ext_modules=[ext],\n"
"version = '1.0',\n"
f"author = \"{getpass.getuser()}\",\n"
f"py_modules = [\"{namespace}\"])\n")
# pyd gen
call(['python', str(py_setup_file), 'build', '--build-lib', directory])
sys.path.append(directory)
module = __import__(namespace)
sys.path.remove(directory)
return module

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше