Created
September 23, 2018 19:46
-
-
Save pwm/18d68d44ee82f91735999933f659926f to your computer and use it in GitHub Desktop.
Simple evaluator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
interface Expr { | |
public function e(Evaluator $eval); | |
public function unbox(); | |
} | |
abstract class LRExpr implements Expr { | |
private $l; | |
private $r; | |
public function __construct(Expr $l, Expr $r) { $this->l = $l; $this->r = $r; } | |
public function l(): Expr { return $this->l; } | |
public function r(): Expr { return $this->r; } | |
public function unbox(): Expr { return $this; } | |
} | |
class I implements Expr { | |
private $i; | |
public function __construct(int $i) { $this->i = $i; } | |
public function e(Evaluator $eval): I { return $eval->eI($this); } | |
public function unbox(): int { return $this->i; } | |
} | |
class B implements Expr { | |
private $b; | |
public function __construct(bool $b) { $this->b = $b; } | |
public function e(Evaluator $eval): B { return $eval->eB($this); } | |
public function unbox(): bool { return $this->b; } | |
} | |
class Add extends LRExpr { | |
public function e(Evaluator $eval): I { return $eval->eAdd($this); } | |
} | |
class Mul extends LRExpr { | |
public function e(Evaluator $eval): I { return $eval->eMul($this); } | |
} | |
class Eq extends LRExpr { | |
public function e(Evaluator $eval): B { return $eval->eEq($this); } | |
} | |
class Evaluator { | |
public function e(Expr $expr): Expr { return $expr->e($this); } | |
public function eI(I $i): I { return $i; } | |
public function eB(B $b): B { return $b; } | |
public function eAdd(Add $a): I { return new I($this->e($a->l())->unbox() + $this->e($a->r())->unbox()); } | |
public function eMul(Mul $m): I { return new I($this->e($m->l())->unbox() * $this->e($m->r())->unbox()); } | |
public function eEq(Eq $expr): B { return new B($this->e($expr->l())->unbox() === $this->e($expr->r())->unbox()); } | |
} | |
$isTrue = (new Evaluator)->e( | |
new Eq( | |
new Add(new I(4), new I(5)), | |
new Mul(new Add(new I(1), new I(2)), new I(3)) | |
) | |
); | |
\assert($isTrue->unbox() === true); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment