Now you can break, continue and return in try statements
This commit is contained in:
@ -115,8 +115,6 @@ do(conditionLikeIf)
|
||||
|
||||
#### 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
|
||||
try {
|
||||
Console.WriteLine("God is good.");
|
||||
|
||||
@ -659,7 +659,11 @@ typedef enum {
|
||||
YIELD,
|
||||
PUSHROOTPATH,
|
||||
PUSHRELATIVEPATH,
|
||||
BREAKPOINT
|
||||
BREAKPOINT,
|
||||
PUSHBREAK,
|
||||
PUSHCONTINUE,
|
||||
JMPIFBREAK,
|
||||
JMPIFCONTINUE
|
||||
} Instruction;
|
||||
/**
|
||||
* @brief Base type for bytecode instruction
|
||||
@ -1344,6 +1348,9 @@ class Parser {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//this is a dummy type with
|
||||
class MethodInvoker {
|
||||
|
||||
@ -1358,11 +1365,19 @@ class Parser {
|
||||
Tesses::Framework::Date::DateTime& GetDate();
|
||||
~TDateTime();
|
||||
};
|
||||
class TBreak {
|
||||
|
||||
};
|
||||
class TContinue {
|
||||
|
||||
};
|
||||
/**
|
||||
* @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 GC;
|
||||
class GC {
|
||||
@ -2072,6 +2087,10 @@ class GC {
|
||||
bool Dup(GC* gc);
|
||||
bool Nop(GC* gc);
|
||||
bool Breakpoint(GC* gc);
|
||||
bool PushBreak(GC* gc);
|
||||
bool PushContinue(GC* gc);
|
||||
bool JumpIfBreak(GC* gc);
|
||||
bool JumpIfContinue(GC* gc);
|
||||
public:
|
||||
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";
|
||||
}
|
||||
else if(contscope == -2)
|
||||
{
|
||||
instructions.push_back(new SimpleInstruction(PUSHCONTINUE));
|
||||
instructions.push_back(new SimpleInstruction(RET));
|
||||
}
|
||||
else
|
||||
{
|
||||
auto cont = scope-contscope;
|
||||
@ -1009,6 +1014,11 @@ namespace Tesses::CrossLang
|
||||
{
|
||||
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
|
||||
{
|
||||
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]))
|
||||
{
|
||||
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,{
|
||||
AdvancedSyntaxNode::Create(ParenthesesExpression,true,{adv.nodes[2]}),
|
||||
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));
|
||||
uint32_t compGenId = NewId();
|
||||
std::string compGenIttr = "__compGenRetThing";
|
||||
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 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));
|
||||
}
|
||||
|
||||
@ -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);
|
||||
instructions.push_back(new ClosureInstruction((uint32_t)fnindex,false));
|
||||
|
||||
@ -5153,6 +5153,57 @@ namespace Tesses::CrossLang {
|
||||
}
|
||||
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)
|
||||
{
|
||||
|
||||
@ -5201,6 +5252,24 @@ namespace Tesses::CrossLang {
|
||||
|
||||
stk->Push(gc,nullptr);
|
||||
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)
|
||||
{
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user