| /******************************************************************************* |
| * 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 */ |