source: src/AST/TypeSubstitution.hpp @ 41c8312

Last change on this file since 41c8312 was b1f2007, checked in by Peter A. Buhr <pabuhr@…>, 6 months ago

first attempt at simplifying SemanticError? and its usage

  • Property mode set to 100644
File size: 6.0 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 : Mon Dec 11 16:07:30 2023
13// Update Count     : 15
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"
28#include "Common/SemanticError.h"  // for SemanticError
29#include "Visitor.hpp"
30#include "Decl.hpp"
31#include "Expr.hpp"
32#include "Node.hpp"
33
34namespace ast {
35
36class TypeSubstitution : public Node {
37  public:
38        TypeSubstitution();
39        template< typename FormalContainer, typename ActualContainer >
40        TypeSubstitution( FormalContainer formals, ActualContainer actuals );
41        template< typename FormalIterator, typename ActualIterator >
42        TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
43        TypeSubstitution( const TypeSubstitution &other );
44        virtual ~TypeSubstitution();
45
46        TypeSubstitution &operator=( const TypeSubstitution &other );
47
48        template< typename node_t >
49        struct ApplyResult {
50                ast::ptr<node_t> node;
51                int count;
52        };
53
54        template< typename node_t >
55        ApplyResult<node_t> apply( const node_t * input ) const {
56                ApplyResult<Node> ret = applyBase( input, false );
57                return { ret.node.strict_as<node_t>(), ret.count };
58        }
59
60        template< typename node_t, enum Node::ref_type ref_t >
61        int apply( ptr_base< node_t, ref_t > & input ) const {
62                ApplyResult<Node> ret = applyBase( input.get(), false );
63                input = ret.node.strict_as<node_t>();
64                return ret.count;
65        }
66
67        template< typename node_t >
68        ApplyResult<node_t> applyFree( const node_t * input ) const {
69                ApplyResult<Node> ret = applyBase( input, true );
70                return { ret.node.strict_as<node_t>(), ret.count };
71        }
72
73        template< typename node_t, enum Node::ref_type ref_t >
74        int applyFree( ptr_base< node_t, ref_t > & input ) const {
75                ApplyResult<Node> ret = applyBase( input.get(), true );
76                input = ret.node.strict_as<node_t>();
77                return ret.count;
78        }
79
80        void add( const TypeInstType * formalType, const Type *actualType );
81        void add( const TypeEnvKey & key, const Type *actualType );
82        void add( const TypeSubstitution &other );
83        void remove( const TypeInstType * formalType );
84        const Type *lookup( const TypeEnvKey & formalType ) const;
85        const Type *lookup( const TypeInstType * formalType ) const;
86        bool empty() const;
87
88        template< typename FormalContainer, typename ActualContainer >
89        void addAll( FormalContainer formals, ActualContainer actuals );
90        template< typename FormalIterator, typename ActualIterator >
91        void addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
92
93        /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
94        static TypeSubstitution * newFromExpr( const Expr * expr, const TypeSubstitution * env );
95
96        void normalize();
97
98        const TypeSubstitution * accept( Visitor & v ) const override { return v.visit( this ); }
99
100        TypeSubstitution * clone() const override { return new TypeSubstitution( *this ); }
101
102  private:
103
104        // Mutator that performs the substitution
105        struct Substituter;
106        ApplyResult<Node> applyBase( const Node * input, bool isFree ) const;
107
108        // TODO: worry about traversing into a forall-qualified function type or type decl with assertions
109
110        void initialize( const TypeSubstitution &src, TypeSubstitution &dest );
111
112        template<typename core_t>
113        friend class Pass;
114
115        typedef std::unordered_map< TypeEnvKey, ptr<Type> > TypeMap;
116        TypeMap typeMap;
117
118  public:
119        // has to come after declaration of typeMap
120        auto begin()       -> decltype( typeMap.begin() ) { return typeMap.begin(); }
121        auto   end()       -> decltype( typeMap.  end() ) { return typeMap.  end(); }
122        auto begin() const -> decltype( typeMap.begin() ) { return typeMap.begin(); }
123        auto   end() const -> decltype( typeMap.  end() ) { return typeMap.  end(); }
124
125};
126
127template< typename FormalContainer, typename ActualContainer >
128TypeSubstitution::TypeSubstitution( FormalContainer formals, ActualContainer actuals ) {
129        assert( formals.size() == actuals.size() );
130        addAll( formals.begin(), formals.end(), actuals.begin() );
131}
132
133template< typename FormalIterator, typename ActualIterator >
134TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
135        addAll( formalBegin, formalEnd, actualBegin );
136}
137
138template< typename FormalContainer, typename ActualContainer >
139void TypeSubstitution::addAll( FormalContainer formals, ActualContainer actuals ) {
140        assert( formals.size() == actuals.size() );
141        addAll( formals.begin(), formals.end(), actuals.begin() );
142}
143
144// this is the only place where type parameters outside a function formal may be substituted.
145template< typename FormalIterator, typename ActualIterator >
146void TypeSubstitution::addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
147        // FormalIterator points to a TypeDecl
148        // ActualIterator points to a Type
149        FormalIterator formalIt = formalBegin;
150        ActualIterator actualIt = actualBegin;
151        for ( ; formalIt != formalEnd; ++formalIt, ++actualIt ) {
152                if ( const TypeDecl *formal = formalIt->template as<TypeDecl>() ) {
153                        if ( const TypeExpr *actual = actualIt->template as<TypeExpr>() ) {
154                                if ( formal->name != "" ) {
155                                        typeMap[ formal ] = actual->type;
156                                } // if
157                        } else {
158                                SemanticError( formal->location, "Attempt to provide non-type parameter %s for type parameter %s",
159                                                           toString( *actualIt ).c_str(), formal->name.c_str() );
160                        } // if
161                } else {
162                        // Is this an error?
163                } // if
164        } // for
165}
166
167} // namespace ast
168
169// Local Variables: //
170// tab-width: 4 //
171// mode: c++ //
172// compile-command: "make install" //
173// End: //
Note: See TracBrowser for help on using the repository browser.