Updating the changelog in the VERSION file, and version_sync.
[shapes.git] / source / opdispatchcase.cc
blob3743bf6eb922f0e1b569bb3d8669ed690f4d6c00
1 /* This file is part of Shapes.
3 * Shapes is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, either version 3 of the License, or
6 * any later version.
8 * Shapes is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with Shapes. If not, see <http://www.gnu.org/licenses/>.
16 * Copyright 2008 Henrik Tidefelt
19 #include <iostream>
21 #include "/home/rt/tidefelt/include/refcount.h"
23 using namespace std;
25 class Value;
26 class A;
27 class B;
28 class C;
30 /* The closest to the one level recursion needed is to start from two sets of symmetric macros.
31 * One set ends in "1", the other ends in "2".
34 /* Define the class heierarcy in macros:
36 #define CLASSTREE1_A( Ma, S, Mb ) Ma( S, Mb, A )
37 #define CLASSTREE1_B( Ma, S, Mb ) Ma( S, Mb, B ) CLASSTREE1_C( Ma, S, Mb )
38 #define CLASSTREE1_C( Ma, S, Mb ) Ma( S, Mb, C )
39 #define CLASSTREE1_ROOT( Ma, S, Mb ) \
40 CLASSTREE1_A( Ma, S, Mb )\
41 CLASSTREE1_B( Ma, S, Mb )
43 #define CLASSTREE2_A( Ma, S, Mb ) Ma( S, Mb, A )
44 #define CLASSTREE2_B( Ma, S, Mb ) Ma( S, Mb, B ) CLASSTREE2_C( Ma, S, Mb )
45 #define CLASSTREE2_C( Ma, S, Mb ) Ma( S, Mb, C )
46 #define CLASSTREE2_ROOT( Ma, S, Mb ) \
47 CLASSTREE2_A( Ma, S, Mb )\
48 CLASSTREE2_B( Ma, S, Mb )
52 /* Define convenient macros for looping.
54 #define SINGLELOOP1_( Sb, M, T ) M( T )
55 #define SINGLELOOP1( Sa, M ) Sa( SINGLELOOP1_,, M )
56 #define DOUBLELOOP1__( M, Ta, Tb ) M( Ta, Tb )
57 #define DOUBLELOOP1_( Sb, M, Ta ) Sb( DOUBLELOOP1__, M, Ta )
58 #define DOUBLELOOP1( Sa, Sb, M ) Sa( DOUBLELOOP1_, Sb, M )
60 #define SINGLELOOP2_( Sb, M, T ) M( T )
61 #define SINGLELOOP2( Sa, M ) Sa( SINGLELOOP2_,, M )
62 #define DOUBLELOOP2__( M, Ta, Tb ) M( Ta, Tb )
63 #define DOUBLELOOP2_( Sb, M, Ta ) Sb( DOUBLELOOP2__, M, Ta )
64 #define DOUBLELOOP2( Sa, Sb, M ) Sa( DOUBLELOOP2_, Sb, M )
66 /* Define a macro that only uses the first argument,
67 * resulting in a macro that calls another macro for each class.
69 #define FORALLCLASSESM( M ) SINGLELOOP1( CLASSTREE1_ROOT, M )
71 /* Define a macro that calls another macro with a given first argument,
72 * varying the second argument over all classes.
74 #define FORALLCLASSESMT( M, T ) CLASSTREE2_ROOT( DOUBLELOOP2__, M, T )
76 /* Use the two looping macros above in a nested manner to produce a default method
77 * for each pair combination of classes.
79 #define DEFAULTOP__( Ta, Tb ) virtual int op( RefCountPtr< const Ta > x1, RefCountPtr< const Tb > x2 ) const { return 0; }
80 #define DEFAULTOP_( Ta ) FORALLCLASSESMT( DEFAULTOP__, Ta )
81 #define DEFAULTOP FORALLCLASSESM( DEFAULTOP_ )
83 /* Define a macro for hiding the default method for a set of classes:
85 #define HIDEDEFAULT_( Ta, Tb ) virtual int op( Ta * v1, Tb * v2 ) const { return 0; }
86 #define HIDEDEFAULT( Sa, Sb ) DOUBLELOOP2( Sa, Sb, HIDEDEFAULT_ )
88 /* Define a macro for hiding the default method for a set of classes:
90 #define CALLIMPL_( Ta, Tb ) virtual int op( RefCountPtr< const Ta > x1, RefCountPtr< const Tb > x2 ) const { return impl( x1.getPtr( ), x1, x2.getPtr( ), x2 ); }
91 #define CALLIMPL( Sa, Sb ) DOUBLELOOP2( Sa, Sb, CALLIMPL_ )
93 class BinOp
95 public:
96 int call( RefCountPtr< const Value > v1, RefCountPtr< const Value > v2 ) const;
97 DEFAULTOP;
100 #define DISPATCH1NULLDECL_ virtual int dispatch1( RefCountPtr< const Value > self, RefCountPtr< const Value > other, const BinOp * op ) const = 0;
101 #define DISPATCH2NULLDECL_( Ts, To ) virtual int dispatch2( RefCountPtr< const To > other, RefCountPtr< const Value > self, const BinOp * op ) const = 0;
103 #define DISPATCHCASE_LEVEL2( T2 )\
104 case TYPEID_ ## T2 : \
106 RefCountPtr< const T2 > arg2 = other.down_cast< const T2 >( ); \
107 if( arg2 == NullPtr< const T2 >( ) ) \
109 throw Exceptions::InternalError( "Downcast in dispatch level 2 failed, " #T2 ); \
111 return op->op( arg1, arg2 ); \
113 break;
115 #define DISPATCHCASE_LEVEL1( T1 )\
116 case TYPEID_ ## T1 : \
118 RefCountPtr< const T1 > arg1 = self.down_cast< const T1 >( ); \
119 if( arg1 == NullPtr< const T1 >( ) ) \
121 throw Exceptions::InternalError( "Downcast in dispatch level 1 failed, " #T1 ); \
123 switch( other->getTypeID( ) ) \
125 SINGLELOOP2( CLASSTREE2_ROOT, DISPATCHCASE_LEVEL2 ); \
126 default: \
127 throw Exceptions::InternalError( "QuickTypeID out of range in dispatch level 2" ); \
130 break;
132 #define DISPATCHCASEDECL static int dispatch1( RefCountPtr< const Value > self, RefCountPtr< const Value > other, const BinOp * op )
133 #define DISPATCHCASEIMPL \
134 int Value::dispatch1( RefCountPtr< const Value > self, RefCountPtr< const Value > other, const BinOp * op )\
136 switch( self->getTypeID( ) )\
138 SINGLELOOP1( CLASSTREE1_ROOT, DISPATCHCASE_LEVEL1 ); \
139 default:\
140 throw Exceptions::InternalError( "QuickTypeID out of range in dispatch level 1" ); \
144 #define DISPATCHNULLDECL DISPATCHCASEDECL
145 /*DISPATCH1NULLDECL_ FORALLCLASSESMT( DISPATCH2NULLDECL_, )*/
147 #define MAKE_TYPEID( T ) TYPEID_ ## T ,
148 enum QuickTypeID
149 { SINGLELOOP1( CLASSTREE1_ROOT, MAKE_TYPEID )
150 NUMBER_OF_TYPEID };
152 class Value
154 public:
155 virtual QuickTypeID getTypeID( ) const = 0;
156 DISPATCHNULLDECL;
159 DISPATCHCASEIMPL;
162 BinOp::call( RefCountPtr< const Value > v1, RefCountPtr< const Value > v2 ) const
164 return v1->dispatch1( v1, v2, this );
167 #define DISPATCH1DECL_ virtual int dispatch1( RefCountPtr< const Value > self, RefCountPtr< const Value > other, const BinOp * op ) const;
168 #define DISPATCH1IMPL_( Ts ) \
169 int Ts::dispatch1( RefCountPtr< const Value > self, RefCountPtr< const Value > other, const BinOp * op ) const \
171 RefCountPtr< const Ts > typedSelf = self.down_cast< const Ts >( ); \
172 if( typedSelf == NullPtr< const Ts >( ) ) \
174 cerr << "Downcast in dispatch1 failed" << endl ;\
176 return other->dispatch2( typedSelf, other, op );\
179 #define DISPATCH2DECL_( Ts, To ) virtual int dispatch2( RefCountPtr< const To > other, RefCountPtr< const Value > self, const BinOp * op ) const;
180 #define DISPATCH2IMPL_( Ts, To ) \
181 int Ts::dispatch2( RefCountPtr< const To > other, RefCountPtr< const Value > self, const BinOp * op ) const\
183 RefCountPtr< const Ts > typedSelf = self.down_cast< const Ts >( ); \
184 if( typedSelf == NullPtr< const Ts >( ) ) \
186 cerr << "Downcast in dispatch1 failed" << endl ;\
188 return op->op( other, typedSelf );\
191 #define GETTYPEIDDECL virtual QuickTypeID getTypeID( ) const;
193 #define DISPATCHDECL GETTYPEIDDECL
194 /* DISPATCH1DECL_ FORALLCLASSESMT( DISPATCH2DECL_, )*/
195 #define DISPATCHIMPL( Ts )
196 /* DISPATCH1IMPL_( Ts ) FORALLCLASSESMT( DISPATCH2IMPL_, Ts )*/
198 class A : public Value
200 public:
201 DISPATCHDECL;
204 class B : public Value
206 public:
207 DISPATCHDECL;
210 class C : public B
212 public:
213 DISPATCHDECL;
216 DISPATCHIMPL( A );
217 DISPATCHIMPL( B );
218 DISPATCHIMPL( C );
220 #define DUMMYANDREF( T ) T *, RefCountPtr< T >
222 class Plus : public BinOp
224 public:
225 CALLIMPL( CLASSTREE1_B, CLASSTREE2_A )
226 private:
227 int impl( DUMMYANDREF( const B ) v1, DUMMYANDREF( const A ) v2 ) const { return 1; }
228 int impl( DUMMYANDREF( const C ) v1, DUMMYANDREF( const A ) v2 ) const { return 2; }
231 class Star : public BinOp
233 public:
234 CALLIMPL( CLASSTREE1_B, CLASSTREE2_B )
235 CALLIMPL( CLASSTREE1_A, CLASSTREE2_B )
236 private:
237 int impl( DUMMYANDREF( const B ) v1, DUMMYANDREF( const B ) v2 ) const { return 1; }
238 int impl( DUMMYANDREF( const A ) v1, DUMMYANDREF( const B ) v2 ) const { return 7; }
241 #define GETTYPEID_MAKER( T ) \
242 QuickTypeID \
243 T::getTypeID( ) const \
245 return TYPEID_ ## T; \
248 SINGLELOOP1( CLASSTREE1_ROOT, GETTYPEID_MAKER )
251 main( )
253 RefCountPtr< A > a;
254 RefCountPtr< B > b;
255 RefCountPtr< C > c;
257 Plus op;
258 const char opstr[] = "+";
259 cout << "A" << opstr << "A => " << op.call( a, a ) << endl ;
260 cout << "A" << opstr << "B => " << op.call( a, b ) << endl ;
261 cout << "A" << opstr << "C => " << op.call( a, c ) << endl ;
262 cout << "B" << opstr << "A => " << op.call( b, a ) << endl ;
263 cout << "B" << opstr << "B => " << op.call( b, b ) << endl ;
264 cout << "B" << opstr << "C => " << op.call( b, c ) << endl ;
265 cout << "C" << opstr << "A => " << op.call( c, a ) << endl ;
266 cout << "C" << opstr << "B => " << op.call( c, b ) << endl ;
267 cout << "C" << opstr << "C => " << op.call( c, c ) << endl ;
269 cout << endl ;
271 Star op;
272 const char opstr[] = "*";
273 cout << "A" << opstr << "A => " << op.call( a, a ) << endl ;
274 cout << "A" << opstr << "B => " << op.call( a, b ) << endl ;
275 cout << "A" << opstr << "C => " << op.call( a, c ) << endl ;
276 cout << "B" << opstr << "A => " << op.call( b, a ) << endl ;
277 cout << "B" << opstr << "B => " << op.call( b, b ) << endl ;
278 cout << "B" << opstr << "C => " << op.call( b, c ) << endl ;
279 cout << "C" << opstr << "A => " << op.call( c, a ) << endl ;
280 cout << "C" << opstr << "B => " << op.call( c, b ) << endl ;
281 cout << "C" << opstr << "C => " << op.call( c, c ) << endl ;
283 return 0;