blob: 9f06dec38bb3671c45b06dcf0dd504defcd89008 [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
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "AvmCode.h"
#include <fml/common/BehavioralElement.h>
#include <fml/common/ObjectElement.h>
#include <fml/executable/AvmProgram.h>
#include <fml/executable/BaseAvmProgram.h>
#include <fml/executable/BaseCompiledForm.h>
#include <fml/executable/BaseInstanceForm.h>
#include <fml/expression/BuiltinArray.h>
#include <fml/builtin/BuiltinForm.h>
#include <fml/expression/ExpressionComparer.h>
#include <fml/expression/ExpressionComparer.h>
#include <fml/expression/StatementTypeChecker.h>
#include <fml/operator/OperatorManager.h>
#include <fml/runtime/RuntimeID.h>
#include <fml/type/BaseTypeSpecifier.h>
#include <fml/workflow/UniFormIdentifier.h>
#include <fml/workflow/WObject.h>
namespace sep
{
/**
* DEFAULT NULL
*/
BFCode BFCode::REF_NULL;
/**
* COMPARISON
* OPERATOR
*/
int AvmCode::compare(const AvmCode & other) const
{
if( this == &other )
{
return( 0 );
}
else if( sameOperator( other ) )
{
int cmpResult = 0;
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
AvmCode::const_iterator itOther = other.begin();
AvmCode::const_iterator endOther = other.end();
for( ; (it != endIt) && (itOther != endOther) ; ++it , ++itOther )
{
cmpResult = (*it).compare( *itOther );
if( cmpResult != 0 )
{
return( cmpResult );
}
}
return( (size() == other.size()) ? 0 :
((size() < other.size()) ? -1 : 1) );
}
else
{
return( (getAvmOpCode() < other.getAvmOpCode()) ? -1 : 1 );
}
}
bool AvmCode::isEQ(const AvmCode & other) const
{
if( this == &other )
{
return( true );
}
else if( sameOperator( other ) && (size() == other.size()) )
{
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
AvmCode::const_iterator itOther = other.begin();
for( ; it != endIt ; ++it , ++itOther )
{
if( not (*it).isEQ( *itOther ) )
{
return( false );
}
}
return( true );
}
else
{
return( false );
}
}
/**
* AvmCode::toStream
* Serialization
*/
OutStream & AvmCode::toDebug(OutStream & out) const
{
AVM_IF_DEBUG_NOT_FLAG_AND( BYTECODE , hasInstruction() )
AVM_DEBUG_ENABLE_FLAG( BYTECODE )
toStreamWithBytecode( out << TAB << "$" ) << EOL_FLUSH;
AVM_DEBUG_DISABLE_FLAG( BYTECODE )
AVM_ELSE
toStream(out);
AVM_ENDIF_DEBUG_NOT_FLAG_AND( BYTECODE )
return( out );
}
void AvmCode::toStreamPrefix(OutStream & out, const BF & arg)
{
if( arg.invalid() )
{
out << TAB << "null<avmcode::arg>" << EOL;
}
else if( arg.is< BuiltinForm >() )
{
out << TAB << arg.to_ptr< BuiltinForm >()->str() << EOL;
}
else if( arg.is< Operator >() )
{
out << TAB << arg.to_ptr< Operator >()->standardSymbol();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< Routine >() )
{
arg.to_ptr< Routine >()->toStreamInvoke(out);
}
else if( arg.is< PropertyElement >() )
{
out << TAB << "&"
<< arg.to_ptr< PropertyElement >()->getFullyQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< BaseInstanceForm >() )
{
out << TAB
<< arg.to_ptr< BaseInstanceForm >()->getFullyQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< BehavioralElement >() )
{
out << TAB << "&"
<< arg.to_ptr< BehavioralElement >()->getFullyQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( WObjectManager::is( arg ) )
{
out << TAB << "&"
<< WObjectManager::from( arg )->getFullyQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< RuntimeID >() )
{
out << TAB << arg.bfRID().str() << EOL;
}
else if( arg.is_exactly< AvmProgram >() )
{
AvmProgram * aProg = arg.to_ptr< AvmProgram >();
if( aProg->isAnonym() )
{
aProg->toStream(out);
}
else
{
out << TAB << aProg->getFullyQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
}
else if( arg.is< BaseAvmProgram >() )
{
out << TAB
<< arg.to_ptr< BaseAvmProgram >()->getFullyQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< BaseTypeSpecifier >() )
{
out << TAB
<< arg.to_ptr< BaseTypeSpecifier >()->getFullyQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< ObjectElement >() )
{
out << TAB << "&"
<< arg.to_ptr< ObjectElement >()->getFullyQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< BuiltinArray >() )
{
arg.to_ptr< BuiltinArray >()->toStream(out);
}
else if ( arg.is< AvmCode >() )
{
arg.to_ptr< AvmCode >()->toStreamPrefix(out);
}
else
{
out << arg;
}
out << std::flush;
}
OutStream & AvmCode::toStreamWithBytecode(OutStream & out) const
{
out << "{ " << strOperator() << " "
<< mInstruction->getMainBytecode().strCode()
<< EOL_INCR_INDENT;
if( nonempty() )
{
const_iterator it = begin();
const_iterator itEnd = end();
for( avm_size_t argOffset = 0 ; it != itEnd ; ++it , ++argOffset )
{
out << TAB << "$( " << mInstruction->at(argOffset).strCode();
if( (*it).is< AvmCode >() )
{
out << " ";
if( (*it).to_ptr< AvmCode >()->hasInstruction() )
{
(*it).to_ptr< AvmCode >()->toStreamWithBytecode(out);
}
else
{
(*it).to_ptr< AvmCode >()->toStreamPrefix(
out << IGNORE_FIRST_TAB, false );
}
}
else
{
ScopeNewIndent asni(out, AVM_STR_INDENT);
toStreamPrefix( out , (*it) );
}
out << " )" << EOL;
}
}
out << DECR_INDENT_TAB << "}" << std::flush;
return( out );
}
OutStream & AvmCode::toStreamRoutine(OutStream & out) const
{
AVM_IF_DEBUG_FLAG( BYTECODE )
if( hasInstruction() )
{
toStreamWithBytecode( out << "$" ) << EOL_FLUSH;
}
else if( OperatorManager::isSchedule(mOperator) )
{
out << " " << strOperator() << EOL;
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
for( ; it != endIt ; ++it )
{
toStreamPrefix(out, (*it));
}
}
else
{
toStreamPrefix( out << EOL );
}
return( out );
AVM_ENDIF_DEBUG_FLAG( BYTECODE )
if( OperatorManager::isSchedule(mOperator) )
{
out << " " << strOperator() << EOL;
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
for( ; it != endIt ; ++it )
{
prettyPrinter(out, (*it));
}
}
else
{
prettyPrinter( out << EOL );
}
return( out );
}
void AvmCode::toStreamPrefix(OutStream & out, bool printEOL) const
{
AVM_IF_DEBUG_FLAG_AND( BYTECODE , hasInstruction() )
toStreamWithBytecode( out << TAB << "$" ) << EOL_FLUSH;
AVM_ELSE_IF( hasOperator() )
std::string strOperatorStd = strOperator();
out << TAB << "${" << strOperatorStd;
if( OperatorManager::isSchedule( mOperator ) ||
OperatorManager::isConditionnal( mOperator ) )
{
out << EOL_INCR_INDENT;
for( const_iterator it = begin() ; it != end() ; ++it )
{
toStreamPrefix(out, (*it));
}
out << DECR_INDENT_TAB << "}" << std::flush;
}
else if( OperatorManager::isActivity( mOperator )
&& populated()
&& second().is< AvmCode >()
&& StatementTypeChecker::isAssign( second() ) )
{
const_iterator it = begin();
toStreamPrefix( (out << AVM_STR_INDENT), (*it) );
out << END_INDENT << EOL_INCR_INDENT;
for( ++it ; it != end() ; ++it )
{
toStreamPrefix(out, (*it));
}
out << DECR_INDENT_TAB << "}" << std::flush;
}
else //if( OperatorManager::isUfiOrCtor( mOperator ) )
{
out << AVM_STR_INDENT;
for( const_iterator it = begin() ; it != end() ; ++it )
{
toStreamPrefix(out, (*it));
}
out << END_INDENT << " }" << std::flush;
}
if( printEOL )
{
out << EOL_FLUSH;
}
return;
AVM_ELSE_IF( nonempty() )
out << TAB << "{" << EOL_INCR_INDENT;
for( const_iterator it = begin() ; it != end() ; ++it )
{
toStreamPrefix(out, (*it));
}
out << DECR_INDENT_TAB << "}" << EOL_FLUSH;
AVM_ENDIF_DEBUG_FLAG_AND( BYTECODE )
}
void AvmCode::prettyPrinter(OutStream & out, bool isStatement) const
{
// switch( mOperator->getFixNotation() )
// {
// case NOTATION_FUNCTION:
// case NOTATION_INFIX:
// case NOTATION_PREFIX:
// case NOTATION_SUFFIX:
// default:
// }
switch( mOperator->getAvmOpCode() )
{
case AVM_OPCODE_NULL:
// AVM NOP STATEMENT
case AVM_OPCODE_NOP:
case AVM_OPCODE_FAILED:
case AVM_OPCODE_THROW:
// AVM META STATEMENT
case AVM_OPCODE_INFORMAL:
case AVM_OPCODE_TRACE:
case AVM_OPCODE_DEBUG:
case AVM_OPCODE_COMMENT:
case AVM_OPCODE_QUOTE:
case AVM_OPCODE_META_EVAL:
case AVM_OPCODE_META_RUN:
{
prettyPrinterBasicStatement( out , isStatement );
break;
}
// AVM UFI STATEMENT
case AVM_OPCODE_UFI:
{
prettyPrinterDefault( out , false );
break;
}
// AVM FORM CONSTRUCTOR STATEMENT
case AVM_OPCODE_CTOR:
{
out << TAB << "ctor<" << AVM_STR_INDENT;
prettyPrinter( out , first() , false );
out << " >(";
prettyPrinter( out , second() , false );
out << " )" << END_INDENT_EOL;
break;
}
// AVM FORM REGEX STATEMENT
case AVM_OPCODE_REGEX:
{
prettyPrinterDefault( out , false );
break;
}
// AVM MACHINE MANAGING
case AVM_OPCODE_CONTEXT_SWITCHER:
{
out << TAB << "ctx<" << AVM_STR_INDENT;
prettyPrinter( out , first() , false );
out << TAB << "> " << END_INDENT << IGNORE_FIRST_TAB;
prettyPrinter( out , second() , isStatement );
break;
}
case AVM_OPCODE_INIT:
case AVM_OPCODE_FINAL:
case AVM_OPCODE_DESTROY:
case AVM_OPCODE_START:
case AVM_OPCODE_RESTART:
case AVM_OPCODE_STOP:
case AVM_OPCODE_WAIT:
case AVM_OPCODE_SUSPEND:
case AVM_OPCODE_RESUME:
case AVM_OPCODE_IENABLE_INVOKE:
case AVM_OPCODE_ENABLE_INVOKE:
case AVM_OPCODE_ENABLE_SET:
case AVM_OPCODE_IDISABLE_INVOKE:
case AVM_OPCODE_DISABLE_INVOKE:
case AVM_OPCODE_DISABLE_SET:
case AVM_OPCODE_DISABLE_CHILD:
case AVM_OPCODE_DISABLE_SELF:
case AVM_OPCODE_DISABLE_SELVES:
case AVM_OPCODE_IABORT_INVOKE:
case AVM_OPCODE_ABORT_INVOKE:
case AVM_OPCODE_ABORT_SET:
case AVM_OPCODE_ABORT_CHILD:
case AVM_OPCODE_ABORT_SELF:
case AVM_OPCODE_ABORT_SELVES:
case AVM_OPCODE_HISTORY_CLEAR:
case AVM_OPCODE_DEEP_HISTORY_INVOKE:
case AVM_OPCODE_SHALLOW_HISTORY_INVOKE:
case AVM_OPCODE_IRUN:
case AVM_OPCODE_RUN:
case AVM_OPCODE_RTC:
case AVM_OPCODE_SCHEDULE_INVOKE:
case AVM_OPCODE_SCHEDULE_GET:
case AVM_OPCODE_SCHEDULE_IN:
case AVM_OPCODE_SCHEDULE_SET:
case AVM_OPCODE_DEFER_INVOKE:
case AVM_OPCODE_DEFER_GET:
case AVM_OPCODE_DEFER_SET:
case AVM_OPCODE_GOTO:
{
prettyPrinterBasicStatement( out , isStatement );
break;
}
case AVM_OPCODE_FORK:
case AVM_OPCODE_JOIN:
case AVM_OPCODE_INPUT_ENABLED:
case AVM_OPCODE_RDV:
case AVM_OPCODE_SYNCHRONIZE:
{
prettyPrinterDefault( out , isStatement );
break;
}
case AVM_OPCODE_INVOKE_NEW:
case AVM_OPCODE_INVOKE_ROUTINE:
case AVM_OPCODE_INVOKE_TRANSITION:
case AVM_OPCODE_INVOKE_METHOD:
case AVM_OPCODE_INVOKE_PROGRAM:
case AVM_OPCODE_INVOKE_FUNCTION:
case AVM_OPCODE_INVOKE_LAMBDA_APPLY:
case AVM_OPCODE_INVOKE_LAMBDA_LET:
{
prettyPrinterBasicStatement( out , isStatement );
break;
}
// AVM MACHINE STATUS
case AVM_OPCODE_STATUS_WAS:
case AVM_OPCODE_STATUS_IS:
case AVM_OPCODE_STATUS_BEING:
case AVM_OPCODE_STATUS_WILL:
case AVM_OPCODE_CHANGED:
case AVM_OPCODE_CHANGED_TO:
{
prettyPrinterDefault( out , isStatement );
break;
}
// AVM PROGRAM SCHEDULING
case AVM_OPCODE_ASYNCHRONOUS:
case AVM_OPCODE_STRONG_SYNCHRONOUS:
case AVM_OPCODE_WEAK_SYNCHRONOUS:
case AVM_OPCODE_INTERLEAVING:
case AVM_OPCODE_PARTIAL_ORDER_REDUCTION:
case AVM_OPCODE_PARALLEL:
// Optimized version of concurrency for RDV synchronization
case AVM_OPCODE_RDV_ASYNCHRONOUS:
case AVM_OPCODE_RDV_STRONG_SYNCHRONOUS:
case AVM_OPCODE_RDV_WEAK_SYNCHRONOUS:
case AVM_OPCODE_RDV_INTERLEAVING:
case AVM_OPCODE_RDV_PARTIAL_ORDER_REDUCTION:
case AVM_OPCODE_RDV_PARALLEL:
case AVM_OPCODE_EXCLUSIVE:
case AVM_OPCODE_NONDETERMINISM:
case AVM_OPCODE_PRIOR_GT:
case AVM_OPCODE_PRIOR_LT:
case AVM_OPCODE_SCHEDULE_AND_THEN:
case AVM_OPCODE_SCHEDULE_OR_ELSE:
case AVM_OPCODE_ATOMIC_SEQUENCE:
case AVM_OPCODE_SEQUENCE:
case AVM_OPCODE_SEQUENCE_SIDE:
case AVM_OPCODE_SEQUENCE_WEAK:
case AVM_OPCODE_PRODUCT:
// AVM BUFFER MANAGING
case AVM_OPCODE_UPDATE_BUFFER:
{
prettyPrinterBlockStatement( out , isStatement );
break;
}
// LAMBDA STATEMENT
case AVM_OPCODE_APPLY:
case AVM_OPCODE_LAMBDA:
// FUNCTIONB STATEMENT
case AVM_OPCODE_FUN:
// LET STATEMENT
case AVM_OPCODE_LET:
{
prettyPrinterDefault( out , isStatement );
break;
}
// LOOKUP STATEMENT
case AVM_OPCODE_LOOKUP_INT_EXT:
case AVM_OPCODE_LOOKUP_INT:
case AVM_OPCODE_LOOKUP_NEAREST:
case AVM_OPCODE_LOOKUP_BELOW:
case AVM_OPCODE_LOOKUP_ABOVE:
case AVM_OPCODE_LOOKUP2D_INT_EXT:
{
prettyPrinterFunctional( out );
break;
}
// AVM PRIMITIVE STATEMENT
case AVM_OPCODE_ASSIGN:
case AVM_OPCODE_ASSIGN_AFTER:
case AVM_OPCODE_ASSIGN_OP:
case AVM_OPCODE_ASSIGN_OP_AFTER:
case AVM_OPCODE_ASSIGN_REF:
case AVM_OPCODE_ASSIGN_MACRO:
{
out << TAB << AVM_STR_INDENT;
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
prettyPrinter(out, (*it), false);
BaseTypeSpecifier * aType = (*it).is< InstanceOfData >() ?
(*it).to_ptr< InstanceOfData >()->getTypeSpecifier() : NULL;
for( ++it ; it != endIt ; ++it )
{
out << TAB << strOperator();
prettyPrinter(out, (*it), aType);
}
( isStatement ? (out << ";") : out ) << END_INDENT_EOL;
break;
}
case AVM_OPCODE_ASSIGN_NEWFRESH:
case AVM_OPCODE_ASSIGN_RESET:
{
prettyPrinterFunctional( out );
break;
}
case AVM_OPCODE_GUARD:
case AVM_OPCODE_TIMED_GUARD:
case AVM_OPCODE_EVENT:
case AVM_OPCODE_CHECK_SAT:
{
prettyPrinterBasicStatement( out , isStatement );
break;
}
case AVM_OPCODE_INPUT:
case AVM_OPCODE_INPUT_FROM:
case AVM_OPCODE_INPUT_SAVE:
// Optimized version of INPUT
case AVM_OPCODE_INPUT_ENV:
case AVM_OPCODE_INPUT_VAR:
case AVM_OPCODE_INPUT_FLOW:
case AVM_OPCODE_INPUT_BUFFER:
case AVM_OPCODE_INPUT_RDV:
case AVM_OPCODE_INPUT_MULTI_RDV:
case AVM_OPCODE_INPUT_BROADCAST:
case AVM_OPCODE_INPUT_DELEGATE:
case AVM_OPCODE_OUTPUT:
case AVM_OPCODE_OUTPUT_TO:
// Optimized version of OUTPUT
case AVM_OPCODE_OUTPUT_ENV:
case AVM_OPCODE_OUTPUT_VAR:
case AVM_OPCODE_OUTPUT_FLOW:
case AVM_OPCODE_OUTPUT_BUFFER:
case AVM_OPCODE_OUTPUT_RDV:
case AVM_OPCODE_OUTPUT_MULTI_RDV:
case AVM_OPCODE_OUTPUT_BROADCAST:
case AVM_OPCODE_OUTPUT_DELEGATE:
{
out << TAB << strOperator() << " " << AVM_NO_INDENT;
prettyPrinter(out, first(), false);
if( populated() )
{
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
out << "(";
prettyPrinter(out, *(++it), false);
for( ++it ; it != endIt ; ++it )
{
out << ", ";
prettyPrinter(out, (*it), false);
}
out << ")";
}
out << ";" << END_INDENT_EOL;
break;
}
case AVM_OPCODE_PRESENT:
case AVM_OPCODE_ABSENT:
{
out << TAB << strOperator() << " " << AVM_NO_INDENT;
prettyPrinter(out, first(), false);
if( populated() )
{
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
out << "(";
prettyPrinter(out, *(++it), false);
for( ++it ; it != endIt ; ++it )
{
out << ", ";
prettyPrinter(out, (*it), false);
}
out << ")";
}
( isStatement ? (out << ";") : out ) << END_INDENT_EOL;
break;
}
case AVM_OPCODE_IF:
{
out << TAB << "if";
prettyPrinterCondition( out , first() );
prettyPrinterBlock( out << EOL , second() );
break;
}
case AVM_OPCODE_IFE:
{
out << TAB << "if";
prettyPrinterCondition( out , first() );
prettyPrinterBlock( out << EOL , second() );
out << TAB << "else" << EOL;
prettyPrinterBlock( out , third() );
break;
}
case AVM_OPCODE_WHERE:
{
out << TAB << "where";
prettyPrinterCondition( out , first() );
prettyPrinterBlock( out << EOL , second() );
break;
}
case AVM_OPCODE_WHERE_ELSE:
{
prettyPrinterCondition( out << TAB << "where" , first() );
prettyPrinterBlock( out << EOL , second() );
prettyPrinterBlock( out << TAB << "else" << EOL , third() );
break;
}
case AVM_OPCODE_FOR:
{
out << TAB << "for( " << AVM_NO_INDENT;
prettyPrinter( out , first() , false );
out << " ; ";
prettyPrinter( out , second() , false );
out << " ; ";
prettyPrinter( out , third() , false );
out << " )" << END_INDENT_EOL;
prettyPrinterBlock( out , fourth() );
break;
}
case AVM_OPCODE_FOREACH:
{
out << TAB << "for( " << AVM_NO_INDENT;
prettyPrinter( out , first() , false );
out << " : ";
prettyPrinter( out , second() , false );
out << " )" << END_INDENT_EOL;
prettyPrinterBlock( out , third() );
break;
}
case AVM_OPCODE_WHILE_DO:
{
prettyPrinterCondition( out << TAB << "while" , first() );
prettyPrinterBlock( out << EOL , second() );
break;
}
case AVM_OPCODE_DO_WHILE:
{
prettyPrinterBlock( out << TAB << "do" << EOL , first() );
prettyPrinterCondition( out << TAB << "while" , second() );
out << ";" << EOL;
break;
}
case AVM_OPCODE_BREAK:
case AVM_OPCODE_CONTINUE:
case AVM_OPCODE_RETURN:
case AVM_OPCODE_EXIT:
{
prettyPrinterBasicStatement( out , isStatement );
break;
}
case AVM_OPCODE_STEP_MARK:
// AVM QUANTIFIER EXPRESSION
case AVM_OPCODE_EXIST:
case AVM_OPCODE_FORALL:
{
prettyPrinterPrefix( out );
break;
}
// AVM PREDICAT EXPRESSION
case AVM_OPCODE_NOT:
case AVM_OPCODE_AND:
case AVM_OPCODE_AND_THEN:
case AVM_OPCODE_NAND:
case AVM_OPCODE_XAND:
case AVM_OPCODE_OR:
case AVM_OPCODE_OR_ELSE:
case AVM_OPCODE_NOR:
case AVM_OPCODE_XOR:
case AVM_OPCODE_XNOR:
// AVM INTEGER BIT A BIT OPERATOR
case AVM_OPCODE_BNOT:
case AVM_OPCODE_BAND:
case AVM_OPCODE_BOR:
case AVM_OPCODE_BXOR:
case AVM_OPCODE_LSHIFT:
case AVM_OPCODE_RSHIFT:
// AVM COMPARISON EXPRESSION
case AVM_OPCODE_EQ:
case AVM_OPCODE_NEQ:
case AVM_OPCODE_SEQ:
case AVM_OPCODE_NSEQ:
case AVM_OPCODE_LT:
case AVM_OPCODE_LTE:
case AVM_OPCODE_GT:
case AVM_OPCODE_GTE:
// AVM ARITHMETIC EXPRESSION
case AVM_OPCODE_PLUS:
case AVM_OPCODE_MINUS:
case AVM_OPCODE_UMINUS:
case AVM_OPCODE_MULT:
case AVM_OPCODE_POW:
case AVM_OPCODE_DIV:
case AVM_OPCODE_MOD:
{
prettyPrinterInfix( out );
break;
}
// AVM MATHEMATICAL FUNCTION
case AVM_OPCODE_MIN:
case AVM_OPCODE_MAX:
// RANDOM
case AVM_OPCODE_RANDOM:
// ROUNDING
case AVM_OPCODE_ABS:
case AVM_OPCODE_CEIL:
case AVM_OPCODE_FLOOR:
case AVM_OPCODE_ROUND:
case AVM_OPCODE_TRUNCATE:
// EXP - LOG
case AVM_OPCODE_SQRT:
case AVM_OPCODE_EXP:
case AVM_OPCODE_LN:
case AVM_OPCODE_LOG:
// TRIGONOMETRIC
case AVM_OPCODE_SIN:
case AVM_OPCODE_COS:
case AVM_OPCODE_TAN:
case AVM_OPCODE_SINH:
case AVM_OPCODE_COSH:
case AVM_OPCODE_TANH:
case AVM_OPCODE_ASIN:
case AVM_OPCODE_ACOS:
case AVM_OPCODE_ATAN:
case AVM_OPCODE_ATAN2:
case AVM_OPCODE_ASINH:
case AVM_OPCODE_ACOSH:
case AVM_OPCODE_ATANH:
{
prettyPrinterFunctional( out );
break;
}
// AVM STRING / CONTAINER OPERATOR
case AVM_OPCODE_CONTAINS:
case AVM_OPCODE_IN:
case AVM_OPCODE_NOTIN:
case AVM_OPCODE_SUBSET:
case AVM_OPCODE_SUBSETEQ:
case AVM_OPCODE_INTERSECT:
case AVM_OPCODE_STARTS_WITH:
case AVM_OPCODE_ENDS_WITH:
case AVM_OPCODE_CONCAT:
{
prettyPrinterInfix( out );
break;
}
case AVM_OPCODE_APPEND:
case AVM_OPCODE_REMOVE:
case AVM_OPCODE_CLEAR:
case AVM_OPCODE_RESIZE:
case AVM_OPCODE_SELECT:
case AVM_OPCODE_PUSH:
case AVM_OPCODE_ASSIGN_TOP:
case AVM_OPCODE_TOP:
case AVM_OPCODE_POP:
case AVM_OPCODE_POP_FROM:
case AVM_OPCODE_EMPTY:
case AVM_OPCODE_NONEMPTY:
case AVM_OPCODE_SINGLETON:
case AVM_OPCODE_POPULATED:
case AVM_OPCODE_FULL:
case AVM_OPCODE_SIZE:
{
prettyPrinterFunctional( out );
break;
}
// CTL* , IOLTL STATEMENT
case AVM_OPCODE_NECESSARILY:
case AVM_OPCODE_POSSIBLY:
case AVM_OPCODE_GLOBALLY:
case AVM_OPCODE_EVENTUALLY:
case AVM_OPCODE_NEXT:
{
prettyPrinterPrefix( out );
break;
}
case AVM_OPCODE_UNTIL:
case AVM_OPCODE_UNLESS:
case AVM_OPCODE_RELEASES:
case AVM_OPCODE_AND_T:
case AVM_OPCODE_OR_T:
case AVM_OPCODE_NOT_T:
case AVM_OPCODE_IMP_T:
{
prettyPrinterInfix( out );
break;
}
case AVM_OPCODE_OBS:
{
prettyPrinterPrefix( out );
break;
}
default:
{
toStreamPrefix( out );
break;
}
}
out << std::flush;
}
void AvmCode::prettyPrinterBasicStatement(
OutStream & out, bool isStatement) const
{
out << TAB << ( isStatement ? "" : "(" ) << strOperator()
<< AVM_STR_INDENT;
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
for( ; it != endIt ; ++it )
{
prettyPrinter(out, (*it), false);
}
out << ( isStatement ? ";" : ")" ) << END_INDENT_EOL;
}
void AvmCode::prettyPrinterBlockStatement(
OutStream & out, bool isStatement) const
{
out << TAB << "{ " << strOperator() << EOL_INCR_INDENT;
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
for( ; it != endIt ; ++it )
{
prettyPrinter(out, (*it), isStatement);
}
out << DECR_INDENT_TAB << "}" << EOL;
}
void AvmCode::prettyPrinterDefault(OutStream & out, bool isStatement) const
{
out << TAB << "${ " << strOperator() << EOL_INCR_INDENT;
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
for( ; it != endIt ; ++it )
{
prettyPrinter(out, (*it), isStatement);
}
out << DECR_INDENT_TAB << "}" << EOL;
}
void AvmCode::prettyPrinterFunctional(OutStream & out) const
{
out << TAB << strOperator() << "(" << AVM_NO_INDENT;
if( singleton() )
{
prettyPrinter(out, first(), false);
}
else if( populated() )
{
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
prettyPrinter(out, (*it), false);
for( ++it ; it != endIt ; ++it )
{
out << ", ";
prettyPrinter(out, (*it), false);
}
}
out << ")" << END_INDENT_EOL;
}
void AvmCode::prettyPrinterInfix(OutStream & out) const
{
out << TAB << "(" << AVM_NO_INDENT;
if( singleton() )
{
out << strOperator() << " ";
prettyPrinter(out, first(), false);
}
else if( populated() )
{
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
prettyPrinter(out, (*it), false);
for( ++it ; it != endIt ; ++it )
{
out << " " << strOperator() << " ";
prettyPrinter(out, (*it), false);
}
}
out << ")" << END_INDENT_EOL;
}
void AvmCode::prettyPrinterPrefix(OutStream & out) const
{
out << TAB << "(" << strOperator() << AVM_STR_INDENT;
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
for( ; it != endIt ; ++it )
{
prettyPrinter(out, (*it), false);
}
out << ")" << END_INDENT_EOL;
}
void AvmCode::prettyPrinterSuffix(OutStream & out) const
{
out << TAB << "(" << AVM_RTS_INDENT;
AvmCode::const_iterator it = begin();
AvmCode::const_iterator endIt = end();
for( ; it != endIt ; ++it )
{
prettyPrinter(out, (*it), false);
}
out << strOperator() << ")" << END_INDENT_EOL;
}
void AvmCode::prettyPrinter(OutStream & out, const BF & arg, bool isStatement)
{
if( arg.invalid() )
{
out << TAB << "null<avmcode::arg>" << EOL;
}
else if( arg.is< AvmCode >() )
{
arg.to_ptr< AvmCode >()->prettyPrinter(out, isStatement);
}
else if( arg.is< BuiltinForm >() )
{
out << TAB << arg.to_ptr< BuiltinForm >()->str() << EOL;
}
else if( arg.is< Operator >() )
{
out << TAB << arg.to_ptr< Operator >()->standardSymbol();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< Routine >() )
{
arg.to_ptr< Routine >()->toStreamInvoke(out);
}
else if( arg.is< PropertyElement >() )
{
out << TAB << "&"
<< arg.to_ptr< PropertyElement >()->getQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< BaseInstanceForm >() )
{
out << TAB //<< "&"
<< arg.to_ptr< BaseInstanceForm >()->getQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< BehavioralElement >() )
{
out << TAB << "&"
<< arg.to_ptr< BehavioralElement >()->getQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( WObjectManager::is( arg ) )
{
out << TAB << "&"
<< WObjectManager::from( arg )->getQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< UniFormIdentifier >() )
{
out << TAB << arg.to_ptr< UniFormIdentifier >()->str() << EOL;
}
else if( arg.is< RuntimeID >() )
{
out << TAB << arg.bfRID().str() << EOL;
}
else if( arg.is_exactly< AvmProgram >() )
{
AvmProgram * aProg = arg.to_ptr< AvmProgram >();
if( aProg->isAnonym() )
{
aProg->toStream(out);
}
else
{
out << TAB << aProg->getQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
}
else if( arg.is< BaseTypeSpecifier >() )
{
out << TAB << arg.to_ptr< BaseTypeSpecifier >()->strT();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< ObjectElement >() )
{
out << TAB << "&"
<< arg.to_ptr< ObjectElement >()->getQualifiedNameID();
arg.AVM_DEBUG_REF_COUNTER(out);
out << EOL;
}
else if( arg.is< BuiltinArray >() )
{
arg.to_ptr< BuiltinArray >()->toStream(out);
}
else
{
arg.toStream( out );
}
}
void AvmCode::prettyPrinter(OutStream & out,
const BF & arg, BaseTypeSpecifier * aType)
{
if( aType != NULL )
{
aType->formatStream(out, arg);
}
else
{
prettyPrinter(out, arg, false);
}
}
void AvmCode::prettyPrinterCondition(OutStream & out, const BF & arg)
{
out << AVM_STR_INDENT;
if( arg.is< AvmCode >() )
{
arg.to_ptr< AvmCode >()->prettyPrinter( out , false );
}
else
{
prettyPrinter(out << "( ", arg, false);
out << " )";
}
out << END_INDENT;
}
void AvmCode::prettyPrinterBlock(OutStream & out, const BF & arg)
{
if( arg.is< AvmCode >() )
{
if( OperatorManager::isSchedule(arg.to_ptr< AvmCode >()->mOperator) )
{
arg.to_ptr< AvmCode >()->prettyPrinter( out, true );
}
else
{
out << TAB << "{" << EOL_INCR_INDENT;
arg.to_ptr< AvmCode >()->prettyPrinter( out, true );
out << DECR_INDENT_TAB << "}" << EOL;
}
}
else
{
out << TAB << "{" << EOL_INCR_INDENT;
prettyPrinter(out, arg, true);
out << DECR_INDENT_TAB << "}" << EOL;
}
}
}