Add dvd builder script

This commit is contained in:
2025-05-08 20:19:44 -05:00
parent 8b1f0786f4
commit 0c1ead790d
14 changed files with 1359 additions and 51 deletions

View File

@ -1,2 +1,2 @@
CompileFlags: # Tweak the parse settings, example directory given to show format CompileFlags: # Tweak the parse settings, example directory given to show format
Add: ["-Iinclude"] Add: ["-Iinclude","-std=gnu++17"]

View File

@ -74,7 +74,8 @@
"stop_token": "cpp", "stop_token": "cpp",
"thread": "cpp", "thread": "cpp",
"bitset": "cpp", "bitset": "cpp",
"regex": "cpp" "regex": "cpp",
"cstdbool": "cpp"
}, },
"clangd.fallbackFlags": [ "clangd.fallbackFlags": [
"-Iinclude" "-Iinclude"

View File

@ -8,6 +8,7 @@ set(CMAKE_CXX_STANDARD 17)
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
#option(CROSSLANG_ENABLE_DOXYGEN "Enable doxygen" ON)
option(CROSSLANG_ENABLE_STATIC "Enable Tesses CrossLang static libraries" ON) option(CROSSLANG_ENABLE_STATIC "Enable Tesses CrossLang static libraries" ON)
option(CROSSLANG_ENABLE_SHARED "Enable Tesses CrossLang shared libraries" ON) option(CROSSLANG_ENABLE_SHARED "Enable Tesses CrossLang shared libraries" ON)
@ -25,6 +26,15 @@ option(CROSSLANG_ENABLE_CONFIG_ENVVAR "Allow setting config directory via the en
option(CROSSLANG_CUSTOM_CONSOLE "Enable custom Console" OFF) option(CROSSLANG_CUSTOM_CONSOLE "Enable custom Console" OFF)
#if(CROSSLANG_ENABLE_DOXYGEN)
#find_package(Doxygen REQUIRED)
#doxygen_add_docs(doxygen-crosslang "${CMAKE_CURRENT_SOURCE_DIR}/include/CrossLang.hpp" "${CMAKE_CURRENT_SOURCE_DIR}/docs" "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
#add_custom_target(crosslang_doxygen ALL
# COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile.doxygen-crosslang
# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
#)
#endif()
if(CROSSLANG_CUSTOM_CONSOLE) if(CROSSLANG_CUSTOM_CONSOLE)
set(CROSSLANG_ENABLE_BINARIES OFF) set(CROSSLANG_ENABLE_BINARIES OFF)

View File

@ -10,9 +10,9 @@ Tesses Cross Language
- CMake - CMake
## What libraries have I embeded from other people ## What libraries have I embeded from other people
- [HodwardHinnart's date]() (in folder src/HodwardHinnart_date, modified tz.cpp to point to correct header) - [HodwardHinnart's date](https://github.com/HowardHinnant/date) (in folder src/HodwardHinnart_date, modified tz.cpp to point to correct header)
- [Sqlite]() (in folder src/sqlite also uses demo VFS (at least on Wii)) - [Sqlite](https://www.sqlite.org/) (in folder src/sqlite also uses demo VFS (at least on Wii))
- [Sago's platform_folders]() (in folder src/sago) - [Sago's platform_folders](https://github.com/sago007/PlatformFolders) (in folder src/sago)
- [subprocess](https://github.com/sheredom/subprocess.h) (as file src/runtime_methods/subprocess.h) - [subprocess](https://github.com/sheredom/subprocess.h) (as file src/runtime_methods/subprocess.h)
## Use in docker (use my container) ## Use in docker (use my container)
```bash ```bash
@ -30,7 +30,9 @@ Tesses Cross Language
- Install [mbedtls](https://github.com/Mbed-TLS/mbedtls) (use sudo apt install libmbedtls-dev on debian) for TessesFramework - Install [mbedtls](https://github.com/Mbed-TLS/mbedtls) (use sudo apt install libmbedtls-dev on debian) for TessesFramework
- Follow the commands bellow - Follow the commands bellow
## Run these commands to install crosslang (or use binaries from [here](https://crosslang.tesseslanguage.com/download/)) ## Run these commands to install crosslang
Or use binaries from [here](https://crosslang.tesseslanguage.com/download/)
```bash ```bash
git clone https://onedev.site.tesses.net/CrossLang git clone https://onedev.site.tesses.net/CrossLang
cd CrossLang cd CrossLang
@ -41,6 +43,16 @@ make
sudo make install sudo make install
``` ```
## To Create the binaries and ISO (You need linux for this)
```bash
sudo apt install xorriso wget curl mingw-w64 nsis cmake tar zip
mkdir dvdwork
cp build-dvd.tcross dvdwork/
cd dvdwork
crossint build-dvd.tcross
bash script.sh # the iso and tarballs will be in Working/Output
```
``` ```
Ye are of God, little children, and have overcome them: because greater is he that is in you, than he that is in the world. (1 John 4:4) Ye are of God, little children, and have overcome them: because greater is he that is in you, than he that is in the world. (1 John 4:4)
``` ```

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
#include <array> #include <array>
#include <map> #include <map>
#include <cstring> #include <cstring>
#include <variant>
namespace Tesses::CrossLang namespace Tesses::CrossLang
{ {
void Write(Tesses::Framework::Streams::Stream* strm, uint8_t* buffer, size_t len) void Write(Tesses::Framework::Streams::Stream* strm, uint8_t* buffer, size_t len)
@ -31,6 +32,7 @@ namespace Tesses::CrossLang
} }
} }
void CodeGen::Save(Tesses::Framework::Filesystem::VFS* vfs, Tesses::Framework::Streams::Stream* stream) void CodeGen::Save(Tesses::Framework::Filesystem::VFS* vfs, Tesses::Framework::Streams::Stream* stream)
{ {
TVMVersion runtime_version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE); TVMVersion runtime_version(TVM_MAJOR,TVM_MINOR,TVM_PATCH,TVM_BUILD,TVM_VERSIONSTAGE);
@ -409,6 +411,32 @@ namespace Tesses::CrossLang
} }
#define ONE_EXPR(EXPRESSION, INSTRUCTION) if(adv.nodeName == EXPRESSION && adv.nodes.size() == 1) {GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);instructions.push_back(new SimpleInstruction(INSTRUCTION));} #define ONE_EXPR(EXPRESSION, INSTRUCTION) if(adv.nodeName == EXPRESSION && adv.nodes.size() == 1) {GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);instructions.push_back(new SimpleInstruction(INSTRUCTION));}
#define TWO_EXPR(EXPRESSION, INSTRUCTION) if(adv.nodeName == EXPRESSION && adv.nodes.size() == 2) {GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);instructions.push_back(new SimpleInstruction(INSTRUCTION));} #define TWO_EXPR(EXPRESSION, INSTRUCTION) if(adv.nodeName == EXPRESSION && adv.nodes.size() == 2) {GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);instructions.push_back(new SimpleInstruction(INSTRUCTION));}
SyntaxNode CodeGen::StringifyListOfVars(SyntaxNode n)
{
if(std::holds_alternative<std::string>(n))
{
return n;
}
else if(std::holds_alternative<AdvancedSyntaxNode>(n))
{
auto itemA=std::get<AdvancedSyntaxNode>(n);
if(itemA.nodeName == GetVariableExpression && itemA.nodes.size()==1 && std::holds_alternative<std::string>(itemA.nodes[0]))
{
return std::get<std::string>(itemA.nodes[0]);
}
else if(itemA.nodeName == CommaExpression && itemA.nodes.size()==2)
{
return AdvancedSyntaxNode::Create(CommaExpression,true,{StringifyListOfVars(itemA.nodes[0]),StringifyListOfVars(itemA.nodes[1])});
}
}
return nullptr;
}
void CodeGen::GenNode(std::vector<ByteCodeInstruction*>& instructions, SyntaxNode n,int32_t scope,int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI) void CodeGen::GenNode(std::vector<ByteCodeInstruction*>& instructions, SyntaxNode n,int32_t scope,int32_t contscope, int32_t brkscope, int32_t contI, int32_t brkI)
{ {
if(std::holds_alternative<std::nullptr_t>(n)) if(std::holds_alternative<std::nullptr_t>(n))
@ -1018,18 +1046,48 @@ namespace Tesses::CrossLang
else if(adv.nodeName == AssignExpression && adv.nodes.size() == 2 && std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0])) else if(adv.nodeName == AssignExpression && adv.nodes.size() == 2 && std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0]))
{ {
auto varNode = std::get<AdvancedSyntaxNode>(adv.nodes[0]); auto varNode = std::get<AdvancedSyntaxNode>(adv.nodes[0]);
if(varNode.nodeName == GetVariableExpression && varNode.nodes.size() == 1 && std::holds_alternative<std::string>(varNode.nodes[0])) if(varNode.nodeName == GetVariableExpression && varNode.nodes.size() == 1 && std::holds_alternative<std::string>(varNode.nodes[0]))
{ {
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(varNode.nodes[0])))); instructions.push_back(new StringInstruction(GetString(std::get<std::string>(varNode.nodes[0]))));
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
instructions.push_back(new SimpleInstruction(SETVARIABLE)); instructions.push_back(new SimpleInstruction(SETVARIABLE));
} }
else if(varNode.nodeName == ArrayExpression && varNode.nodes.size() >= 1)
{
auto vars= StringifyListOfVars(varNode.nodes[0]);
auto nArray = AdvancedSyntaxNode::Create(ArrayExpression,true,{vars});
this->GenNode(instructions,nArray ,scope ,contscope ,brkscope ,contI , brkI);
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
instructions.push_back(new SimpleInstruction(SETVARIABLE));
}
else if(varNode.nodeName == DeclareExpression && varNode.nodes.size() == 1 && std::holds_alternative<std::string>(varNode.nodes[0])) else if(varNode.nodeName == DeclareExpression && varNode.nodes.size() == 1 && std::holds_alternative<std::string>(varNode.nodes[0]))
{ {
instructions.push_back(new StringInstruction(GetString(std::get<std::string>(varNode.nodes[0])))); instructions.push_back(new StringInstruction(GetString(std::get<std::string>(varNode.nodes[0]))));
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI); GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
instructions.push_back(new SimpleInstruction(DECLAREVARIABLE)); instructions.push_back(new SimpleInstruction(DECLAREVARIABLE));
} }
else if(varNode.nodeName == DeclareExpression && varNode.nodes.size() == 1 && std::holds_alternative<AdvancedSyntaxNode>(varNode.nodes[0]))
{
auto adv2 = std::get<AdvancedSyntaxNode>(varNode.nodes[0]);
if(adv2.nodeName == ArrayExpression && adv2.nodes.size() == 1)
{
auto vars= StringifyListOfVars(adv2.nodes[0]);
auto nArray = AdvancedSyntaxNode::Create(ArrayExpression,true,{vars});
this->GenNode(instructions,nArray ,scope ,contscope ,brkscope ,contI , brkI);
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
instructions.push_back(new SimpleInstruction(DECLAREVARIABLE));
}
}
else if(varNode.nodeName == GetFieldExpression && varNode.nodes.size() == 2 && std::holds_alternative<std::string>(varNode.nodes[1])) else if(varNode.nodeName == GetFieldExpression && varNode.nodes.size() == 2 && std::holds_alternative<std::string>(varNode.nodes[1]))
{ {
GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI); GenNode(instructions,varNode.nodes[0],scope,contscope,brkscope,contI,brkI);
@ -1050,9 +1108,41 @@ namespace Tesses::CrossLang
GenNode(instructions,n,scope,contscope,brkscope,contI,brkI); GenNode(instructions,n,scope,contscope,brkscope,contI,brkI);
} }
} }
else if(adv.nodeName == ThrowStatement && adv.nodes.size() == 1) else if(adv.nodeName == BreakpointStatement && adv.nodes.size() == 5)
{
instructions.push_back(new SimpleInstruction(CREATEDICTIONARY));
instructions.push_back(new StringInstruction(GetString("Data")));
GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);
instructions.push_back(new SimpleInstruction(APPENDDICT));
instructions.push_back(new StringInstruction(GetString("Filename")));
GenNode(instructions,adv.nodes[1] ,scope,contscope ,brkscope ,contI ,brkI);
instructions.push_back(new SimpleInstruction(APPENDDICT));
instructions.push_back(new StringInstruction(GetString("Line")));
GenNode(instructions,adv.nodes[2] ,scope,contscope ,brkscope ,contI ,brkI);
instructions.push_back(new SimpleInstruction(APPENDDICT));
instructions.push_back(new StringInstruction(GetString("Column")));
GenNode(instructions,adv.nodes[3] ,scope,contscope ,brkscope ,contI ,brkI);
instructions.push_back(new SimpleInstruction(APPENDDICT));
instructions.push_back(new StringInstruction(GetString("Offset")));
GenNode(instructions,adv.nodes[4] ,scope,contscope ,brkscope ,contI ,brkI);
instructions.push_back(new SimpleInstruction(APPENDDICT));
instructions.push_back(new SimpleInstruction(BREAKPOINT));
}
else if(adv.nodeName == ThrowStatement && adv.nodes.size() == 5)
{ {
GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI); GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);
instructions.push_back(new StringInstruction(GetString("Filename")));
GenNode(instructions,adv.nodes[1] ,scope,contscope ,brkscope ,contI ,brkI);
instructions.push_back(new SimpleInstruction(APPENDDICT));
instructions.push_back(new StringInstruction(GetString("Line")));
GenNode(instructions,adv.nodes[2] ,scope,contscope ,brkscope ,contI ,brkI);
instructions.push_back(new SimpleInstruction(APPENDDICT));
instructions.push_back(new StringInstruction(GetString("Column")));
GenNode(instructions,adv.nodes[3] ,scope,contscope ,brkscope ,contI ,brkI);
instructions.push_back(new SimpleInstruction(APPENDDICT));
instructions.push_back(new StringInstruction(GetString("Offset")));
GenNode(instructions,adv.nodes[4] ,scope,contscope ,brkscope ,contI ,brkI);
instructions.push_back(new SimpleInstruction(APPENDDICT));
instructions.push_back(new SimpleInstruction(THROW)); instructions.push_back(new SimpleInstruction(THROW));
} }
else if(adv.nodeName == ReturnStatement && adv.nodes.size() == 1) else if(adv.nodeName == ReturnStatement && adv.nodes.size() == 1)

