Changeset 18e683b for src


Ignore:
Timestamp:
Jun 24, 2019, 11:11:59 AM (5 years ago)
Author:
Aaron Moss <a3moss@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
c1ea11b
Parents:
8d61d620
Message:

Port LinkReferenceToTypes? pass

Location:
src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Node.hpp

    r8d61d620 r18e683b  
    100100
    101101/// Mutate a node field (only clones if not equal to existing value)
    102 template<typename node_t, typename field_t, typename assn_t>
    103 const node_t * mutate_field( const node_t * node, field_t node_t::* field, assn_t && val ) {
     102template<typename node_t, typename parent_t, typename field_t, typename assn_t>
     103const node_t * mutate_field( const node_t * node, field_t parent_t::* field, assn_t && val ) {
    104104        // skip mutate if equivalent
    105105        if ( node->*field == val ) return node;
     
    112112
    113113/// Mutate a single index of a node field (only clones if not equal to existing value)
    114 template<typename node_t, typename coll_t, typename ind_t, typename field_t>
     114template<typename node_t, typename parent_t, typename coll_t, typename ind_t, typename field_t>
    115115const node_t * mutate_field_index(
    116         const node_t * node, coll_t node_t::* field, ind_t i, field_t && val
     116        const node_t * node, coll_t parent_t::* field, ind_t i, field_t && val
    117117) {
    118118        // skip mutate if equivalent
  • src/ResolvExpr/CandidateFinder.cpp

    r8d61d620 r18e683b  
    10031003                        assert( toType );
    10041004                        toType = resolveTypeof( toType, symtab );
    1005                         toType = SymTab::validateType( toType, symtab );
     1005                        toType = SymTab::validateType( castExpr->location, toType, symtab );
    10061006                        toType = adjustExprType( toType, tenv, symtab );
    10071007
     
    14101410                                // calculate target type
    14111411                                const ast::Type * toType = resolveTypeof( initAlt.type, symtab );
    1412                                 toType = SymTab::validateType( toType, symtab );
     1412                                toType = SymTab::validateType( initExpr->location, toType, symtab );
    14131413                                toType = adjustExprType( toType, tenv, symtab );
    14141414                                // The call to find must occur inside this loop, otherwise polymorphic return
  • src/ResolvExpr/Resolver.cc

    r8d61d620 r18e683b  
    11541154                        return findKindExpression( untyped, symtab );
    11551155                }
    1156 
    1157                 /// Resolve `untyped` to the single expression whose candidate is the best match for the
    1158                 /// given type.
     1156        } // anonymous namespace
     1157
    11591158                ast::ptr< ast::Expr > findSingleExpression(
    11601159                        const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
     
    11671166                }
    11681167
     1168        namespace {
    11691169                /// Predicate for "Candidate has integral type"
    11701170                bool hasIntegralType( const Candidate & i ) {
  • src/ResolvExpr/Resolver.h

    r8d61d620 r18e683b  
    3535        class StmtExpr;
    3636        class SymbolTable;
     37        class Type;
    3738        class TypeEnvironment;
    3839} // namespace ast
     
    6162        ast::ptr< ast::Expr > resolveInVoidContext(
    6263                const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env );
     64        /// Resolve `untyped` to the single expression whose candidate is the best match for the
     65        /// given type.
     66        ast::ptr< ast::Expr > findSingleExpression(
     67                const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab );
    6368        /// Resolves a constructor init expression
    6469        ast::ptr< ast::Init > resolveCtorInit(
  • src/SymTab/Validate.cc

    r8d61d620 r18e683b  
    4444#include <list>                        // for list
    4545#include <string>                      // for string
     46#include <unordered_map>               // for unordered_map
    4647#include <utility>                     // for pair
    4748
     49#include "AST/Chain.hpp"
    4850#include "AST/Decl.hpp"
    4951#include "AST/Node.hpp"
     
    5456#include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
    5557#include "ControlStruct/Mutate.h"      // for ForExprMutator
     58#include "Common/CodeLocation.h"       // for CodeLocation
    5659#include "Common/Stats.h"              // for Stats::Heap
    5760#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
     
    14281431
    14291432        /// Associates forward declarations of aggregates with their definitions
    1430         struct LinkReferenceToTypes_new final
     1433        class LinkReferenceToTypes_new final
    14311434        : public ast::WithSymbolTable, public ast::WithGuards, public
    14321435          ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting {
    14331436               
    1434                 const ast::SymbolTable * localSyms;
    1435 
    1436                 LinkReferenceToTypes_new( const ast::SymbolTable & syms ) : localSyms( &syms ) {}
    1437 
    1438                 #warning incomplete
     1437                // these maps of uses of forward declarations of types need to have the actual type
     1438                // declaration switched in *after* they have been traversed. To enable this in the
     1439                // ast::Pass framework, any node that needs to be so mutated has mutate() called on it
     1440                // before it is placed in the map, properly updating its parents in the usual traversal,
     1441                // then can have the actual mutation applied later
     1442                using ForwardEnumsType = std::unordered_multimap< std::string, ast::EnumInstType * >;
     1443                using ForwardStructsType = std::unordered_multimap< std::string, ast::StructInstType * >;
     1444                using ForwardUnionsType = std::unordered_multimap< std::string, ast::UnionInstType * >;
     1445               
     1446                const CodeLocation & location;
     1447                const ast::SymbolTable * localSymtab;
     1448               
     1449                ForwardEnumsType forwardEnums;
     1450                ForwardStructsType forwardStructs;
     1451                ForwardUnionsType forwardUnions;
     1452
     1453                /// true if currently in a generic type body, so that type parameter instances can be
     1454                /// renamed appropriately
     1455                bool inGeneric = false;
     1456
     1457        public:
     1458                /// contstruct using running symbol table
     1459                LinkReferenceToTypes_new( const CodeLocation & loc )
     1460                : location( loc ), localSymtab( &symtab ) {}
     1461               
     1462                /// construct using provided symbol table
     1463                LinkReferenceToTypes_new( const CodeLocation & loc, const ast::SymbolTable & syms )
     1464                : location( loc ), localSymtab( &syms ) {}
     1465
     1466                const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
     1467                        // ensure generic parameter instances are renamed like the base type
     1468                        if ( inGeneric && typeInst->base ) {
     1469                                typeInst = ast::mutate_field(
     1470                                        typeInst, &ast::TypeInstType::name, typeInst->base->name );
     1471                        }
     1472
     1473                        if (
     1474                                auto typeDecl = dynamic_cast< const ast::TypeDecl * >(
     1475                                        localSymtab->lookupType( typeInst->name ) )
     1476                        ) {
     1477                                typeInst = ast::mutate_field( typeInst, &ast::TypeInstType::kind, typeDecl->kind );
     1478                        }
     1479
     1480                        return typeInst;
     1481                }
     1482
     1483                const ast::Type * postvisit( const ast::EnumInstType * inst ) {
     1484                        const ast::EnumDecl * decl = localSymtab->lookupEnum( inst->name );
     1485                        // not a semantic error if the enum is not found, just an implicit forward declaration
     1486                        if ( decl ) {
     1487                                inst = ast::mutate_field( inst, &ast::EnumInstType::base, decl );
     1488                        }
     1489                        if ( ! decl || ! decl->body ) {
     1490                                // forward declaration
     1491                                auto mut = mutate( inst );
     1492                                forwardEnums.emplace( inst->name, mut );
     1493                                inst = mut;
     1494                        }
     1495                        return inst;
     1496                }
     1497
     1498                void checkGenericParameters( const ast::ReferenceToType * inst ) {
     1499                        for ( const ast::Expr * param : inst->params ) {
     1500                                if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) {
     1501                                        SemanticError(
     1502                                                location, inst, "Expression parameters for generic types are currently "
     1503                                                "unsupported: " );
     1504                                }
     1505                        }
     1506                }
     1507
     1508                const ast::StructInstType * postvisit( const ast::StructInstType * inst ) {
     1509                        const ast::StructDecl * decl = localSymtab->lookupStruct( inst->name );
     1510                        // not a semantic error if the struct is not found, just an implicit forward declaration
     1511                        if ( decl ) {
     1512                                inst = ast::mutate_field( inst, &ast::StructInstType::base, decl );
     1513                        }
     1514                        if ( ! decl || ! decl->body ) {
     1515                                // forward declaration
     1516                                auto mut = mutate( inst );
     1517                                forwardStructs.emplace( inst->name, mut );
     1518                                inst = mut;
     1519                        }
     1520                        checkGenericParameters( inst );
     1521                        return inst;
     1522                }
     1523
     1524                const ast::UnionInstType * postvisit( const ast::UnionInstType * inst ) {
     1525                        const ast::UnionDecl * decl = localSymtab->lookupUnion( inst->name );
     1526                        // not a semantic error if the struct is not found, just an implicit forward declaration
     1527                        if ( decl ) {
     1528                                inst = ast::mutate_field( inst, &ast::UnionInstType::base, decl );
     1529                        }
     1530                        if ( ! decl || ! decl->body ) {
     1531                                // forward declaration
     1532                                auto mut = mutate( inst );
     1533                                forwardUnions.emplace( inst->name, mut );
     1534                                inst = mut;
     1535                        }
     1536                        checkGenericParameters( inst );
     1537                        return inst;
     1538                }
     1539
     1540                const ast::Type * postvisit( const ast::TraitInstType * traitInst ) {
     1541                        // handle other traits
     1542                        const ast::TraitDecl * traitDecl = localSymtab->lookupTrait( traitInst->name );
     1543                        if ( ! traitDecl )       {
     1544                                SemanticError( location, "use of undeclared trait " + traitInst->name );
     1545                        }
     1546                        if ( traitDecl->params.size() != traitInst->params.size() ) {
     1547                                SemanticError( location, traitInst, "incorrect number of trait parameters: " );
     1548                        }
     1549                        traitInst = ast::mutate_field( traitInst, &ast::TraitInstType::base, traitDecl );
     1550
     1551                        // need to carry over the "sized" status of each decl in the instance
     1552                        for ( unsigned i = 0; i < traitDecl->params.size(); ++i ) {
     1553                                auto expr = traitInst->params[i].as< ast::TypeExpr >();
     1554                                if ( ! expr ) {
     1555                                        SemanticError(
     1556                                                traitInst->params[i].get(), "Expression parameters for trait instances "
     1557                                                "are currently unsupported: " );
     1558                                }
     1559
     1560                                if ( auto inst = expr->type.as< ast::TypeInstType >() ) {
     1561                                        if ( traitDecl->params[i]->sized && ! inst->base->sized ) {
     1562                                                // traitInst = ast::mutate_field_index(
     1563                                                //      traitInst, &ast::TraitInstType::params, i,
     1564                                                //      ...
     1565                                                // );
     1566                                                ast::TraitInstType * mut = ast::mutate( traitInst );
     1567                                                ast::chain_mutate( mut->params[i] )
     1568                                                        ( &ast::TypeExpr::type )
     1569                                                                ( &ast::TypeInstType::base )->sized = true;
     1570                                                traitInst = mut;
     1571                                        }
     1572                                }
     1573                        }
     1574
     1575                        return traitInst;
     1576                }
     1577               
     1578                void previsit( const ast::QualifiedType * ) { visit_children = false; }
     1579               
     1580                const ast::Type * postvisit( const ast::QualifiedType * qualType ) {
     1581                        // linking only makes sense for the "oldest ancestor" of the qualified type
     1582                        return ast::mutate_field(
     1583                                qualType, &ast::QualifiedType::parent, qualType->parent->accept( *visitor ) );
     1584                }
     1585
     1586                const ast::Decl * postvisit( const ast::EnumDecl * enumDecl ) {
     1587                        // visit enum members first so that the types of self-referencing members are updated
     1588                        // properly
     1589                        if ( ! enumDecl->body ) return enumDecl;
     1590
     1591                        // update forward declarations to point here
     1592                        auto fwds = forwardEnums.equal_range( enumDecl->name );
     1593                        if ( fwds.first != fwds.second ) {
     1594                                auto inst = fwds.first;
     1595                                do {
     1596                                        // forward decl is stored *mutably* in map, can thus be updated
     1597                                        inst->second->base = enumDecl;
     1598                                } while ( ++inst != fwds.second );
     1599                                forwardEnums.erase( fwds.first, fwds.second );
     1600                        }
     1601                       
     1602                        // ensure that enumerator initializers are properly set
     1603                        for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {
     1604                                auto field = enumDecl->members[i].strict_as< ast::ObjectDecl >();
     1605                                if ( field->init ) {
     1606                                        // need to resolve enumerator initializers early so that other passes that
     1607                                        // determine if an expression is constexpr have appropriate information
     1608                                        auto init = field->init.strict_as< ast::SingleInit >();
     1609                                       
     1610                                        enumDecl = ast::mutate_field_index(
     1611                                                enumDecl, &ast::EnumDecl::members, i,
     1612                                                ast::mutate_field( field, &ast::ObjectDecl::init,
     1613                                                        ast::mutate_field( init, &ast::SingleInit::value,
     1614                                                                ResolvExpr::findSingleExpression(
     1615                                                                        init->value, new ast::BasicType{ ast::BasicType::SignedInt },
     1616                                                                        symtab ) ) ) );
     1617                                }
     1618                        }
     1619
     1620                        return enumDecl;
     1621                }
     1622
     1623                /// rename generic type parameters uniquely so that they do not conflict with user defined
     1624                /// function forall parameters, e.g. the T in Box and the T in f, below
     1625                ///   forall(otype T)
     1626                ///   struct Box {
     1627                ///     T x;
     1628                ///   };
     1629                ///   forall(otype T)
     1630                ///   void f(Box(T) b) {
     1631                ///     ...
     1632                ///   }
     1633                template< typename AggrDecl >
     1634                const AggrDecl * renameGenericParams( const AggrDecl * aggr ) {
     1635                        GuardValue( inGeneric );
     1636                        inGeneric = ! aggr->params.empty();
     1637
     1638                        for ( unsigned i = 0; i < aggr->params.size(); ++i ) {
     1639                                const ast::TypeDecl * td = aggr->params[i];
     1640
     1641                                aggr = ast::mutate_field_index(
     1642                                        aggr, &AggrDecl::params, i,
     1643                                        ast::mutate_field( td, &ast::TypeDecl::name, "__" + td->name + "_generic_" ) );
     1644                        }
     1645                        return aggr;
     1646                }
     1647
     1648                const ast::StructDecl * previsit( const ast::StructDecl * structDecl ) {
     1649                        return renameGenericParams( structDecl );
     1650                }
     1651
     1652                void postvisit( const ast::StructDecl * structDecl ) {
     1653                        // visit struct members first so that the types of self-referencing members are
     1654                        // updated properly
     1655                        if ( ! structDecl->body ) return;
     1656
     1657                        // update forward declarations to point here
     1658                        auto fwds = forwardStructs.equal_range( structDecl->name );
     1659                        if ( fwds.first != fwds.second ) {
     1660                                auto inst = fwds.first;
     1661                                do {
     1662                                        // forward decl is stored *mutably* in map, can thus be updated
     1663                                        inst->second->base = structDecl;
     1664                                } while ( ++inst != fwds.second );
     1665                                forwardStructs.erase( fwds.first, fwds.second );
     1666                        }
     1667                }
     1668
     1669                const ast::UnionDecl * previsit( const ast::UnionDecl * unionDecl ) {
     1670                        return renameGenericParams( unionDecl );
     1671                }
     1672
     1673                void postvisit( const ast::UnionDecl * unionDecl ) {
     1674                        // visit union members first so that the types of self-referencing members are updated
     1675                        // properly
     1676                        if ( ! unionDecl->body ) return;
     1677
     1678                        // update forward declarations to point here
     1679                        auto fwds = forwardUnions.equal_range( unionDecl->name );
     1680                        if ( fwds.first != fwds.second ) {
     1681                                auto inst = fwds.first;
     1682                                do {
     1683                                        // forward decl is stored *mutably* in map, can thus be updated
     1684                                        inst->second->base = unionDecl;
     1685                                } while ( ++inst != fwds.second );
     1686                                forwardUnions.erase( fwds.first, fwds.second );
     1687                        }
     1688                }
     1689
     1690                const ast::Decl * postvisit( const ast::TraitDecl * traitDecl ) {
     1691                        // set the "sized" status for the special "sized" trait
     1692                        if ( traitDecl->name != "sized" ) return traitDecl;
     1693
     1694                        assertf( traitDecl->params.size() == 1, "Built-in trait 'sized' has incorrect number "
     1695                                "of parameters: %zd", traitDecl->params.size() );
     1696
     1697                        return ast::mutate_field_index(
     1698                                traitDecl, &ast::TraitDecl::params, 0,
     1699                                ast::mutate_field(
     1700                                        traitDecl->params.front().get(), &ast::TypeDecl::sized, true ) );
     1701                }
    14391702        };
    14401703
     
    14461709} // anonymous namespace
    14471710
    1448 const ast::Type * validateType( const ast::Type * type, const ast::SymbolTable & symtab ) {
     1711const ast::Type * validateType(
     1712                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
    14491713        ast::Pass< EnumAndPointerDecay_new > epc;
    1450         ast::Pass< LinkReferenceToTypes_new > lrt{ symtab };
     1714        ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab };
    14511715        ast::Pass< ForallPointerDecay_new > fpd;
    14521716
  • src/SymTab/Validate.h

    r8d61d620 r18e683b  
    1919#include <list>  // for list
    2020
     21class CodeLocation;
    2122class Declaration;
    2223class Type;
     
    3435        void validateType( Type *type, const Indexer *indexer );
    3536
    36         const ast::Type * validateType( const ast::Type * type, const ast::SymbolTable & symtab );
     37        const ast::Type * validateType(
     38                const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab );
    3739} // namespace SymTab
    3840
Note: See TracChangeset for help on using the changeset viewer.