mirror of
https://github.com/peklaiho/madlisp.git
synced 2024-11-22 13:24:46 +00:00
simplify code
This commit is contained in:
parent
3463024a07
commit
437bf252c5
@ -3,38 +3,7 @@ namespace MadLisp;
|
||||
|
||||
class Evaller
|
||||
{
|
||||
public function eval(array $expressions, Env $env): array
|
||||
{
|
||||
$results = [];
|
||||
|
||||
foreach ($expressions as $expr) {
|
||||
$results[] = $this->doEval($expr, $env);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function evalAst($ast, Env $env)
|
||||
{
|
||||
if ($ast instanceof Symbol) {
|
||||
// Lookup symbol from env
|
||||
return $env->get($ast->getName());
|
||||
} elseif ($ast instanceof MList) {
|
||||
return new MList(array_map(fn ($a) => $this->doEval($a, $env), $ast->getData()));
|
||||
} elseif ($ast instanceof Vector) {
|
||||
return new Vector(array_map(fn ($a) => $this->doEval($a, $env), $ast->getData()));
|
||||
} elseif ($ast instanceof Hash) {
|
||||
$results = [];
|
||||
foreach ($ast->getData() as $key => $val) {
|
||||
$results[$key] = $this->doEval($val, $env);
|
||||
}
|
||||
return new Hash($results);
|
||||
}
|
||||
|
||||
return $ast;
|
||||
}
|
||||
|
||||
public function doEval($ast, Env $env)
|
||||
public function eval($ast, Env $env)
|
||||
{
|
||||
// Not list or empty list
|
||||
if (!($ast instanceof MList)) {
|
||||
@ -54,7 +23,7 @@ class Evaller
|
||||
throw new MadLispException("first argument to def is not symbol");
|
||||
}
|
||||
|
||||
$value = $this->doEval($ast->get(2), $env);
|
||||
$value = $this->eval($ast->get(2), $env);
|
||||
return $env->set($ast->get(1)->getName(), $value);
|
||||
} elseif ($ast->get(0)->getName() == 'do') {
|
||||
if ($ast->count() < 2) {
|
||||
@ -91,19 +60,19 @@ class Evaller
|
||||
$newEnv->set($bindings[$i]->getName(), $args[$i] ?? null);
|
||||
}
|
||||
|
||||
return $this->doEval($ast->get(2), $newEnv);
|
||||
return $this->eval($ast->get(2), $newEnv);
|
||||
});
|
||||
} elseif ($ast->get(0)->getName() == 'if') {
|
||||
if ($ast->count() < 3 || $ast->count() > 4) {
|
||||
throw new MadLispException("if requires 2 or 3 arguments");
|
||||
}
|
||||
|
||||
$result = $this->doEval($ast->get(1), $env);
|
||||
$result = $this->eval($ast->get(1), $env);
|
||||
|
||||
if ($result == true) {
|
||||
return $this->doEval($ast->get(2), $env);
|
||||
return $this->eval($ast->get(2), $env);
|
||||
} elseif ($ast->count() == 4) {
|
||||
return $this->doEval($ast->get(3), $env);
|
||||
return $this->eval($ast->get(3), $env);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -131,11 +100,11 @@ class Evaller
|
||||
throw new MadLispException("binding key for let is not symbol");
|
||||
}
|
||||
|
||||
$val = $this->doEval($bindings[$i + 1], $newEnv);
|
||||
$val = $this->eval($bindings[$i + 1], $newEnv);
|
||||
$newEnv->set($key->getName(), $val);
|
||||
}
|
||||
|
||||
return $this->doEval($ast->get(2), $newEnv);
|
||||
return $this->eval($ast->get(2), $newEnv);
|
||||
} elseif ($ast->get(0)->getName() == 'quote') {
|
||||
if ($ast->count() != 2) {
|
||||
throw new MadLispException("quote requires exactly 1 argument");
|
||||
@ -156,4 +125,24 @@ class Evaller
|
||||
$args = array_slice($ast->getData(), 1);
|
||||
return $func->call($args);
|
||||
}
|
||||
|
||||
private function evalAst($ast, Env $env)
|
||||
{
|
||||
if ($ast instanceof Symbol) {
|
||||
// Lookup symbol from env
|
||||
return $env->get($ast->getName());
|
||||
} elseif ($ast instanceof MList) {
|
||||
return new MList(array_map(fn ($a) => $this->eval($a, $env), $ast->getData()));
|
||||
} elseif ($ast instanceof Vector) {
|
||||
return new Vector(array_map(fn ($a) => $this->eval($a, $env), $ast->getData()));
|
||||
} elseif ($ast instanceof Hash) {
|
||||
$results = [];
|
||||
foreach ($ast->getData() as $key => $val) {
|
||||
$results[$key] = $this->eval($val, $env);
|
||||
}
|
||||
return new Hash($results);
|
||||
}
|
||||
|
||||
return $ast;
|
||||
}
|
||||
}
|
||||
|
24
src/Lisp.php
24
src/Lisp.php
@ -20,11 +20,11 @@ class Lisp
|
||||
{
|
||||
$tokens = $this->tokenizer->tokenize($input);
|
||||
|
||||
$expressions = $this->reader->read($tokens);
|
||||
$expr = $this->reader->read($tokens);
|
||||
|
||||
$results = $this->eval->eval($expressions, $env);
|
||||
$result = $this->eval->eval($expr, $env);
|
||||
|
||||
$this->printer->print($results);
|
||||
$this->printer->print($result);
|
||||
}
|
||||
|
||||
public function register(Env $env): void
|
||||
@ -39,19 +39,17 @@ class Lisp
|
||||
}
|
||||
));
|
||||
|
||||
$env->set('eval', new CoreFunc('eval', 'Evaluate arguments.', 1, -1,
|
||||
function (...$args) use ($env) {
|
||||
$results = $this->eval->eval($args, $env);
|
||||
|
||||
// Return last evaluated value
|
||||
return $results[count($results) - 1];
|
||||
}
|
||||
$env->set('read', new CoreFunc('read', 'Read string as code.', 1, 1,
|
||||
fn (string $a) => $this->reader->read($this->tokenizer->tokenize($a))
|
||||
));
|
||||
|
||||
$env->set('print', new CoreFunc('print', 'Print arguments.', 1, -1,
|
||||
function (...$args) {
|
||||
$this->printer->print($args);
|
||||
$env->set('eval', new CoreFunc('eval', 'Evaluate argument.', 1, 1,
|
||||
fn ($a) => $this->eval->eval($a, $env)
|
||||
));
|
||||
|
||||
$env->set('print', new CoreFunc('print', 'Print argument.', 1, 1,
|
||||
function ($a) {
|
||||
$this->printer->print($a);
|
||||
return null;
|
||||
}
|
||||
));
|
||||
|
@ -3,11 +3,9 @@ namespace MadLisp;
|
||||
|
||||
class Printer
|
||||
{
|
||||
public function print(array $items): void
|
||||
public function print($ast): void
|
||||
{
|
||||
$strings = array_map(fn ($a) => $this->doPrint($a), $items);
|
||||
|
||||
print(implode(' ', $strings));
|
||||
print($this->doPrint($ast));
|
||||
}
|
||||
|
||||
private function doPrint($a): string
|
||||
|
@ -3,16 +3,10 @@ namespace MadLisp;
|
||||
|
||||
class Reader
|
||||
{
|
||||
public function read(array $tokens): array
|
||||
public function read(array $tokens)
|
||||
{
|
||||
$result = [];
|
||||
$index = 0;
|
||||
|
||||
while ($index < count($tokens)) {
|
||||
$result[] = $this->readForm($tokens, $index);
|
||||
}
|
||||
|
||||
return $result;
|
||||
return $this->readForm($tokens, $index);
|
||||
}
|
||||
|
||||
private function readForm(array $tokens, int &$index)
|
||||
|
Loading…
Reference in New Issue
Block a user