View File

@ -588,10 +588,21 @@ namespace Tesses::CrossLang
{ {
if(i >= tokens.size()) throw std::out_of_range("End of file"); if(i >= tokens.size()) throw std::out_of_range("End of file");
auto variable = tokens[i]; auto variable = tokens[i];
i++; i++;
if(variable.type != LexTokenType::Identifier) throw SyntaxException(variable.lineInfo, "Expected an identifier got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\""); if(variable.type == LexTokenType::Symbol && variable.text == "[")
{
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{
AdvancedSyntaxNode::Create(ArrayExpression ,true,{ParseExpression()})
});
EnsureSymbol("]");
}
else if(variable.type != LexTokenType::Identifier) throw SyntaxException(variable.lineInfo, "Expected an identifier got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\"");
else
{
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{variable.text}); node = AdvancedSyntaxNode::Create(DeclareExpression,true,{variable.text});
} }
}
else if(IsIdentifier("operator")) else if(IsIdentifier("operator"))
{ {
if(i >= tokens.size()) throw std::out_of_range("End of file"); if(i >= tokens.size()) throw std::out_of_range("End of file");
@ -1189,9 +1200,19 @@ namespace Tesses::CrossLang
} }
if(IsIdentifier("throw")) if(IsIdentifier("throw"))
{ {
auto tkn2 = tkn;
auto v = ParseExpression(); auto v = ParseExpression();
EnsureSymbol(";"); EnsureSymbol(";");
return AdvancedSyntaxNode::Create(ThrowStatement,false,{v}); return AdvancedSyntaxNode::Create(ThrowStatement,false,{v,tkn2.lineInfo.filename,(int64_t)tkn2.lineInfo.line,(int64_t)tkn2.lineInfo.column,(int64_t)tkn.lineInfo.offset});
}
if(IsIdentifier("breakpoint"))
{
auto tkn2 = tkn;
auto v = ParseExpression();
EnsureSymbol(";");
return AdvancedSyntaxNode::Create(BreakpointStatement,false,{v,tkn2.lineInfo.filename,(int64_t)tkn2.lineInfo.line,(int64_t)tkn2.lineInfo.column,(int64_t)tkn.lineInfo.offset});
} }
if(IsIdentifier("try")) if(IsIdentifier("try"))
{ {

View File

@ -13,6 +13,7 @@ namespace Tesses::CrossLang
#else #else
static char EnvPathSeperator=':'; static char EnvPathSeperator=':';
#endif #endif
static std::string GetHomeFolder() static std::string GetHomeFolder()
{ {
#if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS) #if defined(CROSSLANG_ENABLE_PLATFORM_FOLDERS)

View File

@ -204,6 +204,14 @@ namespace Tesses::CrossLang
auto strm = dynamic_cast<TStreamHeapObject*>(obj); auto strm = dynamic_cast<TStreamHeapObject*>(obj);
auto svr = dynamic_cast<TServerHeapObject*>(obj); auto svr = dynamic_cast<TServerHeapObject*>(obj);
auto cse = dynamic_cast<CallStackEntry*>(obj); auto cse = dynamic_cast<CallStackEntry*>(obj);
auto rootEnv = dynamic_cast<TRootEnvironment*>(obj);
auto subEnv = dynamic_cast<TSubEnvironment*>(obj);
auto env = dynamic_cast<TEnvironment*>(obj);
if(rootEnv != nullptr) return "RootEnvironment";
if(subEnv != nullptr) return "SubEnvironment";
if(env != nullptr) return "Environment";
if(cse != nullptr) return "YieldedClosure"; if(cse != nullptr) return "YieldedClosure";
if(dynDict != nullptr) return "DynamicDictionary"; if(dynDict != nullptr) return "DynamicDictionary";
if(dynList != nullptr) return "DynamicList"; if(dynList != nullptr) return "DynamicList";
@ -568,6 +576,7 @@ namespace Tesses::CrossLang
GCList ls(gc); GCList ls(gc);
TDictionary* dict = TDictionary::Create(ls); TDictionary* dict = TDictionary::Create(ls);
TDictionary* gc_dict = TDictionary::Create(ls);
dict->DeclareFunction(gc,"LoadNativePlugin","Load a native plugin, requires a dynamic linker and shared build of libcrosslang",{"path"},[gc,env](GCList& ls, std::vector<TObject> args)->TObject { dict->DeclareFunction(gc,"LoadNativePlugin","Load a native plugin, requires a dynamic linker and shared build of libcrosslang",{"path"},[gc,env](GCList& ls, std::vector<TObject> args)->TObject {
Tesses::Framework::Filesystem::VFSPath path; Tesses::Framework::Filesystem::VFSPath path;
if(GetArgumentAsPath(args,0,path)) if(GetArgumentAsPath(args,0,path))
@ -576,8 +585,21 @@ namespace Tesses::CrossLang
} }
return nullptr; return nullptr;
}); });
gc_dict->DeclareFunction(gc,"Collect","Collect garbage",{},[](GCList& ls, std::vector<TObject> args)->TObject{
ls.GetGC()->Collect();
return nullptr;
});
gc_dict->DeclareFunction(gc,"BarrierBegin","Lock globally",{},[](GCList& ls,std::vector<TObject> args)->TObject {
ls.GetGC()->BarrierBegin();
return nullptr;
});
gc_dict->DeclareFunction(gc, "BarrierEnd","Unlock globally",{},[](GCList& ls, std::vector<TObject> args)->TObject {
ls.GetGC()->BarrierEnd();
return nullptr;
});
gc->BarrierBegin(); gc->BarrierBegin();
env->SetVariable("Reflection",dict); env->SetVariable("Reflection",dict);
env->SetVariable("GC", gc_dict);
gc->BarrierEnd(); gc->BarrierEnd();
env->permissions.locked=true; env->permissions.locked=true;
} }

