// rpimpl_oper.cpp
// Copyright (c) Menno Rubingh 2016.  Web: [http://rubinghsoftware.de]
// 
// MR Mar 2016.
//
// Implementation of the OperationXxx member functions.
//
//---
// Implementation notes:
//   - Floating-point errors: 
//     This implementation internally does NO checking for floating-point errors
//     at the point where the math operations are executed.
//     Rationale: to maximize processing speed of the RPInterpreter::evaluate().
//     Further explanation and rationale is given in the text file
//     'rpinterpreter_doc_floatingPointErrors.txt' which should be contained among the
//     sources.
//   - The execute() member functions are not implemented as inline functions,
//     because in this software the member functions of the OperationXxx derived 
//     classes are called exclusively via pointers to the base class OperationBase.
//     In such a case, inlining is impossible.
//



#include "rpimpl_oper.h"   //OperationXxx.

#include <stdio.h>         

#include <math.h>          //pow().




//------------------------------------------------------------------------------------
// The print() member functions.
//------------------------------------------------------------------------------------


void OperationSemicolon:: print( FILE * oF ) const
{
	fprintf( oF, "semicol" );
}


void OperationPushVar:: print( FILE * oF ) const
{
	fprintf( oF, "pushV[%c]", VarTable::indexToName(cm_varIndex) );
}
void OperationPopVar:: print( FILE * oF ) const
{
	fprintf( oF, "popV[%c]", VarTable::indexToName(cm_varIndex) );
}


void OperationPushConst:: print( FILE * oF ) const
{
	fprintf( oF, "pushC[%g]", cm_value );
}


void OperationBinAdd :: print( FILE * oF ) const
{
	fprintf( oF, "binAdd" );
}
void OperationBinSub:: print( FILE * oF ) const
{
	fprintf( oF, "binSub" );
}
void OperationBinMul :: print( FILE * oF ) const
{
	fprintf( oF, "binMul" );
}
void OperationBinDiv :: print( FILE * oF ) const
{
	fprintf( oF, "binDiv" );
}
void OperationBinPow :: print( FILE * oF ) const
{
	fprintf( oF, "binPow" );
}





//------------------------------------------------------------------------------------
// The execute() member functions.
//------------------------------------------------------------------------------------

void OperationSemicolon:: execute( 
	StackDbl *   uStack,
	VarTable *   uVars ) const
{
	if ( uStack->getN() != 0 )
	{
		throw Ex( &cm_cxt, "stacksize != 0 at semicolon" );
	}
}


void OperationPushVar:: execute( 
	StackDbl *   uStack,
	VarTable *   uVars ) const
{
	double val = uVars->getByIndex( cm_varIndex );
	uStack->push( &cm_cxt, val );
}
void OperationPopVar:: execute( 
	StackDbl *   uStack,
	VarTable *   uVars ) const
{
	double val = uStack->pop( &cm_cxt );
	uVars->putByIndex( cm_varIndex, val );
}


void OperationPushConst:: execute( 
	StackDbl *   uStack,
	VarTable *   uVars ) const
{
	uStack->push( &cm_cxt, cm_value );
}


void OperationBinAdd:: execute( 
	StackDbl *   uStack,
	VarTable *   uVars ) const
{
	double valR = uStack->pop( &cm_cxt );
	double valL = uStack->pop( &cm_cxt );
	uStack->push( &cm_cxt, valL + valR );
}
void OperationBinSub:: execute( 
	StackDbl *   uStack,
	VarTable *   uVars ) const
{
	double valR = uStack->pop( &cm_cxt );
	double valL = uStack->pop( &cm_cxt );
	uStack->push( &cm_cxt, valL - valR );
}
void OperationBinMul:: execute( 
	StackDbl *   uStack,
	VarTable *   uVars ) const
{
	double valR = uStack->pop( &cm_cxt );
	double valL = uStack->pop( &cm_cxt );
	uStack->push( &cm_cxt, valL * valR );
}
void OperationBinDiv:: execute( 
	StackDbl *   uStack,
	VarTable *   uVars ) const
{
	double valR = uStack->pop( &cm_cxt );
	double valL = uStack->pop( &cm_cxt );
	uStack->push( &cm_cxt, valL / valR );
}
void OperationBinPow:: execute( 
	StackDbl *   uStack,
	VarTable *   uVars ) const
{
	double valR = uStack->pop( &cm_cxt );
	double valL = uStack->pop( &cm_cxt );
	uStack->push( &cm_cxt, pow( valL, valR ) );
}