From 773f195f371d1c2eea3cb029fbbcca3f36d584b3 Mon Sep 17 00:00:00 2001 From: Pekka Laiho Date: Thu, 28 May 2020 19:41:41 +0700 Subject: [PATCH] eval according to example --- src/Evaller.php | 91 +++++++++++++++++++------------------------------ 1 file changed, 35 insertions(+), 56 deletions(-) diff --git a/src/Evaller.php b/src/Evaller.php index 8c51ea2..6851dbd 100644 --- a/src/Evaller.php +++ b/src/Evaller.php @@ -16,64 +16,43 @@ class Evaller return $results; } - public function doEval($expr, Env $env) + public function evalAst($ast, Env $env) { - if ($expr instanceof MList && $expr->count() > 0) { - $first = $expr->get(0); - - if ($first instanceof Symbol) { - // Special built-in features - if ($first->getName() == 'env') { - return $env; - } elseif ($first->getName() == 'quote') { - if ($expr->count() != 2) { - throw new MadLispException("quote requires exactly 1 argument"); - } - - return $expr->get(1); - } elseif ($first->getName() == 'if') { - if ($expr->count() != 4) { - throw new MadLispException("if requires exactly 3 arguments"); - } - - // Eval condition - $result = $this->doEval($expr->get(1), $env); - - // Eval true or false branch and return it - if ($result == true) { - return $this->doEval($expr->get(2), $env); - } else { - return $this->doEval($expr->get(3), $env); - } - } - - // Normal symbol, fetch from env - $first = $env->get($first->getName()); - } - - if (!($first instanceof Closure)) { - throw new MadLispException("first argument of list is not function"); - } - - $args = array_slice($expr->getData(), 1); - - // Evaluate args - $args = array_map(fn ($a) => $this->doEval($a, $env), $args); - - // Call func and return result - return $first(...$args); - } elseif ($expr instanceof Hash) { - // Hash: return new hash with all items evaluated - $items = []; - foreach ($expr->getData() as $key => $val) { - $items[$key] = $this->doEval($val, $env); - } - return new Hash($items); - } elseif ($expr instanceof Symbol) { - return $env->get($expr->getName()); + 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); } - // Return the expression unchanged - return $expr; + return $ast; + } + + public function doEval($ast, Env $env) + { + // Not list + if (!($ast instanceof MList)) { + return $this->evalAst($ast, $env); + } + + // Empty list + if ($ast->count() == 0) { + return $ast; + } + + // Get new evaluated list + $ast = $this->evalAst($ast, $env); + + $first = $ast->get(0); + + if (!($first instanceof Closure)) { + throw new MadLispException("first item of list is not function"); + } + + $args = array_slice($ast->getData(), 1); + + return $first(...$args); } }