This repository contains a Haskell parser and compiler for the FishCode esoteric programming language (esolang).
FishCode is a turing complete esolang, named as such since programs written in FishCode consists of "fish". FishCode was originally invented by None1 on the EsoLangs wiki, where the corresponding wiki page for FishCode can also be found.
Note that this project utilizes cabal; run cabal build to build the project, then to run a FishCode program enter cabal run and paste in the file-path to the FishCode program (which is simply a .txt file)
FishCode programs consist of one or more lines, each line containing exactly one "fish" of the form
<{COMMANDS}><
- A FishCode program begins from the first line (fish).
- In each fish, operations/commands are carried out sequentially (LtR).
- Control flow to different fishes is controlled by jump commands. FishCode DOES NOT automatically go through fishes.
- If we ever reach the end of any fish without jumping to another, the program will terminate.
Comments are additionally possible; adding ><*>: {COMMENT} (or alternatively π {COMMENT}) in an empty line is valid. Note that comments cannot be made on the same line as a fish. Also, the first line MUST be a fish.
FishCode programs have access to the following stores of memory:
- Two byte-stacks (that is, stacks which hold bytes), which are initially empty
- One byte-register, which is initially set to 0
Overflows and underflows apply to the stored values to keep them in the range
As per the EsoLang wiki specification, FishCode offers the following commands; here
| Command | Meaning |
|---|---|
| + | Increment register |
| - | Decrement register |
| , | Read a character and store it in the register |
| . | Print register as ASCII |
| : | Read register as decimal |
| ; | Print register as decimal |
| ? | Pushes the value of register into the current stack |
| ! | Pops from the current stack and store it into register |
| ~ | Switch current stack |
| (A) | If the register is zero, jump to line A |
| [A] | If the register isn't zero, jump to line A |
| {A} | Jump to line A no matter what |
| ((x)) | Set the register to the value of x (a number) |
| (((x))) | Subtract the value of register by x |
Note that in jumping, fishes are 0-indexed beginning from the top. For example the below fishes are indexed as follows:
FISH 0 | <...><
FISH 1 | <...><
LINE 2 | ><*>: Comment line
LINE 3 |
FISH 4 | <...><
... | ...
The below program (found under the example-programs folder) will take in two integers as input and output their sum:
<:?~:?{3}><
><*>: the above line will take two nums as input
><*>: this will add the two nums
<!(5)-?~!+?~{3}><
π this will output the sum
<~!;><
Haskell is a purely functional programming language which makes it highly applicable in parsers, combinators and related work. This repository serves not only as an exercise in utilizing the power of Applicative parsing, but also as an appreciation for the Haskell/Functional programming lectures given by Dr Jamie Willis and Dr Nick Wu at Imperial College London. I would also like to thank my good friend (https://github.com/jeffkiddo) for joining me in this first look into esolangs.
