mirror of
https://github.com/peklaiho/madlisp.git
synced 2024-11-22 21:35:03 +00:00
improve eval, add env/quote
This commit is contained in:
parent
adc6ab99c3
commit
2acdde303a
2
repl.php
2
repl.php
@ -9,7 +9,7 @@ while (true) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$lisp->rep($input, $env);
|
$lisp->rep($input, $env);
|
||||||
} catch (MadLispException $ex) {
|
} catch (MadLisp\MadLispException $ex) {
|
||||||
print('error: ' . $ex->getMessage());
|
print('error: ' . $ex->getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,8 +149,5 @@ class Core implements ILib
|
|||||||
|
|
||||||
return new Hash($data);
|
return new Hash($data);
|
||||||
});
|
});
|
||||||
|
|
||||||
// for debugging!
|
|
||||||
$env->set('eval', fn ($a) => ml_eval($a, $env));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
41
src/Lisp.php
41
src/Lisp.php
@ -99,19 +99,35 @@ class Lisp
|
|||||||
public function eval($expr, Env $env)
|
public function eval($expr, Env $env)
|
||||||
{
|
{
|
||||||
if ($expr instanceof MList && $expr->count() > 0) {
|
if ($expr instanceof MList && $expr->count() > 0) {
|
||||||
// Evaluate list contents
|
$first = $expr->get(0);
|
||||||
$results = array_map(fn ($a) => $this->eval($a, $env), $expr->getData());
|
|
||||||
|
|
||||||
$fn = $results[0];
|
if ($first instanceof Symbol) {
|
||||||
|
// Special built-in features
|
||||||
|
if ($first->getName() == 'env') {
|
||||||
|
return $env;
|
||||||
|
} elseif ($first->getName() == 'quote') {
|
||||||
|
if ($expr->count() != 2) {
|
||||||
|
throw new MadLispException("quote requires exactly 1 argument");
|
||||||
|
}
|
||||||
|
|
||||||
if ($fn instanceof Closure) {
|
return $expr->get(1);
|
||||||
// If the first item is a function, call it
|
}
|
||||||
$args = array_slice($results, 1);
|
|
||||||
return $fn(...$args);
|
// Normal symbol, fetch from env
|
||||||
} else {
|
$first = $env->get($first->getName());
|
||||||
// Otherwise return new list with evaluated contents
|
|
||||||
return new MList($results);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!($first instanceof Closure)) {
|
||||||
|
throw new MadLispException("first argument of list is not function");
|
||||||
|
}
|
||||||
|
|
||||||
|
$args = array_slice($expr->getData(), 1);
|
||||||
|
|
||||||
|
// Evaluate args
|
||||||
|
$args = array_map(fn ($a) => $this->eval($a, $env), $args);
|
||||||
|
|
||||||
|
// Call func and return result
|
||||||
|
return $first(...$args);
|
||||||
} elseif ($expr instanceof Hash) {
|
} elseif ($expr instanceof Hash) {
|
||||||
// Hash: return new hash with all items evaluated
|
// Hash: return new hash with all items evaluated
|
||||||
$items = [];
|
$items = [];
|
||||||
@ -120,9 +136,10 @@ class Lisp
|
|||||||
}
|
}
|
||||||
return new Hash($items);
|
return new Hash($items);
|
||||||
} elseif ($expr instanceof Symbol) {
|
} elseif ($expr instanceof Symbol) {
|
||||||
return $env->get($expr->name());
|
return $env->get($expr->getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the expression unchanged
|
||||||
return $expr;
|
return $expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +162,7 @@ class Lisp
|
|||||||
}
|
}
|
||||||
$result = '{' . implode(' ', $items) . '}';
|
$result = '{' . implode(' ', $items) . '}';
|
||||||
} elseif ($a instanceof Symbol) {
|
} elseif ($a instanceof Symbol) {
|
||||||
$result = $a->name();
|
$result = $a->getName();
|
||||||
} elseif ($a === true) {
|
} elseif ($a === true) {
|
||||||
$result = 'true';
|
$result = 'true';
|
||||||
} elseif ($a === false) {
|
} elseif ($a === false) {
|
||||||
|
@ -10,7 +10,7 @@ class Symbol
|
|||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function name(): string
|
public function getName(): string
|
||||||
{
|
{
|
||||||
return $this->name;
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user