Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement operators as functions #21

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion src/Call.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,21 @@ public function __construct(
public readonly Type $type,
public readonly array $arguments,
Span $location,
public readonly CallType $callType = CallType::Method,
) {
$this->location = $location;
}

public static function infix(string $name, Expression $left, Expression $right, Type $type): self
{
return new self($left, $name, $type, [$right], $left->location()->to($right->location()), CallType::Infix);
}

public static function prefix(string $name, Expression $argument, Type $type, Span $location): self
{
return new self($argument, $name, $type, [], $location, CallType::Prefix);
}

/**
* @param list<Expression> $a
* @param list<Expression> $b
Expand All @@ -54,7 +65,11 @@ private static function compareArguments(array $a, array $b): bool

public function __toString(): string
{
return sprintf('%s.%s:%s(%s)', $this->target, $this->name, $this->type, implode(', ', $this->arguments));
return match ($this->callType) {
CallType::Infix => sprintf('%s %s %s', $this->target, $this->name, $this->arguments[0]),
CallType::Prefix => sprintf('%s%s', $this->name, $this->target),
CallType::Method => sprintf('%s.%s:%s(%s)', $this->target, $this->name, $this->type, implode(', ', $this->arguments)),
};
}

public function evaluate(Scope $scope): mixed
Expand Down
12 changes: 12 additions & 0 deletions src/CallType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Eventjet\Ausdruck;

enum CallType
{
case Method;
case Infix;
case Prefix;
}
47 changes: 0 additions & 47 deletions src/Eq.php
rieschl marked this conversation as resolved.
Show resolved Hide resolved

This file was deleted.

20 changes: 10 additions & 10 deletions src/Expr.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ private function __construct()
{
}

public static function eq(Expression $left, Expression $right): Eq
public static function eq(Expression $left, Expression $right): Expression
{
return new Eq($left, $right);
return Call::infix('===', $left, $right, Type::bool());
}

/**
Expand Down Expand Up @@ -60,9 +60,9 @@ public static function call(Expression $target, string $name, Type $type, array
return new Call($target, $name, $type, $arguments, $location ?? self::dummySpan());
}

public static function or_(Expression $left, Expression $right): Or_
public static function or_(Expression $left, Expression $right): Expression
{
return new Or_($left, $right);
return Call::infix('||', $left, $right, Type::bool());
}

public static function and_(Expression $left, Expression $right): And_
Expand All @@ -80,19 +80,19 @@ public static function lambda(Expression $body, array $parameters = [], Span|nul
return new Lambda($body, $parameters, $location);
}

public static function subtract(Expression $minuend, Expression $subtrahend): Subtract
public static function subtract(Expression $minuend, Expression $subtrahend): Expression
{
return new Subtract($minuend, $subtrahend);
return Call::infix('-', $minuend, $subtrahend, $minuend->getType());
}

public static function gt(Expression $left, Expression $right): Gt
public static function gt(Expression $left, Expression $right): Expression
{
return new Gt($left, $right);
return Call::infix('>', $left, $right, Type::bool());
}

public static function negative(Expression $expression, Span|null $location = null): Negative
public static function negative(Expression $expression, Span|null $location = null): Expression
{
return new Negative($expression, $location ?? self::dummySpan());
return Call::prefix('-', $expression, $expression->getType(), $location ?? self::dummySpan());
}

private static function dummySpan(): Span
Expand Down
8 changes: 4 additions & 4 deletions src/Expression.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,26 @@
*/
abstract class Expression implements Stringable
{
public function eq(self $other): Eq
public function eq(self $other): self
{
return Expr::eq($this, $other);
}

public function subtract(self $subtrahend): Subtract
public function subtract(self $subtrahend): self
{
/** @var self $self */
$self = $this;
return Expr::subtract($self, $subtrahend);
}

public function gt(self $right): Gt
public function gt(self $right): self
{
/** @var self $self */
$self = $this;
return Expr::gt($self, $right);
}

public function or_(self $other): Or_
public function or_(self $other): self
{
/** @var self $self */
$self = $this;
Expand Down
47 changes: 0 additions & 47 deletions src/Gt.php

This file was deleted.

46 changes: 0 additions & 46 deletions src/Negative.php

This file was deleted.

56 changes: 0 additions & 56 deletions src/Or_.php

This file was deleted.

31 changes: 31 additions & 0 deletions src/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ final class Scope
public function __construct(private readonly array $vars = [], array $funcs = [], private readonly Scope|null $parent = null)
{
$predefinedFuncs = $this->parent === null ? [
'||' => self::or(...),
'===' => self::eq(...),
'-' => self::subtract(...),
'>' => self::gt(...),
'contains' => self::contains(...),
'count' => self::count(...),
'filter' => self::filter(...),
Expand Down Expand Up @@ -215,6 +219,33 @@ private static function identity(mixed $value): mixed
return $value;
}

private static function or(bool $left, bool $right): bool
{
return $left || $right;
}

private static function eq(mixed $left, mixed $right): bool
{
return $left === $right;
}

/**
* @return ($minuend is float ? float : ($subtrahend is float ? float : int))
*/
private static function subtract(int|float $minuend, int|float|null $subtrahend = null): int|float
{
if ($subtrahend === null) {
return -$minuend;
}
/** @psalm-suppress InvalidOperand */
return $minuend - $subtrahend;
}

private static function gt(int|float $left, int|float $right): bool
{
return $left > $right;
}

/**
* @internal
*/
Expand Down
Loading
Loading