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

        $primaryExpression = $type->primaryType()->accept($this);

        if (
            $type->primaryType() instanceof ArrayType &&
            $type->keyType() instanceof MixedType &&
            $type->valueType() instanceof MixedType
        ) {
            return $primaryExpression;
        }

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

        $notTraversableObjectExpression = new LogicalNot(
            new InstanceOfType(
                $valueVariable,
                QualifiedIdentifier::fromString('\Traversable')
            )
        );
        $isArrayCall = new Call(QualifiedIdentifier::fromString('\is_array'));
        $isArrayCall->add($valueVariable);
        $notArrayExpression = new LogicalNot($isArrayCall);
        if ($type->primaryType() instanceof ArrayType) {
            $notTraversableExpression = $notArrayExpression;
        } elseif ($type->primaryType() instanceof ObjectType) {
            $notTraversableExpression = $notTraversableObjectExpression;
        } else {
            $notTraversableExpression = new LogicalAnd(
                $notArrayExpression,
                $notTraversableObjectExpression
            );
        }
        $ifStatement = new IfStatement($notTraversableExpression);
        $ifStatement->trueBranch()->add(
            new ReturnStatement(new Literal(false))
        );
        $closure->statementBlock()->add($ifStatement);

        $keyIdentifier = new Identifier('key');
        $subValueIdentifier = new Identifier('subValue');
        $loopStatement = new StatementBlock;

        $keyVariable = new Variable($keyIdentifier);
        $oldValueIdentifier = $this->valueIdentifier;
        $this->valueIdentifier = $keyIdentifier;
        $keyExpression = $type->keyType()->accept($this);
        $this->valueIdentifier = $oldValueIdentifier;
        if ($keyExpression instanceof Closure) {
            $keyCheckVariable = new Variable(new Identifier('keyCheck'));
            $closure->statementBlock()->add(new ExpressionStatement(new Assign(
                $keyCheckVariable,
                $keyExpression
            )));
            $keyExpression = new Call($keyCheckVariable);
            $keyExpression->add($keyVariable);
        }
        if (null !== $keyExpression) {
            $ifStatement = new IfStatement(new LogicalNot($keyExpression));
            $ifStatement->trueBranch()->add(
                new ReturnStatement(new Literal(false))
            );
            $loopStatement->add($ifStatement);
        }

        $subValueVariable = new Variable($subValueIdentifier);
        $oldValueIdentifier = $this->valueIdentifier;
        $this->valueIdentifier = $subValueIdentifier;
        $valueExpression = $type->valueType()->accept($this);
        $this->valueIdentifier = $oldValueIdentifier;
        if ($valueExpression instanceof Closure) {
            $valueCheckVariable = new Variable(new Identifier('valueCheck'));
            $closure->statementBlock()->add(new ExpressionStatement(new Assign(
                $valueCheckVariable,
                $valueExpression
            )));
            $valueExpression = new Call($valueCheckVariable);
            $valueExpression->add($subValueVariable);
        }
        if (null !== $valueExpression) {
            $ifStatement = new IfStatement(new LogicalNot($valueExpression));
            $ifStatement->trueBranch()->add(
                new ReturnStatement(new Literal(false))
            );
            $loopStatement->add($ifStatement);
        }

        $closure->statementBlock()->add(new ForeachStatement(
            $valueVariable,
            new Parameter($keyIdentifier),
            new Parameter($subValueIdentifier),
            $loopStatement
        ));
        $closure->statementBlock()->add(new ReturnStatement(new Literal(true)));

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

        $primaryExpression = $type->primaryType()->accept($this);

        if (
            $type->primaryType() instanceof ArrayType &&
            $type->keyType() instanceof MixedType &&
            $type->valueType() instanceof MixedType
        ) {
            return $primaryExpression;
        }

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

        $notTraversableObjectExpression = new LogicalNot(
            new InstanceOfType(
                $valueVariable,
                QualifiedIdentifier::fromString('\Traversable')
            )
        );
        $isArrayCall = new Call(QualifiedIdentifier::fromString('\is_array'));
        $isArrayCall->add($valueVariable);
        $notArrayExpression = new LogicalNot($isArrayCall);
        if ($type->primaryType() instanceof ArrayType) {
            $notTraversableExpression = $notArrayExpression;
        } elseif ($type->primaryType() instanceof ObjectType) {
            $notTraversableExpression = $notTraversableObjectExpression;
        } else {
            $notTraversableExpression = new LogicalAnd(
                $notArrayExpression,
                $notTraversableObjectExpression
            );
        }
        $ifStatement = new IfStatement($notTraversableExpression);
        $ifStatement->trueBranch()->add(
            new ReturnStatement(new Literal(false))
        );
        $closure->statementBlock()->add($ifStatement);

        $keyIdentifier = new Identifier('key');
        $subValueIdentifier = new Identifier('subValue');
        $loopStatement = new StatementBlock;

        $keyVariable = new Variable($keyIdentifier);
        $oldValueIdentifier = $this->valueIdentifier;
        $this->valueIdentifier = $keyIdentifier;
        $keyExpression = $type->keyType()->accept($this);
        $this->valueIdentifier = $oldValueIdentifier;
        if ($keyExpression instanceof Closure) {
            $keyCheckVariable = new Variable(new Identifier('keyCheck'));
            $closure->statementBlock()->add(new ExpressionStatement(new Assign(
                $keyCheckVariable,
                $keyExpression
            )));
            $keyExpression = new Call($keyCheckVariable);
            $keyExpression->add($keyVariable);
        }
        if (null !== $keyExpression) {
            $ifStatement = new IfStatement(new LogicalNot($keyExpression));
            $ifStatement->trueBranch()->add(
                new ReturnStatement(new Literal(false))
            );
            $loopStatement->add($ifStatement);
        }

        $subValueVariable = new Variable($subValueIdentifier);
        $oldValueIdentifier = $this->valueIdentifier;
        $this->valueIdentifier = $subValueIdentifier;
        $valueExpression = $type->valueType()->accept($this);
        $this->valueIdentifier = $oldValueIdentifier;
        if ($valueExpression instanceof Closure) {
            $valueCheckVariable = new Variable(new Identifier('valueCheck'));
            $closure->statementBlock()->add(new ExpressionStatement(new Assign(
                $valueCheckVariable,
                $valueExpression
            )));
            $valueExpression = new Call($valueCheckVariable);
            $valueExpression->add($subValueVariable);
        }
        if (null !== $valueExpression) {
            $ifStatement = new IfStatement(new LogicalNot($valueExpression));
            $ifStatement->trueBranch()->add(
                new ReturnStatement(new Literal(false))
            );
            $loopStatement->add($ifStatement);
        }

        $closure->statementBlock()->add(new ForeachStatement(
            $valueVariable,
            new Parameter($keyIdentifier),
            new Parameter($subValueIdentifier),
            $loopStatement
        ));
        $closure->statementBlock()->add(new ReturnStatement(new Literal(true)));

        return $closure;
    }
