--- /dev/null
+
+#ifndef CPP_EXT
+#define CPP_EXT
+ #include "cpp_ext_0.c"
+ #include "cpp_ext_1.c"
+#endif
--- /dev/null
+/*
+ See also
+ https://github.com/18sg/uSHET/blob/master/lib/cpp_magic.h
+ and tutorial at: http://jhnet.co.uk/articles/cpp_magic
+
+ documents in $REPO_HOME/developer/document🖉
+
+1. Provides:
+
+ Raw constants: ZERO, ONE, COMMA, SEMICOLON
+
+ Token tagging: _TWION_0, _TWION_1
+
+ Controlled concatenation: CAT2, CAT3, CAT4
+
+ Existence (now EXISTS) 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.
+
+3.
+ The 'twion' is cute. It is reminiscent of a complex number in math. Like the complex number that is fed into scalar equestions. The twion is a pair given to functions that only take singletons.
+
+4.
+ 0 is false
+ 1 is true
+
+ Macros starting with an '_' (underscore) are private.
+
+ 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 NOT_EXISTS 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)
+
+find a better name for NULL_FN
+
+*/
+
+#ifndef CPP_EXT_0
+#define CPP_EXT_0
+
+/*===========================================================================
+DEBUG
+===========================================================================*/
+
+#include <stdio.h>
+#define DEBUG_CPP
+#define STR(...) #__VA_ARGS__
+
+// print the macro and the evaluation of the macro
+#define SHOW(expr) printf("%s -> %s\n", #expr, STR(expr))
+
+/*===========================================================================
+Constants
+===========================================================================*/
+
+#define COMMA ,
+#define SEMICOLON ;
+
+#define FALSE 0
+#define TRUE 1
+
+//---------
+
+#define _TWION_0 ~,0
+#define _TWION_1 ~,1
+
+// RWR == rewrite rule, RWR_ is followed by macro name it is used in `_<name>_`
+// Matching text is replaced with nothing, making it empty
+// Potential for aliasing if x or y values have '__oo__' embedded in them.
+#define _RWR_NOT__0
+#define _RWR_AND__1__oo__1
+#define _RWR_OR__0__oo__0
+
+// add more of this form to register other equivalences
+#define _RWR_EQ__0__oo__0
+#define _RWR_EQ__1__oo__1
+
+/*===========================================================================
+Primitive Concatenation
+ Not due to elegance, as `##` is convenient, rather this is
+ used to force evaluation of arguments before `##`.
+ There will be a recursive CAT of n things in cpp_ext_1.c
+===========================================================================*/
+
+#define _CAT2(a ,b) a ## b
+#define CAT2(a ,b) _CAT2(a ,b)
+
+#define _CAT3(a ,b ,c) a ## b ## c
+#define CAT3(a ,b ,c) _CAT3(a ,b ,c)
+
+#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
+===========================================================================*/
+
+ //----------------------------------------
+ // primitive access
+
+ // note: _FIRST of nothing, _FIRST(), means passing an empty_item as the first item
+ // so it will return empty.
+ #define _FIRST(a ,...) a
+ #define _SECOND(a ,b ,...) b
+
+ //----------------------------------------
+ // existence
+ //
+ // `##` prevents rewrite of _TWION_ in the _EXISTS_ITEM_1 macro, don't
+ // replace that with CAT!
+
+ #define _EXISTS_ITEM_2(x_item) _SECOND(x_item ,1)
+ #define _EXISTS_ITEM_1(x_item) _EXISTS_ITEM_2(_TWION_0##x_item)
+
+ #define EXISTS_ITEM(x_item) _EXISTS_ITEM_1(x_item)
+ #define EXISTS(...) EXISTS_ITEM( _FIRST(__VA_ARGS__) )
+
+ #define _NOT_EXISTS_ITEM_2(x_item) _SECOND(x_item ,0)
+ #define _NOT_EXISTS_ITEM_1(x_item) _NOT_EXISTS_ITEM_2(_TWION_1##x_item)
+
+ #define NOT_EXISTS_ITEM(x_item) _NOT_EXISTS_ITEM_1(x_item)
+ #define NOT_EXISTS(...) NOT_EXISTS_ITEM( _FIRST(__VA_ARGS__) )
+
+ // useful to use with rewrite rules that substitute to nothing
+ #define MATCH_RWR(x_item) NOT_EXISTS(x_item)
+ #define NOT_MATCH_RWR(x_item) EXISTS(x_item)
+
+/*===========================================================================
+Logic Connectors
+===========================================================================*/
+
+ #define _NOT(x_item) \
+ MATCH_RWR( CAT2(_RWR_NOT__ ,x_item) )
+
+ #define _AND(x_item ,y_item) \
+ MATCH_RWR( CAT4(_RWR_AND__ ,x_item ,__oo__ ,y_item) )
+
+ #define _OR(x_item ,y_item) \
+ NOT_MATCH_RWR( CAT4(_RWR_OR__ ,x_item ,__oo__ ,y_item) )
+
+ #define _BOOL(x_item) \
+ _AND( \
+ EXISTS_ITEM( x_item ) \
+ ,NOT_MATCH_RWR( CAT2(_RWR_EQ__0__oo__ ,x_item) ) \
+ )
+ #define BOOL(x_item) _BOOL(_FIRST(x_item))
+
+ #define NOT(x_item) _NOT(BOOL(x_item))
+ #define AND(x_item ,y_item) _AND(BOOL(x_item) ,BOOL(y_item))
+ #define OR(x_item ,y_item) _OR(BOOL(x_item) ,BOOL(y_item))
+
+/*===========================================================================
+ Equality
+
+ more general than a connector because more rules can be added.
+
+ each registered equality rule has the form
+ _RWR_EQ__<x>__oo__<y>
+ for example, logic equalities are already registered:
+ _RWR_EQ__0__oo__0
+ _RWR_EQ__1__oo__1
+
+===========================================================================*/
+
+ #define EQ(x_item ,y_item) \
+ MATCH_RWR( CAT4(_RWR_EQ__ ,x_item ,__oo__ ,y_item) )
+
+ #define NOT_EQ(x_item ,y_item) \
+ NOT_MATCH_RWR( CAT4(_RWR_EQ__ ,x_item ,__oo__ ,y_item) )
+
+/*===========================================================================
+ 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)
+
+ 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(predicate) CAT2(_IF_ ,BOOL(predicate))
+ #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 ext_1 with recursion for `Nth`
+
+===========================================================================*/
+
+ // _FIRST defined in the logic section
+ #define FIRST(pad ,...)\
+ IF \
+ ( NOT_EXISTS(__VA_ARGS__) ) \
+ (pad) \
+ ( _FIRST(__VA_ARGS__) )
+
+ #define _REST(a ,...) __VA_ARGS__
+ #define REST(...)\
+ IF \
+ ( NOT_EXISTS(__VA_ARGS__) ) \
+ () \
+ ( _REST(__VA_ARGS__) )
+
+ // _SECOND defined in the logic section
+ #define SECOND(pad ,...) \
+ IF \
+ ( NOT_EXISTS(__VA_ARGS__) ) \
+ (pad) \
+ ( _SECOND(__VA_ARGS__ ,pad) )
+
+ #define _THIRD(a ,b ,c ,...) c
+ #define THIRD(pad ,...) \
+ IF \
+ ( NOT_EXISTS(__VA_ARGS__) ) \
+ (pad) \
+ ( _THIRD(__VA_ARGS__ ,pad, pad) )
+
+#endif
--- /dev/null
+/*
+These are the recursive extension.
+
+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_EXISTENT
+
+// scanning left to right finds last that exits
+RIGHTMOST_EXISTENT
+
+DROP_NOT_EXISTS_ALL
+DROP_NOT_EXISTS_LEFT
+DROPE_NOT_EXISTS_RIGHT
+
+#define _CAT(sep,first,...) \
+
+*/
+
+#ifndef CPP_EXT_1
+#define CPP_EXT_1
+
+/*===========================================================================
+ Force extra macro expansion (the EVAL trick)
+ This chain of EVAL macros forces the preprocessor to perform many rescans,
+ which is necessary to “unroll” recursive macros.
+===========================================================================*/
+//#define EVAL(...) EVAL1024(__VA_ARGS__)
+#define EVAL(...) EVAL32(__VA_ARGS__)
+#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))
+#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__))
+#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__))
+#define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__))
+#define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__))
+#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__))
+#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))
+#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__))
+#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__))
+#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))
+#define EVAL1(...) __VA_ARGS__
+
+/*===========================================================================
+ Defer macros: these help “hide” recursive calls for additional expansion passes.
+===========================================================================*/
+#define NULL_FN()
+#define DEFER1(m) m NULL_FN()
+#define DEFER2(m) m NULL_FN NULL_FN()()
+#define DEFER3(m) m NULL_FN NULL_FN NULL_FN()()()
+#define DEFER4(m) m NULL_FN NULL_FN NULL_FN NULL_FN()()()()
+
+/*===========================================================================
+ Quantifiers
+===========================================================================*/
+
+#define _FIND(predicate ,...) \
+ IF \
+ ( NOT_EXISTS(__VA_ARGS__) ) \
+ () \
+ (IF \
+ ( predicate(FIRST(__VA_ARGS__)) ) \
+ ( FIRST( ,__VA_ARGS__) ) \
+ ( DEFER3(_FIND_CONFEDERATE) ()(predicate ,REST(__VA_ARGS__)) ) \
+ )
+#define _FIND_CONFEDERATE() _FIND
+
+// number of evals required depends upon length of not found list prefix
+#define FIND(predicate ,...) EVAL( _FIND(predicate ,__VA_ARGS__) )
+
+
+#endif
+++ /dev/null
-#+TITLE: Advanced cpp Macro Handling: Twions and Emptiness
-#+AUTHOR: Eos
-#+DATE: 2025-03-26
-
-* Introduction
-
-Twions extend the capability of the C preprocessor (cpp) by introducing two-dimensional structures analogous to complex numbers in mathematics, effectively managing cases originally designed for single-dimensional values.
-
-This document builds upon concepts and techniques inspired by [[https://github.com/18sg/uSHET/blob/master/lib/cpp_magic.h][cpp_magic.h]] and the tutorial [[http://jhnet.co.uk/articles/cpp_magic][cpp_magic]] by Jonathan Heathcote.
-
-* Key Concepts for Header Comments
-
-The following comments are recommended for inclusion in the header section of the `cpp_extensions.txt` file:
-
-#+BEGIN_SRC c
-/*
- Inspired by:
- - https://github.com/18sg/uSHET/blob/master/lib/cpp_magic.h
- - Jonathan Heathcote's tutorial: http://jhnet.co.uk/articles/cpp_magic
-
- Twions: Pairs of items used in macros designed for single-item arguments,
- analogous to complex numbers in mathematics.
-
- Key Concepts:
- - Token pasting (`##`) concatenates tokens literally without macro expansion.
- - Empty arguments (`__VA_ARGS__`) are distinct from omitted arguments and
- require careful handling through intermediate macros.
- - Macros requiring single arguments typically end with `_item`.
- - Private identifiers and macros begin with an underscore (`_`).
-*/
-#+END_SRC
-
-* Detailed Explanation and Clarifications
-
-** Token Concatenation (`##`) and Macro Expansion
-
-The `##` operator directly concatenates tokens without expanding their arguments first. For example:
-
-#+BEGIN_SRC c
-#define cat(x,y) x##y
-#define xx 3
-#define yy 5
-
-cat(xx,yy) // expands to xxyy, not 35
-#+END_SRC
-
-To correctly handle token pasting with potentially empty arguments, intermediate macros must be used to avoid literal empty tokens:
-
-Incorrect (direct):
-#+BEGIN_SRC c
-#define IS_EMPTY_ITEM(x_item) _IS_EMPTY_2(_TWION_##x_item)
-#+END_SRC
-
-Correct (using intermediate macro):
-#+BEGIN_SRC c
-#define _IS_EMPTY_1(x_item) _IS_EMPTY_2(_TWION_##x_item)
-#define IS_EMPTY_ITEM(x_item) _IS_EMPTY_1(x_item)
-#+END_SRC
-
-** Function Macro Syntax
-
-Macro names must directly precede their argument lists without spacing:
-
-Correct:
-#+BEGIN_SRC c
-#define sum(p ,q ,r) (p + q + r)
-#+END_SRC
-
-Incorrect (defines object-like macro):
-#+BEGIN_SRC c
-#define sum (p ,q ,r) (p + q + r)
-#+END_SRC
-
-** Grammar and Special Items
-
-- ~empty_item~: A position in a macro argument list explicitly empty but still counted.
-- ~shim_item~ (`~,1`): A two-token item acting as one unit, shifting indexing for variadic macros.
-
-** Logic Macros and Conventions
-
-- Boolean logic: `True` = 1, `False` = 0.
-- Single-item arguments end with `_item` to enforce intended usage.
-
-* Handling Empty Arguments and Lists
-
-** Empty Argument Detection
-
-Variadic macros may contain empty elements (e.g., `a ,b , ,d`). This complicates emptiness checks. Direct argument count overloads are impossible with standard cpp.
-
-A robust method to handle emptiness:
-
-#+BEGIN_SRC c
-#define SECOND_1(a ,b ,...) b
-#define SECOND(...) SECOND_1(__VA_ARGS__, pad)
-#+END_SRC
-
-Even if `__VA_ARGS__` is empty, it ensures a safe fallback (`pad`).
-
-** Differentiating Empty and Non-Empty Arguments
-
-To clearly differentiate empty from non-empty arguments, use:
-
-- **Peek-a-Boo Macro Call**:
-#+BEGIN_SRC c
-macro __VA_ARGS__ ()
-#+END_SRC
-
- - Empty: Calls `macro()`.
- - Non-empty: Results in unintended macro calls, signaling arguments are present.
-
-- **Rewrite Rule Approach**:
-#+BEGIN_SRC c
-#define rewrite_rule new_value
-rewrite##__VA_ARGS__##rule
-#+END_SRC
-
- - Empty arguments yield `rewrite_rule` → `new_value`.
- - Non-empty arguments clearly differ, showing the presence of content.
-
-* Future Integration
-
-Recursion handling methods from [[https://github.com/18sg/uSHET/blob/master/lib/cpp_magic.h][cpp_magic.h]] will also be integrated into future expansions of this macro suite.
-
A call to ~VAL(FORCE_ONE(5))~ will result in `1`. This is because there is no hash symbol in the VAL macro that is stopping the recursive expansion of ~x~.
-5. Example of delayed evaluation
+5. Cascading evaluation
+
+ A macro can also fail to evaluate all possible macros, because during
+ the left to right scan, it did not see the new macro call.
#+BEGIN_SRC c
- #define EMPTY()
+ #define NULL_FN() // expands to nothing
#define NEGATE(x) -x
- #define NOT_SO_FAST(x) NEGATE EMPTY() (x)
+ #define NOT_SO_FAST(x) NEGATE NULL_FN() (x)
#+END_SRC
When evaluating ~NOT_SO_FAST(5)~, here's what happens:
- It enters ~NOT_SO_FAST(5)~, expands it to ~NEGATE (5)~.
- Then ~BE(NEGATE (5))~ becomes ~-5~ through final macro expansion.
+ -------
+
+ The `IF` macro evolves and does three self evaluations, due to new strings
+ being created which in turn match already defined macros.
+
+ <walk through an IF> series of events, explain why the DEFER3, ph
+
+ #+BEGIN_SRC c
+ IF \
+ ( NOT_EXISTS(__VA_ARGS__) ) \
+ () \
+ (IF \
+ ( predicate(FIRST(__VA_ARGS__)) ) \
+ ( FIRST( ,__VA_ARGS__) ) \
+ ( DEFER3(_FIND_CONFEDERATE) ()(predicate ,REST(__VA_ARGS__)) ) \
+ )
+ #+END_SRC
+
+
6. Nesting, recursion approaches that do not work, and one that does.
#+BEGIN_SRC c
--- /dev/null
+
+1.
+
+A semicolon after a macro definition becomes part of the macro body.
+
+
+2.
+
+When defining a macro:
+
+ No space between the macro function name and the parameter list.
+
+ Otherwise the would-be parameter list will be taken to be part of a macro variable definition.
+
+When calling a macro.
+ Can have space between a macro function name and the argument list.
+
+2.
+
+Macros can be called with empty arguments.
+
+ #+BEGIN_SRC c
+ #define a_macro(a ,b ,c) (a + b + c)
+ int a_macro (a,,b) // -> a + + c
+ #+END_SRC
+
+ 3. The access macros, FIRST, SECOND ... have a padding character as a first argument.
+ The padding character is returned if the list is not long enough for the access.
+ It can be left empty.
+
+ FIRST(,) will return the empty_token.
+
+
--- /dev/null
+Grammar
+
+ identifier = [_a-zA-Z][_a-zA-Z0-9]*
+ | ([_a-zA-Z\u00A0-\uFFFF])([_a-zA-Z0-9\u00A0-\uFFFF])*
+
+ macro_name = identifier
+
+ token = identifier
+ | number ; e.g., 42, 0xFF, 3.14
+ | string_literal ; "hello"
+ | character_constant ; 'a', '\n'
+ | operator_token ; +, -, ~, <<, etc.
+ | punctuation ; (), [], {}, etc. (when tokenized)
+ | parenthesized_expr ; (1,2), (x + y)
+
+ empty_item = ε
+ An item with no content, but syntactically present and contributing to list length.
+ For example, ( , ) is a two-item arg_list with two empty_items.
+
+ shim_item = ~,1
+ A special two-token item treated as a single item.
+ Its role is to shift the remaining members of a list by one position when prepended.
+ An honorary member of the single item club.
+
+ item = token | empty_item | shim_item
+
+ arg_list = item (, item)* ; comma-separated list of items
+
+ pair = item , item ; exactly two items
+
+2.2 'private' identify
+
+ By convention private identifiers begin with an `_` character.
+
+ Macros with this prefix are not intended to be called by users, and
+ indentifiers with this prefix are not intended to to used.
+
+++ /dev/null
-#include <stdio.h>
-#include "cpp_RT.c"
-
-#define SHOW( x) printf(#x " = %d\n", x)
-
-int main(void){
- //--------------------------------------------------------------------------
- // Existence Checks (sanity anchor)
- //--------------------------------------------------------------------------
-
- #define x0
- SHOW( EXISTS_ITEM(x0) ); // → 0 (assumed undefined)
- SHOW( NOT_EXISTS_ITEM(x0) ); // → 1
- printf("\n");
-
- SHOW( MATCH(x0) );
- SHOW( NOT_MATCH(x0) );
- printf("\n");
-
-
- //--------------------------------------------------------------------------
- // Primitive Connectors
- //--------------------------------------------------------------------------
-
- SHOW( _NOT(0) ); // _RWR_NOT_0 is defined → MATCH → 1
- SHOW( _NOT(1) ); // no rule → MATCH fails → 0
- printf("\n");
-
- SHOW( _AND(0 ,0) ); // rule defined → MATCH → 1
- SHOW( _AND(1 ,0) ); // rule defined → MATCH → 1
- SHOW( _AND(0 ,1) ); // rule defined → MATCH → 1
- SHOW( _AND(1 ,1) ); // rule defined → MATCH → 1
- SHOW( _AND(1 ,x) ); // not legal args, but worked, rule missing → MATCH fails → 0
- printf("\n");
-
- SHOW( _OR(0 ,0) ); // rule defined → NOT_MATCH → 0
- SHOW( _OR(0 ,1) ); // rule missing → NOT_MATCH → 1
- SHOW( _OR(1 ,0) ); // rule missing → NOT_MATCH → 1
- SHOW( _OR(1 ,1) ); // rule missing → NOT_MATCH → 1
- printf("\n");
-
-
-
- //--------------------------------------------------------------------------
- // Equality
- //--------------------------------------------------------------------------
-
- SHOW( _EQ(0 ,0) ); // rule defined → MATCH → 1
- SHOW( _EQ(1 ,1) ); // rule defined → MATCH → 1
- SHOW( _EQ(0 ,1) ); // no rule → MATCH fails → 0
- SHOW( _EQ(x ,x) ); // no rule → MATCH fails → 0
- printf("\n");
-
- SHOW( _NOT_EQ(0 ,1) ); // rule missing → EXISTS → 1
- SHOW( _NOT_EQ(0 ,0) ); // rule exists → EXISTS → 0
- printf("\n");
-
- //--------------------------------------------------------------------------
- // Logical Connectors (BOOL + AND/OR/NOT)
- //--------------------------------------------------------------------------
-
- SHOW( _BOOL_2(0) ); // 0
- SHOW( _BOOL_2(1) ); // 1
- SHOW( _BOOL_2(2) ); // 1 because it exists
- SHOW( _BOOL_2(x0) ); // 0 because it does not exit (see the #define at the top)
- printf("\n");
-
- SHOW( BOOL(0) ); // _FIRST = 0, EXISTS_ITEM(_FIRST) = 0 → _AND(0 ,1) → 0
- SHOW( BOOL(1) ); // EXISTS_ITEM(1) = 0 → BOOL = 0
- SHOW( BOOL(10) ); // EXISTS_ITEM(1) = 0 → BOOL = 0
- SHOW( BOOL() ); // EXISTS_ITEM(1) = 0 → BOOL = 0
- SHOW( BOOL(x0) ); // EXISTS_ITEM(1) = 0 → BOOL = 0
- printf("\n");
-
- SHOW( NOT(0) ); // BOOL = 0 → NOT(0) = _NOT(0) = 1
- SHOW( NOT(1) ); // BOOL = 0 → NOT(0) = 1
- SHOW( NOT() ); // BOOL = 0 → NOT(0) = 1
- SHOW( NOT(10) ); // BOOL = 0 → NOT(0) = 1
- printf("\n");
-
- SHOW( AND(1 ,0) ); // 0
- SHOW( AND(1 ,1) ); // BOOL(1), BOOL(1) = 0,0 → AND(0 ,0) = _AND(0 ,0) = 1
- printf("\n");
-
- SHOW( OR(0 ,0) ); // BOOL(1), BOOL(0) = 0,0 → OR(0 ,0) = _OR(0 ,0) = 0
- SHOW( OR(1 ,0) ); // BOOL(1), BOOL(0) = 0,0 → OR(0 ,0) = _OR(0 ,0) = 0
- printf("\n");
-
- return 0;
-}
Controlled concatenation: CAT2, CAT3, CAT4
- Existence (now NOT_EMPTY) with token safety via ##
+ Existence (now EXISTS) with token safety via ##
Rewrite matchers: MATCH_RWR, NOT_MATCH_RWR
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
+detect IS_LIST on a list with NOT_EXISTS 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)
+find a better name for NULL_FN
*/
#define COMMA ,
#define SEMICOLON ;
-#define ZERO 0
-#define ONE 1
-
#define FALSE 0
#define TRUE 1
//----------------------------------------
// existence
//
- // `##` prevents rewrite of _TWION_ in the _NOT_EMPTY_ITEM_1 macro, don't
+ // `##` prevents rewrite of _TWION_ in the _EXISTS_ITEM_1 macro, don't
// replace that with CAT!
- #define _NOT_EMPTY_ITEM_2(x_item) _SECOND(x_item ,1)
- #define _NOT_EMPTY_ITEM_1(x_item) _NOT_EMPTY_ITEM_2(_TWION_0##x_item)
+ #define _EXISTS_ITEM_2(x_item) _SECOND(x_item ,1)
+ #define _EXISTS_ITEM_1(x_item) _EXISTS_ITEM_2(_TWION_0##x_item)
- #define NOT_EMPTY_ITEM(x_item) _NOT_EMPTY_ITEM_1(x_item)
- #define NOT_EMPTY(...) NOT_EMPTY_ITEM( _FIRST(__VA_ARGS__) )
+ #define EXISTS_ITEM(x_item) _EXISTS_ITEM_1(x_item)
+ #define EXISTS(...) EXISTS_ITEM( _FIRST(__VA_ARGS__) )
- #define _EMPTY_ITEM_2(x_item) _SECOND(x_item ,0)
- #define _EMPTY_ITEM_1(x_item) _EMPTY_ITEM_2(_TWION_1##x_item)
+ #define _NOT_EXISTS_ITEM_2(x_item) _SECOND(x_item ,0)
+ #define _NOT_EXISTS_ITEM_1(x_item) _NOT_EXISTS_ITEM_2(_TWION_1##x_item)
- #define EMPTY_ITEM(x_item) _EMPTY_ITEM_1(x_item)
- #define EMPTY(...) EMPTY_ITEM( _FIRST(__VA_ARGS__) )
+ #define NOT_EXISTS_ITEM(x_item) _NOT_EXISTS_ITEM_1(x_item)
+ #define NOT_EXISTS(...) NOT_EXISTS_ITEM( _FIRST(__VA_ARGS__) )
// useful to use with rewrite rules that substitute to nothing
- #define MATCH_RWR(x_item) EMPTY(x_item)
- #define NOT_MATCH_RWR(x_item) NOT_EMPTY(x_item)
+ #define MATCH_RWR(x_item) NOT_EXISTS(x_item)
+ #define NOT_MATCH_RWR(x_item) EXISTS(x_item)
/*===========================================================================
Logic Connectors
#define _BOOL(x_item) \
_AND( \
- NOT_EMPTY_ITEM( x_item ) \
+ EXISTS_ITEM( x_item ) \
,NOT_MATCH_RWR( CAT2(_RWR_EQ__0__oo__ ,x_item) ) \
)
#define BOOL(x_item) _BOOL(_FIRST(x_item))
// _FIRST defined in the logic section
#define FIRST(pad ,...)\
IF \
- ( EMPTY(__VA_ARGS__) ) \
+ ( NOT_EXISTS(__VA_ARGS__) ) \
(pad) \
( _FIRST(__VA_ARGS__) )
#define _REST(a ,...) __VA_ARGS__
#define REST(...)\
IF \
- ( EMPTY(__VA_ARGS__) ) \
+ ( NOT_EXISTS(__VA_ARGS__) ) \
() \
( _REST(__VA_ARGS__) )
// _SECOND defined in the logic section
#define SECOND(pad ,...) \
IF \
- ( EMPTY(__VA_ARGS__) ) \
+ ( NOT_EXISTS(__VA_ARGS__) ) \
(pad) \
( _SECOND(__VA_ARGS__ ,pad) )
#define _THIRD(a ,b ,c ,...) c
#define THIRD(pad ,...) \
IF \
- ( EMPTY(__VA_ARGS__) ) \
+ ( NOT_EXISTS(__VA_ARGS__) ) \
(pad) \
( _THIRD(__VA_ARGS__ ,pad, pad) )
LIST_TOO_LONG
// scanning left to right finds first that exists
-LEFTMOST_NOT_EMPTY
+LEFTMOST_EXISTENT
// scanning left to right finds last that exits
-RIGHTMOST_NOT_EMPTY
+RIGHTMOST_EXISTENT
-DROP_EMPTY_ALL
-DROP__EMPTY_LEFT
-DROPE_EMPTY_RIGHT
+DROP_NOT_EXISTS_ALL
+DROP_NOT_EXISTS_LEFT
+DROPE_NOT_EXISTS_RIGHT
#define _CAT(sep,first,...) \
This chain of EVAL macros forces the preprocessor to perform many rescans,
which is necessary to “unroll” recursive macros.
===========================================================================*/
-#define EVAL(...) EVAL1024(__VA_ARGS__)
+//#define EVAL(...) EVAL1024(__VA_ARGS__)
+#define EVAL(...) EVAL32(__VA_ARGS__)
#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))
#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__))
#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__))
/*===========================================================================
Defer macros: these help “hide” recursive calls for additional expansion passes.
===========================================================================*/
-#define EMPTY()
-#define DEFER1(m) m EMPTY()
-#define DEFER2(m) m EMPTY EMPTY()()
-#define DEFER3(m) m EMPTY EMPTY EMPTY()()()
-#define DEFER4(m) m EMPTY EMPTY EMPTY EMPTY()()() /* as needed */
+#define NULL_FN()
+#define DEFER1(m) m NULL_FN()
+#define DEFER2(m) m NULL_FN NULL_FN()()
+#define DEFER3(m) m NULL_FN NULL_FN NULL_FN()()()
+#define DEFER4(m) m NULL_FN NULL_FN NULL_FN NULL_FN()()()()
/*===========================================================================
Quantifiers
===========================================================================*/
-// left right scan returns first element where predicate is true
-#define _FIND(list ,predicate) \
+#define _FIND(predicate ,...) \
IF \
- ( EMPTY(list) ) \
+ ( NOT_EXISTS(__VA_ARGS__) ) \
() \
(IF \
- ( predicate(FIRST(list)) ) \
- ( FIRST(list) ) \
- ( DEFER1(_FIND_CONF)()(REST(list)) )
-
-#dfine _FIND_CONF() _FIND
-
-#define FIND(list ,predicate) EVAL64(_FIND(list ,predicate))
+ ( predicate(FIRST(__VA_ARGS__)) ) \
+ ( FIRST( ,__VA_ARGS__) ) \
+ ( DEFER3(_FIND_CONFEDERATE) ()(predicate ,REST(__VA_ARGS__)) ) \
+ )
+#define _FIND_CONFEDERATE() _FIND
+
+// number of evals required depends upon length of not found list prefix
+#define FIND(predicate ,...) EVAL( _FIND(predicate ,__VA_ARGS__) )
#endif
#define STR(x) #x
#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr))
-#define EMPTY()
+#define NULL_FN()
#define EVAL1(...) __VA_ARGS__
#define A(n) I like the number n
" A (123)\n"
);
SHOW(A (123));
- SHOW(A EMPTY() (123));
+ SHOW(A NULL_FN() (123));
printf("\n");
printf(
" I like the number 123\n"
);
- SHOW(EVAL1(A EMPTY() (123)));
+ SHOW(EVAL1(A NULL_FN() (123)));
printf("\n");
int main(void){
printf("example_eval.c\n");
- #define EMPTY()
+ #define NULL_FN()
#define NEGATE(x) -x
- #define NOT_SO_FAST(x) NEGATE EMPTY() (x)
+ #define NOT_SO_FAST(x) NEGATE NULL_FN() (x)
SHOW(NOT_SO_FAST(5));
#define BE(x) x
#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr))
#define BE(...) __VA_ARGS__
-#define EMPTY()
+#define NULL_FN()
#include <stdio.h>
int main(void){
// case 2
// GROW2(11) --> 19 * GROW2 (11)
- #define GROW2(x) 19 * GROW2 EMPTY() (x)
+ #define GROW2(x) 19 * GROW2 NULL_FN() (x)
SHOW(GROW2(11)) ;
printf("\n");
// case 3
// GROW3(13) --> 119 * 19 * GROW2 (13)
- #define GROW3(x) BE(119 * GROW2 EMPTY() (x))
+ #define GROW3(x) BE(119 * GROW2 NULL_FN() (x))
SHOW(GROW3(13));
printf("\n");
GROW4(15) --> 123 * GROW4 (15)
*/
- #define GROW4(x) BE(123 * GROW4 EMPTY() (x))
+ #define GROW4(x) BE(123 * GROW4 NULL_FN() (x))
SHOW(GROW4(15));
printf("\n");
BE(GROW5(21)) --> 541 * 541 * CONFEDERATE () (21)
BE(BE(GROW5(57))) --> 541 * 541 * 541 * CONFEDERATE () (57)
*/
- #define GROW5(x) 541 * CONFEDERATE EMPTY() () (x)
+ #define GROW5(x) 541 * CONFEDERATE NULL_FN() () (x)
#define CONFEDERATE() GROW5
SHOW(BE(GROW5(21)));
SHOW(BE(BE(GROW5(57))));
/*
Once a recursively called function is marked, or 'colored' it can never be expanded, even when passed through to another variable and separately evaluation.
*/
- #define GROW6(x) 1029 * GROW6 EMPTY() (x)
+ #define GROW6(x) 1029 * GROW6 NULL_FN() (x)
#define RESULT1 GROW6(51)
SHOW(RESULT1);
SHOW(BE(RESULT1));
#define BE(...) __VA_ARGS__
-#define EMPTY()
-#define GROW(x) 19 * _GROW EMPTY() ()(x)
+#define NULL_FN()
+#define GROW(x) 19 * _GROW NULL_FN() ()(x)
#define _GROW() GROW
// no evaluation, and one pass of evalutation
#define SHOW(expr) printf("%s --> %s\n", #expr, STR(expr))
-#define EMPTY()
+#define NULL_FN()
#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__))
#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))
#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))
#define EVAL1(...) __VA_ARGS__
-#define DEFER1(m) m EMPTY()
+#define DEFER1(m) m NULL_FN()
#define RECURSE() I am recursive, look: DEFER1(_RECURSE)()()
#define _RECURSE() RECURSE
+++ /dev/null
-/* macro_lib.c */
-#ifndef MACRO_LIB
-#define MACRO_LIB
-
-/*===========================================================================
- Some Basics
-===========================================================================*/
-
-#define COMMA ,
-
-#define _FIRST(a,...) a
-#define FIRST(...) _FIRST(__VA_ARGS__,~)
-
-#define _SECOND(a,b,...) b
-#define SECOND(...) _SECOND(__VA_ARGS__,~,~)
-
-
-
-/*===========================================================================
- Defer macros: these help “hide” recursive calls for additional expansion passes.
-===========================================================================*/
-#define EMPTY()
-#define DEFER1(m) m EMPTY()
-#define DEFER2(m) m EMPTY EMPTY()()
-#define DEFER3(m) m EMPTY EMPTY EMPTY()()()
-#define DEFER4(m) m EMPTY EMPTY EMPTY EMPTY()()() /* as needed */
-
-/*===========================================================================
- 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 */)
-
-#define Ξ(...) CAT(·,__VA_ARGS__)
-#define Append(...) CAT(COMMA,__VA_ARGS__)
-
-
-/*===========================================================================
- Put a 'PROBE()' in a list then detect it later.
-
- If a single value is given to IS_PROBE it won't have a second member,but
- if the two element PROBE is given,the second element will be 1.
-
-===========================================================================*/
-
-#define PROBE() ~,1
-
-#define __IS_PROBE(a,b,...) b
-#define _IS_PROBE(...) __IS_PROBE(__VA_ARGS__,0,0)
-#define IS_PROBE(...) _IS_PROBE(__VA_ARGS__)
-
-#define _NOT_0 PROBE()
-
-// x == 0: _NOT_##x -> _NOT_0 -> ~,1 -> 1
-// x == 1: _NOT_##x -> _NOT_1 -> 0
-//
-#define _NOT(x) IS_PROBE(_NOT_##x)
-#define NOT(x) _NOT(x)
-#define BOOL(x) NOT(NOT(x))
-
-// This is a rewrite rule,if there is a definition for _IS_EQ_<x>_<y> it is replaced by its #define definition,presumably that of a Probe.
-// The rule will then be #define _IS_EQ_<X>_<X> Probe()
-#define _EQUAL_REWRITE(x,y) IS_PROBE( CAT(_IS_EQ_,x,_##y) )
-
-#define EQUAL(x,y) BOOL( _EQUAL_REWRITE(x,y) )
-
-
-
-/*===========================================================================
- HAS_ARGS: tests whether a variadic argument list is empty.
-
- A bit of a tricky one, _END_OF_ARGUMENTS will only be expanded if it
- is followed by parenthesis,otherwise it is taken literally.
-===========================================================================*/
-#define _END_OF_ARGUMENTS_() 0
-#define HAS_ARGS(...) BOOL(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)())
-
-/*===========================================================================
- 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)
-
-#define MATCH(x,list) EVAL(MATCH_IMPL(x,list))
-
-/* End of macro_lib.c */
-#endif
+++ /dev/null
-#include <stdio.h>
-#include "macro_lib.c"
-
-/* SUM_IF(condition, a, b)
- - If condition is true (nonzero), returns (a)+(b)
- - Otherwise, returns (a)-(b)
- This uses the IF_ELSE construct from the macro library.
-*/
-#define SUM_IF(condition, a, b) IF_ELSE(condition)( (a) + (b) )( (a) - (b) )
-
-int main(void) {
- int result_true = SUM_IF(1, 5, 3); // Expect 5+3 = 8
- int result_false = SUM_IF(0, 5, 3); // Expect 5-3 = 2
-
- printf("SUM_IF(1, 5, 3) = %d\n", result_true);
- printf("SUM_IF(0, 5, 3) = %d\n", result_false);
- return 0;
-}
+++ /dev/null
-/*
- See also https://github.com/18sg/uSHET/blob/master/lib/cpp_magic.h
- and tutorial at: http://jhnet.co.uk/articles/cpp_magic
-
- I could not have even thought about writing this without Jonathan Heathcote's
- little tutorial.
-
- The 'twion' is cute. It is reminiscent of a complex number in math. It is a
- pair given to functions that only take singletons.
-
-*/
-
-
-
-/*===========================================================================
-Constants
-===========================================================================*/
-
-#define COMMA ,
-#define SEMICOLON ;
-
-#define _TWION_0_ ~,0
-#define _TWION_1_ ~,1
-
-// RWR == rewrite rule, RWR_ is followed by macro name it is used in `_<name>_`
-// Matching text is replaced with nothing, making it empty
-// Potential for aliasing if x or y have '__oo__' embedded in them.
-#define _RWR_AND__1__oo__1
-#define _RWR_OR__0__oo__0
-#define _RWR_NOT__0
-
-#define _RWR_EQ__0__oo__0
-#define _RWR_EQ__1__oo__1
-
-/*===========================================================================
-Logic
-===========================================================================*/
-
-// user versions of these functions appear latter in the file
-
-//----------------------------------------
-// primitive access
-
- // note: _FIRST of nothing, _FIRST(), means passing an empty_item as the first item
- // so it will return empty.
- #define _FIRST(a ,...) a
- #define _SECOND(a ,b ,...) b
-
-//----------------------------------------
-// existence
-
- // `##` prevents rewrite of _TWION_ in the _EXISTS_ITEM_1 macro
- #define _EXISTS_ITEM_2(x_item) _SECOND(x_item ,1)
- #define _EXISTS_ITEM_1(x_item) _EXISTS_ITEM_2(_TWION_0_##x_item)
-
- #define EXISTS_ITEM(x_item) _EXISTS_ITEM_1(x_item)
- #define EXISTS(...) EXISTS_ITEM( _FIRST(__VA_ARGS__) )
-
- #define _NOT_EXISTS_ITEM_2(x_item) _SECOND(x_item ,0)
- #define _NOT_EXISTS_ITEM_1(x_item) _NOT_EXISTS_ITEM_2(_TWION_1_##x_item)
-
- #define NOT_EXISTS_ITEM(x_item) _NOT_EXISTS_ITEM_1(x_item)
- #define NOT_EXISTS(...) NOT_EXISTS_ITEM( _FIRST(__VA_ARGS__) )
-
- // useful to use with rewrite rules that substitute to nothing
- #define MATACH(x_item) NOT_EXISTS(x_item)
- #define NOT_MATCH(x_item) EXISTS(x_item)
-
-//----------------------------------------
-// primitive connectors
-
- #define _NOT_1(x_item) MATCH( _RWR_NOT_0_x_##x_item )
- #define _NOT(x_item) _NOT_1(x_item)
-
- #define _AND_1(x_item ,y_item) MATCH( _RWR_AND__##x_item##__oo__##y_item )
- #define _AND(x_item ,y_item) _AND_1(x_item ,y_item)
-
- #define _OR_1(x_item ,y_item) NOT_MATCH( _RWR_OR__##x_item#__oo__##y_item )
- #define _OR(x_item ,y_item) _OR_1(x_item ,y_item)
-
-//----------------------------------------
-// equality
-// works with registerd _RWS_EQ__<A>__oo__<A> rules.
-// for example: _RWR_EQ__0__oo__0
-
-
- #define _EQ(x_item ,y_item) MATCH( RWR_EQ__##x_item##__oo__##y_item )
- #define EQ(x_item ,y_item) _EQ(x_item ,y_item)
-
- #define _NOT_EQ(x_item ,y_item) EXISTS(RWR_EQ_##x_item##__oo__##y_item)
- #define NOT_EQ(x_item ,y_item) _NOT_EQ(x_item ,y_item)
-
-
-//----------------------------------------
-// connectors
-
- #define _BOOL(x_item) \
- _AND(\
- EXISTS_ITEM(_FIRST(x_item) \
- ,NOT_MATCH( _RWR_EQ__0__oo__##x_item) \
- )
- #define BOOL(x_item) _BOOL(_FIRST(x_item))
-
- #define NOT(x_item) _NOT(BOOL(x_item))
- #define AND(x_item ,y_item) _AND(BOOL(x_item) ,BOOL(y_item))
- #define OR(x_item ,y_item) _OR(BOOL(x_item) ,BOOL(y_item))
-
-
+++ /dev/null
-/*
- See also https://github.com/18sg/uSHET/blob/master/lib/cpp_magic.h
- and tutorial at: http://jhnet.co.uk/articles/cpp_magic
-
- I could not have even thought about writing this without Jonathan Heathcote's
- little tutorial.
-
- The 'twion' is cute. It is reminiscent of a complex number in math. It is a
- pair given to functions that only take singletons.
-
-*/
-
-
-
-/*===========================================================================
-Constants
-===========================================================================*/
-
-#define COMMA ,
-#define SEMICOLON ;
-
-#define _TWION_0_ ~,0
-#define _TWION_1_ ~,1
-
-// RWR == rewrite rule, RWR_ is followed by macro name it is used in `_<name>_`
-// Matching text is replaced with nothing, making it empty
-// Potential for aliasing if x or y have '__oo__' embedded in them.
-#define _RWR_AND__1__oo__1
-#define _RWR_OR__0__oo__0
-#define _RWR_NOT__0
-
-#define _RWR_EQ__0__oo__0
-#define _RWR_EQ__1__oo__1
-
-/*===========================================================================
-Logic
-===========================================================================*/
-
-// user versions of these functions appear latter in the file
-
-//----------------------------------------
-// primitive access
-
- // note: _FIRST of nothing, _FIRST(), means passing an empty_item as the first item
- // so it will return empty.
- #define _FIRST(a ,...) a
- #define _SECOND(a ,b ,...) b
-
-//----------------------------------------
-// existence
-
- // `##` prevents rewrite of _TWION_ in the _EXISTS_ITEM_1 macro
- #define _EXISTS_ITEM_2(x_item) _SECOND(x_item ,1)
- #define _EXISTS_ITEM_1(x_item) _EXISTS_ITEM_2(_TWION_0_##x_item)
-
- #define EXISTS_ITEM(x_item) _EXISTS_ITEM_1(x_item)
- #define EXISTS(...) EXISTS_ITEM( _FIRST(__VA_ARGS__) )
-
- #define _NOT_EXISTS_ITEM_2(x_item) _SECOND(x_item ,0)
- #define _NOT_EXISTS_ITEM_1(x_item) _NOT_EXISTS_ITEM_2(_TWION_1_##x_item)
-
- #define NOT_EXISTS_ITEM(x_item) _NOT_EXISTS_ITEM_1(x_item)
- #define NOT_EXISTS(...) NOT_EXISTS_ITEM( _FIRST(__VA_ARGS__) )
-
- // useful to use with rewrite rules that substitute to nothing
- #define MATACH(x_item) NOT_EXISTS(x_item)
- #define NOT_MATCH(x_item) EXISTS(x_item)
-
-//----------------------------------------
-// primitive connectors
-
- #define _NOT_1(x_item) MATCH( _RWR_NOT_0_x_##x_item )
- #define _NOT(x_item) _NOT_1(x_item)
-
- #define _AND_1(x_item ,y_item) MATCH( _RWR_AND__##x_item##__oo__##y_item )
- #define _AND(x_item ,y_item) _AND_1(x_item ,y_item)
-
- #define _OR_1(x_item ,y_item) NOT_MATCH( _RWR_OR__##x_item#__oo__##y_item )
- #define _OR(x_item ,y_item) _OR_1(x_item ,y_item)
-
-//----------------------------------------
-// equality
-// works with registerd _RWS_EQ__<A>__oo__<A> rules.
-// for example: _RWR_EQ__0__oo__0
-
-
- #define _EQ(x_item ,y_item) MATCH( RWR_EQ__##x_item##__oo__##y_item )
- #define EQ(x_item ,y_item) _EQ(x_item ,y_item)
-
- #define _NOT_EQ(x_item ,y_item) EXISTS(RWR_EQ_##x_item##__oo__##y_item)
- #define NOT_EQ(x_item ,y_item) _NOT_EQ(x_item ,y_item)
-
-
-//----------------------------------------
-// connectors
-
- #define _BOOL(x_item) \
- _AND(\
- EXISTS_ITEM(_FIRST(x_item) \
- ,NOT_MATCH( _RWR_EQ__0__oo__##x_item) \
- )
- #define BOOL(x_item) _BOOL(_FIRST(x_item))
-
- #define NOT(x_item) _NOT(BOOL(x_item))
- #define AND(x_item ,y_item) _AND(BOOL(x_item) ,BOOL(y_item))
- #define OR(x_item ,y_item) _OR(BOOL(x_item) ,BOOL(y_item))
-
-
+++ /dev/null
-#include <stdio.h>
-#include "macro_lib.c"
-
-/* Define decrement values for numbers 1 through 5 */
-#define DEC_1 0
-#define DEC_2 1
-#define DEC_3 2
-#define DEC_4 3
-#define DEC_5 4
-#define DEC(n) DEC_##n
-
-/*
- COUNT_DOWN(n):
- - If n is 0, outputs "Done".
- - Otherwise, outputs the current number (as a string), a space,
- and then recursively calls COUNT_DOWN on DEC(n).
-
- Note: DEFER1 is used to postpone the recursive call,
- and EVAL (via ESTR) will force the complete expansion.
-*/
-#define COUNT_DOWN(n) IF_ELSE(EQUAL(n,0))("Done") ( XSTR(n) " " DEFER1(COUNT_DOWN)(DEC(n)) )
-
-/* Minimal stringization helpers.
- STR(x) stringizes without expanding;
- XSTR(x) expands x first then stringizes;
- ESTR(x) forces full expansion (using EVAL) then stringizes.
-*/
-#define STR(x) #x
-#define XSTR(x) STR(x)
-#define ESTR(x) XSTR(EVAL(x))
-
-int main(void) {
- printf("Countdown from 5: %s\n", ESTR(COUNT_DOWN(5)));
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-
-/* Stringizing helpers */
-#define STR(x) #x
-#define XSTR(x) STR(x)
-
-#include "macro_logic.c"
-
-int main(void) {
- /* Test with three tokens */
- printf(
- "FIRST(DEFAULT ,apple ,banana ,cherry) = %s\n"
- ,XSTR(FIRST(DEFAULT ,apple ,banana ,cherry))
- );
- printf(
- "SECOND(DEFAULT ,apple ,banana ,cherry) = %s\n"
- ,XSTR(SECOND(DEFAULT ,apple ,banana ,cherry))
- );
- printf(
- "THIRD(DEFAULT ,apple ,banana ,cherry) = %s\n"
- ,XSTR(THIRD(DEFAULT ,apple ,banana ,cherry))
- );
-
- printf("test default\n");
-
- printf(
- "FIRST(DEFAULT) = %s\n"
- ,XSTR(FIRST(DEFAULT))
- );
- printf(
- "FIRST(DEFAULT ,apple) = %s\n"
- ,XSTR(FIRST(DEFAULT ,apple))
- );
- printf(
- "SECOND(DEFAULT ,apple) = %s\n"
- ,XSTR(SECOND(DEFAULT ,apple))
- );
- printf(
- "THIRD(DEFAULT ,apple) = %s\n"
- ,XSTR(THIRD(DEFAULT ,apple))
- );
-
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-
-#include "macro_logic.c"
-
-#define STR(x) #x
-#define XSTR(x) STR(x)
-
-/*===========================================================================
-Example Program
-===========================================================================*/
-int main(void) {
- /* For testing purposes, we print the macro expansion results as strings.
- (Because TRUE and FALSE have no numeric value, we rely on stringized output.)
- */
- printf("TRUE: %s\n", XSTR(TRUE));
-
- printf("FIRST(a,b,c) = %s\n", XSTR( FIRST(0 ,a ,b ,c) ));
- printf("FIRST(a,b,c) = %s\n", XSTR( FIRST(DEFER3(PAIR)() ,a ,b, ,c) ));
-
- printf("FIRST() = %s\n", XSTR( FIRST(7) ));
- printf("FIRST() = %s\n", XSTR( FIRST(PAIR()) ));
- printf("FIRST() = %s\n", XSTR( FIRST(DEFER3(PAIR)()) ));
-
-
-#if 0
-
-
- printf("EXIST() = %s\n", XSTR(EXIST()));
- printf("EXIST(a) = %s\n", XSTR(EXIST(a)));
-
- printf("NOT_EXIST(TRUE) = %s\n", XSTR(NOT_EXIST(TRUE)));
- printf("EXIST(FALSE) = %s\n", XSTR(EXIST(FALSE)));
- printf("NOT_EXIST(FALSE) = %s\n", XSTR(NOT_EXIST(FALSE)));
-
- printf("BOOL(TRUE) = %s\n", XSTR(BOOL(TRUE)));
- printf("BOOL(FALSE) = %s\n", XSTR(BOOL(FALSE)));
-
- printf("EQUAL(TRUE, TRUE) = %s\n", XSTR(EQUAL(TRUE, TRUE)));
- printf("EQUAL(FALSE, FALSE) = %s\n", XSTR(EQUAL(FALSE, FALSE)));
- printf("EQUAL(TRUE, FALSE) = %s\n", XSTR(EQUAL(TRUE, FALSE)));
-
- printf("IF_ELSE(TRUE)(Yes)(No) = %s\n", XSTR(IF_ELSE(TRUE)(Yes)(No)));
- printf("IF_ELSE(FALSE)(Yes)(No) = %s\n", XSTR(IF_ELSE(FALSE)(Yes)(No)));
-
-
-#endif
- return 0;
-}
+++ /dev/null
-/*===========================================================================
- Force extra macro expansion (the EVAL trick)
- This chain of EVAL macros forces the preprocessor to perform many rescans,
- which is necessary to “unroll” recursive macros.
-===========================================================================*/
-#define EVAL(...) EVAL1024(__VA_ARGS__)
-#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))
-#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__))
-#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__))
-#define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__))
-#define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__))
-#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__))
-#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))
-#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__))
-#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__))
-#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))
-#define EVAL1(...) __VA_ARGS__
-
-/*===========================================================================
- Defer macros: these help “hide” recursive calls for additional expansion passes.
-===========================================================================*/
-#define EMPTY()
-#define DEFER1(m) m EMPTY()
-#define DEFER2(m) m EMPTY EMPTY()()
-#define DEFER3(m) m EMPTY EMPTY EMPTY()()()
-#define DEFER4(m) m EMPTY EMPTY EMPTY EMPTY()()() /* as needed */
-
-
-/*===========================================================================
- Defer macros: these help “hide” recursive calls for additional expansion passes.
-===========================================================================*/
-
-#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 */)
+++ /dev/null
-/* macro_lib.c */
-#ifndef MACRO_LIB
-#define MACRO_LIB
-
-/*===========================================================================
- Some Basics
-===========================================================================*/
-
-#define COMMA ,
-
-#define _FIRST(a,...) a
-#define FIRST(...) _FIRST(__VA_ARGS__,~)
-
-#define _SECOND(a,b,...) b
-#define SECOND(...) _SECOND(__VA_ARGS__,~,~)
-
-
-/*===========================================================================
- Force extra macro expansion (the EVAL trick)
- This chain of EVAL macros forces the preprocessor to perform many rescans,
- which is necessary to “unroll” recursive macros.
-===========================================================================*/
-#define EVAL(...) EVAL1024(__VA_ARGS__)
-#define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__))
-#define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__))
-#define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__))
-#define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__))
-#define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__))
-#define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__))
-#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))
-#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__))
-#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__))
-#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))
-#define EVAL1(...) __VA_ARGS__
-
-/*===========================================================================
- Defer macros: these help “hide” recursive calls for additional expansion passes.
-===========================================================================*/
-#define EMPTY()
-#define DEFER1(m) m EMPTY()
-#define DEFER2(m) m EMPTY EMPTY()()
-#define DEFER3(m) m EMPTY EMPTY EMPTY()()()
-#define DEFER4(m) m EMPTY EMPTY EMPTY EMPTY()()() /* as needed */
-
-/*===========================================================================
- 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 */)
-
-#define Ξ(...) CAT(·,__VA_ARGS__)
-#define Append(...) CAT(COMMA,__VA_ARGS__)
-
-
-/*===========================================================================
- Put a 'PROBE()' in a list then detect it later.
-
- If a single value is given to IS_PROBE it won't have a second member,but
- if the two element PROBE is given,the second element will be 1.
-
-===========================================================================*/
-
-#define PROBE() ~,1
-
-#define __IS_PROBE(a,b,...) b
-#define _IS_PROBE(...) __IS_PROBE(__VA_ARGS__,0,0)
-#define IS_PROBE(...) _IS_PROBE(__VA_ARGS__)
-
-#define _NOT_0 PROBE()
-
-// x == 0: _NOT_##x -> _NOT_0 -> ~,1 -> 1
-// x == 1: _NOT_##x -> _NOT_1 -> 0
-//
-#define _NOT(x) IS_PROBE(_NOT_##x)
-#define NOT(x) _NOT(x)
-#define BOOL(x) NOT(NOT(x))
-
-// This is a rewrite rule,if there is a definition for _IS_EQ_<x>_<y> it is replaced by its #define definition,presumably that of a Probe.
-// The rule will then be #define _IS_EQ_<X>_<X> Probe()
-#define _EQUAL_REWRITE(x,y) IS_PROBE( CAT(_IS_EQ_,x,_##y) )
-
-#define EQUAL(x,y) BOOL( _EQUAL_REWRITE(x,y) )
-
-
-/*===========================================================================
- IF-ELSE construct.
- Usage: IF_ELSE(condition)(<true case>)(<false case>)
-===========================================================================*/
-#define IF_ELSE(condition) _IF_ELSE(BOOL(condition))
-#define _IF_ELSE(condition) CAT(_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__
-
-/*===========================================================================
- HAS_ARGS: tests whether a variadic argument list is empty.
-
- A bit of a tricky one, _END_OF_ARGUMENTS will only be expanded if it
- is followed by parenthesis,otherwise it is taken literally.
-===========================================================================*/
-#define _END_OF_ARGUMENTS_() 0
-#define HAS_ARGS(...) BOOL(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)())
-
-/*===========================================================================
- 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)
-
-#define MATCH(x,list) EVAL(MATCH_IMPL(x,list))
-
-/* End of macro_lib.c */
-#endif
+++ /dev/null
-/*===========================================================================
-Constants
-===========================================================================*/
-
-#define COMMA ,
-#define SEMICOLON ;
-
-#define _REWRITE__·FALSE
-#define _REWRITE__·TRUE__EQ__·TRUE
-#define _REWRITE__·FALSE__EQ__·FALSE
-
-
-#define rewrite_rule ·FALSE
-#define rewrite_ be_true(
-#define _rule )
-#define be_true(...) ·TRUE
-
-/*===========================================================================
-Access
-===========================================================================*/
-
-#define FIRST_1(a ,...) a
-#define FIRST(pad ,...) FIRST_1(__VA_ARGS__ ,pad)
-
-#define SECOND_1(a ,b ,...) b
-#define SECOND(pad ,...) SECOND_1(__VA_ARGS__ ,pad)
-
-#define THIRD_1(a ,b ,c,...) c
-#define THIRD(pad ,...) THIRD_1(__VA_ARGS__ ,pad ,pad)
-
-
-/*===========================================================================
- Defer macros: these help “hide” recursive calls for additional expansion passes.
-===========================================================================*/
-#define EMPTY()
-#define DEFER1(m) m EMPTY()
-#define DEFER2(m) m EMPTY EMPTY()()
-#define DEFER3(m) m EMPTY EMPTY EMPTY()()()
-#define DEFER4(m) m EMPTY EMPTY EMPTY EMPTY()()() /* as needed */
-
-/*===========================================================================
- Two Token concatenation, with optional separator
-===========================================================================*/
-
-#define CAT2(sep,a,b) a##sep##b
-
-
-/*===========================================================================
-LOGIC
-===========================================================================*/
-
-/*
- This is deterministic, and free from possible aliasing with the arguments.
- It does not require that ·TRUE or ·FALSE not be in the data.
-
- No Default value is needed for SECOND, as there will always be at least two
- tokens in `x ,·TRUE`
-
- 1. When __VA_ARGS__ is empty, FIRST returns the default value of `<empty>,·FALSE` for
- `x`. This makes x into a two token value, and the argument list for SECOND will be:
-
- `<empty> ,·FALSE ,·TRUE.
-
- So the SECOND value is ·FALSE.
-
- 2. When __VA_ARGS__ is not empty, it sends a single value of x, so the argument list
- for SECOND will be:
-
- x ,·TRUE.
-
- So the second value will be ·TRUE
-*/
-
-
-
-
-
-
-#define PAIR() ~,·FALSE
-
-#define EXIST_1(x) FIRST(~ ,x ,·TRUE)
-#define EXIST(...) EXIST_1( \
- FIRST( \
- DEFER3(PAIR)() \
- ,__VA_ARGS__ \
- ))
-
-#define NOT_EXIST_1(x) SECOND(,x ,·FALSE)
-#define NOT_EXIST(...) NOT_EXIST_1( \
- FIRST( \
- DEFER1(CAT2)(,·TRUE) \
- ,__VA_ARGS__ \
- ))
-
-// `NOT_1` Returns a ·TRUE, or ·FALSE
-#define NOT_1(x) NOT_EXIST(_REWRITE__##x)
-#define NOT(x) NOT_1(x)
-
-#define BOOL_1(x) EXIST(_REWRITE__##x)
-#define BOOL(x) BOOL_1(x)
-
-#define EQUAL_1(x ,y) NOT_EXIST_1( _REWRITE__##x__EQ__##y )
-#define EQUAL(x ,y) EQUAL_1(x ,y)
-
-
-/*===========================================================================
- IF-ELSE construct.
- Usage: IF_ELSE(condition)(<true case>)(<false case>)
-===========================================================================*/
-#define IF_ELSE(condition) _IF_ELSE(BOOL(condition))
-#define _IF_ELSE(condition) CAT(_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__
-
-
+++ /dev/null
-#include <stdio.h>
-#include "macro_lib.c"
-
-/* Helper macros to turn expanded results into strings.
- Note that STR(x) simply stringizes x without expanding it.
- XSTR(x) expands x first (if possible) and then stringizes it.
- We use EVAL to force full expansion before stringizing.
-*/
-
-#define STR(x) #x
-#define XSTR(x) STR(x)
-#define ESTR(x) XSTR(EVAL(x))
-
-/* --- Example Usage --- */
-
-/* Test 1: FIRST and SECOND */
-int main(void) {
- printf("macro_use.c\n");
-
- printf("FIRST(dog ,cat) = %s\n" ,ESTR(FIRST(dog ,cat)));
-
- printf("SECOND(dog ,cat) = %s\n" ,ESTR(SECOND(dog ,cat)));
- printf("SECOND(dog) = %s\n" ,ESTR(SECOND(dog)));
-
- printf("_IS_PROBE(dog ,cat) = %s\n" ,ESTR(_IS_PROBE(dog ,cat)));
- printf("_IS_PROBE(dog) = %s\n" ,ESTR(_IS_PROBE(dog)));
-
- /* Test 2: CAT with no separator and with COMMA */
- printf( "CAT( x ,dog ,cat ,parakeet) = %s\n" ,ESTR(CAT( ,dog ,cat ,parakeet)) );
-
- printf( "CAT( ,dog ,cat ,parakeet) = %s\n" ,ESTR(EVAL(CAT( ,dog ,cat ,parakeet))) );
-
-
-#if 0
-
- printf("CAT(COMMA ,dog ,cat ,parakeet) = %s\n" ,ESTR(CAT(COMMA ,dog ,cat ,parakeet)));
-
- /* Test 3: Xi macro (using a center dot as separator) */
- printf("Ξ(foo ,bar) = %s\n" ,ESTR(Ξ(foo ,bar)));
-
- /* Test 4: Append macro (using COMMA as separator) */
- printf("Append(dog ,cat) = %s\n" ,ESTR(Append(dog ,cat)));
- printf("Append(dog) = %s\n" ,ESTR(Append(dog)));
-
- /* Test 5: MATCH macro */
- /* Define a static list of animals */
- #define static_animals dog,cat,parakeet
- /* Register equality for tokens that will be compared */
- #undef _IS_EQ_dog_dog
- #undef _IS_EQ_cat_cat
- #undef _IS_EQ_parakeet_parakeet
- #define _IS_EQ_dog_dog PROBE()
- #define _IS_EQ_cat_cat PROBE()
- #define _IS_EQ_parakeet_parakeet PROBE()
- #define _IS_EQ_lizard_lizard PROBE() /* lizard is not in the list */
-
- printf("MATCH(dog ,static_animals) = %s\n" ,ESTR(MATCH(dog ,static_animals)));
- printf("MATCH(cat ,static_animals) = %s\n" ,ESTR(MATCH(cat ,static_animals)));
- printf("MATCH(parakeet ,static_animals) = %s\n" ,ESTR(MATCH(parakeet ,static_animals)));
- printf("MATCH(lizard ,static_animals) = %s\n" ,ESTR(MATCH(lizard ,static_animals)));
-#endif
-
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-#include "macro_lib.c"
-
-/* A very simple base macro that expands to an integer literal */
-#define SIMPLE_MACRO1 549
-#define SIMPLE_MACRO2 7919
-
-/* Define a chain of macros that simply pass along the value.
- Each CALL_n() macro just calls the previous level.
-*/
-#define CALL1() SIMPLE_MACRO1
-#define CALL2a() CALL1 EMPTY() () + 3
-#define CALL2b() DEFER1(CALL1)() + 5
-
-int main(void) {
-
- printf( "SIMPLE_MACRO1 = %d\n", SIMPLE_MACRO1 );
- printf( "CALL1() = %d\n", EVAL(CALL1()) );
- printf( "CALL2a() = %d\n", EVAL(CALL2a()) );
- printf( "CALL2b() = %d\n", EVAL(CALL2b()) );
-
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-
-/*===========================================================================
- Force extra macro expansion (the EVAL trick)
- This chain of EVAL macros forces the preprocessor to perform many rescans,
- which is necessary to “unroll” recursive macros.
-===========================================================================*/
-#define EVAL(...) EVAL8(__VA_ARGS__)
-#define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__))
-#define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__))
-#define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__))
-#define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__))
-#define EVAL1(...) __VA_ARGS__
-
-/*===========================================================================
- Defer macros: these help “hide” recursive calls for additional expansion passes.
-===========================================================================*/
-#define EMPTY()
-#define DEFER1(m) m EMPTY()
-#define DEFER2(m) m EMPTY EMPTY()()
-#define DEFER3(m) m EMPTY EMPTY EMPTY()()()
-#define DEFER4(m) m EMPTY EMPTY EMPTY EMPTY()()() /* as needed */
-
-#define a(x) x + x
-#define b 7
-#define cat(x,y) EVAL(DEFER1(a)(x) * y)
-
-int main(void) {
- int result = cat(5, 7);
- printf("cat(5, 7) = %d\n", result);
- return 0;
-}
+++ /dev/null
-// try_macro_cat.c
-#include <stdio.h>
-#include "macro_cat.c"
-
-// Define test macros
-#define A Hello
-#define B World
-#define C 123
-#define D _XYZ
-#define EMPTY
-
-// Define some variables to test concatenation into identifiers
-int HelloWorld = 10;
-int Hello123 = 20;
-int Hello_XYZ = 30;
-int World = 40;
-
-int main(void) {
-
- // CAT(A,B) → HelloWorld
- printf("CAT(A,B): %d\n", CAT(A,B));
-
- // CAT(A,C) → Hello123
- printf("CAT(A,C): %d\n", CAT(A,C));
-
- // CAT(A,D) → Hello_XYZ
- printf("CAT(A,D): %d\n", CAT(A,D));
-
- // CAT(EMPTY,B) → World
- printf("CAT(EMPTY,B): %d\n", CAT(EMPTY,B));
-
- // CAT(A,EMPTY) → Hello (must define int Hello)
- // Uncomment after defining: int Hello = 50;
- // printf("CAT(A,EMPTY): %d\n", CAT(A,EMPTY));
-
- // Nested concatenation: CAT(CAT(A,EMPTY),B) → HelloWorld
- // Uncomment after defining int Hello = ...;
- // printf("CAT(CAT(A,EMPTY),B): %d\n", CAT(CAT(A,EMPTY),B));
-
- return 0;
-}
+++ /dev/null
-#include <stdio.h>
-
-#define STR(x) #x
-#define XSTR(x) STR(x)
-
-#define mess(...) rewrite_##__VA_ARGS__##_rule
-
-int main(){
-
- printf("a mess %s\n" ,XSTR(mess(1)));
- printf("a mess %s\n" ,XSTR(mess(2)));
- printf("a mess %s\n" ,XSTR(mess(1,2)));
-
-}
-
-/*
-
- It does not like it when I send 2 parameters into mess.
-
- > gcc try_pasting.c
-try_pasting.c: In function ‘main’:
-try_pasting.c:12:1: error: macro "STR" passed 2 arguments, but takes just 1
- 12 | printf("a mess %s\n" ,XSTR(mess(1,2)));
- | ^ ~~~~
-try_pasting.c:3:9: note: macro "STR" defined here
- 3 | #define STR(x) #x
- | ^~~
-try_pasting.c:4:17: error: ‘STR’ undeclared (first use in this function)
- 4 | #define XSTR(x) STR(x)
- | ^~~
-try_pasting.c:12:25: note: in expansion of macro ‘XSTR’
- 12 | printf("a mess %s\n" ,XSTR(mess(1,2)));
- | ^~~~
-try_pasting.c:4:17: note: each undeclared identifier is reported only once for each function it appears in
- 4 | #define XSTR(x) STR(x)
- | ^~~
-try_pasting.c:12:25: note: in expansion of macro ‘XSTR’
- 12 | printf("a mess %s\n" ,XSTR(mess(1,2)));
- | ^~~~
-
-*./
#define D 7
-// Patch for _NOT_EMPTY to succeed on 0
+// Patch for _EXISTS to succeed on 0
#define _REWRITE_TWION_0 _REWRITE_TWION
int main(void){
printf("\n");
// Existence detection
- int empty = NOT_EMPTY_ITEM(); // → 1 (rewrite hits)
- int empty_0 = NOT_EMPTY_ITEM(0); // → 1 (rewrite hits)
- int empty_1 = NOT_EMPTY_ITEM(1); // → 0 (no rewrite)
- int empty_f = NOT_EMPTY_ITEM(hello); // → 0
-
- printf("NOT_EMPTY_ITEM() = %d\n", empty);
- printf("NOT_EMPTY_ITEM(0) = %d\n", empty_0);
- printf("NOT_EMPTY_ITEM(1) = %d\n", empty_1);
- printf("NOT_EMPTY_ITEM(hello) = %d\n", empty_f);
+ int empty = EXISTS_ITEM(); // → 1 (rewrite hits)
+ int empty_0 = EXISTS_ITEM(0); // → 1 (rewrite hits)
+ int empty_1 = EXISTS_ITEM(1); // → 0 (no rewrite)
+ int empty_f = EXISTS_ITEM(hello); // → 0
+
+ printf("EXISTS_ITEM() = %d\n", empty);
+ printf("EXISTS_ITEM(0) = %d\n", empty_0);
+ printf("EXISTS_ITEM(1) = %d\n", empty_1);
+ printf("EXISTS_ITEM(hello) = %d\n", empty_f);
printf("\n");
// Not Existence detection
- empty = EMPTY_ITEM(); // → 1 (rewrite hits)
- empty_0 = EMPTY_ITEM(0); // → 1 (rewrite hits)
- empty_1 = EMPTY_ITEM(1); // → 0 (no rewrite)
- empty_f = EMPTY_ITEM(hello); // → 0
-
- printf("EMPTY_ITEM() = %d\n", empty);
- printf("EMPTY_ITEM(0) = %d\n", empty_0);
- printf("EMPTY_ITEM(1) = %d\n", empty_1);
- printf("EMPTY_ITEM(hello) = %d\n", empty_f);
+ empty = NOT_EXISTS_ITEM(); // → 1 (rewrite hits)
+ empty_0 = NOT_EXISTS_ITEM(0); // → 1 (rewrite hits)
+ empty_1 = NOT_EXISTS_ITEM(1); // → 0 (no rewrite)
+ empty_f = NOT_EXISTS_ITEM(hello); // → 0
+
+ printf("NOT_EXISTS_ITEM() = %d\n", empty);
+ printf("NOT_EXISTS_ITEM(0) = %d\n", empty_0);
+ printf("NOT_EXISTS_ITEM(1) = %d\n", empty_1);
+ printf("NOT_EXISTS_ITEM(hello) = %d\n", empty_f);
printf("\n");
- // int empty_10 = NOT_EMPTY_ITEM(10,11,12); // illegal call, try it anyway ..compilation error
- int empty_11 = NOT_EMPTY(10,11,12); // this is a legal call
- int empty_12 = NOT_EMPTY();
+ // int empty_10 = EXISTS_ITEM(10,11,12); // illegal call, try it anyway ..compilation error
+ int empty_11 = EXISTS(10,11,12); // this is a legal call
+ int empty_12 = EXISTS();
- // printf("NOT_EMPTY_ITEM(10,11,12) = %d\n", empty_10);
- printf("NOT_EMPTY(10,11,12) = %d\n", empty_11);
- printf("NOT_EMPTY() = %d\n", empty_12);
+ // printf("EXISTS_ITEM(10,11,12) = %d\n", empty_10);
+ printf("EXISTS(10,11,12) = %d\n", empty_11);
+ printf("EXISTS() = %d\n", empty_12);
printf("\n");
- // int empty_10 = NOT_EMPTY_ITEM(10,11,12); // illegal call, try it anyway ..compilation error
- empty_11 = EMPTY(10,11,12); // this is a legal call
- empty_12 = EMPTY();
+ // int empty_10 = EXISTS_ITEM(10,11,12); // illegal call, try it anyway ..compilation error
+ empty_11 = NOT_EXISTS(10,11,12); // this is a legal call
+ empty_12 = NOT_EXISTS();
- // printf("EMPTY_ITEM(10,11,12) = %d\n", empty_10);
- printf("EMPTY(10,11,12) = %d\n", empty_11);
- printf("EMPTY() = %d\n", empty_12);
+ // printf("NOT_EXISTS_ITEM(10,11,12) = %d\n", empty_10);
+ printf("NOT_EXISTS(10,11,12) = %d\n", empty_11);
+ printf("NOT_EXISTS() = %d\n", empty_12);
printf("\n");
_FIRST(11 ,22 ,33) = 11
_SECOND(11 ,22 ,33) = 22
- NOT_EMPTY_ITEM() = 0
- NOT_EMPTY_ITEM(0) = 1
- NOT_EMPTY_ITEM(1) = 1
- NOT_EMPTY_ITEM(hello) = 1
+ EXISTS_ITEM() = 0
+ EXISTS_ITEM(0) = 1
+ EXISTS_ITEM(1) = 1
+ EXISTS_ITEM(hello) = 1
- EMPTY_ITEM() = 1
- EMPTY_ITEM(0) = 0
- EMPTY_ITEM(1) = 0
- EMPTY_ITEM(hello) = 0
+ NOT_EXISTS_ITEM() = 1
+ NOT_EXISTS_ITEM(0) = 0
+ NOT_EXISTS_ITEM(1) = 0
+ NOT_EXISTS_ITEM(hello) = 0
- NOT_EMPTY(10,11,12) = 1
- NOT_EMPTY() = 0
+ EXISTS(10,11,12) = 1
+ EXISTS() = 0
- EMPTY(10,11,12) = 0
- EMPTY() = 1
+ NOT_EXISTS(10,11,12) = 0
+ NOT_EXISTS() = 1
*/
//--------------------------------------------------------------------------
#define x0
- SHOW( NOT_EMPTY_ITEM(x0) ); // → 0 (assumed undefined)
- SHOW( EMPTY_ITEM(x0) ); // → 1
+ SHOW( EXISTS_ITEM(x0) ); // → 0 (assumed undefined)
+ SHOW( NOT_EXISTS_ITEM(x0) ); // → 1
printf("\n");
SHOW( MATCH(x0) );
SHOW( _BOOL(x0) ); // 0 because it does not exit (see the #define at the top)
printf("\n");
- SHOW( BOOL(0) ); // _FIRST = 0, NOT_EMPTY_ITEM(_FIRST) = 0 → _AND(0 ,1) → 0
- SHOW( BOOL(1) ); // NOT_EMPTY_ITEM(1) = 0 → BOOL = 0
- SHOW( BOOL(10) ); // NOT_EMPTY_ITEM(1) = 0 → BOOL = 0
- SHOW( BOOL() ); // NOT_EMPTY_ITEM(1) = 0 → BOOL = 0
- SHOW( BOOL(x0) ); // NOT_EMPTY_ITEM(1) = 0 → BOOL = 0
+ SHOW( BOOL(0) ); // _FIRST = 0, EXISTS_ITEM(_FIRST) = 0 → _AND(0 ,1) → 0
+ SHOW( BOOL(1) ); // EXISTS_ITEM(1) = 0 → BOOL = 0
+ SHOW( BOOL(10) ); // EXISTS_ITEM(1) = 0 → BOOL = 0
+ SHOW( BOOL() ); // EXISTS_ITEM(1) = 0 → BOOL = 0
+ SHOW( BOOL(x0) ); // EXISTS_ITEM(1) = 0 → BOOL = 0
printf("\n");
SHOW( NOT(0) ); // BOOL = 0 → NOT(0) = _NOT(0) = 1
2025-03-27T13:00:11Z[developer]
Thomas-developer@Stanley§/home/Thomas-masu/developer/N/developer/example§
> ./a.out
- NOT_EMPTY_ITEM(x0) --> 0
- EMPTY_ITEM(x0) --> 1
+ EXISTS_ITEM(x0) --> 0
+ NOT_EXISTS_ITEM(x0) --> 1
MATCH(x0) --> MATCH()
NOT_MATCH(x0) --> NOT_MATCH()
// NOTEQ Tests — inverse behavior
//---------------------------------------------------------------------------
- SHOW(NOT_EQ(0 ,0)); // Expected → 0 (because EQ → 1, so NOT_EMPTY → 0)
+ SHOW(NOT_EQ(0 ,0)); // Expected → 0 (because EQ → 1, so EXISTS → 0)
SHOW(NOT_EQ(1 ,1)); // Expected → 0
SHOW(NOT_EQ(0 ,1)); // Expected → 1
SHOW(NOT_EQ(1 ,0)); // Expected → 1
#include "cpp_ext_0.c"
#include "cpp_ext_1.c"
-#define LIST int ,float ,char ,void ,long
+#define LIST int ,float ,char ,void
-// Define a predicate macro: returns 1 if argument is "char"
-#define IS_char(x) _IS_char_##x
-#define _IS_char_char 1
+// register equality
+#define _RWR_EQ__int__oo__int
+#define _RWR_EQ__float__oo__float
+#define _RWR_EQ__char__oo__char
+#define _RWR_EQ__void__oo__void
+
+// make predicates
+#define IS_int(x) EQ(x ,int)
+#define IS_float(x) EQ(x ,float)
+#define IS_double(x) EQ(x ,double)
+#define IS_char(x) EQ(x ,char)
+#define IS_void(x) EQ(x ,void)
int main(void){
- //--------------------------------------------------------------------------
- // FIND — returns first matching element from the list
- //--------------------------------------------------------------------------
+#define BE(...) __VA_ARGS__
+
+ SHOW(IS_char(int));
+ SHOW(IS_char(char));
+ printf("\n");
+
+ SHOW( FIND(IS_char ,) );
+ SHOW( FIND(IS_char ,char) ); // → char
+ SHOW( FIND(IS_char ,int) ); // →
+ printf("\n");
+
+ SHOW( FIND(IS_char ,int ,void) ); // →
+ SHOW( FIND(IS_void ,int ,void) ); // →
+ printf("\n");
- // Use FIND to locate "char" in the list
- SHOW( FIND((LIST) ,IS_char) ); // → char
+ SHOW( FIND(IS_int ,LIST) );
+ SHOW( FIND(IS_float ,LIST) );
+ SHOW( FIND(IS_double ,LIST) );
+ SHOW( FIND(IS_char ,LIST) );
+ SHOW( FIND(IS_void ,LIST) );
+ SHOW( FIND(IS_big ,LIST) );
+ printf("\n");
- // 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)
+ //#endif
return 0;
}
+++ /dev/null
-#include <stdio.h>
-#include "cpp_ext_0.c"
-
-#define SHOW(x) printf(#x " = %s\n", x)
-
-#define STRINGIFY(x) #x
-#define EXPAND_STRING(x) STRINGIFY(x)
-
-int main(void){
- //---------------------------------------------------------------------------
- // FIRST with pad fallback
- //---------------------------------------------------------------------------
- SHOW(EXPAND_STRING(FIRST(none))); // → none
- SHOW(EXPAND_STRING(FIRST(pad ,x))); // → x
- SHOW(EXPAND_STRING(FIRST(pad ,x ,y ,z))); // → x
-
- //---------------------------------------------------------------------------
- // SECOND with pad fallback
- //---------------------------------------------------------------------------
- SHOW(EXPAND_STRING(SECOND(pad))); // → pad
- SHOW(EXPAND_STRING(SECOND(pad ,a))); // → pad
- SHOW(EXPAND_STRING(SECOND(pad ,a ,b))); // → b
- SHOW(EXPAND_STRING(SECOND(pad ,a ,b ,c))); // → b
-
- //---------------------------------------------------------------------------
- // THIRD with pad fallback
- //---------------------------------------------------------------------------
- SHOW(EXPAND_STRING(THIRD(pad))); // → pad
- SHOW(EXPAND_STRING(THIRD(pad ,a))); // → pad
- SHOW(EXPAND_STRING(THIRD(pad ,a ,b))); // → pad
- SHOW(EXPAND_STRING(THIRD(pad ,a ,b ,c))); // → c
- SHOW(EXPAND_STRING(THIRD(pad ,a ,b ,c ,d))); // → c
-
- //---------------------------------------------------------------------------
- // REST returns the tail after the first item
- //---------------------------------------------------------------------------
- SHOW(EXPAND_STRING(REST())); // → (empty)
- SHOW(EXPAND_STRING(REST(a))); // → (empty)
- SHOW(EXPAND_STRING(REST(a ,b))); // → b
- SHOW(EXPAND_STRING(REST(a ,b ,c))); // → b ,c
-
- return 0;
-}