blob: c94b1daa73676e27be47369748371952262ab0ac [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 CEA LIST.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Created on: 20 mai 2010
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "AvmBitwisePrimitive.h"
#include <common/BF.h>
#include <computer/EvaluationEnvironment.h>
#include <fml/expression/AvmCode.h>
#include <fml/operator/Operator.h>
#include <fml/operator/OperatorManager.h>
namespace sep
{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///// BITWISE FORMAT
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// INVARIANT:> only << second >> could be << numeric<integer> >>
static void formtatBitwiseExpression(EvaluationEnvironment & ENV,
Operator * op, const BF & first, const BF & second)
{
if( second.isInteger() && first.is< AvmCode >() &&
first.to_ptr< AvmCode >()->isOpCode(op) &&
first.to_ptr< AvmCode >()->second().isInteger() )
{
BF bresult;
switch( op->getAvmOpCode() )
{
case AVM_OPCODE_BAND: // (x & m ) & n == x & (m & n)
{
bresult = ExpressionConstructor::newInteger(second.isInteger() &
first.to_ptr< AvmCode >()->second().isInteger());
break;
}
case AVM_OPCODE_BOR: // (x | m ) | n == x | (m | n)
{
bresult = ExpressionConstructor::newInteger(second.isInteger() |
first.to_ptr< AvmCode >()->second().isInteger());
break;
}
case AVM_OPCODE_BXOR: // (x ^ m ) ^ n == x ^ (m ^ n)
{
bresult = ExpressionConstructor::newInteger(second.isInteger() ^
first.to_ptr< AvmCode >()->second().isInteger());
break;
}
case AVM_OPCODE_LSHIFT: // (x << m ) << n == x << (m + n)
case AVM_OPCODE_RSHIFT: // (x >> m ) >> n == x >> (m + n)
{
bresult = ExpressionConstructor::newInteger(second.isInteger() +
first.to_ptr< AvmCode >()->second().isInteger());
break;
}
default :
{
AVM_OS_EXIT( FAILED )
<< "Unexpected a bitwise operation << "
<< first.str() << " " << op->getUnrestrictedName()
<< " " << second.str() << " >>"
<< SEND_EXIT;
break;
}
}
ENV.outVAL = ExpressionConstructor::newCode(op,
first.to_ptr< AvmCode >()->first(), bresult);
}
else
{
ENV.outVAL = ExpressionConstructor::newCode(op, first, second);
}
// ENV.outVAL = ENV.create(
// ENV.outED->mRID, op->getUnrestrictedName(), TypeManager::INTEGER, ENV.outVAL);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///// BITWISE NOT
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool AvmPrimitive_BNOT::seval(EvaluationEnvironment & ENV)
{
// AFA : si le parametre ne se reduit pas a une valeur numerique
// alors on cree une nouvelle valeur symbolique BNOT#n a laquelle on associe
// un AvmCode correspondant au BNOT de la valeur symbolique
if( ENV.mARG->at(0).isInteger() )
{
// NOT OPERATION
ENV.outVAL = ExpressionConstructor::newInteger(
~ (ENV.mARG->at(0).toInteger()) );
}
else if( ENV.mARG->at(0).is< AvmCode >() &&
ENV.mARG->at(0).to_ptr< AvmCode >()->isOpCode( AVM_OPCODE_BNOT ) )
{
ENV.outVAL = ENV.mARG->at(0).to_ptr< AvmCode >()->first();
}
else
{
ENV.outVAL = ExpressionConstructor::newCode(
OperatorManager::OPERATOR_BNOT, ENV.mARG->at(0));
// ENV.outVAL = ENV.create(ENV.mARG->outED->mRID, "BNOT",
// TypeManager::INTEGER, ENV.mARG->at(0));
}
return( true );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///// BITWISE AND
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool AvmPrimitive_BAND::seval(EvaluationEnvironment & ENV)
{
// AFA : si l'évaluation ne se reduit pas a une valeur numerique
// alors on cree une nouvelle valeur symbolique BAND#n a laquelle
// on associe un AvmCode correspondant au BAND des paramètres évaluées
if ( ENV.mARG->at(0).isInteger() )
{
if ( ENV.mARG->at(1).isInteger() )
{
ENV.outVAL = ExpressionConstructor::newInteger(
ENV.mARG->at(0).toInteger() & ENV.mARG->at(1).toInteger() );
}
else
{
formtatBitwiseExpression(ENV, OperatorManager::OPERATOR_BAND,
ENV.mARG->at(1), ENV.mARG->at(0));
}
}
else
{
formtatBitwiseExpression(ENV, OperatorManager::OPERATOR_BAND,
ENV.mARG->at(0), ENV.mARG->at(1));
}
return( true );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///// BITWISE OR
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool AvmPrimitive_BOR::seval(EvaluationEnvironment & ENV)
{
// AFA : si l'évaluation ne se reduit pas a une valeur numerique
// alors on cree une nouvelle valeur symbolique BOR#n a laquelle
// on associe un AvmCode correspondant au BOR des paramètres évaluées
if ( ENV.mARG->at(0).isInteger() )
{
if ( ENV.mARG->at(1).isInteger() )
{
ENV.outVAL = ExpressionConstructor::newInteger(
ENV.mARG->at(0).toInteger() | ENV.mARG->at(1).toInteger() );
}
else
{
formtatBitwiseExpression(ENV, OperatorManager::OPERATOR_BOR,
ENV.mARG->at(1), ENV.mARG->at(0));
}
}
else
{
formtatBitwiseExpression(ENV, OperatorManager::OPERATOR_BOR,
ENV.mARG->at(0), ENV.mARG->at(1));
}
return( true );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///// BITWISE XOR
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool AvmPrimitive_BXOR::seval(EvaluationEnvironment & ENV)
{
// AFA : si l'évaluation ne se reduit pas a une valeur numerique
// alors on cree une nouvelle valeur symbolique BXOR#n a laquelle
// on associe un AvmCode correspondant au BXOR des paramètres évaluées
if ( ENV.mARG->at(0).isInteger() )
{
if ( ENV.mARG->at(1).isInteger() )
{
ENV.outVAL = ExpressionConstructor::newInteger(
ENV.mARG->at(0).toInteger() ^ ENV.mARG->at(1).toInteger() );
}
else
{
formtatBitwiseExpression(ENV, OperatorManager::OPERATOR_BXOR,
ENV.mARG->at(1), ENV.mARG->at(0));
}
}
else
{
formtatBitwiseExpression(ENV, OperatorManager::OPERATOR_BXOR,
ENV.mARG->at(0), ENV.mARG->at(1));
}
return( true );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///// BITWISE LSHIFT
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool AvmPrimitive_LSHIFT::seval(EvaluationEnvironment & ENV)
{
// AFA : si l'évaluation ne se reduit pas a une valeur numerique
// alors on cree une nouvelle valeur symbolique LSHIFT#n a laquelle
// on associe un AvmCode correspondant au LSHIFT des paramètres évaluées
if ( ENV.mARG->at(0).isInteger() && ENV.mARG->at(1).isInteger() )
{
ENV.outVAL = ExpressionConstructor::newInteger(
ENV.mARG->at(0).toInteger() << ENV.mARG->at(1).toInteger() );
}
else
{
formtatBitwiseExpression(ENV, OperatorManager::OPERATOR_LSHIFT,
ENV.mARG->at(0), ENV.mARG->at(1));
}
return( true );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///// BITWISE RSHIFT
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
bool AvmPrimitive_RSHIFT::seval(EvaluationEnvironment & ENV)
{
// AFA : si l'évaluation ne se reduit pas a une valeur numerique
// alors on cree une nouvelle valeur symbolique RSHIFT#n a laquelle
// on associe un AvmCode correspondant au RSHIFT des paramètres évaluées
if ( ENV.mARG->at(0).isInteger() && ENV.mARG->at(1).isInteger() )
{
ENV.outVAL = ExpressionConstructor::newInteger(
ENV.mARG->at(0).toInteger() >> ENV.mARG->at(1).toInteger() );
}
else
{
formtatBitwiseExpression(ENV, OperatorManager::OPERATOR_RSHIFT,
ENV.mARG->at(0), ENV.mARG->at(1));
}
return( true );
}
}