source: src/AST/Convert.cpp @ 98e8b3b

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 98e8b3b was 98e8b3b, checked in by Andrew Beach <ajbeach@…>, 4 years ago

ast::ReferenceToType? is now ast::BaseInstType?.

  • Property mode set to 100644
File size: 73.3 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->clone(),
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.data.inferParams ) {
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),
596                                        get<Type>().accept1(srcParam.second.actualType)->clone(),
597                                        get<Type>().accept1(srcParam.second.formalType)->clone(),
598                                        get<Expression>().accept1(srcParam.second.expr)->clone()
599                                ));
600                                assert(res.second);
601                        }
602                }
603                if ( srcInferred.data.resnSlots ) {
604                        const ast::ResnSlots &srcSlots = srcInferred.resnSlots();
605                        for (auto srcSlot : srcSlots) {
606                                tgtResnSlots.push_back(srcSlot);
607                        }
608                }
609        }
610
611        Expression * visitBaseExpr_skipResultType(const ast::Expr * src, Expression * tgt) {
612
613                tgt->location  = src->location;
614                tgt->env       = convertTypeSubstitution(src->env);
615                tgt->extension = src->extension;
616
617                convertInferUnion(tgt->inferParams, tgt->resnSlots, src->inferred);
618                return tgt;
619        }
620
621        Expression * visitBaseExpr(const ast::Expr * src, Expression * tgt) {
622
623                tgt->result = get<Type>().accept1(src->result);
624                // Unconditionally use a clone of the result type.
625                // We know this will leak some objects: much of the immediate conversion result.
626                // In some cases, using the conversion result directly gives unintended object sharing.
627                // A parameter (ObjectDecl, a child of a FunctionType) is shared by the weak-ref cache.
628                // But tgt->result must be fully owned privately by tgt.
629                // Applying these conservative copies here means
630                // - weak references point at the declaration's copy, not these expr.result copies (good)
631                // - we copy more objects than really needed (bad, tolerated)
632                if (tgt->result) {
633                        tgt->result = tgt->result->clone();
634                }
635                return visitBaseExpr_skipResultType(src, tgt);
636        }
637
638        const ast::Expr * visit( const ast::ApplicationExpr * node ) override final {
639                auto expr = visitBaseExpr( node,
640                        new ApplicationExpr(
641                                get<Expression>().accept1(node->func),
642                                get<Expression>().acceptL(node->args)
643                        )
644                );
645                this->node = expr;
646                return nullptr;
647        }
648
649        const ast::Expr * visit( const ast::UntypedExpr * node ) override final {
650                auto expr = visitBaseExpr( node,
651                        new UntypedExpr(
652                                get<Expression>().accept1(node->func),
653                                get<Expression>().acceptL(node->args)
654                        )
655                );
656                this->node = expr;
657                return nullptr;
658        }
659
660        const ast::Expr * visit( const ast::NameExpr * node ) override final {
661                auto expr = visitBaseExpr( node,
662                        new NameExpr(
663                                node->name
664                        )
665                );
666                this->node = expr;
667                return nullptr;
668        }
669
670        const ast::Expr * visit( const ast::AddressExpr * node ) override final {
671                auto expr = visitBaseExpr( node,
672                        new AddressExpr(
673                                get<Expression>().accept1(node->arg)
674                        )
675                );
676                this->node = expr;
677                return nullptr;
678        }
679
680        const ast::Expr * visit( const ast::LabelAddressExpr * node ) override final {
681                auto expr = visitBaseExpr( node,
682                        new LabelAddressExpr(
683                                makeLabel(nullptr, node->arg)
684                        )
685                );
686                this->node = expr;
687                return nullptr;
688        }
689
690        const ast::Expr * visit( const ast::CastExpr * node ) override final {
691                auto expr = visitBaseExpr( node,
692                        new CastExpr(
693                                get<Expression>().accept1(node->arg),
694                                (node->isGenerated == ast::GeneratedCast)
695                        )
696                );
697                this->node = expr;
698                return nullptr;
699        }
700
701        const ast::Expr * visit( const ast::KeywordCastExpr * node ) override final {
702                AggregateDecl::Aggregate castTarget = (AggregateDecl::Aggregate)node->target;
703                assert( AggregateDecl::Generator <= castTarget && castTarget <= AggregateDecl::Thread );
704                auto expr = visitBaseExpr( node,
705                        new KeywordCastExpr(
706                                get<Expression>().accept1(node->arg),
707                                castTarget,
708                                {node->concrete_target.field, node->concrete_target.getter}
709                        )
710                );
711                this->node = expr;
712                return nullptr;
713        }
714
715        const ast::Expr * visit( const ast::VirtualCastExpr * node ) override final {
716                auto expr = visitBaseExpr_skipResultType( node,
717                        new VirtualCastExpr(
718                                get<Expression>().accept1(node->arg),
719                                get<Type>().accept1(node->result)
720                        )
721                );
722                this->node = expr;
723                return nullptr;
724        }
725
726        const ast::Expr * visit( const ast::UntypedMemberExpr * node ) override final {
727                auto expr = visitBaseExpr( node,
728                        new UntypedMemberExpr(
729                                get<Expression>().accept1(node->member),
730                                get<Expression>().accept1(node->aggregate)
731                        )
732                );
733                this->node = expr;
734                return nullptr;
735        }
736
737        const ast::Expr * visit( const ast::MemberExpr * node ) override final {
738                auto expr = visitBaseExpr( node,
739                        new MemberExpr(
740                                get<DeclarationWithType>().accept1(node->member),
741                                get<Expression>().accept1(node->aggregate)
742                        )
743                );
744                this->node = expr;
745                return nullptr;
746        }
747
748        const ast::Expr * visit( const ast::VariableExpr * node ) override final {
749                auto expr = new VariableExpr();
750                expr->var = get<DeclarationWithType>().accept1(node->var);
751                visitBaseExpr( node, expr );
752                this->node = expr;
753                return nullptr;
754        }
755
756        const ast::Expr * visit( const ast::ConstantExpr * node ) override final {
757                // Old world:   two types: rslt->constant.type, rslt->result
758                // New workd:   one public type: node->result, plus node->underlyer only to support roundtrip conversion
759                //              preserving underlyer because the correct type for string literals is complicated to construct,
760            //              and distinguishing a string from other literals using the type is hard to do accurately
761                // Both worlds: the outer, expression-level type can change during resolution
762                //              for a string, that's char[k] before-resolve and char * after
763                // Old world:   the inner Constant type stays what it was built with
764                //              for a string, that's char[k] always
765                // Both worlds: the "rep" field of a constant is the C source file fragment that compiles to the desired value
766        //              for a string, that includes outer quotes, backslashes, et al cases from the Literals test
767                ConstantExpr *rslt = new ConstantExpr(Constant(
768                        get<Type>().accept1(node->underlyer),
769                        node->rep,
770                        node->ival));
771                auto expr = visitBaseExpr( node, rslt );
772                this->node = expr;
773                return nullptr;
774        }
775
776        const ast::Expr * visit( const ast::SizeofExpr * node ) override final {
777                assert (node->expr || node->type);
778                assert (! (node->expr && node->type));
779                SizeofExpr *rslt;
780                if (node->expr) {
781                        rslt = new SizeofExpr(
782                                get<Expression>().accept1(node->expr)
783                        );
784                        assert (!rslt->isType);
785                }
786                else {
787                        assert(node->type);
788                        rslt = new SizeofExpr(
789                                get<Type>().accept1(node->type)
790                        );
791                        assert (rslt->isType);
792                }
793                auto expr = visitBaseExpr( node, rslt );
794                this->node = expr;
795                return nullptr;
796        }
797
798        const ast::Expr * visit( const ast::AlignofExpr * node ) override final {
799                assert (node->expr || node->type);
800                assert (! (node->expr && node->type));
801                AlignofExpr *rslt;
802                if (node->expr) {
803                        rslt = new AlignofExpr(
804                                get<Expression>().accept1(node->expr)
805                        );
806                        assert (!rslt->isType);
807                }
808                else {
809                        assert(node->type);
810                        rslt = new AlignofExpr(
811                                get<Type>().accept1(node->type)
812                        );
813                        assert (rslt->isType);
814                }
815                auto expr = visitBaseExpr( node, rslt );
816                this->node = expr;
817                return nullptr;
818        }
819
820        const ast::Expr * visit( const ast::UntypedOffsetofExpr * node ) override final {
821                auto expr = visitBaseExpr( node,
822                        new UntypedOffsetofExpr(
823                                get<Type>().accept1(node->type),
824                                node->member
825                        )
826                );
827                this->node = expr;
828                return nullptr;
829        }
830
831        const ast::Expr * visit( const ast::OffsetofExpr * node ) override final {
832                auto expr = visitBaseExpr( node,
833                        new OffsetofExpr(
834                                get<Type>().accept1(node->type),
835                                get<DeclarationWithType>().accept1(node->member)
836                        )
837                );
838                this->node = expr;
839                return nullptr;
840        }
841
842        const ast::Expr * visit( const ast::OffsetPackExpr * node ) override final {
843                auto expr = visitBaseExpr( node,
844                        new OffsetPackExpr(
845                                get<StructInstType>().accept1(node->type)
846                        )
847                );
848                this->node = expr;
849                return nullptr;
850        }
851
852        const ast::Expr * visit( const ast::LogicalExpr * node ) override final {
853                assert (node->isAnd == ast::LogicalFlag::AndExpr ||
854                                node->isAnd == ast::LogicalFlag::OrExpr );
855                auto expr = visitBaseExpr( node,
856                        new LogicalExpr(
857                                get<Expression>().accept1(node->arg1),
858                                get<Expression>().accept1(node->arg2),
859                                (node->isAnd == ast::LogicalFlag::AndExpr)
860                        )
861                );
862                this->node = expr;
863                return nullptr;
864        }
865
866        const ast::Expr * visit( const ast::ConditionalExpr * node ) override final {
867                auto expr = visitBaseExpr( node,
868                        new ConditionalExpr(
869                                get<Expression>().accept1(node->arg1),
870                                get<Expression>().accept1(node->arg2),
871                                get<Expression>().accept1(node->arg3)
872                        )
873                );
874                this->node = expr;
875                return nullptr;
876        }
877
878        const ast::Expr * visit( const ast::CommaExpr * node ) override final {
879                auto expr = visitBaseExpr( node,
880                        new CommaExpr(
881                                get<Expression>().accept1(node->arg1),
882                                get<Expression>().accept1(node->arg2)
883                        )
884                );
885                this->node = expr;
886                return nullptr;
887        }
888
889        const ast::Expr * visit( const ast::TypeExpr * node ) override final {
890                auto expr = visitBaseExpr( node,
891                        new TypeExpr(
892                                get<Type>().accept1(node->type)
893                        )
894                );
895                this->node = expr;
896                return nullptr;
897        }
898
899        const ast::Expr * visit( const ast::AsmExpr * node ) override final {
900                auto expr = visitBaseExpr( node,
901                        new AsmExpr(
902                                new std::string(node->inout),
903                                get<Expression>().accept1(node->constraint),
904                                get<Expression>().accept1(node->operand)
905                        )
906                );
907                this->node = expr;
908                return nullptr;
909        }
910
911        const ast::Expr * visit( const ast::ImplicitCopyCtorExpr * node ) override final {
912                auto rslt = new ImplicitCopyCtorExpr(
913                        get<ApplicationExpr>().accept1(node->callExpr)
914                );
915
916                auto expr = visitBaseExpr( node, rslt );
917                this->node = expr;
918                return nullptr;
919        }
920
921        const ast::Expr * visit( const ast::ConstructorExpr * node ) override final {
922                auto expr = visitBaseExpr( node,
923                        new ConstructorExpr(
924                                get<Expression>().accept1(node->callExpr)
925                        )
926                );
927                this->node = expr;
928                return nullptr;
929        }
930
931        const ast::Expr * visit( const ast::CompoundLiteralExpr * node ) override final {
932                auto expr = visitBaseExpr_skipResultType( node,
933                        new CompoundLiteralExpr(
934                                get<Type>().accept1(node->result),
935                                get<Initializer>().accept1(node->init)
936                        )
937                );
938                this->node = expr;
939                return nullptr;
940        }
941
942        const ast::Expr * visit( const ast::RangeExpr * node ) override final {
943                auto expr = visitBaseExpr( node,
944                        new RangeExpr(
945                                get<Expression>().accept1(node->low),
946                                get<Expression>().accept1(node->high)
947                        )
948                );
949                this->node = expr;
950                return nullptr;
951        }
952
953        const ast::Expr * visit( const ast::UntypedTupleExpr * node ) override final {
954                auto expr = visitBaseExpr( node,
955                        new UntypedTupleExpr(
956                                get<Expression>().acceptL(node->exprs)
957                        )
958                );
959                this->node = expr;
960                return nullptr;
961        }
962
963        const ast::Expr * visit( const ast::TupleExpr * node ) override final {
964                auto expr = visitBaseExpr( node,
965                        new TupleExpr(
966                                get<Expression>().acceptL(node->exprs)
967                        )
968                );
969                this->node = expr;
970                return nullptr;
971        }
972
973        const ast::Expr * visit( const ast::TupleIndexExpr * node ) override final {
974                auto expr = visitBaseExpr( node,
975                        new TupleIndexExpr(
976                                get<Expression>().accept1(node->tuple),
977                                node->index
978                        )
979                );
980                this->node = expr;
981                return nullptr;
982        }
983
984        const ast::Expr * visit( const ast::TupleAssignExpr * node ) override final {
985                auto expr = visitBaseExpr( node,
986                        new TupleAssignExpr(
987                                get<StmtExpr>().accept1(node->stmtExpr)
988                        )
989                );
990                this->node = expr;
991                return nullptr;
992        }
993
994        const ast::Expr * visit( const ast::StmtExpr * node ) override final {
995                auto stmts = node->stmts;
996                // disable sharing between multiple StmtExprs explicitly.
997                if (inCache(stmts)) {
998                        stmts = ast::deepCopy(stmts.get());
999                }
1000                auto rslt = new StmtExpr(
1001                        get<CompoundStmt>().accept1(stmts)
1002                );
1003
1004                rslt->returnDecls = get<ObjectDecl>().acceptL(node->returnDecls);
1005                rslt->dtors       = get<Expression>().acceptL(node->dtors);
1006
1007                auto expr = visitBaseExpr( node, rslt );
1008                this->node = expr;
1009                return nullptr;
1010        }
1011
1012        const ast::Expr * visit( const ast::UniqueExpr * node ) override final {
1013                auto rslt = new UniqueExpr(
1014                        get<Expression>().accept1(node->expr),
1015                        node->id
1016                );
1017
1018                rslt->object = get<ObjectDecl>  ().accept1(node->object);
1019                rslt->var    = get<VariableExpr>().accept1(node->var);
1020
1021                auto expr = visitBaseExpr( node, rslt );
1022                this->node = expr;
1023                return nullptr;
1024        }
1025
1026        const ast::Expr * visit( const ast::UntypedInitExpr * node ) override final {
1027                std::list<InitAlternative> initAlts;
1028                for (auto ia : node->initAlts) {
1029                        initAlts.push_back(InitAlternative(
1030                                get<Type>       ().accept1(ia.type),
1031                                get<Designation>().accept1(ia.designation)
1032                        ));
1033                }
1034                auto expr = visitBaseExpr( node,
1035                        new UntypedInitExpr(
1036                                get<Expression>().accept1(node->expr),
1037                                initAlts
1038                        )
1039                );
1040                this->node = expr;
1041                return nullptr;
1042        }
1043
1044        const ast::Expr * visit( const ast::InitExpr * node ) override final {
1045                auto expr = visitBaseExpr( node,
1046                        new InitExpr(
1047                                get<Expression>().accept1(node->expr),
1048                                get<Designation>().accept1(node->designation)
1049                        )
1050                );
1051                this->node = expr;
1052                return nullptr;
1053        }
1054
1055        const ast::Expr * visit( const ast::DeletedExpr * node ) override final {
1056                auto expr = visitBaseExpr( node,
1057                        new DeletedExpr(
1058                                get<Expression>().accept1(node->expr),
1059                                inCache(node->deleteStmt) ?
1060                                        strict_dynamic_cast<Declaration*>(this->node) :
1061                                        get<Declaration>().accept1(node->deleteStmt)
1062                        )
1063                );
1064                this->node = expr;
1065                return nullptr;
1066        }
1067
1068        const ast::Expr * visit( const ast::DefaultArgExpr * node ) override final {
1069                auto expr = visitBaseExpr( node,
1070                        new DefaultArgExpr(
1071                                get<Expression>().accept1(node->expr)
1072                        )
1073                );
1074                this->node = expr;
1075                return nullptr;
1076        }
1077
1078        const ast::Expr * visit( const ast::GenericExpr * node ) override final {
1079                std::list<GenericExpr::Association> associations;
1080                for (auto association : node->associations) {
1081                        associations.push_back(GenericExpr::Association(
1082                                get<Type>      ().accept1(association.type),
1083                                get<Expression>().accept1(association.expr)
1084                        ));
1085                }
1086                auto expr = visitBaseExpr( node,
1087                        new GenericExpr(
1088                                get<Expression>().accept1(node->control),
1089                                associations
1090                        )
1091                );
1092                this->node = expr;
1093                return nullptr;
1094        }
1095
1096        const ast::Type * visitType( const ast::Type * node, Type * type ) {
1097                // Some types do this in their constructor so add a check.
1098                if ( !node->attributes.empty() && type->attributes.empty() ) {
1099                        type->attributes = get<Attribute>().acceptL( node->attributes );
1100                }
1101                this->node = type;
1102                return nullptr;
1103        }
1104
1105        const ast::Type * visit( const ast::VoidType * node ) override final {
1106                return visitType( node, new VoidType{ cv( node ) } );
1107        }
1108
1109        const ast::Type * visit( const ast::BasicType * node ) override final {
1110                auto type = new BasicType{ cv( node ), (BasicType::Kind)(unsigned)node->kind };
1111                // I believe this should always be a BasicType.
1112                if ( sizeType == node ) {
1113                        Validate::SizeType = type;
1114                }
1115                return visitType( node, type );
1116        }
1117
1118        const ast::Type * visit( const ast::PointerType * node ) override final {
1119                return visitType( node, new PointerType{
1120                        cv( node ),
1121                        get<Type>().accept1( node->base ),
1122                        get<Expression>().accept1( node->dimension ),
1123                        (bool)node->isVarLen,
1124                        (bool)node->isStatic
1125                } );
1126        }
1127
1128        const ast::Type * visit( const ast::ArrayType * node ) override final {
1129                return visitType( node, new ArrayType{
1130                        cv( node ),
1131                        get<Type>().accept1( node->base ),
1132                        get<Expression>().accept1( node->dimension ),
1133                        (bool)node->isVarLen,
1134                        (bool)node->isStatic
1135                } );
1136        }
1137
1138        const ast::Type * visit( const ast::ReferenceType * node ) override final {
1139                return visitType( node, new ReferenceType{
1140                        cv( node ),
1141                        get<Type>().accept1( node->base )
1142                } );
1143        }
1144
1145        const ast::Type * visit( const ast::QualifiedType * node ) override final {
1146                return visitType( node, new QualifiedType{
1147                        cv( node ),
1148                        get<Type>().accept1( node->parent ),
1149                        get<Type>().accept1( node->child )
1150                } );
1151        }
1152
1153        const ast::Type * visit( const ast::FunctionType * node ) override final {
1154                auto ty = new FunctionType {
1155                        cv( node ),
1156                        (bool)node->isVarArgs
1157                };
1158                ty->returnVals = get<DeclarationWithType>().acceptL( node->returns );
1159                ty->parameters = get<DeclarationWithType>().acceptL( node->params );
1160                ty->forall = get<TypeDecl>().acceptL( node->forall );
1161                return visitType( node, ty );
1162        }
1163
1164        const ast::Type * postvisit( const ast::BaseInstType * old, ReferenceToType * ty ) {
1165                ty->forall = get<TypeDecl>().acceptL( old->forall );
1166                ty->parameters = get<Expression>().acceptL( old->params );
1167                ty->hoistType = old->hoistType;
1168                return visitType( old, ty );
1169        }
1170
1171        const ast::Type * visit( const ast::StructInstType * node ) override final {
1172                StructInstType * ty;
1173                if ( node->base ) {
1174                        ty = new StructInstType{
1175                                cv( node ),
1176                                get<StructDecl>().accept1( node->base ),
1177                                get<Attribute>().acceptL( node->attributes )
1178                        };
1179                } else {
1180                        ty = new StructInstType{
1181                                cv( node ),
1182                                node->name,
1183                                get<Attribute>().acceptL( node->attributes )
1184                        };
1185                }
1186                return postvisit( node, ty );
1187        }
1188
1189        const ast::Type * visit( const ast::UnionInstType * node ) override final {
1190                UnionInstType * ty;
1191                if ( node->base ) {
1192                        ty = new UnionInstType{
1193                                cv( node ),
1194                                get<UnionDecl>().accept1( node->base ),
1195                                get<Attribute>().acceptL( node->attributes )
1196                        };
1197                } else {
1198                        ty = new UnionInstType{
1199                                cv( node ),
1200                                node->name,
1201                                get<Attribute>().acceptL( node->attributes )
1202                        };
1203                }
1204                return postvisit( node, ty );
1205        }
1206
1207        const ast::Type * visit( const ast::EnumInstType * node ) override final {
1208                EnumInstType * ty;
1209                if ( node->base ) {
1210                        ty = new EnumInstType{
1211                                cv( node ),
1212                                get<EnumDecl>().accept1( node->base ),
1213                                get<Attribute>().acceptL( node->attributes )
1214                        };
1215                } else {
1216                        ty = new EnumInstType{
1217                                cv( node ),
1218                                node->name,
1219                                get<Attribute>().acceptL( node->attributes )
1220                        };
1221                }
1222                return postvisit( node, ty );
1223        }
1224
1225        const ast::Type * visit( const ast::TraitInstType * node ) override final {
1226                TraitInstType * ty;
1227                if ( node->base ) {
1228                        ty = new TraitInstType{
1229                                cv( node ),
1230                                get<TraitDecl>().accept1( node->base ),
1231                                get<Attribute>().acceptL( node->attributes )
1232                        };
1233                } else {
1234                        ty = new TraitInstType{
1235                                cv( node ),
1236                                node->name,
1237                                get<Attribute>().acceptL( node->attributes )
1238                        };
1239                }
1240                return postvisit( node, ty );
1241        }
1242
1243        const ast::Type * visit( const ast::TypeInstType * node ) override final {
1244                TypeInstType * ty;
1245                if ( node->base ) {
1246                        ty = new TypeInstType{
1247                                cv( node ),
1248                                node->name,
1249                                get<TypeDecl>().accept1( node->base ),
1250                                get<Attribute>().acceptL( node->attributes )
1251                        };
1252                } else {
1253                        ty = new TypeInstType{
1254                                cv( node ),
1255                                node->name,
1256                                node->kind == ast::TypeDecl::Ftype,
1257                                get<Attribute>().acceptL( node->attributes )
1258                        };
1259                }
1260                return postvisit( node, ty );
1261        }
1262
1263        const ast::Type * visit( const ast::TupleType * node ) override final {
1264                return visitType( node, new TupleType{
1265                        cv( node ),
1266                        get<Type>().acceptL( node->types )
1267                        // members generated by TupleType c'tor
1268                } );
1269        }
1270
1271        const ast::Type * visit( const ast::TypeofType * node ) override final {
1272                return visitType( node, new TypeofType{
1273                        cv( node ),
1274                        get<Expression>().accept1( node->expr ),
1275                        (bool)node->kind
1276                } );
1277        }
1278
1279        const ast::Type * visit( const ast::VarArgsType * node ) override final {
1280                return visitType( node, new VarArgsType{ cv( node ) } );
1281        }
1282
1283        const ast::Type * visit( const ast::ZeroType * node ) override final {
1284                return visitType( node, new ZeroType{ cv( node ) } );
1285        }
1286
1287        const ast::Type * visit( const ast::OneType * node ) override final {
1288                return visitType( node, new OneType{ cv( node ) } );
1289        }
1290
1291        const ast::Type * visit( const ast::GlobalScopeType * node ) override final {
1292                return visitType( node, new GlobalScopeType{} );
1293        }
1294
1295        const ast::Designation * visit( const ast::Designation * node ) override final {
1296                auto designation = new Designation( get<Expression>().acceptL( node->designators ) );
1297                designation->location = node->location;
1298                this->node = designation;
1299                return nullptr;
1300        }
1301
1302        const ast::Init * visit( const ast::SingleInit * node ) override final {
1303                auto init = new SingleInit(
1304                        get<Expression>().accept1( node->value ),
1305                        ast::MaybeConstruct == node->maybeConstructed
1306                );
1307                init->location = node->location;
1308                this->node = init;
1309                return nullptr;
1310        }
1311
1312        const ast::Init * visit( const ast::ListInit * node ) override final {
1313                auto init = new ListInit(
1314                        get<Initializer>().acceptL( node->initializers ),
1315                        get<Designation>().acceptL( node->designations ),
1316                        ast::MaybeConstruct == node->maybeConstructed
1317                );
1318                init->location = node->location;
1319                this->node = init;
1320                return nullptr;
1321        }
1322
1323        const ast::Init * visit( const ast::ConstructorInit * node ) override final {
1324                auto init = new ConstructorInit(
1325                        get<Statement>().accept1( node->ctor ),
1326                        get<Statement>().accept1( node->dtor ),
1327                        get<Initializer>().accept1( node->init )
1328                );
1329                init->location = node->location;
1330                this->node = init;
1331                return nullptr;
1332        }
1333
1334        const ast::Attribute * visit( const ast::Attribute * node ) override final {
1335                auto attr = new Attribute(
1336                        node->name,
1337                        get<Expression>().acceptL(node->params)
1338                );
1339                this->node = attr;
1340                return nullptr;
1341        }
1342
1343        const ast::TypeSubstitution * visit( const ast::TypeSubstitution * node ) override final {
1344                // Handled by convertTypeSubstitution helper instead.
1345                // TypeSubstitution is not a node in the old model, so the conversion result wouldn't fit in this->node.
1346                assert( 0 );
1347                (void)node;
1348                return nullptr;
1349        }
1350};
1351
1352std::list< Declaration * > convert( const std::list< ast::ptr< ast::Decl > > && translationUnit ) {
1353        ConverterNewToOld c;
1354        std::list< Declaration * > decls;
1355        for(auto d : translationUnit) {
1356                decls.emplace_back( c.decl( d ) );
1357        }
1358        return decls;
1359}
1360
1361//================================================================================================
1362
1363class ConverterOldToNew : public Visitor {
1364public:
1365        ast::Decl * decl() {
1366                return strict_dynamic_cast< ast::Decl * >( node );
1367        }
1368
1369        ConverterOldToNew() = default;
1370        ConverterOldToNew(const ConverterOldToNew &) = delete;
1371        ConverterOldToNew(ConverterOldToNew &&) = delete;
1372private:
1373        /// conversion output
1374        ast::Node * node = nullptr;
1375        /// cache of nodes that might be referenced by readonly<> for de-duplication
1376        std::unordered_map< const BaseSyntaxNode *, ast::Node * > cache = {};
1377
1378        // Local Utilities:
1379
1380        template<typename NewT, typename OldT>
1381        NewT * getAccept1( OldT old ) {
1382                if ( ! old ) return nullptr;
1383                old->accept(*this);
1384                ast::Node * ret = node;
1385                node = nullptr;
1386                return strict_dynamic_cast< NewT * >( ret );
1387        }
1388
1389#       define GET_ACCEPT_1(child, type) \
1390                getAccept1< ast::type, decltype( old->child ) >( old->child )
1391
1392        template<typename NewT, typename OldC>
1393        std::vector< ast::ptr<NewT> > getAcceptV( const OldC& old ) {
1394                std::vector< ast::ptr<NewT> > ret;
1395                ret.reserve( old.size() );
1396                for ( auto a : old ) {
1397                        a->accept( *this );
1398                        ret.emplace_back( strict_dynamic_cast< NewT * >(node) );
1399                        node = nullptr;
1400                }
1401                return ret;
1402        }
1403
1404#       define GET_ACCEPT_V(child, type) \
1405                getAcceptV< ast::type, decltype( old->child ) >( old->child )
1406
1407        template<typename NewT, typename OldC>
1408        std::deque< ast::ptr<NewT> > getAcceptD( const OldC& old ) {
1409                std::deque< ast::ptr<NewT> > ret;
1410                for ( auto a : old ) {
1411                        a->accept( *this );
1412                        ret.emplace_back( strict_dynamic_cast< NewT * >(node) );
1413                        node = nullptr;
1414                }
1415                return ret;
1416        }
1417
1418#       define GET_ACCEPT_D(child, type) \
1419                getAcceptD< ast::type, decltype( old->child ) >( old->child )
1420
1421        ast::Label make_label(const Label* old) {
1422                CodeLocation const & location =
1423                    ( old->labelled ) ? old->labelled->location : CodeLocation();
1424                return ast::Label(
1425                        location,
1426                        old->name,
1427                        GET_ACCEPT_V(attributes, Attribute)
1428                );
1429        }
1430
1431        template<template <class...> class C>
1432        C<ast::Label> make_labels(C<Label> olds) {
1433                C<ast::Label> ret;
1434                for (auto oldn : olds) {
1435                        ret.push_back( make_label( &oldn ) );
1436                }
1437                return ret;
1438        }
1439
1440#       define GET_LABELS_V(labels) \
1441                to<std::vector>::from( make_labels( std::move( labels ) ) )
1442
1443        static ast::CV::Qualifiers cv( const Type * ty ) { return { ty->tq.val }; }
1444
1445        /// returns true and sets `node` if in cache
1446        bool inCache( const BaseSyntaxNode * old ) {
1447                auto it = cache.find( old );
1448                if ( it == cache.end() ) return false;
1449                node = it->second;
1450                return true;
1451        }
1452
1453        // Now all the visit functions:
1454
1455        virtual void visit( const ObjectDecl * old ) override final {
1456                auto&& type = GET_ACCEPT_1(type, Type);
1457                auto&& init = GET_ACCEPT_1(init, Init);
1458                auto&& bfwd = GET_ACCEPT_1(bitfieldWidth, Expr);
1459                auto&& attr = GET_ACCEPT_V(attributes, Attribute);
1460                if ( inCache( old ) ) {
1461                        return;
1462                }
1463                auto decl = new ast::ObjectDecl(
1464                        old->location,
1465                        old->name,
1466                        type,
1467                        init,
1468                        { old->get_storageClasses().val },
1469                        { old->linkage.val },
1470                        bfwd,
1471                        std::move(attr),
1472                        { old->get_funcSpec().val }
1473                );
1474                cache.emplace(old, decl);
1475                assert(cache.find( old ) != cache.end());
1476                decl->scopeLevel = old->scopeLevel;
1477                decl->mangleName = old->mangleName;
1478                decl->isDeleted  = old->isDeleted;
1479                decl->asmName    = GET_ACCEPT_1(asmName, Expr);
1480                decl->uniqueId   = old->uniqueId;
1481                decl->extension  = old->extension;
1482
1483                this->node = decl;
1484        }
1485
1486        virtual void visit( const FunctionDecl * old ) override final {
1487                if ( inCache( old ) ) return;
1488                auto decl = new ast::FunctionDecl{
1489                        old->location,
1490                        old->name,
1491                        GET_ACCEPT_1(type, FunctionType),
1492                        {},
1493                        { old->storageClasses.val },
1494                        { old->linkage.val },
1495                        GET_ACCEPT_V(attributes, Attribute),
1496                        { old->get_funcSpec().val }
1497                };
1498                cache.emplace( old, decl );
1499                decl->withExprs = GET_ACCEPT_V(withExprs, Expr);
1500                decl->stmts = GET_ACCEPT_1(statements, CompoundStmt);
1501                decl->scopeLevel = old->scopeLevel;
1502                decl->mangleName = old->mangleName;
1503                decl->isDeleted  = old->isDeleted;
1504                decl->asmName    = GET_ACCEPT_1(asmName, Expr);
1505                decl->uniqueId   = old->uniqueId;
1506                decl->extension  = old->extension;
1507
1508                this->node = decl;
1509
1510                if ( Validate::dereferenceOperator == old ) {
1511                        dereferenceOperator = decl;
1512                }
1513
1514                if ( Validate::dtorStructDestroy == old ) {
1515                        dtorStructDestroy = decl;
1516                }
1517        }
1518
1519        virtual void visit( const StructDecl * old ) override final {
1520                if ( inCache( old ) ) return;
1521                auto decl = new ast::StructDecl(
1522                        old->location,
1523                        old->name,
1524                        (ast::AggregateDecl::Aggregate)old->kind,
1525                        GET_ACCEPT_V(attributes, Attribute),
1526                        { old->linkage.val }
1527                );
1528                cache.emplace( old, decl );
1529                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1530                decl->body   = old->body;
1531                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1532                decl->members    = GET_ACCEPT_V(members, Decl);
1533                decl->extension  = old->extension;
1534                decl->uniqueId   = old->uniqueId;
1535                decl->storage    = { old->storageClasses.val };
1536
1537                this->node = decl;
1538
1539                if ( Validate::dtorStruct == old ) {
1540                        dtorStruct = decl;
1541                }
1542        }
1543
1544        virtual void visit( const UnionDecl * old ) override final {
1545                if ( inCache( old ) ) return;
1546                auto decl = new ast::UnionDecl(
1547                        old->location,
1548                        old->name,
1549                        GET_ACCEPT_V(attributes, Attribute),
1550                        { old->linkage.val }
1551                );
1552                cache.emplace( old, decl );
1553                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1554                decl->body   = old->body;
1555                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1556                decl->members    = GET_ACCEPT_V(members, Decl);
1557                decl->extension  = old->extension;
1558                decl->uniqueId   = old->uniqueId;
1559                decl->storage    = { old->storageClasses.val };
1560
1561                this->node = decl;
1562        }
1563
1564        virtual void visit( const EnumDecl * old ) override final {
1565                if ( inCache( old ) ) return;
1566                auto decl = new ast::EnumDecl(
1567                        old->location,
1568                        old->name,
1569                        GET_ACCEPT_V(attributes, Attribute),
1570                        { old->linkage.val }
1571                );
1572                cache.emplace( old, decl );
1573                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1574                decl->body   = old->body;
1575                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1576                decl->members    = GET_ACCEPT_V(members, Decl);
1577                decl->extension  = old->extension;
1578                decl->uniqueId   = old->uniqueId;
1579                decl->storage    = { old->storageClasses.val };
1580
1581                this->node = decl;
1582        }
1583
1584        virtual void visit( const TraitDecl * old ) override final {
1585                if ( inCache( old ) ) return;
1586                auto decl = new ast::TraitDecl(
1587                        old->location,
1588                        old->name,
1589                        GET_ACCEPT_V(attributes, Attribute),
1590                        { old->linkage.val }
1591                );
1592                cache.emplace( old, decl );
1593                decl->parent = GET_ACCEPT_1(parent, AggregateDecl);
1594                decl->body   = old->body;
1595                decl->params = GET_ACCEPT_V(parameters, TypeDecl);
1596                decl->members    = GET_ACCEPT_V(members, Decl);
1597                decl->extension  = old->extension;
1598                decl->uniqueId   = old->uniqueId;
1599                decl->storage    = { old->storageClasses.val };
1600
1601                this->node = decl;
1602        }
1603
1604        virtual void visit( const TypeDecl * old ) override final {
1605                if ( inCache( old ) ) return;
1606                auto decl = new ast::TypeDecl{
1607                        old->location,
1608                        old->name,
1609                        { old->storageClasses.val },
1610                        GET_ACCEPT_1(base, Type),
1611                        (ast::TypeDecl::Kind)(unsigned)old->kind,
1612                        old->sized,
1613                        GET_ACCEPT_1(init, Type)
1614                };
1615                cache.emplace( old, decl );
1616                decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
1617                decl->params     = GET_ACCEPT_V(parameters, TypeDecl);
1618                decl->extension  = old->extension;
1619                decl->uniqueId   = old->uniqueId;
1620
1621                this->node = decl;
1622        }
1623
1624        virtual void visit( const TypedefDecl * old ) override final {
1625                auto decl = new ast::TypedefDecl(
1626                        old->location,
1627                        old->name,
1628                        { old->storageClasses.val },
1629                        GET_ACCEPT_1(base, Type),
1630                        { old->linkage.val }
1631                );
1632                decl->assertions = GET_ACCEPT_V(assertions, DeclWithType);
1633                decl->params     = GET_ACCEPT_V(parameters, TypeDecl);
1634                decl->extension  = old->extension;
1635                decl->uniqueId   = old->uniqueId;
1636                decl->storage    = { old->storageClasses.val };
1637
1638                this->node = decl;
1639        }
1640
1641        virtual void visit( const AsmDecl * old ) override final {
1642                auto decl = new ast::AsmDecl{
1643                        old->location,
1644                        GET_ACCEPT_1(stmt, AsmStmt)
1645                };
1646                decl->extension  = old->extension;
1647                decl->uniqueId   = old->uniqueId;
1648                decl->storage    = { old->storageClasses.val };
1649
1650                this->node = decl;
1651        }
1652
1653        virtual void visit( const StaticAssertDecl * old ) override final {
1654                auto decl = new ast::StaticAssertDecl{
1655                        old->location,
1656                        GET_ACCEPT_1(condition, Expr),
1657                        GET_ACCEPT_1(message, ConstantExpr)
1658                };
1659                decl->extension  = old->extension;
1660                decl->uniqueId   = old->uniqueId;
1661                decl->storage    = { old->storageClasses.val };
1662
1663                this->node = decl;
1664        }
1665
1666        virtual void visit( const CompoundStmt * old ) override final {
1667                if ( inCache( old ) ) return;
1668                auto stmt = new ast::CompoundStmt(
1669                        old->location,
1670                        to<std::list>::from( GET_ACCEPT_V(kids, Stmt) ),
1671                        GET_LABELS_V(old->labels)
1672                );
1673
1674                this->node = stmt;
1675                cache.emplace( old, this->node );
1676        }
1677
1678        virtual void visit( const ExprStmt * old ) override final {
1679                if ( inCache( old ) ) return;
1680                this->node = new ast::ExprStmt(
1681                        old->location,
1682                        GET_ACCEPT_1(expr, Expr),
1683                        GET_LABELS_V(old->labels)
1684                );
1685                cache.emplace( old, this->node );
1686        }
1687
1688        virtual void visit( const AsmStmt * old ) override final {
1689                if ( inCache( old ) ) return;
1690                this->node = new ast::AsmStmt(
1691                        old->location,
1692                        old->voltile,
1693                        GET_ACCEPT_1(instruction, Expr),
1694                        GET_ACCEPT_V(output, Expr),
1695                        GET_ACCEPT_V(input, Expr),
1696                        GET_ACCEPT_V(clobber, ConstantExpr),
1697                        GET_LABELS_V(old->gotolabels),
1698                        GET_LABELS_V(old->labels)
1699                );
1700                cache.emplace( old, this->node );
1701        }
1702
1703        virtual void visit( const DirectiveStmt * old ) override final {
1704                if ( inCache( old ) ) return;
1705                this->node = new ast::DirectiveStmt(
1706                        old->location,
1707                        old->directive,
1708                        GET_LABELS_V(old->labels)
1709                );
1710                cache.emplace( old, this->node );
1711        }
1712
1713        virtual void visit( const IfStmt * old ) override final {
1714                if ( inCache( old ) ) return;
1715                this->node = new ast::IfStmt(
1716                        old->location,
1717                        GET_ACCEPT_1(condition, Expr),
1718                        GET_ACCEPT_1(thenPart, Stmt),
1719                        GET_ACCEPT_1(elsePart, Stmt),
1720                        GET_ACCEPT_V(initialization, Stmt),
1721                        GET_LABELS_V(old->labels)
1722                );
1723                cache.emplace( old, this->node );
1724        }
1725
1726        virtual void visit( const SwitchStmt * old ) override final {
1727                if ( inCache( old ) ) return;
1728                this->node = new ast::SwitchStmt(
1729                        old->location,
1730                        GET_ACCEPT_1(condition, Expr),
1731                        GET_ACCEPT_V(statements, Stmt),
1732                        GET_LABELS_V(old->labels)
1733                );
1734                cache.emplace( old, this->node );
1735        }
1736
1737        virtual void visit( const CaseStmt * old ) override final {
1738                if ( inCache( old ) ) return;
1739                this->node = new ast::CaseStmt(
1740                        old->location,
1741                        GET_ACCEPT_1(condition, Expr),
1742                        GET_ACCEPT_V(stmts, Stmt),
1743                        GET_LABELS_V(old->labels)
1744                );
1745                cache.emplace( old, this->node );
1746        }
1747
1748        virtual void visit( const WhileStmt * old ) override final {
1749                if ( inCache( old ) ) return;
1750                this->node = new ast::WhileStmt(
1751                        old->location,
1752                        GET_ACCEPT_1(condition, Expr),
1753                        GET_ACCEPT_1(body, Stmt),
1754                        GET_ACCEPT_V(initialization, Stmt),
1755                        old->isDoWhile,
1756                        GET_LABELS_V(old->labels)
1757                );
1758                cache.emplace( old, this->node );
1759        }
1760
1761        virtual void visit( const ForStmt * old ) override final {
1762                if ( inCache( old ) ) return;
1763                this->node = new ast::ForStmt(
1764                        old->location,
1765                        GET_ACCEPT_V(initialization, Stmt),
1766                        GET_ACCEPT_1(condition, Expr),
1767                        GET_ACCEPT_1(increment, Expr),
1768                        GET_ACCEPT_1(body, Stmt),
1769                        GET_LABELS_V(old->labels)
1770                );
1771                cache.emplace( old, this->node );
1772        }
1773
1774        virtual void visit( const BranchStmt * old ) override final {
1775                if ( inCache( old ) ) return;
1776                if (old->computedTarget) {
1777                        this->node = new ast::BranchStmt(
1778                                old->location,
1779                                GET_ACCEPT_1(computedTarget, Expr),
1780                                GET_LABELS_V(old->labels)
1781                        );
1782                } else {
1783                        ast::BranchStmt::Kind kind;
1784                        switch (old->type) {
1785                        #define CASE(n) \
1786                        case BranchStmt::n: \
1787                                kind = ast::BranchStmt::n; \
1788                                break
1789                        CASE(Goto);
1790                        CASE(Break);
1791                        CASE(Continue);
1792                        CASE(FallThrough);
1793                        CASE(FallThroughDefault);
1794                        #undef CASE
1795                        default:
1796                                assertf(false, "Invalid BranchStmt::Type %d\n", old->type);
1797                        }
1798
1799                        auto stmt = new ast::BranchStmt(
1800                                old->location,
1801                                kind,
1802                                make_label(&old->originalTarget),
1803                                GET_LABELS_V(old->labels)
1804                        );
1805                        stmt->target = make_label(&old->target);
1806                        this->node = stmt;
1807                }
1808                cache.emplace( old, this->node );
1809        }
1810
1811        virtual void visit( const ReturnStmt * old ) override final {
1812                if ( inCache( old ) ) return;
1813                this->node = new ast::ReturnStmt(
1814                        old->location,
1815                        GET_ACCEPT_1(expr, Expr),
1816                        GET_LABELS_V(old->labels)
1817                );
1818                cache.emplace( old, this->node );
1819        }
1820
1821        virtual void visit( const ThrowStmt * old ) override final {
1822                if ( inCache( old ) ) return;
1823                ast::ExceptionKind kind;
1824                switch (old->kind) {
1825                case ThrowStmt::Terminate:
1826                        kind = ast::ExceptionKind::Terminate;
1827                        break;
1828                case ThrowStmt::Resume:
1829                        kind = ast::ExceptionKind::Resume;
1830                        break;
1831                default:
1832                        assertf(false, "Invalid ThrowStmt::Kind %d\n", old->kind);
1833                }
1834
1835                this->node = new ast::ThrowStmt(
1836                        old->location,
1837                        kind,
1838                        GET_ACCEPT_1(expr, Expr),
1839                        GET_ACCEPT_1(target, Expr),
1840                        GET_LABELS_V(old->labels)
1841                );
1842                cache.emplace( old, this->node );
1843        }
1844
1845        virtual void visit( const TryStmt * old ) override final {
1846                if ( inCache( old ) ) return;
1847                this->node = new ast::TryStmt(
1848                        old->location,
1849                        GET_ACCEPT_1(block, CompoundStmt),
1850                        GET_ACCEPT_V(handlers, CatchStmt),
1851                        GET_ACCEPT_1(finallyBlock, FinallyStmt),
1852                        GET_LABELS_V(old->labels)
1853                );
1854                cache.emplace( old, this->node );
1855        }
1856
1857        virtual void visit( const CatchStmt * old ) override final {
1858                if ( inCache( old ) ) return;
1859                ast::ExceptionKind kind;
1860                switch (old->kind) {
1861                case CatchStmt::Terminate:
1862                        kind = ast::ExceptionKind::Terminate;
1863                        break;
1864                case CatchStmt::Resume:
1865                        kind = ast::ExceptionKind::Resume;
1866                        break;
1867                default:
1868                        assertf(false, "Invalid CatchStmt::Kind %d\n", old->kind);
1869                }
1870
1871                this->node = new ast::CatchStmt(
1872                        old->location,
1873                        kind,
1874                        GET_ACCEPT_1(decl, Decl),
1875                        GET_ACCEPT_1(cond, Expr),
1876                        GET_ACCEPT_1(body, Stmt),
1877                        GET_LABELS_V(old->labels)
1878                );
1879                cache.emplace( old, this->node );
1880        }
1881
1882        virtual void visit( const FinallyStmt * old ) override final {
1883                if ( inCache( old ) ) return;
1884                this->node = new ast::FinallyStmt(
1885                        old->location,
1886                        GET_ACCEPT_1(block, CompoundStmt),
1887                        GET_LABELS_V(old->labels)
1888                );
1889                cache.emplace( old, this->node );
1890        }
1891
1892        virtual void visit( const SuspendStmt * old ) override final {
1893                if ( inCache( old ) ) return;
1894                ast::SuspendStmt::Type type;
1895                switch (old->type) {
1896                        case SuspendStmt::Coroutine: type = ast::SuspendStmt::Coroutine; break;
1897                        case SuspendStmt::Generator: type = ast::SuspendStmt::Generator; break;
1898                        case SuspendStmt::None     : type = ast::SuspendStmt::None     ; break;
1899                        default: abort();
1900                }
1901                this->node = new ast::SuspendStmt(
1902                        old->location,
1903                        GET_ACCEPT_1(then  , CompoundStmt),
1904                        type,
1905                        GET_LABELS_V(old->labels)
1906                );
1907                cache.emplace( old, this->node );
1908        }
1909
1910        virtual void visit( const WaitForStmt * old ) override final {
1911                if ( inCache( old ) ) return;
1912                ast::WaitForStmt * stmt = new ast::WaitForStmt(
1913                        old->location,
1914                        GET_LABELS_V(old->labels)
1915                );
1916
1917                stmt->clauses.reserve( old->clauses.size() );
1918                for (size_t i = 0 ; i < old->clauses.size() ; ++i) {
1919                        stmt->clauses.push_back({
1920                                ast::WaitForStmt::Target{
1921                                        GET_ACCEPT_1(clauses[i].target.function, Expr),
1922                                        GET_ACCEPT_V(clauses[i].target.arguments, Expr)
1923                                },
1924                                GET_ACCEPT_1(clauses[i].statement, Stmt),
1925                                GET_ACCEPT_1(clauses[i].condition, Expr)
1926                        });
1927                }
1928                stmt->timeout = {
1929                        GET_ACCEPT_1(timeout.time, Expr),
1930                        GET_ACCEPT_1(timeout.statement, Stmt),
1931                        GET_ACCEPT_1(timeout.condition, Expr),
1932                };
1933                stmt->orElse = {
1934                        GET_ACCEPT_1(orelse.statement, Stmt),
1935                        GET_ACCEPT_1(orelse.condition, Expr),
1936                };
1937
1938                this->node = stmt;
1939                cache.emplace( old, this->node );
1940        }
1941
1942        virtual void visit( const WithStmt * old ) override final {
1943                if ( inCache( old ) ) return;
1944                this->node = new ast::WithStmt(
1945                        old->location,
1946                        GET_ACCEPT_V(exprs, Expr),
1947                        GET_ACCEPT_1(stmt, Stmt)
1948                );
1949                cache.emplace( old, this->node );
1950        }
1951
1952        virtual void visit( const NullStmt * old ) override final {
1953                if ( inCache( old ) ) return;
1954                this->node = new ast::NullStmt(
1955                        old->location,
1956                        GET_LABELS_V(old->labels)
1957                );
1958                cache.emplace( old, this->node );
1959        }
1960
1961        virtual void visit( const DeclStmt * old ) override final {
1962                if ( inCache( old ) ) return;
1963                this->node = new ast::DeclStmt(
1964                        old->location,
1965                        GET_ACCEPT_1(decl, Decl),
1966                        GET_LABELS_V(old->labels)
1967                );
1968                cache.emplace( old, this->node );
1969        }
1970
1971        virtual void visit( const ImplicitCtorDtorStmt * old ) override final {
1972                if ( inCache( old ) ) return;
1973                auto stmt = new ast::ImplicitCtorDtorStmt(
1974                        old->location,
1975                        nullptr,
1976                        GET_LABELS_V(old->labels)
1977                );
1978                cache.emplace( old, stmt );
1979                stmt->callStmt = GET_ACCEPT_1(callStmt, Stmt);
1980                this->node = stmt;
1981        }
1982
1983        ast::TypeSubstitution * convertTypeSubstitution(const TypeSubstitution * old) {
1984
1985                if (!old) return nullptr;
1986
1987                ast::TypeSubstitution *rslt = new ast::TypeSubstitution();
1988
1989                for (decltype(old->begin()) old_i = old->begin(); old_i != old->end(); old_i++) {
1990                        rslt->add( old_i->first,
1991                                   getAccept1<ast::Type>(old_i->second) );
1992                }
1993
1994                for (decltype(old->beginVar()) old_i = old->beginVar(); old_i != old->endVar(); old_i++) {
1995                        rslt->addVar( old_i->first,
1996                                      getAccept1<ast::Expr>(old_i->second) );
1997                }
1998
1999                return rslt;
2000        }
2001
2002        void convertInferUnion(ast::Expr::InferUnion               &newInferred,
2003                                                   const std::map<UniqueId,ParamEntry> &oldInferParams,
2004                                                   const std::vector<UniqueId>         &oldResnSlots) {
2005
2006                assert( oldInferParams.empty() || oldResnSlots.empty() );
2007                // assert( newInferred.mode == ast::Expr::InferUnion::Empty );
2008
2009                if ( !oldInferParams.empty() ) {
2010                        ast::InferredParams &tgt = newInferred.inferParams();
2011                        for (auto & old : oldInferParams) {
2012                                tgt[old.first] = ast::ParamEntry(
2013                                        old.second.decl,
2014                                        getAccept1<ast::Decl>(old.second.declptr),
2015                                        getAccept1<ast::Type>(old.second.actualType),
2016                                        getAccept1<ast::Type>(old.second.formalType),
2017                                        getAccept1<ast::Expr>(old.second.expr)
2018                                );
2019                        }
2020                } else if ( !oldResnSlots.empty() ) {
2021                        ast::ResnSlots &tgt = newInferred.resnSlots();
2022                        for (auto old : oldResnSlots) {
2023                                tgt.push_back(old);
2024                        }
2025                }
2026        }
2027
2028        ast::Expr * visitBaseExpr_SkipResultType( const Expression * old, ast::Expr * nw) {
2029
2030                nw->env    = convertTypeSubstitution(old->env);
2031
2032                nw->extension = old->extension;
2033                convertInferUnion(nw->inferred, old->inferParams, old->resnSlots);
2034
2035                return nw;
2036        }
2037
2038        ast::Expr * visitBaseExpr( const Expression * old, ast::Expr * nw) {
2039
2040                nw->result = GET_ACCEPT_1(result, Type);
2041                return visitBaseExpr_SkipResultType(old, nw);;
2042        }
2043
2044        virtual void visit( const ApplicationExpr * old ) override final {
2045                this->node = visitBaseExpr( old,
2046                        new ast::ApplicationExpr(
2047                                old->location,
2048                                GET_ACCEPT_1(function, Expr),
2049                                GET_ACCEPT_V(args, Expr)
2050                        )
2051                );
2052        }
2053
2054        virtual void visit( const UntypedExpr * old ) override final {
2055                this->node = visitBaseExpr( old,
2056                        new ast::UntypedExpr(
2057                                old->location,
2058                                GET_ACCEPT_1(function, Expr),
2059                                GET_ACCEPT_V(args, Expr)
2060                        )
2061                );
2062        }
2063
2064        virtual void visit( const NameExpr * old ) override final {
2065                this->node = visitBaseExpr( old,
2066                        new ast::NameExpr(
2067                                old->location,
2068                                old->get_name()
2069                        )
2070                );
2071        }
2072
2073        virtual void visit( const CastExpr * old ) override final {
2074                this->node = visitBaseExpr( old,
2075                        new ast::CastExpr(
2076                                old->location,
2077                                GET_ACCEPT_1(arg, Expr),
2078                                old->isGenerated ? ast::GeneratedCast : ast::ExplicitCast
2079                        )
2080                );
2081        }
2082
2083        virtual void visit( const KeywordCastExpr * old ) override final {
2084                ast::AggregateDecl::Aggregate castTarget = (ast::AggregateDecl::Aggregate)old->target;
2085                assert( ast::AggregateDecl::Generator <= castTarget && castTarget <= ast::AggregateDecl::Thread );
2086                this->node = visitBaseExpr( old,
2087                        new ast::KeywordCastExpr(
2088                                old->location,
2089                                GET_ACCEPT_1(arg, Expr),
2090                                castTarget,
2091                                {old->concrete_target.field, old->concrete_target.getter}
2092                        )
2093                );
2094        }
2095
2096        virtual void visit( const VirtualCastExpr * old ) override final {
2097                this->node = visitBaseExpr_SkipResultType( old,
2098                        new ast::VirtualCastExpr(
2099                                old->location,
2100                                GET_ACCEPT_1(arg, Expr),
2101                                GET_ACCEPT_1(result, Type)
2102                        )
2103                );
2104        }
2105
2106        virtual void visit( const AddressExpr * old ) override final {
2107                this->node = visitBaseExpr( old,
2108                        new ast::AddressExpr(
2109                                old->location,
2110                                GET_ACCEPT_1(arg, Expr)
2111                        )
2112                );
2113        }
2114
2115        virtual void visit( const LabelAddressExpr * old ) override final {
2116                this->node = visitBaseExpr( old,
2117                        new ast::LabelAddressExpr(
2118                                old->location,
2119                                make_label(&old->arg)
2120                        )
2121                );
2122        }
2123
2124        virtual void visit( const UntypedMemberExpr * old ) override final {
2125                this->node = visitBaseExpr( old,
2126                        new ast::UntypedMemberExpr(
2127                                old->location,
2128                                GET_ACCEPT_1(member, Expr),
2129                                GET_ACCEPT_1(aggregate, Expr)
2130                        )
2131                );
2132        }
2133
2134        virtual void visit( const MemberExpr * old ) override final {
2135                this->node = visitBaseExpr( old,
2136                        new ast::MemberExpr(
2137                                old->location,
2138                                GET_ACCEPT_1(member, DeclWithType),
2139                                GET_ACCEPT_1(aggregate, Expr),
2140                                ast::MemberExpr::NoOpConstructionChosen
2141                        )
2142                );
2143        }
2144
2145        virtual void visit( const VariableExpr * old ) override final {
2146                auto expr = new ast::VariableExpr(
2147                        old->location
2148                );
2149
2150                expr->var = GET_ACCEPT_1(var, DeclWithType);
2151                visitBaseExpr( old, expr );
2152
2153                this->node = expr;
2154        }
2155
2156        virtual void visit( const ConstantExpr * old ) override final {
2157                ast::ConstantExpr *rslt = new ast::ConstantExpr(
2158                        old->location,
2159                        GET_ACCEPT_1(result, Type),
2160                        old->constant.rep,
2161                        old->constant.ival
2162                );
2163                rslt->underlyer = getAccept1< ast::Type, Type* >( old->constant.type );
2164                this->node = visitBaseExpr( old, rslt );
2165        }
2166
2167        virtual void visit( const SizeofExpr * old ) override final {
2168                assert (old->expr || old->type);
2169                assert (! (old->expr && old->type));
2170                ast::SizeofExpr *rslt;
2171                if (old->expr) {
2172                        assert(!old->isType);
2173                        rslt = new ast::SizeofExpr(
2174                                old->location,
2175                                GET_ACCEPT_1(expr, Expr)
2176                        );
2177                }
2178                if (old->type) {
2179                        assert(old->isType);
2180                        rslt = new ast::SizeofExpr(
2181                                old->location,
2182                                GET_ACCEPT_1(type, Type)
2183                        );
2184                }
2185                this->node = visitBaseExpr( old, rslt );
2186        }
2187
2188        virtual void visit( const AlignofExpr * old ) override final {
2189                assert (old->expr || old->type);
2190                assert (! (old->expr && old->type));
2191                ast::AlignofExpr *rslt;
2192                if (old->expr) {
2193                        assert(!old->isType);
2194                        rslt = new ast::AlignofExpr(
2195                                old->location,
2196                                GET_ACCEPT_1(expr, Expr)
2197                        );
2198                }
2199                if (old->type) {
2200                        assert(old->isType);
2201                        rslt = new ast::AlignofExpr(
2202                                old->location,
2203                                GET_ACCEPT_1(type, Type)
2204                        );
2205                }
2206                this->node = visitBaseExpr( old, rslt );
2207        }
2208
2209        virtual void visit( const UntypedOffsetofExpr * old ) override final {
2210                this->node = visitBaseExpr( old,
2211                        new ast::UntypedOffsetofExpr(
2212                                old->location,
2213                                GET_ACCEPT_1(type, Type),
2214                                old->member
2215                        )
2216                );
2217        }
2218
2219        virtual void visit( const OffsetofExpr * old ) override final {
2220                this->node = visitBaseExpr( old,
2221                        new ast::OffsetofExpr(
2222                                old->location,
2223                                GET_ACCEPT_1(type, Type),
2224                                GET_ACCEPT_1(member, DeclWithType)
2225                        )
2226                );
2227        }
2228
2229        virtual void visit( const OffsetPackExpr * old ) override final {
2230                this->node = visitBaseExpr( old,
2231                        new ast::OffsetPackExpr(
2232                                old->location,
2233                                GET_ACCEPT_1(type, StructInstType)
2234                        )
2235                );
2236        }
2237
2238        virtual void visit( const LogicalExpr * old ) override final {
2239                this->node = visitBaseExpr( old,
2240                        new ast::LogicalExpr(
2241                                old->location,
2242                                GET_ACCEPT_1(arg1, Expr),
2243                                GET_ACCEPT_1(arg2, Expr),
2244                                old->get_isAnd() ?
2245                                        ast::LogicalFlag::AndExpr :
2246                                        ast::LogicalFlag::OrExpr
2247                        )
2248                );
2249        }
2250
2251        virtual void visit( const ConditionalExpr * old ) override final {
2252                this->node = visitBaseExpr( old,
2253                        new ast::ConditionalExpr(
2254                                old->location,
2255                                GET_ACCEPT_1(arg1, Expr),
2256                                GET_ACCEPT_1(arg2, Expr),
2257                                GET_ACCEPT_1(arg3, Expr)
2258                        )
2259                );
2260        }
2261
2262        virtual void visit( const CommaExpr * old ) override final {
2263                this->node = visitBaseExpr( old,
2264                        new ast::CommaExpr(
2265                                old->location,
2266                                GET_ACCEPT_1(arg1, Expr),
2267                                GET_ACCEPT_1(arg2, Expr)
2268                        )
2269                );
2270        }
2271
2272        virtual void visit( const TypeExpr * old ) override final {
2273                this->node = visitBaseExpr( old,
2274                        new ast::TypeExpr(
2275                                old->location,
2276                                GET_ACCEPT_1(type, Type)
2277                        )
2278                );
2279        }
2280
2281        virtual void visit( const AsmExpr * old ) override final {
2282                this->node = visitBaseExpr( old,
2283                        new ast::AsmExpr(
2284                                old->location,
2285                                old->inout,
2286                                GET_ACCEPT_1(constraint, Expr),
2287                                GET_ACCEPT_1(operand, Expr)
2288                        )
2289                );
2290        }
2291
2292        virtual void visit( const ImplicitCopyCtorExpr * old ) override final {
2293                auto rslt = new ast::ImplicitCopyCtorExpr(
2294                        old->location,
2295                        GET_ACCEPT_1(callExpr, ApplicationExpr)
2296                );
2297
2298                this->node = visitBaseExpr( old, rslt );
2299        }
2300
2301        virtual void visit( const ConstructorExpr * old ) override final {
2302                this->node = visitBaseExpr( old,
2303                        new ast::ConstructorExpr(
2304                                old->location,
2305                                GET_ACCEPT_1(callExpr, Expr)
2306                        )
2307                );
2308        }
2309
2310        virtual void visit( const CompoundLiteralExpr * old ) override final {
2311                this->node = visitBaseExpr_SkipResultType( old,
2312                        new ast::CompoundLiteralExpr(
2313                                old->location,
2314                                GET_ACCEPT_1(result, Type),
2315                                GET_ACCEPT_1(initializer, Init)
2316                        )
2317                );
2318        }
2319
2320        virtual void visit( const RangeExpr * old ) override final {
2321                this->node = visitBaseExpr( old,
2322                        new ast::RangeExpr(
2323                                old->location,
2324                                GET_ACCEPT_1(low, Expr),
2325                                GET_ACCEPT_1(high, Expr)
2326                        )
2327                );
2328        }
2329
2330        virtual void visit( const UntypedTupleExpr * old ) override final {
2331                this->node = visitBaseExpr( old,
2332                        new ast::UntypedTupleExpr(
2333                                old->location,
2334                                GET_ACCEPT_V(exprs, Expr)
2335                        )
2336                );
2337        }
2338
2339        virtual void visit( const TupleExpr * old ) override final {
2340                this->node = visitBaseExpr( old,
2341                        new ast::TupleExpr(
2342                                old->location,
2343                                GET_ACCEPT_V(exprs, Expr)
2344                        )
2345                );
2346        }
2347
2348        virtual void visit( const TupleIndexExpr * old ) override final {
2349                this->node = visitBaseExpr( old,
2350                        new ast::TupleIndexExpr(
2351                                old->location,
2352                                GET_ACCEPT_1(tuple, Expr),
2353                                old->index
2354                        )
2355                );
2356        }
2357
2358        virtual void visit( const TupleAssignExpr * old ) override final {
2359                this->node = visitBaseExpr_SkipResultType( old,
2360                        new ast::TupleAssignExpr(
2361                                old->location,
2362                                GET_ACCEPT_1(result, Type),
2363                                GET_ACCEPT_1(stmtExpr, StmtExpr)
2364                        )
2365                );
2366        }
2367
2368        virtual void visit( const StmtExpr * old ) override final {
2369                auto rslt = new ast::StmtExpr(
2370                        old->location,
2371                        GET_ACCEPT_1(statements, CompoundStmt)
2372                );
2373                rslt->returnDecls = GET_ACCEPT_V(returnDecls, ObjectDecl);
2374                rslt->dtors       = GET_ACCEPT_V(dtors      , Expr);
2375
2376                this->node = visitBaseExpr_SkipResultType( old, rslt );
2377        }
2378
2379        virtual void visit( const UniqueExpr * old ) override final {
2380                auto rslt = new ast::UniqueExpr(
2381                        old->location,
2382                        GET_ACCEPT_1(expr, Expr),
2383                        old->get_id()
2384                );
2385                rslt->object = GET_ACCEPT_1(object, ObjectDecl);
2386                rslt->var    = GET_ACCEPT_1(var   , VariableExpr);
2387
2388                this->node = visitBaseExpr( old, rslt );
2389        }
2390
2391        virtual void visit( const UntypedInitExpr * old ) override final {
2392                std::deque<ast::InitAlternative> initAlts;
2393                for (auto ia : old->initAlts) {
2394                        initAlts.push_back(ast::InitAlternative(
2395                                getAccept1< ast::Type, Type * >( ia.type ),
2396                                getAccept1< ast::Designation, Designation * >( ia.designation )
2397                        ));
2398                }
2399                this->node = visitBaseExpr( old,
2400                        new ast::UntypedInitExpr(
2401                                old->location,
2402                                GET_ACCEPT_1(expr, Expr),
2403                                std::move(initAlts)
2404                        )
2405                );
2406        }
2407
2408        virtual void visit( const InitExpr * old ) override final {
2409                this->node = visitBaseExpr( old,
2410                        new ast::InitExpr(
2411                                old->location,
2412                                GET_ACCEPT_1(expr, Expr),
2413                                GET_ACCEPT_1(designation, Designation)
2414                        )
2415                );
2416        }
2417
2418        virtual void visit( const DeletedExpr * old ) override final {
2419                this->node = visitBaseExpr( old,
2420                        new ast::DeletedExpr(
2421                                old->location,
2422                                GET_ACCEPT_1(expr, Expr),
2423                                inCache(old->deleteStmt) ?
2424                                        strict_dynamic_cast<ast::Decl*>(this->node) :
2425                                        GET_ACCEPT_1(deleteStmt, Decl)
2426                        )
2427                );
2428        }
2429
2430        virtual void visit( const DefaultArgExpr * old ) override final {
2431                this->node = visitBaseExpr( old,
2432                        new ast::DefaultArgExpr(
2433                                old->location,
2434                                GET_ACCEPT_1(expr, Expr)
2435                        )
2436                );
2437        }
2438
2439        virtual void visit( const GenericExpr * old ) override final {
2440                std::vector<ast::GenericExpr::Association> associations;
2441                for (auto association : old->associations) {
2442                        associations.push_back(ast::GenericExpr::Association(
2443                                getAccept1< ast::Type, Type * >( association.type ),
2444                                getAccept1< ast::Expr, Expression * >( association.expr )
2445                        ));
2446                }
2447                this->node = visitBaseExpr( old,
2448                        new ast::GenericExpr(
2449                                old->location,
2450                                GET_ACCEPT_1(control, Expr),
2451                                std::move(associations)
2452                        )
2453                );
2454        }
2455
2456        void visitType( const Type * old, ast::Type * type ) {
2457                // Some types do this in their constructor so add a check.
2458                if ( !old->attributes.empty() && type->attributes.empty() ) {
2459                        type->attributes = GET_ACCEPT_V(attributes, Attribute);
2460                }
2461                this->node = type;
2462        }
2463
2464        virtual void visit( const VoidType * old ) override final {
2465                visitType( old, new ast::VoidType{ cv( old ) } );
2466        }
2467
2468        virtual void visit( const BasicType * old ) override final {
2469                auto type = new ast::BasicType{ (ast::BasicType::Kind)(unsigned)old->kind, cv( old ) };
2470                // I believe this should always be a BasicType.
2471                if ( Validate::SizeType == old ) {
2472                        sizeType = type;
2473                }
2474                visitType( old, type );
2475        }
2476
2477        virtual void visit( const PointerType * old ) override final {
2478                visitType( old, new ast::PointerType{
2479                        GET_ACCEPT_1( base, Type ),
2480                        GET_ACCEPT_1( dimension, Expr ),
2481                        (ast::LengthFlag)old->isVarLen,
2482                        (ast::DimensionFlag)old->isStatic,
2483                        cv( old )
2484                } );
2485        }
2486
2487        virtual void visit( const ArrayType * old ) override final {
2488                visitType( old, new ast::ArrayType{
2489                        GET_ACCEPT_1( base, Type ),
2490                        GET_ACCEPT_1( dimension, Expr ),
2491                        (ast::LengthFlag)old->isVarLen,
2492                        (ast::DimensionFlag)old->isStatic,
2493                        cv( old )
2494                } );
2495        }
2496
2497        virtual void visit( const ReferenceType * old ) override final {
2498                visitType( old, new ast::ReferenceType{
2499                        GET_ACCEPT_1( base, Type ),
2500                        cv( old )
2501                } );
2502        }
2503
2504        virtual void visit( const QualifiedType * old ) override final {
2505                visitType( old, new ast::QualifiedType{
2506                        GET_ACCEPT_1( parent, Type ),
2507                        GET_ACCEPT_1( child, Type ),
2508                        cv( old )
2509                } );
2510        }
2511
2512        virtual void visit( const FunctionType * old ) override final {
2513                auto ty = new ast::FunctionType {
2514                        (ast::ArgumentFlag)old->isVarArgs,
2515                        cv( old )
2516                };
2517                ty->returns = GET_ACCEPT_V( returnVals, DeclWithType );
2518                ty->params = GET_ACCEPT_V( parameters, DeclWithType );
2519                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
2520                visitType( old, ty );
2521        }
2522
2523        void postvisit( const ReferenceToType * old, ast::BaseInstType * ty ) {
2524                ty->forall = GET_ACCEPT_V( forall, TypeDecl );
2525                ty->params = GET_ACCEPT_V( parameters, Expr );
2526                ty->hoistType = old->hoistType;
2527                visitType( old, ty );
2528        }
2529
2530        virtual void visit( const StructInstType * old ) override final {
2531                ast::StructInstType * ty;
2532                if ( old->baseStruct ) {
2533                        ty = new ast::StructInstType{
2534                                GET_ACCEPT_1( baseStruct, StructDecl ),
2535                                cv( old ),
2536                                GET_ACCEPT_V( attributes, Attribute )
2537                        };
2538                } else {
2539                        ty = new ast::StructInstType{
2540                                old->name,
2541                                cv( old ),
2542                                GET_ACCEPT_V( attributes, Attribute )
2543                        };
2544                }
2545                postvisit( old, ty );
2546        }
2547
2548        virtual void visit( const UnionInstType * old ) override final {
2549                ast::UnionInstType * ty;
2550                if ( old->baseUnion ) {
2551                        ty = new ast::UnionInstType{
2552                                GET_ACCEPT_1( baseUnion, UnionDecl ),
2553                                cv( old ),
2554                                GET_ACCEPT_V( attributes, Attribute )
2555                        };
2556                } else {
2557                        ty = new ast::UnionInstType{
2558                                old->name,
2559                                cv( old ),
2560                                GET_ACCEPT_V( attributes, Attribute )
2561                        };
2562                }
2563                postvisit( old, ty );
2564        }
2565
2566        virtual void visit( const EnumInstType * old ) override final {
2567                ast::EnumInstType * ty;
2568                if ( old->baseEnum ) {
2569                        ty = new ast::EnumInstType{
2570                                GET_ACCEPT_1( baseEnum, EnumDecl ),
2571                                cv( old ),
2572                                GET_ACCEPT_V( attributes, Attribute )
2573                        };
2574                } else {
2575                        ty = new ast::EnumInstType{
2576                                old->name,
2577                                cv( old ),
2578                                GET_ACCEPT_V( attributes, Attribute )
2579                        };
2580                }
2581                postvisit( old, ty );
2582        }
2583
2584        virtual void visit( const TraitInstType * old ) override final {
2585                ast::TraitInstType * ty;
2586                if ( old->baseTrait ) {
2587                        ty = new ast::TraitInstType{
2588                                GET_ACCEPT_1( baseTrait, TraitDecl ),
2589                                cv( old ),
2590                                GET_ACCEPT_V( attributes, Attribute )
2591                        };
2592                } else {
2593                        ty = new ast::TraitInstType{
2594                                old->name,
2595                                cv( old ),
2596                                GET_ACCEPT_V( attributes, Attribute )
2597                        };
2598                }
2599                postvisit( old, ty );
2600        }
2601
2602        virtual void visit( const TypeInstType * old ) override final {
2603                ast::TypeInstType * ty;
2604                if ( old->baseType ) {
2605                        ty = new ast::TypeInstType{
2606                                old->name,
2607                                GET_ACCEPT_1( baseType, TypeDecl ),
2608                                cv( old ),
2609                                GET_ACCEPT_V( attributes, Attribute )
2610                        };
2611                } else {
2612                        ty = new ast::TypeInstType{
2613                                old->name,
2614                                old->isFtype ? ast::TypeDecl::Ftype : ast::TypeDecl::Dtype,
2615                                cv( old ),
2616                                GET_ACCEPT_V( attributes, Attribute )
2617                        };
2618                }
2619                postvisit( old, ty );
2620        }
2621
2622        virtual void visit( const TupleType * old ) override final {
2623                visitType( old, new ast::TupleType{
2624                        GET_ACCEPT_V( types, Type ),
2625                        // members generated by TupleType c'tor
2626                        cv( old )
2627                } );
2628        }
2629
2630        virtual void visit( const TypeofType * old ) override final {
2631                visitType( old, new ast::TypeofType{
2632                        GET_ACCEPT_1( expr, Expr ),
2633                        (ast::TypeofType::Kind)old->is_basetypeof,
2634                        cv( old )
2635                } );
2636        }
2637
2638        virtual void visit( const AttrType * ) override final {
2639                assertf( false, "AttrType deprecated in new AST." );
2640        }
2641
2642        virtual void visit( const VarArgsType * old ) override final {
2643                visitType( old, new ast::VarArgsType{ cv( old ) } );
2644        }
2645
2646        virtual void visit( const ZeroType * old ) override final {
2647                visitType( old, new ast::ZeroType{ cv( old ) } );
2648        }
2649
2650        virtual void visit( const OneType * old ) override final {
2651                visitType( old, new ast::OneType{ cv( old ) } );
2652        }
2653
2654        virtual void visit( const GlobalScopeType * old ) override final {
2655                visitType( old, new ast::GlobalScopeType{} );
2656        }
2657
2658        virtual void visit( const Designation * old ) override final {
2659                this->node = new ast::Designation(
2660                        old->location,
2661                        GET_ACCEPT_D(designators, Expr)
2662                );
2663        }
2664
2665        virtual void visit( const SingleInit * old ) override final {
2666                this->node = new ast::SingleInit(
2667                        old->location,
2668                        GET_ACCEPT_1(value, Expr),
2669                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
2670                );
2671        }
2672
2673        virtual void visit( const ListInit * old ) override final {
2674                this->node = new ast::ListInit(
2675                        old->location,
2676                        GET_ACCEPT_V(initializers, Init),
2677                        GET_ACCEPT_V(designations, Designation),
2678                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
2679                );
2680        }
2681
2682        virtual void visit( const ConstructorInit * old ) override final {
2683                this->node = new ast::ConstructorInit(
2684                        old->location,
2685                        GET_ACCEPT_1(ctor, Stmt),
2686                        GET_ACCEPT_1(dtor, Stmt),
2687                        GET_ACCEPT_1(init, Init)
2688                );
2689        }
2690
2691        virtual void visit( const Constant * ) override final {
2692                // Handled in visit( ConstantEpxr * ).
2693                // In the new tree, Constant fields are inlined into containing ConstantExpression.
2694                assert( 0 );
2695        }
2696
2697        virtual void visit( const Attribute * old ) override final {
2698                this->node = new ast::Attribute(
2699                        old->name,
2700                        GET_ACCEPT_V( parameters, Expr )
2701                );
2702        }
2703};
2704
2705#undef GET_LABELS_V
2706#undef GET_ACCEPT_V
2707#undef GET_ACCEPT_1
2708
2709std::list< ast::ptr< ast::Decl > > convert( const std::list< Declaration * > && translationUnit ) {
2710        ConverterOldToNew c;
2711        std::list< ast::ptr< ast::Decl > > decls;
2712        for(auto d : translationUnit) {
2713                d->accept( c );
2714                decls.emplace_back( c.decl() );
2715        }
2716        deleteAll(translationUnit);
2717        return decls;
2718}
Note: See TracBrowser for help on using the repository browser.