2023-01-21 14:53:55 -08:00
#+Title : Relish: Rusty Expressive LIsp SHell
#+Author : Ava Hahn
2023-03-07 14:29:31 -08:00
Note: this document is best read using a dedicated ORG mode editor
2023-01-22 19:36:37 -08:00
2023-01-21 14:53:55 -08:00
* Purpose statement
2023-03-07 14:29:31 -08:00
The purpose of Relish is to create a highly portable, easy to integrate language that can be used in many environments.
2023-01-21 14:53:55 -08:00
* Goals
2023-05-25 15:00:14 -07:00
- Iterate on the ideas and designs that were tested with [[https://gitlab.com/whom/shs ][SHS ]]
2023-03-07 14:29:31 -08:00
- Create a usable POSIX shell
- Create usable applications/scripts
- To have quality code coverage
2023-05-28 15:14:15 -07:00
- No unsafe code nessesary
Note: as of release 0.3.0, the Posix module requires unsafe code in order to interface with libc.
Users are still able to compile and use Relish without any of the unsafe code involved by removing
the POSIX module. See the Compilation section for more details.
2023-03-07 14:29:31 -08:00
** Stretch Goals
- Create an interpreter that can be booted on one or more SOCs
- Create an interpreter that can be embedded in another application
- Create UI bindings
2023-01-21 14:53:55 -08:00
* Contact
2023-05-16 11:28:50 -07:00
[[https://matrix.to/#/#relish:matrix.sunnypup.io ][Matrix chat: #relish:matrix.sunnypup.io ]]
2023-01-21 14:53:55 -08:00
2023-05-28 23:22:49 +00:00
If you like Relish and want to support me in working on it consider donating: [[https://ko-fi.com/avaaffine ][Ava's Ko-Fi ]].
2023-05-28 15:14:15 -07:00
* Documentation
** Writing in Relish
Users who are new to Relish, or who are seeking documentation on how to effectively write in Relish should reference [[file:Writing.org ][the main language documentation ]]. This will go over the following:
- How Relish operates under the hood
- Relish's syntax
- Relish control flow constructs
- Stdlib functions
- Builting documentation
- Common patterns in using Relish
** Using Relish as your shell
As of version 0.3.0 Relish implements all the features of an interactive shell.
See further documentation in [[file:Shell.org ][the shell documentation ]]. This material goes over the following:
- How to start and view jobs in Relish
- Special forms for modifying the file descriptors of new jobs
- Piping and other special shell control flow
- Special snippets used to provide a first class shell experience
* Configuration
2023-01-21 14:53:55 -08:00
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.
2023-05-25 15:00:14 -07:00
See [[file:snippets/basic_minimal_configuration.rls ][the minimal shell configuration example ]] for an example of a basic configuration file.
2023-05-16 11:28:50 -07:00
Other snippets, including mood-prompt and avas-laptop-prompt demonstrate more complex configurations.
2023-01-21 14:53:55 -08:00
2023-05-28 15:14:15 -07:00
** The configuration file
2023-01-21 14:53:55 -08:00
The configuration file is a script containing arbitrary Relish code.
2023-05-25 15:00:14 -07:00
On start, any shell which leverages the configuration code in the config module ([[file:src/run.rs ][run.rs ]]) will create a clean seperate context, including default configuration values, within which the standard library will be initialized.
2023-05-16 11:28:50 -07:00
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.
2023-03-01 13:27:47 -08:00
Errors during configuration are non-terminal. In such a case any defaults which have not been overwritten will remain present.
2023-01-21 14:53:55 -08:00
**** Important points to note
2023-01-22 19:36:37 -08:00
- When the configuration file is run, it will be run with default configuration values.
2023-03-01 13:27:47 -08:00
- 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.
2023-01-22 19:36:37 -08:00
- 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.
2023-01-21 14:53:55 -08:00
2023-05-28 15:14:15 -07:00
** Configuration Values
2023-06-05 23:32:51 -07:00
- CFG_RELISH_POSIX (default true): when true, enables POSIX style job control and shell features.
2023-03-18 23:00:55 -07:00
- CFG_RELISH_ENV (default true): when true, interpreter's variable table and environment variable table are kept in sync.
2023-03-23 11:52:36 -07:00
- CFG_RELISH_L_PROMPT (default 'λ'): a function that is called with no arguments to output the left hand of the prompt
- CFG_RELISH_R_PROMPT (default ''): a function that is called with no arguments to output the right hand of the prompt
- CFG_RELISH_PROMPT_DELIMITER (default '>'): a function that is called with no arguments to output the delimiter separating prompt from user input
2023-05-28 15:14:15 -07:00
** Prompt design
2023-05-25 15:00:14 -07:00
For an example of prompt design see [[file:snippets/mood-prompt.rls ][the mood prompt ]]
For a more complex example see [[file:snippets/avas-laptop-prompt.rls ][Ava's laptop prompt ]]
2023-01-21 14:53:55 -08:00
2023-05-28 15:14:15 -07:00
** Further configuration
2023-03-08 12:02:20 -08:00
Further configuration can be done by loading scripts that contain more functions and data to evaluate.
Variables and functions defined in an external script loaded by your interpreter will persist in the symbol table.
#+BEGIN_SRC lisp
2023-03-27 14:34:07 -07:00
(call "my-extra-library-functions.rls")
2023-03-08 12:02:20 -08:00
#+END_SRC
2023-03-01 15:17:50 -08:00
2023-05-28 15:14:15 -07:00
* Compilation
Compiling Relish is as simple as kicking off a build with Cargo.
#+BEGIN_EXAMPLE sh
2023-01-21 14:53:55 -08:00
cargo build
2023-05-28 15:14:15 -07:00
#+END_EXAMPLE
2023-06-05 23:32:51 -07:00
This will produce a binary at [[file:target/debug/relish ][target/debug/relish ]] which includes all of the features relish has to offer. This provides a REPL with a full interactive shell that also can manage variables in the Unix environment. It is possible to compile a smaller REPL that does not interact with environment variables and does not offer any shell features. Simply pass the ~--no-default-features~ flag to cargo:
2023-05-28 15:14:15 -07:00
#+BEGIN_EXAMPLE sh
cargo build --no-default-features
#+END_EXAMPLE
2023-06-05 23:32:51 -07:00
In order to run Relish it is recommended to run the resulting binary at [[file:target/debug/relish ][target/debug/relish ]].
2023-01-21 14:53:55 -08:00
** Testing
2023-05-28 15:14:15 -07:00
Relish has upwards of 120 unit tests. Full functionality of the core AST with lex, parse, and eval routines as well as the symbol table and relevant code can be tested with Cargo. Unit tests are also included for the standard library of data manipulations and special cases around quote/eval and lambda use:
#+BEGIN_EXAMPLE sh
2023-01-21 14:53:55 -08:00
cargo test
2023-05-28 15:14:15 -07:00
#+END_EXAMPLE
2023-01-21 14:53:55 -08:00
2023-05-28 15:14:15 -07:00
Userlib tests can be triggered by loading the userlib as well as its test suite directly from a ~cargo run~ invocation:
#+BEGIN_EXAMPLE sh
cargo run snippets/userlib.rls snippets/userlib-tests.rls
#+END_EXAMPLE
2023-01-21 14:53:55 -08:00
2023-03-17 11:42:36 -07:00
* The codebase
2023-05-25 15:00:14 -07:00
** The [[file:tests][tests directory]]
2023-01-21 14:53:55 -08:00
Start here if you are new.
2023-05-25 15:00:14 -07:00
*** [[file:tests/test_eval.rs][Eval tests]]
2023-01-21 14:53:55 -08:00
These are particularly easy to read and write tests.
2023-05-25 15:00:14 -07:00
They primarily cover execution paths in the evaluation process.
*** [[file:tests/test_func.rs][Func tests]]
These tests extend the eval tests to cover the co-recursive nature between eval and func calls.
*** [[file:tests/test_lex.rs][Lex tests]]
2023-01-21 14:53:55 -08:00
These tests verify the handling of syntax.
*** Lib tests: (tests/test_lib*)
2023-03-17 11:42:36 -07:00
These tests are unique per stdlib module and work to prove the functionality of builtin functions in the language.
2023-05-25 15:00:14 -07:00
** [[file:src][Source directory]]
2023-01-21 14:53:55 -08:00
This directory contains all of the user facing code in relish.
Just a few entries of note:
2023-05-25 15:00:14 -07:00
*** [[file:src/segment.rs][Segment module]]
2023-03-17 11:42:36 -07:00
This file lays out the data structures that the interpreter operates on.
Representation of code trees, traversals, and type annotations all live here.
2023-05-28 15:14:15 -07:00
It provides the core representation of data used in Relish, and could provide supplementary refrence material for users seeking a deeper understanding of how their code is stored in memory.
2023-05-25 15:00:14 -07:00
*** [[file:src/lib.rs][lib.rs]]
2023-01-21 14:53:55 -08:00
This defines a library that can be included to provide an interpreter interface within any Rust project.
2023-05-28 15:14:15 -07:00
The components defined here can certainly be used to support language development for other LISP (or non LISP) langauges. An external project may use or not use any number of these components.
2023-05-25 15:00:14 -07:00
*** [[file:src/sym.rs][Symbol module]]
2023-03-17 11:42:36 -07:00
This file contains all code related to symbol expansion and function calling.
The types defined in this file include SymTable, Args, Symbol, and more.
2023-05-25 15:00:14 -07:00
Code to call Lambda functions also exists in here.
*** [[file:src/run.rs][Run module]]
This file contains functions which load and run the configuration file script.
2023-03-01 13:27:47 -08:00
For more information see the configuraiton section above in this Readme.
2023-05-25 15:00:14 -07:00
*** [[file:src/stl.rs][Standard library module]]
2023-03-01 13:27:47 -08:00
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.
2023-05-28 15:14:15 -07:00
The ~dynamic_stdlib~ function loads all symbols in the standard library which *do* need configuration into the symbol table.
2023-03-01 13:27:47 -08:00
The ~dynamic_stdlib~ function uses variables saved in the symbol table to configure the functions and variables it loads.
2023-05-28 15:14:15 -07:00
This module also contains definitions for the default configuration values.
2023-03-17 11:42:36 -07:00
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 stdlib functions).
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 lighter subet of what it is.
2023-05-25 15:00:14 -07:00
You can view the code for standard library functions in [[file:src/stl/ ][the standard library directory ]].
*** [[file:src/bin/][binary directory]]
This contains any executable target of this project. Notably [[file:src/bin/relish.rs ][the main shell ]].
2023-01-27 17:45:19 -08:00
* Current Status / TODO list
2023-03-02 13:49:16 -08:00
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.
2023-05-28 15:14:15 -07:00
** DONE Alpha Release
(See tag: v0.2.0)
** DONE Beta tasks
(See tag: v0.3.0)
2023-04-17 22:11:49 -07:00
** TODO v1.0 tasks
2023-05-25 17:17:45 -07:00
- islist type query
- Can pass args to relish scripts (via interpreter)
- Can pass args to relish scripts (via command line)
- File operations
- read-to-string
- write-to-file
- file exists?
- (path functions)
- (add this all to the readme)
- finish basic goals in the [[file:snippets/interactive-devel.rls ][interactive development library ]]
- Release CI
2023-03-31 11:53:04 -07:00
- Rename to Flesh
2023-05-16 11:01:42 -07:00
- Make an icon if you feel like it
2023-05-25 17:17:45 -07:00
- Post release to relevant channels
2023-05-28 15:14:15 -07:00
** TODO v1.1 tasks
2023-05-25 15:00:14 -07:00
- finish stretch goals in the [[file:snippets/interactive-devel.rls ][interactive development library ]]
2023-05-25 17:17:45 -07:00
- Stl boolean assert builtin
- History length configurable (env var?)
- Lex function
- Read function (Input + Lex)
2023-04-17 22:11:49 -07:00
- execute configurable function on cd
2023-03-17 23:58:59 -07:00
- Post to relevant channels
- Implement Compose for lambdas
2023-05-18 06:53:23 +00:00
(add to readme)
2023-03-17 23:58:59 -07:00
- color control library
2023-05-18 06:53:23 +00:00
- probably more escapes in the lexer
2023-05-25 17:17:45 -07:00
- a snippet with a bunch of color constants
2023-05-18 06:53:23 +00:00
- Search delim configurable
2023-04-17 22:11:49 -07:00
** TODO v1.2 release tasks
2023-05-18 06:53:23 +00:00
- Emacs syntax highlighting and/or LSP implementation
- Bindings for the simplest possible UI library?
2023-05-25 17:17:45 -07:00
- Scheme compatibility layer?
- Get on that bug tracker
2023-03-17 23:58:59 -07:00
- Network library
- HTTP Client
- TCP Stream client
- UDP Client
- TCP Listener
- HTTP Listener
- UDP Listener
2023-05-23 22:06:11 +00:00
* Special thanks
2023-05-25 15:00:14 -07:00
Special thanks to [[https://nul.srht.site/ ]['Underscore Nul' ]] for consulting with me in the early stages of this project. Meeting my goal of only using safe rust (with the exception of the posix module) would have been a much bigger challenge if not for having someone to experiment on design ideas with.