- 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:
Christoph Oelckers 2016-10-17 15:17:48 +02:00
parent d0a8960f61
commit 938ab4ca70
10 changed files with 1033 additions and 10 deletions

View file

@ -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)
{

View file

@ -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:

View file

@ -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):

View file

@ -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);
}

View file

@ -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 },