mirror of
https://github.com/peklaiho/madlisp.git
synced 2024-11-22 13:24:46 +00:00
new classes for functions, not finished
This commit is contained in:
parent
c3c5934c57
commit
cc9fa06117
@ -14,9 +14,9 @@ function ml_get_lisp(): array
|
||||
|
||||
$env = new MadLisp\Env();
|
||||
|
||||
$core = new MadLisp\Lib\Core();
|
||||
$core->register($env);
|
||||
(new MadLisp\Lib\Math())->register($env);
|
||||
|
||||
/*
|
||||
$env->set('eval', function (...$args) use ($eval, $env) {
|
||||
$results = $eval->eval($args, $env);
|
||||
return $results[count($results) - 1];
|
||||
@ -26,6 +26,7 @@ function ml_get_lisp(): array
|
||||
$printer->print($args);
|
||||
return null;
|
||||
});
|
||||
*/
|
||||
|
||||
return [$lisp, $env];
|
||||
}
|
||||
|
44
src/CoreFunc.php
Normal file
44
src/CoreFunc.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
namespace MadLisp;
|
||||
|
||||
use Closure;
|
||||
|
||||
class CoreFunc extends Func
|
||||
{
|
||||
protected string $name;
|
||||
protected string $doc;
|
||||
protected int $minArgs;
|
||||
protected int $maxArgs;
|
||||
|
||||
public function __construct(string $name, string $doc, int $minArgs, int $maxArgs, Closure $closure)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->doc = $doc;
|
||||
$this->minArgs = $minArgs;
|
||||
$this->maxArgs = $maxArgs;
|
||||
$this->closure = $closure;
|
||||
}
|
||||
|
||||
public function call(array $args)
|
||||
{
|
||||
$this->validateArgs(count($args));
|
||||
|
||||
return parent::call($args);
|
||||
}
|
||||
|
||||
private function validateArgs(int $count)
|
||||
{
|
||||
if ($this->minArgs >= 0 && $count < $this->minArgs) {
|
||||
if ($this->minArgs == $this->maxArgs) {
|
||||
throw new MadLispException(sprintf("%s requires exactly %s argument%s", $this->name, $this->minArgs,
|
||||
$this->minArgs == 1 ? '' : 's'));
|
||||
} else {
|
||||
throw new MadLispException(sprintf("%s requires at least %s argument%s", $this->name, $this->minArgs,
|
||||
$this->minArgs == 1 ? '' : 's'));
|
||||
}
|
||||
} elseif ($this->maxArgs >= 0 && $count > $this->maxArgs) {
|
||||
throw new MadLispException(sprintf("%s requires at most %s argument%s", $this->name, $this->maxArgs,
|
||||
$this->maxArgs == 1 ? '' : 's'));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace MadLisp;
|
||||
|
||||
use Closure;
|
||||
|
||||
class Evaller
|
||||
{
|
||||
public function eval(array $expressions, Env $env): array
|
||||
@ -150,10 +148,10 @@ class Evaller
|
||||
|
||||
// Call first argument as function
|
||||
$func = $ast->get(0);
|
||||
if (!($func instanceof Closure)) {
|
||||
if (!($func instanceof Func)) {
|
||||
throw new MadLispException("first item of list is not function");
|
||||
}
|
||||
$args = array_slice($ast->getData(), 1);
|
||||
return $func(...$args);
|
||||
return $func->call($args);
|
||||
}
|
||||
}
|
||||
|
24
src/Func.php
Normal file
24
src/Func.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
namespace MadLisp;
|
||||
|
||||
use Closure;
|
||||
|
||||
abstract class Func
|
||||
{
|
||||
protected Closure $closure;
|
||||
|
||||
public function __construct(Closure $closure)
|
||||
{
|
||||
$this->closure = $closure;
|
||||
}
|
||||
|
||||
public function getClosure(): Closure
|
||||
{
|
||||
return $this->closure;
|
||||
}
|
||||
|
||||
public function call(array $args)
|
||||
{
|
||||
return ($this->closure)(...$args);
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
<?php
|
||||
namespace MadLisp\Lib;
|
||||
|
||||
use Closure;
|
||||
use MadLisp\Env;
|
||||
use MadLisp\Func;
|
||||
use MadLisp\Hash;
|
||||
use MadLisp\MadLispException;
|
||||
use MadLisp\MList;
|
||||
@ -13,72 +13,8 @@ class Core implements ILib
|
||||
{
|
||||
public function register(Env $env): void
|
||||
{
|
||||
// logic
|
||||
|
||||
$env->set('or', function (...$args) {
|
||||
// return first true
|
||||
for ($i = 0; $i < count($args) - 1; $i++) {
|
||||
if ($args[$i] == true) {
|
||||
return $args[$i];
|
||||
}
|
||||
}
|
||||
|
||||
// return last
|
||||
return $args[count($args) - 1];
|
||||
});
|
||||
|
||||
$env->set('and', function (...$args) {
|
||||
// return first false
|
||||
for ($i = 0; $i < count($args) - 1; $i++) {
|
||||
if ($args[$i] == false) {
|
||||
return $args[$i];
|
||||
}
|
||||
}
|
||||
|
||||
// return last
|
||||
return $args[count($args) - 1];
|
||||
});
|
||||
|
||||
$env->set('not', fn ($a) => !$a);
|
||||
|
||||
// arithmetic
|
||||
|
||||
$env->set('+', function (...$args) {
|
||||
return array_sum($args);
|
||||
});
|
||||
|
||||
$env->set('-', function (...$args) {
|
||||
$result = $args[0] ?? null;
|
||||
for ($i = 1; $i < count($args); $i++) {
|
||||
$result -= $args[$i];
|
||||
}
|
||||
return $result;
|
||||
});
|
||||
|
||||
$env->set('*', function (...$args) {
|
||||
$result = $args[0] ?? null;
|
||||
for ($i = 1; $i < count($args); $i++) {
|
||||
$result *= $args[$i];
|
||||
}
|
||||
return $result;
|
||||
});
|
||||
|
||||
$env->set('/', function (...$args) {
|
||||
$result = $args[0] ?? null;
|
||||
for ($i = 1; $i < count($args); $i++) {
|
||||
$result /= $args[$i];
|
||||
}
|
||||
return $result;
|
||||
});
|
||||
|
||||
$env->set('%', function (...$args) {
|
||||
$result = $args[0] ?? null;
|
||||
for ($i = 1; $i < count($args); $i++) {
|
||||
$result %= $args[$i];
|
||||
}
|
||||
return $result;
|
||||
});
|
||||
|
||||
// comparison
|
||||
|
||||
$env->set('=', fn ($a, $b) => $a == $b);
|
||||
@ -91,7 +27,7 @@ class Core implements ILib
|
||||
// types
|
||||
|
||||
$env->set('type?', function ($a) {
|
||||
if ($a instanceof Closure) {
|
||||
if ($a instanceof Func) {
|
||||
return 'function';
|
||||
} elseif ($a instanceof MList) {
|
||||
return 'list';
|
||||
@ -112,7 +48,7 @@ class Core implements ILib
|
||||
}
|
||||
});
|
||||
|
||||
$env->set('fn?', fn ($a) => $a instanceof Closure);
|
||||
$env->set('fn?', fn ($a) => $a instanceof Func);
|
||||
$env->set('list?', fn ($a) => $a instanceof MList);
|
||||
$env->set('hash?', fn ($a) => $a instanceof Hash);
|
||||
$env->set('sym?', fn ($a) => $a instanceof Symbol);
|
||||
@ -124,14 +60,5 @@ class Core implements ILib
|
||||
$env->set('float?', fn ($a) => is_float($a));
|
||||
$env->set('str?', fn ($a) => is_string($a));
|
||||
|
||||
// collections
|
||||
|
||||
$env->set('list', function (...$args) {
|
||||
return new MList($args);
|
||||
});
|
||||
|
||||
$env->set('hash', function (...$args) {
|
||||
return Util::makeHash($args);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
49
src/Lib/Math.php
Normal file
49
src/Lib/Math.php
Normal file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
namespace MadLisp\Lib;
|
||||
|
||||
use MadLisp\CoreFunc;
|
||||
use MadLisp\Env;
|
||||
|
||||
class Math implements ILib
|
||||
{
|
||||
public function register(Env $env): void
|
||||
{
|
||||
// Basic arithmetic
|
||||
|
||||
$env->set('+', new CoreFunc('+', 'Return the sum of all arguments.', 2, -1,
|
||||
function (...$args) {
|
||||
return array_sum($args);
|
||||
}
|
||||
));
|
||||
|
||||
$env->set('-', new CoreFunc('-', 'Subtract the other arguments from the first.', 2, -1,
|
||||
function (...$args) {
|
||||
return array_reduce(array_slice($args, 1), fn ($a, $b) => $a - $b, $args[0]);
|
||||
}
|
||||
));
|
||||
|
||||
$env->set('*', new CoreFunc('*', 'Multiply the arguments.', 2, -1,
|
||||
function (...$args) {
|
||||
return array_reduce(array_slice($args, 1), fn ($a, $b) => $a * $b, $args[0]);
|
||||
}
|
||||
));
|
||||
|
||||
$env->set('/', new CoreFunc('/', 'Divide the arguments.', 2, -1,
|
||||
function (...$args) {
|
||||
return array_reduce(array_slice($args, 1), fn ($a, $b) => $a / $b, $args[0]);
|
||||
}
|
||||
));
|
||||
|
||||
$env->set('//', new CoreFunc('//', 'Divide the arguments using integer division.', 2, -1,
|
||||
function (...$args) {
|
||||
return array_reduce(array_slice($args, 1), fn ($a, $b) => intdiv($a, $b), $args[0]);
|
||||
}
|
||||
));
|
||||
|
||||
$env->set('%', new CoreFunc('%', 'Calculate the modulo of arguments.', 2, -1,
|
||||
function (...$args) {
|
||||
return array_reduce(array_slice($args, 1), fn ($a, $b) => $a % $b, $args[0]);
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
<?php
|
||||
namespace MadLisp;
|
||||
|
||||
use Closure;
|
||||
|
||||
class Printer
|
||||
{
|
||||
public function print(array $items): void
|
||||
@ -14,7 +12,7 @@ class Printer
|
||||
|
||||
private function doPrint($a): string
|
||||
{
|
||||
if ($a instanceof Closure) {
|
||||
if ($a instanceof Func) {
|
||||
return '<function>';
|
||||
} elseif ($a instanceof MList) {
|
||||
return '(' . implode(' ', array_map(fn ($b) => $this->doPrint($b), $a->getData())) . ')';
|
||||
|
7
src/UserFunc.php
Normal file
7
src/UserFunc.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
namespace MadLisp;
|
||||
|
||||
class UserFunc extends Func
|
||||
{
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user