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