[A draft for https://codegolf.stackexchange.com/questions/204891/build-a-turing-incomplete-language]Build a Turing *incomplete* language]
#define a() X b()
#define b() X a()
#define a() X b()
#define b() X a()
$M($M(f, f(args)))
$M(f, f(f(args)))
f, f(f(f(args)))
$M($M(f, f(args)))
$M(f, f(f(args)))
f, f(f(f(args)))
Then, use the previous macro $P
to evaluate $M
$n$ times on f, args...
, and it's possible to get f
applied on args...
$n$ times.
At the moment, it's possible to use $P
to implement the multiplication function:
#define mul_1(x,y) x y, y
#define mul(x,y) $P(x,mul_1, ,y)
In this example, mul_1
is repeatedly applied on the argument (<empty>, y)
$x$ times. For each application, mul_1
transforms (accumulator, y)
to (accumulator+y, y)
; therefore after $x$ iterations the result is (x*y, y)
.
Let's say, you want to implement a function that uses $P
based on another function that uses $P
.
#define add(x,y) x y
#define pre_1(x,y) y,y()
#define pre(x) $P(x,pre_1,,) // <-- this function uses `$P`
#define sub(x,y) $P(y,pre,x) // <-- this function uses `pre`
// similar to the implementation of subtraction using pair in lambda calculus
// returns x-y if x>=y, 0 otherwise.
// (terribly inefficient.)
This will immediately raises a problem -- the inner $P
is not expanded.
Which makes sense, because the inner $P
is created during the expansion of the outer $P
.
There's a trivial workaround for that problem, however -- define a function $P2
with the same definition as $P
(and its helper functions)
This restriction makes sense, because cpp
is not Turing-complete and it should not be possible for two functions to call each other.
Some example functions
With these tools, it should not be too hard to build some simple functions. Ideas from lambda calculus should be useful here.
#define equ(x,y) sub((),sub(x,y) sub(y,x))
// return 1 == () if x and y are equal, 0 == <empty> otherwise.
#define modz_1(result, x, y, value) result equ(x, i), x, y, y value
// modz_1(result, x, y, value) = (result + [x == value], x, y, value + y)
// x and y are the dividend and the divisor.
// value iterates through the first x positive multiples of y,
// and check if any of them are equal to x.
#define modz(x,y) $P3(x,modz_1,,x,y,y)
// returns 1 if x is a multiple of y, 0 otherwise.
// apply modz_1 on (0, x, y, y) x times, then return the first value of the result.