Make crosslang more type safe

This commit is contained in:
2025-09-23 20:28:40 -05:00
parent c9b0578100
commit 026a9e9b49
11 changed files with 708 additions and 531 deletions

4
.vscode/launch.json vendored
View File

@@ -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": [],

View File

@@ -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
)

View File

@@ -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
{

View File

@@ -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;
}
};

View File

@@ -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)

View File

@@ -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

View File

@@ -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
{

View File

@@ -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)

View File

@@ -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")