2020-05-28 10:10:00 +00:00
|
|
|
<?php
|
|
|
|
namespace MadLisp;
|
|
|
|
|
|
|
|
use Closure;
|
|
|
|
|
|
|
|
class Evaller
|
|
|
|
{
|
|
|
|
public function eval(array $expressions, Env $env): array
|
|
|
|
{
|
|
|
|
$results = [];
|
|
|
|
|
|
|
|
foreach ($expressions as $expr) {
|
|
|
|
$results[] = $this->doEval($expr, $env);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
2020-05-28 12:41:41 +00:00
|
|
|
public function evalAst($ast, Env $env)
|
2020-05-28 10:10:00 +00:00
|
|
|
{
|
2020-05-28 12:41:41 +00:00
|
|
|
if ($ast instanceof Symbol) {
|
|
|
|
// Lookup symbol from env
|
|
|
|
return $env->get($ast->getName());
|
|
|
|
} elseif ($ast instanceof MList) {
|
|
|
|
// Eval contents and return new list
|
|
|
|
$results = array_map(fn ($a) => $this->doEval($a, $env), $ast->getData());
|
|
|
|
return new MList($results);
|
|
|
|
}
|
2020-05-28 10:10:00 +00:00
|
|
|
|
2020-05-28 12:41:41 +00:00
|
|
|
return $ast;
|
|
|
|
}
|
2020-05-28 10:10:00 +00:00
|
|
|
|
2020-05-28 12:41:41 +00:00
|
|
|
public function doEval($ast, Env $env)
|
|
|
|
{
|
|
|
|
// Not list
|
|
|
|
if (!($ast instanceof MList)) {
|
|
|
|
return $this->evalAst($ast, $env);
|
|
|
|
}
|
2020-05-28 10:10:00 +00:00
|
|
|
|
2020-05-28 12:41:41 +00:00
|
|
|
// Empty list
|
|
|
|
if ($ast->count() == 0) {
|
|
|
|
return $ast;
|
|
|
|
}
|
2020-05-28 10:10:00 +00:00
|
|
|
|
2020-05-28 12:41:41 +00:00
|
|
|
// Get new evaluated list
|
|
|
|
$ast = $this->evalAst($ast, $env);
|
2020-05-28 10:10:00 +00:00
|
|
|
|
2020-05-28 12:41:41 +00:00
|
|
|
$first = $ast->get(0);
|
2020-05-28 10:10:00 +00:00
|
|
|
|
2020-05-28 12:41:41 +00:00
|
|
|
if (!($first instanceof Closure)) {
|
|
|
|
throw new MadLispException("first item of list is not function");
|
2020-05-28 10:10:00 +00:00
|
|
|
}
|
|
|
|
|
2020-05-28 12:41:41 +00:00
|
|
|
$args = array_slice($ast->getData(), 1);
|
|
|
|
|
|
|
|
return $first(...$args);
|
2020-05-28 10:10:00 +00:00
|
|
|
}
|
|
|
|
}
|