Do proper number conversion for arithmetic operations.
git-svn-id: http://yate.null.ro/svn/yate/trunk@5854 acf43c95-373e-0410-b603-e72c3f656dc1
This commit is contained in:
parent
f73f353c26
commit
7a41ecce69
|
@ -1019,10 +1019,11 @@ bool ExpEvaluator::runOperation(ObjList& stack, const ExpOperation& oper, GenObj
|
|||
switch (oper.opcode()) {
|
||||
case OpcDiv:
|
||||
case OpcMod:
|
||||
if (!op2->valInteger())
|
||||
if (!op2->toNumber())
|
||||
return gotError("Division by zero",oper.lineNumber());
|
||||
break;
|
||||
case OpcAdd:
|
||||
if (op1->isInteger() && op2->isInteger())
|
||||
if (op1->isNumber() && op2->isNumber())
|
||||
break;
|
||||
// turn addition into concatenation
|
||||
{
|
||||
|
@ -1037,6 +1038,7 @@ bool ExpEvaluator::runOperation(ObjList& stack, const ExpOperation& oper, GenObj
|
|||
break;
|
||||
}
|
||||
int64_t val = 0;
|
||||
bool handled = true;
|
||||
switch (oper.opcode()) {
|
||||
case OpcAnd:
|
||||
val = op1->valInteger() & op2->valInteger();
|
||||
|
@ -1053,21 +1055,6 @@ bool ExpEvaluator::runOperation(ObjList& stack, const ExpOperation& oper, GenObj
|
|||
case OpcShr:
|
||||
val = op1->valInteger() >> op2->valInteger();
|
||||
break;
|
||||
case OpcAdd:
|
||||
val = op1->valInteger() + op2->valInteger();
|
||||
break;
|
||||
case OpcSub:
|
||||
val = op1->valInteger() - op2->valInteger();
|
||||
break;
|
||||
case OpcMul:
|
||||
val = op1->valInteger() * op2->valInteger();
|
||||
break;
|
||||
case OpcDiv:
|
||||
val = op1->valInteger() / op2->valInteger();
|
||||
break;
|
||||
case OpcMod:
|
||||
val = op1->valInteger() % op2->valInteger();
|
||||
break;
|
||||
case OpcLt:
|
||||
val = (op1->valInteger() < op2->valInteger()) ? 1 : 0;
|
||||
break;
|
||||
|
@ -1087,8 +1074,35 @@ bool ExpEvaluator::runOperation(ObjList& stack, const ExpOperation& oper, GenObj
|
|||
val = (*op1 != *op2) ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
handled = false;
|
||||
break;
|
||||
}
|
||||
if (!handled) {
|
||||
val = ExpOperation::nonInteger();
|
||||
int64_t op1Val = op1->toNumber();
|
||||
int64_t op2Val = op2->toNumber();
|
||||
if (op1Val != ExpOperation::nonInteger() && op2Val != ExpOperation::nonInteger()) {
|
||||
switch(oper.opcode()) {
|
||||
case OpcAdd:
|
||||
val = op1Val + op2Val;
|
||||
break;
|
||||
case OpcSub:
|
||||
val = op1Val - op2Val;
|
||||
break;
|
||||
case OpcMul:
|
||||
val = op1Val * op2Val;
|
||||
break;
|
||||
case OpcDiv:
|
||||
val = op1Val / op2Val;
|
||||
break;
|
||||
case OpcMod:
|
||||
val = op1Val % op2Val;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
TelEngine::destruct(op1);
|
||||
TelEngine::destruct(op2);
|
||||
if (boolRes) {
|
||||
|
@ -1167,7 +1181,7 @@ bool ExpEvaluator::runOperation(ObjList& stack, const ExpOperation& oper, GenObj
|
|||
return gotError("ExpEvaluator stack underflow",oper.lineNumber());
|
||||
switch (oper.opcode()) {
|
||||
case OpcNeg:
|
||||
pushOne(stack,new ExpOperation(-op->valInteger()));
|
||||
pushOne(stack,new ExpOperation(-op->toNumber()));
|
||||
break;
|
||||
case OpcNot:
|
||||
pushOne(stack,new ExpOperation(~op->valInteger()));
|
||||
|
@ -1494,6 +1508,13 @@ int64_t ExpOperation::valInteger() const
|
|||
return isInteger() ? number() : 0;
|
||||
}
|
||||
|
||||
int64_t ExpOperation::toNumber() const
|
||||
{
|
||||
if (isInteger())
|
||||
return number();
|
||||
return toInt64(nonInteger());
|
||||
}
|
||||
|
||||
bool ExpOperation::valBoolean() const
|
||||
{
|
||||
return isInteger() ? (number() != 0) : !null();
|
||||
|
@ -1504,7 +1525,7 @@ const char* ExpOperation::typeOf() const
|
|||
switch (opcode()) {
|
||||
case ExpEvaluator::OpcPush:
|
||||
case ExpEvaluator::OpcCopy:
|
||||
return isInteger() ? ( isBoolean() ? "boolean" : "number" ) : "string";
|
||||
return isInteger() ? ( isBoolean() ? "boolean" : "number" ) : (isNumber() ? "number" : "string");
|
||||
case ExpEvaluator::OpcFunc:
|
||||
return "function";
|
||||
default:
|
||||
|
|
|
@ -340,7 +340,7 @@ bool JsObject::runField(ObjList& stack, const ExpOperation& oper, GenObject* con
|
|||
else {
|
||||
bool num = true;
|
||||
ExpOperation* o = YOBJECT(ExpOperation,param);
|
||||
if (o && !o->isInteger())
|
||||
if (o && !o->isNumber())
|
||||
num = false;
|
||||
ExpEvaluator::pushOne(stack,new ExpOperation(*param,oper.name(),num));
|
||||
}
|
||||
|
|
|
@ -949,7 +949,7 @@ public:
|
|||
inline ExpOperation(const ExpOperation& original)
|
||||
: NamedString(original.name(),original),
|
||||
m_opcode(original.opcode()), m_number(original.number()), m_bool(original.isBoolean()),
|
||||
m_lineNo(0), m_barrier(original.barrier())
|
||||
m_isNumber(original.isNumber()), m_lineNo(0), m_barrier(original.barrier())
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
@ -960,7 +960,7 @@ public:
|
|||
inline ExpOperation(const ExpOperation& original, const char* name)
|
||||
: NamedString(name,original),
|
||||
m_opcode(original.opcode()), m_number(original.number()), m_bool(original.isBoolean()),
|
||||
m_lineNo(0), m_barrier(original.barrier())
|
||||
m_isNumber(original.isNumber()), m_lineNo(0), m_barrier(original.barrier())
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
@ -974,6 +974,7 @@ public:
|
|||
m_opcode(ExpEvaluator::OpcPush),
|
||||
m_number(autoNum ? value.toInt64(nonInteger()) : nonInteger()),
|
||||
m_bool(autoNum && value.isBoolean()),
|
||||
m_isNumber(autoNum && (value == YSTRING("NaN") || m_number != nonInteger())),
|
||||
m_lineNo(0), m_barrier(false)
|
||||
{ if (m_bool) m_number = value.toBoolean() ? 1 : 0; }
|
||||
|
||||
|
@ -985,7 +986,7 @@ public:
|
|||
inline explicit ExpOperation(const char* value, const char* name = 0)
|
||||
: NamedString(name,value),
|
||||
m_opcode(ExpEvaluator::OpcPush), m_number(nonInteger()), m_bool(false),
|
||||
m_lineNo(0), m_barrier(false)
|
||||
m_isNumber(false), m_lineNo(0), m_barrier(false)
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
@ -996,7 +997,7 @@ public:
|
|||
inline explicit ExpOperation(int64_t value, const char* name = 0)
|
||||
: NamedString(name,"NaN"),
|
||||
m_opcode(ExpEvaluator::OpcPush),
|
||||
m_number(value), m_bool(false), m_lineNo(0), m_barrier(false)
|
||||
m_number(value), m_bool(false), m_isNumber(true), m_lineNo(0), m_barrier(false)
|
||||
{ if (value != nonInteger()) String::operator=(value); }
|
||||
|
||||
/**
|
||||
|
@ -1007,7 +1008,7 @@ public:
|
|||
inline explicit ExpOperation(bool value, const char* name = 0)
|
||||
: NamedString(name,String::boolText(value)),
|
||||
m_opcode(ExpEvaluator::OpcPush),
|
||||
m_number(value ? 1 : 0), m_bool(true),
|
||||
m_number(value ? 1 : 0), m_bool(true), m_isNumber(true),
|
||||
m_lineNo(0), m_barrier(false)
|
||||
{ }
|
||||
|
||||
|
@ -1020,7 +1021,8 @@ public:
|
|||
*/
|
||||
inline ExpOperation(ExpEvaluator::Opcode oper, const char* name = 0, int64_t value = nonInteger(), bool barrier = false)
|
||||
: NamedString(name,""),
|
||||
m_opcode(oper), m_number(value), m_bool(false), m_lineNo(0), m_barrier(barrier)
|
||||
m_opcode(oper), m_number(value), m_bool(false), m_isNumber(false),
|
||||
m_lineNo(0), m_barrier(barrier)
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
@ -1032,7 +1034,8 @@ public:
|
|||
*/
|
||||
inline ExpOperation(ExpEvaluator::Opcode oper, const char* name, const char* value, bool barrier = false)
|
||||
: NamedString(name,value),
|
||||
m_opcode(oper), m_number(nonInteger()), m_bool(false), m_lineNo(0), m_barrier(barrier)
|
||||
m_opcode(oper), m_number(nonInteger()), m_bool(false), m_isNumber(false),
|
||||
m_lineNo(0), m_barrier(barrier)
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
@ -1045,7 +1048,8 @@ public:
|
|||
*/
|
||||
inline ExpOperation(ExpEvaluator::Opcode oper, const char* name, const char* value, int64_t number, bool barrier)
|
||||
: NamedString(name,value),
|
||||
m_opcode(oper), m_number(number), m_bool(false), m_lineNo(0), m_barrier(barrier)
|
||||
m_opcode(oper), m_number(number), m_bool(false), m_isNumber(true),
|
||||
m_lineNo(0), m_barrier(barrier)
|
||||
{ }
|
||||
|
||||
/**
|
||||
|
@ -1076,6 +1080,13 @@ public:
|
|||
inline bool isBoolean() const
|
||||
{ return m_bool; }
|
||||
|
||||
/**
|
||||
* Check if a number type value is stored
|
||||
* @return True if a number type value is stored
|
||||
*/
|
||||
inline bool isNumber() const
|
||||
{ return m_isNumber; }
|
||||
|
||||
/**
|
||||
* Check if this operation acts as an evaluator barrier on the stack
|
||||
* @return True if an expression should not pop this operation off the stack
|
||||
|
@ -1103,7 +1114,7 @@ public:
|
|||
* @return Assigned number
|
||||
*/
|
||||
inline int64_t operator=(int64_t num)
|
||||
{ m_number = num; String::operator=(num); return num; }
|
||||
{ m_number = num; String::operator=(num); m_isNumber = true; return num; }
|
||||
|
||||
/**
|
||||
* Retrieve the numeric value of the operation
|
||||
|
@ -1111,6 +1122,12 @@ public:
|
|||
*/
|
||||
virtual int64_t valInteger() const;
|
||||
|
||||
/**
|
||||
* Convert to number
|
||||
* @return Value converted to number, NaN if not possible of if stored value is NaN
|
||||
*/
|
||||
virtual int64_t toNumber() const;
|
||||
|
||||
/**
|
||||
* Retrieve the boolean value of the operation
|
||||
* @return True if the operation is to be interpreted as true value
|
||||
|
@ -1149,6 +1166,7 @@ private:
|
|||
ExpEvaluator::Opcode m_opcode;
|
||||
int64_t m_number;
|
||||
bool m_bool;
|
||||
bool m_isNumber;
|
||||
unsigned int m_lineNo;
|
||||
bool m_barrier;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue