mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-05-30 08:31:29 +00:00
- implemented '**' (power) operator. To ensure reliability, acustom 'pow' function will be used to calculate it.
- fixed: FxBinary::ResolveLR' check for numeric operations was incomplete. Like far too many other places it just assumed that everything with ValueType->GetRegType() == REGT_INT is a numeric type, but for names this is not the case.
This commit is contained in:
parent
d0a8960f61
commit
938ab4ca70
10 changed files with 1033 additions and 10 deletions
|
@ -1824,13 +1824,16 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric)
|
|||
{
|
||||
ValueType = TypeBool;
|
||||
}
|
||||
if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT)
|
||||
{
|
||||
ValueType = TypeSInt32;
|
||||
}
|
||||
else if (left->IsNumeric() && right->IsNumeric())
|
||||
{
|
||||
ValueType = TypeFloat64;
|
||||
if (left->ValueType->GetRegType() == REGT_INT && right->ValueType->GetRegType() == REGT_INT)
|
||||
{
|
||||
ValueType = TypeSInt32;
|
||||
}
|
||||
else
|
||||
{
|
||||
ValueType = TypeFloat64;
|
||||
}
|
||||
}
|
||||
else if (left->ValueType->GetRegType() == REGT_POINTER && left->ValueType == right->ValueType)
|
||||
{
|
||||
|
@ -2137,6 +2140,60 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
FxPow::FxPow(FxExpression *l, FxExpression *r)
|
||||
: FxBinary(TK_MulMul, new FxFloatCast(l), new FxFloatCast(r))
|
||||
{
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxExpression *FxPow::Resolve(FCompileContext& ctx)
|
||||
{
|
||||
CHECKRESOLVED();
|
||||
|
||||
if (!ResolveLR(ctx, true)) return NULL;
|
||||
|
||||
if (left->isConstant() && right->isConstant())
|
||||
{
|
||||
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
||||
double v2 = static_cast<FxConstant *>(right)->GetValue().GetFloat();
|
||||
return new FxConstant(g_pow(v1, v2), left->ScriptPosition);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
ExpEmit FxPow::Emit(VMFunctionBuilder *build)
|
||||
{
|
||||
ExpEmit op1 = left->Emit(build);
|
||||
ExpEmit op2 = right->Emit(build);
|
||||
|
||||
// Pow is not commutative, so either side may be constant (but not both).
|
||||
assert(!op1.Konst || !op2.Konst);
|
||||
op1.Free(build);
|
||||
op2.Free(build);
|
||||
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
|
||||
ExpEmit to(build, REGT_FLOAT);
|
||||
build->Emit((op1.Konst ? OP_POWF_KR : op2.Konst ? OP_POWF_RK : OP_POWF_RR), to.RegNum, op1.RegNum, op2.RegNum);
|
||||
return to;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FxCompareRel::FxCompareRel(int o, FxExpression *l, FxExpression *r)
|
||||
: FxBinary(o, l, r)
|
||||
{
|
||||
|
|
|
@ -686,6 +686,21 @@ public:
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxPow : public FxBinary
|
||||
{
|
||||
public:
|
||||
|
||||
FxPow(FxExpression*, FxExpression*);
|
||||
FxExpression *Resolve(FCompileContext&);
|
||||
ExpEmit Emit(VMFunctionBuilder *build);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FxBinary
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FxCompareRel : public FxBinary
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -1055,15 +1055,15 @@ begin:
|
|||
|
||||
OP(POWF_RR):
|
||||
ASSERTF(a); ASSERTF(B); ASSERTF(C);
|
||||
reg.f[a] = pow(reg.f[B], reg.f[C]);
|
||||
reg.f[a] = g_pow(reg.f[B], reg.f[C]);
|
||||
NEXTOP;
|
||||
OP(POWF_RK):
|
||||
ASSERTF(a); ASSERTF(B); ASSERTKF(C);
|
||||
reg.f[a] = pow(reg.f[B], konstf[C]);
|
||||
reg.f[a] = g_pow(reg.f[B], konstf[C]);
|
||||
NEXTOP;
|
||||
OP(POWF_KR):
|
||||
ASSERTF(a); ASSERTKF(B); ASSERTF(C);
|
||||
reg.f[a] = pow(konstf[B], reg.f[C]);
|
||||
reg.f[a] = g_pow(konstf[B], reg.f[C]);
|
||||
NEXTOP;
|
||||
|
||||
OP(MINF_RR):
|
||||
|
|
|
@ -2422,6 +2422,9 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
|
|||
case PEX_Mod:
|
||||
return new FxMulDiv(op == PEX_Mul ? '*' : op == PEX_Div ? '/' : '%', left, right);
|
||||
|
||||
case PEX_Pow:
|
||||
return new FxPow(left, right);
|
||||
|
||||
default:
|
||||
I_Error("Binary operator %d not implemented yet", op);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "m_alloc.h"
|
||||
#include "zcc_parser.h"
|
||||
#include "templates.h"
|
||||
#include "math/cmath.h"
|
||||
|
||||
#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
|
||||
|
||||
|
@ -332,7 +333,7 @@ void ZCC_InitOperators()
|
|||
{ PEX_Mod , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, [](auto *l, auto *r, auto &) { l->UIntVal %= r->UIntVal; return l; } },
|
||||
{ PEX_Mod , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal = luai_nummod(l->DoubleVal, r->DoubleVal); return l; } },
|
||||
|
||||
{ PEX_Pow , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal = pow(l->DoubleVal, r->DoubleVal); return l; } },
|
||||
{ PEX_Pow , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, [](auto *l, auto *r, auto &) { l->DoubleVal = g_pow(l->DoubleVal, r->DoubleVal); return l; } },
|
||||
|
||||
{ PEX_Concat , (PType **)&TypeString, (PType **)&TypeString, (PType **)&TypeString, EvalConcat },
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue