mirror of
https://github.com/peklaiho/madlisp.git
synced 2024-11-22 05:14:45 +00:00
add support for variable arguments using &
This commit is contained in:
parent
ed2738c91a
commit
16808c7ff9
@ -241,9 +241,7 @@ class Evaller
|
||||
$closure = function (...$args) use ($bindings, $env, $astData, $depth) {
|
||||
$newEnv = new Env('closure', $env);
|
||||
|
||||
for ($i = 0; $i < count($bindings); $i++) {
|
||||
$newEnv->set($bindings[$i]->getName(), $args[$i] ?? null);
|
||||
}
|
||||
Util::bindArguments($newEnv, $bindings, $args);
|
||||
|
||||
return $this->eval($astData[2], $newEnv, $depth + 1);
|
||||
};
|
||||
|
@ -38,10 +38,7 @@ class UserFunc extends Func
|
||||
{
|
||||
$newEnv = new Env('apply', $this->tempEnv);
|
||||
|
||||
$bindings = $this->bindings->getData();
|
||||
for ($i = 0; $i < count($bindings); $i++) {
|
||||
$newEnv->set($bindings[$i]->getName(), $args[$i] ?? null);
|
||||
}
|
||||
Util::bindArguments($newEnv, $this->bindings->getData(), $args);
|
||||
|
||||
return $newEnv;
|
||||
}
|
||||
|
16
src/Util.php
16
src/Util.php
@ -9,6 +9,22 @@ namespace MadLisp;
|
||||
|
||||
class Util
|
||||
{
|
||||
public static function bindArguments(Env $env, array $bindings, array $args): void
|
||||
{
|
||||
for ($i = 0; $i < count($bindings); $i++) {
|
||||
if ($bindings[$i]->getName() == '&') {
|
||||
if ($i < count($bindings) - 1) {
|
||||
$env->set($bindings[$i + 1]->getName(), new Vector(array_slice($args, $i)));
|
||||
return;
|
||||
} else {
|
||||
throw new MadLispException('no binding after &');
|
||||
}
|
||||
} else {
|
||||
$env->set($bindings[$i]->getName(), $args[$i] ?? null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function makeHash(array $args): Hash
|
||||
{
|
||||
if (count($args) % 2 == 1) {
|
||||
|
@ -7,12 +7,74 @@
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
use MadLisp\Env;
|
||||
use MadLisp\Hash;
|
||||
use MadLisp\MadLispException;
|
||||
use MadLisp\Symbol;
|
||||
use MadLisp\Util;
|
||||
use MadLisp\Vector;
|
||||
|
||||
class UtilTest extends TestCase
|
||||
{
|
||||
public function testBindArguments()
|
||||
{
|
||||
$env = new Env('env');
|
||||
|
||||
Util::bindArguments($env, [
|
||||
new Symbol('a'),
|
||||
new Symbol('b')
|
||||
], [
|
||||
1,
|
||||
2
|
||||
]);
|
||||
|
||||
$this->assertSame(['a' => 1, 'b' => 2], $env->getData());
|
||||
}
|
||||
|
||||
public function testBindArgumentsVariable()
|
||||
{
|
||||
$env = new Env('env');
|
||||
|
||||
Util::bindArguments($env, [
|
||||
new Symbol('a'),
|
||||
new Symbol('b'),
|
||||
new Symbol('&'),
|
||||
new Symbol('c')
|
||||
], [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
]);
|
||||
|
||||
$data = $env->getData();
|
||||
$this->assertCount(3, $data);
|
||||
$this->assertSame(1, $data['a']);
|
||||
$this->assertSame(2, $data['b']);
|
||||
$vec = $data['c'];
|
||||
$this->assertInstanceOf(Vector::class, $vec);
|
||||
$this->assertSame([3, 4], $vec->getData());
|
||||
}
|
||||
|
||||
public function testBindArgumentsVariableInvalid()
|
||||
{
|
||||
$this->expectException(MadLispException::class);
|
||||
$this->expectExceptionMessage('no binding after &');
|
||||
|
||||
$env = new Env('env');
|
||||
|
||||
Util::bindArguments($env, [
|
||||
new Symbol('a'),
|
||||
new Symbol('b'),
|
||||
new Symbol('&')
|
||||
], [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
]);
|
||||
}
|
||||
|
||||
public function testMakeHash()
|
||||
{
|
||||
$hash = Util::makeHash(['a', 1, 'b', 2]);
|
||||
|
Loading…
Reference in New Issue
Block a user