View File

@ -208,6 +208,7 @@ namespace Tesses::CrossLang {
this->marked = true; this->marked = true;
this->dict->Mark(); this->dict->Mark();
for(auto defer : this->defers) defer->Mark(); for(auto defer : this->defers) defer->Mark();
if(this->error != nullptr) this->error->Mark();
} }
TRootEnvironment* TRootEnvironment::Create(GCList* gc,TDictionary* dict) TRootEnvironment* TRootEnvironment::Create(GCList* gc,TDictionary* dict)
{ {
@ -225,4 +226,39 @@ namespace Tesses::CrossLang {
_gc->Watch(env); _gc->Watch(env);
return env; return env;
} }
bool TRootEnvironment::HandleException(GC* gc,TEnvironment* env, TObject err)
{
if(error != nullptr)
{
GCList ls(gc);
return ToBool(error->Call(ls, {
TDictionary::Create(ls,{
TDItem("IsBreakpoint",false),
TDItem("Exception",err),
TDItem("Environment", env)
})
}));
}
return false;
}
bool TRootEnvironment::HandleBreakpoint(GC* gc,TEnvironment* env, TObject err)
{
if(error != nullptr)
{
GCList ls(gc);
return ToBool(error->Call(ls, {
TDictionary::Create(ls,{
TDItem("IsBreakpoint",true),
TDItem("Breakpoint",err),
TDItem("Environment", env)
})
}));
}
return true;
}
void TRootEnvironment::RegisterOnError(TCallable* call)
{
this->error = call;
}
}; };

