#include <stdio.h>
#include <stdarg.h>
typedef struct LAMBDA {
struct LAMBDA *(*fn)(struct LAMBDA *, ...);
} *lambda_t;
// -------- True/False ---------
lambda_t l_true_fn(lambda_t x, ...) {
return x;
}
static const lambda_t L_TRUE = &(struct LAMBDA) { .fn = l_true_fn };
lambda_t l_false_fn(lambda_t x, ...) {
va_list argp;
va_start(argp, x);
lambda_t y = va_arg(argp, lambda_t);
va_end(argp);
return y;
}
static const lambda_t L_FALSE = &(struct LAMBDA) { .fn = l_false_fn };
// -------- Boolean Algebra --------
lambda_t l_not_fn(lambda_t b, ...) {
return b->fn(L_FALSE, L_TRUE);
}
static const lambda_t L_NOT = &(struct LAMBDA) { .fn = l_not_fn };
lambda_t l_and_fn(lambda_t b1, ...) {
va_list argp;
va_start(argp, b1);
lambda_t b2 = va_arg(argp, lambda_t);
va_end(argp);
return b1->fn(b2, L_FALSE);
}
static const lambda_t L_AND = &(struct LAMBDA) { .fn = l_and_fn };
lambda_t l_or_fn(lambda_t b1, ...) {
va_list argp;
va_start(argp, b1);
lambda_t b2 = va_arg(argp, lambda_t);
va_end(argp);
return b1->fn(L_TRUE, b2);
}
static const lambda_t L_OR = &(struct LAMBDA) { .fn = l_or_fn };
// -------- Church Numerals --------
static const lambda_t L_ZERO = &(struct LAMBDA) { .fn = l_false_fn };
lambda_t l_succ_fn(lambda_t n, ...) {
va_list argp;
va_start(argp, n);
lambda_t f = va_arg(argp, lambda_t);
lambda_t x = va_arg(argp, lambda_t);
va_end(argp);
return f->fn(n->fn(f, x));
}
// Initialize SUC
lambda_t L_SUCC = &(struct LAMBDA) { .fn = l_succ_fn };
int main() {
// Test bools
printf("TRUE = %p, FALSE = %p\n", L_TRUE, L_FALSE);
const lambda_t not_true = L_NOT->fn(L_TRUE);
const lambda_t not_false = L_NOT->fn(L_FALSE);
printf("!TRUE = %p, !FALSE = %p\n", not_true, not_false);
const lambda_t false_a_false = L_AND->fn(L_FALSE, L_FALSE);
const lambda_t false_a_true = L_AND->fn(L_FALSE, L_TRUE);
const lambda_t true_a_false = L_AND->fn(L_TRUE, L_FALSE);
const lambda_t true_a_true = L_AND->fn(L_TRUE, L_TRUE);
printf(
"FALSE & FALSE = %p\nFALSE & TRUE = %p\nTRUE & FALSE = %p\nTRUE & TRUE = %p\n",
false_a_false, false_a_true, true_a_false, true_a_true
);
const lambda_t false_o_false = L_OR->fn(L_FALSE, L_FALSE);
const lambda_t false_o_true = L_OR->fn(L_FALSE, L_TRUE);
const lambda_t true_o_false = L_OR->fn(L_TRUE, L_FALSE);
const lambda_t true_o_true = L_OR->fn(L_TRUE, L_TRUE);
printf(
"FALSE | FALSE = %p\nFALSE | TRUE = %p\nTRUE | FALSE = %p\nTRUE | TRUE = %p\n",
false_o_false, false_o_true, true_o_false, true_o_true
);
// Test numerals
printf("0 = %p, s(x) = %p\n", L_ZERO, L_SUCC);
const lambda_t one = L_SUCC->fn(L_ZERO, L_TRUE);
printf("1 = %p\n", one);
const lambda_t two = L_SUCC->fn(one, L_TRUE);
return 0;
}