blob: 0a6df7396bd03bce49f68367da48aa0fd401e391 [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: 2 avr. 2013
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "AvmcodeExpressionCompiler.h"
#include <fml/executable/InstanceOfData.h>
#include <fml/expression/BuiltinArray.h>
#include <fml/expression/ExpressionConstructor.h>
#include <fml/expression/ExpressionFactory.h>
#include <fml/expression/ExpressionTypeChecker.h>
#include <fml/operator/OperatorManager.h>
#include <fml/type/ClassTypeSpecifier.h>
namespace sep
{
////////////////////////////////////////////////////////////////////////////////
// UNARY RVALUE COMPILATION STEP
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeExpressionALUCompiler::optimizeUnaryRvalue(COMPILE_CONTEXT * aCTX,
const BFCode & aCode, BaseTypeSpecifier * aType,
avm_arg_processor_t aProcessor, BaseTypeSpecifier * mainType)
{
AvmInstruction * argsInstruction = aCode->genInstruction();
optimizeArgExpression(aCTX, aCode, 0);
argsInstruction->at(0).dtype = aType;
setArgcodeRValue(aCTX, argsInstruction->at(0), aCode->first(), false);
argsInstruction->computeMainBytecode(
/*context */ AVM_ARG_RETURN_CTX,
/*processor*/ aProcessor,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_EXPRESSION_KIND,
/*dtype */ mainType);
return( aCode );
}
////////////////////////////////////////////////////////////////////////////////
// BINARY RVALUE COMPILATION STEP
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeExpressionALUCompiler::optimizeBinaryRvalue(
COMPILE_CONTEXT * aCTX, const BFCode & aCode,
BaseTypeSpecifier * aType1, BaseTypeSpecifier * aType2,
avm_arg_processor_t aProcessor, BaseTypeSpecifier * mainType)
{
AvmInstruction * argsInstruction = aCode->genInstruction();
optimizeArgExpression(aCTX, aCode, 0);
argsInstruction->at(0).dtype = aType1;
setArgcodeRValue(aCTX, argsInstruction->at(0), aCode->first(), false);
optimizeArgExpression(aCTX, aCode, 1);
argsInstruction->at(1).dtype = aType2;
setArgcodeRValue(aCTX, argsInstruction->at(1), aCode->second(), false);
argsInstruction->computeMainBytecode(
/*context */ AVM_ARG_RETURN_CTX,
/*processor*/ aProcessor,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_EXPRESSION_KIND,
/*dtype */ mainType);
// set operation on string
if( (argsInstruction->at(0).operand == AVM_ARG_STRING_KIND) &&
(argsInstruction->at(1).operand == AVM_ARG_STRING_KIND) )
{
argsInstruction->setMainBytecode(
/*context */ AVM_ARG_RETURN_CTX,
/*processor*/ AVM_ARG_STRING_CPU,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_EXPRESSION_KIND,
/*dtype */ mainType );
}
return( aCode );
}
////////////////////////////////////////////////////////////////////////////////
// ASSOCIATIVE RVALUE COMPILATION STEP
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeExpressionALUCompiler::compileAssociativeRvalue(
COMPILE_CONTEXT * aCTX, const BFCode & aCode, BaseTypeSpecifier * aType)
{
Operator * mainOperator = aCode->getOperator();
BFCode newCode( mainOperator );
BF arg;
AvmCode * pCode;
aCTX = aCTX->clone(aType);
AvmCode::iterator itArg = aCode->begin();
AvmCode::iterator itEndArg = aCode->end();
for( ; itArg != itEndArg ; ++itArg )
{
arg = AVMCODE_COMPILER.decode_compileExpression(aCTX, *itArg);
if( arg.invalid() )
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "AvmCode< expression > compilation error << "
<< (*itArg).str() << " >>" << std::endl << std::endl;
newCode->append( arg );
continue;
}
if( arg.is< AvmCode >() )
{
pCode = arg.to_ptr< AvmCode >();
if( pCode->isOperator( mainOperator ) &&
mainOperator->isAssociative() )
{
newCode->append( pCode->getArgs() );
}
else
{
newCode->append( arg );
}
}
else
{
newCode->append( arg );
}
}
return( newCode );
}
BFCode AvmcodeExpressionALUCompiler::optimizeAssociativeRvalue(
COMPILE_CONTEXT * aCTX, const BFCode & aCode, BaseTypeSpecifier * aType,
avm_arg_processor_t aProcessor, BaseTypeSpecifier * mainType)
{
Operator * mainOperator = aCode->getOperator();
BFCode newCode( mainOperator );
BF arg;
AvmCode * pCode;
AvmCode::iterator itArg = aCode->begin();
AvmCode::iterator itEndArg = aCode->end();
AvmInstruction * argsInstruction = newCode->newEmptyInstruction();
Vector< AvmBytecode > vectorOfArgOpcode;
avm_size_t stringArgCount = 0;
for( ; itArg != itEndArg ; ++itArg )
{
arg = AVMCODE_COMPILER.decode_optimizeExpression(aCTX, *itArg);
if( arg.invalid() )
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "AvmCode< expression > optimization error << "
<< (*itArg).str() << " >>" << std::endl << std::endl;
newCode->append( arg );
continue;
}
if( arg.is< AvmCode >() )
{
pCode = arg.to_ptr< AvmCode >();
if( pCode->isOperator( mainOperator ) &&
mainOperator->isAssociative() )
{
newCode->append( pCode->getArgs() );
vectorOfArgOpcode.append(
pCode->getInstruction()->getBytecode(), pCode->size());
}
else
{
newCode->append( arg );
if( pCode->hasInstruction() )
{
vectorOfArgOpcode.append( argcodeOfExpression(aCTX, pCode) );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected expression without argcode << "
<< pCode->strDebug() << " >> !!!"
<< SEND_EXIT;
vectorOfArgOpcode.append( AvmBytecode(AVM_ARG_ARGUMENT_CTX,
AVM_ARG_SEVAL_RVALUE, AVM_ARG_EXPRESSION_KIND) );
}
vectorOfArgOpcode.back().context = AVM_ARG_ARGUMENT_CTX;
}
}
else
{
newCode->append( arg );
AvmBytecode argOpcode;
setArgcodeRValue(aCTX, argOpcode, arg, false);
argOpcode.context = AVM_ARG_ARGUMENT_CTX;
vectorOfArgOpcode.append( argOpcode );
}
if( vectorOfArgOpcode.back().operand == AVM_ARG_STRING_KIND )
{
stringArgCount += 1;
}
}
argsInstruction->setMainBytecode(
/*context */ AVM_ARG_RETURN_CTX,
/*processor*/ aProcessor,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_EXPRESSION_KIND,
/*dtype */ mainType );
argsInstruction->computeBytecode( false , vectorOfArgOpcode );
// set operation on string
if( stringArgCount > 0 )
{
argsInstruction->setMainBytecode(
/*context */ AVM_ARG_RETURN_CTX,
/*processor*/ AVM_ARG_STRING_CPU,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_EXPRESSION_KIND,
/*dtype */ mainType );
}
return( newCode );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ARITHMETIC LOGIC CPU COMPILATION for UNARY EXPRESSION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeExpressionALUCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileUnaryRvalue(aCTX, aCode, TypeManager::UNIVERSAL) );
}
BF AvmcodeExpressionALUCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
// argsInstruction->setMainBytecode(
// /*context */ AVM_ARG_RETURN_CTX,
// /*processor*/ AVM_ARG_ARITHMETIC_LOGIC_CPU,
// /*operation*/ AVM_ARG_SEVAL_RVALUE,
// /*operand */ AVM_ARG_EXPRESSION_KIND,
// /*dtype */ argsInstruction->at(0).dtype);
return( optimizeUnaryRvalue(aCTX, aCode, TypeManager::UNIVERSAL,
AVM_ARG_ARITHMETIC_LOGIC_CPU, TypeManager::UNIVERSAL) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ARITHMETIC LOGIC CPU COMPILATION for UNARY EXPRESSION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeUnaryArithmeticExpressionALUCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileUnaryRvalue(aCTX, aCode, TypeManager::UNIVERSAL) );
}
BF AvmcodeUnaryArithmeticExpressionALUCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
// argsInstruction->setMainBytecode(
// /*context */ AVM_ARG_RETURN_CTX,
// /*processor*/ AVM_ARG_ARITHMETIC_LOGIC_CPU,
// /*operation*/ AVM_ARG_SEVAL_RVALUE,
// /*operand */ AVM_ARG_EXPRESSION_KIND,
// /*dtype */ argsInstruction->at(0).dtype);
return( optimizeUnaryRvalue(aCTX, aCode, TypeManager::UNIVERSAL,
AVM_ARG_ARITHMETIC_LOGIC_CPU, TypeManager::UNIVERSAL) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ARITHMETIC LOGIC CPU COMPILATION for BINARY EXPRESSION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeBinaryArithmeticExpressionALUCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileBinaryRvalue(aCTX, aCode,
TypeManager::UNIVERSAL, TypeManager::UNIVERSAL) );
}
BF AvmcodeBinaryArithmeticExpressionALUCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( optimizeBinaryRvalue(aCTX, aCode,
TypeManager::UNIVERSAL, TypeManager::UNIVERSAL,
AVM_ARG_ARITHMETIC_LOGIC_CPU, TypeManager::UNIVERSAL) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ARITHMETIC LOGIC CPU COMPILATION for ASSOCIATIVE EXPRESSION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeAssociativeArithmeticExpressionALUCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileAssociativeRvalue(aCTX, aCode, TypeManager::UNIVERSAL) );
}
BF AvmcodeAssociativeArithmeticExpressionALUCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( optimizeAssociativeRvalue(aCTX, aCode, TypeManager::UNIVERSAL,
AVM_ARG_ARITHMETIC_LOGIC_CPU, TypeManager::UNIVERSAL) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE PREDICAT EXPRESSION COMPILATION
////////////////////////////////////////////////////////////////////////////////
static void compareStructure(BaseAvmProgram * aProgram, AvmCode * expandCode,
Operator * op, const Symbol & arg1, const Symbol & arg2)
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
// AVM_OS_TRACE << "compareStructure:> " << std::endl;
// arg1.toStream(AVM_OS_TRACE);
// arg2.toStream(AVM_OS_TRACE);
AVM_OS_TRACE << "compareStructure:> " << std::endl
<< "\t" << str_header( arg1 ) << std::endl
<< "\t" << str_header( arg2 ) << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
if( arg1.hasAttribute() && arg2.hasAttribute() )
{
TableOfSymbol::const_iterator it1 = arg1.getAttribute()->begin();
TableOfSymbol::const_iterator it2 = arg2.getAttribute()->begin();
TableOfSymbol::const_iterator itEnd = arg1.getAttribute()->end();
for( ; it1 != itEnd ; ++it1 , ++it2 )
{
compareStructure(aProgram, expandCode, op, (*it1) , (*it2));
}
}
else if( arg1.hasAttribute() || arg2.hasAttribute() )
{
const Symbol & argAttrs = arg1.hasAttribute() ? arg1 : arg2;
const Symbol & argOther = arg1.hasDataPath() ? arg1 : arg2;
Symbol argAlias;
std::string aQualifiedNameID;
TableOfSymbol::const_iterator it = argAttrs.getAttribute()->begin();
TableOfSymbol::const_iterator itEnd = argAttrs.getAttribute()->end();
for( ; it != itEnd ; ++it )
{
argAlias = new InstanceOfData(argOther.getPointerNature(),
argOther.getContainer(), argOther.rawData(),
*(argOther.getDataPath()), (*it));
aQualifiedNameID = (*it).getFullyQualifiedNameID().substr(
argAttrs.getFullyQualifiedNameID().length() + 1);
argAlias.updateFullyQualifiedNameID(
OSS() << argOther.getFullyQualifiedNameID()
<< '.' << aQualifiedNameID,
OSS() << argOther.getNameID() << '.' << aQualifiedNameID );
aProgram->appendDataAlias(argAlias);
compareStructure(aProgram, expandCode, op, (*it) , argAlias);
}
}
else if( arg1.isTypedStructure() )
{
Symbol arg1Alias;
Symbol arg2Alias;
std::string id;
ClassTypeSpecifier * structT =
arg1.getTypeSpecifier()->as< ClassTypeSpecifier >();
TableOfSymbol::const_iterator it = structT->getSymbolData().begin();
TableOfSymbol::const_iterator itEnd = structT->getSymbolData().end();
for( ; it != itEnd ; ++it )
{
id = (*it).getNameID();
arg1Alias = new InstanceOfData(arg1.getPointerNature(),
arg1.getContainer(), arg1.rawData(),
*(arg1.getDataPath()), (*it));
arg1Alias.updateFullyQualifiedNameID(
( OSS() << arg1.getFullyQualifiedNameID() << '.' << id ),
( OSS() << arg1.getNameID() << '.' << id ) );
aProgram->appendDataAlias(arg1Alias);
arg2Alias = new InstanceOfData(arg2.getPointerNature(),
arg2.getContainer(), arg2.rawData(),
*(arg2.getDataPath()), (*it));
arg2Alias.updateFullyQualifiedNameID(
( OSS() << arg2.getFullyQualifiedNameID() << '.' << id ),
( OSS() << arg2.getNameID() << '.' << id ) );
aProgram->appendDataAlias(arg2Alias);
compareStructure(aProgram, expandCode, op, arg1Alias , arg2Alias);
}
}
else
{
BFCode atomCode(op);
if( arg1.isFieldClassAttributePointer() ||
arg1.isFieldArrayOffsetPointer() )
{
atomCode->append( INCR_BF( arg1.getAliasTarget() ) );
}
else
{
atomCode->append( arg1 );
}
if( arg2.isFieldClassAttributePointer() ||
arg2.isFieldArrayOffsetPointer() )
{
atomCode->append( INCR_BF( arg2.getAliasTarget() ) );
}
else
{
atomCode->append( arg2 );
}
expandCode->append( atomCode );
}
}
static void compareStructure(BaseAvmProgram * aProgram, AvmCode * expandCode,
Operator * op, const Symbol & arg1, const BF & arg2)
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
// AVM_OS_TRACE << "compareStructure:> " << std::endl;
// arg1.toStream(AVM_OS_TRACE);
// arg2.toStream(AVM_OS_TRACE);
AVM_OS_TRACE << "compareStructure:> " << std::endl
<< "\t" << str_header( arg1 ) << std::endl
<< "\t" << arg2.str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
if( arg1.hasAttribute() && arg2.is< ArrayBF >())
{
ArrayBF * arg2Array = arg2.to_ptr< ArrayBF >();
avm_size_t offset = 0;
TableOfSymbol::const_iterator it = arg1.getAttribute()->begin();
TableOfSymbol::const_iterator itEnd = arg1.getAttribute()->end();
for( ; (it != itEnd) && (offset < arg2Array->size()) ; ++it , ++offset )
{
compareStructure(aProgram, expandCode,
op, (*it), arg2Array->at(offset));
}
}
else if( arg1.isTypedStructure() && arg2.is< ArrayBF >() )
{
ArrayBF * arg2Array = arg2.to_ptr< ArrayBF >();
avm_size_t offset = 0;
Symbol arg1Alias;
std::string id;
ClassTypeSpecifier * structT =
arg1.getTypeSpecifier()->as< ClassTypeSpecifier >();
TableOfSymbol::const_iterator it = structT->getSymbolData().begin();
TableOfSymbol::const_iterator itEnd = structT->getSymbolData().end();
for( ; (it != itEnd) && (offset < arg2Array->size()) ; ++it , ++offset )
{
id = (*it).getNameID();
arg1Alias = new InstanceOfData(arg1.getPointerNature(),
arg1.getContainer(), arg1.rawData(),
*(arg1.getDataPath()), (*it));
arg1Alias.updateFullyQualifiedNameID(
( OSS() << arg1.getFullyQualifiedNameID() << '.' << id ),
( OSS() << arg1.getNameID() << '.' << id ) );
aProgram->appendDataAlias(arg1Alias);
compareStructure(aProgram, expandCode, op,
arg1Alias, arg2Array->at(offset));
}
}
else
{
BFCode atomCode(op);
if( arg1.isFieldClassAttributePointer() ||
arg1.isFieldArrayOffsetPointer() )
{
atomCode->append( INCR_BF( arg1.getAliasTarget() ) );
}
else
{
atomCode->append( arg1 );
}
atomCode->append( arg2 );
expandCode->append( atomCode );
}
}
BF AvmcodeRelationalExpressionCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BFCode compileCode = compileBinaryRvalue(aCTX, aCode,
TypeManager::UNIVERSAL, TypeManager::UNIVERSAL);
if( compileCode->first().is< InstanceOfData >() )
{
Symbol arg1( compileCode->first() );
if( aCTX->isNeedTypeChecking() )
{
checkArgType(aCTX, arg1.getTypeSpecifier(), compileCode->second());
}
if( arg1.hasTypeArrayOrStructure() )
{
if( compileCode->second().is< InstanceOfData >() )
{
Symbol arg2( compileCode->second() );
if( arg1.getTypeSpecifier() == arg2.getTypeSpecifier() )
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
AVM_OS_TRACE << "AvmcodeRelationalExpressionCompiler:>\n"
<< "\t" << str_header( arg1 ) << std::endl
<< "\t" << str_header( arg2 ) << std::endl;
AVM_OS_TRACE << "Comparison of data structure << "
<< compileCode->str() << " >> " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
BFCode expandCode(
aCode->isOpCode( AVM_OPCODE_NEQ ) ?
OperatorManager::OPERATOR_OR :
OperatorManager::OPERATOR_AND );
compareStructure(aCTX->mCompileCtx, expandCode,
aCode->getOperator(), arg1, arg2);
if( expandCode->singleton() && expandCode.is< AvmCode >() )
{
compileCode = expandCode->first();
}
else
{
compileCode = expandCode;
}
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
AVM_OS_TRACE << "AvmcodeRelationalExpressionCompiler:result>\n"
<< compileCode.str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
}
}
else if( compileCode->second().is< ArrayBF >() )
{
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
AVM_OS_TRACE << "AvmcodeRelationalExpressionCompiler:>\n"
<< "\t" << str_header( arg1 ) << std::endl
<< "\t" << compileCode->second().str() << std::endl;
AVM_OS_TRACE << "Comparison of data structre << "
<< compileCode->str() << " >> " << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
BFCode expandCode(
aCode->isOpCode( AVM_OPCODE_NEQ ) ?
OperatorManager::OPERATOR_OR :
OperatorManager::OPERATOR_AND );
compareStructure(aCTX->mCompileCtx, expandCode,
aCode->getOperator(), arg1, compileCode->second());
if( expandCode->singleton() && expandCode.is< AvmCode >() )
{
compileCode = expandCode->first();
}
else
{
compileCode = expandCode;
}
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
AVM_OS_TRACE << "AvmcodeRelationalExpressionCompiler:result>\n"
<< compileCode.str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , COMPILING )
}
}
}
else if( compileCode->second().is< InstanceOfData >() )
{
if( aCTX->isNeedTypeChecking() )
{
checkArgType(aCTX, compileCode->second().to_ptr<
InstanceOfData >()->getTypeSpecifier(), compileCode->first());
}
}
return( compileCode );
}
BF AvmcodeRelationalExpressionCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
avm_arg_processor_t processor = AVM_ARG_ARITHMETIC_LOGIC_CPU;
if( aCode->first().is< InstanceOfData >() &&
aCode->first().to_ptr< InstanceOfData >()->hasTypeArrayOrStructure() )
{
processor = AVM_ARG_ARRAY_RVALUE_CPU;
}
else if( aCode->second().is< InstanceOfData >() &&
aCode->second().to_ptr< InstanceOfData >()->hasTypeArrayOrStructure() )
{
processor = AVM_ARG_ARRAY_RVALUE_CPU;
}
else if( aCode->first().is< ArrayBF >() || aCode->second().is< ArrayBF >() )
{
processor = AVM_ARG_ARRAY_RVALUE_CPU;
}
return( optimizeBinaryRvalue( aCTX, aCode, TypeManager::UNIVERSAL,
TypeManager::UNIVERSAL, processor, TypeManager::BOOLEAN) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE PREDICATE EXPRESSION COMPILATION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeUnaryPredicateExpressionCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileUnaryRvalue(aCTX, aCode, TypeManager::BOOLEAN) );
}
BF AvmcodeUnaryPredicateExpressionCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( optimizeUnaryRvalue(aCTX, aCode, TypeManager::BOOLEAN,
AVM_ARG_ARITHMETIC_LOGIC_CPU, TypeManager::BOOLEAN) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE PREDICATE EXPRESSION COMPILATION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeBinaryPredicateExpressionCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileBinaryRvalue(aCTX, aCode,
TypeManager::BOOLEAN, TypeManager::BOOLEAN) );
}
BF AvmcodeBinaryPredicateExpressionCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( optimizeBinaryRvalue(aCTX, aCode,
TypeManager::BOOLEAN, TypeManager::BOOLEAN,
AVM_ARG_ARITHMETIC_LOGIC_CPU, TypeManager::BOOLEAN) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE PREDICATE EXPRESSION COMPILATION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeAssociativePredicateExpressionCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileAssociativeRvalue(aCTX, aCode, TypeManager::BOOLEAN) );
}
BF AvmcodeAssociativePredicateExpressionCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( optimizeAssociativeRvalue(aCTX, aCode, TypeManager::BOOLEAN,
AVM_ARG_ARITHMETIC_LOGIC_CPU, TypeManager::BOOLEAN) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE BITWISE EXPRESSION COMPILATION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeUnaryBitwiseExpressionCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileUnaryRvalue(aCTX, aCode, TypeManager::INTEGER) );
}
BF AvmcodeUnaryBitwiseExpressionCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( optimizeUnaryRvalue(aCTX, aCode, TypeManager::INTEGER,
AVM_ARG_ARITHMETIC_LOGIC_CPU, TypeManager::INTEGER) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE BITWISE EXPRESSION COMPILATION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeBinaryBitwiseExpressionCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileBinaryRvalue(aCTX, aCode,
TypeManager::INTEGER, TypeManager::INTEGER) );
}
BF AvmcodeBinaryBitwiseExpressionCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( optimizeBinaryRvalue(aCTX, aCode,
TypeManager::INTEGER, TypeManager::INTEGER,
AVM_ARG_ARITHMETIC_LOGIC_CPU, TypeManager::INTEGER) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE BITWISE EXPRESSION COMPILATION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeAssociativeBitwiseExpressionCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileAssociativeRvalue(aCTX, aCode, TypeManager::INTEGER) );
}
BF AvmcodeAssociativeBitwiseExpressionCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( optimizeAssociativeRvalue(aCTX, aCode, TypeManager::INTEGER,
AVM_ARG_ARITHMETIC_LOGIC_CPU, TypeManager::INTEGER) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE STRING UNARY EXPRESSION COMPILATION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeUnaryStringExpressionCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileUnaryRvalue(aCTX, aCode, TypeManager::STRING) );
}
BF AvmcodeUnaryStringExpressionCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( optimizeUnaryRvalue(aCTX, aCode, TypeManager::STRING,
AVM_ARG_STRING_CPU, TypeManager::UNIVERSAL) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE STRING BINARY EXPRESSION COMPILATION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeBinaryStringExpressionCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileBinaryRvalue(aCTX, aCode,
TypeManager::STRING, TypeManager::STRING) );
}
BF AvmcodeBinaryStringExpressionCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( optimizeBinaryRvalue(aCTX, aCode,
TypeManager::STRING, TypeManager::STRING,
AVM_ARG_STRING_CPU, TypeManager::UNIVERSAL) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ASSOCIATIVE BINARY EXPRESSION COMPILATION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeAssociativeStringExpressionCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
Operator * mainOperator = aCode->getOperator();
BFCode newCode( mainOperator );
BF arg;
AvmCode * pCode;
aCTX = aCTX->clone(TypeManager::STRING);
AvmCode::iterator itArg = aCode->begin();
AvmCode::iterator itEndArg = aCode->end();
for( ; itArg != itEndArg ; ++itArg )
{
arg = AVMCODE_COMPILER.decode_compileExpression(aCTX, *itArg);
if( arg.valid() )
{
if( (not ExpressionTypeChecker::isTyped(TypeManager::STRING, arg))
&& arg.isnot< BuiltinForm >() )
{
arg = ExpressionConstructor::newCode(
OperatorManager::OPERATOR_CTOR, TypeManager::STRING, arg);
}
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "AvmCode< expression > compilation error << "
<< (*itArg).str() << " >>" << std::endl << std::endl;
newCode->append( arg );
continue;
}
if( arg.is< AvmCode >() )
{
pCode = arg.to_ptr< AvmCode >();
if( pCode->isOperator( mainOperator ) &&
mainOperator->isAssociative() )
{
newCode->append( pCode->getArgs() );
}
else
{
newCode->append( arg );
}
}
else
{
newCode->append( arg );
}
}
return( newCode );
}
BF AvmcodeAssociativeStringExpressionCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
Operator * mainOperator = aCode->getOperator();
BFCode newCode( mainOperator );
BF arg;
AvmCode * pCode;
AvmCode::iterator itArg = aCode->begin();
AvmCode::iterator itEndArg = aCode->end();
AvmInstruction * argsInstruction = newCode->newEmptyInstruction();
Vector< AvmBytecode > vectorOfArgOpcode;
for( ; itArg != itEndArg ; ++itArg )
{
arg = AVMCODE_COMPILER.decode_optimizeExpression(aCTX, *itArg);
if( arg.invalid() )
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "AvmCode< expression > optimization error << "
<< (*itArg).str() << " >>" << std::endl << std::endl;
newCode->append( arg );
continue;
}
if( arg.is< AvmCode >() )
{
pCode = arg.to_ptr< AvmCode >();
if( pCode->isOperator( mainOperator ) &&
mainOperator->isAssociative() )
{
newCode->append( pCode->getArgs() );
vectorOfArgOpcode.append(
pCode->getInstruction()->getBytecode(), pCode->size());
}
else
{
newCode->append( arg );
if( pCode->hasInstruction() )
{
vectorOfArgOpcode.append( argcodeOfExpression(aCTX, pCode) );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected expression without argcode << "
<< pCode->strDebug() << " >> !!!"
<< SEND_EXIT;
vectorOfArgOpcode.append( AvmBytecode(AVM_ARG_ARGUMENT_CTX,
AVM_ARG_SEVAL_RVALUE, AVM_ARG_EXPRESSION_KIND) );
}
vectorOfArgOpcode.back().context = AVM_ARG_ARGUMENT_CTX;
}
}
else
{
newCode->append( arg );
AvmBytecode argOpcode;
setArgcodeRValue(aCTX, argOpcode, arg, false);
argOpcode.context = AVM_ARG_ARGUMENT_CTX;
if( (not ExpressionTypeChecker::isTyped(TypeManager::STRING, arg))
&& arg.is< BuiltinForm >() )
{
argOpcode.processor = AVM_ARG_STRING_CPU;
}
vectorOfArgOpcode.append( argOpcode );
}
}
argsInstruction->setMainBytecode(
/*context */ AVM_ARG_RETURN_CTX,
/*processor*/ AVM_ARG_STRING_CPU,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_EXPRESSION_KIND,
/*dtype */ TypeManager::STRING );
argsInstruction->computeBytecode( false , vectorOfArgOpcode );
return( newCode );
}
} /* namespace sep */