source: src/ResolvExpr/CurrentObject.cc@ a6f26ca

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since a6f26ca was 2890212, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Startup.cfa now compiles with new ast

  • Property mode set to 100644
File size: 36.7 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 : Rob Schluntz
12// Last Modified On : Tue Jun 13 15:28:44 2017
13// Update Count : 2
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/Expr.hpp" // for InitAlternative
24#include "AST/GenericSubstitution.hpp" // for genericSubstitution
25#include "AST/Init.hpp" // for Designation
26#include "AST/Node.hpp" // for readonly
27#include "AST/Print.hpp" // for readonly
28#include "AST/Type.hpp"
29#include "Common/Indenter.h" // for Indenter, operator<<
30#include "Common/SemanticError.h" // for SemanticError
31#include "Common/utility.h" // for toString
32#include "CurrentObject.h"
33#include "SynTree/Constant.h" // for Constant
34#include "SynTree/Declaration.h" // for ObjectDecl, Declaration, Struc...
35#include "SynTree/Expression.h" // for InitAlternative, VariableExpr
36#include "SynTree/Initializer.h" // for Designation, operator<<
37#include "SynTree/Type.h" // for Type, StructInstType, UnionIns...
38#include "SynTree/TypeSubstitution.h" // for TypeSubstitution
39
40#if 0
41#define PRINT(x) x
42#else
43#define PRINT(x)
44#endif
45
46namespace ResolvExpr {
47 template< typename AggrInst >
48 TypeSubstitution makeGenericSubstitution( AggrInst * inst ) {
49 assert( inst );
50 assert( inst->get_baseParameters() );
51 std::list< TypeDecl * > baseParams = *inst->get_baseParameters();
52 std::list< Expression * > typeSubs = inst->get_parameters();
53 TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
54 return subs;
55 }
56
57 TypeSubstitution makeGenericSubstitution( Type * type ) {
58 if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) {
59 return makeGenericSubstitution( inst );
60 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) {
61 return makeGenericSubstitution( inst );
62 } else {
63 return TypeSubstitution();
64 }
65 }
66
67 class MemberIterator {
68 public:
69 virtual ~MemberIterator() {}
70
71 /// walks the current object using the given designators as a guide
72 virtual void setPosition( std::list< Expression * > & designators ) = 0;
73
74 /// retrieve the list of possible Type/Designaton pairs for the current position in the currect object
75 virtual std::list<InitAlternative> operator*() const = 0;
76
77 /// true if the iterator is not currently at the end
78 virtual operator bool() const = 0;
79
80 /// moves the iterator by one member in the current object
81 virtual MemberIterator & bigStep() = 0;
82
83 /// moves the iterator by one member in the current subobject
84 virtual MemberIterator & smallStep() = 0;
85
86 /// the type of the current object
87 virtual Type * getType() = 0;
88
89 /// the type of the current subobject
90 virtual Type * getNext() = 0;
91
92 /// printing for debug
93 virtual void print( std::ostream & out, Indenter indent ) const = 0;
94
95 /// helper for operator*; aggregates must add designator to each init alternative, but
96 /// adding designators in operator* creates duplicates.
97 virtual std::list<InitAlternative> first() const = 0; // should be protected
98 };
99
100 std::ostream & operator<<(std::ostream & out, const MemberIterator & it) {
101 Indenter indenter;
102 it.print( out, indenter );
103 return out;
104 }
105
106 /// create a new MemberIterator that traverses a type correctly
107 MemberIterator * createMemberIterator( Type * type );
108
109 /// iterates "other" types, e.g. basic types, pointer types, etc. which do not change at list initializer entry
110 class SimpleIterator : public MemberIterator {
111 public:
112 SimpleIterator( Type * type ) : type( type ) {}
113
114 virtual void setPosition( std::list< Expression * > & designators ) {
115 assertf( designators.empty(), "simple iterator given non-empty designator..." ); // xxx - might be semantic error
116 }
117
118 virtual std::list<InitAlternative> operator*() const { return first(); }
119 virtual operator bool() const { return type; }
120
121 // big step is the same as small step
122 virtual MemberIterator & bigStep() { return smallStep(); }
123 virtual MemberIterator & smallStep() {
124 type = nullptr; // type is nullified on increment since SimpleIterators do not have members
125 return *this;
126 }
127
128 virtual void print( std::ostream & out, __attribute__((unused)) Indenter indent ) const {
129 out << "SimpleIterator(" << type << ")";
130 }
131
132 virtual Type * getType() { return type; }
133 virtual Type * getNext() { return type; }
134
135 protected:
136 virtual std::list<InitAlternative> first() const {
137 if ( type ) return std::list<InitAlternative>{ { type->clone(), new Designation( {} ) } };
138 else return std::list<InitAlternative>{};
139 }
140 private:
141 Type * type = nullptr;
142 };
143
144 class ArrayIterator : public MemberIterator {
145 public:
146 ArrayIterator( ArrayType * at ) : array( at ) {
147 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
148 base = at->base;
149 memberIter = createMemberIterator( base );
150 if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=: " );
151 setSize( at->dimension );
152 }
153
154 ~ArrayIterator() {
155 delete memberIter;
156 }
157
158 private:
159 void setSize( Expression * expr ) { // replace this logic with an eval call
160 auto res = eval(expr);
161 if (res.second) {
162 size = res.first;
163 } else {
164 SemanticError( expr->location, toString("Array designator must be a constant expression: ", expr) );
165 }
166 }
167
168 public:
169 void setPosition( Expression * expr ) {
170 // need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions
171 if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
172 try {
173 index = constExpr->intValue();
174 } catch( SemanticErrorException & ) {
175 SemanticError( expr, "Constant expression of non-integral type in array designator: " );
176 }
177 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
178 setPosition( castExpr->get_arg() );
179 } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
180 EnumInstType * inst = dynamic_cast<EnumInstType *>( varExpr->get_result() );
181 assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() );
182 long long int value;
183 if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
184 index = value;
185 }
186 } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) {
187 index = 0; // xxx - get actual sizeof/alignof value?
188 } else {
189 assertf( false, "bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
190 }
191 }
192
193 virtual void setPosition( std::list< Expression * > & designators ) {
194 if ( ! designators.empty() ) {
195 setPosition( designators.front() );
196 designators.pop_front();
197 memberIter->setPosition( designators );
198 }
199 }
200
201 virtual std::list<InitAlternative> operator*() const {
202 return first();
203 }
204
205 virtual operator bool() const { return index < size; }
206
207 virtual MemberIterator & bigStep() {
208 PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
209 ++index;
210 delete memberIter;
211 if ( index < size ) memberIter = createMemberIterator( base );
212 else memberIter = nullptr;
213 return *this;
214 }
215
216 virtual MemberIterator & smallStep() {
217 PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
218 if ( memberIter ) {
219 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
220 memberIter->smallStep();
221 if ( *memberIter ) {
222 PRINT( std::cerr << "has valid member iter" << std::endl; )
223 return *this;
224 }
225 }
226 return bigStep();
227 }
228
229 virtual Type * getType() { return array; }
230 virtual Type * getNext() { return base; }
231
232 virtual std::list<InitAlternative> first() const {
233 PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
234 if ( memberIter && *memberIter ) {
235 std::list<InitAlternative> ret = memberIter->first();
236 for ( InitAlternative & alt : ret ) {
237 alt.designation->get_designators().push_front( new ConstantExpr( Constant::from_ulong( index ) ) );
238 }
239 return ret;
240 }
241 return std::list<InitAlternative>();
242 }
243
244 virtual void print( std::ostream & out, Indenter indent ) const {
245 out << "ArrayIterator(Array of " << base << ")";
246 if ( memberIter ) {
247 Indenter childIndent = indent+1;
248 out << std::endl << childIndent;
249 memberIter->print( out, childIndent );
250 }
251 }
252
253 private:
254 ArrayType * array = nullptr;
255 Type * base = nullptr;
256 size_t index = 0;
257 size_t size = 0;
258 MemberIterator * memberIter = nullptr;
259 };
260
261 class AggregateIterator : public MemberIterator {
262 public:
263 typedef std::list<Declaration *> MemberList;
264 typedef MemberList::const_iterator iterator;
265 std::string kind = ""; // for debug
266 std::string name;
267 Type * inst = nullptr;
268 const MemberList & members;
269 iterator curMember;
270 bool atbegin = true; // false at first {small,big}Step -- this aggr type is only added to the possibilities at the beginning
271 Type * curType = nullptr;
272 MemberIterator * memberIter = nullptr;
273 mutable TypeSubstitution sub;
274
275 AggregateIterator( const std::string & kind, const std::string & name, Type * inst, const MemberList & members ) : kind( kind ), name( name ), inst( inst ), members( members ), curMember( members.begin() ), sub( makeGenericSubstitution( inst ) ) {
276 PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
277 init();
278 }
279
280 virtual ~AggregateIterator() {
281 delete memberIter;
282 }
283
284 bool init() {
285 PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
286 if ( curMember != members.end() ) {
287 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( *curMember ) ) {
288 PRINT( std::cerr << "incremented to field: " << field << std::endl; )
289 curType = field->get_type();
290 memberIter = createMemberIterator( curType );
291 return true;
292 }
293 }
294 return false;
295 }
296
297 virtual std::list<InitAlternative> operator*() const {
298 if (memberIter && *memberIter) {
299 std::list<InitAlternative> ret = memberIter->first();
300 PRINT( std::cerr << "sub: " << sub << std::endl; )
301 for ( InitAlternative & alt : ret ) {
302 PRINT( std::cerr << "iterating and adding designators" << std::endl; )
303 alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) );
304 // need to substitute for generic types, so that casts are to concrete types
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 std::list<InitAlternative>();
312 }
313
314 virtual void setPosition( std::list< Expression * > & designators ) {
315 if ( ! designators.empty() ) {
316 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( designators.front() ) ) {
317 for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
318 if ( *curMember == varExpr->get_var() ) {
319 designators.pop_front();
320 delete memberIter;
321 memberIter = createMemberIterator( varExpr->get_result() );
322 curType = varExpr->get_result();
323 atbegin = curMember == members.begin() && designators.empty(); // xxx - is this the right condition for atbegin??
324 memberIter->setPosition( designators );
325 return;
326 } // if
327 } // for
328 assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
329 } else {
330 assertf( false, "bad designator given to %s: %s", kind.c_str(), toString( designators.front() ).c_str() );
331 } // if
332 } // if
333 }
334
335 virtual MemberIterator & smallStep() {
336 PRINT( std::cerr << "smallStep in " << kind << std::endl; )
337 atbegin = false;
338 if ( memberIter ) {
339 PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
340 memberIter->smallStep();
341 if ( *memberIter ) {
342 PRINT( std::cerr << "success!" << std::endl; )
343 return *this;
344 }
345 }
346 return bigStep();
347 }
348
349 virtual Type * getType() { return inst; }
350 virtual Type * getNext() {
351 if ( memberIter && *memberIter ) return memberIter->getType(); // xxx - ??? recursive call???
352 return nullptr;
353 }
354
355 virtual std::list<InitAlternative> first() const {
356 std::list<InitAlternative> ret;
357 PRINT( std::cerr << "first " << kind << std::endl; )
358 if ( memberIter && *memberIter ) { // might not need *memberIter??
359 PRINT( std::cerr << "adding children" << std::endl; )
360 ret = memberIter->first();
361 for ( InitAlternative & alt : ret ) {
362 PRINT( std::cerr << "iterating and adding designators" << std::endl; )
363 alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) );
364 }
365 }
366 if ( atbegin ) {
367 // xxx - what about case of empty struct??
368 // only add self if at the very beginning of the structure
369 PRINT( std::cerr << "adding self" << std::endl; )
370 ret.push_front( { inst->clone(), new Designation( {} ) } );
371 }
372 return ret;
373 }
374
375 virtual void print( std::ostream & out, Indenter indent ) const {
376 out << kind << "(" << name << ")";
377 if ( memberIter ) {
378 Indenter childIndent = indent+1;
379 out << std::endl << childIndent;
380 memberIter->print( out, childIndent );
381 }
382 }
383 };
384
385 class UnionIterator : public AggregateIterator {
386 public:
387 UnionIterator( UnionInstType * inst ) : AggregateIterator( "UnionIterator", inst->get_name(), inst, inst->get_baseUnion()->get_members() ) {}
388
389 virtual operator bool() const { return (memberIter && *memberIter); }
390 virtual MemberIterator & bigStep() {
391 // unions only initialize one member
392 PRINT( std::cerr << "bigStep in " << kind << std::endl; )
393 atbegin = false;
394 delete memberIter;
395 memberIter = nullptr;
396 curType = nullptr;
397 curMember = members.end();
398 return *this;
399 }
400 };
401
402 class StructIterator : public AggregateIterator {
403 public:
404 StructIterator( StructInstType * inst ) : AggregateIterator( "StructIterator", inst->get_name(), inst, inst->get_baseStruct()->get_members() ) {}
405
406 virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); }
407
408 virtual MemberIterator & bigStep() {
409 PRINT( std::cerr << "bigStep in " << kind << std::endl; )
410 atbegin = false;
411 delete memberIter;
412 memberIter = nullptr;
413 curType = nullptr;
414 for ( ; curMember != members.end(); ) {
415 ++curMember;
416 if ( init() ) {
417 return *this;
418 }
419 }
420 return *this;
421 }
422 };
423
424 class TupleIterator : public AggregateIterator {
425 public:
426 TupleIterator( TupleType * inst ) : AggregateIterator( "TupleIterator", toString("Tuple", inst->size()), inst, inst->get_members() ) {}
427
428 virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); }
429
430 virtual MemberIterator & bigStep() {
431 PRINT( std::cerr << "bigStep in " << kind << std::endl; )
432 atbegin = false;
433 delete memberIter;
434 memberIter = nullptr;
435 curType = nullptr;
436 for ( ; curMember != members.end(); ) {
437 ++curMember;
438 if ( init() ) {
439 return *this;
440 }
441 }
442 return *this;
443 }
444 };
445
446 MemberIterator * createMemberIterator( Type * type ) {
447 if ( ReferenceToType * aggr = dynamic_cast< ReferenceToType * >( type ) ) {
448 if ( StructInstType * sit = dynamic_cast< StructInstType * >( aggr ) ) {
449 return new StructIterator( sit );
450 } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( aggr ) ) {
451 return new UnionIterator( uit );
452 } else {
453 assertf( dynamic_cast< EnumInstType * >( type ) || dynamic_cast< TypeInstType * >( type ), "Encountered unhandled ReferenceToType in createMemberIterator: %s", toString( type ).c_str() );
454 return new SimpleIterator( type );
455 }
456 } else if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
457 return new ArrayIterator( at );
458 } else if ( TupleType * tt = dynamic_cast< TupleType * >( type ) ) {
459 return new TupleIterator( tt );
460 } else {
461 return new SimpleIterator( type );
462 }
463 }
464
465 CurrentObject::CurrentObject() {}
466 CurrentObject::CurrentObject( Type * type ) {
467 objStack.push( new SimpleIterator( type ) );
468 }
469
470
471 void CurrentObject::setNext( Designation * designation ) {
472 assertf( ! objStack.empty(), "obj stack empty in setNext" );
473 PRINT( std::cerr << "____setNext" << designation << std::endl; )
474 objStack.top()->setPosition( designation->get_designators() );
475 }
476
477 Designation * CurrentObject::findNext( Designation * designation ) {
478 typedef std::list< Expression * > DesignatorChain;
479 PRINT( std::cerr << "___findNext" << std::endl; )
480 // find all the d's
481 std::list<DesignatorChain> desigAlts{ { } }, newDesigAlts;
482 std::list<Type *> curTypes { (objStack.top())->getType() }, newTypes;
483 for ( Expression * expr : designation->get_designators() ) {
484 PRINT( std::cerr << "____untyped: " << expr << std::endl; )
485 std::list<DesignatorChain>::iterator dit = desigAlts.begin();
486 if ( NameExpr * nexpr = dynamic_cast<NameExpr *>(expr) ) {
487 for ( Type * t : curTypes ) {
488 assert( dit != desigAlts.end() );
489 DesignatorChain & d = *dit;
490 PRINT( std::cerr << "____actual: " << t << std::endl; )
491 ReferenceToType * refType = dynamic_cast<ReferenceToType *>(t);
492 std::list<Declaration *> members;
493 if ( refType ) {
494 refType->lookup( nexpr->get_name(), members ); // concatenate identical field name
495 // xxx - need to also include anonymous members in this somehow...
496 for ( Declaration * mem: members ) {
497 if ( ObjectDecl * field = dynamic_cast<ObjectDecl *>(mem) ) {
498 PRINT( std::cerr << "____alt: " << field->get_type() << std::endl; )
499 DesignatorChain newD = d;
500 newD.push_back( new VariableExpr( field ) );
501 newDesigAlts.push_back( newD );
502 newTypes.push_back( field->get_type() );
503 } // if
504 } // for
505 } // if
506 ++dit;
507 } // for
508 } else {
509 for ( Type * t : curTypes ) {
510 assert( dit != desigAlts.end() );
511 DesignatorChain & d = *dit;
512 if ( ArrayType * at = dynamic_cast< ArrayType * > ( t ) ) {
513 PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
514 d.push_back( expr );
515 newDesigAlts.push_back( d );
516 newTypes.push_back( at->get_base() );
517 }
518 ++dit;
519 } // for
520 } // if
521 desigAlts = newDesigAlts;
522 newDesigAlts.clear();
523 curTypes = newTypes;
524 newTypes.clear();
525 assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
526 } // for
527 if ( desigAlts.size() > 1 ) {
528 SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
529 } else if ( desigAlts.size() == 0 ) {
530 SemanticError( designation, "No reasonable alternatives for designation: " );
531 }
532 DesignatorChain & d = desigAlts.back();
533 PRINT( for ( Expression * expr : d ) {
534 std::cerr << "____desig: " << expr << std::endl;
535 } ) // for
536 assertf( ! curTypes.empty(), "empty designator chosen");
537
538 // set new designators
539 assertf( ! objStack.empty(), "empty object stack when setting designation" );
540 Designation * actualDesignation = new Designation( d );
541 objStack.top()->setPosition( d ); // destroys d
542 return actualDesignation;
543 }
544
545 void CurrentObject::increment() {
546 PRINT( std::cerr << "____increment" << std::endl; )
547 if ( ! objStack.empty() ) {
548 PRINT( std::cerr << *objStack.top() << std::endl; )
549 objStack.top()->smallStep();
550 }
551 }
552
553 void CurrentObject::enterListInit() {
554 PRINT( std::cerr << "____entering list init" << std::endl; )
555 assertf( ! objStack.empty(), "empty obj stack entering list init" );
556 Type * type = objStack.top()->getNext();
557 if ( type ) {
558 objStack.push( createMemberIterator( type ) );
559 } else {
560 assertf( false, "not sure about this case..." );
561 }
562 }
563
564 void CurrentObject::exitListInit() {
565 PRINT( std::cerr << "____exiting list init" << std::endl; )
566 assertf( ! objStack.empty(), "objstack empty" );
567 delete objStack.top();
568 objStack.pop();
569 if ( ! objStack.empty() ) {
570 PRINT( std::cerr << *objStack.top() << std::endl; )
571 objStack.top()->bigStep();
572 }
573 }
574
575 std::list< InitAlternative > CurrentObject::getOptions() {
576 PRINT( std::cerr << "____getting current options" << std::endl; )
577 assertf( ! objStack.empty(), "objstack empty in getOptions" );
578 return **objStack.top();
579 }
580
581 Type * CurrentObject::getCurrentType() {
582 PRINT( std::cerr << "____getting current type" << std::endl; )
583 assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
584 return objStack.top()->getNext();
585 }
586} // namespace ResolvExpr
587
588namespace ast {
589 /// create a new MemberIterator that traverses a type correctly
590 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type );
591
592 /// Iterates "other" types (e.g. basic, pointer) which do not change at list initializer entry
593 class SimpleIterator final : public MemberIterator {
594 CodeLocation location;
595 readonly< Type > type = nullptr;
596 public:
597 SimpleIterator( const CodeLocation & loc, const Type * t ) : location( loc ), type( t ) {}
598
599 void setPosition(
600 std::deque< ptr< Expr > >::const_iterator begin,
601 std::deque< ptr< Expr > >::const_iterator end
602 ) override {
603 if ( begin != end ) {
604 SemanticError( location, "Un-designated initializer given non-empty designator" );
605 }
606 }
607
608 std::deque< InitAlternative > operator* () const override { return first(); }
609
610 operator bool() const override { return type; }
611
612 SimpleIterator & bigStep() override { return smallStep(); }
613 SimpleIterator & smallStep() override {
614 type = nullptr; // empty on increment because no members
615 return *this;
616 }
617
618 const Type * getType() override { return type; }
619
620 const Type * getNext() override { return type; }
621
622 std::deque< InitAlternative > first() const override {
623 if ( type ) return { InitAlternative{ type, new Designation{ location } } };
624 return {};
625 }
626 };
627
628 /// Iterates array types
629 class ArrayIterator final : public MemberIterator {
630 CodeLocation location;
631 readonly< ArrayType > array = nullptr;
632 readonly< Type > base = nullptr;
633 size_t index = 0;
634 size_t size = 0;
635 std::unique_ptr< MemberIterator > memberIter;
636
637 void setSize( const Expr * expr ) {
638 auto res = eval(expr);
639 if ( ! res.second ) {
640 SemanticError( location,
641 toString("Array designator must be a constant expression: ", expr ) );
642 }
643 size = res.first;
644 }
645
646 public:
647 ArrayIterator( const CodeLocation & loc, const ArrayType * at )
648 : location( loc ), array( at ), base( at->base ) {
649 PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
650 memberIter.reset( createMemberIterator( loc, base ) );
651 if ( at->isVarLen ) {
652 SemanticError( location, at, "VLA initialization does not support @=: " );
653 }
654 setSize( at->dimension );
655 }
656
657 void setPosition( const Expr * expr ) {
658 // need to permit integer-constant-expressions, including: integer constants,
659 // enumeration constants, character constants, sizeof expressions, alignof expressions,
660 // cast expressions
661 if ( auto constExpr = dynamic_cast< const ConstantExpr * >( expr ) ) {
662 try {
663 index = constExpr->intValue();
664 } catch ( SemanticErrorException & ) {
665 SemanticError( expr,
666 "Constant expression of non-integral type in array designator: " );
667 }
668 } else if ( auto castExpr = dynamic_cast< const CastExpr * >( expr ) ) {
669 setPosition( castExpr->arg );
670 } else if (
671 dynamic_cast< const SizeofExpr * >( expr )
672 || dynamic_cast< const AlignofExpr * >( expr )
673 ) {
674 index = 0;
675 } else {
676 assertf( false,
677 "bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
678 }
679 }
680
681 void setPosition(
682 std::deque< ptr< Expr > >::const_iterator begin,
683 std::deque< ptr< Expr > >::const_iterator end
684 ) override {
685 if ( begin == end ) return;
686
687 setPosition( *begin );
688 memberIter->setPosition( ++begin, end );
689 }
690
691 std::deque< InitAlternative > operator* () const override { return first(); }
692
693 operator bool() const override { return index < size; }
694
695 ArrayIterator & bigStep() override {
696 PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
697 ++index;
698 memberIter.reset( index < size ? createMemberIterator( location, base ) : nullptr );
699 return *this;
700 }
701
702 ArrayIterator & smallStep() override {
703 PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
704 if ( memberIter ) {
705 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
706 memberIter->smallStep();
707 if ( *memberIter ) {
708 PRINT( std::cerr << "has valid member iter" << std::endl; )
709 return *this;
710 }
711 }
712 return bigStep();
713 }
714
715 const Type * getType() override { return array; }
716
717 const Type * getNext() override { return base; }
718
719 std::deque< InitAlternative > first() const override {
720 PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
721 if ( memberIter && *memberIter ) {
722 std::deque< InitAlternative > ret = memberIter->first();
723 for ( InitAlternative & alt : ret ) {
724 alt.designation.get_and_mutate()->designators.emplace_front(
725 ConstantExpr::from_ulong( location, index ) );
726 }
727 return ret;
728 }
729 return {};
730 }
731 };
732
733 class AggregateIterator : public MemberIterator {
734 protected:
735 using MemberList = std::vector< ptr< Decl > >;
736
737 CodeLocation location;
738 std::string kind; // for debug
739 std::string name;
740 const Type * inst;
741 const MemberList & members;
742 MemberList::const_iterator curMember;
743 bool atbegin = true; // false at first {small,big}Step
744 const Type * curType = nullptr;
745 std::unique_ptr< MemberIterator > memberIter = nullptr;
746 TypeSubstitution sub;
747
748 bool init() {
749 PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
750 if ( curMember != members.end() ) {
751 if ( auto field = curMember->as< ObjectDecl >() ) {
752 PRINT( std::cerr << "incremented to field: " << field << std::endl; )
753 curType = field->get_type();
754 memberIter.reset( createMemberIterator( location, curType ) );
755 return true;
756 }
757 }
758 return false;
759 }
760
761 AggregateIterator(
762 const CodeLocation & loc, const std::string k, const std::string & n, const Type * i,
763 const MemberList & ms )
764 : location( loc ), kind( k ), name( n ), inst( i ), members( ms ), curMember( ms.begin() ),
765 sub( genericSubstitution( i ) ) {
766 PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
767 init();
768 }
769
770 public:
771 void setPosition(
772 std::deque< ptr< Expr > >::const_iterator begin,
773 std::deque< ptr< Expr > >::const_iterator end
774 ) final {
775 if ( begin == end ) return;
776
777 if ( auto varExpr = begin->as< VariableExpr >() ) {
778 for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
779 if ( *curMember != varExpr->var ) continue;
780
781 ++begin;
782
783 memberIter.reset( createMemberIterator( location, varExpr->result ) );
784 curType = varExpr->result;
785 atbegin = curMember == members.begin() && begin == end;
786 memberIter->setPosition( begin, end );
787 return;
788 }
789 assertf( false,
790 "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
791 } else {
792 assertf( false,
793 "bad designator given to %s: %s", kind.c_str(), toString( *begin ).c_str() );
794 }
795 }
796
797 std::deque< InitAlternative > operator* () const final {
798 if ( memberIter && *memberIter ) {
799 std::deque< InitAlternative > ret = memberIter->first();
800 PRINT( std::cerr << "sub: " << sub << std::endl; )
801 for ( InitAlternative & alt : ret ) {
802 PRINT( std::cerr << "iterating and adding designators" << std::endl; )
803 alt.designation.get_and_mutate()->designators.emplace_front(
804 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
805 // need to substitute for generic types so that casts are to concrete types
806 PRINT( std::cerr << " type is: " << alt.type; )
807 sub.apply( alt.type ); // also apply to designation??
808 PRINT( std::cerr << " ==> " << alt.type << std::endl; )
809 }
810 return ret;
811 }
812 return {};
813 }
814
815 AggregateIterator & smallStep() final {
816 PRINT( std::cerr << "smallStep in " << kind << std::endl; )
817 atbegin = false;
818 if ( memberIter ) {
819 PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
820 memberIter->smallStep();
821 if ( *memberIter ) {
822 PRINT( std::cerr << "success!" << std::endl; )
823 return *this;
824 }
825 }
826 return bigStep();
827 }
828
829 AggregateIterator & bigStep() override = 0;
830
831 const Type * getType() final { return inst; }
832
833 const Type * getNext() final {
834 return ( memberIter && *memberIter ) ? memberIter->getType() : nullptr;
835 }
836
837 std::deque< InitAlternative > first() const final {
838 std::deque< InitAlternative > ret;
839 PRINT( std::cerr << "first " << kind << std::endl; )
840 if ( memberIter && *memberIter ) {
841 PRINT( std::cerr << "adding children" << std::endl; )
842 ret = memberIter->first();
843 for ( InitAlternative & alt : ret ) {
844 PRINT( std::cerr << "iterating and adding designators" << std::endl; )
845 alt.designation.get_and_mutate()->designators.emplace_front(
846 new VariableExpr{ location, curMember->strict_as< ObjectDecl >() } );
847 }
848 }
849 if ( atbegin ) {
850 // only add self if at the very beginning of the structure
851 PRINT( std::cerr << "adding self" << std::endl; )
852 ret.emplace_front( inst, new Designation{ location } );
853 }
854 return ret;
855 }
856 };
857
858 class StructIterator final : public AggregateIterator {
859 public:
860 StructIterator( const CodeLocation & loc, const StructInstType * inst )
861 : AggregateIterator( loc, "StructIterator", inst->name, inst, inst->base->members ) {}
862
863 operator bool() const override {
864 return curMember != members.end() || (memberIter && *memberIter);
865 }
866
867 StructIterator & bigStep() override {
868 PRINT( std::cerr << "bigStep in " << kind << std::endl; )
869 atbegin = false;
870 memberIter = nullptr;
871 curType = nullptr;
872 while ( curMember != members.end() ) {
873 ++curMember;
874 if ( init() ) return *this;
875 }
876 return *this;
877 }
878 };
879
880 class UnionIterator final : public AggregateIterator {
881 public:
882 UnionIterator( const CodeLocation & loc, const UnionInstType * inst )
883 : AggregateIterator( loc, "UnionIterator", inst->name, inst, inst->base->members ) {}
884
885 operator bool() const override { return memberIter && *memberIter; }
886
887 UnionIterator & bigStep() override {
888 // unions only initialize one member
889 PRINT( std::cerr << "bigStep in " << kind << std::endl; )
890 atbegin = false;
891 memberIter = nullptr;
892 curType = nullptr;
893 curMember = members.end();
894 return *this;
895 }
896 };
897
898 class TupleIterator final : public AggregateIterator {
899 public:
900 TupleIterator( const CodeLocation & loc, const TupleType * inst )
901 : AggregateIterator(
902 loc, "TupleIterator", toString("Tuple", inst->size()), inst, inst->members
903 ) {}
904
905 operator bool() const override {
906 return curMember != members.end() || (memberIter && *memberIter);
907 }
908
909 TupleIterator & bigStep() override {
910 PRINT( std::cerr << "bigStep in " << kind << std::endl; )
911 atbegin = false;
912 memberIter = nullptr;
913 curType = nullptr;
914 while ( curMember != members.end() ) {
915 ++curMember;
916 if ( init() ) return *this;
917 }
918 return *this;
919 }
920 };
921
922 MemberIterator * createMemberIterator( const CodeLocation & loc, const Type * type ) {
923 if ( auto aggr = dynamic_cast< const ReferenceToType * >( type ) ) {
924 if ( auto sit = dynamic_cast< const StructInstType * >( aggr ) ) {
925 return new StructIterator{ loc, sit };
926 } else if ( auto uit = dynamic_cast< const UnionInstType * >( aggr ) ) {
927 return new UnionIterator{ loc, uit };
928 } else {
929 assertf(
930 dynamic_cast< const EnumInstType * >( type )
931 || dynamic_cast< const TypeInstType * >( type ),
932 "Encountered unhandled ReferenceToType in createMemberIterator: %s",
933 toString( type ).c_str() );
934 return new SimpleIterator{ loc, type };
935 }
936 } else if ( auto at = dynamic_cast< const ArrayType * >( type ) ) {
937 return new ArrayIterator{ loc, at };
938 } else if ( auto tt = dynamic_cast< const TupleType * >( type ) ) {
939 return new TupleIterator{ loc, tt };
940 } else {
941 return new SimpleIterator{ loc, type };
942 }
943 }
944
945 CurrentObject::CurrentObject( const CodeLocation & loc, const Type * type ) : objStack() {
946 objStack.emplace_back( new SimpleIterator{ loc, type } );
947 }
948
949 const Designation * CurrentObject::findNext( const Designation * designation ) {
950 using DesignatorChain = std::deque< ptr< Expr > >;
951 PRINT( std::cerr << "___findNext" << std::endl; )
952
953 // find all the d's
954 std::vector< DesignatorChain > desigAlts{ {} }, newDesigAlts;
955 std::deque< const Type * > curTypes{ objStack.back()->getType() }, newTypes;
956 for ( const Expr * expr : designation->designators ) {
957 PRINT( std::cerr << "____untyped: " << expr << std::endl; )
958 auto dit = desigAlts.begin();
959 if ( auto nexpr = dynamic_cast< const NameExpr * >( expr ) ) {
960 for ( const Type * t : curTypes ) {
961 assert( dit != desigAlts.end() );
962
963 DesignatorChain & d = *dit;
964 PRINT( std::cerr << "____actual: " << t << std::endl; )
965 if ( auto refType = dynamic_cast< const ReferenceToType * >( t ) ) {
966 // concatenate identical field names
967 for ( const Decl * mem : refType->lookup( nexpr->name ) ) {
968 if ( auto field = dynamic_cast< const ObjectDecl * >( mem ) ) {
969 PRINT( std::cerr << "____alt: " << field->type << std::endl; )
970 DesignatorChain d2 = d;
971 d2.emplace_back( new VariableExpr{ expr->location, field } );
972 newDesigAlts.emplace_back( std::move( d2 ) );
973 newTypes.emplace_back( field->type );
974 }
975 }
976 }
977
978 ++dit;
979 }
980 } else {
981 for ( const Type * t : curTypes ) {
982 assert( dit != desigAlts.end() );
983
984 DesignatorChain & d = *dit;
985 if ( auto at = dynamic_cast< const ArrayType * >( t ) ) {
986 PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
987 d.emplace_back( expr );
988 newDesigAlts.emplace_back( d );
989 newTypes.emplace_back( at->base );
990 }
991 }
992 }
993
994 // reset queue
995 desigAlts = std::move( newDesigAlts );
996 newDesigAlts.clear();
997 curTypes = std::move( newTypes );
998 newTypes.clear();
999 assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
1000 }
1001
1002 if ( desigAlts.size() > 1 ) {
1003 SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
1004 } else if ( desigAlts.empty() ) {
1005 SemanticError( designation, "No reasonable alternatives for designation: " );
1006 }
1007
1008 DesignatorChain & d = desigAlts.back();
1009 PRINT( for ( Expression * expr : d ) {
1010 std::cerr << "____desig: " << expr << std::endl;
1011 } ) // for
1012 assertf( ! curTypes.empty(), "empty designator chosen");
1013
1014 // set new designators
1015 assertf( ! objStack.empty(), "empty object stack when setting designation" );
1016 Designation * actualDesignation =
1017 new Designation{ designation->location, DesignatorChain{d} };
1018 objStack.back()->setPosition( d ); // destroys d
1019 return actualDesignation;
1020 }
1021
1022 void CurrentObject::setNext( const Designation * designation ) {
1023 PRINT( std::cerr << "____setNext" << designation << std::endl; )
1024 assertf( ! objStack.empty(), "obj stack empty in setNext" );
1025 objStack.back()->setPosition( designation->designators );
1026 }
1027
1028 void CurrentObject::increment() {
1029 PRINT( std::cerr << "____increment" << std::endl; )
1030 if ( objStack.empty() ) return;
1031 PRINT( std::cerr << *objStack.back() << std::endl; )
1032 objStack.back()->smallStep();
1033 }
1034
1035 void CurrentObject::enterListInit( const CodeLocation & loc ) {
1036 PRINT( std::cerr << "____entering list init" << std::endl; )
1037 assertf( ! objStack.empty(), "empty obj stack entering list init" );
1038 const ast::Type * type = objStack.back()->getNext();
1039 assert( type );
1040 objStack.emplace_back( createMemberIterator( loc, type ) );
1041 }
1042
1043 void CurrentObject::exitListInit() {
1044 PRINT( std::cerr << "____exiting list init" << std::endl; )
1045 assertf( ! objStack.empty(), "objstack empty" );
1046 objStack.pop_back();
1047 if ( ! objStack.empty() ) {
1048 PRINT( std::cerr << *objStack.back() << std::endl; )
1049 objStack.back()->bigStep();
1050 }
1051 }
1052
1053 std::deque< InitAlternative > CurrentObject::getOptions() {
1054 PRINT( std::cerr << "____getting current options" << std::endl; )
1055 assertf( ! objStack.empty(), "objstack empty in getOptions" );
1056 return **objStack.back();
1057 }
1058
1059 const Type * CurrentObject::getCurrentType() {
1060 PRINT( std::cerr << "____getting current type" << std::endl; )
1061 assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
1062 return objStack.back()->getNext();
1063 }
1064}
1065
1066// Local Variables: //
1067// tab-width: 4 //
1068// mode: c++ //
1069// compile-command: "make install" //
1070// End: //
Note: See TracBrowser for help on using the repository browser.