double AM_PARAM::GetValue( const D_CODE* aDcode ) const { double paramvalue = 0.0; double curr_value = 0.0; parm_item_type state = POPVALUE; for( unsigned ii = 0; ii < m_paramStack.size(); ii++ ) { AM_PARAM_ITEM item = m_paramStack[ii]; switch( item.GetType() ) { case ADD: case SUB: case MUL: case DIV: // just an operator for next parameter value: store it state = item.GetType(); break; case PUSHPARM: // get the parameter from the aDcode if( aDcode && item.GetIndex() <= aDcode->GetParamCount() ) curr_value = aDcode->GetParam( item.GetIndex() ); else // Get parameter from local param definition { const APERTURE_MACRO * am_parent = aDcode->GetMacro(); curr_value = am_parent->GetLocalParam( aDcode, item.GetIndex() ); } // Fall through case PUSHVALUE: // a value is on the stack: if( item.GetType() == PUSHVALUE ) curr_value = item.GetValue(); switch( state ) { case POPVALUE: paramvalue = curr_value; break; case ADD: paramvalue += curr_value; break; case SUB: paramvalue -= curr_value; break; case MUL: paramvalue *= curr_value; break; case DIV: paramvalue /= curr_value; break; default: wxLogDebug( wxT( "AM_PARAM::GetValue() : unexpected operator\n" ) ); break; } break; default: wxLogDebug( wxT( "AM_PARAM::GetValue(): unexpected type\n" ) ); break; } } return paramvalue; }
double AM_PARAM::GetValue( const D_CODE* aDcode ) const { // In macros, actual values are sometimes given by an expression like: // 0-$2/2-$4 // Because arithmetic predence is used, the parameters (values (double) and operators) // are stored in a stack, with all numeric values converted to the actual values // when they are defered parameters // Each item is stored in a AM_PARAM_EVAL (a value or an operator) // // Then the stack with all values resolved is parsed and numeric values // calculated according to the precedence of operators double curr_value = 0.0; parm_item_type op_code; AM_PARAM_EVAL_STACK ops; for( unsigned ii = 0; ii < m_paramStack.size(); ii++ ) { AM_PARAM_ITEM item = m_paramStack[ii]; switch( item.GetType() ) { case ADD: case SUB: case MUL: case DIV: // just an operator for next parameter value case OPEN_PAR: case CLOSE_PAR: // Priority modifiers: store in stack op_code = item.GetType(); ops.push_back( AM_PARAM_EVAL( op_code ) ); break; case PUSHPARM: // a defered value: get the actual parameter from the aDcode if( aDcode ) // should be always true here { if( item.GetIndex() <= aDcode->GetParamCount() ) { curr_value = aDcode->GetParam( item.GetIndex() ); } else // Get parameter from local param definition { const APERTURE_MACRO * am_parent = aDcode->GetMacro(); curr_value = am_parent->GetLocalParam( aDcode, item.GetIndex() ); } } else { wxLogDebug( wxT( "AM_PARAM::GetValue(): NULL param aDcode\n" ) ); } ops.push_back( AM_PARAM_EVAL( curr_value ) ); break; case PUSHVALUE: // a value is on the stack: curr_value = item.GetValue(); ops.push_back( AM_PARAM_EVAL( curr_value ) ); break; default: wxLogDebug( "AM_PARAM::GetValue(): dcode %d prm %d/%d: unexpected type %d", aDcode ? aDcode->m_Num_Dcode : -1, ii, m_paramStack.size(), item.GetType() ); break; } } double result = Evaluate( ops ); return result; }