Changes in / [98a8290:0e315a5]
- Location:
- src
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Decl.hpp
r98a8290 r0e315a5 102 102 ptr<Expr> bitfieldWidth; 103 103 104 ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type, 105 Init * init = nullptr, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C, 106 Expr * bitWd = nullptr, std::vector< ptr<Attribute> > && attrs = {}, 107 Function::Specs fs = {} ) 104 ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type, Init * init = nullptr, 105 Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::C, Expr * bitWd = nullptr, 106 std::vector< ptr<Attribute> > && attrs = {}, Function::Specs fs = {}) 108 107 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ), 109 108 init( init ), bitfieldWidth( bitWd ) {} -
src/AST/Node.hpp
r98a8290 r0e315a5 10 10 // Created On : Wed May 8 10:27:04 2019 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Jun 3 13:26:00 201913 // Update Count : 512 // Last Modified On : Thu May 23 16:00:00 2019 13 // Update Count : 4 14 14 // 15 15 … … 107 107 ptr_base() : node(nullptr) {} 108 108 ptr_base( const node_t * n ) : node(n) { if( node ) _inc(node); } 109 ~ptr_base() { if( node ) { auto tmp = node; node = nullptr; _dec(tmp); }}109 ~ptr_base() { if( node ) _dec(node); } 110 110 111 111 ptr_base( const ptr_base & o ) : node(o.node) { … … 127 127 template<typename o_node_t> 128 128 ptr_base & operator=( const o_node_t * node ) { 129 assign( strict_dynamic_cast<const node_t *, nullptr>(node));129 assign( node ? strict_dynamic_cast<const node_t *>(node) : nullptr ); 130 130 return *this; 131 131 } -
src/AST/Type.hpp
r98a8290 r0e315a5 48 48 49 49 Type * set_const( bool v ) { qualifiers.is_const = v; return this; } 50 Type * set_volatile( bool v ) { qualifiers.is_volatile = v; return this; }51 50 Type * set_restrict( bool v ) { qualifiers.is_restrict = v; return this; } 52 51 Type * set_lvalue( bool v ) { qualifiers.is_lvalue = v; return this; } -
src/AST/TypeEnvironment.cpp
r98a8290 r0e315a5 46 46 } 47 47 48 void print( std::ostream & out, const OpenVarSet & open , Indenter indent ) {48 void print( std::ostream & out, const OpenVarSet & openVars, Indenter indent ) { 49 49 out << indent; 50 50 bool first = true; 51 for ( const auto & i : open ) {51 for ( const auto & i : openVars ) { 52 52 if ( first ) { first = false; } else { out << ' '; } 53 53 out << i.first << "(" << i.second << ")"; … … 166 166 167 167 bool TypeEnvironment::combine( 168 const TypeEnvironment & o, OpenVarSet & open , const SymbolTable & symtab ) {168 const TypeEnvironment & o, OpenVarSet & openVars, const SymbolTable & symtab ) { 169 169 // short-circuit easy cases 170 170 if ( o.empty() ) return true; … … 189 189 EqvClass & r = *rt; 190 190 // merge bindings 191 if ( ! mergeBound( r, c, open , symtab ) ) return false;191 if ( ! mergeBound( r, c, openVars, symtab ) ) return false; 192 192 // merge previous unbound variables into this class, checking occurs if needed 193 193 if ( r.bound ) for ( const auto & u : c.vars ) { … … 204 204 } else if ( st != rt ) { 205 205 // bound, but not to the same class 206 if ( ! mergeClasses( rt, st, open , symtab ) ) return false;206 if ( ! mergeClasses( rt, st, openVars, symtab ) ) return false; 207 207 } // ignore bound into the same class 208 208 } … … 216 216 } 217 217 218 void TypeEnvironment::extractOpenVars( OpenVarSet & open ) const {218 void TypeEnvironment::extractOpenVars( OpenVarSet & openVars ) const { 219 219 for ( const auto & clz : env ) { 220 220 for ( const auto & var : clz.vars ) { 221 open [ var ] = clz.data;222 } 223 } 224 } 225 226 void TypeEnvironment::addActual( const TypeEnvironment & actualEnv, OpenVarSet & open ) {221 openVars[ var ] = clz.data; 222 } 223 } 224 } 225 226 void TypeEnvironment::addActual( const TypeEnvironment & actualEnv, OpenVarSet & openVars ) { 227 227 for ( const auto & clz : actualEnv ) { 228 228 EqvClass c = clz; 229 229 c.allowWidening = false; 230 230 for ( const auto & var : c.vars ) { 231 open [ var ] = c.data;231 openVars[ var ] = c.data; 232 232 } 233 233 env.emplace_back( std::move(c) ); … … 268 268 bool TypeEnvironment::bindVar( 269 269 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 270 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, WidenMode widen, 271 const SymbolTable & symtab 272 ) { 270 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 271 WidenMode widenMode, const SymbolTable & symtab ) { 273 272 // remove references from bound type, so that type variables can only bind to value types 274 ptr<Type> target= bindTo->stripReferences();275 auto tyvar = open .find( typeInst->name );276 assert( tyvar != open .end() );277 if ( ! tyVarCompatible( tyvar->second, target) ) return false;278 if ( occurs( target, typeInst->name, *this ) ) return false;273 bindTo = bindTo->stripReferences(); 274 auto tyvar = openVars.find( typeInst->name ); 275 assert( tyvar != openVars.end() ); 276 if ( ! tyVarCompatible( tyvar->second, bindTo ) ) return false; 277 if ( occurs( bindTo, typeInst->name, *this ) ) return false; 279 278 280 279 auto it = internal_lookup( typeInst->name ); … … 283 282 // attempt to unify equivalence class type with type to bind to. 284 283 // equivalence class type has stripped qualifiers which must be restored 285 ptr<Type> common;284 const Type * common = nullptr; 286 285 ptr<Type> newType = it->bound; 287 286 newType.get_and_mutate()->qualifiers = typeInst->qualifiers; 288 287 if ( unifyInexact( 289 newType, target, *this, need, have, open,290 widen & WidenMode{ it->allowWidening, true }, symtab, common ) ) {288 newType, bindTo, *this, need, have, openVars, 289 widenMode & WidenMode{ it->allowWidening, true }, symtab, common ) ) { 291 290 if ( common ) { 292 it->bound = std::move(common);291 it->bound = common; 293 292 clear_qualifiers( it->bound ); 294 293 } 295 294 } else return false; 296 295 } else { 297 it->bound = std::move(target);296 it->bound = bindTo; 298 297 clear_qualifiers( it->bound ); 299 it->allowWidening = widen .first && widen.second;298 it->allowWidening = widenMode.widenFirst && widenMode.widenSecond; 300 299 } 301 300 } else { 302 301 env.emplace_back( 303 typeInst->name, target, widen.first && widen.second, data );302 typeInst->name, bindTo, widenMode.widenFirst && widenMode.widenSecond, data ); 304 303 } 305 304 return true; … … 308 307 bool TypeEnvironment::bindVarToVar( 309 308 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 310 AssertionSet & need, AssertionSet & have, const OpenVarSet & open, 311 WidenMode widen, const SymbolTable & symtab 312 ) { 309 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 310 WidenMode widenMode, const SymbolTable & symtab ) { 313 311 auto c1 = internal_lookup( var1->name ); 314 312 auto c2 = internal_lookup( var2->name ); … … 316 314 // exit early if variables already bound together 317 315 if ( c1 != env.end() && c1 == c2 ) { 318 c1->allowWidening &= widen ;316 c1->allowWidening &= widenMode; 319 317 return true; 320 318 } … … 329 327 type1 = c1->bound; 330 328 } 331 widen1 = widen .first && c1->allowWidening;329 widen1 = widenMode.widenFirst && c1->allowWidening; 332 330 } 333 331 if ( c2 != env.end() ) { … … 336 334 type2 = c2->bound; 337 335 } 338 widen2 = widen .second && c2->allowWidening;336 widen2 = widenMode.widenSecond && c2->allowWidening; 339 337 } 340 338 … … 343 341 ptr<Type> newType1{ type1 }, newType2{ type2 }; 344 342 WidenMode newWidenMode{ widen1, widen2 }; 345 ptr<Type> common;343 const Type * common = nullptr; 346 344 347 345 if ( unifyInexact( 348 newType1, newType2, *this, need, have, open , newWidenMode, symtab, common ) ) {346 newType1, newType2, *this, need, have, openVars, newWidenMode, symtab, common ) ) { 349 347 c1->vars.insert( c2->vars.begin(), c2->vars.end() ); 350 348 c1->allowWidening = widen1 && widen2; 351 349 if ( common ) { 352 c1->bound = std::move(common);350 c1->bound = common; 353 351 clear_qualifiers( c1->bound ); 354 352 } … … 397 395 398 396 bool TypeEnvironment::mergeBound( 399 EqvClass & to, const EqvClass & from, OpenVarSet & open , const SymbolTable & symtab ) {397 EqvClass & to, const EqvClass & from, OpenVarSet & openVars, const SymbolTable & symtab ) { 400 398 if ( from.bound ) { 401 399 if ( to.bound ) { 402 400 // attempt to unify bound types 403 401 ptr<Type> toType{ to.bound }, fromType{ from.bound }; 404 WidenMode widen { to.allowWidening, from.allowWidening };405 ptr<Type> common;402 WidenMode widenMode{ to.allowWidening, from.allowWidening }; 403 const Type * common = nullptr; 406 404 AssertionSet need, have; 407 405 408 406 if ( unifyInexact( 409 toType, fromType, *this, need, have, open , widen, symtab, common ) ) {407 toType, fromType, *this, need, have, openVars, widenMode, symtab, common ) ) { 410 408 // unifies, set common type if necessary 411 409 if ( common ) { 412 to.bound = std::move(common);410 to.bound = common; 413 411 clear_qualifiers( to.bound ); 414 412 } … … 425 423 426 424 bool TypeEnvironment::mergeClasses( 427 ClassList::iterator to, ClassList::iterator from, OpenVarSet & open, const SymbolTable & symtab428 ) {425 ClassList::iterator to, ClassList::iterator from, OpenVarSet & openVars, 426 const SymbolTable & symtab ) { 429 427 EqvClass & r = *to, & s = *from; 430 428 431 429 // ensure bounds match 432 if ( ! mergeBound( r, s, open , symtab ) ) return false;430 if ( ! mergeBound( r, s, openVars, symtab ) ) return false; 433 431 434 432 // check safely bindable -
src/AST/TypeEnvironment.hpp
r98a8290 r0e315a5 178 178 const TypeInstType * typeInst, const Type * bindTo, const TypeDecl::Data & data, 179 179 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 180 ResolvExpr::WidenMode widen , const SymbolTable & symtab );180 ResolvExpr::WidenMode widenMode, const SymbolTable & symtab ); 181 181 182 182 /// Binds the type classes represented by `var1` and `var2` together; will add one or both … … 185 185 const TypeInstType * var1, const TypeInstType * var2, TypeDecl::Data && data, 186 186 AssertionSet & need, AssertionSet & have, const OpenVarSet & openVars, 187 ResolvExpr::WidenMode widen , const SymbolTable & symtab );187 ResolvExpr::WidenMode widenMode, const SymbolTable & symtab ); 188 188 189 189 /// Disallows widening for all bindings in the environment -
src/AST/TypeSubstitution.cpp
r98a8290 r0e315a5 9 9 // Author : Richard C. Bilson 10 10 // Created On : Mon May 18 07:44:20 2015 11 // Last Modified By : Andrew Beach12 // Last Modified On : Mon Jun 3 13:26:00201713 // Update Count : 511 // Last Modified By : Peter A. Buhr 12 // Last Modified On : Thu Mar 16 15:54:35 2017 13 // Update Count : 4 14 14 // 15 15 … … 26 26 } 27 27 28 TypeSubstitution::~TypeSubstitution() {} 28 TypeSubstitution::~TypeSubstitution() { 29 for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) { 30 delete( i->second ); 31 } 32 for ( VarEnvType::iterator i = varEnv.begin(); i != varEnv.end(); ++i ) { 33 delete( i->second ); 34 } 35 } 29 36 30 37 TypeSubstitution &TypeSubstitution::operator=( const TypeSubstitution &other ) { -
src/AST/porting.md
r98a8290 r0e315a5 291 291 * moved to be helper function in `TypeEnvironment.cpp` (its only use) 292 292 293 `WidenMode`294 * changed `widenFirst`, `widenSecond` => `first`, `second`295 * changed `WidenMode widenMode` => `WidenMode widen`296 297 293 [1] https://gcc.gnu.org/onlinedocs/gcc-9.1.0/gcc/Type-Attributes.html#Type-Attributes 298 294 -
src/ResolvExpr/CommonType.cc
r98a8290 r0e315a5 176 176 } 177 177 178 const ast::Type * commonType(179 const ast::Type * type1, const ast::Type * type2, WidenMode widen,180 const ast::SymbolTable & symtab, ast::TypeEnvironment & env,181 const ast::OpenVarSet & open ) {182 #warning unimplemented183 (void)type1; (void)type2; (void)widen; (void)symtab; (void)env; (void)open;184 assert(false);185 return nullptr;186 }187 188 178 // GENERATED START, DO NOT EDIT 189 179 // GENERATED BY BasicTypes-gen.cc -
src/ResolvExpr/FindOpenVars.cc
r98a8290 r0e315a5 93 93 common_action( tupleType ); 94 94 } 95 96 void findOpenVars(97 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,98 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen ) {99 #warning unimplemented100 (void)type; (void)open; (void)closed; (void)need; (void)have; (void)firstIsOpen;101 assert(false);102 }103 95 } // namespace ResolvExpr 104 96 -
src/ResolvExpr/FindOpenVars.h
r98a8290 r0e315a5 16 16 #pragma once 17 17 18 #include "AST/TypeEnvironment.hpp" // for AssertionSet, OpenVarSet19 18 #include "ResolvExpr/TypeEnvironment.h" // for AssertionSet, OpenVarSet 20 19 21 20 class Type; 22 namespace ast {23 class Type;24 }25 21 26 22 namespace ResolvExpr { 27 23 // Updates open and closed variables and their associated assertions 28 24 void findOpenVars( Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ); 29 30 enum FirstMode { FirstClosed, FirstOpen };31 32 // Updates open and closed variables and their associated assertions33 void findOpenVars(34 const ast::Type * type, ast::OpenVarSet & open, ast::OpenVarSet & closed,35 ast::AssertionSet & need, ast::AssertionSet & have, FirstMode firstIsOpen );36 25 } // namespace ResolvExpr 37 26 -
src/ResolvExpr/TypeEnvironment.cc
r98a8290 r0e315a5 205 205 // attempt to unify bound types 206 206 std::unique_ptr<Type> toType{ to.type->clone() }, fromType{ from.type->clone() }; 207 WidenMode widen { to.allowWidening, from.allowWidening };207 WidenMode widenMode{ to.allowWidening, from.allowWidening }; 208 208 Type* common = nullptr; 209 209 AssertionSet need, have; 210 if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widen , indexer, common ) ) {210 if ( unifyInexact( toType.get(), fromType.get(), *this, need, have, openVars, widenMode, indexer, common ) ) { 211 211 // unifies, set common type if necessary 212 212 if ( common ) { … … 343 343 } 344 344 345 bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen , const SymTab::Indexer &indexer ) {345 bool TypeEnvironment::bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) { 346 346 347 347 // remove references from other, so that type variables can only bind to value types … … 362 362 std::unique_ptr< Type > newType( curClass->type->clone() ); 363 363 newType->get_qualifiers() = typeInst->get_qualifiers(); 364 if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widen & WidenMode( curClass->allowWidening, true ), indexer, common ) ) {364 if ( unifyInexact( newType.get(), bindTo, *this, need, have, openVars, widenMode & WidenMode( curClass->allowWidening, true ), indexer, common ) ) { 365 365 if ( common ) { 366 366 common->get_qualifiers() = Type::Qualifiers{}; … … 372 372 newType->get_qualifiers() = Type::Qualifiers{}; 373 373 curClass->set_type( newType ); 374 curClass->allowWidening = widen .first && widen.second;374 curClass->allowWidening = widenMode.widenFirst && widenMode.widenSecond; 375 375 } // if 376 376 } else { … … 379 379 newClass.type = bindTo->clone(); 380 380 newClass.type->get_qualifiers() = Type::Qualifiers(); 381 newClass.allowWidening = widen .first && widen.second;381 newClass.allowWidening = widenMode.widenFirst && widenMode.widenSecond; 382 382 newClass.data = data; 383 383 env.push_back( std::move(newClass) ); … … 388 388 bool TypeEnvironment::bindVarToVar( TypeInstType *var1, TypeInstType *var2, 389 389 TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, 390 const OpenVarSet &openVars, WidenMode widen , const SymTab::Indexer &indexer ) {390 const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) { 391 391 392 392 auto class1 = internal_lookup( var1->get_name() ); … … 395 395 // exit early if variables already bound together 396 396 if ( class1 != env.end() && class1 == class2 ) { 397 class1->allowWidening &= widen ;397 class1->allowWidening &= widenMode; 398 398 return true; 399 399 } … … 408 408 type1 = class1->type; 409 409 } // if 410 widen1 = widen .first && class1->allowWidening;410 widen1 = widenMode.widenFirst && class1->allowWidening; 411 411 } // if 412 412 if ( class2 != env.end() ) { … … 415 415 type2 = class2->type; 416 416 } // if 417 widen2 = widen .second && class2->allowWidening;417 widen2 = widenMode.widenSecond && class2->allowWidening; 418 418 } // if 419 419 -
src/ResolvExpr/TypeEnvironment.h
r98a8290 r0e315a5 136 136 /// Binds the type class represented by `typeInst` to the type `bindTo`; will add 137 137 /// the class if needed. Returns false on failure. 138 bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen , const SymTab::Indexer &indexer );138 bool bindVar( TypeInstType *typeInst, Type *bindTo, const TypeDecl::Data & data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ); 139 139 140 140 /// Binds the type classes represented by `var1` and `var2` together; will add 141 141 /// one or both classes if needed. Returns false on failure. 142 bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widen , const SymTab::Indexer &indexer );142 bool bindVarToVar( TypeInstType *var1, TypeInstType *var2, TypeDecl::Data && data, AssertionSet &need, AssertionSet &have, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ); 143 143 144 144 /// Disallows widening for all bindings in the environment -
src/ResolvExpr/Unify.cc
r98a8290 r0e315a5 14 14 // 15 15 16 #include "Unify.h"17 18 16 #include <cassert> // for assertf, assert 19 17 #include <iterator> // for back_insert_iterator, back_inserter … … 25 23 #include <vector> 26 24 27 #include "AST/Decl.hpp"28 25 #include "AST/Node.hpp" 29 #include "AST/Pass.hpp"30 26 #include "AST/Type.hpp" 31 27 #include "AST/TypeEnvironment.hpp" … … 41 37 #include "Tuples/Tuples.h" // for isTtype 42 38 #include "TypeEnvironment.h" // for EqvClass, AssertionSet, OpenVarSet 39 #include "Unify.h" 43 40 #include "typeops.h" // for flatten, occurs, commonType 44 45 namespace ast {46 class SymbolTable;47 }48 41 49 42 namespace SymTab { … … 55 48 namespace ResolvExpr { 56 49 57 struct Unify _old: public WithShortCircuiting {58 Unify _old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );50 struct Unify : public WithShortCircuiting { 51 Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ); 59 52 60 53 bool get_result() const { return result; } … … 88 81 AssertionSet &haveAssertions; 89 82 const OpenVarSet &openVars; 90 WidenMode widen ;83 WidenMode widenMode; 91 84 const SymTab::Indexer &indexer; 92 85 }; … … 94 87 /// Attempts an inexact unification of type1 and type2. 95 88 /// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers) 96 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ); 97 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ); 98 99 bool unifyExact( 100 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 101 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 102 WidenMode widen, const ast::SymbolTable & symtab ); 89 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common ); 90 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ); 103 91 104 92 bool typesCompatible( Type *first, Type *second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { … … 124 112 const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab, 125 113 const ast::TypeEnvironment & env ) { 126 ast::TypeEnvironment newEnv; 127 ast::OpenVarSet open, closed; 128 ast::AssertionSet need, have; 129 130 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second }; 131 env.apply( newFirst ); 132 env.apply( newSecond ); 133 134 findOpenVars( newFirst, open, closed, need, have, FirstClosed ); 135 findOpenVars( newSecond, open, closed, need, have, FirstOpen ); 136 137 return unifyExact( 138 newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab ); 114 #warning unimplemented 115 assert((first, second, symtab, env, false)); 116 return false; 139 117 } 140 118 … … 166 144 const ast::Type * first, const ast::Type * second, const ast::SymbolTable & symtab, 167 145 const ast::TypeEnvironment & env ) { 168 ast::TypeEnvironment newEnv; 169 ast::OpenVarSet open; 170 ast::AssertionSet need, have; 171 172 ast::ptr<ast::Type> newFirst{ first }, newSecond{ second }; 173 env.apply( newFirst ); 174 env.apply( newSecond ); 175 clear_qualifiers( newFirst ); 176 clear_qualifiers( newSecond ); 177 178 return unifyExact( 179 newFirst, newSecond, newEnv, need, have, open, WidenMode{ false, false }, symtab ); 146 #warning unimplemented 147 assert((first, second, symtab, env, false)); 148 return false; 180 149 } 181 150 … … 202 171 } 203 172 204 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen , const SymTab::Indexer &indexer ) {173 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) { 205 174 #ifdef DEBUG 206 175 TypeEnvironment debugEnv( env ); … … 229 198 result = env.bindVarToVar( 230 199 var1, var2, TypeDecl::Data{ entry1->second, entry2->second }, needAssertions, 231 haveAssertions, openVars, widen , indexer );200 haveAssertions, openVars, widenMode, indexer ); 232 201 } 233 202 } else if ( isopen1 ) { 234 result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widen , indexer );235 } else if ( isopen2 ) { // TODO: swap widen values in call, since type positions are flipped?236 result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widen , indexer );203 result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widenMode, indexer ); 204 } else if ( isopen2 ) { // TODO: swap widenMode values in call, since type positions are flipped? 205 result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widenMode, indexer ); 237 206 } else { 238 PassVisitor<Unify _old> comparator( type2, env, needAssertions, haveAssertions, openVars, widen, indexer );207 PassVisitor<Unify> comparator( type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ); 239 208 type1->accept( comparator ); 240 209 result = comparator.pass.get_result(); … … 261 230 } 262 231 263 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen , const SymTab::Indexer &indexer, Type *&common ) {232 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common ) { 264 233 Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers(); 265 234 type1->get_qualifiers() = Type::Qualifiers(); … … 273 242 std::cerr << std::endl; 274 243 #endif 275 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen , indexer ) ) {244 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widenMode, indexer ) ) { 276 245 #ifdef DEBUG 277 246 std::cerr << "unifyInexact: no exact unification found" << std::endl; 278 247 #endif 279 if ( ( common = commonType( type1, type2, widen .first, widen.second, indexer, env, openVars ) ) ) {248 if ( ( common = commonType( type1, type2, widenMode.widenFirst, widenMode.widenSecond, indexer, env, openVars ) ) ) { 280 249 common->get_qualifiers() = tq1 | tq2; 281 250 #ifdef DEBUG … … 293 262 } else { 294 263 if ( tq1 != tq2 ) { 295 if ( ( tq1 > tq2 || widen .first ) && ( tq2 > tq1 || widen.second ) ) {264 if ( ( tq1 > tq2 || widenMode.widenFirst ) && ( tq2 > tq1 || widenMode.widenSecond ) ) { 296 265 common = type1->clone(); 297 266 common->get_qualifiers() = tq1 | tq2; … … 311 280 } 312 281 313 Unify_old::Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) 314 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen( widen ), indexer( indexer ) { 315 } 316 317 void Unify_old::postvisit( __attribute__((unused)) VoidType *voidType) { 282 bool unifyInexact( 283 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 284 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & openVars, 285 WidenMode widenMode, const ast::SymbolTable & symtab, const ast::Type *& common ) { 286 #warning unimplemented 287 assert((type1, type2, env, need, have, openVars, widenMode, symtab, common, false)); 288 return false; 289 } 290 291 Unify::Unify( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer ) 292 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widenMode( widenMode ), indexer( indexer ) { 293 } 294 295 void Unify::postvisit( __attribute__((unused)) VoidType *voidType) { 318 296 result = dynamic_cast< VoidType* >( type2 ); 319 297 } 320 298 321 void Unify _old::postvisit(BasicType *basicType) {299 void Unify::postvisit(BasicType *basicType) { 322 300 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) { 323 301 result = basicType->get_kind() == otherBasic->get_kind(); … … 347 325 } 348 326 349 void Unify _old::postvisit(PointerType *pointerType) {327 void Unify::postvisit(PointerType *pointerType) { 350 328 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) { 351 329 result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 355 333 } 356 334 357 void Unify _old::postvisit(ReferenceType *refType) {335 void Unify::postvisit(ReferenceType *refType) { 358 336 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) { 359 337 result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ); … … 363 341 } 364 342 365 void Unify _old::postvisit(ArrayType *arrayType) {343 void Unify::postvisit(ArrayType *arrayType) { 366 344 ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 ); 367 345 // to unify, array types must both be VLA or both not VLA … … 443 421 /// If this isn't done then argument lists can have wildly different 444 422 /// size and structure, when they should be compatible. 445 struct TtypeExpander _old: public WithShortCircuiting {423 struct TtypeExpander : public WithShortCircuiting { 446 424 TypeEnvironment & tenv; 447 TtypeExpander _old( TypeEnvironment & tenv ) : tenv( tenv ) {}425 TtypeExpander( TypeEnvironment & tenv ) : tenv( tenv ) {} 448 426 void premutate( TypeInstType * ) { visit_children = false; } 449 427 Type * postmutate( TypeInstType * typeInst ) { … … 464 442 dst.clear(); 465 443 for ( DeclarationWithType * dcl : src ) { 466 PassVisitor<TtypeExpander _old> expander( env );444 PassVisitor<TtypeExpander> expander( env ); 467 445 dcl->acceptMutator( expander ); 468 446 std::list< Type * > types; … … 479 457 } 480 458 481 void Unify _old::postvisit(FunctionType *functionType) {459 void Unify::postvisit(FunctionType *functionType) { 482 460 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 ); 483 461 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) { … … 490 468 491 469 // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors 492 if ( 493 (flatFunc->parameters.size() == flatOther->parameters.size() && 494 flatFunc->returnVals.size() == flatOther->returnVals.size()) 495 || flatFunc->isTtype() 496 || flatOther->isTtype() 497 ) { 470 if ( (flatFunc->parameters.size() == flatOther->parameters.size() && flatFunc->returnVals.size() == flatOther->returnVals.size()) || flatFunc->isTtype() || flatOther->isTtype() ) { 498 471 if ( unifyDeclList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { 499 472 if ( unifyDeclList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) { … … 511 484 512 485 template< typename RefType > 513 void Unify _old::handleRefType( RefType *inst, Type *other ) {486 void Unify::handleRefType( RefType *inst, Type *other ) { 514 487 // check that other type is compatible and named the same 515 488 RefType *otherStruct = dynamic_cast< RefType* >( other ); … … 518 491 519 492 template< typename RefType > 520 void Unify _old::handleGenericRefType( RefType *inst, Type *other ) {493 void Unify::handleGenericRefType( RefType *inst, Type *other ) { 521 494 // Check that other type is compatible and named the same 522 495 handleRefType( inst, other ); … … 586 559 } 587 560 588 void Unify _old::postvisit(StructInstType *structInst) {561 void Unify::postvisit(StructInstType *structInst) { 589 562 handleGenericRefType( structInst, type2 ); 590 563 } 591 564 592 void Unify _old::postvisit(UnionInstType *unionInst) {565 void Unify::postvisit(UnionInstType *unionInst) { 593 566 handleGenericRefType( unionInst, type2 ); 594 567 } 595 568 596 void Unify _old::postvisit(EnumInstType *enumInst) {569 void Unify::postvisit(EnumInstType *enumInst) { 597 570 handleRefType( enumInst, type2 ); 598 571 } 599 572 600 void Unify _old::postvisit(TraitInstType *contextInst) {573 void Unify::postvisit(TraitInstType *contextInst) { 601 574 handleRefType( contextInst, type2 ); 602 575 } 603 576 604 void Unify _old::postvisit(TypeInstType *typeInst) {577 void Unify::postvisit(TypeInstType *typeInst) { 605 578 assert( openVars.find( typeInst->get_name() ) == openVars.end() ); 606 579 TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 ); … … 657 630 } 658 631 659 void Unify _old::postvisit(TupleType *tupleType) {632 void Unify::postvisit(TupleType *tupleType) { 660 633 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) { 661 634 std::unique_ptr<TupleType> flat1( tupleType->clone() ); … … 663 636 std::list<Type *> types1, types2; 664 637 665 PassVisitor<TtypeExpander _old> expander( env );638 PassVisitor<TtypeExpander> expander( env ); 666 639 flat1->acceptMutator( expander ); 667 640 flat2->acceptMutator( expander ); … … 674 647 } 675 648 676 void Unify _old::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {649 void Unify::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) { 677 650 result = dynamic_cast< VarArgsType* >( type2 ); 678 651 } 679 652 680 void Unify _old::postvisit( __attribute__((unused)) ZeroType *zeroType ) {653 void Unify::postvisit( __attribute__((unused)) ZeroType *zeroType ) { 681 654 result = dynamic_cast< ZeroType* >( type2 ); 682 655 } 683 656 684 void Unify _old::postvisit( __attribute__((unused)) OneType *oneType ) {657 void Unify::postvisit( __attribute__((unused)) OneType *oneType ) { 685 658 result = dynamic_cast< OneType* >( type2 ); 686 659 } … … 700 673 } 701 674 702 class Unify_new : public ast::WithShortCircuiting {703 const ast::Type * type2;704 ast::TypeEnvironment & tenv;705 ast::AssertionSet & need;706 ast::AssertionSet & have;707 const ast::OpenVarSet & open;708 WidenMode widen;709 const ast::SymbolTable & symtab;710 public:711 bool result;712 713 Unify_new(714 const ast::Type * type2, ast::TypeEnvironment & env, ast::AssertionSet & need,715 ast::AssertionSet & have, const ast::OpenVarSet & open, WidenMode widen,716 const ast::SymbolTable & symtab )717 : type2(type2), tenv(env), need(need), have(have), open(open), widen(widen),718 symtab(symtab), result(false) {}719 720 void previsit( const ast::Node * ) { visit_children = false; }721 722 void previsit( const ast::VoidType * ) {723 visit_children = false;724 result = dynamic_cast< const ast::VoidType * >( type2 );725 }726 727 void previsit( const ast::BasicType * basic ) {728 visit_children = false;729 if ( auto basic2 = dynamic_cast< const ast::BasicType * >( type2 ) ) {730 result = basic->kind == basic2->kind;731 }732 }733 734 void previsit( const ast::PointerType * pointer ) {735 visit_children = false;736 if ( auto pointer2 = dynamic_cast< const ast::PointerType * >( type2 ) ) {737 result = unifyExact(738 pointer->base, pointer2->base, tenv, need, have, open,739 WidenMode{ false, false }, symtab );740 }741 }742 743 void previsit( const ast::ArrayType * array ) {744 visit_children = false;745 auto array2 = dynamic_cast< const ast::ArrayType * >( type2 );746 if ( ! array2 ) return;747 748 // to unify, array types must both be VLA or both not VLA and both must have a749 // dimension expression or not have a dimension750 if ( array->isVarLen != array2->isVarLen ) return;751 if ( ! array->isVarLen && ! array2->isVarLen752 && array->dimension && array2->dimension ) {753 auto ce1 = array->dimension.as< ast::ConstantExpr >();754 auto ce2 = array2->dimension.as< ast::ConstantExpr >();755 756 // see C11 Reference Manual 6.7.6.2.6757 // two array types with size specifiers that are integer constant expressions are758 // compatible if both size specifiers have the same constant value759 if ( ce1 && ce2 && ce1->intValue() != ce2->intValue() ) return;760 }761 762 result = unifyExact(763 array->base, array2->base, tenv, need, have, open, WidenMode{ false, false },764 symtab );765 }766 767 void previsit( const ast::ReferenceType * ref ) {768 visit_children = false;769 if ( auto ref2 = dynamic_cast< const ast::ReferenceType * >( type2 ) ) {770 result = unifyExact(771 ref->base, ref2->base, tenv, need, have, open, WidenMode{ false, false },772 symtab );773 }774 }775 776 private:777 /// Replaces ttype variables with their bound types.778 /// If this isn't done when satifying ttype assertions, then argument lists can have779 /// different size and structure when they should be compatible.780 struct TtypeExpander_new : public ast::WithShortCircuiting {781 ast::TypeEnvironment & tenv;782 783 TtypeExpander_new( ast::TypeEnvironment & env ) : tenv( env ) {}784 785 const ast::Type * postmutate( const ast::TypeInstType * typeInst ) {786 if ( const ast::EqvClass * clz = tenv.lookup( typeInst->name ) ) {787 // expand ttype parameter into its actual type788 if ( clz->data.kind == ast::TypeVar::Ttype && clz->bound ) {789 return clz->bound;790 }791 }792 return typeInst;793 }794 };795 796 /// returns flattened version of `src`797 static std::vector< ast::ptr< ast::DeclWithType > > flattenList(798 const std::vector< ast::ptr< ast::DeclWithType > > & src, ast::TypeEnvironment & env799 ) {800 std::vector< ast::ptr< ast::DeclWithType > > dst;801 dst.reserve( src.size() );802 for ( const ast::DeclWithType * d : src ) {803 ast::Pass<TtypeExpander_new> expander{ env };804 d = d->accept( expander );805 auto types = flatten( d->get_type() );806 for ( ast::ptr< ast::Type > & t : types ) {807 // outermost const, volatile, _Atomic qualifiers in parameters should not play808 // a role in the unification of function types, since they do not determine809 // whether a function is callable.810 // NOTE: **must** consider at least mutex qualifier, since functions can be811 // overloaded on outermost mutex and a mutex function has different812 // requirements than a non-mutex function813 t.get_and_mutate()->qualifiers814 -= ast::CV::Const | ast::CV::Volatile | ast::CV::Atomic;815 dst.emplace_back( new ast::ObjectDecl{ d->location, "", t } );816 }817 }818 return dst;819 }820 821 /// Creates a tuple type based on a list of DeclWithType822 template< typename Iter >823 static ast::ptr< ast::Type > tupleFromDecls( Iter crnt, Iter end ) {824 std::vector< ast::ptr< ast::Type > > types;825 while ( crnt != end ) {826 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure827 // that this results in a flat tuple828 flatten( (*crnt)->get_type(), types );829 830 ++crnt;831 }832 833 return { new ast::TupleType{ std::move(types) } };834 }835 836 template< typename Iter >837 static bool unifyDeclList(838 Iter crnt1, Iter end1, Iter crnt2, Iter end2, ast::TypeEnvironment & env,839 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,840 const ast::SymbolTable & symtab841 ) {842 while ( crnt1 != end1 && crnt2 != end2 ) {843 const ast::Type * t1 = (*crnt1)->get_type();844 const ast::Type * t2 = (*crnt2)->get_type();845 bool isTuple1 = Tuples::isTtype( t1 );846 bool isTuple2 = Tuples::isTtype( t2 );847 848 // assumes here that ttype *must* be last parameter849 if ( isTuple1 && ! isTuple2 ) {850 // combine remainder of list2, then unify851 return unifyExact(852 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,853 WidenMode{ false, false }, symtab );854 } else if ( ! isTuple1 && isTuple2 ) {855 // combine remainder of list1, then unify856 return unifyExact(857 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,858 WidenMode{ false, false }, symtab );859 }860 861 if ( ! unifyExact(862 t1, t2, env, need, have, open, WidenMode{ false, false }, symtab )863 ) return false;864 865 ++crnt1; ++crnt2;866 }867 868 // May get to the end of one argument list before the other. This is only okay if the869 // other is a ttype870 if ( crnt1 != end1 ) {871 // try unifying empty tuple with ttype872 const ast::Type * t1 = (*crnt1)->get_type();873 if ( ! Tuples::isTtype( t1 ) ) return false;874 return unifyExact(875 t1, tupleFromDecls( crnt2, end2 ), env, need, have, open,876 WidenMode{ false, false }, symtab );877 } else if ( crnt2 != end2 ) {878 // try unifying empty tuple with ttype879 const ast::Type * t2 = (*crnt2)->get_type();880 if ( ! Tuples::isTtype( t2 ) ) return false;881 return unifyExact(882 tupleFromDecls( crnt1, end1 ), t2, env, need, have, open,883 WidenMode{ false, false }, symtab );884 }885 886 return true;887 }888 889 static bool unifyDeclList(890 const std::vector< ast::ptr< ast::DeclWithType > > & list1,891 const std::vector< ast::ptr< ast::DeclWithType > > & list2,892 ast::TypeEnvironment & env, ast::AssertionSet & need, ast::AssertionSet & have,893 const ast::OpenVarSet & open, const ast::SymbolTable & symtab894 ) {895 return unifyDeclList(896 list1.begin(), list1.end(), list2.begin(), list2.end(), env, need, have, open,897 symtab );898 }899 900 static void markAssertionSet( ast::AssertionSet & assns, const ast::DeclWithType * assn ) {901 auto i = assns.find( assn );902 if ( i != assns.end() ) {903 i->second.isUsed = true;904 }905 }906 907 /// mark all assertions in `type` used in both `assn1` and `assn2`908 static void markAssertions(909 ast::AssertionSet & assn1, ast::AssertionSet & assn2,910 const ast::ParameterizedType * type911 ) {912 for ( const auto & tyvar : type->forall ) {913 for ( const ast::DeclWithType * assert : tyvar->assertions ) {914 markAssertionSet( assn1, assert );915 markAssertionSet( assn2, assert );916 }917 }918 }919 920 public:921 void previsit( const ast::FunctionType * func ) {922 visit_children = false;923 auto func2 = dynamic_cast< const ast::FunctionType * >( type2 );924 if ( ! func2 ) return;925 926 if ( func->isVarArgs != func2->isVarArgs ) return;927 928 // Flatten the parameter lists for both functions so that tuple structure does not929 // affect unification. Does not actually mutate function parameters.930 auto params = flattenList( func->params, tenv );931 auto params2 = flattenList( func2->params, tenv );932 933 // sizes don't have to match if ttypes are involved; need to be more precise w.r.t.934 // where the ttype is to prevent errors935 if (936 ( params.size() != params2.size() || func->returns.size() != func2->returns.size() )937 && ! func->isTtype()938 && ! func2->isTtype()939 ) return;940 941 if ( ! unifyDeclList( params, params2, tenv, need, have, open, symtab ) ) return;942 if ( ! unifyDeclList(943 func->returns, func2->returns, tenv, need, have, open, symtab ) ) return;944 945 markAssertions( have, need, func );946 markAssertions( have, need, func2 );947 948 result = true;949 }950 951 private:952 template< typename RefType >953 const RefType * handleRefType( const RefType * inst, const ast::Type * other ) {954 visit_children = false;955 // check that the other type is compatible and named the same956 auto otherInst = dynamic_cast< const RefType * >( other );957 result = otherInst && inst->name == otherInst->name;958 return otherInst;959 }960 961 /// Creates a tuple type based on a list of TypeExpr962 template< typename Iter >963 static const ast::Type * tupleFromExprs(964 const ast::TypeExpr * param, Iter & crnt, Iter end, ast::CV::Qualifiers qs965 ) {966 std::vector< ast::ptr< ast::Type > > types;967 do {968 types.emplace_back( param->type );969 970 ++crnt;971 if ( crnt == end ) break;972 param = strict_dynamic_cast< const ast::TypeExpr * >( crnt->get() );973 } while(true);974 975 return new ast::TupleType{ std::move(types), qs };976 }977 978 template< typename RefType >979 void handleGenericRefType( const RefType * inst, const ast::Type * other ) {980 // check that other type is compatible and named the same981 const RefType * inst2 = handleRefType( inst, other );982 if ( ! inst2 ) return;983 984 // check that parameters of types unify, if any985 const std::vector< ast::ptr< ast::Expr > > & params = inst->params;986 const std::vector< ast::ptr< ast::Expr > > & params2 = inst2->params;987 988 auto it = params.begin();989 auto jt = params2.begin();990 for ( ; it != params.end() && jt != params2.end(); ++it, ++jt ) {991 auto param = strict_dynamic_cast< const ast::TypeExpr * >( it->get() );992 auto param2 = strict_dynamic_cast< const ast::TypeExpr * >( jt->get() );993 994 ast::ptr< ast::Type > pty = param->type;995 ast::ptr< ast::Type > pty2 = param2->type;996 997 bool isTuple = Tuples::isTtype( pty );998 bool isTuple2 = Tuples::isTtype( pty2 );999 1000 if ( isTuple && isTuple2 ) {1001 ++it; ++jt; // skip ttype parameters before break1002 } else if ( isTuple ) {1003 // bundle remaining params into tuple1004 pty2 = tupleFromExprs( param2, jt, params2.end(), pty->qualifiers );1005 ++it; // skip ttype parameter for break1006 } else if ( isTuple2 ) {1007 // bundle remaining params into tuple1008 pty = tupleFromExprs( param, it, params.end(), pty2->qualifiers );1009 ++jt; // skip ttype parameter for break1010 }1011 1012 if ( ! unifyExact(1013 pty, pty2, tenv, need, have, open, WidenMode{ false, false }, symtab ) ) {1014 result = false;1015 return;1016 }1017 1018 // ttype parameter should be last1019 if ( isTuple || isTuple2 ) break;1020 }1021 result = it == params.end() && jt == params2.end();1022 }1023 1024 public:1025 void previsit( const ast::StructInstType * aggrType ) {1026 handleGenericRefType( aggrType, type2 );1027 }1028 1029 void previsit( const ast::UnionInstType * aggrType ) {1030 handleGenericRefType( aggrType, type2 );1031 }1032 1033 void previsit( const ast::EnumInstType * aggrType ) {1034 handleRefType( aggrType, type2 );1035 }1036 1037 void previsit( const ast::TraitInstType * aggrType ) {1038 handleRefType( aggrType, type2 );1039 }1040 1041 void previsit( const ast::TypeInstType * typeInst ) {1042 assert( open.find( typeInst->name ) == open.end() );1043 handleRefType( typeInst, type2 );1044 }1045 1046 private:1047 /// Creates a tuple type based on a list of Type1048 static ast::ptr< ast::Type > tupleFromTypes(1049 const std::vector< ast::ptr< ast::Type > > & tys1050 ) {1051 std::vector< ast::ptr< ast::Type > > out;1052 for ( const ast::Type * ty : tys ) {1053 // it is guaranteed that a ttype variable will be bound to a flat tuple, so ensure1054 // that this results in a flat tuple1055 flatten( ty, out );1056 }1057 1058 return { new ast::TupleType{ std::move(out) } };1059 }1060 1061 static bool unifyList(1062 const std::vector< ast::ptr< ast::Type > > & list1,1063 const std::vector< ast::ptr< ast::Type > > & list2, ast::TypeEnvironment & env,1064 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,1065 const ast::SymbolTable & symtab1066 ) {1067 auto crnt1 = list1.begin();1068 auto crnt2 = list2.begin();1069 while ( crnt1 != list1.end() && crnt2 != list2.end() ) {1070 const ast::Type * t1 = *crnt1;1071 const ast::Type * t2 = *crnt2;1072 bool isTuple1 = Tuples::isTtype( t1 );1073 bool isTuple2 = Tuples::isTtype( t2 );1074 1075 // assumes ttype must be last parameter1076 if ( isTuple1 && ! isTuple2 ) {1077 // combine entirety of list2, then unify1078 return unifyExact(1079 t1, tupleFromTypes( list2 ), env, need, have, open,1080 WidenMode{ false, false }, symtab );1081 } else if ( ! isTuple1 && isTuple2 ) {1082 // combine entirety of list1, then unify1083 return unifyExact(1084 tupleFromTypes( list1 ), t2, env, need, have, open,1085 WidenMode{ false, false }, symtab );1086 }1087 1088 if ( ! unifyExact(1089 t1, t2, env, need, have, open, WidenMode{ false, false }, symtab )1090 ) return false;1091 1092 ++crnt1; ++crnt2;1093 }1094 1095 if ( crnt1 != list1.end() ) {1096 // try unifying empty tuple type with ttype1097 const ast::Type * t1 = *crnt1;1098 if ( ! Tuples::isTtype( t1 ) ) return false;1099 // xxx - this doesn't generate an empty tuple, contrary to comment; both ported1100 // from Rob's code1101 return unifyExact(1102 t1, tupleFromTypes( list2 ), env, need, have, open,1103 WidenMode{ false, false }, symtab );1104 } else if ( crnt2 != list2.end() ) {1105 // try unifying empty tuple with ttype1106 const ast::Type * t2 = *crnt2;1107 if ( ! Tuples::isTtype( t2 ) ) return false;1108 // xxx - this doesn't generate an empty tuple, contrary to comment; both ported1109 // from Rob's code1110 return unifyExact(1111 tupleFromTypes( list1 ), t2, env, need, have, open,1112 WidenMode{ false, false }, symtab );1113 }1114 1115 return true;1116 }1117 1118 public:1119 void previsit( const ast::TupleType * tuple ) {1120 visit_children = false;1121 auto tuple2 = dynamic_cast< const ast::TupleType * >( type2 );1122 if ( ! tuple2 ) return;1123 1124 ast::Pass<TtypeExpander_new> expander{ tenv };1125 const ast::Type * flat = tuple->accept( expander );1126 const ast::Type * flat2 = tuple2->accept( expander );1127 1128 auto types = flatten( flat );1129 auto types2 = flatten( flat2 );1130 1131 result = unifyList( types, types2, tenv, need, have, open, symtab );1132 }1133 1134 void previsit( const ast::VarArgsType * ) {1135 visit_children = false;1136 result = dynamic_cast< const ast::VarArgsType * >( type2 );1137 }1138 1139 void previsit( const ast::ZeroType * ) {1140 visit_children = false;1141 result = dynamic_cast< const ast::ZeroType * >( type2 );1142 }1143 1144 void previsit( const ast::OneType * ) {1145 visit_children = false;1146 result = dynamic_cast< const ast::OneType * >( type2 );1147 }1148 1149 private:1150 template< typename RefType > void handleRefType( RefType *inst, Type *other );1151 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );1152 };1153 1154 bool unifyExact(1155 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,1156 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,1157 WidenMode widen, const ast::SymbolTable & symtab1158 ) {1159 if ( type1->qualifiers != type2->qualifiers ) return false;1160 1161 auto var1 = dynamic_cast< const ast::TypeInstType * >( type1 );1162 auto var2 = dynamic_cast< const ast::TypeInstType * >( type2 );1163 ast::OpenVarSet::const_iterator1164 entry1 = var1 ? open.find( var1->name ) : open.end(),1165 entry2 = var2 ? open.find( var2->name ) : open.end();1166 bool isopen1 = entry1 != open.end();1167 bool isopen2 = entry2 != open.end();1168 1169 if ( isopen1 && isopen2 ) {1170 if ( entry1->second.kind != entry2->second.kind ) return false;1171 return env.bindVarToVar(1172 var1, var2, ast::TypeDecl::Data{ entry1->second, entry2->second }, need, have,1173 open, widen, symtab );1174 } else if ( isopen1 ) {1175 return env.bindVar( var1, type2, entry1->second, need, have, open, widen, symtab );1176 } else if ( isopen2 ) {1177 return env.bindVar( var2, type1, entry2->second, need, have, open, widen, symtab );1178 } else {1179 ast::Pass<Unify_new> comparator{ type2, env, need, have, open, widen, symtab };1180 type1->accept( comparator );1181 return comparator.pass.result;1182 }1183 }1184 1185 bool unifyInexact(1186 ast::ptr<ast::Type> & type1, ast::ptr<ast::Type> & type2, ast::TypeEnvironment & env,1187 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,1188 WidenMode widen, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common1189 ) {1190 ast::CV::Qualifiers q1 = type1->qualifiers, q2 = type2->qualifiers;1191 1192 // force t1 and t2 to be cloned if their qualifiers must be stripped, so that type1 and1193 // type2 are left unchanged; calling convention forces type{1,2}->strong_ref >= 11194 ast::ptr<ast::Type> t1{ type1 }, t2{ type2 };1195 clear_qualifiers( t1 );1196 clear_qualifiers( t2 );1197 1198 if ( unifyExact( t1, t2, env, need, have, open, widen, symtab ) ) {1199 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones1200 1201 // if exact unification on unqualified types, try to merge qualifiers1202 if ( q1 == q2 || ( ( q1 > q2 || widen.first ) && ( q2 > q1 || widen.second ) ) ) {1203 common.set_and_mutate( type1 )->qualifiers = q1 | q2;1204 return true;1205 } else {1206 return false;1207 }1208 1209 } else if (( common = commonType( t1, t2, widen, symtab, env, open ) )) {1210 t1 = nullptr; t2 = nullptr; // release t1, t2 to avoid spurious clones1211 1212 // no exact unification, but common type1213 common.get_and_mutate()->qualifiers = q1 | q2;1214 return true;1215 } else {1216 return false;1217 }1218 }1219 1220 675 ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func ) { 1221 676 if ( func->returns.empty() ) return new ast::VoidType{}; -
src/ResolvExpr/Unify.h
r98a8290 r0e315a5 18 18 #include <list> // for list 19 19 20 #include "AST/Node.hpp" // for ptr21 20 #include "AST/TypeEnvironment.hpp" // for TypeEnvironment, AssertionSet, OpenVarSet 22 21 #include "Common/utility.h" // for deleteAll … … 40 39 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType ); 41 40 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ); 42 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen , const SymTab::Indexer &indexer, Type *&common );41 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widenMode, const SymTab::Indexer &indexer, Type *&common ); 43 42 44 43 template< typename Iterator1, typename Iterator2 > … … 69 68 } 70 69 71 bool unify Exact(70 bool unifyInexact( 72 71 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env, 73 ast::AssertionSet & need, ast::AssertionSet & have, ast::OpenVarSet & open, 74 const ast::SymbolTable & symtab ); 75 76 bool unifyInexact( 77 ast::ptr<ast::Type> & type1, ast::ptr<ast::Type> & type2, ast::TypeEnvironment & env, 78 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open, 79 WidenMode widen, const ast::SymbolTable & symtab, ast::ptr<ast::Type> & common ); 72 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & openVars, 73 WidenMode widenMode, const ast::SymbolTable & symtab, const ast::Type *& common ); 80 74 81 75 } // namespace ResolvExpr -
src/ResolvExpr/WidenMode.h
r98a8290 r0e315a5 18 18 namespace ResolvExpr { 19 19 struct WidenMode { 20 WidenMode( bool first, bool second ): first( first ), second( second ) {} 21 22 WidenMode &operator|=( const WidenMode &other ) { 23 first |= other.first; second |= other.second; return *this; 24 } 20 WidenMode( bool widenFirst, bool widenSecond ): widenFirst( widenFirst ), widenSecond( widenSecond ) {} 21 WidenMode &operator|=( const WidenMode &other ) { widenFirst |= other.widenFirst; widenSecond |= other.widenSecond; return *this; } 22 WidenMode &operator&=( const WidenMode &other ) { widenFirst &= other.widenFirst; widenSecond &= other.widenSecond; return *this; } 23 WidenMode operator|( const WidenMode &other ) { WidenMode newWM( *this ); newWM |= other; return newWM; } 24 WidenMode operator&( const WidenMode &other ) { WidenMode newWM( *this ); newWM &= other; return newWM; } 25 operator bool() { return widenFirst && widenSecond; } 25 26 26 WidenMode &operator&=( const WidenMode &other ) { 27 first &= other.first; second &= other.second; return *this; 28 } 29 30 WidenMode operator|( const WidenMode &other ) { 31 WidenMode newWM( *this ); newWM |= other; return newWM; 32 } 33 34 WidenMode operator&( const WidenMode &other ) { 35 WidenMode newWM( *this ); newWM &= other; return newWM; 36 } 37 38 operator bool() { return first && second; } 39 40 bool first : 1, second : 1; 27 bool widenFirst : 1, widenSecond : 1; 41 28 }; 42 29 } // namespace ResolvExpr -
src/ResolvExpr/typeops.h
r98a8290 r0e315a5 18 18 #include <vector> 19 19 20 #include "Cost.h"21 #include "TypeEnvironment.h"22 #include "WidenMode.h"23 20 #include "AST/Fwd.hpp" 24 21 #include "AST/Node.hpp" … … 29 26 #include "SynTree/Type.h" 30 27 #include "SymTab/Indexer.h" 28 #include "Cost.h" 29 #include "TypeEnvironment.h" 31 30 32 31 namespace ResolvExpr { … … 118 117 // in CommonType.cc 119 118 Type * commonType( Type *type1, Type *type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ); 120 const ast::Type * commonType(121 const ast::Type * type1, const ast::Type * type2, WidenMode widen,122 const ast::SymbolTable & symtab, ast::TypeEnvironment & env, const ast::OpenVarSet & open );123 119 124 120 // in PolyCost.cc … … 145 141 const ast::Expr * referenceToRvalueConversion( const ast::Expr * expr, Cost & cost ); 146 142 147 // /flatten tuple type into list of types143 // flatten tuple type into list of types 148 144 template< typename OutputIterator > 149 145 void flatten( Type * type, OutputIterator out ) { … … 156 152 } 157 153 } 158 159 /// flatten tuple type into existing list of types160 static inline void flatten(161 const ast::Type * type, std::vector< ast::ptr< ast::Type > > & out162 ) {163 if ( auto tupleType = dynamic_cast< const ast::TupleType * >( type ) ) {164 for ( const ast::Type * t : tupleType->types ) {165 flatten( t, out );166 }167 } else {168 out.emplace_back( type );169 }170 }171 172 /// flatten tuple type into list of types173 static inline std::vector< ast::ptr< ast::Type > > flatten( const ast::Type * type ) {174 std::vector< ast::ptr< ast::Type > > out;175 out.reserve( type->size() );176 flatten( type, out );177 return out;178 }179 154 } // namespace ResolvExpr 180 155 -
src/include/cassert
r98a8290 r0e315a5 10 10 // Created On : Thu Aug 18 13:19:26 2016 11 11 // Last Modified By : Andrew Beach 12 // Last Modified On : Mon Jun 3 13:11:00 201713 // Update Count : 1 812 // Last Modified On : Thu May 23 15:30:00 2017 13 // Update Count : 17 14 14 // 15 15 … … 43 43 #endif 44 44 45 template<typename T, typename U> 45 enum StrictAllowNull {NonNull, AllowNull}; 46 47 template<typename T, StrictAllowNull nullable = NonNull, typename U> 46 48 static inline T strict_dynamic_cast( const U & src ) { 49 if (nullable == AllowNull && src == nullptr) { 50 return nullptr; 51 } 47 52 assert(src); 48 53 T ret = dynamic_cast<T>(src); 49 54 assertf(ret, "%s", toString(src).c_str()); 50 55 return ret; 51 }52 53 template<typename T, decltype(nullptr) null, typename U>54 static inline T strict_dynamic_cast( const U & src ) {55 return src ? strict_dynamic_cast<T, U>( src ) : nullptr;56 56 } 57 57
Note: See TracChangeset
for help on using the changeset viewer.