Example #1
0
 /**
  * @param TupleType $type
  *
  * @return LogicalAnd|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;
 }
 /**
  * Visit a tuple type.
  *
  * @param TupleType $type The type.
  *
  * @return mixed The result of visitation.
  */
 public function visitTupleType(TupleType $type)
 {
     $subTypes = array();
     foreach ($type->types() as $subType) {
         $subTypes[] = $subType->accept($this);
     }
     return sprintf('tuple<%s>', implode(',', $subTypes));
 }