Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions 109.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# In this model, Grammar cuts thought complexity

It eliminates hidden control flow and incidental state coupling.

Literally, grammar cuts code into two sides:

* **A side** - file (110.c).
* **B side** - choice-machine side (my side).

A and B sides will interact with each other when we splice them together by running
the c-machine with the starting symbol of our grammar.

Then the c-machine will call axiomatic blocks defined by the grammar, according to grammar rules.

> Grammar dictates execution control flow; the c-machine obeys.

So when we receive execution control flow in one of the axiomatic blocks / Steps defined in 110.c,
we have everything.
We know exactly where we are in the parsing process, just like in recursive
descent you are doing, but now we know the same information without doing parsing.

It is done by the c-machine with executable grammar units, so we can do whatever we want:
build an AST, or directly interpret the language. Who needs an AST when we have a more powerful structure, grammar.

In essence, the incidental state coupling and complexity that we have in recursive descent get sucked
into the B-side, and executable grammar rules are visible and modifiable units.

We can even pause grammar execution by saving / pushing execution context.

All of this is possible by having a cyclic dependency between aStep and bStep with the choice machine (cm).

All Steps, both sides, including grammar rule units, share the following execution context:

```c
#define N(argo) void argo(int* o, int b, int a, int t, int s, int d)
#define S(argo) static N(argo)
```

Step is just a function with fixed parameters/context.
They are tail-call optimized, i.e. they are pure continuations and
do not use the call stack or do invisible side effects.

Interaction is possible by calling continuation Steps.
When the c-machine forwards control flow to an axiomatic block in 110.c, it
defines continuations we need to call at some point. Remember: we can pause, hence “at some point”.

```c
enum color_names { Red, Yellow, Green };
S(Red ) { t = o[d + Red + 0], d = o[t + 4 + 0], (o[t + 5 + 0] + cm)(o, b, a, t, s, d); }
S(Green ) { t = o[d + Green + 0], d = o[t + 4 + 0], (o[t + 5 + 0] + cm)(o, b, a, t, s, d); }
S(Yellow) { t = o[d + Yellow + 0], d = o[t + 4 + 0], (o[t + 5 + 0] + cm)(o, b, a, t, s, d); }
```

* `Red` - do not continue parsing the current grammar rule; i.e. treat this position in the grammar rule as the end.
This is useful to stop left-recursive growth. It is necessary to deal with the `dangling else` problem.
See how the `if` statement is defined in 110.c as a left-recursive rule with `Red` continuation.
* `Green` - continue parsing.
* `Yellow` - go back in time (backtrack) and try the next choice.

117 changes: 117 additions & 0 deletions 110.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include"step.h"
#include"programmer.h"

S(id_) { }
S(comma_) {}
N(sd_Green);

S(parameters);


D(parameters, 2, id_, 1, A)D(A,
3, parameters, 2, comma_, 2, id_, 1, parameters)
//
S(op_) {}
S(cp_) {}
S(block);
S(sa_opt) {} // syntax action: on(backtrack) -> skipt to next text member
S(sa_pbt) {} // syntax action: pop backtrack stack

D(function, 2, id_, 2, op_, 1, A)D(A,
2, sa_opt, 3, parameters, 2, sa_pbt, 1, A)D(A,
2, cp_, 3, block, 1, function)

S(func_) {}
D(funDecl, 2, func_, 3, function, 1, funDecl)

S(expression);
S(number_) {}
S(string_) {}
S(true_) {}
S(false_) {}
D(primary, 2, true_, 1, A)D(A,
2, false_, 1, A)D(A,
2, number_, 1, A)D(A,
2, string_, 1, A)D(A,
2, id_, 1, A)D(A,
2, op_, 3, expression, 2, cp_, 1, primary)

