mirror of
https://git.tesses.org/tesses50/crosslang.git
synced 2026-10-01 09:14:12 +00:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f3bc13e8d | ||
|
|
175afbafeb | ||
|
|
4aab28411a | ||
|
|
c1c3d02bf0 | ||
|
|
2430b62232 |
@@ -5,7 +5,7 @@ on:
|
|||||||
- 'v*'
|
- 'v*'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
TF_VERSION: 0.0.6
|
TF_VERSION: 0.0.7
|
||||||
PACKAGE_AND_BREW: ${{ secrets.PACKAGE_AND_BREW }}
|
PACKAGE_AND_BREW: ${{ secrets.PACKAGE_AND_BREW }}
|
||||||
VERSION: ${{ gitea.ref_name }}
|
VERSION: ${{ gitea.ref_name }}
|
||||||
RESULT_IMAGE_NAME: tesses50/crosslang
|
RESULT_IMAGE_NAME: tesses50/crosslang
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 0.0.10
|
||||||
|
Replace time-based GC with allocation-count trigger, migrate all Create factories to GCList::Create(), fix VFSPath root path, reorder TObject variant
|
||||||
|
|
||||||
## 0.0.9
|
## 0.0.9
|
||||||
Fixed Process.ShellFileOrUrl was broken New.ShellFileOrUrl
|
Fixed Process.ShellFileOrUrl was broken New.ShellFileOrUrl
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@ set(CROSSLANG_STATIC ${TESSESFRAMEWORK_STATIC} CACHE INTERNAL "For CrossLang" FO
|
|||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
TessesFramework
|
TessesFramework
|
||||||
GIT_REPOSITORY https://git.tesses.org/tesses50/tessesframework.git
|
GIT_REPOSITORY https://git.tesses.org/tesses50/tessesframework.git
|
||||||
GIT_TAG bd0587779e68832cf382fe49b6b2e99474bcf81f
|
GIT_TAG 5b54af1728907559999e446e56497055297a3696
|
||||||
)
|
)
|
||||||
set(TESSESFRAMEWORK_ENABLE_EXAMPLES OFF)
|
set(TESSESFRAMEWORK_ENABLE_EXAMPLES OFF)
|
||||||
FetchContent_MakeAvailable(TessesFramework)
|
FetchContent_MakeAvailable(TessesFramework)
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ src/types/class.cpp
|
|||||||
src/types/classenvironment.cpp
|
src/types/classenvironment.cpp
|
||||||
src/types/random.cpp
|
src/types/random.cpp
|
||||||
src/types/queryable.cpp
|
src/types/queryable.cpp
|
||||||
|
src/types/exception.cpp
|
||||||
src/vm/filereader.cpp
|
src/vm/filereader.cpp
|
||||||
src/vm/gc.cpp
|
src/vm/gc.cpp
|
||||||
src/vm/gclist.cpp
|
src/vm/gclist.cpp
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
set(CROSSLANG_MAJOR_VERSION 0)
|
set(CROSSLANG_MAJOR_VERSION 0)
|
||||||
set(CROSSLANG_MINOR_VERSION 0)
|
set(CROSSLANG_MINOR_VERSION 0)
|
||||||
set(CROSSLANG_PATCH_VERSION 9)
|
set(CROSSLANG_PATCH_VERSION 10)
|
||||||
|
|||||||
+550
-140
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -44,7 +44,7 @@ void CrossArchiveCreate(
|
|||||||
strs.push_back("Console");
|
strs.push_back("Console");
|
||||||
strs.push_back("WriteLine");
|
strs.push_back("WriteLine");
|
||||||
strs.push_back("You are trying to run a crvm archive, stop it you won't "
|
strs.push_back("You are trying to run a crvm archive, stop it you won't "
|
||||||
"get anywhere!\nUse crossarchiveextract instead.");
|
"get anywhere!\nUse crosslang archiveextract instead.");
|
||||||
|
|
||||||
std::vector<std::string> resources;
|
std::vector<std::string> resources;
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ SyntaxNode Deserialize(std::string astData) {
|
|||||||
}
|
}
|
||||||
#if defined(CROSSLANG_ENABLE_JSON)
|
#if defined(CROSSLANG_ENABLE_JSON)
|
||||||
static json_t *Serialize2(SyntaxNode node) {
|
static json_t *Serialize2(SyntaxNode node) {
|
||||||
if (std::holds_alternative<std::nullptr_t>(node))
|
if (IsNull(node))
|
||||||
return json_null();
|
return json_null();
|
||||||
if (std::holds_alternative<int64_t>(node)) {
|
if (std::holds_alternative<int64_t>(node)) {
|
||||||
return json_integer(std::get<int64_t>(node));
|
return json_integer(std::get<int64_t>(node));
|
||||||
|
|||||||
+113
-29
@@ -175,7 +175,7 @@ void CodeGen::WriteMetadataObject(std::vector<uint8_t> &bytes, SyntaxNode n) {
|
|||||||
std::vector<SyntaxNode> itms;
|
std::vector<SyntaxNode> itms;
|
||||||
if (asn.nodes.size() > 0)
|
if (asn.nodes.size() > 0)
|
||||||
|
|
||||||
GetFunctionArgs(itms, asn.nodes[0]);
|
FlattenCommas(itms, asn.nodes[0]);
|
||||||
bytes.push_back(7);
|
bytes.push_back(7);
|
||||||
size_t offset = bytes.size();
|
size_t offset = bytes.size();
|
||||||
bytes.resize(offset + 4);
|
bytes.resize(offset + 4);
|
||||||
@@ -189,7 +189,7 @@ void CodeGen::WriteMetadataObject(std::vector<uint8_t> &bytes, SyntaxNode n) {
|
|||||||
std::vector<SyntaxNode> itms;
|
std::vector<SyntaxNode> itms;
|
||||||
if (asn.nodes.size() > 0)
|
if (asn.nodes.size() > 0)
|
||||||
|
|
||||||
GetFunctionArgs(itms, asn.nodes[0]);
|
FlattenCommas(itms, asn.nodes[0]);
|
||||||
bytes.push_back(8);
|
bytes.push_back(8);
|
||||||
size_t offset = bytes.size();
|
size_t offset = bytes.size();
|
||||||
bytes.resize(offset + 4);
|
bytes.resize(offset + 4);
|
||||||
@@ -827,6 +827,8 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
size_t fnindex = this->chunks.size();
|
size_t fnindex = this->chunks.size();
|
||||||
ent.closure = (uint32_t)fnindex;
|
ent.closure = (uint32_t)fnindex;
|
||||||
this->chunks.resize(fnindex + 1);
|
this->chunks.resize(fnindex + 1);
|
||||||
|
|
||||||
|
std::vector<ByteCodeInstruction *> fnInstructions;
|
||||||
auto &nameAndArgs =
|
auto &nameAndArgs =
|
||||||
std::get<AdvancedSyntaxNode>(adv2.nodes[2]);
|
std::get<AdvancedSyntaxNode>(adv2.nodes[2]);
|
||||||
if (nameAndArgs.nodeName == FunctionCallExpression &&
|
if (nameAndArgs.nodeName == FunctionCallExpression &&
|
||||||
@@ -844,14 +846,13 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
std::get<std::string>(getvar.nodes[0]));
|
std::get<std::string>(getvar.nodes[0]));
|
||||||
if (nameAndArgs.nodes.size() > 1) {
|
if (nameAndArgs.nodes.size() > 1) {
|
||||||
GetFunctionArgs(ent.arguments,
|
GetFunctionArgs(ent.arguments,
|
||||||
|
fnInstructions,
|
||||||
nameAndArgs.nodes[1]);
|
nameAndArgs.nodes[1]);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ByteCodeInstruction *> fnInstructions;
|
|
||||||
|
|
||||||
GenNode(fnInstructions, adv2.nodes[3], 0, -1, -1, -1,
|
GenNode(fnInstructions, adv2.nodes[3], 0, -1, -1, -1,
|
||||||
-1);
|
-1);
|
||||||
|
|
||||||
@@ -881,7 +882,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
ent.name = GetString(
|
ent.name = GetString(
|
||||||
std::get<std::string>(getvar.nodes[0]));
|
std::get<std::string>(getvar.nodes[0]));
|
||||||
if (nameAndArgs.nodes.size() > 1) {
|
if (nameAndArgs.nodes.size() > 1) {
|
||||||
GetFunctionArgs(ent.arguments,
|
FlattenCommas(ent.arguments,
|
||||||
nameAndArgs.nodes[1]);
|
nameAndArgs.nodes[1]);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@@ -1041,13 +1042,13 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
}
|
}
|
||||||
if (item.first.second.nodeName == DefaultStatement) {
|
if (item.first.second.nodeName == DefaultStatement) {
|
||||||
if (!defaultJmp.empty())
|
if (!defaultJmp.empty())
|
||||||
std::cout << "ERROR: multiple default in "
|
Tesses::Framework::Console::WriteLine(
|
||||||
|
"ERROR: multiple default in "
|
||||||
"switch statement will cause "
|
"switch statement will cause "
|
||||||
"undefined behaviour, this is not "
|
"undefined behaviour, this is not "
|
||||||
"an exception due to not allowing "
|
"an exception due to not allowing "
|
||||||
"exceptions in codegen stage (the "
|
"exceptions in codegen stage (the "
|
||||||
"compilation shouldn't fail)"
|
"compilation shouldn't fail)");
|
||||||
<< std::endl;
|
|
||||||
defaultJmp = item.first.first;
|
defaultJmp = item.first.first;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1223,7 +1224,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
std::vector<SyntaxNode> itms;
|
std::vector<SyntaxNode> itms;
|
||||||
if (adv.nodes.size() > 0)
|
if (adv.nodes.size() > 0)
|
||||||
|
|
||||||
GetFunctionArgs(itms, adv.nodes[0]);
|
FlattenCommas(itms, adv.nodes[0]);
|
||||||
for (auto item : itms) {
|
for (auto item : itms) {
|
||||||
GenNode(instructions, item, scope, contscope, brkscope, contI,
|
GenNode(instructions, item, scope, contscope, brkscope, contI,
|
||||||
brkI);
|
brkI);
|
||||||
@@ -1233,7 +1234,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
instructions.push_back(new SimpleInstruction(CREATEDICTIONARY));
|
instructions.push_back(new SimpleInstruction(CREATEDICTIONARY));
|
||||||
std::vector<SyntaxNode> itms;
|
std::vector<SyntaxNode> itms;
|
||||||
if (adv.nodes.size() > 0)
|
if (adv.nodes.size() > 0)
|
||||||
GetFunctionArgs(itms, adv.nodes[0]);
|
FlattenCommas(itms, adv.nodes[0]);
|
||||||
for (auto item : itms) {
|
for (auto item : itms) {
|
||||||
if (std::holds_alternative<AdvancedSyntaxNode>(item)) {
|
if (std::holds_alternative<AdvancedSyntaxNode>(item)) {
|
||||||
auto tkn = std::get<AdvancedSyntaxNode>(item);
|
auto tkn = std::get<AdvancedSyntaxNode>(item);
|
||||||
@@ -1273,7 +1274,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
contI, brkI);
|
contI, brkI);
|
||||||
if (adv.nodes.size() == 2) {
|
if (adv.nodes.size() == 2) {
|
||||||
std::vector<SyntaxNode> nodes;
|
std::vector<SyntaxNode> nodes;
|
||||||
GetFunctionArgs(nodes, adv.nodes[1]);
|
FlattenCommas(nodes, adv.nodes[1]);
|
||||||
for (auto item : nodes)
|
for (auto item : nodes)
|
||||||
GenNode(instructions, item, scope, contscope, brkscope,
|
GenNode(instructions, item, scope, contscope, brkscope,
|
||||||
contI, brkI);
|
contI, brkI);
|
||||||
@@ -1288,7 +1289,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
contI, brkI);
|
contI, brkI);
|
||||||
if (adv.nodes.size() == 2) {
|
if (adv.nodes.size() == 2) {
|
||||||
std::vector<SyntaxNode> nodes;
|
std::vector<SyntaxNode> nodes;
|
||||||
GetFunctionArgs(nodes, adv.nodes[1]);
|
FlattenCommas(nodes, adv.nodes[1]);
|
||||||
for (auto item : nodes)
|
for (auto item : nodes)
|
||||||
GenNode(instructions, item, scope, contscope, brkscope,
|
GenNode(instructions, item, scope, contscope, brkscope,
|
||||||
contI, brkI);
|
contI, brkI);
|
||||||
@@ -1555,7 +1556,8 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
|
|
||||||
} else if (adv.nodeName == ContinueStatement) {
|
} else if (adv.nodeName == ContinueStatement) {
|
||||||
if (contscope == -1) {
|
if (contscope == -1) {
|
||||||
std::cout << "WARN: continue does nothing here\n";
|
Tesses::Framework::Console::WriteLine(
|
||||||
|
"WARN: continue does nothing here");
|
||||||
} else if (contscope == -2) {
|
} else if (contscope == -2) {
|
||||||
instructions.push_back(new SimpleInstruction(PUSHCONTINUE));
|
instructions.push_back(new SimpleInstruction(PUSHCONTINUE));
|
||||||
instructions.push_back(new SimpleInstruction(RET));
|
instructions.push_back(new SimpleInstruction(RET));
|
||||||
@@ -1572,7 +1574,8 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
}
|
}
|
||||||
} else if (adv.nodeName == BreakStatement) {
|
} else if (adv.nodeName == BreakStatement) {
|
||||||
if (brkscope == -1) {
|
if (brkscope == -1) {
|
||||||
std::cout << "WARN: break does nothing here\n";
|
Tesses::Framework::Console::WriteLine(
|
||||||
|
"WARN: break does nothing here");
|
||||||
} else if (brkscope == -2) {
|
} else if (brkscope == -2) {
|
||||||
instructions.push_back(new SimpleInstruction(PUSHBREAK));
|
instructions.push_back(new SimpleInstruction(PUSHBREAK));
|
||||||
instructions.push_back(new SimpleInstruction(RET));
|
instructions.push_back(new SimpleInstruction(RET));
|
||||||
@@ -1978,7 +1981,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
//(a,b) => {}
|
//(a,b) => {}
|
||||||
// it has two args
|
// it has two args
|
||||||
std::vector<uint32_t> args;
|
std::vector<uint32_t> args;
|
||||||
GetFunctionArgs(args, adv.nodes[0]);
|
FlattenCommas(args, adv.nodes[0]);
|
||||||
|
|
||||||
std::vector<ByteCodeInstruction *> fnInstructions;
|
std::vector<ByteCodeInstruction *> fnInstructions;
|
||||||
size_t fnindex = this->chunks.size();
|
size_t fnindex = this->chunks.size();
|
||||||
@@ -2008,12 +2011,11 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
// Name => {}
|
// Name => {}
|
||||||
//(a,b) => {}
|
//(a,b) => {}
|
||||||
// it has two args
|
// it has two args
|
||||||
std::vector<uint32_t> args;
|
|
||||||
GetFunctionArgs(args, adv.nodes[0]);
|
|
||||||
|
|
||||||
std::vector<ByteCodeInstruction *> fnInstructions;
|
std::vector<ByteCodeInstruction *> fnInstructions;
|
||||||
size_t fnindex = this->chunks.size();
|
size_t fnindex = this->chunks.size();
|
||||||
this->chunks.resize(fnindex + 1);
|
this->chunks.resize(fnindex + 1);
|
||||||
|
std::vector<uint32_t> args;
|
||||||
|
GetFunctionArgs(args, fnInstructions, adv.nodes[0]);
|
||||||
|
|
||||||
auto body = adv.nodes[1];
|
auto body = adv.nodes[1];
|
||||||
|
|
||||||
@@ -2060,18 +2062,20 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void CodeGen::GetFunctionArgs(std::vector<SyntaxNode> &args, SyntaxNode n) {
|
void CodeGen::FlattenCommas(std::vector<SyntaxNode> &args, SyntaxNode n) {
|
||||||
AdvancedSyntaxNode sn;
|
AdvancedSyntaxNode sn;
|
||||||
if (std::holds_alternative<AdvancedSyntaxNode>(n) &&
|
if (std::holds_alternative<AdvancedSyntaxNode>(n) &&
|
||||||
(sn = std::get<AdvancedSyntaxNode>(n)).nodeName == CommaExpression &&
|
(sn = std::get<AdvancedSyntaxNode>(n)).nodeName == CommaExpression &&
|
||||||
sn.nodes.size() == 2) {
|
sn.nodes.size() == 2) {
|
||||||
GetFunctionArgs(args, sn.nodes[0]);
|
FlattenCommas(args, sn.nodes[0]);
|
||||||
GetFunctionArgs(args, sn.nodes[1]);
|
FlattenCommas(args, sn.nodes[1]);
|
||||||
} else {
|
} else {
|
||||||
args.push_back(n);
|
args.push_back(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void CodeGen::GetFunctionArgs(std::vector<uint32_t> &name, SyntaxNode n) {
|
void CodeGen::GetFunctionArgs(std::vector<uint32_t> &name,
|
||||||
|
std::vector<ByteCodeInstruction *> &instrs,
|
||||||
|
SyntaxNode n) {
|
||||||
if (std::holds_alternative<std::nullptr_t>(n))
|
if (std::holds_alternative<std::nullptr_t>(n))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -2079,10 +2083,90 @@ void CodeGen::GetFunctionArgs(std::vector<uint32_t> &name, SyntaxNode n) {
|
|||||||
auto res = std::get<AdvancedSyntaxNode>(n);
|
auto res = std::get<AdvancedSyntaxNode>(n);
|
||||||
if (res.nodeName == ParenthesesExpression) {
|
if (res.nodeName == ParenthesesExpression) {
|
||||||
for (auto n : res.nodes)
|
for (auto n : res.nodes)
|
||||||
GetFunctionArgs(name, n);
|
GetFunctionArgs(name, instrs, n);
|
||||||
|
} else if (res.nodeName == AssignExpression && res.nodes.size() == 2) {
|
||||||
|
// ennsure the left argument is a getVariableExpression
|
||||||
|
if (std::holds_alternative<AdvancedSyntaxNode>(res.nodes[0])) {
|
||||||
|
auto left = std::get<AdvancedSyntaxNode>(res.nodes[0]);
|
||||||
|
|
||||||
|
if (left.nodeName == GetVariableExpression &&
|
||||||
|
!left.nodes.empty() &&
|
||||||
|
std::holds_alternative<std::string>(left.nodes[0])) {
|
||||||
|
std::string key = std::get<std::string>(left.nodes[0]);
|
||||||
|
if (key.size() >= 2 && key[0] == '$' && key[1] == '$') {
|
||||||
|
Tesses::Framework::Console::WriteLine(
|
||||||
|
"WARN: you can't assign variadic functions to a "
|
||||||
|
"default value, this will be an "
|
||||||
|
"error on future release.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.size() > 0 && key[0] == '$') {
|
||||||
|
key.erase(key.cbegin());
|
||||||
|
}
|
||||||
|
|
||||||
|
name.push_back(GetString('$' + key));
|
||||||
|
|
||||||
|
uint32_t ifId = NewId();
|
||||||
|
std::string compGenSetVar = "__compGenSetVar";
|
||||||
|
compGenSetVar.append(std::to_string(ifId));
|
||||||
|
|
||||||
|
std::string compGenSetVarEnd = "__compGenSetVarEnd";
|
||||||
|
compGenSetVarEnd.append(std::to_string(ifId));
|
||||||
|
GenNode(instrs,
|
||||||
|
AdvancedSyntaxNode::Create(GetVariableExpression,
|
||||||
|
true, {key}),
|
||||||
|
0, -1, -1, -1, -1);
|
||||||
|
instrs.push_back(new JumpStyleInstruction(
|
||||||
|
Tesses::CrossLang::Instruction::JMPUNDEFINED,
|
||||||
|
compGenSetVar));
|
||||||
|
instrs.push_back(new SimpleInstruction(POP));
|
||||||
|
instrs.push_back(new JumpStyleInstruction(
|
||||||
|
Tesses::CrossLang::Instruction::JMP, compGenSetVarEnd));
|
||||||
|
instrs.push_back(new LabelInstruction(compGenSetVar));
|
||||||
|
GenNode(instrs,
|
||||||
|
AdvancedSyntaxNode::Create(
|
||||||
|
AssignExpression, true,
|
||||||
|
{AdvancedSyntaxNode::Create(DeclareExpression,
|
||||||
|
true, {key}),
|
||||||
|
res.nodes[1]}),
|
||||||
|
|
||||||
|
0, -1, -1, -1, -1);
|
||||||
|
instrs.push_back(new SimpleInstruction(POP));
|
||||||
|
instrs.push_back(new LabelInstruction(compGenSetVarEnd));
|
||||||
|
} else {
|
||||||
|
Tesses::Framework::Console::WriteLine(
|
||||||
|
"WARN: assignment does not assign arg, this will be an "
|
||||||
|
"error on future release.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Tesses::Framework::Console::WriteLine(
|
||||||
|
"WARN: assignment does not assign arg, this will be an "
|
||||||
|
"error on future release.");
|
||||||
|
}
|
||||||
} else if (res.nodeName == CommaExpression && res.nodes.size() == 2) {
|
} else if (res.nodeName == CommaExpression && res.nodes.size() == 2) {
|
||||||
GetFunctionArgs(name, res.nodes[0]);
|
GetFunctionArgs(name, instrs, res.nodes[0]);
|
||||||
GetFunctionArgs(name, res.nodes[1]);
|
GetFunctionArgs(name, instrs, res.nodes[1]);
|
||||||
|
} else if (res.nodeName == GetVariableExpression &&
|
||||||
|
res.nodes.size() == 1) {
|
||||||
|
if (std::holds_alternative<std::string>(res.nodes[0])) {
|
||||||
|
name.push_back(GetString(std::get<std::string>(res.nodes[0])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void CodeGen::FlattenCommas(std::vector<uint32_t> &name, SyntaxNode n) {
|
||||||
|
if (std::holds_alternative<std::nullptr_t>(n))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (std::holds_alternative<AdvancedSyntaxNode>(n)) {
|
||||||
|
auto res = std::get<AdvancedSyntaxNode>(n);
|
||||||
|
if (res.nodeName == ParenthesesExpression) {
|
||||||
|
for (auto n : res.nodes)
|
||||||
|
FlattenCommas(name, n);
|
||||||
|
} else if (res.nodeName == CommaExpression && res.nodes.size() == 2) {
|
||||||
|
FlattenCommas(name, res.nodes[0]);
|
||||||
|
FlattenCommas(name, res.nodes[1]);
|
||||||
} else if (res.nodeName == GetVariableExpression &&
|
} else if (res.nodeName == GetVariableExpression &&
|
||||||
res.nodes.size() == 1) {
|
res.nodes.size() == 1) {
|
||||||
if (std::holds_alternative<std::string>(res.nodes[0])) {
|
if (std::holds_alternative<std::string>(res.nodes[0])) {
|
||||||
@@ -2175,14 +2259,14 @@ void CodeGen::GenRoot(SyntaxNode n) {
|
|||||||
functionName.insert(
|
functionName.insert(
|
||||||
functionName.begin(),
|
functionName.begin(),
|
||||||
{GetString(documentation)});
|
{GetString(documentation)});
|
||||||
if (fcalli.nodes.size() == 2)
|
|
||||||
GetFunctionArgs(args,
|
|
||||||
fcalli.nodes[1]);
|
|
||||||
|
|
||||||
std::vector<ByteCodeInstruction *>
|
std::vector<ByteCodeInstruction *>
|
||||||
fnInstructions;
|
fnInstructions;
|
||||||
size_t fnindex = this->chunks.size();
|
size_t fnindex = this->chunks.size();
|
||||||
this->chunks.resize(fnindex + 1);
|
this->chunks.resize(fnindex + 1);
|
||||||
|
if (fcalli.nodes.size() == 2)
|
||||||
|
GetFunctionArgs(args,
|
||||||
|
fnInstructions,
|
||||||
|
fcalli.nodes[1]);
|
||||||
|
|
||||||
GenNode(fnInstructions, res2.nodes[1],
|
GenNode(fnInstructions, res2.nodes[1],
|
||||||
0, -1, -1, -1, -1);
|
0, -1, -1, -1, -1);
|
||||||
|
|||||||
@@ -482,6 +482,7 @@ int Lex(std::string filename, std::istream &strm,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '<':
|
case '<':
|
||||||
|
case '>':
|
||||||
case '?':
|
case '?':
|
||||||
if (peek == read) {
|
if (peek == read) {
|
||||||
Flush();
|
Flush();
|
||||||
@@ -532,7 +533,6 @@ int Lex(std::string filename, std::istream &strm,
|
|||||||
case '^':
|
case '^':
|
||||||
case '~':
|
case '~':
|
||||||
case '!':
|
case '!':
|
||||||
case '>':
|
|
||||||
case '*':
|
case '*':
|
||||||
case '%':
|
case '%':
|
||||||
//*
|
//*
|
||||||
|
|||||||
+12
-151
@@ -5,7 +5,7 @@ namespace Tesses::CrossLang {
|
|||||||
SyntaxNode TObject2SyntaxNode(TObject o) {
|
SyntaxNode TObject2SyntaxNode(TObject o) {
|
||||||
if (std::holds_alternative<Undefined>(o))
|
if (std::holds_alternative<Undefined>(o))
|
||||||
return Undefined();
|
return Undefined();
|
||||||
if (std::holds_alternative<std::nullptr_t>(o))
|
if (IsNull(o))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (std::holds_alternative<std::string>(o))
|
if (std::holds_alternative<std::string>(o))
|
||||||
return std::get<std::string>(o);
|
return std::get<std::string>(o);
|
||||||
@@ -115,59 +115,17 @@ bool Parser::IsIdentifier(std::string txt, bool pop) {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::IsAnySymbol(std::initializer_list<std::string> idents, bool pop) {
|
bool Parser::IsAnySymbol(std::initializer_list<std::string> idents, bool pop) {
|
||||||
|
|
||||||
if (i < tokens.size()) {
|
if (i < tokens.size()) {
|
||||||
if (tokens[i].type != LexTokenType::Symbol)
|
if (tokens[i].type != LexTokenType::Symbol)
|
||||||
return false;
|
return false;
|
||||||
for (auto item : idents) {
|
for (auto item : idents) {
|
||||||
if (item == ">") {
|
|
||||||
if (i + 1 < tokens.size()) {
|
|
||||||
if ((tokens[i + 1].text == ">" ||
|
|
||||||
tokens[i + 1].text == ">=") &&
|
|
||||||
tokens[i + 1].type == LexTokenType::Symbol)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (item == tokens[i].text) {
|
if (item == tokens[i].text) {
|
||||||
tkn = tokens[i];
|
tkn = tokens[i];
|
||||||
if (pop)
|
if (pop)
|
||||||
i++;
|
i++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (item == ">>=") {
|
|
||||||
if (i + 1 < tokens.size()) {
|
|
||||||
if (tokens[i].text == ">" && tokens[i + 1].text == ">=" &&
|
|
||||||
tokens[i].type == LexTokenType::Symbol &&
|
|
||||||
tokens[i + 1].type == LexTokenType::Symbol) {
|
|
||||||
tkn = tokens[i];
|
|
||||||
tkn.text = ">>=";
|
|
||||||
if (pop)
|
|
||||||
i += 2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (item == ">>") {
|
|
||||||
if (i + 1 < tokens.size()) {
|
|
||||||
if (tokens[i].text == ">" && tokens[i + 1].text == ">" &&
|
|
||||||
tokens[i].type == LexTokenType::Symbol &&
|
|
||||||
tokens[i + 1].type == LexTokenType::Symbol) {
|
|
||||||
tkn = tokens[i];
|
|
||||||
tkn.text = ">>";
|
|
||||||
if (pop)
|
|
||||||
i += 2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (item == tokens[i].text) {
|
|
||||||
tkn = tokens[i];
|
|
||||||
if (pop)
|
|
||||||
i++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -176,45 +134,7 @@ bool Parser::IsSymbol(std::string txt, bool pop) {
|
|||||||
if (i < tokens.size()) {
|
if (i < tokens.size()) {
|
||||||
if (tokens[i].type != LexTokenType::Symbol)
|
if (tokens[i].type != LexTokenType::Symbol)
|
||||||
return false;
|
return false;
|
||||||
if (txt == ">") {
|
if (tokens[i].text == txt) {
|
||||||
if (i + 1 < tokens.size()) {
|
|
||||||
if ((tokens[i + 1].text == ">" || tokens[i + 1].text == ">=") &&
|
|
||||||
tokens[i + 1].type == LexTokenType::Symbol)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (txt == tokens[i].text) {
|
|
||||||
tkn = tokens[i];
|
|
||||||
if (pop)
|
|
||||||
i++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (txt == ">>=") {
|
|
||||||
if (i + 1 < tokens.size()) {
|
|
||||||
|
|
||||||
if (tokens[i].text == ">" && tokens[i + 1].text == ">=" &&
|
|
||||||
tokens[i].type == LexTokenType::Symbol &&
|
|
||||||
tokens[i + 1].type == LexTokenType::Symbol) {
|
|
||||||
tkn = tokens[i];
|
|
||||||
tkn.text = ">>=";
|
|
||||||
if (pop)
|
|
||||||
i += 2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (txt == ">>") {
|
|
||||||
if (i + 1 < tokens.size()) {
|
|
||||||
if (tokens[i].text == ">" && tokens[i + 1].text == ">" &&
|
|
||||||
tokens[i].type == LexTokenType::Symbol &&
|
|
||||||
tokens[i + 1].type == LexTokenType::Symbol) {
|
|
||||||
tkn = tokens[i];
|
|
||||||
tkn.text = ">>";
|
|
||||||
if (pop)
|
|
||||||
i += 2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (tokens[i].text == txt) {
|
|
||||||
tkn = tokens[i];
|
tkn = tokens[i];
|
||||||
if (pop)
|
if (pop)
|
||||||
i++;
|
i++;
|
||||||
@@ -233,7 +153,6 @@ static std::string EnsureSafeVariable(LexToken token) {
|
|||||||
}
|
}
|
||||||
void Parser::EnsureSymbol(std::string txt) {
|
void Parser::EnsureSymbol(std::string txt) {
|
||||||
if (i < tokens.size()) {
|
if (i < tokens.size()) {
|
||||||
|
|
||||||
if (tokens[i].type != LexTokenType::Symbol) {
|
if (tokens[i].type != LexTokenType::Symbol) {
|
||||||
throw SyntaxException(
|
throw SyntaxException(
|
||||||
tokens[i].lineInfo,
|
tokens[i].lineInfo,
|
||||||
@@ -241,69 +160,7 @@ void Parser::EnsureSymbol(std::string txt) {
|
|||||||
LexTokenType_ToString(tokens[i].type) + " \"" +
|
LexTokenType_ToString(tokens[i].type) + " \"" +
|
||||||
tokens[i].text + "\" which is not a symbol at all.");
|
tokens[i].text + "\" which is not a symbol at all.");
|
||||||
}
|
}
|
||||||
if (txt == ">") {
|
if (tokens[i].text != txt) {
|
||||||
if (i + 1 < tokens.size()) {
|
|
||||||
if ((tokens[i + 1].text == ">" || tokens[i + 1].text == ">=") &&
|
|
||||||
tokens[i + 1].type == LexTokenType::Symbol)
|
|
||||||
throw SyntaxException(tokens[i].lineInfo,
|
|
||||||
"expected the symbol \"" + txt +
|
|
||||||
"\" but got the symbol \"" +
|
|
||||||
tokens[i].text +
|
|
||||||
tokens[i + 1].text + "\"");
|
|
||||||
;
|
|
||||||
}
|
|
||||||
if (txt == tokens[i].text) {
|
|
||||||
|
|
||||||
tkn = tokens[i];
|
|
||||||
i++;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (txt == ">>=") {
|
|
||||||
if (i + 1 < tokens.size()) {
|
|
||||||
if (tokens[i].text == ">" && tokens[i + 1].text == ">=" &&
|
|
||||||
tokens[i].type == LexTokenType::Symbol &&
|
|
||||||
tokens[i + 1].type == LexTokenType::Symbol) {
|
|
||||||
|
|
||||||
tkn = tokens[i];
|
|
||||||
i += 2;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw SyntaxException(tokens[i].lineInfo,
|
|
||||||
"expected the symbol \"" + txt +
|
|
||||||
"\" but got the symbol \"" +
|
|
||||||
tokens[i].text + tokens[i + 1].text +
|
|
||||||
"\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
throw SyntaxException(tokens[i].lineInfo,
|
|
||||||
"expected the symbol \"" + txt +
|
|
||||||
"\" but got the symbol \"" +
|
|
||||||
tokens[i].text + "\"");
|
|
||||||
} else if (txt == ">>") {
|
|
||||||
if (i + 1 < tokens.size()) {
|
|
||||||
if (tokens[i].text == ">" && tokens[i + 1].text == ">" &&
|
|
||||||
tokens[i].type == LexTokenType::Symbol &&
|
|
||||||
tokens[i + 1].type == LexTokenType::Symbol) {
|
|
||||||
|
|
||||||
tkn = tokens[i];
|
|
||||||
i += 2;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw SyntaxException(tokens[i].lineInfo,
|
|
||||||
"expected the symbol \"" + txt +
|
|
||||||
"\" but got the symbol \"" +
|
|
||||||
tokens[i].text + tokens[i + 1].text +
|
|
||||||
"\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
throw SyntaxException(tokens[i].lineInfo,
|
|
||||||
"expected the symbol \"" + txt +
|
|
||||||
"\" but got the symbol \"" +
|
|
||||||
tokens[i].text + "\"");
|
|
||||||
} else if (tokens[i].text != txt) {
|
|
||||||
|
|
||||||
throw SyntaxException(tokens[i].lineInfo,
|
throw SyntaxException(tokens[i].lineInfo,
|
||||||
"expected the symbol \"" + txt +
|
"expected the symbol \"" + txt +
|
||||||
@@ -633,6 +490,10 @@ void Parser::ParseHtml(std::vector<SyntaxNode> &nodes, std::string var) {
|
|||||||
EnsureSymbol(")");
|
EnsureSymbol(")");
|
||||||
EnsureSymbol(">");
|
EnsureSymbol(">");
|
||||||
|
|
||||||
|
if (std::holds_alternative<std::nullptr_t>(item))
|
||||||
|
item = AdvancedSyntaxNode::Create(DeclareExpression, true,
|
||||||
|
{"item"});
|
||||||
|
|
||||||
std::vector<SyntaxNode> _nodes;
|
std::vector<SyntaxNode> _nodes;
|
||||||
parseFn(_nodes, "each");
|
parseFn(_nodes, "each");
|
||||||
body = AdvancedSyntaxNode::Create(ScopeNode, false, _nodes);
|
body = AdvancedSyntaxNode::Create(ScopeNode, false, _nodes);
|
||||||
@@ -1411,7 +1272,7 @@ SyntaxNode Parser::ParseNode(bool isRoot) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!isRoot)
|
if (!isRoot)
|
||||||
i++;
|
EnsureSymbol("}");
|
||||||
return aSN;
|
return aSN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1517,10 +1378,8 @@ SyntaxNode Parser::ParseNode(bool isRoot) {
|
|||||||
body = ParseNode();
|
body = ParseNode();
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<std::nullptr_t>(item))
|
if (std::holds_alternative<std::nullptr_t>(item))
|
||||||
item = AdvancedSyntaxNode::Create(
|
item =
|
||||||
DeclareExpression, true,
|
AdvancedSyntaxNode::Create(DeclareExpression, true, {"item"});
|
||||||
{AdvancedSyntaxNode::Create(GetVariableExpression, true,
|
|
||||||
{"item"})});
|
|
||||||
|
|
||||||
return AdvancedSyntaxNode::Create(EachStatement, false,
|
return AdvancedSyntaxNode::Create(EachStatement, false,
|
||||||
{item, list, body});
|
{item, list, body});
|
||||||
@@ -2006,6 +1865,8 @@ SyntaxNode Parser::ParseBAnd() {
|
|||||||
SyntaxNode Parser::ParseExpression() {
|
SyntaxNode Parser::ParseExpression() {
|
||||||
SyntaxNode expr = ParseAssignment();
|
SyntaxNode expr = ParseAssignment();
|
||||||
while (IsSymbol(",")) {
|
while (IsSymbol(",")) {
|
||||||
|
if (IsAnySymbol({"]", "}"}, false))
|
||||||
|
break;
|
||||||
expr = AdvancedSyntaxNode::Create(CommaExpression, true,
|
expr = AdvancedSyntaxNode::Create(CommaExpression, true,
|
||||||
{expr, ParseAssignment()});
|
{expr, ParseAssignment()});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ static void Help(std::string &filename) {
|
|||||||
printf(" -n: Set name (MyAppOrLibName defaults to out)\n");
|
printf(" -n: Set name (MyAppOrLibName defaults to out)\n");
|
||||||
printf(" -h, --help: Prints help\n");
|
printf(" -h, --help: Prints help\n");
|
||||||
printf("Options except for help have flag with arg like this: -F ARG\n");
|
printf("Options except for help have flag with arg like this: -F ARG\n");
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t CrossArchiveCreate(std::vector<std::string> &argv) {
|
int64_t CrossArchiveCreate(std::vector<std::string> &argv) {
|
||||||
@@ -53,7 +53,7 @@ int64_t CrossArchiveCreate(std::vector<std::string> &argv) {
|
|||||||
printf("Expected "
|
printf("Expected "
|
||||||
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]"
|
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]"
|
||||||
"]]]\n");
|
"]]]\n");
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ TObject CrossLangShell(GCList &ls, std::vector<std::string> &argv) {
|
|||||||
env->LoadFileWithDependencies(
|
env->LoadFileWithDependencies(
|
||||||
ls.GetGC(), Tesses::Framework::Filesystem::LocalFS, filename);
|
ls.GetGC(), Tesses::Framework::Filesystem::LocalFS, filename);
|
||||||
|
|
||||||
TList *args = TList::Create(ls);
|
TList *args = ls.Create<TList>();
|
||||||
|
|
||||||
args->Add(filename.ToString());
|
args->Add(filename.ToString());
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ static void Help(std::string filename) {
|
|||||||
"for sane with file access to current directory and sub "
|
"for sane with file access to current directory and sub "
|
||||||
"directories, \"full\" has full runtime.\n");
|
"directories, \"full\" has full runtime.\n");
|
||||||
printf("Options except for help have flag with arg like this: -F ARG\n");
|
printf("Options except for help have flag with arg like this: -F ARG\n");
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
void CrossLangCompiler(std::vector<std::string> &argv) {
|
void CrossLangCompiler(std::vector<std::string> &argv) {
|
||||||
/*std::ifstream strm(argv[1],std::ios_base::in|std::ios_base::binary);
|
/*std::ifstream strm(argv[1],std::ios_base::in|std::ios_base::binary);
|
||||||
@@ -107,14 +107,14 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
|
|||||||
printf("Expected "
|
printf("Expected "
|
||||||
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-"
|
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-"
|
||||||
"prod]]]]\n");
|
"prod]]]]\n");
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
dependencies.push_back(
|
dependencies.push_back(
|
||||||
std::pair<std::string, TVMVersion>(str1, v2));
|
std::pair<std::string, TVMVersion>(str1, v2));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
printf("ERROR: Dependency must have version\n");
|
printf("ERROR: Dependency must have version\n");
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (argv[i] == "-t") {
|
} else if (argv[i] == "-t") {
|
||||||
@@ -137,14 +137,14 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
|
|||||||
printf("Expected "
|
printf("Expected "
|
||||||
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-"
|
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-"
|
||||||
"prod]]]]\n");
|
"prod]]]]\n");
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
tools.push_back(
|
tools.push_back(
|
||||||
std::pair<std::string, TVMVersion>(str1, v2));
|
std::pair<std::string, TVMVersion>(str1, v2));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
printf("ERROR: Tool must have version\n");
|
printf("ERROR: Tool must have version\n");
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (argv[i] == "-n") {
|
} else if (argv[i] == "-n") {
|
||||||
@@ -161,7 +161,7 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
|
|||||||
printf("Expected "
|
printf("Expected "
|
||||||
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]"
|
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]"
|
||||||
"]]]\n");
|
"]]]\n");
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (argv[i] == "-D" || argv[i] == "--debug") {
|
} else if (argv[i] == "-D" || argv[i] == "--debug") {
|
||||||
@@ -192,7 +192,7 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
|
|||||||
|
|
||||||
if (comptime == "secure") {
|
if (comptime == "secure") {
|
||||||
TStd::RegisterConsole(gc, env);
|
TStd::RegisterConsole(gc, env);
|
||||||
TStd::RegisterClass(gc, env);
|
TStd::RegisterZeClass(gc, env);
|
||||||
TStd::RegisterCrypto(gc, env);
|
TStd::RegisterCrypto(gc, env);
|
||||||
TStd::RegisterDictionary(gc, env);
|
TStd::RegisterDictionary(gc, env);
|
||||||
TStd::RegisterJson(gc, env);
|
TStd::RegisterJson(gc, env);
|
||||||
@@ -201,7 +201,7 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
|
|||||||
env->permissions.locked = true;
|
env->permissions.locked = true;
|
||||||
} else if (comptime == "secure_file") {
|
} else if (comptime == "secure_file") {
|
||||||
TStd::RegisterConsole(gc, env);
|
TStd::RegisterConsole(gc, env);
|
||||||
TStd::RegisterClass(gc, env);
|
TStd::RegisterZeClass(gc, env);
|
||||||
TStd::RegisterCrypto(gc, env);
|
TStd::RegisterCrypto(gc, env);
|
||||||
TStd::RegisterDictionary(gc, env);
|
TStd::RegisterDictionary(gc, env);
|
||||||
TStd::RegisterJson(gc, env);
|
TStd::RegisterJson(gc, env);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ TObject CrossLangInterperter(GCList &ls, TRootEnvironment *env,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TList *args = TList::Create(ls);
|
TList *args = ls.Create<TList>();
|
||||||
for (int arg = 1; arg < argv.size(); arg++)
|
for (int arg = 1; arg < argv.size(); arg++)
|
||||||
args->Add(std::string(argv[arg]));
|
args->Add(std::string(argv[arg]));
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ TObject CrossLangVM(GCList &ls, TRootEnvironment *env,
|
|||||||
|
|
||||||
env->EnsureDictionary(ls.GetGC(), "Net")
|
env->EnsureDictionary(ls.GetGC(), "Net")
|
||||||
->SetValue("WebServerPort", (int64_t)port);
|
->SetValue("WebServerPort", (int64_t)port);
|
||||||
TList *args2 = TList::Create(ls);
|
TList *args2 = ls.Create<TList>();
|
||||||
for (auto &item : args.positional) {
|
for (auto &item : args.positional) {
|
||||||
args2->Add(item);
|
args2->Add(item);
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ TObject CrossLangVM(GCList &ls, TRootEnvironment *env,
|
|||||||
TF_Quit();
|
TF_Quit();
|
||||||
return (int64_t)0;
|
return (int64_t)0;
|
||||||
} else {
|
} else {
|
||||||
TList *args = TList::Create(ls);
|
TList *args = ls.Create<TList>();
|
||||||
for (size_t arg = 1; arg < argv.size(); arg++)
|
for (size_t arg = 1; arg < argv.size(); arg++)
|
||||||
args->Add(std::string(argv[arg]));
|
args->Add(std::string(argv[arg]));
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
static TList *VectorOfStringToList(GCList &ls, std::vector<std::string> &strs) {
|
static TList *VectorOfStringToList(GCList &ls, std::vector<std::string> &strs) {
|
||||||
TList *list = TList::Create(ls);
|
TList *list = ls.Create<TList>();
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
for (auto &item : strs)
|
for (auto &item : strs)
|
||||||
list->Add(item);
|
list->Add(item);
|
||||||
@@ -10,7 +10,7 @@ static TList *VectorOfStringToList(GCList &ls, std::vector<std::string> &strs) {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
static TList *EntriesToList(GCList &ls, std::vector<TClassEntry> &ents) {
|
static TList *EntriesToList(GCList &ls, std::vector<TClassEntry> &ents) {
|
||||||
TList *list = TList::Create(ls);
|
TList *list = ls.Create<TList>();
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
for (auto &item : ents) {
|
for (auto &item : ents) {
|
||||||
std::string modifier = "public";
|
std::string modifier = "public";
|
||||||
@@ -42,7 +42,7 @@ static TList *EntriesToList(GCList &ls, std::vector<TClassEntry> &ents) {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
static TList *ClassInstanceToList(GCList &ls, TClassObject *co) {
|
static TList *ClassInstanceToList(GCList &ls, TClassObject *co) {
|
||||||
TList *list = TList::Create(ls);
|
TList *list = ls.Create<TList>();
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
for (auto &item : co->entries) {
|
for (auto &item : co->entries) {
|
||||||
if (item.modifier == TClassModifier::Public) {
|
if (item.modifier == TClassModifier::Public) {
|
||||||
@@ -126,7 +126,7 @@ static TObject Class_CreateInstance(TRootEnvironment *env, GCList &ls,
|
|||||||
}
|
}
|
||||||
static TObject Class_GetClassNames(TRootEnvironment *env, GCList &ls,
|
static TObject Class_GetClassNames(TRootEnvironment *env, GCList &ls,
|
||||||
std::vector<TObject> args) {
|
std::vector<TObject> args) {
|
||||||
TList *list = TList::Create(ls);
|
TList *list = ls.Create<TList>();
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
for (auto &item : env->classes) {
|
for (auto &item : env->classes) {
|
||||||
list->Add(JoinPeriod(item.first->classes.at(item.second).name));
|
list->Add(JoinPeriod(item.first->classes.at(item.second).name));
|
||||||
@@ -190,9 +190,9 @@ static TObject Class_GetInfo(TRootEnvironment *env, GCList &ls,
|
|||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
void TStd::RegisterClass(std::shared_ptr<GC> gc, TRootEnvironment *env) {
|
void TStd::RegisterZeClass(std::shared_ptr<GC> gc, TRootEnvironment *env) {
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
env->permissions.canRegisterClass = true;
|
env->permissions.canRegisterZeClass = true;
|
||||||
TDictionary *cls = env->EnsureDictionary(gc, "Class");
|
TDictionary *cls = env->EnsureDictionary(gc, "Class");
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
|
|
||||||
|
|||||||
@@ -72,11 +72,11 @@ TObject Console_Write(GCList &ls, std::vector<TObject> args) {
|
|||||||
TObject Console_Fatal(GCList &ls, std::vector<TObject> args) {
|
TObject Console_Fatal(GCList &ls, std::vector<TObject> args) {
|
||||||
if (args.size() < 1) {
|
if (args.size() < 1) {
|
||||||
Tesses::Framework::Console::ErrorLine("FATAL: <NO MESSAGE>");
|
Tesses::Framework::Console::ErrorLine("FATAL: <NO MESSAGE>");
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
Tesses::Framework::Console::ErrorLine("FATAL: " +
|
Tesses::Framework::Console::ErrorLine("FATAL: " +
|
||||||
ToString(ls.GetGC(), args[0]));
|
ToString(ls.GetGC(), args[0]));
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
TObject Console_WriteLine(GCList &ls, std::vector<TObject> args) {
|
TObject Console_WriteLine(GCList &ls, std::vector<TObject> args) {
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
TObject Dictionary_FindByKey(GCList &ls, std::vector<TObject> args) {
|
TObject Dictionary_FindByKey(GCList &ls, std::vector<TObject> args) {
|
||||||
TList *dest = TList::Create(ls);
|
TList *dest = ls.Create<TList>();
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
std::string key;
|
std::string key;
|
||||||
if (GetArgument(args, 1, key)) {
|
if (GetArgument(args, 1, key)) {
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
#include "CrossLang.hpp"
|
#include "CrossLang.hpp"
|
||||||
#include "TessesFramework/Serialization/BitConverter.hpp"
|
#include "TessesFramework/Serialization/BitConverter.hpp"
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
using namespace Tesses::Framework::Platform::Environment;
|
using namespace Tesses::Framework::Platform::Environment;
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
@@ -95,7 +91,7 @@ static TObject Env_GetRealExecutablePath(GCList &ls,
|
|||||||
}
|
}
|
||||||
static TObject Env_GetAll(GCList &ls, std::vector<TObject> args) {
|
static TObject Env_GetAll(GCList &ls, std::vector<TObject> args) {
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
TList *list = TList::Create(ls);
|
TList *list = ls.Create<TList>();
|
||||||
std::vector<std::pair<std::string, std::string>> env;
|
std::vector<std::pair<std::string, std::string>> env;
|
||||||
Tesses::Framework::Platform::Environment::GetEnvironmentVariables(env);
|
Tesses::Framework::Platform::Environment::GetEnvironmentVariables(env);
|
||||||
for (auto &item : env) {
|
for (auto &item : env) {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ static TObject FS_ReadAllLines(GCList &ls, std::vector<TObject> args) {
|
|||||||
Tesses::Framework::Filesystem::Helpers::ReadAllLines(vfs, path, lines);
|
Tesses::Framework::Filesystem::Helpers::ReadAllLines(vfs, path, lines);
|
||||||
|
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
auto items = TList::Create(ls);
|
auto items = ls.Create<TList>();
|
||||||
for (auto &l : lines) {
|
for (auto &l : lines) {
|
||||||
items->Add(l);
|
items->Add(l);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using namespace Tesses::Framework::Serialization::Json;
|
|||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
|
|
||||||
static bool IsValidForJson(TObject v) {
|
static bool IsValidForJson(TObject v) {
|
||||||
if (std::holds_alternative<std::nullptr_t>(v))
|
if (IsNull(v))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (std::holds_alternative<int64_t>(v))
|
if (std::holds_alternative<int64_t>(v))
|
||||||
@@ -20,10 +20,10 @@ static bool IsValidForJson(TObject v) {
|
|||||||
if (std::holds_alternative<std::string>(v))
|
if (std::holds_alternative<std::string>(v))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (std::holds_alternative<THeapObjectHolder>(v)) {
|
if (std::holds_alternative<THeapObject *>(v)) {
|
||||||
auto res = std::get<THeapObjectHolder>(v);
|
auto res = std::get<THeapObject *>(v);
|
||||||
auto ls = dynamic_cast<TList *>(res.obj);
|
auto ls = dynamic_cast<TList *>(res);
|
||||||
auto dict = dynamic_cast<TDictionary *>(res.obj);
|
auto dict = dynamic_cast<TDictionary *>(res);
|
||||||
if (ls != nullptr)
|
if (ls != nullptr)
|
||||||
return true;
|
return true;
|
||||||
if (dict != nullptr)
|
if (dict != nullptr)
|
||||||
@@ -32,7 +32,7 @@ static bool IsValidForJson(TObject v) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
static JToken JsonSerialize(TObject v) {
|
static JToken JsonSerialize(TObject v) {
|
||||||
if (std::holds_alternative<std::nullptr_t>(v))
|
if (IsNull(v))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (std::holds_alternative<int64_t>(v))
|
if (std::holds_alternative<int64_t>(v))
|
||||||
return std::get<int64_t>(v);
|
return std::get<int64_t>(v);
|
||||||
@@ -42,8 +42,8 @@ static JToken JsonSerialize(TObject v) {
|
|||||||
return std::get<bool>(v);
|
return std::get<bool>(v);
|
||||||
if (std::holds_alternative<std::string>(v))
|
if (std::holds_alternative<std::string>(v))
|
||||||
return std::get<std::string>(v);
|
return std::get<std::string>(v);
|
||||||
if (std::holds_alternative<THeapObjectHolder>(v)) {
|
if (std::holds_alternative<THeapObject *>(v)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(v).obj;
|
auto obj = std::get<THeapObject *>(v);
|
||||||
auto ls = dynamic_cast<TList *>(obj);
|
auto ls = dynamic_cast<TList *>(obj);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ static TObject JsonDeserialize(GCList &ls2, JToken json) {
|
|||||||
if (TryGetJToken(json, str))
|
if (TryGetJToken(json, str))
|
||||||
return str;
|
return str;
|
||||||
if (TryGetJToken(json, arr)) {
|
if (TryGetJToken(json, arr)) {
|
||||||
TList *ls = TList::Create(ls2);
|
TList *ls = ls2.Create<TList>();
|
||||||
|
|
||||||
for (auto &item : arr) {
|
for (auto &item : arr) {
|
||||||
auto itemRes = JsonDeserialize(ls2, item);
|
auto itemRes = JsonDeserialize(ls2, item);
|
||||||
@@ -159,7 +159,7 @@ static TObject JsonDocDecode(GCList &ls2, std::vector<TObject> args) {
|
|||||||
std::string Json_Encode(TObject o, bool indent) {
|
std::string Json_Encode(TObject o, bool indent) {
|
||||||
return Json::Encode(JsonSerialize(o), indent);
|
return Json::Encode(JsonSerialize(o), indent);
|
||||||
}
|
}
|
||||||
TObject Json_Decode(GCList ls, std::string str) {
|
TObject Json_Decode(GCList &ls, std::string str) {
|
||||||
return JsonDeserialize(ls, Json::Decode(str));
|
return JsonDeserialize(ls, Json::Decode(str));
|
||||||
}
|
}
|
||||||
std::string Json_DocEncode(TObject o, bool indent) {
|
std::string Json_DocEncode(TObject o, bool indent) {
|
||||||
@@ -169,7 +169,7 @@ std::string Json_DocEncode(TObject o, bool indent) {
|
|||||||
return Json::DocEncode(ls, indent);
|
return Json::DocEncode(ls, indent);
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
TObject Json_DocDecode(GCList ls, std::string str) {
|
TObject Json_DocDecode(GCList &ls, std::string str) {
|
||||||
return JsonDeserialize(ls, Json::DocDecode(str));
|
return JsonDeserialize(ls, Json::DocDecode(str));
|
||||||
}
|
}
|
||||||
void TStd::RegisterJson(std::shared_ptr<GC> gc, TRootEnvironment *env) {
|
void TStd::RegisterJson(std::shared_ptr<GC> gc, TRootEnvironment *env) {
|
||||||
|
|||||||
+65
-24
@@ -17,13 +17,13 @@ static std::shared_ptr<SMTPBody>
|
|||||||
TObjectToSMTPBody(GCList &ls, std::string mimeType, TObject obj) {
|
TObjectToSMTPBody(GCList &ls, std::string mimeType, TObject obj) {
|
||||||
std::shared_ptr<SMTPBody> body;
|
std::shared_ptr<SMTPBody> body;
|
||||||
std::string text;
|
std::string text;
|
||||||
TByteArray *ba;
|
TByteView *ba;
|
||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> sho;
|
std::shared_ptr<Tesses::Framework::Streams::Stream> sho;
|
||||||
if (GetObject(obj, text)) {
|
if (GetObject(obj, text)) {
|
||||||
body = std::make_shared<SMTPStringBody>(text, mimeType);
|
body = std::make_shared<SMTPStringBody>(text, mimeType);
|
||||||
} else if (GetObjectHeap(obj, ba)) {
|
} else if (GetObjectHeap(obj, ba)) {
|
||||||
std::shared_ptr<MemoryStream> ms = std::make_shared<MemoryStream>(true);
|
std::shared_ptr<MemoryStream> ms = std::make_shared<MemoryStream>(true);
|
||||||
ms->WriteBlock(ba->data.data(), ba->data.size());
|
ms->WriteBlock(ba->GetData(), ba->GetSize());
|
||||||
ms->Seek(0L, SeekOrigin::Begin);
|
ms->Seek(0L, SeekOrigin::Begin);
|
||||||
|
|
||||||
body = std::make_shared<SMTPStreamBody>(mimeType, ms);
|
body = std::make_shared<SMTPStreamBody>(mimeType, ms);
|
||||||
@@ -150,8 +150,48 @@ class THttpDictionary : public TNativeObject {
|
|||||||
value);
|
value);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
} else if (key == "TryGetOnlyOne") {
|
||||||
|
std::string key;
|
||||||
|
std::string value;
|
||||||
|
if (GetArgument(args, 0, key) && dict->TryGetOnlyOne(key, value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
} else if (key == "TryGetOnlyOneBoolean") {
|
||||||
|
std::string key;
|
||||||
|
bool value;
|
||||||
|
if (GetArgument(args, 0, key) &&
|
||||||
|
dict->TryGetOnlyOneBoolean(key, value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
} else if (key == "TryGetOnlyOneDouble") {
|
||||||
|
std::string key;
|
||||||
|
double value;
|
||||||
|
if (GetArgument(args, 0, key) &&
|
||||||
|
dict->TryGetOnlyOneDouble(key, value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
} else if (key == "TryGetOnlyOneInt") {
|
||||||
|
std::string key;
|
||||||
|
int64_t value;
|
||||||
|
if (GetArgument(args, 0, key) &&
|
||||||
|
dict->TryGetOnlyOneInt(key, value)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
} else if (key == "TryGetOnlyOneDate") {
|
||||||
|
std::string key;
|
||||||
|
Tesses::Framework::Date::DateTime value;
|
||||||
|
if (GetArgument(args, 0, key) &&
|
||||||
|
dict->TryGetOnlyOneDate(key, value)) {
|
||||||
|
return std::make_shared<Tesses::Framework::Date::DateTime>(
|
||||||
|
value);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
} else if (key == "ToList") {
|
} else if (key == "ToList") {
|
||||||
TList *_ls = TList::Create(ls);
|
TList *_ls = ls.Create<TList>();
|
||||||
for (auto item : dict->kvp) {
|
for (auto item : dict->kvp) {
|
||||||
for (auto i : item.second) {
|
for (auto i : item.second) {
|
||||||
auto d = TDictionary::Create(ls);
|
auto d = TDictionary::Create(ls);
|
||||||
@@ -239,6 +279,9 @@ class TServerContext : public TNativeObjectThatReturnsHttpDictionary {
|
|||||||
else if (key == "getQueryParams")
|
else if (key == "getQueryParams")
|
||||||
return TNativeObject::Create<THttpDictionary>(ls, &ctx->queryParams,
|
return TNativeObject::Create<THttpDictionary>(ls, &ctx->queryParams,
|
||||||
this);
|
this);
|
||||||
|
else if (key == "getBodyParams")
|
||||||
|
return TNativeObject::Create<THttpDictionary>(ls, &ctx->bodyParams,
|
||||||
|
this);
|
||||||
else if (key == "getRequestHeaders")
|
else if (key == "getRequestHeaders")
|
||||||
return TNativeObject::Create<THttpDictionary>(
|
return TNativeObject::Create<THttpDictionary>(
|
||||||
ls, &ctx->requestHeaders, this);
|
ls, &ctx->requestHeaders, this);
|
||||||
@@ -291,7 +334,7 @@ class TServerContext : public TNativeObjectThatReturnsHttpDictionary {
|
|||||||
return strm;
|
return strm;
|
||||||
});
|
});
|
||||||
|
|
||||||
return TList::Create(ls, response.begin(), response.end());
|
return ls.Create<TList>(response.begin(), response.end());
|
||||||
}
|
}
|
||||||
} else if (key == "getNeedToParseFormData")
|
} else if (key == "getNeedToParseFormData")
|
||||||
return ctx->NeedToParseFormData();
|
return ctx->NeedToParseFormData();
|
||||||
@@ -780,18 +823,20 @@ static TObject Net_Http_ListenOnUnusedPort(GCList &ls,
|
|||||||
static TObject Net_Http_MimeType(GCList &ls, std::vector<TObject> args) {
|
static TObject Net_Http_MimeType(GCList &ls, std::vector<TObject> args) {
|
||||||
Tesses::Framework::Filesystem::VFSPath p;
|
Tesses::Framework::Filesystem::VFSPath p;
|
||||||
if (GetArgumentAsPath(args, 0, p)) {
|
if (GetArgumentAsPath(args, 0, p)) {
|
||||||
std::filesystem::path p2 = p.GetFileName();
|
|
||||||
return HttpUtils::MimeType(p2);
|
return HttpUtils::GetMimeTypePath(p);
|
||||||
}
|
}
|
||||||
return std::string("application/octet-stream");
|
return std::string("application/octet-stream");
|
||||||
}
|
}
|
||||||
class THttpRequestBody : public TNativeObject {
|
class THttpRequestBody : public TNativeObject {
|
||||||
HttpRequestBody *body;
|
std::shared_ptr<HttpRequestBody> body;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
THttpRequestBody(HttpRequestBody *body) { this->body = body; }
|
THttpRequestBody(std::shared_ptr<HttpRequestBody> body) {
|
||||||
|
this->body = body;
|
||||||
|
}
|
||||||
bool IsClosed() { return body == nullptr; }
|
bool IsClosed() { return body == nullptr; }
|
||||||
HttpRequestBody *GetBody() { return this->body; }
|
std::shared_ptr<HttpRequestBody> GetBody() { return this->body; }
|
||||||
|
|
||||||
std::string TypeName() { return "Net.Http.HttpRequestBody"; }
|
std::string TypeName() { return "Net.Http.HttpRequestBody"; }
|
||||||
|
|
||||||
@@ -799,10 +844,7 @@ class THttpRequestBody : public TNativeObject {
|
|||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close() {
|
void Close() { this->body = nullptr; }
|
||||||
delete this->body;
|
|
||||||
this->body = nullptr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class THttpResponse : public TNativeObjectThatReturnsHttpDictionary {
|
class THttpResponse : public TNativeObjectThatReturnsHttpDictionary {
|
||||||
@@ -907,7 +949,8 @@ static TObject Net_Http_MakeRequest(GCList &ls, std::vector<TObject> args,
|
|||||||
_obj = options->GetValue("Body");
|
_obj = options->GetValue("Body");
|
||||||
|
|
||||||
if (GetObjectHeap(_obj, body1)) {
|
if (GetObjectHeap(_obj, body1)) {
|
||||||
req.body = new TDictionaryHttpRequestBody(gc, body1);
|
req.body =
|
||||||
|
std::make_shared<TDictionaryHttpRequestBody>(gc, body1);
|
||||||
} else if (GetObjectHeap(_obj, body2) && !body2->IsClosed()) {
|
} else if (GetObjectHeap(_obj, body2) && !body2->IsClosed()) {
|
||||||
req.body = body2->GetBody();
|
req.body = body2->GetBody();
|
||||||
}
|
}
|
||||||
@@ -920,8 +963,6 @@ static TObject Net_Http_MakeRequest(GCList &ls, std::vector<TObject> args,
|
|||||||
if (req.body != nullptr) {
|
if (req.body != nullptr) {
|
||||||
if (body2 != nullptr) {
|
if (body2 != nullptr) {
|
||||||
body2->Close();
|
body2->Close();
|
||||||
} else if (body1 != nullptr) {
|
|
||||||
delete req.body;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1073,7 +1114,7 @@ static TObject Net_Http_WebSocketClient(GCList &ls, std::vector<TObject> args) {
|
|||||||
if (GetArgument(args, 0, url) && GetArgumentHeap(args, 1, headers) &&
|
if (GetArgument(args, 0, url) && GetArgumentHeap(args, 1, headers) &&
|
||||||
GetArgumentHeap(args, 2, dict)) {
|
GetArgumentHeap(args, 2, dict)) {
|
||||||
GetArgumentHeap(args, 3, callable);
|
GetArgumentHeap(args, 3, callable);
|
||||||
HttpDictionary hdict;
|
HttpDictionary hdict(false);
|
||||||
for (int64_t index = 0; index < headers->Count(); index++) {
|
for (int64_t index = 0; index < headers->Count(); index++) {
|
||||||
_obj = headers->Get(index);
|
_obj = headers->Get(index);
|
||||||
TDictionary *dict;
|
TDictionary *dict;
|
||||||
@@ -1171,7 +1212,7 @@ static TObject Net_Http_WebSocketClient(GCList &ls, std::vector<TObject> args) {
|
|||||||
if (!GetObjectHeap(hobj, headers))
|
if (!GetObjectHeap(hobj, headers))
|
||||||
return Undefined();
|
return Undefined();
|
||||||
|
|
||||||
HttpDictionary hdict;
|
HttpDictionary hdict(false);
|
||||||
for (int64_t index = 0; index < headers->Count(); index++) {
|
for (int64_t index = 0; index < headers->Count(); index++) {
|
||||||
_obj = headers->Get(index);
|
_obj = headers->Get(index);
|
||||||
TDictionary *dict;
|
TDictionary *dict;
|
||||||
@@ -1381,7 +1422,7 @@ static TObject New_StreamHttpRequestBody(GCList &ls,
|
|||||||
|
|
||||||
if (GetArgument(args, 0, strm) && GetArgument(args, 1, mimeType)) {
|
if (GetArgument(args, 0, strm) && GetArgument(args, 1, mimeType)) {
|
||||||
return TNativeObject::Create<THttpRequestBody>(
|
return TNativeObject::Create<THttpRequestBody>(
|
||||||
ls, new StreamHttpRequestBody(strm, mimeType));
|
ls, std::make_shared<StreamHttpRequestBody>(strm, mimeType));
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1390,7 +1431,7 @@ static TObject New_TextHttpRequestBody(GCList &ls, std::vector<TObject> args) {
|
|||||||
std::string mimeType;
|
std::string mimeType;
|
||||||
if (GetArgument(args, 0, text) && GetArgument(args, 1, mimeType)) {
|
if (GetArgument(args, 0, text) && GetArgument(args, 1, mimeType)) {
|
||||||
return TNativeObject::Create<THttpRequestBody>(
|
return TNativeObject::Create<THttpRequestBody>(
|
||||||
ls, new TextHttpRequestBody(text, mimeType));
|
ls, std::make_shared<TextHttpRequestBody>(text, mimeType));
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1398,8 +1439,8 @@ static TObject New_JsonHttpRequestBody(GCList &ls, std::vector<TObject> args) {
|
|||||||
|
|
||||||
if (!args.empty()) {
|
if (!args.empty()) {
|
||||||
return TNativeObject::Create<THttpRequestBody>(
|
return TNativeObject::Create<THttpRequestBody>(
|
||||||
ls,
|
ls, std::make_shared<TextHttpRequestBody>(Json_Encode(args[0]),
|
||||||
new TextHttpRequestBody(Json_Encode(args[0]), "application/json"));
|
"application/json"));
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1423,7 +1464,7 @@ void TStd::RegisterNet(std::shared_ptr<GC> gc, TRootEnvironment *env) {
|
|||||||
"Create a text request body", {"text", "mimeType"},
|
"Create a text request body", {"text", "mimeType"},
|
||||||
New_TextHttpRequestBody);
|
New_TextHttpRequestBody);
|
||||||
_new->DeclareFunction(gc, "JsonHttpRequestBody",
|
_new->DeclareFunction(gc, "JsonHttpRequestBody",
|
||||||
"Create a text request body", {"json"},
|
"Create a json request body", {"json"},
|
||||||
New_JsonHttpRequestBody);
|
New_JsonHttpRequestBody);
|
||||||
_new->DeclareFunction(
|
_new->DeclareFunction(
|
||||||
gc, "HttpServer", "Create a http server (allows multiple)",
|
gc, "HttpServer", "Create a http server (allows multiple)",
|
||||||
@@ -1540,7 +1581,7 @@ void TStd::RegisterNet(std::shared_ptr<GC> gc, TRootEnvironment *env) {
|
|||||||
dict->DeclareFunction(
|
dict->DeclareFunction(
|
||||||
gc, "getIPAddresses", "Get the ip addresses of this machine", {"$ipv6"},
|
gc, "getIPAddresses", "Get the ip addresses of this machine", {"$ipv6"},
|
||||||
[](GCList &ls, std::vector<TObject> args) -> TObject {
|
[](GCList &ls, std::vector<TObject> args) -> TObject {
|
||||||
TList *a = TList::Create(ls);
|
TList *a = ls.Create<TList>();
|
||||||
bool ipv6 = false;
|
bool ipv6 = false;
|
||||||
GetArgument(args, 0, ipv6);
|
GetArgument(args, 0, ipv6);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
|
|||||||
@@ -3,13 +3,9 @@
|
|||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
class ProcessObject : public TNativeObject {
|
class ProcessObject : public TNativeObject {
|
||||||
public:
|
public:
|
||||||
ProcessObject() {
|
|
||||||
arguments = nullptr;
|
|
||||||
environment = nullptr;
|
|
||||||
}
|
|
||||||
ProcessObject(GCList &ls) {
|
ProcessObject(GCList &ls) {
|
||||||
arguments = TList::Create(ls);
|
arguments = ls.Create<TList>();
|
||||||
environment = TList::Create(ls);
|
environment = ls.Create<TList>();
|
||||||
process.includeThisEnv = true;
|
process.includeThisEnv = true;
|
||||||
process.redirectStdIn = false;
|
process.redirectStdIn = false;
|
||||||
|
|
||||||
@@ -167,7 +163,7 @@ static TObject Process_Start(GCList &ls, std::vector<TObject> args,
|
|||||||
TDictionary *dict;
|
TDictionary *dict;
|
||||||
|
|
||||||
if (GetArgumentHeap(args, 0, dict)) {
|
if (GetArgumentHeap(args, 0, dict)) {
|
||||||
auto process = TNativeObject::Create<ProcessObject>(ls);
|
auto process = TNativeObject::Create<ProcessObject>(ls, ls);
|
||||||
auto name = dict->GetValue("FileName");
|
auto name = dict->GetValue("FileName");
|
||||||
auto inh = dict->GetValue("InheritParentEnvironment");
|
auto inh = dict->GetValue("InheritParentEnvironment");
|
||||||
auto rStdIn = dict->GetValue("RedirectStandardInput");
|
auto rStdIn = dict->GetValue("RedirectStandardInput");
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class SQLiteObject : public TNativeObject {
|
|||||||
|
|
||||||
this->db->Exec(arg, res);
|
this->db->Exec(arg, res);
|
||||||
|
|
||||||
TList *list = TList::Create(ls);
|
TList *list = ls.Create<TList>();
|
||||||
|
|
||||||
for (auto &item : res) {
|
for (auto &item : res) {
|
||||||
TDictionary *dict = TDictionary::Create(ls);
|
TDictionary *dict = TDictionary::Create(ls);
|
||||||
|
|||||||
+31
-44
@@ -6,28 +6,17 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#if !defined(CROSSLANG_STATIC)
|
#if !defined(CROSSLANG_STATIC)
|
||||||
#if defined(CROSSLANG_ENABLE_FFI)
|
#if defined(CROSSLANG_ENABLE_FFI)
|
||||||
#include <ffi.h>
|
#include <ffi.h>
|
||||||
#endif
|
#endif
|
||||||
#if defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#undef min
|
|
||||||
#undef max
|
|
||||||
#else
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#if defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include <time.h>
|
|
||||||
#undef min
|
|
||||||
#undef max
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@@ -70,15 +59,18 @@ class DL {
|
|||||||
Tesses::Framework::Filesystem::LocalFilesystem lfs;
|
Tesses::Framework::Filesystem::LocalFilesystem lfs;
|
||||||
std::string str = lfs.VFSPathToSystem(p);
|
std::string str = lfs.VFSPathToSystem(p);
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
handle =
|
|
||||||
LoadLibraryExA(str.c_str(), NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
throw std::runtime_error("I removed support on this platform");
|
||||||
|
// handle =LoadLibraryExA(str.c_str(), NULL,
|
||||||
|
// LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||||
#else
|
#else
|
||||||
handle = dlopen(str.c_str(), RTLD_LAZY);
|
handle = dlopen(str.c_str(), RTLD_LAZY);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
template <typename T> T Resolve(std::string name) {
|
template <typename T> T Resolve(std::string name) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
return (T)GetProcAddress((HMODULE)handle, name.c_str());
|
throw std::runtime_error("I removed support on this platform");
|
||||||
|
// return (T)GetProcAddress((HMODULE)handle, name.c_str());
|
||||||
#else
|
#else
|
||||||
return (T)dlsym(handle, name.c_str());
|
return (T)dlsym(handle, name.c_str());
|
||||||
|
|
||||||
@@ -86,7 +78,9 @@ class DL {
|
|||||||
}
|
}
|
||||||
~DL() {
|
~DL() {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
FreeLibrary((HMODULE)handle);
|
|
||||||
|
throw std::runtime_error("I removed support on this platform");
|
||||||
|
// FreeLibrary((HMODULE)handle);
|
||||||
#else
|
#else
|
||||||
dlclose(handle);
|
dlclose(handle);
|
||||||
#endif
|
#endif
|
||||||
@@ -149,8 +143,8 @@ ffi_tmp_type_t FFI_ConvertTObjectToFFIType(TObject &arg, std::string t) {
|
|||||||
return (ffi_tmp_type_t){
|
return (ffi_tmp_type_t){
|
||||||
.v_ptr = (void *)std::get<std::string>(arg).c_str()};
|
.v_ptr = (void *)std::get<std::string>(arg).c_str()};
|
||||||
}
|
}
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(arg)) {
|
} else if (std::holds_alternative<THeapObject *>(arg)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(arg).obj;
|
auto obj = std::get<THeapObject *>(arg);
|
||||||
auto bA = dynamic_cast<TByteArray *>(obj);
|
auto bA = dynamic_cast<TByteArray *>(obj);
|
||||||
auto nat = dynamic_cast<TNative *>(obj);
|
auto nat = dynamic_cast<TNative *>(obj);
|
||||||
if (bA != nullptr) {
|
if (bA != nullptr) {
|
||||||
@@ -441,13 +435,7 @@ static TObject TypeIsClass(GCList &ls, std::vector<TObject> args) {
|
|||||||
static TObject TypeIsDefined(GCList &ls, std::vector<TObject> args) {
|
static TObject TypeIsDefined(GCList &ls, std::vector<TObject> args) {
|
||||||
if (args.empty())
|
if (args.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return (!std::holds_alternative<std::nullptr_t>(args[0]) &&
|
return (!IsNull(args[0]) && !std::holds_alternative<Undefined>(args[0]));
|
||||||
!std::holds_alternative<Undefined>(args[0]));
|
|
||||||
}
|
|
||||||
static TObject TypeIsHeap(GCList &ls, std::vector<TObject> args) {
|
|
||||||
if (args.empty())
|
|
||||||
return nullptr;
|
|
||||||
return std::holds_alternative<THeapObjectHolder>(args[0]);
|
|
||||||
}
|
}
|
||||||
static TObject TypeIsNumber(GCList &ls, std::vector<TObject> args) {
|
static TObject TypeIsNumber(GCList &ls, std::vector<TObject> args) {
|
||||||
if (args.empty())
|
if (args.empty())
|
||||||
@@ -674,7 +662,7 @@ std::string GetObjectTypeString(TObject _obj) {
|
|||||||
return "Regex";
|
return "Regex";
|
||||||
if (std::holds_alternative<Undefined>(_obj))
|
if (std::holds_alternative<Undefined>(_obj))
|
||||||
return "Undefined";
|
return "Undefined";
|
||||||
if (std::holds_alternative<std::nullptr_t>(_obj))
|
if (IsNull(_obj))
|
||||||
return "Null";
|
return "Null";
|
||||||
if (std::holds_alternative<bool>(_obj))
|
if (std::holds_alternative<bool>(_obj))
|
||||||
return "Boolean";
|
return "Boolean";
|
||||||
@@ -826,8 +814,8 @@ std::string GetObjectTypeString(TObject _obj) {
|
|||||||
}
|
}
|
||||||
return "VFS";
|
return "VFS";
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<THeapObjectHolder>(_obj)) {
|
if (std::holds_alternative<THeapObject *>(_obj)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(_obj).obj;
|
auto obj = std::get<THeapObject *>(_obj);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
|
|
||||||
@@ -1004,11 +992,7 @@ static TObject YieldEnumerableFunc(GCList &ls, std::vector<TObject> args) {
|
|||||||
static TObject DateTime_Sleep(GCList &ls, std::vector<TObject> args) {
|
static TObject DateTime_Sleep(GCList &ls, std::vector<TObject> args) {
|
||||||
int64_t msec;
|
int64_t msec;
|
||||||
if (GetArgument(args, 0, msec)) {
|
if (GetArgument(args, 0, msec)) {
|
||||||
#if defined(_WIN32)
|
Tesses::Framework::TF_Sleep(msec);
|
||||||
Sleep((int)msec);
|
|
||||||
#else
|
|
||||||
usleep(1000 * msec);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -1390,10 +1374,7 @@ void TStd::RegisterRoot(std::shared_ptr<GC> gc, TRootEnvironment *env) {
|
|||||||
env->DeclareFunction(gc, "TypeIsDefined",
|
env->DeclareFunction(gc, "TypeIsDefined",
|
||||||
"Get whether object is not null or undefined",
|
"Get whether object is not null or undefined",
|
||||||
{"object"}, TypeIsDefined);
|
{"object"}, TypeIsDefined);
|
||||||
env->DeclareFunction(
|
|
||||||
gc, "TypeIsHeap",
|
|
||||||
"Get whether object is susceptible to garbage collection", {"object"},
|
|
||||||
TypeIsHeap);
|
|
||||||
env->DeclareFunction(gc, "TypeIsNumber", "Get whether object is a number",
|
env->DeclareFunction(gc, "TypeIsNumber", "Get whether object is a number",
|
||||||
{"object"}, TypeIsNumber);
|
{"object"}, TypeIsNumber);
|
||||||
env->DeclareFunction(gc, "TypeIsLong",
|
env->DeclareFunction(gc, "TypeIsLong",
|
||||||
@@ -1465,9 +1446,9 @@ void TStd::RegisterRoot(std::shared_ptr<GC> gc, TRootEnvironment *env) {
|
|||||||
gc, "Thread", "Create thread", {"callback"},
|
gc, "Thread", "Create thread", {"callback"},
|
||||||
[](GCList &ls, std::vector<TObject> args) -> TObject {
|
[](GCList &ls, std::vector<TObject> args) -> TObject {
|
||||||
if (args.size() == 1 &&
|
if (args.size() == 1 &&
|
||||||
std::holds_alternative<THeapObjectHolder>(args[0])) {
|
std::holds_alternative<THeapObject *>(args[0])) {
|
||||||
auto cb = dynamic_cast<TCallable *>(
|
auto cb =
|
||||||
std::get<THeapObjectHolder>(args[0]).obj);
|
dynamic_cast<TCallable *>(std::get<THeapObject *>(args[0]));
|
||||||
if (cb != nullptr) {
|
if (cb != nullptr) {
|
||||||
return CreateThread(ls, cb, false);
|
return CreateThread(ls, cb, false);
|
||||||
}
|
}
|
||||||
@@ -1587,7 +1568,7 @@ void TStd::RegisterStd(
|
|||||||
RegisterCrypto(gc, env);
|
RegisterCrypto(gc, env);
|
||||||
RegisterOGC(gc, env);
|
RegisterOGC(gc, env);
|
||||||
RegisterProcess(gc, env);
|
RegisterProcess(gc, env);
|
||||||
RegisterClass(gc, env);
|
RegisterZeClass(gc, env);
|
||||||
|
|
||||||
gc->RegisterEverything(env);
|
gc->RegisterEverything(env);
|
||||||
|
|
||||||
@@ -1613,7 +1594,13 @@ void TStd::RegisterStd(
|
|||||||
gc_dict->DeclareFunction(
|
gc_dict->DeclareFunction(
|
||||||
gc, "Collect", "Collect garbage", {},
|
gc, "Collect", "Collect garbage", {},
|
||||||
[](GCList &ls, std::vector<TObject> args) -> TObject {
|
[](GCList &ls, std::vector<TObject> args) -> TObject {
|
||||||
ls.GetGC()->Collect();
|
std::vector<THeapObject *> to_delete;
|
||||||
|
ls.GetGC()->BarrierBegin();
|
||||||
|
ls.GetGC()->Collect(to_delete);
|
||||||
|
ls.GetGC()->BarrierEnd();
|
||||||
|
|
||||||
|
for (auto item : to_delete)
|
||||||
|
delete item;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
});
|
});
|
||||||
gc_dict->DeclareFunction(
|
gc_dict->DeclareFunction(
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ static TObject AstToTObject(GCList &ls, SyntaxNode node) {
|
|||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
r->SetValue("Type", asn.nodeName);
|
r->SetValue("Type", asn.nodeName);
|
||||||
r->SetValue("IsExpression", asn.isExpression);
|
r->SetValue("IsExpression", asn.isExpression);
|
||||||
TList *ls2 = TList::Create(ls);
|
TList *ls2 = ls.Create<TList>();
|
||||||
for (auto item : asn.nodes) {
|
for (auto item : asn.nodes) {
|
||||||
ls2->Add(AstToTObject(ls, item));
|
ls2->Add(AstToTObject(ls, item));
|
||||||
}
|
}
|
||||||
@@ -67,6 +67,8 @@ static TObject VM_SourceToAst(GCList &ls, std::vector<TObject> args) {
|
|||||||
static TObject VM_Eval(GCList &ls, std::vector<TObject> args) {
|
static TObject VM_Eval(GCList &ls, std::vector<TObject> args) {
|
||||||
std::string str;
|
std::string str;
|
||||||
if (GetArgument(args, 0, str)) {
|
if (GetArgument(args, 0, str)) {
|
||||||
|
|
||||||
|
auto current_function = GC::GetCurrentFunction();
|
||||||
if (current_function != nullptr) {
|
if (current_function != nullptr) {
|
||||||
return current_function->env->Eval(ls, str);
|
return current_function->env->Eval(ls, str);
|
||||||
}
|
}
|
||||||
@@ -90,6 +92,8 @@ static TObject Success(GCList &ls) {
|
|||||||
}
|
}
|
||||||
static TObject VM_getCurrentEnvironment(GCList &ls2,
|
static TObject VM_getCurrentEnvironment(GCList &ls2,
|
||||||
std::vector<TObject> args) {
|
std::vector<TObject> args) {
|
||||||
|
|
||||||
|
auto current_function = GC::GetCurrentFunction();
|
||||||
if (current_function != nullptr)
|
if (current_function != nullptr)
|
||||||
return current_function->env;
|
return current_function->env;
|
||||||
return Undefined();
|
return Undefined();
|
||||||
@@ -261,9 +265,10 @@ static TObject VM_Compile(GCList &ls, std::vector<TObject> args) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
static TObject VM_GetStacktrace(GCList &ls, std::vector<TObject> args) {
|
static TObject VM_GetStacktrace(GCList &ls, std::vector<TObject> args) {
|
||||||
|
auto current_function = GC::GetCurrentFunction();
|
||||||
if (current_function != nullptr) {
|
if (current_function != nullptr) {
|
||||||
if (current_function->thread != nullptr) {
|
if (current_function->thread != nullptr) {
|
||||||
TList *list = TList::Create(ls);
|
TList *list = ls.Create<TList>();
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
for (auto item : current_function->thread->call_stack_entries) {
|
for (auto item : current_function->thread->call_stack_entries) {
|
||||||
auto dict = TDictionary::Create(ls);
|
auto dict = TDictionary::Create(ls);
|
||||||
|
|||||||
+2
-16
@@ -1,22 +1,8 @@
|
|||||||
#include "CrossLang.hpp"
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
TAny *TAny::Create(GCList &ls) {
|
TAny *TAny::Create(GCList &ls) { return ls.Create<TAny>(); }
|
||||||
TAny *anyObj = new TAny();
|
TAny *TAny::Create(GCList *ls) { return ls->Create<TAny>(); }
|
||||||
|
|
||||||
std::shared_ptr<GC> gc = ls.GetGC();
|
|
||||||
ls.Add(anyObj);
|
|
||||||
gc->Watch(anyObj);
|
|
||||||
return anyObj;
|
|
||||||
}
|
|
||||||
TAny *TAny::Create(GCList *ls) {
|
|
||||||
TAny *anyObj = new TAny();
|
|
||||||
|
|
||||||
std::shared_ptr<GC> gc = ls->GetGC();
|
|
||||||
ls->Add(anyObj);
|
|
||||||
gc->Watch(anyObj);
|
|
||||||
return anyObj;
|
|
||||||
}
|
|
||||||
void TAny::Mark() {
|
void TAny::Mark() {
|
||||||
if (this->marked)
|
if (this->marked)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -3,18 +3,10 @@
|
|||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
|
|
||||||
TAssociativeArray *TAssociativeArray::Create(GCList &ls) {
|
TAssociativeArray *TAssociativeArray::Create(GCList &ls) {
|
||||||
TAssociativeArray *list = new TAssociativeArray();
|
return ls.Create<TAssociativeArray>();
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(list);
|
|
||||||
_gc->Watch(list);
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
TAssociativeArray *TAssociativeArray::Create(GCList *ls) {
|
TAssociativeArray *TAssociativeArray::Create(GCList *ls) {
|
||||||
TAssociativeArray *list = new TAssociativeArray();
|
return ls->Create<TAssociativeArray>();
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(list);
|
|
||||||
_gc->Watch(list);
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
void TAssociativeArray::Set(std::shared_ptr<GC> gc, TObject key,
|
void TAssociativeArray::Set(std::shared_ptr<GC> gc, TObject key,
|
||||||
TObject value) {
|
TObject value) {
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang {
|
||||||
|
std::string TByteView::TypeName() { return "ByteView"; }
|
||||||
|
TString *TByteView::ToString(GCList &ls) {
|
||||||
|
auto bounds = GetBounds();
|
||||||
|
if (bounds.first == nullptr || bounds.second == 0)
|
||||||
|
return ls.FromString("");
|
||||||
|
|
||||||
|
return ls.Create<TString>(reinterpret_cast<const char *>(bounds.first),
|
||||||
|
bounds.second);
|
||||||
|
}
|
||||||
|
bool TByteView::opExecuteMethod(InterperterThread *thrd, std::shared_ptr<GC> gc,
|
||||||
|
const std::string &name,
|
||||||
|
const std::vector<TObject> &args) {
|
||||||
|
if (name == "Slice") {
|
||||||
|
int64_t offset = 0;
|
||||||
|
int64_t length = -1;
|
||||||
|
|
||||||
|
GetArgument(args, 0, offset);
|
||||||
|
GetArgument(args, 1, length);
|
||||||
|
|
||||||
|
GCList ls(gc);
|
||||||
|
|
||||||
|
thrd->call_stack_entries.back()->Push(
|
||||||
|
gc, ls.Create<TSpan>(this, offset, length));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (name == "Count" || name == "Length") {
|
||||||
|
thrd->call_stack_entries.back()->Push(
|
||||||
|
gc, static_cast<int64_t>(this->GetBounds().second));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (name == "GetAt") {
|
||||||
|
int64_t i64;
|
||||||
|
if (GetArgument(args, 0, i64)) {
|
||||||
|
auto res = this->GetAt(static_cast<size_t>(i64));
|
||||||
|
|
||||||
|
thrd->call_stack_entries.back()->Push(
|
||||||
|
gc, res == -1 ? static_cast<TObject>(nullptr)
|
||||||
|
: static_cast<TObject>(res));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thrd->call_stack_entries.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool TByteView::opGetField(InterperterThread *thrd, std::shared_ptr<GC> gc,
|
||||||
|
const std::string &name) {
|
||||||
|
if (name == "Count" || name == "Length") {
|
||||||
|
thrd->call_stack_entries.back()->Push(
|
||||||
|
gc, static_cast<int64_t>(this->GetBounds().second));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
thrd->call_stack_entries.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void TByteView::CopyTo(TMutByteView *view) {
|
||||||
|
auto myBounds = this->GetBounds();
|
||||||
|
if (myBounds.first == nullptr || myBounds.second == 0)
|
||||||
|
return;
|
||||||
|
auto theirBounds = view->GetMutableBoundsConstrained(0, myBounds.second);
|
||||||
|
|
||||||
|
if (theirBounds.first == nullptr || theirBounds.second == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(theirBounds.first, myBounds.first, theirBounds.second);
|
||||||
|
}
|
||||||
|
void TByteView::CopyTo(TMutByteView *view, size_t srcOffset, size_t destOffset,
|
||||||
|
size_t length) {
|
||||||
|
auto myBounds = this->GetBoundsConstrained(srcOffset, length);
|
||||||
|
if (myBounds.first == nullptr || myBounds.second == 0)
|
||||||
|
return;
|
||||||
|
auto theirBounds =
|
||||||
|
view->GetMutableBoundsConstrained(destOffset, myBounds.second);
|
||||||
|
|
||||||
|
if (theirBounds.first == nullptr || theirBounds.second == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
memcpy(theirBounds.first, myBounds.first, theirBounds.second);
|
||||||
|
}
|
||||||
|
} // namespace Tesses::CrossLang
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang {
|
||||||
|
TResource::TResource(std::vector<uint8_t> &&bytes) : bytes(std::move(bytes)) {}
|
||||||
|
std::pair<const uint8_t *, size_t> TResource::GetBounds() const {
|
||||||
|
return std::pair<const uint8_t *, size_t>(bytes.data(), bytes.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TResource::TypeName() { return "Resource"; }
|
||||||
|
} // namespace Tesses::CrossLang
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang {
|
||||||
|
|
||||||
|
TString::TString() {}
|
||||||
|
TString::TString(std::string_view str) : text(str) {}
|
||||||
|
TString::TString(const char *text, size_t len) : text(text, len) {}
|
||||||
|
TString::TString(std::string_view left, std::string_view right) {
|
||||||
|
text.reserve(left.size() + right.size());
|
||||||
|
text.append(left.begin(), left.end());
|
||||||
|
text.append(right.begin(), right.end());
|
||||||
|
}
|
||||||
|
TString::TString(std::string &&str) : text(std::move(str)) {}
|
||||||
|
|
||||||
|
const std::string &TString::GetString() const { return this->text; }
|
||||||
|
|
||||||
|
std::pair<const uint8_t *, size_t> TString::GetBounds() const {
|
||||||
|
return std::pair<const uint8_t *, size_t>(
|
||||||
|
reinterpret_cast<const uint8_t *>(text.data()), text.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TString::TypeName() { return "String"; }
|
||||||
|
|
||||||
|
TString *TString::ToString(GCList &ls) {
|
||||||
|
ls.Add(this);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TString::opAdd(InterperterThread *thrd, std::shared_ptr<GC> gc,
|
||||||
|
TObject rhs) {
|
||||||
|
TString *rStr;
|
||||||
|
char rChr;
|
||||||
|
if (GetObjectHeap(rhs, rStr)) {
|
||||||
|
GCList ls(gc);
|
||||||
|
thrd->call_stack_entries.back()->Push(
|
||||||
|
gc, ls.Create<TString>(this->GetString(), rStr->GetString()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (GetObject(rhs, rChr)) {
|
||||||
|
GCList ls(gc);
|
||||||
|
thrd->call_stack_entries.back()->Push(
|
||||||
|
gc,
|
||||||
|
ls.Create<TString>(this->GetString(), std::string_view(&rChr, 1)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
thrd->call_stack_entries.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool TString::opLessThan(InterperterThread *thrd, std::shared_ptr<GC> gc,
|
||||||
|
TObject rhs) {
|
||||||
|
|
||||||
|
TString *rStr;
|
||||||
|
if (GetObjectHeap(rhs, rStr)) {
|
||||||
|
thrd->call_stack_entries.back()->Push(gc, this->GetString() <
|
||||||
|
rStr->GetString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
thrd->call_stack_entries.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool TString::opGreaterThan(InterperterThread *thrd, std::shared_ptr<GC> gc,
|
||||||
|
TObject rhs) {
|
||||||
|
|
||||||
|
TString *rStr;
|
||||||
|
if (GetObjectHeap(rhs, rStr)) {
|
||||||
|
thrd->call_stack_entries.back()->Push(gc, this->GetString() >
|
||||||
|
rStr->GetString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
thrd->call_stack_entries.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool TString::opLessThanEqual(InterperterThread *thrd, std::shared_ptr<GC> gc,
|
||||||
|
TObject rhs) {
|
||||||
|
|
||||||
|
TString *rStr;
|
||||||
|
if (GetObjectHeap(rhs, rStr)) {
|
||||||
|
|
||||||
|
thrd->call_stack_entries.back()->Push(gc, this->GetString() <=
|
||||||
|
rStr->GetString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
thrd->call_stack_entries.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool TString::opGreaterThanEqual(InterperterThread *thrd,
|
||||||
|
std::shared_ptr<GC> gc, TObject rhs) {
|
||||||
|
|
||||||
|
TString *rStr;
|
||||||
|
if (GetObjectHeap(rhs, rStr)) {
|
||||||
|
|
||||||
|
thrd->call_stack_entries.back()->Push(gc, this->GetString() >=
|
||||||
|
rStr->GetString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
thrd->call_stack_entries.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool TString::IsEqualTo(std::shared_ptr<GC> gc, TObject rhs) {
|
||||||
|
TString *rStr;
|
||||||
|
if (GetObjectHeap(rhs, rStr)) {
|
||||||
|
if (this == rStr)
|
||||||
|
return true;
|
||||||
|
return this->GetString() == rStr->GetString();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool TString::IsNotEqualTo(std::shared_ptr<GC> gc, TObject rhs) {
|
||||||
|
TString *rStr;
|
||||||
|
if (GetObjectHeap(rhs, rStr)) {
|
||||||
|
if (this == rStr)
|
||||||
|
return false;
|
||||||
|
return this->GetString() != rStr->GetString();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Tesses::CrossLang
|
||||||
@@ -9,22 +9,12 @@ bool TClassEnvironment::HasConstForSet(std::string key) {
|
|||||||
TClassEnvironment *TClassEnvironment::Create(GCList *gc, TEnvironment *env,
|
TClassEnvironment *TClassEnvironment::Create(GCList *gc, TEnvironment *env,
|
||||||
TClassObject *obj) {
|
TClassObject *obj) {
|
||||||
|
|
||||||
TClassEnvironment *env2 = new TClassEnvironment(env, obj);
|
return gc->Create<TClassEnvironment>(env, obj);
|
||||||
|
|
||||||
std::shared_ptr<GC> _gc = gc->GetGC();
|
|
||||||
gc->Add(env2);
|
|
||||||
_gc->Watch(env2);
|
|
||||||
return env2;
|
|
||||||
}
|
}
|
||||||
TClassEnvironment *TClassEnvironment::Create(GCList &gc, TEnvironment *env,
|
TClassEnvironment *TClassEnvironment::Create(GCList &gc, TEnvironment *env,
|
||||||
TClassObject *obj) {
|
TClassObject *obj) {
|
||||||
|
|
||||||
TClassEnvironment *env2 = new TClassEnvironment(env, obj);
|
return gc.Create<TClassEnvironment>(env, obj);
|
||||||
|
|
||||||
std::shared_ptr<GC> _gc = gc.GetGC();
|
|
||||||
gc.Add(env2);
|
|
||||||
_gc->Watch(env2);
|
|
||||||
return env2;
|
|
||||||
}
|
}
|
||||||
TClassEnvironment::TClassEnvironment(TEnvironment *env, TClassObject *obj) {
|
TClassEnvironment::TClassEnvironment(TEnvironment *env, TClassObject *obj) {
|
||||||
this->env = env;
|
this->env = env;
|
||||||
@@ -33,6 +23,7 @@ TClassEnvironment::TClassEnvironment(TEnvironment *env, TClassObject *obj) {
|
|||||||
bool TClassEnvironment::HasVariable(std::string key) {
|
bool TClassEnvironment::HasVariable(std::string key) {
|
||||||
if (key == "this")
|
if (key == "this")
|
||||||
return true;
|
return true;
|
||||||
|
auto current_function = GC::GetCurrentFunction();
|
||||||
if (this->clsObj->HasValue(current_function == nullptr
|
if (this->clsObj->HasValue(current_function == nullptr
|
||||||
? ""
|
? ""
|
||||||
: current_function->callable->className,
|
: current_function->callable->className,
|
||||||
@@ -49,6 +40,8 @@ bool TClassEnvironment::HasVariableOrFieldRecurse(std::string key,
|
|||||||
bool setting) {
|
bool setting) {
|
||||||
if (key == "this")
|
if (key == "this")
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
auto current_function = GC::GetCurrentFunction();
|
||||||
std::string clsName = current_function == nullptr
|
std::string clsName = current_function == nullptr
|
||||||
? ""
|
? ""
|
||||||
: current_function->callable->className;
|
: current_function->callable->className;
|
||||||
@@ -63,6 +56,7 @@ TObject TClassEnvironment::GetVariable(std::string key) {
|
|||||||
if (key == "this")
|
if (key == "this")
|
||||||
return this->clsObj;
|
return this->clsObj;
|
||||||
|
|
||||||
|
auto current_function = GC::GetCurrentFunction();
|
||||||
std::string clsName = current_function == nullptr
|
std::string clsName = current_function == nullptr
|
||||||
? ""
|
? ""
|
||||||
: current_function->callable->className;
|
: current_function->callable->className;
|
||||||
@@ -75,6 +69,7 @@ void TClassEnvironment::SetVariable(std::string key, TObject value) {
|
|||||||
if (key == "this")
|
if (key == "this")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto current_function = GC::GetCurrentFunction();
|
||||||
std::string clsName = current_function == nullptr
|
std::string clsName = current_function == nullptr
|
||||||
? ""
|
? ""
|
||||||
: current_function->callable->className;
|
: current_function->callable->className;
|
||||||
@@ -90,6 +85,7 @@ TObject TClassEnvironment::GetVariable(GCList &ls, std::string key) {
|
|||||||
if (key == "this")
|
if (key == "this")
|
||||||
return this->clsObj;
|
return this->clsObj;
|
||||||
|
|
||||||
|
auto current_function = GC::GetCurrentFunction();
|
||||||
std::string clsName = current_function == nullptr
|
std::string clsName = current_function == nullptr
|
||||||
? ""
|
? ""
|
||||||
: current_function->callable->className;
|
: current_function->callable->className;
|
||||||
@@ -107,6 +103,7 @@ TObject TClassEnvironment::SetVariable(GCList &ls, std::string key, TObject v) {
|
|||||||
if (key == "this")
|
if (key == "this")
|
||||||
return this->clsObj;
|
return this->clsObj;
|
||||||
|
|
||||||
|
auto current_function = GC::GetCurrentFunction();
|
||||||
std::string clsName = current_function == nullptr
|
std::string clsName = current_function == nullptr
|
||||||
? ""
|
? ""
|
||||||
: current_function->callable->className;
|
: current_function->callable->className;
|
||||||
|
|||||||
+24
-46
@@ -1,27 +1,18 @@
|
|||||||
#include "CrossLang.hpp"
|
#include "CrossLang.hpp"
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
|
TArgWrapper::TArgWrapper(TCallable *callable) : callable(callable) {}
|
||||||
TArgWrapper *TArgWrapper::Create(GCList &ls, TCallable *callable) {
|
TArgWrapper *TArgWrapper::Create(GCList &ls, TCallable *callable) {
|
||||||
TArgWrapper *argWrapper = new TArgWrapper();
|
return ls.Create<TArgWrapper>(callable);
|
||||||
argWrapper->callable = callable;
|
|
||||||
std::shared_ptr<GC> gc = ls.GetGC();
|
|
||||||
ls.Add(argWrapper);
|
|
||||||
gc->Watch(argWrapper);
|
|
||||||
return argWrapper;
|
|
||||||
}
|
}
|
||||||
TArgWrapper *TArgWrapper::Create(GCList *ls, TCallable *callable) {
|
TArgWrapper *TArgWrapper::Create(GCList *ls, TCallable *callable) {
|
||||||
TArgWrapper *argWrapper = new TArgWrapper();
|
return ls->Create<TArgWrapper>(callable);
|
||||||
argWrapper->callable = callable;
|
|
||||||
std::shared_ptr<GC> gc = ls->GetGC();
|
|
||||||
ls->Add(argWrapper);
|
|
||||||
gc->Watch(argWrapper);
|
|
||||||
return argWrapper;
|
|
||||||
}
|
}
|
||||||
TObject TArgWrapper::Call(GCList &ls, std::vector<TObject> args) {
|
TObject TArgWrapper::Call(GCList &ls, std::vector<TObject> args) {
|
||||||
auto cse = current_function;
|
auto cse = GC::GetCurrentFunction();
|
||||||
TList *argList = TList::Create(ls);
|
TList *argList = ls.Create<TList>();
|
||||||
argList->items = args;
|
argList->items = args;
|
||||||
TObject v = this->callable->Call(ls, {argList});
|
TObject v = this->callable->Call(ls, {argList});
|
||||||
current_function = cse;
|
GC::SetCurrentFunction(cse);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
void TArgWrapper::Mark() {
|
void TArgWrapper::Mark() {
|
||||||
@@ -46,52 +37,39 @@ void TClosure::Mark() {
|
|||||||
this->closure->Mark();
|
this->closure->Mark();
|
||||||
GC::Mark(this->tag);
|
GC::Mark(this->tag);
|
||||||
}
|
}
|
||||||
TClosure *TClosure::Create(GCList &ls, TEnvironment *env, TFile *file,
|
TClosure::TClosure(TEnvironment *env, TFile *file, uint32_t chunkId,
|
||||||
uint32_t chunkId, bool ownScope) {
|
bool ownScope) {
|
||||||
TClosure *closure = new TClosure();
|
this->className = "";
|
||||||
closure->className = "";
|
this->ownScope = ownScope;
|
||||||
closure->ownScope = ownScope;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
this->chunkId = chunkId;
|
||||||
ls.Add(closure);
|
|
||||||
_gc->Watch(closure);
|
|
||||||
closure->chunkId = chunkId;
|
|
||||||
if (chunkId < file->chunks.size())
|
if (chunkId < file->chunks.size())
|
||||||
closure->closure = file->chunks[chunkId];
|
this->closure = file->chunks[chunkId];
|
||||||
else
|
else
|
||||||
throw VMException("ChunkId out of bounds.");
|
throw VMException("ChunkId out of bounds.");
|
||||||
closure->env = env;
|
this->env = env;
|
||||||
closure->file = file;
|
this->file = file;
|
||||||
|
}
|
||||||
return closure;
|
TClosure *TClosure::Create(GCList &ls, TEnvironment *env, TFile *file,
|
||||||
|
uint32_t chunkId, bool ownScope) {
|
||||||
|
return ls.Create<TClosure>(env, file, chunkId, ownScope);
|
||||||
}
|
}
|
||||||
TClosure *TClosure::Create(GCList *ls, TEnvironment *env, TFile *file,
|
TClosure *TClosure::Create(GCList *ls, TEnvironment *env, TFile *file,
|
||||||
uint32_t chunkId, bool ownScope) {
|
uint32_t chunkId, bool ownScope) {
|
||||||
TClosure *closure = new TClosure();
|
return ls->Create<TClosure>(env, file, chunkId, ownScope);
|
||||||
closure->className = "";
|
|
||||||
closure->ownScope = ownScope;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(closure);
|
|
||||||
_gc->Watch(closure);
|
|
||||||
closure->chunkId = chunkId;
|
|
||||||
if (chunkId < file->chunks.size())
|
|
||||||
closure->closure = file->chunks[chunkId];
|
|
||||||
else
|
|
||||||
throw VMException("ChunkId out of bounds.");
|
|
||||||
closure->env = env;
|
|
||||||
closure->file = file;
|
|
||||||
|
|
||||||
return closure;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TObject TClosure::Call(GCList &ls, std::vector<TObject> args) {
|
TObject TClosure::Call(GCList &ls, std::vector<TObject> args) {
|
||||||
auto cse = current_function;
|
auto cse = GC::GetCurrentFunction();
|
||||||
InterperterThread *thrd = InterperterThread::Create(ls);
|
InterperterThread *thrd = InterperterThread::Create(ls);
|
||||||
thrd->AddCallStackEntry(ls, this, args);
|
thrd->AddCallStackEntry(ls, this, args);
|
||||||
|
|
||||||
thrd->Execute(ls.GetGC());
|
thrd->Execute(ls.GetGC());
|
||||||
|
|
||||||
TObject v = thrd->call_stack_entries[0]->Pop(ls);
|
TObject v = thrd->call_stack_entries[0]->Pop(ls);
|
||||||
current_function = cse;
|
GC::SetCurrentFunction(cse);
|
||||||
|
// current_function = cse;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
} // namespace Tesses::CrossLang
|
} // namespace Tesses::CrossLang
|
||||||
@@ -1,24 +1,15 @@
|
|||||||
#include "CrossLang.hpp"
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
|
TDynamicDictionary::TDynamicDictionary(TCallable *callable) : cb(callable) {}
|
||||||
TDynamicDictionary *TDynamicDictionary::Create(GCList &ls,
|
TDynamicDictionary *TDynamicDictionary::Create(GCList &ls,
|
||||||
TCallable *callable) {
|
TCallable *callable) {
|
||||||
|
|
||||||
TDynamicDictionary *dict = new TDynamicDictionary();
|
return ls.Create<TDynamicDictionary>(callable);
|
||||||
dict->cb = callable;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(dict);
|
|
||||||
_gc->Watch(dict);
|
|
||||||
return dict;
|
|
||||||
}
|
}
|
||||||
TDynamicDictionary *TDynamicDictionary::Create(GCList *ls,
|
TDynamicDictionary *TDynamicDictionary::Create(GCList *ls,
|
||||||
TCallable *callable) {
|
TCallable *callable) {
|
||||||
TDynamicDictionary *dict = new TDynamicDictionary();
|
return ls->Create<TDynamicDictionary>(callable);
|
||||||
dict->cb = callable;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(dict);
|
|
||||||
_gc->Watch(dict);
|
|
||||||
return dict;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TDynamicDictionary::Mark() {
|
void TDynamicDictionary::Mark() {
|
||||||
@@ -54,7 +45,7 @@ TObject TDynamicDictionary::CallMethod(GCList &ls, std::string name,
|
|||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
dict->SetValue("Type", "CallMethod");
|
dict->SetValue("Type", "CallMethod");
|
||||||
dict->SetValue("Name", name);
|
dict->SetValue("Name", name);
|
||||||
auto argVal = TList::Create(ls);
|
auto argVal = ls.Create<TList>();
|
||||||
argVal->items = args;
|
argVal->items = args;
|
||||||
dict->SetValue("Arguments", argVal);
|
dict->SetValue("Arguments", argVal);
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
@@ -165,8 +156,9 @@ void TDictionary::DeclareFunction(
|
|||||||
TObject TDictionary::GetValue(std::string key) {
|
TObject TDictionary::GetValue(std::string key) {
|
||||||
if (this->items.empty())
|
if (this->items.empty())
|
||||||
return Undefined();
|
return Undefined();
|
||||||
if (this->items.count(key) > 0)
|
auto item = this->items.find(key);
|
||||||
return this->items[key];
|
if (item != this->items.end())
|
||||||
|
return item->second;
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
void TDictionary::SetValue(std::string key, TObject value) {
|
void TDictionary::SetValue(std::string key, TObject value) {
|
||||||
@@ -189,18 +181,10 @@ void TDictionary::Mark() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TDictionary *TDictionary::Create(GCList *gc) {
|
TDictionary *TDictionary::Create(GCList *gc) {
|
||||||
TDictionary *dict = new TDictionary();
|
return gc->Create<TDictionary>();
|
||||||
std::shared_ptr<GC> _gc = gc->GetGC();
|
|
||||||
gc->Add(dict);
|
|
||||||
_gc->Watch(dict);
|
|
||||||
return dict;
|
|
||||||
}
|
}
|
||||||
TDictionary *TDictionary::Create(GCList &gc) {
|
TDictionary *TDictionary::Create(GCList &gc) {
|
||||||
TDictionary *dict = new TDictionary();
|
return gc.Create<TDictionary>();
|
||||||
std::shared_ptr<GC> _gc = gc.GetGC();
|
|
||||||
gc.Add(dict);
|
|
||||||
_gc->Watch(dict);
|
|
||||||
return dict;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace Tesses::CrossLang
|
}; // namespace Tesses::CrossLang
|
||||||
|
|||||||
@@ -0,0 +1,168 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang {
|
||||||
|
|
||||||
|
TException::TException(std::string message, std::string type,
|
||||||
|
TDictionary *extraFields, TObject innerException)
|
||||||
|
: message(message), type(type), extraFields(extraFields),
|
||||||
|
innerException(innerException) {}
|
||||||
|
TObject TException::CallMethod(GCList &ls, std::string key,
|
||||||
|
std::vector<TObject> args) {
|
||||||
|
|
||||||
|
if (key == "getMessage" ||
|
||||||
|
key == "getText") // Text is for compatibility reasons
|
||||||
|
return this->message;
|
||||||
|
if (key == "getInnerException")
|
||||||
|
return this->innerException;
|
||||||
|
if (key == "getType")
|
||||||
|
return this->type;
|
||||||
|
if (key == "getLine")
|
||||||
|
return static_cast<int64_t>(this->line.value_or(0));
|
||||||
|
if (key == "getOffset")
|
||||||
|
return static_cast<int64_t>(this->offset.value_or(0));
|
||||||
|
if (key == "getColumn")
|
||||||
|
return static_cast<int64_t>(this->column.value_or(0));
|
||||||
|
if (key == "getFileName")
|
||||||
|
return this->filename.value_or("");
|
||||||
|
|
||||||
|
if (key == "setLine") {
|
||||||
|
int64_t v;
|
||||||
|
if (!this->line && GetArgument(args, 0, v))
|
||||||
|
this->line = static_cast<uint32_t>(v);
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
if (key == "setColumn") {
|
||||||
|
int64_t v;
|
||||||
|
if (!this->column && GetArgument(args, 0, v))
|
||||||
|
this->column = static_cast<uint32_t>(v);
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
if (key == "setOffset") {
|
||||||
|
int64_t v;
|
||||||
|
if (!this->offset && GetArgument(args, 0, v))
|
||||||
|
this->offset = static_cast<uint32_t>(v);
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
if (key == "setFileName") {
|
||||||
|
std::string v;
|
||||||
|
if (!this->filename && GetArgument(args, 0, v))
|
||||||
|
this->filename = v;
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == "ToString") {
|
||||||
|
std::string text;
|
||||||
|
text.reserve(this->type.size() + this->message.size() + 3);
|
||||||
|
text.append(this->type);
|
||||||
|
text.append(": ");
|
||||||
|
text.append(this->message);
|
||||||
|
text.push_back('\n');
|
||||||
|
if (this->filename) {
|
||||||
|
auto &filename = *this->filename;
|
||||||
|
text.reserve(text.size() + filename.size() + 4);
|
||||||
|
text.append("At: ");
|
||||||
|
text.append(filename);
|
||||||
|
|
||||||
|
if (this->line) {
|
||||||
|
text.push_back(':');
|
||||||
|
text.append(std::to_string(*this->line));
|
||||||
|
if (this->column) {
|
||||||
|
|
||||||
|
text.push_back(':');
|
||||||
|
text.append(std::to_string(*this->column));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
text.push_back('\n');
|
||||||
|
|
||||||
|
if (!this->line && this->column) {
|
||||||
|
text.append("Column: ");
|
||||||
|
text.append(std::to_string(*this->column));
|
||||||
|
text.push_back('\n');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (this->line) {
|
||||||
|
text.append("Line: ");
|
||||||
|
text.append(std::to_string(*this->line));
|
||||||
|
text.push_back('\n');
|
||||||
|
}
|
||||||
|
if (this->column) {
|
||||||
|
text.append("Column: ");
|
||||||
|
text.append(std::to_string(*this->column));
|
||||||
|
text.push_back('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->offset) {
|
||||||
|
text.append("Offset: ");
|
||||||
|
text.append(std::to_string(*this->offset));
|
||||||
|
text.push_back('\n');
|
||||||
|
}
|
||||||
|
if (!std::holds_alternative<Undefined>(this->innerException)) {
|
||||||
|
text.append("InnerException:");
|
||||||
|
|
||||||
|
std::string textInner = ToString(ls.GetGC(), this->innerException);
|
||||||
|
|
||||||
|
for (auto item : Tesses::Framework::Http::HttpUtils::SplitString(
|
||||||
|
textInner, "\n")) {
|
||||||
|
if (item.empty()) {
|
||||||
|
text.push_back('\n');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
text.append("\n\t");
|
||||||
|
text.append(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
if (extraFields != nullptr) {
|
||||||
|
GCList ls2(ls.GetGC());
|
||||||
|
if (extraFields->MethodExists(ls2, key)) {
|
||||||
|
return extraFields->CallMethod(ls, key, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.size() > 3 && key[0] == 'g' && key[1] == 'e' && key[2] == 't') {
|
||||||
|
ls.GetGC()->BarrierBegin();
|
||||||
|
auto val = extraFields->GetValue(key.substr(3));
|
||||||
|
ls.GetGC()->BarrierEnd();
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
std::string TException::TypeName() { return this->type; }
|
||||||
|
bool TException::ToBool() { return true; }
|
||||||
|
void TException::Mark() {
|
||||||
|
if (marked)
|
||||||
|
return;
|
||||||
|
marked = true;
|
||||||
|
|
||||||
|
if (this->extraFields)
|
||||||
|
this->extraFields->Mark();
|
||||||
|
|
||||||
|
GC::Mark(this->innerException);
|
||||||
|
}
|
||||||
|
|
||||||
|
TNativeException::TNativeException(const char *what, std::exception_ptr ptr)
|
||||||
|
: what(what != nullptr ? what : ""), ptr(ptr) {}
|
||||||
|
TObject TNativeException::CallMethod(GCList &ls, std::string key,
|
||||||
|
std::vector<TObject> args) {
|
||||||
|
if (key == "getMessage" || key == "getText")
|
||||||
|
return this->what;
|
||||||
|
if (key == "getType")
|
||||||
|
return "NativeException";
|
||||||
|
|
||||||
|
if (key == "ToString") {
|
||||||
|
return "NativeException: " + this->what;
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
std::string TNativeException::TypeName() { return "NativeException"; }
|
||||||
|
std::string TNativeException::What() { return this->what; }
|
||||||
|
std::exception_ptr TNativeException::GetPointer() { return this->ptr; }
|
||||||
|
void TNativeException::ThrowIt() { std::rethrow_exception(this->ptr); }
|
||||||
|
} // namespace Tesses::CrossLang
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
#include "CrossLang.hpp"
|
#include "CrossLang.hpp"
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
TExternalMethod::TExternalMethod(
|
TExternalMethod::TExternalMethod(
|
||||||
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
|
|
||||||
std::string documentation, std::vector<std::string> argNames,
|
std::string documentation, std::vector<std::string> argNames,
|
||||||
|
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
|
||||||
std::function<void()> destroy) {
|
std::function<void()> destroy) {
|
||||||
|
|
||||||
this->cb = cb;
|
this->cb = cb;
|
||||||
@@ -14,43 +14,24 @@ TExternalMethod *TExternalMethod::Create(
|
|||||||
GCList &ls, std::string documentation, std::vector<std::string> argNames,
|
GCList &ls, std::string documentation, std::vector<std::string> argNames,
|
||||||
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
|
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
|
||||||
std::function<void()> destroy) {
|
std::function<void()> destroy) {
|
||||||
auto gc = ls.GetGC();
|
return ls.Create<TExternalMethod>(documentation, argNames, cb, destroy);
|
||||||
TExternalMethod *method =
|
|
||||||
new TExternalMethod(cb, documentation, argNames, destroy);
|
|
||||||
ls.Add(method);
|
|
||||||
gc->Watch(method);
|
|
||||||
return method;
|
|
||||||
}
|
}
|
||||||
TExternalMethod *TExternalMethod::Create(
|
TExternalMethod *TExternalMethod::Create(
|
||||||
GCList *ls, std::string documentation, std::vector<std::string> argNames,
|
GCList *ls, std::string documentation, std::vector<std::string> argNames,
|
||||||
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
|
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
|
||||||
std::function<void()> destroy) {
|
std::function<void()> destroy) {
|
||||||
auto gc = ls->GetGC();
|
return ls->Create<TExternalMethod>(documentation, argNames, cb, destroy);
|
||||||
TExternalMethod *method =
|
|
||||||
new TExternalMethod(cb, documentation, argNames, destroy);
|
|
||||||
ls->Add(method);
|
|
||||||
gc->Watch(method);
|
|
||||||
return method;
|
|
||||||
}
|
}
|
||||||
TExternalMethod *TExternalMethod::Create(
|
TExternalMethod *TExternalMethod::Create(
|
||||||
GCList &ls, std::string documentation, std::vector<std::string> argNames,
|
GCList &ls, std::string documentation, std::vector<std::string> argNames,
|
||||||
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb) {
|
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb) {
|
||||||
auto gc = ls.GetGC();
|
return ls.Create<TExternalMethod>(documentation, argNames, cb);
|
||||||
TExternalMethod *method =
|
|
||||||
new TExternalMethod(cb, documentation, argNames, []() -> void {});
|
|
||||||
ls.Add(method);
|
|
||||||
gc->Watch(method);
|
|
||||||
return method;
|
|
||||||
}
|
}
|
||||||
TExternalMethod *TExternalMethod::Create(
|
TExternalMethod *TExternalMethod::Create(
|
||||||
GCList *ls, std::string documentation, std::vector<std::string> argNames,
|
GCList *ls, std::string documentation, std::vector<std::string> argNames,
|
||||||
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb) {
|
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb) {
|
||||||
auto gc = ls->GetGC();
|
|
||||||
TExternalMethod *method =
|
return ls->Create<TExternalMethod>(documentation, argNames, cb);
|
||||||
new TExternalMethod(cb, documentation, argNames, []() -> void {});
|
|
||||||
ls->Add(method);
|
|
||||||
gc->Watch(method);
|
|
||||||
return method;
|
|
||||||
}
|
}
|
||||||
TObject TExternalMethod::Call(GCList &ls, std::vector<TObject> args) {
|
TObject TExternalMethod::Call(GCList &ls, std::vector<TObject> args) {
|
||||||
if (cb == nullptr)
|
if (cb == nullptr)
|
||||||
|
|||||||
+35
-114
@@ -44,28 +44,15 @@ void TYieldEnumerator::Mark() {
|
|||||||
GC::Mark(this->current);
|
GC::Mark(this->current);
|
||||||
GC::Mark(this->enumerator);
|
GC::Mark(this->enumerator);
|
||||||
}
|
}
|
||||||
TYieldEnumerator *TYieldEnumerator::Create(GCList &ls, TObject v) {
|
|
||||||
TYieldEnumerator *yieldEnum = new TYieldEnumerator();
|
|
||||||
yieldEnum->current = nullptr;
|
|
||||||
yieldEnum->hasStarted = false;
|
|
||||||
yieldEnum->enumerator = v;
|
|
||||||
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
TYieldEnumerator::TYieldEnumerator(TObject v)
|
||||||
ls.Add(yieldEnum);
|
: current(nullptr), hasStarted(false), enumerator(v) {}
|
||||||
_gc->Watch(yieldEnum);
|
|
||||||
return yieldEnum;
|
TYieldEnumerator *TYieldEnumerator::Create(GCList &ls, TObject v) {
|
||||||
|
return ls.Create<TYieldEnumerator>(v);
|
||||||
}
|
}
|
||||||
TYieldEnumerator *TYieldEnumerator::Create(GCList *ls, TObject v) {
|
TYieldEnumerator *TYieldEnumerator::Create(GCList *ls, TObject v) {
|
||||||
|
return ls->Create<TYieldEnumerator>(v);
|
||||||
TYieldEnumerator *yieldEnum = new TYieldEnumerator();
|
|
||||||
yieldEnum->current = nullptr;
|
|
||||||
yieldEnum->hasStarted = false;
|
|
||||||
yieldEnum->enumerator = v;
|
|
||||||
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(yieldEnum);
|
|
||||||
_gc->Watch(yieldEnum);
|
|
||||||
return yieldEnum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TCustomEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
bool TCustomEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||||
@@ -97,21 +84,12 @@ void TCustomEnumerator::Mark() {
|
|||||||
return;
|
return;
|
||||||
this->dict->Mark();
|
this->dict->Mark();
|
||||||
}
|
}
|
||||||
|
TCustomEnumerator::TCustomEnumerator(TDictionary *dict) : dict(dict) {}
|
||||||
TCustomEnumerator *TCustomEnumerator::Create(GCList *ls, TDictionary *dict) {
|
TCustomEnumerator *TCustomEnumerator::Create(GCList *ls, TDictionary *dict) {
|
||||||
TCustomEnumerator *customEnum = new TCustomEnumerator();
|
return ls->Create<TCustomEnumerator>(dict);
|
||||||
customEnum->dict = dict;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(customEnum);
|
|
||||||
_gc->Watch(customEnum);
|
|
||||||
return customEnum;
|
|
||||||
}
|
}
|
||||||
TCustomEnumerator *TCustomEnumerator::Create(GCList &ls, TDictionary *dict) {
|
TCustomEnumerator *TCustomEnumerator::Create(GCList &ls, TDictionary *dict) {
|
||||||
TCustomEnumerator *customEnum = new TCustomEnumerator();
|
return ls.Create<TCustomEnumerator>(dict);
|
||||||
customEnum->dict = dict;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(customEnum);
|
|
||||||
_gc->Watch(customEnum);
|
|
||||||
return customEnum;
|
|
||||||
}
|
}
|
||||||
TEnumerator *TEnumerator::CreateFromObject(GCList &ls, TObject obj) {
|
TEnumerator *TEnumerator::CreateFromObject(GCList &ls, TObject obj) {
|
||||||
std::string str;
|
std::string str;
|
||||||
@@ -141,23 +119,16 @@ TEnumerator *TEnumerator::CreateFromObject(GCList &ls, TObject obj) {
|
|||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
TVFSPathEnumerator::TVFSPathEnumerator(
|
||||||
|
Tesses::Framework::Filesystem::VFSPathEnumerator enumerator)
|
||||||
|
: enumerator(enumerator) {}
|
||||||
TVFSPathEnumerator *TVFSPathEnumerator::Create(
|
TVFSPathEnumerator *TVFSPathEnumerator::Create(
|
||||||
GCList &ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) {
|
GCList &ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) {
|
||||||
TVFSPathEnumerator *vfspathe = new TVFSPathEnumerator();
|
return ls.Create<TVFSPathEnumerator>(enumerator);
|
||||||
vfspathe->enumerator = enumerator;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(vfspathe);
|
|
||||||
_gc->Watch(vfspathe);
|
|
||||||
return vfspathe;
|
|
||||||
}
|
}
|
||||||
TVFSPathEnumerator *TVFSPathEnumerator::Create(
|
TVFSPathEnumerator *TVFSPathEnumerator::Create(
|
||||||
GCList *ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) {
|
GCList *ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) {
|
||||||
TVFSPathEnumerator *vfspathe = new TVFSPathEnumerator();
|
return ls->Create<TVFSPathEnumerator>(enumerator);
|
||||||
vfspathe->enumerator = enumerator;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(vfspathe);
|
|
||||||
_gc->Watch(vfspathe);
|
|
||||||
return vfspathe;
|
|
||||||
}
|
}
|
||||||
bool TVFSPathEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
bool TVFSPathEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||||
return enumerator.MoveNext();
|
return enumerator.MoveNext();
|
||||||
@@ -165,25 +136,15 @@ bool TVFSPathEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
|||||||
TObject TVFSPathEnumerator::GetCurrent(GCList &ls) {
|
TObject TVFSPathEnumerator::GetCurrent(GCList &ls) {
|
||||||
return enumerator.Current;
|
return enumerator.Current;
|
||||||
}
|
}
|
||||||
|
TDictionaryEnumerator::TDictionaryEnumerator(TDictionary *dict)
|
||||||
|
: dict(dict), hasStarted(false) {}
|
||||||
TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList &ls,
|
TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList &ls,
|
||||||
TDictionary *dict) {
|
TDictionary *dict) {
|
||||||
TDictionaryEnumerator *dicte = new TDictionaryEnumerator();
|
return ls.Create<TDictionaryEnumerator>(dict);
|
||||||
dicte->dict = dict;
|
|
||||||
dicte->hasStarted = false;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(dicte);
|
|
||||||
_gc->Watch(dicte);
|
|
||||||
return dicte;
|
|
||||||
}
|
}
|
||||||
TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList *ls,
|
TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList *ls,
|
||||||
TDictionary *dict) {
|
TDictionary *dict) {
|
||||||
TDictionaryEnumerator *dicte = new TDictionaryEnumerator();
|
return ls->Create<TDictionaryEnumerator>(dict);
|
||||||
dicte->dict = dict;
|
|
||||||
dicte->hasStarted = false;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(dicte);
|
|
||||||
_gc->Watch(dicte);
|
|
||||||
return dicte;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TDictionaryEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
bool TDictionaryEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||||
@@ -217,24 +178,13 @@ void TDictionaryEnumerator::Mark() {
|
|||||||
this->marked = true;
|
this->marked = true;
|
||||||
this->dict->Mark();
|
this->dict->Mark();
|
||||||
}
|
}
|
||||||
|
TListEnumerator::TListEnumerator(TList *list) : ls(list), index(-1) {}
|
||||||
|
|
||||||
TListEnumerator *TListEnumerator::Create(GCList &ls, TList *list) {
|
TListEnumerator *TListEnumerator::Create(GCList &ls, TList *list) {
|
||||||
TListEnumerator *liste = new TListEnumerator();
|
return ls.Create<TListEnumerator>(list);
|
||||||
liste->ls = list;
|
|
||||||
liste->index = -1;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(liste);
|
|
||||||
_gc->Watch(liste);
|
|
||||||
return liste;
|
|
||||||
}
|
}
|
||||||
TListEnumerator *TListEnumerator::Create(GCList *ls, TList *list) {
|
TListEnumerator *TListEnumerator::Create(GCList *ls, TList *list) {
|
||||||
TListEnumerator *liste = new TListEnumerator();
|
return ls->Create<TListEnumerator>(list);
|
||||||
liste->ls = list;
|
|
||||||
liste->index = -1;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(liste);
|
|
||||||
_gc->Watch(liste);
|
|
||||||
return liste;
|
|
||||||
}
|
}
|
||||||
bool TListEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
bool TListEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||||
this->index++;
|
this->index++;
|
||||||
@@ -260,25 +210,17 @@ void TListEnumerator::Mark() {
|
|||||||
this->ls->Mark();
|
this->ls->Mark();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TAssociativeArrayEnumerator::TAssociativeArrayEnumerator(
|
||||||
|
TAssociativeArray *list)
|
||||||
|
: ls(list), index(-1) {}
|
||||||
|
|
||||||
TAssociativeArrayEnumerator *
|
TAssociativeArrayEnumerator *
|
||||||
TAssociativeArrayEnumerator::Create(GCList &ls, TAssociativeArray *list) {
|
TAssociativeArrayEnumerator::Create(GCList &ls, TAssociativeArray *list) {
|
||||||
TAssociativeArrayEnumerator *liste = new TAssociativeArrayEnumerator();
|
return ls.Create<TAssociativeArrayEnumerator>(list);
|
||||||
liste->ls = list;
|
|
||||||
liste->index = -1;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(liste);
|
|
||||||
_gc->Watch(liste);
|
|
||||||
return liste;
|
|
||||||
}
|
}
|
||||||
TAssociativeArrayEnumerator *
|
TAssociativeArrayEnumerator *
|
||||||
TAssociativeArrayEnumerator::Create(GCList *ls, TAssociativeArray *list) {
|
TAssociativeArrayEnumerator::Create(GCList *ls, TAssociativeArray *list) {
|
||||||
TAssociativeArrayEnumerator *liste = new TAssociativeArrayEnumerator();
|
return ls->Create<TAssociativeArrayEnumerator>(list);
|
||||||
liste->ls = list;
|
|
||||||
liste->index = -1;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(liste);
|
|
||||||
_gc->Watch(liste);
|
|
||||||
return liste;
|
|
||||||
}
|
}
|
||||||
bool TAssociativeArrayEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
bool TAssociativeArrayEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||||
this->index++;
|
this->index++;
|
||||||
@@ -305,26 +247,16 @@ void TAssociativeArrayEnumerator::Mark() {
|
|||||||
this->marked = true;
|
this->marked = true;
|
||||||
this->ls->Mark();
|
this->ls->Mark();
|
||||||
}
|
}
|
||||||
|
TDynamicListEnumerator::TDynamicListEnumerator(TDynamicList *list)
|
||||||
|
: ls(list), index(-1) {}
|
||||||
|
|
||||||
TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList &ls,
|
TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList &ls,
|
||||||
TDynamicList *list) {
|
TDynamicList *list) {
|
||||||
TDynamicListEnumerator *liste = new TDynamicListEnumerator();
|
return ls.Create<TDynamicListEnumerator>(list);
|
||||||
liste->ls = list;
|
|
||||||
liste->index = -1;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(liste);
|
|
||||||
_gc->Watch(liste);
|
|
||||||
return liste;
|
|
||||||
}
|
}
|
||||||
TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList *ls,
|
TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList *ls,
|
||||||
TDynamicList *list) {
|
TDynamicList *list) {
|
||||||
TDynamicListEnumerator *liste = new TDynamicListEnumerator();
|
return ls->Create<TDynamicListEnumerator>(list);
|
||||||
liste->ls = list;
|
|
||||||
liste->index = -1;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(liste);
|
|
||||||
_gc->Watch(liste);
|
|
||||||
return liste;
|
|
||||||
}
|
}
|
||||||
bool TDynamicListEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
bool TDynamicListEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||||
this->index++;
|
this->index++;
|
||||||
@@ -351,24 +283,13 @@ void TDynamicListEnumerator::Mark() {
|
|||||||
this->marked = true;
|
this->marked = true;
|
||||||
this->ls->Mark();
|
this->ls->Mark();
|
||||||
}
|
}
|
||||||
|
TStringEnumerator::TStringEnumerator(std::string str)
|
||||||
|
: str(str), hasStarted(false) {}
|
||||||
TStringEnumerator *TStringEnumerator::Create(GCList &ls, std::string str) {
|
TStringEnumerator *TStringEnumerator::Create(GCList &ls, std::string str) {
|
||||||
TStringEnumerator *stre = new TStringEnumerator();
|
return ls.Create<TStringEnumerator>(str);
|
||||||
stre->str = str;
|
|
||||||
stre->hasStarted = false;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(stre);
|
|
||||||
_gc->Watch(stre);
|
|
||||||
return stre;
|
|
||||||
}
|
}
|
||||||
TStringEnumerator *TStringEnumerator::Create(GCList *ls, std::string str) {
|
TStringEnumerator *TStringEnumerator::Create(GCList *ls, std::string str) {
|
||||||
TStringEnumerator *stre = new TStringEnumerator();
|
return ls->Create<TStringEnumerator>(str);
|
||||||
stre->str = str;
|
|
||||||
stre->hasStarted = false;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(stre);
|
|
||||||
_gc->Watch(stre);
|
|
||||||
return stre;
|
|
||||||
}
|
}
|
||||||
bool TStringEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
bool TStringEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||||
if (!this->hasStarted) {
|
if (!this->hasStarted) {
|
||||||
|
|||||||
+214
-51
@@ -1,20 +1,11 @@
|
|||||||
#include "CrossLang.hpp"
|
#include "CrossLang.hpp"
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
|
TDynamicList::TDynamicList(TCallable *callable) : cb(callable) {}
|
||||||
TDynamicList *TDynamicList::Create(GCList &ls, TCallable *callable) {
|
TDynamicList *TDynamicList::Create(GCList &ls, TCallable *callable) {
|
||||||
TDynamicList *list = new TDynamicList();
|
return ls.Create<TDynamicList>(callable);
|
||||||
list->cb = callable;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(list);
|
|
||||||
_gc->Watch(list);
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
TDynamicList *TDynamicList::Create(GCList *ls, TCallable *callable) {
|
TDynamicList *TDynamicList::Create(GCList *ls, TCallable *callable) {
|
||||||
TDynamicList *list = new TDynamicList();
|
return ls->Create<TDynamicList>(callable);
|
||||||
list->cb = callable;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(list);
|
|
||||||
_gc->Watch(list);
|
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TDynamicList::Mark() {
|
void TDynamicList::Mark() {
|
||||||
@@ -28,7 +19,7 @@ int64_t TDynamicList::Count(GCList &ls) {
|
|||||||
|
|
||||||
auto dict = TDictionary::Create(ls);
|
auto dict = TDictionary::Create(ls);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
dict->SetValue("Type", "Count");
|
dict->SetValue("Type", ls.FromString("Count"));
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
auto res = cb->Call(ls, {dict});
|
auto res = cb->Call(ls, {dict});
|
||||||
int64_t n;
|
int64_t n;
|
||||||
@@ -40,7 +31,7 @@ TObject TDynamicList::Add(GCList &ls, TObject v) {
|
|||||||
|
|
||||||
auto dict = TDictionary::Create(ls);
|
auto dict = TDictionary::Create(ls);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
dict->SetValue("Type", "Add");
|
dict->SetValue("Type", ls.FromString("Add"));
|
||||||
dict->SetValue("Value", v);
|
dict->SetValue("Value", v);
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
return cb->Call(ls, {dict});
|
return cb->Call(ls, {dict});
|
||||||
@@ -49,7 +40,7 @@ TObject TDynamicList::Insert(GCList &ls, int64_t index, TObject v) {
|
|||||||
|
|
||||||
auto dict = TDictionary::Create(ls);
|
auto dict = TDictionary::Create(ls);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
dict->SetValue("Type", "Insert");
|
dict->SetValue("Type", ls.FromString("Insert"));
|
||||||
dict->SetValue("Index", index);
|
dict->SetValue("Index", index);
|
||||||
dict->SetValue("Value", v);
|
dict->SetValue("Value", v);
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
@@ -58,14 +49,14 @@ TObject TDynamicList::Insert(GCList &ls, int64_t index, TObject v) {
|
|||||||
TObject TDynamicList::Clear(GCList &ls) {
|
TObject TDynamicList::Clear(GCList &ls) {
|
||||||
auto dict = TDictionary::Create(ls);
|
auto dict = TDictionary::Create(ls);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
dict->SetValue("Type", "Clear");
|
dict->SetValue("Type", ls.FromString("Clear"));
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
return cb->Call(ls, {dict});
|
return cb->Call(ls, {dict});
|
||||||
}
|
}
|
||||||
TObject TDynamicList::Remove(GCList &ls, TObject obj) {
|
TObject TDynamicList::Remove(GCList &ls, TObject obj) {
|
||||||
auto dict = TDictionary::Create(ls);
|
auto dict = TDictionary::Create(ls);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
dict->SetValue("Type", "Remove");
|
dict->SetValue("Type", ls.FromString("Remove"));
|
||||||
dict->SetValue("Value", obj);
|
dict->SetValue("Value", obj);
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
|
|
||||||
@@ -74,7 +65,7 @@ TObject TDynamicList::Remove(GCList &ls, TObject obj) {
|
|||||||
TObject TDynamicList::RemoveAllEqual(GCList &ls, TObject obj) {
|
TObject TDynamicList::RemoveAllEqual(GCList &ls, TObject obj) {
|
||||||
auto dict = TDictionary::Create(ls);
|
auto dict = TDictionary::Create(ls);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
dict->SetValue("Type", "RemoveAllEqual");
|
dict->SetValue("Type", ls.FromString("RemoveAllEqual"));
|
||||||
dict->SetValue("Value", obj);
|
dict->SetValue("Value", obj);
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
|
|
||||||
@@ -83,7 +74,7 @@ TObject TDynamicList::RemoveAllEqual(GCList &ls, TObject obj) {
|
|||||||
TObject TDynamicList::RemoveAt(GCList &ls, int64_t index) {
|
TObject TDynamicList::RemoveAt(GCList &ls, int64_t index) {
|
||||||
auto dict = TDictionary::Create(ls);
|
auto dict = TDictionary::Create(ls);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
dict->SetValue("Type", "RemoveAt");
|
dict->SetValue("Type", ls.FromString("RemoveAt"));
|
||||||
dict->SetValue("Index", index);
|
dict->SetValue("Index", index);
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
|
|
||||||
@@ -92,7 +83,7 @@ TObject TDynamicList::RemoveAt(GCList &ls, int64_t index) {
|
|||||||
TObject TDynamicList::ToString(GCList &ls) {
|
TObject TDynamicList::ToString(GCList &ls) {
|
||||||
auto dict = TDictionary::Create(ls);
|
auto dict = TDictionary::Create(ls);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
dict->SetValue("Type", "ToString");
|
dict->SetValue("Type", ls.FromString("ToString"));
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
|
|
||||||
return cb->Call(ls, {dict});
|
return cb->Call(ls, {dict});
|
||||||
@@ -102,7 +93,7 @@ TObject TDynamicList::GetAt(GCList &ls, int64_t index) {
|
|||||||
|
|
||||||
auto dict = TDictionary::Create(ls);
|
auto dict = TDictionary::Create(ls);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
dict->SetValue("Type", "GetAt");
|
dict->SetValue("Type", ls.FromString("GetAt"));
|
||||||
dict->SetValue("Index", index);
|
dict->SetValue("Index", index);
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
return cb->Call(ls, {dict});
|
return cb->Call(ls, {dict});
|
||||||
@@ -111,7 +102,7 @@ TObject TDynamicList::GetAt(GCList &ls, int64_t index) {
|
|||||||
TObject TDynamicList::SetAt(GCList &ls, int64_t index, TObject val) {
|
TObject TDynamicList::SetAt(GCList &ls, int64_t index, TObject val) {
|
||||||
auto dict = TDictionary::Create(ls);
|
auto dict = TDictionary::Create(ls);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
dict->SetValue("Type", "SetAt");
|
dict->SetValue("Type", ls.FromString("SetAt"));
|
||||||
dict->SetValue("Index", index);
|
dict->SetValue("Index", index);
|
||||||
dict->SetValue("Value", val);
|
dict->SetValue("Value", val);
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
@@ -120,35 +111,10 @@ TObject TDynamicList::SetAt(GCList &ls, int64_t index, TObject val) {
|
|||||||
|
|
||||||
TDynamicList::~TDynamicList() {}
|
TDynamicList::~TDynamicList() {}
|
||||||
|
|
||||||
TByteArray *TByteArray::Create(GCList &ls) {
|
TByteArray *TByteArray::Create(GCList &ls) { return ls.Create<TByteArray>(); }
|
||||||
TByteArray *arr = new TByteArray();
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
TByteArray *TByteArray::Create(GCList *ls) { return ls->Create<TByteArray>(); }
|
||||||
ls.Add(arr);
|
|
||||||
_gc->Watch(arr);
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
|
|
||||||
TByteArray *TByteArray::Create(GCList *ls) {
|
|
||||||
TByteArray *arr = new TByteArray();
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(arr);
|
|
||||||
_gc->Watch(arr);
|
|
||||||
return arr;
|
|
||||||
}
|
|
||||||
TList *TList::Create(GCList *gc) {
|
|
||||||
TList *list = new TList();
|
|
||||||
std::shared_ptr<GC> _gc = gc->GetGC();
|
|
||||||
gc->Add(list);
|
|
||||||
_gc->Watch(list);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
TList *TList::Create(GCList &gc) {
|
|
||||||
TList *list = new TList();
|
|
||||||
std::shared_ptr<GC> _gc = gc.GetGC();
|
|
||||||
gc.Add(list);
|
|
||||||
_gc->Watch(list);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
void TList::Add(TObject value) { this->items.push_back(value); }
|
void TList::Add(TObject value) { this->items.push_back(value); }
|
||||||
void TList::Set(int64_t index, TObject value) {
|
void TList::Set(int64_t index, TObject value) {
|
||||||
if (index >= 0 && index < this->Count()) {
|
if (index >= 0 && index < this->Count()) {
|
||||||
@@ -161,7 +127,7 @@ TObject TList::Get(int64_t index) {
|
|||||||
}
|
}
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
int64_t TList::Count() { return (int64_t)this->items.size(); }
|
int64_t TList::Count() { return this->items.size(); }
|
||||||
void TList::Insert(int64_t index, TObject value) {
|
void TList::Insert(int64_t index, TObject value) {
|
||||||
if (index >= 0 && index <= this->Count()) {
|
if (index >= 0 && index <= this->Count()) {
|
||||||
this->items.insert(this->items.begin() + index, value);
|
this->items.insert(this->items.begin() + index, value);
|
||||||
@@ -181,4 +147,201 @@ void TList::Mark() {
|
|||||||
GC::Mark(item);
|
GC::Mark(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
std::string TList::TypeName() { return "List"; }
|
||||||
|
bool TList::opGetField(InterperterThread *thrd, std::shared_ptr<GC> gc,
|
||||||
|
const std::string &name) {
|
||||||
|
auto &cse = thrd->call_stack_entries;
|
||||||
|
if (name == "Count" || name == "Length") {
|
||||||
|
int64_t len = this->Count();
|
||||||
|
if (len < 0)
|
||||||
|
len = 0;
|
||||||
|
|
||||||
|
cse.back()->Push(gc, len);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool TList::opExecuteMethod(InterperterThread *thrd, std::shared_ptr<GC> gc,
|
||||||
|
const std::string &name,
|
||||||
|
const std::vector<TObject> &args) {
|
||||||
|
|
||||||
|
auto &cse = thrd->call_stack_entries;
|
||||||
|
GCList ls(gc);
|
||||||
|
|
||||||
|
if (name == "GetEnumerator") {
|
||||||
|
cse.back()->Push(gc, ls.Create<TListEnumerator>(this));
|
||||||
|
return false;
|
||||||
|
} else if (name == "ToString") {
|
||||||
|
|
||||||
|
cse.back()->Push(gc, Json_Encode(this));
|
||||||
|
return false;
|
||||||
|
|
||||||
|
} else if (name == "Insert") {
|
||||||
|
if (args.size() != 2) {
|
||||||
|
throw VMException("List.Insert must only accept two arguments");
|
||||||
|
}
|
||||||
|
int64_t index;
|
||||||
|
|
||||||
|
if (!GetArgument(args, 0, index)) {
|
||||||
|
throw VMException("List.Insert first argument must be Long");
|
||||||
|
}
|
||||||
|
|
||||||
|
gc->BarrierBegin();
|
||||||
|
this->Insert(index, args[1]);
|
||||||
|
gc->BarrierEnd();
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
} else if (name == "Add") {
|
||||||
|
if (args.size() != 1) {
|
||||||
|
throw VMException("List.Add must only accept one argument");
|
||||||
|
}
|
||||||
|
gc->BarrierBegin();
|
||||||
|
this->Add(args[0]);
|
||||||
|
gc->BarrierEnd();
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
} else if (name == "Contains") {
|
||||||
|
if (args.size() != 1) {
|
||||||
|
throw VMException("List.Contains must only accept one argument");
|
||||||
|
}
|
||||||
|
gc->BarrierBegin();
|
||||||
|
for (int64_t i = 0; i < this->Count(); i++) {
|
||||||
|
auto item = this->Get(i);
|
||||||
|
gc->BarrierEnd();
|
||||||
|
if (Equals(gc, args[0], item)) {
|
||||||
|
cse.back()->Push(gc, true);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gc->BarrierBegin();
|
||||||
|
}
|
||||||
|
gc->BarrierEnd();
|
||||||
|
cse.back()->Push(gc, false);
|
||||||
|
return false;
|
||||||
|
} else if (name == "IndexOf") {
|
||||||
|
// IndexOf(obj, $idx)
|
||||||
|
if (args.size() < 1 || args.size() > 2) {
|
||||||
|
throw VMException("List.IndexOf must either have one "
|
||||||
|
"or two arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t i = 0;
|
||||||
|
|
||||||
|
GetArgument(args, 1, i);
|
||||||
|
gc->BarrierBegin();
|
||||||
|
for (; i < this->Count(); i++) {
|
||||||
|
auto item = this->Get(i);
|
||||||
|
gc->BarrierEnd();
|
||||||
|
if (Equals(gc, args[0], item)) {
|
||||||
|
|
||||||
|
cse.back()->Push(gc, i);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
gc->BarrierBegin();
|
||||||
|
}
|
||||||
|
gc->BarrierEnd();
|
||||||
|
cse.back()->Push(gc, (int64_t)-1);
|
||||||
|
return false;
|
||||||
|
} else if (name == "RemoveAllEqual") {
|
||||||
|
if (args.size() != 1) {
|
||||||
|
throw VMException("List.RemoveAllEqual must only "
|
||||||
|
"accept one argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
gc->BarrierBegin();
|
||||||
|
for (int64_t i = 0; i < this->Count(); i++) {
|
||||||
|
auto item = this->Get(i);
|
||||||
|
gc->BarrierEnd();
|
||||||
|
if (Equals(gc, args[0], item)) {
|
||||||
|
gc->BarrierBegin();
|
||||||
|
this->RemoveAt(i);
|
||||||
|
i--;
|
||||||
|
} else
|
||||||
|
gc->BarrierBegin();
|
||||||
|
}
|
||||||
|
gc->BarrierEnd();
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
} else if (name == "Remove") {
|
||||||
|
if (args.size() != 1) {
|
||||||
|
throw VMException("List.Remove must only accept one argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
gc->BarrierBegin();
|
||||||
|
for (int64_t i = 0; i < this->Count(); i++) {
|
||||||
|
auto item = this->Get(i);
|
||||||
|
gc->BarrierEnd();
|
||||||
|
if (Equals(gc, args[0], item)) {
|
||||||
|
gc->BarrierBegin();
|
||||||
|
this->RemoveAt(i);
|
||||||
|
gc->BarrierEnd();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
gc->BarrierBegin();
|
||||||
|
}
|
||||||
|
gc->BarrierEnd();
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
} else if (name == "RemoveAt") {
|
||||||
|
if (args.size() != 1) {
|
||||||
|
throw VMException("List.RemoveAt must only accept one argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::holds_alternative<int64_t>(args[0])) {
|
||||||
|
throw VMException("List.RemoveAt must only accept a long");
|
||||||
|
}
|
||||||
|
gc->BarrierBegin();
|
||||||
|
this->RemoveAt(std::get<int64_t>(args[0]));
|
||||||
|
gc->BarrierEnd();
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
} else if (name == "Clear") {
|
||||||
|
gc->BarrierBegin();
|
||||||
|
this->Clear();
|
||||||
|
gc->BarrierEnd();
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
} else if (name == "GetAt") {
|
||||||
|
if (args.size() != 1) {
|
||||||
|
throw VMException("List.GetAt must only accept one argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::holds_alternative<int64_t>(args[0])) {
|
||||||
|
throw VMException("List.GetAt must only accept a long");
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t index = std::get<int64_t>(args[0]);
|
||||||
|
if (index >= 0 && index < this->Count()) {
|
||||||
|
cse.back()->Push(gc, this->Get(index));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (name == "SetAt") {
|
||||||
|
if (args.size() != 2) {
|
||||||
|
throw VMException("List.SetAt must only accept two arguments");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!std::holds_alternative<int64_t>(args[0])) {
|
||||||
|
throw VMException("List.SetAt first argument must only "
|
||||||
|
"accept a long");
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t index = std::get<int64_t>(args[0]);
|
||||||
|
if (index >= 0 && index < this->Count()) {
|
||||||
|
this->Set(index, args[1]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (name == "Count" || name == "Length") {
|
||||||
|
gc->BarrierBegin();
|
||||||
|
cse.back()->Push(gc, this->Count());
|
||||||
|
gc->BarrierEnd();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}; // namespace Tesses::CrossLang
|
}; // namespace Tesses::CrossLang
|
||||||
+4
-13
@@ -1,7 +1,6 @@
|
|||||||
#include "CrossLang.hpp"
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
TNativeObject::~TNativeObject() {}
|
|
||||||
|
|
||||||
TNative::TNative(void *ptr, std::function<void(void *)> destroy) {
|
TNative::TNative(void *ptr, std::function<void(void *)> destroy) {
|
||||||
this->ptr = ptr;
|
this->ptr = ptr;
|
||||||
@@ -27,26 +26,18 @@ void TNative::Destroy() {
|
|||||||
}
|
}
|
||||||
bool TNativeObject::ToBool() { return true; }
|
bool TNativeObject::ToBool() { return true; }
|
||||||
bool TNativeObject::Equals(std::shared_ptr<GC> gc, TObject right) {
|
bool TNativeObject::Equals(std::shared_ptr<GC> gc, TObject right) {
|
||||||
if (std::holds_alternative<THeapObjectHolder>(right)) {
|
if (std::holds_alternative<THeapObject *>(right)) {
|
||||||
return this == std::get<THeapObjectHolder>(right).obj;
|
return this == std::get<THeapObject *>(right);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
TNative *TNative::Create(GCList &ls, void *ptr,
|
TNative *TNative::Create(GCList &ls, void *ptr,
|
||||||
std::function<void(void *)> destroy) {
|
std::function<void(void *)> destroy) {
|
||||||
TNative *native = new TNative(ptr, destroy);
|
return ls.Create<TNative>(ptr, destroy);
|
||||||
std::shared_ptr<GC> gc = ls.GetGC();
|
|
||||||
ls.Add(native);
|
|
||||||
gc->Watch(native);
|
|
||||||
return native;
|
|
||||||
}
|
}
|
||||||
TNative *TNative::Create(GCList *ls, void *ptr,
|
TNative *TNative::Create(GCList *ls, void *ptr,
|
||||||
std::function<void(void *)> destroy) {
|
std::function<void(void *)> destroy) {
|
||||||
TNative *native = new TNative(ptr, destroy);
|
return ls->Create<TNative>(ptr, destroy);
|
||||||
std::shared_ptr<GC> gc = ls->GetGC();
|
|
||||||
ls->Add(native);
|
|
||||||
gc->Watch(native);
|
|
||||||
return native;
|
|
||||||
}
|
}
|
||||||
TNative::~TNative() { this->Destroy(); }
|
TNative::~TNative() { this->Destroy(); }
|
||||||
|
|
||||||
|
|||||||
+3
-11
@@ -32,7 +32,7 @@ TList *TQueryable::ToList(GCList &ls) {
|
|||||||
auto enumerator = this->GetEnumerator(ls);
|
auto enumerator = this->GetEnumerator(ls);
|
||||||
if (enumerator == nullptr)
|
if (enumerator == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
auto list = TList::Create(ls);
|
auto list = ls.Create<TList>();
|
||||||
while (enumerator->MoveNext(gc)) {
|
while (enumerator->MoveNext(gc)) {
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
list->Add(enumerator->GetCurrent(ls));
|
list->Add(enumerator->GetCurrent(ls));
|
||||||
@@ -41,19 +41,11 @@ TList *TQueryable::ToList(GCList &ls) {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
TQueryable *TQueryable::Create(GCList &ls, TObject parent) {
|
TQueryable *TQueryable::Create(GCList &ls, TObject parent) {
|
||||||
TQueryable *queryable = new TQueryable(parent);
|
return ls.Create<TQueryable>(parent);
|
||||||
std::shared_ptr<GC> gc = ls.GetGC();
|
|
||||||
ls.Add(queryable);
|
|
||||||
gc->Watch(queryable);
|
|
||||||
return queryable;
|
|
||||||
}
|
}
|
||||||
TQueryable *TQueryable::Create(GCList &ls, TObject parent, TQueryableMode mode,
|
TQueryable *TQueryable::Create(GCList &ls, TObject parent, TQueryableMode mode,
|
||||||
std::vector<TObject> args) {
|
std::vector<TObject> args) {
|
||||||
TQueryable *queryable = new TQueryable(parent, mode, args);
|
return ls.Create<TQueryable>(parent, mode, args);
|
||||||
std::shared_ptr<GC> gc = ls.GetGC();
|
|
||||||
ls.Add(queryable);
|
|
||||||
gc->Watch(queryable);
|
|
||||||
return queryable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TQueryable::Mark() {
|
void TQueryable::Mark() {
|
||||||
|
|||||||
@@ -9,12 +9,11 @@ void ThrowConstError(std::string key) {
|
|||||||
|
|
||||||
void TEnvironment::DeclareConstVariable(std::string key, TObject value) {
|
void TEnvironment::DeclareConstVariable(std::string key, TObject value) {
|
||||||
this->DeclareVariable(key, value);
|
this->DeclareVariable(key, value);
|
||||||
this->consts.push_back(key);
|
this->decls[key] = TEnvironmentDeclType::TEDT_CONST;
|
||||||
}
|
}
|
||||||
bool TEnvironment::HasConstForDeclare(std::string key) {
|
bool TEnvironment::HasConstForDeclare(std::string key) {
|
||||||
for (auto item : this->consts)
|
if (this->decls.count(key) > 0)
|
||||||
if (item == key)
|
return this->decls[key] == TEnvironmentDeclType::TEDT_CONST;
|
||||||
return true;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool TEnvironment::HasConstForSet(std::string key) {
|
bool TEnvironment::HasConstForSet(std::string key) {
|
||||||
@@ -172,9 +171,8 @@ void TEnvironment::DeclareVariable(std::shared_ptr<GC> gc,
|
|||||||
|
|
||||||
TObject v = this->GetVariable(name[0]);
|
TObject v = this->GetVariable(name[0]);
|
||||||
TDictionary *dict = nullptr;
|
TDictionary *dict = nullptr;
|
||||||
if (std::holds_alternative<THeapObjectHolder>(v)) {
|
if (std::holds_alternative<THeapObject *>(v)) {
|
||||||
dict =
|
dict = dynamic_cast<TDictionary *>(std::get<THeapObject *>(v));
|
||||||
dynamic_cast<TDictionary *>(std::get<THeapObjectHolder>(v).obj);
|
|
||||||
if (dict == nullptr) {
|
if (dict == nullptr) {
|
||||||
dict = TDictionary::Create(ls);
|
dict = TDictionary::Create(ls);
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
@@ -192,9 +190,9 @@ void TEnvironment::DeclareVariable(std::shared_ptr<GC> gc,
|
|||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
auto v = dict->GetValue(name[i]);
|
auto v = dict->GetValue(name[i]);
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
if (std::holds_alternative<THeapObjectHolder>(v)) {
|
if (std::holds_alternative<THeapObject *>(v)) {
|
||||||
auto dict2 = dynamic_cast<TDictionary *>(
|
auto dict2 =
|
||||||
std::get<THeapObjectHolder>(v).obj);
|
dynamic_cast<TDictionary *>(std::get<THeapObject *>(v));
|
||||||
if (dict2 == nullptr) {
|
if (dict2 == nullptr) {
|
||||||
dict2 = TDictionary::Create(ls);
|
dict2 = TDictionary::Create(ls);
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
@@ -308,13 +306,15 @@ void TRootEnvironment::SetVariable(std::string key, TObject value) {
|
|||||||
this->dict->SetValue(key, value);
|
this->dict->SetValue(key, value);
|
||||||
}
|
}
|
||||||
void TRootEnvironment::DeclareVariable(std::string key, TObject value) {
|
void TRootEnvironment::DeclareVariable(std::string key, TObject value) {
|
||||||
|
if (this->decls.count(key) == 0)
|
||||||
|
this->decls[key] = TEnvironmentDeclType::TEDT_VAR;
|
||||||
return this->dict->SetValue(key, value);
|
return this->dict->SetValue(key, value);
|
||||||
}
|
}
|
||||||
bool TRootEnvironment::HasVariable(std::string key) {
|
bool TRootEnvironment::HasVariable(std::string key) {
|
||||||
return this->dict->HasValue(key);
|
return this->dict->HasValue(key) || this->decls.count(key) > 0;
|
||||||
}
|
}
|
||||||
bool TRootEnvironment::HasVariableRecurse(std::string key) {
|
bool TRootEnvironment::HasVariableRecurse(std::string key) {
|
||||||
return this->dict->HasValue(key);
|
return this->dict->HasValue(key) || this->decls.count(key) > 0;
|
||||||
}
|
}
|
||||||
TEnvironment *TRootEnvironment::GetParentEnvironment() { return this; }
|
TEnvironment *TRootEnvironment::GetParentEnvironment() { return this; }
|
||||||
TRootEnvironment *TRootEnvironment::GetRootEnvironment() { return this; }
|
TRootEnvironment *TRootEnvironment::GetRootEnvironment() { return this; }
|
||||||
@@ -338,18 +338,10 @@ void TRootEnvironment::Mark() {
|
|||||||
cls.first->Mark();
|
cls.first->Mark();
|
||||||
}
|
}
|
||||||
TRootEnvironment *TRootEnvironment::Create(GCList *gc, TDictionary *dict) {
|
TRootEnvironment *TRootEnvironment::Create(GCList *gc, TDictionary *dict) {
|
||||||
TRootEnvironment *env = new TRootEnvironment(dict);
|
return gc->Create<TRootEnvironment>(dict);
|
||||||
std::shared_ptr<GC> _gc = gc->GetGC();
|
|
||||||
gc->Add(env);
|
|
||||||
_gc->Watch(env);
|
|
||||||
return env;
|
|
||||||
}
|
}
|
||||||
TRootEnvironment *TRootEnvironment::Create(GCList &gc, TDictionary *dict) {
|
TRootEnvironment *TRootEnvironment::Create(GCList &gc, TDictionary *dict) {
|
||||||
TRootEnvironment *env = new TRootEnvironment(dict);
|
return gc.Create<TRootEnvironment>(dict);
|
||||||
std::shared_ptr<GC> _gc = gc.GetGC();
|
|
||||||
gc.Add(env);
|
|
||||||
_gc->Watch(env);
|
|
||||||
return env;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TRootEnvironment::HandleException(std::shared_ptr<GC> gc,
|
bool TRootEnvironment::HandleException(std::shared_ptr<GC> gc,
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang {
|
||||||
|
TMemoryStream::TMemoryStream(
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::MemoryStream> strm)
|
||||||
|
: strm(strm) {}
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::Stream> TMemoryStream::GetStream() {
|
||||||
|
return this->strm;
|
||||||
|
}
|
||||||
|
TObject TMemoryStream::CallMethod(InterperterThread *thrd, GCList &ls,
|
||||||
|
const std::string &name,
|
||||||
|
const std::vector<TObject> &args) {
|
||||||
|
if (name == "GetBytes") {
|
||||||
|
return ls.Create<TMemoryStreamMutByteView>(strm);
|
||||||
|
}
|
||||||
|
return ITStream::CallMethod(thrd, ls, name, args);
|
||||||
|
}
|
||||||
|
TMemoryStreamMutByteView::TMemoryStreamMutByteView(
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::MemoryStream> strm)
|
||||||
|
: strm(strm) {}
|
||||||
|
std::pair<uint8_t *, size_t> TMemoryStreamMutByteView::GetMutableBounds() {
|
||||||
|
if (!strm)
|
||||||
|
return std::pair<uint8_t *, size_t>(nullptr, 0);
|
||||||
|
auto &buff = strm->GetBuffer();
|
||||||
|
return std::pair<uint8_t *, size_t>(buff.data(), buff.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TMemoryStream::TypeName() { return "MemoryStream"; }
|
||||||
|
|
||||||
|
} // namespace Tesses::CrossLang
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang {
|
||||||
|
TNetworkStream::TNetworkStream(
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::NetworkStream> strm)
|
||||||
|
: strm(strm) {}
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::Stream>
|
||||||
|
TNetworkStream::GetStream() {
|
||||||
|
return this->strm;
|
||||||
|
}
|
||||||
|
TObject TNetworkStream::CallMethod(InterperterThread *thrd, GCList &ls,
|
||||||
|
const std::string &name,
|
||||||
|
const std::vector<TObject> &args) {
|
||||||
|
int64_t n0;
|
||||||
|
bool bc;
|
||||||
|
if (name == "setBroadcast" && GetArgument(args, 0, bc))
|
||||||
|
strm->SetBroadcast(bc);
|
||||||
|
if (name == "setNoDelay" && GetArgument(args, 0, bc))
|
||||||
|
strm->SetNoDelay(bc);
|
||||||
|
if (name == "setReuseAddress" && GetArgument(args, 0, bc))
|
||||||
|
strm->SetReuseAddress(bc);
|
||||||
|
if (name == "setReusePort" && GetArgument(args, 0, bc))
|
||||||
|
strm->SetReusePort(bc);
|
||||||
|
if (name == "MulticastTTL" && GetArgument(args, 0, n0))
|
||||||
|
strm->SetMulticastTTL((uint8_t)n0);
|
||||||
|
if (name == "getPort" || name == "GetPort") {
|
||||||
|
return (int64_t)strm->GetPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == "SetMulticastMembership") {
|
||||||
|
std::string ma;
|
||||||
|
std::string ifaceIP = "0.0.0.0";
|
||||||
|
if (GetArgument(args, 0, ma)) {
|
||||||
|
GetArgument(args, 1, ifaceIP);
|
||||||
|
strm->SetMulticastMembership(ma, ifaceIP);
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
if (name == "Bind") {
|
||||||
|
std::string ip;
|
||||||
|
int64_t port;
|
||||||
|
if (GetArgument(args, 0, ip) && GetArgument(args, 1, port))
|
||||||
|
strm->Bind(ip, (uint16_t)port);
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name == "Accept") {
|
||||||
|
std::string ip;
|
||||||
|
uint16_t port;
|
||||||
|
auto strm2 = strm->Accept(ip, port);
|
||||||
|
|
||||||
|
if (strm2 ==
|
||||||
|
nullptr) // just in case, so we don't get a bugged TNetworkStream
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
std::array list = {
|
||||||
|
TDItem("IP", ls.FromString(ip)),
|
||||||
|
TDItem("Port", (int64_t)port),
|
||||||
|
TDItem("Stream", ls.Create<TNetworkStream>(strm2)),
|
||||||
|
};
|
||||||
|
|
||||||
|
return ls.Create<TDictionary>(list.begin(), list.end());
|
||||||
|
}
|
||||||
|
if (name == "Listen") {
|
||||||
|
int64_t backlog;
|
||||||
|
if (GetArgument(args, 0, backlog)) {
|
||||||
|
strm->Listen((int32_t)backlog);
|
||||||
|
} else {
|
||||||
|
strm->Listen(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
if (name == "ReadFrom") {
|
||||||
|
TByteArray *data;
|
||||||
|
int64_t offset;
|
||||||
|
int64_t length;
|
||||||
|
|
||||||
|
if (name == "Read") {
|
||||||
|
TMutByteView *bytes;
|
||||||
|
if (GetArgumentHeap(args, 0, bytes)) {
|
||||||
|
int64_t offset;
|
||||||
|
int64_t length;
|
||||||
|
if (GetArgument(args, 1, offset) &&
|
||||||
|
GetArgument(args, 2, length)) {
|
||||||
|
auto safe = bytes->GetMutableBoundsConstrained(
|
||||||
|
(size_t)offset, (size_t)length);
|
||||||
|
if (safe.first != nullptr) {
|
||||||
|
std::string ip = {};
|
||||||
|
uint16_t port = 0;
|
||||||
|
auto read =
|
||||||
|
strm->ReadFrom(safe.first, safe.second, ip, port);
|
||||||
|
std::array list = {
|
||||||
|
TDItem("IP", ls.FromString(ip)),
|
||||||
|
TDItem("Port", (int64_t)port),
|
||||||
|
TDItem("Read", (int64_t)read),
|
||||||
|
};
|
||||||
|
return ls.Create<TDictionary>(list.begin(), list.end());
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bounds = bytes->GetMutableBounds();
|
||||||
|
|
||||||
|
if (bounds.first) {
|
||||||
|
std::string ip = {};
|
||||||
|
uint16_t port = 0;
|
||||||
|
auto read =
|
||||||
|
strm->ReadFrom(bounds.first, bounds.second, ip, port);
|
||||||
|
std::array list = {
|
||||||
|
TDItem("IP", ls.FromString(ip)),
|
||||||
|
TDItem("Port", (int64_t)port),
|
||||||
|
TDItem("Read", (int64_t)read),
|
||||||
|
};
|
||||||
|
return ls.Create<TDictionary>(list.begin(), list.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name == "WriteTo") {
|
||||||
|
|
||||||
|
// strm->WriteTo(buff, ip, port)
|
||||||
|
// strm->WriteTo(buff, off, len, ip, port)
|
||||||
|
|
||||||
|
TByteView *bytes;
|
||||||
|
if (GetArgumentHeap(args, 0, bytes)) {
|
||||||
|
int64_t offset;
|
||||||
|
int64_t length;
|
||||||
|
TString *ip;
|
||||||
|
int64_t port;
|
||||||
|
if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) {
|
||||||
|
if (!(GetArgumentHeap(args, 3, ip) &&
|
||||||
|
GetArgument(args, 4, port)))
|
||||||
|
return Undefined();
|
||||||
|
auto safe =
|
||||||
|
bytes->GetBoundsConstrained((size_t)offset, (size_t)length);
|
||||||
|
if (safe.first != nullptr) {
|
||||||
|
return strm->WriteTo(safe.first, safe.second,
|
||||||
|
ip->GetString(), (uint16_t)port);
|
||||||
|
} else
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (!(GetArgumentHeap(args, 1, ip) && GetArgument(args, 2, port)))
|
||||||
|
return Undefined();
|
||||||
|
auto bounds = bytes->GetBounds();
|
||||||
|
|
||||||
|
if (bounds.first) {
|
||||||
|
|
||||||
|
return (int64_t)strm->WriteTo(bounds.first, bounds.second,
|
||||||
|
ip->GetString(), (uint16_t)port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ITStream::CallMethod(thrd, ls, name, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TNetworkStream::TypeName() { return "NetworkStream"; }
|
||||||
|
} // namespace Tesses::CrossLang
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang {
|
||||||
|
|
||||||
|
#define CROSSLANG_TSTREAM_NAMES \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(getCanRead) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(getCanSeek) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(getCanWrite) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(getEndOfStream) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(getLength) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(getPosition) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(setPosition) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(Close) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(Dispose) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(CopyTo) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(CopyToLimit) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(Flush) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(Read) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(ReadBlock) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(ReadByte) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(Seek) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(SetRecvTimeout) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(SetSendTimeout) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(Write) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(WriteText) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(WriteBlock) \
|
||||||
|
CROSSLANG_TSTREAM_NAME_ENT(WriteByte)
|
||||||
|
|
||||||
|
enum TStreamFuncNameEnum {
|
||||||
|
#define CROSSLANG_TSTREAM_NAME_ENT(name) TSF_##name,
|
||||||
|
CROSSLANG_TSTREAM_NAMES
|
||||||
|
#undef CROSSLANG_TSTREAM_NAME_ENT
|
||||||
|
}; // namespace Tesses::CrossLang
|
||||||
|
|
||||||
|
static std::unordered_map<std::string_view, TStreamFuncNameEnum>
|
||||||
|
stream_func_names = {
|
||||||
|
#define CROSSLANG_TSTREAM_NAME_ENT(name) {#name, TSF_##name},
|
||||||
|
CROSSLANG_TSTREAM_NAMES
|
||||||
|
#undef CROSSLANG_TSTREAM_NAME_ENT
|
||||||
|
};
|
||||||
|
|
||||||
|
bool ITStream::Exists(std::string_view str) {
|
||||||
|
return stream_func_names.count(str) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
TObject ITStream::CallMethod(InterperterThread *thrd, GCList &ls,
|
||||||
|
const std::string &name,
|
||||||
|
const std::vector<TObject> &args) {
|
||||||
|
|
||||||
|
auto strm = GetStream();
|
||||||
|
if (strm == nullptr)
|
||||||
|
return Undefined();
|
||||||
|
|
||||||
|
auto result = stream_func_names.find(name);
|
||||||
|
|
||||||
|
if (result == stream_func_names.end())
|
||||||
|
return Undefined();
|
||||||
|
|
||||||
|
switch (result->second) {
|
||||||
|
case TSF_getCanRead:
|
||||||
|
return strm->CanRead();
|
||||||
|
case TSF_getCanSeek:
|
||||||
|
return strm->CanSeek();
|
||||||
|
case TSF_getCanWrite:
|
||||||
|
return strm->CanWrite();
|
||||||
|
case TSF_getEndOfStream:
|
||||||
|
return strm->EndOfStream();
|
||||||
|
case TSF_getLength:
|
||||||
|
return strm->GetLength();
|
||||||
|
case TSF_getPosition:
|
||||||
|
return strm->GetPosition();
|
||||||
|
case TSF_setPosition: {
|
||||||
|
int64_t n;
|
||||||
|
if (GetArgument(args, 0, n)) {
|
||||||
|
strm->Seek(n, Tesses::Framework::Streams::SeekOrigin::Begin);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
case TSF_Close:
|
||||||
|
case TSF_Dispose:
|
||||||
|
strm->Close();
|
||||||
|
return Undefined();
|
||||||
|
case TSF_CopyTo: {
|
||||||
|
ITStream *strmDest;
|
||||||
|
if (GetArgumentHeap(args, 0, strmDest)) {
|
||||||
|
int64_t n = 1024;
|
||||||
|
GetArgument(args, 1, n);
|
||||||
|
strm->CopyTo(strmDest->GetStream(), (size_t)n);
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
case TSF_CopyToLimit: {
|
||||||
|
ITStream *strmDest;
|
||||||
|
int64_t len;
|
||||||
|
if (GetArgumentHeap(args, 0, strmDest) && GetArgument(args, 1, len)) {
|
||||||
|
int64_t n = 1024;
|
||||||
|
GetArgument(args, 2, n);
|
||||||
|
strm->CopyToLimit(strmDest->GetStream(), (uint64_t)len, (size_t)n);
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
case TSF_Flush:
|
||||||
|
strm->Flush();
|
||||||
|
return Undefined();
|
||||||
|
case TSF_Read: {
|
||||||
|
TMutByteView *bytes;
|
||||||
|
if (GetArgumentHeap(args, 0, bytes)) {
|
||||||
|
int64_t offset;
|
||||||
|
int64_t length;
|
||||||
|
if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) {
|
||||||
|
auto safe = bytes->GetMutableBoundsConstrained((size_t)offset,
|
||||||
|
(size_t)length);
|
||||||
|
if (safe.first != nullptr)
|
||||||
|
return strm->Read(safe.first, safe.second);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bounds = bytes->GetMutableBounds();
|
||||||
|
|
||||||
|
if (bounds.first) {
|
||||||
|
return (int64_t)strm->Read(bounds.first, bounds.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
case TSF_ReadBlock: {
|
||||||
|
TMutByteView *bytes;
|
||||||
|
if (GetArgumentHeap(args, 0, bytes)) {
|
||||||
|
int64_t offset;
|
||||||
|
int64_t length;
|
||||||
|
if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) {
|
||||||
|
auto safe = bytes->GetMutableBoundsConstrained((size_t)offset,
|
||||||
|
(size_t)length);
|
||||||
|
if (safe.first != nullptr)
|
||||||
|
return strm->ReadBlock(safe.first, safe.second);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bounds = bytes->GetMutableBounds();
|
||||||
|
|
||||||
|
if (bounds.first) {
|
||||||
|
return (int64_t)strm->ReadBlock(bounds.first, bounds.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
case TSF_ReadByte: {
|
||||||
|
return (int64_t)strm->ReadByte();
|
||||||
|
}
|
||||||
|
case TSF_Seek: {
|
||||||
|
int64_t offset;
|
||||||
|
int64_t whence;
|
||||||
|
if (GetArgument(args, 0, offset) && GetArgument(args, 1, whence)) {
|
||||||
|
strm->Seek(offset, (Tesses::Framework::Streams::SeekOrigin)whence);
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
case TSF_SetRecvTimeout: {
|
||||||
|
int64_t to;
|
||||||
|
if (GetArgument(args, 0, to)) {
|
||||||
|
strm->SetRecvTimeout((uint64_t)to);
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
case TSF_SetSendTimeout: {
|
||||||
|
int64_t to;
|
||||||
|
if (GetArgument(args, 0, to)) {
|
||||||
|
strm->SetSendTimeout((uint64_t)to);
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
case TSF_Write: {
|
||||||
|
TByteView *bytes;
|
||||||
|
if (GetArgumentHeap(args, 0, bytes)) {
|
||||||
|
int64_t offset;
|
||||||
|
int64_t length;
|
||||||
|
if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) {
|
||||||
|
auto safe =
|
||||||
|
bytes->GetBoundsConstrained((size_t)offset, (size_t)length);
|
||||||
|
if (safe.first != nullptr)
|
||||||
|
return strm->Write(safe.first, safe.second);
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bounds = bytes->GetBounds();
|
||||||
|
|
||||||
|
if (bounds.first) {
|
||||||
|
return (int64_t)strm->Write(bounds.first, bounds.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
case TSF_WriteText: { // for compat
|
||||||
|
TByteView *bytes;
|
||||||
|
if (GetArgumentHeap(args, 0, bytes)) {
|
||||||
|
auto bounds = bytes->GetBounds();
|
||||||
|
if (bounds.first)
|
||||||
|
strm->WriteBlock(bounds.first, bounds.second);
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
case TSF_WriteBlock: {
|
||||||
|
TByteView *bytes;
|
||||||
|
if (GetArgumentHeap(args, 0, bytes)) {
|
||||||
|
int64_t offset;
|
||||||
|
int64_t length;
|
||||||
|
if (GetArgument(args, 1, offset) && GetArgument(args, 2, length)) {
|
||||||
|
auto safe =
|
||||||
|
bytes->GetBoundsConstrained((size_t)offset, (size_t)length);
|
||||||
|
if (safe.first != nullptr)
|
||||||
|
strm->WriteBlock(safe.first, safe.second);
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto bounds = bytes->GetBounds();
|
||||||
|
|
||||||
|
if (bounds.first) {
|
||||||
|
strm->WriteBlock(bounds.first, bounds.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
case TSF_WriteByte: {
|
||||||
|
int64_t b0;
|
||||||
|
if (GetArgument(args, 0, b0)) {
|
||||||
|
strm->WriteByte((uint8_t)b0);
|
||||||
|
}
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
std::string ITStream::TypeName() { return "Stream"; }
|
||||||
|
|
||||||
|
TStream::TStream(std::shared_ptr<Tesses::Framework::Streams::Stream> strm)
|
||||||
|
: strm(strm) {}
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::Stream> TStream::GetStream() {
|
||||||
|
return this->strm;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Tesses::CrossLang
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#include "CrossLang.hpp"
|
||||||
|
|
||||||
|
namespace Tesses::CrossLang {
|
||||||
|
TObjectStreamWrapper::TObjectStreamWrapper(std::shared_ptr<TObjectStream> strm)
|
||||||
|
: strm(strm) {}
|
||||||
|
TObject TObjectStreamWrapper::CallMethod(InterperterThread *thrd, GCList &ls,
|
||||||
|
const std::string &name,
|
||||||
|
const std::vector<TObject> &args) {
|
||||||
|
if (Exists(name)) {
|
||||||
|
return ITStream::CallMethod(thrd, ls, name, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
TDictionary *dict;
|
||||||
|
|
||||||
|
if (GetObjectHeap(strm->obj, dict)) {
|
||||||
|
auto val = dict->GetValue(name);
|
||||||
|
|
||||||
|
TCallable *call;
|
||||||
|
if (GetObjectHeap(val, call)) {
|
||||||
|
|
||||||
|
auto closure = dynamic_cast<TClosure *>(call);
|
||||||
|
|
||||||
|
if (closure && !closure->closure->args.empty() &&
|
||||||
|
closure->closure->args[0]->GetString() == "this") {
|
||||||
|
std::vector<TObject> args_new;
|
||||||
|
args_new.reserve(args.size() + 1);
|
||||||
|
args_new.push_back(dict);
|
||||||
|
args_new.insert(args_new.cend(), args.begin(), args.end());
|
||||||
|
|
||||||
|
return closure->Call(ls, args_new);
|
||||||
|
} else {
|
||||||
|
return call->Call(ls, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (name.size() > 3 && name[1] == 'e' && name[2] == 't') {
|
||||||
|
char c = name[0];
|
||||||
|
if (c == 'g') {
|
||||||
|
auto fieldName = name.substr(3);
|
||||||
|
return dict->GetValue(fieldName);
|
||||||
|
} else if (c == 's' && !args.empty()) {
|
||||||
|
auto fieldName = name.substr(3);
|
||||||
|
dict->SetValue(fieldName, args[0]);
|
||||||
|
ls.Add(args[0]);
|
||||||
|
return args[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
std::shared_ptr<Tesses::Framework::Streams::Stream>
|
||||||
|
TObjectStreamWrapper::GetStream() {
|
||||||
|
return this->strm;
|
||||||
|
}
|
||||||
|
std::string TObjectStreamWrapper::TypeName() { return "CustomStream"; }
|
||||||
|
} // namespace Tesses::CrossLang
|
||||||
@@ -82,16 +82,24 @@ TObject TSubEnvironment::GetVariable(std::string key) {
|
|||||||
if (this->dict->HasValue(key)) {
|
if (this->dict->HasValue(key)) {
|
||||||
return this->dict->GetValue(key);
|
return this->dict->GetValue(key);
|
||||||
}
|
}
|
||||||
|
if (this->decls.count(key) > 0 &&
|
||||||
|
this->decls[key] == TEnvironmentDeclType::TEDT_VAR) {
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
if (this->env->HasVariableRecurse(key)) {
|
if (this->env->HasVariableRecurse(key)) {
|
||||||
return this->env->GetVariable(key);
|
return this->env->GetVariable(key);
|
||||||
}
|
}
|
||||||
return Undefined();
|
return Undefined();
|
||||||
}
|
}
|
||||||
void TSubEnvironment::DeclareVariable(std::string key, TObject value) {
|
void TSubEnvironment::DeclareVariable(std::string key, TObject value) {
|
||||||
|
if (this->decls.count(key) == 0)
|
||||||
|
this->decls[key] = TEnvironmentDeclType::TEDT_VAR;
|
||||||
|
|
||||||
this->dict->SetValue(key, value);
|
this->dict->SetValue(key, value);
|
||||||
}
|
}
|
||||||
void TSubEnvironment::SetVariable(std::string key, TObject value) {
|
void TSubEnvironment::SetVariable(std::string key, TObject value) {
|
||||||
if (this->dict->HasValue(key)) {
|
|
||||||
|
if (this->dict->HasValue(key) || this->decls.count(key) > 0) {
|
||||||
this->dict->SetValue(key, value);
|
this->dict->SetValue(key, value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -102,10 +110,10 @@ void TSubEnvironment::SetVariable(std::string key, TObject value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool TSubEnvironment::HasVariable(std::string key) {
|
bool TSubEnvironment::HasVariable(std::string key) {
|
||||||
return this->dict->HasValue(key);
|
return this->dict->HasValue(key) || this->decls.count(key) > 0;
|
||||||
}
|
}
|
||||||
bool TSubEnvironment::HasVariableRecurse(std::string key) {
|
bool TSubEnvironment::HasVariableRecurse(std::string key) {
|
||||||
if (this->dict->HasValue(key))
|
if (this->dict->HasValue(key) || this->decls.count(key) > 0)
|
||||||
return true;
|
return true;
|
||||||
return this->env->HasVariableRecurse(key);
|
return this->env->HasVariableRecurse(key);
|
||||||
}
|
}
|
||||||
@@ -159,19 +167,11 @@ TSubEnvironment *TEnvironment::GetSubEnvironment(GCList &gc) {
|
|||||||
}
|
}
|
||||||
TSubEnvironment *TSubEnvironment::Create(GCList *gc, TEnvironment *env,
|
TSubEnvironment *TSubEnvironment::Create(GCList *gc, TEnvironment *env,
|
||||||
TDictionary *dict) {
|
TDictionary *dict) {
|
||||||
TSubEnvironment *senv = new TSubEnvironment(env, dict);
|
return gc->Create<TSubEnvironment>(env, dict);
|
||||||
std::shared_ptr<GC> _gc = gc->GetGC();
|
|
||||||
gc->Add(senv);
|
|
||||||
_gc->Watch(senv);
|
|
||||||
return senv;
|
|
||||||
}
|
}
|
||||||
TSubEnvironment *TSubEnvironment::Create(GCList &gc, TEnvironment *env,
|
TSubEnvironment *TSubEnvironment::Create(GCList &gc, TEnvironment *env,
|
||||||
TDictionary *dict) {
|
TDictionary *dict) {
|
||||||
TSubEnvironment *senv = new TSubEnvironment(env, dict);
|
return gc.Create<TSubEnvironment>(env, dict);
|
||||||
std::shared_ptr<GC> _gc = gc.GetGC();
|
|
||||||
gc.Add(senv);
|
|
||||||
_gc->Watch(senv);
|
|
||||||
return senv;
|
|
||||||
}
|
}
|
||||||
TEnvironment *TSubEnvironment::GetParentEnvironment() { return this->env; }
|
TEnvironment *TSubEnvironment::GetParentEnvironment() { return this->env; }
|
||||||
TRootEnvironment *TSubEnvironment::GetRootEnvironment() {
|
TRootEnvironment *TSubEnvironment::GetRootEnvironment() {
|
||||||
|
|||||||
+12
-2
@@ -119,8 +119,17 @@ bool InterperterThread::Add(std::shared_ptr<GC> gc) {
|
|||||||
str.append(std::get<std::string>(left));
|
str.append(std::get<std::string>(left));
|
||||||
str.push_back(std::get<char>(right));
|
str.push_back(std::get<char>(right));
|
||||||
cse.back()->Push(gc, str);
|
cse.back()->Push(gc, str);
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
|
|
||||||
|
if (obj == nullptr) {
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj->opAdd(this, gc, right);
|
||||||
|
|
||||||
|
/*
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
auto natObj = dynamic_cast<TNativeObject *>(obj);
|
auto natObj = dynamic_cast<TNativeObject *>(obj);
|
||||||
@@ -156,6 +165,7 @@ bool InterperterThread::Add(std::shared_ptr<GC> gc) {
|
|||||||
} else {
|
} else {
|
||||||
cse.back()->Push(gc, Undefined());
|
cse.back()->Push(gc, Undefined());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cse.back()->Push(gc, Undefined());
|
cse.back()->Push(gc, Undefined());
|
||||||
|
|||||||
+18
-21
@@ -14,8 +14,7 @@ namespace Tesses::CrossLang {
|
|||||||
|
|
||||||
bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
|
bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
if (std::holds_alternative<std::nullptr_t>(left) &&
|
if (IsNull(left) && IsNull(right)) {
|
||||||
std::holds_alternative<std::nullptr_t>(right)) {
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -92,8 +91,8 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
|
|||||||
auto r = std::get<Tesses::Framework::Uuid>(right);
|
auto r = std::get<Tesses::Framework::Uuid>(right);
|
||||||
|
|
||||||
return l == r;
|
return l == r;
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -109,12 +108,12 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
|
|||||||
if (GetObjectHeap(obj, callable)) {
|
if (GetObjectHeap(obj, callable)) {
|
||||||
return ToBool(callable->Call(ls, {right}));
|
return ToBool(callable->Call(ls, {right}));
|
||||||
|
|
||||||
} else if (std::holds_alternative<std::nullptr_t>(right)) {
|
} else if (IsNull(right)) {
|
||||||
return false;
|
return false;
|
||||||
} else if (std::holds_alternative<Undefined>(right)) {
|
} else if (std::holds_alternative<Undefined>(right)) {
|
||||||
return false;
|
return false;
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(right)) {
|
} else if (std::holds_alternative<THeapObject *>(right)) {
|
||||||
return cls == std::get<THeapObjectHolder>(right).obj;
|
return cls == std::get<THeapObject *>(right);
|
||||||
}
|
}
|
||||||
} else if (natObj != nullptr) {
|
} else if (natObj != nullptr) {
|
||||||
return natObj->Equals(gc, right);
|
return natObj->Equals(gc, right);
|
||||||
@@ -124,10 +123,10 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
|
|||||||
TObject fn = dict->GetValue("operator==");
|
TObject fn = dict->GetValue("operator==");
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
if (!std::holds_alternative<Undefined>(fn)) {
|
if (!std::holds_alternative<Undefined>(fn)) {
|
||||||
if (std::holds_alternative<THeapObjectHolder>(fn)) {
|
if (std::holds_alternative<THeapObject *>(fn)) {
|
||||||
|
|
||||||
auto obj = dynamic_cast<TCallable *>(
|
auto obj =
|
||||||
std::get<THeapObjectHolder>(fn).obj);
|
dynamic_cast<TCallable *>(std::get<THeapObject *>(fn));
|
||||||
if (obj != nullptr) {
|
if (obj != nullptr) {
|
||||||
auto closure = dynamic_cast<TClosure *>(obj);
|
auto closure = dynamic_cast<TClosure *>(obj);
|
||||||
if (closure != nullptr) {
|
if (closure != nullptr) {
|
||||||
@@ -144,17 +143,17 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
return dict == std::get<THeapObject *>(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
return dict == std::get<THeapObject *>(right);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
return dict == std::get<THeapObjectHolder>(right).obj;
|
return dict == std::get<THeapObject *>(right);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -162,21 +161,19 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
|
|||||||
|
|
||||||
else if (dynDict != nullptr) {
|
else if (dynDict != nullptr) {
|
||||||
auto res = dynDict->CallMethod(ls, "operator==", {right});
|
auto res = dynDict->CallMethod(ls, "operator==", {right});
|
||||||
if (!std::holds_alternative<std::nullptr_t>(res) &&
|
if (!IsNull(res) && std::holds_alternative<Undefined>(res)) {
|
||||||
std::holds_alternative<Undefined>(res)) {
|
|
||||||
return ToBool(res);
|
return ToBool(res);
|
||||||
}
|
}
|
||||||
} else if (native != nullptr &&
|
} else if (native != nullptr && IsNull(right)) {
|
||||||
std::holds_alternative<std::nullptr_t>(right)) {
|
|
||||||
return native->GetDestroyed();
|
return native->GetDestroyed();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::holds_alternative<THeapObjectHolder>(right)) {
|
if (std::holds_alternative<THeapObject *>(right)) {
|
||||||
return obj == std::get<THeapObjectHolder>(right).obj;
|
return obj == std::get<THeapObject *>(right);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (std::holds_alternative<std::nullptr_t>(right)) {
|
else if (IsNull(right)) {
|
||||||
return false;
|
return false;
|
||||||
} else if (std::holds_alternative<Undefined>(right)) {
|
} else if (std::holds_alternative<Undefined>(right)) {
|
||||||
|
|
||||||
@@ -187,7 +184,7 @@ bool Equals(std::shared_ptr<GC> gc, TObject left, TObject right) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (std::holds_alternative<std::nullptr_t>(right)) {
|
else if (IsNull(right)) {
|
||||||
return false;
|
return false;
|
||||||
} else if (std::holds_alternative<Undefined>(right)) {
|
} else if (std::holds_alternative<Undefined>(right)) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+13
-325
@@ -24,7 +24,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
|||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
std::regex regex;
|
std::regex regex;
|
||||||
TVMVersion version;
|
TVMVersion version;
|
||||||
if (std::holds_alternative<std::nullptr_t>(instance)) {
|
if (IsNull(instance)) {
|
||||||
if (key == "ToString") {
|
if (key == "ToString") {
|
||||||
cse.back()->Push(gc, "null");
|
cse.back()->Push(gc, "null");
|
||||||
return false;
|
return false;
|
||||||
@@ -58,7 +58,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
|||||||
if (GetArgument(args, 0, str)) {
|
if (GetArgument(args, 0, str)) {
|
||||||
std::smatch m;
|
std::smatch m;
|
||||||
if (std::regex_search(str, m, regex)) {
|
if (std::regex_search(str, m, regex)) {
|
||||||
auto myLs = TList::Create(ls);
|
auto myLs = ls.Create<TList>();
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
for (auto item : m) {
|
for (auto item : m) {
|
||||||
auto itm = TDictionary::Create(ls);
|
auto itm = TDictionary::Create(ls);
|
||||||
@@ -288,7 +288,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
|||||||
std::get<Tesses::Framework::Filesystem::VFSPath>(instance);
|
std::get<Tesses::Framework::Filesystem::VFSPath>(instance);
|
||||||
if (key == "GetEnumerator") {
|
if (key == "GetEnumerator") {
|
||||||
|
|
||||||
TList *_ls = TList::Create(ls);
|
TList *_ls = ls.Create<TList>();
|
||||||
for (auto item : path.path) {
|
for (auto item : path.path) {
|
||||||
_ls->Add(item);
|
_ls->Add(item);
|
||||||
}
|
}
|
||||||
@@ -683,7 +683,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
|||||||
|
|
||||||
auto res = Tesses::Framework::Http::HttpUtils::SplitString(
|
auto res = Tesses::Framework::Http::HttpUtils::SplitString(
|
||||||
str, delimiter, count);
|
str, delimiter, count);
|
||||||
TList *mls = TList::Create(ls);
|
TList *mls = ls.Create<TList>();
|
||||||
for (auto item : res) {
|
for (auto item : res) {
|
||||||
if (!removeEmpty || !item.empty())
|
if (!removeEmpty || !item.empty())
|
||||||
mls->Add(item);
|
mls->Add(item);
|
||||||
@@ -825,7 +825,7 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
|||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
textReader->ReadAllLines(lines);
|
textReader->ReadAllLines(lines);
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
TList *list = TList::Create(ls);
|
TList *list = ls.Create<TList>();
|
||||||
for (auto &item : lines)
|
for (auto &item : lines)
|
||||||
list->Add(item);
|
list->Add(item);
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
@@ -1072,8 +1072,6 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
|||||||
std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(
|
std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(
|
||||||
instance);
|
instance);
|
||||||
if (strm != nullptr) {
|
if (strm != nullptr) {
|
||||||
auto memStrm = std::dynamic_pointer_cast<
|
|
||||||
Tesses::Framework::Streams::MemoryStream>(strm);
|
|
||||||
auto netStrm = std::dynamic_pointer_cast<
|
auto netStrm = std::dynamic_pointer_cast<
|
||||||
Tesses::Framework::Streams::NetworkStream>(strm);
|
Tesses::Framework::Streams::NetworkStream>(strm);
|
||||||
|
|
||||||
@@ -1090,134 +1088,8 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
|||||||
return InvokeMethod(ls, o, dict2, args);
|
return InvokeMethod(ls, o, dict2, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (memStrm != nullptr) {
|
|
||||||
if (key == "GetBytes") {
|
|
||||||
auto res = TByteArray::Create(ls);
|
|
||||||
res->data = memStrm->GetBuffer();
|
|
||||||
cse.back()->Push(gc, res);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (netStrm != nullptr) {
|
if (netStrm != nullptr) {
|
||||||
if (key == "SetMulticastMembership") {
|
|
||||||
std::string ma;
|
|
||||||
std::string ifaceIP = "0.0.0.0";
|
|
||||||
if (GetArgument(args, 0, ma)) {
|
|
||||||
GetArgument(args, 1, ifaceIP);
|
|
||||||
netStrm->SetMulticastMembership(ma, ifaceIP);
|
|
||||||
}
|
|
||||||
cse.back()->Push(gc, Undefined());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (key == "GetPort") {
|
|
||||||
cse.back()->Push(gc, (int64_t)netStrm->GetPort());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (key == "Bind") {
|
|
||||||
std::string ip;
|
|
||||||
int64_t port;
|
|
||||||
if (GetArgument(args, 0, ip) &&
|
|
||||||
GetArgument(args, 1, port))
|
|
||||||
netStrm->Bind(ip, (uint16_t)port);
|
|
||||||
|
|
||||||
cse.back()->Push(gc, nullptr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (key == "Accept") {
|
|
||||||
std::string ip;
|
|
||||||
uint16_t port;
|
|
||||||
auto strm = netStrm->Accept(ip, port);
|
|
||||||
TDictionary *dict = TDictionary::Create(ls);
|
|
||||||
gc->BarrierBegin();
|
|
||||||
dict->SetValue("IP", ip);
|
|
||||||
dict->SetValue("Port", (int64_t)port);
|
|
||||||
dict->SetValue("Stream", strm);
|
|
||||||
|
|
||||||
gc->BarrierEnd();
|
|
||||||
cse.back()->Push(gc, dict);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (key == "Listen") {
|
|
||||||
int64_t backlog;
|
|
||||||
if (GetArgument(args, 0, backlog)) {
|
|
||||||
netStrm->Listen((int32_t)backlog);
|
|
||||||
} else {
|
|
||||||
netStrm->Listen(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
cse.back()->Push(gc, nullptr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (key == "ReadFrom") {
|
|
||||||
TByteArray *data;
|
|
||||||
int64_t offset;
|
|
||||||
int64_t length;
|
|
||||||
if (GetArgumentHeap<TByteArray *>(args, 0, data) &&
|
|
||||||
GetArgument<int64_t>(args, 1, offset) &&
|
|
||||||
GetArgument<int64_t>(args, 2, length)) {
|
|
||||||
size_t off = (size_t)offset;
|
|
||||||
size_t len = (size_t)length;
|
|
||||||
std::string ip = {};
|
|
||||||
uint16_t port = 0;
|
|
||||||
|
|
||||||
if (off < len)
|
|
||||||
|
|
||||||
len = netStrm->ReadFrom(
|
|
||||||
data->data.data() + off,
|
|
||||||
std::min(len,
|
|
||||||
std::min(data->data.size() - off,
|
|
||||||
data->data.size())),
|
|
||||||
ip, port);
|
|
||||||
|
|
||||||
else
|
|
||||||
len = 0;
|
|
||||||
|
|
||||||
TDictionary *dict = TDictionary::Create(ls);
|
|
||||||
gc->BarrierBegin();
|
|
||||||
dict->SetValue("IP", ip);
|
|
||||||
dict->SetValue("Port", (int64_t)port);
|
|
||||||
dict->SetValue("Read", (int64_t)len);
|
|
||||||
|
|
||||||
gc->BarrierEnd();
|
|
||||||
cse.back()->Push(gc, dict);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cse.back()->Push(gc, nullptr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (key == "WriteTo") {
|
|
||||||
TByteArray *data;
|
|
||||||
int64_t offset;
|
|
||||||
int64_t length;
|
|
||||||
std::string ip;
|
|
||||||
int64_t port;
|
|
||||||
if (GetArgumentHeap<TByteArray *>(args, 0, data) &&
|
|
||||||
GetArgument<int64_t>(args, 1, offset) &&
|
|
||||||
GetArgument<int64_t>(args, 2, length) &&
|
|
||||||
GetArgument(args, 3, ip) &&
|
|
||||||
GetArgument(args, 4, port)) {
|
|
||||||
size_t off = (size_t)offset;
|
|
||||||
size_t len = (size_t)length;
|
|
||||||
|
|
||||||
if (off < len)
|
|
||||||
|
|
||||||
len = netStrm->WriteTo(
|
|
||||||
data->data.data() + off,
|
|
||||||
std::min(len,
|
|
||||||
std::min(data->data.size() - off,
|
|
||||||
data->data.size())),
|
|
||||||
ip, (int64_t)port);
|
|
||||||
|
|
||||||
else
|
|
||||||
len = 0;
|
|
||||||
|
|
||||||
cse.back()->Push(gc, (int64_t)len);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cse.back()->Push(gc, nullptr);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == "Read") {
|
if (key == "Read") {
|
||||||
@@ -1490,12 +1362,12 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
|||||||
pattern,
|
pattern,
|
||||||
callable->ToRouteServerRequestHandler(gc));
|
callable->ToRouteServerRequestHandler(gc));
|
||||||
}
|
}
|
||||||
} else if (key == "Trace") {
|
} else if (key == "Query") {
|
||||||
std::string pattern;
|
std::string pattern;
|
||||||
TCallable *callable;
|
TCallable *callable;
|
||||||
if (GetArgument(args, 0, pattern) &&
|
if (GetArgument(args, 0, pattern) &&
|
||||||
GetArgumentHeap(args, 1, callable)) {
|
GetArgumentHeap(args, 1, callable)) {
|
||||||
routable->Trace(
|
routable->Query(
|
||||||
pattern,
|
pattern,
|
||||||
callable->ToRouteServerRequestHandler(gc));
|
callable->ToRouteServerRequestHandler(gc));
|
||||||
}
|
}
|
||||||
@@ -1964,9 +1836,9 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
|||||||
}
|
}
|
||||||
cse.back()->Push(gc, Undefined());
|
cse.back()->Push(gc, Undefined());
|
||||||
return false;
|
return false;
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(instance)) {
|
} else if (std::holds_alternative<THeapObject *>(instance)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(instance).obj;
|
auto obj = std::get<THeapObject *>(instance);
|
||||||
auto list = dynamic_cast<TList *>(obj);
|
|
||||||
auto dynList = dynamic_cast<TDynamicList *>(obj);
|
auto dynList = dynamic_cast<TDynamicList *>(obj);
|
||||||
auto bArray = dynamic_cast<TByteArray *>(obj);
|
auto bArray = dynamic_cast<TByteArray *>(obj);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
@@ -2292,9 +2164,9 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
|||||||
}
|
}
|
||||||
if (key == "RegisterClass") {
|
if (key == "RegisterClass") {
|
||||||
if ((myEnv->permissions.canRegisterEverything ||
|
if ((myEnv->permissions.canRegisterEverything ||
|
||||||
myEnv->permissions.canRegisterClass) &&
|
myEnv->permissions.canRegisterZeClass) &&
|
||||||
!rootEnv->permissions.locked)
|
!rootEnv->permissions.locked)
|
||||||
TStd::RegisterClass(gc, rootEnv);
|
TStd::RegisterZeClass(gc, rootEnv);
|
||||||
cse.back()->Push(gc, nullptr);
|
cse.back()->Push(gc, nullptr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -3336,190 +3208,6 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
|||||||
}
|
}
|
||||||
cse.back()->Push(gc, Undefined());
|
cse.back()->Push(gc, Undefined());
|
||||||
return false;
|
return false;
|
||||||
} else if (list != nullptr) {
|
|
||||||
|
|
||||||
if (key == "GetEnumerator") {
|
|
||||||
cse.back()->Push(gc, TListEnumerator::Create(ls, list));
|
|
||||||
return false;
|
|
||||||
} else if (key == "ToString") {
|
|
||||||
|
|
||||||
cse.back()->Push(gc, Json_Encode(list));
|
|
||||||
return false;
|
|
||||||
|
|
||||||
} else if (key == "Insert") {
|
|
||||||
if (args.size() != 2) {
|
|
||||||
throw VMException(
|
|
||||||
"List.Insert must only accept two arguments");
|
|
||||||
}
|
|
||||||
int64_t index;
|
|
||||||
|
|
||||||
if (!GetArgument(args, 0, index)) {
|
|
||||||
throw VMException(
|
|
||||||
"List.Insert first argument must be Long");
|
|
||||||
}
|
|
||||||
|
|
||||||
gc->BarrierBegin();
|
|
||||||
list->Insert(index, args[1]);
|
|
||||||
gc->BarrierEnd();
|
|
||||||
cse.back()->Push(gc, Undefined());
|
|
||||||
return false;
|
|
||||||
} else if (key == "Add") {
|
|
||||||
if (args.size() != 1) {
|
|
||||||
throw VMException(
|
|
||||||
"List.Add must only accept one argument");
|
|
||||||
}
|
|
||||||
gc->BarrierBegin();
|
|
||||||
list->Add(args[0]);
|
|
||||||
gc->BarrierEnd();
|
|
||||||
cse.back()->Push(gc, Undefined());
|
|
||||||
return false;
|
|
||||||
} else if (key == "Contains") {
|
|
||||||
if (args.size() != 1) {
|
|
||||||
throw VMException(
|
|
||||||
"List.Contains must only accept one argument");
|
|
||||||
}
|
|
||||||
gc->BarrierBegin();
|
|
||||||
for (int64_t i = 0; i < list->Count(); i++) {
|
|
||||||
auto item = list->Get(i);
|
|
||||||
gc->BarrierEnd();
|
|
||||||
if (Equals(gc, args[0], item)) {
|
|
||||||
cse.back()->Push(gc, true);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
gc->BarrierBegin();
|
|
||||||
}
|
|
||||||
gc->BarrierEnd();
|
|
||||||
cse.back()->Push(gc, false);
|
|
||||||
return false;
|
|
||||||
} else if (key == "IndexOf") {
|
|
||||||
// IndexOf(obj, $idx)
|
|
||||||
if (args.size() < 1 || args.size() > 2) {
|
|
||||||
throw VMException("List.IndexOf must either have one "
|
|
||||||
"or two arguments");
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t i = 0;
|
|
||||||
|
|
||||||
GetArgument(args, 1, i);
|
|
||||||
gc->BarrierBegin();
|
|
||||||
for (; i < list->Count(); i++) {
|
|
||||||
auto item = list->Get(i);
|
|
||||||
gc->BarrierEnd();
|
|
||||||
if (Equals(gc, args[0], item)) {
|
|
||||||
|
|
||||||
cse.back()->Push(gc, i);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
gc->BarrierBegin();
|
|
||||||
}
|
|
||||||
gc->BarrierEnd();
|
|
||||||
cse.back()->Push(gc, (int64_t)-1);
|
|
||||||
return false;
|
|
||||||
} else 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++) {
|
|
||||||
auto item = list->Get(i);
|
|
||||||
gc->BarrierEnd();
|
|
||||||
if (Equals(gc, args[0], item)) {
|
|
||||||
gc->BarrierBegin();
|
|
||||||
list->RemoveAt(i);
|
|
||||||
i--;
|
|
||||||
} else
|
|
||||||
gc->BarrierBegin();
|
|
||||||
}
|
|
||||||
gc->BarrierEnd();
|
|
||||||
cse.back()->Push(gc, Undefined());
|
|
||||||
return false;
|
|
||||||
} else 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++) {
|
|
||||||
auto item = list->Get(i);
|
|
||||||
gc->BarrierEnd();
|
|
||||||
if (Equals(gc, args[0], item)) {
|
|
||||||
gc->BarrierBegin();
|
|
||||||
list->RemoveAt(i);
|
|
||||||
gc->BarrierEnd();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
gc->BarrierBegin();
|
|
||||||
}
|
|
||||||
gc->BarrierEnd();
|
|
||||||
cse.back()->Push(gc, Undefined());
|
|
||||||
return false;
|
|
||||||
} else if (key == "RemoveAt") {
|
|
||||||
if (args.size() != 1) {
|
|
||||||
throw VMException(
|
|
||||||
"List.RemoveAt must only accept one argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!std::holds_alternative<int64_t>(args[0])) {
|
|
||||||
throw VMException(
|
|
||||||
"List.RemoveAt must only accept a long");
|
|
||||||
}
|
|
||||||
gc->BarrierBegin();
|
|
||||||
list->RemoveAt(std::get<int64_t>(args[0]));
|
|
||||||
gc->BarrierEnd();
|
|
||||||
cse.back()->Push(gc, Undefined());
|
|
||||||
return false;
|
|
||||||
} else if (key == "Clear") {
|
|
||||||
gc->BarrierBegin();
|
|
||||||
list->Clear();
|
|
||||||
gc->BarrierEnd();
|
|
||||||
cse.back()->Push(gc, Undefined());
|
|
||||||
return false;
|
|
||||||
} else if (key == "GetAt") {
|
|
||||||
if (args.size() != 1) {
|
|
||||||
throw VMException(
|
|
||||||
"List.GetAt must only accept one argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!std::holds_alternative<int64_t>(args[0])) {
|
|
||||||
throw VMException("List.GetAt must only accept a long");
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t index = std::get<int64_t>(args[0]);
|
|
||||||
if (index >= 0 && index < list->Count()) {
|
|
||||||
cse.back()->Push(gc, list->Get(index));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (key == "SetAt") {
|
|
||||||
if (args.size() != 2) {
|
|
||||||
throw VMException(
|
|
||||||
"List.SetAt must only accept two arguments");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!std::holds_alternative<int64_t>(args[0])) {
|
|
||||||
throw VMException("List.SetAt first argument must only "
|
|
||||||
"accept a long");
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t index = std::get<int64_t>(args[0]);
|
|
||||||
if (index >= 0 && index < list->Count()) {
|
|
||||||
list->Set(index, args[1]);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (key == "Count" || key == "Length") {
|
|
||||||
gc->BarrierBegin();
|
|
||||||
cse.back()->Push(gc, list->Count());
|
|
||||||
gc->BarrierEnd();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
cse.back()->Push(gc, Undefined());
|
|
||||||
return false;
|
|
||||||
} else if (dynList != nullptr) {
|
} else if (dynList != nullptr) {
|
||||||
|
|
||||||
if (key == "GetEnumerator") {
|
if (key == "GetEnumerator") {
|
||||||
|
|||||||
+18
-80
@@ -145,59 +145,6 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, Undefined());
|
cse.back()->Push(gc, Undefined());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<
|
|
||||||
std::shared_ptr<Tesses::Framework::Streams::Stream>>(
|
|
||||||
instance)) {
|
|
||||||
auto strm =
|
|
||||||
std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(
|
|
||||||
instance);
|
|
||||||
if (strm != nullptr) {
|
|
||||||
auto netStrm = std::dynamic_pointer_cast<
|
|
||||||
Tesses::Framework::Streams::NetworkStream>(strm);
|
|
||||||
|
|
||||||
if (key == "CanRead") {
|
|
||||||
|
|
||||||
cse.back()->Push(gc, strm->CanRead());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (key == "CanWrite") {
|
|
||||||
|
|
||||||
cse.back()->Push(gc, strm->CanWrite());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (key == "CanSeek") {
|
|
||||||
|
|
||||||
cse.back()->Push(gc, strm->CanSeek());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (key == "EndOfStream") {
|
|
||||||
|
|
||||||
cse.back()->Push(gc, strm->EndOfStream());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (key == "Length") {
|
|
||||||
|
|
||||||
cse.back()->Push(gc, strm->GetLength());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (key == "Position") {
|
|
||||||
|
|
||||||
cse.back()->Push(gc, strm->GetPosition());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (netStrm != nullptr) {
|
|
||||||
if (key == "Port") {
|
|
||||||
cse.back()->Push(gc, (int64_t)netStrm->GetPort());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cse.back()->Push(gc, Undefined());
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (std::holds_alternative<TVMVersion>(instance)) {
|
if (std::holds_alternative<TVMVersion>(instance)) {
|
||||||
TVMVersion &version = std::get<TVMVersion>(instance);
|
TVMVersion &version = std::get<TVMVersion>(instance);
|
||||||
if (key == "Major") {
|
if (key == "Major") {
|
||||||
@@ -323,8 +270,8 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
stk->Push(gc, Undefined());
|
stk->Push(gc, Undefined());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<THeapObjectHolder>(instance)) {
|
if (std::holds_alternative<THeapObject *>(instance)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(instance).obj;
|
auto obj = std::get<THeapObject *>(instance);
|
||||||
auto bA = dynamic_cast<TByteArray *>(obj);
|
auto bA = dynamic_cast<TByteArray *>(obj);
|
||||||
auto list = dynamic_cast<TList *>(obj);
|
auto list = dynamic_cast<TList *>(obj);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
@@ -391,7 +338,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, file->info);
|
cse.back()->Push(gc, file->info);
|
||||||
return false;
|
return false;
|
||||||
} else if (key == "Dependencies") {
|
} else if (key == "Dependencies") {
|
||||||
auto list = TList::Create(ls);
|
auto list = ls.Create<TList>();
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
for (auto item : file->dependencies) {
|
for (auto item : file->dependencies) {
|
||||||
auto res = TDictionary::Create(ls);
|
auto res = TDictionary::Create(ls);
|
||||||
@@ -403,7 +350,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, list);
|
cse.back()->Push(gc, list);
|
||||||
return false;
|
return false;
|
||||||
} else if (key == "Tools") {
|
} else if (key == "Tools") {
|
||||||
auto list = TList::Create(ls);
|
auto list = ls.Create<TList>();
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
for (auto item : file->tools) {
|
for (auto item : file->tools) {
|
||||||
auto res = TDictionary::Create(ls);
|
auto res = TDictionary::Create(ls);
|
||||||
@@ -415,7 +362,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, list);
|
cse.back()->Push(gc, list);
|
||||||
return false;
|
return false;
|
||||||
} else if (key == "Strings") {
|
} else if (key == "Strings") {
|
||||||
auto list = TList::Create(ls);
|
auto list = ls.Create<TList>();
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
for (auto item : file->name) {
|
for (auto item : file->name) {
|
||||||
list->Add(item);
|
list->Add(item);
|
||||||
@@ -429,7 +376,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, (int64_t)file->metadata.size());
|
cse.back()->Push(gc, (int64_t)file->metadata.size());
|
||||||
return false;
|
return false;
|
||||||
} else if (key == "Metadata") {
|
} else if (key == "Metadata") {
|
||||||
TList *meta = TList::Create(ls);
|
TList *meta = ls.Create<TList>();
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
for (size_t i = 0; i < file->metadata.size(); i++) {
|
for (size_t i = 0; i < file->metadata.size(); i++) {
|
||||||
meta->Add(TDictionary::Create(
|
meta->Add(TDictionary::Create(
|
||||||
@@ -441,7 +388,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, meta);
|
cse.back()->Push(gc, meta);
|
||||||
return false;
|
return false;
|
||||||
} else if (key == "Sections") {
|
} else if (key == "Sections") {
|
||||||
TList *sections = TList::Create(ls);
|
TList *sections = ls.Create<TList>();
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
for (auto &item : file->sections) {
|
for (auto &item : file->sections) {
|
||||||
TByteArray *ba = TByteArray::Create(ls);
|
TByteArray *ba = TByteArray::Create(ls);
|
||||||
@@ -455,7 +402,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, sections);
|
cse.back()->Push(gc, sections);
|
||||||
return false;
|
return false;
|
||||||
} else if (key == "SupportedVMs") {
|
} else if (key == "SupportedVMs") {
|
||||||
TList *supported = TList::Create(ls);
|
TList *supported = ls.Create<TList>();
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
if (file->vms.empty()) {
|
if (file->vms.empty()) {
|
||||||
supported->Add(TDictionary::Create(
|
supported->Add(TDictionary::Create(
|
||||||
@@ -471,7 +418,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, supported);
|
cse.back()->Push(gc, supported);
|
||||||
return false;
|
return false;
|
||||||
} else if (key == "Chunks") {
|
} else if (key == "Chunks") {
|
||||||
auto list = TList::Create(ls);
|
auto list = ls.Create<TList>();
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
for (auto item : file->chunks) {
|
for (auto item : file->chunks) {
|
||||||
list->Add(item);
|
list->Add(item);
|
||||||
@@ -482,7 +429,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, list);
|
cse.back()->Push(gc, list);
|
||||||
return false;
|
return false;
|
||||||
} else if (key == "Classes") {
|
} else if (key == "Classes") {
|
||||||
auto list = TList::Create(ls);
|
auto list = ls.Create<TList>();
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < (uint32_t)file->classes.size();
|
for (uint32_t i = 0; i < (uint32_t)file->classes.size();
|
||||||
@@ -494,13 +441,13 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
return false;
|
return false;
|
||||||
} else if (key == "Functions") {
|
} else if (key == "Functions") {
|
||||||
auto list = TList::Create(ls);
|
auto list = ls.Create<TList>();
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
for (auto &item : file->functions) {
|
for (auto &item : file->functions) {
|
||||||
TDictionary *dict = TDictionary::Create(ls);
|
TDictionary *dict = TDictionary::Create(ls);
|
||||||
if (!item.first.empty())
|
if (!item.first.empty())
|
||||||
dict->SetValue("Documentation", item.first[0]);
|
dict->SetValue("Documentation", item.first[0]);
|
||||||
TList *nameParts = TList::Create(ls);
|
TList *nameParts = ls.Create<TList>();
|
||||||
for (size_t i = 1; i < item.first.size(); i++) {
|
for (size_t i = 1; i < item.first.size(); i++) {
|
||||||
nameParts->Add(item.first[i]);
|
nameParts->Add(item.first[i]);
|
||||||
}
|
}
|
||||||
@@ -530,7 +477,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
}
|
}
|
||||||
if (chunk != nullptr) {
|
if (chunk != nullptr) {
|
||||||
if (key == "Arguments") {
|
if (key == "Arguments") {
|
||||||
auto myargs = TList::Create(ls);
|
auto myargs = ls.Create<TList>();
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
for (auto item : chunk->args) {
|
for (auto item : chunk->args) {
|
||||||
myargs->Add(item);
|
myargs->Add(item);
|
||||||
@@ -586,7 +533,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
if (closure != nullptr) {
|
if (closure != nullptr) {
|
||||||
if (key == "Arguments") {
|
if (key == "Arguments") {
|
||||||
GCList ls2(gc);
|
GCList ls2(gc);
|
||||||
TList *ls = TList::Create(ls2);
|
TList *ls = ls2.Create<TList>();
|
||||||
for (auto arg : closure->closure->args) {
|
for (auto arg : closure->closure->args) {
|
||||||
ls->Add(arg);
|
ls->Add(arg);
|
||||||
}
|
}
|
||||||
@@ -601,7 +548,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
if (externalMethod != nullptr) {
|
if (externalMethod != nullptr) {
|
||||||
if (key == "Arguments") {
|
if (key == "Arguments") {
|
||||||
GCList ls2(gc);
|
GCList ls2(gc);
|
||||||
TList *ls = TList::Create(ls2);
|
TList *ls = ls2.Create<TList>();
|
||||||
for (auto arg : externalMethod->args) {
|
for (auto arg : externalMethod->args) {
|
||||||
ls->Add(arg);
|
ls->Add(arg);
|
||||||
}
|
}
|
||||||
@@ -635,16 +582,7 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (list != nullptr) {
|
|
||||||
if (key == "Count" || key == "Length") {
|
|
||||||
int64_t len = list->Count();
|
|
||||||
if (len < 0)
|
|
||||||
len = 0;
|
|
||||||
|
|
||||||
stk->Push(gc, len);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dynList != nullptr) {
|
if (dynList != nullptr) {
|
||||||
if (key == "Count" || key == "Length") {
|
if (key == "Count" || key == "Length") {
|
||||||
int64_t len = dynList->Count(ls);
|
int64_t len = dynList->Count(ls);
|
||||||
@@ -669,9 +607,9 @@ bool InterperterThread::GetField(std::shared_ptr<GC> gc) {
|
|||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
TObject fn = dict->GetValue("get" + key);
|
TObject fn = dict->GetValue("get" + key);
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
if (std::holds_alternative<THeapObjectHolder>(fn) &&
|
if (std::holds_alternative<THeapObject *>(fn) &&
|
||||||
dynamic_cast<TCallable *>(
|
dynamic_cast<TCallable *>(std::get<THeapObject *>(fn)) !=
|
||||||
std::get<THeapObjectHolder>(fn).obj) != nullptr) {
|
nullptr) {
|
||||||
return InvokeOne(ls, fn, dict);
|
return InvokeOne(ls, fn, dict);
|
||||||
} else {
|
} else {
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
|
|||||||
@@ -15,16 +15,15 @@ namespace Tesses::CrossLang {
|
|||||||
bool InterperterThread::InvokeMethod(GCList &ls, TObject fn, TObject instance,
|
bool InterperterThread::InvokeMethod(GCList &ls, TObject fn, TObject instance,
|
||||||
std::vector<TObject> args) {
|
std::vector<TObject> args) {
|
||||||
|
|
||||||
if (std::holds_alternative<THeapObjectHolder>(fn)) {
|
if (std::holds_alternative<THeapObject *>(fn)) {
|
||||||
|
|
||||||
auto obj =
|
auto obj = dynamic_cast<TCallable *>(std::get<THeapObject *>(fn));
|
||||||
dynamic_cast<TCallable *>(std::get<THeapObjectHolder>(fn).obj);
|
|
||||||
if (obj != nullptr) {
|
if (obj != nullptr) {
|
||||||
auto closure = dynamic_cast<TClosure *>(obj);
|
auto closure = dynamic_cast<TClosure *>(obj);
|
||||||
if (closure != nullptr) {
|
if (closure != nullptr) {
|
||||||
|
|
||||||
if (!closure->closure->args.empty() &&
|
if (!closure->closure->args.empty() &&
|
||||||
closure->closure->args[0] == "this") {
|
closure->closure->args[0].GetString() == "this") {
|
||||||
std::vector<TObject> args2;
|
std::vector<TObject> args2;
|
||||||
args2.push_back(instance);
|
args2.push_back(instance);
|
||||||
args2.insert(args2.end(), args.begin(), args.end());
|
args2.insert(args2.end(), args.begin(), args.end());
|
||||||
|
|||||||
@@ -12,10 +12,9 @@
|
|||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
bool InterperterThread::InvokeTwo(GCList &ls, TObject fn, TObject left,
|
bool InterperterThread::InvokeTwo(GCList &ls, TObject fn, TObject left,
|
||||||
TObject right) {
|
TObject right) {
|
||||||
if (std::holds_alternative<THeapObjectHolder>(fn)) {
|
if (std::holds_alternative<THeapObject *>(fn)) {
|
||||||
|
|
||||||
auto obj =
|
auto obj = dynamic_cast<TCallable *>(std::get<THeapObject *>(fn));
|
||||||
dynamic_cast<TCallable *>(std::get<THeapObjectHolder>(fn).obj);
|
|
||||||
if (obj != nullptr) {
|
if (obj != nullptr) {
|
||||||
auto closure = dynamic_cast<TClosure *>(obj);
|
auto closure = dynamic_cast<TClosure *>(obj);
|
||||||
if (closure != nullptr) {
|
if (closure != nullptr) {
|
||||||
|
|||||||
+5
-30
@@ -231,34 +231,9 @@ bool InterperterThread::SetField(std::shared_ptr<GC> gc) {
|
|||||||
stk->Push(gc, Undefined());
|
stk->Push(gc, Undefined());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<
|
|
||||||
std::shared_ptr<Tesses::Framework::Streams::Stream>>(
|
|
||||||
instance)) {
|
|
||||||
auto strm =
|
|
||||||
std::get<std::shared_ptr<Tesses::Framework::Streams::Stream>>(
|
|
||||||
instance);
|
|
||||||
|
|
||||||
auto netStrm = std::dynamic_pointer_cast<
|
if (std::holds_alternative<THeapObject *>(instance)) {
|
||||||
Tesses::Framework::Streams::NetworkStream>(strm);
|
auto obj = std::get<THeapObject *>(instance);
|
||||||
if (netStrm != nullptr) {
|
|
||||||
int64_t n0;
|
|
||||||
bool bc;
|
|
||||||
if (key == "Broadcast" && GetObject(value, bc))
|
|
||||||
netStrm->SetBroadcast(bc);
|
|
||||||
if (key == "NoDelay" && GetObject(value, bc))
|
|
||||||
netStrm->SetNoDelay(bc);
|
|
||||||
if (key == "ReuseAddress" && GetObject(value, bc))
|
|
||||||
netStrm->SetReuseAddress(bc);
|
|
||||||
if (key == "ReusePort" && GetObject(value, bc))
|
|
||||||
netStrm->SetReusePort(bc);
|
|
||||||
if (key == "MulticastTTL" && GetObject(value, n0))
|
|
||||||
netStrm->SetMulticastTTL((uint8_t)n0);
|
|
||||||
}
|
|
||||||
stk->Push(gc, Undefined());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (std::holds_alternative<THeapObjectHolder>(instance)) {
|
|
||||||
auto obj = std::get<THeapObjectHolder>(instance).obj;
|
|
||||||
|
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -313,9 +288,9 @@ bool InterperterThread::SetField(std::shared_ptr<GC> gc) {
|
|||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
TObject fn = dict->GetValue("set" + key);
|
TObject fn = dict->GetValue("set" + key);
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
if (std::holds_alternative<THeapObjectHolder>(fn) &&
|
if (std::holds_alternative<THeapObject *>(fn) &&
|
||||||
dynamic_cast<TCallable *>(
|
dynamic_cast<TCallable *>(std::get<THeapObject *>(fn)) !=
|
||||||
std::get<THeapObjectHolder>(fn).obj) != nullptr) {
|
nullptr) {
|
||||||
return InvokeTwo(ls, fn, dict, value);
|
return InvokeTwo(ls, fn, dict, value);
|
||||||
} else {
|
} else {
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
|
|||||||
+12
-4
@@ -65,9 +65,17 @@ bool InterperterThread::Sub(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(
|
cse.back()->Push(
|
||||||
gc,
|
gc,
|
||||||
std::make_shared<Tesses::Framework::Date::DateTime>((*l) - (*r)));
|
std::make_shared<Tesses::Framework::Date::DateTime>((*l) - (*r)));
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
|
||||||
|
if (obj == nullptr) {
|
||||||
|
cse.back()->Push(gc, Undefined());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj->opSub(this, gc, right);
|
||||||
|
|
||||||
|
/*auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
|
|
||||||
auto natObj = dynamic_cast<TNativeObject *>(obj);
|
auto natObj = dynamic_cast<TNativeObject *>(obj);
|
||||||
@@ -104,7 +112,7 @@ bool InterperterThread::Sub(std::shared_ptr<GC> gc) {
|
|||||||
} else {
|
} else {
|
||||||
cse.back()->Push(gc, Undefined());
|
cse.back()->Push(gc, Undefined());
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
} else {
|
} else {
|
||||||
cse.back()->Push(gc, Undefined());
|
cse.back()->Push(gc, Undefined());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ bool ToBool(TObject obj) {
|
|||||||
} else if (std::holds_alternative<Tesses::Framework::Uuid>(obj)) {
|
} else if (std::holds_alternative<Tesses::Framework::Uuid>(obj)) {
|
||||||
auto &uuid = std::get<Tesses::Framework::Uuid>(obj);
|
auto &uuid = std::get<Tesses::Framework::Uuid>(obj);
|
||||||
return !uuid.IsEmpty();
|
return !uuid.IsEmpty();
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
} else if (std::holds_alternative<THeapObject *>(obj)) {
|
||||||
auto o = std::get<THeapObjectHolder>(obj).obj;
|
auto o = std::get<THeapObject *>(obj);
|
||||||
auto ls = dynamic_cast<TList *>(o);
|
auto ls = dynamic_cast<TList *>(o);
|
||||||
auto aarray = dynamic_cast<TAssociativeArray *>(o);
|
auto aarray = dynamic_cast<TAssociativeArray *>(o);
|
||||||
auto dict = dynamic_cast<TDictionary *>(o);
|
auto dict = dynamic_cast<TDictionary *>(o);
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ std::string ToString(std::shared_ptr<GC> gc, TObject o) {
|
|||||||
if (std::holds_alternative<char>(o)) {
|
if (std::holds_alternative<char>(o)) {
|
||||||
return std::string{std::get<char>(o)};
|
return std::string{std::get<char>(o)};
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<std::nullptr_t>(o)) {
|
if (IsNull(o)) {
|
||||||
return "null";
|
return "null";
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<Undefined>(o)) {
|
if (std::holds_alternative<Undefined>(o)) {
|
||||||
@@ -54,8 +54,8 @@ std::string ToString(std::shared_ptr<GC> gc, TObject o) {
|
|||||||
return std::get<Tesses::Framework::Uuid>(o).ToString(
|
return std::get<Tesses::Framework::Uuid>(o).ToString(
|
||||||
Framework::UuidStringifyConfig::LowercaseNoCurly);
|
Framework::UuidStringifyConfig::LowercaseNoCurly);
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<THeapObjectHolder>(o)) {
|
if (std::holds_alternative<THeapObject *>(o)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(o).obj;
|
auto obj = std::get<THeapObject *>(o);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
auto list = dynamic_cast<TList *>(obj);
|
auto list = dynamic_cast<TList *>(obj);
|
||||||
auto bArray = dynamic_cast<TByteArray *>(obj);
|
auto bArray = dynamic_cast<TByteArray *>(obj);
|
||||||
|
|||||||
@@ -58,13 +58,13 @@ void ThrowFatalError(std::exception &ex) {
|
|||||||
error.WriteLine(text);
|
error.WriteLine(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
if (clrtexcept != nullptr) {
|
if (clrtexcept != nullptr) {
|
||||||
error.WriteLine("CrossLang has encountered a fatal runtime exception");
|
error.WriteLine("CrossLang has encountered a fatal runtime exception");
|
||||||
error.WriteLine();
|
error.WriteLine();
|
||||||
error.WriteLine(clrtexcept->what());
|
error.WriteLine(clrtexcept->what());
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
if (compiler != nullptr) {
|
if (compiler != nullptr) {
|
||||||
error.WriteLine("CrossLang has encountered a compiler error");
|
error.WriteLine("CrossLang has encountered a compiler error");
|
||||||
@@ -81,13 +81,13 @@ void ThrowFatalError(std::exception &ex) {
|
|||||||
error.Write(":");
|
error.Write(":");
|
||||||
error.WriteLine((int64_t)li.offset);
|
error.WriteLine((int64_t)li.offset);
|
||||||
|
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
error.WriteLine("CrossLang has encountered a fatal C++ exception");
|
error.WriteLine("CrossLang has encountered a fatal C++ exception");
|
||||||
error.WriteLine();
|
error.WriteLine();
|
||||||
error.Write("what(): ");
|
error.Write("what(): ");
|
||||||
error.WriteLine(ex2->what());
|
error.WriteLine(ex2->what());
|
||||||
exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
} // namespace Tesses::CrossLang
|
} // namespace Tesses::CrossLang
|
||||||
+67
-60
@@ -5,22 +5,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
|
|
||||||
TFile *TFile::Create(GCList &ls) {
|
TFile *TFile::Create(GCList &ls) { return ls.Create<TFile>(); }
|
||||||
TFile *f = new TFile();
|
TFile *TFile::Create(GCList *ls) { return ls->Create<TFile>(); }
|
||||||
f->icon = -1;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(f);
|
|
||||||
_gc->Watch(f);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
TFile *TFile::Create(GCList *ls) {
|
|
||||||
TFile *f = new TFile();
|
|
||||||
f->icon = -1;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(f);
|
|
||||||
_gc->Watch(f);
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
void TFileChunk::Mark() {
|
void TFileChunk::Mark() {
|
||||||
if (this->marked)
|
if (this->marked)
|
||||||
return;
|
return;
|
||||||
@@ -28,20 +14,8 @@ void TFileChunk::Mark() {
|
|||||||
this->file->Mark();
|
this->file->Mark();
|
||||||
}
|
}
|
||||||
|
|
||||||
TFileChunk *TFileChunk::Create(GCList &ls) {
|
TFileChunk *TFileChunk::Create(GCList &ls) { return ls.Create<TFileChunk>(); }
|
||||||
TFileChunk *chk = new TFileChunk();
|
TFileChunk *TFileChunk::Create(GCList *ls) { return ls->Create<TFileChunk>(); }
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(chk);
|
|
||||||
_gc->Watch(chk);
|
|
||||||
return chk;
|
|
||||||
}
|
|
||||||
TFileChunk *TFileChunk::Create(GCList *ls) {
|
|
||||||
TFileChunk *chk = new TFileChunk();
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(chk);
|
|
||||||
_gc->Watch(chk);
|
|
||||||
return chk;
|
|
||||||
}
|
|
||||||
void TFile::Mark() {
|
void TFile::Mark() {
|
||||||
if (this->marked)
|
if (this->marked)
|
||||||
return;
|
return;
|
||||||
@@ -69,15 +43,18 @@ void TFile::Ensure(std::shared_ptr<Tesses::Framework::Streams::Stream> stream,
|
|||||||
"End of file, could not read " + std::to_string((int64_t)len) +
|
"End of file, could not read " + std::to_string((int64_t)len) +
|
||||||
" byte(s)., offset=" + std::to_string(stream->GetLength()));
|
" byte(s)., offset=" + std::to_string(stream->GetLength()));
|
||||||
}
|
}
|
||||||
std::string TFile::EnsureString(
|
void TFile::EnsureString(
|
||||||
std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
|
GCList &ls, std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
|
||||||
auto len = EnsureInt(stream);
|
auto len = EnsureInt(stream);
|
||||||
if (len == 0)
|
if (len == 0) {
|
||||||
return {};
|
this->strings.push_back(ls.FromString(""));
|
||||||
|
return;
|
||||||
|
}
|
||||||
std::string str = {};
|
std::string str = {};
|
||||||
str.resize((size_t)len);
|
str.resize((size_t)len);
|
||||||
Ensure(stream, (uint8_t *)str.data(), str.size());
|
Ensure(stream, (uint8_t *)str.data(), str.size());
|
||||||
return str;
|
|
||||||
|
this->strings.push_back(ls.Create<TString>(std::move(str)));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
@@ -86,7 +63,7 @@ TFile::EnsureInt(std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
|
|||||||
Ensure(stream, buffer, 4);
|
Ensure(stream, buffer, 4);
|
||||||
return BitConverter::ToUint32BE(buffer[0]);
|
return BitConverter::ToUint32BE(buffer[0]);
|
||||||
}
|
}
|
||||||
std::string
|
TString *
|
||||||
TFile::GetString(std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
|
TFile::GetString(std::shared_ptr<Tesses::Framework::Streams::Stream> stream) {
|
||||||
uint32_t index = EnsureInt(stream);
|
uint32_t index = EnsureInt(stream);
|
||||||
if (index >= this->strings.size())
|
if (index >= this->strings.size())
|
||||||
@@ -101,7 +78,7 @@ void TFile::EnsureCanRunInCrossLang() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto item : this->vms) {
|
for (auto item : this->vms) {
|
||||||
if (item.first == VMName) {
|
if (item.first->GetString() == VMName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,7 +86,8 @@ void TFile::EnsureCanRunInCrossLang() {
|
|||||||
std::string errorMessage = "The virtual machines supported are:\n";
|
std::string errorMessage = "The virtual machines supported are:\n";
|
||||||
|
|
||||||
for (auto item : this->vms) {
|
for (auto item : this->vms) {
|
||||||
errorMessage += item.first + "\n\t" + item.second + "\n";
|
errorMessage +=
|
||||||
|
item.first->GetString() + "\n\t" + item.second->GetString() + "\n";
|
||||||
}
|
}
|
||||||
throw VMException(errorMessage);
|
throw VMException(errorMessage);
|
||||||
}
|
}
|
||||||
@@ -178,7 +156,7 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) {
|
|||||||
items.push_back(parseEnt());
|
items.push_back(parseEnt());
|
||||||
}
|
}
|
||||||
|
|
||||||
return TList::Create(ls, items.begin(), items.end());
|
return ls.Create<TList>(items.begin(), items.end());
|
||||||
} else
|
} else
|
||||||
throw std::out_of_range("Abrupt end of metadata");
|
throw std::out_of_range("Abrupt end of metadata");
|
||||||
} break;
|
} break;
|
||||||
@@ -192,8 +170,8 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) {
|
|||||||
if (index + 4 <= bytes.size()) {
|
if (index + 4 <= bytes.size()) {
|
||||||
auto val2 = BitConverter::ToUint32BE(bytes[index]);
|
auto val2 = BitConverter::ToUint32BE(bytes[index]);
|
||||||
index += 4;
|
index += 4;
|
||||||
std::string &text = this->strings.at((size_t)val2);
|
TString *text = this->strings.at((size_t)val2);
|
||||||
items.emplace_back(text, parseEnt());
|
items.emplace_back(text->GetString(), parseEnt());
|
||||||
} else
|
} else
|
||||||
throw std::out_of_range("Abrupt end of metadata");
|
throw std::out_of_range("Abrupt end of metadata");
|
||||||
}
|
}
|
||||||
@@ -206,9 +184,7 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) {
|
|||||||
if (index + 4 <= bytes.size()) {
|
if (index + 4 <= bytes.size()) {
|
||||||
auto val = BitConverter::ToUint32BE(bytes[index]);
|
auto val = BitConverter::ToUint32BE(bytes[index]);
|
||||||
index += 4;
|
index += 4;
|
||||||
auto ba = TByteArray::Create(ls);
|
return ls.Create<TByteArray>(this->resources.at((size_t)val));
|
||||||
ba->data = this->resources.at((size_t)val);
|
|
||||||
return ba;
|
|
||||||
} else
|
} else
|
||||||
throw std::out_of_range("Abrupt end of metadata");
|
throw std::out_of_range("Abrupt end of metadata");
|
||||||
} break;
|
} break;
|
||||||
@@ -216,7 +192,8 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) {
|
|||||||
if (index + 4 <= bytes.size()) {
|
if (index + 4 <= bytes.size()) {
|
||||||
auto val = BitConverter::ToUint32BE(bytes[index]);
|
auto val = BitConverter::ToUint32BE(bytes[index]);
|
||||||
index += 4;
|
index += 4;
|
||||||
return std::make_shared<EmbedStream>(ls.GetGC(), this, val);
|
return ls.Create<TStream>(
|
||||||
|
std::make_shared<EmbedStream>(ls.GetGC(), this, val));
|
||||||
} else
|
} else
|
||||||
throw std::out_of_range("Abrupt end of metadata");
|
throw std::out_of_range("Abrupt end of metadata");
|
||||||
} break;
|
} break;
|
||||||
@@ -238,8 +215,8 @@ TDictionary *TFile::MetadataDecode(GCList &ls, size_t midx) {
|
|||||||
ls, "", {},
|
ls, "", {},
|
||||||
[val, this](GCList &ls,
|
[val, this](GCList &ls,
|
||||||
std::vector<TObject> args) -> TObject {
|
std::vector<TObject> args) -> TObject {
|
||||||
return std::make_shared<EmbedStream>(ls.GetGC(), this,
|
return ls.Create<TStream>(std::make_shared<EmbedStream>(
|
||||||
val);
|
ls.GetGC(), this, val));
|
||||||
});
|
});
|
||||||
em->watch.push_back(this);
|
em->watch.push_back(this);
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
@@ -287,26 +264,36 @@ void TFile::Load(std::shared_ptr<GC> gc,
|
|||||||
this->info = GetString(stream);
|
this->info = GetString(stream);
|
||||||
} else if (strncmp(table_name, "DEPS", 4) == 0) // dependencies
|
} else if (strncmp(table_name, "DEPS", 4) == 0) // dependencies
|
||||||
{
|
{
|
||||||
std::string name = GetString(stream);
|
TString *name = GetString(stream);
|
||||||
uint8_t version_bytes[5];
|
uint8_t version_bytes[5];
|
||||||
Ensure(stream, version_bytes, sizeof(version_bytes));
|
Ensure(stream, version_bytes, sizeof(version_bytes));
|
||||||
TVMVersion depVersion(version_bytes);
|
TVMVersion depVersion(version_bytes);
|
||||||
|
gc->BarrierBegin();
|
||||||
this->dependencies.push_back(
|
this->dependencies.push_back(
|
||||||
std::pair<std::string, TVMVersion>(name, depVersion));
|
std::pair<TString *, TVMVersion>(name, depVersion));
|
||||||
|
gc->BarrierEnd();
|
||||||
} else if (strncmp(table_name, "TOOL", 4) ==
|
} else if (strncmp(table_name, "TOOL", 4) ==
|
||||||
0) // compile tools (for package manager)
|
0) // compile tools (for package manager)
|
||||||
{
|
{
|
||||||
std::string name = GetString(stream);
|
TString *name = GetString(stream);
|
||||||
uint8_t version_bytes[5];
|
uint8_t version_bytes[5];
|
||||||
Ensure(stream, version_bytes, sizeof(version_bytes));
|
Ensure(stream, version_bytes, sizeof(version_bytes));
|
||||||
TVMVersion depVersion(version_bytes);
|
TVMVersion depVersion(version_bytes);
|
||||||
|
gc->BarrierBegin();
|
||||||
this->tools.push_back(
|
this->tools.push_back(
|
||||||
std::pair<std::string, TVMVersion>(name, depVersion));
|
std::pair<TString *, TVMVersion>(name, depVersion));
|
||||||
|
gc->BarrierEnd();
|
||||||
} else if (strncmp(table_name, "RESO", 4) ==
|
} else if (strncmp(table_name, "RESO", 4) ==
|
||||||
0) // resources (using embed)
|
0) // resources (using embed)
|
||||||
{
|
{
|
||||||
auto &data = this->resources.emplace_back(tableLen);
|
std::vector<uint8_t> data;
|
||||||
|
data.resize(tableLen);
|
||||||
Ensure(stream, data.data(), data.size());
|
Ensure(stream, data.data(), data.size());
|
||||||
|
GCList ls(gc);
|
||||||
|
gc->BarrierBegin();
|
||||||
|
this->resources.push_back(ls.Create<TResource>(std::move(data)));
|
||||||
|
gc->BarrierEnd();
|
||||||
|
|
||||||
} else if (strncmp(table_name, "CHKS", 4) == 0 &&
|
} else if (strncmp(table_name, "CHKS", 4) == 0 &&
|
||||||
gc != nullptr) // chunks
|
gc != nullptr) // chunks
|
||||||
{
|
{
|
||||||
@@ -314,11 +301,13 @@ void TFile::Load(std::shared_ptr<GC> gc,
|
|||||||
size_t chunkCount = (size_t)EnsureInt(stream);
|
size_t chunkCount = (size_t)EnsureInt(stream);
|
||||||
for (size_t j = 0; j < chunkCount; j++) {
|
for (size_t j = 0; j < chunkCount; j++) {
|
||||||
|
|
||||||
auto chunk = TFileChunk::Create(ls);
|
auto chunk = ls.Create<TFileChunk>();
|
||||||
chunk->file = this;
|
chunk->file = this;
|
||||||
size_t argCount = (size_t)EnsureInt(stream);
|
size_t argCount = (size_t)EnsureInt(stream);
|
||||||
for (size_t k = 0; k < argCount; k++) {
|
for (size_t k = 0; k < argCount; k++) {
|
||||||
|
gc->BarrierBegin();
|
||||||
chunk->args.push_back(GetString(stream));
|
chunk->args.push_back(GetString(stream));
|
||||||
|
gc->BarrierEnd();
|
||||||
}
|
}
|
||||||
size_t len = (size_t)EnsureInt(stream);
|
size_t len = (size_t)EnsureInt(stream);
|
||||||
chunk->code.resize(len);
|
chunk->code.resize(len);
|
||||||
@@ -333,33 +322,45 @@ void TFile::Load(std::shared_ptr<GC> gc,
|
|||||||
size_t funLength = (size_t)EnsureInt(stream);
|
size_t funLength = (size_t)EnsureInt(stream);
|
||||||
|
|
||||||
for (size_t j = 0; j < funLength; j++) {
|
for (size_t j = 0; j < funLength; j++) {
|
||||||
std::vector<std::string> fnParts;
|
std::vector<TString *> fnParts;
|
||||||
uint32_t fnPartsC = EnsureInt(stream);
|
uint32_t fnPartsC = EnsureInt(stream);
|
||||||
for (uint32_t k = 0; k < fnPartsC; k++) {
|
for (uint32_t k = 0; k < fnPartsC; k++) {
|
||||||
fnParts.push_back(GetString(stream));
|
fnParts.push_back(GetString(stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t fnNumber = EnsureInt(stream);
|
uint32_t fnNumber = EnsureInt(stream);
|
||||||
|
gc->BarrierBegin();
|
||||||
this->functions.push_back(
|
this->functions.push_back(
|
||||||
std::pair<std::vector<std::string>, uint32_t>(fnParts,
|
std::pair<std::vector<TString *>, uint32_t>(fnParts,
|
||||||
fnNumber));
|
fnNumber));
|
||||||
|
gc->BarrierEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (strncmp(table_name, "STRS", 4) == 0) // strings
|
} else if (strncmp(table_name, "STRS", 4) == 0) // strings
|
||||||
{
|
{
|
||||||
size_t strsLen = (size_t)EnsureInt(stream);
|
size_t strsLen = (size_t)EnsureInt(stream);
|
||||||
|
|
||||||
|
gc->BarrierBegin();
|
||||||
|
this->strings.reserve(strsLen);
|
||||||
|
gc->BarrierEnd();
|
||||||
|
|
||||||
|
GCList ls(gc);
|
||||||
for (size_t j = 0; j < strsLen; j++) {
|
for (size_t j = 0; j < strsLen; j++) {
|
||||||
this->strings.push_back(EnsureString(stream));
|
gc->BarrierBegin();
|
||||||
|
EnsureString(ls, stream);
|
||||||
|
gc->BarrierEnd();
|
||||||
}
|
}
|
||||||
} else if (strncmp(table_name, "ICON", 4) == 0) // icon
|
} else if (strncmp(table_name, "ICON", 4) == 0) // icon
|
||||||
{
|
{
|
||||||
this->icon = (int32_t)EnsureInt(stream);
|
this->icon = this->resources.at(EnsureInt(stream));
|
||||||
} else if (strncmp(table_name, "MACH", 4) == 0) // machine
|
} else if (strncmp(table_name, "MACH", 4) == 0) // machine
|
||||||
{
|
{
|
||||||
std::string name = GetString(stream);
|
TString *name = GetString(stream);
|
||||||
std::string howToGet = GetString(stream);
|
TString *howToGet = GetString(stream);
|
||||||
|
gc->BarrierBegin();
|
||||||
this->vms.push_back(
|
this->vms.push_back(
|
||||||
std::pair<std::string, std::string>(name, howToGet));
|
std::pair<TString *, TString *>(name, howToGet));
|
||||||
|
gc->BarrierEnd();
|
||||||
} else if (strncmp(table_name, "CLSS", 4) == 0) // classes
|
} else if (strncmp(table_name, "CLSS", 4) == 0) // classes
|
||||||
{
|
{
|
||||||
uint32_t clsCnt = EnsureInt(stream);
|
uint32_t clsCnt = EnsureInt(stream);
|
||||||
@@ -367,14 +368,17 @@ void TFile::Load(std::shared_ptr<GC> gc,
|
|||||||
TClass cls;
|
TClass cls;
|
||||||
cls.documentation = GetString(stream);
|
cls.documentation = GetString(stream);
|
||||||
uint32_t name_cnt = EnsureInt(stream);
|
uint32_t name_cnt = EnsureInt(stream);
|
||||||
|
cls.name.reserve((size_t)name_cnt);
|
||||||
for (uint32_t k = 0; k < name_cnt; k++) {
|
for (uint32_t k = 0; k < name_cnt; k++) {
|
||||||
cls.name.push_back(GetString(stream));
|
cls.name.push_back(GetString(stream));
|
||||||
}
|
}
|
||||||
name_cnt = EnsureInt(stream);
|
name_cnt = EnsureInt(stream);
|
||||||
|
cls.inherits.reserve((size_t)name_cnt);
|
||||||
for (uint32_t k = 0; k < name_cnt; k++) {
|
for (uint32_t k = 0; k < name_cnt; k++) {
|
||||||
cls.inherits.push_back(GetString(stream));
|
cls.inherits.push_back(GetString(stream));
|
||||||
}
|
}
|
||||||
name_cnt = EnsureInt(stream);
|
name_cnt = EnsureInt(stream);
|
||||||
|
cls.entry.reserve((size_t)name_cnt);
|
||||||
for (uint32_t k = 0; k < name_cnt; k++) {
|
for (uint32_t k = 0; k < name_cnt; k++) {
|
||||||
TClassEntry ent;
|
TClassEntry ent;
|
||||||
Ensure(stream, main_header, 1);
|
Ensure(stream, main_header, 1);
|
||||||
@@ -385,12 +389,15 @@ void TFile::Load(std::shared_ptr<GC> gc,
|
|||||||
ent.documentation = GetString(stream);
|
ent.documentation = GetString(stream);
|
||||||
ent.name = GetString(stream);
|
ent.name = GetString(stream);
|
||||||
uint32_t arglen = EnsureInt(stream);
|
uint32_t arglen = EnsureInt(stream);
|
||||||
|
ent.args.reserve((size_t)arglen);
|
||||||
for (uint32_t l = 0; l < arglen; l++)
|
for (uint32_t l = 0; l < arglen; l++)
|
||||||
ent.args.push_back(GetString(stream));
|
ent.args.push_back(GetString(stream));
|
||||||
ent.chunkId = EnsureInt(stream);
|
ent.chunkId = EnsureInt(stream);
|
||||||
cls.entry.push_back(ent);
|
cls.entry.push_back(ent);
|
||||||
}
|
}
|
||||||
|
gc->BarrierBegin();
|
||||||
this->classes.push_back(cls);
|
this->classes.push_back(cls);
|
||||||
|
gc->BarrierEnd();
|
||||||
}
|
}
|
||||||
} else if (strncmp(table_name, "META", 4) == 0) // structured metadata
|
} else if (strncmp(table_name, "META", 4) == 0) // structured metadata
|
||||||
{
|
{
|
||||||
|
|||||||
+87
-83
@@ -2,16 +2,25 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#if defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
#include <windows.h>
|
|
||||||
#else
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace Tesses::Framework::Threading;
|
using namespace Tesses::Framework::Threading;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
|
#if defined(GEKKO) || defined(_EE)
|
||||||
|
|
||||||
|
struct PthreadCmp {
|
||||||
|
bool operator()(const pthread_t &a, const pthread_t &b) const {
|
||||||
|
return pthread_equal(a, b) != 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static std::map<pthread_t, CallStackEntry *, PthreadCmp> current_funcs;
|
||||||
|
static Tesses::Framework::Threading::Mutex current_funcs_mtx;
|
||||||
|
#else
|
||||||
|
thread_local CallStackEntry *current_function;
|
||||||
|
#endif
|
||||||
bool GC::IsRunning() {
|
bool GC::IsRunning() {
|
||||||
|
|
||||||
bool run = this->running;
|
bool run = this->running;
|
||||||
@@ -74,7 +83,13 @@ TDictionary *CreateThread(GCList &ls, TCallable *callable, bool detached) {
|
|||||||
TObject cb = th->callable->Call(ls, {});
|
TObject cb = th->callable->Call(ls, {});
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
th->returnValue = cb;
|
th->returnValue = cb;
|
||||||
|
#if defined(GEKKO) || defined(_EE)
|
||||||
|
current_funcs_mtx.Lock();
|
||||||
|
current_funcs.erase(pthread_self());
|
||||||
|
current_funcs_mtx.Unlock();
|
||||||
|
#endif
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
|
|
||||||
th->hasReturned = true;
|
th->hasReturned = true;
|
||||||
});
|
});
|
||||||
while (!th->hasInit)
|
while (!th->hasInit)
|
||||||
@@ -93,121 +108,88 @@ void GC::Start() {
|
|||||||
return new Tesses::Framework::Threading::ThreadPool(threads);
|
return new Tesses::Framework::Threading::ThreadPool(threads);
|
||||||
},
|
},
|
||||||
[](Tesses::Framework::Threading::ThreadPool *p) -> void { delete p; });
|
[](Tesses::Framework::Threading::ThreadPool *p) -> void { delete p; });
|
||||||
this->mtx = new Mutex();
|
|
||||||
this->running = true;
|
this->running = true;
|
||||||
this->thrd = new Thread([this]() -> void {
|
this->thrd = new Thread([this]() -> void {
|
||||||
std::chrono::time_point<std::chrono::system_clock> last_frame,
|
|
||||||
this_frame;
|
|
||||||
|
|
||||||
this_frame = system_clock::now();
|
|
||||||
last_frame = this_frame;
|
|
||||||
|
|
||||||
while (this->IsRunning()) {
|
while (this->IsRunning()) {
|
||||||
this_frame = system_clock::now();
|
this->BarrierBegin();
|
||||||
if ((this_frame - last_frame) > 10s) {
|
while (this->IsRunning() && (this->allocs < ALLOC_THRESHOLD))
|
||||||
|
this->cond.Wait(&this->mtx);
|
||||||
|
this->allocs = 0;
|
||||||
|
std::vector<THeapObject *> to_delete;
|
||||||
|
this->Collect(to_delete);
|
||||||
|
this->BarrierEnd();
|
||||||
|
|
||||||
last_frame = this_frame;
|
for (auto o : to_delete)
|
||||||
this->Collect();
|
delete o;
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
std::vector<THeapObject *> to_delete;
|
||||||
|
this->BarrierBegin();
|
||||||
|
this->Collect(to_delete);
|
||||||
|
this->BarrierEnd();
|
||||||
|
|
||||||
#if defined(_WIN32)
|
for (auto item : to_delete)
|
||||||
Sleep(100);
|
delete item;
|
||||||
#else
|
|
||||||
usleep(100000);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
GC::Collect();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GC::UsingNullThreads() { return false; }
|
bool GC::UsingNullThreads() { return false; }
|
||||||
|
|
||||||
void GC::BarrierBegin() { this->mtx->Lock(); }
|
void GC::BarrierBegin() { this->mtx.Lock(); }
|
||||||
void GC::BarrierEnd() { this->mtx->Unlock(); }
|
void GC::BarrierEnd() { this->mtx.Unlock(); }
|
||||||
void GC::Watch(TObject obj) {
|
void GC::Watch(TObject obj) {
|
||||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
if (std::holds_alternative<THeapObject *>(obj)) {
|
||||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
auto _item = std::get<THeapObject *>(obj);
|
||||||
this->BarrierBegin();
|
this->BarrierBegin();
|
||||||
|
this->objects.insert(_item);
|
||||||
for (auto item : this->objects) {
|
auto nowAllocs = ++this->allocs;
|
||||||
if (item == _item) {
|
|
||||||
this->BarrierEnd();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->objects.push_back(_item);
|
|
||||||
this->BarrierEnd();
|
this->BarrierEnd();
|
||||||
|
if (nowAllocs >= ALLOC_THRESHOLD)
|
||||||
|
this->cond.Signal();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void GC::Mark(TObject obj) {
|
void GC::Mark(TObject obj) {
|
||||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
if (std::holds_alternative<THeapObject *>(obj)) {
|
||||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
auto _item = std::get<THeapObject *>(obj);
|
||||||
_item->Mark();
|
_item->Mark();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void GC::Unwatch(TObject obj) {
|
void GC::Unwatch(TObject obj) {
|
||||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
if (std::holds_alternative<THeapObject *>(obj)) {
|
||||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
auto _item = std::get<THeapObject *>(obj);
|
||||||
this->BarrierBegin();
|
this->BarrierBegin();
|
||||||
for (auto index = this->objects.begin();
|
this->objects.erase(_item);
|
||||||
index != this->objects.end();) {
|
|
||||||
if (*index == _item) {
|
|
||||||
index = this->objects.erase(index);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
this->BarrierEnd();
|
this->BarrierEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void GC::SetRoot(TObject obj) {
|
void GC::SetRoot(GCList *_item) {
|
||||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
if (_item == nullptr)
|
||||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
return;
|
||||||
this->BarrierBegin();
|
this->BarrierBegin();
|
||||||
|
|
||||||
for (auto item : this->roots) {
|
this->roots.insert(_item);
|
||||||
if (item == _item) {
|
|
||||||
this->BarrierEnd();
|
this->BarrierEnd();
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this->roots.push_back(_item);
|
|
||||||
this->BarrierEnd();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Tesses::Framework::Threading::ThreadPool *GC::GetPool() {
|
Tesses::Framework::Threading::ThreadPool *GC::GetPool() {
|
||||||
return this->tpool->GetValue();
|
return this->tpool->GetValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GC::UnsetRoot(TObject obj) {
|
void GC::UnsetRoot(GCList *_item) {
|
||||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
if (_item == nullptr)
|
||||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
return;
|
||||||
this->BarrierBegin();
|
this->BarrierBegin();
|
||||||
for (auto index = this->roots.begin(); index != this->roots.end();) {
|
this->roots.erase(_item);
|
||||||
if (*index == _item) {
|
|
||||||
index = this->roots.erase(index);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
index++;
|
|
||||||
}
|
|
||||||
this->BarrierEnd();
|
this->BarrierEnd();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
GC::~GC() {
|
GC::~GC() {
|
||||||
GC::BarrierBegin();
|
|
||||||
|
|
||||||
this->roots.clear();
|
|
||||||
GC::BarrierEnd();
|
|
||||||
|
|
||||||
this->running = false;
|
this->running = false;
|
||||||
|
this->cond.Signal();
|
||||||
this->thrd->Join();
|
this->thrd->Join();
|
||||||
delete this->thrd;
|
delete this->thrd;
|
||||||
for (auto item : objects)
|
|
||||||
delete item;
|
|
||||||
|
|
||||||
delete this->tpool;
|
delete this->tpool;
|
||||||
delete this->mtx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GC::RegisterEverythingCallback(
|
void GC::RegisterEverythingCallback(
|
||||||
@@ -218,23 +200,45 @@ void GC::RegisterEverything(TRootEnvironment *env) {
|
|||||||
for (auto item : this->register_everything)
|
for (auto item : this->register_everything)
|
||||||
item(this->shared_from_this(), env);
|
item(this->shared_from_this(), env);
|
||||||
}
|
}
|
||||||
void GC::Collect() {
|
|
||||||
this->BarrierBegin();
|
CallStackEntry *GC::GetCurrentFunction() {
|
||||||
|
#if defined(GEKKO) || defined(_EE)
|
||||||
|
current_funcs_mtx.Lock();
|
||||||
|
auto val = current_funcs[pthread_self()];
|
||||||
|
current_funcs_mtx.Unlock();
|
||||||
|
|
||||||
|
return val;
|
||||||
|
|
||||||
|
#else
|
||||||
|
return current_function;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
void GC::SetCurrentFunction(CallStackEntry *cse) {
|
||||||
|
#if defined(GEKKO) || defined(_EE)
|
||||||
|
current_funcs_mtx.Lock();
|
||||||
|
current_funcs[pthread_self()] = cse;
|
||||||
|
current_funcs_mtx.Unlock();
|
||||||
|
#else
|
||||||
|
current_function = cse;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void GC::Collect(std::vector<THeapObject *> &to_delete) {
|
||||||
|
|
||||||
for (auto item : this->objects) {
|
for (auto item : this->objects) {
|
||||||
item->marked = false;
|
item->marked = false;
|
||||||
}
|
}
|
||||||
for (auto item : this->roots) {
|
for (auto item : this->roots) {
|
||||||
item->Mark();
|
item->Mark();
|
||||||
}
|
}
|
||||||
for (auto index = this->objects.begin(); index != this->objects.end();
|
for (auto index = this->objects.begin(); index != this->objects.end();) {
|
||||||
index++) {
|
|
||||||
THeapObject *o = *index;
|
THeapObject *o = *index;
|
||||||
if (!o->marked) {
|
if (!o->marked) {
|
||||||
delete o;
|
to_delete.push_back(o);
|
||||||
this->objects.erase(index);
|
index = this->objects.erase(index);
|
||||||
index--;
|
} else {
|
||||||
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->BarrierEnd();
|
|
||||||
}
|
}
|
||||||
}; // namespace Tesses::CrossLang
|
}; // namespace Tesses::CrossLang
|
||||||
|
|||||||
+5
-6
@@ -8,10 +8,10 @@ GCList::GCList(std::shared_ptr<GC> gc) {
|
|||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<GC> GCList::GetGC() { return this->gc; }
|
std::shared_ptr<GC> GCList::GetGC() const { return this->gc; }
|
||||||
void GCList::Remove(TObject obj) {
|
void GCList::Remove(TObject obj) {
|
||||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
if (std::holds_alternative<THeapObject *>(obj)) {
|
||||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
auto _item = std::get<THeapObject *>(obj);
|
||||||
this->gc->BarrierBegin();
|
this->gc->BarrierBegin();
|
||||||
for (auto index = this->items.begin(); index != this->items.end();
|
for (auto index = this->items.begin(); index != this->items.end();
|
||||||
index++) {
|
index++) {
|
||||||
@@ -25,8 +25,8 @@ void GCList::Remove(TObject obj) {
|
|||||||
}
|
}
|
||||||
void GCList::Add(TObject obj) {
|
void GCList::Add(TObject obj) {
|
||||||
|
|
||||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
if (std::holds_alternative<THeapObject *>(obj)) {
|
||||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
auto _item = std::get<THeapObject *>(obj);
|
||||||
this->gc->BarrierBegin();
|
this->gc->BarrierBegin();
|
||||||
|
|
||||||
for (auto item : this->items) {
|
for (auto item : this->items) {
|
||||||
@@ -40,7 +40,6 @@ void GCList::Add(TObject obj) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
void GCList::Mark() {
|
void GCList::Mark() {
|
||||||
this->marked = true;
|
|
||||||
for (auto item : this->items) {
|
for (auto item : this->items) {
|
||||||
item->Mark();
|
item->Mark();
|
||||||
}
|
}
|
||||||
|
|||||||
+143
-139
@@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
namespace Tesses::CrossLang {
|
namespace Tesses::CrossLang {
|
||||||
|
|
||||||
thread_local CallStackEntry *current_function = nullptr;
|
|
||||||
|
|
||||||
TObject ExecuteFunction(GCList &ls, TCallable *callable,
|
TObject ExecuteFunction(GCList &ls, TCallable *callable,
|
||||||
std::vector<TObject> args) {
|
std::vector<TObject> args) {
|
||||||
return callable->Call(ls, args);
|
return callable->Call(ls, args);
|
||||||
@@ -81,8 +79,8 @@ bool InterperterThread::Times(std::shared_ptr<GC> gc) {
|
|||||||
} else if (std::holds_alternative<int64_t>(left) &&
|
} else if (std::holds_alternative<int64_t>(left) &&
|
||||||
std::holds_alternative<double>(right)) {
|
std::holds_alternative<double>(right)) {
|
||||||
cse.back()->Push(gc, std::get<int64_t>(left) * std::get<double>(right));
|
cse.back()->Push(gc, std::get<int64_t>(left) * std::get<double>(right));
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -182,8 +180,8 @@ bool InterperterThread::Divide(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, std::get<int64_t>(left) / std::get<double>(right));
|
cse.back()->Push(gc, std::get<int64_t>(left) / std::get<double>(right));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -258,8 +256,8 @@ bool InterperterThread::Mod(std::shared_ptr<GC> gc) {
|
|||||||
gc, fmod(std::get<int64_t>(left), std::get<double>(right)));
|
gc, fmod(std::get<int64_t>(left), std::get<double>(right)));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -314,8 +312,8 @@ bool InterperterThread::Neg(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, -std::get<int64_t>(left));
|
cse.back()->Push(gc, -std::get<int64_t>(left));
|
||||||
} else if (std::holds_alternative<double>(left)) {
|
} else if (std::holds_alternative<double>(left)) {
|
||||||
cse.back()->Push(gc, -std::get<double>(left));
|
cse.back()->Push(gc, -std::get<double>(left));
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
|
|
||||||
@@ -367,7 +365,7 @@ bool InterperterThread::LNot(std::shared_ptr<GC> gc) {
|
|||||||
|
|
||||||
if (std::holds_alternative<Undefined>(left)) {
|
if (std::holds_alternative<Undefined>(left)) {
|
||||||
cse.back()->Push(gc, true);
|
cse.back()->Push(gc, true);
|
||||||
} else if (std::holds_alternative<std::nullptr_t>(left)) {
|
} else if (IsNull(left)) {
|
||||||
cse.back()->Push(gc, true);
|
cse.back()->Push(gc, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,8 +375,8 @@ bool InterperterThread::LNot(std::shared_ptr<GC> gc) {
|
|||||||
|
|
||||||
else if (std::holds_alternative<bool>(left)) {
|
else if (std::holds_alternative<bool>(left)) {
|
||||||
cse.back()->Push(gc, !std::get<bool>(left));
|
cse.back()->Push(gc, !std::get<bool>(left));
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -433,8 +431,8 @@ bool InterperterThread::BNot(std::shared_ptr<GC> gc) {
|
|||||||
cse.back()->Push(gc, ~std::get<int64_t>(left));
|
cse.back()->Push(gc, ~std::get<int64_t>(left));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -540,8 +538,8 @@ bool InterperterThread::Lt(std::shared_ptr<GC> gc) {
|
|||||||
auto &r =
|
auto &r =
|
||||||
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||||
cse.back()->Push(gc, l->TotalSeconds() < r->TotalSeconds());
|
cse.back()->Push(gc, l->TotalSeconds() < r->TotalSeconds());
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -646,8 +644,8 @@ bool InterperterThread::Gt(std::shared_ptr<GC> gc) {
|
|||||||
auto &r =
|
auto &r =
|
||||||
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||||
cse.back()->Push(gc, l->TotalSeconds() > r->TotalSeconds());
|
cse.back()->Push(gc, l->TotalSeconds() > r->TotalSeconds());
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -753,8 +751,8 @@ bool InterperterThread::Lte(std::shared_ptr<GC> gc) {
|
|||||||
auto &r =
|
auto &r =
|
||||||
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||||
cse.back()->Push(gc, l->TotalSeconds() <= r->TotalSeconds());
|
cse.back()->Push(gc, l->TotalSeconds() <= r->TotalSeconds());
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -865,8 +863,8 @@ bool InterperterThread::Gte(std::shared_ptr<GC> gc) {
|
|||||||
auto &r =
|
auto &r =
|
||||||
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||||
cse.back()->Push(gc, l->TotalSeconds() >= r->TotalSeconds());
|
cse.back()->Push(gc, l->TotalSeconds() >= r->TotalSeconds());
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -919,8 +917,7 @@ bool InterperterThread::Eq(std::shared_ptr<GC> gc) {
|
|||||||
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::nullptr_t>(left) &&
|
if (IsNull(left) && IsNull(right)) {
|
||||||
std::holds_alternative<std::nullptr_t>(right)) {
|
|
||||||
cse.back()->Push(gc, true);
|
cse.back()->Push(gc, true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1002,8 +999,8 @@ bool InterperterThread::Eq(std::shared_ptr<GC> gc) {
|
|||||||
auto &r =
|
auto &r =
|
||||||
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||||
cse.back()->Push(gc, l->TotalSeconds() == r->TotalSeconds());
|
cse.back()->Push(gc, l->TotalSeconds() == r->TotalSeconds());
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -1041,25 +1038,23 @@ bool InterperterThread::Eq(std::shared_ptr<GC> gc) {
|
|||||||
|
|
||||||
else if (dynDict != nullptr) {
|
else if (dynDict != nullptr) {
|
||||||
auto res = dynDict->CallMethod(ls, "operator==", {right});
|
auto res = dynDict->CallMethod(ls, "operator==", {right});
|
||||||
if (!std::holds_alternative<std::nullptr_t>(res) &&
|
if (!IsNull(res) && std::holds_alternative<Undefined>(res)) {
|
||||||
std::holds_alternative<Undefined>(res)) {
|
|
||||||
cse.back()->Push(gc, res);
|
cse.back()->Push(gc, res);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (native != nullptr &&
|
else if (native != nullptr && IsNull(right)) {
|
||||||
std::holds_alternative<std::nullptr_t>(right)) {
|
|
||||||
cse.back()->Push(gc, native->GetDestroyed());
|
cse.back()->Push(gc, native->GetDestroyed());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::holds_alternative<THeapObjectHolder>(right)) {
|
if (std::holds_alternative<THeapObject *>(right)) {
|
||||||
cse.back()->Push(gc, obj == std::get<THeapObjectHolder>(right).obj);
|
cse.back()->Push(gc, obj == std::get<THeapObject *>(right));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (std::holds_alternative<std::nullptr_t>(right)) {
|
else if (IsNull(right)) {
|
||||||
cse.back()->Push(gc, false);
|
cse.back()->Push(gc, false);
|
||||||
return false;
|
return false;
|
||||||
} else if (std::holds_alternative<Undefined>(right)) {
|
} else if (std::holds_alternative<Undefined>(right)) {
|
||||||
@@ -1071,7 +1066,7 @@ bool InterperterThread::Eq(std::shared_ptr<GC> gc) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (std::holds_alternative<std::nullptr_t>(right)) {
|
else if (IsNull(right)) {
|
||||||
cse.back()->Push(gc, false);
|
cse.back()->Push(gc, false);
|
||||||
return false;
|
return false;
|
||||||
} else if (std::holds_alternative<Undefined>(right)) {
|
} else if (std::holds_alternative<Undefined>(right)) {
|
||||||
@@ -1089,8 +1084,7 @@ bool InterperterThread::NEq(std::shared_ptr<GC> 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::nullptr_t>(left) &&
|
if (IsNull(left) && IsNull(right)) {
|
||||||
std::holds_alternative<std::nullptr_t>(right)) {
|
|
||||||
cse.back()->Push(gc, false);
|
cse.back()->Push(gc, false);
|
||||||
return false;
|
return false;
|
||||||
} else if (std::holds_alternative<Undefined>(left) &&
|
} else if (std::holds_alternative<Undefined>(left) &&
|
||||||
@@ -1160,8 +1154,8 @@ bool InterperterThread::NEq(std::shared_ptr<GC> gc) {
|
|||||||
auto &r =
|
auto &r =
|
||||||
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
std::get<std::shared_ptr<Tesses::Framework::Date::TimeSpan>>(right);
|
||||||
cse.back()->Push(gc, l->TotalSeconds() != r->TotalSeconds());
|
cse.back()->Push(gc, l->TotalSeconds() != r->TotalSeconds());
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
auto native = dynamic_cast<TNative *>(obj);
|
auto native = dynamic_cast<TNative *>(obj);
|
||||||
auto natObj = dynamic_cast<TNativeObject *>(obj);
|
auto natObj = dynamic_cast<TNativeObject *>(obj);
|
||||||
@@ -1198,22 +1192,20 @@ bool InterperterThread::NEq(std::shared_ptr<GC> gc) {
|
|||||||
else if (dynDict != nullptr) {
|
else if (dynDict != nullptr) {
|
||||||
|
|
||||||
auto res = dynDict->CallMethod(ls, "operator!=", {right});
|
auto res = dynDict->CallMethod(ls, "operator!=", {right});
|
||||||
if (!std::holds_alternative<std::nullptr_t>(res) &&
|
if (!IsNull(res) && std::holds_alternative<Undefined>(res)) {
|
||||||
std::holds_alternative<Undefined>(res)) {
|
|
||||||
cse.back()->Push(gc, res);
|
cse.back()->Push(gc, res);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (native != nullptr &&
|
else if (native != nullptr && IsNull(right)) {
|
||||||
std::holds_alternative<std::nullptr_t>(right)) {
|
|
||||||
cse.back()->Push(gc, !native->GetDestroyed());
|
cse.back()->Push(gc, !native->GetDestroyed());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (std::holds_alternative<THeapObjectHolder>(right)) {
|
if (std::holds_alternative<THeapObject *>(right)) {
|
||||||
cse.back()->Push(gc, obj != std::get<THeapObjectHolder>(right).obj);
|
cse.back()->Push(gc, obj != std::get<THeapObject *>(right));
|
||||||
return false;
|
return false;
|
||||||
} else if (std::holds_alternative<std::nullptr_t>(right)) {
|
} else if (IsNull(right)) {
|
||||||
cse.back()->Push(gc, true);
|
cse.back()->Push(gc, true);
|
||||||
return false;
|
return false;
|
||||||
} else if (std::holds_alternative<Undefined>(right)) {
|
} else if (std::holds_alternative<Undefined>(right)) {
|
||||||
@@ -1226,7 +1218,7 @@ bool InterperterThread::NEq(std::shared_ptr<GC> gc) {
|
|||||||
} else if (std::holds_alternative<Undefined>(right)) {
|
} else if (std::holds_alternative<Undefined>(right)) {
|
||||||
cse.back()->Push(gc, true);
|
cse.back()->Push(gc, true);
|
||||||
return false;
|
return false;
|
||||||
} else if (std::holds_alternative<std::nullptr_t>(right)) {
|
} else if (IsNull(right)) {
|
||||||
cse.back()->Push(gc, true);
|
cse.back()->Push(gc, true);
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@@ -1245,8 +1237,8 @@ bool InterperterThread::LShift(std::shared_ptr<GC> gc) {
|
|||||||
std::holds_alternative<int64_t>(right)) {
|
std::holds_alternative<int64_t>(right)) {
|
||||||
cse.back()->Push(gc, std::get<int64_t>(left)
|
cse.back()->Push(gc, std::get<int64_t>(left)
|
||||||
<< (int)std::get<int64_t>(right));
|
<< (int)std::get<int64_t>(right));
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -1303,8 +1295,8 @@ bool InterperterThread::RShift(std::shared_ptr<GC> gc) {
|
|||||||
std::holds_alternative<int64_t>(right)) {
|
std::holds_alternative<int64_t>(right)) {
|
||||||
cse.back()->Push(gc, std::get<int64_t>(left) >>
|
cse.back()->Push(gc, std::get<int64_t>(left) >>
|
||||||
(int)std::get<int64_t>(right));
|
(int)std::get<int64_t>(right));
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -1361,8 +1353,8 @@ bool InterperterThread::BOr(std::shared_ptr<GC> gc) {
|
|||||||
std::holds_alternative<int64_t>(right)) {
|
std::holds_alternative<int64_t>(right)) {
|
||||||
cse.back()->Push(gc,
|
cse.back()->Push(gc,
|
||||||
std::get<int64_t>(left) | std::get<int64_t>(right));
|
std::get<int64_t>(left) | std::get<int64_t>(right));
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -1419,8 +1411,8 @@ bool InterperterThread::XOr(std::shared_ptr<GC> gc) {
|
|||||||
std::holds_alternative<int64_t>(right)) {
|
std::holds_alternative<int64_t>(right)) {
|
||||||
cse.back()->Push(gc,
|
cse.back()->Push(gc,
|
||||||
std::get<int64_t>(left) ^ std::get<int64_t>(right));
|
std::get<int64_t>(left) ^ std::get<int64_t>(right));
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -1476,8 +1468,8 @@ bool InterperterThread::BAnd(std::shared_ptr<GC> gc) {
|
|||||||
std::holds_alternative<int64_t>(right)) {
|
std::holds_alternative<int64_t>(right)) {
|
||||||
cse.back()->Push(gc,
|
cse.back()->Push(gc,
|
||||||
std::get<int64_t>(left) & std::get<int64_t>(right));
|
std::get<int64_t>(left) & std::get<int64_t>(right));
|
||||||
} else if (std::holds_alternative<THeapObjectHolder>(left)) {
|
} else if (std::holds_alternative<THeapObject *>(left)) {
|
||||||
auto obj = std::get<THeapObjectHolder>(left).obj;
|
auto obj = std::get<THeapObject *>(left);
|
||||||
auto dict = dynamic_cast<TDictionary *>(obj);
|
auto dict = dynamic_cast<TDictionary *>(obj);
|
||||||
|
|
||||||
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
auto dynDict = dynamic_cast<TDynamicDictionary *>(obj);
|
||||||
@@ -1522,10 +1514,9 @@ bool InterperterThread::BAnd(std::shared_ptr<GC> gc) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool InterperterThread::InvokeOne(GCList &ls, TObject fn, TObject arg) {
|
bool InterperterThread::InvokeOne(GCList &ls, TObject fn, TObject arg) {
|
||||||
if (std::holds_alternative<THeapObjectHolder>(fn)) {
|
if (std::holds_alternative<THeapObject *>(fn)) {
|
||||||
|
|
||||||
auto obj =
|
auto obj = dynamic_cast<TCallable *>(std::get<THeapObject *>(fn));
|
||||||
dynamic_cast<TCallable *>(std::get<THeapObjectHolder>(fn).obj);
|
|
||||||
if (obj != nullptr) {
|
if (obj != nullptr) {
|
||||||
auto closure = dynamic_cast<TClosure *>(obj);
|
auto closure = dynamic_cast<TClosure *>(obj);
|
||||||
if (closure != nullptr) {
|
if (closure != nullptr) {
|
||||||
@@ -1570,10 +1561,10 @@ bool InterperterThread::ExecuteFunction(std::shared_ptr<GC> gc) {
|
|||||||
if (args.size() == 3) {
|
if (args.size() == 3) {
|
||||||
|
|
||||||
if (std::holds_alternative<std::string>(args[1]) &&
|
if (std::holds_alternative<std::string>(args[1]) &&
|
||||||
std::holds_alternative<THeapObjectHolder>(args[2])) {
|
std::holds_alternative<THeapObject *>(args[2])) {
|
||||||
std::string key = std::get<std::string>(args[1]);
|
std::string key = std::get<std::string>(args[1]);
|
||||||
TList *ls = dynamic_cast<TList *>(
|
TList *ls = dynamic_cast<TList *>(
|
||||||
std::get<THeapObjectHolder>(args[2]).obj);
|
std::get<THeapObject *>(args[2]));
|
||||||
if (ls != nullptr)
|
if (ls != nullptr)
|
||||||
return ExecuteMethod2(gc, args[0], key, ls->items);
|
return ExecuteMethod2(gc, args[0], key, ls->items);
|
||||||
}
|
}
|
||||||
@@ -1582,10 +1573,10 @@ bool InterperterThread::ExecuteFunction(std::shared_ptr<GC> gc) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std::holds_alternative<THeapObjectHolder>(fn)) {
|
if (std::holds_alternative<THeapObject *>(fn)) {
|
||||||
|
|
||||||
auto obj = dynamic_cast<TCallable *>(
|
auto obj =
|
||||||
std::get<THeapObjectHolder>(fn).obj);
|
dynamic_cast<TCallable *>(std::get<THeapObject *>(fn));
|
||||||
if (obj != nullptr) {
|
if (obj != nullptr) {
|
||||||
auto closure = dynamic_cast<TClosure *>(obj);
|
auto closure = dynamic_cast<TClosure *>(obj);
|
||||||
if (closure != nullptr) {
|
if (closure != nullptr) {
|
||||||
@@ -2051,7 +2042,8 @@ bool InterperterThread::DeclareConstVariable(std::shared_ptr<GC> gc) {
|
|||||||
|
|
||||||
throw VMException(
|
throw VMException(
|
||||||
"[DECLARECONSTVARIABLE] Can't pop string, got type " +
|
"[DECLARECONSTVARIABLE] Can't pop string, got type " +
|
||||||
GetObjectTypeString(key) + " = " + ToString(gc, key) + ".");
|
GetObjectTypeString(key) + " = " + ObjectToString(gc, key) +
|
||||||
|
".");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -2069,10 +2061,8 @@ bool InterperterThread::PushResourceStream(std::shared_ptr<GC> gc) {
|
|||||||
|
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
// TByteArray* arr = TByteArray::Create(ls);
|
stk->Push(gc, ls.Create<TStream>(std::make_shared<EmbedStream>(
|
||||||
// arr->data = stk->callable->file->resources[n];
|
gc, stk->callable->file->resources[n])));
|
||||||
stk->Push(
|
|
||||||
gc, std::make_shared<EmbedStream>(gc, stk->callable->file, n));
|
|
||||||
|
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
} else {
|
} else {
|
||||||
@@ -2095,9 +2085,9 @@ bool InterperterThread::PushResource(std::shared_ptr<GC> gc) {
|
|||||||
|
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
TByteArray *arr = TByteArray::Create(ls);
|
|
||||||
arr->data = stk->callable->file->resources[n];
|
stk->Push(gc,
|
||||||
stk->Push(gc, arr);
|
ls.Create<TByteArray>(stk->callable->file->resources[n]));
|
||||||
|
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
} else {
|
} else {
|
||||||
@@ -2113,9 +2103,15 @@ bool InterperterThread::Throw(std::shared_ptr<GC> gc) {
|
|||||||
|
|
||||||
if (!std::holds_alternative<Undefined>(_res2)) {
|
if (!std::holds_alternative<Undefined>(_res2)) {
|
||||||
auto env = cse.back()->env;
|
auto env = cse.back()->env;
|
||||||
if (!env->GetRootEnvironment()->HandleException(gc, env, _res2))
|
if (!env->GetRootEnvironment()->HandleException(gc, env, _res2)) {
|
||||||
|
TNativeException *nex;
|
||||||
|
if (GetObjectHeap(_res2, nex)) {
|
||||||
|
nex->ThrowIt();
|
||||||
|
}
|
||||||
|
|
||||||
throw VMByteCodeException(gc, _res2, cse.back());
|
throw VMByteCodeException(gc, _res2, cse.back());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool InterperterThread::PushResourceDirectory(std::shared_ptr<GC> gc) {
|
bool InterperterThread::PushResourceDirectory(std::shared_ptr<GC> gc) {
|
||||||
@@ -2143,8 +2139,7 @@ bool InterperterThread::JumpIfDefined(std::shared_ptr<GC> gc) {
|
|||||||
auto _res2 = stk->Pop(ls);
|
auto _res2 = stk->Pop(ls);
|
||||||
|
|
||||||
stk->ip = stk->ip + 4;
|
stk->ip = stk->ip + 4;
|
||||||
if (!std::holds_alternative<Undefined>(_res2) &&
|
if (!std::holds_alternative<Undefined>(_res2) && !IsNull(_res2)) {
|
||||||
!std::holds_alternative<std::nullptr_t>(_res2)) {
|
|
||||||
stk->ip = n;
|
stk->ip = n;
|
||||||
stk->Push(gc, _res2);
|
stk->Push(gc, _res2);
|
||||||
}
|
}
|
||||||
@@ -2223,6 +2218,7 @@ bool InterperterThread::JumpUndefined(std::shared_ptr<GC> gc) {
|
|||||||
bool InterperterThread::Jump(std::shared_ptr<GC> gc) {
|
bool InterperterThread::Jump(std::shared_ptr<GC> gc) {
|
||||||
|
|
||||||
std::vector<CallStackEntry *> &cse = this->call_stack_entries;
|
std::vector<CallStackEntry *> &cse = this->call_stack_entries;
|
||||||
|
|
||||||
auto stk = cse.back();
|
auto stk = cse.back();
|
||||||
|
|
||||||
if (stk->ip + 4 <= stk->callable->closure->code.size()) {
|
if (stk->ip + 4 <= stk->callable->closure->code.size()) {
|
||||||
@@ -2316,9 +2312,8 @@ bool InterperterThread::AppendList(std::shared_ptr<GC> gc) {
|
|||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
auto obj = stk->Pop(ls);
|
auto obj = stk->Pop(ls);
|
||||||
auto objhold = stk->Pop(ls);
|
auto objhold = stk->Pop(ls);
|
||||||
if (std::holds_alternative<THeapObjectHolder>(objhold)) {
|
if (std::holds_alternative<THeapObject *>(objhold)) {
|
||||||
auto list =
|
auto list = dynamic_cast<TList *>(std::get<THeapObject *>(objhold));
|
||||||
dynamic_cast<TList *>(std::get<THeapObjectHolder>(objhold).obj);
|
|
||||||
if (list != nullptr) {
|
if (list != nullptr) {
|
||||||
list->Add(obj);
|
list->Add(obj);
|
||||||
}
|
}
|
||||||
@@ -2348,12 +2343,12 @@ bool InterperterThread::AppendDictionary(std::shared_ptr<GC> gc) {
|
|||||||
auto value = stk->Pop(ls);
|
auto value = stk->Pop(ls);
|
||||||
auto k = stk->Pop(ls);
|
auto k = stk->Pop(ls);
|
||||||
auto objhold = stk->Pop(ls);
|
auto objhold = stk->Pop(ls);
|
||||||
if (std::holds_alternative<THeapObjectHolder>(objhold) &&
|
if (std::holds_alternative<THeapObject *>(objhold) &&
|
||||||
std::holds_alternative<std::string>(k)) {
|
std::holds_alternative<std::string>(k)) {
|
||||||
auto dict = dynamic_cast<TDictionary *>(
|
auto dict =
|
||||||
std::get<THeapObjectHolder>(objhold).obj);
|
dynamic_cast<TDictionary *>(std::get<THeapObject *>(objhold));
|
||||||
auto cls = dynamic_cast<TClassObject *>(
|
auto cls =
|
||||||
std::get<THeapObjectHolder>(objhold).obj);
|
dynamic_cast<TClassObject *>(std::get<THeapObject *>(objhold));
|
||||||
|
|
||||||
if (dict != nullptr) {
|
if (dict != nullptr) {
|
||||||
dict->SetValue(std::get<std::string>(k), value);
|
dict->SetValue(std::get<std::string>(k), value);
|
||||||
@@ -2383,7 +2378,7 @@ bool InterperterThread::CreateArray(std::shared_ptr<GC> gc) {
|
|||||||
std::vector<CallStackEntry *> &cse = this->call_stack_entries;
|
std::vector<CallStackEntry *> &cse = this->call_stack_entries;
|
||||||
auto stk = cse.back();
|
auto stk = cse.back();
|
||||||
GCList ls(gc);
|
GCList ls(gc);
|
||||||
TList *dict = TList::Create(ls);
|
TList *dict = ls.Create<TList>();
|
||||||
stk->Push(gc, dict);
|
stk->Push(gc, dict);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2409,23 +2404,39 @@ bool InterperterThread::TryCatch(std::shared_ptr<GC> gc) {
|
|||||||
if (GetObjectHeap(tryFn, tryC) && GetObjectHeap(catchFn, catchC)) {
|
if (GetObjectHeap(tryFn, tryC) && GetObjectHeap(catchFn, catchC)) {
|
||||||
try {
|
try {
|
||||||
stk->Push(gc, tryC->Call(ls, {}));
|
stk->Push(gc, tryC->Call(ls, {}));
|
||||||
}
|
|
||||||
|
|
||||||
catch (std::exception &ex) {
|
} catch (std::bad_alloc &ex) {
|
||||||
TDictionary *dict = TDictionary::Create(ls);
|
std::cerr
|
||||||
auto gc = ls.GetGC();
|
<< "CrossLang has failed to allocate, sorry for termination."
|
||||||
auto myEx = dynamic_cast<VMByteCodeException *>(&ex);
|
<< std::endl;
|
||||||
if (myEx != nullptr) {
|
std::exit(1);
|
||||||
stk->Push(gc, catchC->Call(ls, {myEx->exception}));
|
} catch (const std::string &ex) {
|
||||||
} else {
|
stk->Push(gc, catchC->Call(ls, {ex}));
|
||||||
gc->BarrierBegin();
|
} catch (const char *ex) {
|
||||||
|
|
||||||
dict->SetValue("Type", "NativeException");
|
stk->Push(gc,
|
||||||
dict->SetValue("Text", ex.what());
|
catchC->Call(ls, {std::string{ex != nullptr ? ex : ""}}));
|
||||||
gc->BarrierEnd();
|
} catch (std::runtime_error &ex) {
|
||||||
|
|
||||||
stk->Push(gc, catchC->Call(ls, {dict}));
|
stk->Push(
|
||||||
}
|
gc, catchC->Call(ls, {TNativeObject::Create<TException>(
|
||||||
|
ls, ex.what(), "RuntimeException")}));
|
||||||
|
} catch (VMException &ex) {
|
||||||
|
stk->Push(
|
||||||
|
gc, catchC->Call(ls, {TNativeObject::Create<TException>(
|
||||||
|
ls, ex.GetMessage(), "VMException")}));
|
||||||
|
} catch (VMByteCodeException &ex) {
|
||||||
|
stk->Push(gc, catchC->Call(ls, {ex.exception}));
|
||||||
|
} catch (std::exception &ex) {
|
||||||
|
stk->Push(gc,
|
||||||
|
catchC->Call(
|
||||||
|
ls, {TNativeObject::Create<TNativeException>(
|
||||||
|
ls, ex.what(), std::current_exception())}));
|
||||||
|
} catch (...) {
|
||||||
|
stk->Push(gc,
|
||||||
|
catchC->Call(ls, {TNativeObject::Create<TNativeException>(
|
||||||
|
ls, "<No Message>",
|
||||||
|
std::current_exception())}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -2693,14 +2704,14 @@ void InterperterThread::Execute(std::shared_ptr<GC> gc) {
|
|||||||
|
|
||||||
std::vector<CallStackEntry *> &cse = this->call_stack_entries;
|
std::vector<CallStackEntry *> &cse = this->call_stack_entries;
|
||||||
#define VM_OPCODE_TABLE_INLINE
|
#define VM_OPCODE_TABLE_INLINE
|
||||||
#include "vm_opcode_table.h"
|
#include "vm_opcode_table.def"
|
||||||
#undef VM_OPCODE_TABLE_INLINE
|
#undef VM_OPCODE_TABLE_INLINE
|
||||||
|
|
||||||
execute:
|
execute:
|
||||||
|
|
||||||
if (!cse.empty()) {
|
if (!cse.empty()) {
|
||||||
auto stk = cse.back();
|
auto stk = cse.back();
|
||||||
current_function = stk;
|
GC::SetCurrentFunction(stk);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
while (stk->ip < 0xFFFFFFFF &&
|
while (stk->ip < 0xFFFFFFFF &&
|
||||||
@@ -2721,7 +2732,7 @@ execute:
|
|||||||
cse[cse.size() - 2]->Push(gc, o);
|
cse[cse.size() - 2]->Push(gc, o);
|
||||||
|
|
||||||
cse.erase(cse.end() - 1);
|
cse.erase(cse.end() - 1);
|
||||||
current_function = cse.back();
|
GC::SetCurrentFunction(cse.back());
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
goto execute;
|
goto execute;
|
||||||
} else {
|
} else {
|
||||||
@@ -2729,8 +2740,13 @@ execute:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gc->UsingNullThreads())
|
if (gc->UsingNullThreads()) {
|
||||||
gc->Collect();
|
std::vector<THeapObject *> objs;
|
||||||
|
gc->Collect(objs);
|
||||||
|
for (auto &item : objs) {
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stk->mustReturn = false;
|
stk->mustReturn = false;
|
||||||
@@ -2764,7 +2780,7 @@ execute:
|
|||||||
}
|
}
|
||||||
if (cse.size() == 1) {
|
if (cse.size() == 1) {
|
||||||
|
|
||||||
current_function = nullptr;
|
GC::SetCurrentFunction(nullptr);
|
||||||
{
|
{
|
||||||
|
|
||||||
gc->BarrierBegin();
|
gc->BarrierBegin();
|
||||||
@@ -2817,7 +2833,7 @@ execute:
|
|||||||
cse[cse.size() - 2]->Push(gc, o);
|
cse[cse.size() - 2]->Push(gc, o);
|
||||||
|
|
||||||
cse.erase(cse.end() - 1);
|
cse.erase(cse.end() - 1);
|
||||||
current_function = cse.back();
|
GC::SetCurrentFunction(cse.back());
|
||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
|
|
||||||
for (auto item : callable) {
|
for (auto item : callable) {
|
||||||
@@ -2846,7 +2862,7 @@ void CallStackEntry::Push(std::shared_ptr<GC> gc, TObject o) {
|
|||||||
gc->BarrierEnd();
|
gc->BarrierEnd();
|
||||||
}
|
}
|
||||||
TObject CallStackEntry::Resume(GCList &ls) {
|
TObject CallStackEntry::Resume(GCList &ls) {
|
||||||
auto cse = current_function;
|
auto cse = GC::GetCurrentFunction();
|
||||||
InterperterThread *thrd = InterperterThread::Create(ls);
|
InterperterThread *thrd = InterperterThread::Create(ls);
|
||||||
ls.GetGC()->BarrierBegin();
|
ls.GetGC()->BarrierBegin();
|
||||||
thrd->call_stack_entries.push_back(this);
|
thrd->call_stack_entries.push_back(this);
|
||||||
@@ -2855,7 +2871,7 @@ TObject CallStackEntry::Resume(GCList &ls) {
|
|||||||
thrd->Execute(ls.GetGC());
|
thrd->Execute(ls.GetGC());
|
||||||
|
|
||||||
TObject v = thrd->call_stack_entries[0]->Pop(ls);
|
TObject v = thrd->call_stack_entries[0]->Pop(ls);
|
||||||
current_function = cse;
|
GC::SetCurrentFunction(cse);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
TObject CallStackEntry::Pop(GCList &gc) {
|
TObject CallStackEntry::Pop(GCList &gc) {
|
||||||
@@ -2870,41 +2886,17 @@ TObject CallStackEntry::Pop(GCList &gc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
InterperterThread *InterperterThread::Create(GCList &ls) {
|
InterperterThread *InterperterThread::Create(GCList &ls) {
|
||||||
InterperterThread *it = new InterperterThread();
|
return ls.Create<InterperterThread>();
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(it);
|
|
||||||
_gc->Watch(it);
|
|
||||||
return it;
|
|
||||||
}
|
}
|
||||||
InterperterThread *InterperterThread::Create(GCList *ls) {
|
InterperterThread *InterperterThread::Create(GCList *ls) {
|
||||||
InterperterThread *it = new InterperterThread();
|
return ls->Create<InterperterThread>();
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(it);
|
|
||||||
_gc->Watch(it);
|
|
||||||
return it;
|
|
||||||
}
|
}
|
||||||
CallStackEntry *CallStackEntry::Create(GCList &ls) {
|
CallStackEntry *CallStackEntry::Create(GCList &ls) {
|
||||||
CallStackEntry *cse = new CallStackEntry();
|
return ls.Create<CallStackEntry>();
|
||||||
cse->mustReturn = false;
|
|
||||||
cse->srcline = -1;
|
|
||||||
cse->srcfile = "";
|
|
||||||
cse->thread = nullptr;
|
|
||||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
|
||||||
ls.Add(cse);
|
|
||||||
_gc->Watch(cse);
|
|
||||||
return cse;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CallStackEntry *CallStackEntry::Create(GCList *ls) {
|
CallStackEntry *CallStackEntry::Create(GCList *ls) {
|
||||||
CallStackEntry *cse = new CallStackEntry();
|
return ls->Create<CallStackEntry>();
|
||||||
cse->mustReturn = false;
|
|
||||||
cse->srcline = -1;
|
|
||||||
cse->srcfile = "";
|
|
||||||
cse->thread = nullptr;
|
|
||||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
|
||||||
ls->Add(cse);
|
|
||||||
_gc->Watch(cse);
|
|
||||||
return cse;
|
|
||||||
}
|
}
|
||||||
void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
|
void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
|
||||||
std::vector<TObject> args) {
|
std::vector<TObject> args) {
|
||||||
@@ -2917,7 +2909,7 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
|
|||||||
: closure->env;
|
: closure->env;
|
||||||
cse->ip = 0;
|
cse->ip = 0;
|
||||||
if (closure->closure->args.empty() && closure->chunkId != 0) {
|
if (closure->closure->args.empty() && closure->chunkId != 0) {
|
||||||
TList *list = TList::Create(ls);
|
TList *list = ls.Create<TList>();
|
||||||
list->items = args;
|
list->items = args;
|
||||||
cse->env->DeclareVariable("arguments", list);
|
cse->env->DeclareVariable("arguments", list);
|
||||||
|
|
||||||
@@ -2963,13 +2955,25 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
|
|||||||
cse->env->DeclareVariable(trimStart(closure->closure->args[i]),
|
cse->env->DeclareVariable(trimStart(closure->closure->args[i]),
|
||||||
args[i]);
|
args[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (; i < closure->closure->args.size(); i++) {
|
||||||
|
auto &a = closure->closure->args[i];
|
||||||
|
if (a.size() > 1 && a[0] == '$') {
|
||||||
|
if (a[1] == '$') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cse->env->DeclareVariable(trimStart(a), Undefined());
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
std::string back = closure->closure->args.empty()
|
std::string back = closure->closure->args.empty()
|
||||||
? std::string()
|
? std::string()
|
||||||
: closure->closure->args.back();
|
: closure->closure->args.back();
|
||||||
if (i == closure->closure->args.size() - 1 && back.size() > 2 &&
|
if (i == closure->closure->args.size() - 1 && back.size() > 2 &&
|
||||||
back[0] == '$' && back[1] == '$') {
|
back[0] == '$' && back[1] == '$') {
|
||||||
auto argName = closure->closure->args[i];
|
auto argName = closure->closure->args[i];
|
||||||
auto lsArgs = TList::Create(ls);
|
auto lsArgs = ls.Create<TList>();
|
||||||
for (; i < args.size(); i++)
|
for (; i < args.size(); i++)
|
||||||
lsArgs->Add(args[i]);
|
lsArgs->Add(args[i]);
|
||||||
cse->env->DeclareVariable(trimStart(argName), lsArgs);
|
cse->env->DeclareVariable(trimStart(argName), lsArgs);
|
||||||
@@ -2979,7 +2983,7 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
|
|||||||
throw VMException("Too many arguments");
|
throw VMException("Too many arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
current_function = cse;
|
GC::SetCurrentFunction(cse);
|
||||||
|
|
||||||
this->call_stack_entries.push_back(cse);
|
this->call_stack_entries.push_back(cse);
|
||||||
ls.GetGC()->BarrierEnd();
|
ls.GetGC()->BarrierEnd();
|
||||||
|
|||||||
Reference in New Issue
Block a user