mirror of
https://onedev.site.tesses.net/crosslang
synced 2026-04-18 10:37:04 +00:00
Add Null Coalescing operator
This commit is contained in:
@@ -664,7 +664,8 @@ typedef enum {
|
|||||||
PUSHBREAK,
|
PUSHBREAK,
|
||||||
PUSHCONTINUE,
|
PUSHCONTINUE,
|
||||||
JMPIFBREAK,
|
JMPIFBREAK,
|
||||||
JMPIFCONTINUE
|
JMPIFCONTINUE,
|
||||||
|
JMPIFDEFINED
|
||||||
} Instruction;
|
} Instruction;
|
||||||
/**
|
/**
|
||||||
* @brief Base type for bytecode instruction
|
* @brief Base type for bytecode instruction
|
||||||
@@ -1274,6 +1275,10 @@ constexpr std::string_view RelativePathExpression = "relativePathExpression";
|
|||||||
* @brief await expression for async/await
|
* @brief await expression for async/await
|
||||||
*/
|
*/
|
||||||
constexpr std::string_view AwaitExpression = "awaitExpression";
|
constexpr std::string_view AwaitExpression = "awaitExpression";
|
||||||
|
/**
|
||||||
|
* @brief ?? operator
|
||||||
|
*/
|
||||||
|
constexpr std::string_view NullCoalescingExpression = "nullCoalescingExpression";
|
||||||
/**
|
/**
|
||||||
* @brief Advanced AST node
|
* @brief Advanced AST node
|
||||||
*
|
*
|
||||||
@@ -1346,6 +1351,7 @@ class Parser {
|
|||||||
SyntaxNode ParseFactor();
|
SyntaxNode ParseFactor();
|
||||||
SyntaxNode ParseValue();
|
SyntaxNode ParseValue();
|
||||||
SyntaxNode ParseUnary();
|
SyntaxNode ParseUnary();
|
||||||
|
SyntaxNode ParseNullCoalescing();
|
||||||
void ParseHtml(std::vector<SyntaxNode>& nodes,std::string var);
|
void ParseHtml(std::vector<SyntaxNode>& nodes,std::string var);
|
||||||
GC* gc;
|
GC* gc;
|
||||||
TRootEnvironment* env;
|
TRootEnvironment* env;
|
||||||
@@ -2254,6 +2260,7 @@ class GC {
|
|||||||
bool ExecuteMethod2(GC* gc, TObject instance, std::string key, std::vector<TObject> args);
|
bool ExecuteMethod2(GC* gc, TObject instance, std::string key, std::vector<TObject> args);
|
||||||
protected:
|
protected:
|
||||||
static void* ThreadCallback(void* ptr);
|
static void* ThreadCallback(void* ptr);
|
||||||
|
bool JumpIfDefined(GC* gc);
|
||||||
bool Add(GC* gc);
|
bool Add(GC* gc);
|
||||||
bool Sub(GC* gc);
|
bool Sub(GC* gc);
|
||||||
bool Times(GC* gc);
|
bool Times(GC* gc);
|
||||||
|
|||||||
@@ -521,7 +521,18 @@ namespace Tesses::CrossLang
|
|||||||
TWO_EXPR(NotEqualsExpression, NEQ)
|
TWO_EXPR(NotEqualsExpression, NEQ)
|
||||||
TWO_EXPR(EqualsExpression, EQ)
|
TWO_EXPR(EqualsExpression, EQ)
|
||||||
TWO_EXPR(XOrExpression, XOR)
|
TWO_EXPR(XOrExpression, XOR)
|
||||||
if(adv.nodeName == ClassStatement && adv.nodes.size() >= 3 && std::holds_alternative<std::string>(adv.nodes[0]))
|
if(adv.nodeName == NullCoalescingExpression && adv.nodes.size() == 2)
|
||||||
|
{
|
||||||
|
uint32_t ifId = NewId();
|
||||||
|
std::string ifIdTrue = "__compGenTrue";
|
||||||
|
ifIdTrue.append(std::to_string(ifId));
|
||||||
|
GenNode(instructions,adv.nodes[0],scope,contscope,brkscope,contI,brkI);
|
||||||
|
instructions.push_back(new JumpStyleInstruction(Instruction::JMPIFDEFINED, ifIdTrue));
|
||||||
|
GenNode(instructions,adv.nodes[1],scope,contscope,brkscope,contI,brkI);
|
||||||
|
instructions.push_back(new LabelInstruction(ifIdTrue));
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(adv.nodeName == ClassStatement && adv.nodes.size() >= 3 && std::holds_alternative<std::string>(adv.nodes[0]))
|
||||||
{
|
{
|
||||||
CodeGenClass cls;
|
CodeGenClass cls;
|
||||||
cls.documentation = GetString(std::get<std::string>(adv.nodes[0]));
|
cls.documentation = GetString(std::get<std::string>(adv.nodes[0]));
|
||||||
|
|||||||
@@ -579,6 +579,7 @@ namespace Tesses::CrossLang
|
|||||||
break;
|
break;
|
||||||
case '<':
|
case '<':
|
||||||
case '>':
|
case '>':
|
||||||
|
case '?':
|
||||||
if(peek == read)
|
if(peek == read)
|
||||||
{
|
{
|
||||||
Flush();
|
Flush();
|
||||||
@@ -670,7 +671,6 @@ namespace Tesses::CrossLang
|
|||||||
case ':':
|
case ':':
|
||||||
case ';':
|
case ';':
|
||||||
case ',':
|
case ',':
|
||||||
case '?':
|
|
||||||
Flush();
|
Flush();
|
||||||
Symbol({read});
|
Symbol({read});
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1088,6 +1088,10 @@ namespace Tesses::CrossLang
|
|||||||
{
|
{
|
||||||
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(XOrExpression,true,{ node,ParseAssignment()})});
|
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(XOrExpression,true,{ node,ParseAssignment()})});
|
||||||
}
|
}
|
||||||
|
else if(IsSymbol("?\?="))
|
||||||
|
{
|
||||||
|
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(NullCoalescingExpression,true,{ node,ParseAssignment()})});
|
||||||
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
SyntaxNode Parser::ParseNode(bool isRoot)
|
SyntaxNode Parser::ParseNode(bool isRoot)
|
||||||
@@ -1547,9 +1551,18 @@ namespace Tesses::CrossLang
|
|||||||
EnsureSymbol(";");
|
EnsureSymbol(";");
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
SyntaxNode Parser::ParseNullCoalescing()
|
||||||
|
{
|
||||||
|
SyntaxNode expr = ParseLOr();
|
||||||
|
while(IsSymbol("?\?"))
|
||||||
|
{
|
||||||
|
expr = AdvancedSyntaxNode::Create(NullCoalescingExpression,true,{expr,ParseLOr()});
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
SyntaxNode Parser::ParseTernary()
|
SyntaxNode Parser::ParseTernary()
|
||||||
{
|
{
|
||||||
SyntaxNode node = ParseLOr();
|
SyntaxNode node = ParseNullCoalescing();
|
||||||
if(IsSymbol("?"))
|
if(IsSymbol("?"))
|
||||||
{
|
{
|
||||||
auto yes = ParseTernary();
|
auto yes = ParseTernary();
|
||||||
|
|||||||
@@ -6163,6 +6163,32 @@ namespace Tesses::CrossLang {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool InterperterThread::JumpIfDefined(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<Undefined>(_res2) && !std::holds_alternative<std::nullptr_t>(_res2))
|
||||||
|
{
|
||||||
|
stk->ip = n;
|
||||||
|
stk->Push(gc,_res2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
throw VMException("Can't read jmpifdefined pc.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool InterperterThread::JumpIfBreak(GC* gc)
|
bool InterperterThread::JumpIfBreak(GC* gc)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user