Skip to content

Instantly share code, notes, and snippets.

@josephcsible
Last active June 16, 2020 21:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josephcsible/b02b78a9249b20fbe60a8f65e29d5553 to your computer and use it in GitHub Desktop.
Save josephcsible/b02b78a9249b20fbe60a8f65e29d5553 to your computer and use it in GitHub Desktop.
Combinatory logic with C, using raw function pointers as closures
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <sys/mman.h>
typedef void *(*f)(void *);
f make_function_with_state(f code, size_t code_len, void *state, size_t state_len) {
f mem = mmap(NULL, code_len + state_len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
memcpy(mem, code, code_len);
memcpy(mem + code_len, state, state_len);
mprotect(mem, code_len + state_len, PROT_READ|PROT_EXEC);
return mem;
}
extern void *single_var_helper(void *);
extern const size_t single_var_helper_len;
__asm__(
"single_var_helper:\n"
"endbr64\n"
"mov %rdi,%rsi\n"
"mov single_var_helper_len(%rip), %rdi\n"
"jmp *single_var_helper_len+8(%rip)\n"
"single_var_helper_len:\n"
".8byte .-single_var_helper"
);
extern void *double_var_helper(void *);
extern const size_t double_var_helper_len;
__asm__(
"double_var_helper:\n"
"endbr64\n"
"mov %rdi,%rdx\n"
"mov double_var_helper_len(%rip), %rdi\n"
"mov double_var_helper_len+8(%rip), %rsi\n"
"jmp *double_var_helper_len+16(%rip)\n"
"double_var_helper_len:\n"
".8byte .-double_var_helper"
);
void *B_inner(void *x, void *y, void *z) {
void *yz = ((f)y)(z);
return ((f)x)(yz);
}
void *B_middle(void *x, void *y) {
void *state[] = {x, y, B_inner};
return make_function_with_state(double_var_helper, double_var_helper_len, state, sizeof(state));
}
void *B(void *x) {
void *state[] = {x, B_middle};
return make_function_with_state(single_var_helper, single_var_helper_len, state, sizeof(state));
}
void *C_inner(void *x, void *y, void *z) {
void *xz = ((f)x)(z);
return ((f)xz)(y);
}
void *C_middle(void *x, void *y) {
void *state[] = {x, y, C_inner};
return make_function_with_state(double_var_helper, double_var_helper_len, state, sizeof(state));
}
void *C(void *x) {
void *state[] = {x, C_middle};
return make_function_with_state(single_var_helper, single_var_helper_len, state, sizeof(state));
}
void *K_inner(void *x, void *y) {
return x;
}
void *K(void *x) {
void *state[] = {x, K_inner};
return make_function_with_state(single_var_helper, single_var_helper_len, state, sizeof(state));
}
void *I(void *x) {
return x;
}
void *S_inner(void *x, void *y, void *z) {
void *xz = ((f)x)(z);
void *yz = ((f)y)(z);
return ((f)xz)(yz);
}
void *S_middle(void *x, void *y) {
void *state[] = {x, y, S_inner};
return make_function_with_state(double_var_helper, double_var_helper_len, state, sizeof(state));
}
void *S(void *x) {
void *state[] = {x, S_middle};
return make_function_with_state(single_var_helper, single_var_helper_len, state, sizeof(state));
}
void *W_inner(void *x, void *y) {
f xy = ((f)x)(y);
return xy(y);
}
void *W(void *x) {
void *state[] = {x, W_inner};
return make_function_with_state(single_var_helper, single_var_helper_len, state, sizeof(state));
}
void *inc(void *x) {
return (void *)(1 + (uintptr_t)x);
}
uintptr_t church_to_int(f church) {
f church_inc = church(inc);
return (uintptr_t)church_inc(0);
}
static f zero, succ;
f int_to_church(uintptr_t i) {
f n = zero;
while(i--) {
n = succ(n);
}
return n;
}
int main(void) {
f BS = B(S);
f BB = B(B);
f plus = BS(BB);
f BW = B(W);
f BBC = BB(C);
f B_BW = B(BW);
f S_alt = B_BW(BBC);
f BS_alt = B(S_alt);
f plus_alt = BS_alt(BB);
f mult = B;
f exp = C(I);
zero = K(I);
f one = I;
succ = plus(one);
f two = succ(one);
f three = succ(two);
f four = int_to_church(4);
f add_three = plus(three);
f three_plus_four = add_three(four);
f add_three_alt = plus_alt(three);
f three_plus_four_alt = add_three_alt(four);
f three_of = mult(three);
f three_times_four = three_of(four);
f three_to = exp(three);
f three_fourth = three_to(four);
printf("3+4 is %" PRIuPTR "\n", church_to_int(three_plus_four));
printf("3+4 a different way is %" PRIuPTR "\n", church_to_int(three_plus_four_alt));
printf("3*4 is %" PRIuPTR "\n", church_to_int(three_times_four));
printf("3^4 is %" PRIuPTR "\n", church_to_int(three_fourth));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment