-
- #include <alloca.h>
- #include <assert.h>
- #include <stdarg.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <ffi.h>
-
- void rt_3addiii(int *res, int a, int b)
- {
- *res = a + b;
- }
-
- void rt_3subiii(int *res, int a, int b)
- {
- *res = a - b;
- }
-
- void rt_2eqbii(bool *res, int a, int b)
- {
- *res = a == b;
- }
-
- void rt_2if(bool test, ...)
- {
- va_list args;
- va_start(args, test);
-
- if (!test)
- {
- int num_skip = va_arg(args, int);
-
- for (int i = 0; i < num_skip; i++)
- {
- (void) va_arg(args, ffi_type*);
- (void) va_arg(args, void*);
- }
- va_arg(args, void(*)());
- }
-
- int num_args = va_arg(args, int);
-
- ffi_cif cif;
- ffi_arg ret;
- ffi_type **types = alloca(sizeof(ffi_type*) * num_args);
- void **values = alloca(sizeof(void(*)()) * num_args);
-
- for (int i = 0; i < num_args; i++)
- {
- types[i] = va_arg(args, ffi_type*);
- values[i] = va_arg(args, void*);
- }
- void (*fun)() = va_arg(args, void*);
-
- ffi_status result = ffi_prep_cif(&cif, FFI_DEFAULT_ABI, num_args, &ffi_type_void, types);
- assert(result == FFI_OK);
- ffi_call(&cif, fun, &ret, values);
- }
-
- int zero = 0;
- int one = 1;
-
- void ack(int *res, int m, int n);
-
- void ack_ret2(int *res, int m)
- {
- int temp;
- rt_3subiii(&temp, m, one);
- ack(res, temp, one);
- }
-
- void ack_rest2(int *res, int m, int n)
- {
- int temp1, temp2, temp3;
- rt_3subiii(&temp1, n, one);
- ack(&temp2, m, temp1);
- rt_3subiii(&temp3, m, one);
- ack(res, temp3, temp2);
- }
-
- void ack_ret1(int *res, int n)
- {
- rt_3addiii(res, n, one);
- }
-
- void ack_rest1(int *res, int m, int n)
- {
- bool temp;
- rt_2eqbii(&temp, n, zero);
- rt_2if(temp,
- 2, &ffi_type_pointer, &res, &ffi_type_sint32, &m, &ack_ret2,
- 3, &ffi_type_pointer, &res, &ffi_type_sint32, &m, &ffi_type_sint32, &n, &ack_rest2
- );
- }
-
- void ack(int *res, int m, int n)
- {
- bool temp;
- rt_2eqbii(&temp, m, zero);
- rt_2if(temp,
- 2, &ffi_type_pointer, &res, &ffi_type_sint32, &n, &ack_ret1,
- 3, &ffi_type_pointer, &res, &ffi_type_sint32, &m, &ffi_type_sint32, &n, &ack_rest1
- );
- }
-
- int wrap_ack(int m, int n)
- {
- int res;
- ack(&res, m, n);
- return res;
- }
-
- int main(int argc, const char *argv[])
- {
- for (int i = 0; i < 10; ++i)
- {
- printf("ack(3, 7) = %i\n", wrap_ack(3, 7));
- }
- }
-