tree-traversing LISP interpreter geared toward embeddability and system scripting
Find a file
Ava Affine 74f73fb493 Move File module and tests to the shell project
Signed-off-by: Ava Affine <ava@sunnypup.io>
2024-07-12 21:07:04 -07:00
.cargo Big project dir refactor 2024-07-12 13:45:09 -07:00
core Move File module and tests to the shell project 2024-07-12 21:07:04 -07:00
shell Move File module and tests to the shell project 2024-07-12 21:07:04 -07:00
snippets Big project dir refactor 2024-07-12 13:45:09 -07:00
.gitignore ignore Cargo.lock 2021-10-17 23:12:22 -07:00
.gitlab-ci.yml Big project dir refactor 2024-07-12 13:45:09 -07:00
Cargo.toml Big project dir refactor 2024-07-12 13:45:09 -07:00
LICENSE.md - syntax tree datatypes 2021-01-24 12:34:58 -08:00
logo.png add logo 2024-02-21 11:48:55 -08:00
Readme.org Big project dir refactor 2024-07-12 13:45:09 -07:00
Shell.org Big project dir refactor 2024-07-12 13:45:09 -07:00
Writing.org add join function to stdlib 2024-06-01 09:20:05 -07:00

Flesh: Flexible Shell

Note: this document is best read using a dedicated ORG mode editor

Purpose statement

The purpose of Flesh is to create a highly portable, easy to integrate language that can be used in many environments.

Goals

  • Iterate on the ideas and designs that were tested with SHS
  • Create a usable POSIX shell
  • Create usable applications/scripts
  • To have quality code coverage
  • 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 Flesh without any of the unsafe code involved by removing the POSIX module. See the Compilation section for more details.

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

Contact

Matrix chat: #relish:matrix.sunnypup.io

If you like Flesh and want to support me in working on it consider donating: Ava's Ko-Fi.

Documentation

Writing in Flesh

Users who are new to Flesh, or who are seeking documentation on how to effectively write in Flesh should reference the main language documentation. This will go over the following:

  • How Flesh operates under the hood
  • Flesh syntax
  • Flesh control flow constructs
  • Stdlib functions
  • Builting documentation
  • Common patterns in using Flesh

Using Flesh as your shell

As of version 0.3.0 Flesh implements all the features of an interactive shell. See further documentation in the shell documentation. This material goes over the following:

  • How to start and view jobs in Flesh
  • 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

By default Flesh will read from ~/.fleshrc for configuration, but the default shell will also accept a filename from the FLESH_CFG_FILE environment variable. See the minimal shell configuration example for an example of a basic configuration file. Other snippets, including mood-prompt and avas-laptop-prompt demonstrate more complex configurations.

The configuration file

The configuration file is a script containing arbitrary Flesh code. On start, any shell which leverages the configuration code in the config module (run.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_FLESH_POSIX (default true): when true, enables POSIX style job control and shell features.
  • CFG_FLESH_ENV (default true): when true, interpreter's variable table and environment variable table are kept in sync.
  • CFG_FLESH_L_PROMPT (default 'λ'): a function that is called with no arguments to output the left hand of the prompt
  • CFG_FLESH_R_PROMPT (default ''): a function that is called with no arguments to output the right hand of the prompt
  • CFG_FLESH_PROMPT_DELIMITER (default '>'): a function that is called with no arguments to output the delimiter separating prompt from user input
  • CFG_FLESH_CD_CB (default None): optional function / lambda that is called with no arguments on every change of CD. See The Shell Documentation for more information.

Prompt design

For an example of prompt design see the mood prompt For a more complex example see Ava's laptop prompt

Further configuration

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.

  (call "my-extra-library-functions.f")

Syntax Highlighting

Syntax Highlighting is implemented for Emacs under the Flesh Mode module (snippets/flesh-mode.el). For installation, consider adding the following to your \~/.emacs:

  (load-file "/PATH/TO/flesh/snippets/flesh-mode.el")

Compilation

Compiling Flesh is as simple as kicking off a build with Cargo.

  cargo build -p flesh-shell

This will produce a binary at target/debug/flesh which includes all of the features flesh 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:

  cargo build -p flesh-shell --no-default-features

In order to run Flesh it is recommended to run the resulting binary at target/debug/flesh.

Testing

Flesh 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:

  cargo test

Userlib tests can be triggered by loading the userlib as well as its test suite directly from a cargo run invocation:

  cargo run snippets/userlib.f snippets/userlib-tests.f

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.

DONE Alpha Release

(See tag: v0.2.0)

DONE Beta tasks

(See tag: v0.3.0)

TODO v1.0 tasks

  • Pipe also operates on stderr
  • fix let var -> env var bug
  • lexer/parser shorthand sugar for quote and eval
  • quote/eval based macro procedures

    • constexpr equivalent
    • const var equivalent
  • finish the interactive development library
  • core code is nostd compatible?
  • cut down all extra clones of code tree branches

TODO v1.1 tasks

  • memoize builtin
  • def marks user defined functions / lambdas as pure/impure
  • optimize routine implemented

    • precomputes pure code branches
    • memoizes pure functions
  • def should call optimize routine on any function or lambda definition
  • interactive development library calls optimize routine
  • Can pass args to flesh scripts (via command line)
  • Can pass args to flesh scripts (via interpreter)
  • all autocomplete is done via configurable userfunction, default documented with 1:1 functionality
  • better emacs language mode
  • Post to relevant channels

TODO v1.2 release tasks

  • History length configurable (env var?)
  • Search delim configurable
  • Implement Compose for lambdas (add to readme)
  • color control library

    • probably more escapes in the lexer
    • a snippet with a bunch of color constants
  • Bindings for the simplest possible UI library?
  • Scheme compatibility layer?
  • Get on that bug tracker
  • Network library

    • HTTP Client
    • TCP Stream client
    • UDP Client
    • TCP Listener
    • HTTP Listener
    • UDP Listener

Special thanks

Special thanks to '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.