D(arguments, 3, expression, 1, A)D(A,
3, arguments, 2, comma_, 3, expression, 1, arguments)
S(excl_) {}
S(minus_) {}
D(unary, 2, excl_, 3, unary, 1, A)D(A,
2, minus_, 3, unary, 1, A)D(A,
2, id_, 2, op_, 2, sa_opt, 3, arguments, 2, sa_pbt, 2, cp_, 1, unary)
S(star_) {}
S(slash_) {}
D(factor, 3, unary, 1, A)D(A,
3, factor, 2, star_, 3, unary, 1, A)D(A,
3, factor, 2, slash_, 3, unary, 1, factor)
S(plus_) {}
D(term, 3, factor, 1, A)D(A,
3, term, 2, plus_, 3, factor, 1, A)D(A,
3, term, 2, minus_, 3, factor, 1, term)
S(lt_) {}
S(gt_) {}
S(le_) {}
S(ge_) {}
D(comparison, 3, term, 1, A)D(A,
3, comparison, 2, lt_, 3, term, 1, A)D(A,
3, comparison, 2, gt_, 3, term, 1, A)D(A,
3, comparison, 2, le_, 3, term, 1, A)D(A,
3, comparison, 2, ge_, 3, term, 1, comparison)
S(eqq_) {}
S(ne_) {}
D(equality, 3, comparison, 1, A)D(A,
3, equality, 2, eqq_, 3, comparison, 1, A)D(A,
3, equality, 2, ne_, 3, comparison, 1, equality)
S(and_) {}
D(logic_and, 3, equality, 1, A)D(A,
3, logic_and, 2, and_, 3, equality, 1, logic_and);
S(or_) {}
D(logic_or, 3, logic_and, 1, A)D(A,
3, logic_or, 2, or_, 3, logic_and, 1, logic_or)
S(eq_) {}
D(assignment, 2, id_, 2, eq_, 3, assignment, 1, A)D(A,
3, logic_or, 1, assignment)
D(expression, 3, assignment, 1, expression)

S(let_) {}
S(semicol_) {}
D(varDecl, 2, let_, 2, id_, 2, eq_, 3, expression, 2, semicol_, 1, varDecl)
D(exprStmt, 3, expression, 2, semicol_, 1, exprStmt);
S(for_) {}
S(in_) {}
S(dot_) {}
S(statement);
D(forStmt, 2, for_, 2, id_, 2, in_, 2, number_, 2, dot_, 2, number_, 3, statement, 1, forStmt)
S(if_) {}
S(else_) {}
S(sa_not) {} /*syntactic action to tell cmachine this is the end of left recursive growth*/
D(ifStmt, 2, if_, 2, op_, 3, expression, 2, cp_, 3, statement, 1, A)D(A,
3, ifStmt, 2, else_, 3, statement, 2, sa_not, 1, ifStmt)
S(print_) {}
D(printStmt, 2, print_, 3, expression, 2, semicol_, 1, printStmt)
S(return_) {}
D(returnStmt, 2, return_, 3, expression, 2, semicol_, 1, returnStmt)
S(while_) {}
D(whileStmt, 2, while_, 2, op_, 3, expression, 2, cp_, 3, statement, 1, whileStmt)
S(declarations);
S(ocb_) {}
S(ccb_) {}
D(block, 2, ocb_, 3, declarations, 2, ccb_, 1, block)
D(statement, 3, exprStmt, 1, A)D(A,
3, forStmt, 1, A)D(A,
3, ifStmt, 1, A)D(A,
3, printStmt, 1, A)D(A,
3, returnStmt,1, A)D(A,
3, whileStmt, 1, A)D(A,
3, block, 1, statement);
D(declaration, 3, funDecl, 1, A)D(A,
3, varDecl, 1, A)D(A,
3, statement, 1, declaration)
D(declarations, 3, declaration, 1, A)D(A,
3, declarations, 3, declaration, 1, declarations)
S(zero_) {}
D(splice, 3, declarations, 2, zero_, 1, splice)
30 changes: 30 additions & 0 deletions programmer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once
#define A PROGRAMMER_CONCAT(id, __LINE__)
#define D(Tail, ...) S(Tail); PROGRAMMER(Tail, __VA_ARGS__)
#define PROGRAMMER(Tail, ...) PROGRAMMER_DISPATCH(PROGRAMMER_NARG(__VA_ARGS__), Tail, __VA_ARGS__)
#define PROGRAMMER_DISPATCH(n, Tail, ...) PROGRAMMER_DISPATCH_(n, Tail, __VA_ARGS__)
#define PROGRAMMER_DISPATCH_(n, Tail, ...) PROGRAMMER_##n(Tail, __VA_ARGS__)

