Skip to content

Instantly share code, notes, and snippets.

@pwm
Created September 23, 2018 19:46
Show Gist options
  • Save pwm/18d68d44ee82f91735999933f659926f to your computer and use it in GitHub Desktop.
Save pwm/18d68d44ee82f91735999933f659926f to your computer and use it in GitHub Desktop.
Simple evaluator
<?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