327 lines
6.7 KiB
C
327 lines
6.7 KiB
C
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
|
|
#include "bytecode.h"
|
|
#include "format.h"
|
|
#include "io.h"
|
|
|
|
#define ELF_HEADER_SIZE 0xb0
|
|
|
|
|
|
// a + (b + (c + d))
|
|
// (a + b) + (c + d)
|
|
// (b + a) + (c + d)
|
|
// b + (a + (c + d))
|
|
//
|
|
|
|
void transition_right(void) {
|
|
assocl_plus();
|
|
mapl_plus_begin();
|
|
out();
|
|
inr();
|
|
mapl_plus_end();
|
|
assocr_plus();
|
|
}
|
|
|
|
void transition_left(void) {
|
|
out();
|
|
inl();
|
|
}
|
|
|
|
void jump_from_to(size_t from, size_t to) {
|
|
if (from < to) {
|
|
mapl_plus_begin();
|
|
inl();
|
|
for(; from <= to; to--) {
|
|
inr();
|
|
}
|
|
mapl_plus_end();
|
|
mapr_plus_begin();
|
|
inr();
|
|
mapr_plus_end();
|
|
out();
|
|
} else if (to > from) {
|
|
for (size_t i = 0; i < from - to; i++) {
|
|
mapr_plus_end();
|
|
mapl_plus_begin();
|
|
inl();
|
|
mapl_plus_end();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void transition_into(void) {
|
|
assocl_plus();
|
|
mapl_plus_begin();
|
|
mapl_plus_begin();
|
|
inl();
|
|
mapl_plus_end();
|
|
out();
|
|
inr();
|
|
mapl_plus_end();
|
|
assocr_plus();
|
|
}
|
|
|
|
void transition_while(void) {
|
|
assocl_plus();
|
|
mapl_plus_begin();
|
|
mapr_plus_begin();
|
|
inr();
|
|
mapr_plus_end();
|
|
out();
|
|
mapl_plus_end();
|
|
assocr_plus();
|
|
}
|
|
|
|
void inc(void) {
|
|
inr();
|
|
factl();
|
|
}
|
|
|
|
void new_nat(void) {
|
|
// ctx
|
|
unitil(); // ctx * 1
|
|
inl(); // ctx * 1 + ctx * 1
|
|
factl(); // ctx * (1 + 1)
|
|
}
|
|
|
|
void swap(void) {
|
|
assocr();
|
|
mapr_begin();
|
|
comm();
|
|
mapr_end();
|
|
assocl();
|
|
}
|
|
|
|
static void select_var(size_t var) {
|
|
// (... * a) * (b * (c * ...))
|
|
for (size_t i = 0; i < var; i++) {
|
|
assocr();
|
|
// ((... * a) * b) * (c * ...)
|
|
}
|
|
comm();
|
|
// (c * ...) * ((... * a) * b)
|
|
assocl();
|
|
// ((c * ...) * (... * a)) * b
|
|
}
|
|
|
|
static void unselect_var(size_t var) {
|
|
assocr();
|
|
comm();
|
|
for (size_t i = 0; i < var; i++) {
|
|
assocl();
|
|
}
|
|
}
|
|
|
|
static void case_on(size_t var) {
|
|
select_var(var);
|
|
distr();
|
|
mapl_plus_begin(); {
|
|
unselect_var(var);
|
|
} mapl_plus_end();
|
|
mapr_plus_begin(); {
|
|
unselect_var(var);
|
|
} mapr_plus_end();
|
|
}
|
|
|
|
static void snipe(size_t var) {
|
|
select_var(var);
|
|
unitel();
|
|
comm();
|
|
for (size_t i = 0; i < var; i++) {
|
|
assocl();
|
|
}
|
|
}
|
|
|
|
symbol compile(void) {
|
|
symbol entry_point = init_bytecode();
|
|
|
|
// This is the program we're trying to execute:
|
|
//
|
|
// fib n = fib_acc n 0 1
|
|
// fib_acc 0 a b = a
|
|
// fib_acc (S n) a b = fib_acc n b (a + b)
|
|
//
|
|
// Looks simple, right? Well, things are a bit more complicated than that.
|
|
//
|
|
// 1. In `fib_acc 0`, we implicitly drop the value of `b`. Because we do not have
|
|
// weakening, we will have to free `b` explicitly here.
|
|
//
|
|
// fib_acc 0 a 0 = a
|
|
// fib_acc 0 a (S b) = fib_acc 0 a b
|
|
//
|
|
// 2. In `fib_acc (S n)`, we use `b` twice. We do not have contraction, so we must
|
|
// explicitly duplicate it, or implicitly duplicate it when we consume `b`.
|
|
//
|
|
// 3. We do not have addition as a built-in; we will need to define it ourselves.
|
|
// Moreover, we do not have functions, so it must be fused into the definition
|
|
// of fib_acc.
|
|
//
|
|
// -- We will duplicate `b` into the first argument (the new `a`)
|
|
// -- while adding it to the second argument (`a`, which will become the new `b`).
|
|
// fib_acc (S n) a b = fib_acc_plus n 0 a b
|
|
// fib_acc_plus n a b' 0 = fib_acc n a b'
|
|
// fib_acc_plus n a b' (S b) = fib_acc_plus n (S a) (S b') b
|
|
//
|
|
// 4. We'll have to do a lot of tedious work shuffling variables around.
|
|
// We don't even have implicit associativity, much less commutativity!
|
|
//
|
|
// We have this hierarchy of states:
|
|
//
|
|
// 1. start(1)
|
|
// 2. fib(n)
|
|
// 3. fib_acc(n, a, b)
|
|
// 4. fib_acc(0, a, b)
|
|
// 5. fib_acc_0(a b)
|
|
//
|
|
|
|
// States:
|
|
// * start(1)
|
|
// * fib(n)
|
|
// * fib_acc(n, a, b)
|
|
// * fib_acc_Z(1, (a, b))
|
|
// * fib_acc_Z_free(a, b)
|
|
// * fib_acc_Z_done
|
|
// * fib_acc_S
|
|
// * fib_acc_S_copy
|
|
// * fib_acc_S_copy_done
|
|
// * fib_acc_S_copy_S
|
|
|
|
// State 0: starting state
|
|
mapl_plus_begin();
|
|
// Initialize with integer (5).
|
|
inl();
|
|
inr();
|
|
inr();
|
|
inr();
|
|
inr();
|
|
inr();
|
|
mapl_plus_end();
|
|
transition_right();
|
|
|
|
mapr_plus_begin();
|
|
// State 1: fib(n);
|
|
mapl_plus_begin();
|
|
// a = 0
|
|
new_nat();
|
|
// b = 1
|
|
new_nat();
|
|
inc();
|
|
mapl_plus_end();
|
|
transition_right();
|
|
|
|
mapr_plus_begin();
|
|
// State 2: fib_acc(n, a, b)
|
|
mapl_plus_begin();
|
|
// if n=1, we return the accumulated value
|
|
assocr();
|
|
distl();
|
|
mapl_plus_end();
|
|
transition_right();
|
|
|
|
mapr_plus_begin();
|
|
mapl_plus_begin();
|
|
// State 3.1.1: fib_acc_Z(1, (a, b))
|
|
mapl_plus_begin();
|
|
uniter();
|
|
// (a, b)
|
|
mapl_plus_end();
|
|
transition_into();
|
|
|
|
mapr_plus_begin();
|
|
// State 3.1.2.1: fib_acc_Z_free(a, b)
|
|
mapl_plus_begin();
|
|
// n * (1 + n)
|
|
distr();
|
|
mapl_plus_end();
|
|
transition_while();
|
|
|
|
// State 3.1.2.2: fib_acc_Z_done
|
|
mapr_plus_begin();
|
|
uniter();
|
|
quit();
|
|
mapr_plus_end();
|
|
mapr_plus_end();
|
|
mapl_plus_end();
|
|
|
|
mapr_plus_begin();
|
|
// State 4: fib_acc_S
|
|
mapl_plus_begin();
|
|
assocl();
|
|
new_nat();
|
|
swap();
|
|
new_nat();
|
|
swap();
|
|
mapl_plus_end();
|
|
transition_into();
|
|
|
|
mapr_plus_begin();
|
|
mapl_plus_begin();
|
|
// State 5.1: fib_acc_S_copy(n, a, b1, b2, b)
|
|
mapl_plus_begin();
|
|
distl();
|
|
mapl_plus_end();
|
|
transition_into();
|
|
mapr_plus_begin();
|
|
mapl_plus_begin();
|
|
// State 5.2.1: fib_acc_S_copy_done(n, a, b, b, 1)
|
|
uniter();
|
|
// TODO:
|
|
mapl_plus_end();
|
|
mapr_plus_begin();
|
|
// State 5.2.2: fib_acc_S_copy_S(n, a, b1, b2, b)
|
|
mapr_plus_end();
|
|
mapr_plus_end();
|
|
mapl_plus_end();
|
|
|
|
mapr_plus_end();
|
|
mapr_plus_end();
|
|
mapr_plus_end();
|
|
mapr_plus_end();
|
|
mapr_plus_end();
|
|
|
|
|
|
// State 1: fib(n)
|
|
assocl_plus();
|
|
mapl_plus_begin();
|
|
|
|
// switch to state 2
|
|
out();
|
|
inr();
|
|
mapl_plus_end();
|
|
assocr_plus();
|
|
|
|
mapr_plus_begin();
|
|
// State 2: fib_acc(n, a, b)
|
|
mapl_plus_begin();
|
|
|
|
|
|
// State 2.1: transition to state 3
|
|
mapl_plus_begin();
|
|
|
|
|
|
mapr_plus_end();
|
|
mapr_plus_end();
|
|
|
|
finish_bytecode();
|
|
return entry_point;
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
if (argc != 3) {
|
|
fprintf(stderr, "usage: %s <output file> <source file>\n", argv[0]);
|
|
exit(1);
|
|
}
|
|
open_files(argv[2], argv[1]);
|
|
|
|
elf_executable();
|
|
symbol entry_point = compile();
|
|
finish_executable(entry_point);
|
|
|
|
close_files();
|
|
return 0;
|
|
}
|