Changeset 3253c32


Ignore:
Timestamp:
Jun 24, 2019, 1:26:04 PM (5 years ago)
Author:
Peter A. Buhr <pabuhr@…>
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:
fb2bde4
Parents:
397edf7 (diff), b58affe7 (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

Files:
10 edited

Legend:

Unmodified
Added
Removed
  • Jenkinsfile

    r397edf7 r3253c32  
    130130                        //Run the tests from the tests directory
    131131                        if ( Settings.RunAllTests ) {
    132                                 sh 'make --no-print-directory -C tests timeouts="--timeout=600" all-tests debug=yes'
    133                                 sh 'make --no-print-directory -C tests timeouts="--timeout=600" all-tests debug=no '
     132                                sh 'make --no-print-directory -C tests timeouts="--timeout=1200" all-tests debug=yes'
     133                                sh 'make --no-print-directory -C tests timeouts="--timeout=1200" all-tests debug=no '
    134134                        }
    135135                        else {
  • driver/cc1.cc

    r397edf7 r3253c32  
    55// file "LICENCE" distributed with Cforall.
    66//
    7 // cc1.cc -- 
     7// cc1.cc --
    88//
    99// Author           : Peter A. Buhr
     
    107107        if ( tmpfilefd != -1 ) {                                                        // RACE, file created ?
    108108                rmtmpfile();                                                                    // remove
    109                 exit( EXIT_FAILURE );                                                   // terminate 
     109                exit( EXIT_FAILURE );                                                   // terminate
    110110        } // if
    111111} // sigTermHandler
     
    360360
    361361                #ifdef __DEBUG_H__
    362                 cerr << "cfa-cpp ncargs: " << o_name << " " << CFA_flag << " " << ncargs << endl;
     362                cerr << "cfa-cpp ncargs: " << (o_name ? o_name : "No -o") << " " << CFA_flag << " " << ncargs << endl;
    363363                for ( int i = 0; cargs[i] != NULL; i += 1 ) {
    364364                        cerr << cargs[i] << " ";
  • src/AST/Convert.cpp

    r397edf7 r3253c32  
    18951895                };
    18961896                stmt->orElse = {
    1897                         GET_ACCEPT_1(timeout.statement, Stmt),
    1898                         GET_ACCEPT_1(timeout.condition, Expr),
     1897                        GET_ACCEPT_1(orelse.statement, Stmt),
     1898                        GET_ACCEPT_1(orelse.condition, Expr),
    18991899                };
    19001900
  • src/AST/Node.hpp

    r397edf7 r3253c32  
    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

    r397edf7 r3253c32  
    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

    r397edf7 r3253c32  
    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

    r397edf7 r3253c32  
    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

    r397edf7 r3253c32  
    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

    r397edf7 r3253c32  
    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
  • tests/sum.cfa

    r397edf7 r3253c32  
    3535
    3636int main( void ) {
     37#if 0
    3738        const int low = 5, High = 15, size = High - low;
    3839
     
    121122                 | sum( size, gs.x ) | ", check" | (int)s;              // add field array in generic type
    122123        delete( gs.x );
     124#else
     125        const int low = 5, High = 15, size = High - low;
     126
     127        signed char s = 0, a[size], v = (char)low;
     128        for ( int i = 0; i < size; i += 1, v += 1hh ) {
     129                s += v;
     130                a[i] = v;
     131        } // for
     132        printf( "sum from %d to %d is %hhd, check %hhd\n", low, High,
     133                 sum( size, (signed char *)a ), (signed char)s );
     134
     135        unsigned char s = 0, a[size], v = low;
     136        for ( int i = 0; i < size; i += 1, v += 1hhu ) {
     137                s += (unsigned char)v;
     138                a[i] = (unsigned char)v;
     139        } // for
     140        printf( "sum from %d to %d is %hhu, check %hhu\n", low, High,
     141                 sum( size, (unsigned char *)a ), (unsigned char)s );
     142
     143        short int s = 0, a[size], v = low;
     144        for ( int i = 0; i < size; i += 1, v += 1h ) {
     145                s += (short int)v;
     146                a[i] = (short int)v;
     147        } // for
     148        printf( "sum from %d to %d is %hd, check %hd\n", low, High,
     149                 sum( size, (short int *)a ), (short int)s );
     150
     151        int s = 0, a[size], v = low;
     152        for ( int i = 0; i < size; i += 1, v += 1 ) {
     153                s += (int)v;
     154                a[i] = (int)v;
     155        } // for
     156        printf( "sum from %d to %d is %d, check %d\n", low, High,
     157                 sum( size, (int *)a ), (int)s );
     158
     159        float s = 0.0f, a[size], v = low / 10.0f;
     160        for ( int i = 0; i < size; i += 1, v += 0.1f ) {
     161                s += (float)v;
     162                a[i] = (float)v;
     163        } // for
     164        printf( "sum from %g to %g is %g, check %g\n", low / 10.0f, High / 10.0f,
     165                 sum( size, (float *)a ), (float)s );
     166
     167        double s = 0.0, a[size], v = low / 10.0;
     168        for ( int i = 0; i < size; i += 1, v += 0.1 ) {
     169                s += (double)v;
     170                a[i] = (double)v;
     171        } // for
     172        printf( "sum from %g to %g is %g, check %g\n", low / 10.0f, High / 10.0f,
     173                 sum( size, (double *)a ), (double)s );
     174
     175        struct S { int i, j; };
     176        void ?{}( S & s ) { s.[i, j] = 0; }
     177        void ?{}( S & s, int i ) { s.[i, j] = [i, 0]; }
     178        void ?{}( S & s, int i, int j ) { s.[i, j] = [i, j]; }
     179        void ?{}( S & s, zero_t ) { s.[i, j] = 0; }
     180        void ?{}( S & s, one_t ) { s.[i, j] = 1; }
     181        S ?+?( S t1, S t2 ) { return (S){ t1.i + t2.i, t1.j + t2.j }; }
     182        S ?+=?( S & t1, S t2 ) { t1 = t1 + t2; return t1; }
     183        S ++?( S & t ) { t += (S){1}; return t; }
     184        S ?++( S & t ) { S temp = t; t += (S){1}; return temp; }
     185        ofstream & ?|?( ofstream & os, S v ) { return os | v.i | v.j; }
     186        void ?|?( ofstream & os, S v ) { (ofstream &)(os | v); nl( os ); }
     187
     188        S s = (S){0}, a[size], v = { low, low };
     189        for ( int i = 0; i < size; i += 1, v += (S){1} ) {
     190                s += (S)v;
     191                a[i] = (S)v;
     192        } // for
     193        printf( "sum from %d to %d is %d %d, check %d %d\n", low, High,
     194                 sum( size, (S *)a ).[i, j], s.[i, j] );
     195
     196        forall( otype Impl | sumable( Impl ) )
     197        struct GS {
     198                Impl * x, * y;
     199        };
     200        GS(int) gs;
     201        // FIX ME, resolution problem with anew not picking up the LH type
     202        gs.x = (typeof(gs.x))anew( size );                                      // create array storage for field
     203        s = 0; v = low;
     204        for ( int i = 0; i < size; i += 1, v += 1 ) {
     205                s += (int)v;
     206                gs.x[i] = (int)v;                                                               // set field array in generic type
     207        } // for
     208        printf( "sum from %d to %d is %d, check %d\n", low, High,
     209                 sum( size, gs.x ), (int)s );           // add field array in generic type
     210        delete( gs.x );
     211#endif
    123212} // main
    124213
Note: See TracChangeset for help on using the changeset viewer.