1. Provides:
- COMMA, SEMICOLON, NOT_EMPTY, EMPTY, ,MATCH_RWR ,NOT_MATCH_RWR, BOOL, NOT, AND, OR, EQ, NOT_EQ, IF_ELSE
+ Raw constants: ZERO, ONE, COMMA, SEMICOLON
+
+ Token tagging: _TWION_0, _TWION_1
+
+ Controlled concatenation: CAT2, CAT3, CAT4
+
+ Existence (now NOT_EMPTY) with token safety via ##
+
+ Rewrite matchers: MATCH_RWR, NOT_MATCH_RWR
+
+ Logical base: _AND, _OR, _NOT, BOOL, EQ, NOT_EQ
+
+ Structural access: FIRST, REST, SECOND, THIRD
+
+ Branching: IF_ELSE(...), with macro-safe conditioning
+
+ Tests for all major features: try_eq.c, try_access.c, try_3_if.c, etc.
2.
These are the non-recursive extensions. See cpp_ext_1 for the recursive extensions.
EQ comparisons apart from logic comparisons, must be registered in advance. They take the form of, _RWR_EQ__<x>__oo__<y>, note comments below.
+5. todo
+
+cpp_ext as separate project
+make the try into tests
+make EXISTS true, leave an empty element as false
+
+IS_LIST to distinguish element from list, though it will be tough to
+detect IS_LIST on a list with EMPTY elements, then a list with all
+empty elements is still a list, still exits.
+
+mv BOOL AND OR
+make AND and OR versions of FIND on EXISTS (existence quantification)
+
*/
#define _CAT4(a ,b ,c ,d) a ## b ## c ## d
#define CAT4(a ,b ,c ,d) _CAT4(a ,b ,c ,d)
+#define APPEND(list ,...) list ,__VA_ARGS__
+
+
/*===========================================================================
Existence
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(predicate) CAT2(_IF_ ,BOOL(predicate))
#define _IF_1(...) __VA_ARGS__ _IF_1_ELSE
#define _IF_0(...) _IF_0_ELSE
#define _IF_1_ELSE(...)
// _FIRST defined in the logic section
#define FIRST(pad ,...)\
- IF_ELSE \
+ IF \
( EMPTY(__VA_ARGS__) ) \
(pad) \
( _FIRST(__VA_ARGS__) )
#define _REST(a ,...) __VA_ARGS__
#define REST(...)\
- IF_ELSE \
+ IF \
( EMPTY(__VA_ARGS__) ) \
() \
( _REST(__VA_ARGS__) )
// _SECOND defined in the logic section
#define SECOND(pad ,...) \
- IF_ELSE \
+ IF \
( EMPTY(__VA_ARGS__) ) \
(pad) \
( _SECOND(__VA_ARGS__ ,pad) )
#define _THIRD(a ,b ,c ,...) c
#define THIRD(pad ,...) \
- IF_ELSE \
+ IF \
( EMPTY(__VA_ARGS__) ) \
(pad) \
( _THIRD(__VA_ARGS__ ,pad, pad) )
Simple errors can lead to very long error outputs, which might be why
the cpp designers had obviously intended that recursion would not be possible.
+To be added:
+
+LIST_TOO_LONG
+
+// scanning left to right finds first that exists
+LEFTMOST_NOT_EMPTY
+
+// scanning left to right finds last that exits
+RIGHTMOST_NOT_EMPTY
+
+DROP_EMPTY_ALL
+DROP__EMPTY_LEFT
+DROPE_EMPTY_RIGHT
+
+#define _CAT(sep,first,...) \
+
*/
#ifndef CPP_EXT_1
#define DEFER3(m) m EMPTY EMPTY EMPTY()()()
#define DEFER4(m) m EMPTY EMPTY EMPTY EMPTY()()() /* as needed */
-
/*===========================================================================
- IF-ELSE construct.
- Usage: IF_ELSE(condition)(<true case>)(<false case>)
-
- A most amazing little macro. It has no dependencies on the other macros
- in this file, though many will be useful for setting (condition)
+ Quantifiers
===========================================================================*/
- #define IF_ELSE(condition) 77
-# #define IF_ELSE(condition) BE64(_IF_ELSE_1(BOOL(condition)))
- #define _IF_ELSE_1(condition) _IF_ELSE_2(condition)
- #define _IF_ELSE_2(condition) _IF_##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__
-
-
-
-/*===========================================================================
- Token concatenation and basic utilities
-===========================================================================*/
-
-/* Assumes that EVAL,DEFER1,IF_ELSE,and HAS_ARGS are defined as in our macro library */
-
-/* Helper: paste exactly two tokens with a separator.
- If 'sep' is empty,then a ## sep ## b is equivalent to a ## b.
-*/
-#define _CAT2(sep,a,b) a ## sep ## b
-
-#define _CAT(sep,first,...) \
- IF_ELSE(HAS_ARGS(__VA_ARGS__))( \
- _CAT2(sep,first,DEFER1(_CAT)(sep,__VA_ARGS__)) \
- )(first)
-
-/* Variadic CAT:
- - If no tokens are provided,returns nothing.
- - If one token is provided,returns that token.
- - Otherwise,it recursively concatenates the tokens with the given separator.
-*/
-#define CAT(sep,...) IF_ELSE(HAS_ARGS(__VA_ARGS__))( EVAL(_CAT(sep,__VA_ARGS__)) )(/* nothing */)
-
-
-/*===========================================================================
- MATCH(x,list) returns 1 if x is a member in the list, else 0
-
- list is comma separated.
-
- when list is passed to EVAL(MATCH_IMPL(x,list)) it gets expanded
- which causes the elements to spread out.
-
- #define list dog,cat,parakeet
- Match(x,list) -> EVAL(MATCH_IMPL(x,dog,cat,parkeet))
-
- HAS_ARGS will return true if there is a 'first' list element, else false.
-
- #define _IS_EQ_<x>_<x> Probe() must be defined for the equality test to work.
-
-===========================================================================*/
-#define MATCH_IMPL(x,first,...) \
- IF_ELSE \
- ( HAS_ARGS(first) ) \
- ( IF_ELSE \
- ( EQUAL(x,first) ) \
- (1) \
- ( MATCH_IMPL(x,__VA_ARGS__) ) \
- ) \
- (0)
+// left right scan returns first element where predicate is true
+#define _FIND(list ,predicate) \
+ IF \
+ ( EMPTY(list) ) \
+ () \
+ (IF \
+ ( predicate(FIRST(list)) ) \
+ ( FIRST(list) ) \
+ ( DEFER1(_FIND_CONF)()(REST(list)) )
-#define MATCH(x,list) EVAL(MATCH_IMPL(x,list))
+#dfine _FIND_CONF() _FIND
+#define FIND(list ,predicate) EVAL64(_FIND(list ,predicate))
-#endif
+#endif
--- /dev/null
+#include "cpp_ext_0.c"
+#include "cpp_ext_1.c"
+
+#define LIST int ,float ,char ,void ,long
+
+// Define a predicate macro: returns 1 if argument is "char"
+#define IS_char(x) _IS_char_##x
+#define _IS_char_char 1
+
+int main(void){
+
+ //--------------------------------------------------------------------------
+ // FIND — returns first matching element from the list
+ //--------------------------------------------------------------------------
+
+ // Use FIND to locate "char" in the list
+ SHOW( FIND((LIST) ,IS_char) ); // → char
+
+ // Try a predicate that won’t match
+ #define IS_double(x) _IS_double_##x
+ #define _IS_double_double 1
+ SHOW( FIND((LIST) ,IS_double) ); // → (empty)
+
+ // Show that FIND returns the first match
+ #define IS_type(x) _IS_type_##x
+ #define _IS_type_float 1
+ #define _IS_type_void 1
+ SHOW( FIND((LIST) ,IS_type) ); // → float (not void)
+
+ return 0;
+}