mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-28 23:12:24 +00:00
- added string handling to comparison operators.
This commit is contained in:
parent
853c6f6684
commit
78a18acf46
3 changed files with 199 additions and 81 deletions
|
@ -676,7 +676,7 @@ FxExpression *FxBoolCast::Resolve(FCompileContext &ctx)
|
||||||
delete this;
|
delete this;
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
else if ((basex->ValueType->GetRegType() == REGT_INT || basex->ValueType->GetRegType() == REGT_FLOAT || basex->ValueType->GetRegType() == REGT_POINTER) && !basex->IsVector())
|
else if (basex->IsBoolCompat())
|
||||||
{
|
{
|
||||||
if (basex->isConstant())
|
if (basex->isConstant())
|
||||||
{
|
{
|
||||||
|
@ -797,7 +797,7 @@ FxExpression *FxIntCast::Resolve(FCompileContext &ctx)
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (basex->ValueType->GetRegType() == REGT_FLOAT && !basex->IsVector())
|
else if (basex->IsFloat())
|
||||||
{
|
{
|
||||||
if (basex->isConstant())
|
if (basex->isConstant())
|
||||||
{
|
{
|
||||||
|
@ -875,7 +875,7 @@ FxExpression *FxFloatCast::Resolve(FCompileContext &ctx)
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
SAFE_RESOLVE(basex, ctx);
|
SAFE_RESOLVE(basex, ctx);
|
||||||
|
|
||||||
if (basex->ValueType->GetRegType() == REGT_FLOAT && !basex->IsVector())
|
if (basex->IsFloat())
|
||||||
{
|
{
|
||||||
FxExpression *x = basex;
|
FxExpression *x = basex;
|
||||||
basex = NULL;
|
basex = NULL;
|
||||||
|
@ -1325,7 +1325,7 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
|
||||||
{
|
{
|
||||||
goto basereturn;
|
goto basereturn;
|
||||||
}
|
}
|
||||||
else if (ValueType->GetRegType() == REGT_FLOAT && !IsVector())
|
else if (IsFloat())
|
||||||
{
|
{
|
||||||
FxExpression *x = new FxFloatCast(basex);
|
FxExpression *x = new FxFloatCast(basex);
|
||||||
x = x->Resolve(ctx);
|
x = x->Resolve(ctx);
|
||||||
|
@ -1635,7 +1635,7 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx)
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
SAFE_RESOLVE(Operand, ctx);
|
SAFE_RESOLVE(Operand, ctx);
|
||||||
|
|
||||||
if (ctx.FromDecorate && Operand->IsNumeric() && Operand->ValueType->GetRegType() == REGT_FLOAT /* lax */)
|
if (ctx.FromDecorate && Operand->IsFloat() /* lax */)
|
||||||
{
|
{
|
||||||
// DECORATE allows floats here so cast them to int.
|
// DECORATE allows floats here so cast them to int.
|
||||||
Operand = new FxIntCast(Operand, true);
|
Operand = new FxIntCast(Operand, true);
|
||||||
|
@ -1648,7 +1648,7 @@ FxExpression *FxUnaryNotBitwise::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Names were not blocked in DECORATE here after the scripting branch merge. Now they are again.
|
// Names were not blocked in DECORATE here after the scripting branch merge. Now they are again.
|
||||||
if (Operand->ValueType->GetRegType() != REGT_INT || Operand->ValueType == TypeName)
|
if (!Operand->IsInteger())
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Integer type expected");
|
ScriptPosition.Message(MSG_ERROR, "Integer type expected");
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -2281,7 +2281,51 @@ bool FxBinary::ResolveLR(FCompileContext& ctx, bool castnumeric)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left->IsVector() || right->IsVector())
|
if (left->ValueType == TypeString || right->ValueType == TypeString)
|
||||||
|
{
|
||||||
|
switch (Operator)
|
||||||
|
{
|
||||||
|
case '+':
|
||||||
|
// later
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
case TK_Geq:
|
||||||
|
case TK_Leq:
|
||||||
|
case TK_Eq:
|
||||||
|
case TK_Neq:
|
||||||
|
case TK_ApproxEq:
|
||||||
|
if (left->ValueType != TypeString)
|
||||||
|
{
|
||||||
|
left = new FxStringCast(left);
|
||||||
|
left = left->Resolve(ctx);
|
||||||
|
if (left == nullptr)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (right->ValueType != TypeString)
|
||||||
|
{
|
||||||
|
right = new FxStringCast(right);
|
||||||
|
right = right->Resolve(ctx);
|
||||||
|
if (right == nullptr)
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ValueType = TypeBool;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ScriptPosition.Message(MSG_ERROR, "Incompatible operands for comparison");
|
||||||
|
delete this;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (left->IsVector() || right->IsVector())
|
||||||
{
|
{
|
||||||
switch (Operator)
|
switch (Operator)
|
||||||
{
|
{
|
||||||
|
@ -2466,7 +2510,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
else if (left->isConstant() && right->isConstant())
|
else if (left->isConstant() && right->isConstant())
|
||||||
{
|
{
|
||||||
if (ValueType->GetRegType() == REGT_FLOAT)
|
if (IsFloat())
|
||||||
{
|
{
|
||||||
double v;
|
double v;
|
||||||
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
||||||
|
@ -2605,7 +2649,7 @@ FxExpression *FxMulDiv::Resolve(FCompileContext& ctx)
|
||||||
}
|
}
|
||||||
else if (left->isConstant() && right->isConstant())
|
else if (left->isConstant() && right->isConstant())
|
||||||
{
|
{
|
||||||
if (ValueType->GetRegType() == REGT_FLOAT)
|
if (IsFloat())
|
||||||
{
|
{
|
||||||
double v;
|
double v;
|
||||||
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
||||||
|
@ -2834,7 +2878,17 @@ FxExpression *FxCompareRel::Resolve(FCompileContext& ctx)
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
|
|
||||||
if (ValueType->GetRegType() == REGT_FLOAT)
|
if (ValueType == TypeString)
|
||||||
|
{
|
||||||
|
FString v1 = static_cast<FxConstant *>(left)->GetValue().GetString();
|
||||||
|
FString v2 = static_cast<FxConstant *>(right)->GetValue().GetString();
|
||||||
|
int res = v1.Compare(v2);
|
||||||
|
v = Operator == '<' ? res < 0 :
|
||||||
|
Operator == '>' ? res > 0 :
|
||||||
|
Operator == TK_Geq ? res >= 0 :
|
||||||
|
Operator == TK_Leq ? res <= 0 : 0;
|
||||||
|
}
|
||||||
|
else if (IsFloat())
|
||||||
{
|
{
|
||||||
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
||||||
double v2 = static_cast<FxConstant *>(right)->GetValue().GetFloat();
|
double v2 = static_cast<FxConstant *>(right)->GetValue().GetFloat();
|
||||||
|
@ -2873,47 +2927,81 @@ ExpEmit FxCompareRel::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit op1 = left->Emit(build);
|
ExpEmit op1 = left->Emit(build);
|
||||||
ExpEmit op2 = right->Emit(build);
|
ExpEmit op2 = right->Emit(build);
|
||||||
assert(op1.RegType == op2.RegType);
|
assert(op1.RegType == op2.RegType);
|
||||||
assert(op1.RegType == REGT_INT || op1.RegType == REGT_FLOAT);
|
|
||||||
assert(!op1.Konst || !op2.Konst);
|
assert(!op1.Konst || !op2.Konst);
|
||||||
assert(Operator == '<' || Operator == '>' || Operator == TK_Geq || Operator == TK_Leq);
|
|
||||||
static const VM_UBYTE InstrMap[][4] =
|
|
||||||
{
|
|
||||||
{ OP_LT_RR, OP_LTF_RR, 0 }, // <
|
|
||||||
{ OP_LE_RR, OP_LEF_RR, 1 }, // >
|
|
||||||
{ OP_LT_RR, OP_LTF_RR, 1 }, // >=
|
|
||||||
{ OP_LE_RR, OP_LEF_RR, 0 } // <=
|
|
||||||
};
|
|
||||||
int instr, check, index;
|
|
||||||
ExpEmit to(build, REGT_INT);
|
|
||||||
|
|
||||||
index = Operator == '<' ? 0 :
|
if (op1.RegType == REGT_STRING)
|
||||||
|
{
|
||||||
|
ExpEmit to(build, REGT_INT);
|
||||||
|
int a = Operator == '<' ? CMP_LT :
|
||||||
|
Operator == '>' ? CMP_LE | CMP_CHECK :
|
||||||
|
Operator == TK_Geq ? CMP_LT | CMP_CHECK : CMP_LE;
|
||||||
|
|
||||||
|
if (op1.Konst)
|
||||||
|
{
|
||||||
|
a |= CMP_BK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
op1.Free(build);
|
||||||
|
}
|
||||||
|
if (op2.Konst)
|
||||||
|
{
|
||||||
|
a |= CMP_CK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
op2.Free(build);
|
||||||
|
}
|
||||||
|
|
||||||
|
build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||||
|
build->Emit(OP_CMPS, a, op1.RegNum, op2.RegNum);
|
||||||
|
build->Emit(OP_JMP, 1);
|
||||||
|
build->Emit(OP_LI, to.RegNum, 1);
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(op1.RegType == REGT_INT || op1.RegType == REGT_FLOAT);
|
||||||
|
assert(Operator == '<' || Operator == '>' || Operator == TK_Geq || Operator == TK_Leq);
|
||||||
|
static const VM_UBYTE InstrMap[][4] =
|
||||||
|
{
|
||||||
|
{ OP_LT_RR, OP_LTF_RR, 0 }, // <
|
||||||
|
{ OP_LE_RR, OP_LEF_RR, 1 }, // >
|
||||||
|
{ OP_LT_RR, OP_LTF_RR, 1 }, // >=
|
||||||
|
{ OP_LE_RR, OP_LEF_RR, 0 } // <=
|
||||||
|
};
|
||||||
|
int instr, check;
|
||||||
|
ExpEmit to(build, REGT_INT);
|
||||||
|
int index = Operator == '<' ? 0 :
|
||||||
Operator == '>' ? 1 :
|
Operator == '>' ? 1 :
|
||||||
Operator == TK_Geq ? 2 : 3;
|
Operator == TK_Geq ? 2 : 3;
|
||||||
instr = InstrMap[index][op1.RegType == REGT_INT ? 0 : 1];
|
|
||||||
check = InstrMap[index][2];
|
|
||||||
if (op2.Konst)
|
|
||||||
{
|
|
||||||
instr += 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
op2.Free(build);
|
|
||||||
}
|
|
||||||
if (op1.Konst)
|
|
||||||
{
|
|
||||||
instr += 2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
op1.Free(build);
|
|
||||||
}
|
|
||||||
|
|
||||||
// See FxBoolCast for comments, since it's the same thing.
|
instr = InstrMap[index][op1.RegType == REGT_INT ? 0 : 1];
|
||||||
build->Emit(OP_LI, to.RegNum, 0, 0);
|
check = InstrMap[index][2];
|
||||||
build->Emit(instr, check, op1.RegNum, op2.RegNum);
|
if (op2.Konst)
|
||||||
build->Emit(OP_JMP, 1);
|
{
|
||||||
build->Emit(OP_LI, to.RegNum, 1);
|
instr += 1;
|
||||||
return to;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
op2.Free(build);
|
||||||
|
}
|
||||||
|
if (op1.Konst)
|
||||||
|
{
|
||||||
|
instr += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
op1.Free(build);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See FxBoolCast for comments, since it's the same thing.
|
||||||
|
build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||||
|
build->Emit(instr, check, op1.RegNum, op2.RegNum);
|
||||||
|
build->Emit(OP_JMP, 1);
|
||||||
|
build->Emit(OP_LI, to.RegNum, 1);
|
||||||
|
return to;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -2952,12 +3040,24 @@ FxExpression *FxCompareEq::Resolve(FCompileContext& ctx)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Operator == TK_ApproxEq && ValueType->GetRegType() != REGT_FLOAT) Operator = TK_Eq;
|
if (Operator == TK_ApproxEq && left->ValueType->GetRegType() != REGT_FLOAT && left->ValueType->GetRegType() != REGT_STRING)
|
||||||
|
Operator = TK_Eq;
|
||||||
if (left->isConstant() && right->isConstant())
|
if (left->isConstant() && right->isConstant())
|
||||||
{
|
{
|
||||||
int v;
|
int v;
|
||||||
|
|
||||||
if (ValueType->GetRegType() == REGT_FLOAT)
|
if (ValueType == TypeString)
|
||||||
|
{
|
||||||
|
FString v1 = static_cast<FxConstant *>(left)->GetValue().GetString();
|
||||||
|
FString v2 = static_cast<FxConstant *>(right)->GetValue().GetString();
|
||||||
|
if (Operator == TK_ApproxEq) v = !v1.CompareNoCase(v2);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v = !!v1.Compare(v2);
|
||||||
|
if (Operator == TK_Eq) v = !v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ValueType->GetRegType() == REGT_FLOAT)
|
||||||
{
|
{
|
||||||
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
double v1 = static_cast<FxConstant *>(left)->GetValue().GetFloat();
|
||||||
double v2 = static_cast<FxConstant *>(right)->GetValue().GetFloat();
|
double v2 = static_cast<FxConstant *>(right)->GetValue().GetFloat();
|
||||||
|
@ -2989,39 +3089,55 @@ ExpEmit FxCompareEq::Emit(VMFunctionBuilder *build)
|
||||||
ExpEmit op1 = left->Emit(build);
|
ExpEmit op1 = left->Emit(build);
|
||||||
ExpEmit op2 = right->Emit(build);
|
ExpEmit op2 = right->Emit(build);
|
||||||
assert(op1.RegType == op2.RegType);
|
assert(op1.RegType == op2.RegType);
|
||||||
assert(op1.RegType == REGT_INT || op1.RegType == REGT_FLOAT || op1.RegType == REGT_POINTER);
|
|
||||||
int instr;
|
int instr;
|
||||||
|
|
||||||
// Only the second operand may be constant.
|
if (op1.RegType == REGT_STRING)
|
||||||
if (op1.Konst)
|
|
||||||
{
|
{
|
||||||
swapvalues(op1, op2);
|
ExpEmit to(build, REGT_INT);
|
||||||
}
|
assert(Operator == TK_Eq || Operator == TK_Neq || Operator == TK_ApproxEq);
|
||||||
assert(!op1.Konst);
|
int a = Operator == TK_Eq ? CMP_EQ :
|
||||||
assert(op1.RegCount >= 1 && op1.RegCount <= 3);
|
Operator == TK_Neq ? CMP_EQ | CMP_CHECK : CMP_EQ | CMP_APPROX;
|
||||||
|
|
||||||
ExpEmit to(build, REGT_INT);
|
build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||||
|
build->Emit(OP_CMPS, a, op1.RegNum, op2.RegNum);
|
||||||
static int flops[] = { OP_EQF_R, OP_EQV2_R, OP_EQV3_R };
|
build->Emit(OP_JMP, 1);
|
||||||
instr = op1.RegType == REGT_INT ? OP_EQ_R :
|
build->Emit(OP_LI, to.RegNum, 1);
|
||||||
op1.RegType == REGT_FLOAT ? flops[op1.RegCount-1] :
|
return to;
|
||||||
OP_EQA_R;
|
|
||||||
op1.Free(build);
|
|
||||||
if (!op2.Konst)
|
|
||||||
{
|
|
||||||
op2.Free(build);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
instr += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See FxUnaryNotBoolean for comments, since it's the same thing.
|
// Only the second operand may be constant.
|
||||||
build->Emit(OP_LI, to.RegNum, 0, 0);
|
if (op1.Konst)
|
||||||
build->Emit(instr, Operator == TK_ApproxEq? CMP_APPROX : Operator != TK_Eq, op1.RegNum, op2.RegNum);
|
{
|
||||||
build->Emit(OP_JMP, 1);
|
swapvalues(op1, op2);
|
||||||
build->Emit(OP_LI, to.RegNum, 1);
|
}
|
||||||
return to;
|
assert(!op1.Konst);
|
||||||
|
assert(op1.RegCount >= 1 && op1.RegCount <= 3);
|
||||||
|
|
||||||
|
ExpEmit to(build, REGT_INT);
|
||||||
|
|
||||||
|
static int flops[] = { OP_EQF_R, OP_EQV2_R, OP_EQV3_R };
|
||||||
|
instr = op1.RegType == REGT_INT ? OP_EQ_R :
|
||||||
|
op1.RegType == REGT_FLOAT ? flops[op1.RegCount - 1] :
|
||||||
|
OP_EQA_R;
|
||||||
|
op1.Free(build);
|
||||||
|
if (!op2.Konst)
|
||||||
|
{
|
||||||
|
op2.Free(build);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
instr += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See FxUnaryNotBoolean for comments, since it's the same thing.
|
||||||
|
build->Emit(OP_LI, to.RegNum, 0, 0);
|
||||||
|
build->Emit(instr, Operator == TK_ApproxEq ? CMP_APPROX : Operator != TK_Eq, op1.RegNum, op2.RegNum);
|
||||||
|
build->Emit(OP_JMP, 1);
|
||||||
|
build->Emit(OP_LI, to.RegNum, 1);
|
||||||
|
return to;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
@ -3047,7 +3163,7 @@ FxExpression *FxBinaryInt::Resolve(FCompileContext& ctx)
|
||||||
CHECKRESOLVED();
|
CHECKRESOLVED();
|
||||||
if (!ResolveLR(ctx, false)) return NULL;
|
if (!ResolveLR(ctx, false)) return NULL;
|
||||||
|
|
||||||
if (ValueType->GetRegType() == REGT_FLOAT && ctx.FromDecorate)
|
if (IsFloat() && ctx.FromDecorate)
|
||||||
{
|
{
|
||||||
// For DECORATE which allows floats here. ZScript does not.
|
// For DECORATE which allows floats here. ZScript does not.
|
||||||
if (left->ValueType->GetRegType() != REGT_INT)
|
if (left->ValueType->GetRegType() != REGT_INT)
|
||||||
|
@ -3557,7 +3673,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx)
|
||||||
ValueType = truex->ValueType;
|
ValueType = truex->ValueType;
|
||||||
else if (truex->ValueType == TypeBool && falsex->ValueType == TypeBool)
|
else if (truex->ValueType == TypeBool && falsex->ValueType == TypeBool)
|
||||||
ValueType = TypeBool;
|
ValueType = TypeBool;
|
||||||
else if (truex->ValueType->GetRegType() == REGT_INT && falsex->ValueType->GetRegType() == REGT_INT)
|
else if (truex->IsInteger() && falsex->IsInteger())
|
||||||
ValueType = TypeSInt32;
|
ValueType = TypeSInt32;
|
||||||
else if (truex->IsNumeric() && falsex->IsNumeric())
|
else if (truex->IsNumeric() && falsex->IsNumeric())
|
||||||
ValueType = TypeFloat64;
|
ValueType = TypeFloat64;
|
||||||
|
@ -3565,7 +3681,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx)
|
||||||
ValueType = TypeVoid;
|
ValueType = TypeVoid;
|
||||||
//else if (truex->ValueType != falsex->ValueType)
|
//else if (truex->ValueType != falsex->ValueType)
|
||||||
|
|
||||||
if (!IsNumeric() && !IsPointer() && !IsVector())
|
if ((!IsNumeric() && !IsPointer() && !IsVector()) || ValueType == TypeVoid)
|
||||||
{
|
{
|
||||||
ScriptPosition.Message(MSG_ERROR, "Incompatible types for ?: operator");
|
ScriptPosition.Message(MSG_ERROR, "Incompatible types for ?: operator");
|
||||||
delete this;
|
delete this;
|
||||||
|
@ -3590,7 +3706,7 @@ FxExpression *FxConditional::Resolve(FCompileContext& ctx)
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ValueType->GetRegType() == REGT_FLOAT)
|
if (IsFloat())
|
||||||
{
|
{
|
||||||
if (truex->ValueType->GetRegType() != REGT_FLOAT)
|
if (truex->ValueType->GetRegType() != REGT_FLOAT)
|
||||||
{
|
{
|
||||||
|
@ -3911,11 +4027,11 @@ FxExpression *FxMinMax::Resolve(FCompileContext &ctx)
|
||||||
RESOLVE(choices[i], ctx);
|
RESOLVE(choices[i], ctx);
|
||||||
ABORT(choices[i]);
|
ABORT(choices[i]);
|
||||||
|
|
||||||
if (choices[i]->ValueType->GetRegType() == REGT_FLOAT)
|
if (choices[i]->IsFloat())
|
||||||
{
|
{
|
||||||
floatcount++;
|
floatcount++;
|
||||||
}
|
}
|
||||||
else if (choices[i]->ValueType->GetRegType() == REGT_INT && choices[i]->ValueType != TypeName)
|
else if (choices[i]->IsInteger())
|
||||||
{
|
{
|
||||||
intcount++;
|
intcount++;
|
||||||
}
|
}
|
||||||
|
@ -5690,7 +5806,7 @@ FxExpression *FxActionSpecialCall::Resolve(FCompileContext& ctx)
|
||||||
failed = true;
|
failed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((*ArgList)[i]->ValueType->GetRegType() != REGT_INT)
|
else if (!(*ArgList)[i]->IsInteger())
|
||||||
{
|
{
|
||||||
if ((*ArgList)[i]->ValueType->GetRegType() == REGT_FLOAT /* lax */)
|
if ((*ArgList)[i]->ValueType->GetRegType() == REGT_FLOAT /* lax */)
|
||||||
{
|
{
|
||||||
|
|
|
@ -295,9 +295,11 @@ public:
|
||||||
virtual PPrototype *ReturnProto();
|
virtual PPrototype *ReturnProto();
|
||||||
virtual VMFunction *GetDirectFunction();
|
virtual VMFunction *GetDirectFunction();
|
||||||
bool IsNumeric() const { return ValueType != TypeName && ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); }
|
bool IsNumeric() const { return ValueType != TypeName && ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); }
|
||||||
|
bool IsFloat() const { return ValueType->GetRegType() == REGT_FLOAT && ValueType->GetRegCount() == 1; }
|
||||||
bool IsInteger() const { return ValueType != TypeName && (ValueType->GetRegType() == REGT_INT); }
|
bool IsInteger() const { return ValueType != TypeName && (ValueType->GetRegType() == REGT_INT); }
|
||||||
bool IsPointer() const { return ValueType->GetRegType() == REGT_POINTER; }
|
bool IsPointer() const { return ValueType->GetRegType() == REGT_POINTER; }
|
||||||
bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; };
|
bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; };
|
||||||
|
bool IsBoolCompat() const { return ValueType->GetRegCount() == 1 && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT || ValueType->GetRegType() == REGT_POINTER); }
|
||||||
|
|
||||||
virtual ExpEmit Emit(VMFunctionBuilder *build);
|
virtual ExpEmit Emit(VMFunctionBuilder *build);
|
||||||
|
|
||||||
|
|
|
@ -921,7 +921,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction
|
||||||
#define PARAM_SOUND_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FSoundID x = param[p].i;
|
#define PARAM_SOUND_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); FSoundID x = param[p].i;
|
||||||
#define PARAM_COLOR_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); PalEntry x; x.d = param[p].i;
|
#define PARAM_COLOR_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); PalEntry x; x.d = param[p].i;
|
||||||
#define PARAM_FLOAT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); double x = param[p].f;
|
#define PARAM_FLOAT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); double x = param[p].f;
|
||||||
#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); DAngle x = param[p].f;
|
#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); DAngle x = param[p].f;
|
||||||
#define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_STRING); FString x = param[p].s();
|
#define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_STRING); FString x = param[p].s();
|
||||||
#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].atag == ATAG_GENERIC || param[p].a == NULL)); FState *x = (FState *)param[p].a;
|
#define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].atag == ATAG_GENERIC || param[p].a == NULL)); FState *x = (FState *)param[p].a;
|
||||||
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a;
|
#define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a;
|
||||||
|
|
Loading…
Reference in a new issue