source: src/GenPoly/GenPoly.cc @ fbb930e

ADTast-experimentalpthread-emulation
Last change on this file since fbb930e was c19edd1, checked in by Thierry Delisle <tdelisle@…>, 2 years ago

Removed some warnings and fixed some whitespace

  • Property mode set to 100644
File size: 23.6 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// GenPoly.cc --
8//
9// Author           : Richard C. Bilson
10// Created On       : Mon May 18 07:44:20 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Wed Jun 29 21:45:53 2016
13// Update Count     : 14
14//
15
16#include "GenPoly.h"
17
18#include <cassert>                      // for assertf, assert
19#include <iostream>                     // for operator<<, ostream, basic_os...
20#include <iterator>                     // for back_insert_iterator, back_in...
21#include <list>                         // for list, _List_iterator, list<>:...
22#include <typeindex>                    // for type_index
23#include <utility>                      // for pair
24#include <vector>                       // for vector
25
26#include "AST/Type.hpp"
27#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
28#include "ResolvExpr/typeops.h"         // for flatten
29#include "SynTree/Constant.h"           // for Constant
30#include "SynTree/Expression.h"         // for Expression, TypeExpr, Constan...
31#include "SynTree/Type.h"               // for Type, StructInstType, UnionIn...
32#include "SynTree/TypeSubstitution.h"   // for TypeSubstitution
33
34using namespace std;
35
36namespace GenPoly {
37        namespace {
38                /// Checks a parameter list for polymorphic parameters; will substitute according to env if present
39                bool hasPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {
40                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
41                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
42                                assertf(paramType, "Aggregate parameters should be type expressions");
43                                if ( isPolyType( paramType->get_type(), env ) ) return true;
44                        }
45                        return false;
46                }
47
48                bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const ast::TypeSubstitution * env) {
49                        for (auto &param : params) {
50                                auto paramType = param.strict_as<ast::TypeExpr>();
51                                if (isPolyType(paramType->type, env)) return true;
52                        }
53                        return false;
54                }
55
56                /// Checks a parameter list for polymorphic parameters from tyVars; will substitute according to env if present
57                bool hasPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
58                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
59                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
60                                assertf(paramType, "Aggregate parameters should be type expressions");
61                                if ( isPolyType( paramType->get_type(), tyVars, env ) ) return true;
62                        }
63                        return false;
64                }
65
66                __attribute__((unused))
67                bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const TyVarMap & tyVars, const ast::TypeSubstitution * env) {
68                        for (auto &param : params) {
69                                auto paramType = param.strict_as<ast::TypeExpr>();
70                                if (isPolyType(paramType->type, tyVars, env)) return true;
71                        }
72                        return false;
73                }
74
75                /// Checks a parameter list for dynamic-layout parameters from tyVars; will substitute according to env if present
76                bool hasDynParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
77                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
78                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
79                                assertf(paramType, "Aggregate parameters should be type expressions");
80                                if ( isDynType( paramType->get_type(), tyVars, env ) ) return true;
81                        }
82                        return false;
83                }
84
85                /// Checks a parameter list for inclusion of polymorphic parameters; will substitute according to env if present
86                bool includesPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {
87                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
88                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
89                                assertf(paramType, "Aggregate parameters should be type expressions");
90                                if ( includesPolyType( paramType->get_type(), env ) ) return true;
91                        }
92                        return false;
93                }
94
95                /// Checks a parameter list for inclusion of polymorphic parameters from tyVars; will substitute according to env if present
96                bool includesPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
97                        for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
98                                TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
99                                assertf(paramType, "Aggregate parameters should be type expressions");
100                                if ( includesPolyType( paramType->get_type(), tyVars, env ) ) return true;
101                        }
102                        return false;
103                }
104        }
105
106        Type* replaceTypeInst( Type* type, const TypeSubstitution* env ) {
107                if ( ! env ) return type;
108                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
109                        Type *newType = env->lookup( typeInst->get_name() );
110                        if ( newType ) return newType;
111                }
112                return type;
113        }
114
115        const ast::Type * replaceTypeInst(const ast::Type * type, const ast::TypeSubstitution * env) {
116                if (!env) return type;
117                if (auto typeInst = dynamic_cast<const ast::TypeInstType*> (type)) {
118                        auto newType = env->lookup(typeInst);
119                        if (newType) return newType;
120                }
121                return type;
122        }
123
124        Type *isPolyType( Type *type, const TypeSubstitution *env ) {
125                type = replaceTypeInst( type, env );
126
127                if ( dynamic_cast< TypeInstType * >( type ) ) {
128                        return type;
129                } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
130                        return isPolyType( arrayType->base, env );
131                } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
132                        if ( hasPolyParams( structType->get_parameters(), env ) ) return type;
133                } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
134                        if ( hasPolyParams( unionType->get_parameters(), env ) ) return type;
135                }
136                return 0;
137        }
138
139        const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env) {
140                type = replaceTypeInst( type, env );
141
142                if ( dynamic_cast< const ast::TypeInstType * >( type ) ) {
143                        return type;
144                } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
145                        return isPolyType( arrayType->base, env );
146                } else if ( auto structType = dynamic_cast< const ast::StructInstType* >( type ) ) {
147                        if ( hasPolyParams( structType->params, env ) ) return type;
148                } else if ( auto unionType = dynamic_cast< const ast::UnionInstType* >( type ) ) {
149                        if ( hasPolyParams( unionType->params, env ) ) return type;
150                }
151                return 0;
152        }
153
154        Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
155                type = replaceTypeInst( type, env );
156
157                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
158                        if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) {
159                                return type;
160                        }
161                } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
162                        return isPolyType( arrayType->base, tyVars, env );
163                } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
164                        if ( hasPolyParams( structType->get_parameters(), tyVars, env ) ) return type;
165                } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
166                        if ( hasPolyParams( unionType->get_parameters(), tyVars, env ) ) return type;
167                }
168                return 0;
169        }
170
171        const ast::Type * isPolyType(const ast::Type * type, const TyVarMap & tyVars, const ast::TypeSubstitution * env) {
172                type = replaceTypeInst( type, env );
173
174                if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
175                        return tyVars.find(typeInst->typeString()) != tyVars.end() ? type : nullptr;
176                } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) {
177                        return isPolyType( arrayType->base, env );
178                } else if ( auto structType = dynamic_cast< const ast::StructInstType* >( type ) ) {
179                        if ( hasPolyParams( structType->params, env ) ) return type;
180                } else if ( auto unionType = dynamic_cast< const ast::UnionInstType* >( type ) ) {
181                        if ( hasPolyParams( unionType->params, env ) ) return type;
182                }
183                return nullptr;
184        }
185
186        ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
187                type = replaceTypeInst( type, env );
188
189                if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
190                        auto var = tyVars.find( typeInst->get_name() );
191                        if ( var != tyVars.end() && var->second.isComplete ) {
192                                return typeInst;
193                        }
194                } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
195                        if ( hasDynParams( structType->get_parameters(), tyVars, env ) ) return structType;
196                } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
197                        if ( hasDynParams( unionType->get_parameters(), tyVars, env ) ) return unionType;
198                }
199                return 0;
200        }
201
202        ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &forallTypes ) {
203                if ( function->get_returnVals().empty() ) return 0;
204
205                return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
206        }
207
208        ReferenceToType *isDynRet( FunctionType *function ) {
209                if ( function->get_returnVals().empty() ) return 0;
210
211                TyVarMap forallTypes( TypeDecl::Data{} );
212                makeTyVarMap( function, forallTypes );
213                return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
214        }
215
216        bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) {
217//              if ( ! adaptee->get_returnVals().empty() && isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
218//                      return true;
219//              } // if
220                if ( isDynRet( adaptee, tyVars ) ) return true;
221
222                for ( std::list< DeclarationWithType* >::const_iterator innerArg = adaptee->get_parameters().begin(); innerArg != adaptee->get_parameters().end(); ++innerArg ) {
223//                      if ( isPolyType( (*innerArg)->get_type(), tyVars ) ) {
224                        if ( isDynType( (*innerArg)->get_type(), tyVars ) ) {
225                                return true;
226                        } // if
227                } // for
228                return false;
229        }
230
231        Type *isPolyPtr( Type *type, const TypeSubstitution *env ) {
232                type = replaceTypeInst( type, env );
233
234                if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
235                        return isPolyType( ptr->get_base(), env );
236                }
237                return 0;
238        }
239
240        Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
241                type = replaceTypeInst( type, env );
242
243                if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
244                        return isPolyType( ptr->get_base(), tyVars, env );
245                }
246                return 0;
247        }
248
249        Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) {
250                int dummy;
251                if ( ! levels ) { levels = &dummy; }
252                *levels = 0;
253
254                while ( true ) {
255                        type = replaceTypeInst( type, env );
256
257                        if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
258                                type = ptr->get_base();
259                                ++(*levels);
260                        } else break;
261                }
262
263                return isPolyType( type, env );
264        }
265
266        Type * hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels, const TypeSubstitution *env ) {
267                int dummy;
268                if ( ! levels ) { levels = &dummy; }
269                *levels = 0;
270
271                while ( true ) {
272                        type = replaceTypeInst( type, env );
273
274                        if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
275                                type = ptr->get_base();
276                                ++(*levels);
277                        } else break;
278                }
279
280                return isPolyType( type, tyVars, env );
281        }
282
283        bool includesPolyType( Type *type, const TypeSubstitution *env ) {
284                type = replaceTypeInst( type, env );
285
286                if ( dynamic_cast< TypeInstType * >( type ) ) {
287                        return true;
288                } else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) {
289                        if ( includesPolyType( pointerType->get_base(), env ) ) return true;
290                } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
291                        if ( includesPolyParams( structType->get_parameters(), env ) ) return true;
292                } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
293                        if ( includesPolyParams( unionType->get_parameters(), env ) ) return true;
294                }
295                return false;
296        }
297
298        bool includesPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
299                type = replaceTypeInst( type, env );
300
301                if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) {
302                        if ( tyVars.find( typeInstType->get_name() ) != tyVars.end() ) {
303                                return true;
304                        }
305                } else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) {
306                        if ( includesPolyType( pointerType->get_base(), tyVars, env ) ) return true;
307                } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
308                        if ( includesPolyParams( structType->get_parameters(), tyVars, env ) ) return true;
309                } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
310                        if ( includesPolyParams( unionType->get_parameters(), tyVars, env ) ) return true;
311                }
312                return false;
313        }
314
315        FunctionType * getFunctionType( Type *ty ) {
316                PointerType *ptrType;
317                if ( ( ptrType = dynamic_cast< PointerType* >( ty ) ) ) {
318                        return dynamic_cast< FunctionType* >( ptrType->get_base() ); // pointer if FunctionType, NULL otherwise
319                } else {
320                        return dynamic_cast< FunctionType* >( ty ); // pointer if FunctionType, NULL otherwise
321                }
322        }
323
324        const ast::FunctionType * getFunctionType( const ast::Type * ty ) {
325                if ( auto pty = dynamic_cast< const ast::PointerType * >( ty ) ) {
326                        return pty->base.as< ast::FunctionType >();
327                } else {
328                        return dynamic_cast< const ast::FunctionType * >( ty );
329                }
330        }
331
332        VariableExpr * getBaseVar( Expression *expr, int *levels ) {
333                int dummy;
334                if ( ! levels ) { levels = &dummy; }
335                *levels = 0;
336
337                while ( true ) {
338                        if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( expr ) ) {
339                                return varExpr;
340                        } else if ( MemberExpr *memberExpr = dynamic_cast< MemberExpr* >( expr ) ) {
341                                expr = memberExpr->get_aggregate();
342                        } else if ( AddressExpr *addressExpr = dynamic_cast< AddressExpr* >( expr ) ) {
343                                expr = addressExpr->get_arg();
344                        } else if ( UntypedExpr *untypedExpr = dynamic_cast< UntypedExpr* >( expr ) ) {
345                                // look for compiler-inserted dereference operator
346                                NameExpr *fn = dynamic_cast< NameExpr* >( untypedExpr->get_function() );
347                                if ( ! fn || fn->get_name() != std::string("*?") ) return 0;
348                                expr = *untypedExpr->begin_args();
349                        } else if ( CommaExpr *commaExpr = dynamic_cast< CommaExpr* >( expr ) ) {
350                                // copy constructors insert comma exprs, look at second argument which contains the variable
351                                expr = commaExpr->get_arg2();
352                                continue;
353                        } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( expr ) ) {
354                                int lvl1;
355                                int lvl2;
356                                VariableExpr * var1 = getBaseVar( condExpr->get_arg2(), &lvl1 );
357                                VariableExpr * var2 = getBaseVar( condExpr->get_arg3(), &lvl2 );
358                                if ( lvl1 == lvl2 && var1 && var2 && var1->get_var() == var2->get_var() ) {
359                                        *levels = lvl1;
360                                        return var1;
361                                }
362                                break;
363                        } else break;
364
365                        ++(*levels);
366                }
367
368                return 0;
369        }
370
371        namespace {
372                /// Checks if is a pointer to D
373                template<typename D, typename B>
374                bool is( const B* p ) { return type_index{typeid(D)} == type_index{typeid(*p)}; }
375
376                /// Converts to a pointer to D without checking for safety
377                template<typename D, typename B>
378                inline D* as( B* p ) { return reinterpret_cast<D*>(p); }
379
380                /// Flattens a declaration list
381                template<typename Output>
382                void flattenList( list< DeclarationWithType* > src, Output out ) {
383                        for ( DeclarationWithType* decl : src ) {
384                                ResolvExpr::flatten( decl->get_type(), out );
385                        }
386                }
387
388                /// Flattens a list of types
389                template<typename Output>
390                void flattenList( list< Type* > src, Output out ) {
391                        for ( Type* ty : src ) {
392                                ResolvExpr::flatten( ty, out );
393                        }
394                }
395
396                /// Checks if two lists of parameters are equal up to polymorphic substitution.
397                bool paramListsPolyCompatible( const list< Expression* >& aparams, const list< Expression* >& bparams ) {
398                        if ( aparams.size() != bparams.size() ) return false;
399
400                        for ( list< Expression* >::const_iterator at = aparams.begin(), bt = bparams.begin();
401                                        at != aparams.end(); ++at, ++bt ) {
402                                TypeExpr *aparam = dynamic_cast< TypeExpr* >(*at);
403                                assertf(aparam, "Aggregate parameters should be type expressions");
404                                TypeExpr *bparam = dynamic_cast< TypeExpr* >(*bt);
405                                assertf(bparam, "Aggregate parameters should be type expressions");
406
407                                // xxx - might need to let VoidType be a wildcard here too; could have some voids
408                                // stuffed in for dtype-statics.
409                                // if ( is<VoidType>( aparam->get_type() ) || is<VoidType>( bparam->get_type() ) ) continue;
410                                if ( ! typesPolyCompatible( aparam->get_type(), bparam->get_type() ) ) return false;
411                        }
412
413                        return true;
414                }
415        }
416
417        bool typesPolyCompatible( Type *a, Type *b ) {
418                type_index aid{ typeid(*a) };
419                // polymorphic types always match
420                if ( aid == type_index{typeid(TypeInstType)} ) return true;
421
422                type_index bid{ typeid(*b) };
423                // polymorphic types always match
424                if ( bid == type_index{typeid(TypeInstType)} ) return true;
425
426                // can't match otherwise if different types
427                if ( aid != bid ) return false;
428
429                // recurse through type structure (conditions borrowed from Unify.cc)
430                if ( aid == type_index{typeid(BasicType)} ) {
431                        return as<BasicType>(a)->get_kind() == as<BasicType>(b)->get_kind();
432                } else if ( aid == type_index{typeid(PointerType)} ) {
433                        PointerType *ap = as<PointerType>(a), *bp = as<PointerType>(b);
434
435                        // void pointers should match any other pointer type
436                        return is<VoidType>( ap->get_base() ) || is<VoidType>( bp->get_base() )
437                                || typesPolyCompatible( ap->get_base(), bp->get_base() );
438                } else if ( aid == type_index{typeid(ReferenceType)} ) {
439                        ReferenceType *ap = as<ReferenceType>(a), *bp = as<ReferenceType>(b);
440                        return is<VoidType>( ap->get_base() ) || is<VoidType>( bp->get_base() )
441                                || typesPolyCompatible( ap->get_base(), bp->get_base() );
442                } else if ( aid == type_index{typeid(ArrayType)} ) {
443                        ArrayType *aa = as<ArrayType>(a), *ba = as<ArrayType>(b);
444
445                        if ( aa->get_isVarLen() ) {
446                                if ( ! ba->get_isVarLen() ) return false;
447                        } else {
448                                if ( ba->get_isVarLen() ) return false;
449
450                                ConstantExpr *ad = dynamic_cast<ConstantExpr*>( aa->get_dimension() );
451                                ConstantExpr *bd = dynamic_cast<ConstantExpr*>( ba->get_dimension() );
452                                if ( ad && bd
453                                                && ad->get_constant()->get_value() != bd->get_constant()->get_value() )
454                                        return false;
455                        }
456
457                        return typesPolyCompatible( aa->get_base(), ba->get_base() );
458                } else if ( aid == type_index{typeid(FunctionType)} ) {
459                        FunctionType *af = as<FunctionType>(a), *bf = as<FunctionType>(b);
460
461                        vector<Type*> aparams, bparams;
462                        flattenList( af->get_parameters(), back_inserter( aparams ) );
463                        flattenList( bf->get_parameters(), back_inserter( bparams ) );
464                        if ( aparams.size() != bparams.size() ) return false;
465
466                        vector<Type*> areturns, breturns;
467                        flattenList( af->get_returnVals(), back_inserter( areturns ) );
468                        flattenList( bf->get_returnVals(), back_inserter( breturns ) );
469                        if ( areturns.size() != breturns.size() ) return false;
470
471                        for ( unsigned i = 0; i < aparams.size(); ++i ) {
472                                if ( ! typesPolyCompatible( aparams[i], bparams[i] ) ) return false;
473                        }
474                        for ( unsigned i = 0; i < areturns.size(); ++i ) {
475                                if ( ! typesPolyCompatible( areturns[i], breturns[i] ) ) return false;
476                        }
477                        return true;
478                } else if ( aid == type_index{typeid(StructInstType)} ) {
479                        StructInstType *aa = as<StructInstType>(a), *ba = as<StructInstType>(b);
480
481                        if ( aa->get_name() != ba->get_name() ) return false;
482                        return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() );
483                } else if ( aid == type_index{typeid(UnionInstType)} ) {
484                        UnionInstType *aa = as<UnionInstType>(a), *ba = as<UnionInstType>(b);
485
486                        if ( aa->get_name() != ba->get_name() ) return false;
487                        return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() );
488                } else if ( aid == type_index{typeid(EnumInstType)} ) {
489                        return as<EnumInstType>(a)->get_name() == as<EnumInstType>(b)->get_name();
490                } else if ( aid == type_index{typeid(TraitInstType)} ) {
491                        return as<TraitInstType>(a)->get_name() == as<TraitInstType>(b)->get_name();
492                } else if ( aid == type_index{typeid(TupleType)} ) {
493                        TupleType *at = as<TupleType>(a), *bt = as<TupleType>(b);
494
495                        vector<Type*> atypes, btypes;
496                        flattenList( at->get_types(), back_inserter( atypes ) );
497                        flattenList( bt->get_types(), back_inserter( btypes ) );
498                        if ( atypes.size() != btypes.size() ) return false;
499
500                        for ( unsigned i = 0; i < atypes.size(); ++i ) {
501                                if ( ! typesPolyCompatible( atypes[i], btypes[i] ) ) return false;
502                        }
503                        return true;
504                } else return true; // VoidType, VarArgsType, ZeroType & OneType just need the same type
505        }
506
507        namespace {
508                // temporary hack to avoid re-implementing anything related to TyVarMap
509                // does this work? these two structs have identical definitions.
510                inline TypeDecl::Data convData(const ast::TypeDecl::Data & data) {
511                        return *reinterpret_cast<const TypeDecl::Data *>(&data);
512                }
513        }
514
515        bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) {
516                // is parameter is not polymorphic, don't need to box
517                if ( ! isPolyType( param, exprTyVars ) ) return false;
518                Type * newType = arg->clone();
519                if ( env ) env->apply( newType );
520                std::unique_ptr<Type> manager( newType );
521                // if the argument's type is polymorphic, we don't need to box again!
522                return ! isPolyType( newType );
523        }
524
525        bool needsBoxing( const ast::Type * param, const ast::Type * arg, const TyVarMap &exprTyVars, const ast::TypeSubstitution * env) {
526                // is parameter is not polymorphic, don't need to box
527                if ( ! isPolyType( param, exprTyVars ) ) return false;
528                ast::ptr<ast::Type> newType = arg;
529                if ( env ) env->apply( newType );
530                // if the argument's type is polymorphic, we don't need to box again!
531                return ! isPolyType( newType );
532        }
533
534        bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) {
535                FunctionType * function = getFunctionType( appExpr->function->result );
536                assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
537                TyVarMap exprTyVars( TypeDecl::Data{} );
538                makeTyVarMap( function, exprTyVars );
539                return needsBoxing( param, arg, exprTyVars, env );
540        }
541
542        bool needsBoxing( const ast::Type * param, const ast::Type * arg, const ast::ApplicationExpr * appExpr, const ast::TypeSubstitution * env) {
543                const ast::FunctionType * function = getFunctionType(appExpr->func->result);
544                assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->func->result ).c_str() );
545                TyVarMap exprTyVars(TypeDecl::Data{});
546                makeTyVarMap(function, exprTyVars);
547                return needsBoxing(param, arg, exprTyVars, env);
548
549        }
550
551        void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
552                tyVarMap.insert( tyVar->name, TypeDecl::Data{ tyVar } );
553        }
554
555        void addToTyVarMap( const ast::TypeInstType * tyVar, TyVarMap & tyVarMap) {
556                tyVarMap.insert(tyVar->typeString(), convData(ast::TypeDecl::Data{tyVar->base}));
557        }
558
559        void makeTyVarMap( Type *type, TyVarMap &tyVarMap ) {
560                for ( Type::ForallList::const_iterator tyVar = type->get_forall().begin(); tyVar != type->get_forall().end(); ++tyVar ) {
561                        assert( *tyVar );
562                        addToTyVarMap( *tyVar, tyVarMap );
563                }
564                if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) {
565                        makeTyVarMap( pointer->get_base(), tyVarMap );
566                }
567        }
568
569        void makeTyVarMap(const ast::Type * type, TyVarMap & tyVarMap) {
570                if (auto ptype = dynamic_cast<const ast::FunctionType *>(type)) {
571                        for (auto & tyVar : ptype->forall) {
572                                assert (tyVar);
573                                addToTyVarMap(tyVar, tyVarMap);
574                        }
575                }
576                if (auto pointer = dynamic_cast<const ast::PointerType *>(type)) {
577                        makeTyVarMap(pointer->base, tyVarMap);
578                }
579        }
580
581        void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {
582                for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {
583                        os << i->first << " (" << i->second << ") ";
584                } // for
585                os << std::endl;
586        }
587
588} // namespace GenPoly
589
590// Local Variables: //
591// tab-width: 4 //
592// mode: c++ //
593// compile-command: "make install" //
594// End: //
Note: See TracBrowser for help on using the repository browser.