source: src/AST/TypeSubstitution.hpp @ 172d9342

ADTarm-ehast-experimentalcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 172d9342 was 172d9342, checked in by Michael Brooks <mlbrooks@…>, 5 years ago

added old-to-new conversion for TypeSubstitution?, within a framework for expressions

  • Property mode set to 100644
File size: 7.2 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// TypeSubstitution.h --
8//
9// Author           : Richard C. Bilson
10// Created On       : Mon May 18 07:44:20 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Tue Apr 30 22:52:47 2019
13// Update Count     : 9
14//
15
16#pragma once
17
18#include <cassert>                 // for assert
19#include <list>                    // for list<>::iterator, _List_iterator
20#include <unordered_map>
21#include <unordered_set>
22#include <string>                  // for string, operator!=
23#include <utility>                 // for pair
24
25#include "Fwd.hpp"        // for UniqueId
26#include "ParseNode.hpp"
27#include "Type.hpp"       // for ptr<Type>
28#include "Common/SemanticError.h"  // for SemanticError
29#include "Visitor.hpp"
30#include "Decl.hpp"
31#include "Expr.hpp"
32
33namespace ast {
34
35class TypeSubstitution : public Node {
36  public:
37        TypeSubstitution();
38        template< typename FormalIterator, typename ActualIterator >
39        TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
40        TypeSubstitution( const TypeSubstitution &other );
41        virtual ~TypeSubstitution();
42
43        TypeSubstitution &operator=( const TypeSubstitution &other );
44
45        template< typename SynTreeClass > int apply( SynTreeClass *&input ) const;
46        template< typename SynTreeClass > int applyFree( SynTreeClass *&input ) const;
47
48        void add( std::string formalType, const Type *actualType );
49        void add( const TypeSubstitution &other );
50        void remove( std::string formalType );
51        const Type *lookup( std::string formalType ) const;
52        bool empty() const;
53
54        void addVar( std::string formalExpr, const Expr *actualExpr );
55
56        template< typename FormalIterator, typename ActualIterator >
57        void add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
58
59        /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
60        static TypeSubstitution * newFromExpr( const Expr * expr, const TypeSubstitution * env );
61
62        void normalize();
63
64        const TypeSubstitution * accept( Visitor & v ) const override { return v.visit( this ); }
65
66        TypeSubstitution * clone() const override { return new TypeSubstitution( *this ); }
67
68  private:
69
70        // Mutator that performs the substitution
71        struct Substituter;
72
73        // TODO: worry about traversing into a forall-qualified function type or type decl with assertions
74
75        void initialize( const TypeSubstitution &src, TypeSubstitution &dest );
76
77        template<typename pass_type>
78        friend class Pass;
79
80        typedef std::unordered_map< std::string, ptr<Type> > TypeEnvType;
81        typedef std::unordered_map< std::string, ptr<Expr> > VarEnvType;
82        TypeEnvType typeEnv;
83        VarEnvType varEnv;
84
85  public:
86        // has to come after declaration of typeEnv
87        auto begin()       -> decltype( typeEnv.begin() ) { return typeEnv.begin(); }
88        auto   end()       -> decltype( typeEnv.  end() ) { return typeEnv.  end(); }
89        auto begin() const -> decltype( typeEnv.begin() ) { return typeEnv.begin(); }
90        auto   end() const -> decltype( typeEnv.  end() ) { return typeEnv.  end(); }
91
92        auto beginVar()       -> decltype( varEnv.begin() ) { return varEnv.begin(); }
93        auto   endVar()       -> decltype( varEnv.  end() ) { return varEnv.  end(); }
94        auto beginVar() const -> decltype( varEnv.begin() ) { return varEnv.begin(); }
95        auto   endVar() const -> decltype( varEnv.  end() ) { return varEnv.  end(); }
96};
97
98template< typename FormalIterator, typename ActualIterator >
99void TypeSubstitution::add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
100        // FormalIterator points to a TypeDecl
101        // ActualIterator points to a Type
102        FormalIterator formalIt = formalBegin;
103        ActualIterator actualIt = actualBegin;
104        for ( ; formalIt != formalEnd; ++formalIt, ++actualIt ) {
105                if ( const TypeDecl *formal = formalIt->template as<TypeDecl>() ) {
106                        if ( const TypeExpr *actual = actualIt->template as<TypeExpr>() ) {
107                                if ( formal->name != "" ) {
108                                        typeEnv[ formal->name ] = actual->type;
109                                } // if
110                        } else {
111                                SemanticError( formal, toString( "Attempt to provide non-type parameter: ", toString( *actualIt ).c_str(), " for type parameter " ) );
112                        } // if
113                } else {
114                        // TODO: type check the formal and actual parameters
115                        if ( (*formalIt)->name != "" ) {
116                                varEnv[ (*formalIt)->name ] = *actualIt;
117                        } // if
118                } // if
119        } // for
120}
121
122template< typename FormalIterator, typename ActualIterator >
123TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
124        add( formalBegin, formalEnd, actualBegin );
125}
126
127} // namespace ast
128
129// include needs to happen after TypeSubstitution is defined so that both TypeSubstitution and
130// PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals.
131#include "Pass.hpp"
132
133namespace ast {
134
135// definitition must happen after PassVisitor is included so that WithGuards can be used
136struct TypeSubstitution::Substituter : public WithGuards, public WithVisitorRef<Substituter> {
137
138                Substituter( const TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {}
139
140#if TIME_TO_CONVERT_PASSES
141
142                Type * postmutate( TypeInstType * aggregateUseType );
143                Expression * postmutate( NameExpr * nameExpr );
144
145                /// Records type variable bindings from forall-statements
146                void premutate( Type * type );
147                /// Records type variable bindings from forall-statements and instantiations of generic types
148                template< typename TypeClass > void handleAggregateType( TypeClass * type );
149
150                void premutate( StructInstType * aggregateUseType );
151                void premutate( UnionInstType * aggregateUseType );
152
153#endif
154
155                const TypeSubstitution & sub;
156                int subCount = 0;
157                bool freeOnly;
158                typedef std::unordered_set< std::string > BoundVarsType;
159                BoundVarsType boundVars;
160
161};
162
163template< typename SynTreeClass >
164int TypeSubstitution::apply( SynTreeClass *&input ) const {
165        assert( input );
166        Pass<Substituter> sub( *this, false );
167        input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
168        assert( input );
169///     std::cerr << "substitution result is: ";
170///     newType->print( std::cerr );
171///     std::cerr << std::endl;
172        return sub.pass.subCount;
173}
174
175template< typename SynTreeClass >
176int TypeSubstitution::applyFree( SynTreeClass *&input ) const {
177        assert( input );
178        Pass<Substituter> sub( *this, true );
179        input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) );
180        assert( input );
181///     std::cerr << "substitution result is: ";
182///     newType->print( std::cerr );
183///     std::cerr << std::endl;
184        return sub.pass.subCount;
185}
186
187/// Instantiate each member of the context given the actual parameters specified, and store the
188/// instantiations for use by the indexer
189template< typename FormalIterator, typename ActualIterator, typename MemberIterator, typename OutputIterator >
190void applySubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actual, MemberIterator memberBegin, MemberIterator memberEnd, OutputIterator out ) {
191        TypeSubstitution sub = TypeSubstitution( formalBegin, formalEnd, actual );
192        for ( auto i = memberBegin; i != memberEnd; ++i ) {
193                sub.apply( *i );
194                *out++ = *i;
195        } // for
196}
197
198} // namespace ast
199
200// Local Variables: //
201// tab-width: 4 //
202// mode: c++ //
203// compile-command: "make install" //
204// End: //
Note: See TracBrowser for help on using the repository browser.