blob: d1f6e77196d31cfc884bf45a7f63a50fc50e4e21 [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 "AvmcodeAssignCompiler.h"
#include <computer/instruction/AvmInstruction.h>
#include <fml/expression/AvmCode.h>
#include <fml/expression/ExpressionConstructor.h>
#include <fml/expression/StatementConstructor.h>
#include <fml/operator/OperatorManager.h>
namespace sep
{
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ASSIGN COMPILATION
////////////////////////////////////////////////////////////////////////////////
inline BF AvmcodeAssignCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileStatement(aCTX, aCode) );
}
inline BF AvmcodeAssignCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
AvmInstruction * argsInstruction = aCode->genInstruction();
setArgcodeLValue(aCTX, argsInstruction->at(0), aCode->first());
optimizeArgExpression(aCTX, aCode, 1);
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_RVALUE_CPU,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_EXPRESSION_KIND,
/*dtype */ argsInstruction->at(0).dtype);
return( aCode );
}
inline BFCode AvmcodeAssignCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BF lvalue = compileArgLvalue(aCTX, aCode->first());
if( lvalue.is< InstanceOfData >() )
{
aCTX = aCTX->clone(
lvalue.to_ptr< InstanceOfData >()->getTypeSpecifier() );
}
BF rvalue = compileArgRvalue(aCTX, aCode->second());
BFCode compilCode = StatementConstructor::newCode(
aCode->getOperator(), lvalue, rvalue );
return( compilCode );
}
// lvalue =: rvalue; ==> [ lvalue , rvalue ]
BFCode AvmcodeAssignCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
AvmInstruction * argsInstruction = aCode->genInstruction();
setArgcodeLValue(aCTX, argsInstruction->at(0), aCode->first());
optimizeArgExpression(aCTX, aCode, 1);
argsInstruction->at(1).dtype = argsInstruction->at(0).dtype;
setArgcodeRValue(aCTX, argsInstruction->at(1), aCode->second());
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 ASSIGN AFTER COMPILATION
////////////////////////////////////////////////////////////////////////////////
inline BF AvmcodeAssignAfterCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BF lvalue = compileArgLvalue(aCTX, aCode->first());
if( lvalue.is< InstanceOfData >() )
{
aCTX = aCTX->clone(
lvalue.to_ptr< InstanceOfData >()->getTypeSpecifier() );
}
return( StatementConstructor::newCode( aCode->getOperator(),
lvalue, lvalue, compileArgRvalue(aCTX, aCode->second()) ) );
}
inline BF AvmcodeAssignAfterCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
AvmInstruction * argsInstruction = aCode->genInstruction();
setArgcodeLValue(aCTX, argsInstruction->at(0), aCode->first());
argsInstruction->at(1).dtype = argsInstruction->at(0).dtype;
setArgcodeRValue(aCTX, argsInstruction->at(1), aCode->second());
optimizeArgExpression(aCTX, aCode, 2);
setArgcodeRValue(aCTX, argsInstruction->at(2), aCode->third());
argsInstruction->computeMainBytecode(
/*context */ AVM_ARG_RETURN_CTX,
/*processor*/ AVM_ARG_MEMORY_RVALUE_CPU,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_EXPRESSION_KIND,
/*dtype */ argsInstruction->at(0).dtype);
return( aCode );
}
inline BFCode AvmcodeAssignAfterCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BF lvalue = compileArgLvalue(aCTX, aCode->first());
if( lvalue.is< InstanceOfData >() )
{
aCTX = aCTX->clone(
lvalue.to_ptr< InstanceOfData >()->getTypeSpecifier() );
}
return( StatementConstructor::newCode(OperatorManager::OPERATOR_ASSIGN,
lvalue, compileArgRvalue(aCTX, aCode->second()) ) );
}
// lvalue =: rvalue; ==> [ lvalue , rvalue ]
BFCode AvmcodeAssignAfterCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unexpected invoke of ASSIGN#AFTER "
"statement compilation optimizer !!!"
<< SEND_EXIT;
return( aCode );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ASSIGN OP COMPILATION
////////////////////////////////////////////////////////////////////////////////
// lvalue op := rvalue; ==> [ lvalue , VAL[lvalue] op rvalue ]
inline BF AvmcodeAssignOpCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BFCode expr = aCode->second().bfCode();
expr = ExpressionConstructor::newCode(expr->getOperator(),
aCode->first(), expr->first());
expr = ExpressionConstructor::newCode(
OperatorManager::OPERATOR_ASSIGN, aCode->first(), expr);
return( AVMCODE_COMPILER.compileExpression(aCTX, expr) );
}
inline BFCode AvmcodeAssignOpCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BFCode expr = aCode->second().bfCode();
expr = ExpressionConstructor::newCode(expr->getOperator(),
aCode->first(), expr->first());
expr = StatementConstructor::newCode(
OperatorManager::OPERATOR_ASSIGN, aCode->first(), expr);
return( AVMCODE_COMPILER.compileStatement(aCTX, expr) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ASSIGN OP AFTER COMPILATION
////////////////////////////////////////////////////////////////////////////////
// lvalue =: op rvalue; ==> [ lvalue , VAL[lvalue] , (VAL[lvalue] op rvalue) ]
inline BF AvmcodeAssignOpAfterCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BFCode expr = aCode->second().bfCode();
expr = ExpressionConstructor::newCode(expr->getOperator(),
aCode->first(), expr->first());
expr = ExpressionConstructor::newCode(
OperatorManager::OPERATOR_ASSIGN_AFTER, aCode->first(), expr);
return( AVMCODE_COMPILER.compileExpression(aCTX, expr) );
}
inline BFCode AvmcodeAssignOpAfterCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BFCode expr = aCode->second().bfCode();
expr = ExpressionConstructor::newCode(expr->getOperator(),
aCode->first(), expr->first());
expr = StatementConstructor::newCode(
OperatorManager::OPERATOR_ASSIGN, aCode->first(), expr);
return( AVMCODE_COMPILER.compileStatement(aCTX, expr) );
}
////////////////////////////////////////////////////////////////////////////////
// AVMCODE ASSIGN REFERENCE COMPILATION
////////////////////////////////////////////////////////////////////////////////
inline BF AvmcodeAssignRefCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileStatement(aCTX, aCode) );
}
inline BF AvmcodeAssignRefCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BFCode optCode = optimizeStatement(aCTX, aCode);
optCode->getInstruction()->setMainOperand( AVM_ARG_EXPRESSION_KIND );
return( optCode );
}
inline BFCode AvmcodeAssignRefCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BF lvalue = compileArgLvalue(aCTX, aCode->first());
if( lvalue.is< InstanceOfData >() )
{
aCTX = aCTX->clone(
lvalue.to_ptr< InstanceOfData >()->getTypeSpecifier() );
}
return( StatementConstructor::newCode( aCode->getOperator(),
lvalue, compileArgLvalue(aCTX, aCode->second()) ) );
}
BFCode AvmcodeAssignRefCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
// lvalue =: lvalue; <==> lvalue = $(quote lvalue);
aCode->setOperator( OperatorManager::OPERATOR_ASSIGN );
AvmInstruction * argsInstruction = aCode->genInstruction();
setArgcodeLValueRef(aCTX, argsInstruction->at(0), aCode->first());
optimizeArgExpression(aCTX, aCode, 1);
argsInstruction->at(1).dtype = argsInstruction->at(0).dtype;
setArgcodeLValue(aCTX, argsInstruction->at(1), aCode->second());
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 ASSIGN Macro COMPILATION
////////////////////////////////////////////////////////////////////////////////
inline BF AvmcodeAssignMacroCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileStatement(aCTX, aCode) );
}
inline BF AvmcodeAssignMacroCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BFCode optCode = optimizeStatement(aCTX, aCode);
optCode->getInstruction()->setMainOperand( AVM_ARG_EXPRESSION_KIND );
return( optCode );
}
inline BFCode AvmcodeAssignMacroCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
BF lvalue = compileArgLvalue(aCTX, aCode->first());
if( lvalue.is< InstanceOfData >() )
{
aCTX = aCTX->clone(
lvalue.to_ptr< InstanceOfData >()->getTypeSpecifier() );
}
return( StatementConstructor::newCode( aCode->getOperator(),
lvalue, compileArgRvalue(aCTX, aCode->second()) ) );
}
BFCode AvmcodeAssignMacroCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
// lvalue =: lvalue; <==> lvalue = $(quote lvalue);
aCode->setOperator( OperatorManager::OPERATOR_ASSIGN );
AvmInstruction * argsInstruction = aCode->genInstruction();
setArgcodeLValueMacro(aCTX, argsInstruction->at(0), aCode->first());
optimizeArgExpression(aCTX, aCode, 1);
argsInstruction->at(1).dtype = argsInstruction->at(0).dtype;
setArgcodeRValue(aCTX, argsInstruction->at(1), aCode->second());
argsInstruction->at(1).setNopOperation();
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 ASSIGN UNARY COMPILATION
////////////////////////////////////////////////////////////////////////////////
inline BF AvmcodeAssignUnaryCompiler::compileExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( compileStatement(aCTX, aCode) );
}
inline BF AvmcodeAssignUnaryCompiler::optimizeExpression(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
AvmInstruction * argsInstruction = aCode->genInstruction();
setArgcodeLValue(aCTX, argsInstruction->at(0), aCode->first());
argsInstruction->computeMainBytecode(
/*context */ AVM_ARG_RETURN_CTX,
/*processor*/ AVM_ARG_MEMORY_RVALUE_CPU,
/*operation*/ AVM_ARG_SEVAL_RVALUE,
/*operand */ AVM_ARG_EXPRESSION_KIND,
/*dtype */ argsInstruction->at(0).dtype);
return( aCode );
}
inline BFCode AvmcodeAssignUnaryCompiler::compileStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
return( StatementConstructor::newCode( aCode->getOperator(),
compileArgLvalue(aCTX, aCode->first()) ) );
}
BFCode AvmcodeAssignUnaryCompiler::optimizeStatement(
COMPILE_CONTEXT * aCTX, const BFCode & aCode)
{
AvmInstruction * argsInstruction = aCode->genInstruction();
setArgcodeLValue(aCTX, argsInstruction->at(0), aCode->first());
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 );
}
}