pass-lang/src/main.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;
}