moving gasm and reisen out
This commit is contained in:
Родитель
d5728c6d11
Коммит
f7a8bf547d
|
@ -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.dll
Двоичный файл не отображается.
Двоичные данные
lib/GraphEngine.Jit.Native.lib
Двоичные данные
lib/GraphEngine.Jit.Native.lib
Двоичный файл не отображается.
Двоичные данные
lib/libGraphEngine.Jit.Native.so
Двоичные данные
lib/libGraphEngine.Jit.Native.so
Двоичный файл не отображается.
Двоичные данные
lib/libtrinity_ffi.so
Двоичные данные
lib/libtrinity_ffi.so
Двоичный файл не отображается.
Двоичные данные
lib/libtrinity_host.so
Двоичные данные
lib/libtrinity_host.so
Двоичный файл не отображается.
Двоичные данные
lib/trinity_ffi.dll
Двоичные данные
lib/trinity_ffi.dll
Двоичный файл не отображается.
Двоичные данные
lib/trinity_ffi.lib
Двоичные данные
lib/trinity_ffi.lib
Двоичный файл не отображается.
Двоичные данные
lib/trinity_host.dll
Двоичные данные
lib/trinity_host.dll
Двоичный файл не отображается.
Двоичные данные
lib/trinity_host.lib
Двоичные данные
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
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче