tree-traversing LISP interpreter geared toward embeddability and system scripting
Find a file
Ava Hahn d640c815a8
add eval test
Signed-off-by: Ava Hahn <ava@aidanis.online>
2023-02-24 15:45:27 -08:00
legacy_snippets WIP commit: 2023-02-15 23:30:44 -08:00
src implement hideously inefficient fix to work around rust 2023-02-24 15:09:00 -08:00
tests add eval test 2023-02-24 15:45:27 -08:00
.gitignore ignore Cargo.lock 2021-10-17 23:12:22 -07:00
.gitlab-ci.yml add dedicated build step to CI 2021-11-02 20:07:10 -07:00
Cargo.toml simplify eval, add member function to symtable to call a symbol 2023-02-23 23:01:47 -08:00
LICENSE.md - syntax tree datatypes 2021-01-24 12:34:58 -08:00
Readme.org little readme update 2023-02-19 13:50:24 -08:00

Relish: Rusty Expressive LIsp SHell

Note: this document is best read within a dedicated ORG mode interpreter

Purpose statement

The purpose of Relish is to create a highly expressive POSIX shell using a lisp interpreter.

Goals

  • Iterate on the ideas and designs that were tested with SHS

https://gitlab.com/whom/shs

  • Act as both a high level scripting language and as a system shell
  • To be as portable as possible
  • To provide code and framework that can be embedded in other applications needing a user facing interpreter
  • To be well tested code
  • No unsafe code without extreme consideration and rigorous containment

Contact

  • Matrix chat: #vomitorium:matrix.sunnypup.io

https://matrix.to/#/#vomitorium:matrix.sunnypup.io

How to use

Configuration

By default Relish will read from ~/.relishrc for configuration, but the default shell will also accept a filename from the RELISH_CFG_FILE environment variable.

The configuration file

The configuration file is a script containing arbitrary Relish code. On start, any shell which leverages the configuration code in the config module (file:src/config.rs) will create a clean seperate context, including default configuration values, within which the standard library will be initialized. The configuration file is evaluated and run as a standalone script and may include arbitrary executable code. Afterwards, configuration values found in the variable map will be used to configure the standard library function mappings that the shell will use. Errors during configuration are non-terminal and will result in default values being returned.

Important points to note
  • When the configuration file is run, it will be run with default configuration values.
  • The user/script interpreter will be run with a re-instantiation of the standard library, using the previously defined configuration variables.
  • Variables and functions defined during configuration will carry over to the user/script interpreter, allowing the user to load any number of custom functions and variables.

Configuration Values

  • CFG_RELISH_POSIX (default 0): when on, enables POSIX style job control.
  • CFG_RELISH_ENV (default 1): when on, interpreter's variable table and environment variable table are kept in sync.
  • CFG_RELISH_PROMPT (default (echo "λ ")): A function definition which is called in order to output the prompt for each loop of the REPL.

Note: CFG_RELISH_PROMPT is only loaded once and will be ignored after initial configuration.

Compilation

  cargo build

Testing

  cargo test

Running (the main shell)

  cargo run src/bin/main.rs

Guide to codebase

file:tests directory

Start here if you are new. Most of these files have unimplemented tests commented out in them. Contributions that help fill out all of these tests

Eval tests: file:tests/test_eval.rs

These are particularly easy to read and write tests.

Func tests: file:tests/test_func.rs

You can consider these to extend the eval tests to cover the co-recursive nature between eval and func calls.

Lex tests: file:tests/test_lex.rs

These tests verify the handling of syntax.

Lib tests: (tests/test_lib*)

These tests are unique per stdlib module.

file:src directory

This directory contains all of the user facing code in relish. Just a few entries of note:

segment: file:src/segment.rs

This file lays out the spiritual theological ideological theoretical mechanical underpinnings of the entire interpreter. The entire LISP machine centers around a singlet or pairing of datum. The Ctr datatype provides an abstraction for which any type of data, including a Seg can be a datum. The Seg datatype provides a mechanism to hold a single datum or a pair of datum. It is implemented as two Ctr~s: ~car and cdr. A primitive type system is provided through the Rust Enum datatype. A number of utility functions follow.

lib: file:src/lib.rs

This defines a library that can be included to provide an interpreter interface within any Rust project. It includes the core interpreter mechanisms, full stdlib, and the configuration system. Your project can use or not use any number of these components. They can certainly be used to support language development for other LISP machines, or even other languages.

stl: file:src/stl.rs

This defines the get_stdlib function. This function takes in a Variable Table (likely containing custom configuration) and returns a Function Table for use in an interpreter. Any new addition to the stdlib must make its way here to be included in the main shell (and any other shell using the included get_stdlib function). You may choose to override this function if you would like to include your own special functions in your own special interpreter, or if you would like to pare down the stdlib to a small minimal subet of what it is.

bin: file:src/bin/

This contains any executable target of this project. Notably the main shell file:src/bin/main.rs.

Current Status / TODO list

Note: this section will not show the status of each item unless you are viewing it with a proper orgmode viewer

DONE Core interpreter stuffs

DONE Lexing
DONE Parsing
DONE Evaluation
DONE Function table
DONE Variable table

DONE Echo function

DONE Redo segment.rs

DONE Clone impl for Ctr

(derived)

DONE Derive Clone for Seg
DONE ToString impl for Ctr
DONE ToString impl for Seg
DONE Display, Debug impls for Ctr
DONE Derive Display, Debug for Seg
DONE Default impl for Ctr
DONE Derive Default for Seg
WONTDO From/Into for Ctr
DONE Iterator for Seg
WONTDO Consider RefCell for tables, or using 'static lifetime

one of these may fix borrow checker insanity

DONE make FTable and VTable singleton modules (global mutable)
WONTDO make FTable and VTable into private definitions
DONE YEET AST EVERYWHERE. PASS AROUND A SEG REF.

TODO refactor code into more digestible, better organized pieces

DONE combine var and func table into global sym table
DONE refactor and reimplement eval
TODO (test and get it working)
TODO lex/eval/e2e tests for var that holds callback func

TODO Rudimentary Control Flow

TODO if clause
TODO loop clause
TODO while clause
TODO circuit clause

DONE Configuration

DONE Function to load configuration into Variable and Function tables
DONE Configure in main shell
DONE manual verification of config settings
DONE manual verification of config defaults

TODO Help function

TODO Env function

DONE User variable declaration

DONE User function declaration

TODO Load (load a script) function

Pull/Refactor the logic out of the configure functions. Optionally return a list of new variables and/or functions? Will need a concatenate function for func tables

TODO Main shell calls Load function on arg and exits

TODO Custom error printing

TODO Custom ast pretty print

DONE Implement Ctr, Ast to_string / Display trait

TODO get_stdlibphase1 -> configuration -> get_stdlibphase2

TODO STDLIB

TODO Shell module

TODO Process launching with environment variables
TODO Foreground process TTY
TODO Background processes
DONE append
TODO string operations
DONE concatenate
TODO substr by index
TODO tokenize by delimiter
TODO sprintf / string build
TODO arithmetic operations
TODO
TODO Serialize/Deserialize basic data types
TODO file opterations
TODO
TODO Network library
TODO HTTP Client
TODO TCP Stream client
TODO UDP Client
TODO TCP Listener
TODO HTTP Listener
TODO UDP Listener

TODO Ensure full test coverage

TODO Implement missing func, Lex, Eval tests
TODO stdlib tests :)