Changeset 44547b0


Ignore:
Timestamp:
Nov 7, 2022, 1:00:22 PM (18 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, ast-experimental, master
Children:
4da152a
Parents:
a805100
Message:

Removed the ObjectDecl? fields now represented on InlineValueDecl?. Removed unused new AST content from Validate (should recompile less often.

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Convert.cpp

    ra805100 r44547b0  
    16211621                        { old->get_funcSpec().val }
    16221622                );
    1623                 decl->enumInLine = old->enumInLine;
    16241623                cache.emplace(old, decl);
    16251624                assert(cache.find( old ) != cache.end());
  • src/AST/Decl.hpp

    ra805100 r44547b0  
    105105        ptr<Init> init;
    106106        ptr<Expr> bitfieldWidth;
    107         bool enumInLine = false; // enum inline is not a real object declaration.
    108         // It is a place holder for a set of enum value (ObjectDecl)
    109         bool importValue = false; // if the value copied from somewhere else
    110107
    111108        ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type,
  • src/SymTab/Validate.cc

    ra805100 r44547b0  
    4747#include <utility>                     // for pair
    4848
    49 #include "AST/Chain.hpp"
    50 #include "AST/Decl.hpp"
    51 #include "AST/Node.hpp"
    52 #include "AST/Pass.hpp"
    53 #include "AST/SymbolTable.hpp"
    54 #include "AST/Type.hpp"
    55 #include "AST/TypeSubstitution.hpp"
    5649#include "CodeGen/CodeGenerator.h"     // for genName
    5750#include "CodeGen/OperatorTable.h"     // for isCtorDtor, isCtorDtorAssign
     
    13261319        }
    13271320
    1328 namespace {
    1329         /// Replaces enum types by int, and function/array types in function parameter and return
    1330         /// lists by appropriate pointers
    1331         /*
    1332         struct EnumAndPointerDecay_new {
    1333                 const ast::EnumDecl * previsit( const ast::EnumDecl * enumDecl ) {
    1334                         // set the type of each member of the enumeration to be EnumConstant
    1335                         for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {
    1336                                 // build new version of object with EnumConstant
    1337                                 ast::ptr< ast::ObjectDecl > obj =
    1338                                         enumDecl->members[i].strict_as< ast::ObjectDecl >();
    1339                                 obj.get_and_mutate()->type =
    1340                                         new ast::EnumInstType{ enumDecl->name, ast::CV::Const };
    1341 
    1342                                 // set into decl
    1343                                 ast::EnumDecl * mut = mutate( enumDecl );
    1344                                 mut->members[i] = obj.get();
    1345                                 enumDecl = mut;
    1346                         }
    1347                         return enumDecl;
    1348                 }
    1349 
    1350                 static const ast::FunctionType * fixFunctionList(
    1351                         const ast::FunctionType * func,
    1352                         std::vector< ast::ptr< ast::DeclWithType > > ast::FunctionType::* field,
    1353                         ast::ArgumentFlag isVarArgs = ast::FixedArgs
    1354                 ) {
    1355                         const auto & dwts = func->* field;
    1356                         unsigned nvals = dwts.size();
    1357                         bool hasVoid = false;
    1358                         for ( unsigned i = 0; i < nvals; ++i ) {
    1359                                 func = ast::mutate_field_index( func, field, i, fixFunction( dwts[i], hasVoid ) );
    1360                         }
    1361 
    1362                         // the only case in which "void" is valid is where it is the only one in the list
    1363                         if ( hasVoid && ( nvals > 1 || isVarArgs ) ) {
    1364                                 SemanticError(
    1365                                         dwts.front()->location, func, "invalid type void in function type" );
    1366                         }
    1367 
    1368                         // one void is the only thing in the list, remove it
    1369                         if ( hasVoid ) {
    1370                                 func = ast::mutate_field(
    1371                                         func, field, std::vector< ast::ptr< ast::DeclWithType > >{} );
    1372                         }
    1373 
    1374                         return func;
    1375                 }
    1376 
    1377                 const ast::FunctionType * previsit( const ast::FunctionType * func ) {
    1378                         func = fixFunctionList( func, &ast::FunctionType::params, func->isVarArgs );
    1379                         return fixFunctionList( func, &ast::FunctionType::returns );
    1380                 }
    1381         };
    1382 
    1383         /// expand assertions from a trait instance, performing appropriate type variable substitutions
    1384         void expandAssertions(
    1385                 const ast::TraitInstType * inst, std::vector< ast::ptr< ast::DeclWithType > > & out
    1386         ) {
    1387                 assertf( inst->base, "Trait instance not linked to base trait: %s", toCString( inst ) );
    1388 
    1389                 // build list of trait members, substituting trait decl parameters for instance parameters
    1390                 ast::TypeSubstitution sub{
    1391                         inst->base->params.begin(), inst->base->params.end(), inst->params.begin() };
    1392                 // deliberately take ast::ptr by-value to ensure this does not mutate inst->base
    1393                 for ( ast::ptr< ast::Decl > decl : inst->base->members ) {
    1394                         auto member = decl.strict_as< ast::DeclWithType >();
    1395                         sub.apply( member );
    1396                         out.emplace_back( member );
    1397                 }
    1398         }
    1399 
    1400         /// Associates forward declarations of aggregates with their definitions
    1401         class LinkReferenceToTypes_new final
    1402         : public ast::WithSymbolTable, public ast::WithGuards, public
    1403           ast::WithVisitorRef<LinkReferenceToTypes_new>, public ast::WithShortCircuiting {
    1404 
    1405                 // these maps of uses of forward declarations of types need to have the actual type
    1406                 // declaration switched in * after * they have been traversed. To enable this in the
    1407                 // ast::Pass framework, any node that needs to be so mutated has mutate() called on it
    1408                 // before it is placed in the map, properly updating its parents in the usual traversal,
    1409                 // then can have the actual mutation applied later
    1410                 using ForwardEnumsType = std::unordered_multimap< std::string, ast::EnumInstType * >;
    1411                 using ForwardStructsType = std::unordered_multimap< std::string, ast::StructInstType * >;
    1412                 using ForwardUnionsType = std::unordered_multimap< std::string, ast::UnionInstType * >;
    1413 
    1414                 const CodeLocation & location;
    1415                 const ast::SymbolTable * localSymtab;
    1416 
    1417                 ForwardEnumsType forwardEnums;
    1418                 ForwardStructsType forwardStructs;
    1419                 ForwardUnionsType forwardUnions;
    1420 
    1421                 /// true if currently in a generic type body, so that type parameter instances can be
    1422                 /// renamed appropriately
    1423                 bool inGeneric = false;
    1424 
    1425         public:
    1426                 /// contstruct using running symbol table
    1427                 LinkReferenceToTypes_new( const CodeLocation & loc )
    1428                 : location( loc ), localSymtab( &symtab ) {}
    1429 
    1430                 /// construct using provided symbol table
    1431                 LinkReferenceToTypes_new( const CodeLocation & loc, const ast::SymbolTable & syms )
    1432                 : location( loc ), localSymtab( &syms ) {}
    1433 
    1434                 const ast::Type * postvisit( const ast::TypeInstType * typeInst ) {
    1435                         // ensure generic parameter instances are renamed like the base type
    1436                         if ( inGeneric && typeInst->base ) {
    1437                                 typeInst = ast::mutate_field(
    1438                                         typeInst, &ast::TypeInstType::name, typeInst->base->name );
    1439                         }
    1440 
    1441                         if (
    1442                                 auto typeDecl = dynamic_cast< const ast::TypeDecl * >(
    1443                                         localSymtab->lookupType( typeInst->name ) )
    1444                         ) {
    1445                                 typeInst = ast::mutate_field( typeInst, &ast::TypeInstType::kind, typeDecl->kind );
    1446                         }
    1447 
    1448                         return typeInst;
    1449                 }
    1450 
    1451                 const ast::Type * postvisit( const ast::EnumInstType * inst ) {
    1452                         const ast::EnumDecl * decl = localSymtab->lookupEnum( inst->name );
    1453                         // not a semantic error if the enum is not found, just an implicit forward declaration
    1454                         if ( decl ) {
    1455                                 inst = ast::mutate_field( inst, &ast::EnumInstType::base, decl );
    1456                         }
    1457                         if ( ! decl || ! decl->body ) {
    1458                                 // forward declaration
    1459                                 auto mut = mutate( inst );
    1460                                 forwardEnums.emplace( inst->name, mut );
    1461                                 inst = mut;
    1462                         }
    1463                         return inst;
    1464                 }
    1465 
    1466                 void checkGenericParameters( const ast::BaseInstType * inst ) {
    1467                         for ( const ast::Expr * param : inst->params ) {
    1468                                 if ( ! dynamic_cast< const ast::TypeExpr * >( param ) ) {
    1469                                         SemanticError(
    1470                                                 location, inst, "Expression parameters for generic types are currently "
    1471                                                 "unsupported: " );
    1472                                 }
    1473                         }
    1474                 }
    1475 
    1476                 const ast::StructInstType * postvisit( const ast::StructInstType * inst ) {
    1477                         const ast::StructDecl * decl = localSymtab->lookupStruct( inst->name );
    1478                         // not a semantic error if the struct is not found, just an implicit forward declaration
    1479                         if ( decl ) {
    1480                                 inst = ast::mutate_field( inst, &ast::StructInstType::base, decl );
    1481                         }
    1482                         if ( ! decl || ! decl->body ) {
    1483                                 // forward declaration
    1484                                 auto mut = mutate( inst );
    1485                                 forwardStructs.emplace( inst->name, mut );
    1486                                 inst = mut;
    1487                         }
    1488                         checkGenericParameters( inst );
    1489                         return inst;
    1490                 }
    1491 
    1492                 const ast::UnionInstType * postvisit( const ast::UnionInstType * inst ) {
    1493                         const ast::UnionDecl * decl = localSymtab->lookupUnion( inst->name );
    1494                         // not a semantic error if the struct is not found, just an implicit forward declaration
    1495                         if ( decl ) {
    1496                                 inst = ast::mutate_field( inst, &ast::UnionInstType::base, decl );
    1497                         }
    1498                         if ( ! decl || ! decl->body ) {
    1499                                 // forward declaration
    1500                                 auto mut = mutate( inst );
    1501                                 forwardUnions.emplace( inst->name, mut );
    1502                                 inst = mut;
    1503                         }
    1504                         checkGenericParameters( inst );
    1505                         return inst;
    1506                 }
    1507 
    1508                 const ast::Type * postvisit( const ast::TraitInstType * traitInst ) {
    1509                         // handle other traits
    1510                         const ast::TraitDecl * traitDecl = localSymtab->lookupTrait( traitInst->name );
    1511                         if ( ! traitDecl )       {
    1512                                 SemanticError( location, "use of undeclared trait " + traitInst->name );
    1513                         }
    1514                         if ( traitDecl->params.size() != traitInst->params.size() ) {
    1515                                 SemanticError( location, traitInst, "incorrect number of trait parameters: " );
    1516                         }
    1517                         traitInst = ast::mutate_field( traitInst, &ast::TraitInstType::base, traitDecl );
    1518 
    1519                         // need to carry over the "sized" status of each decl in the instance
    1520                         for ( unsigned i = 0; i < traitDecl->params.size(); ++i ) {
    1521                                 auto expr = traitInst->params[i].as< ast::TypeExpr >();
    1522                                 if ( ! expr ) {
    1523                                         SemanticError(
    1524                                                 traitInst->params[i].get(), "Expression parameters for trait instances "
    1525                                                 "are currently unsupported: " );
    1526                                 }
    1527 
    1528                                 if ( auto inst = expr->type.as< ast::TypeInstType >() ) {
    1529                                         if ( traitDecl->params[i]->sized && ! inst->base->sized ) {
    1530                                                 // traitInst = ast::mutate_field_index(
    1531                                                 //      traitInst, &ast::TraitInstType::params, i,
    1532                                                 //      ...
    1533                                                 // );
    1534                                                 ast::TraitInstType * mut = ast::mutate( traitInst );
    1535                                                 ast::chain_mutate( mut->params[i] )
    1536                                                         ( &ast::TypeExpr::type )
    1537                                                                 ( &ast::TypeInstType::base )->sized = true;
    1538                                                 traitInst = mut;
    1539                                         }
    1540                                 }
    1541                         }
    1542 
    1543                         return traitInst;
    1544                 }
    1545 
    1546                 void previsit( const ast::QualifiedType * ) { visit_children = false; }
    1547 
    1548                 const ast::Type * postvisit( const ast::QualifiedType * qualType ) {
    1549                         // linking only makes sense for the "oldest ancestor" of the qualified type
    1550                         return ast::mutate_field(
    1551                                 qualType, &ast::QualifiedType::parent, qualType->parent->accept( * visitor ) );
    1552                 }
    1553 
    1554                 const ast::Decl * postvisit( const ast::EnumDecl * enumDecl ) {
    1555                         // visit enum members first so that the types of self-referencing members are updated
    1556                         // properly
    1557                         if ( ! enumDecl->body ) return enumDecl;
    1558 
    1559                         // update forward declarations to point here
    1560                         auto fwds = forwardEnums.equal_range( enumDecl->name );
    1561                         if ( fwds.first != fwds.second ) {
    1562                                 auto inst = fwds.first;
    1563                                 do {
    1564                                         // forward decl is stored * mutably * in map, can thus be updated
    1565                                         inst->second->base = enumDecl;
    1566                                 } while ( ++inst != fwds.second );
    1567                                 forwardEnums.erase( fwds.first, fwds.second );
    1568                         }
    1569 
    1570                         // ensure that enumerator initializers are properly set
    1571                         for ( unsigned i = 0; i < enumDecl->members.size(); ++i ) {
    1572                                 auto field = enumDecl->members[i].strict_as< ast::ObjectDecl >();
    1573                                 if ( field->init ) {
    1574                                         // need to resolve enumerator initializers early so that other passes that
    1575                                         // determine if an expression is constexpr have appropriate information
    1576                                         auto init = field->init.strict_as< ast::SingleInit >();
    1577 
    1578                                         enumDecl = ast::mutate_field_index(
    1579                                                 enumDecl, &ast::EnumDecl::members, i,
    1580                                                 ast::mutate_field( field, &ast::ObjectDecl::init,
    1581                                                         ast::mutate_field( init, &ast::SingleInit::value,
    1582                                                                 ResolvExpr::findSingleExpression(
    1583                                                                         init->value, new ast::BasicType{ ast::BasicType::SignedInt },
    1584                                                                         symtab ) ) ) );
    1585                                 }
    1586                         }
    1587 
    1588                         return enumDecl;
    1589                 }
    1590 
    1591                 /// rename generic type parameters uniquely so that they do not conflict with user defined
    1592                 /// function forall parameters, e.g. the T in Box and the T in f, below
    1593                 ///   forall(otype T)
    1594                 ///   struct Box {
    1595                 ///     T x;
    1596                 ///   };
    1597                 ///   forall(otype T)
    1598                 ///   void f(Box(T) b) {
    1599                 ///     ...
    1600                 ///   }
    1601                 template< typename AggrDecl >
    1602                 const AggrDecl * renameGenericParams( const AggrDecl * aggr ) {
    1603                         GuardValue( inGeneric );
    1604                         inGeneric = ! aggr->params.empty();
    1605 
    1606                         for ( unsigned i = 0; i < aggr->params.size(); ++i ) {
    1607                                 const ast::TypeDecl * td = aggr->params[i];
    1608 
    1609                                 aggr = ast::mutate_field_index(
    1610                                         aggr, &AggrDecl::params, i,
    1611                                         ast::mutate_field( td, &ast::TypeDecl::name, "__" + td->name + "_generic_" ) );
    1612                         }
    1613                         return aggr;
    1614                 }
    1615 
    1616                 const ast::StructDecl * previsit( const ast::StructDecl * structDecl ) {
    1617                         return renameGenericParams( structDecl );
    1618                 }
    1619 
    1620                 void postvisit( const ast::StructDecl * structDecl ) {
    1621                         // visit struct members first so that the types of self-referencing members are
    1622                         // updated properly
    1623                         if ( ! structDecl->body ) return;
    1624 
    1625                         // update forward declarations to point here
    1626                         auto fwds = forwardStructs.equal_range( structDecl->name );
    1627                         if ( fwds.first != fwds.second ) {
    1628                                 auto inst = fwds.first;
    1629                                 do {
    1630                                         // forward decl is stored * mutably * in map, can thus be updated
    1631                                         inst->second->base = structDecl;
    1632                                 } while ( ++inst != fwds.second );
    1633                                 forwardStructs.erase( fwds.first, fwds.second );
    1634                         }
    1635                 }
    1636 
    1637                 const ast::UnionDecl * previsit( const ast::UnionDecl * unionDecl ) {
    1638                         return renameGenericParams( unionDecl );
    1639                 }
    1640 
    1641                 void postvisit( const ast::UnionDecl * unionDecl ) {
    1642                         // visit union members first so that the types of self-referencing members are updated
    1643                         // properly
    1644                         if ( ! unionDecl->body ) return;
    1645 
    1646                         // update forward declarations to point here
    1647                         auto fwds = forwardUnions.equal_range( unionDecl->name );
    1648                         if ( fwds.first != fwds.second ) {
    1649                                 auto inst = fwds.first;
    1650                                 do {
    1651                                         // forward decl is stored * mutably * in map, can thus be updated
    1652                                         inst->second->base = unionDecl;
    1653                                 } while ( ++inst != fwds.second );
    1654                                 forwardUnions.erase( fwds.first, fwds.second );
    1655                         }
    1656                 }
    1657 
    1658                 const ast::Decl * postvisit( const ast::TraitDecl * traitDecl ) {
    1659                         // set the "sized" status for the special "sized" trait
    1660                         if ( traitDecl->name == "sized" ) {
    1661                                 assertf( traitDecl->params.size() == 1, "Built-in trait 'sized' has incorrect "
    1662                                         "number of parameters: %zd", traitDecl->params.size() );
    1663 
    1664                                 traitDecl = ast::mutate_field_index(
    1665                                         traitDecl, &ast::TraitDecl::params, 0,
    1666                                         ast::mutate_field(
    1667                                                 traitDecl->params.front().get(), &ast::TypeDecl::sized, true ) );
    1668                         }
    1669 
    1670                         // move assertions from type parameters into the body of the trait
    1671                         std::vector< ast::ptr< ast::DeclWithType > > added;
    1672                         for ( const ast::TypeDecl * td : traitDecl->params ) {
    1673                                 for ( const ast::DeclWithType * assn : td->assertions ) {
    1674                                         auto inst = dynamic_cast< const ast::TraitInstType * >( assn->get_type() );
    1675                                         if ( inst ) {
    1676                                                 expandAssertions( inst, added );
    1677                                         } else {
    1678                                                 added.emplace_back( assn );
    1679                                         }
    1680                                 }
    1681                         }
    1682                         if ( ! added.empty() ) {
    1683                                 auto mut = mutate( traitDecl );
    1684                                 for ( const ast::DeclWithType * decl : added ) {
    1685                                         mut->members.emplace_back( decl );
    1686                                 }
    1687                                 traitDecl = mut;
    1688                         }
    1689 
    1690                         return traitDecl;
    1691                 }
    1692         };
    1693 
    1694         /// Replaces array and function types in forall lists by appropriate pointer type and assigns
    1695         /// each object and function declaration a unique ID
    1696         class ForallPointerDecay_new {
    1697                 const CodeLocation & location;
    1698         public:
    1699                 ForallPointerDecay_new( const CodeLocation & loc ) : location( loc ) {}
    1700 
    1701                 const ast::ObjectDecl * previsit( const ast::ObjectDecl * obj ) {
    1702                         // ensure that operator names only apply to functions or function pointers
    1703                         if (
    1704                                 CodeGen::isOperator( obj->name )
    1705                                 && ! dynamic_cast< const ast::FunctionType * >( obj->type->stripDeclarator() )
    1706                         ) {
    1707                                 SemanticError( obj->location, toCString( "operator ", obj->name.c_str(), " is not "
    1708                                         "a function or function pointer." )  );
    1709                         }
    1710 
    1711                         // ensure object has unique ID
    1712                         if ( obj->uniqueId ) return obj;
    1713                         auto mut = mutate( obj );
    1714                         mut->fixUniqueId();
    1715                         return mut;
    1716                 }
    1717 
    1718                 const ast::FunctionDecl * previsit( const ast::FunctionDecl * func ) {
    1719                         // ensure function has unique ID
    1720                         if ( func->uniqueId ) return func;
    1721                         auto mut = mutate( func );
    1722                         mut->fixUniqueId();
    1723                         return mut;
    1724                 }
    1725 
    1726                 /// Fix up assertions -- flattens assertion lists, removing all trait instances
    1727                 template< typename node_t, typename parent_t >
    1728                 static const node_t * forallFixer(
    1729                         const CodeLocation & loc, const node_t * node,
    1730                         ast::FunctionType::ForallList parent_t::* forallField
    1731                 ) {
    1732                         for ( unsigned i = 0; i < (node->* forallField).size(); ++i ) {
    1733                                 const ast::TypeDecl * type = (node->* forallField)[i];
    1734                                 if ( type->assertions.empty() ) continue;
    1735 
    1736                                 std::vector< ast::ptr< ast::DeclWithType > > asserts;
    1737                                 asserts.reserve( type->assertions.size() );
    1738 
    1739                                 // expand trait instances into their members
    1740                                 for ( const ast::DeclWithType * assn : type->assertions ) {
    1741                                         auto traitInst =
    1742                                                 dynamic_cast< const ast::TraitInstType * >( assn->get_type() );
    1743                                         if ( traitInst ) {
    1744                                                 // expand trait instance to all its members
    1745                                                 expandAssertions( traitInst, asserts );
    1746                                         } else {
    1747                                                 // pass other assertions through
    1748                                                 asserts.emplace_back( assn );
    1749                                         }
    1750                                 }
    1751 
    1752                                 // apply FixFunction to every assertion to check for invalid void type
    1753                                 for ( ast::ptr< ast::DeclWithType > & assn : asserts ) {
    1754                                         bool isVoid = false;
    1755                                         assn = fixFunction( assn, isVoid );
    1756                                         if ( isVoid ) {
    1757                                                 SemanticError( loc, node, "invalid type void in assertion of function " );
    1758                                         }
    1759                                 }
    1760 
    1761                                 // place mutated assertion list in node
    1762                                 auto mut = mutate( type );
    1763                                 mut->assertions = move( asserts );
    1764                                 node = ast::mutate_field_index( node, forallField, i, mut );
    1765                         }
    1766                         return node;
    1767                 }
    1768 
    1769                 const ast::FunctionType * previsit( const ast::FunctionType * ftype ) {
    1770                         return forallFixer( location, ftype, &ast::FunctionType::forall );
    1771                 }
    1772 
    1773                 const ast::StructDecl * previsit( const ast::StructDecl * aggrDecl ) {
    1774                         return forallFixer( aggrDecl->location, aggrDecl, &ast::StructDecl::params );
    1775                 }
    1776 
    1777                 const ast::UnionDecl * previsit( const ast::UnionDecl * aggrDecl ) {
    1778                         return forallFixer( aggrDecl->location, aggrDecl, &ast::UnionDecl::params );
    1779                 }
    1780         };
    1781         */
    1782 } // anonymous namespace
    1783 
    1784 /*
    1785 const ast::Type * validateType(
    1786                 const CodeLocation & loc, const ast::Type * type, const ast::SymbolTable & symtab ) {
    1787         // ast::Pass< EnumAndPointerDecay_new > epc;
    1788         ast::Pass< LinkReferenceToTypes_new > lrt{ loc, symtab };
    1789         ast::Pass< ForallPointerDecay_new > fpd{ loc };
    1790 
    1791         return type->accept( lrt )->accept( fpd );
    1792 }
    1793 */
    1794 
    17951321} // namespace SymTab
    17961322
Note: See TracChangeset for help on using the changeset viewer.