Add switch, break and continue to constexpr
This commit is contained in:
parent
ab273181f5
commit
4dd3cd967a
|
@ -542,7 +542,7 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp)
|
||||||
return exp;
|
return exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
Eval(exp->mLeft->mDecValue->mValue);
|
Execute(exp->mLeft->mDecValue->mValue);
|
||||||
|
|
||||||
return mResult.ToExpression(mDataSection);
|
return mResult.ToExpression(mDataSection);
|
||||||
}
|
}
|
||||||
|
@ -882,7 +882,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons
|
||||||
mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname);
|
mErrors->Error(exp->mLeft->mDecValue->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown intrinsic function", iname);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
Eval(exp->mLeft->mDecValue->mValue);
|
Execute(exp->mLeft->mDecValue->mValue);
|
||||||
|
|
||||||
return mResult;
|
return mResult;
|
||||||
}
|
}
|
||||||
|
@ -920,9 +920,6 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
|
||||||
{
|
{
|
||||||
case EX_SCOPE:
|
case EX_SCOPE:
|
||||||
return Eval(exp->mLeft);
|
return Eval(exp->mLeft);
|
||||||
case EX_RETURN:
|
|
||||||
mResult = EvalCoerce(exp, Eval(exp->mLeft), mProcType->mBase);
|
|
||||||
return mResult;
|
|
||||||
case EX_CONSTANT:
|
case EX_CONSTANT:
|
||||||
return Value(exp);
|
return Value(exp);
|
||||||
case EX_VARIABLE:
|
case EX_VARIABLE:
|
||||||
|
@ -998,15 +995,6 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EX_SEQUENCE:
|
|
||||||
if (exp->mRight)
|
|
||||||
{
|
|
||||||
Eval(exp->mLeft);
|
|
||||||
return Eval(exp->mRight);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return Eval(exp->mLeft);
|
|
||||||
|
|
||||||
case EX_INITIALIZATION:
|
case EX_INITIALIZATION:
|
||||||
case EX_ASSIGNMENT:
|
case EX_ASSIGNMENT:
|
||||||
{
|
{
|
||||||
|
@ -1019,16 +1007,6 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
|
||||||
return lexp;
|
return lexp;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EX_IF:
|
|
||||||
{
|
|
||||||
Value v = REval(exp->mLeft);
|
|
||||||
if (v.GetInt())
|
|
||||||
Eval(exp->mRight->mLeft);
|
|
||||||
else if (exp->mRight->mRight)
|
|
||||||
Eval(exp->mRight->mRight);
|
|
||||||
return Value();
|
|
||||||
}
|
|
||||||
|
|
||||||
case EX_POSTINCDEC:
|
case EX_POSTINCDEC:
|
||||||
{
|
{
|
||||||
Value vl = Eval(exp->mLeft);
|
Value vl = Eval(exp->mLeft);
|
||||||
|
@ -1044,55 +1022,6 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
|
||||||
return vl;
|
return vl;
|
||||||
}
|
}
|
||||||
|
|
||||||
case EX_WHILE:
|
|
||||||
{
|
|
||||||
Value v = REval(exp->mLeft);
|
|
||||||
while (v.GetInt())
|
|
||||||
{
|
|
||||||
Eval(exp->mRight);
|
|
||||||
v = REval(exp->mLeft);
|
|
||||||
}
|
|
||||||
return Value();
|
|
||||||
}
|
|
||||||
|
|
||||||
case EX_DO:
|
|
||||||
{
|
|
||||||
Value v;
|
|
||||||
|
|
||||||
do {
|
|
||||||
Eval(exp->mRight);
|
|
||||||
v = REval(exp->mLeft);
|
|
||||||
} while (v.GetInt());
|
|
||||||
|
|
||||||
return Value();
|
|
||||||
}
|
|
||||||
|
|
||||||
case EX_FOR:
|
|
||||||
{
|
|
||||||
Value v;
|
|
||||||
|
|
||||||
if (exp->mLeft->mRight)
|
|
||||||
Eval(exp->mLeft->mRight);
|
|
||||||
|
|
||||||
if (exp->mLeft->mLeft->mLeft)
|
|
||||||
v = REval(exp->mLeft->mLeft->mLeft);
|
|
||||||
else
|
|
||||||
v.PutInt(1);
|
|
||||||
|
|
||||||
while (v.GetInt())
|
|
||||||
{
|
|
||||||
Eval(exp->mRight);
|
|
||||||
|
|
||||||
if (exp->mLeft->mLeft->mRight)
|
|
||||||
Eval(exp->mLeft->mLeft->mRight);
|
|
||||||
|
|
||||||
if (exp->mLeft->mLeft->mLeft)
|
|
||||||
v = REval(exp->mLeft->mLeft->mLeft);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Value();
|
|
||||||
}
|
|
||||||
|
|
||||||
case EX_QUALIFY:
|
case EX_QUALIFY:
|
||||||
{
|
{
|
||||||
Value v = Eval(exp->mLeft);
|
Value v = Eval(exp->mLeft);
|
||||||
|
@ -1108,12 +1037,12 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
|
||||||
if (v.mDecType->mType == DT_TYPE_ARRAY)
|
if (v.mDecType->mType == DT_TYPE_ARRAY)
|
||||||
{
|
{
|
||||||
if (v.mBaseValue)
|
if (v.mBaseValue)
|
||||||
return Value(v.mBaseValue, exp->mDecType, v.mOffset + v.mDecType->mBase->mSize * vi.GetInt());
|
return Value(v.mBaseValue, exp->mDecType, v.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt()));
|
||||||
}
|
}
|
||||||
else if (v.mDecType->mType == DT_TYPE_POINTER)
|
else if (v.mDecType->mType == DT_TYPE_POINTER)
|
||||||
{
|
{
|
||||||
Value p = v.GetPtr();
|
Value p = v.GetPtr();
|
||||||
return Value(p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * vi.GetInt());
|
return Value(p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1127,6 +1056,139 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp)
|
||||||
return exp;
|
return exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp)
|
||||||
|
{
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
switch (exp->mType)
|
||||||
|
{
|
||||||
|
case EX_SCOPE:
|
||||||
|
return Execute(exp->mLeft);
|
||||||
|
case EX_RETURN:
|
||||||
|
mResult = EvalCoerce(exp, Eval(exp->mLeft), mProcType->mBase);
|
||||||
|
return FLOW_RETURN;
|
||||||
|
case EX_CONSTANT:
|
||||||
|
case EX_VARIABLE:
|
||||||
|
case EX_BINARY:
|
||||||
|
case EX_RELATIONAL:
|
||||||
|
case EX_PREFIX:
|
||||||
|
case EX_TYPECAST:
|
||||||
|
case EX_CALL:
|
||||||
|
case EX_LIST:
|
||||||
|
case EX_CONDITIONAL:
|
||||||
|
case EX_LOGICAL_AND:
|
||||||
|
case EX_LOGICAL_OR:
|
||||||
|
case EX_LOGICAL_NOT:
|
||||||
|
case EX_INITIALIZATION:
|
||||||
|
case EX_ASSIGNMENT:
|
||||||
|
case EX_POSTINCDEC:
|
||||||
|
case EX_PREINCDEC:
|
||||||
|
case EX_QUALIFY:
|
||||||
|
case EX_INDEX:
|
||||||
|
Eval(exp);
|
||||||
|
return FLOW_NEXT;
|
||||||
|
|
||||||
|
case EX_SEQUENCE:
|
||||||
|
if (exp->mRight)
|
||||||
|
{
|
||||||
|
Flow f = Execute(exp->mLeft);
|
||||||
|
if (f == FLOW_NEXT)
|
||||||
|
return Execute(exp->mRight);
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Execute(exp->mLeft);
|
||||||
|
|
||||||
|
case EX_BREAK:
|
||||||
|
return FLOW_BREAK;
|
||||||
|
|
||||||
|
case EX_CONTINUE:
|
||||||
|
return FLOW_CONTINUE;
|
||||||
|
|
||||||
|
case EX_IF:
|
||||||
|
if (REval(exp->mLeft).GetInt())
|
||||||
|
return Execute(exp->mRight->mLeft);
|
||||||
|
else if (exp->mRight->mRight)
|
||||||
|
return Execute(exp->mRight->mRight);
|
||||||
|
else
|
||||||
|
return FLOW_NEXT;
|
||||||
|
|
||||||
|
case EX_SWITCH:
|
||||||
|
{
|
||||||
|
int64 v = REval(exp->mLeft).GetInt();
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
Expression* sexp = exp->mRight;
|
||||||
|
while (sexp)
|
||||||
|
{
|
||||||
|
Expression* cexp = sexp->mLeft;
|
||||||
|
if (found || cexp->mType == EX_DEFAULT || v == REval(cexp->mLeft).GetInt())
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
if (cexp->mRight)
|
||||||
|
{
|
||||||
|
Flow f = Execute(cexp->mRight);
|
||||||
|
if (f == FLOW_BREAK)
|
||||||
|
return FLOW_NEXT;
|
||||||
|
else if (f != FLOW_NEXT)
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sexp = sexp->mRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FLOW_NEXT;
|
||||||
|
}
|
||||||
|
|
||||||
|
case EX_WHILE:
|
||||||
|
while (REval(exp->mLeft).GetInt())
|
||||||
|
{
|
||||||
|
Flow f = Execute(exp->mRight);
|
||||||
|
if (f == FLOW_RETURN)
|
||||||
|
return FLOW_RETURN;
|
||||||
|
else if (f == FLOW_BREAK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return FLOW_NEXT;
|
||||||
|
|
||||||
|
case EX_DO:
|
||||||
|
do {
|
||||||
|
Flow f = Execute(exp->mRight);
|
||||||
|
if (f == FLOW_RETURN)
|
||||||
|
return FLOW_RETURN;
|
||||||
|
else if (f == FLOW_BREAK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
} while (REval(exp->mLeft).GetInt());
|
||||||
|
return FLOW_NEXT;
|
||||||
|
|
||||||
|
case EX_FOR:
|
||||||
|
if (exp->mLeft->mRight)
|
||||||
|
Eval(exp->mLeft->mRight);
|
||||||
|
|
||||||
|
while (!exp->mLeft->mLeft->mLeft || REval(exp->mLeft->mLeft->mLeft).GetInt())
|
||||||
|
{
|
||||||
|
Flow f = Execute(exp->mRight);
|
||||||
|
if (f == FLOW_RETURN)
|
||||||
|
return FLOW_RETURN;
|
||||||
|
else if (f == FLOW_BREAK)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (exp->mLeft->mLeft->mRight)
|
||||||
|
Eval(exp->mLeft->mLeft->mRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FLOW_NEXT;
|
||||||
|
|
||||||
|
case EX_VOID:
|
||||||
|
return FLOW_NEXT;
|
||||||
|
|
||||||
|
default:
|
||||||
|
mErrors->Error(exp->mLocation, EERR_INVALID_CONSTEXPR, "Invalid constexpr");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ConstexprInterpreter::ValueItem::ValueItem(void)
|
ConstexprInterpreter::ValueItem::ValueItem(void)
|
||||||
: mByte(0), mBaseValue(nullptr)
|
: mByte(0), mBaseValue(nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -80,6 +80,16 @@ protected:
|
||||||
Value REval(Expression* exp);
|
Value REval(Expression* exp);
|
||||||
Value Eval(Expression* exp);
|
Value Eval(Expression* exp);
|
||||||
|
|
||||||
|
enum Flow
|
||||||
|
{
|
||||||
|
FLOW_NEXT,
|
||||||
|
FLOW_CONTINUE,
|
||||||
|
FLOW_BREAK,
|
||||||
|
FLOW_RETURN
|
||||||
|
};
|
||||||
|
|
||||||
|
Flow Execute(Expression* exp);
|
||||||
|
|
||||||
Declaration* mProcType;
|
Declaration* mProcType;
|
||||||
Location mLocation;
|
Location mLocation;
|
||||||
LinkerSection* mDataSection;
|
LinkerSection* mDataSection;
|
||||||
|
|
|
@ -5695,7 +5695,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs)
|
||||||
nexp->mType = EX_VCALL;
|
nexp->mType = EX_VCALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
exp = nexp;
|
exp = nexp->ConstantFold(mErrors, mDataSection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC)
|
else if (mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC)
|
||||||
|
|
Loading…
Reference in New Issue