mirror of
https://github.com/peklaiho/madlisp.git
synced 2024-11-22 21:35:03 +00:00
eval according to example
This commit is contained in:
parent
80faff86f5
commit
773f195f37
@ -16,64 +16,43 @@ class Evaller
|
|||||||
return $results;
|
return $results;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function doEval($expr, Env $env)
|
public function evalAst($ast, Env $env)
|
||||||
{
|
{
|
||||||
if ($expr instanceof MList && $expr->count() > 0) {
|
if ($ast instanceof Symbol) {
|
||||||
$first = $expr->get(0);
|
// Lookup symbol from env
|
||||||
|
return $env->get($ast->getName());
|
||||||
if ($first instanceof Symbol) {
|
} elseif ($ast instanceof MList) {
|
||||||
// Special built-in features
|
// Eval contents and return new list
|
||||||
if ($first->getName() == 'env') {
|
$results = array_map(fn ($a) => $this->doEval($a, $env), $ast->getData());
|
||||||
return $env;
|
return new MList($results);
|
||||||
} 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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the expression unchanged
|
return $ast;
|
||||||
return $expr;
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user