From 1ece3649bc98d70f483d96d864c3759811a3aa62 Mon Sep 17 00:00:00 2001 From: Pekka Laiho Date: Sat, 5 Dec 2020 08:13:17 +0700 Subject: [PATCH] add support for userfuncs to meta --- src/Evaller.php | 2 +- src/LispFactory.php | 12 +++++++++++- src/UserFunc.php | 14 ++++++++++---- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/Evaller.php b/src/Evaller.php index 556f3d0..e6bddb4 100644 --- a/src/Evaller.php +++ b/src/Evaller.php @@ -159,7 +159,7 @@ class Evaller return $this->eval($astData[2], $newEnv); }; - return new UserFunc($closure, $astData[2], $env, $bindings); + return new UserFunc($closure, $astData[2], $env, $astData[1]); } elseif ($symbolName == 'if') { if ($astLength < 3 || $astLength > 4) { throw new MadLispException("if requires 2 or 3 arguments"); diff --git a/src/LispFactory.php b/src/LispFactory.php index fc71aeb..f77a73a 100644 --- a/src/LispFactory.php +++ b/src/LispFactory.php @@ -47,6 +47,16 @@ class LispFactory } else { throw new MadLispException('unknown attribute for meta'); } + } elseif ($obj instanceof UserFunc) { + if ($attribute == 'args') { + return $obj->getBindings(); + } elseif ($attribute == 'body') { + return $obj->getAst(); + } elseif ($attribute == 'code') { + return new MList([new Symbol('fn'), $obj->getBindings(), $obj->getAst()]); + } else { + throw new MadLispException('unknown attribute for meta'); + } } else { throw new MadLispException('unknown entity for meta'); } @@ -71,7 +81,7 @@ class LispFactory )); $env->set('exit', new CoreFunc('exit', 'Terminate the script with given exit code.', 0, 1, - function ($status = 0) { + function (int $status = 0) { exit($status); } )); diff --git a/src/UserFunc.php b/src/UserFunc.php index 59e57c4..fe89727 100644 --- a/src/UserFunc.php +++ b/src/UserFunc.php @@ -7,9 +7,9 @@ class UserFunc extends Func { protected $ast; protected Env $tempEnv; - protected array $bindings; + protected Seq $bindings; - public function __construct(Closure $closure, $ast, Env $tempEnv, array $bindings) + public function __construct(Closure $closure, $ast, Env $tempEnv, Seq $bindings) { parent::__construct($closure, null); @@ -23,12 +23,18 @@ class UserFunc extends Func return $this->ast; } + public function getBindings(): Seq + { + return $this->bindings; + } + public function getEnv(array $args) { $newEnv = new Env('apply', $this->tempEnv); - for ($i = 0; $i < count($this->bindings); $i++) { - $newEnv->set($this->bindings[$i]->getName(), $args[$i] ?? null); + $bindings = $this->bindings->getData(); + for ($i = 0; $i < count($bindings); $i++) { + $newEnv->set($bindings[$i]->getName(), $args[$i] ?? null); } return $newEnv;