Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/adam-mcdaniel/sage-lisp
A general purpose Lisp🛸 intended for use as Sage's preprocessor language
https://github.com/adam-mcdaniel/sage-lisp
interpreter lisp metaprogramming mit-license rust
Last synced: 3 months ago
JSON representation
A general purpose Lisp🛸 intended for use as Sage's preprocessor language
- Host: GitHub
- URL: https://github.com/adam-mcdaniel/sage-lisp
- Owner: adam-mcdaniel
- License: mit
- Created: 2024-04-01T01:54:59.000Z (10 months ago)
- Default Branch: main
- Last Pushed: 2024-11-17T02:55:02.000Z (3 months ago)
- Last Synced: 2024-11-17T03:27:40.635Z (3 months ago)
- Topics: interpreter, lisp, metaprogramming, mit-license, rust
- Language: Rust
- Homepage: https://adam-mcdaniel.net/sage-lisp/
- Size: 530 KB
- Stars: 7
- Watchers: 2
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Sage-Lisp
![Logo](assets/logo.png)
- **Author**: Adam McDaniel
- **GitHub**: [adam-mcdaniel/sage-lisp](https://github.com/adam-mcdaniel/sage-lisp)
- **License**: MITThis crate implements a standalone Lisp implementation, intended for use in the [Sage](https://github.com/adam-mcdaniel/sage) preprocessor.
## Table of Contents
- [About](#about)
- [Features](#features)
- [Usage](#usage)
- [Example Lisp Syntax](#example-lisp-syntax)
- [Example Embedding](#example-embedding)
- [About the Author](#about-the-author)
- [Documentation](#documentation)
- [License](#license)## About
Sage-Lisp is a simple core lisp interpreter written in Rust,
that can be expanded to include new functionality with built-in functions.It's designed such that you can provide your own standard library of functions,
implemented in Rust or in Lisp, and evaluate lisp expressions with your own
standard conventions.It works well as an embedded language for data transformation, where you can
import data into the interpreter (using Serde), perform transformations on it, and then
export the data back out into a format that you can use in your application.## Features
- **Simple Lisp Interpreter**: A simple core lisp interpreter that can evaluate lisp expressions.
- **Built-in Functions**: Extend the language with new functionality using built-in functions.
- **Symbol Interning**: Symbols are interned to ensure that they are unique and fast to compare.
- **Tail Recursion**: Uses tail recursion to evaluate deeply nested function calls without stack overflow.
- **Lazy Evaluation**: Supports lazy evaluation of expressions, for defining special forms.
- **Serde Integration**: Serialize and deserialize lisp expressions using Serde.
- **Error Handling**: Provides helpful error messages for parsing and evaluation errors.
- **Expanded Syntax**: Introduces infix operators, code block syntax, syntax for hashmaps and ordered maps, and more.
- **Customizable**: Define your own standard library of functions and variables, and override the default behavior.## Usage
To run Sage lisp on a program, build it like so:
```bash
$ cargo build --features build-binary --release
```Then, use it to run a file as a program.
```bash
$ cp ./target/release/sagel .
$ ./sagel example.lisp
```Or provide a program as a command line argument.
```bash
$ ./sagel -c "(do (println hi!) (+ 1 2 3))"
hi!
6
```## Example Lisp Syntax
The example below shows some of the syntax that is supported by the interpreter,
along with some of the built-in functions that are provided when the crate is
used as an executable.```lisp
;; Define a function that calculates the factorial of a number
(defun fact (n)
(if n <= 0
1
n * (fact n - 1)))
;; Stirling's approximation for the factorial
(defun stirlings (n)
(if n <= 0 1
(* (sqrt 2 * 3.14159265358979323846 * n)
((n / 2.71828182845904523536) ^ n))))
;; Perform a quicksort on a list of numbers
(defun quicksort (lst)
(if (<= (len lst) 1) lst {
(define pivot (get lst (/ (len lst) 2)))
(define less (filter (\(x) (< x pivot)) lst))
(define equal (filter (\(x) (= x pivot)) lst))
(define greater (filter (\(x) (> x pivot)) lst))
(+ (quicksort less) equal (quicksort greater))}))
```## Example Embedding
Below is an example of how you can embed the interpreter into your application,
with your own standard library of functions and variables.```rust
// Import the necessary types and traits for the interpreter.
use sage_lisp::{Expr, Env};// Create a new environment
fn make_core_env() -> Env {
// Create a new environment
let mut env = Env::new();// Create a function that adds two numbers
env.bind_builtin("+", |env, exprs| {
let mut sum = Expr::default();
for e in exprs {
// Evaluate the supplied argument in the environment
let e = env.eval(e.clone());
// Match the expression to the sum
match (sum, e) {
(Expr::None, b) => sum = b,
(Expr::Int(a), Expr::Int(b)) => sum = Expr::Int(a + b),
(Expr::Float(a), Expr::Float(b)) => sum = Expr::Float(a + b),
(Expr::Int(a), Expr::Float(b)) => sum = Expr::Float(a as f64 + b),
(Expr::Float(a), Expr::Int(b)) => sum = Expr::Float(a + b as f64),
(Expr::String(a), Expr::String(b)) => sum = Expr::String(format!("{}{}", a, b)),
(Expr::List(a), Expr::List(b)) => {
let mut list = a.clone();
list.extend(b);
sum = Expr::List(list);
}
(Expr::List(a), b) => {
let mut list = a.clone();
list.push(b);
sum = Expr::List(list);
}
// Return an error if the expression is invalid
(a, b) => return Expr::error(format!("Invalid expr {} + {}", a, b)),
}
}
sum
});
// Create a function that prints a string
env.bind_builtin("println", |env, exprs| {
for e in exprs {
// Evaluate the supplied argument in the environment
let e = env.eval(e.clone());
// Print the expression
match e {
Expr::String(s) => print!("{}", s),
Expr::Symbol(s) => print!("{}", s.name()),
_ => print!("{}", e),
}
}
println!();
Expr::None
});
env
}fn main() {
// Create a new environment with our custom standard library
let mut env = make_core_env();// Evaluate a lisp expression in the environment
env.eval_str("{ (println 1 + 2) (println (+ 2 2)) }").unwrap();
}
```## About the Author
[I'm a computer science PhD student](https://adam-mcdaniel.net) at the [University of Tennessee, Knoxville🍊](https://www.youtube.com/watch?v=-8MlEo02u54). Rust is my favorite language, and [I've](https://github.com/adam-mcdaniel/sage) [written](https://github.com/adam-mcdaniel/oakc) [many](https://github.com/adam-mcdaniel/harbor) [other](https://github.com/adam-mcdaniel/tsar) [programming](https://github.com/adam-mcdaniel/free) [languages](https://github.com/adam-mcdaniel/xasm).
I'm always looking for new projects to work on, so if you have an idea for a project or a collaboration, feel free to reach out to me or join me on the [Sage Discord server](https://discord.gg/rSGkM4bcdP)!
## Documentation
For more information on how to use the Sage Lisp interpreter, see the [documentation](https://adam-mcdaniel.github.io/sage-lisp/).
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.