Changeset 0c327ce


Ignore:
Timestamp:
Jul 12, 2024, 3:30:06 PM (3 months ago)
Author:
JiadaL <j82liang@…>
Branches:
master
Children:
76b507d
Parents:
9c447e2
Message:
  1. Add bound check to Serial function: now compiler generates the unchecked functions in ImplementEnumFunc?, and enum.hfa implements the bound check on top. Todo: Wrapped the checked version into a trait; 2. countof is now works on any type that implement Countof(). Because Countof() is implemented in enum.hfa for all CfaEnum?, we can call countof on { T | CfaEnum?(T) }
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/enum.cfa

    r9c447e2 r0c327ce  
    55
    66#pragma GCC visibility push(default)
     7
     8forall( E | Serial( E ) ) {
     9    E fromInt( unsigned i ) {
     10        E upper = upperBound();
     11        E lower = lowerBound();
     12        // It is okay to overflow as overflow will be theoretically caught by the other bound
     13        assert( i <= fromInstance(upper) && i >= fromInstance(lower)
     14            &&  "Not a valid value");
     15        return fromInt_unsafe( i );
     16    }
     17
     18    E succ( E e ) {
     19        E upper = upperBound();
     20        assert( (fromInstance(e) < fromInstance(upper))
     21            && "Calling succ() on the last" );
     22        return succ_unsafe(e);
     23    }
     24
     25    E pred( E e ) {
     26        E lower = lowerBound();
     27        assert( (fromInstance(e) > fromInstance(lower))
     28            && "Calling pred() on the first" );
     29        return pred_unsafe(e);
     30    }
     31
     32    int Countof( __attribute__((unused)) E e ) {
     33        E upper = upperBound();
     34        E lower = lowerBound();
     35                return fromInstance( upper ) + fromInstance( lower ) + 1;
     36    }
     37}
    738
    839int scmp( const void * str1, const void * str2 ) {
  • libcfa/src/enum.hfa

    r9c447e2 r0c327ce  
    11#pragma once
    22
     3#include <assert.h>
    34#include "iostream.hfa"
    45
     
    1011forall( E | Bounded( E ) ) trait Serial {
    1112    unsigned fromInstance( E e );
     13    E fromInt_unsafe( unsigned i );
     14    E succ_unsafe( E e );
     15    E pred_unsafe( E e );
     16};
     17
     18forall( E | Serial( E ) ) {
    1219    E fromInt( unsigned i );
    1320    E succ( E e );
    1421    E pred( E e );
    15 };
     22    int Countof( E e );
     23}
     24
     25// forall( E | Bounded(E) ) trait SafeSerial {
     26//     // unsigned fromInstance( E e );
     27//     E fromInt_unsafe( unsigned i );
     28//     // E succ_unsafe( E e );
     29//     //E pred_unsafe( E e );
     30
     31//     unsigned fromInstance( E e );
     32//     E fromInt( unsigned i );
     33//     E succ( E e );
     34//     E pred( E e );
     35// };
    1636
    1737forall( E | Serial( E ) ) trait CfaEnum {
     
    3353        OSTYPE_VOID( E );
    3454}
    35 
    36 // forall( ostype & | ostream( ostype ), E | CfaEnum( E, quasi_void ) ) {
    37 //      ostype & ?|?( ostype &, E );
    38 //      OSTYPE_VOID( E );
    39 // }
    40 
    41 // Design two <- should go for this if we have change the cost model
    42 // forall( E | Serial( E ) ) trait CfaEnum {
    43 //     char * label( E e );
    44 //     unsigned int posn( E e );
    45 // };
    46 
    47 // forall( E, V| CfaEnum( E)) trait TypedEnum {
    48 //     V value( E e);
    49 // };
    5055
    5156static inline
  • src/AST/Expr.cpp

    r9c447e2 r0c327ce  
    284284// --- CountExpr
    285285
     286CountExpr::CountExpr( const CodeLocation & loc, const Expr * e )
     287: Expr( loc, new BasicType( BasicKind::LongUnsignedInt) ), expr(e), type( nullptr ) {}
     288
    286289CountExpr::CountExpr( const CodeLocation & loc, const Type * t )
    287 : Expr( loc, new BasicType( BasicKind::LongUnsignedInt) ), type( t ) {}
     290: Expr( loc, new BasicType( BasicKind::LongUnsignedInt) ), expr(nullptr), type( t ) {}
    288291
    289292// --- AlignofExpr
  • src/AST/Expr.hpp

    r9c447e2 r0c327ce  
    496496class CountExpr final : public Expr {
    497497public:
     498        ptr<Expr> expr;
    498499        ptr<Type> type;
    499500
     501        CountExpr( const CodeLocation & loc, const Expr * t );
    500502        CountExpr( const CodeLocation & loc, const Type * t );
    501503
  • src/AST/Pass.impl.hpp

    r9c447e2 r0c327ce  
    13391339                        maybe_accept( node, &CountExpr::result );
    13401340                }
    1341                 maybe_accept( node, &CountExpr::type );
     1341                if ( node->type ) {
     1342                        maybe_accept( node, &CountExpr::type );
     1343                } else {
     1344                        maybe_accept( node, &CountExpr::expr );
     1345                }
    13421346        }
    13431347        VISIT_END( Expr, node );
  • src/AST/Print.cpp

    r9c447e2 r0c327ce  
    11461146                os << "Count Expression on: ";
    11471147                ++indent;
    1148                 node->type->accept( *this );
     1148                if ( node->type ) node->type->accept( *this );
     1149                else safe_print( node->expr );
    11491150                --indent;
    11501151                postprint( node );
  • src/ControlStruct/TranslateEnumRange.cpp

    r9c447e2 r0c327ce  
    8181            ast::UntypedExpr::createCall( location, "upperBound", {} )  });
    8282    auto increment = ast::UntypedExpr::createCall( location,
    83         stmt->is_inc? "succ": "pred",
     83        stmt->is_inc? "succ_unsafe": "pred_unsafe",
    8484        { new ast::NameExpr( location, indexName ) });
    8585    auto assig = ast::UntypedExpr::createAssign( location, new ast::NameExpr( location, indexName ), increment );
  • src/Parser/parser.yy

    r9c447e2 r0c327ce  
    970970                        // $$ = new ExpressionNode( build_offsetOf( $3, build_varref( $5 ) ) );
    971971                }
     972        | COUNTOF unary_expression
     973                {  $$ = new ExpressionNode( new ast::CountExpr( yylloc, maybeMoveBuild( $2 ) ) ); }
    972974        | COUNTOF '(' type_no_function ')'
    973975                { $$ = new ExpressionNode( new ast::CountExpr( yylloc, maybeMoveBuildType( $3 ) ) ); }
    974         | COUNTOF unary_expression
    975                 { SemanticError( yylloc, "countof for expressions is currently unimplemented. "); $$ = nullptr; }
    976976        ;
    977977
  • src/ResolvExpr/CandidateFinder.cpp

    r9c447e2 r0c327ce  
    14851485
    14861486        void Finder::postvisit( const ast::CountExpr * countExpr ) {
    1487                 assert( countExpr->type );
    1488                 auto enumInst = countExpr->type.as<ast::EnumInstType>();
    1489                 if ( !enumInst ) {
    1490                         SemanticError( countExpr, "Count Expression only supports Enum Type as operand: ");
    1491                 }
    1492                 addCandidate( ast::ConstantExpr::from_ulong(countExpr->location, enumInst->base->members.size()), tenv );
     1487                const ast::UntypedExpr * untyped;
     1488                if ( countExpr->type ) {
     1489                        auto enumInst = countExpr->type.as<ast::EnumInstType>();
     1490                        if ( enumInst ) {
     1491                                addCandidate( ast::ConstantExpr::from_ulong(countExpr->location, enumInst->base->members.size()), tenv );
     1492                                return;
     1493                        }
     1494                        auto untypedFirst = ast::UntypedExpr::createCall( countExpr->location, "lowerBound", {} );
     1495                        auto castFirst = new ast::CastExpr( countExpr->location, untypedFirst , countExpr->type );
     1496                        untyped = ast::UntypedExpr::createCall(
     1497                                countExpr->location, "Countof", { castFirst }
     1498                        );
     1499                }
     1500                if (!untyped) untyped = ast::UntypedExpr::createCall(
     1501                                countExpr->location, "Countof", { countExpr->expr }
     1502                );
     1503                CandidateFinder finder( context, tenv );
     1504                finder.find( untyped );
     1505                CandidateList winners = findMinCost( finder.candidates );
     1506                if ( winners.size() == 0 ) {
     1507                        SemanticError( countExpr->expr, "Countof is not implemented for operand: " );
     1508                }
     1509                if ( winners.size() !=  1 ) {
     1510                        SemanticError( countExpr->expr, "Ambiguous expression in countof operand: " );
     1511                }
     1512                CandidateRef & choice = winners.front();
     1513                choice->expr = referenceToRvalueConversion( choice->expr, choice->cost );
     1514                addCandidate( *choice, choice->expr );
    14931515        }
    14941516
  • src/Validate/ImplementEnumFunc.cpp

    r9c447e2 r0c327ce  
    228228ast::FunctionDecl* EnumAttrFuncGenerator::genFromIntProto() const {
    229229        return genProto(
    230                 "fromInt",
     230                "fromInt_unsafe",
    231231                {new ast::ObjectDecl(getLocation(), "_i", new ast::BasicType(ast::BasicKind::UnsignedInt))},
    232232                {new ast::ObjectDecl(getLocation(), "_ret", new ast::EnumInstType(decl))}
     
    313313                genFromIntProto(),
    314314                genFromInstanceProto(),
    315                 genInstToInstFuncProto("succ"),
    316                 genInstToInstFuncProto("pred")
     315                genInstToInstFuncProto("succ_unsafe"),
     316                genInstToInstFuncProto("pred_unsafe")
    317317        };
    318318        for (auto& proto: protos) produceForwardDecl(proto);
Note: See TracChangeset for help on using the changeset viewer.