Skip to content

Commit

Permalink
Error locations (#11)
Browse files Browse the repository at this point in the history
  • Loading branch information
MidnightDesign authored Jan 8, 2024
1 parent 1c5108b commit 9964bb6
Show file tree
Hide file tree
Showing 27 changed files with 796 additions and 146 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"phpunit/phpunit": "^10.2",
"psalm/plugin-phpunit": "^0.18.4",
"roave/backward-compatibility-check": "^8.3",
"vimeo/psalm": "^5.10"
"vimeo/psalm": "^5.16"
},
"minimum-stability": "stable",
"autoload": {
Expand Down
6 changes: 6 additions & 0 deletions src/Call.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Eventjet\Ausdruck;

use Eventjet\Ausdruck\Parser\Span;

use function array_map;
use function array_unshift;
use function count;
Expand All @@ -18,6 +20,8 @@
*/
final class Call extends Expression
{
use LocationTrait;

/**
* @param Expression<mixed> $target
* @param list<Expression<mixed>> $arguments
Expand All @@ -28,7 +32,9 @@ public function __construct(
public readonly string $name,
public readonly Type $type,
public readonly array $arguments,
Span $location,
) {
$this->location = $location;
}

/**
Expand Down
7 changes: 7 additions & 0 deletions src/Eq.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Eventjet\Ausdruck;

use Eventjet\Ausdruck\Parser\Span;

use function sprintf;

/**
Expand Down Expand Up @@ -43,4 +45,9 @@ public function getType(): Type
{
return Type::bool();
}

public function location(): Span
{
return $this->left->location()->to($this->right->location());
}
}
36 changes: 28 additions & 8 deletions src/Expr.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Eventjet\Ausdruck;

use Eventjet\Ausdruck\Parser\Span;

use function is_string;

/**
Expand Down Expand Up @@ -34,20 +36,20 @@ public static function eq(Expression $left, Expression $right): Eq
* @param Type<T> | class-string<T> $type
* @return Get<T>
*/
public static function get(string $name, Type|string $type): Get
public static function get(string $name, Type|string $type, Span|null $location = null): Get
{
/** @phpstan-ignore-next-line False positive */
return new Get($name, is_string($type) ? Type::object($type) : $type);
return new Get($name, is_string($type) ? Type::object($type) : $type, $location ?? self::dummySpan());
}

/**
* @template T of string | int | float | bool | null | array<array-key, mixed>
* @param T $value
* @return Literal<T>
*/
public static function literal(mixed $value): Literal
public static function literal(mixed $value, Span|null $location = null): Literal
{
return new Literal($value);
return new Literal($value, $location ?? self::dummySpan());
}

/**
Expand All @@ -57,9 +59,9 @@ public static function literal(mixed $value): Literal
* @param Type<T> $type
* @return Call<T>
*/
public static function call(Expression $target, string $name, Type $type, array $arguments): Call
public static function call(Expression $target, string $name, Type $type, array $arguments, Span|null $location = null): Call
{
return new Call($target, $name, $type, $arguments);
return new Call($target, $name, $type, $arguments, $location ?? self::dummySpan());
}

/**
Expand All @@ -77,9 +79,11 @@ public static function or_(Expression $left, Expression $right): Or_
* @param list<string> $parameters
* @return Expression<callable(Scope): T>
*/
public static function lambda(Expression $body, array $parameters = []): Expression
public static function lambda(Expression $body, array $parameters = [], Span|null $location = null): Expression
{
return new Lambda($body, $parameters);
/** @infection-ignore-all We currently don't have a way to test this */
$location ??= self::dummySpan();
return new Lambda($body, $parameters, $location);
}

/**
Expand All @@ -103,4 +107,20 @@ public static function gt(Expression $left, Expression $right): Gt
{
return new Gt($left, $right);
}

/**
* @template T of int | float
* @param Expression<T> $expression
* @return Negative<T>
*/
public static function negative(Expression $expression, Span|null $location = null): Negative
{
return new Negative($expression, $location ?? self::dummySpan());
}

private static function dummySpan(): Span
{
/** @infection-ignore-all These dummy spans are just there to fill parameter lists */
return Span::char(1, 1);
}
}
7 changes: 5 additions & 2 deletions src/Expression.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Eventjet\Ausdruck;

use Eventjet\Ausdruck\Parser\Span;
use Stringable;

/**
Expand Down Expand Up @@ -60,9 +61,9 @@ public function or_(self $other): Or_
* @param Type<U> $type
* @return Call<U>
*/
public function call(string $name, Type $type, array $arguments): Call
public function call(string $name, Type $type, array $arguments, Span|null $location = null): Call
{
return Expr::call($this, $name, $type, $arguments);
return Expr::call($this, $name, $type, $arguments, $location);
}

/**
Expand All @@ -76,6 +77,8 @@ public function matchesType(Type $type): bool
return $this->getType()->equals($type);
}

abstract public function location(): Span;

/**
* @return T
* @throws EvaluationError
Expand Down
6 changes: 5 additions & 1 deletion src/Get.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Eventjet\Ausdruck;

use Eventjet\Ausdruck\Parser\Span;
use TypeError;

use function get_debug_type;
Expand All @@ -17,11 +18,14 @@
*/
final class Get extends Expression
{
use LocationTrait;

/**
* @param Type<T> $type
*/
public function __construct(public readonly string $name, private readonly Type $type)
public function __construct(public readonly string $name, private readonly Type $type, Span $location)
{
$this->location = $location;
}

public function __toString(): string
Expand Down
7 changes: 7 additions & 0 deletions src/Gt.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Eventjet\Ausdruck;

use Eventjet\Ausdruck\Parser\Span;

use function sprintf;

/**
Expand Down Expand Up @@ -44,4 +46,9 @@ public function getType(): Type
{
return Type::bool();
}

public function location(): Span
{
return $this->left->location()->to($this->right->location());
}
}
6 changes: 5 additions & 1 deletion src/Lambda.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Eventjet\Ausdruck;

use Eventjet\Ausdruck\Parser\Span;
use LogicException;

use function implode;
Expand All @@ -17,12 +18,15 @@
*/
final class Lambda extends Expression
{
use LocationTrait;

/**
* @param Expression<T> $body
* @param list<string> $parameters
*/
public function __construct(public readonly Expression $body, public readonly array $parameters = [])
public function __construct(public readonly Expression $body, public readonly array $parameters, Span $location)
{
$this->location = $location;
}

public function __toString(): string
Expand Down
7 changes: 6 additions & 1 deletion src/Literal.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Eventjet\Ausdruck;

use Eventjet\Ausdruck\Parser\Span;

use function array_is_list;
use function array_map;
use function implode;
Expand All @@ -22,11 +24,14 @@
*/
final class Literal extends Expression
{
use LocationTrait;

/**
* @param T $value
*/
public function __construct(private readonly mixed $value)
public function __construct(private readonly mixed $value, Span $location)
{
$this->location = $location;
}

/**
Expand Down
17 changes: 17 additions & 0 deletions src/LocationTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

declare(strict_types=1);

namespace Eventjet\Ausdruck;

use Eventjet\Ausdruck\Parser\Span;

trait LocationTrait
{
private readonly Span $location;

public function location(): Span
{
return $this->location;
}
}
51 changes: 51 additions & 0 deletions src/Negative.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace Eventjet\Ausdruck;

use Eventjet\Ausdruck\Parser\Span;

use function sprintf;

/**
* @template T of int | float
* @extends Expression<T>
*/
final class Negative extends Expression
{
use LocationTrait;

/**
* @param Expression<T> $expression
*/
public function __construct(public readonly Expression $expression, Span $location)
{
$this->location = $location;
}

public function __toString(): string
{
return sprintf('-%s', $this->expression);
}

/**
* @psalm-suppress InvalidReturnType False positive
*/
public function evaluate(Scope $scope): float|int
{
/** @psalm-suppress InvalidReturnStatement False positive */
return -$this->expression->evaluate($scope);
}

public function equals(Expression $other): bool
{
return $other instanceof self
&& $this->expression->equals($other->expression);
}

public function getType(): Type
{
return $this->expression->getType();
}
}
7 changes: 7 additions & 0 deletions src/Or_.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Eventjet\Ausdruck;

use Eventjet\Ausdruck\Parser\Span;

use function sprintf;

/**
Expand Down Expand Up @@ -43,4 +45,9 @@ public function getType(): Type
{
return Type::bool();
}

public function location(): Span
{
return $this->left->location()->to($this->right->location());
}
}
Loading

0 comments on commit 9964bb6

Please sign in to comment.