Update procedures
[shapes.git] / source / opdispatchtest.cc
blobd670a10f316945fa1434668cd526084390bb8bb4
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 CLASSTREE_A_1( Ma, S, Mb ) Ma( S, Mb, A )
37 #define CLASSTREE_B_1( Ma, S, Mb ) Ma( S, Mb, B ) CLASSTREE_C_1( Ma, S, Mb )
38 #define CLASSTREE_C_1( Ma, S, Mb ) Ma( S, Mb, C )
39 #define FORALLCLASSES1( Ma, S, Mb ) \
40 CLASSTREE_A_1( Ma, S, Mb )\
41 CLASSTREE_B_1( Ma, S, Mb )
43 #define CLASSTREE_A_2( Ma, S, Mb ) Ma( S, Mb, A )
44 #define CLASSTREE_B_2( Ma, S, Mb ) Ma( S, Mb, B ) CLASSTREE_C_2( Ma, S, Mb )
45 #define CLASSTREE_C_2( Ma, S, Mb ) Ma( S, Mb, C )
46 #define FORALLCLASSES2( Ma, S, Mb ) \
47 CLASSTREE_A_2( Ma, S, Mb )\
48 CLASSTREE_B_2( Ma, S, Mb )
51 /* Define convenient macros for looping.
53 #define SINGLELOOP1_( Sb, M, T ) M( T )
54 #define SINGLELOOP1( Sa, M ) Sa( SINGLELOOP1_,, M )
55 #define DOUBLELOOP1__( M, Ta, Tb ) M( Ta, Tb )
56 #define DOUBLELOOP1_( Sb, M, Ta ) Sb( DOUBLELOOP1__, M, Ta )
57 #define DOUBLELOOP1( Sa, Sb, M ) Sa( DOUBLELOOP1_, Sb, M )
59 #define SINGLELOOP2_( Sb, M, T ) M( T )
60 #define SINGLELOOP2( Sa, M ) Sa( SINGLELOOP2_,, M )
61 #define DOUBLELOOP2__( M, Ta, Tb ) M( Ta, Tb )
62 #define DOUBLELOOP2_( Sb, M, Ta ) Sb( DOUBLELOOP2__, M, Ta )
63 #define DOUBLELOOP2( Sa, Sb, M ) Sa( DOUBLELOOP2_, Sb, M )
65 /* Define a macro that only uses the first argument,
66 * resulting in a macro that calls another macro for each class.
68 #define FORALLCLASSESM( M ) SINGLELOOP1( FORALLCLASSES1, M )
70 /* Define a macro that calls another macro with a given first argument,
71 * varying the second argument over all classes.
73 #define FORALLCLASSESMT( M, T ) FORALLCLASSES2( DOUBLELOOP2__, M, T )
75 /* Use the two looping macros above in a nested manner to produce a default method
76 * for each pair combination of classes.
78 #define DEFAULTOP__( Ta, Tb ) virtual int op( RefCountPtr< const Ta > x1, RefCountPtr< const Tb > x2 ) const { return 0; }
79 #define DEFAULTOP_( Ta ) FORALLCLASSESMT( DEFAULTOP__, Ta )
80 #define DEFAULTOP FORALLCLASSESM( DEFAULTOP_ )
82 /* Define a macro for hiding the default method for a set of classes:
84 #define HIDEDEFAULT_( Ta, Tb ) virtual int op( Ta * v1, Tb * v2 ) const { return 0; }
85 #define HIDEDEFAULT( Sa, Sb ) DOUBLELOOP2( Sa, Sb, HIDEDEFAULT_ )
87 /* Define a macro for hiding the default method for a set of classes:
89 #define CALLIMPL_( Ta, Tb ) virtual int op( RefCountPtr< const Ta > x1, RefCountPtr< const Tb > x2 ) const { return impl( x1.getPtr( ), x1, x2.getPtr( ), x2 ); }
90 #define CALLIMPL( Sa, Sb ) DOUBLELOOP2( Sa, Sb, CALLIMPL_ )
92 class BinOp
94 public:
95 int call( RefCountPtr< const Value > v1, RefCountPtr< const Value > v2 ) const;
96 DEFAULTOP;
99 #define DISPATCH1NULLDECL_ virtual int dispatch1( RefCountPtr< const Value > self, RefCountPtr< const Value > other, const BinOp * op ) const = 0;
100 #define DISPATCH2NULLDECL_( Ts, To ) virtual int dispatch2( RefCountPtr< const To > other, RefCountPtr< const Value > self, const BinOp * op ) const = 0;
102 #define DISPATCHNULLDECL DISPATCH1NULLDECL_ FORALLCLASSESMT( DISPATCH2NULLDECL_, )
104 class Value
106 public:
107 DISPATCHNULLDECL;
111 BinOp::call( RefCountPtr< const Value > v1, RefCountPtr< const Value > v2 ) const
113 return v1->dispatch1( v1, v2, this );
116 #define DISPATCH1DECL_ virtual int dispatch1( RefCountPtr< const Value > self, RefCountPtr< const Value > other, const BinOp * op ) const;
117 #define DISPATCH1IMPL_( Ts ) \
118 int Ts::dispatch1( RefCountPtr< const Value > self, RefCountPtr< const Value > other, const BinOp * op ) const \
120 RefCountPtr< const Ts > typedSelf = self.down_cast< const Ts >( ); \
121 if( typedSelf == NullPtr< const Ts >( ) ) \
123 cerr << "Downcast in dispatch1 failed" << endl ;\
125 return other->dispatch2( typedSelf, other, op );\
128 #define DISPATCH2DECL_( Ts, To ) virtual int dispatch2( RefCountPtr< const To > other, RefCountPtr< const Value > self, const BinOp * op ) const;
129 #define DISPATCH2IMPL_( Ts, To ) \
130 int Ts::dispatch2( RefCountPtr< const To > other, RefCountPtr< const Value > self, const BinOp * op ) const\
132 RefCountPtr< const Ts > typedSelf = self.down_cast< const Ts >( ); \
133 if( typedSelf == NullPtr< const Ts >( ) ) \
135 cerr << "Downcast in dispatch1 failed" << endl ;\
137 return op->op( other, typedSelf );\
140 #define DISPATCHDECL DISPATCH1DECL_ FORALLCLASSESMT( DISPATCH2DECL_, )
141 #define DISPATCHIMPL( Ts ) DISPATCH1IMPL_( Ts ) FORALLCLASSESMT( DISPATCH2IMPL_, Ts )
143 class A : public Value
145 public:
146 DISPATCHDECL;
149 class B : public Value
151 public:
152 DISPATCHDECL;
155 class C : public B
157 public:
158 DISPATCHDECL;
161 DISPATCHIMPL( A );
162 DISPATCHIMPL( B );
163 DISPATCHIMPL( C );
165 #define DUMMYANDREF( T ) T *, RefCountPtr< T >
167 class Plus : public BinOp
169 public:
170 CALLIMPL( CLASSTREE_B_1, CLASSTREE_A_2 )
171 private:
172 int impl( DUMMYANDREF( const B ) v1, DUMMYANDREF( const A ) v2 ) const { return 1; }
173 int impl( DUMMYANDREF( const C ) v1, DUMMYANDREF( const A ) v2 ) const { return 2; }
176 class Star : public BinOp
178 public:
179 CALLIMPL( CLASSTREE_B_1, CLASSTREE_B_2 )
180 private:
181 int impl( DUMMYANDREF( const B ) v1, DUMMYANDREF( const B ) v2 ) const { return 1; }
182 int impl( DUMMYANDREF( const A ) v1, DUMMYANDREF( const B ) v2 ) const { return 7; }
188 dispatch( Value * v1, Value * v2, const BinOp * op )
195 main( )
197 RefCountPtr< A > a;
198 RefCountPtr< B > b;
199 RefCountPtr< C > c;
201 Plus op;
202 const char opstr[] = "+";
203 cout << "A" << opstr << "A => " << op.call( a, a ) << endl ;
204 cout << "A" << opstr << "B => " << op.call( a, b ) << endl ;
205 cout << "A" << opstr << "C => " << op.call( a, c ) << endl ;
206 cout << "B" << opstr << "A => " << op.call( b, a ) << endl ;
207 cout << "B" << opstr << "B => " << op.call( b, b ) << endl ;
208 cout << "B" << opstr << "C => " << op.call( b, c ) << endl ;
209 cout << "C" << opstr << "A => " << op.call( c, a ) << endl ;
210 cout << "C" << opstr << "B => " << op.call( c, b ) << endl ;
211 cout << "C" << opstr << "C => " << op.call( c, c ) << endl ;
213 cout << endl ;
215 Star op;
216 const char opstr[] = "*";
217 cout << "A" << opstr << "A => " << op.call( a, a ) << endl ;
218 cout << "A" << opstr << "B => " << op.call( a, b ) << endl ;
219 cout << "A" << opstr << "C => " << op.call( a, c ) << endl ;
220 cout << "B" << opstr << "A => " << op.call( b, a ) << endl ;
221 cout << "B" << opstr << "B => " << op.call( b, b ) << endl ;
222 cout << "B" << opstr << "C => " << op.call( b, c ) << endl ;
223 cout << "C" << opstr << "A => " << op.call( c, a ) << endl ;
224 cout << "C" << opstr << "B => " << op.call( c, b ) << endl ;
225 cout << "C" << opstr << "C => " << op.call( c, c ) << endl ;
227 return 0;