#define PROGRAMMER_2(Tail, v1, v2) S(v2) { o[a++] = v1, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_4(Tail, v1, v2, v3, v4) S(v4) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_6(Tail, v1, v2, v3, v4, v5, v6) S(v6) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_8(Tail, v1, v2, v3, v4, v5, v6, v7, v8) S(v8) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_10(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) S(v10) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_12(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) S(v12) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = v10 - cm, o[a++] = v11, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_14(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) S(v14) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = v10 - cm, o[a++] = v11, o[a++] = v12 - cm, o[a++] = v13, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_16(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) S(v16) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = v10 - cm, o[a++] = v11, o[a++] = v12 - cm, o[a++] = v13, o[a++] = v14 - cm, o[a++] = v15, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_18(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) S(v18) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = v10 - cm, o[a++] = v11, o[a++] = v12 - cm, o[a++] = v13, o[a++] = v14 - cm, o[a++] = v15, o[a++] = v16 - cm, o[a++] = v17, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_20(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) S(v20) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = v10 - cm, o[a++] = v11, o[a++] = v12 - cm, o[a++] = v13, o[a++] = v14 - cm, o[a++] = v15, o[a++] = v16 - cm, o[a++] = v17, o[a++] = v18 - cm, o[a++] = v19, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_22(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) S(v22) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = v10 - cm, o[a++] = v11, o[a++] = v12 - cm, o[a++] = v13, o[a++] = v14 - cm, o[a++] = v15, o[a++] = v16 - cm, o[a++] = v17, o[a++] = v18 - cm, o[a++] = v19, o[a++] = v20 - cm, o[a++] = v21, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_24(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) S(v24) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = v10 - cm, o[a++] = v11, o[a++] = v12 - cm, o[a++] = v13, o[a++] = v14 - cm, o[a++] = v15, o[a++] = v16 - cm, o[a++] = v17, o[a++] = v18 - cm, o[a++] = v19, o[a++] = v20 - cm, o[a++] = v21, o[a++] = v22 - cm, o[a++] = v23, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_26(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) S(v26) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = v10 - cm, o[a++] = v11, o[a++] = v12 - cm, o[a++] = v13, o[a++] = v14 - cm, o[a++] = v15, o[a++] = v16 - cm, o[a++] = v17, o[a++] = v18 - cm, o[a++] = v19, o[a++] = v20 - cm, o[a++] = v21, o[a++] = v22 - cm, o[a++] = v23, o[a++] = v24 - cm, o[a++] = v25, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_28(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) S(v28) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = v10 - cm, o[a++] = v11, o[a++] = v12 - cm, o[a++] = v13, o[a++] = v14 - cm, o[a++] = v15, o[a++] = v16 - cm, o[a++] = v17, o[a++] = v18 - cm, o[a++] = v19, o[a++] = v20 - cm, o[a++] = v21, o[a++] = v22 - cm, o[a++] = v23, o[a++] = v24 - cm, o[a++] = v25, o[a++] = v26 - cm, o[a++] = v27, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_30(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) S(v30) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = v10 - cm, o[a++] = v11, o[a++] = v12 - cm, o[a++] = v13, o[a++] = v14 - cm, o[a++] = v15, o[a++] = v16 - cm, o[a++] = v17, o[a++] = v18 - cm, o[a++] = v19, o[a++] = v20 - cm, o[a++] = v21, o[a++] = v22 - cm, o[a++] = v23, o[a++] = v24 - cm, o[a++] = v25, o[a++] = v26 - cm, o[a++] = v27, o[a++] = v28 - cm, o[a++] = v29, o[a++] = Tail - cm, (o[s] + cm)(C); }
#define PROGRAMMER_32(Tail, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) S(v32) { o[a++] = v1, o[a++] = v2 - cm, o[a++] = v3, o[a++] = v4 - cm, o[a++] = v5, o[a++] = v6 - cm, o[a++] = v7, o[a++] = v8 - cm, o[a++] = v9, o[a++] = v10 - cm, o[a++] = v11, o[a++] = v12 - cm, o[a++] = v13, o[a++] = v14 - cm, o[a++] = v15, o[a++] = v16 - cm, o[a++] = v17, o[a++] = v18 - cm, o[a++] = v19, o[a++] = v20 - cm, o[a++] = v21, o[a++] = v22 - cm, o[a++] = v23, o[a++] = v24 - cm, o[a++] = v25, o[a++] = v26 - cm, o[a++] = v27, o[a++] = v28 - cm, o[a++] = v29, o[a++] = v30 - cm, o[a++] = v31, o[a++] = Tail - cm, (o[s] + cm)(C); }

