source: src/AST/Convert.cpp @ 81da70a

arm-ehenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-expr
Last change on this file since 81da70a was 81da70a, checked in by Fangren Yu <f37yu@…>, 2 years ago

actually fill inferred params and disable a check

  • Property mode set to 100644
File size: 73.2 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2019 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// Convert.cpp -- Convert between the new and old syntax trees.
8//
9// Author           : Thierry Delisle
10// Created On       : Thu May 09 15::37::05 2019
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Wed Dec 11 21:39:32 2019
13// Update Count     : 33
14//
15
16#include "Convert.hpp"
17
18#include <deque>
19#include <unordered_map>
20
21#include "AST/Attribute.hpp"
22#include "AST/Copy.hpp"
23#include "AST/Decl.hpp"
24#include "AST/Expr.hpp"
25#include "AST/Init.hpp"
26#include "AST/Stmt.hpp"
27#include "AST/TypeSubstitution.hpp"
28
29#include "SymTab/Autogen.h"
30#include "SynTree/Attribute.h"
31#include "SynTree/Declaration.h"
32#include "SynTree/TypeSubstitution.h"
33
34#include "Validate/FindSpecialDecls.h"
35
36//================================================================================================
37// Utilities
38template<template <class...> class C>
39struct to {
40        template<typename T>
41        static auto from( T && v ) -> C< typename T::value_type > {
42                C< typename T::value_type > l;
43                std::move(std::begin(v), std::end(v), std::back_inserter(l));
44                return l;
45        }
46};
47
48//================================================================================================
49namespace {
50
51// This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not)
52// allow us to use the same stratagy in the new ast.
53ast::Type * sizeType = nullptr;
54ast::FunctionDecl * dereferenceOperator = nullptr;
55ast::StructDecl   * dtorStruct = nullptr;
56ast::FunctionDecl * dtorStructDestroy = nullptr;
57
58}
59
60//================================================================================================
61class ConverterNewToOld : public ast::Visitor {
62        BaseSyntaxNode * node = nullptr;
63        using Cache = std::unordered_map< const ast::Node *, BaseSyntaxNode * >;
64        Cache cache;
65
66        template<typename T>
67        struct Getter {
68                ConverterNewToOld & visitor;
69
70                template<typename U, enum ast::Node::ref_type R>
71                T * accept1( const ast::ptr_base<U, R> & ptr ) {
72                        if ( ! ptr ) return nullptr;
73                        ptr->accept( visitor );
74                        T * ret = strict_dynamic_cast< T * >( visitor.node );
75                        visitor.node = nullptr;
76                        return ret;
77                }
78
79                template<typename U>
80                std::list< T * > acceptL( const U & container ) {
81                        std::list< T * > ret;
82                        for ( auto ptr : container ) {
83                                ret.emplace_back( accept1( ptr ) );
84                        }
85                        return ret;
86                }
87        };
88
89    template<typename T>
90    Getter<T> get() {
91        return Getter<T>{ *this };
92    }
93
94        Label makeLabel(Statement * labelled, const ast::Label& label) {
95                // This probably will leak memory, but only until we get rid of the old tree.
96                if ( nullptr == labelled && label.location.isSet() ) {
97                        labelled = new NullStmt();
98                        labelled->location = label.location;
99                }
100                return Label(
101                        label.name,
102                        labelled,
103                        get<Attribute>().acceptL(label.attributes)
104                );
105        }
106
107        template<template <class...> class C>
108        std::list<Label> makeLabelL(Statement * labelled, const C<ast::Label>& labels) {
109                std::list<Label> ret;
110                for (auto label : labels) {
111                        ret.push_back( makeLabel(labelled, label) );
112                }
113                return ret;
114        }
115
116        /// get new qualifiers from old type
117        Type::Qualifiers cv( const ast::Type * ty ) { return { ty->qualifiers.val }; }
118
119        /// returns true and sets `node` if in cache
120        bool inCache( const ast::Node * node ) {
121                auto it = cache.find( node );
122                if ( it == cache.end() ) return false;
123                this->node = it->second;
124                return true;
125        }
126
127public:
128        Declaration * decl( const ast::Decl * declNode ) {
129                return get<Declaration>().accept1( ast::ptr<ast::Decl>( declNode ) );
130        }
131
132private:
133        void declPostamble( Declaration * decl, const ast::Decl * node ) {
134                decl->location = node->location;
135                // name comes from constructor
136                // linkage comes from constructor
137                decl->extension = node->extension;
138                decl->uniqueId = node->uniqueId;
139                // storageClasses comes from constructor
140                this->node = decl;
141        }
142
143        const ast::DeclWithType * declWithTypePostamble (
144                        DeclarationWithType * decl, const ast::DeclWithType * node ) {
145                cache.emplace( node, decl );
146                decl->mangleName = node->mangleName;
147                decl->scopeLevel = node->scopeLevel;
148                decl->asmName = get<Expression>().accept1( node->asmName );
149                // attributes comes from constructor
150                decl->isDeleted = node->isDeleted;
151                // fs comes from constructor
152                declPostamble( decl, node );
153                return nullptr;
154        }
155
156        const ast::DeclWithType * visit( const ast::ObjectDecl * node ) override final {
157                auto&& bfwd = get<Expression>().accept1( node->bitfieldWidth );
158                auto&& type = get<Type>().accept1( node->type );
159                auto&& init = get<Initializer>().accept1( node->init );
160                auto&& attr = get<Attribute>().acceptL( node->attributes );
161                if ( inCache( node ) ) {
162                        return nullptr;
163                }
164                auto decl = new ObjectDecl(
165                        node->name,
166                        Type::StorageClasses( node->storage.val ),
167                        LinkageSpec::Spec( node->linkage.val ),
168                        bfwd,
169                        type,
170                        init,
171                        attr,
172                        Type::FuncSpecifiers( node->funcSpec.val )
173                );
174                return declWithTypePostamble( decl, node );
175        }
176
177        const ast::DeclWithType * visit( const ast::FunctionDecl * node ) override final {
178                if ( inCache( node ) ) return nullptr;
179                auto decl = new FunctionDecl(
180                        node->name,
181                        Type::StorageClasses( node->storage.val ),
182                        LinkageSpec::Spec( node->linkage.val ),
183                        get<FunctionType>().accept1( node->type ),
184                        {},
185                        get<Attribute>().acceptL( node->attributes ),
186                        Type::FuncSpecifiers( node->funcSpec.val )
187                );
188                cache.emplace( node, decl );
189                decl->statements = get<CompoundStmt>().accept1( node->stmts );
190                decl->withExprs = get<Expression>().acceptL( node->withExprs );
191                if ( dereferenceOperator == node ) {
192                        Validate::dereferenceOperator = decl;
193                }
194                if ( dtorStructDestroy == node ) {
195                        Validate::dtorStructDestroy = decl;
196                }
197                return declWithTypePostamble( decl, node );
198        }
199
200        const ast::Decl * namedTypePostamble( NamedTypeDecl * decl, const ast::NamedTypeDecl * node ) {
201                // base comes from constructor
202                decl->parameters = get<TypeDecl>().acceptL( node->params );
203                decl->assertions = get<DeclarationWithType>().acceptL( node->assertions );
204                declPostamble( decl, node );
205                return nullptr;
206        }
207
208        const ast::Decl * visit( const ast::TypeDecl * node ) override final {
209                if ( inCache( node ) ) return nullptr;
210                auto decl = new TypeDecl(
211                        node->name,
212                        Type::StorageClasses( node->storage.val ),
213                        get<Type>().accept1( node->base ),
214                        (TypeDecl::Kind)(unsigned)node->kind,
215                        node->sized,
216                        get<Type>().accept1( node->init )
217                );
218                cache.emplace( node, decl );
219                return namedTypePostamble( decl, node );
220        }
221
222        const ast::Decl * visit( const ast::TypedefDecl * node ) override final {
223                auto decl = new TypedefDecl(
224                        node->name,
225                        node->location,
226                        Type::StorageClasses( node->storage.val ),
227            get<Type>().accept1( node->base ),
228                        LinkageSpec::Spec( node->linkage.val )
229                );
230                return namedTypePostamble( decl, node );
231        }
232
233        const ast::Decl * aggregatePostamble( AggregateDecl * decl, const ast::AggregateDecl * node ) {
234                cache.emplace( node, decl );
235                decl->members = get<Declaration>().acceptL( node->members );
236                decl->parameters = get<TypeDecl>().acceptL( node->params );
237                decl->body = node->body;
238                // attributes come from constructor
239                decl->parent = get<AggregateDecl>().accept1( node->parent );
240                declPostamble( decl, node );
241                return nullptr;
242        }
243
244        const ast::Decl * visit( const ast::StructDecl * node ) override final {
245                if ( inCache( node ) ) return nullptr;
246                auto decl = new StructDecl(
247                        node->name,
248                        (AggregateDecl::Aggregate)node->kind,
249                        get<Attribute>().acceptL( node->attributes ),
250                        LinkageSpec::Spec( node->linkage.val )
251                );
252
253                if ( dtorStruct == node ) {
254                        Validate::dtorStruct = decl;
255                }
256
257                return aggregatePostamble( decl, node );
258        }
259
260        const ast::Decl * visit( const ast::UnionDecl * node ) override final {
261                if ( inCache( node ) ) return nullptr;
262                auto decl = new UnionDecl(
263                        node->name,
264                        get<Attribute>().acceptL( node->attributes ),
265                        LinkageSpec::Spec( node->linkage.val )
266                );
267                return aggregatePostamble( decl, node );
268        }
269
270        const ast::Decl * visit( const ast::EnumDecl * node ) override final {
271                if ( inCache( node ) ) return nullptr;
272                auto decl = new EnumDecl(
273                        node->name,
274                        get<Attribute>().acceptL( node->attributes ),
275                        LinkageSpec::Spec( node->linkage.val )
276                );
277                return aggregatePostamble( decl, node );
278        }
279
280        const ast::Decl * visit( const ast::TraitDecl * node ) override final {
281                if ( inCache( node ) ) return nullptr;
282                auto decl = new TraitDecl(
283                        node->name,
284                        {},
285                        LinkageSpec::Spec( node->linkage.val )
286                );
287                return aggregatePostamble( decl, node );
288        }
289
290        const ast::AsmDecl * visit( const ast::AsmDecl * node ) override final {
291                auto decl = new AsmDecl( get<AsmStmt>().accept1( node->stmt ) );
292                declPostamble( decl, node );
293                return nullptr;
294        }
295
296        const ast::StaticAssertDecl * visit( const ast::StaticAssertDecl * node ) override final {
297                auto decl = new StaticAssertDecl(
298                        get<Expression>().accept1( node->cond ),
299                        get<ConstantExpr>().accept1( node->msg )
300                );
301                declPostamble( decl, node );
302                return nullptr;
303        }
304
305        const ast::Stmt * stmtPostamble( Statement * stmt, const ast::Stmt * node ) {
306                cache.emplace( node, stmt );
307                stmt->location = node->location;
308                stmt->labels = makeLabelL( stmt, node->labels );
309                this->node = stmt;
310                return nullptr;
311        }
312
313        const ast::CompoundStmt * visit( const ast::CompoundStmt * node ) override final {
314                if ( inCache( node ) ) return nullptr;
315                auto stmt = new CompoundStmt( get<Statement>().acceptL( node->kids ) );
316                stmtPostamble( stmt, node );
317                return nullptr;
318        }
319
320        const ast::Stmt * visit( const ast::ExprStmt * node ) override final {
321                if ( inCache( node ) ) return nullptr;
322                auto stmt = new ExprStmt( nullptr );
323                cache.emplace( node, stmt );
324                stmt->expr = get<Expression>().accept1( node->expr );
325                return stmtPostamble( stmt, node );
326        }
327
328        const ast::Stmt * visit( const ast::AsmStmt * node ) override final {
329                if ( inCache( node ) ) return nullptr;
330                auto stmt = new AsmStmt(
331                        node->isVolatile,
332                        get<Expression>().accept1( node->instruction ),
333                        get<Expression>().acceptL( node->output ),
334                        get<Expression>().acceptL( node->input ),
335                        get<ConstantExpr>().acceptL( node->clobber ),
336                        makeLabelL( nullptr, node->gotoLabels ) // What are these labelling?
337                );
338                return stmtPostamble( stmt, node );
339        }
340
341        const ast::Stmt * visit( const ast::DirectiveStmt * node ) override final {
342                if ( inCache( node ) ) return nullptr;
343                auto stmt = new DirectiveStmt( node->directive );
344                return stmtPostamble( stmt, node );
345        }
346
347        const ast::Stmt * visit( const ast::IfStmt * node ) override final {
348                if ( inCache( node ) ) return nullptr;
349                auto stmt = new IfStmt(
350                        get<Expression>().accept1( node->cond ),
351                        get<Statement>().accept1( node->thenPart ),
352                        get<Statement>().accept1( node->elsePart ),
353                        get<Statement>().acceptL( node->inits )
354                );
355                return stmtPostamble( stmt, node );
356        }
357
358        const ast::Stmt * visit( const ast::SwitchStmt * node ) override final {
359                if ( inCache( node ) ) return nullptr;
360                auto stmt = new SwitchStmt(
361                        get<Expression>().accept1( node->cond ),
362                        get<Statement>().acceptL( node->stmts )
363                );
364                return stmtPostamble( stmt, node );
365        }
366
367        const ast::Stmt * visit( const ast::CaseStmt * node ) override final {
368                if ( inCache( node ) ) return nullptr;
369                auto stmt = new CaseStmt(
370                        get<Expression>().accept1( node->cond ),
371                        get<Statement>().acceptL( node->stmts ),
372                        node->isDefault()
373                );
374                return stmtPostamble( stmt, node );
375        }
376
377        const ast::Stmt * visit( const ast::WhileStmt * node ) override final {
378                if ( inCache( node ) ) return nullptr;
379                auto inits = get<Statement>().acceptL( node->inits );
380                auto stmt = new WhileStmt(
381                        get<Expression>().accept1( node->cond ),
382                        get<Statement>().accept1( node->body ),
383                        inits,
384                        node->isDoWhile
385                );
386                return stmtPostamble( stmt, node );
387        }
388
389        const ast::Stmt * visit( const ast::ForStmt * node ) override final {
390                if ( inCache( node ) ) return nullptr;
391                auto stmt = new ForStmt(
392                        get<Statement>().acceptL( node->inits ),
393                        get<Expression>().accept1( node->cond ),
394                        get<Expression>().accept1( node->inc ),
395                        get<Statement>().accept1( node->body )
396                );
397                return stmtPostamble( stmt, node );
398        }
399
400        const ast::Stmt * visit( const ast::BranchStmt * node ) override final {
401                if ( inCache( node ) ) return nullptr;
402                BranchStmt * stmt;
403                if (node->computedTarget) {
404                        stmt = new BranchStmt( get<Expression>().accept1( node->computedTarget ),
405                                BranchStmt::Goto );
406                } else {
407                        BranchStmt::Type type;
408                        switch (node->kind) {
409                        #define CASE(n) \
410                        case ast::BranchStmt::n: \
411                                type = BranchStmt::n; \
412                                break
413                        CASE(Goto);
414                        CASE(Break);
415                        CASE(Continue);
416                        CASE(FallThrough);
417                        CASE(FallThroughDefault);
418                        #undef CASE
419                        default:
420                                assertf(false, "Invalid ast::BranchStmt::Kind: %d\n", node->kind);
421                        }
422
423                        // The labels here are also weird.
424                        stmt = new BranchStmt( makeLabel( nullptr, node->originalTarget ), type );
425                        stmt->target = makeLabel( stmt, node->target );
426                }
427                return stmtPostamble( stmt, node );
428        }
429
430        const ast::Stmt * visit( const ast::ReturnStmt * node ) override final {
431                if ( inCache( node ) ) return nullptr;
432                auto stmt = new ReturnStmt( get<Expression>().accept1( node->expr ) );
433                return stmtPostamble( stmt, node );
434        }
435
436        const ast::Stmt * visit( const ast::ThrowStmt * node ) override final {
437                if ( inCache( node ) ) return nullptr;
438                ThrowStmt::Kind kind;
439                switch (node->kind) {
440                case ast::ExceptionKind::Terminate:
441                        kind = ThrowStmt::Terminate;
442                        break;
443                case ast::ExceptionKind::Resume:
444                        kind = ThrowStmt::Resume;
445                        break;
446                default:
447                        assertf(false, "Invalid ast::ThrowStmt::Kind: %d\n", node->kind);
448                }
449                auto stmt = new ThrowStmt(
450                        kind,
451                        get<Expression>().accept1( node->expr ),
452                        get<Expression>().accept1( node->target )
453                );
454                return stmtPostamble( stmt, node );
455        }
456
457        const ast::Stmt * visit( const ast::TryStmt * node ) override final {
458                if ( inCache( node ) ) return nullptr;
459                auto handlers = get<CatchStmt>().acceptL( node->handlers );
460                auto stmt = new TryStmt(
461                        get<CompoundStmt>().accept1( node->body ),
462                        handlers,
463                        get<FinallyStmt>().accept1( node->finally )
464                );
465                return stmtPostamble( stmt, node );
466        }
467
468        const ast::Stmt * visit( const ast::CatchStmt * node ) override final {
469                if ( inCache( node ) ) return nullptr;
470                CatchStmt::Kind kind;
471                switch (node->kind) {
472                case ast::ExceptionKind::Terminate:
473                        kind = CatchStmt::Terminate;
474                        break;
475                case ast::ExceptionKind::Resume:
476                        kind = CatchStmt::Resume;
477                        break;
478                default:
479                        assertf(false, "Invalid ast::CatchStmt::Kind: %d\n", node->kind);
480                }
481                auto stmt = new CatchStmt(
482                        kind,
483                        get<Declaration>().accept1( node->decl ),
484                        get<Expression>().accept1( node->cond ),
485                        get<Statement>().accept1( node->body )
486                );
487                return stmtPostamble( stmt, node );
488        }
489
490        const ast::Stmt * visit( const ast::FinallyStmt * node ) override final {
491                if ( inCache( node ) ) return nullptr;
492                auto stmt = new FinallyStmt( get<CompoundStmt>().accept1( node->body ) );
493                return stmtPostamble( stmt, node );
494        }
495
496        const ast::Stmt * visit(const ast::SuspendStmt * node ) override final {
497                if ( inCache( node ) ) return nullptr;
498                auto stmt = new SuspendStmt();
499                stmt->then   = get<CompoundStmt>().accept1( node->then   );
500                switch(node->type) {
501                        case ast::SuspendStmt::None     : stmt->type = SuspendStmt::None     ; break;
502                        case ast::SuspendStmt::Coroutine: stmt->type = SuspendStmt::Coroutine; break;
503                        case ast::SuspendStmt::Generator: stmt->type = SuspendStmt::Generator; break;
504                }
505                return stmtPostamble( stmt, node );
506        }
507
508        const ast::Stmt * visit( const ast::WaitForStmt * node ) override final {
509                if ( inCache( node ) ) return nullptr;
510                auto stmt = new WaitForStmt;
511                stmt->clauses.reserve( node->clauses.size() );
512                for ( auto clause : node->clauses ) {
513                        stmt->clauses.push_back({{
514                                        get<Expression>().accept1( clause.target.func ),
515                                        get<Expression>().acceptL( clause.target.args ),
516                                },
517                                get<Statement>().accept1( clause.stmt ),
518                                get<Expression>().accept1( clause.cond ),
519                        });
520                }
521                stmt->timeout = {
522                        get<Expression>().accept1( node->timeout.time ),
523                        get<Statement>().accept1( node->timeout.stmt ),
524                        get<Expression>().accept1( node->timeout.cond ),
525                };
526                stmt->orelse = {
527                        get<Statement>().accept1( node->orElse.stmt ),
528                        get<Expression>().accept1( node->orElse.cond ),
529                };
530                return stmtPostamble( stmt, node );
531        }
532
533        const ast::Decl * visit( const ast::WithStmt * node ) override final {
534                if ( inCache( node ) ) return nullptr;
535                auto stmt = new WithStmt(
536                        get<Expression>().acceptL( node->exprs ),
537                        get<Statement>().accept1( node->stmt )
538                );
539                declPostamble( stmt, node );
540                return nullptr;
541        }
542
543        const ast::NullStmt * visit( const ast::NullStmt * node ) override final {
544                if ( inCache( node ) ) return nullptr;
545                auto stmt = new NullStmt();
546                stmtPostamble( stmt, node );
547                return nullptr;
548        }
549
550        const ast::Stmt * visit( const ast::DeclStmt * node ) override final {
551                if ( inCache( node ) ) return nullptr;
552                auto stmt = new DeclStmt( get<Declaration>().accept1( node->decl ) );
553                return stmtPostamble( stmt, node );
554        }
555
556        const ast::Stmt * visit( const ast::ImplicitCtorDtorStmt * node ) override final {
557                if ( inCache( node ) ) return nullptr;
558                auto stmt = new ImplicitCtorDtorStmt{
559                        get<Statement>().accept1( node->callStmt )
560                };
561                return stmtPostamble( stmt, node );
562        }
563
564        TypeSubstitution * convertTypeSubstitution(const ast::TypeSubstitution * src) {
565
566                if (!src) return nullptr;
567
568                TypeSubstitution *rslt = new TypeSubstitution();
569
570                for (decltype(src->begin()) src_i = src->begin(); src_i != src->end(); src_i++) {
571                        rslt->add( src_i->first,
572                                   get<Type>().accept1(src_i->second) );
573                }
574
575                for (decltype(src->beginVar()) src_i = src->beginVar(); src_i != src->endVar(); src_i++) {
576                        rslt->addVar( src_i->first,
577                                      get<Expression>().accept1(src_i->second) );
578                }
579
580                return rslt;
581        }
582
583        void convertInferUnion(std::map<UniqueId,ParamEntry> &tgtInferParams,
584                                                   std::vector<UniqueId>         &tgtResnSlots,
585                                                   const ast::Expr::InferUnion   &srcInferred ) {
586
587                assert( tgtInferParams.empty() );
588                assert( tgtResnSlots.empty() );
589
590                if ( srcInferred.mode == ast::Expr::InferUnion::Params ) {
591                        const ast::InferredParams &srcParams = srcInferred.inferParams();
592                        for (auto & srcParam : srcParams) {
593                                auto res = tgtInferParams.emplace(srcParam.first, ParamEntry(
594                                        srcParam.second.decl,
595                                        get<Declaration>().accept1(srcParam.second.declptr)->clone(),
596                                        get<Type>().accept1(srcParam.second.actualType),
597                                        get<Type>().accept1(srcParam.second.formalType),
598                                        get<Expression>().accept1(srcParam.second.expr)
599                                ));
600                                assert(res.second);
601                        }
602                } else if ( srcInferred.mode == ast::Expr::InferUnion::Slots  ) {
603                        const ast::ResnSlots &srcSlots = srcInferred.resnSlots();
604                        for (auto srcSlot : srcSlots) {
605                                tgtResnSlots.push_back(srcSlot);
606                        }
607                }
608        }
609
610        Expression * visitBaseExpr_skipResultType(const ast::Expr * src, Expression * tgt) {
611
612                tgt->location  = src->location;
613                tgt->env       = convertTypeSubstitution(src->env);
614                tgt->extension = src->extension;
615
616                convertInferUnion(tgt->inferParams, tgt->resnSlots, src->inferred);
617                return tgt;
618        }
619
620        Expression * visitBaseExpr(const ast::Expr * src, Expression * tgt) {
621
622                tgt->result = get<Type>().accept1(src->result);
623                // Unconditionally use a clone of the result type.
624                // We know this will leak some objects: much of the immediate conversion result.
625                // In some cases, using the conversion result directly gives unintended object sharing.
626                // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.
627                // But tgt->result must be fully owned privately by tgt.
628                // Applying these conservative copies here means
629                // - weak references point at the declaration's copy, not these expr.result copies (good)
630                // - we copy more objects than really needed (bad, tolerated)
631                if (tgt->result) {
632                        tgt->result = tgt->result->clone();
633                }
634                return visitBaseExpr_skipResultType(src, tgt);
635        }
636
637        const ast::Expr * visit( const ast::ApplicationExpr * node ) override final {
638                auto expr = visitBaseExpr( node,
639                        new ApplicationExpr(
640                                get<Expression>().accept1(node->func),
641                                get<Expression>().acceptL(node->args)
642                        )
643                );
644                this->node = expr;
645                return nullptr;
646        }
647
648        const ast::Expr * visit( const ast::UntypedExpr * node ) override final {
649                auto expr = visitBaseExpr( node,
650                        new UntypedExpr(
651                                get<Expression>().accept1(node->func),
652                                get<Expression>().acceptL(node->args)
653                        )
654                );
655                this->node = expr;
656                return nullptr;
657        }
658
659        const ast::Expr * visit( const ast::NameExpr * node ) override final {
660                auto expr = visitBaseExpr( node,
661                        new NameExpr(
662                                node->name
663                        )
664                );
665                this->node = expr;
666                return nullptr;
667        }
668
669        const ast::Expr * visit( const ast::AddressExpr * node ) override final {
670                auto expr = visitBaseExpr( node,
671                        new AddressExpr(
672                                get<Expression>().accept1(node->arg)
673                        )
674                );
675                this->node = expr;
676                return nullptr;
677        }
678
679        const ast::Expr * visit( const ast::LabelAddressExpr * node ) override final {
680                auto expr = visitBaseExpr( node,
681                        new LabelAddressExpr(
682                                makeLabel(nullptr, node->arg)
683                        )
684                );
685                this->node = expr;
686                return nullptr;
687        }
688
689        const ast::Expr * visit( const ast::CastExpr * node ) override final {
690                auto expr = visitBaseExpr( node,
691                        new CastExpr(
692                                get<Expression>().accept1(node->arg),
693                                (node->isGenerated == ast::GeneratedCast)
694                        )
695                );
696                this->node = expr;
697                return nullptr;
698        }
699
700        const ast::Expr * visit( const ast::KeywordCastExpr * node ) override final {
701                AggregateDecl::Aggregate castTarget = (AggregateDecl::Aggregate)node->target;
702                assert( AggregateDecl::Generator <= castTarget && castTarget <= AggregateDecl::Thread );
703                auto expr = visitBaseExpr( node,
704                        new KeywordCastExpr(
705                                get<Expression>().accept1(node->arg),
706                                castTarget
707                        )
708                );
709                this->node = expr;
710                return nullptr;
711        }
712
713        const ast::Expr * visit( const ast::VirtualCastExpr * node ) override final {
714                auto expr = visitBaseExpr_skipResultType( node,
715                        new VirtualCastExpr(
716                                get<Expression>().accept1(node->arg),
717                                get<Type>().accept1(node->result)
718                        )
719                );
720                this->node = expr;
721                return nullptr;
722        }
723
724        const ast::Expr * visit( const ast::UntypedMemberExpr * node ) override final {
725                auto expr = visitBaseExpr( node,
726                        new UntypedMemberExpr(
727                                get<Expression>().accept1(node->member),
728                                get<Expression>().accept1(node->aggregate)
729                        )
730                );
731                this->node = expr;
732                return nullptr;
733        }
734
735        const ast::Expr * visit( const ast::MemberExpr * node ) override final {
736                auto expr = visitBaseExpr( node,
737                        new MemberExpr(
738                                get<DeclarationWithType>().accept1(node->member),
739                                get<Expression>().accept1(node->aggregate)
740                        )
741                );
742                this->node = expr;
743                return nullptr;
744        }
745
746        const ast::Expr * visit( const ast::VariableExpr * node ) override final {
747                auto expr = new VariableExpr();
748                expr->var = get<DeclarationWithType>().accept1(node->var);
749                visitBaseExpr( node, expr );
750                this->node = expr;
751                return nullptr;
752        }
753
754        const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
755                // Old world:   two types: rslt->constant.type, rslt->result
756                // New workd:   one public type: node->result, plus node->underlyer only to support roundtrip conversion
757                //              preserving underlyer because the correct type for string literals is complicated to construct,
758            //              and distinguishing a string from other literals using the type is hard to do accurately
759                // Both worlds: the outer, expression-level type can change during resolution
760                //              for a string, that's char[k] before-resolve and char * after
761                // Old world:   the inner Constant type stays what it was built with
762                //              for a string, that's char[k] always
763                // Both worlds: the "rep" field of a constant is the C source file fragment that compiles to the desired value
764        //              for a string, that includes outer quotes, backslashes, et al cases from the Literals test
765                ConstantExpr *rslt = new ConstantExpr(Constant(
766                        get<Type>().accept1(node->underlyer),
767                        node->rep,
768                        node->ival));
769                auto expr = visitBaseExpr( node, rslt );
770                this->node = expr;
771                return nullptr;
772        }
773
774        const ast::Expr * visit( const ast::SizeofExpr * node ) override final {
775                assert (node->expr || node->type);
776                assert (! (node->expr && node->type));
777                SizeofExpr *rslt;
778                if (node->expr) {
779                        rslt = new SizeofExpr(
780                                get<Expression>().accept1(node->expr)
781                        );
782                        assert (!rslt->isType);
783                }
784                else {
785                        assert(node->type);
786                        rslt = new SizeofExpr(
787                                get<Type>().accept1(node->type)
788                        );
789                        assert (rslt->isType);
790                }
791                auto expr = visitBaseExpr( node, rslt );
792                this->node = expr;
793                return nullptr;
794        }
795
796        const ast::Expr * visit( const ast::AlignofExpr * node ) override final {
797                assert (node->expr || node->type);
798                assert (! (node->expr && node->type));
799                AlignofExpr *rslt;
800                if (node->expr) {
801                        rslt = new AlignofExpr(
802                                get<Expression>().accept1(node->expr)
803                        );
804                        assert (!rslt->isType);
805                }
806                else {
807                        assert(node->type);
808                        rslt = new AlignofExpr(
809                                get<Type>().accept1(node->type)
810                        );
811                        assert (rslt->isType);
812                }
813                auto expr = visitBaseExpr( node, rslt );
814                this->node = expr;
815                return nullptr;
816        }
817
818        const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) override final {
819                auto expr = visitBaseExpr( node,
820                        new UntypedOffsetofExpr(
821                                get<Type>().accept1(node->type),
822                                node->member
823                        )
824                );
825                this->node = expr;
826                return nullptr;
827        }
828
829        const ast::Expr * visit( const ast::OffsetofExpr * node ) override final {
830                auto expr = visitBaseExpr( node,
831                        new OffsetofExpr(
832                                get<Type>().accept1(node->type),
833                                get<DeclarationWithType>().accept1(node->member)
834                        )
835                );
836                this->node = expr;
837                return nullptr;
838        }
839
840        const ast::Expr * visit( const ast::OffsetPackExpr * node ) override final {
841                auto expr = visitBaseExpr( node,
842                        new OffsetPackExpr(
843                                get<StructInstType>().accept1(node->type)
844                        )
845                );
846                this->node = expr;
847                return nullptr;
848        }
849
850        const ast::Expr * visit( const ast::LogicalExpr * node ) override final {
851                assert (node->isAnd == ast::LogicalFlag::AndExpr ||
852                                node->isAnd == ast::LogicalFlag::OrExpr );
853                auto expr = visitBaseExpr( node,
854                        new LogicalExpr(
855                                get<Expression>().accept1(node->arg1),
856                                get<Expression>().accept1(node->arg2),
857                                (node->isAnd == ast::LogicalFlag::AndExpr)
858                        )
859                );
860                this->node = expr;
861                return nullptr;
862        }
863
864        const ast::Expr * visit( const ast::ConditionalExpr * node ) override final {
865                auto expr = visitBaseExpr( node,
866                        new ConditionalExpr(
867                                get<Expression>().accept1(node->arg1),
868                                get<Expression>().accept1(node->arg2),
869                                get<Expression>().accept1(node->arg3)
870                        )
871                );
872                this->node = expr;
873                return nullptr;
874        }
875
876        const ast::Expr * visit( const ast::CommaExpr * node ) override final {
877                auto expr = visitBaseExpr( node,
878                        new CommaExpr(
879                                get<Expression>().accept1(node->arg1),
880                                get<Expression>().accept1(node->arg2)
881                        )
882                );
883                this->node = expr;
884                return nullptr;
885        }
886
887        const ast::Expr * visit( const ast::TypeExpr * node ) override final {
888                auto expr = visitBaseExpr( node,
889                        new TypeExpr(
890                                get<Type>().accept1(node->type)
891                        )
892                );
893                this->node = expr;
894                return nullptr;
895        }
896
897        const ast::Expr * visit( const ast::AsmExpr * node ) override final {
898                auto expr = visitBaseExpr( node,
899                        new AsmExpr(
900                                new std::string(node->inout),
901                                get<Expression>().accept1(node->constraint),
902                                get<Expression>().accept1(node->operand)
903                        )
904                );
905                this->node = expr;
906                return nullptr;
907        }
908
909        const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) override final {
910                auto rslt = new ImplicitCopyCtorExpr(
911                        get<ApplicationExpr>().accept1(node->callExpr)
912                );
913
914                auto expr = visitBaseExpr( node, rslt );
915                this->node = expr;
916                return nullptr;
917        }
918
919        const ast::Expr * visit( const ast::ConstructorExpr * node ) override final {
920                auto expr = visitBaseExpr( node,
921                        new ConstructorExpr(
922                                get<Expression>().accept1(node->callExpr)
923                        )
924                );
925                this->node = expr;
926                return nullptr;
927        }
928
929        const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) override final {
930                auto expr = visitBaseExpr_skipResultType( node,
931                        new CompoundLiteralExpr(
932                                get<Type>().accept1(node->result),
933                                get<Initializer>().accept1(node->init)
934                        )
935                );
936                this->node = expr;
937                return nullptr;
938        }
939
940        const ast::Expr * visit( const ast::RangeExpr * node ) override final {
941                auto expr = visitBaseExpr( node,
942                        new RangeExpr(
943                                get<Expression>().accept1(node->low),
944                                get<Expression>().accept1(node->high)
945                        )
946                );
947                this->node = expr;
948                return nullptr;
949        }
950
951        const ast::Expr * visit( const ast::UntypedTupleExpr * node ) override final {
952                auto expr = visitBaseExpr( node,
953                        new UntypedTupleExpr(
954                                get<Expression>().acceptL(node->exprs)
955                        )
956                );
957                this->node = expr;
958                return nullptr;
959        }
960
961        const ast::Expr * visit( const ast::TupleExpr * node ) override final {
962                auto expr = visitBaseExpr( node,
963                        new TupleExpr(
964                                get<Expression>().acceptL(node->exprs)
965                        )
966                );
967                this->node = expr;
968                return nullptr;
969        }
970
971        const ast::Expr * visit( const ast::TupleIndexExpr * node ) override final {
972                auto expr = visitBaseExpr( node,
973                        new TupleIndexExpr(
974                                get<Expression>().accept1(node->tuple),
975                                node->index
976                        )
977                );
978                this->node = expr;
979                return nullptr;
980        }
981
982        const ast::Expr * visit( const ast::TupleAssignExpr * node ) override final {
983                auto expr = visitBaseExpr( node,
984                        new TupleAssignExpr(
985                                get<StmtExpr>().accept1(node->stmtExpr)
986                        )
987                );
988                this->node = expr;
989                return nullptr;
990        }
991
992        const ast::Expr * visit( const ast::StmtExpr * node ) override final {
993                auto stmts = node->stmts;
994                // disable sharing between multiple StmtExprs explicitly.
995                if (inCache(stmts)) {
996                        stmts = ast::deepCopy(stmts.get());
997                }
998                auto rslt = new StmtExpr(
999                        get<CompoundStmt>().accept1(stmts)
1000                );
1001
1002                rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
1003                rslt->dtors       = get<Expression>().acceptL(node->dtors);
1004
1005                auto expr = visitBaseExpr( node, rslt );
1006                this->node = expr;
1007                return nullptr;
1008        }
1009
1010        const ast::Expr * visit( const ast::UniqueExpr * node ) override final {
1011                auto rslt = new UniqueExpr(
1012                        get<Expression>().accept1(node->expr),
1013                        node->id
1014                );
1015
1016                rslt->object = get<ObjectDecl>  ().accept1(node->object);
1017                rslt->var    = get<VariableExpr>().accept1(node->var);
1018
1019                auto expr = visitBaseExpr( node, rslt );
1020                this->node = expr;
1021                return nullptr;
1022        }
1023
1024        const ast::Expr * visit( const ast::UntypedInitExpr * node ) override final {
1025                std::list<InitAlternative> initAlts;
1026                for (auto ia : node->initAlts) {
1027                        initAlts.push_back(InitAlternative(
1028                                get<Type>       ().accept1(ia.type),
1029                                get<Designation>().accept1(ia.designation)
1030                        ));
1031                }
1032                auto expr = visitBaseExpr( node,
1033                        new UntypedInitExpr(
1034                                get<Expression>().accept1(node->expr),
1035                                initAlts
1036                        )
1037                );
1038                this->node = expr;
1039                return nullptr;
1040        }
1041
1042        const ast::Expr * visit( const ast::InitExpr * node ) override final {
1043                auto expr = visitBaseExpr( node,
1044                        new InitExpr(
1045                                get<Expression>().accept1(node->expr),
1046                                get<Designation>().accept1(node->designation)
1047                        )
1048                );
1049                this->node = expr;
1050                return nullptr;
1051        }
1052
1053        const ast::Expr * visit( const ast::DeletedExpr * node ) override final {
1054                auto expr = visitBaseExpr( node,
1055                        new DeletedExpr(
1056                                get<Expression>().accept1(node->expr),
1057                                inCache(node->deleteStmt) ?
1058                                        strict_dynamic_cast<Declaration*>(this->node) :
1059                                        get<Declaration>().accept1(node->deleteStmt)
1060                        )
1061                );
1062                this->node = expr;
1063                return nullptr;
1064        }
1065
1066        const ast::Expr * visit( const ast::DefaultArgExpr * node ) override final {
1067                auto expr = visitBaseExpr( node,
1068                        new DefaultArgExpr(
1069                                get<Expression>().accept1(node->expr)
1070                        )
1071                );
1072                this->node = expr;
1073                return nullptr;
1074        }
1075
1076        const ast::Expr * visit( const ast::GenericExpr * node ) override final {
1077                std::list<GenericExpr::Association> associations;
1078                for (auto association : node->associations) {
1079                        associations.push_back(GenericExpr::Association(
1080                                get<Type>      ().accept1(association.type),
1081                                get<Expression>().accept1(association.expr)
1082                        ));
1083                }
1084                auto expr = visitBaseExpr( node,
1085                        new GenericExpr(
1086                                get<Expression>().accept1(node->control),
1087                                associations
1088                        )
1089                );
1090                this->node = expr;
1091                return nullptr;
1092        }
1093
1094        const ast::Type * visitType( const ast::Type * node, Type * type ) {
1095                // Some types do this in their constructor so add a check.
1096                if ( !node->attributes.empty() && type->attributes.empty() ) {
1097                        type->attributes = get<Attribute>().acceptL( node->attributes );
1098                }
1099                this->node = type;
1100                return nullptr;
1101        }
1102
1103        const ast::Type * visit( const ast::VoidType * node ) override final {
1104                return visitType( node, new VoidType{ cv( node ) } );
1105        }
1106
1107        const ast::Type * visit( const ast::BasicType * node ) override final {
1108                auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind };
1109                // I believe this should always be a BasicType.
1110                if ( sizeType == node ) {
1111                        Validate::SizeType = type;
1112                }
1113                return visitType( node, type );
1114        }
1115
1116        const ast::Type * visit( const ast::PointerType * node ) override final {
1117                return visitType( node, new PointerType{
1118                        cv( node ),
1119                        get<Type>().accept1( node->base ),
1120                        get<Expression>().accept1( node->dimension ),
1121                        (bool)node->isVarLen,
1122                        (bool)node->isStatic
1123                } );
1124        }
1125
1126        const ast::Type * visit( const ast::ArrayType * node ) override final {
1127                return visitType( node, new ArrayType{
1128                        cv( node ),
1129                        get<Type>().accept1( node->base ),
1130                        get<Expression>().accept1( node->dimension ),
1131                        (bool)node->isVarLen,
1132                        (bool)node->isStatic
1133                } );
1134        }
1135
1136        const ast::Type * visit( const ast::ReferenceType * node ) override final {
1137                return visitType( node, new ReferenceType{
1138                        cv( node ),
1139                        get<Type>().accept1( node->base )
1140                } );
1141        }
1142
1143        const ast::Type * visit( const ast::QualifiedType * node ) override final {
1144                return visitType( node, new QualifiedType{
1145                        cv( node ),
1146                        get<Type>().accept1( node->parent ),
1147                        get<Type>().accept1( node->child )
1148                } );
1149        }
1150
1151        const ast::Type * visit( const ast::FunctionType * node ) override final {
1152                auto ty = new FunctionType {
1153                        cv( node ),
1154                        (bool)node->isVarArgs
1155                };
1156                ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
1157                ty->parameters = get<DeclarationWithType>().acceptL( node->params );
1158                ty->forall = get<TypeDecl>().acceptL( node->forall );
1159                return visitType( node, ty );
1160        }
1161
1162        const ast::Type * postvisit( const ast::ReferenceToType * old, ReferenceToType * ty ) {
1163                ty->forall = get<TypeDecl>().acceptL( old->forall );
1164                ty->parameters = get<Expression>().acceptL( old->params );
1165                ty->hoistType = old->hoistType;
1166                return visitType( old, ty );
1167        }
1168
1169        const ast::Type * visit( const ast::StructInstType * node ) override final {
1170                StructInstType * ty;
1171                if ( node->base ) {
1172                        ty = new StructInstType{
1173                                cv( node ),
1174                                get<StructDecl>().accept1( node->base ),
1175                                get<Attribute>().acceptL( node->attributes )
1176                        };
1177                } else {
1178                        ty = new StructInstType{
1179                                cv( node ),
1180                                node->name,
1181                                get<Attribute>().acceptL( node->attributes )
1182                        };
1183                }
1184                return postvisit( node, ty );
1185        }
1186
1187        const ast::Type * visit( const ast::UnionInstType * node ) override final {
1188                UnionInstType * ty;
1189                if ( node->base ) {
1190                        ty = new UnionInstType{
1191                                cv( node ),
1192                                get<UnionDecl>().accept1( node->base ),
1193                                get<Attribute>().acceptL( node->attributes )
1194                        };
1195                } else {
1196                        ty = new UnionInstType{
1197                                cv( node ),
1198                                node->name,
1199                                get<Attribute>().acceptL( node->attributes )
1200                        };
1201                }
1202                return postvisit( node, ty );
1203        }
1204
1205        const ast::Type * visit( const ast::EnumInstType * node ) override final {
1206                EnumInstType * ty;
1207                if ( node->base ) {
1208                        ty = new EnumInstType{
1209                                cv( node ),
1210                                get<EnumDecl>().accept1( node->base ),
1211                                get<Attribute>().acceptL( node->attributes )
1212                        };
1213                } else {
1214                        ty = new EnumInstType{
1215                                cv( node ),
1216                                node->name,
1217                                get<Attribute>().acceptL( node->attributes )
1218                        };
1219                }
1220                return postvisit( node, ty );
1221        }
1222
1223        const ast::Type * visit( const ast::TraitInstType * node ) override final {
1224                TraitInstType * ty;
1225                if ( node->base ) {
1226                        ty = new TraitInstType{
1227                                cv( node ),
1228                                get<TraitDecl>().accept1( node->base ),
1229                                get<Attribute>().acceptL( node->attributes )
1230                        };
1231                } else {
1232                        ty = new TraitInstType{
1233                                cv( node ),
1234                                node->name,
1235                                get<Attribute>().acceptL( node->attributes )
1236                        };
1237                }
1238                return postvisit( node, ty );
1239        }
1240
1241        const ast::Type * visit( const ast::TypeInstType * node ) override final {
1242                TypeInstType * ty;
1243                if ( node->base ) {
1244                        ty = new TypeInstType{
1245                                cv( node ),
1246                                node->name,
1247                                get<TypeDecl>().accept1( node->base ),
1248                                get<Attribute>().acceptL( node->attributes )
1249                        };
1250                } else {
1251                        ty = new TypeInstType{
1252                                cv( node ),
1253                                node->name,
1254                                node->kind == ast::TypeDecl::Ftype,
1255                                get<Attribute>().acceptL( node->attributes )
1256                        };
1257                }
1258                return postvisit( node, ty );
1259        }
1260
1261        const ast::Type * visit( const ast::TupleType * node ) override final {
1262                return visitType( node, new TupleType{
1263                        cv( node ),
1264                        get<Type>().acceptL( node->types )
1265                        // members generated by TupleType c'tor
1266                } );
1267        }
1268
1269        const ast::Type * visit( const ast::TypeofType * node ) override final {
1270                return visitType( node, new TypeofType{
1271                        cv( node ),
1272                        get<Expression>().accept1( node->expr ),
1273                        (bool)node->kind
1274                } );
1275        }
1276
1277        const ast::Type * visit( const ast::VarArgsType * node ) override final {
1278                return visitType( node, new VarArgsType{ cv( node ) } );
1279        }
1280
1281        const ast::Type * visit( const ast::ZeroType * node ) override final {
1282                return visitType( node, new ZeroType{ cv( node ) } );
1283        }
1284
1285        const ast::Type * visit( const ast::OneType * node ) override final {
1286                return visitType( node, new OneType{ cv( node ) } );
1287        }
1288
1289        const ast::Type * visit( const ast::GlobalScopeType * node ) override final {
1290                return visitType( node, new GlobalScopeType{} );
1291        }
1292
1293        const ast::Designation * visit( const ast::Designation * node ) override final {
1294                auto designation = new Designation( get<Expression>().acceptL( node->designators ) );
1295                designation->location = node->location;
1296                this->node = designation;
1297                return nullptr;
1298        }
1299
1300        const ast::Init * visit( const ast::SingleInit * node ) override final {
1301                auto init = new SingleInit(
1302                        get<Expression>().accept1( node->value ),
1303                        ast::MaybeConstruct == node->maybeConstructed
1304                );
1305                init->location = node->location;
1306                this->node = init;
1307                return nullptr;
1308        }
1309
1310        const ast::Init * visit( const ast::ListInit * node ) override final {
1311                auto init = new ListInit(
1312                        get<Initializer>().acceptL( node->initializers ),
1313                        get<Designation>().acceptL( node->designations ),
1314                        ast::MaybeConstruct == node->maybeConstructed
1315                );
1316                init->location = node->location;
1317                this->node = init;
1318                return nullptr;
1319        }
1320
1321        const ast::Init * visit( const ast::ConstructorInit * node ) override final {
1322                auto init = new ConstructorInit(
1323                        get<Statement>().accept1( node->ctor ),
1324                        get<Statement>().accept1( node->dtor ),
1325                        get<Initializer>().accept1( node->init )
1326                );
1327                init->location = node->location;
1328                this->node = init;
1329                return nullptr;
1330        }
1331
1332        const ast::Attribute * visit( const ast::Attribute * node ) override final {
1333                auto attr = new Attribute(
1334                        node->name,
1335                        get<Expression>().acceptL(node->params)
1336                );
1337                this->node = attr;
1338                return nullptr;
1339        }
1340
1341        const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) override final {
1342                // Handled by convertTypeSubstitution helper instead.
1343                // TypeSubstitution is not a node in the old model, so the conversion result wouldn't fit in this->node.
1344                assert( 0 );
1345                (void)node;
1346                return nullptr;
1347        }
1348};
1349
1350std::list< Declaration * > convert( const std::list< ast::ptr< ast::Decl > > && translationUnit ) {
1351        ConverterNewToOld c;
1352        std::list< Declaration * > decls;
1353        for(auto d : translationUnit) {
1354                decls.emplace_back( c.decl( d ) );
1355        }
1356        return decls;
1357}
1358
1359//================================================================================================
1360
1361class ConverterOldToNew : public Visitor {
1362public:
1363        ast::Decl * decl() {
1364                return strict_dynamic_cast< ast::Decl * >( node );
1365        }
1366
1367        ConverterOldToNew() = default;
1368        ConverterOldToNew(const ConverterOldToNew &) = delete;
1369        ConverterOldToNew(ConverterOldToNew &&) = delete;
1370private:
1371        /// conversion output
1372        ast::Node * node = nullptr;
1373        /// cache of nodes that might be referenced by readonly<> for de-duplication
1374        std::unordered_map< const BaseSyntaxNode *, ast::Node * > cache = {};
1375
1376        // Local Utilities:
1377
1378        template<typename NewT, typename OldT>
1379        NewT * getAccept1( OldT old ) {
1380                if ( ! old ) return nullptr;
1381                old->accept(*this);
1382                ast::Node * ret = node;
1383                node = nullptr;
1384                return strict_dynamic_cast< NewT * >( ret );
1385        }
1386
1387#       define GET_ACCEPT_1(child, type) \
1388                getAccept1< ast::type, decltype( old->child ) >( old->child )
1389
1390        template<typename NewT, typename OldC>
1391        std::vector< ast::ptr<NewT> > getAcceptV( const OldC& old ) {
1392                std::vector< ast::ptr<NewT> > ret;
1393                ret.reserve( old.size() );
1394                for ( auto a : old ) {
1395                        a->accept( *this );
1396                        ret.emplace_back( strict_dynamic_cast< NewT * >(node) );
1397                        node = nullptr;
1398                }
1399                return ret;
1400        }
1401
1402#       define GET_ACCEPT_V(child, type) \
1403                getAcceptV< ast::type, decltype( old->child ) >( old->child )
1404
1405        template<typename NewT, typename OldC>
1406        std::deque< ast::ptr<NewT> > getAcceptD( const OldC& old ) {
1407                std::deque< ast::ptr<NewT> > ret;
1408                for ( auto a : old ) {
1409                        a->accept( *this );
1410                        ret.emplace_back( strict_dynamic_cast< NewT * >(node) );
1411                        node = nullptr;
1412                }
1413                return ret;
1414        }
1415
1416#       define GET_ACCEPT_D(child, type) \
1417                getAcceptD< ast::type, decltype( old->child ) >( old->child )
1418
1419        ast::Label make_label(const Label* old) {
1420                CodeLocation const & location =
1421                    ( old->labelled ) ? old->labelled->location : CodeLocation();
1422                return ast::Label(
1423                        location,
1424                        old->name,
1425                        GET_ACCEPT_V(attributes, Attribute)
1426                );
1427        }
1428
1429        template<template <class...> class C>
1430        C<ast::Label> make_labels(C<Label> olds) {
1431                C<ast::Label> ret;
1432                for (auto oldn : olds) {
1433                        ret.push_back( make_label( &oldn ) );
1434                }
1435                return ret;
1436        }
1437
1438#       define GET_LABELS_V(labels) \
1439                to<std::vector>::from( make_labels( std::move( labels ) ) )
1440
1441        static ast::CV::Qualifiers cv( const Type * ty ) { return { ty->tq.val }; }
1442
1443        /// returns true and sets `node` if in cache
1444        bool inCache( const BaseSyntaxNode * old ) {
1445                auto it = cache.find( old );
1446                if ( it == cache.end() ) return false;
1447                node = it->second;
1448                return true;
1449        }
1450
1451        // Now all the visit functions:
1452
1453        virtual void visit( const ObjectDecl * old ) override final {
1454                auto&& type = GET_ACCEPT_1(type, Type);
1455                auto&& init = GET_ACCEPT_1(init, Init);
1456                auto&& bfwd = GET_ACCEPT_1(bitfieldWidth, Expr);
1457                auto&& attr = GET_ACCEPT_V(attributes, Attribute);
1458                if ( inCache( old ) ) {
1459                        return;
1460                }
1461                auto decl = new ast::ObjectDecl(
1462                        old->location,
1463                        old->name,
1464                        type,
1465                        init,
1466                        { old->get_storageClasses().val },
1467                        { old->linkage.val },
1468                        bfwd,
1469                        std::move(attr),
1470                        { old->get_funcSpec().val }
1471                );
1472                cache.emplace(old, decl);
1473                assert(cache.find( old ) != cache.end());
1474                decl->scopeLevel = old->scopeLevel;
1475                decl->mangleName = old->mangleName;
1476                decl->isDeleted  = old->isDeleted;
1477                decl->asmName    = GET_ACCEPT_1(asmName, Expr);
1478                decl->uniqueId   = old->uniqueId;
1479                decl->extension  = old->extension;
1480
1481                this->node = decl;
1482        }
1483
1484        virtual void visit( const FunctionDecl * old ) override final {
1485                if ( inCache( old ) ) return;
1486                auto decl = new ast::FunctionDecl{
1487                        old->location,
1488                        old->name,
1489                        GET_ACCEPT_1(type, FunctionType),
1490                        {},
1491                        { old->storageClasses.val },
1492                        { old->linkage.val },
1493                        GET_ACCEPT_V(attributes, Attribute),
1494                        { old->get_funcSpec().val }
1495                };
1496                cache.emplace( old, decl );
1497                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
1498                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
1499                decl->scopeLevel = old->scopeLevel;
1500                decl->mangleName = old->mangleName;
1501                decl->isDeleted  = old->isDeleted;
1502                decl->asmName    = GET_ACCEPT_1(asmName, Expr);
1503                decl->uniqueId   = old->uniqueId;
1504                decl->extension  = old->extension;
1505
1506                this->node = decl;
1507
1508                if ( Validate::dereferenceOperator == old ) {
1509                        dereferenceOperator = decl;
1510                }
1511
1512                if ( Validate::dtorStructDestroy == old ) {
1513                        dtorStructDestroy = decl;
1514                }
1515        }
1516
1517        virtual void visit( const StructDecl * old ) override final {
1518                if ( inCache( old ) ) return;
1519                auto decl = new ast::StructDecl(
1520                        old->location,
1521                        old->name,
1522                        (ast::AggregateDecl::Aggregate)old->kind,
1523                        GET_ACCEPT_V(attributes, Attribute),
1524                        { old->linkage.val }
1525                );
1526                cache.emplace( old, decl );
1527                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1528                decl->body   = old->body;
1529                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1530                decl->members    = GET_ACCEPT_V(members, Decl);
1531                decl->extension  = old->extension;
1532                decl->uniqueId   = old->uniqueId;
1533                decl->storage    = { old->storageClasses.val };
1534
1535                this->node = decl;
1536
1537                if ( Validate::dtorStruct == old ) {
1538                        dtorStruct = decl;
1539                }
1540        }
1541
1542        virtual void visit( const UnionDecl * old ) override final {
1543                if ( inCache( old ) ) return;
1544                auto decl = new ast::UnionDecl(
1545                        old->location,
1546                        old->name,
1547                        GET_ACCEPT_V(attributes, Attribute),
1548                        { old->linkage.val }
1549                );
1550                cache.emplace( old, decl );
1551                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1552                decl->body   = old->body;
1553                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1554                decl->members    = GET_ACCEPT_V(members, Decl);
1555                decl->extension  = old->extension;
1556                decl->uniqueId   = old->uniqueId;
1557                decl->storage    = { old->storageClasses.val };
1558
1559                this->node = decl;
1560        }
1561
1562        virtual void visit( const EnumDecl * old ) override final {
1563                if ( inCache( old ) ) return;
1564                auto decl = new ast::EnumDecl(
1565                        old->location,
1566                        old->name,
1567                        GET_ACCEPT_V(attributes, Attribute),
1568                        { old->linkage.val }
1569                );
1570                cache.emplace( old, decl );
1571                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1572                decl->body   = old->body;
1573                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1574                decl->members    = GET_ACCEPT_V(members, Decl);
1575                decl->extension  = old->extension;
1576                decl->uniqueId   = old->uniqueId;
1577                decl->storage    = { old->storageClasses.val };
1578
1579                this->node = decl;
1580        }
1581
1582        virtual void visit( const TraitDecl * old ) override final {
1583                if ( inCache( old ) ) return;
1584                auto decl = new ast::TraitDecl(
1585                        old->location,
1586                        old->name,
1587                        GET_ACCEPT_V(attributes, Attribute),
1588                        { old->linkage.val }
1589                );
1590                cache.emplace( old, decl );
1591                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1592                decl->body   = old->body;
1593                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1594                decl->members    = GET_ACCEPT_V(members, Decl);
1595                decl->extension  = old->extension;
1596                decl->uniqueId   = old->uniqueId;
1597                decl->storage    = { old->storageClasses.val };
1598
1599                this->node = decl;
1600        }
1601
1602        virtual void visit( const TypeDecl * old ) override final {
1603                if ( inCache( old ) ) return;
1604                auto decl = new ast::TypeDecl{
1605                        old->location,
1606                        old->name,
1607                        { old->storageClasses.val },
1608                        GET_ACCEPT_1(base, Type),
1609                        (ast::TypeDecl::Kind)(unsigned)old->kind,
1610                        old->sized,
1611                        GET_ACCEPT_1(init, Type)
1612                };
1613                cache.emplace( old, decl );
1614                decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
1615                decl->params     = GET_ACCEPT_V(parameters, TypeDecl);
1616                decl->extension  = old->extension;
1617                decl->uniqueId   = old->uniqueId;
1618
1619                this->node = decl;
1620        }
1621
1622        virtual void visit( const TypedefDecl * old ) override final {
1623                auto decl = new ast::TypedefDecl(
1624                        old->location,
1625                        old->name,
1626                        { old->storageClasses.val },
1627                        GET_ACCEPT_1(base, Type),
1628                        { old->linkage.val }
1629                );
1630                decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
1631                decl->params     = GET_ACCEPT_V(parameters, TypeDecl);
1632                decl->extension  = old->extension;
1633                decl->uniqueId   = old->uniqueId;
1634                decl->storage    = { old->storageClasses.val };
1635
1636                this->node = decl;
1637        }
1638
1639        virtual void visit( const AsmDecl * old ) override final {
1640                auto decl = new ast::AsmDecl{
1641                        old->location,
1642                        GET_ACCEPT_1(stmt, AsmStmt)
1643                };
1644                decl->extension  = old->extension;
1645                decl->uniqueId   = old->uniqueId;
1646                decl->storage    = { old->storageClasses.val };
1647
1648                this->node = decl;
1649        }
1650
1651        virtual void visit( const StaticAssertDecl * old ) override final {
1652                auto decl = new ast::StaticAssertDecl{
1653                        old->location,
1654                        GET_ACCEPT_1(condition, Expr),
1655                        GET_ACCEPT_1(message, ConstantExpr)
1656                };
1657                decl->extension  = old->extension;
1658                decl->uniqueId   = old->uniqueId;
1659                decl->storage    = { old->storageClasses.val };
1660
1661                this->node = decl;
1662        }
1663
1664        virtual void visit( const CompoundStmt * old ) override final {
1665                if ( inCache( old ) ) return;
1666                auto stmt = new ast::CompoundStmt(
1667                        old->location,
1668                        to<std::list>::from( GET_ACCEPT_V(kids, Stmt) ),
1669                        GET_LABELS_V(old->labels)
1670                );
1671
1672                this->node = stmt;
1673                cache.emplace( old, this->node );
1674        }
1675
1676        virtual void visit( const ExprStmt * old ) override final {
1677                if ( inCache( old ) ) return;
1678                this->node = new ast::ExprStmt(
1679                        old->location,
1680                        GET_ACCEPT_1(expr, Expr),
1681                        GET_LABELS_V(old->labels)
1682                );
1683                cache.emplace( old, this->node );
1684        }
1685
1686        virtual void visit( const AsmStmt * old ) override final {
1687                if ( inCache( old ) ) return;
1688                this->node = new ast::AsmStmt(
1689                        old->location,
1690                        old->voltile,
1691                        GET_ACCEPT_1(instruction, Expr),
1692                        GET_ACCEPT_V(output, Expr),
1693                        GET_ACCEPT_V(input, Expr),
1694                        GET_ACCEPT_V(clobber, ConstantExpr),
1695                        GET_LABELS_V(old->gotolabels),
1696                        GET_LABELS_V(old->labels)
1697                );
1698                cache.emplace( old, this->node );
1699        }
1700
1701        virtual void visit( const DirectiveStmt * old ) override final {
1702                if ( inCache( old ) ) return;
1703                this->node = new ast::DirectiveStmt(
1704                        old->location,
1705                        old->directive,
1706                        GET_LABELS_V(old->labels)
1707                );
1708                cache.emplace( old, this->node );
1709        }
1710
1711        virtual void visit( const IfStmt * old ) override final {
1712                if ( inCache( old ) ) return;
1713                this->node = new ast::IfStmt(
1714                        old->location,
1715                        GET_ACCEPT_1(condition, Expr),
1716                        GET_ACCEPT_1(thenPart, Stmt),
1717                        GET_ACCEPT_1(elsePart, Stmt),
1718                        GET_ACCEPT_V(initialization, Stmt),
1719                        GET_LABELS_V(old->labels)
1720                );
1721                cache.emplace( old, this->node );
1722        }
1723
1724        virtual void visit( const SwitchStmt * old ) override final {
1725                if ( inCache( old ) ) return;
1726                this->node = new ast::SwitchStmt(
1727                        old->location,
1728                        GET_ACCEPT_1(condition, Expr),
1729                        GET_ACCEPT_V(statements, Stmt),
1730                        GET_LABELS_V(old->labels)
1731                );
1732                cache.emplace( old, this->node );
1733        }
1734
1735        virtual void visit( const CaseStmt * old ) override final {
1736                if ( inCache( old ) ) return;
1737                this->node = new ast::CaseStmt(
1738                        old->location,
1739                        GET_ACCEPT_1(condition, Expr),
1740                        GET_ACCEPT_V(stmts, Stmt),
1741                        GET_LABELS_V(old->labels)
1742                );
1743                cache.emplace( old, this->node );
1744        }
1745
1746        virtual void visit( const WhileStmt * old ) override final {
1747                if ( inCache( old ) ) return;
1748                this->node = new ast::WhileStmt(
1749                        old->location,
1750                        GET_ACCEPT_1(condition, Expr),
1751                        GET_ACCEPT_1(body, Stmt),
1752                        GET_ACCEPT_V(initialization, Stmt),
1753                        old->isDoWhile,
1754                        GET_LABELS_V(old->labels)
1755                );
1756                cache.emplace( old, this->node );
1757        }
1758
1759        virtual void visit( const ForStmt * old ) override final {
1760                if ( inCache( old ) ) return;
1761                this->node = new ast::ForStmt(
1762                        old->location,
1763                        GET_ACCEPT_V(initialization, Stmt),
1764                        GET_ACCEPT_1(condition, Expr),
1765                        GET_ACCEPT_1(increment, Expr),
1766                        GET_ACCEPT_1(body, Stmt),
1767                        GET_LABELS_V(old->labels)
1768                );
1769                cache.emplace( old, this->node );
1770        }
1771
1772        virtual void visit( const BranchStmt * old ) override final {
1773                if ( inCache( old ) ) return;
1774                if (old->computedTarget) {
1775                        this->node = new ast::BranchStmt(
1776                                old->location,
1777                                GET_ACCEPT_1(computedTarget, Expr),
1778                                GET_LABELS_V(old->labels)
1779                        );
1780                } else {
1781                        ast::BranchStmt::Kind kind;
1782                        switch (old->type) {
1783                        #define CASE(n) \
1784                        case BranchStmt::n: \
1785                                kind = ast::BranchStmt::n; \
1786                                break
1787                        CASE(Goto);
1788                        CASE(Break);
1789                        CASE(Continue);
1790                        CASE(FallThrough);
1791                        CASE(FallThroughDefault);
1792                        #undef CASE
1793                        default:
1794                                assertf(false, "Invalid BranchStmt::Type %d\n", old->type);
1795                        }
1796
1797                        auto stmt = new ast::BranchStmt(
1798                                old->location,
1799                                kind,
1800                                make_label(&old->originalTarget),
1801                                GET_LABELS_V(old->labels)
1802                        );
1803                        stmt->target = make_label(&old->target);
1804                        this->node = stmt;
1805                }
1806                cache.emplace( old, this->node );
1807        }
1808
1809        virtual void visit( const ReturnStmt * old ) override final {
1810                if ( inCache( old ) ) return;
1811                this->node = new ast::ReturnStmt(
1812                        old->location,
1813                        GET_ACCEPT_1(expr, Expr),
1814                        GET_LABELS_V(old->labels)
1815                );
1816                cache.emplace( old, this->node );
1817        }
1818
1819        virtual void visit( const ThrowStmt * old ) override final {
1820                if ( inCache( old ) ) return;
1821                ast::ExceptionKind kind;
1822                switch (old->kind) {
1823                case ThrowStmt::Terminate:
1824                        kind = ast::ExceptionKind::Terminate;
1825                        break;
1826                case ThrowStmt::Resume:
1827                        kind = ast::ExceptionKind::Resume;
1828                        break;
1829                default:
1830                        assertf(false, "Invalid ThrowStmt::Kind %d\n", old->kind);
1831                }
1832
1833                this->node = new ast::ThrowStmt(
1834                        old->location,
1835                        kind,
1836                        GET_ACCEPT_1(expr, Expr),
1837                        GET_ACCEPT_1(target, Expr),
1838                        GET_LABELS_V(old->labels)
1839                );
1840                cache.emplace( old, this->node );
1841        }
1842
1843        virtual void visit( const TryStmt * old ) override final {
1844                if ( inCache( old ) ) return;
1845                this->node = new ast::TryStmt(
1846                        old->location,
1847                        GET_ACCEPT_1(block, CompoundStmt),
1848                        GET_ACCEPT_V(handlers, CatchStmt),
1849                        GET_ACCEPT_1(finallyBlock, FinallyStmt),
1850                        GET_LABELS_V(old->labels)
1851                );
1852                cache.emplace( old, this->node );
1853        }
1854
1855        virtual void visit( const CatchStmt * old ) override final {
1856                if ( inCache( old ) ) return;
1857                ast::ExceptionKind kind;
1858                switch (old->kind) {
1859                case CatchStmt::Terminate:
1860                        kind = ast::ExceptionKind::Terminate;
1861                        break;
1862                case CatchStmt::Resume:
1863                        kind = ast::ExceptionKind::Resume;
1864                        break;
1865                default:
1866                        assertf(false, "Invalid CatchStmt::Kind %d\n", old->kind);
1867                }
1868
1869                this->node = new ast::CatchStmt(
1870                        old->location,
1871                        kind,
1872                        GET_ACCEPT_1(decl, Decl),
1873                        GET_ACCEPT_1(cond, Expr),
1874                        GET_ACCEPT_1(body, Stmt),
1875                        GET_LABELS_V(old->labels)
1876                );
1877                cache.emplace( old, this->node );
1878        }
1879
1880        virtual void visit( const FinallyStmt * old ) override final {
1881                if ( inCache( old ) ) return;
1882                this->node = new ast::FinallyStmt(
1883                        old->location,
1884                        GET_ACCEPT_1(block, CompoundStmt),
1885                        GET_LABELS_V(old->labels)
1886                );
1887                cache.emplace( old, this->node );
1888        }
1889
1890        virtual void visit( const SuspendStmt * old ) override final {
1891                if ( inCache( old ) ) return;
1892                ast::SuspendStmt::Type type;
1893                switch (old->type) {
1894                        case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break;
1895                        case SuspendStmt::Generator: type = ast::SuspendStmt::Generator; break;
1896                        case SuspendStmt::None     : type = ast::SuspendStmt::None     ; break;
1897                        default: abort();
1898                }
1899                this->node = new ast::SuspendStmt(
1900                        old->location,
1901                        GET_ACCEPT_1(then  , CompoundStmt),
1902                        type,
1903                        GET_LABELS_V(old->labels)
1904                );
1905                cache.emplace( old, this->node );
1906        }
1907
1908        virtual void visit( const WaitForStmt * old ) override final {
1909                if ( inCache( old ) ) return;
1910                ast::WaitForStmt * stmt = new ast::WaitForStmt(
1911                        old->location,
1912                        GET_LABELS_V(old->labels)
1913                );
1914
1915                stmt->clauses.reserve( old->clauses.size() );
1916                for (size_t i = 0 ; i < old->clauses.size() ; ++i) {
1917                        stmt->clauses.push_back({
1918                                ast::WaitForStmt::Target{
1919                                        GET_ACCEPT_1(clauses[i].target.function, Expr),
1920                                        GET_ACCEPT_V(clauses[i].target.arguments, Expr)
1921                                },
1922                                GET_ACCEPT_1(clauses[i].statement, Stmt),
1923                                GET_ACCEPT_1(clauses[i].condition, Expr)
1924                        });
1925                }
1926                stmt->timeout = {
1927                        GET_ACCEPT_1(timeout.time, Expr),
1928                        GET_ACCEPT_1(timeout.statement, Stmt),
1929                        GET_ACCEPT_1(timeout.condition, Expr),
1930                };
1931                stmt->orElse = {
1932                        GET_ACCEPT_1(orelse.statement, Stmt),
1933                        GET_ACCEPT_1(orelse.condition, Expr),
1934                };
1935
1936                this->node = stmt;
1937                cache.emplace( old, this->node );
1938        }
1939
1940        virtual void visit( const WithStmt * old ) override final {
1941                if ( inCache( old ) ) return;
1942                this->node = new ast::WithStmt(
1943                        old->location,
1944                        GET_ACCEPT_V(exprs, Expr),
1945                        GET_ACCEPT_1(stmt, Stmt)
1946                );
1947                cache.emplace( old, this->node );
1948        }
1949
1950        virtual void visit( const NullStmt * old ) override final {
1951                if ( inCache( old ) ) return;
1952                this->node = new ast::NullStmt(
1953                        old->location,
1954                        GET_LABELS_V(old->labels)
1955                );
1956                cache.emplace( old, this->node );
1957        }
1958
1959        virtual void visit( const DeclStmt * old ) override final {
1960                if ( inCache( old ) ) return;
1961                this->node = new ast::DeclStmt(
1962                        old->location,
1963                        GET_ACCEPT_1(decl, Decl),
1964                        GET_LABELS_V(old->labels)
1965                );
1966                cache.emplace( old, this->node );
1967        }
1968
1969        virtual void visit( const ImplicitCtorDtorStmt * old ) override final {
1970                if ( inCache( old ) ) return;
1971                auto stmt = new ast::ImplicitCtorDtorStmt(
1972                        old->location,
1973                        nullptr,
1974                        GET_LABELS_V(old->labels)
1975                );
1976                cache.emplace( old, stmt );
1977                stmt->callStmt = GET_ACCEPT_1(callStmt, Stmt);
1978                this->node = stmt;
1979        }
1980
1981        ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) {
1982
1983                if (!old) return nullptr;
1984
1985                ast::TypeSubstitution *rslt = new ast::TypeSubstitution();
1986
1987                for (decltype(old->begin()) old_i = old->begin(); old_i != old->end(); old_i++) {
1988                        rslt->add( old_i->first,
1989                                   getAccept1<ast::Type>(old_i->second) );
1990                }
1991
1992                for (decltype(old->beginVar()) old_i = old->beginVar(); old_i != old->endVar(); old_i++) {
1993                        rslt->addVar( old_i->first,
1994                                      getAccept1<ast::Expr>(old_i->second) );
1995                }
1996
1997                return rslt;
1998        }
1999
2000        void convertInferUnion(ast::Expr::InferUnion               &newInferred,
2001                                                   const std::map<UniqueId,ParamEntry> &oldInferParams,
2002                                                   const std::vector<UniqueId>         &oldResnSlots) {
2003
2004                assert( oldInferParams.empty() || oldResnSlots.empty() );
2005                assert( newInferred.mode == ast::Expr::InferUnion::Empty );
2006
2007                if ( !oldInferParams.empty() ) {
2008                        ast::InferredParams &tgt = newInferred.inferParams();
2009                        for (auto & old : oldInferParams) {
2010                                tgt[old.first] = ast::ParamEntry(
2011                                        old.second.decl,
2012                                        getAccept1<ast::Decl>(old.second.declptr),
2013                                        getAccept1<ast::Type>(old.second.actualType),
2014                                        getAccept1<ast::Type>(old.second.formalType),
2015                                        getAccept1<ast::Expr>(old.second.expr)
2016                                );
2017                        }
2018                } else if ( !oldResnSlots.empty() ) {
2019                        ast::ResnSlots &tgt = newInferred.resnSlots();
2020                        for (auto old : oldResnSlots) {
2021                                tgt.push_back(old);
2022                        }
2023                }
2024        }
2025
2026        ast::Expr * visitBaseExpr_SkipResultType( const Expression * old, ast::Expr * nw) {
2027
2028                nw->env    = convertTypeSubstitution(old->env);
2029
2030                nw->extension = old->extension;
2031                convertInferUnion(nw->inferred, old->inferParams, old->resnSlots);
2032
2033                return nw;
2034        }
2035
2036        ast::Expr * visitBaseExpr( const Expression * old, ast::Expr * nw) {
2037
2038                nw->result = GET_ACCEPT_1(result, Type);
2039                return visitBaseExpr_SkipResultType(old, nw);;
2040        }
2041
2042        virtual void visit( const ApplicationExpr * old ) override final {
2043                this->node = visitBaseExpr( old,
2044                        new ast::ApplicationExpr(
2045                                old->location,
2046                                GET_ACCEPT_1(function, Expr),
2047                                GET_ACCEPT_V(args, Expr)
2048                        )
2049                );
2050        }
2051
2052        virtual void visit( const UntypedExpr * old ) override final {
2053                this->node = visitBaseExpr( old,
2054                        new ast::UntypedExpr(
2055                                old->location,
2056                                GET_ACCEPT_1(function, Expr),
2057                                GET_ACCEPT_V(args, Expr)
2058                        )
2059                );
2060        }
2061
2062        virtual void visit( const NameExpr * old ) override final {
2063                this->node = visitBaseExpr( old,
2064                        new ast::NameExpr(
2065                                old->location,
2066                                old->get_name()
2067                        )
2068                );
2069        }
2070
2071        virtual void visit( const CastExpr * old ) override final {
2072                this->node = visitBaseExpr( old,
2073                        new ast::CastExpr(
2074                                old->location,
2075                                GET_ACCEPT_1(arg, Expr),
2076                                old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast
2077                        )
2078                );
2079        }
2080
2081        virtual void visit( const KeywordCastExpr * old ) override final {
2082                ast::AggregateDecl::Aggregate castTarget = (ast::AggregateDecl::Aggregate)old->target;
2083                assert( ast::AggregateDecl::Generator <= castTarget && castTarget <= ast::AggregateDecl::Thread );
2084                this->node = visitBaseExpr( old,
2085                        new ast::KeywordCastExpr(
2086                                old->location,
2087                                GET_ACCEPT_1(arg, Expr),
2088                                castTarget
2089                        )
2090                );
2091        }
2092
2093        virtual void visit( const VirtualCastExpr * old ) override final {
2094                this->node = visitBaseExpr_SkipResultType( old,
2095                        new ast::VirtualCastExpr(
2096                                old->location,
2097                                GET_ACCEPT_1(arg, Expr),
2098                                GET_ACCEPT_1(result, Type)
2099                        )
2100                );
2101        }
2102
2103        virtual void visit( const AddressExpr * old ) override final {
2104                this->node = visitBaseExpr( old,
2105                        new ast::AddressExpr(
2106                                old->location,
2107                                GET_ACCEPT_1(arg, Expr)
2108                        )
2109                );
2110        }
2111
2112        virtual void visit( const LabelAddressExpr * old ) override final {
2113                this->node = visitBaseExpr( old,
2114                        new ast::LabelAddressExpr(
2115                                old->location,
2116                                make_label(&old->arg)
2117                        )
2118                );
2119        }
2120
2121        virtual void visit( const UntypedMemberExpr * old ) override final {
2122                this->node = visitBaseExpr( old,
2123                        new ast::UntypedMemberExpr(
2124                                old->location,
2125                                GET_ACCEPT_1(member, Expr),
2126                                GET_ACCEPT_1(aggregate, Expr)
2127                        )
2128                );
2129        }
2130
2131        virtual void visit( const MemberExpr * old ) override final {
2132                this->node = visitBaseExpr( old,
2133                        new ast::MemberExpr(
2134                                old->location,
2135                                GET_ACCEPT_1(member, DeclWithType),
2136                                GET_ACCEPT_1(aggregate, Expr),
2137                                ast::MemberExpr::NoOpConstructionChosen
2138                        )
2139                );
2140        }
2141
2142        virtual void visit( const VariableExpr * old ) override final {
2143                auto expr = new ast::VariableExpr(
2144                        old->location
2145                );
2146
2147                expr->var = GET_ACCEPT_1(var, DeclWithType);
2148                visitBaseExpr( old, expr );
2149
2150                this->node = expr;
2151        }
2152
2153        virtual void visit( const ConstantExpr * old ) override final {
2154                ast::ConstantExpr *rslt = new ast::ConstantExpr(
2155                        old->location,
2156                        GET_ACCEPT_1(result, Type),
2157                        old->constant.rep,
2158                        old->constant.ival
2159                );
2160                rslt->underlyer = getAccept1< ast::Type, Type* >( old->constant.type );
2161                this->node = visitBaseExpr( old, rslt );
2162        }
2163
2164        virtual void visit( const SizeofExpr * old ) override final {
2165                assert (old->expr || old->type);
2166                assert (! (old->expr && old->type));
2167                ast::SizeofExpr *rslt;
2168                if (old->expr) {
2169                        assert(!old->isType);
2170                        rslt = new ast::SizeofExpr(
2171                                old->location,
2172                                GET_ACCEPT_1(expr, Expr)
2173                        );
2174                }
2175                if (old->type) {
2176                        assert(old->isType);
2177                        rslt = new ast::SizeofExpr(
2178                                old->location,
2179                                GET_ACCEPT_1(type, Type)
2180                        );
2181                }
2182                this->node = visitBaseExpr( old, rslt );
2183        }
2184
2185        virtual void visit( const AlignofExpr * old ) override final {
2186                assert (old->expr || old->type);
2187                assert (! (old->expr && old->type));
2188                ast::AlignofExpr *rslt;
2189                if (old->expr) {
2190                        assert(!old->isType);
2191                        rslt = new ast::AlignofExpr(
2192                                old->location,
2193                                GET_ACCEPT_1(expr, Expr)
2194                        );
2195                }
2196                if (old->type) {
2197                        assert(old->isType);
2198                        rslt = new ast::AlignofExpr(
2199                                old->location,
2200                                GET_ACCEPT_1(type, Type)
2201                        );
2202                }
2203                this->node = visitBaseExpr( old, rslt );
2204        }
2205
2206        virtual void visit( const UntypedOffsetofExpr * old ) override final {
2207                this->node = visitBaseExpr( old,
2208                        new ast::UntypedOffsetofExpr(
2209                                old->location,
2210                                GET_ACCEPT_1(type, Type),
2211                                old->member
2212                        )
2213                );
2214        }
2215
2216        virtual void visit( const OffsetofExpr * old ) override final {
2217                this->node = visitBaseExpr( old,
2218                        new ast::OffsetofExpr(
2219                                old->location,
2220                                GET_ACCEPT_1(type, Type),
2221                                GET_ACCEPT_1(member, DeclWithType)
2222                        )
2223                );
2224        }
2225
2226        virtual void visit( const OffsetPackExpr * old ) override final {
2227                this->node = visitBaseExpr( old,
2228                        new ast::OffsetPackExpr(
2229                                old->location,
2230                                GET_ACCEPT_1(type, StructInstType)
2231                        )
2232                );
2233        }
2234
2235        virtual void visit( const LogicalExpr * old ) override final {
2236                this->node = visitBaseExpr( old,
2237                        new ast::LogicalExpr(
2238                                old->location,
2239                                GET_ACCEPT_1(arg1, Expr),
2240                                GET_ACCEPT_1(arg2, Expr),
2241                                old->get_isAnd() ?
2242                                        ast::LogicalFlag::AndExpr :
2243                                        ast::LogicalFlag::OrExpr
2244                        )
2245                );
2246        }
2247
2248        virtual void visit( const ConditionalExpr * old ) override final {
2249                this->node = visitBaseExpr( old,
2250                        new ast::ConditionalExpr(
2251                                old->location,
2252                                GET_ACCEPT_1(arg1, Expr),
2253                                GET_ACCEPT_1(arg2, Expr),
2254                                GET_ACCEPT_1(arg3, Expr)
2255                        )
2256                );
2257        }
2258
2259        virtual void visit( const CommaExpr * old ) override final {
2260                this->node = visitBaseExpr( old,
2261                        new ast::CommaExpr(
2262                                old->location,
2263                                GET_ACCEPT_1(arg1, Expr),
2264                                GET_ACCEPT_1(arg2, Expr)
2265                        )
2266                );
2267        }
2268
2269        virtual void visit( const TypeExpr * old ) override final {
2270                this->node = visitBaseExpr( old,
2271                        new ast::TypeExpr(
2272                                old->location,
2273                                GET_ACCEPT_1(type, Type)
2274                        )
2275                );
2276        }
2277
2278        virtual void visit( const AsmExpr * old ) override final {
2279                this->node = visitBaseExpr( old,
2280                        new ast::AsmExpr(
2281                                old->location,
2282                                old->inout,
2283                                GET_ACCEPT_1(constraint, Expr),
2284                                GET_ACCEPT_1(operand, Expr)
2285                        )
2286                );
2287        }
2288
2289        virtual void visit( const ImplicitCopyCtorExpr * old ) override final {
2290                auto rslt = new ast::ImplicitCopyCtorExpr(
2291                        old->location,
2292                        GET_ACCEPT_1(callExpr, ApplicationExpr)
2293                );
2294
2295                this->node = visitBaseExpr( old, rslt );
2296        }
2297
2298        virtual void visit( const ConstructorExpr * old ) override final {
2299                this->node = visitBaseExpr( old,
2300                        new ast::ConstructorExpr(
2301                                old->location,
2302                                GET_ACCEPT_1(callExpr, Expr)
2303                        )
2304                );
2305        }
2306
2307        virtual void visit( const CompoundLiteralExpr * old ) override final {
2308                this->node = visitBaseExpr_SkipResultType( old,
2309                        new ast::CompoundLiteralExpr(
2310                                old->location,
2311                                GET_ACCEPT_1(result, Type),
2312                                GET_ACCEPT_1(initializer, Init)
2313                        )
2314                );
2315        }
2316
2317        virtual void visit( const RangeExpr * old ) override final {
2318                this->node = visitBaseExpr( old,
2319                        new ast::RangeExpr(
2320                                old->location,
2321                                GET_ACCEPT_1(low, Expr),
2322                                GET_ACCEPT_1(high, Expr)
2323                        )
2324                );
2325        }
2326
2327        virtual void visit( const UntypedTupleExpr * old ) override final {
2328                this->node = visitBaseExpr( old,
2329                        new ast::UntypedTupleExpr(
2330                                old->location,
2331                                GET_ACCEPT_V(exprs, Expr)
2332                        )
2333                );
2334        }
2335
2336        virtual void visit( const TupleExpr * old ) override final {
2337                this->node = visitBaseExpr( old,
2338                        new ast::TupleExpr(
2339                                old->location,
2340                                GET_ACCEPT_V(exprs, Expr)
2341                        )
2342                );
2343        }
2344
2345        virtual void visit( const TupleIndexExpr * old ) override final {
2346                this->node = visitBaseExpr( old,
2347                        new ast::TupleIndexExpr(
2348                                old->location,
2349                                GET_ACCEPT_1(tuple, Expr),
2350                                old->index
2351                        )
2352                );
2353        }
2354
2355        virtual void visit( const TupleAssignExpr * old ) override final {
2356                this->node = visitBaseExpr_SkipResultType( old,
2357                        new ast::TupleAssignExpr(
2358                                old->location,
2359                                GET_ACCEPT_1(result, Type),
2360                                GET_ACCEPT_1(stmtExpr, StmtExpr)
2361                        )
2362                );
2363        }
2364
2365        virtual void visit( const StmtExpr * old ) override final {
2366                auto rslt = new ast::StmtExpr(
2367                        old->location,
2368                        GET_ACCEPT_1(statements, CompoundStmt)
2369                );
2370                rslt->returnDecls = GET_ACCEPT_V(returnDecls, ObjectDecl);
2371                rslt->dtors       = GET_ACCEPT_V(dtors      , Expr);
2372
2373                this->node = visitBaseExpr_SkipResultType( old, rslt );
2374        }
2375
2376        virtual void visit( const UniqueExpr * old ) override final {
2377                auto rslt = new ast::UniqueExpr(
2378                        old->location,
2379                        GET_ACCEPT_1(expr, Expr),
2380                        old->get_id()
2381                );
2382                rslt->object = GET_ACCEPT_1(object, ObjectDecl);
2383                rslt->var    = GET_ACCEPT_1(var   , VariableExpr);
2384
2385                this->node = visitBaseExpr( old, rslt );
2386        }
2387
2388        virtual void visit( const UntypedInitExpr * old ) override final {
2389                std::deque<ast::InitAlternative> initAlts;
2390                for (auto ia : old->initAlts) {
2391                        initAlts.push_back(ast::InitAlternative(
2392                                getAccept1< ast::Type, Type * >( ia.type ),
2393                                getAccept1< ast::Designation, Designation * >( ia.designation )
2394                        ));
2395                }
2396                this->node = visitBaseExpr( old,
2397                        new ast::UntypedInitExpr(
2398                                old->location,
2399                                GET_ACCEPT_1(expr, Expr),
2400                                std::move(initAlts)
2401                        )
2402                );
2403        }
2404
2405        virtual void visit( const InitExpr * old ) override final {
2406                this->node = visitBaseExpr( old,
2407                        new ast::InitExpr(
2408                                old->location,
2409                                GET_ACCEPT_1(expr, Expr),
2410                                GET_ACCEPT_1(designation, Designation)
2411                        )
2412                );
2413        }
2414
2415        virtual void visit( const DeletedExpr * old ) override final {
2416                this->node = visitBaseExpr( old,
2417                        new ast::DeletedExpr(
2418                                old->location,
2419                                GET_ACCEPT_1(expr, Expr),
2420                                inCache(old->deleteStmt) ?
2421                                        strict_dynamic_cast<ast::Decl*>(this->node) :
2422                                        GET_ACCEPT_1(deleteStmt, Decl)
2423                        )
2424                );
2425        }
2426
2427        virtual void visit( const DefaultArgExpr * old ) override final {
2428                this->node = visitBaseExpr( old,
2429                        new ast::DefaultArgExpr(
2430                                old->location,
2431                                GET_ACCEPT_1(expr, Expr)
2432                        )
2433                );
2434        }
2435
2436        virtual void visit( const GenericExpr * old ) override final {
2437                std::vector<ast::GenericExpr::Association> associations;
2438                for (auto association : old->associations) {
2439                        associations.push_back(ast::GenericExpr::Association(
2440                                getAccept1< ast::Type, Type * >( association.type ),
2441                                getAccept1< ast::Expr, Expression * >( association.expr )
2442                        ));
2443                }
2444                this->node = visitBaseExpr( old,
2445                        new ast::GenericExpr(
2446                                old->location,
2447                                GET_ACCEPT_1(control, Expr),
2448                                std::move(associations)
2449                        )
2450                );
2451        }
2452
2453        void visitType( const Type * old, ast::Type * type ) {
2454                // Some types do this in their constructor so add a check.
2455                if ( !old->attributes.empty() && type->attributes.empty() ) {
2456                        type->attributes = GET_ACCEPT_V(attributes, Attribute);
2457                }
2458                this->node = type;
2459        }
2460
2461        virtual void visit( const VoidType * old ) override final {
2462                visitType( old, new ast::VoidType{ cv( old ) } );
2463        }
2464
2465        virtual void visit( const BasicType * old ) override final {
2466                auto type = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind, cv( old ) };
2467                // I believe this should always be a BasicType.
2468                if ( Validate::SizeType == old ) {
2469                        sizeType = type;
2470                }
2471                visitType( old, type );
2472        }
2473
2474        virtual void visit( const PointerType * old ) override final {
2475                visitType( old, new ast::PointerType{
2476                        GET_ACCEPT_1( base, Type ),
2477                        GET_ACCEPT_1( dimension, Expr ),
2478                        (ast::LengthFlag)old->isVarLen,
2479                        (ast::DimensionFlag)old->isStatic,
2480                        cv( old )
2481                } );
2482        }
2483
2484        virtual void visit( const ArrayType * old ) override final {
2485                visitType( old, new ast::ArrayType{
2486                        GET_ACCEPT_1( base, Type ),
2487                        GET_ACCEPT_1( dimension, Expr ),
2488                        (ast::LengthFlag)old->isVarLen,
2489                        (ast::DimensionFlag)old->isStatic,
2490                        cv( old )
2491                } );
2492        }
2493
2494        virtual void visit( const ReferenceType * old ) override final {
2495                visitType( old, new ast::ReferenceType{
2496                        GET_ACCEPT_1( base, Type ),
2497                        cv( old )
2498                } );
2499        }
2500
2501        virtual void visit( const QualifiedType * old ) override final {
2502                visitType( old, new ast::QualifiedType{
2503                        GET_ACCEPT_1( parent, Type ),
2504                        GET_ACCEPT_1( child, Type ),
2505                        cv( old )
2506                } );
2507        }
2508
2509        virtual void visit( const FunctionType * old ) override final {
2510                auto ty = new ast::FunctionType {
2511                        (ast::ArgumentFlag)old->isVarArgs,
2512                        cv( old )
2513                };
2514                ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
2515                ty->params = GET_ACCEPT_V( parameters, DeclWithType );
2516                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
2517                visitType( old, ty );
2518        }
2519
2520        void postvisit( const ReferenceToType * old, ast::ReferenceToType * ty ) {
2521                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
2522                ty->params = GET_ACCEPT_V( parameters, Expr );
2523                ty->hoistType = old->hoistType;
2524                visitType( old, ty );
2525        }
2526
2527        virtual void visit( const StructInstType * old ) override final {
2528                ast::StructInstType * ty;
2529                if ( old->baseStruct ) {
2530                        ty = new ast::StructInstType{
2531                                GET_ACCEPT_1( baseStruct, StructDecl ),
2532                                cv( old ),
2533                                GET_ACCEPT_V( attributes, Attribute )
2534                        };
2535                } else {
2536                        ty = new ast::StructInstType{
2537                                old->name,
2538                                cv( old ),
2539                                GET_ACCEPT_V( attributes, Attribute )
2540                        };
2541                }
2542                postvisit( old, ty );
2543        }
2544
2545        virtual void visit( const UnionInstType * old ) override final {
2546                ast::UnionInstType * ty;
2547                if ( old->baseUnion ) {
2548                        ty = new ast::UnionInstType{
2549                                GET_ACCEPT_1( baseUnion, UnionDecl ),
2550                                cv( old ),
2551                                GET_ACCEPT_V( attributes, Attribute )
2552                        };
2553                } else {
2554                        ty = new ast::UnionInstType{
2555                                old->name,
2556                                cv( old ),
2557                                GET_ACCEPT_V( attributes, Attribute )
2558                        };
2559                }
2560                postvisit( old, ty );
2561        }
2562
2563        virtual void visit( const EnumInstType * old ) override final {
2564                ast::EnumInstType * ty;
2565                if ( old->baseEnum ) {
2566                        ty = new ast::EnumInstType{
2567                                GET_ACCEPT_1( baseEnum, EnumDecl ),
2568                                cv( old ),
2569                                GET_ACCEPT_V( attributes, Attribute )
2570                        };
2571                } else {
2572                        ty = new ast::EnumInstType{
2573                                old->name,
2574                                cv( old ),
2575                                GET_ACCEPT_V( attributes, Attribute )
2576                        };
2577                }
2578                postvisit( old, ty );
2579        }
2580
2581        virtual void visit( const TraitInstType * old ) override final {
2582                ast::TraitInstType * ty;
2583                if ( old->baseTrait ) {
2584                        ty = new ast::TraitInstType{
2585                                GET_ACCEPT_1( baseTrait, TraitDecl ),
2586                                cv( old ),
2587                                GET_ACCEPT_V( attributes, Attribute )
2588                        };
2589                } else {
2590                        ty = new ast::TraitInstType{
2591                                old->name,
2592                                cv( old ),
2593                                GET_ACCEPT_V( attributes, Attribute )
2594                        };
2595                }
2596                postvisit( old, ty );
2597        }
2598
2599        virtual void visit( const TypeInstType * old ) override final {
2600                ast::TypeInstType * ty;
2601                if ( old->baseType ) {
2602                        ty = new ast::TypeInstType{
2603                                old->name,
2604                                GET_ACCEPT_1( baseType, TypeDecl ),
2605                                cv( old ),
2606                                GET_ACCEPT_V( attributes, Attribute )
2607                        };
2608                } else {
2609                        ty = new ast::TypeInstType{
2610                                old->name,
2611                                old->isFtype ? ast::TypeDecl::Ftype : ast::TypeDecl::Dtype,
2612                                cv( old ),
2613                                GET_ACCEPT_V( attributes, Attribute )
2614                        };
2615                }
2616                postvisit( old, ty );
2617        }
2618
2619        virtual void visit( const TupleType * old ) override final {
2620                visitType( old, new ast::TupleType{
2621                        GET_ACCEPT_V( types, Type ),
2622                        // members generated by TupleType c'tor
2623                        cv( old )
2624                } );
2625        }
2626
2627        virtual void visit( const TypeofType * old ) override final {
2628                visitType( old, new ast::TypeofType{
2629                        GET_ACCEPT_1( expr, Expr ),
2630                        (ast::TypeofType::Kind)old->is_basetypeof,
2631                        cv( old )
2632                } );
2633        }
2634
2635        virtual void visit( const AttrType * ) override final {
2636                assertf( false, "AttrType deprecated in new AST." );
2637        }
2638
2639        virtual void visit( const VarArgsType * old ) override final {
2640                visitType( old, new ast::VarArgsType{ cv( old ) } );
2641        }
2642
2643        virtual void visit( const ZeroType * old ) override final {
2644                visitType( old, new ast::ZeroType{ cv( old ) } );
2645        }
2646
2647        virtual void visit( const OneType * old ) override final {
2648                visitType( old, new ast::OneType{ cv( old ) } );
2649        }
2650
2651        virtual void visit( const GlobalScopeType * old ) override final {
2652                visitType( old, new ast::GlobalScopeType{} );
2653        }
2654
2655        virtual void visit( const Designation * old ) override final {
2656                this->node = new ast::Designation(
2657                        old->location,
2658                        GET_ACCEPT_D(designators, Expr)
2659                );
2660        }
2661
2662        virtual void visit( const SingleInit * old ) override final {
2663                this->node = new ast::SingleInit(
2664                        old->location,
2665                        GET_ACCEPT_1(value, Expr),
2666                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
2667                );
2668        }
2669
2670        virtual void visit( const ListInit * old ) override final {
2671                this->node = new ast::ListInit(
2672                        old->location,
2673                        GET_ACCEPT_V(initializers, Init),
2674                        GET_ACCEPT_V(designations, Designation),
2675                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
2676                );
2677        }
2678
2679        virtual void visit( const ConstructorInit * old ) override final {
2680                this->node = new ast::ConstructorInit(
2681                        old->location,
2682                        GET_ACCEPT_1(ctor, Stmt),
2683                        GET_ACCEPT_1(dtor, Stmt),
2684                        GET_ACCEPT_1(init, Init)
2685                );
2686        }
2687
2688        virtual void visit( const Constant * ) override final {
2689                // Handled in visit( ConstantEpxr * ).
2690                // In the new tree, Constant fields are inlined into containing ConstantExpression.
2691                assert( 0 );
2692        }
2693
2694        virtual void visit( const Attribute * old ) override final {
2695                this->node = new ast::Attribute(
2696                        old->name,
2697                        GET_ACCEPT_V( parameters, Expr )
2698                );
2699        }
2700};
2701
2702#undef GET_LABELS_V
2703#undef GET_ACCEPT_V
2704#undef GET_ACCEPT_1
2705
2706std::list< ast::ptr< ast::Decl > > convert( const std::list< Declaration * > && translationUnit ) {
2707        ConverterOldToNew c;
2708        std::list< ast::ptr< ast::Decl > > decls;
2709        for(auto d : translationUnit) {
2710                d->accept( c );
2711                decls.emplace_back( c.decl() );
2712        }
2713        deleteAll(translationUnit);
2714        return decls;
2715}
Note: See TracBrowser for help on using the repository browser.