#include <stdio.h>
#define DEBUG_CPP
-#define STR(x) #x
+#define STR(...) #__VA_ARGS__
// print the macro and the evaluation of the macro
#define SHOW(expr) printf("%s -> %s\n", #expr, STR(expr))
#define SEMICOLON ;
#define ZERO 0
-#define ONE 1
+#define ONE 1
+
+#define FALSE 0
+#define TRUE 1
//---------
/*===========================================================================
-Logic
+Existence
===========================================================================*/
//----------------------------------------
#define NOT_EQ(x_item ,y_item) \
NOT_MATCH_RWR( CAT4(_RWR_EQ__ ,x_item ,__oo__ ,y_item) )
-#if 0
-
-
-
/*===========================================================================
IF-ELSE construct.
Usage: IF_ELSE(condition)(<true case>)(<false case>)
The seemingly extra layer prevents BOOL_(condition) from being pasted with a ## which, if done, would prevent it from being evaluated. Recall, the first step in evaluation is a literal copy in of the arguments. ===symbol ========================================================================*/
- #define _IF_ELSE(condition) CAT2(_IF_ ,BOOL(condition))
+ #define IF_ELSE(condition) CAT2(_IF_ ,BOOL(condition))
#define _IF_1(...) __VA_ARGS__ _IF_1_ELSE
#define _IF_0(...) _IF_0_ELSE
#define _IF_1_ELSE(...)
#define _IF_0_ELSE(...) __VA_ARGS__
-
/*===========================================================================
Access
- see below the recursion section for Nth .. when it is written ;-)
+ see ext_1 with recursion for `Nth`
===========================================================================*/
// _FIRST defined in the logic section
#define FIRST(pad ,...)\
- If_ELSE \
+ IF_ELSE \
( NOT_EXISTS(__VA_ARGS__) ) \
(pad) \
( _FIRST(__VA_ARGS__) )
#define _REST(a ,...) __VA_ARGS__
#define REST(...)\
- If_ELSE \
+ IF_ELSE \
( NOT_EXISTS(__VA_ARGS__) ) \
() \
( _REST(__VA_ARGS__) )
// _SECOND defined in the logic section
#define SECOND(pad ,...) \
- If_ELSE \
+ IF_ELSE \
( NOT_EXISTS(__VA_ARGS__) ) \
(pad) \
( _SECOND(__VA_ARGS__ ,pad) )
#define _THIRD(a ,b ,c ,...) c
#define THIRD(pad ,...) \
- If_ELSE \
+ IF_ELSE \
( NOT_EXISTS(__VA_ARGS__) ) \
(pad) \
( _THIRD(__VA_ARGS__ ,pad, pad) )
-#endif
-
#endif
//---------------------------------------------------------------------------
SHOW(IF_ELSE(1)(yes)(no));
-#if 0
SHOW(IF_ELSE(0)(yes)(no)); // → no
+ printf("\n");
//---------------------------------------------------------------------------
// Symbolic identifiers
SHOW(IF_ELSE(TRUE)(ok)(fail)); // → ok
SHOW(IF_ELSE(FALSE)(ok)(fail)); // → fail
SHOW(IF_ELSE(foo)(alpha)(omega)); // → omega (foo is undefined)
+ printf("\n");
//---------------------------------------------------------------------------
// Logic expressions
SHOW(IF_ELSE(AND(1 ,1))(pass)(fail)); // → pass
SHOW(IF_ELSE(OR(0 ,0))(yes)(no)); // → no
SHOW(IF_ELSE(NOT(0))(on)(off)); // → on
+ printf("\n");
//---------------------------------------------------------------------------
// Code-like output
//---------------------------------------------------------------------------
SHOW(IF_ELSE(1)(int x = 1;)(int x = 2;)); // → int x = 1;
SHOW(IF_ELSE(0)(int x = 1;)(int x = 2;)); // → int x = 2;
+ printf("\n");
//---------------------------------------------------------------------------
// Comma usage in true/false branches
//---------------------------------------------------------------------------
SHOW(IF_ELSE(1)(a ,b ,c)(x ,y ,z)); // → a ,b ,c
SHOW(IF_ELSE(0)(a ,b ,c)(x ,y ,z)); // → x ,y ,z
+ printf("\n");
//---------------------------------------------------------------------------
// Empty condition
//---------------------------------------------------------------------------
SHOW(IF_ELSE()(true)(false)); // → false (BOOL() = 0)
+ printf("\n");
//---------------------------------------------------------------------------
// Nested IF_ELSE
outer_false
)
); // → inner_false
+ printf("\n");
-#endif
return 0;
}
--- /dev/null
+#include "cpp_ext_0.c"
+
+int main(void){
+
+ //---------------------------------------------------------------------------
+ // FIRST
+ //---------------------------------------------------------------------------
+
+ SHOW(FIRST(foo)); // → foo (only pad, no args)
+ SHOW(FIRST(foo ,a)); // → a
+ SHOW(FIRST(foo ,a ,b ,c)); // → a
+ printf("\n");
+
+ //---------------------------------------------------------------------------
+ // REST
+ //---------------------------------------------------------------------------
+
+ SHOW(REST()); // → (empty)
+ SHOW(REST(a)); // → (empty)
+ SHOW(REST(a ,b)); // → b
+ SHOW(REST(a ,b ,c ,d)); // → b ,c ,d
+ printf("\n");
+
+ //---------------------------------------------------------------------------
+ // SECOND
+ //---------------------------------------------------------------------------
+
+ SHOW(SECOND(X)); // → X (only pad)
+ SHOW(SECOND(X ,a)); // → X (only one arg, fallback to pad)
+ SHOW(SECOND(X ,a ,b)); // → b
+ SHOW(SECOND(X ,a ,b ,c)); // → b
+ printf("\n");
+
+ //---------------------------------------------------------------------------
+ // THIRD
+ //---------------------------------------------------------------------------
+
+ SHOW(THIRD(X)); // → X (pad returned)
+ SHOW(THIRD(X ,a)); // → X
+ SHOW(THIRD(X ,a ,b)); // → X
+ SHOW(THIRD(X ,a ,b ,c)); // → c
+ SHOW(THIRD(X ,a ,b ,c ,d)); // → c
+ printf("\n");
+
+ return 0;
+}