source: src/GenPoly/GenPoly.cc@ 0fba0d4

ADT ast-experimental enum forall-pointer-decay pthread-emulation qualifiedEnum
Last change on this file since 0fba0d4 was 943bfad, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Fixed several warnings for clang@head

  • 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__((ununsed))
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.