Permalink
Browse files

Implemented extensions system.

New types:
 * ExtensionLoaderInterface
 * ExtensionLoader
 * ExtensionInterface

`TyphaxASTGenerator` is now constructed with a second parameter, a `ExtensionLoaderInterface`. This parameter is defaulted to a new instance of `ExtensionLoader`.

When an `ExtensionType` is encountered the AST generator queries the extension loader for the appropriate extension, then calls `$extension->generateTypeCheck($this, $type)`, where `$this` is the current `TyphaxASTGenerator` instance, and `$type` is the Typhax `ExtensionType` instance.

The extension is required to produce a Pasta `Closure`, which is injected into the generated code like any other closure-based type check.
  • Loading branch information...
1 parent ac9488b commit 0099ed6136d839d14db73e68909f0ec14dfdd91b @jmalloc jmalloc committed Jan 23, 2013
View
@@ -17,7 +17,7 @@
"eloquent/blox": "~1",
"eloquent/cosmos": "~2",
"eloquent/enumeration": "~3",
- "eloquent/typhax": "~0.8",
+ "eloquent/typhax": "dev-master",
"icecave/isolator": "~2",
"icecave/pasta-ast": "~0.1",
"icecave/rasta": "~0.1",
View

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
@@ -0,0 +1,32 @@
+<?php
+namespace Eloquent\Typhoon\TypeCheck\Validator\Eloquent\Typhoon\Extension\Exception;
+
+class InvalidExtensionExceptionTypeCheck extends \Eloquent\Typhoon\TypeCheck\AbstractValidator
+{
+ public function validateConstruct(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount < 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\MissingArgumentException('className', 0, 'string');
+ } elseif ($argumentCount > 2) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(2, $arguments[2]);
+ }
+ $value = $arguments[0];
+ if (!\is_string($value)) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentValueException(
+ 'className',
+ 0,
+ $arguments[0],
+ 'string'
+ );
+ }
+ }
+
+ public function className(array $arguments)
+ {
+ if (\count($arguments) > 0) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(0, $arguments[0]);
+ }
+ }
+
+}
@@ -0,0 +1,82 @@
+<?php
+namespace Eloquent\Typhoon\TypeCheck\Validator\Eloquent\Typhoon\Extension;
+
+class ExtensionLoaderTypeCheck extends \Eloquent\Typhoon\TypeCheck\AbstractValidator
+{
+ public function validateConstruct(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount > 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
+ }
+ }
+
+ public function load(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount < 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\MissingArgumentException('className', 0, 'string');
+ } elseif ($argumentCount > 2) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(2, $arguments[2]);
+ }
+ $value = $arguments[0];
+ if (!\is_string($value)) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentValueException(
+ 'className',
+ 0,
+ $arguments[0],
+ 'string'
+ );
+ }
+ if ($argumentCount > 1) {
+ $value = $arguments[1];
+ if (!\is_bool($value)) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentValueException(
+ 'forceReload',
+ 1,
+ $arguments[1],
+ 'boolean'
+ );
+ }
+ }
+ }
+
+ public function unload(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount < 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\MissingArgumentException('className', 0, 'string');
+ } elseif ($argumentCount > 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
+ }
+ $value = $arguments[0];
+ if (!\is_string($value)) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentValueException(
+ 'className',
+ 0,
+ $arguments[0],
+ 'string'
+ );
+ }
+ }
+
+ public function isLoaded(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount < 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\MissingArgumentException('className', 0, 'string');
+ } elseif ($argumentCount > 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
+ }
+ $value = $arguments[0];
+ if (!\is_string($value)) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentValueException(
+ 'className',
+ 0,
+ $arguments[0],
+ 'string'
+ );
+ }
+ }
+
+}
@@ -6,8 +6,8 @@ class TyphaxASTGeneratorTypeCheck extends \Eloquent\Typhoon\TypeCheck\AbstractVa
public function validateConstruct(array $arguments)
{
$argumentCount = \count($arguments);
- if ($argumentCount > 1) {
- throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
+ if ($argumentCount > 2) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(2, $arguments[2]);
}
}
@@ -51,6 +51,16 @@ public function visitCallableType(array $arguments)
}
}
+ public function visitExtensionType(array $arguments)
+ {
+ $argumentCount = \count($arguments);
+ if ($argumentCount < 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\MissingArgumentException('type', 0, 'Eloquent\\Typhax\\Type\\ExtensionType');
+ } elseif ($argumentCount > 1) {
+ throw new \Eloquent\Typhoon\TypeCheck\Exception\UnexpectedArgumentException(1, $arguments[1]);
+ }
+ }
+
public function visitFloatType(array $arguments)
{
$argumentCount = \count($arguments);
@@ -0,0 +1,53 @@
+<?php
+
+/*
+ * This file is part of the Typhoon package.
+ *
+ * Copyright © 2012 Erin Millard
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Eloquent\Typhoon\Extension\Exception;
+
+use Eloquent\Typhoon\TypeCheck\TypeCheck;
+use Exception;
+use LogicException;
+
+final class InvalidExtensionException extends LogicException
+{
+ /**
+ * @param string $className
+ * @param Exception|null $previous
+ */
+ public function __construct(
+ $className,
+ Exception $previous = null
+ ) {
+ $this->typeCheck = TypeCheck::get(__CLASS__, func_get_args());
+ $this->className = $className;
+
+ parent::__construct(
+ sprintf(
+ "The extension type '%s' does not exist, or does not implement ExtensionInterface.",
+ $this->className()
+ ),
+ 0,
+ $previous
+ );
+ }
+
+ /**
+ * @return string
+ */
+ public function className()
+ {
+ $this->typeCheck->className(func_get_args());
+
+ return $this->className;
+ }
+
+ private $className;
+ private $typeCheck;
+}
@@ -0,0 +1,27 @@
+<?php
+
+/*
+ * This file is part of the Typhoon package.
+ *
+ * Copyright © 2012 Erin Millard
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Eloquent\Typhoon\Extension;
+
+use Eloquent\Typhax\Type\ExtensionType;
+use Eloquent\Typhoon\Generator\TyphaxASTGenerator;
+use Icecave\Pasta\AST\Func\Closure;
+
+interface ExtensionInterface
+{
+ /**
+ * @param TyphaxASTGenerator $generator The AST generator that loaded this extension.
+ * @param ExtensionType $type Type extension type for which code should be generated.
+ *
+ * @return Closure A closure AST node that accepts a single value parameter.
+ */
+ public function generateTypeCheck(TyphaxASTGenerator $generator, ExtensionType $extensionType);
+}
Oops, something went wrong.

0 comments on commit 0099ed6

Please sign in to comment.