2008-02-15 18:31:40 +01:00
/*
2011-02-04 17:27:33 +01:00
* Copyright ( C ) 2008 - 2010 Dynare Team
2008-02-15 18:31:40 +01:00
*
* This file is part of Dynare .
*
* Dynare is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Dynare is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Dynare . If not , see < http : //www.gnu.org/licenses/>.
*/
# ifndef _MACRO_VALUE_HH
# define _MACRO_VALUE_HH
using namespace std ;
# include <string>
# include <vector>
2008-02-19 15:24:40 +01:00
# include <sstream>
2008-02-15 18:31:40 +01:00
2008-02-29 17:21:01 +01:00
class MacroDriver ;
2008-02-20 10:56:47 +01:00
//! Base class for representing values in macro language
2008-02-15 18:31:40 +01:00
class MacroValue
{
2008-02-29 17:21:01 +01:00
protected :
//! Reference to enclosing MacroDriver
MacroDriver & driver ;
2008-02-15 18:31:40 +01:00
public :
2008-02-20 10:56:47 +01:00
//! Exception thrown when type error occurs in macro language
2008-02-15 18:31:40 +01:00
class TypeError
{
public :
const string message ;
2009-12-16 18:13:23 +01:00
TypeError ( const string & message_arg ) : message ( message_arg )
{
} ;
2008-02-15 18:31:40 +01:00
} ;
2008-02-22 13:03:38 +01:00
//! Exception thrown when doing an out-of-bounds access through [] operator
class OutOfBoundsError
{
} ;
2008-02-29 17:21:01 +01:00
MacroValue ( MacroDriver & driver_arg ) ;
2008-02-19 15:24:40 +01:00
virtual ~ MacroValue ( ) ;
2008-02-20 10:56:47 +01:00
//! Applies + operator
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator + ( const MacroValue & mv ) const throw ( TypeError ) = 0 ;
2008-02-22 13:03:38 +01:00
//! Applies unary + operator
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator + ( ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Applies - operator
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator - ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Applies unary - operator
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator - ( ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Applies * operator
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator * ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Applies / operator
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator / ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Less comparison
2008-02-29 17:21:01 +01:00
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue * operator < ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Greater comparision
2008-02-29 17:21:01 +01:00
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue * operator > ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Less or equal comparison
2008-02-29 17:21:01 +01:00
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue * operator < = ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Greater or equal comparison
2008-02-29 17:21:01 +01:00
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue * operator > = ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Equal comparison
2008-02-29 17:21:01 +01:00
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue * operator = = ( const MacroValue & mv ) const throw ( TypeError ) = 0 ;
2008-02-20 10:56:47 +01:00
//! Not equal comparison
2008-02-29 17:21:01 +01:00
/*! Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue * operator ! = ( const MacroValue & mv ) const throw ( TypeError ) = 0 ;
2008-02-20 10:56:47 +01:00
//! Applies && operator
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator & & ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Applies || operator
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator | | ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Applies unary ! operator
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator ! ( ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Applies [] operator
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator [ ] ( const MacroValue & mv ) const throw ( TypeError , OutOfBoundsError ) ;
2008-02-20 10:56:47 +01:00
//! Converts value to string
2008-02-15 18:31:40 +01:00
virtual string toString ( ) const = 0 ;
2008-02-20 10:56:47 +01:00
//! Converts value to array form
2008-02-29 17:21:01 +01:00
virtual const MacroValue * toArray ( ) const = 0 ;
2008-02-20 10:56:47 +01:00
//! Appends value at the end of an array
2008-12-08 16:13:08 +01:00
/*! The argument must be an array. */
2008-02-29 17:21:01 +01:00
virtual const MacroValue * append ( const MacroValue * array ) const throw ( TypeError ) ;
2008-12-08 16:13:08 +01:00
//! Applies "in" operator
/*! The argument must be an array. Returns an IntMV, equal to 0 or 1 */
virtual const MacroValue * in ( const MacroValue * array ) const throw ( TypeError ) ;
2008-02-22 13:03:38 +01:00
//! Returns a new IntMV
/*! Necessary for ArrayMV::operator[] (template issue) */
2008-02-29 17:21:01 +01:00
static const MacroValue * new_base_value ( MacroDriver & driver , int i ) ;
2008-02-22 13:03:38 +01:00
//! Returns a new StringMV
/*! Necessary for ArrayMV::operator[] (template issue) */
2008-02-29 17:21:01 +01:00
static const MacroValue * new_base_value ( MacroDriver & driver , const string & s ) ;
2008-02-15 18:31:40 +01:00
} ;
2008-02-20 10:56:47 +01:00
//! Represents an integer value in macro language
2008-02-15 18:31:40 +01:00
class IntMV : public MacroValue
{
2008-02-19 15:24:40 +01:00
friend class StringMV ;
2008-03-07 16:58:35 +01:00
friend class MacroDriver ;
2008-02-15 18:31:40 +01:00
private :
2008-02-20 10:56:47 +01:00
//! Underlying integer value
2008-02-29 17:21:01 +01:00
const int value ;
2008-02-15 18:31:40 +01:00
public :
2008-02-29 17:21:01 +01:00
IntMV ( MacroDriver & driver , int value_arg ) ;
2008-02-19 15:24:40 +01:00
virtual ~ IntMV ( ) ;
2008-02-20 10:56:47 +01:00
//! Computes arithmetic addition
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator + ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-22 13:03:38 +01:00
//! Unary plus
2008-02-29 17:21:01 +01:00
/*! Returns itself */
virtual const MacroValue * operator + ( ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Computes arithmetic substraction
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator - ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Computes opposite
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator - ( ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Computes arithmetic multiplication
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator * ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Computes arithmetic division
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator / ( const MacroValue & mv ) const throw ( TypeError ) ;
virtual const MacroValue * operator < ( const MacroValue & mv ) const throw ( TypeError ) ;
virtual const MacroValue * operator > ( const MacroValue & mv ) const throw ( TypeError ) ;
virtual const MacroValue * operator < = ( const MacroValue & mv ) const throw ( TypeError ) ;
virtual const MacroValue * operator > = ( const MacroValue & mv ) const throw ( TypeError ) ;
virtual const MacroValue * operator = = ( const MacroValue & mv ) const throw ( TypeError ) ;
virtual const MacroValue * operator ! = ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Computes logical and
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator & & ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Computes logical or
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator | | ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Computes logical negation
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator ! ( ) const throw ( TypeError ) ;
2008-02-15 18:31:40 +01:00
virtual string toString ( ) const ;
2008-02-20 10:56:47 +01:00
//! Converts value to array form
2008-02-29 17:21:01 +01:00
/*! Returns an integer array containing a single value */
virtual const MacroValue * toArray ( ) const ;
2008-02-20 10:56:47 +01:00
//! Appends value at the end of an array
2008-02-29 17:21:01 +01:00
/*! The first argument must be an integer array. */
virtual const MacroValue * append ( const MacroValue * array ) const throw ( TypeError ) ;
2008-12-08 16:13:08 +01:00
virtual const MacroValue * in ( const MacroValue * array ) const throw ( TypeError ) ;
2008-02-20 10:56:47 +01:00
//! Creates a integer range
/*! Arguments must be of type IntMV.
2009-01-23 11:59:37 +01:00
Returns an integer array containing all integers between mv1 and mv2 .
2010-05-12 11:50:27 +02:00
If mv2 < mv1 , returns an empty range ( for consistency with MATLAB ) .
2008-02-20 10:56:47 +01:00
*/
2008-02-29 17:21:01 +01:00
static const MacroValue * new_range ( MacroDriver & driver , const MacroValue * mv1 , const MacroValue * mv2 ) throw ( TypeError ) ;
2008-02-15 18:31:40 +01:00
} ;
2008-02-20 10:56:47 +01:00
//! Represents a string value in macro language
2008-02-15 18:31:40 +01:00
class StringMV : public MacroValue
{
2008-03-07 16:58:35 +01:00
friend class MacroDriver ;
2008-02-15 18:31:40 +01:00
private :
2008-02-20 10:56:47 +01:00
//! Underlying string value
2008-02-29 17:21:01 +01:00
const string value ;
2008-02-15 18:31:40 +01:00
public :
2008-02-29 17:21:01 +01:00
StringMV ( MacroDriver & driver , const string & value_arg ) ;
2008-02-19 15:24:40 +01:00
virtual ~ StringMV ( ) ;
2008-02-20 10:56:47 +01:00
//! Computes string concatenation
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator + ( const MacroValue & mv ) const throw ( TypeError ) ;
virtual const MacroValue * operator = = ( const MacroValue & mv ) const throw ( TypeError ) ;
virtual const MacroValue * operator ! = ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-19 15:24:40 +01:00
//! Subscripting operator
2008-02-29 17:21:01 +01:00
/*! Argument must be an ArrayMV<int>. Indexes begin at 1. Returns a StringMV. */
virtual const MacroValue * operator [ ] ( const MacroValue & mv ) const throw ( TypeError , OutOfBoundsError ) ;
2008-02-20 10:56:47 +01:00
//! Returns underlying string value
2008-02-15 18:31:40 +01:00
virtual string toString ( ) const ;
2008-02-20 10:56:47 +01:00
//! Converts value to array form
2008-02-29 17:21:01 +01:00
/*! Returns a string array containing a single value */
virtual const MacroValue * toArray ( ) const ;
2008-02-20 10:56:47 +01:00
//! Appends value at the end of an array
2008-02-29 17:21:01 +01:00
/*! The first argument must be a string array. Returns a string array. */
virtual const MacroValue * append ( const MacroValue * array ) const throw ( TypeError ) ;
2008-12-08 16:13:08 +01:00
virtual const MacroValue * in ( const MacroValue * array ) const throw ( TypeError ) ;
2008-02-15 18:31:40 +01:00
} ;
2008-02-20 10:56:47 +01:00
//! Represents an array in macro language
2008-02-19 15:24:40 +01:00
template < typename T >
class ArrayMV : public MacroValue
2008-02-15 18:31:40 +01:00
{
2008-02-19 15:24:40 +01:00
friend class IntMV ;
friend class StringMV ;
friend class ArrayMV < string > ; // Necessary for operator[] to access values of integer array when subscripting a string array
2008-02-29 17:21:01 +01:00
friend class MacroDriver ;
2008-02-15 18:31:40 +01:00
private :
2008-02-20 10:56:47 +01:00
//! Underlying vector
2008-02-29 17:21:01 +01:00
const vector < T > values ;
2008-02-15 18:31:40 +01:00
public :
2008-02-29 17:21:01 +01:00
ArrayMV ( MacroDriver & driver , const vector < T > & values_arg ) ;
2008-02-19 15:24:40 +01:00
virtual ~ ArrayMV ( ) ;
2008-02-20 10:56:47 +01:00
//! Computes array concatenation
2008-02-29 17:21:01 +01:00
/*! Both array must be of same type */
virtual const MacroValue * operator + ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-04-14 11:19:01 +02:00
//! Returns an array in which the elements of the second array have been removed from the first
/*! It is close to a set difference operation, except that if an element appears two times in the first array, it will also be in the returned value (provided it is not in the second array) */
virtual const MacroValue * operator - ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator = = ( const MacroValue & mv ) const throw ( TypeError ) ;
virtual const MacroValue * operator ! = ( const MacroValue & mv ) const throw ( TypeError ) ;
2008-02-19 15:24:40 +01:00
//! Subscripting operator
2008-02-20 10:56:47 +01:00
/*! Argument must be an ArrayMV<int>. Indexes begin at 1.
2009-01-23 11:59:37 +01:00
If argument is a one - element array , returns an IntMV or StringMV .
Otherwise returns an array . */
2008-02-29 17:21:01 +01:00
virtual const MacroValue * operator [ ] ( const MacroValue & mv ) const throw ( TypeError , OutOfBoundsError ) ;
2008-02-20 10:56:47 +01:00
//! Returns a string containing the concatenation of string representations of elements
2008-02-15 18:31:40 +01:00
virtual string toString ( ) const ;
2008-02-29 17:21:01 +01:00
//! Returns itself
virtual const MacroValue * toArray ( ) const ;
2008-02-15 18:31:40 +01:00
} ;
2008-02-19 15:24:40 +01:00
template < typename T >
2008-02-29 17:21:01 +01:00
ArrayMV < T > : : ArrayMV ( MacroDriver & driver , const vector < T > & values_arg ) : MacroValue ( driver ) , values ( values_arg )
2008-02-15 18:31:40 +01:00
{
2008-02-19 15:24:40 +01:00
}
template < typename T >
ArrayMV < T > : : ~ ArrayMV ( )
{
}
template < typename T >
2008-02-29 17:21:01 +01:00
const MacroValue *
2008-02-19 15:24:40 +01:00
ArrayMV < T > : : operator + ( const MacroValue & mv ) const throw ( TypeError )
{
const ArrayMV < T > * mv2 = dynamic_cast < const ArrayMV < T > * > ( & mv ) ;
if ( mv2 = = NULL )
throw TypeError ( " Type mismatch for operands of + operator " ) ;
2008-02-20 10:56:47 +01:00
vector < T > values_copy ( values ) ;
values_copy . insert ( values_copy . end ( ) , mv2 - > values . begin ( ) , mv2 - > values . end ( ) ) ;
2008-02-29 17:21:01 +01:00
return new ArrayMV < T > ( driver , values_copy ) ;
2008-02-19 15:24:40 +01:00
}
2008-04-14 11:19:01 +02:00
template < typename T >
const MacroValue *
ArrayMV < T > : : operator - ( const MacroValue & mv ) const throw ( TypeError )
{
const ArrayMV < T > * mv2 = dynamic_cast < const ArrayMV < T > * > ( & mv ) ;
if ( mv2 = = NULL )
throw TypeError ( " Type mismatch for operands of - operator " ) ;
/* Highly inefficient algorithm for computing set difference
( but vector < T > is not suited for that . . . ) */
vector < T > new_values ;
2009-12-16 18:13:23 +01:00
for ( typename vector < T > : : const_iterator it = values . begin ( ) ;
it ! = values . end ( ) ; it + + )
2008-04-14 11:19:01 +02:00
{
typename vector < T > : : const_iterator it2 ;
2009-12-16 18:13:23 +01:00
for ( it2 = mv2 - > values . begin ( ) ; it2 ! = mv2 - > values . end ( ) ; it2 + + )
2008-04-14 11:19:01 +02:00
if ( * it = = * it2 )
break ;
if ( it2 = = mv2 - > values . end ( ) )
new_values . push_back ( * it ) ;
}
return new ArrayMV < T > ( driver , new_values ) ;
}
2008-02-19 15:24:40 +01:00
template < typename T >
2008-02-29 17:21:01 +01:00
const MacroValue *
2008-02-19 15:24:40 +01:00
ArrayMV < T > : : operator = = ( const MacroValue & mv ) const throw ( TypeError )
{
const ArrayMV < T > * mv2 = dynamic_cast < const ArrayMV < T > * > ( & mv ) ;
if ( mv2 = = NULL )
2008-02-29 17:21:01 +01:00
return new IntMV ( driver , 0 ) ;
2008-02-19 15:24:40 +01:00
else
2008-02-29 17:21:01 +01:00
return new IntMV ( driver , values = = mv2 - > values ) ;
2008-02-19 15:24:40 +01:00
}
template < typename T >
2008-02-29 17:21:01 +01:00
const MacroValue *
2008-02-19 15:24:40 +01:00
ArrayMV < T > : : operator ! = ( const MacroValue & mv ) const throw ( TypeError )
{
const ArrayMV < T > * mv2 = dynamic_cast < const ArrayMV < T > * > ( & mv ) ;
if ( mv2 = = NULL )
2008-02-29 17:21:01 +01:00
return new IntMV ( driver , 1 ) ;
2008-02-19 15:24:40 +01:00
else
2008-02-29 17:21:01 +01:00
return new IntMV ( driver , values ! = mv2 - > values ) ;
2008-02-19 15:24:40 +01:00
}
template < typename T >
2008-02-29 17:21:01 +01:00
const MacroValue *
2008-02-22 13:03:38 +01:00
ArrayMV < T > : : operator [ ] ( const MacroValue & mv ) const throw ( TypeError , OutOfBoundsError )
2008-02-19 15:24:40 +01:00
{
const ArrayMV < int > * mv2 = dynamic_cast < const ArrayMV < int > * > ( & mv ) ;
if ( mv2 = = NULL )
throw TypeError ( " Expression inside [] must be an integer array " ) ;
vector < T > result ;
2009-12-16 18:13:23 +01:00
for ( vector < int > : : const_iterator it = mv2 - > values . begin ( ) ;
it ! = mv2 - > values . end ( ) ; it + + )
2008-02-22 13:03:38 +01:00
{
if ( * it < 1 | | * it > ( int ) values . size ( ) )
throw OutOfBoundsError ( ) ;
result . push_back ( values [ * it - 1 ] ) ;
}
2009-02-06 16:47:26 +01:00
if ( result . size ( ) > 1 | | result . size ( ) = = 0 )
2008-02-29 17:21:01 +01:00
return new ArrayMV < T > ( driver , result ) ;
2008-02-22 13:03:38 +01:00
else
2008-02-29 17:21:01 +01:00
return MacroValue : : new_base_value ( driver , result [ 0 ] ) ;
2008-02-19 15:24:40 +01:00
}
template < typename T >
string
ArrayMV < T > : : toString ( ) const
{
ostringstream ss ;
2009-12-16 18:13:23 +01:00
for ( typename vector < T > : : const_iterator it = values . begin ( ) ;
it ! = values . end ( ) ; it + + )
2008-02-19 15:24:40 +01:00
ss < < * it ;
return ss . str ( ) ;
}
template < typename T >
2008-02-29 17:21:01 +01:00
const MacroValue *
2008-02-19 15:24:40 +01:00
ArrayMV < T > : : toArray ( ) const
{
2008-02-29 17:21:01 +01:00
return this ;
2008-02-19 15:24:40 +01:00
}
2008-02-15 18:31:40 +01:00
# endif