| [51587aa] | 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 | // | 
|---|
| [540de412] | 7 | // GenPoly.cc -- | 
|---|
| [51587aa] | 8 | // | 
|---|
|  | 9 | // Author           : Richard C. Bilson | 
|---|
|  | 10 | // Created On       : Mon May 18 07:44:20 2015 | 
|---|
| [3606fe4] | 11 | // Last Modified By : Andrew Beach | 
|---|
| [63d1ebe] | 12 | // Last Modified On : Mon Oct 24 15:19:00 2022 | 
|---|
|  | 13 | // Update Count     : 17 | 
|---|
| [51587aa] | 14 | // | 
|---|
| [51b73452] | 15 |  | 
|---|
|  | 16 | #include "GenPoly.h" | 
|---|
| [ffad73a] | 17 |  | 
|---|
| [08fc48f] | 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 |  | 
|---|
| [a0d1f1c] | 26 | #include "AST/Expr.hpp" | 
|---|
| [d76c588] | 27 | #include "AST/Type.hpp" | 
|---|
| [a0d1f1c] | 28 | #include "AST/TypeSubstitution.hpp" | 
|---|
| [08fc48f] | 29 | #include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it... | 
|---|
|  | 30 | #include "ResolvExpr/typeops.h"         // for flatten | 
|---|
|  | 31 | #include "SynTree/Constant.h"           // for Constant | 
|---|
|  | 32 | #include "SynTree/Expression.h"         // for Expression, TypeExpr, Constan... | 
|---|
|  | 33 | #include "SynTree/Type.h"               // for Type, StructInstType, UnionIn... | 
|---|
|  | 34 | #include "SynTree/TypeSubstitution.h"   // for TypeSubstitution | 
|---|
| [51b73452] | 35 |  | 
|---|
| [b1a6d6b] | 36 | using namespace std; | 
|---|
| [51b73452] | 37 |  | 
|---|
|  | 38 | namespace GenPoly { | 
|---|
| [ffad73a] | 39 | namespace { | 
|---|
| [0f889a77] | 40 | /// Checks a parameter list for polymorphic parameters; will substitute according to env if present | 
|---|
|  | 41 | bool hasPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) { | 
|---|
|  | 42 | for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) { | 
|---|
|  | 43 | TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); | 
|---|
| [7350ff97] | 44 | assertf(paramType, "Aggregate parameters should be type expressions"); | 
|---|
| [0f889a77] | 45 | if ( isPolyType( paramType->get_type(), env ) ) return true; | 
|---|
|  | 46 | } | 
|---|
|  | 47 | return false; | 
|---|
|  | 48 | } | 
|---|
|  | 49 |  | 
|---|
| [3df4cd9] | 50 | bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const ast::TypeSubstitution * env ) { | 
|---|
|  | 51 | for ( auto ¶m : params ) { | 
|---|
|  | 52 | auto paramType = param.as<ast::TypeExpr>(); | 
|---|
|  | 53 | assertf( paramType, "Aggregate parameters should be type expressions" ); | 
|---|
|  | 54 | if ( isPolyType( paramType->type, env ) ) return true; | 
|---|
| [490fb92e] | 55 | } | 
|---|
|  | 56 | return false; | 
|---|
|  | 57 | } | 
|---|
|  | 58 |  | 
|---|
| [0f889a77] | 59 | /// Checks a parameter list for polymorphic parameters from tyVars; will substitute according to env if present | 
|---|
| [ffad73a] | 60 | bool hasPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) { | 
|---|
|  | 61 | for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) { | 
|---|
|  | 62 | TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); | 
|---|
| [5a3ac84] | 63 | assertf(paramType, "Aggregate parameters should be type expressions"); | 
|---|
| [ffad73a] | 64 | if ( isPolyType( paramType->get_type(), tyVars, env ) ) return true; | 
|---|
|  | 65 | } | 
|---|
|  | 66 | return false; | 
|---|
|  | 67 | } | 
|---|
| [3bb195cb] | 68 |  | 
|---|
| [3df4cd9] | 69 | bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const TypeVarMap & typeVars, const ast::TypeSubstitution * env ) { | 
|---|
|  | 70 | for ( auto & param : params ) { | 
|---|
|  | 71 | auto paramType = param.as<ast::TypeExpr>(); | 
|---|
|  | 72 | assertf( paramType, "Aggregate parameters should be type expressions" ); | 
|---|
|  | 73 | if ( isPolyType( paramType->type, typeVars, env ) ) return true; | 
|---|
|  | 74 | } | 
|---|
|  | 75 | return false; | 
|---|
|  | 76 | } | 
|---|
|  | 77 |  | 
|---|
| [3bb195cb] | 78 | /// Checks a parameter list for dynamic-layout parameters from tyVars; will substitute according to env if present | 
|---|
|  | 79 | bool hasDynParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) { | 
|---|
|  | 80 | for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) { | 
|---|
|  | 81 | TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); | 
|---|
| [5a3ac84] | 82 | assertf(paramType, "Aggregate parameters should be type expressions"); | 
|---|
| [3bb195cb] | 83 | if ( isDynType( paramType->get_type(), tyVars, env ) ) return true; | 
|---|
|  | 84 | } | 
|---|
|  | 85 | return false; | 
|---|
|  | 86 | } | 
|---|
| [5a3ac84] | 87 |  | 
|---|
| [c8837e5] | 88 | bool hasDynParams( | 
|---|
|  | 89 | const std::vector<ast::ptr<ast::Expr>> & params, | 
|---|
|  | 90 | const TypeVarMap & typeVars, | 
|---|
|  | 91 | const ast::TypeSubstitution * subst ) { | 
|---|
|  | 92 | for ( ast::ptr<ast::Expr> const & paramExpr : params ) { | 
|---|
|  | 93 | auto param = paramExpr.as<ast::TypeExpr>(); | 
|---|
|  | 94 | assertf( param, "Aggregate parameters should be type expressions." ); | 
|---|
|  | 95 | if ( isDynType( param->type.get(), typeVars, subst ) ) { | 
|---|
| [3606fe4] | 96 | return true; | 
|---|
|  | 97 | } | 
|---|
|  | 98 | } | 
|---|
|  | 99 | return false; | 
|---|
|  | 100 | } | 
|---|
|  | 101 |  | 
|---|
| [5a3ac84] | 102 | /// Checks a parameter list for inclusion of polymorphic parameters; will substitute according to env if present | 
|---|
|  | 103 | bool includesPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) { | 
|---|
|  | 104 | for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) { | 
|---|
|  | 105 | TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); | 
|---|
|  | 106 | assertf(paramType, "Aggregate parameters should be type expressions"); | 
|---|
|  | 107 | if ( includesPolyType( paramType->get_type(), env ) ) return true; | 
|---|
|  | 108 | } | 
|---|
|  | 109 | return false; | 
|---|
|  | 110 | } | 
|---|
|  | 111 |  | 
|---|
|  | 112 | /// Checks a parameter list for inclusion of polymorphic parameters from tyVars; will substitute according to env if present | 
|---|
|  | 113 | bool includesPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) { | 
|---|
|  | 114 | for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) { | 
|---|
|  | 115 | TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param ); | 
|---|
|  | 116 | assertf(paramType, "Aggregate parameters should be type expressions"); | 
|---|
|  | 117 | if ( includesPolyType( paramType->get_type(), tyVars, env ) ) return true; | 
|---|
|  | 118 | } | 
|---|
|  | 119 | return false; | 
|---|
|  | 120 | } | 
|---|
| [c2ad3c9] | 121 | } | 
|---|
| [83de11e] | 122 |  | 
|---|
| [c2ad3c9] | 123 | Type* replaceTypeInst( Type* type, const TypeSubstitution* env ) { | 
|---|
|  | 124 | if ( ! env ) return type; | 
|---|
|  | 125 | if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) { | 
|---|
|  | 126 | Type *newType = env->lookup( typeInst->get_name() ); | 
|---|
|  | 127 | if ( newType ) return newType; | 
|---|
| [e24955a] | 128 | } | 
|---|
| [c2ad3c9] | 129 | return type; | 
|---|
| [ffad73a] | 130 | } | 
|---|
| [0f889a77] | 131 |  | 
|---|
| [4da152a] | 132 | const Type* replaceTypeInst( const Type* type, const TypeSubstitution* env ) { | 
|---|
|  | 133 | if ( ! env ) return type; | 
|---|
|  | 134 | if ( auto typeInst = dynamic_cast< const TypeInstType* >( type ) ) { | 
|---|
|  | 135 | Type *newType = env->lookup( typeInst->get_name() ); | 
|---|
|  | 136 | if ( newType ) return newType; | 
|---|
|  | 137 | } | 
|---|
|  | 138 | return type; | 
|---|
|  | 139 | } | 
|---|
|  | 140 |  | 
|---|
| [490fb92e] | 141 | const ast::Type * replaceTypeInst(const ast::Type * type, const ast::TypeSubstitution * env) { | 
|---|
|  | 142 | if (!env) return type; | 
|---|
| [75f6a5f] | 143 | if ( auto typeInst = dynamic_cast<const ast::TypeInstType*>(type) ) { | 
|---|
| [3e5dd913] | 144 | auto newType = env->lookup(typeInst); | 
|---|
| [490fb92e] | 145 | if (newType) return newType; | 
|---|
|  | 146 | } | 
|---|
|  | 147 | return type; | 
|---|
|  | 148 | } | 
|---|
|  | 149 |  | 
|---|
| [0f889a77] | 150 | Type *isPolyType( Type *type, const TypeSubstitution *env ) { | 
|---|
| [e24955a] | 151 | type = replaceTypeInst( type, env ); | 
|---|
| [83de11e] | 152 |  | 
|---|
| [ca35c51] | 153 | if ( dynamic_cast< TypeInstType * >( type ) ) { | 
|---|
| [0f889a77] | 154 | return type; | 
|---|
| [5f61546] | 155 | } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { | 
|---|
|  | 156 | return isPolyType( arrayType->base, env ); | 
|---|
| [0f889a77] | 157 | } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) { | 
|---|
|  | 158 | if ( hasPolyParams( structType->get_parameters(), env ) ) return type; | 
|---|
|  | 159 | } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) { | 
|---|
|  | 160 | if ( hasPolyParams( unionType->get_parameters(), env ) ) return type; | 
|---|
|  | 161 | } | 
|---|
|  | 162 | return 0; | 
|---|
|  | 163 | } | 
|---|
| [540de412] | 164 |  | 
|---|
| [490fb92e] | 165 | const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env) { | 
|---|
|  | 166 | type = replaceTypeInst( type, env ); | 
|---|
|  | 167 |  | 
|---|
|  | 168 | if ( dynamic_cast< const ast::TypeInstType * >( type ) ) { | 
|---|
|  | 169 | return type; | 
|---|
|  | 170 | } else if ( auto arrayType = dynamic_cast< const ast::ArrayType * >( type ) ) { | 
|---|
|  | 171 | return isPolyType( arrayType->base, env ); | 
|---|
|  | 172 | } else if ( auto structType = dynamic_cast< const ast::StructInstType* >( type ) ) { | 
|---|
|  | 173 | if ( hasPolyParams( structType->params, env ) ) return type; | 
|---|
|  | 174 | } else if ( auto unionType = dynamic_cast< const ast::UnionInstType* >( type ) ) { | 
|---|
|  | 175 | if ( hasPolyParams( unionType->params, env ) ) return type; | 
|---|
|  | 176 | } | 
|---|
|  | 177 | return 0; | 
|---|
|  | 178 | } | 
|---|
|  | 179 |  | 
|---|
| [ffad73a] | 180 | Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) { | 
|---|
| [e24955a] | 181 | type = replaceTypeInst( type, env ); | 
|---|
| [83de11e] | 182 |  | 
|---|
| [e56cfdb0] | 183 | if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) { | 
|---|
| [e9b5043] | 184 | if ( tyVars.contains( typeInst->get_name() ) ) { | 
|---|
| [ffad73a] | 185 | return type; | 
|---|
| [0f889a77] | 186 | } | 
|---|
| [5f61546] | 187 | } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { | 
|---|
|  | 188 | return isPolyType( arrayType->base, tyVars, env ); | 
|---|
| [ffad73a] | 189 | } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) { | 
|---|
|  | 190 | if ( hasPolyParams( structType->get_parameters(), tyVars, env ) ) return type; | 
|---|
|  | 191 | } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) { | 
|---|
|  | 192 | if ( hasPolyParams( unionType->get_parameters(), tyVars, env ) ) return type; | 
|---|
|  | 193 | } | 
|---|
|  | 194 | return 0; | 
|---|
| [01aeade] | 195 | } | 
|---|
| [b1a6d6b] | 196 |  | 
|---|
| [c8837e5] | 197 | const ast::Type * isPolyType( const ast::Type * type, | 
|---|
|  | 198 | const TypeVarMap & typeVars, const ast::TypeSubstitution * subst ) { | 
|---|
|  | 199 | type = replaceTypeInst( type, subst ); | 
|---|
|  | 200 |  | 
|---|
|  | 201 | if ( auto inst = dynamic_cast< const ast::TypeInstType * >( type ) ) { | 
|---|
| [e9b5043] | 202 | if ( typeVars.contains( *inst ) ) return type; | 
|---|
| [c8837e5] | 203 | } else if ( auto array = dynamic_cast< const ast::ArrayType * >( type ) ) { | 
|---|
| [3df4cd9] | 204 | return isPolyType( array->base, typeVars, subst ); | 
|---|
| [c8837e5] | 205 | } else if ( auto sue = dynamic_cast< const ast::StructInstType * >( type ) ) { | 
|---|
| [3df4cd9] | 206 | if ( hasPolyParams( sue->params, typeVars, subst ) ) return type; | 
|---|
| [c8837e5] | 207 | } else if ( auto sue = dynamic_cast< const ast::UnionInstType * >( type ) ) { | 
|---|
| [3df4cd9] | 208 | if ( hasPolyParams( sue->params, typeVars, subst ) ) return type; | 
|---|
| [c8837e5] | 209 | } | 
|---|
|  | 210 | return nullptr; | 
|---|
|  | 211 | } | 
|---|
|  | 212 |  | 
|---|
| [33a7b6d] | 213 | ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) { | 
|---|
| [3bb195cb] | 214 | type = replaceTypeInst( type, env ); | 
|---|
|  | 215 |  | 
|---|
|  | 216 | if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) { | 
|---|
|  | 217 | auto var = tyVars.find( typeInst->get_name() ); | 
|---|
| [2c57025] | 218 | if ( var != tyVars.end() && var->second.isComplete ) { | 
|---|
| [33a7b6d] | 219 | return typeInst; | 
|---|
| [3bb195cb] | 220 | } | 
|---|
|  | 221 | } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) { | 
|---|
| [33a7b6d] | 222 | if ( hasDynParams( structType->get_parameters(), tyVars, env ) ) return structType; | 
|---|
| [3bb195cb] | 223 | } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) { | 
|---|
| [33a7b6d] | 224 | if ( hasDynParams( unionType->get_parameters(), tyVars, env ) ) return unionType; | 
|---|
| [3bb195cb] | 225 | } | 
|---|
|  | 226 | return 0; | 
|---|
|  | 227 | } | 
|---|
|  | 228 |  | 
|---|
| [c8837e5] | 229 | const ast::BaseInstType * isDynType( | 
|---|
|  | 230 | const ast::Type * type, const TypeVarMap & typeVars, | 
|---|
|  | 231 | const ast::TypeSubstitution * subst ) { | 
|---|
|  | 232 | type = replaceTypeInst( type, subst ); | 
|---|
|  | 233 |  | 
|---|
|  | 234 | if ( auto inst = dynamic_cast<ast::TypeInstType const *>( type ) ) { | 
|---|
| [63d1ebe] | 235 | auto var = typeVars.find( *inst ); | 
|---|
| [c8837e5] | 236 | if ( var != typeVars.end() && var->second.isComplete ) { | 
|---|
| [75f6a5f] | 237 | return inst; | 
|---|
| [3606fe4] | 238 | } | 
|---|
| [c8837e5] | 239 | } else if ( auto inst = dynamic_cast<ast::StructInstType const *>( type ) ) { | 
|---|
|  | 240 | if ( hasDynParams( inst->params, typeVars, subst ) ) { | 
|---|
|  | 241 | return inst; | 
|---|
|  | 242 | } | 
|---|
|  | 243 | } else if ( auto inst = dynamic_cast<ast::UnionInstType const *>( type ) ) { | 
|---|
|  | 244 | if ( hasDynParams( inst->params, typeVars, subst ) ) { | 
|---|
|  | 245 | return inst; | 
|---|
|  | 246 | } | 
|---|
| [3606fe4] | 247 | } | 
|---|
| [c8837e5] | 248 | return nullptr; | 
|---|
|  | 249 | } | 
|---|
| [3606fe4] | 250 |  | 
|---|
| [3bb195cb] | 251 | ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &forallTypes ) { | 
|---|
|  | 252 | if ( function->get_returnVals().empty() ) return 0; | 
|---|
| [8c49c0e] | 253 |  | 
|---|
| [3bb195cb] | 254 | return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes ); | 
|---|
|  | 255 | } | 
|---|
|  | 256 |  | 
|---|
| [c8837e5] | 257 | const ast::BaseInstType *isDynRet( | 
|---|
|  | 258 | const ast::FunctionType * type, const TypeVarMap & typeVars ) { | 
|---|
|  | 259 | if ( type->returns.empty() ) return nullptr; | 
|---|
|  | 260 |  | 
|---|
|  | 261 | return isDynType( type->returns.front(), typeVars ); | 
|---|
|  | 262 | } | 
|---|
|  | 263 |  | 
|---|
| [3bb195cb] | 264 | ReferenceToType *isDynRet( FunctionType *function ) { | 
|---|
|  | 265 | if ( function->get_returnVals().empty() ) return 0; | 
|---|
|  | 266 |  | 
|---|
| [2c57025] | 267 | TyVarMap forallTypes( TypeDecl::Data{} ); | 
|---|
| [3bb195cb] | 268 | makeTyVarMap( function, forallTypes ); | 
|---|
|  | 269 | return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes ); | 
|---|
|  | 270 | } | 
|---|
|  | 271 |  | 
|---|
| [c97b448] | 272 | const ast::BaseInstType *isDynRet( const ast::FunctionType * func ) { | 
|---|
|  | 273 | if ( func->returns.empty() ) return nullptr; | 
|---|
|  | 274 |  | 
|---|
|  | 275 | TypeVarMap forallTypes = { ast::TypeData() }; | 
|---|
|  | 276 | makeTypeVarMap( func, forallTypes ); | 
|---|
|  | 277 | return isDynType( func->returns.front(), forallTypes ); | 
|---|
|  | 278 | } | 
|---|
|  | 279 |  | 
|---|
| [3bb195cb] | 280 | bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) { | 
|---|
|  | 281 | //              if ( ! adaptee->get_returnVals().empty() && isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) { | 
|---|
|  | 282 | //                      return true; | 
|---|
|  | 283 | //              } // if | 
|---|
|  | 284 | if ( isDynRet( adaptee, tyVars ) ) return true; | 
|---|
| [8c49c0e] | 285 |  | 
|---|
| [3bb195cb] | 286 | for ( std::list< DeclarationWithType* >::const_iterator innerArg = adaptee->get_parameters().begin(); innerArg != adaptee->get_parameters().end(); ++innerArg ) { | 
|---|
|  | 287 | //                      if ( isPolyType( (*innerArg)->get_type(), tyVars ) ) { | 
|---|
|  | 288 | if ( isDynType( (*innerArg)->get_type(), tyVars ) ) { | 
|---|
|  | 289 | return true; | 
|---|
|  | 290 | } // if | 
|---|
|  | 291 | } // for | 
|---|
|  | 292 | return false; | 
|---|
|  | 293 | } | 
|---|
|  | 294 |  | 
|---|
| [c8837e5] | 295 | bool needsAdapter( | 
|---|
|  | 296 | ast::FunctionType const * adaptee, const TypeVarMap & typeVars ) { | 
|---|
|  | 297 | if ( isDynRet( adaptee, typeVars ) ) return true; | 
|---|
|  | 298 |  | 
|---|
|  | 299 | for ( auto param : adaptee->params ) { | 
|---|
|  | 300 | if ( isDynType( param, typeVars ) ) { | 
|---|
|  | 301 | return true; | 
|---|
|  | 302 | } | 
|---|
|  | 303 | } | 
|---|
|  | 304 | return false; | 
|---|
|  | 305 | } | 
|---|
|  | 306 |  | 
|---|
| [0f889a77] | 307 | Type *isPolyPtr( Type *type, const TypeSubstitution *env ) { | 
|---|
| [e24955a] | 308 | type = replaceTypeInst( type, env ); | 
|---|
| [83de11e] | 309 |  | 
|---|
| [0f889a77] | 310 | if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) { | 
|---|
|  | 311 | return isPolyType( ptr->get_base(), env ); | 
|---|
| [e24955a] | 312 | } | 
|---|
| [0f889a77] | 313 | return 0; | 
|---|
|  | 314 | } | 
|---|
| [540de412] | 315 |  | 
|---|
| [ffad73a] | 316 | Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) { | 
|---|
| [e24955a] | 317 | type = replaceTypeInst( type, env ); | 
|---|
| [83de11e] | 318 |  | 
|---|
| [ffad73a] | 319 | if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) { | 
|---|
|  | 320 | return isPolyType( ptr->get_base(), tyVars, env ); | 
|---|
| [e24955a] | 321 | } | 
|---|
| [ffad73a] | 322 | return 0; | 
|---|
| [bdf1954] | 323 | } | 
|---|
|  | 324 |  | 
|---|
| [c97b448] | 325 | const ast::Type * isPolyPtr( | 
|---|
|  | 326 | const ast::Type * type, const TypeVarMap & typeVars, | 
|---|
|  | 327 | const ast::TypeSubstitution * typeSubs ) { | 
|---|
|  | 328 | type = replaceTypeInst( type, typeSubs ); | 
|---|
|  | 329 |  | 
|---|
|  | 330 | if ( auto * ptr = dynamic_cast<ast::PointerType const *>( type ) ) { | 
|---|
|  | 331 | return isPolyType( ptr->base, typeVars, typeSubs ); | 
|---|
|  | 332 | } | 
|---|
|  | 333 | return nullptr; | 
|---|
|  | 334 | } | 
|---|
|  | 335 |  | 
|---|
| [8488c715] | 336 | Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) { | 
|---|
|  | 337 | int dummy; | 
|---|
|  | 338 | if ( ! levels ) { levels = &dummy; } | 
|---|
|  | 339 | *levels = 0; | 
|---|
|  | 340 |  | 
|---|
|  | 341 | while ( true ) { | 
|---|
| [e24955a] | 342 | type = replaceTypeInst( type, env ); | 
|---|
| [83de11e] | 343 |  | 
|---|
| [8488c715] | 344 | if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) { | 
|---|
|  | 345 | type = ptr->get_base(); | 
|---|
|  | 346 | ++(*levels); | 
|---|
|  | 347 | } else break; | 
|---|
| [05d47278] | 348 | } | 
|---|
|  | 349 |  | 
|---|
|  | 350 | return isPolyType( type, env ); | 
|---|
|  | 351 | } | 
|---|
| [540de412] | 352 |  | 
|---|
| [8488c715] | 353 | Type * hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels, const TypeSubstitution *env ) { | 
|---|
|  | 354 | int dummy; | 
|---|
|  | 355 | if ( ! levels ) { levels = &dummy; } | 
|---|
|  | 356 | *levels = 0; | 
|---|
|  | 357 |  | 
|---|
|  | 358 | while ( true ) { | 
|---|
| [e24955a] | 359 | type = replaceTypeInst( type, env ); | 
|---|
| [83de11e] | 360 |  | 
|---|
| [8488c715] | 361 | if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) { | 
|---|
|  | 362 | type = ptr->get_base(); | 
|---|
|  | 363 | ++(*levels); | 
|---|
|  | 364 | } else break; | 
|---|
| [05d47278] | 365 | } | 
|---|
|  | 366 |  | 
|---|
|  | 367 | return isPolyType( type, tyVars, env ); | 
|---|
|  | 368 | } | 
|---|
|  | 369 |  | 
|---|
| [c8837e5] | 370 | ast::Type const * hasPolyBase( | 
|---|
|  | 371 | ast::Type const * type, const TypeVarMap & typeVars, | 
|---|
|  | 372 | int * levels, const ast::TypeSubstitution * subst ) { | 
|---|
|  | 373 | int level_count = 0; | 
|---|
|  | 374 |  | 
|---|
|  | 375 | while ( true ) { | 
|---|
|  | 376 | type = replaceTypeInst( type, subst ); | 
|---|
|  | 377 |  | 
|---|
|  | 378 | if ( auto ptr = dynamic_cast<ast::PointerType const *>( type ) ) { | 
|---|
|  | 379 | type = ptr->base; | 
|---|
|  | 380 | ++level_count; | 
|---|
|  | 381 | } else { | 
|---|
|  | 382 | break; | 
|---|
|  | 383 | } | 
|---|
|  | 384 | } | 
|---|
|  | 385 |  | 
|---|
|  | 386 | if ( nullptr != levels ) { *levels = level_count; } | 
|---|
|  | 387 | return isPolyType( type, typeVars, subst ); | 
|---|
|  | 388 | } | 
|---|
|  | 389 |  | 
|---|
| [5a3ac84] | 390 | bool includesPolyType( Type *type, const TypeSubstitution *env ) { | 
|---|
|  | 391 | type = replaceTypeInst( type, env ); | 
|---|
|  | 392 |  | 
|---|
|  | 393 | if ( dynamic_cast< TypeInstType * >( type ) ) { | 
|---|
|  | 394 | return true; | 
|---|
|  | 395 | } else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) { | 
|---|
|  | 396 | if ( includesPolyType( pointerType->get_base(), env ) ) return true; | 
|---|
|  | 397 | } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) { | 
|---|
|  | 398 | if ( includesPolyParams( structType->get_parameters(), env ) ) return true; | 
|---|
|  | 399 | } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) { | 
|---|
|  | 400 | if ( includesPolyParams( unionType->get_parameters(), env ) ) return true; | 
|---|
|  | 401 | } | 
|---|
|  | 402 | return false; | 
|---|
|  | 403 | } | 
|---|
|  | 404 |  | 
|---|
|  | 405 | bool includesPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) { | 
|---|
|  | 406 | type = replaceTypeInst( type, env ); | 
|---|
|  | 407 |  | 
|---|
|  | 408 | if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) { | 
|---|
| [e9b5043] | 409 | if ( tyVars.contains( typeInstType->get_name() ) ) { | 
|---|
| [5a3ac84] | 410 | return true; | 
|---|
|  | 411 | } | 
|---|
|  | 412 | } else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) { | 
|---|
|  | 413 | if ( includesPolyType( pointerType->get_base(), tyVars, env ) ) return true; | 
|---|
|  | 414 | } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) { | 
|---|
|  | 415 | if ( includesPolyParams( structType->get_parameters(), tyVars, env ) ) return true; | 
|---|
|  | 416 | } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) { | 
|---|
|  | 417 | if ( includesPolyParams( unionType->get_parameters(), tyVars, env ) ) return true; | 
|---|
|  | 418 | } | 
|---|
|  | 419 | return false; | 
|---|
|  | 420 | } | 
|---|
|  | 421 |  | 
|---|
| [7754cde] | 422 | FunctionType * getFunctionType( Type *ty ) { | 
|---|
|  | 423 | PointerType *ptrType; | 
|---|
|  | 424 | if ( ( ptrType = dynamic_cast< PointerType* >( ty ) ) ) { | 
|---|
|  | 425 | return dynamic_cast< FunctionType* >( ptrType->get_base() ); // pointer if FunctionType, NULL otherwise | 
|---|
|  | 426 | } else { | 
|---|
|  | 427 | return dynamic_cast< FunctionType* >( ty ); // pointer if FunctionType, NULL otherwise | 
|---|
|  | 428 | } | 
|---|
|  | 429 | } | 
|---|
|  | 430 |  | 
|---|
| [d76c588] | 431 | const ast::FunctionType * getFunctionType( const ast::Type * ty ) { | 
|---|
|  | 432 | if ( auto pty = dynamic_cast< const ast::PointerType * >( ty ) ) { | 
|---|
|  | 433 | return pty->base.as< ast::FunctionType >(); | 
|---|
|  | 434 | } else { | 
|---|
|  | 435 | return dynamic_cast< const ast::FunctionType * >( ty ); | 
|---|
|  | 436 | } | 
|---|
|  | 437 | } | 
|---|
|  | 438 |  | 
|---|
| [8488c715] | 439 | VariableExpr * getBaseVar( Expression *expr, int *levels ) { | 
|---|
|  | 440 | int dummy; | 
|---|
|  | 441 | if ( ! levels ) { levels = &dummy; } | 
|---|
|  | 442 | *levels = 0; | 
|---|
|  | 443 |  | 
|---|
|  | 444 | while ( true ) { | 
|---|
|  | 445 | if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( expr ) ) { | 
|---|
|  | 446 | return varExpr; | 
|---|
| [d9f1b2d] | 447 | } else if ( MemberExpr *memberExpr = dynamic_cast< MemberExpr* >( expr ) ) { | 
|---|
|  | 448 | expr = memberExpr->get_aggregate(); | 
|---|
| [8488c715] | 449 | } else if ( AddressExpr *addressExpr = dynamic_cast< AddressExpr* >( expr ) ) { | 
|---|
|  | 450 | expr = addressExpr->get_arg(); | 
|---|
|  | 451 | } else if ( UntypedExpr *untypedExpr = dynamic_cast< UntypedExpr* >( expr ) ) { | 
|---|
|  | 452 | // look for compiler-inserted dereference operator | 
|---|
|  | 453 | NameExpr *fn = dynamic_cast< NameExpr* >( untypedExpr->get_function() ); | 
|---|
|  | 454 | if ( ! fn || fn->get_name() != std::string("*?") ) return 0; | 
|---|
|  | 455 | expr = *untypedExpr->begin_args(); | 
|---|
| [540de412] | 456 | } else if ( CommaExpr *commaExpr = dynamic_cast< CommaExpr* >( expr ) ) { | 
|---|
|  | 457 | // copy constructors insert comma exprs, look at second argument which contains the variable | 
|---|
|  | 458 | expr = commaExpr->get_arg2(); | 
|---|
|  | 459 | continue; | 
|---|
| [1aa4b71] | 460 | } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( expr ) ) { | 
|---|
|  | 461 | int lvl1; | 
|---|
|  | 462 | int lvl2; | 
|---|
|  | 463 | VariableExpr * var1 = getBaseVar( condExpr->get_arg2(), &lvl1 ); | 
|---|
|  | 464 | VariableExpr * var2 = getBaseVar( condExpr->get_arg3(), &lvl2 ); | 
|---|
|  | 465 | if ( lvl1 == lvl2 && var1 && var2 && var1->get_var() == var2->get_var() ) { | 
|---|
|  | 466 | *levels = lvl1; | 
|---|
|  | 467 | return var1; | 
|---|
|  | 468 | } | 
|---|
|  | 469 | break; | 
|---|
| [8488c715] | 470 | } else break; | 
|---|
|  | 471 |  | 
|---|
|  | 472 | ++(*levels); | 
|---|
|  | 473 | } | 
|---|
|  | 474 |  | 
|---|
|  | 475 | return 0; | 
|---|
| [05d47278] | 476 | } | 
|---|
|  | 477 |  | 
|---|
| [5a3ac84] | 478 | namespace { | 
|---|
|  | 479 | /// Checks if is a pointer to D | 
|---|
|  | 480 | template<typename D, typename B> | 
|---|
|  | 481 | bool is( const B* p ) { return type_index{typeid(D)} == type_index{typeid(*p)}; } | 
|---|
|  | 482 |  | 
|---|
|  | 483 | /// Converts to a pointer to D without checking for safety | 
|---|
|  | 484 | template<typename D, typename B> | 
|---|
|  | 485 | inline D* as( B* p ) { return reinterpret_cast<D*>(p); } | 
|---|
|  | 486 |  | 
|---|
| [3606fe4] | 487 | template<typename D, typename B> | 
|---|
|  | 488 | inline D const * as( B const * p ) { | 
|---|
|  | 489 | return reinterpret_cast<D const *>( p ); | 
|---|
|  | 490 | } | 
|---|
|  | 491 |  | 
|---|
| [5a3ac84] | 492 | /// Flattens a declaration list | 
|---|
|  | 493 | template<typename Output> | 
|---|
|  | 494 | void flattenList( list< DeclarationWithType* > src, Output out ) { | 
|---|
|  | 495 | for ( DeclarationWithType* decl : src ) { | 
|---|
|  | 496 | ResolvExpr::flatten( decl->get_type(), out ); | 
|---|
|  | 497 | } | 
|---|
|  | 498 | } | 
|---|
|  | 499 |  | 
|---|
|  | 500 | /// Flattens a list of types | 
|---|
|  | 501 | template<typename Output> | 
|---|
|  | 502 | void flattenList( list< Type* > src, Output out ) { | 
|---|
|  | 503 | for ( Type* ty : src ) { | 
|---|
|  | 504 | ResolvExpr::flatten( ty, out ); | 
|---|
|  | 505 | } | 
|---|
|  | 506 | } | 
|---|
|  | 507 |  | 
|---|
| [7b5694d] | 508 | /// Flattens a list of types. | 
|---|
|  | 509 | // There is another flattenList in Unify. | 
|---|
| [3606fe4] | 510 | void flattenList( vector<ast::ptr<ast::Type>> const & src, | 
|---|
|  | 511 | vector<ast::ptr<ast::Type>> & out ) { | 
|---|
|  | 512 | for ( auto const & type : src ) { | 
|---|
|  | 513 | ResolvExpr::flatten( type, out ); | 
|---|
|  | 514 | } | 
|---|
|  | 515 | } | 
|---|
|  | 516 |  | 
|---|
| [5a3ac84] | 517 | /// Checks if two lists of parameters are equal up to polymorphic substitution. | 
|---|
|  | 518 | bool paramListsPolyCompatible( const list< Expression* >& aparams, const list< Expression* >& bparams ) { | 
|---|
|  | 519 | if ( aparams.size() != bparams.size() ) return false; | 
|---|
|  | 520 |  | 
|---|
|  | 521 | for ( list< Expression* >::const_iterator at = aparams.begin(), bt = bparams.begin(); | 
|---|
|  | 522 | at != aparams.end(); ++at, ++bt ) { | 
|---|
|  | 523 | TypeExpr *aparam = dynamic_cast< TypeExpr* >(*at); | 
|---|
|  | 524 | assertf(aparam, "Aggregate parameters should be type expressions"); | 
|---|
|  | 525 | TypeExpr *bparam = dynamic_cast< TypeExpr* >(*bt); | 
|---|
|  | 526 | assertf(bparam, "Aggregate parameters should be type expressions"); | 
|---|
|  | 527 |  | 
|---|
| [cccc534] | 528 | // xxx - might need to let VoidType be a wildcard here too; could have some voids | 
|---|
| [5a3ac84] | 529 | // stuffed in for dtype-statics. | 
|---|
|  | 530 | // if ( is<VoidType>( aparam->get_type() ) || is<VoidType>( bparam->get_type() ) ) continue; | 
|---|
|  | 531 | if ( ! typesPolyCompatible( aparam->get_type(), bparam->get_type() ) ) return false; | 
|---|
|  | 532 | } | 
|---|
| [cccc534] | 533 |  | 
|---|
| [5a3ac84] | 534 | return true; | 
|---|
|  | 535 | } | 
|---|
| [3606fe4] | 536 |  | 
|---|
|  | 537 | bool paramListsPolyCompatible( | 
|---|
|  | 538 | std::vector<ast::ptr<ast::Expr>> const & lparams, | 
|---|
|  | 539 | std::vector<ast::ptr<ast::Expr>> const & rparams ) { | 
|---|
|  | 540 | if ( lparams.size() != rparams.size() ) { | 
|---|
|  | 541 | return false; | 
|---|
|  | 542 | } | 
|---|
|  | 543 |  | 
|---|
|  | 544 | for ( auto lparam = lparams.begin(), rparam = rparams.begin() ; | 
|---|
|  | 545 | lparam != lparams.end() ; ++lparam, ++rparam ) { | 
|---|
|  | 546 | ast::TypeExpr const * lexpr = lparam->as<ast::TypeExpr>(); | 
|---|
|  | 547 | assertf( lexpr, "Aggregate parameters should be type expressions" ); | 
|---|
|  | 548 | ast::TypeExpr const * rexpr = rparam->as<ast::TypeExpr>(); | 
|---|
|  | 549 | assertf( rexpr, "Aggregate parameters should be type expressions" ); | 
|---|
|  | 550 |  | 
|---|
|  | 551 | // xxx - might need to let VoidType be a wildcard here too; could have some voids | 
|---|
|  | 552 | // stuffed in for dtype-statics. | 
|---|
|  | 553 | // if ( is<VoidType>( lexpr->type() ) || is<VoidType>( bparam->get_type() ) ) continue; | 
|---|
|  | 554 | if ( !typesPolyCompatible( lexpr->type, rexpr->type ) ) { | 
|---|
|  | 555 | return false; | 
|---|
|  | 556 | } | 
|---|
|  | 557 | } | 
|---|
|  | 558 |  | 
|---|
|  | 559 | return true; | 
|---|
|  | 560 | } | 
|---|
| [5a3ac84] | 561 | } | 
|---|
|  | 562 |  | 
|---|
|  | 563 | bool typesPolyCompatible( Type *a, Type *b ) { | 
|---|
|  | 564 | type_index aid{ typeid(*a) }; | 
|---|
|  | 565 | // polymorphic types always match | 
|---|
|  | 566 | if ( aid == type_index{typeid(TypeInstType)} ) return true; | 
|---|
| [cccc534] | 567 |  | 
|---|
| [5a3ac84] | 568 | type_index bid{ typeid(*b) }; | 
|---|
|  | 569 | // polymorphic types always match | 
|---|
|  | 570 | if ( bid == type_index{typeid(TypeInstType)} ) return true; | 
|---|
| [cccc534] | 571 |  | 
|---|
| [5a3ac84] | 572 | // can't match otherwise if different types | 
|---|
|  | 573 | if ( aid != bid ) return false; | 
|---|
|  | 574 |  | 
|---|
|  | 575 | // recurse through type structure (conditions borrowed from Unify.cc) | 
|---|
|  | 576 | if ( aid == type_index{typeid(BasicType)} ) { | 
|---|
|  | 577 | return as<BasicType>(a)->get_kind() == as<BasicType>(b)->get_kind(); | 
|---|
|  | 578 | } else if ( aid == type_index{typeid(PointerType)} ) { | 
|---|
|  | 579 | PointerType *ap = as<PointerType>(a), *bp = as<PointerType>(b); | 
|---|
|  | 580 |  | 
|---|
|  | 581 | // void pointers should match any other pointer type | 
|---|
|  | 582 | return is<VoidType>( ap->get_base() ) || is<VoidType>( bp->get_base() ) | 
|---|
|  | 583 | || typesPolyCompatible( ap->get_base(), bp->get_base() ); | 
|---|
| [682dcae] | 584 | } else if ( aid == type_index{typeid(ReferenceType)} ) { | 
|---|
|  | 585 | ReferenceType *ap = as<ReferenceType>(a), *bp = as<ReferenceType>(b); | 
|---|
|  | 586 | return is<VoidType>( ap->get_base() ) || is<VoidType>( bp->get_base() ) | 
|---|
|  | 587 | || typesPolyCompatible( ap->get_base(), bp->get_base() ); | 
|---|
| [5a3ac84] | 588 | } else if ( aid == type_index{typeid(ArrayType)} ) { | 
|---|
|  | 589 | ArrayType *aa = as<ArrayType>(a), *ba = as<ArrayType>(b); | 
|---|
|  | 590 |  | 
|---|
|  | 591 | if ( aa->get_isVarLen() ) { | 
|---|
|  | 592 | if ( ! ba->get_isVarLen() ) return false; | 
|---|
|  | 593 | } else { | 
|---|
|  | 594 | if ( ba->get_isVarLen() ) return false; | 
|---|
|  | 595 |  | 
|---|
|  | 596 | ConstantExpr *ad = dynamic_cast<ConstantExpr*>( aa->get_dimension() ); | 
|---|
|  | 597 | ConstantExpr *bd = dynamic_cast<ConstantExpr*>( ba->get_dimension() ); | 
|---|
| [cccc534] | 598 | if ( ad && bd | 
|---|
| [5a3ac84] | 599 | && ad->get_constant()->get_value() != bd->get_constant()->get_value() ) | 
|---|
|  | 600 | return false; | 
|---|
|  | 601 | } | 
|---|
|  | 602 |  | 
|---|
|  | 603 | return typesPolyCompatible( aa->get_base(), ba->get_base() ); | 
|---|
|  | 604 | } else if ( aid == type_index{typeid(FunctionType)} ) { | 
|---|
|  | 605 | FunctionType *af = as<FunctionType>(a), *bf = as<FunctionType>(b); | 
|---|
|  | 606 |  | 
|---|
|  | 607 | vector<Type*> aparams, bparams; | 
|---|
|  | 608 | flattenList( af->get_parameters(), back_inserter( aparams ) ); | 
|---|
|  | 609 | flattenList( bf->get_parameters(), back_inserter( bparams ) ); | 
|---|
|  | 610 | if ( aparams.size() != bparams.size() ) return false; | 
|---|
|  | 611 |  | 
|---|
|  | 612 | vector<Type*> areturns, breturns; | 
|---|
|  | 613 | flattenList( af->get_returnVals(), back_inserter( areturns ) ); | 
|---|
|  | 614 | flattenList( bf->get_returnVals(), back_inserter( breturns ) ); | 
|---|
|  | 615 | if ( areturns.size() != breturns.size() ) return false; | 
|---|
|  | 616 |  | 
|---|
|  | 617 | for ( unsigned i = 0; i < aparams.size(); ++i ) { | 
|---|
|  | 618 | if ( ! typesPolyCompatible( aparams[i], bparams[i] ) ) return false; | 
|---|
|  | 619 | } | 
|---|
|  | 620 | for ( unsigned i = 0; i < areturns.size(); ++i ) { | 
|---|
|  | 621 | if ( ! typesPolyCompatible( areturns[i], breturns[i] ) ) return false; | 
|---|
|  | 622 | } | 
|---|
|  | 623 | return true; | 
|---|
|  | 624 | } else if ( aid == type_index{typeid(StructInstType)} ) { | 
|---|
|  | 625 | StructInstType *aa = as<StructInstType>(a), *ba = as<StructInstType>(b); | 
|---|
|  | 626 |  | 
|---|
|  | 627 | if ( aa->get_name() != ba->get_name() ) return false; | 
|---|
|  | 628 | return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() ); | 
|---|
|  | 629 | } else if ( aid == type_index{typeid(UnionInstType)} ) { | 
|---|
|  | 630 | UnionInstType *aa = as<UnionInstType>(a), *ba = as<UnionInstType>(b); | 
|---|
|  | 631 |  | 
|---|
|  | 632 | if ( aa->get_name() != ba->get_name() ) return false; | 
|---|
|  | 633 | return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() ); | 
|---|
|  | 634 | } else if ( aid == type_index{typeid(EnumInstType)} ) { | 
|---|
|  | 635 | return as<EnumInstType>(a)->get_name() == as<EnumInstType>(b)->get_name(); | 
|---|
|  | 636 | } else if ( aid == type_index{typeid(TraitInstType)} ) { | 
|---|
|  | 637 | return as<TraitInstType>(a)->get_name() == as<TraitInstType>(b)->get_name(); | 
|---|
|  | 638 | } else if ( aid == type_index{typeid(TupleType)} ) { | 
|---|
|  | 639 | TupleType *at = as<TupleType>(a), *bt = as<TupleType>(b); | 
|---|
|  | 640 |  | 
|---|
|  | 641 | vector<Type*> atypes, btypes; | 
|---|
|  | 642 | flattenList( at->get_types(), back_inserter( atypes ) ); | 
|---|
|  | 643 | flattenList( bt->get_types(), back_inserter( btypes ) ); | 
|---|
|  | 644 | if ( atypes.size() != btypes.size() ) return false; | 
|---|
|  | 645 |  | 
|---|
|  | 646 | for ( unsigned i = 0; i < atypes.size(); ++i ) { | 
|---|
|  | 647 | if ( ! typesPolyCompatible( atypes[i], btypes[i] ) ) return false; | 
|---|
|  | 648 | } | 
|---|
|  | 649 | return true; | 
|---|
|  | 650 | } else return true; // VoidType, VarArgsType, ZeroType & OneType just need the same type | 
|---|
|  | 651 | } | 
|---|
|  | 652 |  | 
|---|
| [3606fe4] | 653 | bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs ) { | 
|---|
|  | 654 | type_index const lid = typeid(*lhs); | 
|---|
|  | 655 |  | 
|---|
|  | 656 | // Polymorphic types always match: | 
|---|
|  | 657 | if ( type_index(typeid(ast::TypeInstType)) == lid ) return true; | 
|---|
|  | 658 |  | 
|---|
|  | 659 | type_index const rid = typeid(*rhs); | 
|---|
|  | 660 | if ( type_index(typeid(ast::TypeInstType)) == rid ) return true; | 
|---|
|  | 661 |  | 
|---|
|  | 662 | // All other types only match if they are the same type: | 
|---|
|  | 663 | if ( lid != rid ) return false; | 
|---|
|  | 664 |  | 
|---|
|  | 665 | // So remaining types can be examined case by case. | 
|---|
|  | 666 | // Recurse through type structure (conditions borrowed from Unify.cc). | 
|---|
|  | 667 |  | 
|---|
|  | 668 | if ( type_index(typeid(ast::BasicType)) == lid ) { | 
|---|
|  | 669 | return as<ast::BasicType>(lhs)->kind == as<ast::BasicType>(rhs)->kind; | 
|---|
|  | 670 | } else if ( type_index(typeid(ast::PointerType)) == lid ) { | 
|---|
|  | 671 | ast::PointerType const * l = as<ast::PointerType>(lhs); | 
|---|
|  | 672 | ast::PointerType const * r = as<ast::PointerType>(rhs); | 
|---|
|  | 673 |  | 
|---|
|  | 674 | // void pointers should match any other pointer type. | 
|---|
|  | 675 | return is<ast::VoidType>( l->base.get() ) | 
|---|
|  | 676 | || is<ast::VoidType>( r->base.get() ) | 
|---|
|  | 677 | || typesPolyCompatible( l->base.get(), r->base.get() ); | 
|---|
|  | 678 | } else if ( type_index(typeid(ast::ReferenceType)) == lid ) { | 
|---|
|  | 679 | ast::ReferenceType const * l = as<ast::ReferenceType>(lhs); | 
|---|
|  | 680 | ast::ReferenceType const * r = as<ast::ReferenceType>(rhs); | 
|---|
|  | 681 |  | 
|---|
|  | 682 | // void references should match any other reference type. | 
|---|
|  | 683 | return is<ast::VoidType>( l->base.get() ) | 
|---|
|  | 684 | || is<ast::VoidType>( r->base.get() ) | 
|---|
|  | 685 | || typesPolyCompatible( l->base.get(), r->base.get() ); | 
|---|
|  | 686 | } else if ( type_index(typeid(ast::ArrayType)) == lid ) { | 
|---|
|  | 687 | ast::ArrayType const * l = as<ast::ArrayType>(lhs); | 
|---|
|  | 688 | ast::ArrayType const * r = as<ast::ArrayType>(rhs); | 
|---|
|  | 689 |  | 
|---|
|  | 690 | if ( l->isVarLen ) { | 
|---|
|  | 691 | if ( !r->isVarLen ) return false; | 
|---|
|  | 692 | } else { | 
|---|
|  | 693 | if ( r->isVarLen ) return false; | 
|---|
|  | 694 |  | 
|---|
|  | 695 | auto lc = l->dimension.as<ast::ConstantExpr>(); | 
|---|
|  | 696 | auto rc = r->dimension.as<ast::ConstantExpr>(); | 
|---|
|  | 697 | if ( lc && rc && lc->intValue() != rc->intValue() ) { | 
|---|
|  | 698 | return false; | 
|---|
|  | 699 | } | 
|---|
|  | 700 | } | 
|---|
|  | 701 |  | 
|---|
|  | 702 | return typesPolyCompatible( l->base.get(), r->base.get() ); | 
|---|
|  | 703 | } else if ( type_index(typeid(ast::FunctionType)) == lid ) { | 
|---|
|  | 704 | ast::FunctionType const * l = as<ast::FunctionType>(lhs); | 
|---|
|  | 705 | ast::FunctionType const * r = as<ast::FunctionType>(rhs); | 
|---|
|  | 706 |  | 
|---|
|  | 707 | std::vector<ast::ptr<ast::Type>> lparams, rparams; | 
|---|
|  | 708 | flattenList( l->params, lparams ); | 
|---|
|  | 709 | flattenList( r->params, rparams ); | 
|---|
|  | 710 | if ( lparams.size() != rparams.size() ) return false; | 
|---|
|  | 711 | for ( unsigned i = 0; i < lparams.size(); ++i ) { | 
|---|
|  | 712 | if ( !typesPolyCompatible( lparams[i], rparams[i] ) ) return false; | 
|---|
|  | 713 | } | 
|---|
|  | 714 |  | 
|---|
|  | 715 | std::vector<ast::ptr<ast::Type>> lrets, rrets; | 
|---|
|  | 716 | flattenList( l->returns, lrets ); | 
|---|
|  | 717 | flattenList( r->returns, rrets ); | 
|---|
|  | 718 | if ( lrets.size() != rrets.size() ) return false; | 
|---|
|  | 719 | for ( unsigned i = 0; i < lrets.size(); ++i ) { | 
|---|
|  | 720 | if ( !typesPolyCompatible( lrets[i], rrets[i] ) ) return false; | 
|---|
|  | 721 | } | 
|---|
|  | 722 | return true; | 
|---|
|  | 723 | } else if ( type_index(typeid(ast::StructInstType)) == lid ) { | 
|---|
|  | 724 | ast::StructInstType const * l = as<ast::StructInstType>(lhs); | 
|---|
|  | 725 | ast::StructInstType const * r = as<ast::StructInstType>(rhs); | 
|---|
|  | 726 |  | 
|---|
|  | 727 | if ( l->name != r->name ) return false; | 
|---|
|  | 728 | return paramListsPolyCompatible( l->params, r->params ); | 
|---|
|  | 729 | } else if ( type_index(typeid(ast::UnionInstType)) == lid ) { | 
|---|
|  | 730 | ast::UnionInstType const * l = as<ast::UnionInstType>(lhs); | 
|---|
|  | 731 | ast::UnionInstType const * r = as<ast::UnionInstType>(rhs); | 
|---|
|  | 732 |  | 
|---|
|  | 733 | if ( l->name != r->name ) return false; | 
|---|
|  | 734 | return paramListsPolyCompatible( l->params, r->params ); | 
|---|
|  | 735 | } else if ( type_index(typeid(ast::EnumInstType)) == lid ) { | 
|---|
|  | 736 | ast::EnumInstType const * l = as<ast::EnumInstType>(lhs); | 
|---|
|  | 737 | ast::EnumInstType const * r = as<ast::EnumInstType>(rhs); | 
|---|
|  | 738 |  | 
|---|
|  | 739 | return l->name == r->name; | 
|---|
|  | 740 | } else if ( type_index(typeid(ast::TraitInstType)) == lid ) { | 
|---|
|  | 741 | ast::TraitInstType const * l = as<ast::TraitInstType>(lhs); | 
|---|
|  | 742 | ast::TraitInstType const * r = as<ast::TraitInstType>(rhs); | 
|---|
|  | 743 |  | 
|---|
|  | 744 | return l->name == r->name; | 
|---|
|  | 745 | } else if ( type_index(typeid(ast::TupleType)) == lid ) { | 
|---|
|  | 746 | ast::TupleType const * l = as<ast::TupleType>(lhs); | 
|---|
|  | 747 | ast::TupleType const * r = as<ast::TupleType>(rhs); | 
|---|
|  | 748 |  | 
|---|
|  | 749 | std::vector<ast::ptr<ast::Type>> ltypes, rtypes; | 
|---|
|  | 750 | flattenList( l->types, ( ltypes ) ); | 
|---|
|  | 751 | flattenList( r->types, ( rtypes ) ); | 
|---|
|  | 752 | if ( ltypes.size() != rtypes.size() ) return false; | 
|---|
|  | 753 |  | 
|---|
|  | 754 | for ( unsigned i = 0 ; i < ltypes.size() ; ++i ) { | 
|---|
|  | 755 | if ( !typesPolyCompatible( ltypes[i], rtypes[i] ) ) return false; | 
|---|
|  | 756 | } | 
|---|
|  | 757 | return true; | 
|---|
|  | 758 | // The remaining types (VoidType, VarArgsType, ZeroType & OneType) | 
|---|
|  | 759 | // have no variation so will always be equal. | 
|---|
|  | 760 | } else { | 
|---|
|  | 761 | return true; | 
|---|
|  | 762 | } | 
|---|
|  | 763 | } | 
|---|
|  | 764 |  | 
|---|
| [02fdb8e] | 765 | bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) { | 
|---|
| [ae1b9ea] | 766 | // is parameter is not polymorphic, don't need to box | 
|---|
|  | 767 | if ( ! isPolyType( param, exprTyVars ) ) return false; | 
|---|
|  | 768 | Type * newType = arg->clone(); | 
|---|
|  | 769 | if ( env ) env->apply( newType ); | 
|---|
|  | 770 | std::unique_ptr<Type> manager( newType ); | 
|---|
|  | 771 | // if the argument's type is polymorphic, we don't need to box again! | 
|---|
|  | 772 | return ! isPolyType( newType ); | 
|---|
|  | 773 | } | 
|---|
|  | 774 |  | 
|---|
| [c8837e5] | 775 | bool needsBoxing( const ast::Type * param, const ast::Type * arg, | 
|---|
|  | 776 | const TypeVarMap & typeVars, const ast::TypeSubstitution * subst ) { | 
|---|
|  | 777 | // Don't need to box if the parameter is not polymorphic. | 
|---|
|  | 778 | if ( !isPolyType( param, typeVars ) ) return false; | 
|---|
|  | 779 |  | 
|---|
|  | 780 | ast::ptr<ast::Type> newType = arg; | 
|---|
|  | 781 | if ( subst ) { | 
|---|
|  | 782 | int count = subst->apply( newType ); | 
|---|
|  | 783 | (void)count; | 
|---|
| [490fb92e] | 784 | } | 
|---|
| [c8837e5] | 785 | // Only need to box if the argument is not also polymorphic. | 
|---|
|  | 786 | return !isPolyType( newType ); | 
|---|
|  | 787 | } | 
|---|
| [490fb92e] | 788 |  | 
|---|
| [02fdb8e] | 789 | bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) { | 
|---|
| [ae1b9ea] | 790 | FunctionType * function = getFunctionType( appExpr->function->result ); | 
|---|
|  | 791 | assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() ); | 
|---|
|  | 792 | TyVarMap exprTyVars( TypeDecl::Data{} ); | 
|---|
|  | 793 | makeTyVarMap( function, exprTyVars ); | 
|---|
|  | 794 | return needsBoxing( param, arg, exprTyVars, env ); | 
|---|
|  | 795 | } | 
|---|
|  | 796 |  | 
|---|
| [c8837e5] | 797 | bool needsBoxing( | 
|---|
|  | 798 | const ast::Type * param, const ast::Type * arg, | 
|---|
|  | 799 | const ast::ApplicationExpr * expr, | 
|---|
|  | 800 | const ast::TypeSubstitution * subst ) { | 
|---|
|  | 801 | const ast::FunctionType * function = getFunctionType( expr->func->result ); | 
|---|
|  | 802 | assertf( function, "ApplicationExpr has non-function type: %s", toString( expr->func->result ).c_str() ); | 
|---|
| [93c10de] | 803 | TypeVarMap exprTyVars = { ast::TypeData() }; | 
|---|
| [c8837e5] | 804 | makeTypeVarMap( function, exprTyVars ); | 
|---|
|  | 805 | return needsBoxing( param, arg, exprTyVars, subst ); | 
|---|
|  | 806 | } | 
|---|
| [490fb92e] | 807 |  | 
|---|
| [2c57025] | 808 | void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) { | 
|---|
| [7ba1324] | 809 | tyVarMap.insert( tyVar->name, TypeDecl::Data{ tyVar } ); | 
|---|
| [2c57025] | 810 | } | 
|---|
|  | 811 |  | 
|---|
| [c97b448] | 812 | void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) { | 
|---|
|  | 813 | typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) ); | 
|---|
|  | 814 | } | 
|---|
|  | 815 |  | 
|---|
| [c8837e5] | 816 | void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars ) { | 
|---|
| [c97b448] | 817 | typeVars.insert( ast::TypeEnvKey( *type ), ast::TypeData( type->base ) ); | 
|---|
| [c8837e5] | 818 | } | 
|---|
| [490fb92e] | 819 |  | 
|---|
| [aadc9a4] | 820 | void makeTyVarMap( Type *type, TyVarMap &tyVarMap ) { | 
|---|
| [8c49c0e] | 821 | for ( Type::ForallList::const_iterator tyVar = type->get_forall().begin(); tyVar != type->get_forall().end(); ++tyVar ) { | 
|---|
| [aadc9a4] | 822 | assert( *tyVar ); | 
|---|
| [2c57025] | 823 | addToTyVarMap( *tyVar, tyVarMap ); | 
|---|
| [aadc9a4] | 824 | } | 
|---|
|  | 825 | if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) { | 
|---|
|  | 826 | makeTyVarMap( pointer->get_base(), tyVarMap ); | 
|---|
|  | 827 | } | 
|---|
|  | 828 | } | 
|---|
| [540de412] | 829 |  | 
|---|
| [c8837e5] | 830 | void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars ) { | 
|---|
|  | 831 | if ( auto func = dynamic_cast<ast::FunctionType const *>( type ) ) { | 
|---|
|  | 832 | for ( auto & typeVar : func->forall ) { | 
|---|
|  | 833 | assert( typeVar ); | 
|---|
|  | 834 | addToTypeVarMap( typeVar, typeVars ); | 
|---|
| [490fb92e] | 835 | } | 
|---|
|  | 836 | } | 
|---|
| [c8837e5] | 837 | if ( auto pointer = dynamic_cast<ast::PointerType const *>( type ) ) { | 
|---|
|  | 838 | makeTypeVarMap( pointer->base, typeVars ); | 
|---|
|  | 839 | } | 
|---|
|  | 840 | } | 
|---|
| [490fb92e] | 841 |  | 
|---|
| [c97b448] | 842 | void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars ) { | 
|---|
|  | 843 | for ( auto & typeDecl : decl->type_params ) { | 
|---|
|  | 844 | addToTypeVarMap( typeDecl, typeVars ); | 
|---|
|  | 845 | } | 
|---|
|  | 846 | } | 
|---|
|  | 847 |  | 
|---|
| [01aeade] | 848 | void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) { | 
|---|
|  | 849 | for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) { | 
|---|
|  | 850 | os << i->first << " (" << i->second << ") "; | 
|---|
|  | 851 | } // for | 
|---|
|  | 852 | os << std::endl; | 
|---|
|  | 853 | } | 
|---|
| [ffad73a] | 854 |  | 
|---|
| [51b73452] | 855 | } // namespace GenPoly | 
|---|
| [01aeade] | 856 |  | 
|---|
| [51587aa] | 857 | // Local Variables: // | 
|---|
|  | 858 | // tab-width: 4 // | 
|---|
|  | 859 | // mode: c++ // | 
|---|
|  | 860 | // compile-command: "make install" // | 
|---|
|  | 861 | // End: // | 
|---|