mirror of
https://github.com/peklaiho/madlisp.git
synced 2024-10-18 13:02:04 +00:00
add Vector, other improvements
This commit is contained in:
parent
5869b2f483
commit
9e03179650
@ -22,11 +22,9 @@ class Evaller
|
|||||||
// Lookup symbol from env
|
// Lookup symbol from env
|
||||||
return $env->get($ast->getName());
|
return $env->get($ast->getName());
|
||||||
} elseif ($ast instanceof MList) {
|
} elseif ($ast instanceof MList) {
|
||||||
$results = [];
|
return new MList(array_map(fn ($a) => $this->doEval($a, $env), $ast->getData()));
|
||||||
foreach ($ast->getData() as $val) {
|
} elseif ($ast instanceof Vector) {
|
||||||
$results[] = $this->doEval($val, $env);
|
return new Vector(array_map(fn ($a) => $this->doEval($a, $env), $ast->getData()));
|
||||||
}
|
|
||||||
return new MList($results);
|
|
||||||
} elseif ($ast instanceof Hash) {
|
} elseif ($ast instanceof Hash) {
|
||||||
$results = [];
|
$results = [];
|
||||||
foreach ($ast->getData() as $key => $val) {
|
foreach ($ast->getData() as $key => $val) {
|
||||||
|
@ -4,9 +4,10 @@ namespace MadLisp\Lib;
|
|||||||
use Closure;
|
use Closure;
|
||||||
use MadLisp\Env;
|
use MadLisp\Env;
|
||||||
use MadLisp\Hash;
|
use MadLisp\Hash;
|
||||||
|
use MadLisp\MadLispException;
|
||||||
use MadLisp\MList;
|
use MadLisp\MList;
|
||||||
use MadLisp\Symbol;
|
use MadLisp\Symbol;
|
||||||
use MadLisp\MadLispException;
|
use MadLisp\Util;
|
||||||
|
|
||||||
class Core implements ILib
|
class Core implements ILib
|
||||||
{
|
{
|
||||||
@ -130,24 +131,7 @@ class Core implements ILib
|
|||||||
});
|
});
|
||||||
|
|
||||||
$env->set('hash', function (...$args) {
|
$env->set('hash', function (...$args) {
|
||||||
if (count($args) % 2 == 1) {
|
return Util::makeHash($args);
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MadLisp;
|
namespace MadLisp;
|
||||||
|
|
||||||
class MList extends Collection
|
class MList extends Seq
|
||||||
{
|
{
|
||||||
public function get(int $index)
|
public function get(int $index)
|
||||||
{
|
{
|
||||||
|
@ -7,51 +7,34 @@ class Printer
|
|||||||
{
|
{
|
||||||
public function print(array $items): void
|
public function print(array $items): void
|
||||||
{
|
{
|
||||||
for ($i = 0; $i < count($items); $i++) {
|
$strings = array_map(fn ($a) => $this->doPrint($a), $items);
|
||||||
if ($i > 0) {
|
|
||||||
print(' ');
|
print(implode(' ', $strings));
|
||||||
}
|
|
||||||
$this->doPrint($items[$i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function doPrint($a): void
|
private function doPrint($a): string
|
||||||
{
|
{
|
||||||
if ($a instanceof Closure) {
|
if ($a instanceof Closure) {
|
||||||
print('<function>');
|
return '<function>';
|
||||||
} elseif ($a instanceof MList) {
|
} elseif ($a instanceof MList) {
|
||||||
print('(');
|
return '(' . implode(' ', array_map(fn ($b) => $this->doPrint($b), $a->getData())) . ')';
|
||||||
for ($i = 0; $i < $a->count(); $i++) {
|
} elseif ($a instanceof Vector) {
|
||||||
if ($i > 0) {
|
return '[' . implode(' ', array_map(fn ($b) => $this->doPrint($b), $a->getData())) . ']';
|
||||||
print(' ');
|
|
||||||
}
|
|
||||||
$this->doPrint($a->get($i));
|
|
||||||
}
|
|
||||||
print(')');
|
|
||||||
} elseif ($a instanceof Hash) {
|
} elseif ($a instanceof Hash) {
|
||||||
print('{');
|
return '{' . implode(' ', array_map(fn ($key, $val) => $this->doPrint($key) . ':' . $this->doPrint($val),
|
||||||
$keys = array_keys($a->getData());
|
array_keys($a->getData()), array_values($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('}');
|
|
||||||
} elseif ($a instanceof Symbol) {
|
} elseif ($a instanceof Symbol) {
|
||||||
print($a->getName());
|
return $a->getName();
|
||||||
} elseif ($a === true) {
|
} elseif ($a === true) {
|
||||||
print('true');
|
return 'true';
|
||||||
} elseif ($a === false) {
|
} elseif ($a === false) {
|
||||||
print('false');
|
return 'false';
|
||||||
} elseif ($a === null) {
|
} elseif ($a === null) {
|
||||||
print('null');
|
return 'null';
|
||||||
} elseif (is_string($a)) {
|
} elseif (is_string($a)) {
|
||||||
print('"' . $a . '"');
|
return '"' . $a . '"';
|
||||||
} else {
|
} else {
|
||||||
print($a);
|
return $a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,26 +19,46 @@ class Reader
|
|||||||
{
|
{
|
||||||
if ($tokens[$index] == '(') {
|
if ($tokens[$index] == '(') {
|
||||||
return $this->readList($tokens, $index);
|
return $this->readList($tokens, $index);
|
||||||
|
} elseif ($tokens[$index] == '[') {
|
||||||
|
return $this->readVector($tokens, $index);
|
||||||
|
} elseif ($tokens[$index] == '{') {
|
||||||
|
return $this->readHash($tokens, $index);
|
||||||
} else {
|
} else {
|
||||||
return $this->readAtom($tokens, $index);
|
return $this->readAtom($tokens, $index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function readList(array $tokens, int &$index): MList
|
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 = [];
|
$result = [];
|
||||||
|
|
||||||
// start tag
|
// start tag
|
||||||
$index++;
|
$index++;
|
||||||
|
|
||||||
while ($tokens[$index] != ')') {
|
while ($tokens[$index] != $endTag) {
|
||||||
$result[] = $this->readForm($tokens, $index);
|
$result[] = $this->readForm($tokens, $index);
|
||||||
}
|
}
|
||||||
|
|
||||||
// end tag
|
// end tag
|
||||||
$index++;
|
$index++;
|
||||||
|
|
||||||
return new MList($result);
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function readAtom(array $tokens, int &$index)
|
private function readAtom(array $tokens, int &$index)
|
||||||
|
7
src/Seq.php
Normal file
7
src/Seq.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
namespace MadLisp;
|
||||||
|
|
||||||
|
abstract class Seq extends Collection
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@ -28,7 +28,7 @@ class Tokenizer
|
|||||||
// Inside string, add all characters
|
// Inside string, add all characters
|
||||||
$current .= $c;
|
$current .= $c;
|
||||||
|
|
||||||
// Stop at double quote
|
// Stop at first double quote
|
||||||
if ($c == '"') {
|
if ($c == '"') {
|
||||||
$addCurrent();
|
$addCurrent();
|
||||||
$isString = false;
|
$isString = false;
|
||||||
|
27
src/Util.php
Normal file
27
src/Util.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
namespace MadLisp;
|
||||||
|
|
||||||
|
class Util
|
||||||
|
{
|
||||||
|
public static function makeHash(array $args): Hash
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
14
src/Vector.php
Normal file
14
src/Vector.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
namespace MadLisp;
|
||||||
|
|
||||||
|
class Vector extends Seq
|
||||||
|
{
|
||||||
|
public function get(int $index)
|
||||||
|
{
|
||||||
|
if ($this->has($index)) {
|
||||||
|
return $this->data[$index];
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new MadLispException("vector does not contain index $index");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user