Implement the %, ^, %=, ^=, &= and |= operators

fixes #7813
This commit is contained in:
Gunnar Beutner 2014-11-25 17:04:20 +01:00
parent 1e5751c540
commit cee13fbec0
4 changed files with 70 additions and 3 deletions

View File

@ -278,10 +278,16 @@ in return T_IN;
-= { yylval->csop = OpSetSubtract; return T_SET_SUBTRACT; }
\*= { yylval->csop = OpSetMultiply; return T_SET_MULTIPLY; }
\/= { yylval->csop = OpSetDivide; return T_SET_DIVIDE; }
\%= { yylval->csop = OpSetModulo; return T_SET_MODULO; }
\^= { yylval->csop = OpSetXor; return T_SET_XOR; }
\&= { yylval->csop = OpSetBinaryAnd; return T_SET_BINARY_AND; }
\|= { yylval->csop = OpSetBinaryOr; return T_SET_BINARY_OR; }
\+ return T_PLUS;
\- return T_MINUS;
\* return T_MULTIPLY;
\/ return T_DIVIDE_OP;
\% return T_MODULO;
\^ return T_XOR;
\& return T_BINARY_AND;
\| return T_BINARY_OR;
\< return T_LESS_THAN;

View File

@ -114,6 +114,10 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%token <csop> T_SET_SUBTRACT "-= (T_SET_SUBTRACT)"
%token <csop> T_SET_MULTIPLY "*= (T_SET_MULTIPLY)"
%token <csop> T_SET_DIVIDE "/= (T_SET_DIVIDE)"
%token <csop> T_SET_MODULO "%= (T_SET_MODULO)"
%token <csop> T_SET_XOR "^= (T_SET_XOR)"
%token <csop> T_SET_BINARY_AND "&= (T_SET_BINARY_AND)"
%token <csop> T_SET_BINARY_OR "|= (T_SET_BINARY_OR)"
%token T_SHIFT_LEFT "<< (T_SHIFT_LEFT)"
%token T_SHIFT_RIGHT ">> (T_SHIFT_RIGHT)"
@ -129,6 +133,8 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%token T_MINUS "- (T_MINUS)"
%token T_MULTIPLY "* (T_MULTIPLY)"
%token T_DIVIDE_OP "/ (T_DIVIDE_OP)"
%token T_MODULO "% (T_MODULO)"
%token T_XOR "^ (T_XOR)"
%token T_BINARY_AND "& (T_BINARY_AND)"
%token T_BINARY_OR "| (T_BINARY_OR)"
%token T_LESS_THAN "< (T_LESS_THAN)"
@ -203,8 +209,9 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
%left T_LOGICAL_AND
%left T_LOCAL T_RETURN
%left T_IDENTIFIER
%left T_SET T_SET_ADD T_SET_SUBTRACT T_SET_MULTIPLY T_SET_DIVIDE
%left T_SET T_SET_ADD T_SET_SUBTRACT T_SET_MULTIPLY T_SET_DIVIDE T_SET_MODULO T_SET_XOR T_SET_BINARY_AND T_SET_BINARY_OR
%left T_BINARY_OR
%left T_XOR T_MODULO
%left T_BINARY_AND
%left T_IN T_NOT_IN
%nonassoc T_EQUAL T_NOT_EQUAL
@ -560,6 +567,10 @@ combined_set_op: T_SET
| T_SET_SUBTRACT
| T_SET_MULTIPLY
| T_SET_DIVIDE
| T_SET_MODULO
| T_SET_XOR
| T_SET_BINARY_AND
| T_SET_BINARY_OR
{
$$ = $1;
}
@ -802,6 +813,8 @@ rterm_without_indexer: T_STRING
| rterm T_MINUS rterm { MakeRBinaryOp<SubtractExpression>(&$$, $1, $3, @1, @3); }
| rterm T_MULTIPLY rterm { MakeRBinaryOp<MultiplyExpression>(&$$, $1, $3, @1, @3); }
| rterm T_DIVIDE_OP rterm { MakeRBinaryOp<DivideExpression>(&$$, $1, $3, @1, @3); }
| rterm T_MODULO rterm { MakeRBinaryOp<ModuloExpression>(&$$, $1, $3, @1, @3); }
| rterm T_XOR rterm { MakeRBinaryOp<XorExpression>(&$$, $1, $3, @1, @3); }
| T_FUNCTION identifier '(' identifier_items ')' use_specifier rterm_scope
{
DictExpression *aexpr = dynamic_cast<DictExpression *>($7);

View File

@ -124,6 +124,16 @@ Value DivideExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
return m_Operand1->Evaluate(frame) / m_Operand2->Evaluate(frame);
}
Value ModuloExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
{
return (long)m_Operand1->Evaluate(frame) % (long)m_Operand2->Evaluate(frame);
}
Value XorExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
{
return (long)m_Operand1->Evaluate(frame) ^ (long)m_Operand2->Evaluate(frame);
}
Value BinaryAndExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
{
return m_Operand1->Evaluate(frame) & m_Operand2->Evaluate(frame);
@ -337,6 +347,18 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
case OpSetDivide:
right = DivideExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
break;
case OpSetModulo:
right = ModuloExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
break;
case OpSetXor:
right = XorExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
break;
case OpSetBinaryAnd:
right = BinaryAndExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
break;
case OpSetBinaryOr:
right = BinaryOrExpression(lhs, rhs, m_DebugInfo).Evaluate(frame, dhint);
break;
default:
VERIFY(!"Invalid opcode.");
}

View File

@ -98,7 +98,11 @@ enum CombinedSetOp
OpSetAdd,
OpSetSubtract,
OpSetMultiply,
OpSetDivide
OpSetDivide,
OpSetModulo,
OpSetXor,
OpSetBinaryAnd,
OpSetBinaryOr
};
class InterruptExecutionError : virtual public std::exception, virtual public boost::exception
@ -309,7 +313,29 @@ public:
protected:
virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API ModuloExpression : public BinaryExpression
{
public:
ModuloExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo = DebugInfo())
: BinaryExpression(operand1, operand2, debugInfo)
{ }
protected:
virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API XorExpression : public BinaryExpression
{
public:
XorExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo = DebugInfo())
: BinaryExpression(operand1, operand2, debugInfo)
{ }
protected:
virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
};
class I2_CONFIG_API BinaryAndExpression : public BinaryExpression
{
public: