blob: 28a26be58a519a476a2f0c453245dca7a4b4760b [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: 7 avr. 2011
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "AbstractAvmcodeCompiler.h"
#include <builder/primitive/AvmcodeCompiler.h>
#include <computer/instruction/AvmInstruction.h>
#include <fml/builtin/QualifiedIdentifier.h>
#include <fml/executable/BaseAvmProgram.h>
#include <fml/executable/ExecutableLib.h>
#include <fml/executable/InstanceOfBuffer.h>
#include <fml/executable/InstanceOfConnect.h>
#include <fml/executable/InstanceOfData.h>
#include <fml/executable/InstanceOfMachine.h>
#include <fml/executable/InstanceOfPort.h>
#include <fml/builtin/Boolean.h>
#include <fml/builtin/Character.h>
#include <fml/numeric/Float.h>
#include <fml/numeric/Integer.h>
#include <fml/numeric/Rational.h>
#include <fml/expression/AvmCode.h>
#include <fml/expression/BuiltinArray.h>
#include <fml/expression/ExpressionTypeChecker.h>
#include <fml/expression/StatementTypeChecker.h>
#include <fml/lib/AvmOperationFactory.h>
#include <fml/lib/ITypeSpecifier.h>
#include <fml/type/ContainerTypeSpecifier.h>
#include <fml/infrastructure/Buffer.h>
#include <fml/infrastructure/Connector.h>
#include <fml/infrastructure/Machine.h>
#include <fml/infrastructure/Port.h>
#include <fml/infrastructure/Routine.h>
#include <fml/infrastructure/Transition.h>
#include <fml/infrastructure/Variable.h>
#include <fml/workflow/UniFormIdentifier.h>
namespace sep
{
////////////////////////////////////////////////////////////////////////////////
// SPECIFIC ARGUMENT COMPILATION
////////////////////////////////////////////////////////////////////////////////
BF AbstractAvmcodeCompiler::compileArgLvalue(
COMPILE_CONTEXT * aCTX, const BF & arg)
{
BF compileArg;
switch( arg.classKind() )
{
case FORM_XFSP_VARIABLE_KIND:
{
compileArg = AVMCODE_COMPILER.compileVariable(aCTX, arg);
break;
}
case FORM_BUILTIN_QUALIFIED_IDENTIFIER_KIND:
{
if( arg.to_ptr< QualifiedIdentifier >()->isPositionalParameter() )
{
compileArg = AVMCODE_COMPILER.
compileQualifiedPositionalIdentifier(aCTX, arg);
}
else if( arg.str().find(':') != std::string::npos )
{
compileArg = AVMCODE_COMPILER.
compileFullyQualifiedNameID(aCTX, arg);
}
else
{
compileArg = AVMCODE_COMPILER.
compileQualifiedIdentifier(aCTX, arg);
}
break;
}
case FORM_BUILTIN_IDENTIFIER_KIND:
{
compileArg = AVMCODE_COMPILER.compileIdentifier(aCTX, arg);
break;
}
case FORM_XFSP_BUFFER_KIND:
case FORM_XFSP_CHANNEL_KIND:
case FORM_XFSP_CONNECTOR_KIND:
case FORM_XFSP_MACHINE_KIND:
case FORM_XFSP_PORT_KIND:
case FORM_XFSP_ROUTINE_KIND:
case FORM_XFSP_SYSTEM_KIND:
case FORM_XFSP_TRANSITION_KIND:
case FORM_XFSP_DATATYPE_KIND:
{
compileArg = AVMCODE_COMPILER.compileElement(aCTX, arg);
break;
}
case FORM_UFI_KIND:
{
compileArg = AVMCODE_COMPILER.compileUFI(
aCTX, arg.to_ref< UniFormIdentifier>());
break;
}
case FORM_AVMCODE_KIND:
{
compileArg = AVMCODE_COMPILER.compileExpression(aCTX, arg.bfCode());
break;
}
case FORM_INSTANCE_DATA_KIND:
{
compileArg = arg;
break;
}
default:
{
compileArg = AVMCODE_COMPILER.decode_compileExpression(aCTX, arg);
break;
}
}
if( compileArg.valid() )
{
if( compileArg.is< InstanceOfData >() )
{
InstanceOfData * iodArg = compileArg.to_ptr< InstanceOfData >();
if( iodArg->getModifier().hasFeatureMutable() )
{
if( iodArg->isAlias() )
{
if( not iodArg->getModifier().
isVisibilityPublic( aCTX->getModifier() ) )
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "compileArgLvalue:> compilation error : "
"Illegal access of non \"public\" LVALUE << "
<< str_header( iodArg ) << " >> for << "
<< arg.str() << " >>" << std::endl << std::endl;
}
if( not iodArg->getModifier().
hasFeatureVolatile( aCTX->getModifier() ) )
{
if( iodArg->getAstElement()->isnot< ObjectElement >() )
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "compileArgLvalue:> compilation error : "
"Illegal access of non \"volatile\" LVALUE << "
<< str_header( iodArg ) << " >> for << "
<< arg.str() << " >>" << std::endl << std::endl;
}
}
}
return( compileArg );
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "compileArgLvalue:> compilation error : "
"Illegal access of a \"const\" LVALUE << "
<< str_header( iodArg ) << " >> for << "
<< arg.str() << " >>" << std::endl << std::endl;
return( arg );
}
}
else if( compileArg.is< AvmCode >() )
{
return( compileArg );
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "compileArgLvalue:> compilation error : "
"Unexpected << " << compileArg.str()
<< " >> as LVALUE for << " << arg.str() << " >>"
<< std::endl << std::endl;
return( arg );
}
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "compileArgLvalue:> compilation error << "
<< arg.str() << " >>" << std::endl << std::endl;
return( arg );
}
}
BF AbstractAvmcodeCompiler::compileArgRvalue(
COMPILE_CONTEXT * aCTX, const BF & arg, bool needTypeChecking)
{
BF compileArg = AVMCODE_COMPILER.decode_compileExpression(aCTX, arg);
if( compileArg.valid() )
{
if( compileArg.is< InstanceOfData >() )
{
InstanceOfData * iodArg = compileArg.to_ptr< InstanceOfData >();
if( iodArg->getModifier().hasFeatureMutable() )
{
if( iodArg->isAlias() )
{
if( not iodArg->getModifier().
isVisibilityPublic( aCTX->getModifier() ) )
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "compileArgLvalue:> compilation error : "
"Illegal access of non \"public\" RVALUE << "
<< str_header( iodArg ) << " >> for << "
<< arg.str() << " >>" << std::endl << std::endl;
}
}
}
}
}
if( compileArg.valid() )
{
if( aCTX->isNeedTypeChecking(needTypeChecking) )
{
checkArgType(aCTX, aCTX->mType, compileArg);
}
return( compileArg );
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "compileArgRvalue:> compilation error << "
<< arg.str() << " >>" << std::endl << std::endl;
return( arg );
}
}
////////////////////////////////////////////////////////////////////////////////
// COMPILATION OF EXPRESSION
////////////////////////////////////////////////////////////////////////////////
BFCode AbstractAvmcodeCompiler::compileExpressionCode(
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();
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 AbstractAvmcodeCompiler::optimizeExpressionCode(
COMPILE_CONTEXT * aCTX, const BFCode & aCode,
avm_arg_operand_t anOperand)
{
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 );
vectorOfArgOpcode.append( argcodeOfExpression(aCTX, pCode) );
}
}
else
{
newCode->append( arg );
AvmBytecode argOpcode;
setArgcodeRValue(aCTX, argOpcode, arg, false);
vectorOfArgOpcode.append( argOpcode );
}
}
argsInstruction->setMainBytecode(
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ anOperand );
argsInstruction->computeBytecode( false , vectorOfArgOpcode );
return( newCode );
}
////////////////////////////////////////////////////////////////////////////////
// COMPILATION OF STATEMENT
////////////////////////////////////////////////////////////////////////////////
BFCode AbstractAvmcodeCompiler::compileStatementCode(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
Operator * mainOperator = aCode->getOperator();
BFCode newCode( mainOperator );
BF arg;
AvmCode::iterator itArg = aCode->begin();
AvmCode::iterator itEndArg = aCode->end();
for( ; itArg != itEndArg ; ++itArg )
{
arg = AVMCODE_COMPILER.decode_compileStatement(aCTX, *itArg);
if( arg.invalid() )
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "AvmCode< statement > compilation error << "
<< (*itArg).str() << " >>" << std::endl << std::endl;
newCode->append( *itArg );
continue;
}
switch( arg.classKind() )
{
case FORM_AVMCODE_KIND:
{
if( arg.to_ptr< AvmCode >()->isOpCode( mainOperator )
&& mainOperator->isAssociative() )
{
newCode->append( arg.to_ptr< AvmCode >()->getArgs() );
}
else
{
newCode->append( arg );
}
break;
}
default:
{
newCode->append( arg );
break;
}
}
}
return( newCode );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE COMPILATION STEP
////////////////////////////////////////////////////////////////////////////////
BFCode AbstractAvmcodeCompiler::compileAvmcode(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
Operator * mainOperator = aCode->getOperator();
BFCode newCode( mainOperator );
BF arg;
AvmCode::iterator itArg = aCode->begin();
AvmCode::iterator itEndArg = aCode->end();
for( ; itArg != itEndArg ; ++itArg )
{
switch( (*itArg).classKind() )
{
case FORM_AVMCODE_KIND:
{
arg = compileAvmcode(aCTX, (*itArg).bfCode());
break;
}
default:
{
arg = AVMCODE_COMPILER.decode_compileExpression(aCTX, *itArg);
break;
}
}
if( arg.invalid() )
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "AvmCode< statement > compilation error << "
<< (*itArg).str() << " >>" << std::endl << std::endl;
newCode->append( *itArg );
continue;
}
switch( arg.classKind() )
{
case FORM_AVMCODE_KIND:
{
if( arg.to_ptr< AvmCode >()->isOperator( mainOperator )
&& mainOperator->isAssociative() )
{
newCode->append( arg.to_ptr< AvmCode >()->getArgs() );
}
else
{
newCode->append( arg );
}
break;
}
default:
{
newCode->append( arg );
break;
}
}
}
return( newCode );
}
////////////////////////////////////////////////////////////////////////////////
// AVM OPCODE COMPILATION
////////////////////////////////////////////////////////////////////////////////
/**
* operand
*/
bool AbstractAvmcodeCompiler::mustBeEvaluatedArgument(const BF & arg)
{
switch( arg.classKind() )
{
case FORM_BUILTIN_BOOLEAN_KIND:
case FORM_BUILTIN_INTEGER_KIND:
case FORM_BUILTIN_RATIONAL_KIND:
case FORM_BUILTIN_FLOAT_KIND:
case FORM_BUILTIN_CHARACTER_KIND:
case FORM_BUILTIN_STRING_KIND:
{
return( false );
}
case FORM_BUILTIN_IDENTIFIER_KIND:
case FORM_BUILTIN_QUALIFIED_IDENTIFIER_KIND:
{
return( true );
}
case FORM_AVMCODE_KIND:
{
return( true );
}
case FORM_ARRAY_BOOLEAN_KIND:
case FORM_ARRAY_CHARACTER_KIND:
case FORM_ARRAY_INTEGER_KIND:
case FORM_ARRAY_RATIONAL_KIND:
case FORM_ARRAY_FLOAT_KIND:
case FORM_ARRAY_STRING_KIND:
case FORM_ARRAY_IDENTIFIER_KIND:
case FORM_ARRAY_QUALIFIED_IDENTIFIER_KIND:
{
return( false );
}
case FORM_ARRAY_BF_KIND:
{
return( mustBeEvaluatedArgumentArray( arg.to_ptr< ArrayBF >() ) );
}
case FORM_INSTANCE_DATA_KIND:
{
return( true );
}
case FORM_RUNTIME_ID_KIND:
case FORM_INSTANCE_PORT_KIND:
case FORM_INSTANCE_BUFFER_KIND:
case FORM_INSTANCE_CONNECTOR_KIND:
{
return( false );
}
case FORM_OPERATOR_KIND:
case FORM_AVMLAMBDA_KIND:
case FORM_AVMPROGRAM_KIND:
case FORM_AVMTRANSITION_KIND:
case FORM_EXECUTABLE_MACHINE_KIND:
case FORM_EXECUTABLE_SYSTEM_KIND:
{
return( false );
}
default:
{
return( true );
}
}
}
bool AbstractAvmcodeCompiler::mustBeEvaluatedArgumentArray(ArrayBF * arrayArg)
{
for( avm_size_t idx = 0 ; idx < arrayArg->size() ; ++idx )
{
if( mustBeEvaluatedArgument(arrayArg->at(idx)) )
{
return( true );
}
}
return( false );
}
avm_arg_operand_t AbstractAvmcodeCompiler::operandOf(const BF & arg)
{
switch( arg.classKind() )
{
case FORM_BUILTIN_BOOLEAN_KIND:
{
return( AVM_ARG_BOOLEAN_KIND );
}
case FORM_BUILTIN_INTEGER_KIND:
{
return( AVM_ARG_INTEGER_KIND );
}
case FORM_BUILTIN_RATIONAL_KIND:
{
return( AVM_ARG_RATIONAL_KIND );
}
case FORM_BUILTIN_FLOAT_KIND:
{
return( AVM_ARG_FLOAT_KIND );
}
case FORM_BUILTIN_CHARACTER_KIND:
{
return( AVM_ARG_CHARACTER_KIND );
}
case FORM_BUILTIN_STRING_KIND:
{
return( AVM_ARG_STRING_KIND );
}
case FORM_BUILTIN_IDENTIFIER_KIND:
case FORM_BUILTIN_QUALIFIED_IDENTIFIER_KIND:
{
return( AVM_ARG_BUILTIN_KIND );
}
case FORM_OPERATOR_KIND:
{
return( AVM_ARG_OPERATOR_KIND );
}
case FORM_AVMCODE_KIND:
{
return( AVM_ARG_EXPRESSION_KIND );
}
case FORM_ARRAY_BOOLEAN_KIND:
case FORM_ARRAY_CHARACTER_KIND:
case FORM_ARRAY_INTEGER_KIND:
case FORM_ARRAY_RATIONAL_KIND:
case FORM_ARRAY_FLOAT_KIND:
case FORM_ARRAY_STRING_KIND:
case FORM_ARRAY_IDENTIFIER_KIND:
case FORM_ARRAY_QUALIFIED_IDENTIFIER_KIND:
{
return( AVM_ARG_BUILTIN_ARRAY_KIND );
}
case FORM_ARRAY_BF_KIND:
{
ArrayBF * arrayArg = arg.to_ptr< ArrayBF >();
for( avm_size_t idx = 0 ; idx < arrayArg->size() ; ++idx )
{
if( mustBeEvaluatedArgument(arrayArg->at(idx)) )
{
return( AVM_ARG_EXPRESSION_KIND );
}
}
return( AVM_ARG_BUILTIN_ARRAY_KIND );
}
case FORM_INSTANCE_DATA_KIND:
{
InstanceOfData * anInstance = arg.to_ptr< InstanceOfData >();
if( anInstance->isUfiMixedPointer() )
{
return( AVM_ARG_DATA_UFI_KIND );
}
else if( anInstance->getModifier().hasNatureReference() )
{
return( anInstance->isUfiOffsetPointer() ?
AVM_ARG_DATA_UFI_KIND : AVM_ARG_DATA_REF_KIND );
}
else if( anInstance->getModifier().hasNatureMacro() )
{
return( AVM_ARG_DATA_MACRO_KIND );
}
else if( anInstance->getModifier().hasFeatureMutable() )
{
return( AVM_ARG_DATA_KIND );
}
else if( anInstance->getModifier().hasModifierPublicFinalStatic() )
{
if( ExecutableLib::MACHINE_COMPONENT_SELF == anInstance )
{
return( AVM_ARG_COMPONENT_SELF_RID );
}
else if( ExecutableLib::MACHINE_COMPONENT_PARENT == anInstance )
{
return( AVM_ARG_COMPONENT_PARENT_RID );
}
else if( ExecutableLib::MACHINE_COMPONENT_COMMUNICATOR
== anInstance )
{
return( AVM_ARG_COMPONENT_COMMUNICATOR_RID );
}
else if( ExecutableLib::MACHINE_ENVIRONMENT == anInstance )
{
return( AVM_ARG_ENVIRONMENT_RID );
}
else if( ExecutableLib::MACHINE_SYSTEM == anInstance )
{
return( AVM_ARG_SYSTEM_RID );
}
else if( ExecutableLib::MACHINE_SELF == anInstance )
{
return( AVM_ARG_SELF_RID );
}
else if( ExecutableLib::MACHINE_PARENT == anInstance )
{
return( AVM_ARG_PARENT_RID );
}
else if( ExecutableLib::MACHINE_COMMUNICATOR == anInstance )
{
return( AVM_ARG_COMMUNICATOR_RID );
}
else
{
return( AVM_ARG_DATA_CST_KIND );
}
}
else if( anInstance->getModifier().hasFeatureFinal() )
{
return( AVM_ARG_DATA_CST_KIND );
}
else
{
return( AVM_ARG_DATA_KIND );
}
}
case FORM_RUNTIME_ID_KIND:
{
return( AVM_ARG_MACHINE_RID );
}
case FORM_INSTANCE_PORT_KIND:
{
return( AVM_ARG_PORT_KIND );
}
case FORM_INSTANCE_BUFFER_KIND:
{
return( AVM_ARG_BUFFER_KIND );
}
case FORM_INSTANCE_CONNECTOR_KIND:
{
return( AVM_ARG_CONNECTOR_KIND );
}
case FORM_AVMLAMBDA_KIND:
case FORM_AVMPROGRAM_KIND:
case FORM_AVMTRANSITION_KIND:
case FORM_EXECUTABLE_MACHINE_KIND:
case FORM_EXECUTABLE_SYSTEM_KIND:
{
return( AVM_ARG_STATEMENT_KIND );
}
default:
{
return( AVM_ARG_UNDEFINED_OPERAND );
}
}
}
avm_arg_processor_t AbstractAvmcodeCompiler::processorOf(
BaseTypeSpecifier * aType)
{
switch( aType->getTypeSpecifierKind() )
{
case TYPE_BOOLEAN_SPECIFIER:
case TYPE_INTEGER_SPECIFIER:
case TYPE_RATIONAL_SPECIFIER:
case TYPE_FLOAT_SPECIFIER:
{
return( AVM_ARG_ARITHMETIC_LOGIC_CPU );
}
case TYPE_CHARACTER_SPECIFIER:
{
return( AVM_ARG_CHARACTER_CPU );
}
case TYPE_STRING_SPECIFIER:
{
return( AVM_ARG_STRING_CPU );
}
case TYPE_ARRAY_SPECIFIER:
{
return( AVM_ARG_ARRAY_RVALUE_CPU );
// return( AVM_ARG_ARRAY_LVALUE_CPU );
}
case TYPE_VECTOR_SPECIFIER:
case TYPE_REVERSE_VECTOR_SPECIFIER:
{
return( AVM_ARG_VECTOR_CPU );
}
case TYPE_LIST_SPECIFIER:
{
return( AVM_ARG_LIST_CPU );
}
case TYPE_FIFO_SPECIFIER:
case TYPE_LIFO_SPECIFIER:
case TYPE_MULTI_FIFO_SPECIFIER:
case TYPE_MULTI_LIFO_SPECIFIER:
case TYPE_RAM_SPECIFIER:
{
return( AVM_ARG_QUEUE_CPU );
}
case TYPE_SET_SPECIFIER:
case TYPE_MULTISET_SPECIFIER:
{
return( AVM_ARG_COLLECTION_CPU );
}
default:
{
return( AVM_ARG_UNDEFINED_PROCESSOR );
}
}
}
avm_arg_operand_t AbstractAvmcodeCompiler::operandOf(BaseTypeSpecifier * aType)
{
switch( aType->getTypeSpecifierKind() )
{
case TYPE_BOOLEAN_SPECIFIER:
{
return( AVM_ARG_BOOLEAN_KIND );
}
case TYPE_INTEGER_SPECIFIER:
{
return( AVM_ARG_INTEGER_KIND );
}
case TYPE_RATIONAL_SPECIFIER:
{
return( AVM_ARG_RATIONAL_KIND );
}
case TYPE_FLOAT_SPECIFIER:
{
return( AVM_ARG_FLOAT_KIND );
}
case TYPE_CHARACTER_SPECIFIER:
{
return( AVM_ARG_CHARACTER_KIND );
}
case TYPE_STRING_SPECIFIER:
{
return( AVM_ARG_STRING_KIND );
}
case TYPE_OPERATOR_SPECIFIER:
{
return( AVM_ARG_OPERATOR_KIND );
}
case TYPE_AVMCODE_SPECIFIER:
{
return( AVM_ARG_EXPRESSION_KIND );
}
case TYPE_ARRAY_SPECIFIER:
{
return( AVM_ARG_ARRAY_KIND );
}
default:
{
if( aType->hasTypeCollection() )
{
return( AVM_ARG_COLLECTION_KIND );
}
else
{
return( AVM_ARG_UNDEFINED_OPERAND );
}
}
}
}
void AbstractAvmcodeCompiler::setArgcodeLValue(COMPILE_CONTEXT * aCTX,
AvmBytecode & argCode, const BF & arg, bool needTypeChecking)
{
argCode.processor = AVM_ARG_MEMORY_LVALUE_CPU;
argCode.operation = AVM_ARG_SEVAL_LVALUE;
if( arg.is< InstanceOfData >() )
{
InstanceOfData * anInstance = arg.to_ptr< InstanceOfData >();
if( aCTX->isNeedTypeChecking(needTypeChecking) )
{
if( argCode.hasType() )
{
checkArgType(aCTX, argCode.dtype, arg);
}
else if( aCTX->hasType() )
{
argCode.dtype = aCTX->mType;
checkArgType(aCTX, argCode.dtype, arg);
}
else
{
argCode.dtype = anInstance->getTypeSpecifier();
}
}
else if( not argCode.hasType() )
{
argCode.dtype = anInstance->getTypeSpecifier();
}
if( anInstance->isUfiMixedPointer() )
{
argCode.operand = AVM_ARG_DATA_UFI_KIND;
}
else if( anInstance->getModifier().hasNatureReference() )
{
argCode.operand = (anInstance->isUfiOffsetPointer() ?
AVM_ARG_DATA_UFI_KIND : AVM_ARG_DATA_REF_KIND);
}
else if( anInstance->getModifier().hasNatureMacro() )
{
argCode.operand = AVM_ARG_DATA_MACRO_KIND;
}
else if( anInstance->getModifier().hasFeatureMutable() )
{
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_LVALUE;
argCode.operand = AVM_ARG_DATA_KIND;
}
else
{
getCompilerTable().incrWarningCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeLvalue :> Unexpected the InstanceOfData << "
<< str_header( arg ) << " >> as << " << argCode.strType()
<< " >> argument !!!" << std::endl;
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_LVALUE;
argCode.operand = AVM_ARG_DATA_KIND;
}
}
else if( arg.is< AvmCode >() )
{
argCode.operand = AVM_ARG_EXPRESSION_KIND;
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeLvalue :> Unexpected << "
<< str_header( arg ) << " >> as lvalue argument typed by "
<< argCode.strType() << " >> !!!" << std::endl;
argCode.operand = AVM_ARG_EXPRESSION_KIND;
}
}
void AbstractAvmcodeCompiler::setArgcodeLValueRef(COMPILE_CONTEXT * aCTX,
AvmBytecode & argCode, const BF & arg, bool needTypeChecking)
{
if( arg.is< InstanceOfData >()
&& arg.to_ptr< InstanceOfData >()->getModifier().hasNatureReference() )
{
if( aCTX->isNeedTypeChecking(needTypeChecking) )
{
if( argCode.hasType() )
{
checkArgType(aCTX, argCode.dtype, arg);
}
else if( aCTX->hasType() )
{
argCode.dtype = aCTX->mType;
checkArgType(aCTX, argCode.dtype, arg);
}
else
{
argCode.dtype = arg.to_ptr<
InstanceOfData >()->getTypeSpecifier();
}
}
else if( not argCode.hasType() )
{
argCode.dtype = arg.to_ptr<
InstanceOfData >()->getTypeSpecifier();
}
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_LVALUE;
argCode.operand = AVM_ARG_DATA_REF_KIND;
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeLvalue :> Unexpected << "
<< str_header( arg ) << " >> as << " << argCode.strType()
<< " >> reference InstanceOfData argument !!!" << std::endl;
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_LVALUE;
argCode.operand = AVM_ARG_EXPRESSION_KIND;
}
}
void AbstractAvmcodeCompiler::setArgcodeLValueMacro(COMPILE_CONTEXT * aCTX,
AvmBytecode & argCode, const BF & arg, bool needTypeChecking)
{
if( arg.is< InstanceOfData >()
&& arg.to_ptr< InstanceOfData >()->getModifier().hasNatureMacro() )
{
if( aCTX->isNeedTypeChecking(needTypeChecking) )
{
if( argCode.hasType() )
{
checkArgType(aCTX, argCode.dtype, arg);
}
else if( aCTX->hasType() )
{
argCode.dtype = aCTX->mType;
checkArgType(aCTX, argCode.dtype, arg);
}
else
{
argCode.dtype = arg.to_ptr<
InstanceOfData >()->getTypeSpecifier();
}
}
else if( not argCode.hasType() )
{
argCode.dtype = arg.to_ptr<
InstanceOfData >()->getTypeSpecifier();
}
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_LVALUE;
argCode.operand = AVM_ARG_DATA_MACRO_KIND;
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeLvalue :> Unexpected << "
<< str_header( arg ) << " >> as << " << argCode.strType()
<< " >> macro InstanceOfData argument !!!" << std::endl;
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_LVALUE;
argCode.operand = AVM_ARG_EXPRESSION_KIND;
}
}
void AbstractAvmcodeCompiler::setArgcodeRValue(COMPILE_CONTEXT * aCTX,
AvmBytecode & argCode, BF & arg, bool needTypeChecking)
{
if( argCode.dtype->isTypedArray() )
{
setArgcodeRValueArray(aCTX, argCode, arg, needTypeChecking);
return;
}
if( aCTX->isNeedTypeChecking(needTypeChecking) )
{
checkArgType(aCTX, argCode.dtype, arg);
}
if( arg.is< ArrayBF >() )
{
setArgcodeRValueArray(aCTX, argCode,
arg.to_ptr< ArrayBF >(), needTypeChecking);
}
else if( arg.isBuiltinValue() )
{
// argCode.processor = AVM_ARG_ARITHMETIC_LOGIC_CPU;
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
if( arg.is< Boolean >() )
{
argCode.operand = AVM_ARG_BOOLEAN_KIND;
}
else if( arg.is< Integer >() )
{
argCode.operand = AVM_ARG_INTEGER_KIND;
}
else if( arg.is< Rational >() )
{
argCode.operand = AVM_ARG_RATIONAL_KIND;
}
else if( arg.is< Float >() )
{
argCode.operand = AVM_ARG_FLOAT_KIND;
}
else if( arg.is< Character >() )
{
// argCode.processor = AVM_ARG_CHARACTER_CPU;
argCode.operand = AVM_ARG_CHARACTER_KIND;
}
else if( arg.is< String >() )
{
// argCode.processor = AVM_ARG_STRING_CPU;
argCode.operand = AVM_ARG_STRING_KIND;
}
else
{
argCode.operand = AVM_ARG_BUILTIN_KIND;
}
}
else if( arg.is< InstanceOfData >() )
{
InstanceOfData * anInstance = arg.to_ptr< InstanceOfData >();
argCode.processor = anInstance->isTypedMachine() ?
AVM_ARG_MEMORY_MACHINE_CPU : AVM_ARG_MEMORY_RVALUE_CPU;
argCode.operation = AVM_ARG_SEVAL_RVALUE;
if( anInstance->isUfiMixedPointer() )
{
argCode.operand = AVM_ARG_DATA_UFI_KIND;
}
else if( anInstance->getModifier().hasNatureReference() )
{
argCode.operand = (anInstance->isUfiOffsetPointer() ?
AVM_ARG_DATA_UFI_KIND : AVM_ARG_DATA_REF_KIND);
}
else if( anInstance->getModifier().hasNatureMacro() )
{
argCode.operand = AVM_ARG_DATA_MACRO_KIND;
}
else if( anInstance->getModifier().hasFeatureMutable() )
{
argCode.operand = AVM_ARG_DATA_KIND;
}
else if( anInstance->getModifier().hasModifierPublicFinalStatic() )
{
if( anInstance->isTypedEnum() && anInstance->hasValue() )
{
arg = anInstance->getValue();
setArgcodeRValue(aCTX, argCode, arg, false);
}
else
{
argCode.processor = AVM_ARG_MEMORY_MACHINE_CPU;
if( ExecutableLib::MACHINE_COMPONENT_SELF == anInstance )
{
argCode.operand = AVM_ARG_COMPONENT_SELF_RID;
}
else if( ExecutableLib::MACHINE_COMPONENT_PARENT == anInstance )
{
argCode.operand = AVM_ARG_COMPONENT_PARENT_RID;
}
else if( ExecutableLib::MACHINE_COMPONENT_COMMUNICATOR == anInstance )
{
argCode.operand = AVM_ARG_COMPONENT_COMMUNICATOR_RID;
}
else if( ExecutableLib::MACHINE_ENVIRONMENT == anInstance )
{
argCode.operand = AVM_ARG_ENVIRONMENT_RID;
}
else if( ExecutableLib::MACHINE_SYSTEM == anInstance )
{
argCode.operand = AVM_ARG_SYSTEM_RID;
}
else if( ExecutableLib::MACHINE_SELF == anInstance )
{
argCode.operand = AVM_ARG_SELF_RID;
}
else if( ExecutableLib::MACHINE_PARENT == anInstance )
{
argCode.operand = AVM_ARG_PARENT_RID;
}
else if( ExecutableLib::MACHINE_COMMUNICATOR == anInstance )
{
argCode.operand = AVM_ARG_COMMUNICATOR_RID;
}
else
{
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_DATA_CST_KIND;
}
}
}
else if( anInstance->getModifier().hasFeatureFinal() )
{
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_DATA_CST_KIND;
}
else
{
getCompilerTable().incrWarningCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeRvalue :> Unexpected the InstanceOfData << "
<< str_header( anInstance ) << " >> as << "
<< argCode.strType() << " >> argument !!!" << std::endl;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_DATA_KIND;
}
if( argCode.dtype == TypeManager::UNIVERSAL )
{
argCode.dtype = anInstance->getTypeSpecifier();
}
}
else if( arg.is< RuntimeID >() )
{
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_MACHINE_RID;
}
else if( arg.is< InstanceOfMachine >() )
{
argCode.processor = AVM_ARG_MEMORY_MACHINE_CPU;
if( (not argCode.hasType()) || argCode.dtype->isTypedMachine() )
{
argCode.operation = AVM_ARG_SEVAL_RVALUE;
argCode.operand = AVM_ARG_MACHINE_RID;
}
else
{
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_DATA_KIND;
}
}
else if( arg.is< InstanceOfPort >() )
{
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_PORT_KIND;
}
else if( arg.is< InstanceOfBuffer >() )
{
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_BUFFER_KIND;
}
else if( arg.is< InstanceOfConnect >() )
{
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_CONNECTOR_KIND;
}
else if( arg.is< BaseInstanceForm >() )
{
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_DATA_KIND;
}
else if( arg.is< AvmCode >() )
{
if( not arg.to_ptr< AvmCode >()->hasInstruction() )
{
arg = AVMCODE_COMPILER.optimizeExpression(aCTX, arg.bfCode());
}
argCode = argcodeOfExpression(aCTX, arg.to_ptr< AvmCode >());
}
else if( arg.is< Operator >()
&& ( (not argCode.hasType())
|| argCode.dtype->isTypedOperator() ) )
{
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_OPERATOR_KIND;
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeRvalue :> Unexpected << "
<< str_header( arg ) << " >> as << " << argCode.strType()
<< " >> argument !!!" << std::endl;
argCode.processor = AVM_ARG_ARITHMETIC_LOGIC_CPU;
argCode.operation = AVM_ARG_SEVAL_RVALUE;
argCode.operand = AVM_ARG_EXPRESSION_KIND;
}
}
AvmBytecode AbstractAvmcodeCompiler::argcodeOfExpression(
COMPILE_CONTEXT * aCTX, AvmCode * aCode)
{
AVM_OS_ASSERT_FATAL_ERROR_EXIT( aCode->hasInstruction() )
<< "setArgcodeRvalue :> Unexpected << " << aCode->str()
<< " >> without compileInstruction !!!"
<< SEND_EXIT;
AvmBytecode argCode = aCode->getInstruction()->getMainBytecode();
if(StatementTypeChecker::isAssign(aCode) )
{
argCode.processor = AVM_ARG_MEMORY_RVALUE_CPU;
if( argCode.isNopOperation() )
{
argCode.operation = AVM_ARG_SEVAL_RVALUE;
}
}
else if(StatementTypeChecker::isCommunication(aCode) )
{
argCode.processor = AVM_ARG_STATEMENT_CPU;
argCode.operation = AVM_ARG_SEVAL_RVALUE;
argCode.operand = AVM_ARG_STATEMENT_KIND;
}
else if(ExpressionTypeChecker::isCtor(aCode) )
{
argCode.operand = AVM_ARG_EXPRESSION_KIND;
}
return( argCode );
}
void AbstractAvmcodeCompiler::setArgcodeRValueArray(COMPILE_CONTEXT * aCTX,
AvmBytecode & argCode, BF & arg, bool needTypeChecking)
{
ContainerTypeSpecifier * arrayT =
argCode.dtype->as< ContainerTypeSpecifier >();
if( arg.is< ArrayBF >() )
{
if( aCTX->isNeedTypeChecking(needTypeChecking) )
{
checkArgType(aCTX, argCode.dtype, arg);
}
ArrayBF * argArray = arg.to_ptr< ArrayBF >();
if( argArray->size() < arrayT->size() )
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeRValueArray :> Too few element in array :>\n<< "
<< arg.str() << " >>\nas type << " << arrayT->strT()
<< " >> argument !!!" << std::endl;
}
else if( argArray->size() > arrayT->size() )
{
getCompilerTable().incrWarningCount();
aCTX->warningContext( AVM_OS_WARN )
<< "setArgcodeRValueArray :> Too much element in array\n<< "
<< arg.str() << " >>\nas type << " << arrayT->strType()
<< " >> argument !!!" << std::endl;
ArrayBF * reducedArgArray = new ArrayBF(arrayT, arrayT->size());
for( avm_size_t idx = 0 ; idx < arrayT->size() ; ++idx )
{
reducedArgArray->set(idx, argArray->at(idx));
}
arg.renew( reducedArgArray );
setArgcodeRValueArray(aCTX, argCode,
reducedArgArray, needTypeChecking);
}
else
{
setArgcodeRValueArray(aCTX, argCode,
arg.to_ptr< ArrayBF >(), needTypeChecking);
}
}
else if( arg.is< InstanceOfData >()
&& ExpressionTypeChecker::weaklyTyped( arrayT,
arg.to_ptr< InstanceOfData >()->getTypeSpecifier() ) )
{
argCode.processor = AVM_ARG_MEMORY_RVALUE_CPU;
argCode.operation = AVM_ARG_SEVAL_RVALUE;
argCode.operand = AVM_ARG_DATA_KIND;
}
else if( ExpressionTypeChecker::isTyped(arrayT, arg) )
{
argCode.processor = AVM_ARG_ARITHMETIC_LOGIC_CPU;
argCode.operation = AVM_ARG_SEVAL_RVALUE;
argCode.operand = AVM_ARG_EXPRESSION_KIND;
}
else
{
while( arrayT->getContentsTypeSpecifier().isTypedArray() )
{
arrayT = arrayT->getContentsTypeSpecifier().rawContainer();
}
if( aCTX->isNeedTypeChecking(needTypeChecking) )
{
checkArgType(aCTX, arrayT->getContentsTypeSpecifier(), arg);
}
argCode.processor = AVM_ARG_ARRAY_RVALUE_CPU;
argCode.operation = AVM_ARG_SEVAL_RVALUE;
argCode.operand = operandOf(arg);
}
}
void AbstractAvmcodeCompiler::setArgcodeRValueArray(COMPILE_CONTEXT * aCTX,
AvmBytecode & argCode, ArrayBF * argArray, bool needTypeChecking)
{
avm_size_t argArraySize = argArray->size();
argCode.processor = AVM_ARG_ARRAY_RVALUE_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_BUILTIN_ARRAY_KIND;
for( avm_size_t idx = 0 ; idx < argArraySize ; ++idx )
{
if( mustBeEvaluatedArgument(argArray->at(idx)) )
{
argCode.operation = AVM_ARG_SEVAL_RVALUE;
argCode.operand = AVM_ARG_ARRAY_KIND;
break;
}
}
AvmInstruction * arrayInstruction = new AvmInstruction( argArraySize );
argArray->setInstruction( arrayInstruction );
// Global ArgCode
arrayInstruction->setMainBytecode(argCode);
if( argArray->getTypeSpecifier()->is< ClassTypeSpecifier >() )
{
ClassTypeSpecifier * structT =
argArray->getTypeSpecifier()->to< ClassTypeSpecifier >();
for( avm_size_t idx = 0 ; idx < argArraySize ; ++idx )
{
setArgcodeRValue(
aCTX->clone(structT->getSymbolData(idx).getTypeSpecifier()),
arrayInstruction->at(idx), argArray->at(idx), needTypeChecking);
arrayInstruction->at(idx).offset = idx;
}
}
else
{
if( argArray->getTypeSpecifier()->is< ContainerTypeSpecifier >() )
{
aCTX = aCTX->clone( argArray->getTypeSpecifier()->
to< ContainerTypeSpecifier >()->getContentsTypeSpecifier() );
}
else
{
needTypeChecking = false;
}
for( avm_size_t idx = 0 ; idx < argArraySize ; ++idx )
{
setArgcodeRValue(aCTX, arrayInstruction->at(idx),
argArray->at(idx), needTypeChecking);
arrayInstruction->at(idx).offset = idx;
}
}
}
void AbstractAvmcodeCompiler::setArgcodeContainerWValue(COMPILE_CONTEXT * aCTX,
AvmBytecode & argCode, const BF & arg)
{
argCode.processor = AVM_ARG_MEMORY_WVALUE_CPU;
if( arg.is< BuiltinContainer >() )
{
argCode.operation = AVM_ARG_SEVAL_WVALUE;
argCode.operand = AVM_ARG_BUILTIN_CONTAINER_KIND;
}
else if( arg.is< InstanceOfBuffer >() )
{
argCode.operation = AVM_ARG_SEVAL_WVALUE;
argCode.operand = AVM_ARG_BUFFER_KIND;
argCode.dtype = TypeManager::BUFFER;
}
else if( arg.is< InstanceOfData >() )
{
argCode.operation = AVM_ARG_SEVAL_WVALUE;
InstanceOfData * anInstance = arg.to_ptr< InstanceOfData >();
if( anInstance->isUfiMixedPointer() )
{
argCode.operand = AVM_ARG_DATA_UFI_KIND;
}
else if( anInstance->getModifier().hasNatureReference() )
{
argCode.operand = (anInstance->isUfiOffsetPointer() ?
AVM_ARG_DATA_UFI_KIND : AVM_ARG_DATA_REF_KIND);
}
else if( anInstance->getModifier().hasNatureMacro() )
{
argCode.operand = AVM_ARG_DATA_MACRO_KIND;
}
else if( anInstance->getModifier().hasFeatureMutable() )
{
argCode.operand = AVM_ARG_DATA_KIND;
}
else
{
getCompilerTable().incrWarningCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeContainerWValue :> "
"Unexpected the InstanceOfData << "
<< str_header( anInstance ) << " >> as << "
<< argCode.strType() << " >> argument !!!" << std::endl;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_DATA_KIND;
}
if( anInstance->isTypedBuffer() || anInstance->hasTypeCollection() )
{
argCode.dtype = anInstance->getTypeSpecifier();
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeContainerWValue :> Unexpected << "
<< str_header( anInstance ) << " >> as << Collection< T >"
<< " >> argument !!!" << std::endl;
AVM_OS_WARN << "The type below, is there a type of "
"collection ? If yes, you found a BUG ! "
<< std::endl
<< to_stream( anInstance->referedTypeSpecifier() );
}
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeContainerWValue :> Unexpected << "
<< str_header( arg ) << " >> as << container >> argument !!!"
<< std::endl;
argCode.operation = AVM_ARG_SEVAL_WVALUE;
argCode.operand = AVM_ARG_EXPRESSION_KIND;
}
}
void AbstractAvmcodeCompiler::setArgcodeContainerRValue(COMPILE_CONTEXT * aCTX,
AvmBytecode & argCode, const BF & arg)
{
if( arg.is< BuiltinContainer >() )
{
argCode.processor = AVM_ARG_COLLECTION_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_BUILTIN_CONTAINER_KIND;
}
else if( arg.is< InstanceOfBuffer >() )
{
argCode.processor = AVM_ARG_BUFFER_CPU;
argCode.operation = AVM_ARG_SEVAL_RVALUE;
argCode.operand = AVM_ARG_BUFFER_KIND;
argCode.dtype = TypeManager::BUFFER;
}
else if( arg.is< InstanceOfData >() )
{
argCode.processor = AVM_ARG_MEMORY_RVALUE_CPU;
argCode.operation = AVM_ARG_SEVAL_RVALUE;
InstanceOfData * anInstance = arg.to_ptr< InstanceOfData >();
if( anInstance->isUfiMixedPointer() )
{
argCode.operand = AVM_ARG_DATA_UFI_KIND;
}
else if( anInstance->getModifier().hasNatureReference() )
{
argCode.operand = (anInstance->isUfiOffsetPointer() ?
AVM_ARG_DATA_UFI_KIND : AVM_ARG_DATA_REF_KIND);
}
else if( anInstance->getModifier().hasNatureMacro() )
{
argCode.operand = AVM_ARG_DATA_MACRO_KIND;
}
else if( anInstance->getModifier().hasFeatureMutable() )
{
argCode.operand = AVM_ARG_DATA_KIND;
}
else
{
getCompilerTable().incrWarningCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeContainerRValue :> "
"Unexpected the InstanceOfData << "
<< str_header( anInstance ) << " >> as << "
<< argCode.strType() << " >> argument !!!" << std::endl;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_DATA_KIND;
}
if( anInstance->isTypedBuffer()
|| anInstance->isTypedString()
|| anInstance->hasTypeCollection() )
{
argCode.dtype = anInstance->getTypeSpecifier();
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeContainerRValue :> Unexpected << "
<< str_header( anInstance ) << " >> as << Collection< T >"
<< " >> argument !!!" << std::endl;
AVM_OS_WARN << "The type below, is there a type of "
"collection ? if yes, you found a BUG ! "
<< std::endl
<< to_stream( anInstance->referedTypeSpecifier() );
}
}
else
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeContainerRValue :> Unexpected << "
<< arg.raw_pointer()->classKindInfo() << " : " << str_header( arg )
<< " >> as << container >> argument !!!" << std::endl;
argCode.operation = AVM_ARG_SEVAL_RVALUE;
argCode.operand = AVM_ARG_EXPRESSION_KIND;
}
}
void AbstractAvmcodeCompiler::setArgcodeStatement(COMPILE_CONTEXT * aCTX,
AvmBytecode & argCode, const BF & arg, bool needTypeChecking)
{
argCode.dtype = TypeManager::AVMCODE;
if( aCTX->isNeedTypeChecking(needTypeChecking) )
{
checkArgType(aCTX, argCode.dtype, arg);
}
argCode.operation = AVM_ARG_UNDEFINED_OPERATION;
argCode.operand = AVM_ARG_UNDEFINED_OPERAND;
if( arg.is< InstanceOfData >() )
{
InstanceOfData * anInstance = arg.to_ptr< InstanceOfData >();
argCode.processor = AVM_ARG_MEMORY_RVALUE_CPU;
argCode.operation = AVM_ARG_SEVAL_RVALUE;
if( anInstance->isUfiMixedPointer() )
{
argCode.operand = AVM_ARG_DATA_UFI_KIND;
}
else if( anInstance->getModifier().hasNatureReference() )
{
argCode.operand = (anInstance->isUfiOffsetPointer() ?
AVM_ARG_DATA_UFI_KIND : AVM_ARG_DATA_REF_KIND);
}
else if( anInstance->getModifier().hasNatureMacro() )
{
argCode.operand = AVM_ARG_DATA_MACRO_KIND;
}
else if( anInstance->getModifier().hasFeatureMutable() )
{
argCode.operand = AVM_ARG_DATA_KIND;
}
}
else if( arg.is< AvmCode >() )
{
argCode.processor = AVM_ARG_NOP_CPU;
argCode.operation = AVM_ARG_NOP_RVALUE;
argCode.operand = AVM_ARG_STATEMENT_KIND;
}
if( (argCode.operation == AVM_ARG_UNDEFINED_OPERATION)
&& (argCode.operand == AVM_ARG_UNDEFINED_OPERAND) )
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "setArgcodeStatement :> Unexpected << "
<< str_header( arg ) << " >> as << "
<< argCode.strType() << " >> argument !!!" << std::endl;
argCode.operation = AVM_ARG_SEVAL_RVALUE;
argCode.operand = AVM_ARG_STATEMENT_KIND;
}
}
ExecutableForm * AbstractAvmcodeCompiler::getExecutableMachine(
COMPILE_CONTEXT * aCTX, const BF & arg)
{
switch( arg.classKind() )
{
case FORM_RUNTIME_ID_KIND:
{
return( arg.bfRID().getExecutable() );
}
case FORM_INSTANCE_MACHINE_KIND:
{
return( arg.to_ptr< InstanceOfMachine >()->getExecutable() );
}
case FORM_INSTANCE_DATA_KIND:
{
InstanceOfData * anInstance = arg.to_ptr< InstanceOfData >();
if( anInstance->isTypedMachine()
&& anInstance->getModifier().hasModifierPublicFinalStatic() )
{
ExecutableForm * anExecutable = aCTX->mCompileCtx->getExecutable();
if( ExecutableLib::MACHINE_COMPONENT_SELF == anInstance )
{
while( anExecutable != NULL )
{
if( anExecutable->isMainComponent() )
{
return( anExecutable );
}
anExecutable = anExecutable->getExecutableContainer();
}
return( anExecutable );
}
else if( ExecutableLib::MACHINE_COMPONENT_PARENT == anInstance )
{
for( bool isParent = false ; anExecutable != NULL ; )
{
if( anExecutable->isMainComponent() )
{
if( isParent )
{
return( anExecutable );
}
isParent = true;
}
anExecutable = anExecutable->getExecutableContainer();
}
return( anExecutable );
}
else if( ExecutableLib::MACHINE_COMPONENT_COMMUNICATOR
== anInstance )
{
while( anExecutable != NULL )
{
if( anExecutable->isMainComponent()
&& anExecutable->hasPort() )
{
return( anExecutable );
}
anExecutable = anExecutable->getExecutableContainer();
}
return( anExecutable );
}
else if( ExecutableLib::MACHINE_SYSTEM == anInstance )
{
while( anExecutable->hasContainer() )
{
anExecutable = anExecutable->getExecutableContainer();
}
return( anExecutable );
}
if( ExecutableLib::MACHINE_SELF == anInstance )
{
return( anExecutable );
}
else if( ExecutableLib::MACHINE_PARENT == anInstance )
{
return( anExecutable->getExecutableContainer() );
}
else if( ExecutableLib::MACHINE_COMMUNICATOR == anInstance )
{
while( anExecutable != NULL )
{
if( anExecutable->hasPort() )
{
return( anExecutable );
}
anExecutable = anExecutable->getExecutableContainer();
}
return( anExecutable );
}
}
return( NULL );
}
case FORM_UFI_KIND:
case FORM_AVMCODE_KIND:
default:
{
return( NULL );
}
}
return( NULL );
}
void AbstractAvmcodeCompiler::checkArgType(COMPILE_CONTEXT * aCTX,
BaseTypeSpecifier * aType, const BF & arg)
{
if( (aType == NULL) || aType->isTypedUniversal() )
{
return;
}
else if( not ExpressionTypeChecker::isTyped(aType, arg) )
{
getCompilerTable().incrErrorCount();
aCTX->errorContext( AVM_OS_WARN )
<< "checkArgType :> Unexpected << ";
AVM_IF_DEBUG_FLAG( COMPILING )
AVM_OS_WARN << std::endl << arg;
AVM_ELSE
AVM_OS_WARN << str_header( arg );
AVM_ENDIF_DEBUG_FLAG( COMPILING )
AVM_OS_WARN << " >> as << " << aType->strT()
<< " >> argument !!!" << std::endl;
if( aType->isTypedAlias() )
{
AVM_OS_WARN << "Info: << " << aType->strT()
<< " >> is an alias or a typedef of :> "
<< aType->referedTypeSpecifier()->strT() << std::endl;
}
}
}
}