Changeset d672350 for src


Ignore:
Timestamp:
Mar 21, 2022, 1:44:06 PM (4 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, ast-experimental, enum, master, pthread-emulation, qualifiedEnum
Children:
a76202d
Parents:
ef3c383 (diff), dbe2533 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

Location:
src
Files:
4 added
2 deleted
33 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    ref3c383 rd672350  
    99// Author           : Thierry Delisle
    1010// Created On       : Thu May 09 15::37::05 2019
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Wed Feb  2 13:19:22 2022
    13 // Update Count     : 41
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Mar 16 15:01:00 2022
     13// Update Count     : 42
    1414//
    1515
     
    4949//================================================================================================
    5050namespace ast {
    51 
    52 // This is to preserve the FindSpecialDecls hack. It does not (and perhaps should not)
    53 // allow us to use the same stratagy in the new ast.
    54 // xxx - since convert back pass works, this concern seems to be unnecessary.
    55 
    56 // these need to be accessed in new FixInit now
    57 ast::ptr<ast::Type> sizeType = nullptr;
    58 const ast::FunctionDecl * dereferenceOperator = nullptr;
    59 const ast::StructDecl   * dtorStruct = nullptr;
    60 const ast::FunctionDecl * dtorStructDestroy = nullptr;
     51// These are the shared local information used by ConverterNewToOld and
     52// ConverterOldToNew to update the global information in the two versions.
     53
     54static ast::ptr<ast::Type> sizeType = nullptr;
     55static const ast::FunctionDecl * dereferenceOperator = nullptr;
     56static const ast::StructDecl   * dtorStruct = nullptr;
     57static const ast::FunctionDecl * dtorStructDestroy = nullptr;
    6158
    6259}
  • src/AST/Decl.cpp

    ref3c383 rd672350  
    3939        if ( uniqueId ) return;  // ensure only set once
    4040        uniqueId = ++lastUniqueId;
    41         idMap[ uniqueId ] = this;
     41        // The extra readonly pointer is causing some reference counting issues.
     42        // idMap[ uniqueId ] = this;
    4243}
    4344
    4445readonly<Decl> Decl::fromId( UniqueId id ) {
     46        // Right now this map is always empty, so don't use it.
     47        assert( false );
    4548        IdMapType::const_iterator i = idMap.find( id );
    4649        if ( i != idMap.end() ) return i->second;
  • src/AST/Fwd.hpp

    ref3c383 rd672350  
    141141
    142142class TranslationUnit;
    143 // TODO: Get from the TranslationUnit:
    144 extern ptr<Type> sizeType;
    145 extern const FunctionDecl * dereferenceOperator;
    146 extern const StructDecl   * dtorStruct;
    147 extern const FunctionDecl * dtorStructDestroy;
     143class TranslationGlobal;
    148144
    149145}
  • src/AST/GenericSubstitution.cpp

    ref3c383 rd672350  
    4545                        visit_children = false;
    4646                        const AggregateDecl * aggr = ty->aggr();
    47                         sub = TypeSubstitution{ aggr->params.begin(), aggr->params.end(), ty->params.begin() };
     47                        sub = TypeSubstitution( aggr->params, ty->params );
    4848                }
    4949
  • src/AST/TranslationUnit.hpp

    ref3c383 rd672350  
    1010// Created On       : Tue Jun 11 15:30:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Jun 11 15:42:00 2019
    13 // Update Count     : 0
     12// Last Modified On : Tue Mar 11 11:19:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    2323namespace ast {
    2424
     25class TranslationGlobal {
     26public:
     27        std::map< UniqueId, Decl * > idMap;
     28
     29        ptr<Type> sizeType;
     30        const FunctionDecl * dereference;
     31        const StructDecl * dtorStruct;
     32        const FunctionDecl * dtorDestroy;
     33};
     34
    2535class TranslationUnit {
    2636public:
    2737        std::list< ptr< Decl > > decls;
    28 
    29         struct Global {
    30                 std::map< UniqueId, Decl * > idMap;
    31 
    32                 ptr<Type> sizeType;
    33                 const FunctionDecl * dereference;
    34                 const StructDecl * dtorStruct;
    35                 const FunctionDecl * dtorDestroy;
    36         } global;
     38        TranslationGlobal global;
    3739};
    3840
  • src/AST/TypeSubstitution.hpp

    ref3c383 rd672350  
    3737  public:
    3838        TypeSubstitution();
     39        template< typename FormalContainer, typename ActualContainer >
     40        TypeSubstitution( FormalContainer formals, ActualContainer actuals );
    3941        template< typename FormalIterator, typename ActualIterator >
    4042        TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
     
    7678        bool empty() const;
    7779
     80        template< typename FormalContainer, typename ActualContainer >
     81        void addAll( FormalContainer formals, ActualContainer actuals );
    7882        template< typename FormalIterator, typename ActualIterator >
    79         void add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
     83        void addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin );
    8084
    8185        /// create a new TypeSubstitution using bindings from env containing all of the type variables in expr
     
    112116};
    113117
     118template< typename FormalContainer, typename ActualContainer >
     119TypeSubstitution::TypeSubstitution( FormalContainer formals, ActualContainer actuals ) {
     120        assert( formals.size() == actuals.size() );
     121        addAll( formals.begin(), formals.end(), actuals.begin() );
     122}
     123
     124template< typename FormalIterator, typename ActualIterator >
     125TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
     126        addAll( formalBegin, formalEnd, actualBegin );
     127}
     128
     129template< typename FormalContainer, typename ActualContainer >
     130void TypeSubstitution::addAll( FormalContainer formals, ActualContainer actuals ) {
     131        assert( formals.size() == actuals.size() );
     132        addAll( formals.begin(), formals.end(), actuals.begin() );
     133}
     134
    114135// this is the only place where type parameters outside a function formal may be substituted.
    115136template< typename FormalIterator, typename ActualIterator >
    116 void TypeSubstitution::add( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
     137void TypeSubstitution::addAll( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
    117138        // FormalIterator points to a TypeDecl
    118139        // ActualIterator points to a Type
     
    129150                        } // if
    130151                } else {
    131                        
     152                        // Is this an error?
    132153                } // if
    133154        } // for
    134155}
    135 
    136 
    137 
    138 template< typename FormalIterator, typename ActualIterator >
    139 TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) {
    140         add( formalBegin, formalEnd, actualBegin );
    141 }
    142 
    143156
    144157} // namespace ast
  • src/AST/module.mk

    ref3c383 rd672350  
    1616
    1717SRC_AST = \
    18         AST/AssertAcyclic.cpp \
    19         AST/AssertAcyclic.hpp \
    2018        AST/Attribute.cpp \
    2119        AST/Attribute.hpp \
     
    6462        AST/TypeSubstitution.cpp \
    6563        AST/TypeSubstitution.hpp \
     64        AST/Util.cpp \
     65        AST/Util.hpp \
    6666        AST/Visitor.hpp
    6767
  • src/Common/CodeLocationTools.cpp

    ref3c383 rd672350  
    99// Author           : Andrew Beach
    1010// Created On       : Fri Dec  4 15:42:00 2020
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  1 09:14:39 2022
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Mon Mar 14 15:14:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    239239};
    240240
     241class LocalFillCore : public ast::WithGuards {
     242        CodeLocation const * parent;
     243public:
     244        LocalFillCore( CodeLocation const & location ) : parent( &location ) {
     245                assert( location.isSet() );
     246        }
     247
     248        template<typename node_t>
     249        auto previsit( node_t const * node )
     250                        -> typename std::enable_if<has_code_location<node_t>::value, node_t const *>::type {
     251                if ( node->location.isSet() ) {
     252                        GuardValue( parent ) = &node->location;
     253                        return node;
     254                } else {
     255                        node_t * mut = ast::mutate( node );
     256                        mut->location = *parent;
     257                        return mut;
     258                }
     259        }
     260};
     261
    241262} // namespace
    242263
     
    278299        ast::Pass<FillCore>::run( unit );
    279300}
     301
     302ast::Node const * localFillCodeLocations(
     303                CodeLocation const & location , ast::Node const * node ) {
     304        ast::Pass<LocalFillCore> visitor( location );
     305        return node->accept( visitor );
     306}
  • src/Common/CodeLocationTools.hpp

    ref3c383 rd672350  
    1010// Created On       : Fri Dec  4 15:35:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Dec  9  9:53:00 2020
    13 // Update Count     : 1
     12// Last Modified On : Mon Mar 14 15:14:00 2022
     13// Update Count     : 2
    1414//
    1515
    1616#pragma once
    1717
     18struct CodeLocation;
    1819namespace ast {
     20        class Node;
    1921        class TranslationUnit;
    2022}
     
    2830// Assign a nearby code-location to any unset code locations in the forest.
    2931void forceFillCodeLocations( ast::TranslationUnit & unit );
     32
     33// Fill in code-locations with a parent code location,
     34// using the provided CodeLocation as the base.
     35ast::Node const *
     36        localFillCodeLocations( CodeLocation const &, ast::Node const * );
  • src/Common/Examine.cc

    ref3c383 rd672350  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Examine.h --
     7// Examine.cc -- Helpers for examining AST code.
    88//
    99// Author           : Andrew Beach
    1010// Created On       : Wed Sept 2 14:02 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Sep  8 12:15 2020
    13 // Update Count     : 0
     12// Last Modified On : Fri Dec 10 10:27 2021
     13// Update Count     : 1
    1414//
    1515
    1616#include "Common/Examine.h"
    1717
     18#include "AST/Type.hpp"
    1819#include "CodeGen/OperatorTable.h"
     20#include "InitTweak/InitTweak.h"
    1921
    2022DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind ) {
     
    3638
    3739namespace {
     40
     41// getTypeofThis but does some extra checks used in this module.
     42const ast::Type * getTypeofThisSolo( const ast::FunctionDecl * func ) {
     43        if ( 1 != func->params.size() ) {
     44                return nullptr;
     45        }
     46        auto ref = func->type->params.front().as<ast::ReferenceType>();
     47        return (ref) ? ref->base : nullptr;
     48}
     49
     50}
     51
     52const ast::DeclWithType * isMainFor(
     53                const ast::FunctionDecl * func, ast::AggregateDecl::Aggregate kind ) {
     54        if ( "main" != func->name ) return nullptr;
     55        if ( 1 != func->params.size() ) return nullptr;
     56
     57        auto param = func->params.front();
     58
     59        auto type = dynamic_cast<const ast::ReferenceType *>( param->get_type() );
     60        if ( !type ) return nullptr;
     61
     62        auto obj = type->base.as<ast::StructInstType>();
     63        if ( !obj ) return nullptr;
     64
     65        if ( kind != obj->base->kind ) return nullptr;
     66
     67        return param;
     68}
     69
     70namespace {
    3871        Type * getDestructorParam( FunctionDecl * func ) {
    3972                if ( !CodeGen::isDestructor( func->name ) ) return nullptr;
     
    4881                return nullptr;
    4982        }
     83
     84const ast::Type * getDestructorParam( const ast::FunctionDecl * func ) {
     85        if ( !CodeGen::isDestructor( func->name ) ) return nullptr;
     86        //return InitTweak::getParamThis( func )->type;
     87        return getTypeofThisSolo( func );
     88}
     89
    5090}
    5191
     
    5797        return false;
    5898}
     99
     100bool isDestructorFor(
     101                const ast::FunctionDecl * func, const ast::StructDecl * type_decl ) {
     102        if ( const ast::Type * type = getDestructorParam( func ) ) {
     103                auto stype = dynamic_cast<const ast::StructInstType *>( type );
     104                return stype && stype->base.get() == type_decl;
     105        }
     106        return false;
     107}
  • src/Common/Examine.h

    ref3c383 rd672350  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // Examine.h --
     7// Examine.h -- Helpers for examining AST code.
    88//
    99// Author           : Andrew Beach
    1010// Created On       : Wed Sept 2 13:57 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Sep  8 12:08 2020
    13 // Update Count     : 0
     12// Last Modified On : Fri Dec 10 10:28 2021
     13// Update Count     : 1
    1414//
    1515
     16#include "AST/Decl.hpp"
    1617#include "SynTree/Declaration.h"
    1718
    1819/// Check if this is a main function for a type of an aggregate kind.
    1920DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind );
     21const ast::DeclWithType * isMainFor(
     22        const ast::FunctionDecl * func, ast::AggregateDecl::Aggregate kind );
    2023// Returns a pointer to the parameter if true, nullptr otherwise.
    2124
    2225/// Check if this function is a destructor for the given structure.
    2326bool isDestructorFor( FunctionDecl * func, StructDecl * type_decl );
     27bool isDestructorFor(
     28        const ast::FunctionDecl * func, const ast::StructDecl * type );
  • src/Concurrency/Keywords.cc

    ref3c383 rd672350  
    422422                        ;
    423423                else if ( auto param = isMainFor( decl, cast_target ) ) {
    424                         // This should never trigger.
    425                         assert( vtable_decl );
     424                        if ( !vtable_decl ) {
     425                                SemanticError( decl, context_error );
     426                        }
    426427                        // Should be safe because of isMainFor.
    427428                        StructInstType * struct_type = static_cast<StructInstType *>(
     
    12031204                                        //new TypeofType( noQualifiers, args.front()->clone() )
    12041205                                        new TypeofType( noQualifiers, new UntypedExpr(
    1205                                                         new NameExpr( "__get_type" ),
     1206                                                        new NameExpr( "__get_mutexstmt_lock_type" ),
    12061207                                                        { args.front()->clone() }
    12071208                                                )
     
    12151216                                map_range < std::list<Initializer*> > ( args, [](Expression * var ){
    12161217                                        return new SingleInit( new UntypedExpr(
    1217                                                         new NameExpr( "__get_ptr" ),
     1218                                                        new NameExpr( "__get_mutexstmt_lock_ptr" ),
    12181219                                                        { var }
    12191220                                        ) );
     
    12261227                TypeExpr * lock_type_expr = new TypeExpr(
    12271228                        new TypeofType( noQualifiers, new UntypedExpr(
    1228                                 new NameExpr( "__get_type" ),
     1229                                new NameExpr( "__get_mutexstmt_lock_type" ),
    12291230                                { args.front()->clone() }
    12301231                                )
  • src/Concurrency/KeywordsNew.cpp

    ref3c383 rd672350  
    1010// Created On       : Tue Nov 16  9:53:00 2021
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Dec  1 11:24:00 2021
    13 // Update Count     : 1
     12// Last Modified On : Fri Mar 11 10:40:00 2022
     13// Update Count     : 2
    1414//
     15
     16#include <iostream>
    1517
    1618#include "Concurrency/Keywords.h"
     
    1820#include "AST/Copy.hpp"
    1921#include "AST/Decl.hpp"
     22#include "AST/Expr.hpp"
    2023#include "AST/Pass.hpp"
    2124#include "AST/Stmt.hpp"
     25#include "AST/DeclReplacer.hpp"
    2226#include "AST/TranslationUnit.hpp"
    2327#include "CodeGen/OperatorTable.h"
     28#include "Common/Examine.h"
    2429#include "Common/utility.h"
     30#include "Common/UniqueName.h"
     31#include "ControlStruct/LabelGeneratorNew.hpp"
    2532#include "InitTweak/InitTweak.h"
     33#include "Virtual/Tables.h"
    2634
    2735namespace Concurrency {
     
    2937namespace {
    3038
    31 inline static bool isThread( const ast::DeclWithType * decl ) {
     39// --------------------------------------------------------------------------
     40// Loose Helper Functions:
     41
     42/// Detect threads constructed with the keyword thread.
     43bool isThread( const ast::DeclWithType * decl ) {
    3244        auto baseType = decl->get_type()->stripDeclarator();
    3345        auto instType = dynamic_cast<const ast::StructInstType *>( baseType );
     
    3648}
    3749
     50/// Get the virtual type id if given a type name.
     51std::string typeIdType( std::string const & exception_name ) {
     52        return exception_name.empty() ? std::string()
     53                : Virtual::typeIdType( exception_name );
     54}
     55
     56/// Get the vtable type name if given a type name.
     57std::string vtableTypeName( std::string const & exception_name ) {
     58        return exception_name.empty() ? std::string()
     59                : Virtual::vtableTypeName( exception_name );
     60}
     61
     62static ast::Type * mutate_under_references( ast::ptr<ast::Type>& type ) {
     63        ast::Type * mutType = type.get_and_mutate();
     64        for ( ast::ReferenceType * mutRef
     65                ; (mutRef = dynamic_cast<ast::ReferenceType *>( mutType ))
     66                ; mutType = mutRef->base.get_and_mutate() );
     67        return mutType;
     68}
     69
     70// Describe that it adds the generic parameters and the uses of the generic
     71// parameters on the function and first "this" argument.
     72ast::FunctionDecl * fixupGenerics(
     73                const ast::FunctionDecl * func, const ast::StructDecl * decl ) {
     74        const CodeLocation & location = decl->location;
     75        // We have to update both the declaration
     76        auto mutFunc = ast::mutate( func );
     77        auto mutType = mutFunc->type.get_and_mutate();
     78
     79        if ( decl->params.empty() ) {
     80                return mutFunc;
     81        }
     82
     83        assert( 0 != mutFunc->params.size() );
     84        assert( 0 != mutType->params.size() );
     85
     86        // Add the "forall" clause information.
     87        for ( const ast::ptr<ast::TypeDecl> & typeParam : decl->params ) {
     88                auto typeDecl = ast::deepCopy( typeParam );
     89                mutFunc->type_params.push_back( typeDecl );
     90                mutType->forall.push_back(
     91                        new ast::TypeInstType( typeDecl->name, typeDecl ) );
     92                for ( auto & assertion : typeDecl->assertions ) {
     93                        mutFunc->assertions.push_back( assertion );
     94                        mutType->assertions.emplace_back(
     95                                new ast::VariableExpr( location, assertion ) );
     96                }
     97                typeDecl->assertions.clear();
     98        }
     99
     100        // Even chain_mutate is not powerful enough for this:
     101        ast::ptr<ast::Type>& paramType = strict_dynamic_cast<ast::ObjectDecl *>(
     102                mutFunc->params[0].get_and_mutate() )->type;
     103        auto paramTypeInst = strict_dynamic_cast<ast::StructInstType *>(
     104                mutate_under_references( paramType ) );
     105        auto typeParamInst = strict_dynamic_cast<ast::StructInstType *>(
     106                mutate_under_references( mutType->params[0] ) );
     107
     108        for ( const ast::ptr<ast::TypeDecl> & typeDecl : mutFunc->type_params ) {
     109                paramTypeInst->params.push_back(
     110                        new ast::TypeExpr( location,
     111                                new ast::TypeInstType( typeDecl->name, typeDecl ) ) );
     112                typeParamInst->params.push_back(
     113                        new ast::TypeExpr( location,
     114                                new ast::TypeInstType( typeDecl->name, typeDecl ) ) );
     115        }
     116
     117        return mutFunc;
     118}
     119
    38120// --------------------------------------------------------------------------
    39 struct MutexKeyword final {
     121struct ConcurrentSueKeyword : public ast::WithDeclsToAdd<> {
     122        ConcurrentSueKeyword(
     123                std::string&& type_name, std::string&& field_name,
     124                std::string&& getter_name, std::string&& context_error,
     125                std::string&& exception_name,
     126                bool needs_main, ast::AggregateDecl::Aggregate cast_target
     127        ) :
     128                type_name( type_name ), field_name( field_name ),
     129                getter_name( getter_name ), context_error( context_error ),
     130                exception_name( exception_name ),
     131                typeid_name( typeIdType( exception_name ) ),
     132                vtable_name( vtableTypeName( exception_name ) ),
     133                needs_main( needs_main ), cast_target( cast_target )
     134        {}
     135
     136        virtual ~ConcurrentSueKeyword() {}
     137
     138        const ast::Decl * postvisit( const ast::StructDecl * decl );
     139        const ast::DeclWithType * postvisit( const ast::FunctionDecl * decl );
     140        const ast::Expr * postvisit( const ast::KeywordCastExpr * expr );
     141
     142        struct StructAndField {
     143                const ast::StructDecl * decl;
     144                const ast::ObjectDecl * field;
     145        };
     146
     147        const ast::StructDecl * handleStruct( const ast::StructDecl * );
     148        void handleMain( const ast::FunctionDecl *, const ast::StructInstType * );
     149        void addTypeId( const ast::StructDecl * );
     150        void addVtableForward( const ast::StructDecl * );
     151        const ast::FunctionDecl * forwardDeclare( const ast::StructDecl * );
     152        StructAndField addField( const ast::StructDecl * );
     153        void addGetRoutines( const ast::ObjectDecl *, const ast::FunctionDecl * );
     154        void addLockUnlockRoutines( const ast::StructDecl * );
     155
     156private:
     157        const std::string type_name;
     158        const std::string field_name;
     159        const std::string getter_name;
     160        const std::string context_error;
     161        const std::string exception_name;
     162        const std::string typeid_name;
     163        const std::string vtable_name;
     164        const bool needs_main;
     165        const ast::AggregateDecl::Aggregate cast_target;
     166
     167        const ast::StructDecl   * type_decl = nullptr;
     168        const ast::FunctionDecl * dtor_decl = nullptr;
     169        const ast::StructDecl * except_decl = nullptr;
     170        const ast::StructDecl * typeid_decl = nullptr;
     171        const ast::StructDecl * vtable_decl = nullptr;
     172
     173};
     174
     175// Handles thread type declarations:
     176//
     177// thread Mythread {                         struct MyThread {
     178//  int data;                                  int data;
     179//  a_struct_t more_data;                      a_struct_t more_data;
     180//                                =>             thread$ __thrd_d;
     181// };                                        };
     182//                                           static inline thread$ * get_thread( MyThread * this ) { return &this->__thrd_d; }
     183//
     184struct ThreadKeyword final : public ConcurrentSueKeyword {
     185        ThreadKeyword() : ConcurrentSueKeyword(
     186                "thread$",
     187                "__thrd",
     188                "get_thread",
     189                "thread keyword requires threads to be in scope, add #include <thread.hfa>\n",
     190                "ThreadCancelled",
     191                true,
     192                ast::AggregateDecl::Thread )
     193        {}
     194
     195        virtual ~ThreadKeyword() {}
     196};
     197
     198// Handles coroutine type declarations:
     199//
     200// coroutine MyCoroutine {                   struct MyCoroutine {
     201//  int data;                                  int data;
     202//  a_struct_t more_data;                      a_struct_t more_data;
     203//                                =>             coroutine$ __cor_d;
     204// };                                        };
     205//                                           static inline coroutine$ * get_coroutine( MyCoroutine * this ) { return &this->__cor_d; }
     206//
     207struct CoroutineKeyword final : public ConcurrentSueKeyword {
     208        CoroutineKeyword() : ConcurrentSueKeyword(
     209                "coroutine$",
     210                "__cor",
     211                "get_coroutine",
     212                "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n",
     213                "CoroutineCancelled",
     214                true,
     215                ast::AggregateDecl::Coroutine )
     216        {}
     217
     218        virtual ~CoroutineKeyword() {}
     219};
     220
     221// Handles monitor type declarations:
     222//
     223// monitor MyMonitor {                       struct MyMonitor {
     224//  int data;                                  int data;
     225//  a_struct_t more_data;                      a_struct_t more_data;
     226//                                =>             monitor$ __mon_d;
     227// };                                        };
     228//                                           static inline monitor$ * get_coroutine( MyMonitor * this ) {
     229//                                               return &this->__cor_d;
     230//                                           }
     231//                                           void lock(MyMonitor & this) {
     232//                                               lock(get_monitor(this));
     233//                                           }
     234//                                           void unlock(MyMonitor & this) {
     235//                                               unlock(get_monitor(this));
     236//                                           }
     237//
     238struct MonitorKeyword final : public ConcurrentSueKeyword {
     239        MonitorKeyword() : ConcurrentSueKeyword(
     240                "monitor$",
     241                "__mon",
     242                "get_monitor",
     243                "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n",
     244                "",
     245                false,
     246                ast::AggregateDecl::Monitor )
     247        {}
     248
     249        virtual ~MonitorKeyword() {}
     250};
     251
     252// Handles generator type declarations:
     253//
     254// generator MyGenerator {                   struct MyGenerator {
     255//  int data;                                  int data;
     256//  a_struct_t more_data;                      a_struct_t more_data;
     257//                                =>             int __generator_state;
     258// };                                        };
     259//
     260struct GeneratorKeyword final : public ConcurrentSueKeyword {
     261        GeneratorKeyword() : ConcurrentSueKeyword(
     262                "generator$",
     263                "__generator_state",
     264                "get_generator",
     265                "Unable to find builtin type generator$\n",
     266                "",
     267                true,
     268                ast::AggregateDecl::Generator )
     269        {}
     270
     271        virtual ~GeneratorKeyword() {}
     272};
     273
     274const ast::Decl * ConcurrentSueKeyword::postvisit(
     275                const ast::StructDecl * decl ) {
     276        if ( !decl->body ) {
     277                return decl;
     278        } else if ( cast_target == decl->kind ) {
     279                return handleStruct( decl );
     280        } else if ( type_name == decl->name ) {
     281                assert( !type_decl );
     282                type_decl = decl;
     283        } else if ( exception_name == decl->name ) {
     284                assert( !except_decl );
     285                except_decl = decl;
     286        } else if ( typeid_name == decl->name ) {
     287                assert( !typeid_decl );
     288                typeid_decl = decl;
     289        } else if ( vtable_name == decl->name ) {
     290                assert( !vtable_decl );
     291                vtable_decl = decl;
     292        }
     293        return decl;
     294}
     295
     296// Try to get the full definition, but raise an error on conflicts.
     297const ast::FunctionDecl * getDefinition(
     298                const ast::FunctionDecl * old_decl,
     299                const ast::FunctionDecl * new_decl ) {
     300        if ( !new_decl->stmts ) {
     301                return old_decl;
     302        } else if ( !old_decl->stmts ) {
     303                return new_decl;
     304        } else {
     305                assert( !old_decl->stmts || !new_decl->stmts );
     306                return nullptr;
     307        }
     308}
     309
     310const ast::DeclWithType * ConcurrentSueKeyword::postvisit(
     311                const ast::FunctionDecl * decl ) {
     312        if ( type_decl && isDestructorFor( decl, type_decl ) ) {
     313                // Check for forward declarations, try to get the full definition.
     314                dtor_decl = (dtor_decl) ? getDefinition( dtor_decl, decl ) : decl;
     315        } else if ( !vtable_name.empty() && decl->has_body() ) {
     316                if (const ast::DeclWithType * param = isMainFor( decl, cast_target )) {
     317                        if ( !vtable_decl ) {
     318                                SemanticError( decl, context_error );
     319                        }
     320                        // Should be safe because of isMainFor.
     321                        const ast::StructInstType * struct_type =
     322                                static_cast<const ast::StructInstType *>(
     323                                        static_cast<const ast::ReferenceType *>(
     324                                                param->get_type() )->base.get() );
     325
     326                        handleMain( decl, struct_type );
     327                }
     328        }
     329        return decl;
     330}
     331
     332const ast::Expr * ConcurrentSueKeyword::postvisit(
     333                const ast::KeywordCastExpr * expr ) {
     334        if ( cast_target == expr->target ) {
     335                // Convert `(thread &)ex` to `(thread$ &)*get_thread(ex)`, etc.
     336                if ( !type_decl || !dtor_decl ) {
     337                        SemanticError( expr, context_error );
     338                }
     339                assert( nullptr == expr->result );
     340                auto cast = ast::mutate( expr );
     341                cast->result = new ast::ReferenceType( new ast::StructInstType( type_decl ) );
     342                cast->concrete_target.field  = field_name;
     343                cast->concrete_target.getter = getter_name;
     344                return cast;
     345        }
     346        return expr;
     347}
     348
     349const ast::StructDecl * ConcurrentSueKeyword::handleStruct(
     350                const ast::StructDecl * decl ) {
     351        assert( decl->body );
     352
     353        if ( !type_decl || !dtor_decl ) {
     354                SemanticError( decl, context_error );
     355        }
     356
     357        if ( !exception_name.empty() ) {
     358                if( !typeid_decl || !vtable_decl ) {
     359                        SemanticError( decl, context_error );
     360                }
     361                addTypeId( decl );
     362                addVtableForward( decl );
     363        }
     364
     365        const ast::FunctionDecl * func = forwardDeclare( decl );
     366        StructAndField addFieldRet = addField( decl );
     367        decl = addFieldRet.decl;
     368        const ast::ObjectDecl * field = addFieldRet.field;
     369
     370        addGetRoutines( field, func );
     371        // Add routines to monitors for use by mutex stmt.
     372        if ( ast::AggregateDecl::Monitor == cast_target ) {
     373                addLockUnlockRoutines( decl );
     374        }
     375
     376        return decl;
     377}
     378
     379void ConcurrentSueKeyword::handleMain(
     380                const ast::FunctionDecl * decl, const ast::StructInstType * type ) {
     381        assert( vtable_decl );
     382        assert( except_decl );
     383
     384        const CodeLocation & location = decl->location;
     385
     386        std::vector<ast::ptr<ast::Expr>> poly_args = {
     387                new ast::TypeExpr( location, type ),
     388        };
     389        ast::ObjectDecl * vtable_object = Virtual::makeVtableInstance(
     390                location,
     391                "_default_vtable_object_declaration",
     392                new ast::StructInstType( vtable_decl, copy( poly_args ) ),
     393                type,
     394                nullptr
     395        );
     396        declsToAddAfter.push_back( vtable_object );
     397        declsToAddAfter.push_back(
     398                new ast::ObjectDecl(
     399                        location,
     400                        Virtual::concurrentDefaultVTableName(),
     401                        new ast::ReferenceType( vtable_object->type, ast::CV::Const ),
     402                        new ast::SingleInit( location,
     403                                new ast::VariableExpr( location, vtable_object ) ),
     404                        ast::Storage::Classes(),
     405                        ast::Linkage::Cforall
     406                )
     407        );
     408        declsToAddAfter.push_back( Virtual::makeGetExceptionFunction(
     409                location,
     410                vtable_object,
     411                new ast::StructInstType( except_decl, copy( poly_args ) )
     412        ) );
     413}
     414
     415void ConcurrentSueKeyword::addTypeId( const ast::StructDecl * decl ) {
     416        assert( typeid_decl );
     417        const CodeLocation & location = decl->location;
     418
     419        ast::StructInstType * typeid_type =
     420                new ast::StructInstType( typeid_decl, ast::CV::Const );
     421        typeid_type->params.push_back(
     422                new ast::TypeExpr( location, new ast::StructInstType( decl ) ) );
     423        declsToAddBefore.push_back(
     424                Virtual::makeTypeIdInstance( location, typeid_type ) );
     425        // If the typeid_type is going to be kept, the other reference will have
     426        // been made by now, but we also get to avoid extra mutates.
     427        ast::ptr<ast::StructInstType> typeid_cleanup = typeid_type;
     428}
     429
     430void ConcurrentSueKeyword::addVtableForward( const ast::StructDecl * decl ) {
     431        assert( vtable_decl );
     432        const CodeLocation& location = decl->location;
     433
     434        std::vector<ast::ptr<ast::Expr>> poly_args = {
     435                new ast::TypeExpr( location, new ast::StructInstType( decl ) ),
     436        };
     437        declsToAddBefore.push_back( Virtual::makeGetExceptionForward(
     438                location,
     439                new ast::StructInstType( vtable_decl, copy( poly_args ) ),
     440                new ast::StructInstType( except_decl, copy( poly_args ) )
     441        ) );
     442        ast::ObjectDecl * vtable_object = Virtual::makeVtableForward(
     443                location,
     444                "_default_vtable_object_declaration",
     445                new ast::StructInstType( vtable_decl, std::move( poly_args ) )
     446        );
     447        declsToAddBefore.push_back( vtable_object );
     448        declsToAddBefore.push_back(
     449                new ast::ObjectDecl(
     450                        location,
     451                        Virtual::concurrentDefaultVTableName(),
     452                        new ast::ReferenceType( vtable_object->type, ast::CV::Const ),
     453                        nullptr,
     454                        ast::Storage::Extern,
     455                        ast::Linkage::Cforall
     456                )
     457        );
     458}
     459
     460const ast::FunctionDecl * ConcurrentSueKeyword::forwardDeclare(
     461                const ast::StructDecl * decl ) {
     462        const CodeLocation & location = decl->location;
     463
     464        ast::StructDecl * forward = ast::deepCopy( decl );
     465        {
     466                // If removing members makes ref-count go to zero, do not free.
     467                ast::ptr<ast::StructDecl> forward_ptr = forward;
     468                forward->body = false;
     469                forward->members.clear();
     470                forward_ptr.release();
     471        }
     472
     473        ast::ObjectDecl * this_decl = new ast::ObjectDecl(
     474                location,
     475                "this",
     476                new ast::ReferenceType( new ast::StructInstType( decl ) ),
     477                nullptr,
     478                ast::Storage::Classes(),
     479                ast::Linkage::Cforall
     480        );
     481
     482        ast::ObjectDecl * ret_decl = new ast::ObjectDecl(
     483                location,
     484                "ret",
     485                new ast::PointerType( new ast::StructInstType( type_decl ) ),
     486                nullptr,
     487                ast::Storage::Classes(),
     488                ast::Linkage::Cforall
     489        );
     490
     491        ast::FunctionDecl * get_decl = new ast::FunctionDecl(
     492                location,
     493                getter_name,
     494                {}, // forall
     495                { this_decl }, // params
     496                { ret_decl }, // returns
     497                nullptr, // stmts
     498                ast::Storage::Static,
     499                ast::Linkage::Cforall,
     500                { new ast::Attribute( "const" ) },
     501                ast::Function::Inline
     502        );
     503        get_decl = fixupGenerics( get_decl, decl );
     504
     505        ast::FunctionDecl * main_decl = nullptr;
     506        if ( needs_main ) {
     507                // `this_decl` is copied here because the original was used above.
     508                main_decl = new ast::FunctionDecl(
     509                        location,
     510                        "main",
     511                        {},
     512                        { ast::deepCopy( this_decl ) },
     513                        {},
     514                        nullptr,
     515                        ast::Storage::Classes(),
     516                        ast::Linkage::Cforall
     517                );
     518                main_decl = fixupGenerics( main_decl, decl );
     519        }
     520
     521        declsToAddBefore.push_back( forward );
     522        if ( needs_main ) declsToAddBefore.push_back( main_decl );
     523        declsToAddBefore.push_back( get_decl );
     524
     525        return get_decl;
     526}
     527
     528ConcurrentSueKeyword::StructAndField ConcurrentSueKeyword::addField(
     529                const ast::StructDecl * decl ) {
     530        const CodeLocation & location = decl->location;
     531
     532        ast::ObjectDecl * field = new ast::ObjectDecl(
     533                location,
     534                field_name,
     535                new ast::StructInstType( type_decl ),
     536                nullptr,
     537                ast::Storage::Classes(),
     538                ast::Linkage::Cforall
     539        );
     540
     541        auto mutDecl = ast::mutate( decl );
     542        mutDecl->members.push_back( field );
     543
     544        return {mutDecl, field};
     545}
     546
     547void ConcurrentSueKeyword::addGetRoutines(
     548                const ast::ObjectDecl * field, const ast::FunctionDecl * forward ) {
     549        // Say it is generated at the "same" places as the forward declaration.
     550        const CodeLocation & location = forward->location;
     551
     552        const ast::DeclWithType * param = forward->params.front();
     553        ast::Stmt * stmt = new ast::ReturnStmt( location,
     554                new ast::AddressExpr( location,
     555                        new ast::MemberExpr( location,
     556                                field,
     557                                new ast::CastExpr( location,
     558                                        new ast::VariableExpr( location, param ),
     559                                        ast::deepCopy( param->get_type()->stripReferences() ),
     560                                        ast::ExplicitCast
     561                                )
     562                        )
     563                )
     564        );
     565
     566        ast::FunctionDecl * decl = ast::deepCopy( forward );
     567        decl->stmts = new ast::CompoundStmt( location, { stmt } );
     568        declsToAddAfter.push_back( decl );
     569}
     570
     571void ConcurrentSueKeyword::addLockUnlockRoutines(
     572                const ast::StructDecl * decl ) {
     573        // This should only be used on monitors.
     574        assert( ast::AggregateDecl::Monitor == cast_target );
     575
     576        const CodeLocation & location = decl->location;
     577
     578        // The parameter for both routines.
     579        ast::ObjectDecl * this_decl = new ast::ObjectDecl(
     580                location,
     581                "this",
     582                new ast::ReferenceType( new ast::StructInstType( decl ) ),
     583                nullptr,
     584                ast::Storage::Classes(),
     585                ast::Linkage::Cforall
     586        );
     587
     588        ast::FunctionDecl * lock_decl = new ast::FunctionDecl(
     589                location,
     590                "lock",
     591                { /* forall */ },
     592                {
     593                        // Copy the declaration of this.
     594                        ast::deepCopy( this_decl ),
     595                },
     596                { /* returns */ },
     597                nullptr,
     598                ast::Storage::Static,
     599                ast::Linkage::Cforall,
     600                { /* attributes */ },
     601                ast::Function::Inline
     602        );
     603        lock_decl = fixupGenerics( lock_decl, decl );
     604
     605        lock_decl->stmts = new ast::CompoundStmt( location, {
     606                new ast::ExprStmt( location,
     607                        new ast::UntypedExpr( location,
     608                                new ast::NameExpr( location, "lock" ),
     609                                {
     610                                        new ast::UntypedExpr( location,
     611                                                new ast::NameExpr( location, "get_monitor" ),
     612                                                { new ast::VariableExpr( location,
     613                                                        InitTweak::getParamThis( lock_decl ) ) }
     614                                        )
     615                                }
     616                        )
     617                )
     618        } );
     619
     620        ast::FunctionDecl * unlock_decl = new ast::FunctionDecl(
     621                location,
     622                "unlock",
     623                { /* forall */ },
     624                {
     625                        // Last use, consume the declaration of this.
     626                        this_decl,
     627                },
     628                { /* returns */ },
     629                nullptr,
     630                ast::Storage::Static,
     631                ast::Linkage::Cforall,
     632                { /* attributes */ },
     633                ast::Function::Inline
     634        );
     635        unlock_decl = fixupGenerics( unlock_decl, decl );
     636
     637        unlock_decl->stmts = new ast::CompoundStmt( location, {
     638                new ast::ExprStmt( location,
     639                        new ast::UntypedExpr( location,
     640                                new ast::NameExpr( location, "unlock" ),
     641                                {
     642                                        new ast::UntypedExpr( location,
     643                                                new ast::NameExpr( location, "get_monitor" ),
     644                                                { new ast::VariableExpr( location,
     645                                                        InitTweak::getParamThis( unlock_decl ) ) }
     646                                        )
     647                                }
     648                        )
     649                )
     650        } );
     651
     652        declsToAddAfter.push_back( lock_decl );
     653        declsToAddAfter.push_back( unlock_decl );
     654}
     655
     656
     657// --------------------------------------------------------------------------
     658struct SuspendKeyword final :
     659                public ast::WithStmtsToAdd<>, public ast::WithGuards {
     660        SuspendKeyword() = default;
     661        virtual ~SuspendKeyword() = default;
     662
     663        void previsit( const ast::FunctionDecl * );
     664        const ast::DeclWithType * postvisit( const ast::FunctionDecl * );
     665        const ast::Stmt * postvisit( const ast::SuspendStmt * );
     666
     667private:
     668        bool is_real_suspend( const ast::FunctionDecl * );
     669
     670        const ast::Stmt * make_generator_suspend( const ast::SuspendStmt * );
     671        const ast::Stmt * make_coroutine_suspend( const ast::SuspendStmt * );
     672
     673        struct LabelPair {
     674                ast::Label obj;
     675                int idx;
     676        };
     677
     678        LabelPair make_label(const ast::Stmt * stmt ) {
     679                labels.push_back( ControlStruct::newLabel( "generator", stmt ) );
     680                return { labels.back(), int(labels.size()) };
     681        }
     682
     683        const ast::DeclWithType * in_generator = nullptr;
     684        const ast::FunctionDecl * decl_suspend = nullptr;
     685        std::vector<ast::Label> labels;
     686};
     687
     688void SuspendKeyword::previsit( const ast::FunctionDecl * decl ) {
     689        GuardValue( in_generator ); in_generator = nullptr;
     690
     691        // If it is the real suspend, grab it if we don't have one already.
     692        if ( is_real_suspend( decl ) ) {
     693                decl_suspend = decl_suspend ? decl_suspend : decl;
     694                return;
     695        }
     696
     697        // Otherwise check if this is a generator main and, if so, handle it.
     698        auto param = isMainFor( decl, ast::AggregateDecl::Generator );
     699        if ( !param ) return;
     700
     701        if ( 0 != decl->returns.size() ) {
     702                SemanticError( decl->location, "Generator main must return void" );
     703        }
     704
     705        in_generator = param;
     706        GuardValue( labels ); labels.clear();
     707}
     708
     709const ast::DeclWithType * SuspendKeyword::postvisit(
     710                const ast::FunctionDecl * decl ) {
     711        // Only modify a full definition of a generator with states.
     712        if ( !decl->stmts || !in_generator || labels.empty() ) return decl;
     713
     714        const CodeLocation & location = decl->location;
     715
     716        // Create a new function body:
     717        // static void * __generator_labels[] = {&&s0, &&s1, ...};
     718        // void * __generator_label = __generator_labels[GEN.__generator_state];
     719        // goto * __generator_label;
     720        // s0: ;
     721        // OLD_BODY
     722
     723        // This is the null statement inserted right before the body.
     724        ast::NullStmt * noop = new ast::NullStmt( location );
     725        noop->labels.push_back( ControlStruct::newLabel( "generator", noop ) );
     726        const ast::Label & first_label = noop->labels.back();
     727
     728        // Add each label to the init, starting with the first label.
     729        std::vector<ast::ptr<ast::Init>> inits = {
     730                new ast::SingleInit( location,
     731                        new ast::LabelAddressExpr( location, copy( first_label ) ) ) };
     732        // Then go through all the stored labels, and clear the store.
     733        for ( auto && label : labels ) {
     734                inits.push_back( new ast::SingleInit( label.location,
     735                        new ast::LabelAddressExpr( label.location, std::move( label )
     736                        ) ) );
     737        }
     738        labels.clear();
     739        // Then construct the initializer itself.
     740        auto init = new ast::ListInit( location, std::move( inits ) );
     741
     742        ast::ObjectDecl * generatorLabels = new ast::ObjectDecl(
     743                location,
     744                "__generator_labels",
     745                new ast::ArrayType(
     746                        new ast::PointerType( new ast::VoidType() ),
     747                        nullptr,
     748                        ast::FixedLen,
     749                        ast::DynamicDim
     750                ),
     751                init,
     752                ast::Storage::Classes(),
     753                ast::Linkage::AutoGen
     754        );
     755
     756        ast::ObjectDecl * generatorLabel = new ast::ObjectDecl(
     757                location,
     758                "__generator_label",
     759                new ast::PointerType( new ast::VoidType() ),
     760                new ast::SingleInit( location,
     761                        new ast::UntypedExpr( location,
     762                                new ast::NameExpr( location, "?[?]" ),
     763                                {
     764                                        // TODO: Could be a variable expr.
     765                                        new ast::NameExpr( location, "__generator_labels" ),
     766                                        new ast::UntypedMemberExpr( location,
     767                                                new ast::NameExpr( location, "__generator_state" ),
     768                                                new ast::VariableExpr( location, in_generator )
     769                                        )
     770                                }
     771                        )
     772                ),
     773                ast::Storage::Classes(),
     774                ast::Linkage::AutoGen
     775        );
     776
     777        ast::BranchStmt * theGoTo = new ast::BranchStmt(
     778                location, new ast::VariableExpr( location, generatorLabel )
     779        );
     780
     781        // The noop goes here in order.
     782
     783        ast::CompoundStmt * body = new ast::CompoundStmt( location, {
     784                { new ast::DeclStmt( location, generatorLabels ) },
     785                { new ast::DeclStmt( location, generatorLabel ) },
     786                { theGoTo },
     787                { noop },
     788                { decl->stmts },
     789        } );
     790
     791        auto mutDecl = ast::mutate( decl );
     792        mutDecl->stmts = body;
     793        return mutDecl;
     794}
     795
     796const ast::Stmt * SuspendKeyword::postvisit( const ast::SuspendStmt * stmt ) {
     797        switch ( stmt->type ) {
     798        case ast::SuspendStmt::None:
     799                // Use the context to determain the implicit target.
     800                if ( in_generator ) {
     801                        return make_generator_suspend( stmt );
     802                } else {
     803                        return make_coroutine_suspend( stmt );
     804                }
     805        case ast::SuspendStmt::Coroutine:
     806                return make_coroutine_suspend( stmt );
     807        case ast::SuspendStmt::Generator:
     808                // Generator suspends must be directly in a generator.
     809                if ( !in_generator ) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type." );
     810                return make_generator_suspend( stmt );
     811        }
     812        assert( false );
     813        return stmt;
     814}
     815
     816/// Find the real/official suspend declaration.
     817bool SuspendKeyword::is_real_suspend( const ast::FunctionDecl * decl ) {
     818        return ( !decl->linkage.is_mangled
     819                && 0 == decl->params.size()
     820                && 0 == decl->returns.size()
     821                && "__cfactx_suspend" == decl->name );
     822}
     823
     824const ast::Stmt * SuspendKeyword::make_generator_suspend(
     825                const ast::SuspendStmt * stmt ) {
     826        assert( in_generator );
     827        // Target code is:
     828        //   GEN.__generator_state = X;
     829        //   THEN
     830        //   return;
     831        //   __gen_X:;
     832
     833        const CodeLocation & location = stmt->location;
     834
     835        LabelPair label = make_label( stmt );
     836
     837        // This is the context saving statement.
     838        stmtsToAddBefore.push_back( new ast::ExprStmt( location,
     839                new ast::UntypedExpr( location,
     840                        new ast::NameExpr( location, "?=?" ),
     841                        {
     842                                new ast::UntypedMemberExpr( location,
     843                                        new ast::NameExpr( location, "__generator_state" ),
     844                                        new ast::VariableExpr( location, in_generator )
     845                                ),
     846                                ast::ConstantExpr::from_int( location, label.idx ),
     847                        }
     848                )
     849        ) );
     850
     851        // The THEN component is conditional (return is not).
     852        if ( stmt->then ) {
     853                stmtsToAddBefore.push_back( stmt->then.get() );
     854        }
     855        stmtsToAddBefore.push_back( new ast::ReturnStmt( location, nullptr ) );
     856
     857        // The null statement replaces the old suspend statement.
     858        return new ast::NullStmt( location, { label.obj } );
     859}
     860
     861const ast::Stmt * SuspendKeyword::make_coroutine_suspend(
     862                const ast::SuspendStmt * stmt ) {
     863        // The only thing we need from the old statement is the location.
     864        const CodeLocation & location = stmt->location;
     865
     866        if ( !decl_suspend ) {
     867                SemanticError( location, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n" );
     868        }
     869        if ( stmt->then ) {
     870                SemanticError( location, "Compound statement following coroutines is not implemented." );
     871        }
     872
     873        return new ast::ExprStmt( location,
     874                new ast::UntypedExpr( location,
     875                        ast::VariableExpr::functionPointer( location, decl_suspend ) )
     876        );
     877}
     878
     879// --------------------------------------------------------------------------
     880struct MutexKeyword final : public ast::WithDeclsToAdd<> {
    40881        const ast::FunctionDecl * postvisit( const ast::FunctionDecl * decl );
    41882        void postvisit( const ast::StructDecl * decl );
     
    50891        ast::CompoundStmt * addStatements( const ast::CompoundStmt * body, const std::vector<ast::ptr<ast::Expr>> & args );
    51892        ast::CompoundStmt * addThreadDtorStatements( const ast::FunctionDecl* func, const ast::CompoundStmt * body, const std::vector<const ast::DeclWithType *> & args );
    52 
     893        ast::ExprStmt * genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param);
     894        ast::IfStmt * genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam );
    53895private:
    54896        const ast::StructDecl * monitor_decl = nullptr;
     
    59901
    60902        static ast::ptr<ast::Type> generic_func;
     903
     904        UniqueName mutex_func_namer = UniqueName("__lock_unlock_curr");
    61905};
    62906
     
    1601004
    1611005const ast::Stmt * MutexKeyword::postvisit( const ast::MutexStmt * stmt ) {
     1006        if ( !lock_guard_decl ) {
     1007                SemanticError( stmt->location, "mutex stmt requires a header, add #include <mutex_stmt.hfa>\n" );
     1008        }
    1621009        ast::CompoundStmt * body =
    1631010                        new ast::CompoundStmt( stmt->location, { stmt->stmt } );
    164         addStatements( body, stmt->mutexObjs );
    165         return body;
     1011       
     1012        return addStatements( body, stmt->mutexObjs );;
    1661013}
    1671014
     
    2511098                                {
    2521099                                        new ast::SingleInit( location,
    253                                                 new ast::AddressExpr(
     1100                                                new ast::AddressExpr( location,
    2541101                                                        new ast::VariableExpr( location, monitor ) ) ),
    2551102                                        new ast::SingleInit( location,
     
    3581205}
    3591206
     1207// generates a cast to the void ptr to the appropriate lock type and dereferences it before calling lock or unlock on it
     1208// used to undo the type erasure done by storing all the lock pointers as void
     1209ast::ExprStmt * MutexKeyword::genVirtLockUnlockExpr( const std::string & fnName, ast::ptr<ast::Expr> expr, const CodeLocation & location, ast::Expr * param ) {
     1210        return new ast::ExprStmt( location,
     1211                new ast::UntypedExpr( location,
     1212                        new ast::NameExpr( location, fnName ), {
     1213                                ast::UntypedExpr::createDeref(
     1214                                        location,
     1215                                        new ast::CastExpr( location,
     1216                                                param,
     1217                                                new ast::PointerType( new ast::TypeofType( new ast::UntypedExpr(
     1218                                                        expr->location,
     1219                                                        new ast::NameExpr( expr->location, "__get_mutexstmt_lock_type" ),
     1220                                                        { expr }
     1221                                                ) ) ),
     1222                                                ast::GeneratedFlag::ExplicitCast
     1223                                        )
     1224                                )
     1225                        }
     1226                )
     1227        );
     1228}
     1229
     1230ast::IfStmt * MutexKeyword::genTypeDiscrimLockUnlock( const std::string & fnName, const std::vector<ast::ptr<ast::Expr>> & args, const CodeLocation & location, ast::UntypedExpr * thisParam ) {
     1231        ast::IfStmt * outerLockIf = nullptr;
     1232        ast::IfStmt * lastLockIf = nullptr;
     1233
     1234        //adds an if/elif clause for each lock to assign type from void ptr based on ptr address
     1235        for ( long unsigned int i = 0; i < args.size(); i++ ) {
     1236               
     1237                ast::UntypedExpr * ifCond = new ast::UntypedExpr( location,
     1238                        new ast::NameExpr( location, "?==?" ), {
     1239                                ast::deepCopy( thisParam ),
     1240                                new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() ))
     1241                        }
     1242                );
     1243
     1244                ast::IfStmt * currLockIf = new ast::IfStmt(
     1245                        location,
     1246                        ifCond,
     1247                        genVirtLockUnlockExpr( fnName, args.at(i), location, ast::deepCopy( thisParam ) )
     1248                );
     1249               
     1250                if ( i == 0 ) {
     1251                        outerLockIf = currLockIf;
     1252                } else {
     1253                        // add ifstmt to else of previous stmt
     1254                        lastLockIf->else_ = currLockIf;
     1255                }
     1256
     1257                lastLockIf = currLockIf;
     1258        }
     1259        return outerLockIf;
     1260}
     1261
    3601262ast::CompoundStmt * MutexKeyword::addStatements(
    3611263                const ast::CompoundStmt * body,
    3621264                const std::vector<ast::ptr<ast::Expr>> & args ) {
    363         ast::CompoundStmt * mutBody = ast::mutate( body );
    3641265
    3651266        // Code is generated near the beginning of the compound statement.
    366         const CodeLocation & location = mutBody->location;
     1267        const CodeLocation & location = body->location;
     1268
     1269                // final body to return
     1270        ast::CompoundStmt * newBody = new ast::CompoundStmt( location );
     1271
     1272        // std::string lockFnName = mutex_func_namer.newName();
     1273        // std::string unlockFnName = mutex_func_namer.newName();
    3671274
    3681275        // Make pointer to the monitors.
     
    3721279                new ast::ArrayType(
    3731280                        new ast::PointerType(
    374                                 new ast::TypeofType(
    375                                         new ast::UntypedExpr(
    376                                                 location,
    377                                                 new ast::NameExpr( location, "__get_type" ),
    378                                                 { args.front() }
    379                                         )
    380                                 )
     1281                                new ast::VoidType()
    3811282                        ),
    3821283                        ast::ConstantExpr::from_ulong( location, args.size() ),
     
    3921293                                                new ast::UntypedExpr(
    3931294                                                        expr->location,
    394                                                         new ast::NameExpr( expr->location, "__get_ptr" ),
     1295                                                        new ast::NameExpr( expr->location, "__get_mutexstmt_lock_ptr" ),
    3951296                                                        { expr }
    3961297                                                )
     
    4051306        ast::StructInstType * lock_guard_struct =
    4061307                        new ast::StructInstType( lock_guard_decl );
    407         ast::TypeExpr * lock_type_expr = new ast::TypeExpr(
    408                 location,
    409                 new ast::TypeofType(
    410                         new ast::UntypedExpr(
    411                                 location,
    412                                 new ast::NameExpr( location, "__get_type" ),
    413                                 { args.front() }
    414                         )
    415                 )
    416         );
    417 
    418         lock_guard_struct->params.push_back( lock_type_expr );
    419 
    420         // In reverse order:
     1308
     1309        // use try stmts to lock and finally to unlock
     1310        ast::TryStmt * outerTry = nullptr;
     1311        ast::TryStmt * currentTry;
     1312        ast::CompoundStmt * lastBody = nullptr;
     1313
     1314        // adds a nested try stmt for each lock we are locking
     1315        for ( long unsigned int i = 0; i < args.size(); i++ ) {
     1316                ast::UntypedExpr * innerAccess = new ast::UntypedExpr(
     1317                        location,
     1318                        new ast::NameExpr( location,"?[?]" ), {
     1319                                new ast::NameExpr( location, "__monitors" ),
     1320                                ast::ConstantExpr::from_int( location, i )
     1321                        }
     1322                );
     1323
     1324                // make the try body
     1325                ast::CompoundStmt * currTryBody = new ast::CompoundStmt( location );
     1326                ast::IfStmt * lockCall = genTypeDiscrimLockUnlock( "lock", args, location, innerAccess );
     1327                currTryBody->push_back( lockCall );
     1328
     1329                // make the finally stmt
     1330                ast::CompoundStmt * currFinallyBody = new ast::CompoundStmt( location );
     1331                ast::IfStmt * unlockCall = genTypeDiscrimLockUnlock( "unlock", args, location, innerAccess );
     1332                currFinallyBody->push_back( unlockCall );
     1333
     1334                // construct the current try
     1335                currentTry = new ast::TryStmt(
     1336                        location,
     1337                        currTryBody,
     1338                        {},
     1339                        new ast::FinallyStmt( location, currFinallyBody )
     1340                );
     1341                if ( i == 0 ) outerTry = currentTry;
     1342                else {
     1343                        // pushback try into the body of the outer try
     1344                        lastBody->push_back( currentTry );
     1345                }
     1346                lastBody = currTryBody;
     1347        }
     1348
     1349        // push body into innermost try body
     1350        if ( lastBody != nullptr ) {
     1351                lastBody->push_back( body );
     1352                newBody->push_front( outerTry );
     1353        }       
     1354
    4211355        // monitor_guard_t __guard = { __monitors, # };
    422         mutBody->push_front(
     1356        newBody->push_front(
    4231357                new ast::DeclStmt(
    4241358                        location,
     
    4471381
    4481382        // monitor$ * __monitors[] = { get_monitor(a), get_monitor(b) };
    449         mutBody->push_front( new ast::DeclStmt( location, monitors ) );
    450 
    451         return mutBody;
     1383        newBody->push_front( new ast::DeclStmt( location, monitors ) );
     1384
     1385        // // The parameter for both __lock_curr/__unlock_curr routines.
     1386        // ast::ObjectDecl * this_decl = new ast::ObjectDecl(
     1387        //      location,
     1388        //      "this",
     1389        //      new ast::PointerType( new ast::VoidType() ),
     1390        //      nullptr,
     1391        //      {},
     1392        //      ast::Linkage::Cforall
     1393        // );
     1394
     1395        // ast::FunctionDecl * lock_decl = new ast::FunctionDecl(
     1396        //      location,
     1397        //      lockFnName,
     1398        //      { /* forall */ },
     1399        //      {
     1400        //              // Copy the declaration of this.
     1401        //              this_decl,
     1402        //      },
     1403        //      { /* returns */ },
     1404        //      nullptr,
     1405        //      0,
     1406        //      ast::Linkage::Cforall,
     1407        //      { /* attributes */ },
     1408        //      ast::Function::Inline
     1409        // );
     1410
     1411        // ast::FunctionDecl * unlock_decl = new ast::FunctionDecl(
     1412        //      location,
     1413        //      unlockFnName,
     1414        //      { /* forall */ },
     1415        //      {
     1416        //              // Copy the declaration of this.
     1417        //              ast::deepCopy( this_decl ),
     1418        //      },
     1419        //      { /* returns */ },
     1420        //      nullptr,
     1421        //      0,
     1422        //      ast::Linkage::Cforall,
     1423        //      { /* attributes */ },
     1424        //      ast::Function::Inline
     1425        // );
     1426
     1427        // ast::IfStmt * outerLockIf = nullptr;
     1428        // ast::IfStmt * outerUnlockIf = nullptr;
     1429        // ast::IfStmt * lastLockIf = nullptr;
     1430        // ast::IfStmt * lastUnlockIf = nullptr;
     1431
     1432        // //adds an if/elif clause for each lock to assign type from void ptr based on ptr address
     1433        // for ( long unsigned int i = 0; i < args.size(); i++ ) {
     1434        //      ast::VariableExpr * thisParam = new ast::VariableExpr( location, InitTweak::getParamThis( lock_decl ) );
     1435        //      ast::UntypedExpr * ifCond = new ast::UntypedExpr( location,
     1436        //              new ast::NameExpr( location, "?==?" ), {
     1437        //                      thisParam,
     1438        //                      new ast::CastExpr( location, new ast::AddressExpr( location, args.at(i) ), new ast::PointerType( new ast::VoidType() ))
     1439        //              }
     1440        //      );
     1441
     1442        //      ast::IfStmt * currLockIf = new ast::IfStmt(
     1443        //              location,
     1444        //              ast::deepCopy( ifCond ),
     1445        //              genVirtLockUnlockExpr( "lock", args.at(i), location, ast::deepCopy( thisParam ) )
     1446        //      );
     1447
     1448        //      ast::IfStmt * currUnlockIf = new ast::IfStmt(
     1449        //              location,
     1450        //              ifCond,
     1451        //              genVirtLockUnlockExpr( "unlock", args.at(i), location, ast::deepCopy( thisParam ) )
     1452        //      );
     1453               
     1454        //      if ( i == 0 ) {
     1455        //              outerLockIf = currLockIf;
     1456        //              outerUnlockIf = currUnlockIf;
     1457        //      } else {
     1458        //              // add ifstmt to else of previous stmt
     1459        //              lastLockIf->else_ = currLockIf;
     1460        //              lastUnlockIf->else_ = currUnlockIf;
     1461        //      }
     1462
     1463        //      lastLockIf = currLockIf;
     1464        //      lastUnlockIf = currUnlockIf;
     1465        // }
     1466       
     1467        // // add pointer typing if/elifs to body of routines
     1468        // lock_decl->stmts = new ast::CompoundStmt( location, { outerLockIf } );
     1469        // unlock_decl->stmts = new ast::CompoundStmt( location, { outerUnlockIf } );
     1470
     1471        // // add routines to scope
     1472        // declsToAddBefore.push_back( lock_decl );
     1473        // declsToAddBefore.push_back( unlock_decl );
     1474
     1475        // newBody->push_front(new ast::DeclStmt( location, lock_decl ));
     1476        // newBody->push_front(new ast::DeclStmt( location, unlock_decl ));
     1477
     1478        return newBody;
    4521479}
    4531480
     
    5641591
    5651592// --------------------------------------------------------------------------
     1593// Interface Functions:
    5661594
    5671595void implementKeywords( ast::TranslationUnit & translationUnit ) {
    568         (void)translationUnit;
    569         assertf(false, "Apply Keywords not implemented." );
     1596        ast::Pass<ThreadKeyword>::run( translationUnit );
     1597        ast::Pass<CoroutineKeyword>::run( translationUnit );
     1598        ast::Pass<MonitorKeyword>::run( translationUnit );
     1599        ast::Pass<GeneratorKeyword>::run( translationUnit );
     1600        ast::Pass<SuspendKeyword>::run( translationUnit );
    5701601}
    5711602
  • src/ControlStruct/ExceptTranslateNew.cpp

    ref3c383 rd672350  
    99// Author           : Andrew Beach
    1010// Created On       : Mon Nov  8 11:53:00 2021
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Jan 31 18:49:58 2022
    13 // Update Count     : 1
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Mar 11 17:51:00 2022
     13// Update Count     : 2
    1414//
    1515
     
    2727
    2828        typedef std::list<ast::CatchStmt*> CatchList;
    29 
    30         void split( CatchList& allHandlers, CatchList& terHandlers,
    31                                 CatchList& resHandlers ) {
    32                 while ( !allHandlers.empty() ) {
    33                         ast::CatchStmt * stmt = allHandlers.front();
    34                         allHandlers.pop_front();
    35                         if (stmt->kind == ast::ExceptionKind::Terminate) {
    36                                 terHandlers.push_back(stmt);
    37                         } else {
    38                                 resHandlers.push_back(stmt);
    39                         }
    40                 }
    41         }
    4229
    4330        void appendDeclStmt( ast::CompoundStmt * block, ast::DeclWithType * item ) {
     
    171158        ast::Stmt * create_resume_rethrow( const ast::ThrowStmt * throwStmt );
    172159
    173         // Types used in translation, make sure to use clone.
     160        // Types used in translation, first group are internal.
     161        ast::ObjectDecl * make_index_object( CodeLocation const & ) const;
     162        ast::ObjectDecl * make_exception_object( CodeLocation const & ) const;
     163        ast::ObjectDecl * make_bool_object( CodeLocation const & ) const;
     164        ast::ObjectDecl * make_voidptr_object( CodeLocation const & ) const;
     165        ast::ObjectDecl * make_unused_index_object( CodeLocation const & ) const;
    174166        // void (*function)();
    175         ast::FunctionDecl * try_func_t;
     167        ast::FunctionDecl * make_try_function( CodeLocation const & ) const;
    176168        // void (*function)(int, exception);
    177         ast::FunctionDecl * catch_func_t;
     169        ast::FunctionDecl * make_catch_function( CodeLocation const & ) const;
    178170        // int (*function)(exception);
    179         ast::FunctionDecl * match_func_t;
     171        ast::FunctionDecl * make_match_function( CodeLocation const & ) const;
    180172        // bool (*function)(exception);
    181         ast::FunctionDecl * handle_func_t;
     173        ast::FunctionDecl * make_handle_function( CodeLocation const & ) const;
    182174        // void (*function)(__attribute__((unused)) void *);
    183         ast::FunctionDecl * finally_func_t;
    184 
    185         ast::StructInstType * create_except_type() {
    186                 assert( except_decl );
    187                 return new ast::StructInstType( except_decl );
    188         }
    189         void init_func_types();
     175        ast::FunctionDecl * make_finally_function( CodeLocation const & ) const;
    190176
    191177public:
     
    199185};
    200186
    201 void TryMutatorCore::init_func_types() {
     187ast::ObjectDecl * TryMutatorCore::make_index_object(
     188                CodeLocation const & location ) const {
     189        return new ast::ObjectDecl(
     190                location,
     191                "__handler_index",
     192                new ast::BasicType(ast::BasicType::SignedInt),
     193                nullptr, //init
     194                ast::Storage::Classes{},
     195                ast::Linkage::Cforall
     196                );
     197}
     198
     199ast::ObjectDecl * TryMutatorCore::make_exception_object(
     200                CodeLocation const & location ) const {
    202201        assert( except_decl );
    203 
    204         ast::ObjectDecl index_obj(
    205                 {},
    206                 "__handler_index",
    207                 new ast::BasicType(ast::BasicType::SignedInt)
    208                 );
    209         ast::ObjectDecl exception_obj(
    210                 {},
     202        return new ast::ObjectDecl(
     203                location,
    211204                "__exception_inst",
    212205                new ast::PointerType(
    213206                        new ast::StructInstType( except_decl )
    214207                        ),
    215                 NULL
    216                 );
    217         ast::ObjectDecl bool_obj(
    218                 {},
     208                nullptr, //init
     209                ast::Storage::Classes{},
     210                ast::Linkage::Cforall
     211                );
     212}
     213
     214ast::ObjectDecl * TryMutatorCore::make_bool_object(
     215                CodeLocation const & location ) const {
     216        return new ast::ObjectDecl(
     217                location,
    219218                "__ret_bool",
    220219                new ast::BasicType( ast::BasicType::Bool ),
     
    225224                std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
    226225                );
    227         ast::ObjectDecl voidptr_obj(
    228                 {},
     226}
     227
     228ast::ObjectDecl * TryMutatorCore::make_voidptr_object(
     229                CodeLocation const & location ) const {
     230        return new ast::ObjectDecl(
     231                location,
    229232                "__hook",
    230233                new ast::PointerType(
     
    237240                std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
    238241                );
    239 
    240         ast::ObjectDecl unused_index_obj(
    241                 {},
     242}
     243
     244ast::ObjectDecl * TryMutatorCore::make_unused_index_object(
     245                CodeLocation const & location ) const {
     246        return new ast::ObjectDecl(
     247                location,
    242248                "__handler_index",
    243249                new ast::BasicType(ast::BasicType::SignedInt),
     
    248254                std::vector<ast::ptr<ast::Attribute>>{ new ast::Attribute( "unused" ) }
    249255        );
    250         //unused_index_obj->attributes.push_back( new Attribute( "unused" ) );
    251 
    252         try_func_t = new ast::FunctionDecl(
    253                 {},
     256}
     257
     258ast::FunctionDecl * TryMutatorCore::make_try_function(
     259                CodeLocation const & location ) const {
     260        return new ast::FunctionDecl(
     261                location,
    254262                "try",
    255263                {}, //forall
     
    260268                ast::Linkage::Cforall
    261269        );
    262 
    263         catch_func_t = new ast::FunctionDecl(
    264                 {},
     270}
     271
     272ast::FunctionDecl * TryMutatorCore::make_catch_function(
     273                CodeLocation const & location ) const {
     274        return new ast::FunctionDecl(
     275                location,
    265276                "catch",
    266277                {}, //forall
    267                 {ast::deepCopy(&index_obj), ast::deepCopy(&exception_obj)},//param
     278                { make_index_object( location ), make_exception_object( location ) },
    268279                {}, //return void
    269280                nullptr,
     
    271282                ast::Linkage::Cforall
    272283        );
    273 
    274         match_func_t = new ast::FunctionDecl(
    275                 {},
     284}
     285
     286ast::FunctionDecl * TryMutatorCore::make_match_function(
     287                CodeLocation const & location ) const {
     288        return new ast::FunctionDecl(
     289                location,
    276290                "match",
    277291                {}, //forall
    278                 {ast::deepCopy(&exception_obj)},
    279                 {ast::deepCopy(&unused_index_obj)},
     292                { make_exception_object( location ) },
     293                { make_unused_index_object( location ) },
    280294                nullptr,
    281295                ast::Storage::Classes{},
    282296                ast::Linkage::Cforall
    283297        );
    284 
    285         handle_func_t = new ast::FunctionDecl(
    286                 {},
     298}
     299
     300ast::FunctionDecl * TryMutatorCore::make_handle_function(
     301                CodeLocation const & location ) const {
     302        return new ast::FunctionDecl(
     303                location,
    287304                "handle",
    288305                {}, //forall
    289                 {ast::deepCopy(&exception_obj)},
    290                 {ast::deepCopy(&bool_obj)},
     306                { make_exception_object( location ) },
     307                { make_bool_object( location ) },
    291308                nullptr,
    292309                ast::Storage::Classes{},
    293310                ast::Linkage::Cforall
    294311        );
    295 
    296         finally_func_t = new ast::FunctionDecl(
    297                 {},
     312}
     313
     314ast::FunctionDecl * TryMutatorCore::make_finally_function(
     315                CodeLocation const & location ) const {
     316        return new ast::FunctionDecl(
     317                location,
    298318                "finally",
    299319                {}, //forall
    300                 {ast::deepCopy(&voidptr_obj)},
     320                { make_voidptr_object( location ) },
    301321                {}, //return void
    302322                nullptr,
     
    304324                ast::Linkage::Cforall
    305325        );
    306 
    307         //catch_func_t.get_parameters().push_back( index_obj.clone() );
    308         //catch_func_t.get_parameters().push_back( exception_obj.clone() );
    309         //match_func_t.get_returnVals().push_back( unused_index_obj );
    310         //match_func_t.get_parameters().push_back( exception_obj.clone() );
    311         //handle_func_t.get_returnVals().push_back( bool_obj.clone() );
    312         //handle_func_t.get_parameters().push_back( exception_obj.clone() );
    313         //finally_func_t.get_parameters().push_back( voidptr_obj.clone() );
    314326}
    315327
    316328// TryStmt Mutation Helpers
    317 
    318 /*
    319 ast::CompoundStmt * TryMutatorCore::take_try_block( ast::TryStmt *tryStmt ) {
    320         ast::CompoundStmt * block = tryStmt->body;
    321         tryStmt->body = nullptr;
    322         return block;
    323 }
    324 */
    325329
    326330ast::FunctionDecl * TryMutatorCore::create_try_wrapper(
    327331                const ast::CompoundStmt *body ) {
    328332
    329         ast::FunctionDecl * ret = ast::deepCopy(try_func_t);
     333        ast::FunctionDecl * ret = make_try_function( body->location );
    330334        ret->stmts = body;
    331335        return ret;
     
    339343        const CodeLocation loc = handlers.front()->location;
    340344
    341         ast::FunctionDecl * func_t = ast::deepCopy(catch_func_t);
     345        ast::FunctionDecl * func_t = make_catch_function( loc );
    342346        const ast::DeclWithType * index_obj = func_t->params.front();
    343347        const ast::DeclWithType * except_obj = func_t->params.back();
     
    386390                // handler->body = nullptr;
    387391
    388                 handler_wrappers.push_back( new ast::CaseStmt(loc, 
     392                handler_wrappers.push_back( new ast::CaseStmt(loc,
    389393                        ast::ConstantExpr::from_int(loc, index) ,
    390394                        { block, new ast::ReturnStmt( loc, nullptr ) }
     
    393397        // TODO: Some sort of meaningful error on default perhaps?
    394398
    395         /*
    396         std::list<Statement*> stmt_handlers;
    397         while ( !handler_wrappers.empty() ) {
    398                 stmt_handlers.push_back( handler_wrappers.front() );
    399                 handler_wrappers.pop_front();
    400         }
    401         */
    402 
    403         ast::SwitchStmt * handler_lookup = new ast::SwitchStmt(loc,
     399        ast::SwitchStmt * handler_lookup = new ast::SwitchStmt( loc,
    404400                new ast::VariableExpr( loc, index_obj ),
    405401                std::move(handler_wrappers)
    406402                );
    407         ast::CompoundStmt * body = new ast::CompoundStmt(loc,
    408                 {handler_lookup});
     403        ast::CompoundStmt * body = new ast::CompoundStmt( loc, {handler_lookup} );
    409404
    410405        func_t->stmts = body;
     
    433428
    434429        // Check for type match.
    435         ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc, 
     430        ast::VirtualCastExpr * vcex = new ast::VirtualCastExpr(loc,
    436431                new ast::VariableExpr(loc, except_obj ),
    437432                local_except->get_type()
     
    445440        }
    446441        // Construct the match condition.
    447         block->push_back( new ast::IfStmt(loc, 
     442        block->push_back( new ast::IfStmt(loc,
    448443                cond, modded_handler->body, nullptr ) );
    449444
    450         // xxx - how does this work in new ast
    451         //modded_handler->set_decl( nullptr );
    452         //modded_handler->set_cond( nullptr );
    453         //modded_handler->set_body( nullptr );
    454         //delete modded_handler;
    455445        return block;
    456446}
     
    467457        ast::CompoundStmt * body = new ast::CompoundStmt(loc);
    468458
    469         ast::FunctionDecl * func_t = ast::deepCopy(match_func_t);
     459        ast::FunctionDecl * func_t = make_match_function( loc );
    470460        const ast::DeclWithType * except_obj = func_t->params.back();
    471461
     
    490480        }
    491481
    492         body->push_back( new ast::ReturnStmt(loc, 
     482        body->push_back( new ast::ReturnStmt(loc,
    493483                ast::ConstantExpr::from_int( loc, 0 ) ));
    494484
     
    525515        ast::CompoundStmt * body = new ast::CompoundStmt(loc);
    526516
    527         ast::FunctionDecl * func_t = ast::deepCopy(handle_func_t);
     517        ast::FunctionDecl * func_t = make_handle_function( loc );
    528518        const ast::DeclWithType * except_obj = func_t->params.back();
    529519
     
    535525                ast::CompoundStmt * handling_code;
    536526                if (handler->body.as<ast::CompoundStmt>()) {
    537                         handling_code =
    538                         strict_dynamic_cast<ast::CompoundStmt*>( handler->body.get_and_mutate() );
     527                        handling_code = strict_dynamic_cast<ast::CompoundStmt*>(
     528                                handler->body.get_and_mutate() );
    539529                } else {
    540530                        handling_code = new ast::CompoundStmt(loc);
     
    600590        const ast::CompoundStmt * body = finally->body;
    601591
    602         ast::FunctionDecl * func_t = ast::deepCopy(finally_func_t);
     592        ast::FunctionDecl * func_t = make_finally_function( tryStmt->location );
    603593        func_t->stmts = body;
    604594
    605         // finally->set_block( nullptr );
    606         // delete finally;
    607595        tryStmt->finally = nullptr;
    608 
    609596
    610597        return func_t;
     
    617604
    618605        const CodeLocation loc = finally_wrapper->location;
    619         // Make Cleanup Attribute.
    620         /*
    621         std::list< ast::Attribute * > attributes;
    622         {
    623                 std::list<  > attr_params;
    624                 attr_params.push_back( nameOf( finally_wrapper ) );
    625                 attributes.push_back( new Attribute( "cleanup", attr_params ) );
    626         }
    627         */
    628 
    629606        return new ast::ObjectDecl(
    630607                loc,
     
    644621        // return false;
    645622        const CodeLocation loc = throwStmt->location;
    646         ast::Stmt * result = new ast::ReturnStmt(loc, 
     623        ast::Stmt * result = new ast::ReturnStmt(loc,
    647624                ast::ConstantExpr::from_bool( loc, false )
    648625                );
    649626        result->labels = throwStmt->labels;
    650         // delete throwStmt; done by postvisit
    651627        return result;
    652628}
     
    660636                assert( nullptr == except_decl );
    661637                except_decl = structDecl;
    662                 init_func_types();
    663638        } else if ( structDecl->name == "__cfaehm_try_resume_node" ) {
    664639                assert( nullptr == node_decl );
     
    706681                }
    707682        }
    708         // split( mutStmt->handlers,
    709         //              termination_handlers, resumption_handlers );
    710683
    711684        if ( resumption_handlers.size() ) {
  • src/InitTweak/FixGlobalInit.cc

    ref3c383 rd672350  
    113113                accept_all(translationUnit, fixer);
    114114
     115                // Say these magic declarations come at the end of the file.
     116                CodeLocation const & location = translationUnit.decls.back()->location;
     117
    115118                if ( !fixer.core.initStmts.empty() ) {
    116119                        std::vector<ast::ptr<ast::Expr>> ctorParams;
    117                         if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int({}, 200));
    118                         auto initFunction = new ast::FunctionDecl({}, "__global_init__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.initStmts)),
    119                                 ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("constructor", std::move(ctorParams))});
     120                        if (inLibrary) ctorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
     121                        auto initFunction = new ast::FunctionDecl(location,
     122                                "__global_init__", {}, {}, {},
     123                                new ast::CompoundStmt(location, std::move(fixer.core.initStmts)),
     124                                ast::Storage::Static, ast::Linkage::C,
     125                                {new ast::Attribute("constructor", std::move(ctorParams))});
    120126
    121127                        translationUnit.decls.emplace_back( initFunction );
     
    124130                if ( !fixer.core.destroyStmts.empty() ) {
    125131                        std::vector<ast::ptr<ast::Expr>> dtorParams;
    126                         if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int({}, 200));
    127                         auto destroyFunction = new ast::FunctionDecl({}, "__global_destroy__", {}, {}, {}, new ast::CompoundStmt({}, std::move(fixer.core.destroyStmts)),
    128                                 ast::Storage::Static, ast::Linkage::C, {new ast::Attribute("destructor", std::move(dtorParams))});
     132                        if (inLibrary) dtorParams.emplace_back(ast::ConstantExpr::from_int(location, 200));
     133                        auto destroyFunction = new ast::FunctionDecl( location,
     134                                "__global_destroy__", {}, {}, {},
     135                                new ast::CompoundStmt(location, std::move(fixer.core.destroyStmts)),
     136                                ast::Storage::Static, ast::Linkage::C,
     137                                {new ast::Attribute("destructor", std::move(dtorParams))});
    129138
    130139                        translationUnit.decls.emplace_back(destroyFunction);
  • src/InitTweak/FixInitNew.cpp

    ref3c383 rd672350  
    1616#include "CodeGen/GenType.h"           // for genPrettyType
    1717#include "CodeGen/OperatorTable.h"
     18#include "Common/CodeLocationTools.hpp"
    1819#include "Common/PassVisitor.h"        // for PassVisitor, WithStmtsToAdd
    1920#include "Common/SemanticError.h"      // for SemanticError
     
    8586        /// generate/resolve copy construction expressions for each, and generate/resolve destructors for both
    8687        /// arguments and return value temporaries
    87         struct ResolveCopyCtors final : public ast::WithGuards, public ast::WithStmtsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithVisitorRef<ResolveCopyCtors> {
     88        struct ResolveCopyCtors final : public ast::WithGuards, public ast::WithStmtsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithVisitorRef<ResolveCopyCtors>, public ast::WithConstTranslationUnit {
    8889                const ast::Expr * postvisit( const ast::ImplicitCopyCtorExpr * impCpCtorExpr );
    8990                const ast::StmtExpr * previsit( const ast::StmtExpr * stmtExpr );
     
    189190        /// for any member that is missing a corresponding ctor/dtor call.
    190191        /// error if a member is used before constructed
    191         struct GenStructMemberCalls final : public ast::WithGuards, public ast::WithShortCircuiting, public ast::WithSymbolTable, public ast::WithVisitorRef<GenStructMemberCalls> {
     192        struct GenStructMemberCalls final : public ast::WithGuards, public ast::WithShortCircuiting, public ast::WithSymbolTable, public ast::WithVisitorRef<GenStructMemberCalls>, public ast::WithConstTranslationUnit {
    192193                void previsit( const ast::FunctionDecl * funcDecl );
    193194                const ast::DeclWithType * postvisit( const ast::FunctionDecl * funcDecl );
     
    214215
    215216        /// expands ConstructorExpr nodes into comma expressions, using a temporary for the first argument
    216         struct FixCtorExprs final : public ast::WithDeclsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting {
     217        struct FixCtorExprs final : public ast::WithDeclsToAdd<>, public ast::WithSymbolTable, public ast::WithShortCircuiting, public ast::WithConstTranslationUnit {
    217218                const ast::Expr * postvisit( const ast::ConstructorExpr * ctorExpr );
    218219        };
     
    509510                // (VariableExpr and already resolved expression)
    510511                CP_CTOR_PRINT( std::cerr << "ResolvingCtorDtor " << untyped << std::endl; )
    511                 ast::ptr<ast::Expr> resolved = ResolvExpr::findVoidExpression(untyped, symtab);
     512                ast::ptr<ast::Expr> resolved = ResolvExpr::findVoidExpression(untyped, { symtab, transUnit().global } );
    512513                assert( resolved );
    513514                if ( resolved->env ) {
     
    553554                ast::ptr<ast::Expr> guard = mutArg;
    554555
    555                 ast::ptr<ast::ObjectDecl> tmp = new ast::ObjectDecl({}, "__tmp", mutResult, nullptr );
     556                ast::ptr<ast::ObjectDecl> tmp = new ast::ObjectDecl(loc, "__tmp", mutResult, nullptr );
    556557
    557558                // create and resolve copy constructor
     
    587588
    588589        ast::Expr * ResolveCopyCtors::destructRet( const ast::ObjectDecl * ret, const ast::Expr * arg ) {
     590                auto global = transUnit().global;
    589591                // TODO: refactor code for generating cleanup attribute, since it's common and reused in ~3-4 places
    590592                // check for existing cleanup attribute before adding another(?)
    591593                // need to add __Destructor for _tmp_cp variables as well
    592594
    593                 assertf( ast::dtorStruct, "Destructor generation requires __Destructor definition." );
    594                 assertf( ast::dtorStruct->members.size() == 2, "__Destructor definition does not have expected fields." );
    595                 assertf( ast::dtorStructDestroy, "Destructor generation requires __destroy_Destructor." );
     595                assertf( global.dtorStruct, "Destructor generation requires __Destructor definition." );
     596                assertf( global.dtorStruct->members.size() == 2, "__Destructor definition does not have expected fields." );
     597                assertf( global.dtorDestroy, "Destructor generation requires __destroy_Destructor." );
    596598
    597599                const CodeLocation loc = ret->location;
     
    610612                auto dtorFunc = getDtorFunc( ret, new ast::ExprStmt(loc, dtor ), stmtsToAddBefore );
    611613
    612                 auto dtorStructType = new ast::StructInstType(ast::dtorStruct);
     614                auto dtorStructType = new ast::StructInstType( global.dtorStruct );
    613615
    614616                // what does this do???
     
    622624                static UniqueName namer( "_ret_dtor" );
    623625                auto retDtor = new ast::ObjectDecl(loc, namer.newName(), dtorStructType, new ast::ListInit(loc, { new ast::SingleInit(loc, ast::ConstantExpr::null(loc) ), new ast::SingleInit(loc, new ast::CastExpr( new ast::VariableExpr(loc, dtorFunc ), dtorType ) ) } ) );
    624                 retDtor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, ast::dtorStructDestroy ) } ) );
     626                retDtor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr(loc, global.dtorDestroy ) } ) );
    625627                stmtsToAddBefore.push_back( new ast::DeclStmt(loc, retDtor ) );
    626628
    627629                if ( arg ) {
    628                         auto member = new ast::MemberExpr(loc, ast::dtorStruct->members.front().strict_as<ast::DeclWithType>(), new ast::VariableExpr(loc, retDtor ) );
     630                        auto member = new ast::MemberExpr(loc, global.dtorStruct->members.front().strict_as<ast::DeclWithType>(), new ast::VariableExpr(loc, retDtor ) );
    629631                        auto object = new ast::CastExpr( new ast::AddressExpr( new ast::VariableExpr(loc, ret ) ), new ast::PointerType(new ast::VoidType() ) );
    630632                        ast::Expr * assign = createBitwiseAssignment( member, object );
     
    799801        // to prevent warnings ('_unq0' may be used uninitialized in this function),
    800802        // insert an appropriate zero initializer for UniqueExpr temporaries.
    801         ast::Init * makeInit( const ast::Type * t ) {
     803        ast::Init * makeInit( const ast::Type * t, CodeLocation const & loc ) {
    802804                if ( auto inst = dynamic_cast< const ast::StructInstType * >( t ) ) {
    803805                        // initizer for empty struct must be empty
    804                         if ( inst->base->members.empty() ) return new ast::ListInit({}, {});
     806                        if ( inst->base->members.empty() ) {
     807                                return new ast::ListInit( loc, {} );
     808                        }
    805809                } else if ( auto inst = dynamic_cast< const ast::UnionInstType * >( t ) ) {
    806810                        // initizer for empty union must be empty
    807                         if ( inst->base->members.empty() ) return new ast::ListInit({}, {});
    808                 }
    809 
    810                 return new ast::ListInit( {}, { new ast::SingleInit( {}, ast::ConstantExpr::from_int({}, 0) ) } );
     811                        if ( inst->base->members.empty() ) {
     812                                return new ast::ListInit( loc, {} );
     813                        }
     814                }
     815
     816                return new ast::ListInit( loc, {
     817                        new ast::SingleInit( loc, ast::ConstantExpr::from_int( loc, 0 ) )
     818                } );
    811819        }
    812820
     
    832840                        } else {
    833841                                // expr isn't a call expr, so create a new temporary variable to use to hold the value of the unique expression
    834                                 mutExpr->object = new ast::ObjectDecl( mutExpr->location, toString("_unq", mutExpr->id), mutExpr->result, makeInit( mutExpr->result ) );
     842                                mutExpr->object = new ast::ObjectDecl( mutExpr->location, toString("_unq", mutExpr->id), mutExpr->result, makeInit( mutExpr->result, mutExpr->location ) );
    835843                                mutExpr->var = new ast::VariableExpr( mutExpr->location, mutExpr->object );
    836844                        }
     
    11721180                        auto guard = makeFuncGuard( [this]() { symtab.enterScope(); }, [this]() { symtab.leaveScope(); } );
    11731181                        symtab.addFunction( function );
     1182                        auto global = transUnit().global;
    11741183
    11751184                        // need to iterate through members in reverse in order for
     
    12171226
    12181227                                                        static UniqueName memberDtorNamer = { "__memberDtor" };
    1219                                                         assertf( ast::dtorStruct, "builtin __Destructor not found." );
    1220                                                         assertf( ast::dtorStructDestroy, "builtin __destroy_Destructor not found." );
     1228                                                        assertf( global.dtorStruct, "builtin __Destructor not found." );
     1229                                                        assertf( global.dtorDestroy, "builtin __destroy_Destructor not found." );
    12211230
    12221231                                                        ast::Expr * thisExpr = new ast::CastExpr( new ast::AddressExpr( new ast::VariableExpr(loc, thisParam ) ), new ast::PointerType( new ast::VoidType(), ast::CV::Qualifiers() ) );
     
    12281237                                                        auto dtorType = new ast::PointerType( dtorFtype );
    12291238
    1230                                                         auto destructor = new ast::ObjectDecl(loc, memberDtorNamer.newName(), new ast::StructInstType( ast::dtorStruct ), new ast::ListInit(loc, { new ast::SingleInit(loc, thisExpr ), new ast::SingleInit(loc, new ast::CastExpr( dtorExpr, dtorType ) ) } ) );
    1231                                                         destructor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr({}, ast::dtorStructDestroy ) } ) );
     1239                                                        auto destructor = new ast::ObjectDecl(loc, memberDtorNamer.newName(), new ast::StructInstType( global.dtorStruct ), new ast::ListInit(loc, { new ast::SingleInit(loc, thisExpr ), new ast::SingleInit(loc, new ast::CastExpr( dtorExpr, dtorType ) ) } ) );
     1240                                                        destructor->attributes.push_back( new ast::Attribute( "cleanup", { new ast::VariableExpr( loc, global.dtorDestroy ) } ) );
    12321241                                                        mutStmts->push_front( new ast::DeclStmt(loc, destructor ) );
    12331242                                                        mutStmts->kids.splice( mutStmts->kids.begin(), stmtsToAdd );
     
    13231332
    13241333        const ast::Expr * GenStructMemberCalls::postvisit( const ast::UntypedExpr * untypedExpr ) {
    1325                 // Expression * newExpr = untypedExpr;
    13261334                // xxx - functions returning ast::ptr seems wrong...
    1327                 auto res = ResolvExpr::findVoidExpression( untypedExpr, symtab );
    1328                 return res.release();
    1329                 // return newExpr;
     1335                auto res = ResolvExpr::findVoidExpression( untypedExpr, { symtab, transUnit().global } );
     1336                // Fix CodeLocation (at least until resolver is fixed).
     1337                auto fix = localFillCodeLocations( untypedExpr->location, res.release() );
     1338                return strict_dynamic_cast<const ast::Expr *>( fix );
    13301339        }
    13311340
     
    13611370
    13621371                // resolve assignment and dispose of new env
    1363                 auto resolved = ResolvExpr::findVoidExpression( assign, symtab );
     1372                auto resolved = ResolvExpr::findVoidExpression( assign, { symtab, transUnit().global } );
    13641373                auto mut = resolved.get_and_mutate();
    13651374                assertf(resolved.get() == mut, "newly resolved expression must be unique");
  • src/Parser/parser.yy

    ref3c383 rd672350  
    1010// Created On       : Sat Sep  1 20:22:55 2001
    1111// Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Feb 11 14:26:15 2022
    13 // Update Count     : 5174
     12// Last Modified On : Mon Mar 14 16:35:29 2022
     13// Update Count     : 5276
    1414//
    1515
     
    610610        // | RESUME '(' comma_expression ')' compound_statement
    611611        //      { SemanticError( yylloc, "Resume expression is currently unimplemented." ); $$ = nullptr; }
     612        | IDENTIFIER IDENTIFIER                                                         // syntax error
     613                {
     614                        SemanticError( yylloc, ::toString( "Adjacent identifiers are not meaningful in an expression. "
     615                                                                                           "Possible problem is identifier \"", *$1.str,
     616                                                                                           "\" is a misspelled typename or an incorrectly specified type name, "
     617                                                                                           "e.g., missing generic parameter or missing struct/union/enum before typename." ) );
     618                        $$ = nullptr;
     619                }
     620        | IDENTIFIER direct_type                                                        // syntax error
     621                {
     622                        SemanticError( yylloc, ::toString( "Identifier \"", *$1.str, "\" cannot appear before a type. "
     623                                                                                           "Possible problem is misspelled storage or CV qualifier." ) );
     624                        $$ = nullptr;
     625                }
    612626        ;
    613627
     
    638652                        // Historic, transitional: Disallow commas in subscripts.
    639653                        // Switching to this behaviour may help check if a C compatibilty case uses comma-exprs in subscripts.
    640                 // { SemanticError( yylloc, "New array subscript is currently unimplemented." ); $$ = nullptr; }
    641654                        // Current: Commas in subscripts make tuples.
    642655                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, new ExpressionNode( build_tuple( (ExpressionNode *)($3->set_last( $5 ) ) )) ) ); }
     
    647660                // equivalent to the old x[i,j].
    648661                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
     662        | constant '[' assignment_expression ']'                        // 3[a], 'a'[a], 3.5[a]
     663                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, $1, $3 ) ); }
     664        | string_literal '[' assignment_expression ']'          // "abc"[3], 3["abc"]
     665                { $$ = new ExpressionNode( build_binary_val( OperKinds::Index, new ExpressionNode( $1 ), $3 ) ); }
    649666        | postfix_expression '{' argument_expression_list_opt '}' // CFA, constructor call
    650667                {
     
    10521069        identifier_or_type_name ':' attribute_list_opt statement
    10531070                { $$ = $4->add_label( $1, $3 ); }
     1071        | identifier_or_type_name ':' attribute_list_opt error // syntax error
     1072                {
     1073                        SemanticError( yylloc, ::toString( "Label \"", *$1.str, "\" must be associated with a statement, "
     1074                                                                                           "where a declaration, case, or default is not a statement. "
     1075                                                                                           "Move the label or terminate with a semi-colon." ) );
     1076                        $$ = nullptr;
     1077                }
    10541078        ;
    10551079
     
    10861110        | statement_list_nodecl statement
    10871111                { assert( $1 ); $1->set_last( $2 ); $$ = $1; }
     1112        | statement_list_nodecl error                                           // syntax error
     1113                { SemanticError( yylloc, "Declarations only allowed at the start of the switch body, i.e., after the '{'." ); $$ = nullptr; }
    10881114        ;
    10891115
     
    10931119        | MUTEX '(' ')' comma_expression ';'
    10941120                { $$ = new StatementNode( build_mutex( nullptr, new StatementNode( build_expr( $4 ) ) ) ); }
    1095                 // { SemanticError( yylloc, "Mutex expression is currently unimplemented." ); $$ = nullptr; }
    10961121        ;
    10971122
     
    11131138                        $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    11141139                }
     1140        | SWITCH '(' comma_expression ')' '{' error '}'         // CFA, syntax error
     1141                { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; }
    11151142        | CHOOSE '(' comma_expression ')' case_clause           // CFA
    11161143                { $$ = new StatementNode( build_switch( false, $3, $5 ) ); }
     
    11201147                        $$ = $7 ? new StatementNode( build_compound( (StatementNode *)((new StatementNode( $7 ))->set_last( sw )) ) ) : sw;
    11211148                }
     1149        | CHOOSE '(' comma_expression ')' '{' error '}'         // CFA, syntax error
     1150                { SemanticError( yylloc, "Only declarations can appear before the list of case clauses." ); $$ = nullptr; }
    11221151        ;
    11231152
     
    11581187
    11591188case_label:                                                                                             // CFA
    1160         CASE case_value_list ':'                                        { $$ = $2; }
     1189        CASE error                                                                                      // syntax error
     1190                { SemanticError( yylloc, "Missing case list after case." ); $$ = nullptr; }
     1191        | CASE case_value_list ':'                                      { $$ = $2; }
     1192        | CASE case_value_list error                                            // syntax error
     1193                { SemanticError( yylloc, "Missing colon after case list." ); $$ = nullptr; }
    11611194        | DEFAULT ':'                                                           { $$ = new StatementNode( build_default() ); }
    11621195                // A semantic check is required to ensure only one default clause per switch/choose statement.
    1163         ;
    1164 
    1165 //label_list_opt:
    1166 //      // empty
    1167 //      | identifier_or_type_name ':'
    1168 //      | label_list_opt identifier_or_type_name ':'
    1169 //      ;
     1196        | DEFAULT error                                                                         //  syntax error
     1197                { SemanticError( yylloc, "Missing colon after default." ); $$ = nullptr; }
     1198        ;
    11701199
    11711200case_label_list:                                                                                // CFA
     
    14031432        | when_clause_opt ELSE statement
    14041433                { $$ = build_waitfor_timeout( nullptr, maybe_build_compound( $3 ), $1 ); }
    1405                 // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
    1406         | when_clause_opt timeout statement WOR ELSE statement
     1434        // "else" must be conditional after timeout or timeout is never triggered (i.e., it is meaningless)
     1435        | when_clause_opt timeout statement WOR ELSE statement // syntax error
    14071436                { SemanticError( yylloc, "else clause must be conditional after timeout or timeout never triggered." ); $$ = nullptr; }
    14081437        | when_clause_opt timeout statement WOR when_clause ELSE statement
  • src/ResolvExpr/CandidateFinder.cpp

    ref3c383 rd672350  
    1010// Created On       : Wed Jun 5 14:30:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  1 14:55:00 2019
    13 // Update Count     : 2
     12// Last Modified On : Wed Mar 16 11:58:00 2022
     13// Update Count     : 3
    1414//
    1515
     
    595595        /// Actually visits expressions to find their candidate interpretations
    596596        class Finder final : public ast::WithShortCircuiting {
     597                const ResolveContext & context;
    597598                const ast::SymbolTable & symtab;
    598599        public:
     
    618619
    619620                Finder( CandidateFinder & f )
    620                 : symtab( f.localSyms ), selfFinder( f ), candidates( f.candidates ), tenv( f.env ),
    621                   targetType( f.targetType ) {}
     621                : context( f.context ), symtab( context.symtab ), selfFinder( f ),
     622                  candidates( f.candidates ), tenv( f.env ), targetType( f.targetType ) {}
    622623
    623624                void previsit( const ast::Node * ) { visit_children = false; }
     
    872873                        Tuples::handleTupleAssignment( selfFinder, untypedExpr, argCandidates );
    873874
    874                         CandidateFinder funcFinder{ symtab, tenv };
     875                        CandidateFinder funcFinder( context, tenv );
    875876                        if (auto nameExpr = untypedExpr->func.as<ast::NameExpr>()) {
    876877                                auto kind = ast::SymbolTable::getSpecialFunctionKind(nameExpr->name);
     
    918919                        // find function operators
    919920                        ast::ptr< ast::Expr > opExpr = new ast::NameExpr{ untypedExpr->location, "?()" };
    920                         CandidateFinder opFinder{ symtab, tenv };
     921                        CandidateFinder opFinder( context, tenv );
    921922                        // okay if there aren't any function operations
    922923                        opFinder.find( opExpr, ResolvMode::withoutFailFast() );
     
    10591060
    10601061                void postvisit( const ast::AddressExpr * addressExpr ) {
    1061                         CandidateFinder finder{ symtab, tenv };
     1062                        CandidateFinder finder( context, tenv );
    10621063                        finder.find( addressExpr->arg );
    10631064
     
    10791080                        ast::ptr< ast::Type > toType = castExpr->result;
    10801081                        assert( toType );
    1081                         toType = resolveTypeof( toType, symtab );
     1082                        toType = resolveTypeof( toType, context );
    10821083                        // toType = SymTab::validateType( castExpr->location, toType, symtab );
    10831084                        toType = adjustExprType( toType, tenv, symtab );
    10841085
    1085                         CandidateFinder finder{ symtab, tenv, toType };
     1086                        CandidateFinder finder( context, tenv, toType );
    10861087                        finder.find( castExpr->arg, ResolvMode::withAdjustment() );
    10871088
     
    11361137                void postvisit( const ast::VirtualCastExpr * castExpr ) {
    11371138                        assertf( castExpr->result, "Implicit virtual cast targets not yet supported." );
    1138                         CandidateFinder finder{ symtab, tenv };
     1139                        CandidateFinder finder( context, tenv );
    11391140                        // don't prune here, all alternatives guaranteed to have same type
    11401141                        finder.find( castExpr->arg, ResolvMode::withoutPrune() );
     
    11531154                        auto target = inst->base.get();
    11541155
    1155                         CandidateFinder finder{ symtab, tenv };
     1156                        CandidateFinder finder( context, tenv );
    11561157
    11571158                        auto pick_alternatives = [target, this](CandidateList & found, bool expect_ref) {
     
    12021203
    12031204                void postvisit( const ast::UntypedMemberExpr * memberExpr ) {
    1204                         CandidateFinder aggFinder{ symtab, tenv };
     1205                        CandidateFinder aggFinder( context, tenv );
    12051206                        aggFinder.find( memberExpr->aggregate, ResolvMode::withAdjustment() );
    12061207                        for ( CandidateRef & agg : aggFinder.candidates ) {
     
    12871288                                addCandidate(
    12881289                                        new ast::SizeofExpr{
    1289                                                 sizeofExpr->location, resolveTypeof( sizeofExpr->type, symtab ) },
     1290                                                sizeofExpr->location, resolveTypeof( sizeofExpr->type, context ) },
    12901291                                        tenv );
    12911292                        } else {
    12921293                                // find all candidates for the argument to sizeof
    1293                                 CandidateFinder finder{ symtab, tenv };
     1294                                CandidateFinder finder( context, tenv );
    12941295                                finder.find( sizeofExpr->expr );
    12951296                                // find the lowest-cost candidate, otherwise ambiguous
     
    13111312                                addCandidate(
    13121313                                        new ast::AlignofExpr{
    1313                                                 alignofExpr->location, resolveTypeof( alignofExpr->type, symtab ) },
     1314                                                alignofExpr->location, resolveTypeof( alignofExpr->type, context ) },
    13141315                                        tenv );
    13151316                        } else {
    13161317                                // find all candidates for the argument to alignof
    1317                                 CandidateFinder finder{ symtab, tenv };
     1318                                CandidateFinder finder( context, tenv );
    13181319                                finder.find( alignofExpr->expr );
    13191320                                // find the lowest-cost candidate, otherwise ambiguous
     
    13541355
    13551356                void postvisit( const ast::LogicalExpr * logicalExpr ) {
    1356                         CandidateFinder finder1{ symtab, tenv };
     1357                        CandidateFinder finder1( context, tenv );
    13571358                        finder1.find( logicalExpr->arg1, ResolvMode::withAdjustment() );
    13581359                        if ( finder1.candidates.empty() ) return;
    13591360
    1360                         CandidateFinder finder2{ symtab, tenv };
     1361                        CandidateFinder finder2( context, tenv );
    13611362                        finder2.find( logicalExpr->arg2, ResolvMode::withAdjustment() );
    13621363                        if ( finder2.candidates.empty() ) return;
     
    13841385                void postvisit( const ast::ConditionalExpr * conditionalExpr ) {
    13851386                        // candidates for condition
    1386                         CandidateFinder finder1{ symtab, tenv };
     1387                        CandidateFinder finder1( context, tenv );
    13871388                        finder1.find( conditionalExpr->arg1, ResolvMode::withAdjustment() );
    13881389                        if ( finder1.candidates.empty() ) return;
    13891390
    13901391                        // candidates for true result
    1391                         CandidateFinder finder2{ symtab, tenv };
     1392                        CandidateFinder finder2( context, tenv );
    13921393                        finder2.find( conditionalExpr->arg2, ResolvMode::withAdjustment() );
    13931394                        if ( finder2.candidates.empty() ) return;
    13941395
    13951396                        // candidates for false result
    1396                         CandidateFinder finder3{ symtab, tenv };
     1397                        CandidateFinder finder3( context, tenv );
    13971398                        finder3.find( conditionalExpr->arg3, ResolvMode::withAdjustment() );
    13981399                        if ( finder3.candidates.empty() ) return;
     
    14451446                void postvisit( const ast::CommaExpr * commaExpr ) {
    14461447                        ast::TypeEnvironment env{ tenv };
    1447                         ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, symtab, env );
    1448 
    1449                         CandidateFinder finder2{ symtab, env };
     1448                        ast::ptr< ast::Expr > arg1 = resolveInVoidContext( commaExpr->arg1, context, env );
     1449
     1450                        CandidateFinder finder2( context, env );
    14501451                        finder2.find( commaExpr->arg2, ResolvMode::withAdjustment() );
    14511452
     
    14601461
    14611462                void postvisit( const ast::ConstructorExpr * ctorExpr ) {
    1462                         CandidateFinder finder{ symtab, tenv };
     1463                        CandidateFinder finder( context, tenv );
    14631464                        finder.find( ctorExpr->callExpr, ResolvMode::withoutPrune() );
    14641465                        for ( CandidateRef & r : finder.candidates ) {
     
    14691470                void postvisit( const ast::RangeExpr * rangeExpr ) {
    14701471                        // resolve low and high, accept candidates where low and high types unify
    1471                         CandidateFinder finder1{ symtab, tenv };
     1472                        CandidateFinder finder1( context, tenv );
    14721473                        finder1.find( rangeExpr->low, ResolvMode::withAdjustment() );
    14731474                        if ( finder1.candidates.empty() ) return;
    14741475
    1475                         CandidateFinder finder2{ symtab, tenv };
     1476                        CandidateFinder finder2( context, tenv );
    14761477                        finder2.find( rangeExpr->high, ResolvMode::withAdjustment() );
    14771478                        if ( finder2.candidates.empty() ) return;
     
    15491550
    15501551                void postvisit( const ast::UniqueExpr * unqExpr ) {
    1551                         CandidateFinder finder{ symtab, tenv };
     1552                        CandidateFinder finder( context, tenv );
    15521553                        finder.find( unqExpr->expr, ResolvMode::withAdjustment() );
    15531554                        for ( CandidateRef & r : finder.candidates ) {
     
    15581559
    15591560                void postvisit( const ast::StmtExpr * stmtExpr ) {
    1560                         addCandidate( resolveStmtExpr( stmtExpr, symtab ), tenv );
     1561                        addCandidate( resolveStmtExpr( stmtExpr, context ), tenv );
    15611562                }
    15621563
     
    15701571                        for ( const ast::InitAlternative & initAlt : initExpr->initAlts ) {
    15711572                                // calculate target type
    1572                                 const ast::Type * toType = resolveTypeof( initAlt.type, symtab );
     1573                                const ast::Type * toType = resolveTypeof( initAlt.type, context );
    15731574                                // toType = SymTab::validateType( initExpr->location, toType, symtab );
    15741575                                toType = adjustExprType( toType, tenv, symtab );
     
    15761577                                // types are not bound to the initialization type, since return type variables are
    15771578                                // only open for the duration of resolving the UntypedExpr.
    1578                                 CandidateFinder finder{ symtab, tenv, toType };
     1579                                CandidateFinder finder( context, tenv, toType );
    15791580                                finder.find( initExpr->expr, ResolvMode::withAdjustment() );
    15801581                                for ( CandidateRef & cand : finder.candidates ) {
     
    16931694                }
    16941695                else {
    1695                         satisfyAssertions(candidate, localSyms, satisfied, errors);
     1696                        satisfyAssertions(candidate, context.symtab, satisfied, errors);
    16961697                        needRecomputeKey = true;
    16971698                }
     
    18551856                        r->expr = ast::mutate_field(
    18561857                                r->expr.get(), &ast::Expr::result,
    1857                                 adjustExprType( r->expr->result, r->env, localSyms ) );
     1858                                adjustExprType( r->expr->result, r->env, context.symtab ) );
    18581859                }
    18591860        }
     
    18731874
    18741875        for ( const auto & x : xs ) {
    1875                 out.emplace_back( localSyms, env );
     1876                out.emplace_back( context, env );
    18761877                out.back().find( x, ResolvMode::withAdjustment() );
    18771878
  • src/ResolvExpr/CandidateFinder.hpp

    ref3c383 rd672350  
    1010// Created On       : Wed Jun 5 14:30:00 2019
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Oct  1  9:51:00 2019
    13 // Update Count     : 2
     12// Last Modified On : Wed Mar 16 15:22:00 2022
     13// Update Count     : 3
    1414//
    1515
     
    2525namespace ResolvExpr {
    2626
     27struct ResolveContext;
     28
    2729/// Data to perform expression resolution
    2830struct CandidateFinder {
    2931        CandidateList candidates;          ///< List of candidate resolutions
    30         const ast::SymbolTable & localSyms;   ///< Symbol table to lookup candidates
     32        const ResolveContext & context;  ///< Information about where the canditates are being found.
    3133        const ast::TypeEnvironment & env;  ///< Substitutions performed in this resolution
    3234        ast::ptr< ast::Type > targetType;  ///< Target type for resolution
     
    3436
    3537        CandidateFinder(
    36                 const ast::SymbolTable & syms, const ast::TypeEnvironment & env,
     38                const ResolveContext & context, const ast::TypeEnvironment & env,
    3739                const ast::Type * tt = nullptr )
    38         : candidates(), localSyms( syms ), env( env ), targetType( tt ) {}
     40        : candidates(), context( context ), env( env ), targetType( tt ) {}
    3941
    4042        /// Fill candidates with feasible resolutions for `expr`
  • src/ResolvExpr/CandidatePrinter.cpp

    ref3c383 rd672350  
    1010// Created On       : Tue Nov  9  9:54:00 2021
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Tue Nov  9 15:47:00 2021
    13 // Update Count     : 0
     12// Last Modified On : Wed Mar 16 13:56:00 2022
     13// Update Count     : 1
    1414//
    1515
     
    2222#include "AST/TranslationUnit.hpp"
    2323#include "ResolvExpr/CandidateFinder.hpp"
     24#include "ResolvExpr/Resolver.h"
    2425
    2526#include <iostream>
     
    2930namespace {
    3031
    31 class CandidatePrintCore : public ast::WithSymbolTable {
     32class CandidatePrintCore : public ast::WithSymbolTable,
     33                public ast::WithConstTranslationUnit {
    3234        std::ostream & os;
    3335public:
     
    3638        void postvisit( const ast::ExprStmt * stmt ) {
    3739                ast::TypeEnvironment env;
    38                 CandidateFinder finder( symtab, env );
     40                CandidateFinder finder( { symtab, transUnit().global }, env );
    3941                finder.find( stmt->expr, ResolvMode::withAdjustment() );
    4042                int count = 1;
  • src/ResolvExpr/ResolveTypeof.cc

    ref3c383 rd672350  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:12:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue May 19 16:49:04 2015
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Mar 16 16:09:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    2222#include "AST/Node.hpp"
    2323#include "AST/Pass.hpp"
     24#include "AST/TranslationUnit.hpp"
    2425#include "AST/Type.hpp"
    2526#include "AST/TypeEnvironment.hpp"
     
    119120namespace {
    120121        struct ResolveTypeof_new : public ast::WithShortCircuiting {
    121                 const ast::SymbolTable & localSymtab;
    122 
    123                 ResolveTypeof_new( const ast::SymbolTable & syms ) : localSymtab( syms ) {}
     122                const ResolveContext & context;
     123
     124                ResolveTypeof_new( const ResolveContext & context ) :
     125                        context( context ) {}
    124126
    125127                void previsit( const ast::TypeofType * ) { visit_children = false; }
     
    137139                                ast::TypeEnvironment dummy;
    138140                                ast::ptr< ast::Expr > newExpr =
    139                                         resolveInVoidContext( typeofType->expr, localSymtab, dummy );
     141                                        resolveInVoidContext( typeofType->expr, context, dummy );
    140142                                assert( newExpr->result && ! newExpr->result->isVoid() );
    141143                                newType = newExpr->result;
     
    161163} // anonymous namespace
    162164
    163 const ast::Type * resolveTypeof( const ast::Type * type , const ast::SymbolTable & symtab ) {
    164         ast::Pass< ResolveTypeof_new > mutator{ symtab };
     165const ast::Type * resolveTypeof( const ast::Type * type , const ResolveContext & context ) {
     166        ast::Pass< ResolveTypeof_new > mutator( context );
    165167        return type->accept( mutator );
    166168}
     
    168170struct FixArrayDimension {
    169171        // should not require a mutable symbol table - prevent pass template instantiation
    170         const ast::SymbolTable & _symtab;
    171         FixArrayDimension(const ast::SymbolTable & symtab): _symtab(symtab) {}
     172        const ResolveContext & context;
     173        FixArrayDimension(const ResolveContext & context) : context( context ) {}
    172174
    173175        const ast::ArrayType * previsit (const ast::ArrayType * arrayType) {
    174176                if (!arrayType->dimension) return arrayType;
    175177                auto mutType = mutate(arrayType);
    176                 ast::ptr<ast::Type> sizetype = ast::sizeType ? ast::sizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt);
    177                 mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, _symtab);
     178                auto globalSizeType = context.global.sizeType;
     179                ast::ptr<ast::Type> sizetype = globalSizeType ? globalSizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt);
     180                mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, context );
    178181
    179182                if (InitTweak::isConstExpr(mutType->dimension)) {
     
    187190};
    188191
    189 const ast::Type * fixArrayType( const ast::Type * type, const ast::SymbolTable & symtab) {
    190         ast::Pass<FixArrayDimension> visitor {symtab};
     192const ast::Type * fixArrayType( const ast::Type * type, const ResolveContext & context ) {
     193        ast::Pass<FixArrayDimension> visitor(context);
    191194        return type->accept(visitor);
    192195}
    193196
    194 const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab ) {
    195         if (!decl->isTypeFixed) { 
     197const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & context ) {
     198        if (!decl->isTypeFixed) {
    196199                auto mutDecl = mutate(decl);
    197                 auto resolvedType = resolveTypeof(decl->type, symtab);
    198                 resolvedType = fixArrayType(resolvedType, symtab);
     200                auto resolvedType = resolveTypeof(decl->type, context);
     201                resolvedType = fixArrayType(resolvedType, context);
    199202                mutDecl->type = resolvedType;
    200203
  • src/ResolvExpr/ResolveTypeof.h

    ref3c383 rd672350  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:14:53 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Sat Jul 22 09:38:35 2017
    13 // Update Count     : 3
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Mar 16 11:33:00 2022
     13// Update Count     : 4
    1414//
    1515
     
    2222namespace ast {
    2323        class Type;
    24         class SymbolTable;
    2524        class ObjectDecl;
    2625}
    2726
    2827namespace ResolvExpr {
     28        struct ResolveContext;
     29
    2930        Type *resolveTypeof( Type*, const SymTab::Indexer &indexer );
    30         const ast::Type * resolveTypeof( const ast::Type *, const ast::SymbolTable & );
    31         const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab );
     31        const ast::Type * resolveTypeof( const ast::Type *, const ResolveContext & );
     32        const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ResolveContext & );
    3233} // namespace ResolvExpr
    3334
  • src/ResolvExpr/Resolver.cc

    ref3c383 rd672350  
    99// Author           : Aaron B. Moss
    1010// Created On       : Sun May 17 12:17:01 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  1 16:27:14 2022
    13 // Update Count     : 245
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Fri Mar 18 10:41:00 2022
     13// Update Count     : 247
    1414//
    1515
     
    997997                /// Calls the CandidateFinder and finds the single best candidate
    998998                CandidateRef findUnfinishedKindExpression(
    999                         const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind,
     999                        const ast::Expr * untyped, const ResolveContext & context, const std::string & kind,
    10001000                        std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {}
    10011001                ) {
     
    10071007                        ++recursion_level;
    10081008                        ast::TypeEnvironment env;
    1009                         CandidateFinder finder{ symtab, env };
     1009                        CandidateFinder finder( context, env );
    10101010                        finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    10111011                        --recursion_level;
     
    11291129
    11301130        ast::ptr< ast::Expr > resolveInVoidContext(
    1131                 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env
     1131                const ast::Expr * expr, const ResolveContext & context,
     1132                ast::TypeEnvironment & env
    11321133        ) {
    11331134                assertf( expr, "expected a non-null expression" );
     
    11361137                ast::ptr< ast::CastExpr > untyped = new ast::CastExpr{ expr };
    11371138                CandidateRef choice = findUnfinishedKindExpression(
    1138                         untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() );
     1139                        untyped, context, "", anyCandidate, ResolvMode::withAdjustment() );
    11391140
    11401141                // a cast expression has either 0 or 1 interpretations (by language rules);
     
    11491150                /// context.
    11501151                ast::ptr< ast::Expr > findVoidExpression(
    1151                         const ast::Expr * untyped, const ast::SymbolTable & symtab
     1152                        const ast::Expr * untyped, const ResolveContext & context
    11521153                ) {
    11531154                        ast::TypeEnvironment env;
    1154                         ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env );
     1155                        ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, context, env );
    11551156                        finishExpr( newExpr, env, untyped->env );
    11561157                        return newExpr;
     
    11631164                /// lowest cost, returning the resolved version
    11641165                ast::ptr< ast::Expr > findKindExpression(
    1165                         const ast::Expr * untyped, const ast::SymbolTable & symtab,
     1166                        const ast::Expr * untyped, const ResolveContext & context,
    11661167                        std::function<bool(const Candidate &)> pred = anyCandidate,
    11671168                        const std::string & kind = "", ResolvMode mode = {}
     
    11691170                        if ( ! untyped ) return {};
    11701171                        CandidateRef choice =
    1171                                 findUnfinishedKindExpression( untyped, symtab, kind, pred, mode );
     1172                                findUnfinishedKindExpression( untyped, context, kind, pred, mode );
    11721173                        ResolvExpr::finishExpr( choice->expr, choice->env, untyped->env );
    11731174                        return std::move( choice->expr );
     
    11761177                /// Resolve `untyped` to the single expression whose candidate is the best match
    11771178                ast::ptr< ast::Expr > findSingleExpression(
    1178                         const ast::Expr * untyped, const ast::SymbolTable & symtab
     1179                        const ast::Expr * untyped, const ResolveContext & context
    11791180                ) {
    11801181                        Stats::ResolveTime::start( untyped );
    1181                         auto res = findKindExpression( untyped, symtab );
     1182                        auto res = findKindExpression( untyped, context );
    11821183                        Stats::ResolveTime::stop();
    11831184                        return res;
     
    11861187
    11871188        ast::ptr< ast::Expr > findSingleExpression(
    1188                 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
     1189                const ast::Expr * untyped, const ast::Type * type,
     1190                const ResolveContext & context
    11891191        ) {
    11901192                assert( untyped && type );
    11911193                ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
    1192                 ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
    1193                 removeExtraneousCast( newExpr, symtab );
     1194                ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, context );
     1195                removeExtraneousCast( newExpr, context.symtab );
    11941196                return newExpr;
    11951197        }
     
    12171219                /// Resolve `untyped` as an integral expression, returning the resolved version
    12181220                ast::ptr< ast::Expr > findIntegralExpression(
    1219                         const ast::Expr * untyped, const ast::SymbolTable & symtab
     1221                        const ast::Expr * untyped, const ResolveContext & context
    12201222                ) {
    1221                         return findKindExpression( untyped, symtab, hasIntegralType, "condition" );
     1223                        return findKindExpression( untyped, context, hasIntegralType, "condition" );
    12221224                }
    12231225
     
    12491251                // for work previously in GenInit
    12501252                static InitTweak::ManagedTypes_new managedTypes;
     1253                ResolveContext context;
    12511254
    12521255                bool inEnumDecl = false;
     
    12541257        public:
    12551258                static size_t traceId;
    1256                 Resolver_new() = default;
    1257                 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
     1259                Resolver_new( const ast::TranslationGlobal & global ) :
     1260                        context{ symtab, global } {}
     1261                Resolver_new( const ResolveContext & context ) :
     1262                        ast::WithSymbolTable{ context.symtab },
     1263                        context{ symtab, context.global } {}
    12581264
    12591265                const ast::FunctionDecl * previsit( const ast::FunctionDecl * );
     
    12721278                const ast::AsmStmt *         previsit( const ast::AsmStmt * );
    12731279                const ast::IfStmt *          previsit( const ast::IfStmt * );
    1274                 const ast::WhileDoStmt *       previsit( const ast::WhileDoStmt * );
     1280                const ast::WhileDoStmt *     previsit( const ast::WhileDoStmt * );
    12751281                const ast::ForStmt *         previsit( const ast::ForStmt * );
    12761282                const ast::SwitchStmt *      previsit( const ast::SwitchStmt * );
     
    12991305
    13001306        void resolve( ast::TranslationUnit& translationUnit ) {
    1301                 ast::Pass< Resolver_new >::run( translationUnit );
     1307                ast::Pass< Resolver_new >::run( translationUnit, translationUnit.global );
    13021308        }
    13031309
    13041310        ast::ptr< ast::Init > resolveCtorInit(
    1305                 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab
     1311                const ast::ConstructorInit * ctorInit, const ResolveContext & context
    13061312        ) {
    13071313                assert( ctorInit );
    1308                 ast::Pass< Resolver_new > resolver{ symtab };
     1314                ast::Pass< Resolver_new > resolver( context );
    13091315                return ctorInit->accept( resolver );
    13101316        }
    13111317
    13121318        const ast::Expr * resolveStmtExpr(
    1313                 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab
     1319                const ast::StmtExpr * stmtExpr, const ResolveContext & context
    13141320        ) {
    13151321                assert( stmtExpr );
    1316                 ast::Pass< Resolver_new > resolver{ symtab };
     1322                ast::Pass< Resolver_new > resolver( context );
    13171323                auto ret = mutate(stmtExpr->accept(resolver));
    13181324                strict_dynamic_cast< ast::StmtExpr * >( ret )->computeResult();
     
    13211327
    13221328        namespace {
    1323                 const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ast::SymbolTable & symtab) {
     1329                const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ResolveContext & context) {
    13241330                        std::string name = attr->normalizedName();
    13251331                        if (name == "constructor" || name == "destructor") {
    13261332                                if (attr->params.size() == 1) {
    13271333                                        auto arg = attr->params.front();
    1328                                         auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), symtab );
     1334                                        auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), context );
    13291335                                        auto result = eval(arg);
    13301336
     
    13691375
    13701376                        for (auto & attr: mutDecl->attributes) {
    1371                                 attr = handleAttribute(mutDecl->location, attr, symtab);
     1377                                attr = handleAttribute(mutDecl->location, attr, context );
    13721378                        }
    13731379
     
    13821388                        }
    13831389                        for (auto & asst : mutDecl->assertions) {
    1384                                 asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab);
     1390                                asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), context);
    13851391                                symtab.addId(asst);
    13861392                                mutType->assertions.emplace_back(new ast::VariableExpr(functionDecl->location, asst));
     
    13941400
    13951401                        for (auto & param : mutDecl->params) {
    1396                                 param = fixObjectType(param.strict_as<ast::ObjectDecl>(), symtab);
     1402                                param = fixObjectType(param.strict_as<ast::ObjectDecl>(), context);
    13971403                                symtab.addId(param);
    13981404                                paramTypes.emplace_back(param->get_type());
    13991405                        }
    14001406                        for (auto & ret : mutDecl->returns) {
    1401                                 ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), symtab);
     1407                                ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), context);
    14021408                                returnTypes.emplace_back(ret->get_type());
    14031409                        }
     
    14701476                        // enumerator initializers should not use the enum type to initialize, since the
    14711477                        // enum type is still incomplete at this point. Use `int` instead.
    1472                         objectDecl = fixObjectType(objectDecl, symtab);
     1478                        objectDecl = fixObjectType(objectDecl, context);
    14731479                        currentObject = ast::CurrentObject{
    14741480                                objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
     
    14761482                else {
    14771483                        if (!objectDecl->isTypeFixed) {
    1478                                 auto newDecl = fixObjectType(objectDecl, symtab);
     1484                                auto newDecl = fixObjectType(objectDecl, context);
    14791485                                auto mutDecl = mutate(newDecl);
    14801486
     
    15071513                        // nested type decls are hoisted already. no need to do anything
    15081514                        if (auto obj = member.as<ast::ObjectDecl>()) {
    1509                                 member = fixObjectType(obj, symtab);
     1515                                member = fixObjectType(obj, context);
    15101516                        }
    15111517                }
     
    15301536                return ast::mutate_field(
    15311537                        assertDecl, &ast::StaticAssertDecl::cond,
    1532                         findIntegralExpression( assertDecl->cond, symtab ) );
     1538                        findIntegralExpression( assertDecl->cond, context ) );
    15331539        }
    15341540
    15351541        template< typename PtrType >
    1536         const PtrType * handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) {
     1542        const PtrType * handlePtrType( const PtrType * type, const ResolveContext & context ) {
    15371543                if ( type->dimension ) {
    1538                         ast::ptr< ast::Type > sizeType = ast::sizeType;
     1544                        ast::ptr< ast::Type > sizeType = context.global.sizeType;
    15391545                        ast::mutate_field(
    15401546                                type, &PtrType::dimension,
    1541                                 findSingleExpression( type->dimension, sizeType, symtab ) );
     1547                                findSingleExpression( type->dimension, sizeType, context ) );
    15421548                }
    15431549                return type;
     
    15451551
    15461552        const ast::ArrayType * Resolver_new::previsit( const ast::ArrayType * at ) {
    1547                 return handlePtrType( at, symtab );
     1553                return handlePtrType( at, context );
    15481554        }
    15491555
    15501556        const ast::PointerType * Resolver_new::previsit( const ast::PointerType * pt ) {
    1551                 return handlePtrType( pt, symtab );
     1557                return handlePtrType( pt, context );
    15521558        }
    15531559
     
    15571563
    15581564                return ast::mutate_field(
    1559                         exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) );
     1565                        exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, context ) );
    15601566        }
    15611567
     
    15641570
    15651571                asmExpr = ast::mutate_field(
    1566                         asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) );
     1572                        asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, context ) );
    15671573
    15681574                return asmExpr;
     
    15781584        const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) {
    15791585                return ast::mutate_field(
    1580                         ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) );
     1586                        ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, context ) );
    15811587        }
    15821588
    15831589        const ast::WhileDoStmt * Resolver_new::previsit( const ast::WhileDoStmt * whileDoStmt ) {
    15841590                return ast::mutate_field(
    1585                         whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, symtab ) );
     1591                        whileDoStmt, &ast::WhileDoStmt::cond, findIntegralExpression( whileDoStmt->cond, context ) );
    15861592        }
    15871593
     
    15891595                if ( forStmt->cond ) {
    15901596                        forStmt = ast::mutate_field(
    1591                                 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) );
     1597                                forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, context ) );
    15921598                }
    15931599
    15941600                if ( forStmt->inc ) {
    15951601                        forStmt = ast::mutate_field(
    1596                                 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) );
     1602                                forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, context ) );
    15971603                }
    15981604
     
    16041610                switchStmt = ast::mutate_field(
    16051611                        switchStmt, &ast::SwitchStmt::cond,
    1606                         findIntegralExpression( switchStmt->cond, symtab ) );
     1612                        findIntegralExpression( switchStmt->cond, context ) );
    16071613                currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result };
    16081614                return switchStmt;
     
    16171623                        ast::ptr< ast::Expr > untyped =
    16181624                                new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type };
    1619                         ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, symtab );
     1625                        ast::ptr< ast::Expr > newExpr = findSingleExpression( untyped, context );
    16201626
    16211627                        // case condition cannot have a cast in C, so it must be removed here, regardless of
     
    16381644                        branchStmt = ast::mutate_field(
    16391645                                branchStmt, &ast::BranchStmt::computedTarget,
    1640                                 findSingleExpression( branchStmt->computedTarget, target, symtab ) );
     1646                                findSingleExpression( branchStmt->computedTarget, target, context ) );
    16411647                }
    16421648                return branchStmt;
     
    16481654                        returnStmt = ast::mutate_field(
    16491655                                returnStmt, &ast::ReturnStmt::expr,
    1650                                 findSingleExpression( returnStmt->expr, functionReturn, symtab ) );
     1656                                findSingleExpression( returnStmt->expr, functionReturn, context ) );
    16511657                }
    16521658                return returnStmt;
     
    16631669                        throwStmt = ast::mutate_field(
    16641670                                throwStmt, &ast::ThrowStmt::expr,
    1665                                 findSingleExpression( throwStmt->expr, exceptType, symtab ) );
     1671                                findSingleExpression( throwStmt->expr, exceptType, context ) );
    16661672                }
    16671673                return throwStmt;
     
    17071713
    17081714                        ast::TypeEnvironment env;
    1709                         CandidateFinder funcFinder{ symtab, env };
     1715                        CandidateFinder funcFinder( context, env );
    17101716
    17111717                        // Find all candidates for a function in canonical form
     
    19211927                                );
    19221928
    1923                                 clause2.target.args.emplace_back( findSingleExpression( init, symtab ) );
     1929                                clause2.target.args.emplace_back( findSingleExpression( init, context ) );
    19241930                        }
    19251931
    19261932                        // Resolve the conditions as if it were an IfStmt, statements normally
    1927                         clause2.cond = findSingleExpression( clause.cond, symtab );
     1933                        clause2.cond = findSingleExpression( clause.cond, context );
    19281934                        clause2.stmt = clause.stmt->accept( *visitor );
    19291935
     
    19401946                        ast::ptr< ast::Type > target =
    19411947                                new ast::BasicType{ ast::BasicType::LongLongUnsignedInt };
    1942                         timeout2.time = findSingleExpression( stmt->timeout.time, target, symtab );
    1943                         timeout2.cond = findSingleExpression( stmt->timeout.cond, symtab );
     1948                        timeout2.time = findSingleExpression( stmt->timeout.time, target, context );
     1949                        timeout2.cond = findSingleExpression( stmt->timeout.cond, context );
    19441950                        timeout2.stmt = stmt->timeout.stmt->accept( *visitor );
    19451951
     
    19541960                        ast::WaitForStmt::OrElse orElse2;
    19551961
    1956                         orElse2.cond = findSingleExpression( stmt->orElse.cond, symtab );
     1962                        orElse2.cond = findSingleExpression( stmt->orElse.cond, context );
    19571963                        orElse2.stmt = stmt->orElse.stmt->accept( *visitor );
    19581964
     
    19751981                for (auto & expr : exprs) {
    19761982                        // only struct- and union-typed expressions are viable candidates
    1977                         expr = findKindExpression( expr, symtab, structOrUnion, "with expression" );
     1983                        expr = findKindExpression( expr, context, structOrUnion, "with expression" );
    19781984
    19791985                        // if with expression might be impure, create a temporary so that it is evaluated once
     
    20012007                ast::ptr< ast::Expr > untyped = new ast::UntypedInitExpr{
    20022008                        singleInit->location, singleInit->value, currentObject.getOptions() };
    2003                 ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, symtab );
     2009                ast::ptr<ast::Expr> newExpr = findSingleExpression( untyped, context );
    20042010                const ast::InitExpr * initExpr = newExpr.strict_as< ast::InitExpr >();
    20052011
  • src/ResolvExpr/Resolver.h

    ref3c383 rd672350  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 12:18:34 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Mon Feb 18 20:40:38 2019
    13 // Update Count     : 4
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Mar 16 11:32:00 2022
     13// Update Count     : 5
    1414//
    1515
     
    2323class Declaration;
    2424class Expression;
     25class DeletedExpr;
    2526class StmtExpr;
     27class Type;
    2628namespace SymTab {
    2729        class Indexer;
     
    3537        class StmtExpr;
    3638        class SymbolTable;
     39        class TranslationGlobal;
    3740        class TranslationUnit;
    3841        class Type;
     
    5558        void resolveWithExprs( std::list< Declaration * > & translationUnit );
    5659
     60        /// Helper Type: Passes around information between various sub-calls.
     61        struct ResolveContext {
     62                const ast::SymbolTable & symtab;
     63                const ast::TranslationGlobal & global;
     64        };
     65
    5766        /// Checks types and binds syntactic constructs to typed representations
    5867        void resolve( ast::TranslationUnit& translationUnit );
     
    6271        /// context.
    6372        ast::ptr< ast::Expr > resolveInVoidContext(
    64                 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env );
     73                const ast::Expr * expr, const ResolveContext &, ast::TypeEnvironment & env );
    6574        /// Resolve `untyped` to the single expression whose candidate is the best match for the
    6675        /// given type.
    6776        ast::ptr< ast::Expr > findSingleExpression(
    68                 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab );
     77                const ast::Expr * untyped, const ast::Type * type, const ResolveContext & );
    6978        ast::ptr< ast::Expr > findVoidExpression(
    70                 const ast::Expr * untyped, const ast::SymbolTable & symtab);
     79                const ast::Expr * untyped, const ResolveContext & );
    7180        /// Resolves a constructor init expression
    7281        ast::ptr< ast::Init > resolveCtorInit(
    73                 const ast::ConstructorInit * ctorInit, const ast::SymbolTable & symtab );
     82                const ast::ConstructorInit * ctorInit, const ResolveContext & context );
    7483        /// Resolves a statement expression
    7584        const ast::Expr * resolveStmtExpr(
    76                 const ast::StmtExpr * stmtExpr, const ast::SymbolTable & symtab );
     85                const ast::StmtExpr * stmtExpr, const ResolveContext & context );
    7786} // namespace ResolvExpr
    7887
  • src/ResolvExpr/Unify.cc

    ref3c383 rd672350  
    943943                        // check that the other type is compatible and named the same
    944944                        auto otherInst = dynamic_cast< const XInstType * >( other );
    945                         this->result = otherInst && inst->name == otherInst->name;
     945                        if (otherInst && inst->name == otherInst->name) this->result = otherInst;
    946946                        return otherInst;
    947947                }
  • src/SymTab/Validate.cc

    ref3c383 rd672350  
    194194        };
    195195
     196        // These structs are the sub-sub-passes of ForallPointerDecay_old.
     197
     198        struct TraitExpander_old final {
     199                void previsit( FunctionType * );
     200                void previsit( StructDecl * );
     201                void previsit( UnionDecl * );
     202        };
     203
     204        struct AssertionFixer_old final {
     205                void previsit( FunctionType * );
     206                void previsit( StructDecl * );
     207                void previsit( UnionDecl * );
     208        };
     209
     210        struct CheckOperatorTypes_old final {
     211                void previsit( ObjectDecl * );
     212        };
     213
     214        struct FixUniqueIds_old final {
     215                void previsit( DeclarationWithType * );
     216        };
     217
    196218        struct ReturnChecker : public WithGuards {
    197219                /// Checks that return statements return nothing if their return type is void
     
    386408
    387409        void validate_D( std::list< Declaration * > & translationUnit ) {
    388                 PassVisitor<ForallPointerDecay_old> fpd;
    389410                {
    390411                        Stats::Heap::newPass("validate-D");
     
    394415                        });
    395416                        Stats::Time::TimeBlock("Forall Pointer Decay", [&]() {
    396                                 acceptAll( translationUnit, fpd ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution
     417                                decayForallPointers( translationUnit ); // must happen before autogenerateRoutines, after Concurrency::applyKeywords because uniqueIds must be set on declaration before resolution
    397418                        });
    398419                        Stats::Time::TimeBlock("Hoist Control Declarations", [&]() {
     
    454475
    455476        void decayForallPointers( std::list< Declaration * > & translationUnit ) {
    456                 PassVisitor<ForallPointerDecay_old> fpd;
    457                 acceptAll( translationUnit, fpd );
     477                PassVisitor<TraitExpander_old> te;
     478                acceptAll( translationUnit, te );
     479                PassVisitor<AssertionFixer_old> af;
     480                acceptAll( translationUnit, af );
     481                PassVisitor<CheckOperatorTypes_old> cot;
     482                acceptAll( translationUnit, cot );
     483                PassVisitor<FixUniqueIds_old> fui;
     484                acceptAll( translationUnit, fui );
     485        }
     486
     487        void decayForallPointersA( std::list< Declaration * > & translationUnit ) {
     488                PassVisitor<TraitExpander_old> te;
     489                acceptAll( translationUnit, te );
     490        }
     491        void decayForallPointersB( std::list< Declaration * > & translationUnit ) {
     492                PassVisitor<AssertionFixer_old> af;
     493                acceptAll( translationUnit, af );
     494        }
     495        void decayForallPointersC( std::list< Declaration * > & translationUnit ) {
     496                PassVisitor<CheckOperatorTypes_old> cot;
     497                acceptAll( translationUnit, cot );
     498        }
     499        void decayForallPointersD( std::list< Declaration * > & translationUnit ) {
     500                PassVisitor<FixUniqueIds_old> fui;
     501                acceptAll( translationUnit, fui );
    458502        }
    459503
     
    470514                PassVisitor<EnumAndPointerDecay_old> epc;
    471515                PassVisitor<LinkReferenceToTypes_old> lrt( indexer );
    472                 PassVisitor<ForallPointerDecay_old> fpd;
     516                PassVisitor<TraitExpander_old> te;
     517                PassVisitor<AssertionFixer_old> af;
     518                PassVisitor<CheckOperatorTypes_old> cot;
     519                PassVisitor<FixUniqueIds_old> fui;
    473520                type->accept( epc );
    474521                type->accept( lrt );
    475                 type->accept( fpd );
     522                type->accept( te );
     523                type->accept( af );
     524                type->accept( cot );
     525                type->accept( fui );
    476526        }
    477527
     
    9721022        }
    9731023
     1024        /// Replace all traits in assertion lists with their assertions.
     1025        void expandTraits( std::list< TypeDecl * > & forall ) {
     1026                for ( TypeDecl * type : forall ) {
     1027                        std::list< DeclarationWithType * > asserts;
     1028                        asserts.splice( asserts.end(), type->assertions );
     1029                        // expand trait instances into their members
     1030                        for ( DeclarationWithType * assertion : asserts ) {
     1031                                if ( TraitInstType * traitInst = dynamic_cast< TraitInstType * >( assertion->get_type() ) ) {
     1032                                        // expand trait instance into all of its members
     1033                                        expandAssertions( traitInst, back_inserter( type->assertions ) );
     1034                                        delete traitInst;
     1035                                } else {
     1036                                        // pass other assertions through
     1037                                        type->assertions.push_back( assertion );
     1038                                } // if
     1039                        } // for
     1040                }
     1041        }
     1042
     1043        /// Fix each function in the assertion list and check for invalid void type.
     1044        void fixAssertions(
     1045                        std::list< TypeDecl * > & forall, BaseSyntaxNode * node ) {
     1046                for ( TypeDecl * type : forall ) {
     1047                        for ( DeclarationWithType *& assertion : type->assertions ) {
     1048                                bool isVoid = fixFunction( assertion );
     1049                                if ( isVoid ) {
     1050                                        SemanticError( node, "invalid type void in assertion of function " );
     1051                                } // if
     1052                        } // for
     1053                }
     1054        }
     1055
    9741056        void ForallPointerDecay_old::previsit( ObjectDecl * object ) {
    9751057                // ensure that operator names only apply to functions or function pointers
     
    9941076        void ForallPointerDecay_old::previsit( UnionDecl * aggrDecl ) {
    9951077                forallFixer( aggrDecl->parameters, aggrDecl );
     1078        }
     1079
     1080        void TraitExpander_old::previsit( FunctionType * ftype ) {
     1081                expandTraits( ftype->forall );
     1082        }
     1083
     1084        void TraitExpander_old::previsit( StructDecl * aggrDecl ) {
     1085                expandTraits( aggrDecl->parameters );
     1086        }
     1087
     1088        void TraitExpander_old::previsit( UnionDecl * aggrDecl ) {
     1089                expandTraits( aggrDecl->parameters );
     1090        }
     1091
     1092        void AssertionFixer_old::previsit( FunctionType * ftype ) {
     1093                fixAssertions( ftype->forall, ftype );
     1094        }
     1095
     1096        void AssertionFixer_old::previsit( StructDecl * aggrDecl ) {
     1097                fixAssertions( aggrDecl->parameters, aggrDecl );
     1098        }
     1099
     1100        void AssertionFixer_old::previsit( UnionDecl * aggrDecl ) {
     1101                fixAssertions( aggrDecl->parameters, aggrDecl );
     1102        }
     1103
     1104        void CheckOperatorTypes_old::previsit( ObjectDecl * object ) {
     1105                // ensure that operator names only apply to functions or function pointers
     1106                if ( CodeGen::isOperator( object->name ) && ! dynamic_cast< FunctionType * >( object->type->stripDeclarator() ) ) {
     1107                        SemanticError( object->location, toCString( "operator ", object->name.c_str(), " is not a function or function pointer." )  );
     1108                }
     1109        }
     1110
     1111        void FixUniqueIds_old::previsit( DeclarationWithType * decl ) {
     1112                decl->fixUniqueId();
    9961113        }
    9971114
  • src/SymTab/Validate.h

    ref3c383 rd672350  
    4343        void validate_F( std::list< Declaration * > &translationUnit );
    4444        void decayForallPointers( std::list< Declaration * > & translationUnit );
     45        void decayForallPointersA( std::list< Declaration * > & translationUnit );
     46        void decayForallPointersB( std::list< Declaration * > & translationUnit );
     47        void decayForallPointersC( std::list< Declaration * > & translationUnit );
     48        void decayForallPointersD( std::list< Declaration * > & translationUnit );
    4549
    4650        const ast::Type * validateType(
  • src/Tuples/TupleAssignment.cc

    ref3c383 rd672350  
    99// Author           : Rodolfo G. Esteves
    1010// Created On       : Mon May 18 07:44:20 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Fri Dec 13 23:45:33 2019
    13 // Update Count     : 9
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Wed Mar 16 14:06:00 2022
     13// Update Count     : 10
    1414//
    1515
     
    465465                                        // resolve ctor/dtor for the new object
    466466                                        ast::ptr< ast::Init > ctorInit = ResolvExpr::resolveCtorInit(
    467                                                         InitTweak::genCtorInit( location, ret ), spotter.crntFinder.localSyms );
     467                                                        InitTweak::genCtorInit( location, ret ), spotter.crntFinder.context );
    468468                                        // remove environments from subexpressions of stmtExpr
    469469                                        ast::Pass< EnvRemover > rm{ env };
     
    560560                                        // resolve the cast expression so that rhsCand return type is bound by the cast
    561561                                        // type as needed, and transfer the resulting environment
    562                                         ResolvExpr::CandidateFinder finder{ spotter.crntFinder.localSyms, env };
     562                                        ResolvExpr::CandidateFinder finder( spotter.crntFinder.context, env );
    563563                                        finder.find( rhsCand->expr, ResolvExpr::ResolvMode::withAdjustment() );
    564564                                        assert( finder.candidates.size() == 1 );
     
    609609                                        // explode the LHS so that each field of a tuple-valued expr is assigned
    610610                                        ResolvExpr::CandidateList lhs;
    611                                         explode( *lhsCand, crntFinder.localSyms, back_inserter(lhs), true );
     611                                        explode( *lhsCand, crntFinder.context.symtab, back_inserter(lhs), true );
    612612                                        for ( ResolvExpr::CandidateRef & cand : lhs ) {
    613613                                                // each LHS value must be a reference - some come in with a cast, if not
     
    629629                                                        if ( isTuple( rhsCand->expr ) ) {
    630630                                                                // multiple assignment
    631                                                                 explode( *rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
     631                                                                explode( *rhsCand, crntFinder.context.symtab, back_inserter(rhs), true );
    632632                                                                matcher.reset(
    633633                                                                        new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    648648                                                        // multiple assignment
    649649                                                        ResolvExpr::CandidateList rhs;
    650                                                         explode( rhsCand, crntFinder.localSyms, back_inserter(rhs), true );
     650                                                        explode( rhsCand, crntFinder.context.symtab, back_inserter(rhs), true );
    651651                                                        matcher.reset(
    652652                                                                new MultipleAssignMatcher{ *this, expr->location, lhs, rhs } );
     
    678678                                )
    679679
    680                                 ResolvExpr::CandidateFinder finder{ crntFinder.localSyms, matcher->env };
     680                                ResolvExpr::CandidateFinder finder( crntFinder.context, matcher->env );
    681681
    682682                                try {
  • src/Validate/FindSpecialDeclsNew.cpp

    ref3c383 rd672350  
    3030
    3131struct FindDeclsCore : public ast::WithShortCircuiting {
    32         ast::TranslationUnit::Global & global;
    33         FindDeclsCore( ast::TranslationUnit::Global & g ) : global( g ) {}
     32        ast::TranslationGlobal & global;
     33        FindDeclsCore( ast::TranslationGlobal & g ) : global( g ) {}
    3434
    3535        void previsit( const ast::Decl * decl );
     
    7474        ast::Pass<FindDeclsCore>::run( translationUnit, translationUnit.global );
    7575
    76         // TODO: When everything gets the globals from the translation unit,
    77         // remove these.
    78         ast::dereferenceOperator = translationUnit.global.dereference;
    79         ast::dtorStruct = translationUnit.global.dtorStruct;
    80         ast::dtorStructDestroy = translationUnit.global.dtorDestroy;
    81 
    8276        // TODO: conditionally generate 'fake' declarations for missing features,
    8377        // so that translation can proceed in the event that builtins, prelude,
  • src/Validate/module.mk

    ref3c383 rd672350  
    2020        Validate/CompoundLiteral.cpp \
    2121        Validate/CompoundLiteral.hpp \
     22        Validate/ForallPointerDecay.cpp \
     23        Validate/ForallPointerDecay.hpp \
    2224        Validate/HandleAttributes.cc \
    2325        Validate/HandleAttributes.h \
  • src/Virtual/Tables.cc

    ref3c383 rd672350  
    1010// Created On       : Mon Aug 31 11:11:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Apr 21 15:36:00 2021
    13 // Update Count     : 2
    14 //
    15 
     12// Last Modified On : Fri Mar 11 10:40:00 2022
     13// Update Count     : 3
     14//
     15
     16#include "AST/Attribute.hpp"
     17#include "AST/Copy.hpp"
     18#include "AST/Decl.hpp"
     19#include "AST/Expr.hpp"
     20#include "AST/Init.hpp"
     21#include "AST/Stmt.hpp"
     22#include "AST/Type.hpp"
    1623#include <SynTree/Attribute.h>
    1724#include <SynTree/Declaration.h>
     
    7784}
    7885
     86static ast::ObjectDecl * makeVtableDeclaration(
     87                CodeLocation const & location, std::string const & name,
     88                ast::StructInstType const * type, ast::Init const * init ) {
     89        ast::Storage::Classes storage;
     90        if ( nullptr == init ) {
     91                storage.is_extern = true;
     92        }
     93        return new ast::ObjectDecl(
     94                location,
     95                name,
     96                type,
     97                init,
     98                storage,
     99                ast::Linkage::Cforall
     100        );
     101}
     102
    79103ObjectDecl * makeVtableForward( std::string const & name, StructInstType * type ) {
    80104        assert( type );
    81105        return makeVtableDeclaration( name, type, nullptr );
     106}
     107
     108ast::ObjectDecl * makeVtableForward(
     109                CodeLocation const & location, std::string const & name,
     110                ast::StructInstType const * vtableType ) {
     111        assert( vtableType );
     112        return makeVtableDeclaration( location, name, vtableType, nullptr );
    82113}
    83114
     
    123154}
    124155
     156static std::vector<ast::ptr<ast::Init>> buildInits(
     157                CodeLocation const & location,
     158                //std::string const & name,
     159                ast::StructInstType const * vtableType,
     160                ast::Type const * objectType ) {
     161        ast::StructDecl const * vtableStruct = vtableType->base;
     162
     163        std::vector<ast::ptr<ast::Init>> inits;
     164        inits.reserve( vtableStruct->members.size() );
     165
     166        // This is designed to run before the resolver.
     167        for ( auto field : vtableStruct->members ) {
     168                if ( std::string( "parent" ) == field->name ) {
     169                        // This will not work with polymorphic state.
     170                        auto oField = field.strict_as<ast::ObjectDecl>();
     171                        auto fieldType = oField->type.strict_as<ast::PointerType>();
     172                        auto parentType = fieldType->base.strict_as<ast::StructInstType>();
     173                        std::string const & parentInstance = instanceName( parentType->name );
     174                        inits.push_back(
     175                                        new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, parentInstance ) ) ) );
     176                } else if ( std::string( "__cfavir_typeid" ) == field->name ) {
     177                        std::string const & baseType = baseTypeName( vtableType->name );
     178                        std::string const & typeId = typeIdName( baseType );
     179                        inits.push_back( new ast::SingleInit( location, new ast::AddressExpr( new ast::NameExpr( location, typeId ) ) ) );
     180                } else if ( std::string( "size" ) == field->name ) {
     181                        inits.push_back( new ast::SingleInit( location, new ast::SizeofExpr( location, objectType )
     182                        ) );
     183                } else if ( std::string( "align" ) == field->name ) {
     184                        inits.push_back( new ast::SingleInit( location,
     185                                new ast::AlignofExpr( location, objectType )
     186                        ) );
     187                } else {
     188                        inits.push_back( new ast::SingleInit( location,
     189                                new ast::NameExpr( location, field->name )
     190                        ) );
     191                }
     192                //ast::Expr * expr = buildInitExpr(...);
     193                //inits.push_back( new ast::SingleInit( location, expr ) )
     194        }
     195
     196        return inits;
     197}
     198
     199ast::ObjectDecl * makeVtableInstance(
     200                CodeLocation const & location,
     201                std::string const & name,
     202                ast::StructInstType const * vtableType,
     203                ast::Type const * objectType,
     204                ast::Init const * init ) {
     205        assert( vtableType );
     206        assert( objectType );
     207
     208        // Build the initialization.
     209        if ( nullptr == init ) {
     210                init = new ast::ListInit( location,
     211                        buildInits( location, vtableType, objectType ) );
     212
     213        // The provided init should initialize everything except the parent
     214        // pointer, the size-of and align-of fields. These should be inserted.
     215        } else {
     216                // Except this is not yet supported.
     217                assert(false);
     218        }
     219        return makeVtableDeclaration( location, name, vtableType, init );
     220}
     221
    125222namespace {
    126223        std::string const functionName = "get_exception_vtable";
     
    140237                new ReferenceType( noQualifiers, vtableType ),
    141238                nullptr,
    142         { new Attribute("unused") }
     239                { new Attribute("unused") }
    143240        ) );
    144241        type->parameters.push_back( new ObjectDecl(
     
    157254                type,
    158255                nullptr
     256        );
     257}
     258
     259ast::FunctionDecl * makeGetExceptionForward(
     260                CodeLocation const & location,
     261                ast::Type const * vtableType,
     262                ast::Type const * exceptType ) {
     263        assert( vtableType );
     264        assert( exceptType );
     265        return new ast::FunctionDecl(
     266                location,
     267                functionName,
     268                { /* forall */ },
     269                { new ast::ObjectDecl(
     270                        location,
     271                        "__unused",
     272                        new ast::PointerType( exceptType )
     273                ) },
     274                { new ast::ObjectDecl(
     275                        location,
     276                        "_retvalue",
     277                        new ast::ReferenceType( vtableType )
     278                ) },
     279                nullptr,
     280                ast::Storage::Classes(),
     281                ast::Linkage::Cforall,
     282                { new ast::Attribute( "unused" ) }
    159283        );
    160284}
     
    172296}
    173297
     298ast::FunctionDecl * makeGetExceptionFunction(
     299                CodeLocation const & location,
     300                ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType ) {
     301        assert( vtableInstance );
     302        assert( exceptType );
     303        ast::FunctionDecl * func = makeGetExceptionForward(
     304                        location, ast::deepCopy( vtableInstance->type ), exceptType );
     305        func->stmts = new ast::CompoundStmt( location, {
     306                new ast::ReturnStmt( location, new ast::VariableExpr( location, vtableInstance ) )
     307        } );
     308        return func;
     309}
     310
    174311ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) {
    175312        assert( typeIdType );
     
    191328}
    192329
    193 }
     330ast::ObjectDecl * makeTypeIdInstance(
     331                CodeLocation const & location,
     332                ast::StructInstType const * typeIdType ) {
     333        assert( typeIdType );
     334        ast::StructInstType * type = ast::mutate( typeIdType );
     335        type->set_const( true );
     336        std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
     337        return new ast::ObjectDecl(
     338                location,
     339                typeid_name,
     340                type,
     341                new ast::ListInit( location, {
     342                        new ast::SingleInit( location,
     343                                new ast::AddressExpr( location,
     344                                        new ast::NameExpr( location, "__cfatid_exception_t" ) ) )
     345                } ),
     346                ast::Storage::Classes(),
     347                ast::Linkage::Cforall,
     348                nullptr,
     349                { new ast::Attribute( "cfa_linkonce" ) }
     350        );
     351}
     352
     353}
  • src/Virtual/Tables.h

    ref3c383 rd672350  
    1010// Created On       : Mon Aug 31 11:07:00 2020
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Apr 21 10:30:00 2021
    13 // Update Count     : 2
     12// Last Modified On : Wec Dec  8 16:58:00 2021
     13// Update Count     : 3
    1414//
    1515
    1616#include <list>  // for list
    1717
     18#include <string>
     19#include "AST/Fwd.hpp"
    1820class Declaration;
    1921class StructDecl;
     
    3537 * vtableType node is consumed.
    3638 */
     39ast::ObjectDecl * makeVtableForward(
     40        CodeLocation const & location, std::string const & name,
     41        ast::StructInstType const * vtableType );
    3742
    3843ObjectDecl * makeVtableInstance(
     
    4348 * vtableType and init (if provided) nodes are consumed.
    4449 */
     50ast::ObjectDecl * makeVtableInstance(
     51        CodeLocation const & location,
     52        std::string const & name,
     53        ast::StructInstType const * vtableType,
     54        ast::Type const * objectType,
     55        ast::Init const * init = nullptr );
    4556
    4657// Some special code for how exceptions interact with virtual tables.
     
    4960 * linking the vtableType to the exceptType. Both nodes are consumed.
    5061 */
     62ast::FunctionDecl * makeGetExceptionForward(
     63        CodeLocation const & location,
     64        ast::Type const * vtableType,
     65        ast::Type const * exceptType );
    5166
    5267FunctionDecl * makeGetExceptionFunction(
     
    5570 * exceptType node is consumed.
    5671 */
     72ast::FunctionDecl * makeGetExceptionFunction(
     73        CodeLocation const & location,
     74        ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType );
    5775
    5876ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType );
     
    6078 * TODO: Should take the parent type. Currently locked to the exception_t.
    6179 */
     80ast::ObjectDecl * makeTypeIdInstance(
     81        const CodeLocation & location, ast::StructInstType const * typeIdType );
    6282
    6383}
  • src/main.cc

    ref3c383 rd672350  
    1010// Created On       : Fri May 15 23:12:02 2015
    1111// Last Modified By : Andrew Beach
    12 // Last Modified On : Wed Jan 26 14:09:00 2022
    13 // Update Count     : 670
     12// Last Modified On : Fri Mar 11 10:39:00 2022
     13// Update Count     : 671
    1414//
    1515
     
    7676#include "Validate/Autogen.hpp"             // for autogenerateRoutines
    7777#include "Validate/FindSpecialDecls.h"      // for findGlobalDecls
     78#include "Validate/ForallPointerDecay.hpp"  // for decayForallPointers
    7879#include "Validate/CompoundLiteral.hpp"     // for handleCompoundLiterals
    7980#include "Validate/InitializerLength.hpp"   // for setLengthFromInitializer
     
    331332
    332333                if( useNewAST ) {
    333                         PASS( "Apply Concurrent Keywords", Concurrency::applyKeywords( translationUnit ) );
    334                         PASS( "Forall Pointer Decay", SymTab::decayForallPointers( translationUnit ) );
    335334                        CodeTools::fillLocations( translationUnit );
    336335
     
    342341
    343342                        forceFillCodeLocations( transUnit );
     343
     344                        PASS( "Implement Concurrent Keywords", Concurrency::implementKeywords( transUnit ) );
     345
     346                        // Must be after implement concurrent keywords; because uniqueIds
     347                        //   must be set on declaration before resolution.
     348                        // Must happen before autogen routines are added.
     349                        PASS( "Forall Pointer Decay", Validate::decayForallPointers( transUnit ) );
    344350
    345351                        // Must happen before autogen routines are added.
     
    487493                        PASS( "Translate Tries" , ControlStruct::translateTries( translationUnit ) );
    488494                }
    489 
    490                
    491495
    492496                PASS( "Gen Waitfor" , Concurrency::generateWaitFor( translationUnit ) );
Note: See TracChangeset for help on using the changeset viewer.