diff --git a/src/Evaller.php b/src/Evaller.php index aad14b9..f9ab0c4 100644 --- a/src/Evaller.php +++ b/src/Evaller.php @@ -22,11 +22,9 @@ class Evaller // Lookup symbol from env return $env->get($ast->getName()); } elseif ($ast instanceof MList) { - $results = []; - foreach ($ast->getData() as $val) { - $results[] = $this->doEval($val, $env); - } - return new MList($results); + 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) { diff --git a/src/Lib/Core.php b/src/Lib/Core.php index 95d6b91..0ce5e81 100644 --- a/src/Lib/Core.php +++ b/src/Lib/Core.php @@ -4,9 +4,10 @@ namespace MadLisp\Lib; use Closure; use MadLisp\Env; use MadLisp\Hash; +use MadLisp\MadLispException; use MadLisp\MList; use MadLisp\Symbol; -use MadLisp\MadLispException; +use MadLisp\Util; class Core implements ILib { @@ -130,24 +131,7 @@ class Core implements ILib }); $env->set('hash', function (...$args) { - if (count($args) % 2 == 1) { - throw new MadLispException('uneven number of arguments for hash'); - } - - $data = []; - - for ($i = 0; $i < count($args) - 1; $i += 2) { - $key = $args[$i]; - $val = $args[$i + 1]; - - if (!is_string($key)) { - throw new MadLispException('invalid key for hash (not string)'); - } - - $data[$key] = $val; - } - - return new Hash($data); + return Util::makeHash($args); }); } } diff --git a/src/MList.php b/src/MList.php index 74e296b..fa6d5a1 100644 --- a/src/MList.php +++ b/src/MList.php @@ -1,7 +1,7 @@ 0) { - print(' '); - } - $this->doPrint($items[$i]); - } + $strings = array_map(fn ($a) => $this->doPrint($a), $items); + + print(implode(' ', $strings)); } - private function doPrint($a): void + private function doPrint($a): string { if ($a instanceof Closure) { - print(''); + return ''; } elseif ($a instanceof MList) { - print('('); - for ($i = 0; $i < $a->count(); $i++) { - if ($i > 0) { - print(' '); - } - $this->doPrint($a->get($i)); - } - print(')'); + return '(' . implode(' ', array_map(fn ($b) => $this->doPrint($b), $a->getData())) . ')'; + } elseif ($a instanceof Vector) { + return '[' . implode(' ', array_map(fn ($b) => $this->doPrint($b), $a->getData())) . ']'; } elseif ($a instanceof Hash) { - print('{'); - $keys = array_keys($a->getData()); - for ($i = 0; $i < count($keys); $i++) { - if ($i > 0) { - print(' '); - } - $this->doPrint($keys[$i]); - print(':'); - $this->doPrint($a->get($keys[$i])); - } - print('}'); + return '{' . implode(' ', array_map(fn ($key, $val) => $this->doPrint($key) . ':' . $this->doPrint($val), + array_keys($a->getData()), array_values($a->getData()))) . '}'; } elseif ($a instanceof Symbol) { - print($a->getName()); + return $a->getName(); } elseif ($a === true) { - print('true'); + return 'true'; } elseif ($a === false) { - print('false'); + return 'false'; } elseif ($a === null) { - print('null'); + return 'null'; } elseif (is_string($a)) { - print('"' . $a . '"'); + return '"' . $a . '"'; } else { - print($a); + return $a; } } } diff --git a/src/Reader.php b/src/Reader.php index 98ea869..5882b9e 100644 --- a/src/Reader.php +++ b/src/Reader.php @@ -19,26 +19,46 @@ class Reader { if ($tokens[$index] == '(') { return $this->readList($tokens, $index); + } elseif ($tokens[$index] == '[') { + return $this->readVector($tokens, $index); + } elseif ($tokens[$index] == '{') { + return $this->readHash($tokens, $index); } else { return $this->readAtom($tokens, $index); } } private function readList(array $tokens, int &$index): MList + { + return new MList($this->readCollection($tokens, $index, ')')); + } + + private function readVector(array $tokens, int &$index): Vector + { + return new Vector($this->readCollection($tokens, $index, ']')); + } + + private function readHash(array $tokens, int &$index): Hash + { + $contents = $this->readCollection($tokens, $index, '}'); + return Util::makeHash($contents); + } + + private function readCollection(array $tokens, int &$index, string $endTag): array { $result = []; // start tag $index++; - while ($tokens[$index] != ')') { + while ($tokens[$index] != $endTag) { $result[] = $this->readForm($tokens, $index); } // end tag $index++; - return new MList($result); + return $result; } private function readAtom(array $tokens, int &$index) diff --git a/src/Seq.php b/src/Seq.php new file mode 100644 index 0000000..d79d9ed --- /dev/null +++ b/src/Seq.php @@ -0,0 +1,7 @@ +has($index)) { + return $this->data[$index]; + } + + throw new MadLispException("vector does not contain index $index"); + } +} \ No newline at end of file