source: src/ResolvExpr/CurrentObject.cc @ 6ea85b22

Last change on this file since 6ea85b22 was c6b4432, checked in by Andrew Beach <ajbeach@…>, 12 months ago

Remove BaseSyntaxNode? and clean-up.

  • Property mode set to 100644
File size: 20.6 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// CurrentObject.h --
8//
9// Author           : Rob Schluntz
10// Created On       : Tue Jun 13 15:28:32 2017
11// Last Modified By : Andrew Beach
12// Last Modified On : Mon Apr 10  9:40:00 2023
13// Update Count     : 18
14//
15
16#include <stddef.h>                    // for size_t
17#include <cassert>                     // for assertf, assert, safe_dynamic_...
18#include <deque>
19#include <iostream>                    // for ostream, operator<<, basic_ost...
20#include <stack>                       // for stack
21#include <string>                      // for string, operator<<, allocator
22
23#include "AST/Copy.hpp"                // for shallowCopy
24#include "AST/Expr.hpp"                // for InitAlternative
25#include "AST/GenericSubstitution.hpp" // for genericSubstitution
26#include "AST/Init.hpp"                // for Designation
27#include "AST/Node.hpp"                // for readonly
28#include "AST/Print.hpp"               // for readonly
29#include "AST/Type.hpp"
30#include "Common/Eval.h"               // for eval
31#include "Common/Indenter.h"           // for Indenter, operator<<
32#include "Common/SemanticError.h"      // for SemanticError
33#include "Common/utility.h"            // for toString
34#include "CurrentObject.h"
35
36#if 0
37#define PRINT(x) x
38#else
39#define PRINT(x)
40#endif
41
42namespace ast {
43        /// Iterates members of a type by initializer.
44        class MemberIterator {
45        public:
46                virtual ~MemberIterator() {}
47
48                /// Internal set position based on iterator ranges.
49                virtual void setPosition(
50                        std::deque< ptr< Expr > >::const_iterator it,
51                        std::deque< ptr< Expr > >::const_iterator end ) = 0;
52
53                /// Walks the current object using the given designators as a guide.
54                void setPosition( const std::deque< ptr< Expr > > & designators ) {
55                        setPosition( designators.begin(), designators.end() );
56                }
57
58                /// Retrieve the list of possible (Type,Designation) pairs for the
59                /// current position in the current object.
60                virtual std::deque< InitAlternative > operator* () const = 0;
61
62                /// True if the iterator is not currently at the end.
63                virtual operator bool() const = 0;
64
65                /// Moves the iterator by one member in the current object.
66                virtual MemberIterator & bigStep() = 0;
67
68                /// Moves the iterator by one member in the current subobject.
69                virtual MemberIterator & smallStep() = 0;
70
71                /// The type of the current object.
72                virtual const Type * getType() = 0;
73
74                /// The type of the current subobject.
75                virtual const Type * getNext() = 0;
76
77                /// Helper for operator*; aggregates must add designator to each init
78                /// alternative, but adding designators in operator* creates duplicates.
79                virtual std::deque< InitAlternative > first() const = 0;
80        };
81
82        /// create a new MemberIterator that traverses a type correctly
83        MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );
84
85        /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
86        class SimpleIterator final : public MemberIterator {
87                CodeLocation location;
88                const Type * type = nullptr;
89        public:
90                SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
91
92                void setPosition(
93                        std::deque< ptr< Expr > >::const_iterator begin,
94                        std::deque< ptr< Expr > >::const_iterator end
95                ) override {
96                        if ( begin != end ) {
97                                SemanticError( location, "Un-designated initializer given non-empty designator" );
98                        }
99                }
100
101                std::deque< InitAlternative > operator* () const override { return first(); }
102
103                operator bool() const override { return type; }
104
105                SimpleIterator & bigStep() override { return smallStep(); }
106                SimpleIterator & smallStep() override {
107                        type = nullptr;  // empty on increment because no members
108                        return *this;
109                }
110
111                const Type * getType() override { return type; }
112
113                const Type * getNext() override { return type; }
114
115                std::deque< InitAlternative > first() const override {
116                        if ( type ) return { InitAlternative{ type, new Designation{ location } } };
117                        return {};
118                }
119        };
120
121        /// Iterates over an indexed type:
122        class IndexIterator : public MemberIterator {
123        protected:
124                CodeLocation location;
125                size_t index = 0;
126                size_t size = 0;
127                std::unique_ptr<MemberIterator> memberIter;
128        public:
129                IndexIterator( const CodeLocation & loc, size_t size ) :
130                        location( loc ), size( size )
131                {}
132
133                void setPosition( const Expr * expr ) {
134                        // need to permit integer-constant-expressions, including: integer constants,
135                        // enumeration constants, character constants, sizeof expressions, alignof expressions,
136                        // cast expressions
137
138                        auto arg = eval( expr );
139                        assertf( arg.hasKnownValue, "Non-evaluable expression made it to IndexIterator" );
140                        index = arg.knownValue;
141
142                        // if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
143                        //      try {
144                        //              index = constExpr->intValue();
145                        //      } catch ( SemanticErrorException & ) {
146                        //              SemanticError( expr, "Constant expression of non-integral type in array designator: " );
147                        //      }
148                        // } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
149                        //      setPosition( castExpr->arg );
150                        // } else if ( dynamic_cast< const SizeofExpr * >( expr ) || dynamic_cast< const AlignofExpr * >( expr ) ) {
151                        //      index = 0;
152                        // } else {
153                        //      assertf( false, "2 bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
154                        // }
155                }
156
157                void setPosition(
158                        std::deque<ast::ptr<ast::Expr>>::const_iterator begin,
159                        std::deque<ast::ptr<ast::Expr>>::const_iterator end
160                ) override {
161                        if ( begin == end ) return;
162
163                        setPosition( *begin );
164                        memberIter->setPosition( ++begin, end );
165                }
166
167                std::deque< InitAlternative > operator* () const override { return first(); }
168
169                operator bool() const override { return index < size; }
170        };
171
172        /// Iterates over the members of array types:
173        class ArrayIterator final : public IndexIterator {
174                const ArrayType * array = nullptr;
175                const Type * base = nullptr;
176
177                size_t getSize( const Expr * expr ) {
178                        auto res = eval( expr );
179                        if ( !res.hasKnownValue ) {
180                                SemanticError( location, toString( "Array designator must be a constant expression: ", expr ) );
181                        }
182                        return res.knownValue;
183                }
184
185        public:
186                ArrayIterator( const CodeLocation & loc, const ArrayType * at ) :
187                                IndexIterator( loc, getSize( at->dimension) ),
188                                array( at ), base( at->base ) {
189                        PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
190                        memberIter.reset( createMemberIterator( loc, base ) );
191                        if ( at->isVarLen ) {
192                                SemanticError( location, at, "VLA initialization does not support @=: " );
193                        }
194                }
195
196                ArrayIterator & bigStep() override {
197                        PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
198                        ++index;
199                        memberIter.reset( index < size ? createMemberIterator( location, base ) : nullptr );
200                        return *this;
201                }
202
203                ArrayIterator & smallStep() override {
204                        PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
205                        if ( memberIter ) {
206                                PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
207                                memberIter->smallStep();
208                                if ( *memberIter ) {
209                                        PRINT( std::cerr << "has valid member iter" << std::endl; )
210                                        return *this;
211                                }
212                        }
213                        return bigStep();
214                }
215
216                const Type * getType() override { return array; }
217
218                const Type * getNext() override { return base; }
219
220                std::deque< InitAlternative > first() const override {
221                        PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
222                        if ( memberIter && *memberIter ) {
223                                std::deque< InitAlternative > ret = memberIter->first();
224                                for ( InitAlternative & alt : ret ) {
225                                        alt.designation.get_and_mutate()->designators.emplace_front( ConstantExpr::from_ulong( location, index ) );
226                                }
227                                return ret;
228                        }
229                        return {};
230                }
231        };
232
233        class AggregateIterator : public MemberIterator {
234        protected:
235                using MemberList = std::vector< ptr< Decl > >;
236
237                CodeLocation location;
238                std::string kind;  // for debug
239                std::string name;
240                const Type * inst;
241                const MemberList & members;
242                MemberList::const_iterator curMember;
243                bool atbegin = true;  // false at first {small,big}Step
244                const Type * curType = nullptr;
245                std::unique_ptr< MemberIterator > memberIter = nullptr;
246                TypeSubstitution sub;
247
248                bool init() {
249                        PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
250                        if ( curMember != members.end() ) {
251                                if ( auto field = curMember->as< ObjectDecl >() ) {
252                                        PRINT( std::cerr << "incremented to field: " << field << std::endl; )
253                                        curType = field->get_type();
254                                        memberIter.reset( createMemberIterator( location, curType ) );
255                                        return true;
256                                }
257                        }
258                        return false;
259                }
260
261                AggregateIterator(
262                        const CodeLocation & loc, const std::string k, const std::string & n, const Type * i,
263                        const MemberList & ms )
264                : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ),
265                  sub( genericSubstitution( i ) ) {
266                        PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
267                        init();
268                }
269
270        public:
271                void setPosition(
272                        std::deque< ptr< Expr > >::const_iterator begin,
273                        std::deque< ptr< Expr > >::const_iterator end
274                ) final {
275                        if ( begin == end ) return;
276
277                        if ( auto varExpr = begin->as< VariableExpr >() ) {
278                                for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
279                                        if ( *curMember != varExpr->var ) continue;
280
281                                        ++begin;
282
283                                        memberIter.reset( createMemberIterator( location, varExpr->result ) );
284                                        curType = varExpr->result;
285                                        atbegin = curMember == members.begin() && begin == end;
286                                        memberIter->setPosition( begin, end );
287                                        return;
288                                }
289                                assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
290                        } else {
291                                assertf( false, "1 bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
292                        }
293                }
294
295                std::deque< InitAlternative > operator* () const final {
296                        if ( memberIter && *memberIter ) {
297                                std::deque< InitAlternative > ret = memberIter->first();
298                                PRINT( std::cerr << "sub: " << sub << std::endl; )
299                                for ( InitAlternative & alt : ret ) {
300                                        PRINT( std::cerr << "iterating and adding designators" << std::endl; )
301                                        alt.designation.get_and_mutate()->designators.emplace_front(
302                                                new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
303                                        // need to substitute for generic types so that casts are to concrete types
304                                        alt.type = shallowCopy(alt.type.get());
305                                        PRINT( std::cerr << "  type is: " << alt.type; )
306                                        sub.apply( alt.type ); // also apply to designation??
307                                        PRINT( std::cerr << " ==> " << alt.type << std::endl; )
308                                }
309                                return ret;
310                        }
311                        return {};
312                }
313
314                AggregateIterator & smallStep() final {
315                        PRINT( std::cerr << "smallStep in " << kind << std::endl; )
316                        atbegin = false;
317                        if ( memberIter ) {
318                                PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
319                                memberIter->smallStep();
320                                if ( *memberIter ) {
321                                        PRINT( std::cerr << "success!" << std::endl; )
322                                        return *this;
323                                }
324                        }
325                        return bigStep();
326                }
327
328                AggregateIterator & bigStep() override = 0;
329
330                const Type * getType() final { return inst; }
331
332                const Type * getNext() final {
333                        bool hasMember = memberIter && *memberIter;
334                        return hasMember ? memberIter->getType() : nullptr;
335                }
336
337                std::deque< InitAlternative > first() const final {
338                        std::deque< InitAlternative > ret;
339                        PRINT( std::cerr << "first " << kind << std::endl; )
340                        if ( memberIter && *memberIter ) {
341                                PRINT( std::cerr << "adding children" << std::endl; )
342                                ret = memberIter->first();
343                                for ( InitAlternative & alt : ret ) {
344                                        PRINT( std::cerr << "iterating and adding designators" << std::endl; )
345                                        alt.designation.get_and_mutate()->designators.emplace_front(
346                                                new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
347                                }
348                        }
349                        if ( atbegin ) {
350                                // only add self if at the very beginning of the structure
351                                PRINT( std::cerr << "adding self" << std::endl; )
352                                ret.emplace_front( inst, new Designation{ location } );
353                        }
354                        return ret;
355                }
356        };
357
358        class StructIterator final : public AggregateIterator {
359        public:
360                StructIterator( const CodeLocation & loc, const StructInstType * inst )
361                : AggregateIterator( loc, "StructIterator", inst->name, inst, inst->base->members ) {}
362
363                operator bool() const override {
364                        return curMember != members.end() || (memberIter && *memberIter);
365                }
366
367                StructIterator & bigStep() override {
368                        PRINT( std::cerr << "bigStep in " << kind << std::endl; )
369                        atbegin = false;
370                        memberIter = nullptr;
371                        curType = nullptr;
372                        while ( curMember != members.end() ) {
373                                ++curMember;
374                                if ( init() ) return *this;
375                        }
376                        return *this;
377                }
378        };
379
380        class UnionIterator final : public AggregateIterator {
381        public:
382                UnionIterator( const CodeLocation & loc, const UnionInstType * inst )
383                : AggregateIterator( loc, "UnionIterator", inst->name, inst, inst->base->members ) {}
384
385                operator bool() const override { return memberIter && *memberIter; }
386
387                UnionIterator & bigStep() override {
388                        // unions only initialize one member
389                        PRINT( std::cerr << "bigStep in " << kind << std::endl; )
390                        atbegin = false;
391                        memberIter = nullptr;
392                        curType = nullptr;
393                        curMember = members.end();
394                        return *this;
395                }
396        };
397
398        /// Iterates across the positions in a tuple:
399        class TupleIterator final : public IndexIterator {
400                ast::TupleType const * const tuple;
401
402                const ast::Type * typeAtIndex() const {
403                        assert( index < size );
404                        return tuple->types[ index ].get();
405                }
406
407        public:
408                TupleIterator( const CodeLocation & loc, const TupleType * type )
409                : IndexIterator( loc, type->size() ), tuple( type ) {
410                        PRINT( std::cerr << "Creating tuple iterator: " << type << std::endl; )
411                        memberIter.reset( createMemberIterator( loc, typeAtIndex() ) );
412                }
413
414                TupleIterator & bigStep() override {
415                        ++index;
416                        memberIter.reset( index < size ?
417                                createMemberIterator( location, typeAtIndex() ) : nullptr );
418                        return *this;
419                }
420
421                TupleIterator & smallStep() override {
422                        if ( memberIter ) {
423                                PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
424                                memberIter->smallStep();
425                                if ( !memberIter ) {
426                                        PRINT( std::cerr << "has valid member iter" << std::endl; )
427                                        return *this;
428                                }
429                        }
430                        return bigStep();
431                }
432
433                const ast::Type * getType() override {
434                        return tuple;
435                }
436
437                const ast::Type * getNext() override {
438                        bool hasMember = memberIter && *memberIter;
439                        return hasMember ? memberIter->getType() : nullptr;
440                }
441
442                std::deque< InitAlternative > first() const override {
443                        PRINT( std::cerr << "first in TupleIterator (" << index << "/" << size << ")" << std::endl; )
444                        if ( memberIter && *memberIter ) {
445                                std::deque< InitAlternative > ret = memberIter->first();
446                                for ( InitAlternative & alt : ret ) {
447                                        alt.designation.get_and_mutate()->designators.emplace_front(
448                                                ConstantExpr::from_ulong( location, index ) );
449                                }
450                                return ret;
451                        }
452                        return {};
453                }
454        };
455
456        MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
457                if ( auto aggr = dynamic_cast< const BaseInstType * >( type ) ) {
458                        if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
459                                assert( sit->base );
460                                return new StructIterator{ loc, sit };
461                        } else if ( auto uit = dynamic_cast< const UnionInstType * >( aggr ) ) {
462                                assert( uit->base );
463                                return new UnionIterator{ loc, uit };
464                        } else {
465                                assertf(
466                                        dynamic_cast< const EnumInstType * >( type )
467                                                || dynamic_cast< const TypeInstType * >( type ),
468                                        "Encountered unhandled BaseInstType in createMemberIterator: %s",
469                                                toString( type ).c_str() );
470                                return new SimpleIterator{ loc, type };
471                        }
472                } else if ( auto at = dynamic_cast< const ArrayType * >( type ) ) {
473                        return new ArrayIterator{ loc, at };
474                } else if ( auto tt = dynamic_cast< const TupleType * >( type ) ) {
475                        return new TupleIterator{ loc, tt };
476                } else {
477                        return new SimpleIterator{ loc, type };
478                }
479        }
480
481        CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() {
482                objStack.emplace_back( new SimpleIterator{ loc, type } );
483        }
484
485        const Designation * CurrentObject::findNext( const Designation * designation ) {
486                using DesignatorChain = std::deque< ptr< Expr > >;
487                PRINT( std::cerr << "___findNext" << std::endl; )
488
489                // find all the d's
490                std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;
491                std::deque< const Type * > curTypes{ objStack.back()->getType() }, newTypes;
492                for ( const Expr * expr : designation->designators ) {
493                        PRINT( std::cerr << "____untyped: " << expr << std::endl; )
494                        auto dit = desigAlts.begin();
495
496                        for ( const Type * t : curTypes ) {
497                                assert( dit != desigAlts.end() );
498                                DesignatorChain & d = *dit;
499                                if ( auto nexpr = dynamic_cast< const NameExpr *>( expr ) ) {
500                                        PRINT( std::cerr << "____actual: " << t << std::endl; )
501                                        if ( auto refType = dynamic_cast< const BaseInstType * >( t ) ) {
502                                                // concatenate identical field names
503                                                for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
504                                                        if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) {
505                                                                PRINT( std::cerr << "____alt: " << field->type << std::endl; )
506                                                                DesignatorChain d2 = d;
507                                                                d2.emplace_back( new VariableExpr{ expr->location, field } );
508                                                                newDesigAlts.emplace_back( std::move( d2 ) );
509                                                                newTypes.emplace_back( field->type );
510                                                        }
511                                                }
512                                        } else if ( auto at = dynamic_cast< const ArrayType * >( t ) ) {
513                                                auto nexpr = dynamic_cast< const NameExpr *>( expr );
514                                                for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
515                                                        if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) {
516                                                                DesignatorChain d2 = d;
517                                                                d2.emplace_back( new VariableExpr{ expr->location, field } );
518                                                                newDesigAlts.emplace_back( std::move( d2 ) );
519                                                                newTypes.emplace_back( at->base );
520                                                        }
521                                                }
522                                        }
523
524                                        ++dit;
525                                } else {
526                                        if ( auto at = dynamic_cast< const ArrayType * >( t ) ) {
527                                                PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
528                                                d.emplace_back( expr );
529                                                newDesigAlts.emplace_back( d );
530                                                newTypes.emplace_back( at->base );
531                                        }
532                                }
533                        }
534
535                        // reset queue
536                        desigAlts = std::move( newDesigAlts );
537                        newDesigAlts.clear();
538                        curTypes = std::move( newTypes );
539                        newTypes.clear();
540                        assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
541                }
542
543                if ( desigAlts.size() > 1 ) {
544                        SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
545                } else if ( desigAlts.empty() ) {
546                        SemanticError( designation, "No reasonable alternatives for designation: " );
547                }
548
549                DesignatorChain & d = desigAlts.back();
550                PRINT( for ( Expression * expr : d ) {
551                        std::cerr << "____desig: " << expr << std::endl;
552                } ) // for
553                assertf( ! curTypes.empty(), "empty designator chosen");
554
555                // set new designators
556                assertf( ! objStack.empty(), "empty object stack when setting designation" );
557                Designation * actualDesignation =
558                        new Designation{ designation->location, DesignatorChain{d} };
559                objStack.back()->setPosition( d ); // destroys d
560                return actualDesignation;
561        }
562
563        void CurrentObject::setNext( const Designation * designation ) {
564                PRINT( std::cerr << "____setNext" << designation << std::endl; )
565                assertf( ! objStack.empty(), "obj stack empty in setNext" );
566                objStack.back()->setPosition( designation->designators );
567        }
568
569        void CurrentObject::increment() {
570                PRINT( std::cerr << "____increment" << std::endl; )
571                if ( objStack.empty() ) return;
572                PRINT( std::cerr << *objStack.back() << std::endl; )
573                objStack.back()->smallStep();
574        }
575
576        void CurrentObject::enterListInit( const CodeLocation & loc ) {
577                PRINT( std::cerr << "____entering list init" << std::endl; )
578                assertf( ! objStack.empty(), "empty obj stack entering list init" );
579                const ast::Type * type = objStack.back()->getNext();
580                assert( type );
581                objStack.emplace_back( createMemberIterator( loc, type ) );
582        }
583
584        void CurrentObject::exitListInit() {
585                PRINT( std::cerr << "____exiting list init" << std::endl; )
586                assertf( ! objStack.empty(), "objstack empty" );
587                objStack.pop_back();
588                if ( ! objStack.empty() ) {
589                        PRINT( std::cerr << *objStack.back() << std::endl; )
590                        objStack.back()->bigStep();
591                }
592        }
593
594        std::deque< InitAlternative > CurrentObject::getOptions() {
595                PRINT( std::cerr << "____getting current options" << std::endl; )
596                assertf( ! objStack.empty(), "objstack empty in getOptions" );
597                return **objStack.back();
598        }
599
600        const Type * CurrentObject::getCurrentType() {
601                PRINT( std::cerr << "____getting current type" << std::endl; )
602                assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
603                return objStack.back()->getNext();
604        }
605}
606
607// Local Variables: //
608// tab-width: 4 //
609// mode: c++ //
610// compile-command: "make install" //
611// End: //
Note: See TracBrowser for help on using the repository browser.