public function visitTraversableType ( TraversableType $ type ) { $ this -> typeCheck -> visitTraversableType ( func_get_args ( ) ) ; $ primaryExpression = $ type -> primaryType ( ) -> accept ( $ this ) ; if ( $ type -> primaryType ( ) instanceof ArrayType && $ type -> keyType ( ) instanceof MixedType && $ type -> valueType ( ) instanceof MixedType ) { return $ primaryExpression ; } $ closure = new Closure ; $ closure -> addParameter ( new Parameter ( $ this -> valueIdentifier ) ) ; $ valueVariable = new Variable ( $ this -> valueIdentifier ) ; $ notTraversableObjectExpression = new LogicalNot ( new InstanceOfType ( $ valueVariable , QualifiedIdentifier :: fromString ( '\Traversable' ) ) ) ; $ isArrayCall = new Call ( QualifiedIdentifier :: fromString ( '\is_array' ) ) ; $ isArrayCall -> add ( $ valueVariable ) ; $ notArrayExpression = new LogicalNot ( $ isArrayCall ) ; if ( $ type -> primaryType ( ) instanceof ArrayType ) { $ notTraversableExpression = $ notArrayExpression ; } elseif ( $ type -> primaryType ( ) instanceof ObjectType ) { $ notTraversableExpression = $ notTraversableObjectExpression ; } else { $ notTraversableExpression = new LogicalAnd ( $ notArrayExpression , $ notTraversableObjectExpression ) ; } $ ifStatement = new IfStatement ( $ notTraversableExpression ) ; $ ifStatement -> trueBranch ( ) -> add ( new ReturnStatement ( new Literal ( false ) ) ) ; $ closure -> statementBlock ( ) -> add ( $ ifStatement ) ; $ keyIdentifier = new Identifier ( 'key' ) ; $ subValueIdentifier = new Identifier ( 'subValue' ) ; $ loopStatement = new StatementBlock ; $ keyVariable = new Variable ( $ keyIdentifier ) ; $ oldValueIdentifier = $ this -> valueIdentifier ; $ this -> valueIdentifier = $ keyIdentifier ; $ keyExpression = $ type -> keyType ( ) -> accept ( $ this ) ; $ this -> valueIdentifier = $ oldValueIdentifier ; if ( $ keyExpression instanceof Closure ) { $ keyCheckVariable = new Variable ( new Identifier ( 'keyCheck' ) ) ; $ closure -> statementBlock ( ) -> add ( new ExpressionStatement ( new Assign ( $ keyCheckVariable , $ keyExpression ) ) ) ; $ keyExpression = new Call ( $ keyCheckVariable ) ; $ keyExpression -> add ( $ keyVariable ) ; } if ( null !== $ keyExpression ) { $ ifStatement = new IfStatement ( new LogicalNot ( $ keyExpression ) ) ; $ ifStatement -> trueBranch ( ) -> add ( new ReturnStatement ( new Literal ( false ) ) ) ; $ loopStatement -> add ( $ ifStatement ) ; } $ subValueVariable = new Variable ( $ subValueIdentifier ) ; $ oldValueIdentifier = $ this -> valueIdentifier ; $ this -> valueIdentifier = $ subValueIdentifier ; $ valueExpression = $ type -> valueType ( ) -> accept ( $ this ) ; $ this -> valueIdentifier = $ oldValueIdentifier ; if ( $ valueExpression instanceof Closure ) { $ valueCheckVariable = new Variable ( new Identifier ( 'valueCheck' ) ) ; $ closure -> statementBlock ( ) -> add ( new ExpressionStatement ( new Assign ( $ valueCheckVariable , $ valueExpression ) ) ) ; $ valueExpression = new Call ( $ valueCheckVariable ) ; $ valueExpression -> add ( $ subValueVariable ) ; } if ( null !== $ valueExpression ) { $ ifStatement = new IfStatement ( new LogicalNot ( $ valueExpression ) ) ; $ ifStatement -> trueBranch ( ) -> add ( new ReturnStatement ( new Literal ( false ) ) ) ; $ loopStatement -> add ( $ ifStatement ) ; } $ closure -> statementBlock ( ) -> add ( new ForeachStatement ( $ valueVariable , new Parameter ( $ keyIdentifier ) , new Parameter ( $ subValueIdentifier ) , $ loopStatement ) ) ; $ closure -> statementBlock ( ) -> add ( new ReturnStatement ( new Literal ( true ) ) ) ; return $ closure ; }
@param TraversableType $type

@return Call|Closure
@param TraversableType $type