Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Validate.cc

    rc1398e4 rc1ed2ee  
    4444#include <list>                        // for list
    4545#include <string>                      // for string
    46 #include <unordered_map>               // for unordered_map
    4746#include <utility>                     // for pair
    4847
    49 #include "AST/Chain.hpp"
    5048#include "AST/Decl.hpp"
    5149#include "AST/Node.hpp"
     
    5351#include "AST/SymbolTable.hpp"
    5452#include "AST/Type.hpp"
    55 #include "AST/TypeSubstitution.hpp"
    5653#include "CodeGen/CodeGenerator.h"     // for genName
    5754#include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
    5855#include "ControlStruct/Mutate.h"      // for ForExprMutator
    59 #include "Common/CodeLocation.h"       // for CodeLocation
    6056#include "Common/Stats.h"              // for Stats::Heap
    6157#include "Common/PassVisitor.h"        // for PassVisitor, WithDeclsToAdd
     
    14311427        };
    14321428
    1433         /// expand assertions from a trait instance, performing appropriate type variable substitutions
    1434         void expandAssertions(
    1435                 const ast::TraitInstType * inst, std::vector< ast::ptr< ast::DeclWithType > > & out
    1436         ) {
    1437                 assertf( inst->base, "Trait instance not linked to base trait: %s", toCString( inst ) );
    1438 
    1439                 // build list of trait members, substituting trait decl parameters for instance parameters
    1440                 ast::TypeSubstitution sub{
    1441                         inst->base->params.begin(), inst->base->params.end(), inst->params.begin() };
    1442                 // deliberately take ast::ptr by-value to ensure this does not mutate inst->base
    1443                 for ( ast::ptr< ast::Decl > decl : inst->base->members ) {
    1444                         auto member = decl.strict_as< ast::DeclWithType >();
    1445                         sub.apply( member );
    1446                         out.emplace_back( member );
    1447                 }
    1448         }
    1449 
    14501429        /// Associates forward declarations of aggregates with their definitions
    1451         class LinkReferenceToTypes_new final
     1430        struct LinkReferenceToTypes_new final
    14521431        : public ast::WithSymbolTable, public ast::WithGuards, public
    14531432          ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting {
    14541433               
    1455                 // these maps of uses of forward declarations of types need to have the actual type
    1456                 // declaration switched in *after* they have been traversed. To enable this in the
    1457                 // ast::Pass framework, any node that needs to be so mutated has mutate() called on it
    1458                 // before it is placed in the map, properly updating its parents in the usual traversal,
    1459                 // then can have the actual mutation applied later
    1460                 using ForwardEnumsType = std::unordered_multimap< std::string, ast::EnumInstType * >;
    1461                 using ForwardStructsType = std::unordered_multimap< std::string, ast::StructInstType * >;
    1462                 using ForwardUnionsType = std::unordered_multimap< std::string, ast::UnionInstType * >;
    1463                
    1464                 const CodeLocation & location;
    1465                 const ast::SymbolTable * localSymtab;
    1466                
    1467                 ForwardEnumsType forwardEnums;
    1468                 ForwardStructsType forwardStructs;
    1469                 ForwardUnionsType forwardUnions;
    1470 
    1471                 /// true if currently in a generic type body, so that type parameter instances can be
    1472                 /// renamed appropriately
    1473                 bool inGeneric = false;
    1474 
    1475         public:
    1476                 /// contstruct using running symbol table
    1477                 LinkReferenceToTypes_new( const CodeLocation & loc )
    1478                 : location( loc ), localSymtab( &symtab ) {}
    1479                
    1480                 /// construct using provided symbol table
    1481                 LinkReferenceToTypes_new( const CodeLocation & loc, const ast::SymbolTable & syms )
    1482                 : location( loc ), localSymtab( &syms ) {}
    1483 
    1484                 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    1485                         // ensure generic parameter instances are renamed like the base type
    1486                         if ( inGeneric && typeInst->base ) {
    1487                                 typeInst = ast::mutate_field(
    1488                                         typeInst, &ast::TypeInstType::name, typeInst->base->name );
    1489                         }
    1490 
    1491                         if (
    1492                                 auto typeDecl = dynamic_cast< const ast::TypeDecl * >(
    1493                                         localSymtab->lookupType( typeInst->name ) )
    1494                         ) {
    1495                                 typeInst = ast::mutate_field( typeInst, &ast::TypeInstType::kind, typeDecl->kind );
    1496                         }
    1497 
    1498                         return typeInst;
    1499                 }
    1500 
    1501                 const ast::Type * postvisit( const ast::EnumInstType * inst ) {
    1502                         const ast::EnumDecl * decl = localSymtab->lookupEnum( inst->name );
    1503                         // not a semantic error if the enum is not found, just an implicit forward declaration
    1504                         if ( decl ) {
    1505                                 inst = ast::mutate_field( inst, &ast::EnumInstType::base, decl );
    1506                         }
    1507                         if ( ! decl || ! decl->body ) {
    1508                                 // forward declaration
    1509                                 auto mut = mutate( inst );
    1510                                 forwardEnums.emplace( inst->name, mut );
    1511                                 inst = mut;
    1512                         }
    1513                         return inst;
    1514                 }
    1515 
    1516                 void checkGenericParameters( const ast::ReferenceToType * inst ) {
    1517                         for ( const ast::Expr * param : inst->params ) {
    1518                                 if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) {
    1519                                         SemanticError(
    1520                                                 location, inst, "Expression parameters for generic types are currently "
    1521                                                 "unsupported: " );
    1522                                 }
    1523                         }
    1524                 }
    1525 
    1526                 const ast::StructInstType * postvisit( const ast::StructInstType * inst ) {
    1527                         const ast::StructDecl * decl = localSymtab->lookupStruct( inst->name );
    1528                         // not a semantic error if the struct is not found, just an implicit forward declaration
    1529                         if ( decl ) {
    1530                                 inst = ast::mutate_field( inst, &ast::StructInstType::base, decl );
    1531                         }
    1532                         if ( ! decl || ! decl->body ) {
    1533                                 // forward declaration
    1534                                 auto mut = mutate( inst );
    1535                                 forwardStructs.emplace( inst->name, mut );
    1536                                 inst = mut;
    1537                         }
    1538                         checkGenericParameters( inst );
    1539                         return inst;
    1540                 }
    1541 
    1542                 const ast::UnionInstType * postvisit( const ast::UnionInstType * inst ) {
    1543                         const ast::UnionDecl * decl = localSymtab->lookupUnion( inst->name );
    1544                         // not a semantic error if the struct is not found, just an implicit forward declaration
    1545                         if ( decl ) {
    1546                                 inst = ast::mutate_field( inst, &ast::UnionInstType::base, decl );
    1547                         }
    1548                         if ( ! decl || ! decl->body ) {
    1549                                 // forward declaration
    1550                                 auto mut = mutate( inst );
    1551                                 forwardUnions.emplace( inst->name, mut );
    1552                                 inst = mut;
    1553                         }
    1554                         checkGenericParameters( inst );
    1555                         return inst;
    1556                 }
    1557 
    1558                 const ast::Type * postvisit( const ast::TraitInstType * traitInst ) {
    1559                         // handle other traits
    1560                         const ast::TraitDecl * traitDecl = localSymtab->lookupTrait( traitInst->name );
    1561                         if ( ! traitDecl )       {
    1562                                 SemanticError( location, "use of undeclared trait " + traitInst->name );
    1563                         }
    1564                         if ( traitDecl->params.size() != traitInst->params.size() ) {
    1565                                 SemanticError( location, traitInst, "incorrect number of trait parameters: " );
    1566                         }
    1567                         traitInst = ast::mutate_field( traitInst, &ast::TraitInstType::base, traitDecl );
    1568 
    1569                         // need to carry over the "sized" status of each decl in the instance
    1570                         for ( unsigned i = 0; i < traitDecl->params.size(); ++i ) {
    1571                                 auto expr = traitInst->params[i].as< ast::TypeExpr >();
    1572                                 if ( ! expr ) {
    1573                                         SemanticError(
    1574                                                 traitInst->params[i].get(), "Expression parameters for trait instances "
    1575                                                 "are currently unsupported: " );
    1576                                 }
    1577 
    1578                                 if ( auto inst = expr->type.as< ast::TypeInstType >() ) {
    1579                                         if ( traitDecl->params[i]->sized && ! inst->base->sized ) {
    1580                                                 // traitInst = ast::mutate_field_index(
    1581                                                 //      traitInst, &ast::TraitInstType::params, i,
    1582                                                 //      ...
    1583                                                 // );
    1584                                                 ast::TraitInstType * mut = ast::mutate( traitInst );
    1585                                                 ast::chain_mutate( mut->params[i] )
    1586                                                         ( &ast::TypeExpr::type )
    1587                                                                 ( &ast::TypeInstType::base )->sized = true;
    1588                                                 traitInst = mut;
    1589                                         }
    1590                                 }
    1591                         }
    1592 
    1593                         return traitInst;
    1594                 }
    1595                
    1596                 void previsit( const ast::QualifiedType * ) { visit_children = false; }
    1597                
    1598                 const ast::Type * postvisit( const ast::QualifiedType * qualType ) {
    1599                         // linking only makes sense for the "oldest ancestor" of the qualified type
    1600                         return ast::mutate_field(
    1601                                 qualType, &ast::QualifiedType::parent, qualType->parent->accept( *visitor ) );
    1602                 }
    1603 
    1604                 const ast::Decl * postvisit( const ast::EnumDecl * enumDecl ) {
    1605                         // visit enum members first so that the types of self-referencing members are updated
    1606                         // properly
    1607                         if ( ! enumDecl->body ) return enumDecl;
    1608 
    1609                         // update forward declarations to point here
    1610                         auto fwds = forwardEnums.equal_range( enumDecl->name );
    1611                         if ( fwds.first != fwds.second ) {
    1612                                 auto inst = fwds.first;
    1613                                 do {
    1614                                         // forward decl is stored *mutably* in map, can thus be updated
    1615                                         inst->second->base = enumDecl;
    1616                                 } while ( ++inst != fwds.second );
    1617                                 forwardEnums.erase( fwds.first, fwds.second );
    1618                         }
    1619                        
    1620                         // ensure that enumerator initializers are properly set
    1621                         for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {
    1622                                 auto field = enumDecl->members[i].strict_as< ast::ObjectDecl >();
    1623                                 if ( field->init ) {
    1624                                         // need to resolve enumerator initializers early so that other passes that
    1625                                         // determine if an expression is constexpr have appropriate information
    1626                                         auto init = field->init.strict_as< ast::SingleInit >();
    1627                                        
    1628                                         enumDecl = ast::mutate_field_index(
    1629                                                 enumDecl, &ast::EnumDecl::members, i,
    1630                                                 ast::mutate_field( field, &ast::ObjectDecl::init,
    1631                                                         ast::mutate_field( init, &ast::SingleInit::value,
    1632                                                                 ResolvExpr::findSingleExpression(
    1633                                                                         init->value, new ast::BasicType{ ast::BasicType::SignedInt },
    1634                                                                         symtab ) ) ) );
    1635                                 }
    1636                         }
    1637 
    1638                         return enumDecl;
    1639                 }
    1640 
    1641                 /// rename generic type parameters uniquely so that they do not conflict with user defined
    1642                 /// function forall parameters, e.g. the T in Box and the T in f, below
    1643                 ///   forall(otype T)
    1644                 ///   struct Box {
    1645                 ///     T x;
    1646                 ///   };
    1647                 ///   forall(otype T)
    1648                 ///   void f(Box(T) b) {
    1649                 ///     ...
    1650                 ///   }
    1651                 template< typename AggrDecl >
    1652                 const AggrDecl * renameGenericParams( const AggrDecl * aggr ) {
    1653                         GuardValue( inGeneric );
    1654                         inGeneric = ! aggr->params.empty();
    1655 
    1656                         for ( unsigned i = 0; i < aggr->params.size(); ++i ) {
    1657                                 const ast::TypeDecl * td = aggr->params[i];
    1658 
    1659                                 aggr = ast::mutate_field_index(
    1660                                         aggr, &AggrDecl::params, i,
    1661                                         ast::mutate_field( td, &ast::TypeDecl::name, "__" + td->name + "_generic_" ) );
    1662                         }
    1663                         return aggr;
    1664                 }
    1665 
    1666                 const ast::StructDecl * previsit( const ast::StructDecl * structDecl ) {
    1667                         return renameGenericParams( structDecl );
    1668                 }
    1669 
    1670                 void postvisit( const ast::StructDecl * structDecl ) {
    1671                         // visit struct members first so that the types of self-referencing members are
    1672                         // updated properly
    1673                         if ( ! structDecl->body ) return;
    1674 
    1675                         // update forward declarations to point here
    1676                         auto fwds = forwardStructs.equal_range( structDecl->name );
    1677                         if ( fwds.first != fwds.second ) {
    1678                                 auto inst = fwds.first;
    1679                                 do {
    1680                                         // forward decl is stored *mutably* in map, can thus be updated
    1681                                         inst->second->base = structDecl;
    1682                                 } while ( ++inst != fwds.second );
    1683                                 forwardStructs.erase( fwds.first, fwds.second );
    1684                         }
    1685                 }
    1686 
    1687                 const ast::UnionDecl * previsit( const ast::UnionDecl * unionDecl ) {
    1688                         return renameGenericParams( unionDecl );
    1689                 }
    1690 
    1691                 void postvisit( const ast::UnionDecl * unionDecl ) {
    1692                         // visit union members first so that the types of self-referencing members are updated
    1693                         // properly
    1694                         if ( ! unionDecl->body ) return;
    1695 
    1696                         // update forward declarations to point here
    1697                         auto fwds = forwardUnions.equal_range( unionDecl->name );
    1698                         if ( fwds.first != fwds.second ) {
    1699                                 auto inst = fwds.first;
    1700                                 do {
    1701                                         // forward decl is stored *mutably* in map, can thus be updated
    1702                                         inst->second->base = unionDecl;
    1703                                 } while ( ++inst != fwds.second );
    1704                                 forwardUnions.erase( fwds.first, fwds.second );
    1705                         }
    1706                 }
    1707 
    1708                 const ast::Decl * postvisit( const ast::TraitDecl * traitDecl ) {
    1709                         // set the "sized" status for the special "sized" trait
    1710                         if ( traitDecl->name == "sized" ) {
    1711                                 assertf( traitDecl->params.size() == 1, "Built-in trait 'sized' has incorrect "
    1712                                         "number of parameters: %zd", traitDecl->params.size() );
    1713 
    1714                                 traitDecl = ast::mutate_field_index(
    1715                                         traitDecl, &ast::TraitDecl::params, 0,
    1716                                         ast::mutate_field(
    1717                                                 traitDecl->params.front().get(), &ast::TypeDecl::sized, true ) );
    1718                         }
    1719 
    1720                         // move assertions from type parameters into the body of the trait
    1721                         std::vector< ast::ptr< ast::DeclWithType > > added;
    1722                         for ( const ast::TypeDecl * td : traitDecl->params ) {
    1723                                 for ( const ast::DeclWithType * assn : td->assertions ) {
    1724                                         auto inst = dynamic_cast< const ast::TraitInstType * >( assn->get_type() );
    1725                                         if ( inst ) {
    1726                                                 expandAssertions( inst, added );
    1727                                         } else {
    1728                                                 added.emplace_back( assn );
    1729                                         }
    1730                                 }
    1731                         }
    1732                         if ( ! added.empty() ) {
    1733                                 auto mut = mutate( traitDecl );
    1734                                 for ( const ast::DeclWithType * decl : added ) {
    1735                                         mut->members.emplace_back( decl );
    1736                                 }
    1737                                 traitDecl = mut;
    1738                         }
    1739                        
    1740                         return traitDecl;
    1741                 }
     1434                const ast::SymbolTable * localSyms;
     1435
     1436                LinkReferenceToTypes_new( const ast::SymbolTable & syms ) : localSyms( &syms ) {}
     1437
     1438                #warning incomplete
    17421439        };
    17431440
    17441441        /// Replaces array and function types in forall lists by appropriate pointer type and assigns
    17451442        /// each object and function declaration a unique ID
    1746         class ForallPointerDecay_new {
    1747                 const CodeLocation & location;
    1748         public:
    1749                 ForallPointerDecay_new( const CodeLocation & loc ) : location( loc ) {}
    1750 
    1751                 const ast::ObjectDecl * previsit( const ast::ObjectDecl * obj ) {
    1752                         // ensure that operator names only apply to functions or function pointers
    1753                         if (
    1754                                 CodeGen::isOperator( obj->name )
    1755                                 && ! dynamic_cast< const ast::FunctionType * >( obj->type->stripDeclarator() )
    1756                         ) {
    1757                                 SemanticError( obj->location, toCString( "operator ", obj->name.c_str(), " is not "
    1758                                         "a function or function pointer." )  );
    1759                         }
    1760 
    1761                         // ensure object has unique ID
    1762                         if ( obj->uniqueId ) return obj;
    1763                         auto mut = mutate( obj );
    1764                         mut->fixUniqueId();
    1765                         return mut;
    1766                 }
    1767 
    1768                 const ast::FunctionDecl * previsit( const ast::FunctionDecl * func ) {
    1769                         // ensure function has unique ID
    1770                         if ( func->uniqueId ) return func;
    1771                         auto mut = mutate( func );
    1772                         mut->fixUniqueId();
    1773                         return mut;
    1774                 }
    1775 
    1776                 /// Fix up assertions -- flattens assertion lists, removing all trait instances
    1777                 template< typename node_t, typename parent_t >
    1778                 static const node_t * forallFixer(
    1779                         const CodeLocation & loc, const node_t * node,
    1780                         ast::ParameterizedType::ForallList parent_t::* forallField
    1781                 ) {
    1782                         for ( unsigned i = 0; i < (node->*forallField).size(); ++i ) {
    1783                                 const ast::TypeDecl * type = (node->*forallField)[i];
    1784                                 if ( type->assertions.empty() ) continue;
    1785 
    1786                                 std::vector< ast::ptr< ast::DeclWithType > > asserts;
    1787                                 asserts.reserve( type->assertions.size() );
    1788 
    1789                                 // expand trait instances into their members
    1790                                 for ( const ast::DeclWithType * assn : type->assertions ) {
    1791                                         auto traitInst =
    1792                                                 dynamic_cast< const ast::TraitInstType * >( assn->get_type() );
    1793                                         if ( traitInst ) {
    1794                                                 // expand trait instance to all its members
    1795                                                 expandAssertions( traitInst, asserts );
    1796                                         } else {
    1797                                                 // pass other assertions through
    1798                                                 asserts.emplace_back( assn );
    1799                                         }
    1800                                 }
    1801 
    1802                                 // apply FixFunction to every assertion to check for invalid void type
    1803                                 for ( ast::ptr< ast::DeclWithType > & assn : asserts ) {
    1804                                         bool isVoid = false;
    1805                                         assn = fixFunction( assn, isVoid );
    1806                                         if ( isVoid ) {
    1807                                                 SemanticError( loc, node, "invalid type void in assertion of function " );
    1808                                         }
    1809                                 }
    1810 
    1811                                 // place mutated assertion list in node
    1812                                 auto mut = mutate( type );
    1813                                 mut->assertions = move( asserts );
    1814                                 node = ast::mutate_field_index( node, forallField, i, mut );
    1815                         }
    1816                         return node;
    1817                 }
    1818 
    1819                 const ast::FunctionType * previsit( const ast::FunctionType * ftype ) {
    1820                         return forallFixer( location, ftype, &ast::FunctionType::forall );
    1821                 }
    1822 
    1823                 const ast::StructDecl * previsit( const ast::StructDecl * aggrDecl ) {
    1824                         return forallFixer( aggrDecl->location, aggrDecl, &ast::StructDecl::params );
    1825                 }
    1826 
    1827                 const ast::UnionDecl * previsit( const ast::UnionDecl * aggrDecl ) {
    1828                         return forallFixer( aggrDecl->location, aggrDecl, &ast::UnionDecl::params );
    1829                 }
     1443        struct ForallPointerDecay_new {
     1444                #warning incomplete
    18301445        };
    18311446} // anonymous namespace
    18321447
    1833 const ast::Type * validateType(
    1834                 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
     1448const ast::Type * validateType( const ast::Type * type, const ast::SymbolTable & symtab ) {
    18351449        ast::Pass< EnumAndPointerDecay_new > epc;
    1836         ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab };
    1837         ast::Pass< ForallPointerDecay_new > fpd{ loc };
     1450        ast::Pass< LinkReferenceToTypes_new > lrt{ symtab };
     1451        ast::Pass< ForallPointerDecay_new > fpd;
    18381452
    18391453        return type->accept( epc )->accept( lrt )->accept( fpd );
Note: See TracChangeset for help on using the changeset viewer.