From: Thomas Walker Lynch Date: Tue, 1 Apr 2025 03:06:31 +0000 (+0000) Subject: checkpoint X-Git-Url: https://git.reasoningtechnology.com/style/static/gitweb.css?a=commitdiff_plain;h=6aa5b52788895b292fdb8bbd6f8162f1cffefdb5;p=N checkpoint --- diff --git "a/developer/cc\360\237\226\211/cpp_ext_0.c" "b/developer/cc\360\237\226\211/cpp_ext_0.c" index 9b90e07..e196e92 100644 --- "a/developer/cc\360\237\226\211/cpp_ext_0.c" +++ "b/developer/cc\360\237\226\211/cpp_ext_0.c" @@ -5,54 +5,14 @@ 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____oo__, 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 */ @@ -87,23 +47,11 @@ Constants #define _TWION_0 ~,0 #define _TWION_1 ~,1 -// RWR == rewrite rule, RWR_ is followed by macro name it is used in `__` -// 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) @@ -115,129 +63,208 @@ Primitive Concatenation #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)()() - #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____oo__ - 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)()() +===========================================================================*/ - 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 +*/ diff --git "a/developer/cc\360\237\226\211/cpp_ext_1.c" "b/developer/cc\360\237\226\211/cpp_ext_1.c" index a188507..5f8a5b4 100644 --- "a/developer/cc\360\237\226\211/cpp_ext_1.c" +++ "b/developer/cc\360\237\226\211/cpp_ext_1.c" @@ -8,17 +8,12 @@ To be added: 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,...) \ */ @@ -30,61 +25,141 @@ DROPE_NOT_EXISTS_RIGHT 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 diff --git "a/developer/document\360\237\226\211/cpp.txt" "b/developer/document\360\237\226\211/cpp.txt" deleted file mode 100644 index 3896b03..0000000 --- "a/developer/document\360\237\226\211/cpp.txt" +++ /dev/null @@ -1,184 +0,0 @@ - -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##. 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 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.) - - diff --git "a/developer/document\360\237\226\211/cpp_evaluation.org" "b/developer/document\360\237\226\211/cpp_evaluation.org" index b320ac4..5c6a493 100644 --- "a/developer/document\360\237\226\211/cpp_evaluation.org" +++ "b/developer/document\360\237\226\211/cpp_evaluation.org" @@ -4,6 +4,9 @@ 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 diff --git "a/developer/document\360\237\226\211/cpp_grammar.org" "b/developer/document\360\237\226\211/cpp_grammar.org" index ef88176..98e5154 100644 --- "a/developer/document\360\237\226\211/cpp_grammar.org" +++ "b/developer/document\360\237\226\211/cpp_grammar.org" @@ -14,19 +14,34 @@ Grammar | 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 diff --git a/developer/example_cpp/0_readme.org b/developer/example_cpp/0_readme.org index d10769b..cb3056f 100644 --- a/developer/example_cpp/0_readme.org +++ b/developer/example_cpp/0_readme.org @@ -1,4 +1,4 @@ -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 diff --git a/developer/example_cpp/cpp_ext_0.c b/developer/example_cpp/cpp_ext_0.c deleted file mode 100644 index 573c27c..0000000 --- a/developer/example_cpp/cpp_ext_0.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - 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____oo__, 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 -#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 `__` -// 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____oo__ - 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)()() - - 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 diff --git a/developer/example_cpp/cpp_ext_1.c b/developer/example_cpp/cpp_ext_1.c deleted file mode 100644 index bc241d7..0000000 --- a/developer/example_cpp/cpp_ext_1.c +++ /dev/null @@ -1,90 +0,0 @@ -/* -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 diff --git a/developer/example_cpp/try_1_exists.c b/developer/example_cpp/try_1_exists.c deleted file mode 100644 index c2ca07d..0000000 --- a/developer/example_cpp/try_1_exists.c +++ /dev/null @@ -1,110 +0,0 @@ -#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 -*/ diff --git a/developer/example_cpp/try_2_connectors.c b/developer/example_cpp/try_2_connectors.c deleted file mode 100644 index 98078f1..0000000 --- a/developer/example_cpp/try_2_connectors.c +++ /dev/null @@ -1,200 +0,0 @@ -#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§ - > -*/ - - diff --git a/developer/example_cpp/try_3_eq.c b/developer/example_cpp/try_3_eq.c deleted file mode 100644 index c388f03..0000000 --- a/developer/example_cpp/try_3_eq.c +++ /dev/null @@ -1,55 +0,0 @@ -#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; -} diff --git a/developer/example_cpp/try_4_if.c b/developer/example_cpp/try_4_if.c deleted file mode 100644 index 4d9d3ae..0000000 --- a/developer/example_cpp/try_4_if.c +++ /dev/null @@ -1,62 +0,0 @@ -#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; -} diff --git a/developer/example_cpp/try_5_access.c b/developer/example_cpp/try_5_access.c deleted file mode 100644 index aee6c94..0000000 --- a/developer/example_cpp/try_5_access.c +++ /dev/null @@ -1,46 +0,0 @@ -#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; -} diff --git a/developer/example_cpp/try_6_list.c b/developer/example_cpp/try_6_list.c deleted file mode 100644 index 75506ec..0000000 --- a/developer/example_cpp/try_6_list.c +++ /dev/null @@ -1,60 +0,0 @@ -#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; -} diff --git a/developer/example_cpp/try_ext_0.c b/developer/example_cpp/try_ext_0.c new file mode 100644 index 0000000..127f3f0 --- /dev/null +++ b/developer/example_cpp/try_ext_0.c @@ -0,0 +1,116 @@ +#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)); + + +} + diff --git a/developer/example_cpp/try_ext_1.c b/developer/example_cpp/try_ext_1.c new file mode 100644 index 0000000..8e87532 --- /dev/null +++ b/developer/example_cpp/try_ext_1.c @@ -0,0 +1,106 @@ +#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 +}