Now you can break, continue and return in try statements
This commit is contained in:
@ -115,8 +115,6 @@ do(conditionLikeIf)
|
|||||||
|
|
||||||
#### Try statement
|
#### Try statement
|
||||||
|
|
||||||
Note: you can't yield, return, break or continue from inside a try statement (also applys to catch and finally due to these being internally closures)
|
|
||||||
|
|
||||||
```js
|
```js
|
||||||
try {
|
try {
|
||||||
Console.WriteLine("God is good.");
|
Console.WriteLine("God is good.");
|
||||||
|
|||||||
@ -659,7 +659,11 @@ typedef enum {
|
|||||||
YIELD,
|
YIELD,
|
||||||
PUSHROOTPATH,
|
PUSHROOTPATH,
|
||||||
PUSHRELATIVEPATH,
|
PUSHRELATIVEPATH,
|
||||||
BREAKPOINT
|
BREAKPOINT,
|
||||||
|
PUSHBREAK,
|
||||||
|
PUSHCONTINUE,
|
||||||
|
JMPIFBREAK,
|
||||||
|
JMPIFCONTINUE
|
||||||
} Instruction;
|
} Instruction;
|
||||||
/**
|
/**
|
||||||
* @brief Base type for bytecode instruction
|
* @brief Base type for bytecode instruction
|
||||||
@ -1344,6 +1348,9 @@ class Parser {
|
|||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//this is a dummy type with
|
//this is a dummy type with
|
||||||
class MethodInvoker {
|
class MethodInvoker {
|
||||||
|
|
||||||
@ -1358,11 +1365,19 @@ class Parser {
|
|||||||
Tesses::Framework::Date::DateTime& GetDate();
|
Tesses::Framework::Date::DateTime& GetDate();
|
||||||
~TDateTime();
|
~TDateTime();
|
||||||
};
|
};
|
||||||
|
class TBreak {
|
||||||
|
|
||||||
|
};
|
||||||
|
class TContinue {
|
||||||
|
|
||||||
|
};
|
||||||
/**
|
/**
|
||||||
* @brief A script object
|
* @brief A script object
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
using TObject = std::variant<int64_t,double,char,bool,std::string,std::regex,Tesses::Framework::Filesystem::VFSPath,std::nullptr_t,Undefined,MethodInvoker,THeapObjectHolder,TVMVersion,TDateTime>;
|
|
||||||
|
using TObject = std::variant<int64_t,double,char,bool,std::string,std::regex,Tesses::Framework::Filesystem::VFSPath,std::nullptr_t,Undefined,MethodInvoker,THeapObjectHolder,TVMVersion,TDateTime,TBreak,TContinue>;
|
||||||
|
|
||||||
class TRootEnvironment;
|
class TRootEnvironment;
|
||||||
class GC;
|
class GC;
|
||||||
class GC {
|
class GC {
|
||||||
@ -2072,6 +2087,10 @@ class GC {
|
|||||||
bool Dup(GC* gc);
|
bool Dup(GC* gc);
|
||||||
bool Nop(GC* gc);
|
bool Nop(GC* gc);
|
||||||
bool Breakpoint(GC* gc);
|
bool Breakpoint(GC* gc);
|
||||||
|
bool PushBreak(GC* gc);
|
||||||
|
bool PushContinue(GC* gc);
|
||||||
|
bool JumpIfBreak(GC* gc);
|
||||||
|
bool JumpIfContinue(GC* gc);
|
||||||
public:
|
public:
|
||||||
static InterperterThread* Create(GCList* ls);
|
static InterperterThread* Create(GCList* ls);
|
||||||
static InterperterThread* Create(GCList& ls);
|
static InterperterThread* Create(GCList& ls);
|
||||||
|
|||||||
@ -991,6 +991,11 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
std::cout << "WARN: continue does nothing here\n";
|
std::cout << "WARN: continue does nothing here\n";
|
||||||
}
|
}
|
||||||
|
else if(contscope == -2)
|
||||||
|
{
|
||||||
|
instructions.push_back(new SimpleInstruction(PUSHCONTINUE));
|
||||||
|
instructions.push_back(new SimpleInstruction(RET));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto cont = scope-contscope;
|
auto cont = scope-contscope;
|
||||||
@ -1009,6 +1014,11 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
std::cout << "WARN: break does nothing here\n";
|
std::cout << "WARN: break does nothing here\n";
|
||||||
}
|
}
|
||||||
|
else if(brkscope == -2)
|
||||||
|
{
|
||||||
|
instructions.push_back(new SimpleInstruction(PUSHBREAK));
|
||||||
|
instructions.push_back(new SimpleInstruction(RET));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto _brk = scope-brkscope;
|
auto _brk = scope-brkscope;
|
||||||
@ -1223,17 +1233,63 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
if(std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0]) && std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[1]) && std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[2]))
|
if(std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[0]) && std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[1]) && std::holds_alternative<AdvancedSyntaxNode>(adv.nodes[2]))
|
||||||
{
|
{
|
||||||
GenNode(instructions,AdvancedSyntaxNode::Create(ScopelessClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}),adv.nodes[0]}),scope,contscope,brkscope,contI,brkI);
|
GenNode(instructions,AdvancedSyntaxNode::Create(ScopelessClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}),adv.nodes[0]}),scope,contscope == -1 ? -1 : -2,brkscope == -1 ? -1 : -2,contI,brkI);
|
||||||
GenNode(instructions,AdvancedSyntaxNode::Create(ScopelessClosureExpression,true,{
|
GenNode(instructions,AdvancedSyntaxNode::Create(ScopelessClosureExpression,true,{
|
||||||
AdvancedSyntaxNode::Create(ParenthesesExpression,true,{adv.nodes[2]}),
|
AdvancedSyntaxNode::Create(ParenthesesExpression,true,{adv.nodes[2]}),
|
||||||
adv.nodes[1]
|
adv.nodes[1]
|
||||||
}),scope,contscope,brkscope,contI,brkI);
|
}),scope,contscope == -1 ? -1 : -2,brkscope == -1 ? -1 : -2,contI,brkI);
|
||||||
instructions.push_back(new SimpleInstruction(TRYCATCH));
|
instructions.push_back(new SimpleInstruction(TRYCATCH));
|
||||||
uint32_t compGenId = NewId();
|
uint32_t compGenId = NewId();
|
||||||
std::string compGenIttr = "__compGenRetThing";
|
std::string compGenIttr = "__compGenRetThing";
|
||||||
compGenIttr.append(std::to_string(compGenId));
|
compGenIttr.append(std::to_string(compGenId));
|
||||||
|
if(contscope != -1)
|
||||||
|
{
|
||||||
|
instructions.push_back(new JumpStyleInstruction(JMPIFCONTINUE,compGenIttr+"_cont"));
|
||||||
|
}
|
||||||
|
if(brkscope != -1)
|
||||||
|
{
|
||||||
|
instructions.push_back(new JumpStyleInstruction(JMPIFBREAK,compGenIttr+"_brk"));
|
||||||
|
}
|
||||||
instructions.push_back(new JumpStyleInstruction(JMPUNDEFINED, compGenIttr));
|
instructions.push_back(new JumpStyleInstruction(JMPUNDEFINED, compGenIttr));
|
||||||
instructions.push_back(new SimpleInstruction(RET));
|
instructions.push_back(new SimpleInstruction(RET));
|
||||||
|
if(contscope == -2)
|
||||||
|
{
|
||||||
|
instructions.push_back(new LabelInstruction(compGenIttr+"_cont"));
|
||||||
|
instructions.push_back(new SimpleInstruction(PUSHCONTINUE));
|
||||||
|
instructions.push_back(new SimpleInstruction(RET));
|
||||||
|
}
|
||||||
|
else if(contscope != -1)
|
||||||
|
{
|
||||||
|
instructions.push_back(new LabelInstruction(compGenIttr+"_cont"));
|
||||||
|
auto cont = scope-contscope;
|
||||||
|
if(cont > 0)
|
||||||
|
instructions.push_back(new ScopeEndTimesInstruction((uint32_t)cont));
|
||||||
|
|
||||||
|
std::string myJmp = "__compGenCont";
|
||||||
|
myJmp.append(std::to_string(contI));
|
||||||
|
|
||||||
|
instructions.push_back(new JumpStyleInstruction(JMP,myJmp));
|
||||||
|
}
|
||||||
|
if(brkscope == -2)
|
||||||
|
{
|
||||||
|
instructions.push_back(new LabelInstruction(compGenIttr+"_brk"));
|
||||||
|
instructions.push_back(new SimpleInstruction(PUSHBREAK));
|
||||||
|
instructions.push_back(new SimpleInstruction(RET));
|
||||||
|
}
|
||||||
|
else if(brkscope != -1)
|
||||||
|
{
|
||||||
|
instructions.push_back(new LabelInstruction(compGenIttr+"_brk"));
|
||||||
|
auto _brk = scope-brkscope;
|
||||||
|
if(_brk > 0)
|
||||||
|
instructions.push_back(new ScopeEndTimesInstruction((uint32_t)_brk));
|
||||||
|
|
||||||
|
std::string myJmp = "__compGenBrk";
|
||||||
|
myJmp.append(std::to_string(brkI));
|
||||||
|
|
||||||
|
instructions.push_back(new JumpStyleInstruction(JMP,myJmp));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
instructions.push_back(new LabelInstruction(compGenIttr));
|
instructions.push_back(new LabelInstruction(compGenIttr));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1264,7 +1320,7 @@ namespace Tesses::CrossLang
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GenNode(fnInstructions,body,0,-1,-1,-1,-1);
|
GenNode(fnInstructions,body,0,contscope == -2 ? -2 : -1,brkscope == -2 ? -2 : -1,-1,-1);
|
||||||
|
|
||||||
this->chunks[fnindex] = std::pair<std::vector<uint32_t>,std::vector<ByteCodeInstruction*>>(args, fnInstructions);
|
this->chunks[fnindex] = std::pair<std::vector<uint32_t>,std::vector<ByteCodeInstruction*>>(args, fnInstructions);
|
||||||
instructions.push_back(new ClosureInstruction((uint32_t)fnindex,false));
|
instructions.push_back(new ClosureInstruction((uint32_t)fnindex,false));
|
||||||
|
|||||||
@ -5153,6 +5153,57 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool InterperterThread::JumpIfBreak(GC* gc)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||||
|
auto stk = cse.back();
|
||||||
|
|
||||||
|
if(stk->ip + 4 <= stk->callable->closure->code.size())
|
||||||
|
{
|
||||||
|
uint32_t n=BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]);
|
||||||
|
|
||||||
|
GCList ls(gc);
|
||||||
|
auto _res2 = stk->Pop(ls);
|
||||||
|
|
||||||
|
stk->ip = stk->ip + 4;
|
||||||
|
if(std::holds_alternative<TBreak>(_res2))
|
||||||
|
stk->ip = n;
|
||||||
|
else
|
||||||
|
stk->Push(gc,_res2);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw VMException("Can't read jmpifbreak pc.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InterperterThread::JumpIfContinue(GC* gc)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||||
|
auto stk = cse.back();
|
||||||
|
|
||||||
|
if(stk->ip + 4 <= stk->callable->closure->code.size())
|
||||||
|
{
|
||||||
|
uint32_t n=BitConverter::ToUint32BE(stk->callable->closure->code[stk->ip]);
|
||||||
|
|
||||||
|
GCList ls(gc);
|
||||||
|
auto _res2 = stk->Pop(ls);
|
||||||
|
|
||||||
|
stk->ip = stk->ip + 4;
|
||||||
|
if(std::holds_alternative<TContinue>(_res2))
|
||||||
|
stk->ip = n;
|
||||||
|
else
|
||||||
|
stk->Push(gc,_res2);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw VMException("Can't read jmpifcontinue pc.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool InterperterThread::JumpUndefined(GC* gc)
|
bool InterperterThread::JumpUndefined(GC* gc)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -5201,6 +5252,24 @@ namespace Tesses::CrossLang {
|
|||||||
|
|
||||||
stk->Push(gc,nullptr);
|
stk->Push(gc,nullptr);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
bool InterperterThread::PushBreak(GC* gc)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||||
|
auto stk = cse.back();
|
||||||
|
|
||||||
|
stk->Push(gc,TBreak());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool InterperterThread::PushContinue(GC* gc)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::vector<CallStackEntry*>& cse=this->call_stack_entries;
|
||||||
|
auto stk = cse.back();
|
||||||
|
|
||||||
|
stk->Push(gc,TContinue());
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
bool InterperterThread::PushUndefined(GC* gc)
|
bool InterperterThread::PushUndefined(GC* gc)
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user