documents in $REPO_HOME/developer/documentπ
-1. Provides:
+1. We use a truth of existence
- Raw constants: ZERO, ONE, COMMA, SEMICOLON
+ An empty value is false. Anything else is true. Hence, even the token '0' is true.
- Token tagging: _TWION_0, _TWION_1
+2. todo
- 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, 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, NOT() would then be 'true'
-
-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
+- cpp_ext as separate project
+- make the try into tests
*/
#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 EQ__0__oo__0
-#define 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
-===========================================================================*/
+Fixed arg count concatenation
+
+ Not implemented for elegance, rather CAT is used to force evaluation of arguments before `##`.
+*/
#define _CAT2(a ,b) a ## b
#define CAT2(a ,b) _CAT2(a ,b)
#define CAT4(a ,b ,c ,d) _CAT4(a ,b ,c ,d)
/*===========================================================================
-Existence
-===========================================================================*/
+LOGIC
+
+ empty - false
+ NOT() - not empty, is true
+*/
//----------------------------------------
// primitive access
- // note: _FIRST(), means passing an empty_item as the first item
- // so it will return empty.
+ // _FIRST with zero arguments returns nothing, otherwise returns first token
+ // in the list, which can also be nothing. e.g. _FIRST(,2,3) returns nothing.
#define _FIRST(a ,...) a
+
+ // _SECOND must be given a list of length 2, though no tokens need be given
#define _SECOND(a ,b ,...) b
//----------------------------------------
- // existence
+ // given one or zero arguments, returns nothing
//
- // `##` 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 RETURN_NOTHING()
- #define EXISTS_ITEM(x_item) _EXISTS_ITEM_1(x_item)
- #define EXISTS(...) EXISTS_ITEM( _FIRST(__VA_ARGS__) )
+ //----------------------------------------
+ // given a list returns a token
+ // given an token returns a token
+ // given nothing, returns nothing
+ //
+ #define _OR(...) _FIRST(RETURN_NOTHING __VA_ARGS__ ())
+
+ /*----------------------------------------
+ given a token returns nothing
+ given nothing returns 1
+
+ `##` prevents rewrite of _TWION_ in the _EXISTS_TOKEN_1 macro, don't
+ replace that with CAT!
+ */
+ #define _NOT_TOKEN_ss(x_token) _SECOND(x_token ,)
+ #define _NOT_TOKEN_s(x_token) _NOT_TOKEN_ss(_TWION_1##x_token)
+ #define _NOT_TOKEN(x_token) _NOT_TOKEN_s(x_token)
+
+ /*----------------------------------------
+ given a token or a list, returns nothing
+ given nothing, returns 1
+ */
+ #define NOT(...) _NOT_TOKEN( _OR(__VA_ARGS__) )
+
+ /*----------------------------------------
+ given argument is empty returns empty
+ given argument is not empty, returns 1
+ */
+ #define EXISTS(...) NOT( NOT(__VA_ARGS__) )
+
+ // useful synonym
+ #define MATCH_RWR(x) NOT(x)
- #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)
+/*===========================================================================
+ IF-ELSE construct.
+ Usage: IF_ELSE(condition)(<true case>)(<false case>)
- #define NOT_EXISTS_ITEM(x_item) _NOT_EXISTS_ITEM_1(x_item)
- #define NOT_EXISTS(...) NOT_EXISTS_ITEM( _FIRST(__VA_ARGS__) )
+ A most amazing little macro. It has no dependencies on the other macros
+ in this file, though many of those will be useful in predicates
+*/
- // 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)
+ #define IF(...) CAT2(_IF_ ,EXISTS(__VA_ARGS__))
+ #define _IF_1(...) __VA_ARGS__ _IF_1_ELSE
+ #define _IF_(...) _IF__ELSE
+ #define _IF_1_ELSE(...)
+ #define _IF__ELSE(...) __VA_ARGS__
/*===========================================================================
-Logic Connectors
-===========================================================================*/
- #define _NOT(x_item) \
- MATCH_RWR( CAT2(_RWR_NOT__ ,x_item) )
+ In cpp_ext logic:
+ Ξ΅ is false and anything else is true
+
+ In BOOLEAN logic
+ Ξ΅ is an error, 0 is false, anything else is true
- #define _AND(x_item ,y_item) \
- MATCH_RWR( CAT4(_RWR_AND__ ,x_item ,__oo__ ,y_item) )
+ USE this operator to convert something in cpp_ext logic to something for
+ the built-in operators.
- #define _OR(x_item ,y_item) \
- NOT_MATCH_RWR( CAT4(_RWR_OR__ ,x_item ,__oo__ ,y_item) )
+ Note the output of BOOLEAN is always an existing token, so it will
+ aways be 'true' in cpp_ext logic.
+
+*/
+ #define BOOLEAN(...) IF(__VA_ARGS__) (1) (0)
- #define _BOOL(x_item) \
- _AND( \
- EXISTS_ITEM( x_item ) \
- ,NOT_MATCH_RWR( CAT2(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
+ Logic connectors
+*/
+ #define LEQ2(x ,y) IF(x) (y) (NOT(y))
+ #define XOR2(x ,y) IF(x) (NOT(y)) (y)
+ #define AND2(x ,y) IF(x) (y) ()
+ #define OR2(x ,y) IF(x) (1) (y)
+
+
+/*===========================================================================
+ Registered Equivalence
- more general than a connector because more rules can be added.
+ Checks if x and y have been paired in a rewrite rule.
- each registered equality rule has the form
+ Logic values can not be paired, as anything except an empty argument is taken as true.
+
+ each pairing rule has the form
EQ__<x>__oo__<y>
- for example, logic equalities are already registered:
- EQ__0__oo__0
- EQ__1__oo__1
-===========================================================================*/
+ for example:
+ #define EQ__APPLE__oo__APPLE
+ #define EQ__PEAR__oo__PEAR
- #define EQ(x_item ,y_item) \
- MATCH_RWR( CAT4(EQ__ ,x_item ,__oo__ ,y_item) )
+ SHOW( EQ(APPLE ,APPLE) ); -> 1
+ SHOW( EQ(APPLE ,PEAR) ); -> Ξ΅
- #define NOT_EQ(x_item ,y_item) \
- NOT_MATCH_RWR( CAT4(EQ__ ,x_item ,__oo__ ,y_item) )
+ // if empty should be EQ to empty, add this
+ // without this, EQ(,) -> Ξ΅
+ #define EQ____oo__
-/*===========================================================================
- 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)
+ // if empty should be EQ to empty, keep this
+ // without this, EQ(,) -> Ξ΅
+ #define EQ____oo__
- 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 EQ__0__oo__0
+ #define EQ__1__oo__1
- #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__
+ #define EQ(x_token ,y_token) MATCH_RWR( CAT4(EQ__ ,x_token ,__oo__ ,y_token) )
/*===========================================================================
-Access
- see ext_1 with recursion for `Nth`
-
+Remainder of list
===========================================================================*/
- // _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) )
+ (__VA_ARGS__) \
+ ( _REST(__VA_ARGS__) ) \
+ ()
#endif
+/*
+ _FIRST(1) -> 1
+ _FIRST() ->
+ _SECOND(1,2) -> 2
+ _SECOND(1,) ->
+
+ RETURN_NOTHING() ->
+
+ _OR() ->
+ _OR(1) -> RETURN_NOTHING 1 ()
+ _OR(1,2,3) -> RETURN_NOTHING 1
+
+ T(x) -> 7
+ _NOT_ITEM() -> _NOT_ITEM()
+ _NOT_ITEM(1) -> _NOT_ITEM(1)
+ _NOT_ITEM(T(x)) -> _NOT_ITEM(7)
+
+ NOT() -> 1
+ NOT(1) ->
+ NOT(T(x)) ->
+ NOT(1,2,3) ->
+
+ BOOL() -> BOOL()
+ CAT2(_IF_ ,BOOL()) -> _IF_BOOL()
+
+ TO_1_OR_0() -> TO_1_OR_0()
+ TO_1_OR_0(1) -> TO_1_OR_0(1)
+ TO_1_OR_0(x) -> TO_1_OR_0(x)
+ TO_1_OR_0(1.2.3) -> TO_1_OR_0(1.2.3)
+
+ EXISTS() ->
+ EXISTS(0) -> 1
+ EXISTS(x,y,z) -> 1
+
+ LEQ2( , ) -> 1
+ LEQ2( , 1 ) ->
+ LEQ2( 1, ) ->
+ LEQ2( 1, 0 ) -> 0
+
+ XOR2( , ) ->
+ XOR2( , 0 ) -> 0
+ XOR2( 0, 0 ) ->
+
+ AND2( , 0 ) ->
+ AND2( 0, 1 ) -> 1
+
+ OR2( , ) ->
+ OR2( , 0 ) -> 0
+
+ EQ(APPLE ,APPLE) -> 1
+ EQ(APPLE ,PEAR) ->
+ EQ(PEAR ,PEAR) -> 1
+ EQ(,) -> 1
+ EQ(,PEAR) ->
+ EQ(PEAR ,) ->
+
+ BOOLEAN() -> 0
+ BOOLEAN(0) -> 1
+ BOOLEAN(foo) -> 1
+ BOOLEAN(1,2,3) -> 1
+
+ REST() ->
+ REST(1) ->
+ REST(1,2) -> 2
+ REST(1,2,3) -> 2,3
+*/
LIST_TOO_LONG
-// scanning left to right finds first that exists
-LEFTMOST_EXISTENT
+cleanup list
+DROP_EMPTY_ALL
+DROP_EMPTY_LEFT
+DROPE_EMPTY_RIGHT
-// 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,...) \
+#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(...) 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__
+ //#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()()()()
+// defined in cpp_ext_0: RETURN_NOTHING()
+
+ #define DEFER1(m) \
+ m RETURN_NOTHING()
+ #define DEFER2(m) \
+ m RETURN_NOTHING RETURN_NOTHING()()
+ #define DEFER3(m) \
+ m RETURN_NOTHING RETURN_NOTHING RETURN_NOTHING()()()
+ #define DEFER4(m) \
+ m RETURN_NOTHING RETURN_NOTHING RETURN_NOTHING RETURN_NOTHING()()()()
+ #define DEFER5(m) \
+ m RETURN_NOTHING RETURN_NOTHING RETURN_NOTHING RETURN_NOTHING RETURN_NOTHING()()()()()
/*===========================================================================
- Quantifiers
-===========================================================================*/
+ Find an item in a list
+
+ number of EVALs required depends upon length of not found list prefix
+
+ REST will return nothing on one of two conditions, that the list has
+ been exhausted, or that the list is about to exhausted, it has nothing
+ after the last comma. To assure that a tailing item always gets sent
+ to the predicate, even when empty, we append an empty item.
-#define _FIND(predicate ,...) \
+===========================================================================*/
+ // defined in cpp_ext_0: _FIRST(a ,...) a
+
+ // returns found item or EOL()
+ #define _FIND(predicate ,...) \
+ IF \
+ (__VA_ARGS__) \
+ (IF \
+ ( predicate(_FIRST(__VA_ARGS__)) ) \
+ ( _FIRST(__VA_ARGS__) ) \
+ ( DEFER3(_FIND_CONFEDERATE)()(predicate ,REST(__VA_ARGS__)) ) \
+ ) \
+ (EOL())
+ #define _FIND_CONFEDERATE() _FIND
+ #define FIND(predicate ,...) EVAL( _FIND(predicate ,__VA_ARGS__ ,) )
+
+ // true if list exhausted, false otherwise
+ #define _WHILE(predicate ,...) \
+ IF \
+ (__VA_ARGS__) \
+ (IF \
+ ( predicate(_FIRST(__VA_ARGS__)) ) \
+ ( DEFER3(_WHILE_CONFEDERATE)()(predicate ,REST(__VA_ARGS__)) ) \
+ () \
+ ) \
+ (1)
+ #define _WHILE_CONFEDERATE() _WHILE
+ #define WHILE(predicate ,...) EVAL( _WHILE(predicate ,__VA_ARGS__ ,) )
+
+ // returns true or false
+ #define _HAS_ITEM(item ,...) \
+ IF \
+ (__VA_ARGS__) \
+ (IF \
+ ( EQ(item ,_FIRST(__VA_ARGS__)) ) \
+ ( 1 ) \
+ ( DEFER3(_HAS_ITEM_CONFEDERATE)()(item ,REST(__VA_ARGS__)) ) \
+ ) \
+ ()
+ #define _HAS_ITEM_CONFEDERATE() _HAS_ITEM
+ #define HAS_ITEM(predicate ,...) EVAL( _HAS_ITEM(predicate ,__VA_ARGS__ ,) )
+
+ // if no list, returns EOL(), else returns last item in the list
+ #define _LAST(...) \
+ IF \
+ (__VA_ARGS__) \
+ ( _LAST_s(_FIRST(__VA_ARGS__) ,REST(__VA_ARGS__)) ) \
+ (EOL())
+ #define _LAST_s(item, ...) \
+ IF \
+ (__VA_ARGS__) \
+ ( DEFER3(_LAST_s_CONFEDERATE)()(_FIRST(__VA_ARGS__) ,REST(__VA_ARGS__)) ) \
+ (item)
+ #define _LAST_s_CONFEDERATE() _LAST_s
+ #define LAST(...) EVAL( _LAST(__VA_ARGS__ ,) )
+
+ // join tokens with a separator in between, separator can have nothing as a value
+
+
+#define _CAT(sep ,...) \
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__) )
-
-#define _FIND_ITEM(item ,...) \
+ (__VA_ARGS__) \
+ (_CAT_s(sep ,__VA_ARGS__)) \
+ ()
+
+#define _CAT_s(sep ,a ,...) \
IF \
- ( NOT_EXISTS(__VA_ARGS__) ) \
- () \
- (IF \
- ( EQ(item ,FIRST(,__VA_ARGS__)) ) \
- ( item ) \
- ( DEFER3(_FIND_ITEM_CONFEDERATE) ()(item ,REST(__VA_ARGS__)) ) \
- )
-#define _FIND_ITEM_CONFEDERATE() _FIND_ITEM
-
-// number of evals required depends upon length of not found list prefix
-#define FIND_ITEM(predicate ,...) EVAL( _FIND_ITEM(predicate ,__VA_ARGS__) )
+ (__VA_ARGS__) \
+ ( CAT3( a ,sep ,DEFER5(_CAT_s_CONFEDERATE())(sep ,__VA_ARGS__)) ) \
+ (a)
+
+#define _CAT_s_CONFEDERATE() _CAT_s
+
+#define CAT(...) EVAL( _CAT(__VA_ARGS__ ,) )
+
+
+
+/*===========================================================================
+ Quantifiers
+===========================================================================*/
+
+ // AKA all quantification, returns true or false
+ #define AND(...) WHILE(EXISTS ,__VA_ARGS__)
+
+ // AKA existence quantification, returns true or false
+ #define OR(...) NOT(WHILE(NOT ,__VA_ARGS__)
+
+/*===========================================================================
+ Access
+===========================================================================*/
+ #define FIRST(...) \
+ IF( __VA_ARGS__ ) \
+ ( _FIRST(__VA_ARGS__) ) \
+ (EOL())
#endif
+++ /dev/null
-
-The twions do for cpp what complex numbers do for mathematics. A two dimensional value used with a structure designed for one dimensional values.
-
-/*
-Code in this file is based on: https://github.com/18sg/uSHET/blob/master/lib/cpp_magic.h
-see tutorial at: http://jhnet.co.uk/articles/cpp_magic
-
-----------------------------------------
-1. Issues
-
-1.1 Empty argument name is still a name
-
- `##` arguments are not evaluated so, for example:
- ```
- #define cat(x,y) x##y
- #define xx 3
- #define yy 5
- cat(xx,yy) --> xxyy
- ```
- xx and yy are not rewritten.
-
- For my cpp with an empty __VAR_ARGS__ is still acting like it exists with a##__VAR_ARGS__ as though it expands out to a##<empty>. To make the empty args empty, we must pass through from a macro that does not use `##` on them. I guess this also applies to
- other empty arguments. Thus <empty> is taken literally as were `xx` and `yy` in the
- example above, though it does not have a name as do `xx` and `yy`.
-
- Hence instead of calling
-
- #define IS_EMPTY_ITEM(x_item) _IS_EMPTY_2(_TWION_##x_item)
-
- We have
-
- #define _IS_EMPTY_1(x_item) _IS_EMPTY_2(_TWION_##x_item)
- #define IS_EMPTY_ITEM(x_item) _IS_EMPTY_1(x_item)
-
-1.1 function macro definition - no space between the macro name and the parameter
- list.
-
- #define sum(p ,q ,r) (p + q + r) // good
-
- #define sum (p ,q ,r) (p + q + r) // defines rewrite sum -> (p ,q ,r) (p + q + r)
-
-----------------------------------------
-2. cpp
-
-2.1 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.
-
-----------------------------------------
-3. Logic
-
- 2.1 Logic Values
-
- False: 0
- True: 1
-
- 2.2 One Item Arguments
-
- Some logic functions are required to be given a single item, i.e. to not be given a list.. This requirement is maintained by the manner they are used. For example, being passed a value gotten by FIRST.
-
- Macro arguments that must be single items are suffixed with `_item`.
-
-*/
-
-EMPTYNESS
-
-2. Empty argument list query
-
-2.1 if empty values are allowed for arguments
-
- There is a nuance when checking that a list is empty, because lists can
- have empty elements. E.g. `a ,b , ,d ,e` including leading elements or
- even all empty elements, e.g. `, , , ,`.
-
- Hence, if we use the first element to represent that a list argument is present, we might happen upon an empty first element. Even if we CAT all the elements for a long list of empty values, we can produce an empty element.
-
- We can not overload macro definitions with different argument counts, this is
- not allowed.
-
-2.2 when empty elements should not happen
-
- Fortunately, in many applications empty elements do not have meaning. In
- such applications, if the first element is not empty, we can we conclude
- there is a list, rather than an empty list.
-
- Access of the nth element is more fundamental than logic, so access can be
- used.
-
- Note this simplified implementation for SECOND:
-
- #define SECOND_1(a ,b ,...) b
- #define SECOND(...) SECOND_1(__VA_ARGS__, pad)
-
- Notice that if __VA_ARGS__ is empty, that it will become the empty
- `a` value in SECOND. Thus SECOND_1 will always be given at least
- one argument, even when SECOND is given no arguments!
-
- In contrast to access, the variadic CAT function relies upon having
- an predicate to detect emptiness so as to stop the recursion, so it
- is not possible to use to CAT all the elements of a list to see that
- some elements are not empty.
-
-2.3 Getting different behavior from an empty __VA_ARGS__ and a non-empty one.
-
- 2.3.1 peek-a-boo macro call
-
- The primary trick is this:
-
- macro __VA_ARGS__ ()
-
- The macro will only be called when it is followed by parens, so it will only be called when __VA_ARGS__ is empty. However when __VA_ARGS__ is not empty we have a mess. Say it is a,b,c. Then:
-
- macro a,b,c () -> macroa,b,c()
-
- That is three elements ending in a macro call `c()` which is surely unintentional.
- Suppose we instead do:
-
- macro FIRST(__VA_ARGS_) () -> macro a () -> macroa()
-
- Which is another macro call, though probably not one that is defined. If
- the first argument in the __VA_ARGS__ list is empty, then we are back to
- `macro()` - indistinguishable from a call with an empty argument list.
-
- 2.3.1 rewrite rule
-
- Another approach is to use a rewrite rule:
-
- #define rewrite_rule new_value
-
- then in the macro:
-
- rewrite __VA_ARGS__
-
- when __VARGS__ is empty:
-
- rewrite##__VA_ARGS__##rule -> rewrite_rule -> new_value
-
- when __VARGS__ is, say, a,b,c:
-
- rewrite##a,b,c##_rule -> rewritea,b,c_rule
-
- which is a rather messed up three item list. If we use FIRST on the middle
- string:
-
- -> rewritea_rule
-
- Which is a 1 element list.
-
- (Note, `##` is evaluate before the macro expansions.)
-
-
1. Macro function definition
+ Macro function definitions are not evaluated, so macro calls in them remain
+ literal.
+
A macro function has three parts, 1) a name 2) a parameter list 3) body
Parameters are declared by listing them between parenthesis after the name. No space
| 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.
+ This stands for nothing. It is useful for talking about item lists, because in general lists can have empty slots. Remember cpp works with literal text.
- 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.
+ For example, ( , ) is a length 2 list with two empty slots.
+
+ For example, (1,,2) is a length 3 three list with one empty slot.
+
+ On calls, the length of the arg_list must match length of the parameter list.
+
+ For example, _FIRST() has a first parameter that expands to nothing if it is referenced
+ #define _FIRST(a ,...) a
+ _FIRST() --> Ξ΅ is not a bad argument count error, but instead expands to nothing
- item = token | empty_item | shim_item
+ general_list = token (, token | Ξ΅)*
+ Comma-separated list of items. Commas can appear without tokens between them.
+
+ arg_list = general_list
+
+ pair = token | Ξ΅ , token | Ξ΅; exactly two tokens.
+
+ twion = pair
+ A special two-token list given to certain macros in a place one token is expected.
+ Its role is to shift the remaining members of a list by one position when prepended.
+ An honorary member of the single token club. A common twion is `~,1`
- arg_list = item (, item)* ; comma-separated list of items
+ parm_list = identifier (, identifier)* ; comma-separated list of identifiers
+ A parameter list differs from a general list in that two commas can not
+ appear adjacent to each other, and all members are identifiers.
- pair = item , item ; exactly two items
2.2 'private' identify
-These are direct built one at a time, for example:
+These examples are directly built one at a time, for example:
#+BEGIN_SRC bash
> gcc try_6_list.c
+++ /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, 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 EQ__0__oo__0
-#define 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(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
- EQ__<x>__oo__<y>
- for example, logic equalities are already registered:
- EQ__0__oo__0
- EQ__1__oo__1
-
-===========================================================================*/
-
- #define EQ(x_item ,y_item) \
- MATCH_RWR( CAT4(EQ__ ,x_item ,__oo__ ,y_item) )
-
- #define NOT_EQ(x_item ,y_item) \
- NOT_MATCH_RWR( CAT4(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__) )
-
-#define _FIND_ITEM(item ,...) \
- IF \
- ( NOT_EXISTS(__VA_ARGS__) ) \
- () \
- (IF \
- ( EQ(item ,FIRST(__VA_ARGS__)) ) \
- ( FIRST( ,__VA_ARGS__) ) \
- ( DEFER3(_FIND_ITEM_CONFEDERATE) ()(predicate ,REST(__VA_ARGS__)) ) \
- )
-#define _FIND_ITEM_CONFEDERATE() _FIND_ITEM
-
-// number of evals required depends upon length of not found list prefix
-#define FIND_ITEM(predicate ,...) EVAL( _FIND_ITEM(predicate ,__VA_ARGS__) )
-
-
-
-#endif
+++ /dev/null
-#include "../ccπ/cpp_ext_0.c"
-
-#define F 1
-#define O1 2
-#define O2 3
-#define B 4
-#define A 5
-#define R 6
-#define D 7
-
-
-// Patch for _EXISTS to succeed on 0
-#define _REWRITE_TWION_0 _REWRITE_TWION
-
-int main(void){
- printf("try_1_exists\n\n");
-
- // Constant macros
- int x COMMA y = 1; // Tests that COMMA = ,
- printf("y? %d\n", y);
- printf("\n");
-
- // Token paste test
- int _cat_result = CAT2(CAT3(F ,O1 ,O2) ,CAT4(B ,A ,R ,D));
- printf("FOOBARD %d\n" ,_cat_result);
- printf("\n");
-
- // Selector macros
- int first = _FIRST(11 ,22 ,33); // β 11
- int second = _SECOND(11 ,22 ,33); // β 22
- printf("_FIRST(11 ,22 ,33) = %d\n", first);
- printf("_SECOND(11 ,22 ,33) = %d\n", second);
- printf("\n");
-
- // Existence detection
- 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 = 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 = 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("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 = 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("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");
-
-
- return 0;
-}
-
-/*
- 2025-03-27T12:38:04Z[developer]
- Thomas-developer@StanleyΒ§/home/Thomas-masu/developer/N/developer/exampleΒ§
- > gcc try_1_exists.c
-
- 2025-03-27T12:40:32Z[developer]
- Thomas-developer@StanleyΒ§/home/Thomas-masu/developer/N/developer/exampleΒ§
- > ./a.out
- _CAT(FOO ,BAR) β 12345
-
- _FIRST(11 ,22 ,33) = 11
- _SECOND(11 ,22 ,33) = 22
-
- EXISTS_ITEM() = 0
- EXISTS_ITEM(0) = 1
- EXISTS_ITEM(1) = 1
- EXISTS_ITEM(hello) = 1
-
- NOT_EXISTS_ITEM() = 1
- NOT_EXISTS_ITEM(0) = 0
- NOT_EXISTS_ITEM(1) = 0
- NOT_EXISTS_ITEM(hello) = 0
-
- EXISTS(10,11,12) = 1
- EXISTS() = 0
-
- NOT_EXISTS(10,11,12) = 0
- NOT_EXISTS() = 1
-*/
+++ /dev/null
-#include "../ccπ/cpp_ext_0.c"
-
-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");
-
- //--------------------------------------------------------------------------
- // Logical Connectors (BOOL + AND/OR/NOT)
- //--------------------------------------------------------------------------
-
- printf("x0 is a macro with an empty definition");
-
- SHOW( _BOOL(0) ); // 0
- SHOW( _BOOL(1) ); // 1
- SHOW( _BOOL(2) ); // 1 because it exists
- SHOW( _BOOL(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");
-
- //--------------------------------------------------------------------------
- // Compound Connectors
- //--------------------------------------------------------------------------
-
- // Double NOT
- SHOW( NOT(NOT(0)) ); // β NOT(1) β _NOT(1) β 0
- SHOW( NOT(NOT(1)) ); // β NOT(0) β _NOT(0) β 1
-
- // Triple NOT
- SHOW( NOT(NOT(NOT(0))) ); // β NOT(0) β _NOT(0) β 1
- SHOW( NOT(NOT(NOT(1))) ); // β NOT(1) β _NOT(1) β 0
- printf("\n");
-
- // Nested AND
- SHOW( AND(1 ,AND(1 ,0)) ); // AND(1 ,AND(1 ,0)) β AND(1 ,0) β _AND(1 ,0) = 0
- SHOW( AND(1 ,AND(1 ,1)) ); // β AND(1 ,1) β _AND(1 ,1) = 1
- printf("\n");
-
- // Nested OR
- SHOW( OR(0 ,OR(0 ,1)) ); // β OR(0 ,1) β _OR(0 ,1) = 1
- SHOW( OR(0 ,OR(0 ,0)) ); // β OR(0 ,0) β _OR(0 ,0) = 0
- printf("\n");
-
- // Mixed nesting
- SHOW( AND(NOT(0) ,1) ); // β AND(1 ,1) β _AND(1 ,1) = 1
- SHOW( AND(NOT(1) ,1) ); // β AND(0 ,1) β _AND(0 ,1) = 0
- SHOW( OR(NOT(1) ,1) ); // β OR(0 ,1) β _OR(0 ,1) = 1
- SHOW( OR(NOT(0) ,0) ); // β OR(1 ,0) β _OR(1 ,0) = 1
- printf("\n");
-
- // Deep mix
- SHOW( NOT(AND(1 ,NOT(1))) ); // AND(1 ,0) = _AND(1 ,0) = 0 β NOT(0) = _NOT(0) = 1
- SHOW( NOT(OR(0 ,NOT(0))) ); // OR(0 ,1) = _OR(0 ,1) = 1 β NOT(1) = _NOT(1) = 0
- printf("\n");
-
- // Asymmetric nesting
- SHOW( AND(OR(0 ,1) ,AND(1 ,1)) ); // OR(0 ,1) = 1, AND(1 ,1) = 1 β AND(1 ,1) = 1
- SHOW( OR(AND(1 ,0) ,AND(1 ,1)) ); // AND(1 ,0) = 0, AND(1 ,1) = 1 β OR(0 ,1) = 1
- printf("\n");
-
- return 0;
-}
-/*
- 2025-03-27T12:59:39Z[developer]
- Thomas-developer@StanleyΒ§/home/Thomas-masu/developer/N/developer/exampleΒ§
- > gcc try_2_connectors.c
-
- 2025-03-27T13:00:11Z[developer]
- Thomas-developer@StanleyΒ§/home/Thomas-masu/developer/N/developer/exampleΒ§
- > ./a.out
- EXISTS_ITEM(x0) --> 0
- NOT_EXISTS_ITEM(x0) --> 1
-
- MATCH(x0) --> MATCH()
- NOT_MATCH(x0) --> NOT_MATCH()
-
- _NOT(0) --> 1
- _NOT(1) --> 0
-
- _AND(0 ,0) --> 0
- _AND(1 ,0) --> 0
- _AND(0 ,1) --> 0
- _AND(1 ,1) --> 1
- _AND(1 ,x) --> 0
-
- _OR(0 ,0) --> 0
- _OR(0 ,1) --> 1
- _OR(1 ,0) --> 1
- _OR(1 ,1) --> 1
-
- _EQ(0 ,0) --> 1
- _EQ(1 ,1) --> 1
- _EQ(0 ,1) --> 0
- _EQ(x ,x) --> 0
-
- _NOT_EQ(0 ,1) --> 1
- _NOT_EQ(0 ,0) --> 0
-
- _BOOL_2(0) --> 0
- _BOOL_2(1) --> 1
- _BOOL_2(2) --> 1
- _BOOL_2(x0) --> 0
-
- BOOL(0) --> 0
- BOOL(1) --> 1
- BOOL(10) --> 1
- BOOL() --> 0
- BOOL(x0) --> 0
-
- NOT(0) --> 1
- NOT(1) --> 0
- NOT() --> 1
- NOT(10) --> 0
-
- AND(1 ,0) --> 0
- AND(1 ,1) --> 1
-
- OR(0 ,0) --> 0
- OR(1 ,0) --> 1
-
- NOT(NOT(0)) --> 0
- NOT(NOT(1)) --> 1
- NOT(NOT(NOT(0))) --> 1
- NOT(NOT(NOT(1))) --> 0
-
- AND(1 ,AND(1 ,0)) --> 0
- AND(1 ,AND(1 ,1)) --> 1
-
- OR(0 ,OR(0 ,1)) --> 1
- OR(0 ,OR(0 ,0)) --> 0
-
- AND(NOT(0) ,1) --> 1
- AND(NOT(1) ,1) --> 0
- OR(NOT(1) ,1) --> 1
- OR(NOT(0) ,0) --> 1
-
- NOT(AND(1 ,NOT(1))) --> 1
- NOT(OR(0 ,NOT(0))) --> 0
-
- AND(OR(0 ,1) ,AND(1 ,1)) --> 1
- OR(AND(1 ,0) ,AND(1 ,1)) --> 1
-
-
- 2025-03-27T13:00:12Z[developer]
- Thomas-developer@StanleyΒ§/home/Thomas-masu/developer/N/developer/exampleΒ§
- >
-*/
-
-
+++ /dev/null
-#include "../ccπ/cpp_ext_0.c"
-
-int main(void){
-
- //---------------------------------------------------------------------------
- // EQ Tests β identity and mismatch
- //---------------------------------------------------------------------------
-
- SHOW(EQ(0 ,0)); // Expected β 1
- SHOW(EQ(1 ,1)); // Expected β 1
- SHOW(EQ(0 ,1)); // Expected β 0
- SHOW(EQ(1 ,0)); // Expected β 0
-
- SHOW(EQ(x ,x)); // Expected β 0 (no _RWREQ__x__oo__x defined)
- SHOW(EQ(x ,y)); // Expected β 0
-
- //---------------------------------------------------------------------------
- // NOTEQ Tests β inverse behavior
- //---------------------------------------------------------------------------
-
- 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
-
- SHOW(NOT_EQ(x ,x)); // Expected β 1 (EQ not defined β NOTEQ = 1)
- SHOW(NOT_EQ(x ,y)); // Expected β 1
-
- //---------------------------------------------------------------------------
- // Mixed cases with macros
- //---------------------------------------------------------------------------
-
- #define XSYM 0
- #define YSYM 1
-
- SHOW(EQ(XSYM ,XSYM)); // Expected β 1 (0,0)
- SHOW(EQ(XSYM ,YSYM)); // Expected β 0 (0,1)
- SHOW(NOT_EQ(XSYM ,YSYM)); // Expected β 1
-
- SHOW(EQ(XSYM ,0)); // Expected β 1
- SHOW(EQ(XSYM ,1)); // Expected β 0
-
- SHOW(NOT_EQ(YSYM ,0)); // Expected β 1
- SHOW(NOT_EQ(YSYM ,1)); // Expected β 0
-
- //---------------------------------------------------------------------------
- // Edge case: undefined symbol
- //---------------------------------------------------------------------------
-
- SHOW(EQ(z ,z)); // Expected β 0
- SHOW(NOT_EQ(z ,z)); // Expected β 1
-
- printf("\n");
- return 0;
-}
+++ /dev/null
-#include "../ccπ/cpp_ext_0.c"
-
-int main(void){
-
- //---------------------------------------------------------------------------
- // Basic boolean cases
- //---------------------------------------------------------------------------
-
- SHOW(IF_ELSE(1)(yes)(no));
- 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
- //---------------------------------------------------------------------------
- SHOW(
- IF_ELSE(AND(1 ,1))(
- IF_ELSE(0)(inner_true)(inner_false)
- )(
- outer_false
- )
- ); // β inner_false
- printf("\n");
-
- return 0;
-}
+++ /dev/null
-#include "../ccπ/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;
-}
+++ /dev/null
-#include "../ccπ/cpp_ext_0.c"
-#include "../ccπ/cpp_ext_1.c"
-
-#define LIST Integer ,Float ,Char ,Void
-
-// register equality
-#define EQ__Integer__oo__Integer
-#define EQ__Float__oo__Float
-#define EQ__Char__oo__Char
-#define EQ__Void__oo__Void
-
-// make predicates
-#define IS_Integer(x) EQ(x ,Integer)
-#define IS_Float(x) EQ(x ,Float)
-#define IS_Missing(x) EQ(x ,Missing)
-#define IS_Char(x) EQ(x ,Char)
-#define IS_Void(x) EQ(x ,Void)
-
-int main(void){
-
- SHOW(IS_Char(Integer));
- SHOW(IS_Char(Char));
- printf("\n");
-
- SHOW( FIND(IS_Char ,) );
- SHOW( FIND(IS_Char ,Char) );
- SHOW( FIND(IS_Char ,Integer) );
- printf("\n");
-
- SHOW( FIND(IS_Char ,Integer ,Void) );
- SHOW( FIND(IS_Void ,Integer ,Void) );
- printf("\n");
-
- SHOW( FIND(IS_Integer ,LIST) );
- SHOW( FIND(IS_Float ,LIST) );
- SHOW( FIND(IS_Missing ,LIST) );
- SHOW( FIND(IS_Char ,LIST) );
- SHOW( FIND(IS_Void ,LIST) );
- SHOW( FIND(IS_big ,LIST) ); // literal 'IS_big' will be seen as true
- printf("\n");
-
- SHOW( FIND_ITEM(Char ,) );
- SHOW( FIND_ITEM(Char ,Char) );
- SHOW( FIND_ITEM(Char ,Integer) );
- printf("\n");
-
- SHOW( FIND_ITEM(Char ,Integer ,Void) );
- SHOW( FIND_ITEM(Void ,Integer ,Void) );
- printf("\n");
-
- SHOW( FIND_ITEM(Integer ,LIST) );
- SHOW( FIND_ITEM(Float ,LIST) );
- SHOW( FIND_ITEM(Missing ,LIST) );
- SHOW( FIND_ITEM(Char ,LIST) );
- SHOW( FIND_ITEM(Void ,LIST) );
- SHOW( FIND_ITEM(big ,LIST) );
- printf("\n");
-
- return 0;
-}
--- /dev/null
+#include "../ccπ/cpp_ext_0.c"
+
+int main(void){
+ //--------------------------------------------------------------------------
+ // Existence Checks (sanity anchor)
+ //--------------------------------------------------------------------------
+
+ SHOW( _FIRST(1) );
+ SHOW( _FIRST() ); // returns nothing, as empty args are permitted
+ SHOW( _SECOND(1,2) );
+ // SHOW( _SECOND(1) ); // fails, as _SECOND needs at least two args
+ SHOW( _SECOND(1,) ); // returns nothing, as empty args arg slots are permitted
+ printf("\n");
+
+ SHOW( RETURN_NOTHING() );
+ printf("\n");
+
+ SHOW( _OR() );
+ SHOW( _OR(1) );
+ SHOW( _OR(1,2,3) );
+ printf("\n");
+
+ #define T(x) 7
+ SHOW( T(x) );
+
+ SHOW( _NOT_ITEM() );
+ SHOW( _NOT_ITEM(1) );
+ SHOW( _NOT_ITEM(T(x)) );
+ // SHOW( NOT_ITEM(1,2,3) ); // compiler error parameter arity mismatch
+ printf("\n");
+
+ SHOW( NOT() );
+ SHOW( NOT(1) );
+ SHOW( NOT(T(x)) );
+ SHOW( NOT(1,2,3) );
+ printf("\n");
+
+ SHOW( BOOL() );
+ SHOW( CAT2(_IF_ ,BOOL()) );
+ printf("\n");
+
+ SHOW( TO_1_OR_0() );
+ SHOW( TO_1_OR_0(1) );
+ SHOW( TO_1_OR_0(x) );
+ SHOW( TO_1_OR_0(1.2.3) );
+ printf("\n");
+
+ //--------------------------------------------------------------------------
+ // EXISTS
+ //--------------------------------------------------------------------------
+
+ SHOW( EXISTS() ); // false β Ξ΅
+ SHOW( EXISTS(0) ); // true β 1
+ SHOW( EXISTS(x,y,z) ); // true β 1
+ printf("\n");
+
+ //--------------------------------------------------------------------------
+ // Logic Connectors
+ //--------------------------------------------------------------------------
+
+ SHOW( LEQ2( , ) ); // () implies () β 1
+ SHOW( LEQ2( , 1 ) ); // () implies 1 β 1
+ SHOW( LEQ2( 1, ) ); // 1 implies () β () (fail)
+ SHOW( LEQ2( 1, 0 ) ); // 1 implies 0 β 0 (still true!)
+ printf("\n");
+
+ SHOW( XOR2( , ) ); // both false β false
+ SHOW( XOR2( , 0 ) ); // one true β true
+ SHOW( XOR2( 0, 0 ) ); // both true β false
+ printf("\n");
+
+ SHOW( AND2( , 0 ) ); // one false β false
+ SHOW( AND2( 0, 1 ) ); // both true β true
+ printf("\n");
+
+ SHOW( OR2( , ) ); // both false β false
+ SHOW( OR2( , 0 ) ); // one true β true
+ printf("\n");
+
+ //--------------------------------------------------------------------------
+ // Registered Equivalence
+ //--------------------------------------------------------------------------
+
+ #define EQ__APPLE__oo__APPLE
+ #define EQ__PEAR__oo__PEAR
+
+ SHOW( EQ(APPLE ,APPLE) );
+ SHOW( EQ(APPLE ,PEAR) );
+ SHOW( EQ(PEAR ,PEAR) );
+ SHOW( EQ(,) );
+ SHOW( EQ(,PEAR) );
+ SHOW( EQ(PEAR ,) );
+ printf("\n");
+
+ //--------------------------------------------------------------------------
+ // BOOLEAN
+ //--------------------------------------------------------------------------
+
+ SHOW( BOOLEAN() ); // false β 0
+ SHOW( BOOLEAN(0) ); // true β 1
+ SHOW( BOOLEAN(foo) ); // true β 1
+ SHOW( BOOLEAN(1,2,3) ); // true β 1
+ printf("\n");
+
+ //--------------------------------------------------------------------------
+ // Remainder of a list
+ //--------------------------------------------------------------------------
+
+ SHOW(REST());
+ SHOW(REST(1));
+ SHOW(REST(1,2));
+ SHOW(REST(1,2,3));
+
+
+}
+
--- /dev/null
+#include "../ccπ/cpp_ext_0.c"
+#include "../ccπ/cpp_ext_1.c"
+
+int main(void){
+
+ //--------------------------------------------------------------------------
+ // EVAL and DEFER sanity check (no visual outputβverifies expansion only)
+ //--------------------------------------------------------------------------
+
+ #define PLUS_ONE(x) x + 1
+ #define EXAMPLE_CHAIN(x) PLUS_ONE(PLUS_ONE(x))
+ SHOW( EVAL(EXAMPLE_CHAIN(3)) ); // -> 3 + 1 + 1
+ printf("\n");
+
+ //--------------------------------------------------------------------------
+ // FIND: returns first matching item from list
+ //--------------------------------------------------------------------------
+
+ #define EQ__A__oo__A
+ #define EQ__B__oo__B
+ #define EQ__C__oo__C
+ #define EQ__D__oo__D
+
+ #define EQ__X__oo__X
+ #define EQ__Y__oo__Y
+ #define EQ__Z__oo__Z
+
+ #define IS_X(a) EQ(a ,X) // IS makes use of the EQ template for X
+
+ SHOW( FIND(IS_X ,A ,B ,X ,Y ,Z) ); // β X
+ SHOW( FIND(IS_X ,A ,B ,C ,D) ); // β Ξ΅
+ printf("\n");
+
+ //--------------------------------------------------------------------------
+ // HAS_ITEM: returns 1 if item found
+ // HAS requires the EQ templates to be set for each case.
+ //--------------------------------------------------------------------------
+
+ SHOW( EQ(A ,B) );
+ SHOW( EQ(B ,B) );
+ printf("\n");
+
+ SHOW( HAS_ITEM(C ,A ,B ,C ,D) ); // β 1
+ SHOW( HAS_ITEM(Z ,A ,B ,C ,D) ); // β Ξ΅
+ printf("\n");
+
+
+ //--------------------------------------------------------------------------
+ // WHILE: stops when predicate fails
+ //--------------------------------------------------------------------------
+
+ #define NON_Z(x) NOT(EQ(x ,Z)) // makes uses of the EQ template for Z
+
+ SHOW( WHILE(NON_Z ,A ,B ,C ,Z ,D ,E) ); // β Ξ΅ (stops at Z)
+ SHOW( WHILE(NON_Z ,A ,B ,C) ); // β 1 (all pass)
+ printf("\n");
+
+ SHOW(EXISTS());
+ SHOW(EXISTS(0));
+ SHOW(EXISTS(1));
+ SHOW(EXISTS(X));
+ SHOW( WHILE(EXISTS ,1 ,X , ));
+ SHOW( WHILE(EXISTS ,1 , ,X ,0));
+ SHOW( WHILE(EXISTS ,1 ,X ,0));
+
+ printf("\n");
+
+
+ //--------------------------------------------------------------------------
+ // LAST: returns final item of list
+ //--------------------------------------------------------------------------
+
+ SHOW( LAST(A ,B ,C ,D ,Z) ); // β Z
+ SHOW( LAST(A ,B ,) ); // β
+ SHOW( LAST() ); // β Ξ΅
+ printf("\n");
+
+ //--------------------------------------------------------------------------
+ // CAT: join items with a separator
+ //--------------------------------------------------------------------------
+
+ // SHOW( CAT( ;, A ,B ,C ,D ,Z) ); // β Z
+ SHOW( CAT(,A ,B ,C) ); // β
+ SHOW( CAT( COMMA, A ,B ,C ,D ,Z) ); // β Z
+ SHOW( CAT(,A ,B ,) ); // β
+ SHOW( CAT(,1) );
+ SHOW( CAT(,) ); // β Ξ΅
+ printf("\n");
+
+ //--------------------------------------------------------------------------
+ // AND: true if all items are true (non-empty)
+ //--------------------------------------------------------------------------
+#if 0
+ SHOW( AND(1 ,X ,0) ); // β 1
+ SHOW( AND(1 ,X ,) ); // β Ξ΅
+ printf("\n");
+
+ //--------------------------------------------------------------------------
+ // OR: true if any item is true (non-empty)
+ //--------------------------------------------------------------------------
+
+ SHOW( OR( , , ,X) ); // β 1
+ SHOW( OR( , , ,) ); // β Ξ΅
+ printf("\n");
+#endif
+}