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
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
21 #include "/home/rt/tidefelt/include/refcount.h"
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_ )
95 int call( RefCountPtr
< const Value
> v1
, RefCountPtr
< const Value
> v2
) const;
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_, )
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
149 class B
: public Value
165 #define DUMMYANDREF( T ) T *, RefCountPtr< T >
167 class Plus
: public BinOp
170 CALLIMPL( CLASSTREE_B_1
, CLASSTREE_A_2
)
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
179 CALLIMPL( CLASSTREE_B_1
, CLASSTREE_B_2
)
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 )
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
;
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
;