blob: 34d9fa3b7cc766ffc9214b0bdcefcb8bdc504277 [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: 12 avr. 2011
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "AvmcodeActivityCompiler.h"
#include <collection/Typedef.h>
#include <builder/primitive/AvmcodeSequenceCompiler.h>
#include <builder/primitive/AvmcodeUfiCastExpressionCompiler.h>
#include <fml/common/ObjectElement.h>
#include <fml/executable/ExecutableLib.h>
#include <fml/expression/AvmCode.h>
#include <fml/expression/ExpressionConstructor.h>
#include <fml/expression/ExpressionTypeChecker.h>
#include <fml/expression/StatementConstructor.h>
#include <fml/expression/StatementTypeChecker.h>
#include <fml/operator/OperatorManager.h>
#include <fml/workflow/UniFormIdentifier.h>
namespace sep
{
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ACTIVITY STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeActivityStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
return( aCode );
}
else
{
return( compileStatementParams(aCTX, aCode) );
}
}
BFCode AvmcodeActivityStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->hasInstruction() )
{
return( aCode );
}
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
AvmInstruction * argsInstruction = aCode->genInstruction();
argsInstruction->at(0).dtype = TypeManager::MACHINE;
setArgcodeRValue(aCTX, argsInstruction->at(0), aCode->first());
if( aCode->populated() )
{
AvmCode::iterator itParam = aCode->begin();
AvmCode::iterator itEndParam = aCode->end();
avm_offset_t offset = 1;
for( ++itParam ; itParam != itEndParam ; ++itParam , ++offset )
{
optimizeArgExpression(aCTX, aCode, offset);
setArgcodeParamValue(aCTX, argsInstruction->at(offset), (*itParam), false);
}
}
argsInstruction->computeMainBytecode(
/*context */ AVM_ARG_STANDARD_CTX,
/*processor*/ AVM_ARG_STATEMENT_CPU,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_STATEMENT_KIND,
/*dtype */ argsInstruction->at(0).dtype);
return( aCode );
}
BFCode AvmcodeActivityStatementCompiler::compileStatementParams(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BFCode newCode( aCode->getOperator() );
if( aCode->empty() )
{
return( newCode );
}
AvmCode::iterator itArg = aCode->begin();
newCode->append( compileArgRvalue(aCTX, TypeManager::MACHINE, (*itArg)) );
AvmCode::iterator itEndArg = aCode->end();
for( ++itArg ; itArg != itEndArg ; ++itArg )
{
switch( (*itArg).classKind() )
{
case FORM_AVMCODE_KIND:
{
const BFCode & argCode = (*itArg).bfCode();
if( aCode->populated() &&
StatementTypeChecker::isAssign( argCode ) &&
newCode->first().is< InstanceOfMachine >() )
{
ExecutableForm * execInstance = newCode->first().
to_ptr< InstanceOfMachine >()->getExecutable();
if( argCode->populated() )
{
newCode->append( StatementConstructor::newCode(
argCode->getOperator(),
compileArgLvalue( aCTX->newCTX(execInstance,
Modifier::PROPERTY_PUBLIC_VOLATILE_MODIFIER),
argCode->first()),
compileArgRvalue( aCTX->newCTX(
Modifier::PROPERTY_PUBLIC_VOLATILE_MODIFIER),
argCode->second())) );
}
else
{
newCode->append( StatementConstructor::newCode(
argCode->getOperator(), compileArgLvalue(
aCTX->newCTX(execInstance,
Modifier::PROPERTY_PUBLIC_VOLATILE_MODIFIER),
argCode->first())) );
}
}
else
{
newCode->append(
AVMCODE_COMPILER.compileExpression(aCTX, argCode) );
}
break;
}
default:
{
newCode->append( compileArgRvalue(aCTX, (*itArg)) );
break;
}
}
}
return( newCode );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE CONTEXT SWITCHER STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeContextSwitcherStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->size() != 2 )
{
AVM_OS_FATAL_ERROR_EXIT
<< "Expected CONTEXT SWITCHER with one running "
"machine and a statement as parameter !!!"
<< SEND_EXIT;
}
BF ctxMachine = compileArgRvalue(aCTX, TypeManager::MACHINE, aCode->first() );
if( ctxMachine.is< InstanceOfMachine >() )
{
aCTX = aCTX->newCTX(
//ctxMachine.to_ptr< InstanceOfMachine >()->getExecutable(),
ctxMachine.to_ptr< InstanceOfMachine >()->getExecutable() );
}
return( StatementConstructor::newCode( aCode->getOperator(), ctxMachine,
compileStatementCode(aCTX, aCode->second().bfCode())) );
}
BFCode AvmcodeContextSwitcherStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
AvmInstruction * argsInstruction = aCode->genInstruction();
argsInstruction->at(0).dtype = TypeManager::MACHINE;
setArgcodeRValue(aCTX, argsInstruction->at(0), aCode->first());
if( aCode->first().is< InstanceOfMachine >() )
{
aCTX = aCTX->newCTX(aCode->first().
to_ptr< InstanceOfMachine >()->getExecutable() );
}
optimizeArgStatement(aCTX, aCode, 1);
argsInstruction->at(1).dtype = TypeManager::UNIVERSAL;
setArgcodeStatement(aCTX, argsInstruction->at(1), aCode->second(), false);
argsInstruction->computeMainBytecode(
/*context */ AVM_ARG_STANDARD_CTX,
/*processor*/ AVM_ARG_STATEMENT_CPU,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_STATEMENT_KIND,
/*dtype */ argsInstruction->at(0).dtype);
return( aCode );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE IENABLE STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeIEnableStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
else if( aCode->singleton() )
{
return( StatementConstructor::newCode(aCode->getOperator(),
compileArgRvalue(aCTX, TypeManager::MACHINE, aCode->first())) );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected IENABLE STATEMENT with more "
"than one running machine as parameter !!!"
<< SEND_EXIT;
}
return( aCode );
}
BFCode AvmcodeIEnableStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
ExecutableForm * anExecutable = getExecutableMachine(aCTX, aCode->first());
if( anExecutable != NULL )
{
if( anExecutable->hasOnIEnable() )
{
if( aCTX->isInlineEnable(anExecutable) )
{
BFCode optiCode = AVMCODE_COMPILER.optimizeStatement(
aCTX->newCTX(anExecutable), anExecutable->getOnIEnable() );
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
return( StatementConstructor::newCodeFlat(
OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
StatementConstructor::newComment(
"<ienable> " + anExecutable->getFullyQualifiedNameID()),
optiCode,
StatementConstructor::newComment(
"end<ienable> " + anExecutable->getFullyQualifiedNameID()) ));
AVM_ELSE
return( optiCode );
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
}
else
{
return( AvmcodeActivityStatementCompiler::
optimizeStatement(aCTX, aCode) );
}
}
else
{
return( StatementConstructor::newComment(
"nop<ienable> " + anExecutable->getFullyQualifiedNameID() ));
}
}
return( AvmcodeActivityStatementCompiler::optimizeStatement(aCTX, aCode) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ENABLE STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeEnableStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
else if( aCode->singleton() )
{
return( StatementConstructor::newCode(aCode->getOperator(),
compileArgRvalue(aCTX, TypeManager::MACHINE, aCode->first())) );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected ENABLE STATEMENT with more "
"than one running machine as parameter !!!"
<< SEND_EXIT;
}
return( aCode );
}
BFCode AvmcodeEnableStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
ExecutableForm * anExecutable = getExecutableMachine(aCTX, aCode->first());
if( anExecutable != NULL )
{
if( anExecutable->hasOnEnable() )
{
if( aCTX->isInlineEnable(anExecutable) )
{
BFCode optiCode = AVMCODE_COMPILER.optimizeStatement(
aCTX->newCTX(anExecutable), anExecutable->getOnEnable() );
AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
return( StatementConstructor::newCodeFlatMiddle(
OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
StatementConstructor::newComment(
"begin<enable> " + anExecutable->getFullyQualifiedNameID() ),
optiCode,
StatementConstructor::newComment(
"end<enable> " + anExecutable->getFullyQualifiedNameID()) ));
AVM_ELSE
return( optiCode );
AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
}
else
{
return( AvmcodeActivityStatementCompiler::
optimizeStatement(aCTX, aCode) );
}
}
else
{
return( StatementConstructor::newComment(
"nop<enable> " + anExecutable->getFullyQualifiedNameID() ));
}
}
return( AvmcodeActivityStatementCompiler::optimizeStatement(aCTX, aCode) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE IDISABLE STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeIDisableStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
else if( aCode->singleton() )
{
return( StatementConstructor::newCode( aCode->getOperator(),
compileArgRvalue(aCTX, TypeManager::MACHINE, aCode->first())) );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected IDISABLE STATEMENT with more "
"than one running machine as parameter !!!"
<< SEND_EXIT;
}
return( aCode );
}
BFCode AvmcodeIDisableStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
ExecutableForm * anExecutable = getExecutableMachine(aCTX, aCode->first());
if( anExecutable != NULL )
{
if( anExecutable->hasOnIDisable() )
{
// BFCode optiCode = AVMCODE_COMPILER.optimizeStatement(
// aCTX->newCTX(anExecutable), anExecutable->getOnIDisable() );
//
//AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
// return( StatementConstructor::newCodeFlatMiddle(
// OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
//
// StatementConstructor::newComment(
// "begin<idisable> " + anExecutable->getFullyQualifiedNameID()),
//
// optiCode,
//
// StatementConstructor::newComment(
// "end<idisable> " + anExecutable->getFullyQualifiedNameID()) ));
//_AVM_ELSE_
//
// return( optiCode );
//
//AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
}
else
{
return( StatementConstructor::newComment(
"nop<idisable> " + anExecutable->getFullyQualifiedNameID()) );
}
}
return( AvmcodeActivityStatementCompiler::optimizeStatement(aCTX, aCode) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE DISABLE STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeDisableStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
else if( aCode->singleton() )
{
if( ExpressionTypeChecker::isInteger(aCode->first()) )
{
return( AVMCODE_COMPILER.compileStatement(aCTX,
StatementConstructor::newCode(
OperatorManager::OPERATOR_DISABLE_SELVES,
aCode->first() )));
}
return( StatementConstructor::newCode( aCode->getOperator(),
compileArgRvalue(aCTX, TypeManager::MACHINE, aCode->first())) );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected DISABLE STATEMENT with more "
"than one running machine as parameter !!!"
<< SEND_EXIT;
}
return( aCode );
}
BFCode AvmcodeDisableStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
ExecutableForm * anExecutable = getExecutableMachine(aCTX, aCode->first());
if( anExecutable != NULL )
{
if( anExecutable->hasOnDisable() )
{
// BFCode optiCode = AVMCODE_COMPILER.optimizeStatement(
// aCTX->newCTX(anExecutable), anExecutable->getOnDisable() );
//
//AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
// return( StatementConstructor::newCodeFlatMiddle(
// OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
//
// StatementConstructor::newComment(
// "begin<disable> " + anExecutable->getFullyQualifiedNameID()),
//
// optiCode,
//
// StatementConstructor::newComment(
// "end<disable> " + anExecutable->getFullyQualifiedNameID()) ));
//_AVM_ELSE_
//
// return( optiCode );
//
//AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
}
else if( aCode->first() == ExecutableLib::MACHINE_SELF )
{
return( StatementConstructor::newCode(
OperatorManager::OPERATOR_DISABLE_SELF) );
}
else
{
return( AvmcodeActivityStatementCompiler::optimizeStatement(
aCTX, StatementConstructor::newCode(
OperatorManager::OPERATOR_DISABLE_SET, aCode->first() )));
}
}
else if( aCode->first() == ExecutableLib::MACHINE_SELF )
{
return( StatementConstructor::newCode(
OperatorManager::OPERATOR_DISABLE_SELF) );
}
return( AvmcodeActivityStatementCompiler::optimizeStatement(aCTX, aCode) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE DISABLE#SELVES STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeDisableSelvesStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->singleton() )
{
if( ExpressionTypeChecker::isInteger(aCode->first()) )
{
if( aCode->first().isWeakInteger() &&
(aCode->first().toInteger() < 0) )
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected DISABLE#SELVES STATEMENT with "
"a negative integer as parameter !!!"
<< SEND_EXIT;
return( StatementConstructor::newCode(
aCode->getOperator(),
ExpressionConstructor::newUInteger(
(- aCode->first().toInteger()) ) ) );
}
}
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected DISABLE#SELVES STATEMENT with "
"only an unsigned integer as parameter !!!"
<< SEND_EXIT;
}
return( aCode );
}
BFCode AvmcodeDisableSelvesStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BFCode optCode;
if( aCode->first().isWeakInteger() )
{
ExecutableForm * anExecutable = aCTX->mCompileCtx->getExecutable();
avm_integer_t interLevel = 0;
optCode = StatementConstructor::newCode(
OperatorManager::OPERATOR_ATOMIC_SEQUENCE);
avm_integer_t disableLevel = aCode->first().toInteger();
for( avm_integer_t level = disableLevel ;
(level > 0) && (anExecutable != NULL) ; --level )
{
if( anExecutable->hasOnIDisable() )
{
if( interLevel > 1 )
{
optCode->append( StatementConstructor::newOptiNopCode(
OperatorManager::OPERATOR_DISABLE_SELVES,
ExpressionConstructor::newUInteger(interLevel),
AVM_ARG_BUILTIN_KIND) );
}
else if( interLevel == 1 )
{
optCode->append( StatementConstructor::newCode(
OperatorManager::OPERATOR_DISABLE_SELF) );
}
optCode->appendFlat( anExecutable->getOnIDisable() );
interLevel = 0;
}
else
{
interLevel = interLevel + 1;
}
anExecutable = anExecutable->getExecutableContainer();
}
if( interLevel != disableLevel )
{
if( interLevel > 1 )
{
optCode->append( StatementConstructor::newOptiNopCode(
OperatorManager::OPERATOR_DISABLE_SELVES,
ExpressionConstructor::newUInteger(interLevel),
AVM_ARG_BUILTIN_KIND) );
}
else if( interLevel == 1 )
{
optCode->append( StatementConstructor::newCode(
OperatorManager::OPERATOR_DISABLE_SELF) );
}
return( AvmcodeStrongSequenceCompiler::atomizeSequence(optCode) );
}
else
{
AvmInstruction * argsInstruction = aCode->genInstruction();
argsInstruction->set( 0,
/*operation*/ AVM_ARG_NOP_RVALUE,
/*operand */ AVM_ARG_BUILTIN_KIND,
/*dtype */ TypeManager::INTEGER );
argsInstruction->computeMainBytecode(0);
return( aCode );
}
}
else
{
AvmInstruction * argsInstruction = aCode->genInstruction();
optimizeArgExpression(aCTX, aCode, 0);
argsInstruction->at(0).dtype = TypeManager::INTEGER;
setArgcodeRValue(aCTX, argsInstruction->at(0), aCode->first());
argsInstruction->computeMainBytecode(0);
return( aCode );
}
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE IABORT STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeIAbortStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
else if( aCode->singleton() )
{
return( StatementConstructor::newCode(aCode->getOperator(),
compileArgRvalue(aCTX, TypeManager::MACHINE, aCode->first())) );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected IABORT STATEMENT with more "
"than one running machine as parameter !!!"
<< SEND_EXIT;
}
return( aCode );
}
BFCode AvmcodeIAbortStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
ExecutableForm * anExecutable = getExecutableMachine(aCTX, aCode->first());
if( anExecutable != NULL )
{
if( anExecutable->hasOnIAbort() )
{
// BFCode optiCode = AVMCODE_COMPILER.optimizeStatement(
// aCTX->newCTX(anExecutable), anExecutable->getOnIAbort() );
//
//AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
// return(StatementConstructor::newCodeFlatMiddle(
// OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
//
// StatementConstructor::newComment(
// "begin<iabort> " + anExecutable->getFullyQualifiedNameID()),
//
// optiCode,
//
// StatementConstructor::newComment(
// "end<iabort> " + anExecutable->getFullyQualifiedNameID()) ));
//_AVM_ELSE_
//
// return( optiCode );
//
//AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
}
else
{
return( StatementConstructor::newComment(
"nop<iabort> " + anExecutable->getFullyQualifiedNameID()) );
}
}
return( AvmcodeActivityStatementCompiler::optimizeStatement(aCTX, aCode) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ABORT STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeAbortStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
else if( aCode->singleton() )
{
return( StatementConstructor::newCode(aCode->getOperator(),
compileArgRvalue(aCTX, TypeManager::MACHINE, aCode->first())) );
}
else if( aCode->nonempty() )
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected ABORT STATEMENT with more "
"than one running machine as parameter !!!"
<< SEND_EXIT;
}
return( aCode );
}
BFCode AvmcodeAbortStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
ExecutableForm * anExecutable = getExecutableMachine(aCTX, aCode->first());
if( anExecutable != NULL )
{
if( anExecutable->hasOnAbort() )
{
// BFCode optiCode = AVMCODE_COMPILER.optimizeStatement(
// aCTX->newCTX(anExecutable), anExecutable->getOnAbort() );
//
//AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
// return( StatementConstructor::newCodeFlatMiddle(
// OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
//
// StatementConstructor::newComment(
// "begin<abort> " + anExecutable->getFullyQualifiedNameID() ),
//
// optiCode,
//
// StatementConstructor::newComment(
// "end<abort> " + anExecutable->getFullyQualifiedNameID()) ));
//_AVM_ELSE_
//
// return( optiCode );
//
//AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
}
else if( aCode->first() == ExecutableLib::MACHINE_SELF )
{
return( StatementConstructor::newCode(
OperatorManager::OPERATOR_ABORT_SELF) );
}
else
{
return( AvmcodeActivityStatementCompiler::optimizeStatement(
aCTX, StatementConstructor::newCode(
OperatorManager::OPERATOR_ABORT_SET,
aCode->first() )));
}
}
return( AvmcodeActivityStatementCompiler::optimizeStatement(aCTX, aCode) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ABORT#SELVES STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeAbortSelvesStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->singleton() )
{
if( ExpressionTypeChecker::isInteger(aCode->first()) )
{
if( aCode->first().isWeakInteger() &&
(aCode->first().toInteger() < 0) )
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected ABORT#SELVES STATEMENT with "
"a negative integer as parameter !!!"
<< SEND_EXIT;
return( StatementConstructor::newCode(
aCode->getOperator(),
ExpressionConstructor::newUInteger(
(- aCode->first().toInteger()) ) ) );
}
}
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected ABORT#SELVES STATEMENT with "
"only an unsigned integer as parameter !!!"
<< SEND_EXIT;
}
return( aCode );
}
BFCode AvmcodeAbortSelvesStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->first().isWeakInteger() )
{
ExecutableForm * anExecutable = aCTX->mCompileCtx->getExecutable();
avm_integer_t interLevel = 0;
BFCode optCode = StatementConstructor::newCode(
OperatorManager::OPERATOR_ATOMIC_SEQUENCE);
avm_integer_t abortLevel = aCode->first().toInteger();
for( avm_integer_t level = abortLevel ;
(level > 0) && (anExecutable != NULL) ; --level )
{
if( anExecutable->hasOnIAbort() )
{
if( interLevel > 1 )
{
optCode->append( StatementConstructor::newOptiNopCode(
OperatorManager::OPERATOR_ABORT_SELVES,
ExpressionConstructor::newUInteger(interLevel),
AVM_ARG_BUILTIN_KIND) );
}
else if( interLevel == 1 )
{
optCode->append( StatementConstructor::newCode(
OperatorManager::OPERATOR_ABORT_SELF) );
}
optCode->appendFlat( anExecutable->getOnIDisable() );
interLevel = 0;
}
else
{
interLevel = interLevel + 1;
}
anExecutable = anExecutable->getExecutableContainer();
}
if( interLevel != abortLevel )
{
if( interLevel > 1 )
{
optCode->append( StatementConstructor::newOptiNopCode(
OperatorManager::OPERATOR_ABORT_SELVES,
ExpressionConstructor::newUInteger(interLevel),
AVM_ARG_BUILTIN_KIND) );
}
else if( interLevel == 1 )
{
optCode->append( StatementConstructor::newCode(
OperatorManager::OPERATOR_ABORT_SELF) );
}
return( AvmcodeStrongSequenceCompiler::atomizeSequence(optCode) );
}
else
{
AvmInstruction * argsInstruction = aCode->genInstruction();
argsInstruction->set( 0,
/*operation*/ AVM_ARG_NOP_RVALUE,
/*operand */ AVM_ARG_BUILTIN_KIND,
/*dtype */ TypeManager::INTEGER );
argsInstruction->computeMainBytecode(0);
return( aCode );
}
}
else
{
AvmInstruction * argsInstruction = aCode->genInstruction();
optimizeArgExpression(aCTX, aCode, 0);
argsInstruction->at(0).dtype = TypeManager::INTEGER;
setArgcodeRValue(aCTX, argsInstruction->at(0), aCode->first());
argsInstruction->computeMainBytecode(0);
return( aCode );
}
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE FORK STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeForkStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->size() < 2 )
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected FORK STATEMENT with less "
"than 2 running machines as parameters !!!"
<< SEND_EXIT;
return( aCode );
}
else
{
return( AbstractAvmcodeCompiler::compileStatement(aCTX, aCode) );
}
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE JOIN STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeJoinStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected JOIN STATEMENT without "
"running machines as parameters !!!"
<< SEND_EXIT;
return( aCode );
}
else if( aCode->singleton() )
{
return( StatementConstructor::newCode( aCode->getOperator(),
compileArgRvalue(aCTX, aCode->first()) ) );
}
else
{
return( compileStatementParams(aCTX, aCode) );
}
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE GOTO STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeGotoStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected GOTO STATEMENT without "
"one running machine as target !!!"
<< SEND_EXIT;
return( aCode );
}
else
{
BF gotoTarget = AVMCODE_COMPILER.decode_compileVariableMachine(
aCTX, aCode->first());
AVM_OS_ASSERT_FATAL_ERROR_EXIT( gotoTarget.is< InstanceOfMachine >() )
<< "Unexpected GOTO machine target:>\n" << aCode.str()
<< SEND_EXIT;
BFCode flowStatement;
if( aCode->populated() && gotoTarget.is< InstanceOfMachine >() )
{
flowStatement = AVMCODE_COMPILER.decode_compileStatement(
gotoTarget.to_ptr< InstanceOfMachine >()->getExecutable(),
aCode->second());
AVM_OS_ASSERT_FATAL_ERROR_EXIT( flowStatement.valid() )
<< "Unexpected GOTO flow statement:>\n" << aCode.str()
<< SEND_EXIT;
}
const Machine * source =
aCTX->mCompileCtx->getExecutable()->getAstMachine();
const Machine * target =
gotoTarget.to_ptr< InstanceOfMachine >()->getAstMachine();
const Machine * lcaMachine = source->LCRA(target);
AVM_OS_ASSERT_FATAL_NULL_POINTER_EXIT( lcaMachine )
<< "Unexpected a <null> LCA( "
<< source->getFullyQualifiedNameID() << " , "
<< target->getFullyQualifiedNameID() << " )"
<< SEND_EXIT;
BFCode disableCode( OperatorManager::OPERATOR_DISABLE_INVOKE );
BFCode enableCode ( OperatorManager::OPERATOR_ENABLE_INVOKE );
BFList listOfEnableTarget;
if( (source != lcaMachine)
&& (source->getContainerMachine() != lcaMachine) )
{
avm_uinteger_t disableLevel = 1;
const Machine * containerOfSource = source->getContainerMachine();
for( ; containerOfSource != lcaMachine ; ++disableLevel )
{
containerOfSource = containerOfSource->getContainerMachine();
}
disableCode = StatementConstructor::newOptiNopCode(
OperatorManager::OPERATOR_DISABLE_SELVES,
ExpressionConstructor::newUInteger(disableLevel),
AVM_ARG_BUILTIN_KIND);
}
if( target != lcaMachine )
{
const Machine * containerOfMachine = target;
for( ; containerOfMachine != lcaMachine ;
containerOfMachine = containerOfMachine->getContainerMachine() )
{
listOfEnableTarget.push_front(
getSymbolTable().searchInstanceStatic(containerOfMachine) );
}
enableCode.append( listOfEnableTarget );
if( flowStatement.valid() )
{
enableCode = AvmcodeStrongSequenceCompiler::atomizeSequence(
StatementConstructor::newCodeFlat(
OperatorManager::OPERATOR_SEQUENCE,
enableCode, flowStatement) );
}
}
if( source != lcaMachine ) // for disable self
{
if( enableCode->nonempty() )
{
return( AvmcodeStrongSequenceCompiler::atomizeSequence(
StatementConstructor::newCodeFlat(
OperatorManager::OPERATOR_SEQUENCE,
disableCode, enableCode) ));
}
else
{
return( disableCode );
}
}
else
{
return( enableCode );
}
// return( compileStatementParams(aCTX, aCode) );
}
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE SCHEDULE STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeRtcStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
return( aCode );
}
else
{
return( AvmcodeActivityStatementCompiler::
compileStatement(aCTX, aCode) );
}
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE SCHEDULE#INVOKE STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeScheduleStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
return( aCode );
}
else
{
return( AvmcodeActivityStatementCompiler::
compileStatement(aCTX, aCode) );
}
}
BFCode AvmcodeScheduleStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->empty() )
{
aCode->append( ExecutableLib::MACHINE_SELF );
}
// ExecutableForm * anExecutable = getExecutableMachine(aCTX, aCode->first());
//
// if( (anExecutable != NULL) && anExecutable->hasOnSchedule() &&
// anExecutable->isInlinableSchedule() )
// {
// BFCode optiCode = AVMCODE_COMPILER.optimizeStatement(
// aCTX->newCTX(anExecutable), anExecutable->getOnSchedule() );
//
//AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
// return( StatementConstructor::newCodeFlatMiddle(
// OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
//
// StatementConstructor::newComment(
// "begin<schedule> " + anExecutable->getFullyQualifiedNameID() ),
//
// optiCode,
//
// StatementConstructor::newComment(
// "end<schedule> " + anExecutable->getFullyQualifiedNameID()) ));
//
//AVM_ELSE
//
// return( optiCode );
//
//AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT )
// }
return( AvmcodeActivityStatementCompiler::optimizeStatement(aCTX, aCode) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE SCHEDULE#IN STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BF AvmcodeScheduleInStatementCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
if( aCode->size() == 2 )
{
BF machine = compileArgRvalue(aCTX, TypeManager::MACHINE, aCode->second());
if( machine.is< InstanceOfMachine >() )
{
aCTX = aCTX->newCTX(
machine.to_ptr< InstanceOfMachine >()->getExecutable() );
}
BF submachine = compileArgRvalue(aCTX, TypeManager::MACHINE, aCode->first());
BFCode newCode( aCode->getOperator(), submachine, machine);
return( newCode );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected ENABLE#SET STATEMENT with more "
"than one running machine as parameter !!!"
<< SEND_EXIT;
return( aCode );
}
}
BF AvmcodeScheduleInStatementCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
AvmInstruction * argsInstruction = aCode->genInstruction();
argsInstruction->at(0).dtype = TypeManager::MACHINE;
setArgcodeRValue(aCTX, argsInstruction->at(0), aCode->first());
argsInstruction->at(1).dtype = argsInstruction->at(0).dtype;
setArgcodeRValue(aCTX, argsInstruction->at(1), aCode->second());
argsInstruction->computeMainBytecode(
/*context */ AVM_ARG_RETURN_CTX,
/*processor*/ AVM_ARG_MEMORY_MACHINE_CPU,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_EXPRESSION_KIND,
/*dtype */ TypeManager::MACHINE);
return( aCode );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE INPUT_ENABLED STATEMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BFCode AvmcodeInputEnabledStatementCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BFCode newCode( aCode->getOperator(),
AbstractAvmcodeCompiler::compileStatementCode(aCTX,
aCode->first().bfCode()) );
return( newCode );
}
BFCode AvmcodeInputEnabledStatementCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BFCode optCode( aCode->getOperator() );
optCode->append( AVMCODE_COMPILER.optimizeStatement(aCTX,
aCode->first().bfCode() ));
return( optCode );
}
}