Add dvd builder script
This commit is contained in:
2
.clangd
2
.clangd
@ -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"]
|
||||||
|
|||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -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"
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
20
README.md
20
README.md
@ -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
@ -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)
|
||||||
|
|||||||
@ -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"))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
@ -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))
|
||||||
|
|||||||
470
src/vm/vm.cpp
470
src/vm/vm.cpp
@ -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
Reference in New Issue
Block a user