This is the challenge 30 from the Coding Challenges by John Crickett https://codingchallenges.fyi/challenges/challenge-lisp.
this solution implement a Lisp interpreter in Java:
- full tokenizer and parser based on clisp standard
- implemented interpreter using a stack with all variable possiblities
- implemented 34 (!!!) built-ins and easy to implement new ones
- many testcases to validate parser
- implemented a cache for pure functions to speed up execution (e.g. fact, fib, ...) if recursion algorithms are heavily used
- implemented multi-dimensional arrays
Open Intellij or any other IDE with gradle support. run "installDist"
Run test cases using gradle "test" command. checkout many test files for scanner, parser, runtime, builtin-tests, etc
I am using picocli to parse arguments
./lisp.sh -h
Usage: lisp [-hV] [-c=<command>] [-f=<fileName>]
This challenge is to build Your Own Lisp Interpreter
-c=<command> -c specifies the command executed
-f=<fileName> -f specifies a file name to load
-h, --help Show this help message and exit.
-V, --version Print version information and exit.
./repl.sh
clisp>> (+ 42 43)
85
clisp>>
this will load a file and execute it and run a command based on the same runtime.
./lisp.sh -f=app/src/test/resources/tests.step5/final.step.lisp -c="(fib 42)"
Load from file app/src/test/resources/tests.step5/final.step.lisp
Hello Coding Challenge World
The double of 5 is 10
Factorial of 5 is 120
The 7th number of the Fibonacci sequence is 13
The 42th number of the Fibonacci sequence is 267914296
The 100th number of the Fibonacci sequence is 2147483647
267914296
if you dont pass a command, you will end up in the REPL console
./lisp.sh -f=app/src/test/resources/tests.step5/final.step.lisp
Load from file app/src/test/resources/tests.step5/final.step.lisp
Hello Coding Challenge World
The double of 5 is 10
Factorial of 5 is 120
The 7th number of the Fibonacci sequence is 13
The 42th number of the Fibonacci sequence is 267914296
The 100th number of the Fibonacci sequence is 2147483647
clisp>> (fib 101)
2147483647
clisp>>
I have implemented a pure function as a built-in to be able to cash results. The two defined examples from John fib and fact had been implemented in the recursive way and for large numbers, it will kill your machine.
The idea behind the caching of a pure function is that the pure function only uses information via its parameters. This means we could cache the result with same parameters.
run this first in interactive mode:
(defun fib (n)
(if (< n 2)
n
(+ (fib (- n 1))
(fib (- n 2)))))
try without pure : kills your PC
(fib 100)
or with plugin. The plugin is embedded in the run time interpreter to return cached results with same parameters
(pure fib)
(fib 100)
- I wanted to implement a Neuronal network with forward and backward propagation. Lisp code from ChatGPT + adaptations
- I have implemented many built-ins for this, but still not really working.
- multidimensional are supported but not while using the tokenizer: #2A((1 2)(2 2))
It was awesome to implement a Lisp interpreter. These days nobody knows anymore what is Lisp. I will continue to fix the NN example and will proceed implementing built-ins
I was using https://rextester.com/l/common_lisp_online_compiler to test the real functionality.
ChatGPT is cool to generate TEST case (valid and invalid ones). PLEASE do not use it to generate the code - this you need to practice yourself