src/Eloquent/Typhoon/Generator/TyphaxASTGenerator.php
public function visitTupleType(TupleType $type)
    {
        $this->typeCheck->visitTupleType(func_get_args());

        $tupleSize = count($type->types());
        $isArrayCall = new Call(QualifiedIdentifier::fromString('\is_array'));
        $isArrayCall->add($this->valueExpression());
        $arrayKeysCall = new Call(QualifiedIdentifier::fromString('\array_keys'));
        $arrayKeysCall->add($this->valueExpression());
        $rangeCall = new Call(QualifiedIdentifier::fromString('\range'));
        $rangeCall->add(new Literal(0));
        $rangeCall->add(new Literal($tupleSize - 1));
        $sequentialKeyExpression = new StrictEquals(
            $arrayKeysCall,
            $rangeCall
        );
        $expressions = array(
            $isArrayCall,
            $sequentialKeyExpression
        );

        $closures = array();
        $closureCalls = array();
        $checkVariable = new Variable(new Identifier('check'));
        foreach ($type->types() as $index => $subType) {
            $this->valueIndex = $index;

            $expression = $subType->accept($this);
            if ($expression instanceof Closure) {
                $closures[] = $expression;
                $checkCall = new Call($checkVariable);
                $checkCall->add($this->valueExpression());
                $closureCalls[] = $checkCall;
            } else {
                $expressions[] = $expression;
            }
        }
        $this->valueIndex = null;

        $tupleExpression = null;
        foreach ($expressions as $expression) {
            if ($tupleExpression) {
                $tupleExpression->add($expression);
            } else {
                $tupleExpression = new LogicalAnd($expression);
            }
        }

        $numClosures = count($closures);
        if ($numClosures < 1) {
            return $tupleExpression;
        }

        $closure = new Closure;
        $closure->addParameter(new Parameter($this->valueIdentifier));

        $ifStatement = new IfStatement(new LogicalNot($tupleExpression));
        $ifStatement->trueBranch()->add(
            new ReturnStatement(new Literal(false))
        );
        $closure->statementBlock()->add($ifStatement);

        $lastClosureIndex = $numClosures - 1;
        for ($i = 0; $i < $lastClosureIndex; $i ++) {
            $closure->statementBlock()->add(new ExpressionStatement(new Assign(
                $checkVariable,
                $closures[$i]
            )));
            $ifStatement = new IfStatement(new LogicalNot($closureCalls[$i]));
            $ifStatement->trueBranch()->add(
                new ReturnStatement(new Literal(false))
            );
            $closure->statementBlock()->add($ifStatement);
        }

        $closure->statementBlock()->add(new ExpressionStatement(new Assign(
            $checkVariable,
            $closures[$lastClosureIndex]
        )));
        $closure->statementBlock()->add(new ReturnStatement($closureCalls[$lastClosureIndex]));

        return $closure;
    }
public function visitTupleType(TupleType $type)
    {
        $this->typeCheck->visitTupleType(func_get_args());

        $tupleSize = count($type->types());
        $isArrayCall = new Call(QualifiedIdentifier::fromString('\is_array'));
        $isArrayCall->add($this->valueExpression());
        $arrayKeysCall = new Call(QualifiedIdentifier::fromString('\array_keys'));
        $arrayKeysCall->add($this->valueExpression());
        $rangeCall = new Call(QualifiedIdentifier::fromString('\range'));
        $rangeCall->add(new Literal(0));
        $rangeCall->add(new Literal($tupleSize - 1));
        $sequentialKeyExpression = new StrictEquals(
            $arrayKeysCall,
            $rangeCall
        );
        $expressions = array(
            $isArrayCall,
            $sequentialKeyExpression
        );

        $closures = array();
        $closureCalls = array();
        $checkVariable = new Variable(new Identifier('check'));
        foreach ($type->types() as $index => $subType) {
            $this->valueIndex = $index;

            $expression = $subType->accept($this);
            if ($expression instanceof Closure) {
                $closures[] = $expression;
                $checkCall = new Call($checkVariable);
                $checkCall->add($this->valueExpression());
                $closureCalls[] = $checkCall;
            } else {
                $expressions[] = $expression;
            }
        }
        $this->valueIndex = null;

        $tupleExpression = null;
        foreach ($expressions as $expression) {
            if ($tupleExpression) {
                $tupleExpression->add($expression);
            } else {
                $tupleExpression = new LogicalAnd($expression);
            }
        }

        $numClosures = count($closures);
        if ($numClosures < 1) {
            return $tupleExpression;
        }

        $closure = new Closure;
        $closure->addParameter(new Parameter($this->valueIdentifier));

        $ifStatement = new IfStatement(new LogicalNot($tupleExpression));
        $ifStatement->trueBranch()->add(
            new ReturnStatement(new Literal(false))
        );
        $closure->statementBlock()->add($ifStatement);

        $lastClosureIndex = $numClosures - 1;
        for ($i = 0; $i < $lastClosureIndex; $i ++) {
            $closure->statementBlock()->add(new ExpressionStatement(new Assign(
                $checkVariable,
                $closures[$i]
            )));
            $ifStatement = new IfStatement(new LogicalNot($closureCalls[$i]));
            $ifStatement->trueBranch()->add(
                new ReturnStatement(new Literal(false))
            );
            $closure->statementBlock()->add($ifStatement);
        }

        $closure->statementBlock()->add(new ExpressionStatement(new Assign(
            $checkVariable,
            $closures[$lastClosureIndex]
        )));
        $closure->statementBlock()->add(new ReturnStatement($closureCalls[$lastClosureIndex]));

        return $closure;
    }
