Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/tsavola/lep
Mini language for embedding interactive consoles into Rust programs
https://github.com/tsavola/lep
command-line-interface lisp-interpreter rust
Last synced: about 23 hours ago
JSON representation
Mini language for embedding interactive consoles into Rust programs
- Host: GitHub
- URL: https://github.com/tsavola/lep
- Owner: tsavola
- License: mit
- Created: 2019-04-17T21:21:39.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2022-12-22T06:35:34.000Z (almost 2 years ago)
- Last Synced: 2024-11-14T10:50:37.230Z (5 days ago)
- Topics: command-line-interface, lisp-interpreter, rust
- Language: Rust
- Homepage: https://crates.io/crates/lep
- Size: 64.5 KB
- Stars: 7
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Lep
Mini language for interactive consoles, featuring small code footprint. It's
essentially a sugarcoated Lisp subset, approximating shell syntax, influenced
by Python.The core language is functional/declarative. It's not Turing complete:
function creation, looping and recursion are not supported. Variable binding
is supported at the top-level (session scope). Extension functions may
introduce side-effects.The idea is that the Rust program (which embeds Lep) implements extension
functions, effectively creating a domain-specific query or administration
language. The host program is also responsible for setting up the REPL
(read-eval-print-loop), thus choosing where the input is read from and what
gets printed.## Syntax
Evaluation is line-oriented: one line corresponds to one statement. A
statement yields an observable result value.Statement syntax (both parts are optional):
!variable expression
The variable name is any character string excluding whitespace, `(` and `)`.
The expression is an otherwise usual
[s-expression](https://en.wikipedia.org/wiki/S-expression), but the outermost
parentheses may be omitted.The statement yields the value of the expression. If the `!` prefix is
present, the value is also assigned to a variable. If variable name is empty,
an unused name is chosen (e.g. `$1`). If the `!` prefix is omitted, the value
is assigned to the `_` variable. If the expression is omitted, the `_`
variable is evaluated.Examples:
>> echo "foo"
foo
>> + 1 2 3
6
>> (+ _ 10)
16
>> * (/ (- 10 5) 2) 50
100
>> ()
>> cons 1 2
(1 . 2)
>> list 1 2
(1 2)
>> ! + 1 2 3
$1 = 6
>> !x + 1 2 3
x = 6
>> !y (* x 2)
y = 12
>> and (or (and x y) (or)) true false
false
>> !z
z = false
>> !
$2 = false
>> env
(($2 . false) (z . false) (y . 12) (x . 6) ($1 . 6))The statement syntax is optimized for two-step usage:
1. Evaluate an expression
2. Decide whether the result is worth remembering!An expression without outer parentheses evaluates a variable/literal or invokes
a function depending on the type of the first term.When the first term is a variable or a literal and there are multiple terms,
the expression is quoted:>> 1 2 3
(1 2 3)A statement consisting only of whitespace yields `()` and leaves the variables
unchanged. When the user inputs an empty line, the embedder program doesn't
need to evaluate it, and may do something else instead.## Functions
Built-in functions:
```scheme
(and arg1 arg2 ...)
(or arg1 arg2 ...)
(not arg)
(apply function arguments)
(+ arg1 arg2 ...)
(- arg1 arg2 ...)
(* arg1 arg2 ...)
(/ arg1 arg2 ...)
(car arg)
(cdr arg)
(cons arg1 arg2)
(list arg1 arg2 ...)
(drop list count)
(take list count)
(env)
```Custom extension functions have signature
`fn(args: &Rc) -> Result, String>`
or implement the `lep::Fun` or the `lep::FunMut` trait.## Types
Lep has a dynamic and open-ended type system. Type `Rc` (aliased as
`lep::Obj`) is used to pass immutable values to and from functions. Extension
functions may return and accept custom types, but they cannot be used with
built-in arithmetic functions, and logical functions will treat their values as
truthful.Fully supported types:
- `()`
- `bool`
- `i64`
- `String`
- `lep::Name` (symbol)
- `lep::Ref` (function)
- `lep::Pair` (cons cell, e.g. a list node)The following values are considered untrue:
- `()`
- `false`
- `0` (only i64)
- `""` (only String)## Evaluation
Extension functions are bound to a `lep::Domain` object:
```rust
let mut domain = lep::Domain::new();
lep::builtin::register(&mut domain);
domain.register("nop", |args: &lep::Obj| Ok(lep::obj::nil()));
```An evaluation iteration takes an existing `lep::State` and replaces it with a
new one:```rust
let mut state = lep::State::new();
loop {
match lep::eval_stmt(&mut domain, state.clone(), read_line()) {
Ok(new_state) => {
// Print result here.
state = new_state;
}
Err(msg) {
println!("error: {}", msg);
}
}
}
```