An interpreter for a C-inspired Functional Machine Calculus (FMC) variant which has first-class locations. This forms part of my dissertation project at the University of Bath which aims to investigate first-class locations in the FMC.
Program which pushes (prints) 0
to the output stream.
write = (<@a> . <x> . a[x])
print = ([#out] . write)
main = ([0] . print)
The function print
is defined in terms of a more general variant called write
which parameterizes a location to write to and a term to write with.
Define function LinkedList
to build a linked-list and define function push_back
to push elements to its tail.
LinkedList = (
<v> . new<@p> . [#null]p . [v]p . [#p]
)
push_back = (
<v> . <@p> . p<pv> . p<@pp> . [#pp] . (
null -> [v] . LinkedList . <@npp> . [#npp]p . [pv]p,
otherwise -> [#pp]p . [pv]p . [#pp] . [v] . push_back
)
)
Define function traverse
for traversing the list in order and running a function f
on each element.
traverse = (
<f> . <@p> . p<pv> . p<@pp> . [#pp]p . [pv]p . [#pp] . (
null -> [pv] . f,
otherwise -> [pv] . f . [#pp] . [f] . traverse
)
)
Create a linked-list called p
by calling LinkedList
, then add elements by calling push_back
, then print each element by calling traverse
with the function print
.
print = (
<x> . [x]out
)
main = (
[1] . LinkedList . <@p>
. [#p] . [2] . push_back
. [#p] . [3] . push_back
. [#p] . [4] . push_back
. [#p] . [5] . push_back
. [#p] . [print] . traverse
)
Define functions nil
and cons
to build a list and define functions head
and tail
to access the head and tail of the list, respectively.
nil = (<_> . <x> . [x])
cons = (<h> . <t> . <f> . <x> . [t] . [h] . f)
head = (<l> . [nil] . [<h> . <_> . h] . l)
tail = (<l> . [nil] . [<_> . <t> . t] . l)
Define function map
for lazily mapping the list to a new one which has f
applied to each element.
map = (<f> . <l> . [nil] . [<h> . <t> . [[[t] . [f] . map] . [[h] . f] . cons]] . l)
Create a list by building it with cons
, then map it with double
to double each element.
double = (<x> . [x] . [x] . +)
main = (
[[[[nil] . [3] . cons] . [2] . cons] . [1] . cons] . [double] . map . print
)
The program must take a file (containing the program source) or program source directly (but not both). These are given with the options --file path
or --source src
.
Usage: cfmc [--help] [--debug] [--file path | --source src]
For example, running the program in fibonacci.fmc
would look like.
cfmc --file fibonacci.fmc
For example, running the program main = ([in<x> . [x]out] . <echo> . echo)
would look like.
cfmc --source 'main = ([in<x> . [x]out] . <echo> . echo)'
You can optionally specify --debug
to display the state of the stack after running the machine.
Execute the included shell script build.sh
to compile the program. This will generate the binary cfmc
in the directory build/
.
Execute the included batch script build.bat
to compile the program. This will generate the binary cfmc.exe
in the directory build/
. It will work if executed from the VS Developer Command Prompt. Alternatively, just use WSL !