add meta function

This commit is contained in:
Pekka Laiho 2020-10-24 10:02:50 +07:00
parent 1e33e4d146
commit c110522f3b
3 changed files with 36 additions and 0 deletions

View File

@ -116,6 +116,20 @@ The special single quote character can be used to quote an expression (skip eval
Environments are hash-maps which store key-value pairs and use symbols as keys. Symbols are evaluated by looking up the corresponding value from the current environment. If the key is not defined in current environment the lookup proceeds to the parent environment and so forth. The initial environment is called `root` and contains all the built-in functions listed here. Then another environment called `user` is created for anything the user wants to define. The `let` and `fn` special forms create new local environments. Note that `def` always uses the current environment, so anything defined with `def` is not visible in the parent environment.
You can get the name of an environment using the `meta` function:
```
> (meta (env) "name")
"root/user"
```
You can also retrieve the parent environment:
```
> (meta (env) "parent")
{}
```
## Special forms
Name | Example | Example result | Description
@ -142,6 +156,7 @@ Name | Example | Example result | Description
----- | ------- | -------------- | -----------
doc | `(doc +)` | `"Return the sum of all arguments."` | Show description of a built-in function.
loop | `(loop (fn (a) (do (print a) (coinflip))) "hello ")` | `hello hello hello false` | Call the given function repeatedly in a loop until it returns false.
meta | `(meta (env) "name")` | `"root/user"` | Read meta information of an entity.
read | `(read "(+ 1 2 3)")` | `(+ 1 2 3)` | Read a string as code and return the expression.
print | `(print "hello world")` | `"hello world"null` | Print expression on the screen. Print returns null (which is shown due to the extra print in repl). Give optional second argument as `true` to show strings in readable format.
error | `(error "invalid value")` | `error: invalid value` | Throw an exception with message as argument.

View File

@ -32,6 +32,11 @@ class Env extends Hash
throw new MadLispException("symbol $key not defined in env");
}
public function getParent(): ?Env
{
return $this->parent;
}
public function set(string $key, $value)
{
// Do not allow overwriting values in root env

View File

@ -33,6 +33,22 @@ class LispFactory
}
));
$env->set('meta', new CoreFunc('meta', 'Read meta information of an entity.', 2, 2,
function ($obj, $attribute) {
if ($obj instanceof Env) {
if ($attribute == 'name') {
return $obj->getFullName();
} elseif ($attribute == 'parent') {
return $obj->getParent();
} else {
throw new MadLispException('unknown attribute for meta');
}
} else {
throw new MadLispException('unknown entity for meta');
}
}
));
$env->set('read', new CoreFunc('read', 'Read string as code.', 1, 1,
fn (string $a) => $reader->read($tokenizer->tokenize($a))
));