// // Copyright (c) 2002 by Stephen C. Dewhurst // Permission to use, copy, modify, distribute and sell this software for any purpose is // hereby granted without fee, provided that the above copyright notice appears in all copies // and that both that copyright notice and this permission notice appear in supporting documentation. // The author or makes no representations about the suitability of this software for any purpose. // It is provided "as is" without express or implied warranty. // // "typeof" operator implementation // // Described in CUJ 20(8, 10, and 12), August, October, and December 2002: "A Bit-Wise Typeof" // #ifndef GENGN_H #define GENGN_H #include "multishift.h" #include "utils.h" // // Godel numbering approximation // const Code BaseLen = 6; const Code BaseMax = (1< struct TypeCode; template struct DeCode; // Special handling for void, due to inability to declare void &. Int2Int typeCode( void ); template <> struct TypeCode { enum { value = VoidVal }; }; template <> struct DeCode { typedef void R; }; #define REGISTER( T, N )\ Int2Int\ typeCode(T &);\ template <>\ struct TypeCode {\ enum { value = N };\ };\ template <>\ struct DeCode {\ typedef T R;\ } // Pre-registration of built-in types. // Users are responsible for registering user-defined types. REGISTER( bool, BoolVal ); REGISTER( char, CharVal ); REGISTER( unsigned char, UCharVal ); REGISTER( signed char, SCharVal ); REGISTER( short, ShortVal ); REGISTER( unsigned short, UShortVal ); REGISTER( int, IntVal ); REGISTER( unsigned int, UIntVal ); REGISTER( long, LongVal ); REGISTER( unsigned long, ULongVal ); REGISTER( float, FloatVal ); REGISTER( double, DoubleVal ); REGISTER( long double, LDoubleVal ); template struct BaseType { typedef typename DeQual::R S; enum { base = TypeCode::value, code = base | (IsConst::result << ConstBasePos) | (IsVol::result << VolBasePos), len = QualBaseLen }; GODEL_NUMBER_LENGTH_CHECK(len); }; template struct GN { enum { code4 = 0, code3 = 0, code2 = 0, code1 = BaseType::code, len = BaseType::len }; GODEL_NUMBER_LENGTH_CHECK(len); }; template struct GN { typedef GN GNT; enum { c1 = GNT::code1, c2 = GNT::code2, c3 = GNT::code3, c4 = GNT::code4 }; typedef ShiftLeft SL; enum { code4 = SL::code4, code3 = SL::code3, code2 = SL::code2, code1 = SL::code1 | Ptr, len = GNT::len+ModLen }; GODEL_NUMBER_LENGTH_CHECK(len); }; template struct GN { typedef GN GNTS; enum { code4 = GNTS::code4, code3 = GNTS::code3, code2 = GNTS::code2, code1 = GNTS::code1 | Const, len = GNTS::len }; }; template struct GN { typedef GN GNTS; enum { code4 = GNTS::code4, code3 = GNTS::code3, code2 = GNTS::code2, code1 = GNTS::code1 | Vol, len = GNTS::len }; }; template struct GN { typedef GN GNTS; enum { code4 = GNTS::code4, code3 = GNTS::code3, code2 = GNTS::code2, code1 = GNTS::code1 | Const+Vol, len = GNTS::len }; }; template struct GN { typedef GN GNT; enum { c1 = GNT::code1, c2 = GNT::code2, c3 = GNT::code3, c4 = GNT::code4 }; typedef ShiftLeft SL; enum { code4 = SL::code4, code3 = SL::code3, code2 = SL::code2, code1 = SL::code1 | Ref, len = GNT::len+ModLen }; GODEL_NUMBER_LENGTH_CHECK(len); }; template struct GN { typedef GN GNT; enum { c1 = GNT::code1, c2 = GNT::code2, c3 = GNT::code3, c4 = GNT::code4 }; typedef ShiftLeft SL; enum { code4 = SL::code4, code3 = SL::code3, code2 = SL::code2, code1 = SL::code1 | ((ArrayboundMask&N)< struct GN { typedef GN GNR; enum { c1 = GNR::code1, c2 = GNR::code2, c3 = GNR::code3, c4 = GNR::code4 }; typedef ShiftLeft SL; enum { code4 = SL::code4, code3 = SL::code3, code2 = SL::code2, code1 = SL::code1 | 0 | Fun, len = GNR::len+ArgcountLen+ModLen }; GODEL_NUMBER_LENGTH_CHECK(len); }; template struct GN { typedef R RetType; typedef A ArgType; typedef R FuncType( A ); typedef GN GNA; typedef GN GNR; enum { argshift = ArglenLen+ArgcountLen+ModLen, arglen = GNA::len, // get code for return type retshift = arglen+argshift, r1 = GNR::code1, r2 = GNR::code2, r3 = GNR::code3, r4 = GNR::code4, retlen = GNR::len, // get code for arg type a1 = GNA::code1, a2 = GNA::code2, a3 = GNA::code3, a4 = GNA::code4 }; typedef ShiftLeft SLA; typedef ShiftLeft SLR; enum { // shift arg type sa4 = SLA::code4, sa3 = SLA::code3, sa2 = SLA::code2, sa1 = SLA::code1, // shift return type sr4 = SLR::code4, sr3 = SLR::code3, sr2 = SLR::code2, sr1 = SLR::code1, // paste everything together code4 = sr4 | sa4, code3 = sr3 | sa3, code2 = sr2 | sa2, // note assumption below that ArgcountLen+Modlen < number of bits in Code! code1 = sr1 | sa1 | (arglen<<(ArgcountLen+ModLen)) | (1< struct GN { typedef GN GNT; enum { // Note class type is not qualified: BaseLen, not QualBaseLen, TypeCode, not GN or BaseType. c1 = GNT::code1, c2 = GNT::code2, c3 = GNT::code3, c4 = GNT::code4 }; typedef ShiftLeft SL; enum { code4 = SL::code4, code3 = SL::code3, code2 = SL::code2, code1 = SL::code1 | (TypeCode::value< struct GN { typedef GN GNTPM; enum { code4 = GNTPM::code4, code3 = GNTPM::code3, code2 = GNTPM::code2, code1 = GNTPM::code1 | Const, len = GNTPM::len }; }; template struct GN { typedef GN GNTPM; enum { code4 = GNTPM::code4, code3 = GNTPM::code3, code2 = GNTPM::code2, code1 = GNTPM::code1 | Vol, len = GNTPM::len }; }; template struct GN { typedef GN GNTPM; enum { code4 = GNTPM::code4, code3 = GNTPM::code3, code2 = GNTPM::code2, code1 = GNTPM::code1 | Const+Vol, len = GNTPM::len }; }; // Note that a member function is a very different beast from // a non-member function, so we have to special-case for them. // However, we can leverage much of our implementation of non-member // functions if we're careful. // Note also that (for pedegogic reasons?) we've taken a different tack // with the implementation of pointers to member functions. We're being // more "combinatorial" here, with different modifier codes for each number // of arguments and each cv-qualifer combination. This does cause // something of a "combinatorial explosion" when combined with the possible // cv-qualifiers of the pointer to member itself (4*4*(max_#_args+1)). // This can be improved by factoring the templates, which I'll get around to some day... // Laziness compelled me to permit only unqualified pointers to member // function below, though the member functions themselves may be qualified. template struct GN { typedef R M(); typedef GN GNM; enum { // Note class type is not qualified: BaseLen, not QualBaseLen, TypeCode, not GN or BaseType. c1 = GNM::code1, // could change this to memfun, add cv-quals c2 = GNM::code2, c3 = GNM::code3, c4 = GNM::code4 }; typedef ShiftLeft SL; enum { code4 = SL::code4, code3 = SL::code3, code2 = SL::code2, code1 = SL::code1 | (TypeCode::value< struct GN { typedef GN GNMF; enum { code4 = GNMF::code4, code3 = GNMF::code3, code2 = GNMF::code2, code1 = (GNMF::code1 ^ PcmFun0) | PcmFun0C, // replace existing modifier len = GNMF::len }; }; template struct GN { typedef GN GNMF; enum { code4 = GNMF::code4, code3 = GNMF::code3, code2 = GNMF::code2, code1 = (GNMF::code1 ^ PcmFun0) | PcmFun0V, len = GNMF::len }; }; template struct GN { typedef GN GNMF; enum { code4 = GNMF::code4, code3 = GNMF::code3, code2 = GNMF::code2, code1 = (GNMF::code1 ^ PcmFun0) | PcmFun0CV, len = GNMF::len }; }; template struct GN { typedef R Ret; typedef A Arg; typedef R M(A); typedef GN GNM; enum { // Note class type is not qualified: BaseLen, not QualBaseLen, TypeCode, not GN or BaseType. c1 = GNM::code1, c2 = GNM::code2, c3 = GNM::code3, c4 = GNM::code4 }; typedef ShiftLeft SL; enum { code4 = SL::code4, code3 = SL::code3, code2 = SL::code2, code1 = SL::code1 | (TypeCode::value< struct GN { typedef GN GNMF; enum { code4 = GNMF::code4, code3 = GNMF::code3, code2 = GNMF::code2, code1 = (GNMF::code1 ^ PcmFun1) | PcmFun1C, len = GNMF::len }; }; template struct GN { typedef GN GNMF; enum { code4 = GNMF::code4, code3 = GNMF::code3, code2 = GNMF::code2, code1 = (GNMF::code1 ^ PcmFun1) | PcmFun1V, len = GNMF::len }; }; template struct GN { typedef GN GNMF; enum { code4 = GNMF::code4, code3 = GNMF::code3, code2 = GNMF::code2, code1 = (GNMF::code1 ^ PcmFun1) | PcmFun1CV, len = GNMF::len }; }; char (*genGN1( void ))[GN::code1+1]; // no definition char (*genGN2( void ))[GN::code2+1]; char (*genGN3( void ))[GN::code3+1]; char (*genGN4( void ))[GN::code4+1]; template char (*genGN1( T & ))[GN::code1+1]; // no definition template char (*genGN2( T & ))[GN::code2+1]; template char (*genGN3( T & ))[GN::code3+1]; template char (*genGN4( T & ))[GN::code4+1]; #endif