Beispiel #1
0
function PatternMatcherOnig($t_args, $inputs)
{
    grokit_assert(\count($inputs) == 1, 'PatternMatcherOnig GF only supports 1 input!');
    $pattern = get_first_key($t_args, ['pattern']);
    $inName = array_keys($inputs)[0];
    $inType = array_get_index($inputs, 0);
    $inTypeString = $inType->name();
    $validTypes = ['BASE::STRING_LITERAL'];
    grokit_assert(in_array($inTypeString, $validTypes), 'Unsupported input type ' . $inTypeString);
    $className = generate_name('PatternMatcherOnigGF');
    ?>

class <?php 
    echo $className;
    ?>
 {

    PatternMatcherOnig matcher;

public:
    <?php 
    echo $className;
    ?>
() :
        matcher("<?php 
    echo $pattern;
    ?>
")
    { }

    bool Filter( const <?php 
    echo $inType;
    ?>
 & <?php 
    echo $inName;
    ?>
 ) {
        return matcher.Match(<?php 
    echo $inName;
    ?>
);
    }
};

<?php 
    return ['kind' => 'GF', 'name' => $className, 'input' => $inputs, 'user_headers' => ['PatternMatcherOnig.h']];
}
Beispiel #2
0
/**
 *  GI that generates data in clusters, using a specified distribution for each
 *  cluster.
 *
 *  This GI requires the following template arguments:
 *      - 'n' or 0
 *          The number of tuples to generate. Note: this value is per task.
 *          The total number of tuples generated will be n_tasks * n
 *      - 'centers' or 1
 *          A list of configuration for the centers.
 *
 *  The following template arguments are optional:
 *      - 'outputs'
 *          If the outputs of the GI are not given implicitly, they can be
 *          specified in this template argument. The number of dimensions will
 *          be determined by the number of outputs.
 *
 *          All output types must be numeric real types. The default type for
 *          outputs is DOUBLE.
 *      - 'dist.lib' = 'std'
 *          Which library to use for generating distributions.
 *          Valid options are:
 *              - std
 *              - boost
 *      - 'seed' = null
 *          The seed to be used for the random number generator. This seed will
 *          be used to generate the seed for each task, and different runs with
 *          the same seed will produce the same data.
 *      - 'compute.sets' = 1
 *          The number of sets of tuples to compute at once.
 *
 *  Each center configuration is a functor with the form:
 *      dist_name(args)
 *
 *  The following distributions are supported:
 *      { Uniform Distributions }
 *      - uniform(a = 0, b = 1)
 *
 *      { Normal Distributions }
 *      - normal(mean = 0.0, std_dev = 1.0) [ synonyms: gaussian ]
 *      - inverse_gaussian(mean = 1, shape = 1) [ synonyms: inverse_normal ]
 *
 *      { Bernoulli Distributions }
 *      - binomial(t = 1, p = 0.5)
 *      - negative_binomial(k = 1, p = 0.5)
 *
 *      { Poisson Distributions }
 *      - exponential( lambda = 1 )
 *      - gamma(alpha = 1, beta = 1)    [ synonyms: Gamma ]
 */
function ClusterGen(array $t_args, array $outputs)
{
    $sys_headers = ['array', 'cinttypes'];
    $user_headers = [];
    $libraries = [];
    if (\count($outputs) == 0) {
        grokit_assert(array_key_exists('outputs', $t_args), 'ClusterGen: No outputs specified');
        $count = 0;
        foreach ($t_args['outputs'] as $type) {
            if (is_identifier($type)) {
                $type = lookupType($type);
            }
            grokit_assert(is_datatype($type), 'ClusterGen: Non data-type ' . $type . ' given as output');
            $name = 'output' . $count++;
            $outputs[$name] = $type;
        }
    }
    foreach ($outputs as $name => &$type) {
        if (is_null($type)) {
            $type = lookupType('base::DOUBLE');
        } else {
            grokit_assert($type->is('real'), 'ClusterGen: Non-real datatype ' . $type . ' given as output');
        }
    }
    $myOutputs = [];
    foreach ($outputs as $name => $type) {
        $myOutputs[$name] = $type;
    }
    $tSize = \count($outputs);
    $seed = get_default($t_args, 'seed', null);
    if ($seed !== null) {
        grokit_assert(is_int($seed), 'ClusterGen: Seed must be an integer or null.');
    } else {
        $user_headers[] = 'HashFunctions.h';
    }
    $distLib = get_default($t_args, 'dist.lib', 'std');
    $distNS = '';
    switch ($distLib) {
        case 'std':
            $sys_headers[] = 'random';
            $distNS = 'std';
            break;
        case 'boost':
            $sys_headers[] = 'boost/random.hpp';
            $distNS = 'boost::random';
            $libraries[] = 'boost_random-mt';
            if ($seed === null) {
                // Need random_device
                $sys_headers[] = 'boost/random/random_device.hpp';
                $libraries[] = 'boost_system-mt';
            }
            break;
        default:
            grokit_error('ClusterGen: Unknown RNG library ' . $distLib);
    }
    $distRNG = 'mt19937';
    $RNGtype = $distNS . '::' . $distRNG;
    $nTuples = get_first_key($t_args, ['n', '0']);
    grokit_assert(is_int($nTuples), 'ClusterGen: the number of tuples to be produced must be an integer.');
    $centers = get_first_key($t_args, ['centers', 1]);
    grokit_assert(is_array($centers), 'ClusterGen: centers must be an array of functors');
    $handleDist = function ($name, $args, $oType) use($distNS) {
        $distName = '';
        $distArgs = [];
        switch ($name) {
            case 'gaussian':
            case 'normal':
                $distName = $distNS . '::' . 'normal_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 2, 'ClusterGen: Normal distribution takes at most 2 arguments, ' . \count($args) . ' given');
                $mean = get_default($args, ['mean', 0], 0.0);
                $sigma = get_default($args, ['std_dev', 'sigma', 1], 1.0);
                grokit_assert(is_numeric($mean), 'ClusterGen: mean parameter of binomial distribution must be a real number.');
                grokit_assert(is_numeric($sigma), 'ClusterGen: sigma parameter of binomial distribution must be a real number.');
                $mean = floatval($mean);
                $sigma = floatval($sigma);
                $distArgs = [$mean, $sigma];
                break;
            case 'binomial':
                $distName = $distNS . '::' . 'binomial_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 2, 'ClusterGen: Binomial distribution takes at most 2 arguments, ' . \count($args) . ' given');
                $t = get_default($args, ['t', 0], 1);
                $p = get_default($args, ['p', 1], 0.5);
                grokit_assert(is_int($t), 'ClusterGen: t parameter of binomial distribution must be an integer.');
                grokit_assert(is_numeric($p), 'ClusterGen: p parameter of binomial distribution must be a real number.');
                $p = floatval($p);
                grokit_assert($p >= 0 && $p <= 1, 'ClusterGen: p parameter of binomial distribution must be in the range [0, 1]');
                grokit_assert($t >= 0, 'ClusterGen: t parameter of binomial distribution must be in the range [0, +inf)');
                $distArgs = [$t, $p];
                break;
            case 'negative_binomial':
                $distName = $distNS . '::' . 'negative_binomial_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 2, 'ClusterGen: Negative Binomial distribution takes at most 2 arguments, ' . \count($args) . ' given');
                $k = get_default($args, ['k', 0], 1);
                $p = get_default($args, ['p', 1], 0.5);
                grokit_assert(is_int($k), 'ClusterGen: k parameter of binomial distribution must be an integer.');
                grokit_assert(is_numeric($p), 'ClusterGen: p parameter of binomial distribution must be a real number.');
                $p = floatval($p);
                grokit_assert($p > 0 && $p <= 1, 'ClusterGen: p parameter of negative binomial distribution must be in the range (0, 1]');
                grokit_assert($k > 0, 'ClusterGen: k parameter of negative binomial distribution must be in the range (0, +inf)');
                $distArgs = [$k, $p];
                break;
            case 'inverse_gaussian':
            case 'inverse_normal':
                grokit_assert(\count($args) <= 2, 'ClusterGen: Inverse Gaussian distribution takes at most 2 arguments, ' . \count($args) . ' given');
                $mean = get_default($args, ['mean', 0], 1);
                $shape = get_default($args, ['shape', 1], 1);
                grokit_assert(is_numeric($mean), 'ClusterGen: mean parameter of inverse gaussian distribution must be a real number.');
                grokit_assert(is_numeric($shape), 'ClusterGen: shape parameter of inverse gaussian distribution must be a real number.');
                $mean = floatval($mean);
                $shape = floatval($shape);
                grokit_assert($mean > 0, 'ClusterGen: mean of inverse gaussian distribution must be in range (0, inf)');
                grokit_assert($shape > 0, 'ClusterGen: shape of inverse gaussian distribution must be in range (0, inf)');
                $gen_args = ['output' => $oType, 'ns' => $distNS];
                $distName = strval(lookupResource('datagen::InverseGaussianGen', $gen_args));
                $distArgs = [$mean, $shape];
                break;
            case 'uniform':
                $distName = $distNS . '::' . 'uniform_real_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 2, 'ClusterGen: Uniform distribution takes at most 2 arguments, ' . \count($args) . ' given');
                $a = get_default($args, ['a', 0], 0.0);
                $b = get_default($args, ['b', 1], 1.0);
                grokit_assert(is_numeric($a), 'ClusterGen: `a` parameter of uniform distribution must be a real number.');
                grokit_assert(is_numeric($b), 'ClusterGen: `b` parameter of uniform distribution must be a real number.');
                $a = floatval($a);
                $b = floatval($b);
                grokit_assert($b >= $a, 'ClusterGen: `b` parameter of uniform distribution must be >= the `a` parameter.');
                $distArgs = [$a, $b];
                break;
            case 'exponential':
                $distName = $distNS . '::' . 'exponential_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 1, 'ClusterGen: Exponential distribution takes at most 1 argument.');
                $lambda = get_default($args, ['lambda', 0], 1.0);
                grokit_assert(is_numeric($lambda), 'ClusterGen: `lambda` parameter of exponential distribution must be a real number.');
                $lambda = floatval($lambda);
                grokit_assert($lambda > 0, 'ClusterGen: `lambda` parameter of exponential distribution must be in range (0, +inf).');
                $distArgs = [$lambda];
                break;
            case 'gamma':
            case 'Gamma':
                $distName = $distNS . '::' . 'gamma_distribution<' . $oType . '>';
                grokit_assert(\count($args) <= 2, 'ClusterGen: Gamma distribution takes at most 2 arguments.');
                $alpha = get_default($args, ['alpha', 0], 1.0);
                $beta = det_default($args, ['beta', 1], 1.0);
                grokit_assert(is_numeric($alpha), 'ClusterGen: `alpha` parameter of gamma distribution must be a real number.');
                grokit_assert(is_numeric($beta), 'ClusterGen: `beta` parameter of gamma distribution must be a real number.');
                $alpha = floatval($alpha);
                $beta = floatval($beta);
                $distArgs = [$alpha, $beta];
                break;
            default:
                grokit_error('ClusterGen: Unknown distribution ' . $name . ' given for center');
        }
        return [$distName, $distArgs];
    };
    $dists = [];
    $distArgs = [];
    $count = 0;
    $oType = '';
    $nCenters = 1;
    reset($outputs);
    foreach ($centers as $val) {
        $cluster = $val;
        if (is_functor($val)) {
            $cluster = [$val];
        } else {
            if (is_array($val)) {
                $nCenters = lcm($nCenters, \count($val));
            } else {
                grokit_error('ClusterGen: center descriptions must be functors or list of functors');
            }
        }
        $curDist = [];
        $curDistArgs = [];
        $curDistName = 'distribution' . $count++;
        $oType = strval(current($outputs));
        $iCount = 0;
        foreach ($cluster as $functor) {
            grokit_assert(is_functor($functor), 'ClusterGen: center description must be a functor');
            $vName = $curDistName . '_' . $iCount++;
            $ret = $handleDist($functor->name(), $functor->args(), $oType);
            $curDist[$vName] = $ret[0];
            $curDistArgs[$vName] = $ret[1];
        }
        next($outputs);
        $dists[$curDistName] = $curDist;
        $distArgs[$curDistName] = $curDistArgs;
    }
    // Determine the default number of sets to compute at a time.
    // We want to generate either $nTuples or 10,000 tuples, depending on which
    // is less.
    $defaultSetsTarget = min($nTuples, 10000);
    $setsToTarget = intval(ceil($defaultSetsTarget / $nCenters));
    $computeSets = get_default($t_args, 'compute.sets', $setsToTarget);
    grokit_assert(is_int($computeSets) && $computeSets > 0, 'ClusterGen: compute.sets must be a positive integer, ' . $computeSets . ' given');
    $className = generate_name('ClusterGen');
    // For some BIZZARE reason, the $outputs array was getting modified while
    // traversing over the $dists array. Making a deep copy of the outputs and
    // then reassigning it seems to fix the issue.
    $outputs = $myOutputs;
    ?>

class <?php 
    echo $className;
    ?>
 {

    // The number of tuples to produce per task
    static constexpr size_t N = <?php 
    echo $nTuples;
    ?>
;
    static constexpr size_t CacheSize = <?php 
    echo $computeSets * $nCenters;
    ?>
;

    // Typedefs
    typedef std::tuple<<?php 
    echo array_template('{val}', ', ', $outputs);
    ?>
> Tuple;
    typedef std::array<Tuple, CacheSize> TupleArray;
    typedef TupleArray::const_iterator TupleIterator;
    typedef <?php 
    echo $RNGtype;
    ?>
 RandGen;

    // Number of tuples produced.
    uintmax_t count;

    // Cache a number of outputs for efficiency
    TupleArray cache;
    TupleIterator cacheIt;

    // Random number generator
    RandGen rng;

    // Distributions
<?php 
    // This is the section causing issues.
    foreach ($dists as $name => $list) {
        foreach ($list as $vName => $type) {
            ?>
    <?php 
            echo $type;
            ?>
 <?php 
            echo $vName;
            ?>
;
<?php 
        }
        // foreach distribution
    }
    // foreach cluster set
    ?>

    // Helper function to generate tuples.
    void GenerateTuples(void) {
<?php 
    $tIndex = 0;
    foreach ($dists as $name => $list) {
        $lCenters = \count($list);
        // $nCenters has been defined to be the LCM of the number of centers in
        // any column, so $lCenter is guaranteed to divide evenly into
        // CacheSize
        ?>
        for( size_t index = 0; CacheSize > index; index += <?php 
        echo $lCenters;
        ?>
 ) {
<?php 
        $index = 0;
        foreach ($list as $vName => $type) {
            ?>
            std::get<<?php 
            echo $tIndex;
            ?>
>(cache[index + <?php 
            echo $index;
            ?>
]) = <?php 
            echo $vName;
            ?>
(rng);
<?php 
            $index++;
        }
        // foreach value in tuple
        ?>
        }
<?php 
        $tIndex++;
    }
    // foreach distribution
    ?>
        cacheIt = cache.cbegin();
    }

public:
    // Constructor
    <?php 
    echo $className;
    ?>
( GIStreamProxy & _stream ) :
        cache()
        , cacheIt()
        , count(0)
        , rng()
<?php 
    foreach ($dists as $name => $list) {
        foreach ($list as $vName => $type) {
            ?>
        , <?php 
            echo $vName;
            ?>
(<?php 
            echo implode(', ', $distArgs[$name][$vName]);
            ?>
)
<?php 
        }
        // foreach distribution
    }
    // foreach cluster set
    ?>

    {
<?php 
    if (is_null($seed)) {
        ?>
        <?php 
        echo $distNS;
        ?>
::random_device rd;
<?php 
    }
    // if seed is null
    ?>
        RandGen::result_type seed = <?php 
    echo is_null($seed) ? 'rd()' : "CongruentHash({$seed}, _stream.get_id() )";
    ?>
;
        rng.seed(seed);

        cacheIt = cache.cend();
    }

    // Destructor
    ~<?php 
    echo $className;
    ?>
(void) { }

    bool ProduceTuple(<?php 
    echo typed_ref_args($outputs);
    ?>
) {
        if( N > count ) {
            if( cacheIt == cache.cend() ) {
                GenerateTuples();
            }
<?php 
    $tIndex = 0;
    foreach ($outputs as $name => $type) {
        ?>
            <?php 
        echo $name;
        ?>
 = std::get<<?php 
        echo $tIndex;
        ?>
>(*cacheIt);
<?php 
        $tIndex++;
    }
    // foreach output
    ?>

            ++cacheIt;
            ++count;

            return true;
        }
        else {
            return false;
        }
    }
};

<?php 
    return array('kind' => 'GI', 'name' => $className, 'output' => $outputs, 'system_headers' => $sys_headers, 'user_headers' => $user_headers, 'libraries' => $libraries);
}
Beispiel #3
0
function ExtremeTuples(array $t_args, array $inputs, array $outputs)
{
    $extremes = get_first_key($t_args, ['extremes']);
    $nExt = \count($extremes);
    grokit_assert($nExt > 0, 'No extremes specified for ExtremeTuples GLA.');
    if (\count($inputs) == 0) {
        grokit_assert(array_key_exists('inputs', $t_args), 'No arguments specified for ExtremeTuples GLA.');
        $count = 0;
        foreach ($t_args['inputs'] as $type) {
            if (is_identifier($type)) {
                $type = lookupType(strval($type));
            }
            grokit_assert(is_datatype($type), 'Only datatypes can be specified as inputs to ' . 'the ExtremeTuples GLA');
            $name = 'et_val' . $count;
            $inputs[$name] = $type;
        }
    }
    $outputMap = [];
    reset($outputs);
    foreach ($inputs as $name => $type) {
        $oKey = key($outputs);
        $outputs[$oKey] = $type;
        $outputMap[$oKey] = $name;
        next($outputs);
    }
    grokit_assert($nExt <= \count($inputs), 'There can not be more extreme values than there are inputs!');
    $mainAtts = [];
    $extraAtts = [];
    $minOpts = ['MIN', 'MINIMUM', '-', '<'];
    $maxOpts = ['MAX', 'MAXIMUM', '+', '>'];
    $inArrayCase = function ($needle, $haystack) {
        foreach ($haystack as $item) {
            if (strcasecmp($needle, $item) == 0) {
                return true;
            }
        }
        return false;
    };
    $minimum = [];
    foreach ($extremes as $name => $val) {
        grokit_assert(array_key_exists($name, $inputs), "ExtremeTuples: Expression with name " . $name . " specified as extreme not found in inputs");
    }
    foreach ($inputs as $name => $type) {
        if (array_key_exists($name, $extremes)) {
            $mainAtts[$name] = $type;
            if ($inArrayCase($extremes[$name], $minOpts)) {
                $minimum[$name] = true;
            } else {
                if ($inArrayCase($extremes[$name], $maxOpts)) {
                    $minimum[$name] = false;
                } else {
                    grokit_error('Unknown extreme type ' . $extremes[$name] . ' specified for ' . $name);
                }
            }
        } else {
            $extraAtts[$name] = $type;
        }
    }
    $debug = get_default($t_args, 'debug', 0);
    $className = generate_name('ExtremeTuples');
    ?>

class <?php 
    echo $className;
    ?>
 {

    struct Tuple {
<?php 
    foreach ($inputs as $name => $type) {
        ?>
        <?php 
        echo $type;
        ?>
 <?php 
        echo $name;
        ?>
;
<?php 
    }
    // foreach input
    ?>

        // Default Constructor, Copy Constructor, and Copy Assignment are all
        // default
        Tuple(void) = default;
        Tuple(const Tuple &) = default;
        Tuple & operator = (const Tuple &) = default;

        Tuple(<?php 
    echo array_template('const {val} & _{key}', ', ', $inputs);
    ?>
) :
            <?php 
    echo array_template('{key}(_{key})', ', ', $inputs);
    ?>

        { }

        // operator > means that this tuple is "better" than the other tuple.
        bool operator > ( const Tuple & other ) const {
<?php 
    foreach ($mainAtts as $name => $type) {
        $op1 = $minimum[$name] ? '<' : '>';
        $op2 = !$minimum[$name] ? '<' : '>';
        ?>
            if( <?php 
        echo $name;
        ?>
 <?php 
        echo $op1;
        ?>
 other.<?php 
        echo $name;
        ?>
 )
                return true;
            else if( <?php 
        echo $name;
        ?>
 <?php 
        echo $op2;
        ?>
 other.<?php 
        echo $name;
        ?>
 )
                return false;
<?php 
    }
    // foreach main attribute
    ?>

            return false;
        }

        bool operator < ( const Tuple& other ) const {
            return other > *this;
        }

        bool operator <= (const Tuple & other ) const {
            return ! (*this > other );
        }

        bool operator >= (const Tuple & other ) const {
            return !( other > *this );
        }

        bool operator == (const Tuple & other ) const {
            bool ret = true;
<?php 
    foreach ($mainAtts as $name => $type) {
        ?>
            ret &= <?php 
        echo $name;
        ?>
 == other.<?php 
        echo $name;
        ?>
;
<?php 
    }
    // foreach main attribute
    ?>
            return ret;
        }
    }; // struct Tuple

    typedef std::vector<Tuple> TupleVector;
public:
    class Iterator {
    public:
        typedef TupleVector::const_iterator iter_type;

    private:
        iter_type begin;
        iter_type end;

    public:
        Iterator(void) = default;
        Iterator(const Iterator &) = default;
        Iterator( const iter_type & _begin, const iter_type & _end ) : begin(_begin), end(_end)
        { }
        Iterator( const iter_type && _begin, const iter_type && _end ) : begin(_begin), end(_end)
        { }

        bool GetNextResult(<?php 
    echo typed_ref_args($outputs);
    ?>
) {
            if( begin != end ) {
<?php 
    foreach ($outputs as $name => $type) {
        ?>
                <?php 
        echo $name;
        ?>
 = begin-><?php 
        echo $outputMap[$name];
        ?>
;
<?php 
    }
    ?>
                begin++;
                return true;
            }
            else {
                return false;
            }
        }

    };

private:

    uintmax_t __count;  // number of tuples covered

    TupleVector tuples;

    // Iterator for multi output type
    Iterator multiIterator;

public:
    // Constructor and destructor
    <?php 
    echo $className;
    ?>
(void) : __count(0), tuples(), multiIterator()
    { }

    ~<?php 
    echo $className;
    ?>
() { }

    void AddItem( <?php 
    echo const_typed_ref_args($inputs);
    ?>
 ) {
        ++__count;
        Tuple t(<?php 
    echo args($inputs);
    ?>
);

        if( tuples.empty() ) {
            tuples.push_back(t);
        }
        else if( t > tuples.front() ) {
            tuples.clear();
            tuples.push_back(t);
        }
        else if( t == tuples.front() ) {
            tuples.push_back(t);
        }
    }

    void AddState( <?php 
    echo $className;
    ?>
 & other ) {
        if( tuples.size() == 0 ) {
            tuples.swap(other.tuples);
        }
        else if( other.tuples.size() == 0 ) {
            // Do nothing
        }
        else if( tuples.front() > other.tuples.front() ) {
            // fast path
        }
        else if( other.tuples.front() > tuples.front() ) {
            tuples.swap(other.tuples);
        }
        else {
            for( Tuple & t : other.tuples ) {
                tuples.push_back(t);
            }
        }
    }

    void Finalize( void ) {
        multiIterator = Iterator(tuples.cbegin(), tuples.cend());
    }

    bool GetNextResult(<?php 
    echo typed_ref_args($outputs);
    ?>
) {
        return multiIterator.GetNextResult(<?php 
    echo args($outputs);
    ?>
);
    }
}; // class <?php 
    echo $className;
    ?>

<?php 
    $system_headers = ['vector', 'algorithm', 'cinttypes'];
    if ($debug > 0) {
        $system_headers = array_merge($system_headers, ['iostream', 'sstream', 'string']);
    }
    return array('kind' => 'GLA', 'name' => $className, 'input' => $inputs, 'output' => $outputs, 'result_type' => 'multi', 'system_headers' => $system_headers);
}
Beispiel #4
0
function STATE(array $t_args)
{
    $type = get_first_key($t_args, ['type', '0']);
    grokit_assert(is_gla($type), 'Template argument to STATE must be a valid GLA.');
    $type = $type->lookup();
    $gContent = '';
    $functions = [];
    $methods = [];
    $className = generate_name('STATE_');
    ?>

/** Type definition for generic GLA states. This type is only used to
    trannsport states withing the same memory space between
    operators. The object the state points to MUST be treated like a
    const.

    Note: this type cannot be read from the disk or written to the
    output. A different mechanism will be used for that.

    The type in the object must be a hash of the name of the class
    used to encode the object. Any function that assumes a certain
    type must explicitly verify the correctness of the type.

    The object can be manipulated like a basic datatype. STATE objects
    do not know how to deallocate the memory they use. Other
    mechanisms have to be used to ensure correct deallocation
    (acknowledgements of data packets that contain this as members).

**/

class <?php 
    echo $className;
    ?>
 {
public:
    typedef <?php 
    echo $type;
    ?>
* pointer_type;
    typedef uint64_t hash_type;

private:
    pointer_type object;
    hash_type type;

public:

    <?php 
    echo $className;
    ?>
():
        object(nullptr),
        type(0)
    {}
    <?php 
    echo $className;
    ?>
(pointer_type _object):
        object(_object),
        type(<?php 
    echo $type->cHash();
    ?>
)
    {}

    pointer_type GetObject() const {
        FATALIF(type != <?php 
    echo $type->cHash();
    ?>
, "STATE contains incorrect type!");
        return object;
    }

<?php 
    $methods[] = ['IsNull', [], 'BASE::BOOL', true];
    ?>
    bool IsNull() const {
        return object == nullptr;
    }

    /** no destructor. object should not be deallocated here */
};

<?php 
    ob_start();
    ?>

<?php 
    $functions[] = ['IsNull', ['@type'], 'BASE::BOOL', true, true];
    ?>
inline
bool IsNull( const @type & d ) {
    return d.IsNull();
}

<?php 
    $gContent .= ob_get_clean();
    ?>

<?php 
    return array('kind' => 'TYPE', 'name' => $className, "complex" => false, 'extras' => ['type' => $type], 'properties' => ['__state__'], 'global_content' => $gContent, 'methods' => $methods, 'functions' => $functions);
}
Beispiel #5
0
function CATEGORY(array $t_args)
{
    if (array_key_exists('dict', $t_args)) {
        $values = $t_args['dict'];
        $maxID = 0;
        foreach ($values as $id => $val) {
            $maxID = \max($id, $maxID);
        }
    } else {
        $old_vals = get_first_key($t_args, ['values', 0]);
        $startAt = get_first_key_default($t_args, ['start.at'], 0);
        $values = [];
        $maxID = $startAt;
        foreach ($old_vals as $ind => $val) {
            $values[$maxID++] = $val;
        }
    }
    $cardinality = \count($values);
    // Add 1 to the cardinality for the invalid id
    $storageTypeBits = ceil(log($maxID + 1, 2));
    if ($storageTypeBits > 64) {
        // This should never happen. PHP would explode processing 2^64 values.
        grokit_error("Unable to store {$cardinality} values within 64 bits.");
    } else {
        if ($storageTypeBits > 32) {
            $storageType = 'uint64_t';
            $storageBytes = 8;
        } else {
            if ($storageTypeBits > 16) {
                $storageType = 'uint32_t';
                $storageBytes = 4;
            } else {
                if ($storageTypeBits > 8) {
                    $storageType = 'uint16_t';
                    $storageBytes = 2;
                } else {
                    $storageType = 'uint8_t';
                    $storageBytes = 1;
                }
            }
        }
    }
    $className = generate_name('CATEGORY');
    $stringType = lookupType('base::STRING');
    $methods = [];
    $constructors = [];
    $functions = [];
    ?>

class <?php 
    echo $className;
    ?>
 {
public:
    typedef <?php 
    echo $storageType;
    ?>
 StorageType;
    typedef std::unordered_map<StorageType, std::string> IDToNameMap;
    typedef std::unordered_map<std::string, StorageType> NameToIDMap;

    static const StorageType InvalidID __attribute__((weak));

private:
    static const IDToNameMap idToName __attribute__((weak));
    static const NameToIDMap nameToID __attribute__((weak));

    // The ID of this categorical variable
    StorageType myID;

public:

    /* ----- Constructors / Destructor ----- */
    <?php 
    echo $className;
    ?>
( void );

<?php 
    $constructors[] = [['base::STRING_LITERAL'], true];
    ?>
    <?php 
    echo $className;
    ?>
( const char * );
<?php 
    $constructors[] = [['base::STRING'], true];
    ?>
    <?php 
    echo $className;
    ?>
( const <?php 
    echo $stringType;
    ?>
 & );
    <?php 
    echo $className;
    ?>
( const <?php 
    echo $storageType;
    ?>
 );
    <?php 
    echo $className;
    ?>
( const <?php 
    echo $className;
    ?>
 & );
<?php 
    $constructors[] = [['BASE::NULL'], true];
    ?>
    <?php 
    echo $className;
    ?>
( const GrokitNull & );

    <?php 
    echo $className;
    ?>
 & operator =( const <?php 
    echo $className;
    ?>
 & ) = default;

    ~<?php 
    echo $className;
    ?>
(void) {}

    /* ----- Methods ----- */
    void FromString( const char * );

<?php 
    $methods[] = ['ToString', [], 'base::STRING_LITERAL', true];
    ?>
    const char * ToString( void ) const;

    StorageType GetID( void ) const;
    void SetID( StorageType id );

    // Determines whether or not the category is valid.
<?php 
    $methods[] = ['Invalid', [], 'base::bool', true];
    ?>
    bool Invalid(void) const;
<?php 
    $methods[] = ['Valid', [], 'base::bool', true];
    ?>
    bool Valid(void) const;

    /* ----- Operators ----- */
    bool operator ==( const <?php 
    echo $className;
    ?>
 & ) const;
    bool operator !=( const <?php 
    echo $className;
    ?>
 & ) const;
    bool operator <( const <?php 
    echo $className;
    ?>
 & ) const;
    bool operator <=( const <?php 
    echo $className;
    ?>
 & ) const;
    bool operator >( const <?php 
    echo $className;
    ?>
 & ) const;
    bool operator >=( const <?php 
    echo $className;
    ?>
 & ) const;

    // Implicit conversion to storage type
    operator <?php 
    echo $storageType;
    ?>
() const;

    // To/From Json
    void toJson( Json::Value & dest ) const;
    void fromJson( const Json::Value & src );
};

/* ----- Constructors ----- */

inline
<?php 
    echo $className;
    ?>
 :: <?php 
    echo $className;
    ?>
( void ) :
    myID(InvalidID)
{ }

inline
<?php 
    echo $className;
    ?>
 :: <?php 
    echo $className;
    ?>
( const char * str ) {
    FromString(str);
}

inline
<?php 
    echo $className;
    ?>
 :: <?php 
    echo $className;
    ?>
( const <?php 
    echo $stringType;
    ?>
 & str ) {
    FromString(str.ToString());
}

inline
<?php 
    echo $className;
    ?>
 :: <?php 
    echo $className;
    ?>
( const <?php 
    echo $storageType;
    ?>
 val ) :
    myID(val)
{ }

inline
<?php 
    echo $className;
    ?>
 :: <?php 
    echo $className;
    ?>
( const <?php 
    echo $className;
    ?>
 & other ) : myID(other.myID)
{ }

inline
<?php 
    echo $className;
    ?>
 :: <?php 
    echo $className;
    ?>
( const GrokitNull & nullval ) : myID(InvalidID)
{ }

/* ----- Methods ----- */

inline
void <?php 
    echo $className;
    ?>
 :: FromString( const char * str ) {
    auto it = nameToID.find(str);
    if( it != nameToID.end() ) {
        myID = it->second;
    }
    else {
        myID = InvalidID;
    }
}

inline
const char * <?php 
    echo $className;
    ?>
 :: ToString( void ) const {
    auto it = idToName.find(myID);
    if( it != idToName.end() ) {
        return it->second.c_str();
    }
    else {
        return "NULL";
    }
}

inline
auto <?php 
    echo $className;
    ?>
 :: GetID( void ) const -> StorageType {
    return myID;
}

inline
void <?php 
    echo $className;
    ?>
 :: SetID( StorageType id ) {
    myID = id;
}

inline
bool <?php 
    echo $className;
    ?>
 :: Valid(void) const {
    return idToName.count(myID) > 0;
}

inline
bool <?php 
    echo $className;
    ?>
 :: Invalid(void) const {
    return ! Valid();
}


/* ----- Operators ----- */
inline
bool <?php 
    echo $className;
    ?>
 :: operator ==( const <?php 
    echo $className;
    ?>
 & other ) const {
    return myID == other.myID;
}

inline
bool <?php 
    echo $className;
    ?>
 :: operator !=( const <?php 
    echo $className;
    ?>
 & other ) const {
    return myID != other.myID;
}

inline
bool <?php 
    echo $className;
    ?>
 :: operator <( const <?php 
    echo $className;
    ?>
 & other ) const {
    return myID < other.myID;
}

inline
bool <?php 
    echo $className;
    ?>
 :: operator >( const <?php 
    echo $className;
    ?>
 & other ) const {
    return myID > other.myID;
}

inline
bool <?php 
    echo $className;
    ?>
 :: operator <=( const <?php 
    echo $className;
    ?>
 & other ) const {
    return myID <= other.myID;
}

inline
bool <?php 
    echo $className;
    ?>
 :: operator >=( const <?php 
    echo $className;
    ?>
 & other ) const {
    return myID >= other.myID;
}

// To/From Json
inline
void <?php 
    echo $className;
    ?>
 :: toJson( Json::Value & dest ) const {
    dest = (Json::Int64) myID;
}

inline
void <?php 
    echo $className;
    ?>
 :: fromJson( const Json::Value & src ) {
    myID = (StorageType) src.asInt64();
}

inline
<?php 
    echo $className;
    ?>
 :: operator <?php 
    echo $storageType;
    ?>
 () const {
    return myID;
}

<?php 
    ob_start();
    $functions[] = ['Hash', ['@type'], 'base::BIGINT', true, true];
    ?>
template<>
inline
uint64_t Hash(const @type & thing) {
    return thing.GetID();
}

inline
void FromString( @type & c, const char * str ) {
    c.FromString(str);
}

inline
int ToString( const @type & c, char * buffer ) {
    const char * str = c.ToString();
    strcpy( buffer, str);
    int len = strlen(buffer);
    return len + 1;
}

inline
void ToJson( const @type & src, Json::Value & dest ) {
    src.toJson(dest);
}

inline
void FromJson( const Json::Value & src, @type & dest ) {
    dest.fromJson(src);
}

<?php 
    $functions[] = ['IsNull', ['@type'], 'BASE::BOOL', true, true];
    ?>
inline
bool IsNull( const @type c ) {
    return c.Invalid();
}
<?php 
    $globalContents = ob_get_clean();
    ?>

// Initialize static values
const <?php 
    echo $className;
    ?>
::IDToNameMap <?php 
    echo $className;
    ?>
 :: idToName = { <?php 
    echo array_template('{{key},"{val}"}', ',', $values);
    ?>
 };
const <?php 
    echo $className;
    ?>
::NameToIDMap <?php 
    echo $className;
    ?>
 :: nameToID = { <?php 
    echo array_template('{"{val}",{key}}', ',', $values);
    ?>
 };
const <?php 
    echo $className;
    ?>
::StorageType <?php 
    echo $className;
    ?>
 :: InvalidID = std::numeric_limits<<?php 
    echo $className;
    ?>
::StorageType>::max();

<?php 
    return ['kind' => 'TYPE', 'name' => $className, 'properties' => ['categorical'], 'extras' => ['cardinality' => $cardinality, 'size.bytes' => $storageBytes], 'binary_operators' => ['==', '!=', '<', '>', '<=', '>='], 'system_headers' => ['cinttypes', 'unordered_map', 'string', 'cstring', 'limits'], 'global_content' => $globalContents, 'complex' => false, 'methods' => $methods, 'constructors' => $constructors, 'functions' => $functions, 'describe_json' => DescribeJson('factor', DescribeJsonStatic(['levels' => $values]))];
}
Beispiel #6
0
function Multiplexer(array $t_args, array $inputs, array $outputs)
{
    $className = generate_name('Multiplexer');
    if (\count($inputs) == 0) {
        grokit_assert(array_key_exists('input', $t_args), 'No inputs specified for Multiplexer');
        $inputs = $t_args['input'];
        foreach ($t_args['inputs'] as $name => &$type) {
            if (is_identifier($type)) {
                $type = lookupType(strval($type));
            }
            grokit_assert(is_datatype($type), 'Only types may be specified as inputs to Multiplexer.');
        }
        $inputs = ensure_valid_names($inputs, 'multi_input');
    }
    $glas = get_first_key($t_args, ['glas', 0]);
    grokit_assert(\count($glas) > 0, 'No GLAs specified for Multiplexer.');
    $myGLAs = [];
    $glaInputs = [];
    $glaOutputs = [];
    $resultType = 'multi';
    $usedOutputs = [];
    $libraries = [];
    $glaGenStates = [];
    $glaReqStates = [];
    $configurable = false;
    $constArgs = [];
    $genStates = [];
    $reqStates = [];
    $iterable = null;
    foreach ($glas as $name => $glaInfo) {
        grokit_assert(is_array($glaInfo), 'Template argument \'glas\' must be an array');
        grokit_assert(array_key_exists('gla', $glaInfo), 'No GLA given for glas[' . $name . ']');
        grokit_assert(array_key_exists('inputs', $glaInfo), 'No inputs given for glas[' . $name . ']');
        grokit_assert(array_key_exists('outputs', $glaInfo), 'No outputs given for glas[' . $name . ']');
        $gla = $glaInfo['gla'];
        $glaInAtts = $glaInfo['inputs'];
        $glaOutAtts = $glaInfo['outputs'];
        grokit_assert(is_gla($gla), 'Non-GLA given for glas[' . $name . '][gla]');
        grokit_assert(is_array($glaInAtts), 'Non-array given for inputs for gla ' . $name);
        grokit_assert(is_array($glaOutAtts), 'Non-array given for outputs for gla ' . $name);
        $glaInAtts = array_map('strval', $glaInAtts);
        $glaOutAtts = array_map('strval', $glaOutAtts);
        $glaName = "innerGLA_" . $name;
        $glaInputs[$glaName] = [];
        $glaOutputs[$glaName] = [];
        foreach ($glaInAtts as $att) {
            grokit_assert(array_key_exists($att, $inputs), 'Input ' . $att . ' for GLA ' . $name . ' not found in inputs');
            $glaInputs[$glaName][$att] = $inputs[$att];
        }
        foreach ($glaOutAtts as $att) {
            grokit_assert(array_key_exists($att, $outputs), 'Output ' . $att . ' for GLA ' . $name . ' not found in outputs');
            grokit_assert(!in_array($att, $usedOutputs), 'Output ' . $att . ' used by multiple GLAs');
            $usedOutputs[] = $att;
            $glaOutputs[$glaName][$att] = $outputs[$att];
        }
        //fwrite(STDERR, "Inputs for GLA " . $glaName . ": " . print_r($glaInputs[$glaName], true) . PHP_EOL );
        //fwrite(STDERR, "Outputs for GLA " . $glaName . ": " . print_r($glaOutputs[$glaName], true) . PHP_EOL );
        $gla = $gla->apply($glaInputs[$glaName], $glaOutputs[$glaName]);
        $myGLAs[$glaName] = $gla;
        $glaRez[$glaName] = get_first_value($gla->result_type(), ['multi', 'single', 'state']);
        $libraries = array_merge($libraries, $gla->libraries());
        if ($glaRez[$glaName] == 'state') {
            grokit_assert(\count($glaOutputs[$glaName]) == 1, "GLA {$glaName} is produced as state, and thus must have exactly 1 output.");
            $stateType = lookupType('base::STATE', ['type' => $gla]);
            $glaOutputs[$glaName] = array_combine(array_keys($glaOutputs[$glaName]), [$stateType]);
        } else {
            grokit_assert(\count($glaOutputs[$glaName]) == \count($gla->output()), 'GLA ' . $glaName . ' produces different number of outputs than expected');
            $glaOutputs[$glaName] = array_combine(array_keys($glaOutputs[$glaName]), $gla->output());
        }
        // Set types for our output
        foreach ($glaOutputs[$glaName] as $attName => $type) {
            $outputs[$attName] = $type;
        }
        if (is_null($iterable)) {
            $iterable = $gla->iterable();
        } else {
            grokit_assert($iterable == $gla->iterable(), 'Multiplexer does not support mixing iterable and non-iterable GLAs');
        }
        $glaReqStates[$glaName] = $gla->req_states();
        foreach ($gla->req_states() as $rstate) {
            $reqStates[] = $rstate;
        }
        $glaGenStates[$glaName] = $gla->state();
        // TODO: Support constant states
        grokit_assert(!$gla->has_state(), 'Multiplexer currently does not support constant states.');
    }
    $libraries = array_unique($libraries);
    $extra = ['glas' => $myGLAs];
    ?>

class <?php 
    echo $className;
    ?>
 {
<?php 
    foreach ($myGLAs as $name => $type) {
        ?>
    <?php 
        echo $type;
        ?>
 <?php 
        echo $name;
        ?>
;
<?php 
    }
    // foreach inner gla
    ?>

    class Iterator {

        bool _gotResultsOnce;
        bool _valid;

<?php 
    foreach ($myGLAs as $name => $type) {
        ?>
        <?php 
        echo $type;
        ?>
 * it_<?php 
        echo $name;
        ?>
;
<?php 
    }
    // foreach inner gla
    ?>

    public:
        Iterator(void) : _gotResultsOnce(false), _valid(false),
            <?php 
    echo array_template('it_{key}(nullptr)', ', ', $myGLAs);
    ?>

        { }

        Iterator(<?php 
    echo typed_ref_args($myGLAs);
    ?>
) : _gotResultsOnce(false), _valid(true),
            <?php 
    echo array_template('it_{key}(&{key})', ', ', $myGLAs);
    ?>

        {
<?php 
    foreach ($myGLAs as $name => $type) {
        if ($glaRez[$name] == 'multi') {
            ?>
            <?php 
            echo $name;
            ?>
.Finalize();
<?php 
        }
        // if inner GLA is multi
    }
    // foreach inner gla
    ?>
        }

        Iterator( const Iterator & other) = default;

        ~Iterator() { }

        bool GetNextResult( <?php 
    echo typed_ref_args($outputs);
    ?>
 ) {
            FATALIF(!_valid, "Tried to get results from an invalid iterator.");

            bool ret = !_gotResultsOnce;
            _gotResultsOnce = true;

<?php 
    foreach ($myGLAs as $name => $type) {
        if ($glaRez[$name] == 'multi') {
            ?>
            ret |= it_<?php 
            echo $name;
            ?>
->GetNextResult(<?php 
            echo args($glaOutputs[$name]);
            ?>
);
<?php 
        }
        // if inner GLA is multi
    }
    // foreach inner gla
    ?>

            if( ret ) {
<?php 
    foreach ($myGLAs as $name => $type) {
        if ($glaRez[$name] == 'single') {
            ?>
                it_<?php 
            echo $name;
            ?>
->GetResult(<?php 
            echo args($glaOutputs[$name]);
            ?>
);
<?php 
        } else {
            if ($glaRez[$name] == 'state') {
                $stateVar = array_keys($glaOutputs[$name])[0];
                $stateType = $glaOutputs[$name][$stateVar];
                ?>
                <?php 
                echo $stateVar;
                ?>
 = <?php 
                echo $stateType;
                ?>
(it_<?php 
                echo $name;
                ?>
);
<?php 
            }
        }
        // if inner GLA is state
    }
    // foreach inner gla
    ?>
            }

            return ret;
        }
    };

    Iterator multiIterator;

public:
    <?php 
    echo $className;
    ?>
() { }
    ~<?php 
    echo $className;
    ?>
() { }

    void AddItem(<?php 
    echo const_typed_ref_args($inputs);
    ?>
) {
        // Call AddItem individually on each GLA.
<?php 
    foreach ($myGLAs as $gName => $gType) {
        ?>
        <?php 
        echo $gName;
        ?>
.AddItem(<?php 
        echo args($glaInputs[$gName]);
        ?>
);
<?php 
    }
    // foreach inner gla
    ?>
    }

    void AddState( <?php 
    echo $className;
    ?>
 & other ) {
        // Call AddState individually on each GLA.
<?php 
    foreach ($myGLAs as $gName => $gType) {
        ?>
        <?php 
        echo $gName;
        ?>
.AddState(other.<?php 
        echo $gName;
        ?>
);
<?php 
    }
    // foreach inner gla
    ?>
    }

    void Finalize() {
        multiIterator = Iterator(<?php 
    echo args($myGLAs);
    ?>
);
    }

    bool GetNextResult(<?php 
    echo typed_ref_args($outputs);
    ?>
) {
        return multiIterator.GetNextResult(<?php 
    echo args($outputs);
    ?>
);
    }

    void GetResult(<?php 
    echo typed_ref_args($outputs);
    ?>
) {
        Finalize();
        GetNextResult(<?php 
    echo args($outputs);
    ?>
);
    }

<?php 
    foreach (array_keys($myGLAs) as $index => $name) {
        ?>
    const <?php 
        echo $myGLAs[$name];
        ?>
& GetGLA<?php 
        echo $index;
        ?>
() const {
      return <?php 
        echo $name;
        ?>
;
    }
<?php 
    }
    ?>
};

<?php 
    return array('kind' => 'GLA', 'name' => $className, 'input' => $inputs, 'output' => $outputs, 'result_type' => $resultType, 'libraries' => $libraries, 'configurable' => $configurable, 'extra' => $extra);
}
Beispiel #7
0
function HEX($t_args)
{
    // The number of bytes encoded per string.
    $size = get_first_key($t_args, ['size', 0]);
    $className = 'Hex' . $size;
    $systemHeaders = ['cstdio', 'cstring'];
    $userHeaders = [];
    $libHeaders = [];
    $libraries = [];
    $constructors = [];
    $methods = [];
    $functions = [];
    $binaryOperators = [];
    $unaryOperators = [];
    $globalContent = '';
    $complex = false;
    $properties = [];
    $extra = ['size.bytes' => $size];
    $describeJson = DescribeJson('hex', DescribeJsonStatic(['size' => $size]));
    $globalContent = '';
    ?>

class <?php 
    echo $className;
    ?>
 {
 public:
  // Lookup table per pair of hex digits.
  static constexpr const char lookup[256] __attribute__((weak)) = {
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    0,  1,  2,  3,  4,  5,  6,  7,  8,  9, -1, -1, -1, -1, -1, -1,
   -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
  };

  static constexpr const char to_char[16] __attribute__((weak)) = {
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
  };

  // The number of bytes encoded.
  static const constexpr size_t kSize = <?php 
    echo $size;
    ?>
;

  // The length of decoded strings.
  static const constexpr size_t kLength = 2 * kSize;

 private:
  // The binary data corresponding to the encoded string.
  std::array<char, kSize> bytes;

 public:
<?php 
    $constructors[] = [[], true];
    ?>
  <?php 
    echo $className;
    ?>
();
<?php 
    $constructors[] = [['BASE::NULL'], true];
    ?>
  <?php 
    echo $className;
    ?>
(const GrokitNull& nullval);
<?php 
    $constructors[] = [['BASE::STRING_LITERAL'], true];
    ?>
  <?php 
    echo $className;
    ?>
(const char* str);

<?php 
    $methods[] = ['IsValid', [], 'BASE::BOOL', true];
    ?>
  bool IsValid(void) const;
<?php 
    $methods[] = ['IsNull', [], 'BASE::BOOL', true];
    ?>
  bool IsNull(void) const;

<?php 
    $binaryOperators[] = '==';
    ?>
  bool operator ==(const <?php 
    echo $className;
    ?>
& other) const;
<?php 
    $binaryOperators[] = '!=';
    ?>
  bool operator !=(const <?php 
    echo $className;
    ?>
& other) const;

  void FromString(const char* str);
  int ToString(char* buffer) const;

  void FromJson(const Json::Value& src);
  void ToJson(Json::Value& dest) const;
};

// Allocate storage for static variables
constexpr const char <?php 
    echo $className;
    ?>
::lookup[256];
constexpr const char <?php 
    echo $className;
    ?>
::to_char[16];

inline <?php 
    echo $className;
    ?>
::<?php 
    echo $className;
    ?>
() {
  bytes.fill(0);
}

inline <?php 
    echo $className;
    ?>
::<?php 
    echo $className;
    ?>
(const GrokitNull& nullval) {
  bytes.fill(0);
}

inline <?php 
    echo $className;
    ?>
::<?php 
    echo $className;
    ?>
(const char* str) {
  this->FromString(str);
}

inline bool <?php 
    echo $className;
    ?>
::operator ==(const <?php 
    echo $className;
    ?>
& other) const {
  return std::memcmp(bytes.data(), other.bytes.data(), kSize);
}

inline bool <?php 
    echo $className;
    ?>
::operator !=(const <?php 
    echo $className;
    ?>
& other) const {
  return !(*this == other);
}

inline void <?php 
    echo $className;
    ?>
::FromString(const char* str) {
  size_t len = strlen(str);
  FATALIF(len != kLength, "Incorrectly sized string, expected %zu, got %zu: %s",
    kLength, len, str);
  for (size_t i = 0; i < kSize; i++) {
    char a = lookup[str[2 * i]];
    char b = lookup[str[2 * i + 1]];
    FATALIF(a < 0 || b < 0, "Illegal hex character: %c%c",
            str[2 * i], str[2 * i + 1]);
    bytes[i] = (a << 4) | b;
  }
}

inline int <?php 
    echo $className;
    ?>
::ToString(char* buffer) const {
  for (size_t i = 0; i < kSize; i++) {
    char byte = bytes[i];
    buffer[2 * i] = to_char[(byte >> 4) & 0x0F];
    buffer[2 * i + 1] = to_char[byte & 0x0F];
  }
  buffer[kLength] = '\0';
  return 1 + kLength;
}

inline void <?php 
    echo $className;
    ?>
::FromJson(const Json::Value& src) {
  this->FromString(src.asCString());
}

inline void <?php 
    echo $className;
    ?>
::ToJson(Json::Value& dest) const {
  char buffer[kLength + 1];
  this->ToString(buffer);
  dest = buffer;
}

<?php 
    ob_start();
    ?>

inline void FromString(@type& data, const char* buffer) {
  data.FromString(buffer);;
}

inline int ToString(const @type& data, char* buffer) {
  return data.ToString(buffer);
}

inline void FromJson(const Json::Value& src, @type& dest) {
  dest.FromJson(src);
}

inline void ToJson(const @type& src, Json::Value& dest) {
  src.ToJson(dest);
}

<?php 
    $globalContent .= ob_get_clean();
    ?>

<?php 
    return ['kind' => 'TYPE', 'name' => $className, 'complex' => $complex, 'system_headers' => $systemHeaders, 'user_headers' => $userHeaders, 'lib_headers' => $libHeaders, 'libraries' => $libraries, 'binary_operators' => $binaryOperators, 'unary_operators' => $unaryOperators, 'global_content' => $globalContent, 'constructors' => $constructors, 'methods' => $methods, 'functions' => $functions, 'libraries' => $libraries, 'properties' => $properties, 'extras' => $extra, 'describe_json' => $describeJson];
}
Beispiel #8
0
function Segmenter(array $t_args, array $input, array $output, array $given_states)
{
    $resType = ['fragment', 'multi'];
    $system_headers = ['array', 'vector', 'memory', 'cinttypes', 'unordered_map'];
    $user_headers = ['HashFunctions.h'];
    $lib_headers = [];
    $preferFragment = get_default($t_args, 'inner.prefer.fragment', false);
    $wantedRes = $preferFragment ? ['fragment', 'multi'] : ['multi', 'fragment'];
    $nInputs = \count($input);
    grokit_assert($nInputs > 1, 'Segmenter: Not enough inputs specified!');
    $keyName = array_keys($input)[0];
    $keyType = array_get_index($input, 0);
    $innerInputs = array_slice($input, 1, $nInputs - 1, true);
    $gla = get_first_key($t_args, ['gla', 'GLA', 0]);
    grokit_assert(is_gla($gla), 'Segmenter: [gla] argument must be a valid GLA');
    $gla = $gla->apply($innerInputs, $output, $given_states);
    $n_passes = get_default($t_args, 'passes', 1);
    grokit_assert(is_int($n_passes), 'Segmenter: [passes] argument must be an integer');
    grokit_assert($n_passes > 0, 'Segmenter: [passes] argument must be > 0');
    $libraries = $gla->libraries();
    $innerRes = get_first_value($gla->result_type(), $wantedRes);
    $innerInputs = $gla->input();
    $innerOutput = $gla->output();
    $input = array_merge([$keyName => $keyType], $innerInputs);
    $output = $innerOutput;
    $segments = get_default($t_args, 'segments', 64);
    $constState = lookupResource('BASE::SegmenterState', ['gla' => $gla, 'passes' => $n_passes, 'segments' => $segments]);
    $className = generate_name('Segmenter_');
    $savedArgs = [];
    $cArgs = [];
    $innerCArgs = [];
    if ($gla->configurable()) {
        $savedArgs['json_init'] = 'Json::Value';
        $cArgs['json_init'] = 'Json::Value';
        $innerCArgs[] = 'json_init';
    }
    $cArgs['const_state'] = $constState;
    if ($gla->has_state()) {
        $innerCArgs[] = 'constState.inner_cstate';
    }
    $cstStr = \count($innerCArgs) > 0 ? '(' . implode(',', $innerCArgs) . ')' : '';
    grokit_assert(!$gla->iterable(), 'Segementer does not support iterable GLAs');
    $iterable = $n_passes > 1;
    ?>

class <?php 
    echo $className;
    ?>
 {
private:

    using ConstantState = <?php 
    echo $constState;
    ?>
;
    using SplitState = ConstantState::SplitState;

    static constexpr const size_t NUM_STATES = SplitState::NUM_STATES;

    using InnerGLA = <?php 
    echo $gla;
    ?>
;
    using InnerGLAPtr = std::unique_ptr<InnerGLA>;
    using GLA_Array = std::array<InnerGLAPtr, NUM_STATES>;

public:
    using size_type = std::size_t;

<?php 
    if ($innerRes == 'fragment') {
        ?>
    class Iterator {
    private:
        InnerGLA * gla;
        int fragmentNum;

        InnerGLA::Iterator * innerIter;

    public:
        Iterator( InnerGLA * _gla, int _fragmentNum, int _innerFrag ) :
            gla(_gla), fragmentNum(_fragmentNum),
            innerIter(nullptr)
        {
            innerIter = gla->Finalize(_innerFrag);
        }

        ~Iterator(void) {
            if( innerIter != nullptr ) {
                delete innerIter;
                innerIter = nullptr;
            }
        }

        bool GetNextResult( <?php 
        echo typed_ref_args($gla->output());
        ?>
 ) {
            return innerIter->GetNextResult(<?php 
        echo args($gla->output());
        ?>
);
        }

        int FragmentNumber() {
            return fragmentNum;
        }
    };
<?php 
    } else {
        // if inner result type is fragment
        ?>
    class Iterator {
    private:
        InnerGLA * gla;
        int fragmentNum;

    public:
        Iterator( InnerGLA * _gla, int fragNo ) : gla(_gla), fragmentNum(fragNo) {
            gla->Finalize();
        }

        ~Iterator(void) { }

        bool GetNextResult( <?php 
        echo typed_ref_args($gla->output());
        ?>
 ) {
            return gla->GetNextResult(<?php 
        echo args($gla->output());
        ?>
);
        }

        int FragmentNumber() {
            return fragmentNum;
        }
    };
<?php 
    }
    // if inner result type is multi
    ?>

private:

    const ConstantState & constState;
    GLA_Array localState;

    // Iteration state for multi result type
    int numFrags;
    int multiFragNo;
    Iterator * multiIter;

<?php 
    if ($innerRes == 'fragment') {
        ?>
    using frag_info = std::pair<int, int>;
    using frag_map_t = std::unordered_map<int, frag_info>;
    frag_map_t fragMap;
<?php 
    }
    ?>


<?php 
    foreach ($savedArgs as $name => $type) {
        ?>
    const <?php 
        echo $type;
        ?>
 <?php 
        echo $name;
        ?>
;
<?php 
    }
    // foreach saved arg
    ?>

public:

    // Constructor
    <?php 
    echo $className;
    ?>
( <?php 
    echo const_typed_ref_args($cArgs);
    ?>
 ) :
        constState(const_state)
        , localState()
        , numFrags(0)
        , multiFragNo(0)
        , multiIter(nullptr)
<?php 
    if ($innerRes == 'fragment') {
        ?>
        , fragMap()
<?php 
    }
    foreach ($savedArgs as $name => $type) {
        ?>
        , <?php 
        echo $name;
        ?>
(<?php 
        echo $name;
        ?>
)
<?php 
    }
    // foreach constructor arg to save
    ?>
    {
        for( auto & elem : localState ) {
            elem.reset(new InnerGLA<?php 
    echo $cstStr;
    ?>
);
        }
    }

    void AddItem( <?php 
    echo const_typed_ref_args($input);
    ?>
 ) {
        uint64_t hashVal = CongruentHash(Hash(<?php 
    echo $keyName;
    ?>
), H_b + 1);
        uint64_t passNum = (hashVal / NUM_STATES) % ConstantState::N_PASSES;
        uint64_t segNum = hashVal % NUM_STATES;

<?php 
    if ($n_passes > 1) {
        ?>
        if( passNum != constState.pass ) {
            return;
        }
<?php 
    }
    // more than 1 pass
    ?>
        localState[segNum]->AddItem(<?php 
    echo args($innerInputs);
    ?>
);
    }

    void ChunkBoundary(void) {
        // Merge local states into the global state

        SplitState & globalStates = constState.segments;

        int theseAreOk[NUM_STATES];
        for( int i = 0; NUM_STATES > i; i++ ) {
            theseAreOk[i] = 1;
        }

        int segsLeft = NUM_STATES;

        while( segsLeft > 0 ) {
            InnerGLA * checkedOut = nullptr;
            int whichOne = globalStates.CheckOutOne( theseAreOk, checkedOut );

            if( checkedOut == NULL ) {
                checkedOut = new InnerGLA<?php 
    echo $cstStr;
    ?>
;
            }

            checkedOut->AddState( *(localState[whichOne]) );

            globalStates.CheckIn( whichOne, checkedOut );

            theseAreOk[whichOne] = 0;
            segsLeft--;
        }

        // Re-initialize the local states
        for( auto & elem : localState ) {
<?php 
    if ($gla->is('resettable')) {
        ?>
            elem->Reset();
<?php 
    } else {
        // if resettable
        ?>
            elem.reset(new InnerGLA<?php 
        echo $cstStr;
        ?>
);
<?php 
    }
    // if not resettable
    ?>
        }
    }

    void AddState( <?php 
    echo $className;
    ?>
 & o ) {
        // Do nothing
    }

    void Finalize() {
        SplitState & globalStates = constState.segments;

        if( multiIter != nullptr)
            delete multiIter;

        multiFragNo = 0;
<?php 
    if ($innerRes == 'fragment') {
        ?>
        frag_info fInfo = fragMap[multiFragNo];
        multiIter = new Iterator(globalStates.Peek(fInfo.first), multiFragNo,
            fInfo.second);
<?php 
    } else {
        ?>
        multiIter = new Iterator(globalStates.Peek(multiFragNo), multiFragNo);
<?php 
    }
    ?>
    }

    bool GetNextResult(<?php 
    echo typed_ref_args($output);
    ?>
) {
        bool gotResult = false;
        SplitState & globalStates = constState.segments;

        while( (multiFragNo < numFrags && multiIter != nullptr) && !gotResult ) {
            gotResult = multiIter->GetNextResult(<?php 
    echo args($output);
    ?>
);

            if( !gotResult ) {
                multiFragNo++;
                delete multiIter;

                if( numFrags > multiFragNo ) {
<?php 
    if ($innerRes == 'fragment') {
        ?>
                    frag_info fInfo = fragMap[multiFragNo];
                    multiIter = new Iterator(globalStates.Peek(fInfo.first), multiFragNo,
                        fInfo.second);
<?php 
    } else {
        ?>
                    multiIter = new Iterator(globalStates.Peek(multiFragNo), multiFragNo);
<?php 
    }
    ?>
                } else {
                    multiIter = nullptr;
                }
            }
        }

        return gotResult;
    }

    int GetNumFragments(void) {
<?php 
    if ($innerRes == 'fragment') {
        ?>
        SplitState & globalStates = constState.segments;
        numFrags = 0;

        for (int i = 0; i < NUM_STATES; i++) {
            int curFrags = globalStates.Peek(i)->GetNumFragments();

            for (int curFrag = 0; curFrag < curFrags; curFrag++) {
                fragMap[numFrags] = frag_info(i, curFrag);

                numFrags++;
            }
        }
<?php 
    } else {
        ?>
        numFrags = NUM_STATES;
<?php 
    }
    ?>
        return numFrags;
    }

    Iterator * Finalize( int fragment ) {
        SplitState & globalStates = constState.segments;

<?php 
    if ($innerRes == 'fragment') {
        ?>
        frag_info info = fragMap[fragment];
        return new Iterator(globalStates.Peek(info.first), fragment, info.second);
<?php 
    } else {
        ?>
        return new Iterator(globalStates.Peek(fragment), fragment);
<?php 
    }
    ?>
    }

    bool GetNextResult( Iterator * it, <?php 
    echo typed_ref_args($output);
    ?>
 ) {
        bool ret = it->GetNextResult(<?php 
    echo args($output);
    ?>
);

        return ret;
    }

<?php 
    if ($iterable) {
        ?>
    bool ShouldIterate( ConstantState & modible ) {
        modible.pass++;

        return modible.pass < ConstantState::N_PASSES;
    }

    void PostFinalize() {
        constState.segments.Reset();
    }
<?php 
    }
    // iterable
    ?>

<?php 
    if ($gla->is('finite container')) {
        ?>
    size_type size() {
        SplitState & globalStates = constState.segments;
        size_type s = 0;
        for( int i = 0; NUM_STATES > i; i++ ) {
            InnerGLA * ptr = globalStates.Peek(i);
            s += ptr->size();
        }

        return s;
    }

    size_type size(int frag) {
        SplitState & globalStates = constState.segments;
        return globalStates.Peek(frag)->size();
    }
<?php 
    }
    // if the gla is a container
    ?>
};

typedef <?php 
    echo $className;
    ?>
::Iterator <?php 
    echo $className;
    ?>
_Iterator;

<?php 
    return ['kind' => 'GLA', 'name' => $className, 'system_headers' => $system_headers, 'user_headers' => $user_headers, 'lib_headers' => $lib_headers, 'libraries' => $libraries, 'input' => $input, 'output' => $output, 'result_type' => $resType, 'generated_state' => $constState, 'required_states' => $gla->req_states(), 'chunk_boundary' => true, 'configurable' => $gla->configurable(), 'iterable' => $iterable, 'post_finalize' => $iterable, 'intermediates' => true];
}
Beispiel #9
0
function FACTOR(array $t_args)
{
    $rawDict = get_first_key($t_args, ['dictionary', 'dict', 0]);
    // Double the quotes so that we escape them in SQLite, and add backslashes
    // to them so that we escape them in C++.
    $dict = addcslashes(\grokit\doubleChars($rawDict, '"'), '"\\');
    $cardinality = \grokit\dictionarySize($rawDict);
    $storageBytes = get_first_key_default($t_args, ['bytes', 1], 2);
    $cardBytes = $cardinality > 0 ? intval(ceil(log($cardinality, 256))) : 1;
    $storageBytes = $cardBytes > $storageBytes ? $cardBytes : $storageBytes;
    switch ($storageBytes) {
        case 1:
            $storageType = 'uint8_t';
            break;
        case 2:
            $storageType = 'uint16_t';
            break;
        case 4:
            $storageType = 'uint32_t';
            break;
        case 8:
            $storageType = 'uint64_t';
            break;
        default:
            grokit_error('Unsupported # of bytes (' . $storageBytes . ') given for FACTOR, only 1, 2, 4, and 8 supported.');
    }
    $className = generate_name('FACTOR_' . ensure_identifier($dict));
    $stringType = lookupType('base::STRING');
    $globalContent = '';
    $methods = [];
    $constructors = [];
    $functions = [];
    ?>

class <?php 
    echo $className;
    ?>
 {
public:
    typedef <?php 
    echo $storageType;
    ?>
 StorageType;

    static const        char *          DictionaryName      __attribute__((weak));
    static const        StorageType     InvalidID           __attribute__((weak));
    static const        StorageType     MaxID               __attribute__((weak));
    static const        Dictionary &    globalDictionary    __attribute__((weak));

public:
    /* ----- Members ----- */

    // The ID of this Factor;
    StorageType myID;

    /* ----- Constructors / Destructors ----- */

    // Default constructor
    <?php 
    echo $className;
    ?>
( void );

    // Constructor from null (same as default)
    <?php 
    echo $className;
    ?>
( const GrokitNull & );

    // Constructor from C strings / string literals
<?php 
    $constructors[] = [['base::STRING_LITERAL'], true];
    ?>
    <?php 
    echo $className;
    ?>
( const char * );

    // Constructor from Grokit STRING type.
<?php 
    $constructors[] = [['base::STRING'], true];
    ?>
    <?php 
    echo $className;
    ?>
( const <?php 
    echo $stringType;
    ?>
 & );

    // Constructor from storage type
    <?php 
    echo $className;
    ?>
( const StorageType );

    // Copy constructor and copy assignment
    // These can both be default
    <?php 
    echo $className;
    ?>
( const <?php 
    echo $className;
    ?>
 & ) = default;
    <?php 
    echo $className;
    ?>
 & operator =( const <?php 
    echo $className;
    ?>
 & ) = default;

    // Destructor
    ~<?php 
    echo $className;
    ?>
() { }

    /* ----- Methods ----- */

    // Standard FromString method
    void FromString( const char * );

    // FromString method used when building the dictionaries.
    void FromString( const char *, Dictionary & );

    // Looks up the factor in the global dictionary and returns the string
<?php 
    $methods[] = ['ToString', [], 'base::STRING_LITERAL', true];
    ?>
    const char * ToString( void ) const;

    // Returns the ID of the Factor.
    StorageType GetID( void ) const;

    // Returns whether or not the Factor is valid.
<?php 
    $methods[] = ['Valid', [], 'base::bool', true];
    ?>
    bool Valid( void ) const;
<?php 
    $methods[] = ['Invalid', [], 'base::bool', true];
    ?>
    bool Invalid( void ) const;

    // Translate the content
    void Translate( const Dictionary::TranslationTable& );

    void toJson( Json::Value & dest ) const;
    void fromJson( const Json::Value & src );

    /* ----- Operators ----- */

    // The dictionary keeps track of what the sorted order of the strings is.
    // These methods are based on the lexicographical ordering of the strings
    // the factors represent
    bool operator ==( const <?php 
    echo $className;
    ?>
 & ) const;
    bool operator !=( const <?php 
    echo $className;
    ?>
 & ) const;
    bool operator <( const <?php 
    echo $className;
    ?>
 & ) const;
    bool operator <=( const <?php 
    echo $className;
    ?>
 & ) const;
    bool operator >( const <?php 
    echo $className;
    ?>
 & ) const;
    bool operator >=( const <?php 
    echo $className;
    ?>
 & ) const;

    // Implicit conversion to storage type
    operator StorageType () const;
};

// Static member initialization
const <?php 
    echo $className;
    ?>
::StorageType <?php 
    echo $className;
    ?>
::InvalidID = std::numeric_limits<StorageType>::max();
const <?php 
    echo $className;
    ?>
::StorageType <?php 
    echo $className;
    ?>
::MaxID = <?php 
    echo $className;
    ?>
::InvalidID - 1;
const char * <?php 
    echo $className;
    ?>
::DictionaryName = "<?php 
    echo $dict;
    ?>
";
const Dictionary & <?php 
    echo $className;
    ?>
::globalDictionary = Dictionary::GetDictionary(<?php 
    echo $className;
    ?>
::DictionaryName);

/* ----- Constructors ----- */

// Default constructor
inline
<?php 
    echo $className;
    ?>
 :: <?php 
    echo $className;
    ?>
( void ):
    myID(InvalidID)
{}

inline
<?php 
    echo $className;
    ?>
 :: <?php 
    echo $className;
    ?>
( const GrokitNull & nullval ):
    myID(InvalidID)
{ }

// Constructor from C strings / string literals
inline
<?php 
    echo $className;
    ?>
 :: <?php 
    echo $className;
    ?>
( const char * str ) {
    FromString(str);
}

// Constructor from Grokit STRING type
inline
<?php 
    echo $className;
    ?>
 :: <?php 
    echo $className;
    ?>
( const <?php 
    echo $stringType;
    ?>
 & str ) {
    FromString(str.ToString());
}

// Constructor from storage type
inline
<?php 
    echo $className;
    ?>
 :: <?php 
    echo $className;
    ?>
( const <?php 
    echo $storageType;
    ?>
 id ):
    myID(id)
{ }

/* ----- Methods ----- */

inline
auto <?php 
    echo $className;
    ?>
 :: GetID(void) const -> StorageType {
    return myID;
}

// Standard FromString method
inline
void <?php 
    echo $className;
    ?>
 :: FromString( const char * str ) {
    // Global dictionary will return InvalidID if not found
    myID = globalDictionary.Lookup(str, InvalidID );
}

// FromString method used when building the dictionaries
inline
void <?php 
    echo $className;
    ?>
 :: FromString( const char * str, Dictionary & localDict ) {
    // First check if we are in the local dictionary
    myID = localDict.Lookup(str, InvalidID );
    if( myID != InvalidID )
        return;

    // Next check if we are in the global dictionary
    myID = globalDictionary.Lookup(str, InvalidID );
    if( myID != InvalidID )
        return;

    // Add a new entry to the local dictionary.
    // The dictionary should throw an error if the new ID is greater than
    // MaxID.
    myID = localDict.Insert( str, MaxID );
}

// Looks up the factor in the global dictionary and returns the string
inline
const char * <?php 
    echo $className;
    ?>
 :: ToString( void ) const {
    return globalDictionary.Dereference(myID);
}

// Determine whether or not the factor is valid
inline
bool <?php 
    echo $className;
    ?>
 :: Valid( void ) const {
    return myID != InvalidID;
}

inline
bool <?php 
    echo $className;
    ?>
 :: Invalid(void) const {
    return myID == InvalidID;
}

// Translate the content
inline
void <?php 
    echo $className;
    ?>
 :: Translate( const Dictionary::TranslationTable & tbl ) {
    auto it = tbl.find(myID);
    if( it != tbl.end() ) {
        myID = it->second;
    }
}


inline
void <?php 
    echo $className;
    ?>
 :: toJson( Json::Value & dest ) const {
    dest = (Json::Int64) myID;
}

inline
void <?php 
    echo $className;
    ?>
 :: fromJson( const Json::Value & src ) {
    myID = (StorageType) src.asInt64();
}

/* ----- Operators ----- */

inline
bool <?php 
    echo $className;
    ?>
 :: operator ==( const <?php 
    echo $className;
    ?>
 & o ) const {
    return myID == o.myID;
}

inline
bool <?php 
    echo $className;
    ?>
 :: operator !=( const <?php 
    echo $className;
    ?>
 & o ) const {
    return myID != o.myID;
}

inline
bool <?php 
    echo $className;
    ?>
 :: operator <( const <?php 
    echo $className;
    ?>
 & o ) const {
    return Valid() && o.Valid() && globalDictionary.Compare(myID, o.myID) < 0;
}

inline
bool <?php 
    echo $className;
    ?>
 :: operator <=( const <?php 
    echo $className;
    ?>
 & o ) const {
    return Valid() && o.Valid() && globalDictionary.Compare(myID, o.myID) <= 0;
}

inline
bool <?php 
    echo $className;
    ?>
 :: operator >( const <?php 
    echo $className;
    ?>
 & o ) const {
    return Valid() && o.Valid() && globalDictionary.Compare(myID, o.myID) > 0;
}

inline
bool <?php 
    echo $className;
    ?>
 :: operator >=( const <?php 
    echo $className;
    ?>
 & o ) const {
    return Valid() && o.Valid() && globalDictionary.Compare(myID, o.myID) >= 0;
}

// Implicit conversion to storage type
inline
<?php 
    echo $className;
    ?>
 :: operator StorageType() const {
    return myID;
}

<?php 
    ob_start();
    // Global functions
    ?>

inline
void FromString( @type & f, const char * str ) {
    f.FromString(str);
}

inline
void FromString( @type & f, const char * str, Dictionary & localDict ) {
    f.FromString(str, localDict);
}

inline
int ToString( const @type & f, char * buffer ) {
    const char * str = f.ToString();
    strcpy(buffer, str);
    return strlen(buffer) + 1;
}

<?php 
    $functions[] = ['Hash', ['@type'], 'base::BIGINT', true, true];
    ?>
template<>
inline
uint64_t Hash( const @type & x ) {
    return x.GetID();
}

inline
void ToJson( const @type & src, Json::Value & dest ) {
    src.toJson(dest);
}

inline
void FromJson( const Json::Value & src, @type & dest ) {
    dest.fromJson(src);
}

<?php 
    $functions[] = ['IsNull', ['@type'], 'BASE::BOOL', true, true];
    ?>
inline
bool IsNull( const @type f ) {
    return f.Invalid();
}

<?php 
    $globalContent .= ob_get_clean();
    ?>

<?php 
    // Function to get the dictionary at runtime.
    $describeInfoJson = function ($var, $myType) {
        ?>
    <?php 
        echo $var;
        ?>
["levels"] = Json::Value(Json::arrayValue);
    for( auto it = <?php 
        echo $myType;
        ?>
::globalDictionary.cbegin(); it != <?php 
        echo $myType;
        ?>
::globalDictionary.cend(); it++ ) {
        <?php 
        echo $var;
        ?>
["levels"][it->first] = it->second;
    }
<?php 
    };
    return ['kind' => 'TYPE', 'name' => $className, 'dictionary' => $dict, 'system_headers' => ['limits', 'cstring', 'cinttypes'], 'user_headers' => ['Dictionary.h', 'DictionaryManager.h', 'ColumnIteratorDict.h'], 'properties' => ['categorical'], 'extras' => ['cardinality' => $cardinality, 'size.bytes' => $storageBytes], 'binary_operators' => ['==', '!=', '<', '>', '<=', '>='], 'global_content' => $globalContent, 'complex' => 'ColumnIteratorDict< @type >', 'methods' => $methods, 'constructors' => $constructors, 'functions' => $functions, 'describe_json' => DescribeJson('factor', $describeInfoJson)];
}
Beispiel #10
0
function CATEGORYSET($t_args)
{
    // The dictionary of the associated factor.
    $dictionary = get_first_key($t_args, ['dictionary', 'dict', 0]);
    $values = array_values($dictionary);
    // The component types used.
    $category = lookupType('category', ['dict' => $dictionary]);
    $bitset = lookupType('bitset', ['values' => $values]);
    $size = $bitset->get('size.bytes');
    // The name of the object type.
    $className = 'CategorySet' . $size;
    $systemHeaders = ['cstdio', 'cstring'];
    $userHeaders = [];
    $libHeaders = [];
    $libraries = [];
    $constructors = [];
    $methods = [];
    $functions = [];
    $binaryOperators = [];
    $unaryOperators = [];
    $globalContent = '';
    $complex = false;
    $properties = [];
    $extra = ['size.bytes' => $size];
    $describeJson = DescribeJson('categoryset', DescribeJsonStatic(['levels' => $values]));
    $globalContent = '';
    ?>

class <?php 
    echo $className;
    ?>
 {
 public:
  using Category = <?php 
    echo $category;
    ?>
;
  using BitSet = <?php 
    echo $bitset;
    ?>
;
  using StorageType = BitSet::StorageType;

 private:
  // The binary data corresponding to the encoded string.
  BitSet data;

 public:
<?php 
    $constructors[] = [[], true];
    ?>
  <?php 
    echo $className;
    ?>
();
<?php 
    $constructors[] = [['BASE::NULL'], true];
    ?>
  <?php 
    echo $className;
    ?>
(const GrokitNull& null);
<?php 
    $constructors[] = [['BASE::STRING_LITERAL'], true];
    ?>
  <?php 
    echo $className;
    ?>
(const char* str);
  <?php 
    echo $className;
    ?>
(const BitSet& data);
  <?php 
    echo $className;
    ?>
(const <?php 
    echo $className;
    ?>
& other);

<?php 
    $methods[] = ['IsEmpty', [], 'BASE::BOOL', true];
    ?>
  bool IsEmpty() const;

  <?php 
    echo $className;
    ?>
& operator =(const <?php 
    echo $className;
    ?>
& other) = default;
<?php 
    $binaryOperators[] = '==';
    ?>
  bool operator ==(const <?php 
    echo $className;
    ?>
& other) const;
<?php 
    $binaryOperators[] = '!=';
    ?>
  bool operator !=(const <?php 
    echo $className;
    ?>
& other) const;
<?php 
    $binaryOperators[] = '<';
    ?>
  bool operator <(const <?php 
    echo $className;
    ?>
& other) const;
<?php 
    $binaryOperators[] = '>';
    ?>
  bool operator >(const <?php 
    echo $className;
    ?>
& other) const;
<?php 
    $binaryOperators[] = '<=';
    ?>
  bool operator <=(const <?php 
    echo $className;
    ?>
& other) const;
<?php 
    $binaryOperators[] = '>=';
    ?>
  bool operator >=(const <?php 
    echo $className;
    ?>
& other) const;

  void FromString(const char* str);
  int ToString(char* buffer) const;

  void FromJson(const Json::Value& src);
  void ToJson(Json::Value& dest) const;
};

inline <?php 
    echo $className;
    ?>
::<?php 
    echo $className;
    ?>
()
    : data() {
}

inline <?php 
    echo $className;
    ?>
::<?php 
    echo $className;
    ?>
(const GrokitNull& null)
    : data() {
}

inline <?php 
    echo $className;
    ?>
::<?php 
    echo $className;
    ?>
(const char* str) {
  this->FromString(str);
}

inline <?php 
    echo $className;
    ?>
::<?php 
    echo $className;
    ?>
(const <?php 
    echo $className;
    ?>
::BitSet& data)
    : data(data) {
}

inline <?php 
    echo $className;
    ?>
::<?php 
    echo $className;
    ?>
(const <?php 
    echo $className;
    ?>
& other)
    : data(other.data) {
}

inline bool <?php 
    echo $className;
    ?>
::IsEmpty() const {
  return data == 0;
}

inline bool <?php 
    echo $className;
    ?>
::operator ==(const <?php 
    echo $className;
    ?>
& other) const {
  return this->data == other.data;
}

inline bool <?php 
    echo $className;
    ?>
::operator !=(const <?php 
    echo $className;
    ?>
& other) const {
  return this->data != other.data;
}

inline bool <?php 
    echo $className;
    ?>
::operator <(const <?php 
    echo $className;
    ?>
& other) const {
  return this->data < other.data;
}

inline bool <?php 
    echo $className;
    ?>
::operator >(const <?php 
    echo $className;
    ?>
&other) const {
  return this->data > other.data;
}

inline bool <?php 
    echo $className;
    ?>
::operator <=(const <?php 
    echo $className;
    ?>
& other) const {
  return this->data <= other.data;
}

inline bool <?php 
    echo $className;
    ?>
::operator >=(const <?php 
    echo $className;
    ?>
& other) const {
  return this->data >= other.data;
}

inline void <?php 
    echo $className;
    ?>
::FromString(const char* str) {
  StorageType mask;
  char* storage;
  char* copy = strdup(str);
  char* token = strtok_r(copy, " ", &storage);
  while (token != NULL) {
    Category level (token);
    WARNINGIF(level.Invalid(), "Invalid token: %s", token);
    mask |= 1 << level;
    token = strtok_r(NULL, " ", &storage);
  }
  data = mask;
  free(copy);
}

inline int <?php 
    echo $className;
    ?>
::ToString(char* buffer) const {
  char* start = buffer;
<?php 
    foreach ($dictionary as $name) {
        ?>
  if (data.<?php 
        echo $name;
        ?>
())
    buffer += sprintf(buffer, "%s ", "<?php 
        echo $name;
        ?>
");
<?php 
    }
    ?>
  if (start == buffer) {
    buffer[0] = '\0';
    return 1;
  } else {
    buffer[-1] = '\0';
    return buffer - start;
  }
}

inline void <?php 
    echo $className;
    ?>
::FromJson(const Json::Value& src) {
  this->FromString(src.asCString());
}

inline void <?php 
    echo $className;
    ?>
::ToJson(Json::Value& dest) const {
  char* buffer;
  this->ToString(buffer);
  dest = buffer;
}

<?php 
    ob_start();
    ?>

inline void FromString(@type& data, const char* buffer) {
  data.FromString(buffer);
}

inline int ToString(const @type& data, char* buffer) {
  return data.ToString(buffer);
}

inline void FromJson(const Json::Value& src, @type& dest) {
  dest.FromJson(src);
}

inline void ToJson(const @type& src, Json::Value& dest) {
  src.ToJson(dest);
}

<?php 
    $globalContent .= ob_get_clean();
    ?>

<?php 
    return ['kind' => 'TYPE', 'name' => $className, 'complex' => $complex, 'system_headers' => $systemHeaders, 'user_headers' => $userHeaders, 'lib_headers' => $libHeaders, 'libraries' => $libraries, 'binary_operators' => $binaryOperators, 'unary_operators' => $unaryOperators, 'global_content' => $globalContent, 'constructors' => $constructors, 'methods' => $methods, 'functions' => $functions, 'libraries' => $libraries, 'properties' => $properties, 'extras' => $extra, 'describe_json' => $describeJson];
}
Beispiel #11
0
function BASE64($t_args)
{
    // The number of bytes encoded per string.
    $size = get_first_key($t_args, ['size', 0]);
    // The number of characters that should be used to encode each string.
    // Padding is acceptable but not necessarily, hence the acceptable number of
    // characters is an interval.
    $min = ceil($size * 4 / 3);
    $max = 4 * ceil($min / 4);
    $className = 'Base64_' . $size;
    $systemHeaders = ['cstring', 'cstdio'];
    $userHeaders = [];
    $libHeaders = ['base64.h'];
    $libraries = [];
    $constructors = [];
    $methods = [];
    $functions = [];
    $binaryOperators = [];
    $unaryOperators = [];
    $globalContent = '';
    $complex = false;
    $properties = [];
    $extra = ['size.bytes' => 40];
    $describeJson = DescribeJson('base64', DescribeJsonStatic(['size' => $size]));
    $globalContent = '';
    ?>

class <?php 
    echo $className;
    ?>
 {
 public:
  // The number of bytes encoded.
  static const constexpr int kSize = <?php 
    echo $size;
    ?>
;

  // The maximum number of characters that an input string is expected to have.
  static const constexpr int kMax = <?php 
    echo $max;
    ?>
;

  // The minimum number of characters that an input string is expected to have.
  static const constexpr int kMin = <?php 
    echo $min;
    ?>
;

 private:
  std::array<char, kSize> bytes;

 public:
<?php 
    $constructors[] = [[], true];
    ?>
  <?php 
    echo $className;
    ?>
();
<?php 
    $constructors[] = [['BASE::NULL'], true];
    ?>
  <?php 
    echo $className;
    ?>
(const GrokitNull& nullval);
<?php 
    $constructors[] = [['BASE::STRING_LITERAL'], true];
    ?>
  <?php 
    echo $className;
    ?>
(const char* str);

<?php 
    $binaryOperators[] = '==';
    ?>
  bool operator ==(const <?php 
    echo $className;
    ?>
& other) const;
<?php 
    $binaryOperators[] = '!=';
    ?>
  bool operator !=(const <?php 
    echo $className;
    ?>
& other) const;

  void FromString(const char* str);
  int ToString(char* buffer) const;

  void FromJson(const Json::Value& src);
  void ToJson(Json::Value& src) const;
};

inline <?php 
    echo $className;
    ?>
::<?php 
    echo $className;
    ?>
() {
  bytes.fill(0);
}

<?php 
    echo $className;
    ?>
::<?php 
    echo $className;
    ?>
(const GrokitNull& nullval) {
  bytes.fill(0);
}

inline  <?php 
    echo $className;
    ?>
::<?php 
    echo $className;
    ?>
(const char* str) {
  this->FromString(str);
}

inline bool <?php 
    echo $className;
    ?>
::operator ==(const <?php 
    echo $className;
    ?>
& other) const {
  return std::memcmp(bytes.data(), other.bytes.data(), kSize);
}

inline bool <?php 
    echo $className;
    ?>
::operator !=(const <?php 
    echo $className;
    ?>
& other) const {
  return !(*this == other);
}

inline void <?php 
    echo $className;
    ?>
::FromString(const char* str) {
  size_t length = strlen(str);
  FATALIF(kMax < length || length < kMin,"Illegal base64-%d input: '%s'",
          kSize, str);
  std::string message = base64_decode(std::string(str));
  std::memcpy(bytes.data(), message.data(), message.size());
}

inline int <?php 
    echo $className;
    ?>
::ToString(char* buffer) const {
  std::string encoded = base64_encode((unsigned char*) bytes.data(), kSize);
  return 1 + sprintf(buffer, "%s", encoded.c_str());
}

inline void <?php 
    echo $className;
    ?>
::FromJson(const Json::Value& src) {
  this->FromString(src.asCString());
}

inline void <?php 
    echo $className;
    ?>
::ToJson(Json::Value& dest) const {
  dest = base64_encode((unsigned char*) bytes.data(), kSize);
}

<?php 
    ob_start();
    ?>

inline void FromString(@type& data, const char* buffer) {
  data.FromString(buffer);
}

inline int ToString(const @type& data, char* buffer) {
  return data.ToString(buffer);
}

inline void FromJson(const Json::Value& src, @type& dest) {
  dest.FromJson(src);
}

inline void ToJson(const @type& src, Json::Value& dest) {
  src.ToJson(dest);
}

<?php 
    $globalContent .= ob_get_clean();
    ?>

<?php 
    return ['kind' => 'TYPE', 'name' => $className, 'complex' => $complex, 'system_headers' => $systemHeaders, 'user_headers' => $userHeaders, 'lib_headers' => $libHeaders, 'libraries' => $libraries, 'binary_operators' => $binaryOperators, 'unary_operators' => $unaryOperators, 'global_content' => $globalContent, 'constructors' => $constructors, 'methods' => $methods, 'functions' => $functions, 'libraries' => $libraries, 'properties' => $properties, 'extras' => $extra, 'describe_json' => $describeJson];
}
Beispiel #12
0
function Match($inputs, $args)
{
    // Processing of template arguments.
    $pattern = get_first_key($args, ['pattern', 0], 'Match: no pattern given.');
    grokit_assert(is_string($pattern), 'Match: pattern should be a string.');
    // Processing of inputs.
    $count = \count($inputs);
    grokit_assert($count == 1, "Match supports exactly 1 input. {$count} given");
    $inputs_ = array_combine(['input'], $inputs);
    $input = $inputs_['input']->name();
    grokit_assert(in_array($input, ['BASE::STRING_LITERAL', 'BASE::STRING']), "Match: input should be a string (literal). {$input} given.");
    $result = lookupType('BASE::BOOL');
    $className = generate_name('Pattern');
    $functName = generate_name('Matcher');
    $userHeaders = ['PatternMatcherOnig.h'];
    ?>

class <?php 
    echo $className;
    ?>
 {
 public:
  static PatternMatcherOnig pattern;
};

PatternMatcherOnig <?php 
    echo $className;
    ?>
::pattern("<?php 
    echo $pattern;
    ?>
");

<?php 
    echo $result;
    ?>
 <?php 
    echo $functName;
    ?>
(<?php 
    echo const_typed_ref_args($inputs_);
    ?>
) {
<?php 
    if ($input == 'BASE::STRING_LITERAL') {
        ?>
  return  <?php 
        echo $className;
        ?>
::pattern.Match(input);
<?php 
    } else {
        ?>
  return  <?php 
        echo $className;
        ?>
::pattern.Match(input.ToString());
<?php 
    }
    ?>
}

<?php 
    return ['kind' => 'FUNCTION', 'name' => $functName, 'input' => $inputs, 'result' => $result, 'deterministic' => true, 'user_headers' => $userHeaders];
}
Beispiel #13
0
 public function __construct($hash, $name, $value, array $args, array $origArgs)
 {
     parent::__construct(InfoKind::T_TYPE, $hash, $name, $value, $args, $origArgs[0]);
     $iterator = 'ColumnIterator<' . $value . '>';
     if (array_key_exists('complex', $args)) {
         $iter = $args['complex'];
         if ($iter !== false) {
             $iterator = str_replace('@type', $this->value(), $iter);
         }
     }
     $this->iterator = $iterator;
     if (array_key_exists('destroy', $args)) {
         $destroy = $args['destroy'];
         if (is_bool($destroy)) {
             $this->destroy = $destroy;
         } else {
             grokit_error("Expected boolean value for 'destroy' attribute of datatype " . $this->value());
         }
     }
     if (array_key_exists('dictionary', $args)) {
         $this->dictionary = $args['dictionary'];
     }
     if (array_key_exists('fixed_size', $args)) {
         $this->fixedSize = $args['fixed_size'];
     }
     // Deal with operators defined by the type.
     if (array_key_exists('unary_operators', $args)) {
         foreach ($args['unary_operators'] as $op) {
             LibraryManager::AlphaOperator($op, 1, $this);
         }
     }
     if (array_key_exists('binary_operators', $args)) {
         foreach ($args['binary_operators'] as $op) {
             LibraryManager::AlphaOperator($op, 2, $this);
         }
     }
     if (array_key_exists('constructors', $args)) {
         foreach ($args['constructors'] as $cstr) {
             $cArgs = get_first_key($cstr, ['args', 0]);
             $cDet = get_first_key_default($cstr, ['deterministic', 1], true);
             $myType = $this->value();
             $myName = end(explode('::', $myType));
             $cName = get_first_key_default($cstr, ['c_name', 2], $myName);
             $callback = function ($args, $t_args = []) use($cArgs, $cDet, $myType, $cName) {
                 $myArgs = array_map('lookupType', $cArgs);
                 $myRet = lookupType($myType);
                 $retVal = ['kind' => 'FUNCTION', 'input' => $myArgs, 'result' => $myRet, 'deterministic' => $cDet];
                 if ($cName !== null) {
                     $retVal['name'] = $cName;
                 }
                 return $retVal;
             };
             declareFunctionGlobal('', $myType, $cArgs, $callback);
         }
     }
     if (array_key_exists('functions', $args)) {
         foreach ($args['functions'] as $fnct) {
             $fName = get_first_key($fnct, ['name', 0]);
             $fArgs = get_first_key($fnct, ['args', 1]);
             $fRet = get_first_key($fnct, ['result', 2]);
             $fDet = get_first_key_default($fnct, ['deterministic', 3], false);
             $fGlobal = get_first_key_default($fnct, ['global', 4], false);
             $cName = get_first_key_default($fnct, ['c_name', 5], null);
             foreach ($fArgs as &$arg) {
                 $arg = str_replace('@type', $this->value(), $arg);
             }
             $fRet = str_replace('@type', $this->value(), $fRet);
             $callback = function ($args, $t_args = []) use($fArgs, $fRet, $fDet, $cName, $fGlobal) {
                 $myArgs = array_map('lookupType', $fArgs);
                 $myRet = lookupType($fRet);
                 $retVal = ['kind' => 'FUNCTION', 'input' => $myArgs, 'result' => $myRet, 'deterministic' => $fDet, 'global' => $fGlobal];
                 if ($cName !== null) {
                     $retVal['name'] = $cName;
                 }
                 return $retVal;
             };
             $fNS = $fGlobal ? 'BASE' : LibraryManager::ExtractNamespace($this->value());
             $fName = LibraryManager::JoinNamespace($fNS, $fName);
             declareFunctionGlobal('', $fName, $fArgs, $callback);
         }
     }
     if (array_key_exists('methods', $args)) {
         foreach ($args['methods'] as $method) {
             $mName = get_first_key($method, ['name', 0]);
             $mArgs = get_first_key($method, ['args', 1]);
             $mRet = get_first_key($method, ['result', 2]);
             $mDet = get_first_key_default($method, ['deterministic', 3], false);
             if ($mRet == '@type') {
                 $mRet = $this->value();
             }
             foreach ($mArgs as &$mArg) {
                 if ($mArg == '@type') {
                     $mArg = $this->value();
                 }
             }
             //fwrite(STDERR, 'Defining method ' . $this->value() . '->' . $mName .
             //'(' . implode(', ', $mArgs ) . ') : ' . $mRet . PHP_EOL );
             $info = new MethodInfo($mName, $mArgs, $mRet, $mDet);
             if (!array_key_exists($mName, $this->methods)) {
                 $this->methods[$mName] = [$info];
             } else {
                 foreach ($this->methods[$mName] as $cm) {
                     if ($info == $cm) {
                         grokit_error('Attempting to multiply define method ' . $this->value() . '->' . $mName . '(' . implode(', ', $mArgs) . ')');
                     }
                 }
                 $this->methods[$mName][] = $info;
             }
         }
     }
     if (array_key_exists('describe_json', $args)) {
         $this->describers['json'] = $args['describe_json'];
     }
 }
/**
* generate title, description and source link of a feed
*/
function generate_feed_details($content, $global, &$feed_data)
{
    global $board_url, $config, $user, $db, $phpEx;
    if ($content == 'pm') {
        global $folder;
        // custom folder?
        if (is_int($folder)) {
            global $folder_name;
        } else {
            $user->add_lang('ucp');
            $folder_name = $user->lang['PM_' . strtoupper($folder)];
        }
        $title = sprintf($user->lang['SYNDICATION_PM_TITLE'], $folder_name);
        $description = sprintf($user->lang['SYNDICATION_PM_DESCRIPTION'], $folder_name, $config['sitename']);
        $source_link = "ucp.{$phpEx}?i=pm&amp;folder={$folder}";
    } else {
        // give the feed a name and description
        if ($global) {
            $title = sprintf($user->lang['SYNDICATION_' . strtoupper($content) . '_GLOBAL_TITLE'], $config['sitename']);
            $description = sprintf($user->lang['SYNDICATION_' . strtoupper($content) . '_GLOBAL_DESCRIPTION'], $config['sitename']);
            $source_link = "index.{$phpEx}";
        } else {
            if ($content == 'topic_posts') {
                global $topic_row, $topic_id;
                $title = sprintf($user->lang['SYNDICATION_TOPIC_POSTS_TITLE'], $topic_row['topic_title']);
                $description = sprintf($user->lang['SYNDICATION_TOPIC_POSTS_DESCRIPTION'], $topic_row['topic_title'], $config['sitename']);
                $source_link = "viewtopic.{$phpEx}?f={$topic_row['forum_id']}&amp;t={$topic_id}";
            } else {
                global $single_cat, $only_cats, $forum_ids;
                if ($single_cat) {
                    global $forum_name;
                    $title = sprintf($user->lang['SYNDICATION_' . strtoupper($content) . '_CATEGORY_TITLE'], $forum_name);
                    $description = sprintf($user->lang['SYNDICATION_' . strtoupper($content) . '_CATEGORY_DESCRIPTION'], $forum_name, $config['sitename']);
                    $source_link = "viewforum.{$phpEx}?f=" . get_first_key($forum_ids);
                } else {
                    if ($only_cats) {
                        $title = $user->lang['SYNDICATION_' . strtoupper($content) . '_CATEGORIES_TITLE'];
                        $description = sprintf($user->lang['SYNDICATION_' . strtoupper($content) . '_CATEGORIES_DESCRIPTION'], $config['sitename']);
                        $source_link = "index.{$phpEx}";
                    } else {
                        // if we have only a single forum, get details about it
                        if (sizeof($forum_ids) == 1) {
                            $sql = 'SELECT forum_name
						FROM ' . FORUMS_TABLE . '
						WHERE forum_id = ' . get_first_key($forum_ids);
                            $result = $db->sql_query($sql, 3600);
                            $forum_name = $db->sql_fetchfield('forum_name', 0, $result);
                            $db->sql_freeresult($result);
                            $title = sprintf($user->lang['SYNDICATION_' . strtoupper($content) . '_TITLE'], $forum_name);
                            $description = sprintf($user->lang['SYNDICATION_' . strtoupper($content) . '_DESCRIPTION'], $forum_name, $config['sitename']);
                            $source_link = "viewforum.{$phpEx}?f=" . get_first_key($forum_ids);
                        } else {
                            $title = sprintf($user->lang['SYNDICATION_' . strtoupper($content) . '_VARIOUS_TITLE'], $config['sitename']);
                            $description = sprintf($user->lang['SYNDICATION_' . strtoupper($content) . '_VARIOUS_DESCRIPTION'], $config['sitename']);
                            $source_link = "index.{$phpEx}";
                        }
                    }
                }
            }
        }
    }
    $feed_data += array('title' => $title, 'description' => $description, 'source_link' => "{$board_url}/{$source_link}", 'lang' => $user->data['user_lang']);
}
Beispiel #15
0
function CSVReader(array $t_args, array $output)
{
    $my_output = [];
    // Handle case where outputs are given as template arguments
    // and not implied.
    if (\count($output) == 0) {
        grokit_assert(array_key_exists('output', $t_args), 'Did not receive any description of my output!');
        $output_list = $t_args['output'];
        grokit_assert(is_array($output_list), 'Expected list of types for template argument "output"');
        $i = 1;
        foreach ($outputs_list as $name => $out_type) {
            grokit_assert(is_datatype($out_type) || is_identifier($out_type), 'Expected only types in the "output" list');
            if (is_identifier($out_type)) {
                $out_type = lookupType($out_type->value());
            }
            $name = 'val_' . $i;
            $my_output[$name] = $out_type;
            $i += 1;
        }
    } else {
        foreach ($output as $key => $out) {
            $name = $key;
            $my_output[$name] = $out;
        }
    }
    $debug = get_default($t_args, 'debug', 0);
    $simple = get_default($t_args, 'simple', false);
    $trimCR = get_default($t_args, 'trim.cr', false);
    // Handle separator
    $separator = ',';
    if (array_key_exists('sep', $t_args) || array_key_exists('separator', $t_args)) {
        $sep = get_first_key($t_args, ['sep', 'separator']);
        grokit_assert(is_string($sep), "Got " . gettype($sep) . " instead of string for separator.");
        if (strtolower($sep) === 'tab') {
            $sep = '\\t';
        }
        grokit_assert($sep != "\n", 'CSV column delimiter cannot be new line');
        // Scream if separator is longer than one character
        grokit_assert(\strlen($sep) == 1 || $sep == '\\t', 'Expected string of length 1 for separator, got string <' . $sep . '> instead');
        $separator = $sep;
    }
    // Handle quote character
    $quotechar = '"';
    if (array_key_exists('quote', $t_args) && !is_null($t_args['quote'])) {
        grokit_assert(!$simple, 'Quote option not available for simple CSVReader');
        $quote = $t_args['quote'];
        grokit_assert(is_string($quote), "Got " . gettype($quote) . " instead of string for quote.");
        // Scream if separator is longer than one character
        grokit_assert(\strlen($quote) == 1, 'Expected string of length 1 for quote character, got string <' . $quote . '> instead');
        $quotechar = $quote;
    }
    $quotechar = addcslashes($quotechar, '\\\'');
    // Handle escape character
    $escapeChar = '\\';
    if (array_key_exists('escape', $t_args) && !is_null($t_args['escape'])) {
        grokit_assert(!$simple, 'Escape option not available for simple CSVReader');
        $escape = $t_args['escape'];
        grokit_assert(is_string($escape), 'Got ' . gettype($escape) . ' instead of string for escape character.');
        grokit_assert(\strlen($escape) == 1, 'Expected string of length 1 for escape character, got string <' . $escape . '> instead');
        $escapeChar = $escape;
    }
    $escapeChar = addcslashes($escapeChar, '\\\'');
    // Handle header lines
    $headerLines = 0;
    if (array_key_exists('skip', $t_args)) {
        $headerLines = $t_args['skip'];
        grokit_assert(is_int($headerLines), 'Got ' . gettype($headerLines) . ' instead of int for number of lines to skip.');
        grokit_assert($headerLines >= 0, 'Cannot skip a negative number of lines.');
    }
    // Maximum number of lines to read
    $maxLines = get_default($t_args, 'n', -1);
    grokit_assert(is_int($maxLines), 'Got ' . gettype($maxLines) . ' instead of int for template argument "n"');
    $nullArg = get_first_key_default($t_args, ['nullable'], false);
    $nullable = [];
    $nullStr = [];
    foreach ($my_output as $name => $type) {
        $nullable[$name] = false;
    }
    if ($nullArg === true) {
        foreach ($my_output as $name => $type) {
            $nullable[$name] = true;
            $nullStr[$name] = 'NULL';
        }
    } else {
        if (is_array($nullArg)) {
            foreach ($nullArg as $n => $v) {
                // If nullable value is an associative mapping, the value is either true/false
                // or the value of the null string
                if (is_string($n)) {
                    grokit_assert(is_string($v) || is_bool($v), 'CSVReader: nullable associative mapping must have string or boolean values');
                    grokit_assert(array_key_exists($n, $nullable), 'CSVReader: cannot make unknown attribute ' . $n . ' nullable');
                    if (is_bool($v)) {
                        $nullable[$n] = $v;
                        $nullStr[$n] = 'NULL';
                    } else {
                        $nullable[$n] = true;
                        $nullStr[$n] = $v;
                    }
                } else {
                    if (is_array($v)) {
                        grokit_assert(array_key_exists('attr', $v), 'CSVReader: Name of nullable attribute not specified');
                        $attrName = $v['attr']->name();
                        $nullable[$attrName] = true;
                        $nullStr[$attrName] = array_key_exists('null', $v) ? $v['null'] : 'NULL';
                    } else {
                        // Otherwise, it's just nullable
                        $attrName = $v->name();
                        grokit_assert(array_key_exists($attrName, $nullable), 'CSVReader: cannot make unknown attribute ' . $v . ' nullable');
                        $nullable[$attrName] = true;
                        $nullStr[$attrName] = 'NULL';
                    }
                }
            }
        } else {
            if ($nullArg === false) {
                // Nothing
            } else {
                if (is_string($nullArg)) {
                    foreach ($my_output as $name => $type) {
                        $nullable[$name] = true;
                        $nullStr[$name] = $nullArg;
                    }
                } else {
                    grokit_error('Template argument "nullable" must be boolean or array, ' . typeof($nullArg) . ' given');
                }
            }
        }
    }
    // Come up with a name for ourselves
    $className = generate_name('CSVReader');
    if ($debug >= 2) {
        foreach ($my_output as $name => $type) {
            fwrite(STDERR, "CSVReader: {$name} is nullable: " . ($nullable[$name] ? 'true' : 'false') . PHP_EOL);
        }
    }
    ?>

class <?php 
    echo $className;
    ?>
 {
    std::istream& my_stream;
    std::string fileName;

    // Template parameters
    static constexpr size_t MAX_LINES = <?php 
    echo $maxLines;
    ?>
;
    static constexpr size_t HEADER_LINES = <?php 
    echo $headerLines;
    ?>
;
    static constexpr char DELIMITER = '<?php 
    echo $separator;
    ?>
';
<?php 
    if (!$simple) {
        ?>
    static constexpr char QUOTE_CHAR = '<?php 
        echo $quotechar;
        ?>
';
    static constexpr char ESCAPE_CHAR = '<?php 
        echo $escapeChar;
        ?>
';

    typedef boost::escaped_list_separator<char> separator;
    typedef boost::tokenizer< separator > Tokenizer;
    separator my_separator;
    Tokenizer my_tokenizer;
<?php 
    }
    ?>

    // Prevent having to allocate this every time.
    std::string line;
    std::vector<std::string> tokens;

    size_t count;

<?php 
    \grokit\declareDictionaries($my_output);
    ?>

public:

    <?php 
    echo $className;
    ?>
 ( GIStreamProxy& _stream ) :
        my_stream(_stream.get_stream())
        , fileName(_stream.get_file_name())
<?php 
    if (!$simple) {
        ?>
        , my_separator(ESCAPE_CHAR, DELIMITER, QUOTE_CHAR)
        , my_tokenizer(std::string(""))
<?php 
    }
    ?>
        , count(0)
    {
<?php 
    if ($headerLines > 0) {
        ?>
        for( size_t i = 0; i < HEADER_LINES; ++i ) {
            FATALIF( !getline( my_stream, line ), "CSV Reader reached end of file before finishing header.\n" );
        }
<?php 
    }
    // If headerLines > 0
    ?>
    }

// >

    bool ProduceTuple( <?php 
    echo typed_ref_args($my_output);
    ?>
 ) {
        if (count < MAX_LINES) { //>
            count++;
        } else {
            return false;
        }

        if( getline( my_stream, line ) ) {
<?php 
    if ($trimCR) {
        ?>
            if( line.back() == '\r' ) {
                line.pop_back();
            }
<?php 
    }
    // if trimCR
    if (!$simple) {
        if ($debug >= 1) {
            ?>
            try {
<?php 
        }
        // if debug >= 1
        ?>
            my_tokenizer.assign( line, my_separator );
<?php 
        if ($debug >= 1) {
            ?>
            } catch(...) {
                FATAL("CSVReader for file %s failed on line: %s", fileName.c_str(), line.c_str());
            }
<?php 
        }
        // if debug >= 1
        ?>
            Tokenizer::iterator it = my_tokenizer.begin();

<?php 
        foreach ($my_output as $name => $type) {
            if ($nullable[$name]) {
                // nullable
                ?>
            <?php 
                \grokit\fromStringNullable($name, $type, 'it->c_str()', true, $nullStr[$name]);
                ?>

<?php 
            } else {
                // not nullable
                ?>
            <?php 
                echo \grokit\fromStringDict($name, $type, 'it->c_str()');
                ?>
;
<?php 
            }
            // end nullable check
            ?>
            ++it;
<?php 
        }
        // foreach output
    } else {
        ?>
            for( char & c : line ) {
                if( c == DELIMITER )
                    c = '\0';
            }

            const char * ptr = line.c_str();
<?php 
        $first = true;
        foreach ($my_output as $name => $type) {
            if ($first) {
                $first = false;
            } else {
                ?>
            while( *(ptr++) != '\0' )
                ; // Advance past next delimiter
<?php 
            }
            // not first output
            if ($nullable[$name]) {
                ?>
            <?php 
                echo \grokit\fromStringNullable($name, $type, 'ptr', true, $nullStr[$name]);
            } else {
                // not nullable
                ?>
            <?php 
                echo \grokit\fromStringDict($name, $type, 'ptr');
                ?>
;
<?php 
            }
            // if nullable
        }
        // foreach output
    }
    // if simple reader
    ?>

            return true;
        }
        else {
            return false;
        }
    }

<?php 
    \grokit\declareDictionaryGetters($my_output);
    ?>
};

<?php 
    $sys_headers = ['vector', 'string', 'iostream', 'cstdint'];
    if (!$simple) {
        $sys_headers[] = 'boost/tokenizer.hpp';
    }
    return ['name' => $className, 'kind' => 'GI', 'output' => $my_output, 'system_headers' => $sys_headers, 'user_headers' => ['GIStreamInfo.h', 'Dictionary.h', 'DictionaryManager.h']];
}