Skip to content
Open
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
67 changes: 45 additions & 22 deletions cloak.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,24 @@
#ifndef CLOAK_GUARD_H
#define CLOAK_GUARD_H

/* fix bug: In Visual Stido, __VA_ARGS__ is treated as a separate parameter */
#define FIX_VS_BUG(x) x

/* catenate */
#define PRIMITIVE_CAT(a, ...) FIX_VS_BUG(a ## __VA_ARGS__)
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__

/* unary complement (bit inversion) */
#define COMPL(b) PRIMITIVE_CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0

/* BITAND(x)(y) => x & y */
#define BITAND(x) PRIMITIVE_CAT(BITAND_, x)
#define BITAND_0(y) 0
#define BITAND_1(y) y

/* increase */
#define INC(x) PRIMITIVE_CAT(INC_, x)
#define INC_0 1
#define INC_1 2
Expand All @@ -30,7 +37,9 @@
#define INC_7 8
#define INC_8 9
#define INC_9 9
/* ... */

/* decrease */
#define DEC(x) PRIMITIVE_CAT(DEC_, x)
#define DEC_0 0
#define DEC_1 0
Expand All @@ -42,79 +51,93 @@
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8
/* ... */

/* run the 2nd param */
#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
#define CHECK(...) FIX_VS_BUG(CHECK_N(__VA_ARGS__, 0,))
#define PROBE(x) x, 1,

#define IS_PAREN(x) CHECK(IS_PAREN_PROBE x)
/* PROBE(~) => ~, 1, */
#define IS_PAREN_PROBE(...) PROBE(~)
/* IS_PAREN(xxx) => 0 */
/* IS_PAREN((xxx)) => 1 */
#define IS_PAREN(x) CHECK(IS_PAREN_PROBE x)

#define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x))
#define NOT_0 PROBE(~)

#define COMPL(b) PRIMITIVE_CAT(COMPL_, b)
#define COMPL_0 1
#define COMPL_1 0

#define BOOL(x) COMPL(NOT(x))

#define IIF(c) PRIMITIVE_CAT(IIF_, c)
/* run the 2nd param */
#define IIF_0(t, ...) __VA_ARGS__
/* run the 1st param */
#define IIF_1(t, ...) t

#define IF(c) IIF(BOOL(c))

#define EAT(...)
#define EXPAND(...) __VA_ARGS__
/* WHEN(0)(...) => EXPAND(...) => ... */
/* WHEN(1)(...) => EAT(...) => *nothing* */
#define WHEN(c) IF(c)(EXPAND, EAT)

#define EMPTY()
#define DEFER(id) id EMPTY()
#define OBSTRUCT(id) id DEFER(EMPTY)()

/* evaluate? */
#define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
#define EVAL5(...) __VA_ARGS__

/* EVAL(REPEAT(3, A, B)) => A(0, B) A(1, B) A(2, B) */
#define REPEAT(count, macro, ...) \
WHEN(count) \
( \
OBSTRUCT(REPEAT_INDIRECT) () \
( \
WHEN(count) ( \
OBSTRUCT(REPEAT_INDIRECT) () ( \
DEC(count), macro, __VA_ARGS__ \
) \
OBSTRUCT(macro) \
( \
OBSTRUCT(macro) ( \
DEC(count), __VA_ARGS__ \
) \
)
#define REPEAT_INDIRECT() REPEAT

/*
EVAL(WHILE(A, B, C)) =>
while (A(C)) {
C = B(C).args[0];
// DARK MAGIC ~
}
return args;
*/
#define WHILE(pred, op, ...) \
IF(pred(__VA_ARGS__)) \
( \
OBSTRUCT(WHILE_INDIRECT) () \
( \
IF(pred(__VA_ARGS__)) ( \
OBSTRUCT(WHILE_INDIRECT) () ( \
pred, op, op(__VA_ARGS__) \
), \
__VA_ARGS__ \
)
#define WHILE_INDIRECT() WHILE

#define PRIMITIVE_COMPARE(x, y) IS_PAREN \
( \
COMPARE_ ## x ( COMPARE_ ## y) (()) \
/*
#define COMPARE_foo(x) x
#define COMPARE_bar(x) x
PRIMITIVE_COMPARE(foo, bar) // Expands to 1
PRIMITIVE_COMPARE(foo, foo) // Expands to 0
*/
#define PRIMITIVE_COMPARE(x, y) IS_PAREN ( \
COMPARE_ ## x ( COMPARE_ ## y) (()) \
)

#define IS_COMPARABLE(x) IS_PAREN( CAT(COMPARE_, x) (()) )

#define NOT_EQUAL(x, y) \
IIF(BITAND(IS_COMPARABLE(x))(IS_COMPARABLE(y)) ) \
( \
IIF(BITAND(IS_COMPARABLE(x))(IS_COMPARABLE(y))) ( \
PRIMITIVE_COMPARE, \
1 EAT \
)(x, y)
Expand Down