Example #1
0
 /**
  * @param TraversableType $type
  *
  * @return Call|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;
 }
 /**
  * Visit a traversable type.
  *
  * @param TraversableType $type The type.
  *
  * @return mixed The result of visitation.
  */
 public function visitTraversableType(TraversableType $type)
 {
     $primaryType = $type->primaryType()->accept($this);
     $subTypes = array();
     if ($type->keyType()) {
         $subTypes[] = $type->keyType()->accept($this);
         $subTypes[] = $type->valueType()->accept($this);
     } elseif (!$type->primaryType() instanceof ArrayType || !$type->valueType() instanceof MixedType) {
         $subTypes[] = $type->valueType()->accept($this);
     }
     if (count($subTypes) < 1) {
         return $primaryType;
     }
     return sprintf('%s<%s>', $primaryType, implode(',', $subTypes));
 }