Replace time-based GC with allocation-count trigger, migrate all Create factories to GCList::Create(), fix VFSPath root path, reorder TObject variant
Build and Deploy on Tag / 🔨 Build for PowerPC (push) Successful in 1m11s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-riscv64:latest, riscv64-linux-gnu, riscv64) (push) Successful in 3m22s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-x64:latest, x86_64-linux-gnu, amd64) (push) Successful in 3m34s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-arm:latest, arm-linux-gnueabihf, arm7) (push) Successful in 3m37s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-arm64:latest, aarch64-linux-gnu, arm64) (push) Successful in 3m39s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-x86:latest, i386-linux-gnu, 386) (push) Successful in 55s
Build and Deploy on Tag / update-tap (push) Failing after 4m8s
Build and Deploy on Tag / 🔨 Build for PowerPC (push) Successful in 1m11s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-riscv64:latest, riscv64-linux-gnu, riscv64) (push) Successful in 3m22s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-x64:latest, x86_64-linux-gnu, amd64) (push) Successful in 3m34s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-arm:latest, arm-linux-gnueabihf, arm7) (push) Successful in 3m37s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-arm64:latest, aarch64-linux-gnu, arm64) (push) Successful in 3m39s
Build and Deploy on Tag / 🔨 Build for everything else (git.tesses.org/tesses50/linux-x86:latest, i386-linux-gnu, 386) (push) Successful in 55s
Build and Deploy on Tag / update-tap (push) Failing after 4m8s
This commit is contained in:
+1
-1
@@ -44,7 +44,7 @@ void CrossArchiveCreate(
|
||||
strs.push_back("Console");
|
||||
strs.push_back("WriteLine");
|
||||
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;
|
||||
|
||||
|
||||
+118
-34
@@ -175,7 +175,7 @@ void CodeGen::WriteMetadataObject(std::vector<uint8_t> &bytes, SyntaxNode n) {
|
||||
std::vector<SyntaxNode> itms;
|
||||
if (asn.nodes.size() > 0)
|
||||
|
||||
GetFunctionArgs(itms, asn.nodes[0]);
|
||||
FlattenCommas(itms, asn.nodes[0]);
|
||||
bytes.push_back(7);
|
||||
size_t offset = bytes.size();
|
||||
bytes.resize(offset + 4);
|
||||
@@ -189,7 +189,7 @@ void CodeGen::WriteMetadataObject(std::vector<uint8_t> &bytes, SyntaxNode n) {
|
||||
std::vector<SyntaxNode> itms;
|
||||
if (asn.nodes.size() > 0)
|
||||
|
||||
GetFunctionArgs(itms, asn.nodes[0]);
|
||||
FlattenCommas(itms, asn.nodes[0]);
|
||||
bytes.push_back(8);
|
||||
size_t offset = bytes.size();
|
||||
bytes.resize(offset + 4);
|
||||
@@ -827,6 +827,8 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
size_t fnindex = this->chunks.size();
|
||||
ent.closure = (uint32_t)fnindex;
|
||||
this->chunks.resize(fnindex + 1);
|
||||
|
||||
std::vector<ByteCodeInstruction *> fnInstructions;
|
||||
auto &nameAndArgs =
|
||||
std::get<AdvancedSyntaxNode>(adv2.nodes[2]);
|
||||
if (nameAndArgs.nodeName == FunctionCallExpression &&
|
||||
@@ -844,14 +846,13 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
std::get<std::string>(getvar.nodes[0]));
|
||||
if (nameAndArgs.nodes.size() > 1) {
|
||||
GetFunctionArgs(ent.arguments,
|
||||
fnInstructions,
|
||||
nameAndArgs.nodes[1]);
|
||||
}
|
||||
} else
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<ByteCodeInstruction *> fnInstructions;
|
||||
|
||||
GenNode(fnInstructions, adv2.nodes[3], 0, -1, -1, -1,
|
||||
-1);
|
||||
|
||||
@@ -881,8 +882,8 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
ent.name = GetString(
|
||||
std::get<std::string>(getvar.nodes[0]));
|
||||
if (nameAndArgs.nodes.size() > 1) {
|
||||
GetFunctionArgs(ent.arguments,
|
||||
nameAndArgs.nodes[1]);
|
||||
FlattenCommas(ent.arguments,
|
||||
nameAndArgs.nodes[1]);
|
||||
}
|
||||
} else
|
||||
continue;
|
||||
@@ -1041,13 +1042,13 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
}
|
||||
if (item.first.second.nodeName == DefaultStatement) {
|
||||
if (!defaultJmp.empty())
|
||||
std::cout << "ERROR: multiple default in "
|
||||
"switch statement will cause "
|
||||
"undefined behaviour, this is not "
|
||||
"an exception due to not allowing "
|
||||
"exceptions in codegen stage (the "
|
||||
"compilation shouldn't fail)"
|
||||
<< std::endl;
|
||||
Tesses::Framework::Console::WriteLine(
|
||||
"ERROR: multiple default in "
|
||||
"switch statement will cause "
|
||||
"undefined behaviour, this is not "
|
||||
"an exception due to not allowing "
|
||||
"exceptions in codegen stage (the "
|
||||
"compilation shouldn't fail)");
|
||||
defaultJmp = item.first.first;
|
||||
}
|
||||
}
|
||||
@@ -1223,7 +1224,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
std::vector<SyntaxNode> itms;
|
||||
if (adv.nodes.size() > 0)
|
||||
|
||||
GetFunctionArgs(itms, adv.nodes[0]);
|
||||
FlattenCommas(itms, adv.nodes[0]);
|
||||
for (auto item : itms) {
|
||||
GenNode(instructions, item, scope, contscope, brkscope, contI,
|
||||
brkI);
|
||||
@@ -1233,7 +1234,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
instructions.push_back(new SimpleInstruction(CREATEDICTIONARY));
|
||||
std::vector<SyntaxNode> itms;
|
||||
if (adv.nodes.size() > 0)
|
||||
GetFunctionArgs(itms, adv.nodes[0]);
|
||||
FlattenCommas(itms, adv.nodes[0]);
|
||||
for (auto item : itms) {
|
||||
if (std::holds_alternative<AdvancedSyntaxNode>(item)) {
|
||||
auto tkn = std::get<AdvancedSyntaxNode>(item);
|
||||
@@ -1273,7 +1274,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
contI, brkI);
|
||||
if (adv.nodes.size() == 2) {
|
||||
std::vector<SyntaxNode> nodes;
|
||||
GetFunctionArgs(nodes, adv.nodes[1]);
|
||||
FlattenCommas(nodes, adv.nodes[1]);
|
||||
for (auto item : nodes)
|
||||
GenNode(instructions, item, scope, contscope, brkscope,
|
||||
contI, brkI);
|
||||
@@ -1288,7 +1289,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
contI, brkI);
|
||||
if (adv.nodes.size() == 2) {
|
||||
std::vector<SyntaxNode> nodes;
|
||||
GetFunctionArgs(nodes, adv.nodes[1]);
|
||||
FlattenCommas(nodes, adv.nodes[1]);
|
||||
for (auto item : nodes)
|
||||
GenNode(instructions, item, scope, contscope, brkscope,
|
||||
contI, brkI);
|
||||
@@ -1555,7 +1556,8 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
|
||||
} else if (adv.nodeName == ContinueStatement) {
|
||||
if (contscope == -1) {
|
||||
std::cout << "WARN: continue does nothing here\n";
|
||||
Tesses::Framework::Console::WriteLine(
|
||||
"WARN: continue does nothing here");
|
||||
} else if (contscope == -2) {
|
||||
instructions.push_back(new SimpleInstruction(PUSHCONTINUE));
|
||||
instructions.push_back(new SimpleInstruction(RET));
|
||||
@@ -1572,7 +1574,8 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
}
|
||||
} else if (adv.nodeName == BreakStatement) {
|
||||
if (brkscope == -1) {
|
||||
std::cout << "WARN: break does nothing here\n";
|
||||
Tesses::Framework::Console::WriteLine(
|
||||
"WARN: break does nothing here");
|
||||
} else if (brkscope == -2) {
|
||||
instructions.push_back(new SimpleInstruction(PUSHBREAK));
|
||||
instructions.push_back(new SimpleInstruction(RET));
|
||||
@@ -1978,7 +1981,7 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
//(a,b) => {}
|
||||
// it has two args
|
||||
std::vector<uint32_t> args;
|
||||
GetFunctionArgs(args, adv.nodes[0]);
|
||||
FlattenCommas(args, adv.nodes[0]);
|
||||
|
||||
std::vector<ByteCodeInstruction *> fnInstructions;
|
||||
size_t fnindex = this->chunks.size();
|
||||
@@ -2008,12 +2011,11 @@ void CodeGen::GenNode(std::vector<ByteCodeInstruction *> &instructions,
|
||||
// Name => {}
|
||||
//(a,b) => {}
|
||||
// it has two args
|
||||
std::vector<uint32_t> args;
|
||||
GetFunctionArgs(args, adv.nodes[0]);
|
||||
|
||||
std::vector<ByteCodeInstruction *> fnInstructions;
|
||||
size_t fnindex = this->chunks.size();
|
||||
this->chunks.resize(fnindex + 1);
|
||||
std::vector<uint32_t> args;
|
||||
GetFunctionArgs(args, fnInstructions, adv.nodes[0]);
|
||||
|
||||
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;
|
||||
if (std::holds_alternative<AdvancedSyntaxNode>(n) &&
|
||||
(sn = std::get<AdvancedSyntaxNode>(n)).nodeName == CommaExpression &&
|
||||
sn.nodes.size() == 2) {
|
||||
GetFunctionArgs(args, sn.nodes[0]);
|
||||
GetFunctionArgs(args, sn.nodes[1]);
|
||||
FlattenCommas(args, sn.nodes[0]);
|
||||
FlattenCommas(args, sn.nodes[1]);
|
||||
} else {
|
||||
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))
|
||||
return;
|
||||
|
||||
@@ -2079,10 +2083,90 @@ void CodeGen::GetFunctionArgs(std::vector<uint32_t> &name, SyntaxNode n) {
|
||||
auto res = std::get<AdvancedSyntaxNode>(n);
|
||||
if (res.nodeName == ParenthesesExpression) {
|
||||
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) {
|
||||
GetFunctionArgs(name, res.nodes[0]);
|
||||
GetFunctionArgs(name, res.nodes[1]);
|
||||
GetFunctionArgs(name, instrs, res.nodes[0]);
|
||||
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 &&
|
||||
res.nodes.size() == 1) {
|
||||
if (std::holds_alternative<std::string>(res.nodes[0])) {
|
||||
@@ -2175,14 +2259,14 @@ void CodeGen::GenRoot(SyntaxNode n) {
|
||||
functionName.insert(
|
||||
functionName.begin(),
|
||||
{GetString(documentation)});
|
||||
if (fcalli.nodes.size() == 2)
|
||||
GetFunctionArgs(args,
|
||||
fcalli.nodes[1]);
|
||||
|
||||
std::vector<ByteCodeInstruction *>
|
||||
fnInstructions;
|
||||
size_t fnindex = this->chunks.size();
|
||||
this->chunks.resize(fnindex + 1);
|
||||
if (fcalli.nodes.size() == 2)
|
||||
GetFunctionArgs(args,
|
||||
fnInstructions,
|
||||
fcalli.nodes[1]);
|
||||
|
||||
GenNode(fnInstructions, res2.nodes[1],
|
||||
0, -1, -1, -1, -1);
|
||||
|
||||
@@ -482,6 +482,7 @@ int Lex(std::string filename, std::istream &strm,
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
case '>':
|
||||
case '?':
|
||||
if (peek == read) {
|
||||
Flush();
|
||||
@@ -532,7 +533,6 @@ int Lex(std::string filename, std::istream &strm,
|
||||
case '^':
|
||||
case '~':
|
||||
case '!':
|
||||
case '>':
|
||||
case '*':
|
||||
case '%':
|
||||
//*
|
||||
|
||||
+14
-153
@@ -115,58 +115,16 @@ bool Parser::IsIdentifier(std::string txt, bool pop) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Parser::IsAnySymbol(std::initializer_list<std::string> idents, bool pop) {
|
||||
|
||||
if (i < tokens.size()) {
|
||||
if (tokens[i].type != LexTokenType::Symbol)
|
||||
return false;
|
||||
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) {
|
||||
tkn = tokens[i];
|
||||
if (pop)
|
||||
i++;
|
||||
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;
|
||||
}
|
||||
if (item == tokens[i].text) {
|
||||
tkn = tokens[i];
|
||||
if (pop)
|
||||
i++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -176,45 +134,7 @@ bool Parser::IsSymbol(std::string txt, bool pop) {
|
||||
if (i < tokens.size()) {
|
||||
if (tokens[i].type != LexTokenType::Symbol)
|
||||
return false;
|
||||
if (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) {
|
||||
if (tokens[i].text == txt) {
|
||||
tkn = tokens[i];
|
||||
if (pop)
|
||||
i++;
|
||||
@@ -233,7 +153,6 @@ static std::string EnsureSafeVariable(LexToken token) {
|
||||
}
|
||||
void Parser::EnsureSymbol(std::string txt) {
|
||||
if (i < tokens.size()) {
|
||||
|
||||
if (tokens[i].type != LexTokenType::Symbol) {
|
||||
throw SyntaxException(
|
||||
tokens[i].lineInfo,
|
||||
@@ -241,69 +160,7 @@ void Parser::EnsureSymbol(std::string txt) {
|
||||
LexTokenType_ToString(tokens[i].type) + " \"" +
|
||||
tokens[i].text + "\" which is not a symbol at all.");
|
||||
}
|
||||
if (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) {
|
||||
if (tokens[i].text != txt) {
|
||||
|
||||
throw SyntaxException(tokens[i].lineInfo,
|
||||
"expected the symbol \"" + txt +
|
||||
@@ -633,6 +490,11 @@ void Parser::ParseHtml(std::vector<SyntaxNode> &nodes, std::string var) {
|
||||
EnsureSymbol(")");
|
||||
EnsureSymbol(">");
|
||||
|
||||
if (std::holds_alternative<std::nullptr_t>(item))
|
||||
item = AdvancedSyntaxNode::Create(
|
||||
DeclareExpression, true,
|
||||
{"item"});
|
||||
|
||||
std::vector<SyntaxNode> _nodes;
|
||||
parseFn(_nodes, "each");
|
||||
body = AdvancedSyntaxNode::Create(ScopeNode, false, _nodes);
|
||||
@@ -1411,7 +1273,7 @@ SyntaxNode Parser::ParseNode(bool isRoot) {
|
||||
}
|
||||
|
||||
if (!isRoot)
|
||||
i++;
|
||||
EnsureSymbol("}");
|
||||
return aSN;
|
||||
}
|
||||
|
||||
@@ -1519,8 +1381,7 @@ SyntaxNode Parser::ParseNode(bool isRoot) {
|
||||
if (std::holds_alternative<std::nullptr_t>(item))
|
||||
item = AdvancedSyntaxNode::Create(
|
||||
DeclareExpression, true,
|
||||
{AdvancedSyntaxNode::Create(GetVariableExpression, true,
|
||||
{"item"})});
|
||||
{"item"});
|
||||
|
||||
return AdvancedSyntaxNode::Create(EachStatement, false,
|
||||
{item, list, body});
|
||||
|
||||
@@ -16,7 +16,7 @@ static void Help(std::string &filename) {
|
||||
printf(" -n: Set name (MyAppOrLibName defaults to out)\n");
|
||||
printf(" -h, --help: Prints help\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) {
|
||||
@@ -53,7 +53,7 @@ int64_t CrossArchiveCreate(std::vector<std::string> &argv) {
|
||||
printf("Expected "
|
||||
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]"
|
||||
"]]]\n");
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -27,7 +27,7 @@ static void Help(std::string filename) {
|
||||
"for sane with file access to current directory and sub "
|
||||
"directories, \"full\" has full runtime.\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) {
|
||||
/*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 "
|
||||
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-"
|
||||
"prod]]]]\n");
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
dependencies.push_back(
|
||||
std::pair<std::string, TVMVersion>(str1, v2));
|
||||
|
||||
} else {
|
||||
printf("ERROR: Dependency must have version\n");
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
} else if (argv[i] == "-t") {
|
||||
@@ -137,14 +137,14 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
|
||||
printf("Expected "
|
||||
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-"
|
||||
"prod]]]]\n");
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
tools.push_back(
|
||||
std::pair<std::string, TVMVersion>(str1, v2));
|
||||
|
||||
} else {
|
||||
printf("ERROR: Tool must have version\n");
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
} else if (argv[i] == "-n") {
|
||||
@@ -161,7 +161,7 @@ void CrossLangCompiler(std::vector<std::string> &argv) {
|
||||
printf("Expected "
|
||||
"MAJOR[.MINOR[.PATCH[.BUILD[-dev,-alpha,-beta,-prod]"
|
||||
"]]]\n");
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
} else if (argv[i] == "-D" || argv[i] == "--debug") {
|
||||
|
||||
@@ -72,11 +72,11 @@ TObject Console_Write(GCList &ls, std::vector<TObject> args) {
|
||||
TObject Console_Fatal(GCList &ls, std::vector<TObject> args) {
|
||||
if (args.size() < 1) {
|
||||
Tesses::Framework::Console::ErrorLine("FATAL: <NO MESSAGE>");
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
Tesses::Framework::Console::ErrorLine("FATAL: " +
|
||||
ToString(ls.GetGC(), args[0]));
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
TObject Console_WriteLine(GCList &ls, std::vector<TObject> args) {
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ static TObject JsonDocDecode(GCList &ls2, std::vector<TObject> args) {
|
||||
std::string Json_Encode(TObject o, bool 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));
|
||||
}
|
||||
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 "";
|
||||
}
|
||||
TObject Json_DocDecode(GCList ls, std::string str) {
|
||||
TObject Json_DocDecode(GCList &ls, std::string str) {
|
||||
return JsonDeserialize(ls, Json::DocDecode(str));
|
||||
}
|
||||
void TStd::RegisterJson(std::shared_ptr<GC> gc, TRootEnvironment *env) {
|
||||
|
||||
+59
-18
@@ -150,6 +150,46 @@ class THttpDictionary : public TNativeObject {
|
||||
value);
|
||||
}
|
||||
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") {
|
||||
TList *_ls = TList::Create(ls);
|
||||
for (auto item : dict->kvp) {
|
||||
@@ -239,6 +279,9 @@ class TServerContext : public TNativeObjectThatReturnsHttpDictionary {
|
||||
else if (key == "getQueryParams")
|
||||
return TNativeObject::Create<THttpDictionary>(ls, &ctx->queryParams,
|
||||
this);
|
||||
else if (key == "getBodyParams")
|
||||
return TNativeObject::Create<THttpDictionary>(ls, &ctx->bodyParams,
|
||||
this);
|
||||
else if (key == "getRequestHeaders")
|
||||
return TNativeObject::Create<THttpDictionary>(
|
||||
ls, &ctx->requestHeaders, this);
|
||||
@@ -781,17 +824,19 @@ static TObject Net_Http_MimeType(GCList &ls, std::vector<TObject> args) {
|
||||
Tesses::Framework::Filesystem::VFSPath p;
|
||||
if (GetArgumentAsPath(args, 0, p)) {
|
||||
std::filesystem::path p2 = p.GetFileName();
|
||||
return HttpUtils::MimeType(p2);
|
||||
return HttpUtils::GetMimeType(p2);
|
||||
}
|
||||
return std::string("application/octet-stream");
|
||||
}
|
||||
class THttpRequestBody : public TNativeObject {
|
||||
HttpRequestBody *body;
|
||||
std::shared_ptr<HttpRequestBody> body;
|
||||
|
||||
public:
|
||||
THttpRequestBody(HttpRequestBody *body) { this->body = body; }
|
||||
THttpRequestBody(std::shared_ptr<HttpRequestBody> body) {
|
||||
this->body = body;
|
||||
}
|
||||
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"; }
|
||||
|
||||
@@ -799,10 +844,7 @@ class THttpRequestBody : public TNativeObject {
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
void Close() {
|
||||
delete this->body;
|
||||
this->body = nullptr;
|
||||
}
|
||||
void Close() { this->body = nullptr; }
|
||||
};
|
||||
|
||||
class THttpResponse : public TNativeObjectThatReturnsHttpDictionary {
|
||||
@@ -907,7 +949,8 @@ static TObject Net_Http_MakeRequest(GCList &ls, std::vector<TObject> args,
|
||||
_obj = options->GetValue("Body");
|
||||
|
||||
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()) {
|
||||
req.body = body2->GetBody();
|
||||
}
|
||||
@@ -920,8 +963,6 @@ static TObject Net_Http_MakeRequest(GCList &ls, std::vector<TObject> args,
|
||||
if (req.body != nullptr) {
|
||||
if (body2 != nullptr) {
|
||||
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) &&
|
||||
GetArgumentHeap(args, 2, dict)) {
|
||||
GetArgumentHeap(args, 3, callable);
|
||||
HttpDictionary hdict;
|
||||
HttpDictionary hdict(false);
|
||||
for (int64_t index = 0; index < headers->Count(); index++) {
|
||||
_obj = headers->Get(index);
|
||||
TDictionary *dict;
|
||||
@@ -1171,7 +1212,7 @@ static TObject Net_Http_WebSocketClient(GCList &ls, std::vector<TObject> args) {
|
||||
if (!GetObjectHeap(hobj, headers))
|
||||
return Undefined();
|
||||
|
||||
HttpDictionary hdict;
|
||||
HttpDictionary hdict(false);
|
||||
for (int64_t index = 0; index < headers->Count(); index++) {
|
||||
_obj = headers->Get(index);
|
||||
TDictionary *dict;
|
||||
@@ -1381,7 +1422,7 @@ static TObject New_StreamHttpRequestBody(GCList &ls,
|
||||
|
||||
if (GetArgument(args, 0, strm) && GetArgument(args, 1, mimeType)) {
|
||||
return TNativeObject::Create<THttpRequestBody>(
|
||||
ls, new StreamHttpRequestBody(strm, mimeType));
|
||||
ls, std::make_shared<StreamHttpRequestBody>(strm, mimeType));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1390,7 +1431,7 @@ static TObject New_TextHttpRequestBody(GCList &ls, std::vector<TObject> args) {
|
||||
std::string mimeType;
|
||||
if (GetArgument(args, 0, text) && GetArgument(args, 1, mimeType)) {
|
||||
return TNativeObject::Create<THttpRequestBody>(
|
||||
ls, new TextHttpRequestBody(text, mimeType));
|
||||
ls, std::make_shared<TextHttpRequestBody>(text, mimeType));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1398,8 +1439,8 @@ static TObject New_JsonHttpRequestBody(GCList &ls, std::vector<TObject> args) {
|
||||
|
||||
if (!args.empty()) {
|
||||
return TNativeObject::Create<THttpRequestBody>(
|
||||
ls,
|
||||
new TextHttpRequestBody(Json_Encode(args[0]), "application/json"));
|
||||
ls, std::make_shared<TextHttpRequestBody>(Json_Encode(args[0]),
|
||||
"application/json"));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1423,7 +1464,7 @@ void TStd::RegisterNet(std::shared_ptr<GC> gc, TRootEnvironment *env) {
|
||||
"Create a text request body", {"text", "mimeType"},
|
||||
New_TextHttpRequestBody);
|
||||
_new->DeclareFunction(gc, "JsonHttpRequestBody",
|
||||
"Create a text request body", {"json"},
|
||||
"Create a json request body", {"json"},
|
||||
New_JsonHttpRequestBody);
|
||||
_new->DeclareFunction(
|
||||
gc, "HttpServer", "Create a http server (allows multiple)",
|
||||
|
||||
@@ -3,10 +3,6 @@
|
||||
namespace Tesses::CrossLang {
|
||||
class ProcessObject : public TNativeObject {
|
||||
public:
|
||||
ProcessObject() {
|
||||
arguments = nullptr;
|
||||
environment = nullptr;
|
||||
}
|
||||
ProcessObject(GCList &ls) {
|
||||
arguments = TList::Create(ls);
|
||||
environment = TList::Create(ls);
|
||||
@@ -167,7 +163,7 @@ static TObject Process_Start(GCList &ls, std::vector<TObject> args,
|
||||
TDictionary *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 inh = dict->GetValue("InheritParentEnvironment");
|
||||
auto rStdIn = dict->GetValue("RedirectStandardInput");
|
||||
|
||||
@@ -1613,7 +1613,13 @@ void TStd::RegisterStd(
|
||||
gc_dict->DeclareFunction(
|
||||
gc, "Collect", "Collect garbage", {},
|
||||
[](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;
|
||||
});
|
||||
gc_dict->DeclareFunction(
|
||||
|
||||
@@ -67,6 +67,8 @@ static TObject VM_SourceToAst(GCList &ls, std::vector<TObject> args) {
|
||||
static TObject VM_Eval(GCList &ls, std::vector<TObject> args) {
|
||||
std::string str;
|
||||
if (GetArgument(args, 0, str)) {
|
||||
|
||||
auto current_function = GC::GetCurrentFunction();
|
||||
if (current_function != nullptr) {
|
||||
return current_function->env->Eval(ls, str);
|
||||
}
|
||||
@@ -90,6 +92,8 @@ static TObject Success(GCList &ls) {
|
||||
}
|
||||
static TObject VM_getCurrentEnvironment(GCList &ls2,
|
||||
std::vector<TObject> args) {
|
||||
|
||||
auto current_function = GC::GetCurrentFunction();
|
||||
if (current_function != nullptr)
|
||||
return current_function->env;
|
||||
return Undefined();
|
||||
@@ -261,6 +265,7 @@ static TObject VM_Compile(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->thread != nullptr) {
|
||||
TList *list = TList::Create(ls);
|
||||
|
||||
+2
-16
@@ -1,22 +1,8 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
TAny *TAny::Create(GCList &ls) {
|
||||
TAny *anyObj = new 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;
|
||||
}
|
||||
TAny *TAny::Create(GCList &ls) { return ls.Create<TAny>(); }
|
||||
TAny *TAny::Create(GCList *ls) { return ls->Create<TAny>(); }
|
||||
void TAny::Mark() {
|
||||
if (this->marked)
|
||||
return;
|
||||
|
||||
@@ -3,18 +3,10 @@
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
TAssociativeArray *TAssociativeArray::Create(GCList &ls) {
|
||||
TAssociativeArray *list = new TAssociativeArray();
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(list);
|
||||
_gc->Watch(list);
|
||||
return list;
|
||||
return ls.Create<TAssociativeArray>();
|
||||
}
|
||||
TAssociativeArray *TAssociativeArray::Create(GCList *ls) {
|
||||
TAssociativeArray *list = new TAssociativeArray();
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(list);
|
||||
_gc->Watch(list);
|
||||
return list;
|
||||
return ls->Create<TAssociativeArray>();
|
||||
}
|
||||
void TAssociativeArray::Set(std::shared_ptr<GC> gc, TObject key,
|
||||
TObject value) {
|
||||
|
||||
@@ -9,22 +9,12 @@ bool TClassEnvironment::HasConstForSet(std::string key) {
|
||||
TClassEnvironment *TClassEnvironment::Create(GCList *gc, TEnvironment *env,
|
||||
TClassObject *obj) {
|
||||
|
||||
TClassEnvironment *env2 = new TClassEnvironment(env, obj);
|
||||
|
||||
std::shared_ptr<GC> _gc = gc->GetGC();
|
||||
gc->Add(env2);
|
||||
_gc->Watch(env2);
|
||||
return env2;
|
||||
return gc->Create<TClassEnvironment>(env, obj);
|
||||
}
|
||||
TClassEnvironment *TClassEnvironment::Create(GCList &gc, TEnvironment *env,
|
||||
TClassObject *obj) {
|
||||
|
||||
TClassEnvironment *env2 = new TClassEnvironment(env, obj);
|
||||
|
||||
std::shared_ptr<GC> _gc = gc.GetGC();
|
||||
gc.Add(env2);
|
||||
_gc->Watch(env2);
|
||||
return env2;
|
||||
return gc.Create<TClassEnvironment>(env, obj);
|
||||
}
|
||||
TClassEnvironment::TClassEnvironment(TEnvironment *env, TClassObject *obj) {
|
||||
this->env = env;
|
||||
@@ -33,6 +23,7 @@ TClassEnvironment::TClassEnvironment(TEnvironment *env, TClassObject *obj) {
|
||||
bool TClassEnvironment::HasVariable(std::string key) {
|
||||
if (key == "this")
|
||||
return true;
|
||||
auto current_function = GC::GetCurrentFunction();
|
||||
if (this->clsObj->HasValue(current_function == nullptr
|
||||
? ""
|
||||
: current_function->callable->className,
|
||||
@@ -49,6 +40,8 @@ bool TClassEnvironment::HasVariableOrFieldRecurse(std::string key,
|
||||
bool setting) {
|
||||
if (key == "this")
|
||||
return true;
|
||||
|
||||
auto current_function = GC::GetCurrentFunction();
|
||||
std::string clsName = current_function == nullptr
|
||||
? ""
|
||||
: current_function->callable->className;
|
||||
@@ -63,6 +56,7 @@ TObject TClassEnvironment::GetVariable(std::string key) {
|
||||
if (key == "this")
|
||||
return this->clsObj;
|
||||
|
||||
auto current_function = GC::GetCurrentFunction();
|
||||
std::string clsName = current_function == nullptr
|
||||
? ""
|
||||
: current_function->callable->className;
|
||||
@@ -75,6 +69,7 @@ void TClassEnvironment::SetVariable(std::string key, TObject value) {
|
||||
if (key == "this")
|
||||
return;
|
||||
|
||||
auto current_function = GC::GetCurrentFunction();
|
||||
std::string clsName = current_function == nullptr
|
||||
? ""
|
||||
: current_function->callable->className;
|
||||
@@ -90,6 +85,7 @@ TObject TClassEnvironment::GetVariable(GCList &ls, std::string key) {
|
||||
if (key == "this")
|
||||
return this->clsObj;
|
||||
|
||||
auto current_function = GC::GetCurrentFunction();
|
||||
std::string clsName = current_function == nullptr
|
||||
? ""
|
||||
: current_function->callable->className;
|
||||
@@ -107,6 +103,7 @@ TObject TClassEnvironment::SetVariable(GCList &ls, std::string key, TObject v) {
|
||||
if (key == "this")
|
||||
return this->clsObj;
|
||||
|
||||
auto current_function = GC::GetCurrentFunction();
|
||||
std::string clsName = current_function == nullptr
|
||||
? ""
|
||||
: current_function->callable->className;
|
||||
|
||||
+23
-45
@@ -1,27 +1,18 @@
|
||||
#include "CrossLang.hpp"
|
||||
namespace Tesses::CrossLang {
|
||||
TArgWrapper::TArgWrapper(TCallable *callable) : callable(callable) {}
|
||||
TArgWrapper *TArgWrapper::Create(GCList &ls, TCallable *callable) {
|
||||
TArgWrapper *argWrapper = new TArgWrapper();
|
||||
argWrapper->callable = callable;
|
||||
std::shared_ptr<GC> gc = ls.GetGC();
|
||||
ls.Add(argWrapper);
|
||||
gc->Watch(argWrapper);
|
||||
return argWrapper;
|
||||
return ls.Create<TArgWrapper>(callable);
|
||||
}
|
||||
TArgWrapper *TArgWrapper::Create(GCList *ls, TCallable *callable) {
|
||||
TArgWrapper *argWrapper = new TArgWrapper();
|
||||
argWrapper->callable = callable;
|
||||
std::shared_ptr<GC> gc = ls->GetGC();
|
||||
ls->Add(argWrapper);
|
||||
gc->Watch(argWrapper);
|
||||
return argWrapper;
|
||||
return ls->Create<TArgWrapper>(callable);
|
||||
}
|
||||
TObject TArgWrapper::Call(GCList &ls, std::vector<TObject> args) {
|
||||
auto cse = current_function;
|
||||
auto cse = GC::GetCurrentFunction();
|
||||
TList *argList = TList::Create(ls);
|
||||
argList->items = args;
|
||||
TObject v = this->callable->Call(ls, {argList});
|
||||
current_function = cse;
|
||||
GC::SetCurrentFunction(cse);
|
||||
return v;
|
||||
}
|
||||
void TArgWrapper::Mark() {
|
||||
@@ -46,52 +37,39 @@ void TClosure::Mark() {
|
||||
this->closure->Mark();
|
||||
GC::Mark(this->tag);
|
||||
}
|
||||
TClosure *TClosure::Create(GCList &ls, TEnvironment *env, TFile *file,
|
||||
uint32_t chunkId, bool ownScope) {
|
||||
TClosure *closure = new TClosure();
|
||||
closure->className = "";
|
||||
closure->ownScope = ownScope;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(closure);
|
||||
_gc->Watch(closure);
|
||||
closure->chunkId = chunkId;
|
||||
TClosure::TClosure(TEnvironment *env, TFile *file, uint32_t chunkId,
|
||||
bool ownScope) {
|
||||
this->className = "";
|
||||
this->ownScope = ownScope;
|
||||
|
||||
this->chunkId = chunkId;
|
||||
|
||||
if (chunkId < file->chunks.size())
|
||||
closure->closure = file->chunks[chunkId];
|
||||
this->closure = file->chunks[chunkId];
|
||||
else
|
||||
throw VMException("ChunkId out of bounds.");
|
||||
closure->env = env;
|
||||
closure->file = file;
|
||||
|
||||
return closure;
|
||||
this->env = env;
|
||||
this->file = file;
|
||||
}
|
||||
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,
|
||||
uint32_t chunkId, bool ownScope) {
|
||||
TClosure *closure = new TClosure();
|
||||
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;
|
||||
return ls->Create<TClosure>(env, file, chunkId, ownScope);
|
||||
}
|
||||
|
||||
TObject TClosure::Call(GCList &ls, std::vector<TObject> args) {
|
||||
auto cse = current_function;
|
||||
auto cse = GC::GetCurrentFunction();
|
||||
InterperterThread *thrd = InterperterThread::Create(ls);
|
||||
thrd->AddCallStackEntry(ls, this, args);
|
||||
|
||||
thrd->Execute(ls.GetGC());
|
||||
|
||||
TObject v = thrd->call_stack_entries[0]->Pop(ls);
|
||||
current_function = cse;
|
||||
GC::SetCurrentFunction(cse);
|
||||
// current_function = cse;
|
||||
return v;
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
@@ -1,24 +1,15 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
TDynamicDictionary::TDynamicDictionary(TCallable *callable) : cb(callable) {}
|
||||
TDynamicDictionary *TDynamicDictionary::Create(GCList &ls,
|
||||
TCallable *callable) {
|
||||
|
||||
TDynamicDictionary *dict = new TDynamicDictionary();
|
||||
dict->cb = callable;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(dict);
|
||||
_gc->Watch(dict);
|
||||
return dict;
|
||||
return ls.Create<TDynamicDictionary>(callable);
|
||||
}
|
||||
TDynamicDictionary *TDynamicDictionary::Create(GCList *ls,
|
||||
TCallable *callable) {
|
||||
TDynamicDictionary *dict = new TDynamicDictionary();
|
||||
dict->cb = callable;
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(dict);
|
||||
_gc->Watch(dict);
|
||||
return dict;
|
||||
return ls->Create<TDynamicDictionary>(callable);
|
||||
}
|
||||
|
||||
void TDynamicDictionary::Mark() {
|
||||
@@ -165,8 +156,9 @@ void TDictionary::DeclareFunction(
|
||||
TObject TDictionary::GetValue(std::string key) {
|
||||
if (this->items.empty())
|
||||
return Undefined();
|
||||
if (this->items.count(key) > 0)
|
||||
return this->items[key];
|
||||
auto item = this->items.find(key);
|
||||
if (item != this->items.end())
|
||||
return item->second;
|
||||
return Undefined();
|
||||
}
|
||||
void TDictionary::SetValue(std::string key, TObject value) {
|
||||
@@ -189,18 +181,10 @@ void TDictionary::Mark() {
|
||||
}
|
||||
}
|
||||
TDictionary *TDictionary::Create(GCList *gc) {
|
||||
TDictionary *dict = new TDictionary();
|
||||
std::shared_ptr<GC> _gc = gc->GetGC();
|
||||
gc->Add(dict);
|
||||
_gc->Watch(dict);
|
||||
return dict;
|
||||
return gc->Create<TDictionary>();
|
||||
}
|
||||
TDictionary *TDictionary::Create(GCList &gc) {
|
||||
TDictionary *dict = new TDictionary();
|
||||
std::shared_ptr<GC> _gc = gc.GetGC();
|
||||
gc.Add(dict);
|
||||
_gc->Watch(dict);
|
||||
return dict;
|
||||
return gc.Create<TDictionary>();
|
||||
}
|
||||
|
||||
}; // 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"
|
||||
namespace Tesses::CrossLang {
|
||||
TExternalMethod::TExternalMethod(
|
||||
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
|
||||
std::string documentation, std::vector<std::string> argNames,
|
||||
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
|
||||
std::function<void()> destroy) {
|
||||
|
||||
this->cb = cb;
|
||||
@@ -14,43 +14,24 @@ TExternalMethod *TExternalMethod::Create(
|
||||
GCList &ls, std::string documentation, std::vector<std::string> argNames,
|
||||
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
|
||||
std::function<void()> destroy) {
|
||||
auto gc = ls.GetGC();
|
||||
TExternalMethod *method =
|
||||
new TExternalMethod(cb, documentation, argNames, destroy);
|
||||
ls.Add(method);
|
||||
gc->Watch(method);
|
||||
return method;
|
||||
return ls.Create<TExternalMethod>(documentation, argNames, cb, destroy);
|
||||
}
|
||||
TExternalMethod *TExternalMethod::Create(
|
||||
GCList *ls, std::string documentation, std::vector<std::string> argNames,
|
||||
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb,
|
||||
std::function<void()> destroy) {
|
||||
auto gc = ls->GetGC();
|
||||
TExternalMethod *method =
|
||||
new TExternalMethod(cb, documentation, argNames, destroy);
|
||||
ls->Add(method);
|
||||
gc->Watch(method);
|
||||
return method;
|
||||
return ls->Create<TExternalMethod>(documentation, argNames, cb, destroy);
|
||||
}
|
||||
TExternalMethod *TExternalMethod::Create(
|
||||
GCList &ls, std::string documentation, std::vector<std::string> argNames,
|
||||
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb) {
|
||||
auto gc = ls.GetGC();
|
||||
TExternalMethod *method =
|
||||
new TExternalMethod(cb, documentation, argNames, []() -> void {});
|
||||
ls.Add(method);
|
||||
gc->Watch(method);
|
||||
return method;
|
||||
return ls.Create<TExternalMethod>(documentation, argNames, cb);
|
||||
}
|
||||
TExternalMethod *TExternalMethod::Create(
|
||||
GCList *ls, std::string documentation, std::vector<std::string> argNames,
|
||||
std::function<TObject(GCList &ls, std::vector<TObject> args)> cb) {
|
||||
auto gc = ls->GetGC();
|
||||
TExternalMethod *method =
|
||||
new TExternalMethod(cb, documentation, argNames, []() -> void {});
|
||||
ls->Add(method);
|
||||
gc->Watch(method);
|
||||
return method;
|
||||
|
||||
return ls->Create<TExternalMethod>(documentation, argNames, cb);
|
||||
}
|
||||
TObject TExternalMethod::Call(GCList &ls, std::vector<TObject> args) {
|
||||
if (cb == nullptr)
|
||||
|
||||
+35
-114
@@ -44,28 +44,15 @@ void TYieldEnumerator::Mark() {
|
||||
GC::Mark(this->current);
|
||||
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();
|
||||
ls.Add(yieldEnum);
|
||||
_gc->Watch(yieldEnum);
|
||||
return yieldEnum;
|
||||
TYieldEnumerator::TYieldEnumerator(TObject v)
|
||||
: current(nullptr), hasStarted(false), enumerator(v) {}
|
||||
|
||||
TYieldEnumerator *TYieldEnumerator::Create(GCList &ls, TObject v) {
|
||||
return ls.Create<TYieldEnumerator>(v);
|
||||
}
|
||||
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();
|
||||
ls->Add(yieldEnum);
|
||||
_gc->Watch(yieldEnum);
|
||||
return yieldEnum;
|
||||
return ls->Create<TYieldEnumerator>(v);
|
||||
}
|
||||
|
||||
bool TCustomEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||
@@ -97,21 +84,12 @@ void TCustomEnumerator::Mark() {
|
||||
return;
|
||||
this->dict->Mark();
|
||||
}
|
||||
TCustomEnumerator::TCustomEnumerator(TDictionary *dict) : dict(dict) {}
|
||||
TCustomEnumerator *TCustomEnumerator::Create(GCList *ls, TDictionary *dict) {
|
||||
TCustomEnumerator *customEnum = new TCustomEnumerator();
|
||||
customEnum->dict = dict;
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(customEnum);
|
||||
_gc->Watch(customEnum);
|
||||
return customEnum;
|
||||
return ls->Create<TCustomEnumerator>(dict);
|
||||
}
|
||||
TCustomEnumerator *TCustomEnumerator::Create(GCList &ls, TDictionary *dict) {
|
||||
TCustomEnumerator *customEnum = new TCustomEnumerator();
|
||||
customEnum->dict = dict;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(customEnum);
|
||||
_gc->Watch(customEnum);
|
||||
return customEnum;
|
||||
return ls.Create<TCustomEnumerator>(dict);
|
||||
}
|
||||
TEnumerator *TEnumerator::CreateFromObject(GCList &ls, TObject obj) {
|
||||
std::string str;
|
||||
@@ -141,23 +119,16 @@ TEnumerator *TEnumerator::CreateFromObject(GCList &ls, TObject obj) {
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
TVFSPathEnumerator::TVFSPathEnumerator(
|
||||
Tesses::Framework::Filesystem::VFSPathEnumerator enumerator)
|
||||
: enumerator(enumerator) {}
|
||||
TVFSPathEnumerator *TVFSPathEnumerator::Create(
|
||||
GCList &ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) {
|
||||
TVFSPathEnumerator *vfspathe = new TVFSPathEnumerator();
|
||||
vfspathe->enumerator = enumerator;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(vfspathe);
|
||||
_gc->Watch(vfspathe);
|
||||
return vfspathe;
|
||||
return ls.Create<TVFSPathEnumerator>(enumerator);
|
||||
}
|
||||
TVFSPathEnumerator *TVFSPathEnumerator::Create(
|
||||
GCList *ls, Tesses::Framework::Filesystem::VFSPathEnumerator enumerator) {
|
||||
TVFSPathEnumerator *vfspathe = new TVFSPathEnumerator();
|
||||
vfspathe->enumerator = enumerator;
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(vfspathe);
|
||||
_gc->Watch(vfspathe);
|
||||
return vfspathe;
|
||||
return ls->Create<TVFSPathEnumerator>(enumerator);
|
||||
}
|
||||
bool TVFSPathEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||
return enumerator.MoveNext();
|
||||
@@ -165,25 +136,15 @@ bool TVFSPathEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||
TObject TVFSPathEnumerator::GetCurrent(GCList &ls) {
|
||||
return enumerator.Current;
|
||||
}
|
||||
TDictionaryEnumerator::TDictionaryEnumerator(TDictionary *dict)
|
||||
: dict(dict), hasStarted(false) {}
|
||||
TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList &ls,
|
||||
TDictionary *dict) {
|
||||
TDictionaryEnumerator *dicte = new TDictionaryEnumerator();
|
||||
dicte->dict = dict;
|
||||
dicte->hasStarted = false;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(dicte);
|
||||
_gc->Watch(dicte);
|
||||
return dicte;
|
||||
return ls.Create<TDictionaryEnumerator>(dict);
|
||||
}
|
||||
TDictionaryEnumerator *TDictionaryEnumerator::Create(GCList *ls,
|
||||
TDictionary *dict) {
|
||||
TDictionaryEnumerator *dicte = new TDictionaryEnumerator();
|
||||
dicte->dict = dict;
|
||||
dicte->hasStarted = false;
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(dicte);
|
||||
_gc->Watch(dicte);
|
||||
return dicte;
|
||||
return ls->Create<TDictionaryEnumerator>(dict);
|
||||
}
|
||||
|
||||
bool TDictionaryEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||
@@ -217,24 +178,13 @@ void TDictionaryEnumerator::Mark() {
|
||||
this->marked = true;
|
||||
this->dict->Mark();
|
||||
}
|
||||
TListEnumerator::TListEnumerator(TList *list) : ls(list), index(-1) {}
|
||||
|
||||
TListEnumerator *TListEnumerator::Create(GCList &ls, TList *list) {
|
||||
TListEnumerator *liste = new TListEnumerator();
|
||||
liste->ls = list;
|
||||
liste->index = -1;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(liste);
|
||||
_gc->Watch(liste);
|
||||
return liste;
|
||||
return ls.Create<TListEnumerator>(list);
|
||||
}
|
||||
TListEnumerator *TListEnumerator::Create(GCList *ls, TList *list) {
|
||||
TListEnumerator *liste = new TListEnumerator();
|
||||
liste->ls = list;
|
||||
liste->index = -1;
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(liste);
|
||||
_gc->Watch(liste);
|
||||
return liste;
|
||||
return ls->Create<TListEnumerator>(list);
|
||||
}
|
||||
bool TListEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||
this->index++;
|
||||
@@ -260,25 +210,17 @@ void TListEnumerator::Mark() {
|
||||
this->ls->Mark();
|
||||
}
|
||||
|
||||
TAssociativeArrayEnumerator::TAssociativeArrayEnumerator(
|
||||
TAssociativeArray *list)
|
||||
: ls(list), index(-1) {}
|
||||
|
||||
TAssociativeArrayEnumerator *
|
||||
TAssociativeArrayEnumerator::Create(GCList &ls, TAssociativeArray *list) {
|
||||
TAssociativeArrayEnumerator *liste = new TAssociativeArrayEnumerator();
|
||||
liste->ls = list;
|
||||
liste->index = -1;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(liste);
|
||||
_gc->Watch(liste);
|
||||
return liste;
|
||||
return ls.Create<TAssociativeArrayEnumerator>(list);
|
||||
}
|
||||
TAssociativeArrayEnumerator *
|
||||
TAssociativeArrayEnumerator::Create(GCList *ls, TAssociativeArray *list) {
|
||||
TAssociativeArrayEnumerator *liste = new TAssociativeArrayEnumerator();
|
||||
liste->ls = list;
|
||||
liste->index = -1;
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(liste);
|
||||
_gc->Watch(liste);
|
||||
return liste;
|
||||
return ls->Create<TAssociativeArrayEnumerator>(list);
|
||||
}
|
||||
bool TAssociativeArrayEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||
this->index++;
|
||||
@@ -305,26 +247,16 @@ void TAssociativeArrayEnumerator::Mark() {
|
||||
this->marked = true;
|
||||
this->ls->Mark();
|
||||
}
|
||||
TDynamicListEnumerator::TDynamicListEnumerator(TDynamicList *list)
|
||||
: ls(list), index(-1) {}
|
||||
|
||||
TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList &ls,
|
||||
TDynamicList *list) {
|
||||
TDynamicListEnumerator *liste = new TDynamicListEnumerator();
|
||||
liste->ls = list;
|
||||
liste->index = -1;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(liste);
|
||||
_gc->Watch(liste);
|
||||
return liste;
|
||||
return ls.Create<TDynamicListEnumerator>(list);
|
||||
}
|
||||
TDynamicListEnumerator *TDynamicListEnumerator::Create(GCList *ls,
|
||||
TDynamicList *list) {
|
||||
TDynamicListEnumerator *liste = new TDynamicListEnumerator();
|
||||
liste->ls = list;
|
||||
liste->index = -1;
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(liste);
|
||||
_gc->Watch(liste);
|
||||
return liste;
|
||||
return ls->Create<TDynamicListEnumerator>(list);
|
||||
}
|
||||
bool TDynamicListEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||
this->index++;
|
||||
@@ -351,24 +283,13 @@ void TDynamicListEnumerator::Mark() {
|
||||
this->marked = true;
|
||||
this->ls->Mark();
|
||||
}
|
||||
|
||||
TStringEnumerator::TStringEnumerator(std::string str)
|
||||
: str(str), hasStarted(false) {}
|
||||
TStringEnumerator *TStringEnumerator::Create(GCList &ls, std::string str) {
|
||||
TStringEnumerator *stre = new TStringEnumerator();
|
||||
stre->str = str;
|
||||
stre->hasStarted = false;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(stre);
|
||||
_gc->Watch(stre);
|
||||
return stre;
|
||||
return ls.Create<TStringEnumerator>(str);
|
||||
}
|
||||
TStringEnumerator *TStringEnumerator::Create(GCList *ls, std::string str) {
|
||||
TStringEnumerator *stre = new TStringEnumerator();
|
||||
stre->str = str;
|
||||
stre->hasStarted = false;
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(stre);
|
||||
_gc->Watch(stre);
|
||||
return stre;
|
||||
return ls->Create<TStringEnumerator>(str);
|
||||
}
|
||||
bool TStringEnumerator::MoveNext(std::shared_ptr<GC> ls) {
|
||||
if (!this->hasStarted) {
|
||||
|
||||
+8
-41
@@ -1,20 +1,11 @@
|
||||
#include "CrossLang.hpp"
|
||||
namespace Tesses::CrossLang {
|
||||
TDynamicList::TDynamicList(TCallable *callable) : cb(callable) {}
|
||||
TDynamicList *TDynamicList::Create(GCList &ls, TCallable *callable) {
|
||||
TDynamicList *list = new TDynamicList();
|
||||
list->cb = callable;
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(list);
|
||||
_gc->Watch(list);
|
||||
return list;
|
||||
return ls.Create<TDynamicList>(callable);
|
||||
}
|
||||
TDynamicList *TDynamicList::Create(GCList *ls, TCallable *callable) {
|
||||
TDynamicList *list = new TDynamicList();
|
||||
list->cb = callable;
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(list);
|
||||
_gc->Watch(list);
|
||||
return list;
|
||||
return ls->Create<TDynamicList>(callable);
|
||||
}
|
||||
|
||||
void TDynamicList::Mark() {
|
||||
@@ -120,35 +111,11 @@ TObject TDynamicList::SetAt(GCList &ls, int64_t index, TObject val) {
|
||||
|
||||
TDynamicList::~TDynamicList() {}
|
||||
|
||||
TByteArray *TByteArray::Create(GCList &ls) {
|
||||
TByteArray *arr = new TByteArray();
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(arr);
|
||||
_gc->Watch(arr);
|
||||
return arr;
|
||||
}
|
||||
TByteArray *TByteArray::Create(GCList &ls) { return ls.Create<TByteArray>(); }
|
||||
|
||||
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;
|
||||
}
|
||||
TByteArray *TByteArray::Create(GCList *ls) { return ls->Create<TByteArray>(); }
|
||||
TList *TList::Create(GCList *gc) { return gc->Create<TList>(); }
|
||||
TList *TList::Create(GCList &gc) { return gc.Create<TList>(); }
|
||||
void TList::Add(TObject value) { this->items.push_back(value); }
|
||||
void TList::Set(int64_t index, TObject value) {
|
||||
if (index >= 0 && index < this->Count()) {
|
||||
@@ -161,7 +128,7 @@ TObject TList::Get(int64_t index) {
|
||||
}
|
||||
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) {
|
||||
if (index >= 0 && index <= this->Count()) {
|
||||
this->items.insert(this->items.begin() + index, value);
|
||||
|
||||
+2
-11
@@ -1,7 +1,6 @@
|
||||
#include "CrossLang.hpp"
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
TNativeObject::~TNativeObject() {}
|
||||
|
||||
TNative::TNative(void *ptr, std::function<void(void *)> destroy) {
|
||||
this->ptr = ptr;
|
||||
@@ -34,19 +33,11 @@ bool TNativeObject::Equals(std::shared_ptr<GC> gc, TObject right) {
|
||||
}
|
||||
TNative *TNative::Create(GCList &ls, void *ptr,
|
||||
std::function<void(void *)> destroy) {
|
||||
TNative *native = new TNative(ptr, destroy);
|
||||
std::shared_ptr<GC> gc = ls.GetGC();
|
||||
ls.Add(native);
|
||||
gc->Watch(native);
|
||||
return native;
|
||||
return ls.Create<TNative>(ptr, destroy);
|
||||
}
|
||||
TNative *TNative::Create(GCList *ls, void *ptr,
|
||||
std::function<void(void *)> destroy) {
|
||||
TNative *native = new TNative(ptr, destroy);
|
||||
std::shared_ptr<GC> gc = ls->GetGC();
|
||||
ls->Add(native);
|
||||
gc->Watch(native);
|
||||
return native;
|
||||
return ls->Create<TNative>(ptr, destroy);
|
||||
}
|
||||
TNative::~TNative() { this->Destroy(); }
|
||||
|
||||
|
||||
+2
-10
@@ -41,19 +41,11 @@ TList *TQueryable::ToList(GCList &ls) {
|
||||
return list;
|
||||
}
|
||||
TQueryable *TQueryable::Create(GCList &ls, TObject parent) {
|
||||
TQueryable *queryable = new TQueryable(parent);
|
||||
std::shared_ptr<GC> gc = ls.GetGC();
|
||||
ls.Add(queryable);
|
||||
gc->Watch(queryable);
|
||||
return queryable;
|
||||
return ls.Create<TQueryable>(parent);
|
||||
}
|
||||
TQueryable *TQueryable::Create(GCList &ls, TObject parent, TQueryableMode mode,
|
||||
std::vector<TObject> args) {
|
||||
TQueryable *queryable = new TQueryable(parent, mode, args);
|
||||
std::shared_ptr<GC> gc = ls.GetGC();
|
||||
ls.Add(queryable);
|
||||
gc->Watch(queryable);
|
||||
return queryable;
|
||||
return ls.Create<TQueryable>(parent, mode, args);
|
||||
}
|
||||
|
||||
void TQueryable::Mark() {
|
||||
|
||||
@@ -9,12 +9,11 @@ void ThrowConstError(std::string key) {
|
||||
|
||||
void TEnvironment::DeclareConstVariable(std::string key, TObject value) {
|
||||
this->DeclareVariable(key, value);
|
||||
this->consts.push_back(key);
|
||||
this->decls[key] = TEnvironmentDeclType::TEDT_CONST;
|
||||
}
|
||||
bool TEnvironment::HasConstForDeclare(std::string key) {
|
||||
for (auto item : this->consts)
|
||||
if (item == key)
|
||||
return true;
|
||||
if (this->decls.count(key) > 0)
|
||||
return this->decls[key] == TEnvironmentDeclType::TEDT_CONST;
|
||||
return false;
|
||||
}
|
||||
bool TEnvironment::HasConstForSet(std::string key) {
|
||||
@@ -308,13 +307,15 @@ void TRootEnvironment::SetVariable(std::string key, TObject value) {
|
||||
this->dict->SetValue(key, 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);
|
||||
}
|
||||
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) {
|
||||
return this->dict->HasValue(key);
|
||||
return this->dict->HasValue(key) || this->decls.count(key) > 0;
|
||||
}
|
||||
TEnvironment *TRootEnvironment::GetParentEnvironment() { return this; }
|
||||
TRootEnvironment *TRootEnvironment::GetRootEnvironment() { return this; }
|
||||
@@ -338,18 +339,10 @@ void TRootEnvironment::Mark() {
|
||||
cls.first->Mark();
|
||||
}
|
||||
TRootEnvironment *TRootEnvironment::Create(GCList *gc, TDictionary *dict) {
|
||||
TRootEnvironment *env = new TRootEnvironment(dict);
|
||||
std::shared_ptr<GC> _gc = gc->GetGC();
|
||||
gc->Add(env);
|
||||
_gc->Watch(env);
|
||||
return env;
|
||||
return gc->Create<TRootEnvironment>(dict);
|
||||
}
|
||||
TRootEnvironment *TRootEnvironment::Create(GCList &gc, TDictionary *dict) {
|
||||
TRootEnvironment *env = new TRootEnvironment(dict);
|
||||
std::shared_ptr<GC> _gc = gc.GetGC();
|
||||
gc.Add(env);
|
||||
_gc->Watch(env);
|
||||
return env;
|
||||
return gc.Create<TRootEnvironment>(dict);
|
||||
}
|
||||
|
||||
bool TRootEnvironment::HandleException(std::shared_ptr<GC> gc,
|
||||
|
||||
@@ -82,16 +82,24 @@ TObject TSubEnvironment::GetVariable(std::string key) {
|
||||
if (this->dict->HasValue(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)) {
|
||||
return this->env->GetVariable(key);
|
||||
}
|
||||
return Undefined();
|
||||
}
|
||||
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);
|
||||
}
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@@ -102,10 +110,10 @@ void TSubEnvironment::SetVariable(std::string key, TObject value) {
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (this->dict->HasValue(key))
|
||||
if (this->dict->HasValue(key) || this->decls.count(key) > 0)
|
||||
return true;
|
||||
return this->env->HasVariableRecurse(key);
|
||||
}
|
||||
@@ -159,19 +167,11 @@ TSubEnvironment *TEnvironment::GetSubEnvironment(GCList &gc) {
|
||||
}
|
||||
TSubEnvironment *TSubEnvironment::Create(GCList *gc, TEnvironment *env,
|
||||
TDictionary *dict) {
|
||||
TSubEnvironment *senv = new TSubEnvironment(env, dict);
|
||||
std::shared_ptr<GC> _gc = gc->GetGC();
|
||||
gc->Add(senv);
|
||||
_gc->Watch(senv);
|
||||
return senv;
|
||||
return gc->Create<TSubEnvironment>(env, dict);
|
||||
}
|
||||
TSubEnvironment *TSubEnvironment::Create(GCList &gc, TEnvironment *env,
|
||||
TDictionary *dict) {
|
||||
TSubEnvironment *senv = new TSubEnvironment(env, dict);
|
||||
std::shared_ptr<GC> _gc = gc.GetGC();
|
||||
gc.Add(senv);
|
||||
_gc->Watch(senv);
|
||||
return senv;
|
||||
return gc.Create<TSubEnvironment>(env, dict);
|
||||
}
|
||||
TEnvironment *TSubEnvironment::GetParentEnvironment() { return this->env; }
|
||||
TRootEnvironment *TSubEnvironment::GetRootEnvironment() {
|
||||
|
||||
@@ -1490,12 +1490,12 @@ bool InterperterThread::ExecuteMethod2(std::shared_ptr<GC> gc, TObject instance,
|
||||
pattern,
|
||||
callable->ToRouteServerRequestHandler(gc));
|
||||
}
|
||||
} else if (key == "Trace") {
|
||||
} else if (key == "Query") {
|
||||
std::string pattern;
|
||||
TCallable *callable;
|
||||
if (GetArgument(args, 0, pattern) &&
|
||||
GetArgumentHeap(args, 1, callable)) {
|
||||
routable->Trace(
|
||||
routable->Query(
|
||||
pattern,
|
||||
callable->ToRouteServerRequestHandler(gc));
|
||||
}
|
||||
|
||||
@@ -58,13 +58,13 @@ void ThrowFatalError(std::exception &ex) {
|
||||
error.WriteLine(text);
|
||||
}
|
||||
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
if (clrtexcept != nullptr) {
|
||||
error.WriteLine("CrossLang has encountered a fatal runtime exception");
|
||||
error.WriteLine();
|
||||
error.WriteLine(clrtexcept->what());
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
if (compiler != nullptr) {
|
||||
error.WriteLine("CrossLang has encountered a compiler error");
|
||||
@@ -81,13 +81,13 @@ void ThrowFatalError(std::exception &ex) {
|
||||
error.Write(":");
|
||||
error.WriteLine((int64_t)li.offset);
|
||||
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
|
||||
error.WriteLine("CrossLang has encountered a fatal C++ exception");
|
||||
error.WriteLine();
|
||||
error.Write("what(): ");
|
||||
error.WriteLine(ex2->what());
|
||||
exit(1);
|
||||
std::exit(1);
|
||||
}
|
||||
} // namespace Tesses::CrossLang
|
||||
+4
-30
@@ -5,22 +5,8 @@
|
||||
#include <iostream>
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
TFile *TFile::Create(GCList &ls) { return ls.Create<TFile>(); }
|
||||
TFile *TFile::Create(GCList *ls) { return ls->Create<TFile>(); }
|
||||
void TFileChunk::Mark() {
|
||||
if (this->marked)
|
||||
return;
|
||||
@@ -28,20 +14,8 @@ void TFileChunk::Mark() {
|
||||
this->file->Mark();
|
||||
}
|
||||
|
||||
TFileChunk *TFileChunk::Create(GCList &ls) {
|
||||
TFileChunk *chk = new 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;
|
||||
}
|
||||
TFileChunk *TFileChunk::Create(GCList &ls) { return ls.Create<TFileChunk>(); }
|
||||
TFileChunk *TFileChunk::Create(GCList *ls) { return ls->Create<TFileChunk>(); }
|
||||
void TFile::Mark() {
|
||||
if (this->marked)
|
||||
return;
|
||||
|
||||
+87
-79
@@ -11,7 +11,18 @@
|
||||
using namespace Tesses::Framework::Threading;
|
||||
using namespace std::chrono;
|
||||
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 run = this->running;
|
||||
@@ -74,7 +85,14 @@ TDictionary *CreateThread(GCList &ls, TCallable *callable, bool detached) {
|
||||
TObject cb = th->callable->Call(ls, {});
|
||||
gc->BarrierBegin();
|
||||
th->returnValue = cb;
|
||||
std::map<pthread_t, int> mt;
|
||||
#if defined(GEKKO) || defined(_EE)
|
||||
current_funcs_mtx.Lock();
|
||||
current_funcs.erase(pthread_self());
|
||||
current_funcs_mtx.Unlock();
|
||||
#endif
|
||||
gc->BarrierEnd();
|
||||
|
||||
th->hasReturned = true;
|
||||
});
|
||||
while (!th->hasInit)
|
||||
@@ -93,50 +111,47 @@ void GC::Start() {
|
||||
return new Tesses::Framework::Threading::ThreadPool(threads);
|
||||
},
|
||||
[](Tesses::Framework::Threading::ThreadPool *p) -> void { delete p; });
|
||||
this->mtx = new Mutex();
|
||||
|
||||
this->running = true;
|
||||
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()) {
|
||||
this_frame = system_clock::now();
|
||||
if ((this_frame - last_frame) > 10s) {
|
||||
this->BarrierBegin();
|
||||
while (this->allocs < ALLOC_THRESHOLD)
|
||||
this->cond.Wait(
|
||||
&this->mtx); // your wrapper around pthread_cond_wait
|
||||
this->allocs = 0;
|
||||
std::vector<THeapObject *> to_delete;
|
||||
this->Collect(to_delete);
|
||||
this->BarrierEnd();
|
||||
|
||||
last_frame = this_frame;
|
||||
this->Collect();
|
||||
}
|
||||
for (auto o : to_delete)
|
||||
delete o;
|
||||
}
|
||||
{
|
||||
std::vector<THeapObject *> to_delete;
|
||||
this->BarrierBegin();
|
||||
this->Collect(to_delete);
|
||||
this->BarrierEnd();
|
||||
|
||||
#if defined(_WIN32)
|
||||
Sleep(100);
|
||||
#else
|
||||
usleep(100000);
|
||||
#endif
|
||||
for (auto item : to_delete)
|
||||
delete item;
|
||||
}
|
||||
GC::Collect();
|
||||
});
|
||||
}
|
||||
|
||||
bool GC::UsingNullThreads() { return false; }
|
||||
|
||||
void GC::BarrierBegin() { this->mtx->Lock(); }
|
||||
void GC::BarrierEnd() { this->mtx->Unlock(); }
|
||||
void GC::BarrierBegin() { this->mtx.Lock(); }
|
||||
void GC::BarrierEnd() { this->mtx.Unlock(); }
|
||||
void GC::Watch(TObject obj) {
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
|
||||
for (auto item : this->objects) {
|
||||
if (item == _item) {
|
||||
this->BarrierEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->objects.push_back(_item);
|
||||
this->objects.insert(_item);
|
||||
auto nowAllocs = ++this->allocs;
|
||||
this->BarrierEnd();
|
||||
if (nowAllocs >= ALLOC_THRESHOLD)
|
||||
this->cond.Signal();
|
||||
}
|
||||
}
|
||||
void GC::Mark(TObject obj) {
|
||||
@@ -149,65 +164,36 @@ void GC::Unwatch(TObject obj) {
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
for (auto index = this->objects.begin();
|
||||
index != this->objects.end();) {
|
||||
if (*index == _item) {
|
||||
index = this->objects.erase(index);
|
||||
continue;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
this->objects.erase(_item);
|
||||
this->BarrierEnd();
|
||||
}
|
||||
}
|
||||
void GC::SetRoot(TObject obj) {
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
void GC::SetRoot(GCList *_item) {
|
||||
if (_item == nullptr)
|
||||
return;
|
||||
this->BarrierBegin();
|
||||
|
||||
for (auto item : this->roots) {
|
||||
if (item == _item) {
|
||||
this->BarrierEnd();
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->roots.push_back(_item);
|
||||
this->BarrierEnd();
|
||||
}
|
||||
this->roots.insert(_item);
|
||||
this->BarrierEnd();
|
||||
}
|
||||
Tesses::Framework::Threading::ThreadPool *GC::GetPool() {
|
||||
return this->tpool->GetValue();
|
||||
}
|
||||
|
||||
void GC::UnsetRoot(TObject obj) {
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
this->BarrierBegin();
|
||||
for (auto index = this->roots.begin(); index != this->roots.end();) {
|
||||
if (*index == _item) {
|
||||
index = this->roots.erase(index);
|
||||
continue;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
this->BarrierEnd();
|
||||
}
|
||||
void GC::UnsetRoot(GCList *_item) {
|
||||
if (_item == nullptr)
|
||||
return;
|
||||
this->BarrierBegin();
|
||||
this->roots.erase(_item);
|
||||
this->BarrierEnd();
|
||||
}
|
||||
|
||||
GC::~GC() {
|
||||
GC::BarrierBegin();
|
||||
|
||||
this->roots.clear();
|
||||
GC::BarrierEnd();
|
||||
|
||||
this->running = false;
|
||||
this->cond.Signal();
|
||||
this->thrd->Join();
|
||||
delete this->thrd;
|
||||
for (auto item : objects)
|
||||
delete item;
|
||||
|
||||
delete this->tpool;
|
||||
delete this->mtx;
|
||||
}
|
||||
|
||||
void GC::RegisterEverythingCallback(
|
||||
@@ -218,23 +204,45 @@ void GC::RegisterEverything(TRootEnvironment *env) {
|
||||
for (auto item : this->register_everything)
|
||||
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) {
|
||||
item->marked = false;
|
||||
}
|
||||
for (auto item : this->roots) {
|
||||
item->Mark();
|
||||
}
|
||||
for (auto index = this->objects.begin(); index != this->objects.end();
|
||||
index++) {
|
||||
for (auto index = this->objects.begin(); index != this->objects.end();) {
|
||||
THeapObject *o = *index;
|
||||
if (!o->marked) {
|
||||
delete o;
|
||||
this->objects.erase(index);
|
||||
index--;
|
||||
to_delete.push_back(o);
|
||||
index = this->objects.erase(index);
|
||||
} else {
|
||||
++index;
|
||||
}
|
||||
}
|
||||
this->BarrierEnd();
|
||||
}
|
||||
}; // namespace Tesses::CrossLang
|
||||
|
||||
+1
-2
@@ -8,7 +8,7 @@ GCList::GCList(std::shared_ptr<GC> gc) {
|
||||
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) {
|
||||
if (std::holds_alternative<THeapObjectHolder>(obj)) {
|
||||
auto _item = std::get<THeapObjectHolder>(obj).obj;
|
||||
@@ -40,7 +40,6 @@ void GCList::Add(TObject obj) {
|
||||
}
|
||||
}
|
||||
void GCList::Mark() {
|
||||
this->marked = true;
|
||||
for (auto item : this->items) {
|
||||
item->Mark();
|
||||
}
|
||||
|
||||
+69
-55
@@ -12,8 +12,6 @@
|
||||
|
||||
namespace Tesses::CrossLang {
|
||||
|
||||
thread_local CallStackEntry *current_function = nullptr;
|
||||
|
||||
TObject ExecuteFunction(GCList &ls, TCallable *callable,
|
||||
std::vector<TObject> args) {
|
||||
return callable->Call(ls, args);
|
||||
@@ -2113,8 +2111,14 @@ bool InterperterThread::Throw(std::shared_ptr<GC> gc) {
|
||||
|
||||
if (!std::holds_alternative<Undefined>(_res2)) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -2223,6 +2227,7 @@ bool InterperterThread::JumpUndefined(std::shared_ptr<GC> gc) {
|
||||
bool InterperterThread::Jump(std::shared_ptr<GC> gc) {
|
||||
|
||||
std::vector<CallStackEntry *> &cse = this->call_stack_entries;
|
||||
|
||||
auto stk = cse.back();
|
||||
|
||||
if (stk->ip + 4 <= stk->callable->closure->code.size()) {
|
||||
@@ -2409,23 +2414,39 @@ bool InterperterThread::TryCatch(std::shared_ptr<GC> gc) {
|
||||
if (GetObjectHeap(tryFn, tryC) && GetObjectHeap(catchFn, catchC)) {
|
||||
try {
|
||||
stk->Push(gc, tryC->Call(ls, {}));
|
||||
}
|
||||
|
||||
catch (std::exception &ex) {
|
||||
TDictionary *dict = TDictionary::Create(ls);
|
||||
auto gc = ls.GetGC();
|
||||
auto myEx = dynamic_cast<VMByteCodeException *>(&ex);
|
||||
if (myEx != nullptr) {
|
||||
stk->Push(gc, catchC->Call(ls, {myEx->exception}));
|
||||
} else {
|
||||
gc->BarrierBegin();
|
||||
} catch (std::bad_alloc &ex) {
|
||||
std::cerr
|
||||
<< "CrossLang has failed to allocate, sorry for termination."
|
||||
<< std::endl;
|
||||
std::exit(1);
|
||||
} catch (const std::string &ex) {
|
||||
stk->Push(gc, catchC->Call(ls, {ex}));
|
||||
} catch (const char *ex) {
|
||||
|
||||
dict->SetValue("Type", "NativeException");
|
||||
dict->SetValue("Text", ex.what());
|
||||
gc->BarrierEnd();
|
||||
stk->Push(gc,
|
||||
catchC->Call(ls, {std::string{ex != nullptr ? ex : ""}}));
|
||||
} 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;
|
||||
@@ -2693,14 +2714,14 @@ void InterperterThread::Execute(std::shared_ptr<GC> gc) {
|
||||
|
||||
std::vector<CallStackEntry *> &cse = this->call_stack_entries;
|
||||
#define VM_OPCODE_TABLE_INLINE
|
||||
#include "vm_opcode_table.h"
|
||||
#include "vm_opcode_table.def"
|
||||
#undef VM_OPCODE_TABLE_INLINE
|
||||
|
||||
execute:
|
||||
|
||||
if (!cse.empty()) {
|
||||
auto stk = cse.back();
|
||||
current_function = stk;
|
||||
GC::SetCurrentFunction(stk);
|
||||
|
||||
try {
|
||||
while (stk->ip < 0xFFFFFFFF &&
|
||||
@@ -2721,7 +2742,7 @@ execute:
|
||||
cse[cse.size() - 2]->Push(gc, o);
|
||||
|
||||
cse.erase(cse.end() - 1);
|
||||
current_function = cse.back();
|
||||
GC::SetCurrentFunction(cse.back());
|
||||
gc->BarrierEnd();
|
||||
goto execute;
|
||||
} else {
|
||||
@@ -2729,8 +2750,13 @@ execute:
|
||||
}
|
||||
}
|
||||
|
||||
if (gc->UsingNullThreads())
|
||||
gc->Collect();
|
||||
if (gc->UsingNullThreads()) {
|
||||
std::vector<THeapObject *> objs;
|
||||
gc->Collect(objs);
|
||||
for (auto &item : objs) {
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stk->mustReturn = false;
|
||||
@@ -2764,7 +2790,7 @@ execute:
|
||||
}
|
||||
if (cse.size() == 1) {
|
||||
|
||||
current_function = nullptr;
|
||||
GC::SetCurrentFunction(nullptr);
|
||||
{
|
||||
|
||||
gc->BarrierBegin();
|
||||
@@ -2817,7 +2843,7 @@ execute:
|
||||
cse[cse.size() - 2]->Push(gc, o);
|
||||
|
||||
cse.erase(cse.end() - 1);
|
||||
current_function = cse.back();
|
||||
GC::SetCurrentFunction(cse.back());
|
||||
gc->BarrierEnd();
|
||||
|
||||
for (auto item : callable) {
|
||||
@@ -2846,7 +2872,7 @@ void CallStackEntry::Push(std::shared_ptr<GC> gc, TObject o) {
|
||||
gc->BarrierEnd();
|
||||
}
|
||||
TObject CallStackEntry::Resume(GCList &ls) {
|
||||
auto cse = current_function;
|
||||
auto cse = GC::GetCurrentFunction();
|
||||
InterperterThread *thrd = InterperterThread::Create(ls);
|
||||
ls.GetGC()->BarrierBegin();
|
||||
thrd->call_stack_entries.push_back(this);
|
||||
@@ -2855,7 +2881,7 @@ TObject CallStackEntry::Resume(GCList &ls) {
|
||||
thrd->Execute(ls.GetGC());
|
||||
|
||||
TObject v = thrd->call_stack_entries[0]->Pop(ls);
|
||||
current_function = cse;
|
||||
GC::SetCurrentFunction(cse);
|
||||
return v;
|
||||
}
|
||||
TObject CallStackEntry::Pop(GCList &gc) {
|
||||
@@ -2870,41 +2896,17 @@ TObject CallStackEntry::Pop(GCList &gc) {
|
||||
}
|
||||
|
||||
InterperterThread *InterperterThread::Create(GCList &ls) {
|
||||
InterperterThread *it = new InterperterThread();
|
||||
std::shared_ptr<GC> _gc = ls.GetGC();
|
||||
ls.Add(it);
|
||||
_gc->Watch(it);
|
||||
return it;
|
||||
return ls.Create<InterperterThread>();
|
||||
}
|
||||
InterperterThread *InterperterThread::Create(GCList *ls) {
|
||||
InterperterThread *it = new InterperterThread();
|
||||
std::shared_ptr<GC> _gc = ls->GetGC();
|
||||
ls->Add(it);
|
||||
_gc->Watch(it);
|
||||
return it;
|
||||
return ls->Create<InterperterThread>();
|
||||
}
|
||||
CallStackEntry *CallStackEntry::Create(GCList &ls) {
|
||||
CallStackEntry *cse = new 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;
|
||||
return ls.Create<CallStackEntry>();
|
||||
}
|
||||
|
||||
CallStackEntry *CallStackEntry::Create(GCList *ls) {
|
||||
CallStackEntry *cse = new 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;
|
||||
return ls->Create<CallStackEntry>();
|
||||
}
|
||||
void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
|
||||
std::vector<TObject> args) {
|
||||
@@ -2963,6 +2965,18 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
|
||||
cse->env->DeclareVariable(trimStart(closure->closure->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()
|
||||
: closure->closure->args.back();
|
||||
@@ -2979,7 +2993,7 @@ void InterperterThread::AddCallStackEntry(GCList &ls, TClosure *closure,
|
||||
throw VMException("Too many arguments");
|
||||
}
|
||||
|
||||
current_function = cse;
|
||||
GC::SetCurrentFunction(cse);
|
||||
|
||||
this->call_stack_entries.push_back(cse);
|
||||
ls.GetGC()->BarrierEnd();
|
||||
|
||||
Reference in New Issue
Block a user