#define PROGRAMMER_NARG(...) PROGRAMMER_NARG_(__VA_ARGS__, PROGRAMMER_RSEQ_N())
#define PROGRAMMER_NARG_(...) PROGRAMMER_ARG_N(__VA_ARGS__)
#define PROGRAMMER_ARG_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,N,...) N
#define PROGRAMMER_RSEQ_N() 32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
#define PROGRAMMER_CONCAT_IMPL(x, y) x##y
#define PROGRAMMER_CONCAT(x, y) PROGRAMMER_CONCAT_IMPL(x, y)
156 changes: 156 additions & 0 deletions step.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#pragma once
#define N(argo) void argo(int*o, int b, int a, int t, int s, int d)
#define S(argo) static N(argo)
#define C o, b, a, t, s, d
#define Step(a, b, n, s, d) N(a##b##_##n) { t = o[b s n s d], b = o[t s 4 s d], (o[t s 5 s d] + cm)(C); }
N(cm);
#define Q0(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = a, \
o[a s 1 s d] = o[b s 1 s d], \
o[a s 2 s d] = o[b s 2 s d], \
o[a s 3 s d] = o[b s 3 s d], \
o[a s 4 s d] = b, \
b = a
#define Q1(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = o[b s 0 s d], \
o[a s 1 s d] = a, \
o[a s 2 s d] = o[b s 2 s d], \
o[a s 3 s d] = o[b s 3 s d], \
o[a s 4 s d] = b, \
b = a
#define Q01(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = a, \
o[a s 1 s d] = a, \
o[a s 2 s d] = o[b s 2 s d], \
o[a s 3 s d] = o[b s 3 s d], \
o[a s 4 s d] = b, \
b = a
#define Q2(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = o[b s 0 s d], \
o[a s 1 s d] = o[b s 1 s d], \
o[a s 2 s d] = a, \
o[a s 3 s d] = o[b s 3 s d], \
o[a s 4 s d] = b, \
b = a
#define Q02(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = a, \
o[a s 1 s d] = o[b s 1 s d], \
o[a s 2 s d] = a, \
o[a s 3 s d] = o[b s 3 s d], \
o[a s 4 s d] = b, \
b = a
#define Q12(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = o[b s 0 s d], \
o[a s 1 s d] = a, \
o[a s 2 s d] = a, \
o[a s 3 s d] = o[b s 3 s d], \
o[a s 4 s d] = b, \
b = a
#define Q012(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = a, \
o[a s 1 s d] = a, \
o[a s 2 s d] = a, \
o[a s 3 s d] = o[b s 3 s d], \
o[a s 4 s d] = b, \
b = a
#define Q3(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = o[b s 0 s d], \
o[a s 1 s d] = o[b s 1 s d], \
o[a s 2 s d] = o[b s 2 s d], \
o[a s 3 s d] = a, \
o[a s 4 s d] = b, \
b = a
#define Q03(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = a, \
o[a s 1 s d] = o[b s 1 s d], \
o[a s 2 s d] = o[b s 2 s d], \
o[a s 3 s d] = a, \
o[a s 4 s d] = b, \
b = a
#define Q13(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = o[b s 0 s d], \
o[a s 1 s d] = a, \
o[a s 2 s d] = o[b s 2 s d], \
o[a s 3 s d] = a, \
o[a s 4 s d] = b, \
b = a
#define Q013(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = a, \
o[a s 1 s d] = a, \
o[a s 2 s d] = o[b s 2 s d], \
o[a s 3 s d] = a, \
o[a s 4 s d] = b, \
b = a
#define Q23(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = o[b s 0 s d], \
o[a s 1 s d] = o[b s 1 s d], \
o[a s 2 s d] = a, \
o[a s 3 s d] = a, \
o[a s 4 s d] = b, \
b = a
#define Q023(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = a, \
o[a s 1 s d] = o[b s 1 s d], \
o[a s 2 s d] = a, \
o[a s 3 s d] = a, \
o[a s 4 s d] = b, \
b = a
#define Q123(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = o[b s 0 s d], \
o[a s 1 s d] = a, \
o[a s 2 s d] = a, \
o[a s 3 s d] = a, \
o[a s 4 s d] = b, \
b = a
#define Q0123(a, b, s, d) \
a = a s - 5, \
o[a s 0 s d] = a, \
o[a s 1 s d] = a, \
o[a s 2 s d] = a, \
o[a s 3 s d] = a, \
o[a s 4 s d] = b, \
b = a
#define AB_Red(step) o[a++] = step - cm, Q0(a, b, -, 1)
#define AB_Yellow(step) o[a++] = step - cm, Q1(a, b, -, 1)
#define AB_Red_Yellow(step) o[a++] = step - cm, Q01(a, b, -, 1)
#define AB_Green(step) o[a++] = step - cm, Q2(a, b, -, 1)
#define AB_Red_Green(step) o[a++] = step - cm, Q02(a, b, -, 1)
#define AB_Yellow_Green(step) o[a++] = step - cm, Q12(a, b, -, 1)
#define AB_Red_Yellow_Green(step) o[a++] = step - cm, Q012(a, b, -, 1)
#define AB_Blue(step) o[a++] = step - cm, Q3(a, b, -, 1)
#define AB_Red_Blue(step) o[a++] = step - cm, Q03(a, b, -, 1)
#define AB_Yellow_Blue(step) o[a++] = step - cm, Q13(a, b, -, 1)
#define AB_Red_Yellow_Blue(step) o[a++] = step - cm, Q013(a, b, -, 1)
#define AB_Green_Blue(step) o[a++] = step - cm, Q23(a, b, -, 1)
#define AB_Red_Green_Blue(step) o[a++] = step - cm, Q023(a, b, -, 1)
#define AB_Yellow_Green_Blue(step) o[a++] = step - cm, Q123(a, b, -, 1)
#define AB_Red_Yellow_Green_Blue(step) o[a++] = step - cm, Q0123(a, b, -, 1)
#define SD_Red(step) o[--s] = step - cm, Q0(s, d, +, 0)
#define SD_Yellow(step) o[--s] = step - cm, Q1(s, d, +, 0)
#define SD_Red_Yellow(step) o[--s] = step - cm, Q01(s, d, +, 0)
#define SD_Green(step) o[--s] = step - cm, Q2(s, d, +, 0)
#define SD_Red_Green(step) o[--s] = step - cm, Q02(s, d, +, 0)
#define SD_Yellow_Green(step) o[--s] = step - cm, Q12(s, d, +, 0)
#define SD_Red_Yellow_Green(step) o[--s] = step - cm, Q012(s, d, +, 0)
#define SD_Blue(step) o[--s] = step - cm, Q3(s, d, +, 0)
#define SD_Red_Blue(step) o[--s] = step - cm, Q03(s, d, +, 0)
#define SD_Yellow_Blue(step) o[--s] = step - cm, Q13(s, d, +, 0)
#define SD_Red_Yellow_Blue(step) o[--s] = step - cm, Q013(s, d, +, 0)
#define SD_Green_Blue(step) o[--s] = step - cm, Q23(s, d, +, 0)
#define SD_Red_Green_Blue(step) o[--s] = step - cm, Q023(s, d, +, 0)
#define SD_Yellow_Green_Blue(step) o[--s] = step - cm, Q123(s, d, +, 0)
#define SD_Red_Yellow_Green_Blue(step) o[--s] = step - cm, Q0123(s, d, +, 0)