protected function generateConstructor(RuntimeConfiguration $configuration)
    {
        $this->typeCheck->generateConstructor(func_get_args());

        $parameterNameIdentifier = new Identifier('parameterName');
        $parameterNameVariable = new Variable($parameterNameIdentifier);
        $indexIdentifier = new Identifier('index');
        $indexVariable = new Variable($indexIdentifier);
        $valueIdentifier = new Identifier('value');
        $valueVariable = new Variable($valueIdentifier);
        $expectedTypeIdentifier = new Identifier('expectedType');
        $expectedTypeVariable = new Variable($expectedTypeIdentifier);
        $previousIdentifier = new Identifier('previous');
        $previousVariable = new Variable($previousIdentifier);
        $typeInspectorIdentifier = new Identifier('typeInspector');
        $typeInspectorVariable = new Variable($typeInspectorIdentifier);
        $thisVariable = new Variable(new Identifier('this'));
        $thisParameterNameMember = new Member(
            $thisVariable,
            new Constant($parameterNameIdentifier)
        );
        $thisIndexMember = new Member(
            $thisVariable,
            new Constant($indexIdentifier)
        );
        $thisValueMember = new Member(
            $thisVariable,
            new Constant($valueIdentifier)
        );
        $thisExpectedTypeMember = new Member(
            $thisVariable,
            new Constant($expectedTypeIdentifier)
        );
        $thisTypeInspectorMember = new Member(
            $thisVariable,
            new Constant($typeInspectorIdentifier)
        );
        $thisUnexpectedTypeMember = new Member(
            $thisVariable,
            new Constant(new Identifier('unexpectedType'))
        );
        $typeInspectorClassName = QualifiedIdentifier::fromString(
            $configuration
                ->validatorNamespace()
                ->joinAtoms('TypeInspector')
                ->string()
        );

        $method = new ConcreteMethod(
            new Identifier('__construct'),
            AccessModifier::PUBLIC_()
        );
        $method->addParameter(new Parameter($parameterNameIdentifier));
        $method->addParameter(new Parameter($indexIdentifier));
        $method->addParameter(new Parameter($valueIdentifier));
        $method->addParameter(new Parameter($expectedTypeIdentifier));
        $previousParameter = new Parameter(
            $previousIdentifier,
            new ObjectTypeHint(QualifiedIdentifier::fromString('\Exception'))
        );
        $previousParameter->setDefaultValue(new Literal(null));
        $method->addParameter($previousParameter);
        $typeInspectorParameter = new Parameter(
            $typeInspectorIdentifier,
            new ObjectTypeHint($typeInspectorClassName)
        );
        $typeInspectorParameter->setDefaultValue(new Literal(null));
        $method->addParameter($typeInspectorParameter);

        $nullTypeInspectorIf = new IfStatement(new StrictEquals(
            new Literal(null),
            $typeInspectorVariable
        ));
        $nullTypeInspectorIf->trueBranch()->add(new ExpressionStatement(
            new Assign(
                $typeInspectorVariable,
                new NewOperator(new Call($typeInspectorClassName))
            )
        ));
        $method->statementBlock()->add($nullTypeInspectorIf);

        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisParameterNameMember,
            $parameterNameVariable
        )));
        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisIndexMember,
            $indexVariable
        )));
        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisValueMember,
            $valueVariable
        )));
        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisExpectedTypeMember,
            $expectedTypeVariable
        )));
        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisTypeInspectorMember,
            $typeInspectorVariable
        )));

        $typeInspectorTypeCall = new Call(new Member(
            $typeInspectorVariable,
            new Constant(new Identifier('type'))
        ));
        $typeInspectorTypeCall->add($thisValueMember);
        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisUnexpectedTypeMember,
            $typeInspectorTypeCall
        )));

        $sprintfCall = new Call(QualifiedIdentifier::fromString('\sprintf'));
        $sprintfCall->add(new Literal(
            "Unexpected argument of type '%s' for parameter '%s' at index %d. Expected '%s'."
        ));
        $sprintfCall->add($thisUnexpectedTypeMember);
        $sprintfCall->add($parameterNameVariable);
        $sprintfCall->add($indexVariable);
        $sprintfCall->add($expectedTypeVariable);
        $parentConstructCall = new Call(new StaticMember(
            new Constant(new Identifier('parent')),
            new Constant(new Identifier('__construct'))
        ));
        $parentConstructCall->add($sprintfCall);
        $parentConstructCall->add(new Variable($previousIdentifier));
        $method->statementBlock()->add(new ExpressionStatement(
            $parentConstructCall
        ));

        return $method;
    }
