mirror of
https://onedev.site.tesses.net/crosslang
synced 2026-02-08 17:15:45 +00:00
Make crosslang more type safe
This commit is contained in:
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@@ -8,8 +8,8 @@
|
||||
"name": "(gdb) Launch",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "/usr/local/bin/crossint",
|
||||
"args": ["/home/mike/"],
|
||||
"program": "${workspaceFolder}/builds/linux/crosslang",
|
||||
"args": ["token"],
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
|
||||
@@ -170,7 +170,6 @@ src/vm/filereader.cpp
|
||||
src/vm/gc.cpp
|
||||
src/vm/gclist.cpp
|
||||
src/vm/vm.cpp
|
||||
src/bitconverter.cpp
|
||||
src/archive.cpp
|
||||
src/markedtobject.cpp
|
||||
)
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
*
|
||||
*/
|
||||
namespace Tesses::CrossLang {
|
||||
using BitConverter = Tesses::Framework::Serialization::BitConverter;
|
||||
constexpr std::string_view VMName = "CrossLangVM";
|
||||
constexpr std::string_view VMHowToGet = "https://crosslang.tesseslanguage.com/";
|
||||
/**
|
||||
@@ -719,48 +720,6 @@ class SimpleInstruction : public ByteCodeInstruction {
|
||||
void Write(std::vector<uint8_t>& data);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A bit converter
|
||||
*
|
||||
*/
|
||||
class BitConverter {
|
||||
public:
|
||||
/**
|
||||
* @brief Get the bits of a double from a int64_t
|
||||
*
|
||||
* @param v a int64_t with double's bits
|
||||
* @return double the double
|
||||
*/
|
||||
static double ToDoubleBits(uint64_t v);
|
||||
/**
|
||||
* @brief Get the bits of a int64_t from a double
|
||||
*
|
||||
* @param v a double with int64_t's bits
|
||||
* @return uint64_t the int64_t
|
||||
*/
|
||||
static uint64_t ToUintBits(double v);
|
||||
/**
|
||||
* @brief Get big endian double from uint8_t reference of first element of 8 byte array
|
||||
*
|
||||
* @param b a reference to the first byte of an array
|
||||
* @return double the double
|
||||
*/
|
||||
static double ToDoubleBE(uint8_t& b);
|
||||
/**
|
||||
* @brief Get big endian uint64_t from uint8_t reference of first element of 8 byte array
|
||||
*
|
||||
* @param b a reference to the first byte of an array
|
||||
* @return uint64_t the uint64_t
|
||||
*/
|
||||
static uint64_t ToUint64BE(uint8_t& b);
|
||||
static uint32_t ToUint32BE(uint8_t& b);
|
||||
static uint16_t ToUint16BE(uint8_t& b);
|
||||
static void FromDoubleBE(uint8_t& b, double v);
|
||||
static void FromUint64BE(uint8_t& b, uint64_t v);
|
||||
static void FromUint32BE(uint8_t& b, uint32_t v);
|
||||
static void FromUint16BE(uint8_t& b, uint16_t v);
|
||||
};
|
||||
|
||||
class StringInstruction : public ByteCodeInstruction {
|
||||
public:
|
||||
uint32_t n;
|
||||
@@ -1763,6 +1722,7 @@ class GC {
|
||||
bool HasValue(std::string className,std::string name);
|
||||
bool HasField(std::string className,std::string name);
|
||||
bool HasMethod(std::string className,std::string name);
|
||||
TObject CallMethod(GCList& ls, std::string className, std::string name,std::vector<TObject> args);
|
||||
std::string TypeName();
|
||||
void Mark();
|
||||
};
|
||||
@@ -2034,32 +1994,57 @@ class GC {
|
||||
{
|
||||
public:
|
||||
Tesses::Framework::Streams::Stream* stream;
|
||||
std::vector<TObject> watch;
|
||||
|
||||
static TStreamHeapObject* Create(GCList& ls, Tesses::Framework::Streams::Stream* strm);
|
||||
static TStreamHeapObject* Create(GCList* ls, Tesses::Framework::Streams::Stream* strm);
|
||||
~TStreamHeapObject();
|
||||
void Close();
|
||||
|
||||
void Mark()
|
||||
{
|
||||
if(this->marked) return;
|
||||
this->marked=true;
|
||||
for(auto item : watch)
|
||||
GC::Mark(item);
|
||||
}
|
||||
};
|
||||
|
||||
class TVFSHeapObject : public THeapObject
|
||||
{
|
||||
public:
|
||||
Tesses::Framework::Filesystem::VFS* vfs;
|
||||
std::vector<TObject> watch;
|
||||
static TVFSHeapObject* Create(GCList& ls, Tesses::Framework::Filesystem::VFS* vfs);
|
||||
static TVFSHeapObject* Create(GCList* ls, Tesses::Framework::Filesystem::VFS* vfs);
|
||||
~TVFSHeapObject();
|
||||
void Close();
|
||||
|
||||
void Mark()
|
||||
{
|
||||
if(this->marked) return;
|
||||
this->marked=true;
|
||||
for(auto item : watch)
|
||||
GC::Mark(item);
|
||||
}
|
||||
};
|
||||
|
||||
class TServerHeapObject : public THeapObject
|
||||
{
|
||||
public:
|
||||
Tesses::Framework::Http::IHttpServer* server;
|
||||
std::vector<TObject> watch;
|
||||
static TServerHeapObject* Create(GCList& ls, Tesses::Framework::Http::IHttpServer* vfs);
|
||||
static TServerHeapObject* Create(GCList* ls, Tesses::Framework::Http::IHttpServer* vfs);
|
||||
~TServerHeapObject();
|
||||
void Close();
|
||||
bool Handle(std::vector<TObject> args);
|
||||
void Mark()
|
||||
{
|
||||
if(this->marked) return;
|
||||
this->marked=true;
|
||||
for(auto item : watch)
|
||||
GC::Mark(item);
|
||||
}
|
||||
};
|
||||
class TObjectVFS : public Tesses::Framework::Filesystem::VFS
|
||||
{
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
double BitConverter::ToDoubleBits(uint64_t v)
|
||||
{
|
||||
return *(double*)&v;
|
||||
}
|
||||
uint64_t BitConverter::ToUintBits(double v)
|
||||
{
|
||||
return *(uint64_t*)&v;
|
||||
}
|
||||
double BitConverter::ToDoubleBE(uint8_t& b)
|
||||
{
|
||||
return ToDoubleBits(ToUint64BE(b));
|
||||
}
|
||||
uint64_t BitConverter::ToUint64BE(uint8_t& b)
|
||||
{
|
||||
uint8_t* b2 = &b;
|
||||
uint64_t v = 0;
|
||||
v |= ((uint64_t)b2[0] << 56);
|
||||
v |= ((uint64_t)b2[1] << 48);
|
||||
v |= ((uint64_t)b2[2] << 40);
|
||||
v |= ((uint64_t)b2[3] << 32);
|
||||
v |= ((uint64_t)b2[4] << 24);
|
||||
v |= ((uint64_t)b2[5] << 16);
|
||||
v |= ((uint64_t)b2[6] << 8);
|
||||
v |= (uint64_t)b2[7];
|
||||
return v;
|
||||
}
|
||||
uint32_t BitConverter::ToUint32BE(uint8_t& b)
|
||||
{
|
||||
uint8_t* b2 = &b;
|
||||
uint32_t v = 0;
|
||||
|
||||
v |= ((uint32_t)b2[0] << 24);
|
||||
v |= ((uint32_t)b2[1] << 16);
|
||||
v |= ((uint32_t)b2[2] << 8);
|
||||
v |= (uint32_t)b2[3];
|
||||
return v;
|
||||
}
|
||||
uint16_t BitConverter::ToUint16BE(uint8_t& b)
|
||||
{
|
||||
uint8_t* b2 = &b;
|
||||
uint16_t v = 0;
|
||||
|
||||
|
||||
v |= ((uint16_t)b2[0] << 8);
|
||||
v |= (uint16_t)b2[1];
|
||||
return v;
|
||||
}
|
||||
void BitConverter::FromDoubleBE(uint8_t& b, double v)
|
||||
{
|
||||
FromUint64BE(b,ToUintBits(v));
|
||||
}
|
||||
void BitConverter::FromUint64BE(uint8_t& b, uint64_t v)
|
||||
{
|
||||
uint8_t* b2 = &b;
|
||||
b2[0] = (uint8_t)(v >> 56);
|
||||
b2[1] = (uint8_t)(v >> 48);
|
||||
b2[2] = (uint8_t)(v >> 40);
|
||||
b2[3] = (uint8_t)(v >> 32);
|
||||
b2[4] = (uint8_t)(v >> 24);
|
||||
b2[5] = (uint8_t)(v >> 16);
|
||||
b2[6] = (uint8_t)(v >> 8);
|
||||
b2[7] = (uint8_t)v;
|
||||
}
|
||||
void BitConverter::FromUint32BE(uint8_t& b, uint32_t v)
|
||||
{
|
||||
uint8_t* b2 = &b;
|
||||
|
||||
b2[0] = (uint8_t)(v >> 24);
|
||||
b2[1] = (uint8_t)(v >> 16);
|
||||
b2[2] = (uint8_t)(v >> 8);
|
||||
b2[3] = (uint8_t)v;
|
||||
}
|
||||
void BitConverter::FromUint16BE(uint8_t& b, uint16_t v)
|
||||
{
|
||||
uint8_t* b2 = &b;
|
||||
|
||||
b2[0] = (uint8_t)(v >> 8);
|
||||
b2[1] = (uint8_t)v;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <map>
|
||||
#include <cstring>
|
||||
#include <variant>
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
void Write(Tesses::Framework::Streams::Stream* strm, uint8_t* buffer, size_t len)
|
||||
|
||||
@@ -220,9 +220,10 @@ namespace Tesses::CrossLang {
|
||||
dict->DeclareFunction(gc,"Read", "Reads a byte from stdin",{},Console_Read);
|
||||
dict->DeclareFunction(gc,"ReadLine","Reads line from stdin",{},Console_ReadLine);
|
||||
dict->DeclareFunction(gc,"Write","Write text \"text\" to stdout",{"text"},Console_Write);
|
||||
dict->DeclareFunction(gc,"WriteLine","Write text \"text\" to stdout with new line",{"text"},Console_WriteLine);
|
||||
dict->DeclareFunction(gc,"WriteLine","Write text \"text\" to stdout with new line",{"$text"},Console_WriteLine);
|
||||
dict->DeclareFunction(gc,"Error", "Write text \"error\" to stderr",{"error"},Console_Error);
|
||||
dict->DeclareFunction(gc,"ErrorLine","Write text \"error\" to stderr",{"error"},Console_ErrorLine);
|
||||
dict->DeclareFunction(gc,"ErrorLine","Write text \"error\" to stderr",{"$error"},Console_ErrorLine);
|
||||
if(env->permissions.canRegisterEverything)
|
||||
dict->DeclareFunction(gc,"Fatal","Stop the program with an optional error message",{"$text"},Console_Fatal);
|
||||
dict->DeclareFunction(gc,"getIn","Get stdin Stream",{},Console_getIn);
|
||||
dict->DeclareFunction(gc,"getOut","Get stdout Stream",{},Console_getOut);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,4 @@
|
||||
|
||||
#include "CrossLang.hpp"
|
||||
#if defined(CROSSLANG_ENABLE_SHARED)
|
||||
#if defined(CROSSLANG_ENABLE_FFI)
|
||||
@@ -30,6 +31,35 @@
|
||||
|
||||
namespace Tesses::CrossLang
|
||||
{
|
||||
class TMuxex : public TNativeObject
|
||||
{
|
||||
public:
|
||||
Tesses::Framework::Threading::Mutex mtx;
|
||||
|
||||
std::string TypeName()
|
||||
{
|
||||
return "Mutex";
|
||||
}
|
||||
|
||||
TObject CallMethod(GCList& ls, std::string key, std::vector<TObject> args)
|
||||
{
|
||||
if(key == "Lock")
|
||||
{
|
||||
mtx.Lock();
|
||||
}
|
||||
else if(key == "Unlock")
|
||||
{
|
||||
mtx.Unlock();
|
||||
}
|
||||
else if(key == "TryLock")
|
||||
{
|
||||
return mtx.TryLock();
|
||||
}
|
||||
|
||||
return Undefined();
|
||||
}
|
||||
};
|
||||
|
||||
class DocumentationParser : public TNativeObject
|
||||
{
|
||||
public:
|
||||
@@ -1284,48 +1314,8 @@ namespace Tesses::CrossLang
|
||||
return nullptr;
|
||||
});
|
||||
newTypes->DeclareFunction(gc, "Mutex", "Create mutex",{}, [](GCList& ls,std::vector<TObject> args)->TObject {
|
||||
ls.GetGC()->BarrierBegin();
|
||||
auto mtx = TDictionary::Create(ls);
|
||||
auto native = TNative::Create(ls, new Tesses::Framework::Threading::Mutex(),[](void* ptr)->void{
|
||||
delete static_cast<Tesses::Framework::Threading::Mutex*>(ptr);
|
||||
});
|
||||
auto lock = TExternalMethod::Create(ls,"Lock the mutex",{},[native](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
if(native->GetDestroyed()) return nullptr;
|
||||
auto r = static_cast<Tesses::Framework::Threading::Mutex*>(native->GetPointer());
|
||||
r->Lock();
|
||||
return nullptr;
|
||||
});
|
||||
lock->watch.push_back(native);
|
||||
mtx->SetValue("Lock",lock);
|
||||
|
||||
auto unlock = TExternalMethod::Create(ls,"Unlock the mutex",{},[native](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
if(native->GetDestroyed()) return nullptr;
|
||||
auto r = static_cast<Tesses::Framework::Threading::Mutex*>(native->GetPointer());
|
||||
r->Unlock();
|
||||
return nullptr;
|
||||
});
|
||||
unlock->watch.push_back(native);
|
||||
mtx->SetValue("Unlock",unlock);
|
||||
|
||||
|
||||
auto trylock = TExternalMethod::Create(ls,"Try to lock the mutex, returns true if we aquire the lock, false if we can't due to another thread owning it",{},[native](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
if(native->GetDestroyed()) return true;
|
||||
auto r = static_cast<Tesses::Framework::Threading::Mutex*>(native->GetPointer());
|
||||
return r->TryLock();
|
||||
});
|
||||
trylock->watch.push_back(native);
|
||||
mtx->SetValue("TryLock",trylock);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
|
||||
auto close = TExternalMethod::Create(ls,"Try to lock the mutex, returns true if we aquire the lock, false if we can't due to another thread owning it",{},[native](GCList& ls, std::vector<TObject> args)->TObject {
|
||||
native->Destroy();
|
||||
return nullptr;
|
||||
});
|
||||
close->watch.push_back(native);
|
||||
mtx->SetValue("Close",close);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
return mtx;
|
||||
return TNativeObject::Create<TMuxex>(ls);
|
||||
});
|
||||
newTypes->DeclareFunction(gc, "Thread","Create thread",{"callback"},[](GCList& ls, std::vector<TObject> args)-> TObject
|
||||
{
|
||||
|
||||
@@ -8,6 +8,16 @@ namespace Tesses::CrossLang
|
||||
for(auto& item : this->inherit_tree) type += " : " + item;
|
||||
return type;
|
||||
}
|
||||
TObject TClassObject::CallMethod(GCList& ls, std::string className, std::string name,std::vector<TObject> args)
|
||||
{
|
||||
auto value = this->GetValue(className,name);
|
||||
TCallable* callable;
|
||||
if(GetObjectHeap(value, callable))
|
||||
{
|
||||
return callable->Call(ls,args);
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
TClassObjectEntry* TClassObject::GetEntry(std::string classN, std::string key)
|
||||
{
|
||||
for(auto& item : this->entries)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
#include "CrossLang.hpp"
|
||||
#include <TessesFramework/Filesystem/VFS.hpp>
|
||||
#include <cstddef>
|
||||
@@ -3253,28 +3254,7 @@ namespace Tesses::CrossLang {
|
||||
}
|
||||
if(key == "Handle")
|
||||
{
|
||||
|
||||
if(GetArgumentHeap(args,0,dict))
|
||||
{
|
||||
gc->BarrierBegin();
|
||||
auto nat = dict->GetValue("native");
|
||||
gc->BarrierEnd();
|
||||
TNative* nat2;
|
||||
if(GetObjectHeap(nat,nat2))
|
||||
{
|
||||
if(!nat2->GetDestroyed())
|
||||
{
|
||||
auto ctx = static_cast<Tesses::Framework::Http::ServerContext*>(nat2->GetPointer());
|
||||
if(ctx != nullptr)
|
||||
{
|
||||
cse.back()->Push(gc,svr->server->Handle(*ctx));
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
cse.back()->Push(gc,false);
|
||||
cse.back()->Push(gc,svr->Handle(args));
|
||||
return false;
|
||||
}
|
||||
if(key == "Close")
|
||||
|
||||
Reference in New Issue
Block a user