tree-traversing LISP interpreter geared toward embeddability and system scripting
Find a file
Ava Hahn dc6342bc74
Several changes, see commit msg
* clean up all tests
* bugfix for zero value functions, and test
* removed expand function, put in snippets
* added doc strings to Symbol type
* added doc strings to symbol declarations
* implemented display for Args type
* wrote a help function
* wrote docstrings for all builtins and config vars
2023-03-05 22:18:49 -08:00
snippets Several changes, see commit msg 2023-03-05 22:18:49 -08:00
src Several changes, see commit msg 2023-03-05 22:18:49 -08:00
tests Several changes, see commit msg 2023-03-05 22:18:49 -08:00
.gitignore ignore Cargo.lock 2021-10-17 23:12:22 -07:00
.gitlab-ci.yml rustfmt 2023-03-01 11:47:37 -08: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 Several changes, see commit msg 2023-03-05 22:18:49 -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

TODO Syntax

TODO Basic data types

TODO S-Expressions

TODO calling a function

TODO Control flow

TODO if
TODO while
TODO let
TODO circuit

TODO Defining variables and functions

TODO Anatomy
TODO Naming conventions
TODO Undefining variables and functions

TODO Easy patterns

TODO while-let combo
TODO main loop application

TODO Builtin functions

TODO Documentation

TODO Tests
TODO Help function
TODO Snippets directory

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. See file:snippets/basic_minimal_configuration.rls for an example of a basic minimal configuration file.

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. In such a case any defaults which have not been overwritten will remain present.

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 the standard library configured to use the previously defined configuration variables.
  • The standard library will then be re-processed and re-added to the symbol table with new configuration.
  • 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. This function will be reloaded each REPL loop and will be called by the interpreter with no arguments.

TODO Further 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.

config: file:src/config.rs

This file contains default configuration values as well as functions which load and run the configuration file script. For more information see the configuraiton section above in this Readme.

stl: file:src/stl.rs

This defines the static_stdlib function and the dynamic_stdlib function. The static_stdlib function loads all symbols in the standard library which do not need further configuration into the symbol table. The dyanmic_stdlib function loads all symbols in the standard library which do need configuration into the symbol table. The dynamic_stdlib function uses variables saved in the symbol table to configure the functions and variables it loads. For more information see file:src/config. 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 these functions 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.

You can view the code for standard library functions in file:src/stl/.

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. Note: this section only tracks the state of incomplete TODO items. Having everything on here would be cluttered.

TODO Custom ast pretty print

TODO Help function

DONE add doc string to function form
DONE write doc strings to all symbols
DONE pretty printer for help doc
DONE help function outputs name, args, and help doc
TODO help function outputs current value or function form pretty printed

TODO Eval function

TODO Input function

TODO Env function

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 tables

TODO Main shell calls Load function on arg and exits

TODO Can enter multiple lines of text, with formatting in repl

TODO arithmetic operations

TODO typecast (int)
TODO typecast (float)
TODO add
TODO sub
TODO div
TODO mul
TODO exp
TODO mod
TODO inc
TODO dec
TODO int (float to int)
TODO gt?
TODO lt?
TODO snippets for gte and lte

TODO string operations

TODO typecast (string)
TODO contains
TODO len
TODO concat
TODO substr by index
TODO split (on delimiter)
TODO strcons (sprintf but its all string tokens under the hood)

TODO Shell module

TODO Args parsing helper
TODO Process launching with environment variables
TODO Optional form of process which allows fd redirecting
TODO Foreground process TTY
TODO Background processes
TODO Update config env var docstring with functions loaded or unloaded

TODO list operations

DONE append
DONE expand
TODO head (returns (head rest))
TODO tail (returns (rest tail))
TODO queue (append to front)
TODO snippet for dequeue
TODO snippet for pop

TODO file operations

TODO read-to-string
TODO write-to-file

TODO Rename to Flesh

TODO Pick through core/ast and make sure no unnessesary moves are happening

TODO Create a dedicated community channel on matrix.sunnypup.io

TODO Post to relevant channels

TODO Network library

TODO HTTP Client
TODO TCP Stream client
TODO UDP Client
TODO TCP Listener
TODO HTTP Listener
TODO UDP Listener