public function visitTupleType ( TupleType $ type ) { $ this -> typeCheck -> visitTupleType ( func_get_args ( ) ) ; $ tupleSize = count ( $ type -> types ( ) ) ; $ isArrayCall = new Call ( QualifiedIdentifier :: fromString ( '\is_array' ) ) ; $ isArrayCall -> add ( $ this -> valueExpression ( ) ) ; $ arrayKeysCall = new Call ( QualifiedIdentifier :: fromString ( '\array_keys' ) ) ; $ arrayKeysCall -> add ( $ this -> valueExpression ( ) ) ; $ rangeCall = new Call ( QualifiedIdentifier :: fromString ( '\range' ) ) ; $ rangeCall -> add ( new Literal ( 0 ) ) ; $ rangeCall -> add ( new Literal ( $ tupleSize - 1 ) ) ; $ sequentialKeyExpression = new StrictEquals ( $ arrayKeysCall , $ rangeCall ) ; $ expressions = array ( $ isArrayCall , $ sequentialKeyExpression ) ; $ closures = array ( ) ; $ closureCalls = array ( ) ; $ checkVariable = new Variable ( new Identifier ( 'check' ) ) ; foreach ( $ type -> types ( ) as $ index => $ subType ) { $ this -> valueIndex = $ index ; $ expression = $ subType -> accept ( $ this ) ; if ( $ expression instanceof Closure ) { $ closures [ ] = $ expression ; $ checkCall = new Call ( $ checkVariable ) ; $ checkCall -> add ( $ this -> valueExpression ( ) ) ; $ closureCalls [ ] = $ checkCall ; } else { $ expressions [ ] = $ expression ; } } $ this -> valueIndex = null ; $ tupleExpression = null ; foreach ( $ expressions as $ expression ) { if ( $ tupleExpression ) { $ tupleExpression -> add ( $ expression ) ; } else { $ tupleExpression = new LogicalAnd ( $ expression ) ; } } $ numClosures = count ( $ closures ) ; if ( $ numClosures < 1 ) { return $ tupleExpression ; } $ closure = new Closure ; $ closure -> addParameter ( new Parameter ( $ this -> valueIdentifier ) ) ; $ ifStatement = new IfStatement ( new LogicalNot ( $ tupleExpression ) ) ; $ ifStatement -> trueBranch ( ) -> add ( new ReturnStatement ( new Literal ( false ) ) ) ; $ closure -> statementBlock ( ) -> add ( $ ifStatement ) ; $ lastClosureIndex = $ numClosures - 1 ; for ( $ i = 0 ; $ i < $ lastClosureIndex ; $ i ++ ) { $ closure -> statementBlock ( ) -> add ( new ExpressionStatement ( new Assign ( $ checkVariable , $ closures [ $ i ] ) ) ) ; $ ifStatement = new IfStatement ( new LogicalNot ( $ closureCalls [ $ i ] ) ) ; $ ifStatement -> trueBranch ( ) -> add ( new ReturnStatement ( new Literal ( false ) ) ) ; $ closure -> statementBlock ( ) -> add ( $ ifStatement ) ; } $ closure -> statementBlock ( ) -> add ( new ExpressionStatement ( new Assign ( $ checkVariable , $ closures [ $ lastClosureIndex ] ) ) ) ; $ closure -> statementBlock ( ) -> add ( new ReturnStatement ( $ closureCalls [ $ lastClosureIndex ] ) ) ; return $ closure ; }
@param TupleType $type

@return LogicalAnd|Closure
@param TupleType $type