source: translator/ResolvExpr/Unify.cc @ a0d9f94

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsctordeferred_resndemanglerenumforall-pointer-decaygc_noraiijacob/cs343-translationjenkins-sandboxmemorynew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newstringwith_gc
Last change on this file since a0d9f94 was 51b7345, checked in by Peter A. Buhr <pabuhr@…>, 10 years ago

initial commit

  • Property mode set to 100644
File size: 19.9 KB
Line 
1/*
2 * This file is part of the Cforall project
3 *
4 * $Id: Unify.cc,v 1.14 2005/08/29 20:14:16 rcbilson Exp $
5 *
6 */
7
8#include <set>
9#include <memory>
10
11#include "Unify.h"
12#include "TypeEnvironment.h"
13#include "typeops.h"
14#include "FindOpenVars.h"
15#include "SynTree/Visitor.h"
16#include "SynTree/Type.h"
17#include "SynTree/Declaration.h"
18#include "SymTab/Indexer.h"
19#include "utility.h"
20
21
22//#define DEBUG
23
24namespace ResolvExpr {
25
26struct WidenMode
27{
28  WidenMode( bool widenFirst, bool widenSecond ): widenFirst( widenFirst ), widenSecond( widenSecond ) {}
29  WidenMode &operator|=( const WidenMode &other ) { widenFirst |= other.widenFirst; widenSecond |= other.widenSecond; return *this; }
30  WidenMode &operator&=( const WidenMode &other ) { widenFirst &= other.widenFirst; widenSecond &= other.widenSecond; return *this; }
31  WidenMode operator|( const WidenMode &other ) { WidenMode newWM( *this ); newWM |= other; return newWM; }
32  WidenMode operator&( const WidenMode &other ) { WidenMode newWM( *this ); newWM &= other; return newWM; }
33  operator bool() { return widenFirst && widenSecond; }
34 
35  bool widenFirst : 1, widenSecond : 1;
36};
37
38class Unify : public Visitor
39{
40public:
41  Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
42 
43  bool get_result() const { return result; }
44
45private:
46  virtual void visit(VoidType *voidType);
47  virtual void visit(BasicType *basicType);
48  virtual void visit(PointerType *pointerType);
49  virtual void visit(ArrayType *arrayType);
50  virtual void visit(FunctionType *functionType);
51  virtual void visit(StructInstType *aggregateUseType);
52  virtual void visit(UnionInstType *aggregateUseType);
53  virtual void visit(EnumInstType *aggregateUseType);
54  virtual void visit(ContextInstType *aggregateUseType);
55  virtual void visit(TypeInstType *aggregateUseType);
56  virtual void visit(TupleType *tupleType);
57
58  template< typename RefType > void handleRefType( RefType *inst, Type *other );
59
60  bool result;
61  Type *type2;                          // inherited
62  TypeEnvironment &env;
63  AssertionSet &needAssertions;
64  AssertionSet &haveAssertions;
65  const OpenVarSet &openVars;
66  WidenMode widenMode;
67  Type *commonType;
68  const SymTab::Indexer &indexer;
69};
70
71bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common );
72bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer );
73 
74bool
75typesCompatible( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env )
76{
77  TypeEnvironment newEnv;
78  OpenVarSet openVars;
79  AssertionSet needAssertions, haveAssertions;
80  Type *newFirst = first->clone(), *newSecond = second->clone();
81  env.apply( newFirst );
82  env.apply( newSecond );
83  bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
84  delete newFirst;
85  delete newSecond;
86  return result;
87}
88
89bool
90typesCompatibleIgnoreQualifiers( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env )
91{
92  TypeEnvironment newEnv;
93  OpenVarSet openVars;
94  AssertionSet needAssertions, haveAssertions;
95  Type *newFirst = first->clone(), *newSecond = second->clone();
96  env.apply( newFirst );
97  env.apply( newSecond );
98  newFirst->get_qualifiers() = Type::Qualifiers();
99  newSecond->get_qualifiers() = Type::Qualifiers();
100///   std::cout << "first is ";
101///   first->print( std::cout );
102///   std::cout << std::endl << "second is ";
103///   second->print( std::cout );
104///   std::cout << std::endl << "newFirst is ";
105///   newFirst->print( std::cout );
106///   std::cout << std::endl << "newSecond is ";
107///   newSecond->print( std::cout );
108///   std::cout << std::endl;
109  bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
110  delete newFirst;
111  delete newSecond;
112  return result;
113}
114
115bool
116isFtype( Type *type, const SymTab::Indexer &indexer )
117{
118  if( dynamic_cast< FunctionType* >( type ) ) {
119    return true;
120  } else if( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
121    return typeInst->get_isFtype();
122  }
123  return false;
124}
125
126bool
127tyVarCompatible( TypeDecl::Kind kind, Type *type, const SymTab::Indexer &indexer )
128{
129  switch( kind ) {
130  case TypeDecl::Any:
131  case TypeDecl::Dtype:
132    return !isFtype( type, indexer );
133 
134  case TypeDecl::Ftype:
135    return isFtype( type, indexer );
136  }
137  assert( false );
138  return false;
139}
140
141bool
142bindVar( TypeInstType *typeInst, Type *other, TypeDecl::Kind kind, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer )
143{
144  OpenVarSet::const_iterator tyvar = openVars.find( typeInst->get_name() );
145  assert( tyvar != openVars.end() );
146  if( !tyVarCompatible( tyvar->second, other, indexer ) ) {
147    return false;
148  }
149  if( occurs( other, typeInst->get_name(), env ) ) {
150    return false;
151  }
152  EqvClass curClass;
153  if( env.lookup( typeInst->get_name(), curClass ) ) {
154    if( curClass.type ) {
155      Type *common = 0;
156      std::auto_ptr< Type > newType( curClass.type->clone() );
157      if( unifyInexact( newType.get(), other, env, needAssertions, haveAssertions, openVars, widenMode & WidenMode( curClass.allowWidening, true ), indexer, common ) ) {
158        if( common ) {
159          common->get_qualifiers() = Type::Qualifiers();
160          delete curClass.type;
161          curClass.type = common;
162          env.add( curClass );
163        }
164        return true;
165      } else {
166        return false;
167      }
168    } else {
169      curClass.type = other->clone();
170      curClass.type->get_qualifiers() = Type::Qualifiers();
171      curClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
172      env.add( curClass );
173    }
174  } else {
175    EqvClass newClass;
176    newClass.vars.insert( typeInst->get_name() );
177    newClass.type = other->clone();
178    newClass.type->get_qualifiers() = Type::Qualifiers();
179    newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond;
180    newClass.kind = kind;
181    env.add( newClass );
182  }
183  return true;
184}
185
186bool
187bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Kind kind, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer )
188{
189  bool result = true;
190  EqvClass class1, class2;
191  bool hasClass1 = false, hasClass2 = false;
192  bool widen1 = false, widen2 = false;
193  Type *type1 = 0, *type2 = 0;
194 
195  if( env.lookup( var1->get_name(), class1 ) ) {
196    hasClass1 = true;
197    if( class1.type ) {
198      if( occurs( class1.type, var2->get_name(), env ) ) {
199        return false;
200      }
201      type1 = class1.type->clone();
202    }
203    widen1 = widenMode.widenFirst && class1.allowWidening;
204  }
205  if( env.lookup( var2->get_name(), class2 ) ) {
206    hasClass2 = true;
207    if( class2.type ) {
208      if( occurs( class2.type, var1->get_name(), env ) ) {
209        return false;
210      }
211      type2 = class2.type->clone();
212    }
213    widen2 = widenMode.widenSecond && class2.allowWidening;
214  }
215 
216  if( type1 && type2 ) {
217//    std::cout << "has type1 && type2" << std::endl;
218    WidenMode newWidenMode ( widen1, widen2 );
219    Type *common = 0;
220    if( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, newWidenMode, indexer, common ) ) {
221      class1.vars.insert( class2.vars.begin(), class2.vars.end() );
222      class1.allowWidening = widen1 && widen2;
223      if( common ) {
224        common->get_qualifiers() = Type::Qualifiers();
225        delete class1.type;
226        class1.type = common;
227      }
228      env.add( class1 );
229    } else {
230      result = false;
231    }
232  } else if( hasClass1 && hasClass2 ) {
233    if( type1 ) {
234      class1.vars.insert( class2.vars.begin(), class2.vars.end() );
235      class1.allowWidening = widen1;
236      env.add( class1 );
237    } else {
238      class2.vars.insert( class1.vars.begin(), class1.vars.end() );
239      class2.allowWidening = widen2;
240      env.add( class2 );
241    }
242  } else if( hasClass1 ) {
243    class1.vars.insert( var2->get_name() );
244    class1.allowWidening = widen1;
245    env.add( class1 );
246  } else if( hasClass2 ) {
247    class2.vars.insert( var1->get_name() );
248    class2.allowWidening = widen2;
249    env.add( class2 );
250  } else {
251    EqvClass newClass;
252    newClass.vars.insert( var1->get_name() );
253    newClass.vars.insert( var2->get_name() );
254    newClass.allowWidening = widen1 && widen2;
255    newClass.kind = kind;
256    env.add( newClass );
257  }
258  delete type1;
259  delete type2;
260  return result;
261}
262
263bool
264unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer )
265{
266  OpenVarSet closedVars;
267  findOpenVars( type1, openVars, closedVars, needAssertions, haveAssertions, false );
268  findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true );
269  Type *commonType = 0;
270  if( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) {
271    if( commonType ) {
272      delete commonType;
273    }
274    return true;
275  } else {
276    return false;
277  }
278}
279
280bool
281unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType )
282{
283  OpenVarSet closedVars;
284  findOpenVars( type1, openVars, closedVars, needAssertions, haveAssertions, false );
285  findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true );
286  return unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType );
287}
288
289bool
290unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer )
291{
292#ifdef DEBUG
293  TypeEnvironment debugEnv( env );
294#endif
295  bool result;
296  TypeInstType *var1 = dynamic_cast< TypeInstType* >( type1 );
297  TypeInstType *var2 = dynamic_cast< TypeInstType* >( type2 );
298  OpenVarSet::const_iterator entry1, entry2;
299  if( var1 ) {
300    entry1 = openVars.find( var1->get_name() );
301  }
302  if( var2 ) {
303    entry2 = openVars.find( var2->get_name() );
304  }
305  bool isopen1 = var1 && ( entry1 != openVars.end() );
306  bool isopen2 = var2 && ( entry2 != openVars.end() );
307  if( type1->get_qualifiers() != type2->get_qualifiers() ) {
308    return false;
309  } else if( isopen1 && isopen2 && entry1->second == entry2->second ) {
310    result = bindVarToVar( var1, var2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
311  } else if( isopen1 ) {
312    result = bindVar( var1, type2, entry1->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
313  } else if( isopen2 ) {
314    result = bindVar( var2, type1, entry2->second, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
315  } else {
316    Unify comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer );
317    type1->accept( comparator );
318    result = comparator.get_result();
319  }
320#ifdef DEBUG
321  std::cout << "============ unifyExact" << std::endl;
322  std::cout << "type1 is ";
323  type1->print( std::cout );
324  std::cout << std::endl << "type2 is ";
325  type2->print( std::cout );
326  std::cout << std::endl << "openVars are ";
327  printOpenVarSet( openVars, std::cout, 8 );
328  std::cout << std::endl << "input env is " << std::endl;
329  debugEnv.print( std::cout, 8 );
330  std::cout << std::endl << "result env is " << std::endl;
331  env.print( std::cout, 8 );
332  std::cout << "result is " << result << std::endl;
333#endif
334  return result;
335}
336
337bool
338unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer )
339{
340  return unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
341}
342
343bool
344unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common )
345{
346  Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers();
347  type1->get_qualifiers() = Type::Qualifiers();
348  type2->get_qualifiers() = Type::Qualifiers();
349  bool result;
350#ifdef DEBUG
351  std::cout << "unifyInexact type 1 is ";
352  type1->print( std::cout );
353  std::cout << "type 2 is ";
354  type2->print( std::cout );
355  std::cout << std::endl;
356#endif
357  if( !unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ) ) {
358#ifdef DEBUG
359    std::cout << "unifyInexact: no exact unification found" << std::endl;
360#endif
361    if( ( common = commonType( type1, type2, widenMode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) {
362      common->get_qualifiers() = tq1 + tq2;
363#ifdef DEBUG
364      std::cout << "unifyInexact: common type is ";
365      common->print( std::cout );
366      std::cout << std::endl;
367#endif
368      result = true;
369    } else {
370#ifdef DEBUG
371      std::cout << "unifyInexact: no common type found" << std::endl;
372#endif
373      result = false;
374    }
375  } else {
376    if( tq1 != tq2 ) {
377      if( ( tq1 > tq2 || widenMode.widenFirst ) && ( tq2 > tq1 || widenMode.widenSecond ) ) {
378        common = type1->clone();
379        common->get_qualifiers() = tq1 + tq2;
380        result = true;
381      } else {
382        result = false;
383      }
384    } else {
385      result = true;
386    }
387  }
388  type1->get_qualifiers() = tq1;
389  type2->get_qualifiers() = tq2;
390  return result;
391}
392
393Unify::Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer )
394  : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widenMode( widenMode ), indexer( indexer )
395{
396}
397
398void 
399Unify::visit(VoidType *voidType)
400{
401  result = dynamic_cast< VoidType* >( type2 );
402}
403
404void 
405Unify::visit(BasicType *basicType)
406{
407  if( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
408    result = basicType->get_kind() == otherBasic->get_kind();
409  }
410}
411
412void
413markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert )
414{
415///   std::cout << "assertion set is" << std::endl;
416///   printAssertionSet( assertions, std::cout, 8 );
417///   std::cout << "looking for ";
418///   assert->print( std::cout );
419///   std::cout << std::endl;
420  AssertionSet::iterator i = assertions.find( assert );
421  if( i != assertions.end() ) {
422///     std::cout << "found it!" << std::endl;
423    i->second = true;
424  }
425}
426
427void
428markAssertions( AssertionSet &assertion1, AssertionSet &assertion2, Type *type )
429{
430  for( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
431    for( std::list< DeclarationWithType* >::const_iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
432      markAssertionSet( assertion1, *assert );
433      markAssertionSet( assertion2, *assert );
434    }
435  }
436}
437
438void 
439Unify::visit(PointerType *pointerType)
440{
441  if( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
442    result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
443    markAssertions( haveAssertions, needAssertions, pointerType );
444    markAssertions( haveAssertions, needAssertions, otherPointer );
445  }
446}
447
448void 
449Unify::visit(ArrayType *arrayType)
450{
451  // XXX -- compare array dimension
452  ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
453  if( otherArray && arrayType->get_isVarLen() == otherArray->get_isVarLen() ) {
454    result = unifyExact( arrayType->get_base(), otherArray->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
455  }
456}
457
458template< typename Iterator1, typename Iterator2 >
459bool
460unifyDeclList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
461  for( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
462    if( !unifyExact( (*list1Begin)->get_type(), (*list2Begin)->get_type(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
463      return false;
464    }
465  }
466  if( list1Begin != list1End || list2Begin != list2End ) {
467    return false;
468  } else {
469    return true;
470  }
471}
472
473void 
474Unify::visit(FunctionType *functionType)
475{
476  FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
477  if( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
478 
479    if( unifyDeclList( functionType->get_parameters().begin(), functionType->get_parameters().end(), otherFunction->get_parameters().begin(), otherFunction->get_parameters().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
480   
481      if( unifyDeclList( functionType->get_returnVals().begin(), functionType->get_returnVals().end(), otherFunction->get_returnVals().begin(), otherFunction->get_returnVals().end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
482
483        markAssertions( haveAssertions, needAssertions, functionType );
484        markAssertions( haveAssertions, needAssertions, otherFunction );
485
486        result = true;
487      }
488    }
489  }
490}
491
492template< typename RefType >
493void
494Unify::handleRefType( RefType *inst, Type *other )
495{ 
496  RefType *otherStruct = dynamic_cast< RefType* >( other );
497  result = otherStruct && inst->get_name() == otherStruct->get_name();
498} 
499
500void 
501Unify::visit(StructInstType *structInst)
502{
503  handleRefType( structInst, type2 );
504}
505
506void 
507Unify::visit(UnionInstType *unionInst)
508{
509  handleRefType( unionInst, type2 );
510}
511
512void 
513Unify::visit(EnumInstType *enumInst)
514{
515  handleRefType( enumInst, type2 );
516}
517
518void 
519Unify::visit(ContextInstType *contextInst)
520{
521  handleRefType( contextInst, type2 );
522}
523
524void 
525Unify::visit(TypeInstType *typeInst)
526{
527  assert( openVars.find( typeInst->get_name() ) == openVars.end() );
528  TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 );
529  if( otherInst && typeInst->get_name() == otherInst->get_name() ) {
530    result = true;
531///   } else {
532///     NamedTypeDecl *nt = indexer.lookupType( typeInst->get_name() );
533///     if( nt ) {
534///       TypeDecl *type = dynamic_cast< TypeDecl* >( nt );
535///       assert( type );
536///       if( type->get_base() ) {
537///         result = unifyExact( type->get_base(), typeInst, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
538///       }
539///     }
540  }
541}
542
543template< typename Iterator1, typename Iterator2 >
544bool
545unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) {
546  for( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
547    Type *commonType = 0;
548    if( !unifyInexact( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, widenMode, indexer, commonType ) ) {
549      return false;
550    }
551    delete commonType;
552  }
553  if( list1Begin != list1End || list2Begin != list2End ) {
554    return false;
555  } else {
556    return true;
557  }
558}
559
560void 
561Unify::visit(TupleType *tupleType)
562{
563  if( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
564    result = unifyList( tupleType->get_types().begin(), tupleType->get_types().end(), otherTuple->get_types().begin(), otherTuple->get_types().end(), env, needAssertions, haveAssertions, openVars, widenMode, indexer );
565  }
566}
567
568} // namespace ResolvExpr
Note: See TracBrowser for help on using the repository browser.