Skip to content

A scripting language to make Hidey-Chess compliant with Greenspun's tenth rule

License

Notifications You must be signed in to change notification settings

oitzujoey/duck-lisp

Repository files navigation

duck-lisp

A simple scripting language for Hidey-Chess and similar projects.

Duck-lisp is your typical hobby lisp with one or two twists. I started this project before I knew what lisp was, choosing the syntax solely for parsability, so variable declaration has a bit of a JavaScript-like feel. Macros are also a little weird since the language is split into separate runtime and compile-time environments. Parentheses are optional.

Features

  • Optional free-form parenthesis inference that is mostly backwards compatible with S-expressions
  • Optional compile-time arity checks (part of parenthesis inference)
  • First class functions and lexical scope
  • Common Lisp-like macros
  • UTF-8 compatible
  • C FFI
  • Split compiler and VM
  • Compilation with the C standard library is optional
  • Tested on x64 (Linux) and ARM (Linux)
  • A simplified VM has been used on an ATmega328P, and the full VM runs on an LPC1769.
  • C99 minimum

Planned features

  • Independent of OS

Quirks

  • Functions created by defun and defmacro are lexically scoped.
  • Built-in keywords can be overridden using var, defun and defmacro.
  • Variables are declared as they are in C-like languages. There is no let.
  • Parenthesis inference does not work well with lisp auto-formatters.
  • Not quite a lisp-2.
  • Recursion is performed using they keyword self.

Misfeatures

  • Error reporting is horrible. It will likely stay this way.
  • There are no debug features other than a disassembler.
  • Macros are unhygienic due to the inability of closures to be passed from the compilation VM to the runtime VM. Thus the lisp-2.

Examples

Building

git clone https://github.com/oitzujoey/duck-lisp
cd duck-lisp/scratchwork
mkdir build && cd build
cmake ..
cmake --build .

You can generally ignore compile flags, but they are here in case you want them:

To enable parenthesis inference and compile-time arity checks, configure the project with cmake .. -DUSE_PARENTHESIS_INFERENCE=ON instead of cmake ...
To build with shared libraries, set -DBUILD_SHARED_LIBS=ON as with the option above.
To use DuckLib's memory allocator instead of the system's, set -DUSE_DUCKLIB_MALLOC=ON. DuckLib's allocator is sluggish.
Duck-lisp may be used without the standard library if necessary. Use the option USE_STDLIB=OFF. This will result in decreased performance.
Advanced options: The settings NO_OPTIMIZE_JUMPS=ON and NO_OPTIMIZE_PUSHPOPS=ON disable peephole optimizations. I suggest ignoring these variables.
If you need maximum performance out of the compiler, then USE_DATALOGGING=ON might be helpful. duckLisp-dev is setup to print the data collected when this flag is enabled.

For maximum performance, I suggest using -DUSE_DUCKLIB_MALLOC=OFF -DUSE_STDLIB=ON -DNO_OPTIMIZE_JUMPS=OFF -DNO_OPTIMIZE_PUSHPOPS=OFF. This is the default.
For maximum portability, I suggest using -DUSE_DUCKLIB_MALLOC=ON -DUSE_STDLIB=OFF.

Examples and other junk can be found in the scratchwork directory.

Running

# Run duck-lisp language tests.
./duckLisp-test ../../tests
# Run the duck-lisp program "factorial.dl".
./duckLisp-dev ../scripts/factorial.dl
# Run a script with arguments.
./duckLisp-dev "(include \"../scripts/underout.dl\") (main 52)"
# Start the REPL.
./duckLisp-dev

Index

"docs/language.md" contains a brief description of the language.
"docs/language-reference.md" contains a description of all duck-lisp keywords.
"docs/api.md" contains the C API documentation. (incomplete)

"duckLisp.h" contains everything needed for normal usage of the compiler.
"parser.h" contains declarations for the reader.
"emitters.h" contains declarations for emitters for all special forms.
"generators.h" contains declarations for generators for all special forms.
"duckVM.h" contains everything needed usage of the VM.

"duckLisp.c" contains the main compiler functions.
"parser.c" contains the reader.
"parenthesis-inferrer.c" contains the parenthesis inferrer and arity checker.
"emitters.c" contains the emitters (functions that produce "high-level assembly").
"generators.c" contains the generators (functions that convert AST forms to "high-level assembly" by calling emitters).
"assembler.c" contains the assembler for the "high-level assembly" generated by the compiler.
"compiler-debug.c" contains a single 7500 line function that disassembles bytecode.
"duckVM.c" contains the VM.

Typical usage of the language only requires including "duckLisp.h" and "duckVM.h". Adding new user-defined generators that generate bytecode requires "emitters.h". Some user-defined generators may want to call existing generators, which are declared in "generators.h". Function declarations for the reader can be found in "parser.h".

Examples on how to extend the language can be found in scratchwork/duckLisp-dev.c.

Contact

https://matrix.to/#/#duck-lisp-space:matrix.org

About

A scripting language to make Hidey-Chess compliant with Greenspun's tenth rule

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages