Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/SpecCost.cc

    rc6b4432 r978e5eb  
    2121#include "AST/Pass.hpp"
    2222#include "AST/Type.hpp"
     23#include "Common/PassVisitor.h"
     24#include "SynTree/Declaration.h"
     25#include "SynTree/Expression.h"
     26#include "SynTree/Type.h"
    2327
    2428namespace ResolvExpr {
     29
     30        /// Counts specializations in a type
     31        class CountSpecs : public WithShortCircuiting, public WithVisitorRef<CountSpecs> {
     32                int count = -1;  ///< specialization count (-1 for none)
     33
     34        public:
     35                int get_count() const { return count >= 0 ? count : 0; }
     36
     37                // mark specialization of base type
     38                void postvisit(PointerType*) { if ( count >= 0 ) ++count; }
     39
     40                // mark specialization of base type
     41                void postvisit(ArrayType*) { if ( count >= 0 ) ++count; }
     42
     43                // mark specialization of base type
     44                void postvisit(ReferenceType*) { if ( count >= 0 ) ++count; }
     45
     46                void postvisit(StructInstType*) { if ( count >= 0 ) ++count; }
     47                void postvisit(UnionInstType*) { if ( count >= 0 ) ++count; }
     48
     49        private:
     50                // takes minimum non-negative count over parameter/return list
     51                void takeminover( int& mincount, std::list<DeclarationWithType*>& dwts ) {
     52                        for ( DeclarationWithType* dwt : dwts ) {
     53                                count = -1;
     54                                maybeAccept( dwt->get_type(), *visitor );
     55                                if ( count != -1 && count < mincount ) mincount = count;
     56                        }
     57                }
     58
     59        public:
     60                // take minimal specialization value over ->returnVals and ->parameters
     61                void previsit(FunctionType* fty) {
     62                        int mincount = std::numeric_limits<int>::max();
     63                        takeminover( mincount, fty->parameters );
     64                        takeminover( mincount, fty->returnVals );
     65                        // add another level to mincount if set
     66                        count = mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
     67                        // already visited children
     68                        visit_children = false;
     69                }
     70
     71        private:
     72                // returns minimum non-negative count + 1 over type parameters (-1 if none such)
     73                int minover( std::list<Expression*>& parms ) {
     74                        int mincount = std::numeric_limits<int>::max();
     75                        for ( Expression* parm : parms ) {
     76                                count = -1;
     77                                maybeAccept( parm->result, *visitor );
     78                                if ( count != -1 && count < mincount ) mincount = count;
     79                        }
     80                        return mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
     81                }
     82
     83        public:
     84                // look for polymorphic parameters
     85                void previsit(StructInstType* sty) {
     86                        count = minover( sty->parameters );
     87                }
     88
     89                // look for polymorphic parameters
     90                void previsit(UnionInstType* uty) {
     91                        count = minover( uty->parameters );
     92                }
     93
     94                // note polymorphic type (which may be specialized)
     95                // xxx - maybe account for open/closed type variables
     96                void postvisit(TypeInstType*) { count = 0; }
     97
     98                // take minimal specialization over elements
     99                // xxx - maybe don't increment, tuple flattening doesn't necessarily specialize
     100                void previsit(TupleType* tty) {
     101                        int mincount = std::numeric_limits<int>::max();
     102                        for ( Type* ty : tty->types ) {
     103                                count = -1;
     104                                maybeAccept( ty, *visitor );
     105                                if ( count != -1 && count < mincount ) mincount = count;
     106                        }
     107                        count = mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
     108                        visit_children = false;
     109                }
     110        };
     111
     112        /// Returns the (negated) specialization cost for a given type
     113        int specCost( Type* ty ) {
     114                PassVisitor<CountSpecs> counter;
     115                maybeAccept( ty, *counter.pass.visitor );
     116                return counter.pass.get_count();
     117        }
    25118
    26119namespace {
Note: See TracChangeset for help on using the changeset viewer.