protected function generateConstructor(RuntimeConfiguration $configuration)
    {
        $this->typeCheck->generateConstructor(func_get_args());

        $parameterNameIdentifier = new Identifier('parameterName');
        $parameterNameVariable = new Variable($parameterNameIdentifier);
        $indexIdentifier = new Identifier('index');
        $indexVariable = new Variable($indexIdentifier);
        $valueIdentifier = new Identifier('value');
        $valueVariable = new Variable($valueIdentifier);
        $expectedTypeIdentifier = new Identifier('expectedType');
        $expectedTypeVariable = new Variable($expectedTypeIdentifier);
        $previousIdentifier = new Identifier('previous');
        $previousVariable = new Variable($previousIdentifier);
        $typeInspectorIdentifier = new Identifier('typeInspector');
        $typeInspectorVariable = new Variable($typeInspectorIdentifier);
        $thisVariable = new Variable(new Identifier('this'));
        $thisParameterNameMember = new Member(
            $thisVariable,
            new Constant($parameterNameIdentifier)
        );
        $thisIndexMember = new Member(
            $thisVariable,
            new Constant($indexIdentifier)
        );
        $thisValueMember = new Member(
            $thisVariable,
            new Constant($valueIdentifier)
        );
        $thisExpectedTypeMember = new Member(
            $thisVariable,
            new Constant($expectedTypeIdentifier)
        );
        $thisTypeInspectorMember = new Member(
            $thisVariable,
            new Constant($typeInspectorIdentifier)
        );
        $thisUnexpectedTypeMember = new Member(
            $thisVariable,
            new Constant(new Identifier('unexpectedType'))
        );
        $typeInspectorClassName = QualifiedIdentifier::fromString(
            $configuration
                ->validatorNamespace()
                ->joinAtoms('TypeInspector')
                ->string()
        );

        $method = new ConcreteMethod(
            new Identifier('__construct'),
            AccessModifier::PUBLIC_()
        );
        $method->addParameter(new Parameter($parameterNameIdentifier));
        $method->addParameter(new Parameter($indexIdentifier));
        $method->addParameter(new Parameter($valueIdentifier));
        $method->addParameter(new Parameter($expectedTypeIdentifier));
        $previousParameter = new Parameter(
            $previousIdentifier,
            new ObjectTypeHint(QualifiedIdentifier::fromString('\Exception'))
        );
        $previousParameter->setDefaultValue(new Literal(null));
        $method->addParameter($previousParameter);
        $typeInspectorParameter = new Parameter(
            $typeInspectorIdentifier,
            new ObjectTypeHint($typeInspectorClassName)
        );
        $typeInspectorParameter->setDefaultValue(new Literal(null));
        $method->addParameter($typeInspectorParameter);

        $nullTypeInspectorIf = new IfStatement(new StrictEquals(
            new Literal(null),
            $typeInspectorVariable
        ));
        $nullTypeInspectorIf->trueBranch()->add(new ExpressionStatement(
            new Assign(
                $typeInspectorVariable,
                new NewOperator(new Call($typeInspectorClassName))
            )
        ));
        $method->statementBlock()->add($nullTypeInspectorIf);

        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisParameterNameMember,
            $parameterNameVariable
        )));
        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisIndexMember,
            $indexVariable
        )));
        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisValueMember,
            $valueVariable
        )));
        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisExpectedTypeMember,
            $expectedTypeVariable
        )));
        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisTypeInspectorMember,
            $typeInspectorVariable
        )));

        $typeInspectorTypeCall = new Call(new Member(
            $typeInspectorVariable,
            new Constant(new Identifier('type'))
        ));
        $typeInspectorTypeCall->add($thisValueMember);
        $method->statementBlock()->add(new ExpressionStatement(new Assign(
            $thisUnexpectedTypeMember,
            $typeInspectorTypeCall
        )));

        $sprintfCall = new Call(QualifiedIdentifier::fromString('\sprintf'));
        $sprintfCall->add(new Literal(
            "Unexpected argument of type '%s' for parameter '%s' at index %d. Expected '%s'."
        ));
        $sprintfCall->add($thisUnexpectedTypeMember);
        $sprintfCall->add($parameterNameVariable);
        $sprintfCall->add($indexVariable);
        $sprintfCall->add($expectedTypeVariable);
        $parentConstructCall = new Call(new StaticMember(
            new Constant(new Identifier('parent')),
            new Constant(new Identifier('__construct'))
        ));
        $parentConstructCall->add($sprintfCall);
        $parentConstructCall->add(new Variable($previousIdentifier));
        $method->statementBlock()->add(new ExpressionStatement(
            $parentConstructCall
        ));

        return $method;
    }
@param RuntimeConfiguration $configuration

@return ConcreteMethod