View File

@ -1,6 +1,10 @@
#include "CrossLang.hpp" #include "CrossLang.hpp"
namespace Tesses::CrossLang { namespace Tesses::CrossLang {
TDictionary* TSubEnvironment::GetDictionary()
{
return this->dict;
}
TObject TSubEnvironment::GetVariable(std::string key) TObject TSubEnvironment::GetVariable(std::string key)
{ {
if(this->dict->HasValue(key)) if(this->dict->HasValue(key))

View File

@ -1,6 +1,7 @@
#include "CrossLang.hpp" #include "CrossLang.hpp"
#include <TessesFramework/Filesystem/VFS.hpp> #include <TessesFramework/Filesystem/VFS.hpp>
#include <cstddef> #include <cstddef>
#include <exception>
#include <iostream> #include <iostream>
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
@ -74,6 +75,170 @@ namespace Tesses::CrossLang {
return false; return false;
} }
bool Equals(GC* gc, TObject left, TObject right)
{
GCList ls(gc);
if(std::holds_alternative<std::nullptr_t>(left) && std::holds_alternative<std::nullptr_t>(right))
{
return true;
}
else if(std::holds_alternative<Undefined>(left) && std::holds_alternative<Undefined>(right))
{
return true;
}
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<int64_t>(right))
{
return std::get<int64_t>(left) == std::get<int64_t>(right);
}
else if(std::holds_alternative<double>(left) && std::holds_alternative<double>(right))
{
return std::get<double>(left) == std::get<double>(right);
}
else if(std::holds_alternative<double>(left) && std::holds_alternative<int64_t>(right))
{
return std::get<double>(left) == std::get<int64_t>(right);
}
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<double>(right))
{
return std::get<int64_t>(left) == std::get<double>(right);
}
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<std::string>(right))
{
return std::get<std::string>(left) == std::get<std::string>(right);
}
else if(std::holds_alternative<bool>(left) && std::holds_alternative<bool>(right))
{
return std::get<bool>(left) == std::get<bool>(right);
}
else if(std::holds_alternative<char>(left) && std::holds_alternative<char>(right))
{
return std::get<char>(left) == std::get<char>(right);
}
else if(std::holds_alternative<char>(left) && std::holds_alternative<int64_t>(right))
{
return std::get<char>(left) == std::get<int64_t>(right);
}
else if(std::holds_alternative<int64_t>(left) && std::holds_alternative<char>(right))
{
return std::get<int64_t>(left) == std::get<char>(right);
}
else if(std::holds_alternative<TVMVersion>(left) && std::holds_alternative<TVMVersion>(right))
{
auto lver= std::get<TVMVersion>(left);
auto rver = std::get<TVMVersion>(right);
auto r = lver.CompareTo(rver);
return r == 0;
}
else if(std::holds_alternative<THeapObjectHolder>(left))
{
auto obj = std::get<THeapObjectHolder>(left).obj;
auto dict = dynamic_cast<TDictionary*>(obj);
auto dynDict = dynamic_cast<TDynamicDictionary*>(obj);
auto native = dynamic_cast<TNative*>(obj);
if(dict != nullptr)
{
gc->BarrierBegin();
TObject fn = dict->GetValue("operator==");
gc->BarrierEnd();
if(!std::holds_alternative<Undefined>(fn))
{
if(std::holds_alternative<THeapObjectHolder>(fn))
{
auto obj = dynamic_cast<TCallable*>(std::get<THeapObjectHolder>(fn).obj);
if(obj != nullptr)
{
auto closure = dynamic_cast<TClosure*>(obj);
if(closure != nullptr)
{
if(!closure->closure->args.empty() && closure->closure->args[0] == "this")
{
return ToBool(obj->Call(ls,{left,right}));
}
else
{
return ToBool(obj->Call(ls,{right}));
}
}
else
{
return ToBool(obj->Call(ls,{right}));
}
}
}
}
return false;
}
else if(dynDict != nullptr)
{
auto res = dynDict->CallMethod(ls,"operator==",{right});
if(!std::holds_alternative<std::nullptr_t>(res) && std::holds_alternative<Undefined>(res))
{
return ToBool(res);
}
}
else if(native != nullptr && std::holds_alternative<std::nullptr_t>(right))
{
return native->GetDestroyed();
}
if(std::holds_alternative<THeapObjectHolder>(right))
{
return obj == std::get<THeapObjectHolder>(right).obj;
}
else if(std::holds_alternative<std::nullptr_t>(right))
{
return false;
}
else if(std::holds_alternative<Undefined>(right))
{
return false;
}
else
{
return false;
}
}
else if(std::holds_alternative<std::nullptr_t>(right))
{
return false;
}
else if(std::holds_alternative<Undefined>(right))
{
return false;
}
else
{
return false;
}
return false;
}
TObject ExecuteFunction(GCList& ls,TCallable* callable, std::vector<TObject> args) TObject ExecuteFunction(GCList& ls,TCallable* callable, std::vector<TObject> args)
{ {
return callable->Call(ls,args); return callable->Call(ls,args);
@ -172,6 +337,20 @@ namespace Tesses::CrossLang {
this->call_stack_entries.back()->Push(ls.GetGC(),Undefined()); this->call_stack_entries.back()->Push(ls.GetGC(),Undefined());
return false; return false;
} }
bool InterperterThread::InterperterThread::Breakpoint(GC* gc)
{
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
GCList ls(gc);
auto res = cse.back()->Pop(ls);
auto env = cse.back()->env;
if(!env->GetRootEnvironment()->HandleBreakpoint(gc, env, res))
{
throw std::exception();
}
return false;
}
bool InterperterThread::Sub(GC* gc) bool InterperterThread::Sub(GC* gc)
{ {
std::vector<CallStackEntry*>& cse=this->call_stack_entries; std::vector<CallStackEntry*>& cse=this->call_stack_entries;
@ -299,8 +478,11 @@ namespace Tesses::CrossLang {
GCList ls(gc); GCList ls(gc);
auto right = cse.back()->Pop(ls); auto right = cse.back()->Pop(ls);
auto left = cse.back()->Pop(ls); auto left = cse.back()->Pop(ls);
if(std::holds_alternative<std::string>(left) && std::holds_alternative<std::string>(right))
if(std::holds_alternative<std::string>(left) && std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(right)) {
cse.back()->Push(gc,Tesses::Framework::Filesystem::VFSPath(std::get<std::string>(left)) / std::get<std::string>(right));
}
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<Tesses::Framework::Filesystem::VFSPath>(right))
{ {
cse.back()->Push(gc,std::get<std::string>(left) / std::get<Tesses::Framework::Filesystem::VFSPath>(right)); cse.back()->Push(gc,std::get<std::string>(left) / std::get<Tesses::Framework::Filesystem::VFSPath>(right));
@ -610,6 +792,10 @@ namespace Tesses::CrossLang {
auto r = lver.CompareTo(rver); auto r = lver.CompareTo(rver);
cse.back()->Push(gc, r < 0); cse.back()->Push(gc, r < 0);
} }
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<std::string>(right))
{
cse.back()->Push(gc, std::get<std::string>(left) < std::get<std::string>(right));
}
else if(std::holds_alternative<THeapObjectHolder>(left)) else if(std::holds_alternative<THeapObjectHolder>(left))
{ {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObjectHolder>(left).obj;
@ -685,6 +871,10 @@ namespace Tesses::CrossLang {
auto r = lver.CompareTo(rver); auto r = lver.CompareTo(rver);
cse.back()->Push(gc, r > 0); cse.back()->Push(gc, r > 0);
} }
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<std::string>(right))
{
cse.back()->Push(gc, std::get<std::string>(left) > std::get<std::string>(right));
}
else if(std::holds_alternative<THeapObjectHolder>(left)) else if(std::holds_alternative<THeapObjectHolder>(left))
{ {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObjectHolder>(left).obj;
@ -759,6 +949,10 @@ namespace Tesses::CrossLang {
auto r = lver.CompareTo(rver); auto r = lver.CompareTo(rver);
cse.back()->Push(gc, r <= 0); cse.back()->Push(gc, r <= 0);
} }
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<std::string>(right))
{
cse.back()->Push(gc, std::get<std::string>(left) <= std::get<std::string>(right));
}
else if(std::holds_alternative<THeapObjectHolder>(left)) else if(std::holds_alternative<THeapObjectHolder>(left))
{ {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObjectHolder>(left).obj;
@ -834,7 +1028,10 @@ namespace Tesses::CrossLang {
auto r = lver.CompareTo(rver); auto r = lver.CompareTo(rver);
cse.back()->Push(gc, r >= 0); cse.back()->Push(gc, r >= 0);
} }
else if(std::holds_alternative<std::string>(left) && std::holds_alternative<std::string>(right))
{
cse.back()->Push(gc, std::get<std::string>(left) >= std::get<std::string>(right));
}
else if(std::holds_alternative<THeapObjectHolder>(left)) else if(std::holds_alternative<THeapObjectHolder>(left))
{ {
auto obj = std::get<THeapObjectHolder>(left).obj; auto obj = std::get<THeapObjectHolder>(left).obj;
@ -2262,6 +2459,8 @@ namespace Tesses::CrossLang {
auto strm = dynamic_cast<TStreamHeapObject*>(obj); auto strm = dynamic_cast<TStreamHeapObject*>(obj);
auto vfs = dynamic_cast<TVFSHeapObject*>(obj); auto vfs = dynamic_cast<TVFSHeapObject*>(obj);
auto env = dynamic_cast<TEnvironment*>(obj); auto env = dynamic_cast<TEnvironment*>(obj);
auto subEnv = dynamic_cast<TSubEnvironment*>(obj);
auto rootEnv = dynamic_cast<TRootEnvironment*>(obj); auto rootEnv = dynamic_cast<TRootEnvironment*>(obj);
auto callable = dynamic_cast<TCallable*>(obj); auto callable = dynamic_cast<TCallable*>(obj);
auto callstackEntry = dynamic_cast<CallStackEntry*>(obj); auto callstackEntry = dynamic_cast<CallStackEntry*>(obj);
@ -2369,6 +2568,17 @@ namespace Tesses::CrossLang {
//TStd::RegisterSqlite //TStd::RegisterSqlite
//TStd::RegisterVM //TStd::RegisterVM
auto myEnv = cse.back()->env->GetRootEnvironment(); auto myEnv = cse.back()->env->GetRootEnvironment();
if(key == "RegisterOnError")
{
TCallable* callable;
if(!rootEnv->permissions.locked && GetArgumentHeap(args,0,callable))
{
gc->BarrierBegin();
rootEnv->RegisterOnError(callable);
gc->BarrierEnd();
}
}
if(key == "RegisterEverything") if(key == "RegisterEverything")
{ {
if(myEnv->permissions.canRegisterEverything) if(myEnv->permissions.canRegisterEverything)
@ -2593,6 +2803,14 @@ namespace Tesses::CrossLang {
return false; return false;
} }
} }
if(subEnv != nullptr)
{
if(key == "GetDictionary")
{
cse.back()->Push(gc,subEnv->GetDictionary());
return false;
}
}
if(env != nullptr) if(env != nullptr)
{ {
@ -2614,6 +2832,7 @@ namespace Tesses::CrossLang {
cse.back()->Push(gc,env->GetRootEnvironment()); cse.back()->Push(gc,env->GetRootEnvironment());
return false; return false;
} }
if(key == "GetSubEnvironment") if(key == "GetSubEnvironment")
{ {
cse.back()->Push(gc,env->GetSubEnvironment(ls)); cse.back()->Push(gc,env->GetSubEnvironment(ls));
@ -3573,6 +3792,48 @@ namespace Tesses::CrossLang {
cse.back()->Push(gc, Undefined()); cse.back()->Push(gc, Undefined());
return false; return false;
} }
if(key == "RemoveAllEqual")
{
if(args.size() != 1)
{
throw VMException("List.RemoveAllEqual must only accept one argument");
}
gc->BarrierBegin();
for(int64_t i = 0; i < list->Count(); i++)
{
if(Equals(gc,args[0],list->Get(i)))
{
list->RemoveAt(i);
i--;
}
}
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
}
if(key == "Remove")
{
if(args.size() != 1)
{
throw VMException("List.Remove must only accept one argument");
}
gc->BarrierBegin();
for(int64_t i = 0; i < list->Count(); i++)
{
if(Equals(gc,args[0],list->Get(i)))
{
list->RemoveAt(i);
break;
}
}
gc->BarrierEnd();
cse.back()->Push(gc, Undefined());
return false;
}
if(key == "RemoveAt") if(key == "RemoveAt")
{ {
if(args.size() != 1) if(args.size() != 1)
@ -4290,6 +4551,7 @@ namespace Tesses::CrossLang {
GCList ls(gc); GCList ls(gc);
auto value = stk->Pop(ls); auto value = stk->Pop(ls);
auto key = stk->Pop(ls); auto key = stk->Pop(ls);
TList* mls;
if(std::holds_alternative<std::string>(key)) if(std::holds_alternative<std::string>(key))
{ {
gc->BarrierBegin(); gc->BarrierBegin();
@ -4297,6 +4559,105 @@ namespace Tesses::CrossLang {
stk->Push(gc, value); stk->Push(gc, value);
gc->BarrierEnd(); gc->BarrierEnd();
} }
else if(GetObjectHeap(key,mls))
{
gc->BarrierBegin();
TList* valueLs;
TDynamicList* valueDynList;
TDictionary* valueDict;
TDynamicDictionary* valueDynDict;
if(GetObjectHeap(value, valueLs))
{
TDictionary* result = TDictionary::Create(ls);
int64_t len = std::min(valueLs->Count(), mls->Count());
for(int64_t i = 0; i < len; i++)
{
std::string mkey;
auto item = mls->Get(i);
if(GetObject(item,mkey))
{
auto val = valueLs->Get(i);
result->SetValue(mkey, val);
stk->env->SetVariable(mkey,val);
}
}
stk->Push(gc,result);
}
else if(GetObjectHeap(value, valueDynList))
{
TDictionary* result = TDictionary::Create(ls);
gc->BarrierEnd();
int64_t len = std::min(valueDynList->Count(ls), mls->Count());
gc->BarrierBegin();
for(int64_t i = 0; i < len; i++)
{
std::string mkey;
auto item = mls->Get(i);
if(GetObject(item,mkey))
{
gc->BarrierEnd();
auto val = valueDynList->GetAt(ls,i);
gc->BarrierBegin();
result->SetValue(mkey, val);
stk->env->SetVariable(mkey,val);
}
}
stk->Push(gc,result);
}
else if(GetObjectHeap(value, valueDict))
{
TDictionary* result = TDictionary::Create(ls);
int64_t len = mls->Count();
for(int64_t i = 0; i < len; i++)
{
std::string mkey;
auto item = mls->Get(i);
if(GetObject(item,mkey))
{
auto val = valueDict->GetValue(mkey);
result->SetValue(mkey, val);
stk->env->SetVariable(mkey,val);
}
}
stk->Push(gc,result);
}
else if(GetObjectHeap(value, valueDynDict))
{
TDictionary* result = TDictionary::Create(ls);
int64_t len =mls->Count();
for(int64_t i = 0; i < len; i++)
{
std::string mkey;
auto item = mls->Get(i);
if(GetObject(item,mkey))
{
gc->BarrierEnd();
auto val = valueDynDict->GetField(ls,mkey);
gc->BarrierBegin();
result->SetValue(mkey, val);
stk->env->SetVariable(mkey,val);
}
}
stk->Push(gc,result);
}
else {
int64_t len =mls->Count();
for(int64_t i = 0; i < len; i++)
{
std::string mkey;
auto item = mls->Get(i);
if(GetObject(item,mkey))
{
stk->env->SetVariable(mkey, value);
}
}
stk->Push(gc, value);
}
gc->BarrierEnd();
}
else else
{ {
throw VMException("[SETVARIABLE] Can't pop string."); throw VMException("[SETVARIABLE] Can't pop string.");
@ -4315,6 +4676,8 @@ namespace Tesses::CrossLang {
auto value = stk->Pop(ls); auto value = stk->Pop(ls);
auto key = stk->Pop(ls); auto key = stk->Pop(ls);
TList* mls;
if(std::holds_alternative<std::string>(key)) if(std::holds_alternative<std::string>(key))
{ {
gc->BarrierBegin(); gc->BarrierBegin();
@ -4322,6 +4685,105 @@ namespace Tesses::CrossLang {
stk->Push(gc, value); stk->Push(gc, value);
gc->BarrierEnd(); gc->BarrierEnd();
} }
else if(GetObjectHeap(key,mls))
{
gc->BarrierBegin();
TList* valueLs;
TDynamicList* valueDynList;
TDictionary* valueDict;
TDynamicDictionary* valueDynDict;
if(GetObjectHeap(value, valueLs))
{
TDictionary* result = TDictionary::Create(ls);
int64_t len = std::min(valueLs->Count(), mls->Count());
for(int64_t i = 0; i < len; i++)
{
std::string mkey;
auto item = mls->Get(i);
if(GetObject(item,mkey))
{
auto val = valueLs->Get(i);
result->SetValue(mkey, val);
stk->env->DeclareVariable(mkey,val);
}
}
stk->Push(gc,result);
}
else if(GetObjectHeap(value, valueDynList))
{
TDictionary* result = TDictionary::Create(ls);
gc->BarrierEnd();
int64_t len = std::min(valueDynList->Count(ls), mls->Count());
gc->BarrierBegin();
for(int64_t i = 0; i < len; i++)
{
std::string mkey;
auto item = mls->Get(i);
if(GetObject(item,mkey))
{
gc->BarrierEnd();
auto val = valueDynList->GetAt(ls,i);
gc->BarrierBegin();
result->SetValue(mkey, val);
stk->env->DeclareVariable(mkey,val);
}
}
stk->Push(gc,result);
}
else if(GetObjectHeap(value, valueDict))
{
TDictionary* result = TDictionary::Create(ls);
int64_t len = mls->Count();
for(int64_t i = 0; i < len; i++)
{
std::string mkey;
auto item = mls->Get(i);
if(GetObject(item,mkey))
{
auto val = valueDict->GetValue(mkey);
result->SetValue(mkey, val);
stk->env->DeclareVariable(mkey,val);
}
}
stk->Push(gc,result);
}
else if(GetObjectHeap(value, valueDynDict))
{
TDictionary* result = TDictionary::Create(ls);
int64_t len =mls->Count();
for(int64_t i = 0; i < len; i++)
{
std::string mkey;
auto item = mls->Get(i);
if(GetObject(item,mkey))
{
gc->BarrierEnd();
auto val = valueDynDict->GetField(ls,mkey);
gc->BarrierBegin();
result->SetValue(mkey, val);
stk->env->DeclareVariable(mkey,val);
}
}
stk->Push(gc,result);
}
else {
int64_t len =mls->Count();
for(int64_t i = 0; i < len; i++)
{
std::string mkey;
auto item = mls->Get(i);
if(GetObject(item,mkey))
{
stk->env->DeclareVariable(mkey, value);
}
}
stk->Push(gc, value);
}
gc->BarrierEnd();
}
else else
{ {
throw VMException("[DECLAREVARIABLE] Can't pop string."); throw VMException("[DECLAREVARIABLE] Can't pop string.");
@ -4368,6 +4830,8 @@ namespace Tesses::CrossLang {
if(!std::holds_alternative<Undefined>(_res2)) if(!std::holds_alternative<Undefined>(_res2))
{ {
auto env = cse.back()->env;
if(!env->GetRootEnvironment()->HandleException(gc,env, _res2))
throw VMByteCodeException(gc,_res2); throw VMByteCodeException(gc,_res2);
} }
return false; return false;

File diff suppressed because one or more lines are too long