public function visitStreamType(StreamType $type)
    {
        $this->typeCheck->visitStreamType(func_get_args());

        $isResourceCall = new Call(QualifiedIdentifier::fromString('\is_resource'));
        $isResourceCall->add($this->valueExpression());
        $getResourceTypeCall = new Call(QualifiedIdentifier::fromString('\get_resource_type'));
        $getResourceTypeCall->add($this->valueExpression());
        $isStreamExpression = new LogicalAnd(
            $isResourceCall,
            new StrictEquals(
                $getResourceTypeCall,
                new Literal('stream')
            )
        );

        if (
            null === $type->readable() &&
            null === $type->writable()
        ) {
            return $isStreamExpression;
        }

        $closure = new Closure;
        $closure->addParameter(new Parameter(new Identifier('value')));

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

        $streamMetaDataVariable = new Variable(new Identifier('streamMetaData'));
        $streamModeExpression = new Subscript(
            $streamMetaDataVariable,
            new Literal('mode')
        );

        $streamGetMetaDataCall = new Call(
            QualifiedIdentifier::fromString('stream_get_meta_data')
        );
        $streamGetMetaDataCall->add($this->valueExpression());
        $closure->statementBlock()->add(new ExpressionStatement(new Assign(
            $streamMetaDataVariable,
            $streamGetMetaDataCall
        )));

        if (null !== $type->readable()) {
            $strpbrkCall = new Call(QualifiedIdentifier::fromString('\strpbrk'));
            $strpbrkCall->add($streamModeExpression);
            $strpbrkCall->add(new Literal('r+'));
            $isReadableExpression = new StrictNotEquals(
                $strpbrkCall,
                new Literal(false)
            );

            if (null === $type->writable()) {
                if ($type->readable()) {
                    $closure->statementBlock()->add(new ReturnStatement($isReadableExpression));
                } else {
                    $closure->statementBlock()->add(new ReturnStatement(new LogicalNot($isReadableExpression)));
                }
            } else {
                if ($type->readable()) {
                    $ifStatement = new IfStatement(new LogicalNot($isReadableExpression));
                    $ifStatement->trueBranch()->add(
                        new ReturnStatement(new Literal(false))
                    );
                } else {
                    $ifStatement = new IfStatement($isReadableExpression);
                    $ifStatement->trueBranch()->add(
                        new ReturnStatement(new Literal(false))
                    );
                }
                $closure->statementBlock()->add($ifStatement);
            }
        }

        if (null !== $type->writable()) {
            $strpbrkCall = new Call(QualifiedIdentifier::fromString('\strpbrk'));
            $strpbrkCall->add($streamModeExpression);
            $strpbrkCall->add(new Literal('waxc+'));
            $isWritableExpression = new StrictNotEquals(
                $strpbrkCall,
                new Literal(false)
            );

            if ($type->writable()) {
                $closure->statementBlock()->add(new ReturnStatement($isWritableExpression));
            } else {
                $closure->statementBlock()->add(new ReturnStatement(new LogicalNot($isWritableExpression)));
            }
        }

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

        $isResourceCall = new Call(QualifiedIdentifier::fromString('\is_resource'));
        $isResourceCall->add($this->valueExpression());
        $getResourceTypeCall = new Call(QualifiedIdentifier::fromString('\get_resource_type'));
        $getResourceTypeCall->add($this->valueExpression());
        $isStreamExpression = new LogicalAnd(
            $isResourceCall,
            new StrictEquals(
                $getResourceTypeCall,
                new Literal('stream')
            )
        );

        if (
            null === $type->readable() &&
            null === $type->writable()
        ) {
            return $isStreamExpression;
        }

        $closure = new Closure;
        $closure->addParameter(new Parameter(new Identifier('value')));

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

        $streamMetaDataVariable = new Variable(new Identifier('streamMetaData'));
        $streamModeExpression = new Subscript(
            $streamMetaDataVariable,
            new Literal('mode')
        );

        $streamGetMetaDataCall = new Call(
            QualifiedIdentifier::fromString('stream_get_meta_data')
        );
        $streamGetMetaDataCall->add($this->valueExpression());
        $closure->statementBlock()->add(new ExpressionStatement(new Assign(
            $streamMetaDataVariable,
            $streamGetMetaDataCall
        )));

        if (null !== $type->readable()) {
            $strpbrkCall = new Call(QualifiedIdentifier::fromString('\strpbrk'));
            $strpbrkCall->add($streamModeExpression);
            $strpbrkCall->add(new Literal('r+'));
            $isReadableExpression = new StrictNotEquals(
                $strpbrkCall,
                new Literal(false)
            );

            if (null === $type->writable()) {
                if ($type->readable()) {
                    $closure->statementBlock()->add(new ReturnStatement($isReadableExpression));
                } else {
                    $closure->statementBlock()->add(new ReturnStatement(new LogicalNot($isReadableExpression)));
                }
            } else {
                if ($type->readable()) {
                    $ifStatement = new IfStatement(new LogicalNot($isReadableExpression));
                    $ifStatement->trueBranch()->add(
                        new ReturnStatement(new Literal(false))
                    );
                } else {
                    $ifStatement = new IfStatement($isReadableExpression);
                    $ifStatement->trueBranch()->add(
                        new ReturnStatement(new Literal(false))
                    );
                }
                $closure->statementBlock()->add($ifStatement);
            }
        }

        if (null !== $type->writable()) {
            $strpbrkCall = new Call(QualifiedIdentifier::fromString('\strpbrk'));
            $strpbrkCall->add($streamModeExpression);
            $strpbrkCall->add(new Literal('waxc+'));
            $isWritableExpression = new StrictNotEquals(
                $strpbrkCall,
                new Literal(false)
            );

            if ($type->writable()) {
                $closure->statementBlock()->add(new ReturnStatement($isWritableExpression));
            } else {
                $closure->statementBlock()->add(new ReturnStatement(new LogicalNot($isWritableExpression)));
            }
        }

        return $closure;
    }
@param StreamType $type

@return LogicalAnd|Closure