2013-10-24 04:06:32 +00:00
|
|
|
#include "dobject.h"
|
|
|
|
#include "sc_man.h"
|
|
|
|
#include "c_console.h"
|
|
|
|
#include "c_dispatch.h"
|
|
|
|
#include "w_wad.h"
|
|
|
|
#include "cmdlib.h"
|
|
|
|
#include "m_alloc.h"
|
|
|
|
#include "zcc_parser.h"
|
|
|
|
#include "templates.h"
|
|
|
|
|
|
|
|
#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b))
|
|
|
|
|
|
|
|
ZCC_OpInfoType ZCC_OpInfo[PEX_COUNT_OF] =
|
|
|
|
{
|
2013-11-02 02:28:00 +00:00
|
|
|
#define xx(a,z) { #a, NULL },
|
2013-10-24 04:06:32 +00:00
|
|
|
#include "zcc_exprlist.h"
|
|
|
|
};
|
|
|
|
|
|
|
|
// Structures used for initializing operator overloads
|
|
|
|
struct OpProto1
|
|
|
|
{
|
|
|
|
EZCCExprType Op;
|
|
|
|
PType **Type;
|
|
|
|
EvalConst1op EvalConst;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct OpProto2
|
|
|
|
{
|
|
|
|
EZCCExprType Op;
|
|
|
|
PType **Res, **Ltype, **Rtype;
|
|
|
|
EvalConst2op EvalConst;
|
|
|
|
};
|
|
|
|
|
|
|
|
void ZCC_OpInfoType::AddProto(PType *res, PType *optype, EvalConst1op evalconst)
|
|
|
|
{
|
|
|
|
ZCC_OpProto *proto = new ZCC_OpProto(res, optype, NULL);
|
|
|
|
proto->EvalConst1 = evalconst;
|
|
|
|
proto->Next = Protos;
|
|
|
|
Protos = proto;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ZCC_OpInfoType::AddProto(PType *res, PType *ltype, PType *rtype, EvalConst2op evalconst)
|
|
|
|
{
|
|
|
|
assert(ltype != NULL);
|
|
|
|
ZCC_OpProto *proto = new ZCC_OpProto(res, ltype, rtype);
|
|
|
|
proto->EvalConst2 = evalconst;
|
|
|
|
proto->Next = Protos;
|
|
|
|
Protos = proto;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// ZCC_OpInfoType :: FindBestProto (Unary)
|
|
|
|
//
|
|
|
|
// Finds the "best" prototype for this operand type. Best is defined as the
|
|
|
|
// one that requires the fewest conversions. Also returns the conversion
|
|
|
|
// route necessary to get from the input type to the desired type.
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
ZCC_OpProto *ZCC_OpInfoType::FindBestProto(PType *optype, const PType::Conversion **route, int &numslots)
|
|
|
|
{
|
|
|
|
assert(optype != NULL);
|
|
|
|
|
|
|
|
const PType::Conversion *routes[2][CONVERSION_ROUTE_SIZE];
|
|
|
|
const PType::Conversion **best_route = NULL;
|
|
|
|
int cur_route = 0;
|
|
|
|
ZCC_OpProto *best_proto = NULL;
|
|
|
|
int best_dist = INT_MAX;
|
|
|
|
|
|
|
|
// Find the best prototype.
|
|
|
|
for (ZCC_OpProto *proto = Protos; best_dist != 0 && proto != NULL; proto = proto->Next)
|
|
|
|
{
|
|
|
|
if (proto->Type2 != NULL)
|
|
|
|
{ // Not a unary prototype.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int dist = optype->FindConversion(proto->Type1, routes[cur_route], CONVERSION_ROUTE_SIZE);
|
|
|
|
if (dist >= 0 && dist < best_dist)
|
|
|
|
{
|
|
|
|
best_dist = dist;
|
|
|
|
best_proto = proto;
|
|
|
|
best_route = routes[cur_route];
|
|
|
|
cur_route ^= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Copy best conversion route to the caller's array.
|
|
|
|
if (best_route != NULL && route != NULL && numslots > 0)
|
|
|
|
{
|
|
|
|
numslots = MIN(numslots, best_dist);
|
|
|
|
if (numslots > 0)
|
|
|
|
{
|
|
|
|
memcpy(route, best_route, sizeof(*route) * numslots);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return best_proto;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// ZCC_OpInfoType :: FindBestProto (Binary)
|
|
|
|
//
|
|
|
|
// Finds the "best" prototype for the given operand types. Here, best is
|
|
|
|
// defined as the one that requires the fewest conversions for *one* of the
|
|
|
|
// operands. For prototypes with matching distances, the first one found
|
|
|
|
// is used. ZCC_InitOperators() initializes the prototypes in order such
|
|
|
|
// that this will result in the precedences: double > uint > int
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
ZCC_OpProto *ZCC_OpInfoType::FindBestProto(
|
|
|
|
PType *left, const PType::Conversion **route1, int &numslots1,
|
|
|
|
PType *right, const PType::Conversion **route2, int &numslots2)
|
|
|
|
{
|
|
|
|
assert(left != NULL && right != NULL);
|
|
|
|
|
|
|
|
const PType::Conversion *routes[2][2][CONVERSION_ROUTE_SIZE];
|
|
|
|
const PType::Conversion **best_route1 = NULL, **best_route2 = NULL;
|
|
|
|
int cur_route1 = 0, cur_route2 = 0;
|
|
|
|
int best_dist1 = INT_MAX, best_dist2 = INT_MAX;
|
|
|
|
|
|
|
|
ZCC_OpProto *best_proto = NULL;
|
|
|
|
int best_low_dist = INT_MAX;
|
|
|
|
|
|
|
|
for (ZCC_OpProto *proto = Protos; best_low_dist != 0 && proto != NULL; proto = proto->Next)
|
|
|
|
{
|
|
|
|
if (proto->Type2 == NULL)
|
|
|
|
{ // Not a binary prototype
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int dist1 = left->FindConversion(proto->Type1, routes[0][cur_route1], CONVERSION_ROUTE_SIZE);
|
|
|
|
int dist2 = right->FindConversion(proto->Type2, routes[1][cur_route2], CONVERSION_ROUTE_SIZE);
|
|
|
|
if (dist1 < 0 || dist2 < 0)
|
|
|
|
{ // one or both operator types are unreachable
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int dist = MIN(dist1, dist2);
|
|
|
|
if (dist < best_low_dist)
|
|
|
|
{
|
|
|
|
best_low_dist = dist;
|
|
|
|
best_proto = proto;
|
|
|
|
best_dist1 = dist1;
|
|
|
|
best_dist2 = dist2;
|
|
|
|
best_route1 = routes[0][cur_route1];
|
|
|
|
best_route2 = routes[1][cur_route2];
|
|
|
|
cur_route1 ^= 1;
|
|
|
|
cur_route2 ^= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Copy best conversion route to the caller's arrays.
|
|
|
|
if (best_route1 != NULL && route1 != NULL && numslots1 > 0)
|
|
|
|
{
|
|
|
|
numslots1 = MIN(numslots1, best_dist1);
|
|
|
|
if (numslots1 > 0)
|
|
|
|
{
|
|
|
|
memcpy(route1, best_route1, sizeof(*route1) * numslots1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (best_route2 != NULL && route2 != NULL && numslots2 > 0)
|
|
|
|
{
|
|
|
|
numslots2 = MIN(numslots2, best_dist2);
|
|
|
|
if (numslots2 > 0)
|
|
|
|
{
|
|
|
|
memcpy(route2, best_route2, sizeof(*route2) * numslots2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return best_proto;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalIncFloat64(ZCC_ExprConstant *val)
|
|
|
|
{
|
|
|
|
val->DoubleVal++;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalIncInt32(ZCC_ExprConstant *val)
|
|
|
|
{
|
|
|
|
val->IntVal++;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalDecFloat64(ZCC_ExprConstant *val)
|
|
|
|
{
|
|
|
|
val->DoubleVal--;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalDecInt32(ZCC_ExprConstant *val)
|
|
|
|
{
|
|
|
|
val->IntVal--;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalNegateFloat64(ZCC_ExprConstant *val)
|
|
|
|
{
|
|
|
|
val->DoubleVal = -val->DoubleVal;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalNegateInt32(ZCC_ExprConstant *val)
|
|
|
|
{
|
|
|
|
val->IntVal = -val->IntVal;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalIdentity(ZCC_ExprConstant *val)
|
|
|
|
{
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalBitNot(ZCC_ExprConstant *val)
|
|
|
|
{
|
|
|
|
val->IntVal = ~val->IntVal;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalBoolNot(ZCC_ExprConstant *val)
|
|
|
|
{
|
|
|
|
val->IntVal = !val->IntVal;
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalAddFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->DoubleVal += r->DoubleVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalAddInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal += r->IntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalSubFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->DoubleVal -= r->DoubleVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalSubInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal -= r->IntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalMulFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->DoubleVal *= r->DoubleVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalMulUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->UIntVal *= r->UIntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalMulSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal *= r->IntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalDivFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->DoubleVal /= r->DoubleVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalDivUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->UIntVal /= r->UIntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalDivSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal /= r->IntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalModFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->DoubleVal = luai_nummod(l->DoubleVal, r->DoubleVal);
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalModUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->UIntVal %= r->UIntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalModSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal %= r->IntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalPow(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->DoubleVal = pow(l->DoubleVal, r->DoubleVal);
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalConcat(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &strings)
|
|
|
|
{
|
|
|
|
FString str = *l->StringVal + *r->StringVal;
|
|
|
|
l->StringVal = strings.Alloc(str);
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalBitAnd(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal &= r->IntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalBitOr(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal |= r->IntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalBitXor(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal ^= r->IntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalBoolAnd(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->IntVal && r->IntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalBoolOr(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->IntVal || r->IntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalSHL(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal <<= r->UIntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalSHR_S(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal >>= r->UIntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalSHR_U(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->UIntVal >>= r->UIntVal;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalLTSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->IntVal < r->IntVal;
|
|
|
|
l->Type = TypeBool;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalLTUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->UIntVal < r->UIntVal;
|
|
|
|
l->Type = TypeBool;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalLTFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->DoubleVal < r->DoubleVal;
|
|
|
|
l->Type = TypeBool;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalLTEQSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->IntVal <= r->IntVal;
|
|
|
|
l->Type = TypeBool;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalLTEQUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->UIntVal <= r->UIntVal;
|
|
|
|
l->Type = TypeBool;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalLTEQFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->DoubleVal <= r->DoubleVal;
|
|
|
|
l->Type = TypeBool;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalEQEQSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->IntVal == r->IntVal;
|
|
|
|
l->Type = TypeBool;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalEQEQUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->UIntVal == r->UIntVal;
|
|
|
|
l->Type = TypeBool;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalEQEQFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->DoubleVal == r->DoubleVal;
|
|
|
|
l->Type = TypeBool;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalLTGTEQSInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->IntVal < r->IntVal ? -1 : l->IntVal == r->IntVal ? 0 : 1;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalLTGTEQUInt32(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->UIntVal < r->UIntVal ? -1 : l->UIntVal == r->UIntVal ? 0 : 1;
|
|
|
|
l->Type = TypeSInt32;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ZCC_ExprConstant *EvalLTGTEQFloat64(ZCC_ExprConstant *l, ZCC_ExprConstant *r, FSharedStringArena &)
|
|
|
|
{
|
|
|
|
l->IntVal = l->DoubleVal < r->DoubleVal ? -1 : l->DoubleVal == r->DoubleVal ? 0 : 1;
|
|
|
|
l->Type = TypeSInt32;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ZCC_InitOperators()
|
|
|
|
{
|
|
|
|
// Prototypes are added from lowest to highest conversion precedence.
|
|
|
|
|
|
|
|
// Unary operators
|
|
|
|
static const OpProto1 UnaryOpInit[] =
|
|
|
|
{
|
|
|
|
{ PEX_PostInc , (PType **)&TypeSInt32, EvalIdentity },
|
|
|
|
{ PEX_PostInc , (PType **)&TypeUInt32, EvalIdentity },
|
|
|
|
{ PEX_PostInc , (PType **)&TypeFloat64, EvalIdentity },
|
|
|
|
|
|
|
|
{ PEX_PostDec , (PType **)&TypeSInt32, EvalIdentity },
|
|
|
|
{ PEX_PostDec , (PType **)&TypeUInt32, EvalIdentity },
|
|
|
|
{ PEX_PostDec , (PType **)&TypeFloat64, EvalIdentity },
|
|
|
|
|
|
|
|
{ PEX_PreInc , (PType **)&TypeSInt32, EvalIncInt32 },
|
|
|
|
{ PEX_PreInc , (PType **)&TypeUInt32, EvalIncInt32 },
|
|
|
|
{ PEX_PreInc , (PType **)&TypeFloat64, EvalIncFloat64 },
|
|
|
|
|
|
|
|
{ PEX_PreDec , (PType **)&TypeSInt32, EvalDecInt32 },
|
|
|
|
{ PEX_PreDec , (PType **)&TypeUInt32, EvalDecInt32 },
|
|
|
|
{ PEX_PreDec , (PType **)&TypeFloat64, EvalDecFloat64 },
|
|
|
|
|
|
|
|
{ PEX_Negate , (PType **)&TypeSInt32, EvalNegateInt32 },
|
|
|
|
{ PEX_Negate , (PType **)&TypeFloat64, EvalNegateFloat64 },
|
|
|
|
|
|
|
|
{ PEX_AntiNegate , (PType **)&TypeSInt32, EvalIdentity },
|
|
|
|
{ PEX_AntiNegate , (PType **)&TypeUInt32, EvalIdentity },
|
|
|
|
{ PEX_AntiNegate , (PType **)&TypeFloat64, EvalIdentity },
|
|
|
|
|
|
|
|
{ PEX_BitNot , (PType **)&TypeSInt32, EvalBitNot },
|
|
|
|
{ PEX_BitNot , (PType **)&TypeUInt32, EvalBitNot },
|
|
|
|
|
|
|
|
{ PEX_BoolNot , (PType **)&TypeBool, EvalBoolNot },
|
|
|
|
};
|
|
|
|
for (size_t i = 0; i < countof(UnaryOpInit); ++i)
|
|
|
|
{
|
|
|
|
ZCC_OpInfo[UnaryOpInit[i].Op].AddProto(*UnaryOpInit[i].Type, *UnaryOpInit[i].Type, UnaryOpInit[i].EvalConst);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Binary operators
|
|
|
|
static const OpProto2 BinaryOpInit[] =
|
|
|
|
{
|
|
|
|
{ PEX_Add , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalAddInt32 },
|
|
|
|
{ PEX_Add , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalAddInt32 },
|
|
|
|
{ PEX_Add , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalAddFloat64 },
|
|
|
|
|
|
|
|
{ PEX_Sub , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalSubInt32 },
|
|
|
|
{ PEX_Sub , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalSubInt32 },
|
|
|
|
{ PEX_Sub , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalSubFloat64 },
|
|
|
|
|
|
|
|
{ PEX_Mul , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalMulSInt32 },
|
|
|
|
{ PEX_Mul , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalMulUInt32 },
|
|
|
|
{ PEX_Mul , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalMulFloat64 },
|
|
|
|
|
|
|
|
{ PEX_Div , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalDivSInt32 },
|
|
|
|
{ PEX_Div , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalDivUInt32 },
|
|
|
|
{ PEX_Div , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalDivFloat64 },
|
|
|
|
|
|
|
|
{ PEX_Mod , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalModSInt32 },
|
|
|
|
{ PEX_Mod , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalModUInt32 },
|
|
|
|
{ PEX_Mod , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalModFloat64 },
|
|
|
|
|
|
|
|
{ PEX_Pow , (PType **)&TypeFloat64, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalPow },
|
|
|
|
|
|
|
|
{ PEX_Concat , (PType **)&TypeString, (PType **)&TypeString, (PType **)&TypeString, EvalConcat },
|
|
|
|
|
|
|
|
{ PEX_BitAnd , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalBitAnd },
|
|
|
|
{ PEX_BitAnd , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalBitAnd },
|
|
|
|
|
|
|
|
{ PEX_BitOr , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalBitOr },
|
|
|
|
{ PEX_BitOr , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalBitOr },
|
|
|
|
|
|
|
|
{ PEX_BitXor , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalBitXor },
|
|
|
|
{ PEX_BitXor , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalBitXor },
|
|
|
|
|
|
|
|
{ PEX_BoolAnd , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalBoolAnd },
|
|
|
|
{ PEX_BoolAnd , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalBoolAnd },
|
|
|
|
|
|
|
|
{ PEX_BoolOr , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalBoolOr },
|
|
|
|
{ PEX_BoolOr , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalBoolOr },
|
|
|
|
|
|
|
|
{ PEX_LeftShift , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeUInt32, EvalSHL },
|
|
|
|
{ PEX_LeftShift , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalSHL },
|
|
|
|
|
|
|
|
{ PEX_RightShift , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeUInt32, EvalSHR_S },
|
|
|
|
{ PEX_RightShift , (PType **)&TypeUInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalSHR_U },
|
|
|
|
|
|
|
|
{ PEX_LT , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalLTSInt32 },
|
|
|
|
{ PEX_LT , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalLTUInt32 },
|
|
|
|
{ PEX_LT , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalLTFloat64 },
|
|
|
|
|
|
|
|
{ PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalLTEQSInt32 },
|
|
|
|
{ PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalLTEQUInt32 },
|
|
|
|
{ PEX_LTEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalLTEQFloat64 },
|
|
|
|
|
|
|
|
{ PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalEQEQSInt32 },
|
|
|
|
{ PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalEQEQUInt32 },
|
|
|
|
{ PEX_EQEQ , (PType **)&TypeBool, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalEQEQFloat64 },
|
|
|
|
|
|
|
|
{ PEX_LTGTEQ , (PType **)&TypeSInt32, (PType **)&TypeSInt32, (PType **)&TypeSInt32, EvalLTGTEQSInt32 },
|
|
|
|
{ PEX_LTGTEQ , (PType **)&TypeSInt32, (PType **)&TypeUInt32, (PType **)&TypeUInt32, EvalLTGTEQUInt32 },
|
|
|
|
{ PEX_LTGTEQ , (PType **)&TypeSInt32, (PType **)&TypeFloat64, (PType **)&TypeFloat64, EvalLTGTEQFloat64 },
|
|
|
|
};
|
|
|
|
for (size_t i = 0; i < countof(BinaryOpInit); ++i)
|
|
|
|
{
|
|
|
|
ZCC_OpInfo[BinaryOpInit[i].Op].AddProto(*BinaryOpInit[i].Res, *BinaryOpInit[i].Ltype, *BinaryOpInit[i].Rtype, BinaryOpInit[i].EvalConst);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void IntToS32(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
// Integers always fill out the full sized 32-bit field, so converting
|
|
|
|
// from a smaller sized integer to a 32-bit one is as simple as changing
|
|
|
|
// the type field.
|
|
|
|
expr->Type = TypeSInt32;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void S32toS8(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
expr->IntVal = ((expr->IntVal << 24) >> 24);
|
|
|
|
expr->Type = TypeSInt8;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void S32toS16(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
expr->IntVal = ((expr->IntVal << 16) >> 16);
|
|
|
|
expr->Type = TypeSInt16;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void S32toU8(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
expr->IntVal &= 0xFF;
|
|
|
|
expr->Type = TypeUInt8;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void S32toU16(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
expr->IntVal &= 0xFFFF;
|
|
|
|
expr->Type = TypeUInt16;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void S32toU32(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
expr->Type = TypeUInt32;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void S32toD(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
expr->DoubleVal = expr->IntVal;
|
|
|
|
expr->Type = TypeFloat64;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DtoS32(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
expr->IntVal = (int)expr->DoubleVal;
|
|
|
|
expr->Type = TypeSInt32;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void U32toD(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
expr->DoubleVal = expr->UIntVal;
|
|
|
|
expr->Type = TypeFloat64;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DtoU32(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
expr->UIntVal = (unsigned int)expr->DoubleVal;
|
|
|
|
expr->Type = TypeUInt32;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void S32toS(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
char str[16];
|
|
|
|
int len = mysnprintf(str, countof(str), "%i", expr->IntVal);
|
|
|
|
expr->StringVal = str_arena.Alloc(str, len);
|
|
|
|
expr->Type = TypeString;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void U32toS(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
char str[16];
|
|
|
|
int len = mysnprintf(str, countof(str), "%u", expr->UIntVal);
|
|
|
|
expr->StringVal = str_arena.Alloc(str, len);
|
|
|
|
expr->Type = TypeString;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void DtoS(ZCC_ExprConstant *expr, FSharedStringArena &str_arena)
|
|
|
|
{
|
|
|
|
// Convert to a string with enough precision such that converting
|
|
|
|
// back to a double will not lose any data.
|
|
|
|
char str[64];
|
|
|
|
int len = mysnprintf(str, countof(str), "%H", expr->DoubleVal);
|
|
|
|
expr->StringVal = str_arena.Alloc(str, len);
|
|
|
|
expr->Type = TypeString;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// ZCC_InitConversions
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void ZCC_InitConversions()
|
|
|
|
{
|
|
|
|
TypeUInt8->AddConversion(TypeSInt32, IntToS32);
|
|
|
|
TypeSInt8->AddConversion(TypeSInt32, IntToS32);
|
|
|
|
TypeUInt16->AddConversion(TypeSInt32, IntToS32);
|
|
|
|
TypeSInt16->AddConversion(TypeSInt32, IntToS32);
|
|
|
|
|
|
|
|
TypeUInt32->AddConversion(TypeSInt32, IntToS32);
|
|
|
|
TypeUInt32->AddConversion(TypeFloat64, U32toD);
|
|
|
|
TypeUInt32->AddConversion(TypeString, U32toS);
|
|
|
|
|
|
|
|
TypeSInt32->AddConversion(TypeUInt8, S32toU8);
|
|
|
|
TypeSInt32->AddConversion(TypeSInt8, S32toS8);
|
|
|
|
TypeSInt32->AddConversion(TypeSInt16, S32toS16);
|
|
|
|
TypeSInt32->AddConversion(TypeUInt16, S32toU16);
|
|
|
|
TypeSInt32->AddConversion(TypeUInt32, S32toU32);
|
|
|
|
TypeSInt32->AddConversion(TypeFloat64, S32toD);
|
|
|
|
TypeSInt32->AddConversion(TypeString, S32toS);
|
|
|
|
|
|
|
|
TypeFloat64->AddConversion(TypeUInt32, DtoU32);
|
|
|
|
TypeFloat64->AddConversion(TypeSInt32, DtoS32);
|
|
|
|
TypeFloat64->AddConversion(TypeString, DtoS);
|
|
|
|
}
|