diff options
| author | 2026-02-23 20:36:05 +0100 | |
|---|---|---|
| committer | 2026-02-23 20:36:05 +0100 | |
| commit | 052144cabb126efe925a96f8a0597a0f2005d206 (patch) | |
| tree | 4fd87244b9eef018b30e90fdff24c5b1a145a85e /test | |
| parent | 4e9020dfb847d80475415f9f5914efaa50238767 (diff) | |
add metalang99 testsuite (preprocessor stress testing)
Diffstat (limited to 'test')
119 files changed, 16971 insertions, 2 deletions
diff --git a/test/all.sh b/test/all.sh index e632e0a..d80db09 100755 --- a/test/all.sh +++ b/test/all.sh @@ -3,8 +3,11 @@ cd $(dirname "$0") ./run.sh -echo "--- Lua 5.4.0 ---" +echo "=== Lua 5.4.0 ===" ./lua.sh -echo "--- c-testsuite ---" +echo "=== c-testsuite ===" ./c-testsuite.sh + +echo "=== metalang99 (preprocessor) ===" +./metalang99.sh diff --git a/test/external/metalang99/.clang-format b/test/external/metalang99/.clang-format new file mode 100644 index 0000000..a195560 --- /dev/null +++ b/test/external/metalang99/.clang-format @@ -0,0 +1,17 @@ +Language: Cpp +BasedOnStyle: LLVM + +IndentWidth: 4 +ContinuationIndentWidth: 4 +ColumnLimit: 100 + +AllowShortFunctionsOnASingleLine: Empty +AllowAllArgumentsOnNextLine: false +BinPackArguments: false +AllowAllParametersOfDeclarationOnNextLine: true +BinPackParameters: true + +AlignConsecutiveMacros: true +AlignAfterOpenBracket: AlwaysBreak + +StatementMacros: ["ML99_EVAL", "ML99_CLANG_PRAGMA", "ML99_GCC_PRAGMA"] diff --git a/test/external/metalang99/.github/workflows/c-cpp.yml b/test/external/metalang99/.github/workflows/c-cpp.yml new file mode 100644 index 0000000..0c0aef1 --- /dev/null +++ b/test/external/metalang99/.github/workflows/c-cpp.yml @@ -0,0 +1,88 @@ +name: C/C++ CI + +on: + push: + branches: [master] + pull_request: + branches: [master] + +jobs: + test: + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + include: + - os: ubuntu-latest + compiler: gcc + - os: macos-latest + compiler: clang + - os: windows-latest + compiler: msvc + + runs-on: ${{ matrix.os }} + env: + CC: ${{ matrix.compiler }} + + steps: + - uses: actions/checkout@v2 + + - name: Test + run: ./scripts/test-all.sh + + test-tcc: + runs-on: ubuntu-latest + env: + CC: tcc + + steps: + - uses: actions/checkout@v2 + + - name: Install TCC + run: sudo apt install tcc + + - name: Test + run: ./scripts/test-all.sh + + test-cxx-stmt: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Test C++ statement chaining + run: | + g++ tests/stmt.c -o stmt -Iinclude -Wall -Wextra -pedantic -std=c++11 -ftrack-macro-expansion=0 + ./stmt + + bench: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Bench + run: ./scripts/bench.sh + + check-arities: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Install Doxygen + run: sudo apt install doxygen + + - name: Check arity specifiers + run: python3 scripts/check-arities.py + + check-fmt: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - name: Download run-clang-format + run: git submodule update --init run-clang-format + + - name: Check code formatting + run: ./scripts/check-fmt.sh diff --git a/test/external/metalang99/.gitignore b/test/external/metalang99/.gitignore new file mode 100644 index 0000000..8546167 --- /dev/null +++ b/test/external/metalang99/.gitignore @@ -0,0 +1,61 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +# Doxygen XML output +xml + +# Sphinx output +_build + +# CMake build files +build/ diff --git a/test/external/metalang99/.gitmodules b/test/external/metalang99/.gitmodules new file mode 100644 index 0000000..517f2a7 --- /dev/null +++ b/test/external/metalang99/.gitmodules @@ -0,0 +1,3 @@ +[submodule "run-clang-format"] + path = run-clang-format + url = https://github.com/Sarcasm/run-clang-format diff --git a/test/external/metalang99/.readthedocs.yaml b/test/external/metalang99/.readthedocs.yaml new file mode 100644 index 0000000..92f2760 --- /dev/null +++ b/test/external/metalang99/.readthedocs.yaml @@ -0,0 +1,17 @@ +# See <https://docs.readthedocs.io/en/stable/config-file/index.html>. + +version: 2 + +build: + os: ubuntu-22.04 + tools: + python: "3.12" + +python: + install: + - requirements: docs/requirements.txt + +sphinx: + builder: html + configuration: docs/conf.py + fail_on_warning: true diff --git a/test/external/metalang99/ARCHITECTURE.md b/test/external/metalang99/ARCHITECTURE.md new file mode 100644 index 0000000..b1fe1cc --- /dev/null +++ b/test/external/metalang99/ARCHITECTURE.md @@ -0,0 +1,25 @@ +# Architecture + +_This document describes the high-level architecture of Metalang99._ + +## Interpreter + +The interpreter interprets the core metalanguage described in the [specification]. + +[specification]: https://github.com/hirrolot/metalang99/blob/master/spec/spec.pdf + +### `eval/eval.h` + +`eval/eval.h` exposes a single macro `ML99_PRIV_EVAL` which evaluates a given metaprogram. It is implemented as a machine in [continuation-passing style] which is described in the specification too. + +[continuation-passing style]: https://en.wikipedia.org/wiki/Continuation-passing_style + +### `eval/rec.h` + +`eval/rec.h` contains a macro recursion engine upon which everything executes. + +## Standard library + +The Metalang99 standard library is a set of functions implemented using the core metalanguage. They are located inside corresponding files listed at the [documentation]'s front page. + +[documentation]: https://metalang99.readthedocs.io/en/latest/ diff --git a/test/external/metalang99/CHANGELOG.md b/test/external/metalang99/CHANGELOG.md new file mode 100644 index 0000000..0a97127 --- /dev/null +++ b/test/external/metalang99/CHANGELOG.md @@ -0,0 +1,464 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## unreleased + +### Fixed + + - Remove outdated Doxygen configuration options ([issue #34](https://github.com/hirrolot/metalang99/issues/34)). + +## 1.13.5 - 2025-03-17 + +### Fixed + + - Update the minimum required CMake version to 3.10.0 due to deprecation ([issue #33](https://github.com/hirrolot/metalang99/issues/33)). + +## 1.13.4 - 2025-03-17 + +### Fixed + + - Update the minimum required CMake version to 3.5.0 due to deprecation ([issue #32](https://github.com/hirrolot/metalang99/issues/32)). + +## 1.13.3 - 2023-03-11 + +### Fixed + + - Fix the `DOWNLOAD_EXTRACT_TIMESTAMP` CMake warning (see [datatype99/issues/15](https://github.com/hirrolot/datatype99/issues/15)). + +## 1.13.2 - 2022-05-15 + +### Fixed + + - Fix C++ compilation for `ML99_INTRODUCE_VAR_TO_STMT` and `ML99_INTRODUCE_NON_NULL_PTR_TO_STMT` ([issue #25](https://github.com/hirrolot/metalang99/issues/25)). + +## 1.13.1 - 2021-12-09 + +### Fixed + + - Specify `C` as the project language in `CMakeLists.txt`. Previously, CMake detected C++ and required a C++ compiler to compile the project. + +## 1.13.0 - 2021-12-01 + +### Added + + - Add the root `CMakeLists.txt` to be able to use CMake with [`FetchContent`] or [`add_subdirectory`] ([PR #20](https://github.com/hirrolot/metalang99/pull/20)). + - `list.h`: + - `ML99_listFilterMap` to filter a list with a maybe-returning function. + +[`FetchContent`]: https://cmake.org/cmake/help/latest/module/FetchContent.html +[`add_subdirectory`]: https://cmake.org/cmake/help/latest/command/add_subdirectory.html + +## 1.12.1 - 2021-11-23 + +### Deprecated + + - Deprecate `ML99_catEval` because there were no use cases over time. + +## 1.12.0 - 2021-11-09 + +### Added + + - `choice.h`: + - `ML99_choiceData`, `ML99_CHOICE_DATA` to extract a choice value data. + - `gen.h`: + - Add `ML99_fnPtr(Stmt)` to generate a function pointer. + - New module `stmt.h`: + - Take `ML99_INTRODUCE_VAR_TO_STMT`, `ML99_INTRODUCE_NON_NULL_PTR_TO_STMT`, `ML99_CHAIN_EXPR_STMT`, `ML99_CHAIN_EXPR_STMT_AFTER`, and `ML99_SUPPRESS_UNUSED_BEFORE_STMT` from `gen.h`. + +### Changed + + - `choice.h`: + - Define the representation of choice types as `(tag, ...)`. + - `tuple.h`: + - Emit a fatal error in `ML99_untuple` if an argument is not a tuple. + - `gen.h`: + - Move all statement chaining macros to `stmt.h` (see above). + - Move `ML99_GEN_SYM` and `ML99_TRAILING_SEMICOLON` to `util.h`. + +### Deprecated + + - `tuple.h`: + - `ML99_untupleChecked` because it is the same as `ML99_untuple`. + - `ML99_tupleEval`, `ML99_untupleEval` because there were no use cases over time. + - `logical.h`: + - Move all functions to `bool.h`. + - `control.h`: + - Move `ML99_OVERLOAD` to `variadics.h`. + - Move `ML99_if`, `ML99_IF` to `bool.h`. + - Move `ML99_repeat`, `ML99_times` to `gen.h`. + +## 1.11.0 - 2021-10-02 + +### Added + + - New module `seq.h`: + - `ML99_seqIsEmpty`, `ML99_SEQ_IS_EMPTY` to check for the empty sequence. + - `ML99_seqGet`, `ML99_SEQ_GET` to get an `i`-indexed element. + - `ML99_seqTail`, `ML99_SEQ_TAIL` to get a tail. + - `ML99_seqForEach(I)` to iterate through each element. + - `logical.h`: + - `ML99_boolMatch(WithArgs)` to perform pattern matching on a boolean value. + +### Changed + + - `list.h`, `variadics.h`: + - Remove the requirement that `ML99_listFromTuples` and `ML99_variadicsForEach(I)` can accept at most 63 arguments. + +## 1.10.0 - 2021-09-14 + +### Added + + - `util.h`: + - `ML99_COMMA` that expands to a single comma. + +### Deprecated + + - `util.h`: + - `ML99_(L|R)PAREN` because they result in code that is difficult to reason about. + +## 1.9.0 - 2021-08-27 + +### Added + + - `metalang99.h`: + - `ML99_VERSION_COMPATIBLE` to check for a SemVer-compatible version. + - `ML99_VERSION_EQ` to check for an exact version. + +## 1.8.0 - 2021-08-26 + +### Added + + - `ident.h`: + - `ML99_charLit`, `ML99_CHAR_LIT` to convert a Metalang99 character to a C character literal. + +## 1.7.0 - 2021-08-13 + +### Changed + + - `assert.h`: + - Generate `_Static_assert` from the assertion macros if compiling on C11. + +## 1.6.0 - 2021-08-13 + +### Added + + - Tuple counterparts of variadics (`tuple.h`): + - `ML99_tupleCount`, `ML99_TUPLE_COUNT`. + - `ML99_tupleIsSingle`, `ML99_TUPLE_IS_SINGLE`. + - `ML99_tupleForEach(I)`. + +### Fixed + + - `util.h`: + - `ML99_cat3` & `ML99_cat4` to desugar to themselves instead of `ML99_cat`. + - `variadics.h`: + - Make `variadics.h` work without including `nat.h` & `util.h`. + +## 1.5.0 - 2021-08-11 + +### Added + + - `ML99_assignInitializerList(Stmt)` as `ML99_assign(Stmt)` counterparts for initializer lists. + +## 1.4.1 - 2021-08-05 + +### Fixed + + - Invalid C11 standard detection for `_Static_assert` ([issue #15](https://github.com/hirrolot/metalang99/issues/15)). + - Invalid C11 standard detection for `_Static_assert` on MSVC ([issue #16](https://github.com/hirrolot/metalang99/issues/16)). + +## 1.4.0 - 2021-08-02 + +### Added + +- `ML99_ALLOW_POOR_DIAGNOSTICS`: if your compiler does not support decent diagnostic messages, Metalang99 will emit an error that can be suppressed by defining this macro. + +### Fixed + + - Emit `_Static_assert` for diagnostics where possible: + - C11. + - Clang if `__has_extension(c_static_assert)`. + - GCC if newer than [4.6](https://gcc.gnu.org/gcc-4.6/changes.html). + +## 1.3.0 - 2021-07-24 + +### Added + + - `util.h`: + - `ML99_todo(WithMsg)` and `ML99_unimplemented(WithMsg)` to indicate unimplemented functionality. + +### Fixed + + - Handle the `(...) (...) ...` form in `ML99_isUntuple`: + - All the dependent public functions inherit this ability too: `ML99_isTuple`, `ML99_untupleChecked`, and `ML99_listFromTuples`. + - Now the interpreter is able to emit a syntax error for `v(123) v(456)`. + +### Changed + + - Emit syntax errors and errors from `ML99_fatal` right to a console if compiling on GCC. + +## 1.2.0 - 2021-06-06 + +### Added + + - `list.h`: + - `ML99_listFromTuples` to transform comma-separated tuples into a list. + - `util.h`: + - `ML99_(L|R)PAREN` that expand to an opening/closing parenthesis. + - `tuple.h`: + - `ML99_untupleChecked` to emit a fatal error if a provided argument is not a tuple. + - New module `ident.h`: + - Migrate `ML99_detectIdent`, `ML99_identEq`, `ML99_DETECT_IDENT`, `ML99_IDENT_EQ`, `ML99_C_KEYWORD_DETECTOR`, `ML99_UNDERSCORE_DETECTOR` from `util.h`. + - `ML99_(LOWER|UPPER)CASE_DETECTOR` to detect lower/uppercase characters. + - `ML99_DIGIT_DETECTOR` to detect digits. + - `ML99_char_eq`, `ML99_CHAR_EQ` to compare two characters. + - `ML99_is(Lower|Upper)case`, `ML99_IS_(LOWER|UPPER)CASE` to check whether a letter is lower/uppercased. + - `ML99_isDigit`, `ML99_IS_DIGIT` to check whether a character is digit. + - `ML99_isChar`, `ML99_IS_CHAR` to check whether an identifier is a character. + - `ML99_(LOWER|UPPER)CASE_CHARS` that expands to all comma-separated lower/uppercase characters. + - `ML99_DIGITS` that expands to all comma-separated digits. + +### Changed + + - `util.h`: + - Automatically include `ident.h` for backwards compatibility. + +### Fixed + + - Make Metalang99 work on TCC (see [datatype99/issues/10](https://github.com/hirrolot/datatype99/issues/10)). + +## 1.1.0 - 2021-04-24 + +### Added + + - `gen.h`: + - Statement chaining macros: + - `ML99_CHAIN_EXPR_STMT` to execute a statement before the next statement. + - `ML99_CHAIN_EXPR_STMT_AFTER` to execute a statement afterwards. + - `ML99_INTRODUCE_NON_NULL_PTR_TO_STMT` to introduce a non-null pointer to a statement. + - Other: + - `ML99_GEN_SYM` to generate unique identifiers. + - `ML99_TRAILING_SEMICOLON` to force a trailing semicolon. + - `ML99_semicoloned` that puts a semicolon after its argument. + - `ML99_assign` to assign something to something. + - `ML99_assignStmt` to generate an assignment statement. + - `ML99_invoke` to invoke a macro/function. + - `ML99_invokeStmt` to generate a macro/function invocation statement. + - `ML99_prefixedBlock` to generate `prefix { code }`. + - `util.h`: + - Dealing with identifiers: + - `ML99_detectIdent`. + - `ML99_identEq`, `ML99_IDENT_EQ` to compare two identifiers. + - `ML99_C_KEYWORD_DETECTOR` to detect the C11 keywords. + - `ML99_UNDERSCORE_DETECTOR` to detect the underscore character (`_`). + - Other: + - `ML99_uncomma` to evaluate terms with the space-separator. + - `ML99_reify` to reify a macro/function to a Metalang99-compliant metafunction. + - `ML99_cat3`, `ML99_CAT3`, `ML99_CAT3_PRIMITIVE`. + - `ML99_cat4`, `ML99_CAT4`, `ML99_CAT4_PRIMITIVE`. + - `assert.h`: + - `ML99_assert`, `ML99_assertEq`. + - `variadics.h`: + - `ML99_variadicsIsSingle`, `ML99_VARIADICS_IS_SINGLE`. + - Built-in data type assertion macros: + - `tuple.h`: `ML99_assertIsTuple`. + - `nat.h`: `ML99_assertIsNat`. + +### Fixed + + - `assert.h`: + - Parenthesize expressions passed to `ML99_ASSERT`, `ML99_ASSERT_EQ`. + +### Changed + + - `gen.h`: + - `ML99_INTRODUCE_VAR_TO_STMT` can deal with several variables. + +### Deprecated + + - `gen.h`: + - `ML99_SUPPRESS_UNUSED_BEFORE_STMT` (use `ML99_CHAIN_EXPR_STMT((void)expr)` instead). + +## 1.0.0 - 2021-03-27 + +### Added + + - `ML99_QUOTE`. + +### Removed + + - `ML99_consume`, `ML99_CONSUME`. + +### Changed + + - Move `ML99_TERMS` from `util.h` to `lang.h`. + - Return a list of tuples from `ML99_listZip`, accept a list of tuples in `ML99_listUnzip`, return a tuple of lists from `ML99_listPartition`. + - `ML99_listEval` => `ML99_LIST_EVAL`, `ML99_listEvalCommaSep` => `ML99_LIST_EVAL_COMMA_SEP`. + - Accept ignored variadics in `ML99_nil`, `ML99_empty`, `ML99_true`, `ML99_false`, `ML99_nothing` (and their plain versions). + +### Fixed + + - Emit the correct metafunction name in case of an error in `ML99_listGet`. + - Remove a precondition that metafunctions passed to `ML99_listFoldl`, `ML99_listFolr`, `ML99_listFoldl1`, `ML99_listMap`, `ML99_listMapI`, `ML99_listFor`, `ML99_listMapInitLast`, and `ML99_listForInitLast` must evaluate to a single term. + +## 0.5.0 - 2021-03-22 + +### Added + + - `ML99_SUPPRESS_UNUSED_BEFORE_STMT`. + - `ML99_tupleGet`, `ML99_variadicsGet`, `ML99_TUPLE_GET`, `ML99_VARIADICS_GET`. + - `ML99_tupleAppend`, `ML99_tuplePrepend`. + - `ML99_indexedArgs`. + - `ML99_appl4`. + - `ML99_times`. + - `ML99_TRUE`, `ML99_FALSE`. + - `ML99_LEFT`, `ML99_RIGHT`, `ML99_IS_LEFT`, `ML99_IS_RIGHT`. + - `ML99_JUST`, `ML99_NOTHING`, `ML99_IS_JUST`, `ML99_IS_NOTHING`. + - `ML99_NAT_MAX`, `ML99_DIV_CHECKED`. + - `gen.h`. + +### Removed + + - `M_choiceEmpty(Plain)` (this allows a more optimal choice representation). + - `M_semicolon` (this macro turned out to be [dangerous](https://github.com/hirrolot/metalang99/commit/f12ba642b1fcf313e291fc0e353b01f666a980f8)). + - `M_tupleHead`, `M_variadicsHead`. + - `M_overload`. + - `M_when(Plain)`, `M_whenLazy(Plain)`. + - `M_putBefore`, `M_putAfter`, `M_putBetween`. + - `M_leftUnderscored`, `M_rightUnderscored`. + - `misc.h`, `eval.h`. + +### Changed + + - Do not guarantee the exact number of available reduction steps, instead keep it "reasonable" for the practical needs. + - Amalgamate `lang.h` with `eval.h`. + - Employ the `SCREAMING_CASE` naming convention for plain macros. + - All macros are prefixed with `ML99_`, unconditionally. + - Accept a number as a first argument and a function as the second in `ML99_repeat`. + - `M_get` => `ML99_listGet`. + - `M_overloadPlain` => `ML99_OVERLOAD`. + - `M_eval` => `ML99_EVAL`. + - `M_callTrivial` => `ML99_callUneval`. + - Move `ML99_repeat` from `misc.h` to `control.h`. + - Move `ML99_indexed(Params, Fields, InitializerList, Args)` from `misc.h` to `gen.h`. + - Move `ML99_braced`, `ML99_typedef`, `ML99_struct`, `ML99_anonStruct`, `ML99_union`, `ML99_anonUnion`, `ML99_enum`, `ML99_anonEnum` from `util.h` to `gen.h`. + - `M_assertPlain` => `ML99_ASSERT_UNEVAL`, `M_assertEmptyPlain` => `ML99_ASSERT_EMPTY_UNEVAL`. + - Rename "unsigned integers" to "natural numbers": + - `uint.h` => `nat.h`. + - `M_uintMatch(WithArgs)` => `ML99_natMatch(WithArgs)`. + - `M_uintEq` => `ML99_natEq`. + - `M_uintNeq` => `ML99_natNeq`. + +### Fixed + + - Emit a compile-time error if [`/Zc:preprocessor`] (MSVC) was not specified. + - Allow branches in `ML99_IF` expand to commas. + +[`/Zc:preprocessor`]: https://docs.microsoft.com/en-us/cpp/build/reference/zc-preprocessor?view=msvc-160 + +## 0.4.2 - 2021-02-28 + +### Added + + - `METALANG99_MAJOR`, `METALANG99_MINOR`, `METALANG99_PATCH`. + - `M_union`, `M_anonUnion`, `M_enum`, `M_anonEnum`. + - `METALANG99_GCC_PRAGMA`, `METALANG99_CLANG_PRAGMA`. + +### Fixed + + - Suppress Clang's `-Wshadow` for a variable produced by `M_INTRODUCE_VAR_TO_STMT`. + +## 0.4.1 - 2021-02-28 + +### Added + + - `M_DETECT_IDENT` + - `M_choicePlain`, `M_choiceEmptyPlain`, `M_consPlain`, `M_nilPlain`. + - `M_listMapInPlace`, `M_listMapInPlaceI`. + +### Changed + + - Increase the maximum arity from 16 to 255. + - Specify the exact number of commas produced by `M_indexedInitializerList`. + +### Fixed + + - Initialize variables produced by `M_semicolon` and `M_assertPlain` to suppress warnings. + +## 0.4.0 - 2021-02-26 + +### Added + + - `tuple.h`: `M_tuple(Plain)`, `M_tupleEval`, `M_untuple(Plain)`, `M_untupleEval`, `M_isTuple(Plain)`, `M_isUntuple(Plain)`, `M_tupleHead(Plain)`, `M_tupleTail(Plain)`. + +### Changed + + - Move the corresponding functions from `util.h` and `variadics.h` to `tuple.h`. + +## 0.3.0 - 2021-02-26 + +### Added + + - `M_when`, `M_whenPlain`, `M_whenLazy`, `M_whenLazyPlain`. + - `M_leftUnderscored`, `M_rightUnderscored`. + - `M_INTRODUCE_VAR_TO_STMT`. + - `M_terms`. + - `M_tupleHead`, `M_tupleHeadPlain`, `M_tupleTail`, `M_tupleTailPlain`. + - `M_indexedParams`, `M_indexedFields`, `M_indexedInitializerList`. + - `M_typedef`, `M_struct`, `M_anonStruct`. + - `M_choiceTag`, `M_choiceTagPlain`, `M_isNilPlain`, `M_isCons`, `M_isConsPlain`. + +### Changed + + - Make `M_variadicsHead` accept a single argument too. + - Now at most 63 variadic arguments are acceptable by `M_list`, `M_variadicsCount`, and `M_variadicsCountPlain`. + - Terms now need to be separated by commas, e.g. instead of `v(1) M_call(F, v(2)) v(3)`, write `v(1), M_call(F, v(2)), v(3)` or `M_terms(v(1), M_call(F, v(2)), v(3)`. + - The empty sequence is prohibited by `M_eval`, `M_call` and `M_abort`. + - Use American style endings (because it is prevalent): + - `M_(un)parenthesise(Eval)` => `M_(un)tuple(Eval)`. + - `M_isParenthesised` => `M_isTuple`. + - `M_isUnparenthesised` => `M_isUntuple`. + - `M_parenthesisedVariadics(Head|Tail)` => `M_tuple(Head|Tail)`. + - Shorten functions on unsigned integers: + - `M_uintInc(Plain)` => `M_inc(Plain)`. + - `M_uintDec(Plain)` => `M_dec(Plain)`. + - `M_uintAdd(3)` => `M_add(3)`. + - `M_uintSub(3)` => `M_sub(3)`. + - `M_uintMul(3)` => `M_mul(3)`. + - `M_uintDiv(3)` => `M_div(3)`. + - `M_uintDivChecked` => `M_divChecked`. + - `M_uintLesser(Eq)` => `M_lesser(Eq)`. + - `M_uintGreater(Eq)` => `M_greater(Eq)`. + - `M_uintMod` => `M_mod`. + - `M_uintMin` => `M_min`. + - `M_uintMax` => `M_max`. + - `M_variadicsMap` => `M_variadicsForEach`, `M_variadicsMapI` => `M_variadicsForEachI`. + +### Fixed + + - `aux.*` => `util.*` for compatibility with Windows. + +### Removed + + - `M_variadicsMapCommaSep`, `M_variadicsMapICommaSep` (better use lists). + - `M_const2`, `M_const3`. + +## 0.2.0 - 2021-02-05 + +### Changed + + - The project name `Epilepsy` => `Metalang99` (more neutral). + +### Fixed + + - Reporting about syntactic mismatches. + +## 0.1.0 - 2021-02-04 + +### Added + + - This excellent project. diff --git a/test/external/metalang99/CMakeLists.txt b/test/external/metalang99/CMakeLists.txt new file mode 100644 index 0000000..96733b4 --- /dev/null +++ b/test/external/metalang99/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.10.0) +project(metalang99 LANGUAGES C) + +# Fix the warnings about `DOWNLOAD_EXTRACT_TIMESTAMP` in newer CMake versions. +if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") + cmake_policy(SET CMP0135 NEW) +endif() + +add_library(${PROJECT_NAME} INTERFACE) +target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/test/external/metalang99/CONTRIBUTING.md b/test/external/metalang99/CONTRIBUTING.md new file mode 100644 index 0000000..2e9e0d1 --- /dev/null +++ b/test/external/metalang99/CONTRIBUTING.md @@ -0,0 +1,32 @@ +# Contributing + +To introduce changes: + + 1. Fork this repository. + 2. Create your own branch `xxx` from `master`. + 3. Make required changes. + 4. Open a PR to `master` from your `xxx`. + 5. Wait until it gets reviewed. + +To be able to work with low-level stuff such as the interpreter, I highly recommend to first observe the [Cloak Wiki]. + +To be able to work with the metalanguage itself, some basic familiarity with programming language theory is expected. For learning materials, see https://github.com/steshaw/plt. + +[Cloak Wiki]: https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms + +Some useful scripts are: + +| Description | Command | +|----------|----------| +| Format all the code base | `./scripts/fmt.sh` | +| Check code formatting | `./scripts/check-fmt.sh` | +| Test only `tests/` | `./scripts/test.sh` | +| Test only `examples/` | `./scripts/test-examples.sh` | +| Test both `tests/` and `examples/` | `./scripts/test-all.sh` | +| Generate the documentation | `./scripts/docs.sh` | +| Open the documentation | `./scripts/open-docs.sh` | +| Generate the specification | `./scripts/spec.sh` | +| Open the specification | `./scripts/open-spec.sh` | +| Run the benchmarks | `./scripts/bench.sh` | + +Happy hacking! diff --git a/test/external/metalang99/Doxyfile b/test/external/metalang99/Doxyfile new file mode 100644 index 0000000..8144215 --- /dev/null +++ b/test/external/metalang99/Doxyfile @@ -0,0 +1,2859 @@ +# Doxyfile 1.9.8 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = Metalang99 + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = 1.13.5 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "Full-blown preprocessor metaprogramming" + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096 +# sub-directories (in 2 levels) under the output directory of each output format +# and will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# number of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:^^" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to +# generate identifiers for the Markdown headings. Note: Every identifier is +# unique. +# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0 and GITHUB use the lower case version of title +# with any whitespace replaced by '-' and punctuation characters removed. +# The default value is: DOXYGEN. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_ID_STYLE = DOXYGEN + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +# If the TIMESTAMP tag is set different from NO then each generated page will +# contain the date or date and time when the page was generated. Setting this to +# NO can help when comparing the output of multiple runs. +# Possible values are: YES, NO, DATETIME and DATE. +# The default value is: NO. + +TIMESTAMP = NO + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = NO + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if <section_label> ... \endif and \cond <section_label> +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = NO + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete +# function parameter documentation. If set to NO, doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about +# undocumented enumeration values. If set to NO, doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then doxygen behaves +# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined doxygen will not +# write the warning messages in between other messages but write them at the end +# of a run, in case a WARN_LOGFILE is defined the warning messages will be +# besides being in the defined file also be shown at the end of a run, unless +# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case +# the behavior will remain as with the setting FAIL_ON_WARNINGS. +# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# See also: WARN_LINE_FORMAT +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = include \ + include/metalang99 + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING) if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding +# "INPUT_ENCODING" for further information on supported encodings. + +INPUT_FILE_ENCODING = + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, +# *.cpp, *.cppm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, +# *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.ixx, *.l, *.cs, *.d, *.php, +# *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be +# provided as doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = NO + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# ANamespace::AClass, ANamespace::*Test + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = examples + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# <filter> <input-file> +# +# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If the CLANG_ASSISTED_PARSING tag is set to YES and the CLANG_ADD_INC_PATHS +# tag is set to YES then doxygen will add the directory of each input to the +# include path. +# The default value is: YES. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_ADD_INC_PATHS = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = NO + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generate light mode output, DARK always +# generate dark mode output, AUTO_LIGHT automatically set the mode according to +# the user preference, use light mode if no preference is set (the default), +# AUTO_DARK automatically set the mode according to the user preference, use +# dark mode if no preference is set and TOGGLE allow to user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = AUTO_LIGHT + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a color-wheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use gray-scales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be +# dynamically folded and expanded in the generated HTML source code. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_CODE_FOLDING = YES + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline the HTML help workshop was already many years +# in maintenance mode). You can download the HTML help workshop from the web +# archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# The SITEMAP_URL tag is used to specify the full URL of the place where the +# generated documentation will be placed on the server by the user during the +# deployment of the documentation. The generated sitemap is called sitemap.xml +# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL +# is specified no sitemap is generated. For information about the sitemap +# protocol see https://www.sitemaps.org +# This tag requires that the tag GENERATE_HTML is set to YES. + +SITEMAP_URL = + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has the same information as the tab index, you could +# consider setting DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the +# FULL_SIDEBAR option determines if the side bar is limited to only the treeview +# area (value NO) or if it should extend to the full height of the window (value +# YES). Setting this to YES gives a layout similar to +# https://docs.readthedocs.io with more room for contents, but less room for the +# project logo, title, and description. If either GENERATE_TREEVIEW or +# DISABLE_INDEX is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = YES + +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use <access key> + S +# (what the <access key> is depends on the OS and browser, but it is typically +# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down +# key> to jump into the search results window, the results can be navigated +# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel +# the search. The filter options can be selected when the cursor is inside the +# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys> +# to select a filter and <Enter> or <escape> to activate or cancel the filter +# option. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using JavaScript. There +# are two flavors of web server based searching depending on the EXTERNAL_SEARCH +# setting. When disabled, doxygen will generate a PHP script for searching and +# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing +# and searching needs to be provided by external tools. See the section +# "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain the +# search results. +# +# Doxygen ships with an example indexer (doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: +# https://xapian.org/). +# +# See the section "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will return the search results when EXTERNAL_SEARCH is enabled. +# +# Doxygen ships with an example indexer (doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: +# https://xapian.org/). See the section "External Indexing and Searching" for +# details. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. +# The default file is: searchdata.xml. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of +# to a relative location where the documentation can be found. The format is: +# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. +# The default value is: YES. + +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. +# +# Note that when not enabling USE_PDFLATEX the default is latex when enabling +# USE_PDFLATEX the default is pdflatex and when in the later case latex is +# chosen this is overwritten by pdflatex. For specific output languages the +# default can have been set differently, this depends on the implementation of +# the output language. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate +# index for LaTeX. +# Note: This tag is used in the Makefile / make.bat. +# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file +# (.tex). +# The default file is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +MAKEINDEX_CMD_NAME = makeindex + +# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. +# Note: This tag is used in the generated output file (.tex). +# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. +# The default value is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_MAKEINDEX_CMD = makeindex + +# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used by the +# printer. +# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x +# 14 inches) and executive (7.25 x 10.5 inches). +# The default value is: a4. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PAPER_TYPE = a4 + +# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names +# that should be included in the LaTeX output. The package can be specified just +# by its name or with the correct syntax as to be used with the LaTeX +# \usepackage command. To get the times font for instance you can specify : +# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times} +# To use the option intlimits with the amsmath package you can specify: +# EXTRA_PACKAGES=[intlimits]{amsmath} +# If left blank no extra packages will be included. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for +# the generated LaTeX document. The header should contain everything until the +# first chapter. If it is left blank doxygen will generate a standard header. It +# is highly recommended to start with a default header using +# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty +# and then modify the file new_header.tex. See also section "Doxygen usage" for +# information on how to generate the default header that doxygen normally uses. +# +# Note: Only use a user-defined header if you know what you are doing! +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. The following +# commands have a special meaning inside the header (and footer): For a +# description of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for +# the generated LaTeX document. The footer should contain everything after the +# last chapter. If it is left blank doxygen will generate a standard footer. See +# LATEX_HEADER for more information on how to generate a default footer and what +# special commands can be used inside the footer. See also section "Doxygen +# usage" for information on how to generate the default footer that doxygen +# normally uses. Note: Only use a user-defined footer if you know what you are +# doing! +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_FOOTER = + +# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# LaTeX style sheets that are included after the standard style sheets created +# by doxygen. Using this option one can overrule certain style aspects. Doxygen +# will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_STYLESHEET = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the LATEX_OUTPUT output +# directory. Note that the files will be copied as-is; there are no commands or +# markers available. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is +# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will +# contain links (just like the HTML output) instead of page references. This +# makes the output suitable for online browsing using a PDF viewer. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as +# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX +# files. Set this option to YES, to get a higher quality PDF documentation. +# +# See also section LATEX_CMD_NAME for selecting the engine. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +USE_PDFLATEX = YES + +# The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error. +# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch +# mode nothing is printed on the terminal, errors are scrolled as if <return> is +# hit at every error; missing files that TeX tries to input or request from +# keyboard input (\read on a not open input stream) cause the job to abort, +# NON_STOP In nonstop mode the diagnostic message will appear on the terminal, +# but there is no possibility of user interaction just like in batch mode, +# SCROLL In scroll mode, TeX will stop only for missing files to input or if +# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at +# each error, asking for user intervention. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BATCHMODE = NO + +# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the +# index chapters (such as File Index, Compound Index, etc.) in the output. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HIDE_INDICES = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. See +# https://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# The default value is: plain. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BIB_STYLE = plain + +# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) +# path from which the emoji images will be read. If a relative path is entered, +# it will be relative to the LATEX_OUTPUT directory. If left blank the +# LATEX_OUTPUT directory will be used. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EMOJI_DIRECTORY = + +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The +# RTF output is optimized for Word 97 and may not look too pretty with other RTF +# readers/editors. +# The default value is: NO. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: rtf. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will +# contain hyperlink fields. The RTF file will contain links (just like the HTML +# output) instead of page references. This makes the output suitable for online +# browsing using Word or some other Word compatible readers that support those +# fields. +# +# Note: WordPad (write) and others do not support links. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# configuration file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. +# +# See also section "Doxygen usage" for information on how to generate the +# default style sheet that doxygen normally uses. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an RTF document. Syntax is +# similar to doxygen's configuration file. A template extensions file can be +# generated using doxygen -e rtf extensionFile. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for +# classes and files. +# The default value is: NO. + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. A directory man3 will be created inside the directory specified by +# MAN_OUTPUT. +# The default directory is: man. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to the generated +# man pages. In case the manual section does not start with a number, the number +# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is +# optional. +# The default value is: .3. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_EXTENSION = .3 + +# The MAN_SUBDIR tag determines the name of the directory created within +# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by +# MAN_EXTENSION with the initial . removed. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_SUBDIR = + +# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it +# will generate one additional man file for each entity documented in the real +# man page(s). These additional files only source the real man page, but without +# them the man command would be unable to find the correct page. +# The default value is: NO. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that +# captures the structure of the code including all documentation. +# The default value is: NO. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: xml. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_OUTPUT = xml + +# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program +# listings (including syntax highlighting and cross-referencing information) to +# the XML output. Note that enabling this will significantly increase the size +# of the XML output. +# The default value is: YES. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_PROGRAMLISTING = YES + +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include +# namespace members in file scope as well, matching the HTML output. +# The default value is: NO. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_NS_MEMB_FILE_SCOPE = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files +# that can be used to generate PDF. +# The default value is: NO. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. +# The default directory is: docbook. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_OUTPUT = docbook + +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an +# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures +# the structure of the code including all documentation. Note that this feature +# is still experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to Sqlite3 output +#--------------------------------------------------------------------------- + +# If the GENERATE_SQLITE3 tag is set to YES doxygen will generate a Sqlite3 +# database with symbols found by doxygen stored in tables. +# The default value is: NO. + +GENERATE_SQLITE3 = NO + +# The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be +# put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put +# in front of it. +# The default directory is: sqlite3. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_OUTPUT = sqlite3 + +# The SQLITE3_OVERWRITE_DB tag is set to YES, the existing doxygen_sqlite3.db +# database file will be recreated with each doxygen run. If set to NO, doxygen +# will warn if an a database file is already found and not modify it. +# The default value is: YES. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_RECREATE_DB = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module +# file that captures the structure of the code including all documentation. +# +# Note that this feature is still experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary +# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI +# output from the Perl module output. +# The default value is: NO. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely +# formatted so it can be parsed by a human reader. This is useful if you want to +# understand what is going on. On the other hand, if this tag is set to NO, the +# size of the Perl module output will be much smaller and Perl will parse it +# just the same. +# The default value is: YES. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file are +# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful +# so different doxyrules.make files included by the same Makefile don't +# overwrite each other's variables. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all +# C-preprocessor directives found in the sources and include files. +# The default value is: YES. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names +# in the source code. If set to NO, only conditional compilation will be +# performed. Macro expansion can be done in a controlled way by setting +# EXPAND_ONLY_PREDEF to YES. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then +# the macro expansion is limited to the macros specified with the PREDEFINED and +# EXPAND_AS_DEFINED tags. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES, the include files in the +# INCLUDE_PATH will be searched if a #include is found. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by the +# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of +# RECURSIVE has no effect here. +# This tag requires that the tag SEARCH_INCLUDES is set to YES. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will be +# used. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that are +# defined before the preprocessor is started (similar to the -D option of e.g. +# gcc). The argument of the tag is a list of macros of the form: name or +# name=definition (no spaces). If the definition and the "=" are omitted, "=1" +# is assumed. To prevent a macro definition from being undefined via #undef or +# recursively expanded use the := operator instead of the = operator. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +PREDEFINED = DOXYGEN_IGNORE \ + __COUNTER__ + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this +# tag can be used to specify a list of macro names that should be expanded. The +# macro definition that is found in the sources will be used. Use the PREDEFINED +# tag if you want to use a different macro definition that overrules the +# definition found in the source code. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will +# remove all references to function-like macros that are alone on a line, have +# an all uppercase name, and do not end with a semicolon. Such function macros +# are typically used for boiler-plate code, and will confuse the parser if not +# removed. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tag files. For each tag +# file the location of the external documentation should be added. The format of +# a tag file without this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where loc1 and loc2 can be relative or absolute paths or URLs. See the +# section "Linking to external documentation" for more information about the use +# of tag files. +# Note: Each tag file must have a unique name (where the name does NOT include +# the path). If a tag file is not located in the directory in which doxygen is +# run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create a +# tag file that is based on the input files it reads. See section "Linking to +# external documentation" for more information about the usage of tag files. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES, all external classes and namespaces +# will be listed in the class and namespace index. If set to NO, only the +# inherited external classes will be listed. +# The default value is: NO. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed +# in the topic index. If set to NO, only the current project's groups will be +# listed. +# The default value is: YES. + +EXTERNAL_GROUPS = YES + +# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in +# the related pages index. If set to NO, only the current project's pages will +# be listed. +# The default value is: YES. + +EXTERNAL_PAGES = YES + +#--------------------------------------------------------------------------- +# Configuration options related to diagram generator tools +#--------------------------------------------------------------------------- + +# If set to YES the inheritance and collaboration graphs will hide inheritance +# and usage relations if the target is undocumented or is not a class. +# The default value is: YES. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz (see: +# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# Bell Labs. The other options in this section have no effect if this option is +# set to NO +# The default value is: YES. + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed +# to run in parallel. When set to 0 doxygen will base this on the number of +# processors available in the system. You can set it explicitly to a value +# larger than 0 to get control over the balance between CPU load and processing +# speed. +# Minimum value: 0, maximum value: 32, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NUM_THREADS = 0 + +# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of +# subgraphs. When you want a differently looking font in the dot files that +# doxygen generates you can specify fontname, fontcolor and fontsize attributes. +# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node, +# Edge and Graph Attributes specification</a> You need to make sure dot is able +# to find the font, which can be done by putting it in a standard location or by +# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. Default graphviz fontsize is 14. +# The default value is: fontname=Helvetica,fontsize=10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10" + +# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can +# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a +# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about +# arrows shapes.</a> +# The default value is: labelfontname=Helvetica,labelfontsize=10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10" + +# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes +# around nodes set 'shape=plain' or 'shape=plaintext' <a +# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a> +# The default value is: shape=box,height=0.2,width=0.4. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" + +# You can set the path where dot can find font specified with fontname in +# DOT_COMMON_ATTR and others dot attributes. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTPATH = + +# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then doxygen will +# generate a graph for each documented class showing the direct and indirect +# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and +# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case +# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the +# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used. +# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance +# relations will be shown as texts / links. +# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN. +# The default value is: YES. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a +# graph for each documented class showing the direct and indirect implementation +# dependencies (inheritance, containment, and class references variables) of the +# class with other documented classes. Explicit enabling a collaboration graph, +# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the +# command \collaborationgraph. Disabling a collaboration graph can be +# accomplished by means of the command \hidecollaborationgraph. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for +# groups, showing the direct groups dependencies. Explicit enabling a group +# dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means +# of the command \groupgraph. Disabling a directory graph can be accomplished by +# means of the command \hidegroupgraph. See also the chapter Grouping in the +# manual. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside the +# class node. If there are many fields or methods and many nodes the graph may +# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the +# number of items for each type to make the size more manageable. Set this to 0 +# for no limit. Note that the threshold may be exceeded by 50% before the limit +# is enforced. So when you set the threshold to 10, up to 15 fields may appear, +# but if the number exceeds 15, the total amount of fields shown is limited to +# 10. +# Minimum value: 0, maximum value: 100, default value: 10. +# This tag requires that the tag UML_LOOK is set to YES. + +UML_LIMIT_NUM_FIELDS = 10 + +# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and +# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS +# tag is set to YES, doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen +# will not generate fields with class member information in the UML graphs. The +# class diagrams will look similar to the default class diagrams but using UML +# notation for the relationships. +# Possible values are: NO, YES and NONE. +# The default value is: NO. +# This tag requires that the tag UML_LOOK is set to YES. + +DOT_UML_DETAILS = NO + +# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters +# to display on a single line. If the actual line length exceeds this threshold +# significantly it will wrapped across multiple lines. Some heuristics are apply +# to avoid ugly line breaks. +# Minimum value: 0, maximum value: 1000, default value: 17. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_WRAP_THRESHOLD = 17 + +# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and +# collaboration graphs will show the relations between templates and their +# instances. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +TEMPLATE_RELATIONS = NO + +# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to +# YES then doxygen will generate a graph for each documented file showing the +# direct and indirect include dependencies of the file with other documented +# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO, +# can be accomplished by means of the command \includegraph. Disabling an +# include graph can be accomplished by means of the command \hideincludegraph. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDE_GRAPH = NO + +# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are +# set to YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other documented +# files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set +# to NO, can be accomplished by means of the command \includedbygraph. Disabling +# an included by graph can be accomplished by means of the command +# \hideincludedbygraph. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH tag is set to YES then doxygen will generate a call +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. Disabling a call graph can be +# accomplished by means of the command \hidecallgraph. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALL_GRAPH = NO + +# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. Disabling a caller graph can be +# accomplished by means of the command \hidecallergraph. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALLER_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical +# hierarchy of all classes instead of a textual one. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GRAPHICAL_HIERARCHY = NO + +# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the +# dependencies a directory has on other directories in a graphical way. The +# dependency relations are determined by the #include relations between the +# files in the directories. Explicit enabling a directory graph, when +# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command +# \directorygraph. Disabling a directory graph can be accomplished by means of +# the command \hidedirectorygraph. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DIRECTORY_GRAPH = NO + +# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels +# of child directories generated in directory dependency graphs by dot. +# Minimum value: 1, maximum value: 25, default value: 1. +# This tag requires that the tag DIRECTORY_GRAPH is set to YES. + +DIR_GRAPH_MAX_DEPTH = 1 + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. For an explanation of the image formats see the section +# output formats in the documentation of the dot tool (Graphviz (see: +# https://www.graphviz.org/)). +# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order +# to make the SVG files visible in IE 9+ (other browsers do not have this +# requirement). +# Possible values are: png, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, +# gif, gif:cairo, gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, +# png:cairo, png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and +# png:gdiplus:gdiplus. +# The default value is: png. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# +# Note that this requires a modern browser other than Internet Explorer. Tested +# and working are Firefox, Chrome, Safari, and Opera. +# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make +# the SVG files visible. Older versions of IE do not have SVG support. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +INTERACTIVE_SVG = NO + +# The DOT_PATH tag can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the \dotfile +# command). +# This tag requires that the tag HAVE_DOT is set to YES. + +DOTFILE_DIRS = + +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. + +DIA_PATH = + +# The DIAFILE_DIRS tag can be used to specify one or more directories that +# contain dia files that are included in the documentation (see the \diafile +# command). + +DIAFILE_DIRS = + +# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file or to the filename of jar file +# to be used. If left blank, it is assumed PlantUML is not used or called during +# a preprocessing step. Doxygen will generate a warning when it encounters a +# \startuml command in this case and will not generate output for the diagram. + +PLANTUML_JAR_PATH = + +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. + +PLANTUML_CFG_FILE = + +# When using plantuml, the specified paths are searched for files specified by +# the !include statement in a plantuml block. + +PLANTUML_INCLUDE_PATH = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes +# that will be shown in the graph. If the number of nodes in a graph becomes +# larger than this value, doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that doxygen if the number of direct +# children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that +# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. +# Minimum value: 0, maximum value: 10000, default value: 50. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_GRAPH_MAX_NODES = 50 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs +# generated by dot. A depth value of 3 means that only nodes reachable from the +# root by following a path via at most 3 edges will be shown. Nodes that lay +# further from the root node will be omitted. Note that setting this option to 1 +# or 2 may greatly reduce the computation time needed for large code bases. Also +# note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. +# Minimum value: 0, maximum value: 1000, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) support +# this, this feature is disabled by default. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_MULTI_TARGETS = NO + +# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page +# explaining the meaning of the various boxes and arrows in the dot generated +# graphs. +# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal +# graphical representation for inheritance and collaboration diagrams is used. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate +# files that are used to generate the various graphs. +# +# Note: This setting is not only used for dot files but also for msc temporary +# files. +# The default value is: YES. + +DOT_CLEANUP = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. If the MSCGEN_TOOL tag is left empty (the default), then doxygen will +# use a built-in version of mscgen tool to produce the charts. Alternatively, +# the MSCGEN_TOOL tag can also specify the name an external tool. For instance, +# specifying prog as the value, doxygen will call the tool as prog -T +# <outfile_format> -o <outputfile> <inputfile>. The external tool should support +# output file formats "png", "eps", "svg", and "ismap". + +MSCGEN_TOOL = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = diff --git a/test/external/metalang99/LICENSE b/test/external/metalang99/LICENSE new file mode 100644 index 0000000..dd7fd5b --- /dev/null +++ b/test/external/metalang99/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2025 hirrolot + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/test/external/metalang99/README.md b/test/external/metalang99/README.md new file mode 100644 index 0000000..6985549 --- /dev/null +++ b/test/external/metalang99/README.md @@ -0,0 +1,391 @@ +# Metalang99 + +[](https://github.com/hirrolot/metalang99/actions) +[](https://metalang99.readthedocs.io/en/latest/) +[](https://hirrolot.gitbook.io/metalang99/) +[](https://github.com/hirrolot/metalang99/blob/master/spec/spec.pdf) + +> The dark side of the force is a pathway to many abilities, some considered to be unnatural.<br>    <b>-- Darth Sidious</b> + +Based on [`examples/demo.c`](examples/demo.c): + +<table> +<tr><td><b>Compile-time list manipulation</b></td></tr> + +<tr> +<td> + +```c +// 3, 3, 3, 3, 3 +static int five_threes[] = { + ML99_LIST_EVAL_COMMA_SEP(ML99_listReplicate(v(5), v(3))), +}; + +// 5, 4, 3, 2, 1 +static int from_5_to_1[] = { + ML99_LIST_EVAL_COMMA_SEP(ML99_listReverse(ML99_list(v(1, 2, 3, 4, 5)))), +}; + +// 9, 2, 5 +static int lesser_than_10[] = { + ML99_LIST_EVAL_COMMA_SEP( + ML99_listFilter(ML99_appl(v(ML99_greater), v(10)), ML99_list(v(9, 2, 11, 13, 5)))), +}; +``` + +</td> +</tr> +</table> + +<table> +<tr><td><b>Macro recursion</b></td></tr> + +<tr> +<td> + +```c +#define factorial(n) ML99_natMatch(n, v(factorial_)) +#define factorial_Z_IMPL(...) v(1) +#define factorial_S_IMPL(n) ML99_mul(ML99_inc(v(n)), factorial(v(n))) + +ML99_ASSERT_EQ(factorial(v(4)), v(24)); +``` + +</td> +</tr> +</table> + +<table> +<tr><td><b>Overloading on a number of arguments</b></td></tr> + +<tr> +<td> + +```c +typedef struct { + double width, height; +} Rect; + +#define Rect_new(...) ML99_OVERLOAD(Rect_new_, __VA_ARGS__) +#define Rect_new_1(x) \ + { x, x } +#define Rect_new_2(x, y) \ + { x, y } + +static Rect _7x8 = Rect_new(7, 8), _10x10 = Rect_new(10); + +// ... and more! + +int main(void) { + // Yeah. All is done at compile time. +} +``` + +</td> +</tr> +</table> + +(Hint: `v(something)` evaluates to `something`.) + +Metalang99 is a firm foundation for writing reliable and maintainable metaprograms in pure C99. It is implemented as an interpreted FP language atop of preprocessor macros: just `#include <metalang99.h>` and you are ready to go. Metalang99 features algebraic data types, pattern matching, recursion, currying, and collections; in addition, it provides means for compile-time error reporting and debugging. With our [built-in syntax checker], macro errors should be perfectly comprehensible, enabling you for convenient development. + +[built-in syntax checker]: #q-what-about-compile-time-errors + +Currently, Metalang99 is used at [OpenIPC] as an indirect dependency of [Datatype99] and [Interface99]; this includes an [RTSP 1.0 implementation] along with ~50k lines of private code. + +[OpenIPC]: https://openipc.org/ +[RTSP 1.0 implementation]: https://github.com/OpenIPC/smolrtsp/ + +[Datatype99]: https://github.com/hirrolot/Datatype99 +[Interface99]: https://github.com/hirrolot/Interface99 + +## Motivation + +Macros facilitate code re-use, macros are the building material that lets you shape the language to suit the problem being solved, leading to more clean and concise code. However, metaprogramming in C is utterly castrated: we cannot even operate with control flow, integers, unbounded sequences, and compound data structures, thereby throwing a lot of hypothetically useful metaprograms out of scope. + +To solve the problem, I have implemented Metalang99. Having its functionality at our disposal, it becomes possible to develop even fairly non-trivial metaprograms, such as [Datatype99]: + +```c +#include <datatype99.h> + +datatype( + BinaryTree, + (Leaf, int), + (Node, BinaryTree *, int, BinaryTree *) +); + +int sum(const BinaryTree *tree) { + match(*tree) { + of(Leaf, x) return *x; + of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs); + } + + return -1; +} +``` + +Or [Interface99]: + +```c +#include <interface99.h> + +#include <stdio.h> + +#define Shape_IFACE \ + vfunc( int, perim, const VSelf) \ + vfunc(void, scale, VSelf, int factor) + +interface(Shape); + +typedef struct { + int a, b; +} Rectangle; + +int Rectangle_perim(const VSelf) { /* ... */ } +void Rectangle_scale(VSelf, int factor) { /* ... */ } + +impl(Shape, Rectangle); + +typedef struct { + int a, b, c; +} Triangle; + +int Triangle_perim(const VSelf) { /* ... */ } +void Triangle_scale(VSelf, int factor) { /* ... */ } + +impl(Shape, Triangle); + +void test(Shape shape) { + printf("perim = %d\n", VCALL(shape, perim)); + VCALL(shape, scale, 5); + printf("perim = %d\n", VCALL(shape, perim)); +} +``` + +Unlike the vague techniques, such as [tagged unions] or [virtual method tables], the above metaprograms leverage type safety, syntax conciseness, and maintain the exact memory layout of generated code. + +Looks interesting? Check out the [motivational post] for more information. + +[tagged unions]: https://en.wikipedia.org/wiki/Tagged_union +[virtual method tables]: https://en.wikipedia.org/wiki/Virtual_method_table +[motivational post]: https://hirrolot.github.io/posts/macros-on-steroids-or-how-can-pure-c-benefit-from-metaprogramming.html + +## Getting started + +Metalang99 is just a set of header files and nothing else. To use it as a dependency, you need to: + + 1. Add `metalang99/include` to include directories. + 2. Specify [`-ftrack-macro-expansion=0`] (GCC) or [`-fmacro-backtrace-limit=1`] (Clang) to avoid useless macro expansion errors. + +[`-ftrack-macro-expansion=0`]: https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html +[`-fmacro-backtrace-limit=1`]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fmacro-backtrace-limit + +If you use CMake, the recommended way is [`FetchContent`]: + +[`FetchContent`]: https://cmake.org/cmake/help/latest/module/FetchContent.html + +```cmake +include(FetchContent) + +FetchContent_Declare( + metalang99 + URL https://github.com/hirrolot/metalang99/archive/refs/tags/vx.y.z.tar.gz # vx.y.z +) + +FetchContent_MakeAvailable(metalang99) + +target_link_libraries(MyProject metalang99) + +# Disable full macro expansion backtraces for Metalang99. +if(CMAKE_C_COMPILER_ID STREQUAL "Clang") + target_compile_options(MyProject PRIVATE -fmacro-backtrace-limit=1) +elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") + target_compile_options(MyProject PRIVATE -ftrack-macro-expansion=0) +endif() +``` + +Optionally, you can [precompile headers] in your project that rely on Metalang99. This will decrease compilation time because the headers will not be compiled each time they are included. + +[precompile headers]: https://en.wikipedia.org/wiki/Precompiled_header + +[Tutorial](https://hirrolot.gitbook.io/metalang99/) | [Examples](examples/) | [User documentation](https://metalang99.readthedocs.io/en/latest/) + +Happy hacking! + +## Highlights + + - **Macro recursion.** Recursive calls behave as expected. In particular, to implement recursion, [Boost/Preprocessor] just copy-pastes all recursive functions up to a certain limit and forces to either keep track of recursion depth or rely on their built-in deduction. Being an interpreter, Metalang99 is free from such drawbacks. + + - **Almost the same syntax.** Metalang99 does not look too alien in comparison with [Order PP] because the syntax differs insignificantly from usual preprocessor code. + + - **Partial application.** Instead of tracking auxiliary arguments here and there (as it is done in Boost/Preprocessor), Metalang99's partial application allows to capture an environment by applying constant values first. Besides that, partial application facilitates better reuse of metafunctions; see `ML99_const`, `ML99_compose`, etc. + + - **Debugging and error reporting.** You can conveniently debug your macros with `ML99_abort` and report unrecoverable errors with `ML99_fatal`. The interpreter will immediately halt and do the trick. To the best of our knowledge, no other macro framework provides such a mechanism for debugging and error reporting. + +[Boost/Preprocessor]: http://boost.org/libs/preprocessor +[Order PP]: https://github.com/rofl0r/order-pp + +## Philosophy and origins + +My work on [Poica], a research programming language implemented upon [Boost/Preprocessor], has left me unsatisfied with the result. The fundamental limitations of Boost/Preprocessor have made the codebase simply unmaintainable; these include recursive macro calls (blocked by the preprocessor), which have made debugging a complete nightmare, the absence of partial application that has made context passing utterly awkward, and every single mistake that resulted in megabytes of compiler error messages. + +Only then I have understood that instead of enriching the preprocessor with various ad-hoc mechanisms, we should really establish a clear paradigm in which to structure metaprograms. With these thoughts in mind, I started to implement Metalang99... + +Long story short, it took half of a year of hard work to release v0.1.0 and almost a year to make it stable. As a real-world application of Metalang99, I created [Datatype99] exactly of the same form I wanted it to be: the implementation is highly declarative, the syntax is nifty, and the semantics is well-defined. + +Finally, I want to say that Metalang99 is only about syntax transformations and not about CPU-bound tasks; the preprocessor is just too slow and limited for such kind of abuse. + +[Poica]: https://github.com/hirrolot/poica + +## Guidelines + + - If possible, assert macro parameters for well-formedness using `ML99_assertIsTuple`, `ML99_assertIsNat`, etc. for better diagnostic messages. + - Prefer the `##` token-pasting operator inside [Metalang99-compliant macros] instead of `ML99_cat` or its friends, because arguments will nevertheless be fully expanded. + - Use [`ML99_todo` and its friends] to indicate unimplemented functionality. + +[Metalang99-compliant macros]: https://metalang99.readthedocs.io/en/latest/#definitions +[`ML99_todo` and its friends]: https://metalang99.readthedocs.io/en/latest/util.html#c.ML99_todo + +## Blog posts + + - [_Pretty-Printable Enumerations in Pure C_](https://hirrolot.github.io/posts/pretty-printable-enumerations-in-pure-c.html) + - [_What’s the Point of the C Preprocessor, Actually?_] + - [_Macros on Steroids, Or: How Can Pure C Benefit From Metaprogramming_](https://hirrolot.github.io/posts/macros-on-steroids-or-how-can-pure-c-benefit-from-metaprogramming.html) + - [_Extend Your Language, Don’t Alter It_](https://hirrolot.github.io/posts/extend-your-language-dont-alter-it.html) + +[_What’s the Point of the C Preprocessor, Actually?_]: https://hirrolot.github.io/posts/whats-the-point-of-the-c-preprocessor-actually.html + +## Contributing + +See [`CONTRIBUTING.md`](CONTRIBUTING.md). + +## Architecture + +See [`ARCHITECTURE.md`](ARCHITECTURE.md). + +## Idioms + +See [`idioms.md`](idioms.md). + +## Optimization tips + +See [`optimization_tips.md`](optimization_tips.md). + +## Release procedure + + 1. Update the `PROJECT_NUMBER` field in `Doxyfile`. + 2. Update the `release` field in `docs/conf.py`. + 3. Update `ML99_MAJOR`, `ML99_MINOR`, and `ML99_PATCH` in `include/metalang99.h`. + 4. Update the version number in `spec/spec.tex` & `spec/spec.pdf`. + 5. Update `CHANGELOG.md`. + 6. Release the project in [GitHub Releases]. + +[GitHub Releases]: https://github.com/hirrolot/metalang99/releases + +## FAQ + +### Q: What about compile-time errors? + +A: Metalang99 is a big step towards understandable compiler diagnostics. It has a built-in syntax checker that tests all incoming terms for validity: + +[`playground.c`] +```c +ML99_EVAL(123) +ML99_EVAL(x, y, z) +ML99_EVAL(v(Billie) v(Jean)) +``` + +[`/bin/sh`] +``` +$ gcc playground.c -Imetalang99/include -ftrack-macro-expansion=0 +playground.c:3:1: error: static assertion failed: "invalid term `123`" + 3 | ML99_EVAL(123) + | ^~~~~~~~~ +playground.c:4:1: error: static assertion failed: "invalid term `x`" + 4 | ML99_EVAL(x, y, z) + | ^~~~~~~~~ +playground.c:5:1: error: static assertion failed: "invalid term `(0v, Billie) (0v, Jean)`, did you miss a comma?" + 5 | ML99_EVAL(v(Billie) v(Jean)) + | ^~~~~~~~~ +``` + +Metalang99 can even check for macro preconditions and report an error: + +[`playground.c`] +```c +ML99_EVAL(ML99_listHead(ML99_nil())) +ML99_EVAL(ML99_unwrapLeft(ML99_right(v(123)))) +ML99_EVAL(ML99_div(v(18), v(4))) +``` + +[`/bin/sh`] +``` +$ gcc playground.c -Imetalang99/include -ftrack-macro-expansion=0 +playground.c:3:1: error: static assertion failed: "ML99_listHead: expected a non-empty list" + 3 | ML99_EVAL(ML99_listHead(ML99_nil())) + | ^~~~~~~~~ +playground.c:4:1: error: static assertion failed: "ML99_unwrapLeft: expected ML99_left but found ML99_right" + 4 | ML99_EVAL(ML99_unwrapLeft(ML99_right(v(123)))) + | ^~~~~~~~~ +playground.c:5:1: error: static assertion failed: "ML99_div: 18 is not divisible by 4" + 5 | ML99_EVAL(ML99_div(v(18), v(4))) + | ^~~~~~~~~ +``` + +However, if you do something awkward, compile-time errors can become quite obscured: + +```c +// ML99_PRIV_REC_NEXT_ML99_PRIV_IF_0 blah(ML99_PRIV_SYNTAX_CHECKER_EMIT_ERROR, ML99_PRIV_TERM_MATCH) ((~, ~, ~) blah, ML99_PRIV_EVAL_)(ML99_PRIV_REC_STOP, (~), 0fspace, (, ), ((0end, ~), ~), ~, ~ blah)(0)() +ML99_EVAL((~, ~, ~) blah) +``` + +In either case, you can try to [iteratively debug your metaprogram](https://hirrolot.gitbook.io/metalang99/testing-debugging-and-error-reporting). From my experience, 95% of errors are comprehensible -- Metalang99 is built for humans, not for macro monsters. + +### Q: What about debugging? + +A: See the chapter [_"Testing, debugging, and error reporting"_](https://hirrolot.gitbook.io/metalang99/testing-debugging-and-error-reporting). + +### Q: What about IDE support? + +A: I use VS Code for development. It enables pop-up suggestments of macro-generated constructions but, of course, it does not support macro syntax highlighting. + +### Q: Compilation times? + +A: To run the benchmarks, execute `./scripts/bench.sh` from the root directory. + +### Q: How does it work? + +A: + + 1. Because macro recursion is prohibited, there is an ad-hoc [recursion engine] which works by deferring macro expansions and passing continuations here and there. + 2. Upon it, the [continuation-passing style] [interpreter] reduces language expressions into final results. + 3. The standard library is nothing but a set of metafunctions implemented using the core metalanguage, i.e. they are to be evaluated by the interpreter. + +[recursion engine]: include/metalang99/eval/rec.h +[interpreter]: include/metalang99/eval/eval.h +[continuation-passing style]: https://en.wikipedia.org/wiki/Continuation-passing_style + +### Q: Why not third-party code generators? + +A: See the blog post [_"What’s the Point of the C Preprocessor, Actually?"_](https://hirrolot.github.io/posts/whats-the-point-of-the-c-preprocessor-actually.html) + +### Q: Is it Turing-complete? + +A: The C/C++ preprocessor is capable to iterate only [up to a certain limit](https://stackoverflow.com/questions/3136686/is-the-c99-preprocessor-turing-complete). For Metalang99, this limit is defined in terms of reductions steps: once a fixed amount of reduction steps is exhausted, your metaprogram will not be able to execute anymore. + +### Q: Why macros if we have templates? + +A: Metalang99 is primarily targeted at pure C, and C lacks templates. But anyway, you can find the argumentation for C++ at the website of [Boost/Preprocessor]. + +### Q: Which standards are supported? + +A: C99/C++11 and onwards. + +### Q: Which compilers are tested? + +A: Metalang99 is known to work on these compilers: + + - GCC + - Clang + - MSVC + - TCC diff --git a/test/external/metalang99/bench/100_call.c b/test/external/metalang99/bench/100_call.c new file mode 100644 index 0000000..e4b1981 --- /dev/null +++ b/test/external/metalang99/bench/100_call.c @@ -0,0 +1,12 @@ +#include <metalang99.h> + +#define F_IMPL(x, y, z) v(x + y + z) + +#define _5 \ + ML99_call(F, v(1), v(2), v(3)), ML99_call(F, v(1), v(2), v(3)), \ + ML99_call(F, v(1), v(2), v(3)), ML99_call(F, v(1), v(2), v(3)), \ + ML99_call(F, v(1), v(2), v(3)) +#define _10 _5, _5 +#define _100 _10, _10, _10, _10, _10, _10, _10, _10, _10, _10 + +ML99_EVAL(_100) diff --git a/test/external/metalang99/bench/100_v.c b/test/external/metalang99/bench/100_v.c new file mode 100644 index 0000000..d97c3ed --- /dev/null +++ b/test/external/metalang99/bench/100_v.c @@ -0,0 +1,8 @@ +#include <metalang99.h> + +#define _10 \ + v(~~~~~~~~~~), v(~~~~~~~~~~), v(~~~~~~~~~~), v(~~~~~~~~~~), v(~~~~~~~~~~), v(~~~~~~~~~~), \ + v(~~~~~~~~~~), v(~~~~~~~~~~), v(~~~~~~~~~~), v(~~~~~~~~~~) +#define _100 _10, _10, _10, _10, _10, _10, _10, _10, _10, _10 + +ML99_EVAL(_100) diff --git a/test/external/metalang99/bench/README.md b/test/external/metalang99/bench/README.md new file mode 100644 index 0000000..f8cb95e --- /dev/null +++ b/test/external/metalang99/bench/README.md @@ -0,0 +1,3 @@ +# Benchmarking + +Execute `./scripts/bench.sh` from the root directory to run the benchmarks. diff --git a/test/external/metalang99/bench/compare_25_items.c b/test/external/metalang99/bench/compare_25_items.c new file mode 100644 index 0000000..5a166f9 --- /dev/null +++ b/test/external/metalang99/bench/compare_25_items.c @@ -0,0 +1,6 @@ +#include <metalang99.h> + +#define NUMBERS \ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 + +ML99_ASSERT(ML99_listEq(v(ML99_natEq), ML99_list(v(NUMBERS)), ML99_list(v(NUMBERS)))); diff --git a/test/external/metalang99/bench/filter_map.c b/test/external/metalang99/bench/filter_map.c new file mode 100644 index 0000000..8aeb211 --- /dev/null +++ b/test/external/metalang99/bench/filter_map.c @@ -0,0 +1,9 @@ +#include <metalang99.h> + +#define _10 5, 5, 5, 5, 5, 3, 3, 3, 3, 3 +#define _50 _10, _10, _10, _10, _10 + +#define F_IMPL(x) ML99_if(ML99_natEq(v(x), v(5)), ML99_just(v(x)), ML99_nothing()) +#define F_ARITY 1 + +ML99_LIST_EVAL(ML99_listFilterMap(v(F), ML99_list(v(_50, _10, 3, 3, 3)))) diff --git a/test/external/metalang99/bench/list_of_63_items.c b/test/external/metalang99/bench/list_of_63_items.c new file mode 100644 index 0000000..8ee1f5c --- /dev/null +++ b/test/external/metalang99/bench/list_of_63_items.c @@ -0,0 +1,8 @@ +#include <metalang99.h> + +#define NUMBERS \ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, \ + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, \ + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63 + +ML99_EVAL(ML99_list(v(NUMBERS))) diff --git a/test/external/metalang99/bench/many_call_in_arg_pos.c b/test/external/metalang99/bench/many_call_in_arg_pos.c new file mode 100644 index 0000000..712738f --- /dev/null +++ b/test/external/metalang99/bench/many_call_in_arg_pos.c @@ -0,0 +1,10 @@ +#include <metalang99.h> + +#define F_IMPL(x) v(x) + +#define CALL ML99_call(F, ML99_call(F, ML99_call(F, v(~~~~~)))) +#define _5 CALL, CALL, CALL, CALL, CALL +#define _10 _5, _5 +#define _100 _10, _10, _10, _10, _10, _10, _10, _10, _10, _10 + +ML99_EVAL(_100) diff --git a/test/external/metalang99/docs/Makefile b/test/external/metalang99/docs/Makefile new file mode 100644 index 0000000..d4bb2cb --- /dev/null +++ b/test/external/metalang99/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/test/external/metalang99/docs/assert.rst b/test/external/metalang99/docs/assert.rst new file mode 100644 index 0000000..18d1ac0 --- /dev/null +++ b/test/external/metalang99/docs/assert.rst @@ -0,0 +1,5 @@ +assert.h +======== + +.. doxygenfile:: assert.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/bool.rst b/test/external/metalang99/docs/bool.rst new file mode 100644 index 0000000..8ef73f1 --- /dev/null +++ b/test/external/metalang99/docs/bool.rst @@ -0,0 +1,5 @@ +bool.h +====== + +.. doxygenfile:: bool.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/choice.rst b/test/external/metalang99/docs/choice.rst new file mode 100644 index 0000000..3ee0ab6 --- /dev/null +++ b/test/external/metalang99/docs/choice.rst @@ -0,0 +1,5 @@ +choice.h +======== + +.. doxygenfile:: choice.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/conf.py b/test/external/metalang99/docs/conf.py new file mode 100644 index 0000000..daebca3 --- /dev/null +++ b/test/external/metalang99/docs/conf.py @@ -0,0 +1,57 @@ +# Configuration file for the Sphinx documentation builder. +# +# This file only contains a selection of the most common options. For a full +# list see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + +# -- Project information ----------------------------------------------------- + +import subprocess + +subprocess.call("cd .. ; doxygen", shell=True) + +project = 'Metalang99' +copyright = '2021, hirrolot' +author = 'hirrolot' + +# The full version, including alpha/beta/rc tags +release = '1.13.5' + + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ["breathe"] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = "insipid" + +breathe_projects = {"Metalang99": "../xml"} +breathe_default_project = "Metalang99" +primary_domain = 'c' +highlight_language = 'c' diff --git a/test/external/metalang99/docs/either.rst b/test/external/metalang99/docs/either.rst new file mode 100644 index 0000000..5da16a2 --- /dev/null +++ b/test/external/metalang99/docs/either.rst @@ -0,0 +1,5 @@ +either.h +======== + +.. doxygenfile:: either.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/gen.rst b/test/external/metalang99/docs/gen.rst new file mode 100644 index 0000000..09a20b2 --- /dev/null +++ b/test/external/metalang99/docs/gen.rst @@ -0,0 +1,5 @@ +gen.h +===== + +.. doxygenfile:: gen.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/ident.rst b/test/external/metalang99/docs/ident.rst new file mode 100644 index 0000000..51823cf --- /dev/null +++ b/test/external/metalang99/docs/ident.rst @@ -0,0 +1,5 @@ +ident.h +======= + +.. doxygenfile:: ident.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/index.rst b/test/external/metalang99/docs/index.rst new file mode 100644 index 0000000..4666879 --- /dev/null +++ b/test/external/metalang99/docs/index.rst @@ -0,0 +1,120 @@ +.. Metalang99 documentation master file, created by + sphinx-quickstart on Mon Jan 4 08:10:23 2021. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +The Metalang99 Standard Library +=============================== + +The Metalang99 standard library exports a set of macros implemented using the `Metalang99 metalanguage`_. + +Definitions +----------- + + - A plain macro is a macro whose result can be computed only by preprocessor expansion. + + - A Metalang99-compliant macro is a macro called through `ML99_call`/`ML99_callUneval`, directly or indirectly. To compute its result, the Metalang99 interpreter is needed. + + - A desugaring macro is a convenience macro `X(params...)` which expands to `ML99_call(X, params...)` so that you can invoke `X` as `X(v(1), v(2), v(3))`. Desugaring macros are provided for all public Metalang99-compliant macros. + +Naming conventions +------------------ + + - Plain macros follow the `SCREAMING_CASE` convention. + - Metalang99-compliant macros follow the `camelCase` convention. + - Macros denoting language terms (defined by `lang.h`) follow the `camelCase` convention. + +Sometimes, there exist two versions of the same macro: one is plain, and the other is Metalang99-compliant. For example, here are two complete metaprograms, one using `ML99_untuple` and the second one using `ML99_UNTUPLE`: + +.. code:: c + + ML99_EVAL(ML99_untuple(v((1, 2, 3)))) + +.. code:: c + + ML99_UNTUPLE((1, 2, 3)) + +Both metaprograms result in `1, 2, 3`. + +Version manipulation macros +--------------------------- + +*The following macros are defined in metalang99.h*. + +`ML99_MAJOR`, `ML99_MINOR`, and `ML99_PATCH` denote the major, the minor, and the patch version numbers, respectively. + +`ML99_VERSION_COMPATIBLE(x, y, z)` and `ML99_VERSION_EQ(x, y, z)` are function-like macros that expand to a constant boolean expression: + + - The former holds iff the current Metalang99 version is at least vx.y.z in a `SemVer`_-compatible way. Thus, if the current version is v1.2.3, then `ML99_VERSION_COMPATIBLE` will hold for v1.2.3, v1.2.6, v1.6.0, but not for v2.5.0 or v3.0.0. + - The latter one holds iff the version is exactly vx.y.z. + +These macros can be used as follows: + +.. code:: c + + #if !ML99_VERSION_COMPATIBLE(1, 2, 3) + #error Please, update your Metalang99 to v1.2.3 or higher! + #endif + +.. toctree:: + :hidden: + + lang + choice + tuple + variadics + list + seq + either + maybe + nat + ident + bool + util + assert + gen + stmt + +Contents +==================================== + + - `lang.h`_ - The core metalanguage. + - `choice.h`_ - Choice types: `(tag, ...)`. + - `tuple.h`_ - Tuples: `(x, y, z)`. + - `variadics.h`_ - Variadic arguments: `x, y, z`. + - `list.h`_ - Cons-lists. + - `seq.h`_ - Sequences: `(x)(y)(z)`. + - `either.h`_ - A choice type with two cases. + - `maybe.h`_ - An optional value. + - `nat.h`_ - Natural numbers: [0; 255]. + - `ident.h`_ - Identifiers: `[a-zA-Z0-9_]+`. + - `bool.h`_ - Boolean algebra. + - `util.h`_ - Utilitary stuff. + - `assert.h`_ - Static assertions. + - `gen.h`_ - Support for C language constructions. + - `stmt.h`_ - Statement chaining. + +Indices and tables +==================================== + +* :ref:`genindex` +* :ref:`search` + +.. _Metalang99 metalanguage: https://github.com/hirrolot/metalang99 +.. _SemVer: https://semver.org/ + +.. _lang.h: lang.html +.. _choice.h: choice.html +.. _tuple.h: tuple.html +.. _variadics.h: variadics.html +.. _list.h: list.html +.. _seq.h: seq.html +.. _either.h: either.html +.. _maybe.h: maybe.html +.. _nat.h: nat.html +.. _ident.h: ident.html +.. _bool.h: bool.html +.. _util.h: util.html +.. _assert.h: assert.html +.. _gen.h: gen.html +.. _stmt.h: stmt.html diff --git a/test/external/metalang99/docs/lang.rst b/test/external/metalang99/docs/lang.rst new file mode 100644 index 0000000..1e413c1 --- /dev/null +++ b/test/external/metalang99/docs/lang.rst @@ -0,0 +1,5 @@ +lang.h +====== + +.. doxygenfile:: lang.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/list.rst b/test/external/metalang99/docs/list.rst new file mode 100644 index 0000000..7da444c --- /dev/null +++ b/test/external/metalang99/docs/list.rst @@ -0,0 +1,5 @@ +list.h +====== + +.. doxygenfile:: list.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/make.bat b/test/external/metalang99/docs/make.bat new file mode 100644 index 0000000..2119f51 --- /dev/null +++ b/test/external/metalang99/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/test/external/metalang99/docs/maybe.rst b/test/external/metalang99/docs/maybe.rst new file mode 100644 index 0000000..7b23c60 --- /dev/null +++ b/test/external/metalang99/docs/maybe.rst @@ -0,0 +1,5 @@ +maybe.h +======= + +.. doxygenfile:: maybe.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/nat.rst b/test/external/metalang99/docs/nat.rst new file mode 100644 index 0000000..e1410c2 --- /dev/null +++ b/test/external/metalang99/docs/nat.rst @@ -0,0 +1,5 @@ +nat.h +===== + +.. doxygenfile:: nat.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/requirements.txt b/test/external/metalang99/docs/requirements.txt new file mode 100644 index 0000000..2b0e822 --- /dev/null +++ b/test/external/metalang99/docs/requirements.txt @@ -0,0 +1,2 @@ +breathe >= 4.25.1 +insipid-sphinx-theme >= 0.2.8 diff --git a/test/external/metalang99/docs/seq.rst b/test/external/metalang99/docs/seq.rst new file mode 100644 index 0000000..dc8ea0d --- /dev/null +++ b/test/external/metalang99/docs/seq.rst @@ -0,0 +1,5 @@ +seq.h +===== + +.. doxygenfile:: seq.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/stmt.rst b/test/external/metalang99/docs/stmt.rst new file mode 100644 index 0000000..c0548c6 --- /dev/null +++ b/test/external/metalang99/docs/stmt.rst @@ -0,0 +1,5 @@ +stmt.h +====== + +.. doxygenfile:: stmt.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/tuple.rst b/test/external/metalang99/docs/tuple.rst new file mode 100644 index 0000000..c81bcf2 --- /dev/null +++ b/test/external/metalang99/docs/tuple.rst @@ -0,0 +1,5 @@ +tuple.h +======= + +.. doxygenfile:: tuple.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/util.rst b/test/external/metalang99/docs/util.rst new file mode 100644 index 0000000..f0637e8 --- /dev/null +++ b/test/external/metalang99/docs/util.rst @@ -0,0 +1,5 @@ +util.h +====== + +.. doxygenfile:: util.h + :project: Metalang99 diff --git a/test/external/metalang99/docs/variadics.rst b/test/external/metalang99/docs/variadics.rst new file mode 100644 index 0000000..126c2a8 --- /dev/null +++ b/test/external/metalang99/docs/variadics.rst @@ -0,0 +1,5 @@ +variadics.h +=========== + +.. doxygenfile:: variadics.h + :project: Metalang99 diff --git a/test/external/metalang99/examples/.gitignore b/test/external/metalang99/examples/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/test/external/metalang99/examples/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/test/external/metalang99/examples/CMakeLists.txt b/test/external/metalang99/examples/CMakeLists.txt new file mode 100644 index 0000000..ed8e963 --- /dev/null +++ b/test/external/metalang99/examples/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.16) +project(examples LANGUAGES C) + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + add_compile_options(-Wall -Wextra -pedantic -std=c99 + -ftrack-macro-expansion=0) +elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang") + add_compile_options("-fmacro-backtrace-limit=1") +elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") + # Enable a standard-conforming C99/C11 preprocessor. + add_compile_options("/std:c11") +elseif(CMAKE_C_COMPILER_ID STREQUAL "TinyCC") + add_compile_definitions(ML99_ALLOW_POOR_DIAGNOSTICS) +endif() + +include_directories(../include) + +add_executable(ackermann ackermann.c) +add_executable(assert_for_each assert_for_each.c) +add_executable(binary_tree binary_tree.c) +add_executable(demo demo.c) +add_executable(duffs_device duffs_device.c) +add_executable(factorial factorial.c) +add_executable(overload overload.c) +add_executable(rectangle rectangle.c) +add_executable(lambda_calculus lambda_calculus.c) + +foreach(TARGET ${BUILDSYSTEM_TARGETS}) + set_target_properties(TARGET PROPERTIES C_STANDARD 99 C_STANDARD_REQUIRED ON) +endforeach() diff --git a/test/external/metalang99/examples/ackermann.c b/test/external/metalang99/examples/ackermann.c new file mode 100644 index 0000000..a3ea623 --- /dev/null +++ b/test/external/metalang99/examples/ackermann.c @@ -0,0 +1,22 @@ +#include <metalang99.h> + +#define ack(m, n) ML99_natMatchWithArgs(m, v(ack_), n) + +#define ack_Z_IMPL(n) ML99_inc(v(n)) +#define ack_S_IMPL(m, n) ML99_natMatchWithArgs(v(n), v(ack_S_), v(m)) +#define ack_S_Z_IMPL(m) ack(v(m), v(1)) +#define ack_S_S_IMPL(n, m) ack(v(m), ack(ML99_inc(v(m)), v(n))) + +ML99_ASSERT_EQ(ack(v(0), v(0)), v(1)); +ML99_ASSERT_EQ(ack(v(0), v(1)), v(2)); +ML99_ASSERT_EQ(ack(v(0), v(2)), v(3)); + +ML99_ASSERT_EQ(ack(v(1), v(0)), v(2)); +ML99_ASSERT_EQ(ack(v(1), v(1)), v(3)); +ML99_ASSERT_EQ(ack(v(1), v(2)), v(4)); + +ML99_ASSERT_EQ(ack(v(2), v(0)), v(3)); +ML99_ASSERT_EQ(ack(v(2), v(1)), v(5)); +ML99_ASSERT_EQ(ack(v(2), v(2)), v(7)); + +int main(void) {} diff --git a/test/external/metalang99/examples/assert_for_each.c b/test/external/metalang99/examples/assert_for_each.c new file mode 100644 index 0000000..3ba9127 --- /dev/null +++ b/test/external/metalang99/examples/assert_for_each.c @@ -0,0 +1,31 @@ +// Asserts multiple expressions at once. + +#include <metalang99.h> + +#include <assert.h> + +#define ASSERT_FOR_EACH(...) \ + do { \ + ML99_EVAL(ML99_variadicsForEach( \ + ML99_compose(v(ML99_semicoloned), ML99_reify(v(assert))), \ + v(__VA_ARGS__))) \ + } while (0) + +int main(void) { + ASSERT_FOR_EACH(123 == 123, 2 + 2 == 4, "foo"[1] == 'o'); + + /* + * If we combine multiple assertions with the && operator, we will not be able to distinguish + * them if one of them fails apparently: + * + * main: Assertion `123 == 321 && 2 + 2 == 4 && "foo"[1] == 'o' failed. + * assert(123 == 321 && 2 + 2 == 4 && "foo"[1] == 'o'); + */ + + /* + * ... unlike `ASSERT_FOR_EACH` telling us which one has failed: + * + * main: Assertion `123 == 321' failed. + * ASSERT_FOR_EACH(123 == 321, 2 + 2 == 4, "foo"[1] == 'o'); + */ +} diff --git a/test/external/metalang99/examples/binary_tree.c b/test/external/metalang99/examples/binary_tree.c new file mode 100644 index 0000000..8cd9177 --- /dev/null +++ b/test/external/metalang99/examples/binary_tree.c @@ -0,0 +1,25 @@ +// Sums all nodes of a binary tree, recursively. + +#include <metalang99.h> + +#define leaf(x) ML99_choice(v(leaf), x) +#define node(lhs, data, rhs) ML99_choice(v(node), lhs, data, rhs) + +#define sumTree(tree) ML99_match(tree, v(sumTree_)) +#define sumTree_leaf_IMPL(x) v(x) +#define sumTree_node_IMPL(lhs, data, rhs) ML99_add3(sumTree(v(lhs)), v(data), sumTree(v(rhs))) + +/* + * 4 + * / \ + * / \ + * / \ + * 2 6 + * / \ / \ + * 1 3 5 7 + */ +#define TREE node(node(leaf(v(1)), v(2), leaf(v(3))), v(4), node(leaf(v(5)), v(6), leaf(v(7)))) + +ML99_ASSERT_EQ(sumTree(TREE), v(28)); + +int main(void) {} diff --git a/test/external/metalang99/examples/demo.c b/test/external/metalang99/examples/demo.c new file mode 100644 index 0000000..4a209d9 --- /dev/null +++ b/test/external/metalang99/examples/demo.c @@ -0,0 +1,48 @@ +// `...` is sometimes used to workaround a TCC bug, see +// <https://github.com/hirrolot/datatype99/issues/10#issuecomment-830813172>. + +#include <metalang99.h> + +// Compile-time list manipulation: + +// 3, 3, 3, 3, 3 +static int five_threes[] = { + ML99_LIST_EVAL_COMMA_SEP(ML99_listReplicate(v(5), v(3))), +}; + +// 5, 4, 3, 2, 1 +static int from_5_to_1[] = { + ML99_LIST_EVAL_COMMA_SEP(ML99_listReverse(ML99_list(v(1, 2, 3, 4, 5)))), +}; + +// 9, 2, 5 +static int lesser_than_10[] = { + ML99_LIST_EVAL_COMMA_SEP( + ML99_listFilter(ML99_appl(v(ML99_greater), v(10)), ML99_list(v(9, 2, 11, 13, 5)))), +}; + +// Macro recursion: +#define factorial(n) ML99_natMatch(n, v(factorial_)) +#define factorial_Z_IMPL(...) v(1) // `...` due to the TCC's bug. +#define factorial_S_IMPL(n) ML99_mul(ML99_inc(v(n)), factorial(v(n))) + +ML99_ASSERT_EQ(factorial(v(4)), v(24)); + +// Overloading on a number of arguments: +typedef struct { + double width, height; +} Rect; + +#define Rect_new(...) ML99_OVERLOAD(Rect_new_, __VA_ARGS__) +#define Rect_new_1(x) \ + { x, x } +#define Rect_new_2(x, y) \ + { x, y } + +static Rect _7x8 = Rect_new(7, 8), _10x10 = Rect_new(10); + +// ... and more! + +int main(void) { + // Yeah. All is done at compile time. +} diff --git a/test/external/metalang99/examples/duffs_device.c b/test/external/metalang99/examples/duffs_device.c new file mode 100644 index 0000000..cc5ade0 --- /dev/null +++ b/test/external/metalang99/examples/duffs_device.c @@ -0,0 +1,76 @@ +/** + * Duff's device [1] is a technique to implement loop unrolling through amalgamation of a switch + * statement with a do-while loop. + * + * In this example, we are going to implement automatic generation of Duff's device. + * + * [1]: https://en.wikipedia.org/wiki/Duff's_device + */ + +#include <metalang99.h> + +#include <assert.h> + +#define DUFFS_DEVICE(unrolling_factor, counter_ty, count, ...) \ + do { \ + if ((count) > 0) { \ + counter_ty DUFFS_DEVICE_n = ((count) + ML99_DEC(unrolling_factor)) / unrolling_factor; \ + switch ((count) % unrolling_factor) { \ + case 0: \ + do { \ + __VA_ARGS__ \ + ML99_EVAL(ML99_callUneval(genCases, ML99_DEC(unrolling_factor), __VA_ARGS__)) \ + } while (--DUFFS_DEVICE_n > 0); \ + } \ + } \ + } while (0) + +#define genCases_IMPL(i, ...) \ + ML99_IF( \ + ML99_NAT_EQ(i, 0), \ + ML99_empty(), \ + ML99_TERMS( \ + v(/* FALLTHROUGH */ case i \ + : __VA_ARGS__), \ + ML99_callUneval(genCases, ML99_DEC(i), __VA_ARGS__))) + +int main(void) { +#define ARRAY_LEN 50 +#define UNROLLING_FACTOR 3 + + int array[ARRAY_LEN] = { ML99_EVAL(ML99_times(v(ARRAY_LEN), v(5, ))) }; + int *n_ptr = array; + + // Square all the elements in the array. + DUFFS_DEVICE(UNROLLING_FACTOR, int, ARRAY_LEN, { + *n_ptr *= *n_ptr; + n_ptr++; + }); + + for (int i = 0; i < ARRAY_LEN; i++) { + assert(25 == array[i]); + } +} + +/* +The generated Duff's device: + +int DUFFS_DEVICE_n = ((50) + 2) / 3; +switch ((50) % 3) { +case 0: + do { + { + *n_ptr *= *n_ptr; + n_ptr++; + } + case 2: { + *n_ptr *= *n_ptr; + n_ptr++; + } + case 1: { + *n_ptr *= *n_ptr; + n_ptr++; + } + } while (--DUFFS_DEVICE_n > 0); +} +*/ diff --git a/test/external/metalang99/examples/factorial.c b/test/external/metalang99/examples/factorial.c new file mode 100644 index 0000000..ed381fa --- /dev/null +++ b/test/external/metalang99/examples/factorial.c @@ -0,0 +1,16 @@ +// `...` is sometimes used to workaround a TCC bug, see +// <https://github.com/hirrolot/datatype99/issues/10#issuecomment-830813172>. + +#include <metalang99.h> + +#define factorial(n) ML99_natMatch(n, v(factorial_)) +#define factorial_Z_IMPL(...) v(1) // `...` due to the TCC's bug. +#define factorial_S_IMPL(n) ML99_mul(ML99_inc(v(n)), factorial(v(n))) + +ML99_ASSERT_EQ(factorial(v(0)), v(1)); +ML99_ASSERT_EQ(factorial(v(1)), v(1)); +ML99_ASSERT_EQ(factorial(v(2)), v(2)); +ML99_ASSERT_EQ(factorial(v(3)), v(6)); +ML99_ASSERT_EQ(factorial(v(4)), v(24)); + +int main(void) {} diff --git a/test/external/metalang99/examples/lambda_calculus.c b/test/external/metalang99/examples/lambda_calculus.c new file mode 100644 index 0000000..e300304 --- /dev/null +++ b/test/external/metalang99/examples/lambda_calculus.c @@ -0,0 +1,209 @@ +/* + * An untyped lambda calculus [1] interpreter using De Bruijn indices [2] and normal order + * evaluation strategy [3]. + * + * [1] https://en.wikipedia.org/wiki/Lambda_calculus + * [2] https://en.wikipedia.org/wiki/De_Bruijn_index + * [3] https://en.wikipedia.org/wiki/Evaluation_strategy#Normal_order + */ + +#include <metalang99.h> + +// Syntactic terms { + +#define var(i) ML99_call(var, i) +#define appl(M, N) ML99_call(appl, M, N) +#define lam(M) ML99_call(lam, M) + +#define var_IMPL(i) v(VAR(i)) +#define appl_IMPL(M, N) v(APPL(M, N)) +#define lam_IMPL(M) v(LAM(M)) + +#define VAR(i) ML99_CHOICE(var, i) +#define APPL(M, N) ML99_CHOICE(appl, M, N) +#define LAM(M) ML99_CHOICE(lam, M) +// } (Syntactic terms) + +// Variable substitution: `M[1=x]` { + +#define subst(M, x) ML99_call(subst, M, x) + +#define subst_IMPL(M, x) substAux_IMPL(M, x, 1) +#define substAux_IMPL(M, x, depth) ML99_callUneval(ML99_matchWithArgs, M, substAux_, x, depth) + +#define substAux_var_IMPL(i, x, depth) \ + ML99_IF( \ + ML99_NAT_EQ(i, depth), \ + v(x), \ + ML99_call(ML99_if, ML99_callUneval(ML99_greater, i, depth), v(VAR(ML99_DEC(i)), VAR(i)))) +#define substAux_appl_IMPL(M, N, x, depth) \ + appl(substAux_IMPL(M, x, depth), substAux_IMPL(N, x, depth)) +#define substAux_lam_IMPL(M, x, depth) \ + lam(ML99_call(substAux, v(M), incFreeVars_IMPL(x), v(ML99_INC(depth)))) +// } (Variable substitution) + +// Increment free variables in `M` { + +#define incFreeVars(M) ML99_call(incFreeVars, M) + +#define incFreeVars_IMPL(M) incFreeVarsAux_IMPL(M, 1) +#define incFreeVarsAux_IMPL(M, depth) ML99_callUneval(ML99_matchWithArgs, M, incFreeVarsAux_, depth) + +#define incFreeVarsAux_var_IMPL(i, depth) \ + ML99_call(ML99_if, ML99_callUneval(ML99_greaterEq, i, depth), v(VAR(ML99_INC(i)), VAR(i))) +#define incFreeVarsAux_appl_IMPL(M, N, depth) \ + appl(incFreeVarsAux_IMPL(M, depth), incFreeVarsAux_IMPL(N, depth)) +#define incFreeVarsAux_lam_IMPL(M, depth) lam(incFreeVarsAux_IMPL(M, ML99_INC(depth))) +// } (Increment free variables) + +// Evaluation { + +#define eval(M) ML99_call(eval, M) + +#define eval_IMPL(M) ML99_callUneval(ML99_match, M, eval_) +#define eval_var_IMPL(i) v(VAR(i)) +#define eval_appl_IMPL(M, N) ML99_callUneval(ML99_matchWithArgs, M, eval_appl_, N) +#define eval_lam_IMPL(M) lam(eval_IMPL(M)) + +#define eval_appl_var_IMPL(i, N) appl(v(VAR(i)), eval_IMPL(N)) +#define eval_appl_appl_IMPL(M, N, N1) \ + ML99_call(ML99_matchWithArgs, eval(appl_IMPL(M, N)), v(eval_appl_appl_, N1)) +#define eval_appl_lam_IMPL(M, N) eval(subst_IMPL(M, N)) + +#define eval_appl_appl_var_IMPL eval_appl_var_IMPL +#define eval_appl_appl_appl_IMPL(M, N, N1) appl(appl_IMPL(M, N), eval_IMPL(N1)) +#define eval_appl_appl_lam_IMPL eval_appl_lam_IMPL +// } (Evaluation) + +// Syntactical equality { + +#define termEq(lhs, rhs) ML99_matchWithArgs(lhs, v(termEq_), rhs) +#define termEq_var_IMPL(i, rhs) termEqPropagate(var, rhs, i) +#define termEq_appl_IMPL(M, N, rhs) termEqPropagate(appl, rhs, M, N) +#define termEq_lam_IMPL(M, rhs) termEqPropagate(lam, rhs, M) + +#define termEqPropagate(term_kind, rhs, ...) \ + ML99_IF( \ + ML99_IDENT_EQ(TERM_, ML99_CHOICE_TAG(rhs), term_kind), \ + ML99_matchWithArgs(v(rhs), v(termEq_##term_kind##_), v(__VA_ARGS__)), \ + ML99_false()) + +#define termEq_var_var_IMPL(j, i) v(ML99_NAT_EQ(i, j)) +#define termEq_appl_appl_IMPL(M, N, M1, N1) ML99_and(termEq(v(M), v(M1)), termEq(v(N), v(N1))) +#define termEq_lam_lam_IMPL(M, M1) termEq(v(M), v(M1)) + +#define TERM_var_var () +#define TERM_appl_appl () +#define TERM_lam_lam () +// } (Syntactical equality) + +#define ASSERT_REDUCES_TO(lhs, rhs) \ + /* Use two interpreter passes: one for `eval(lhs)`, one for `termEq`. Thereby we achieve more \ + * Metalang99 reduction steps available. */ \ + ML99_ASSERT_UNEVAL(ML99_EVAL(termEq(v(ML99_EVAL(eval(v(lhs)))), v(ML99_EVAL(eval(v(rhs))))))) + +// The identity combinator { + +#define I LAM(VAR(1)) + +ASSERT_REDUCES_TO(APPL(I, VAR(5)), VAR(5)); +// } (The identity combinator) + +// The K, S combinators { + +#define K LAM(LAM(VAR(2))) +#define S LAM(LAM(LAM(APPL(APPL(VAR(3), VAR(1)), APPL(VAR(2), VAR(1)))))) + +ASSERT_REDUCES_TO(APPL(APPL(S, K), K), I); +ASSERT_REDUCES_TO(APPL(APPL(APPL(S, K), S), K), K); + +ASSERT_REDUCES_TO(APPL(APPL(APPL(S, K), VAR(5)), VAR(6)), VAR(6)); +ASSERT_REDUCES_TO(APPL(APPL(K, VAR(5)), VAR(6)), VAR(5)); +// } (The K, S combinators) + +// Church booleans { + +#define T LAM(LAM(VAR(2))) +#define F LAM(LAM(VAR(1))) + +#define NOT LAM(APPL(APPL(VAR(1), F), T)) +#define AND LAM(LAM(APPL(APPL(VAR(2), VAR(1)), VAR(2)))) +#define OR LAM(LAM(APPL(APPL(VAR(2), VAR(2)), VAR(1)))) +#define XOR LAM(LAM(APPL(APPL(VAR(2), APPL(NOT, VAR(1))), VAR(1)))) + +#define IF LAM(LAM(LAM(APPL(APPL(VAR(3), VAR(2)), VAR(1))))) + +ASSERT_REDUCES_TO(APPL(NOT, T), F); +ASSERT_REDUCES_TO(APPL(NOT, F), T); +ASSERT_REDUCES_TO(APPL(NOT, APPL(NOT, T)), T); +ASSERT_REDUCES_TO(APPL(NOT, APPL(NOT, F)), F); + +ASSERT_REDUCES_TO(APPL(APPL(AND, T), T), T); +ASSERT_REDUCES_TO(APPL(APPL(AND, T), F), F); +ASSERT_REDUCES_TO(APPL(APPL(AND, F), T), F); +ASSERT_REDUCES_TO(APPL(APPL(AND, F), F), F); + +ASSERT_REDUCES_TO(APPL(APPL(OR, T), T), T); +ASSERT_REDUCES_TO(APPL(APPL(OR, T), F), T); +ASSERT_REDUCES_TO(APPL(APPL(OR, F), T), T); +ASSERT_REDUCES_TO(APPL(APPL(OR, F), F), F); + +ASSERT_REDUCES_TO(APPL(APPL(XOR, T), T), F); +ASSERT_REDUCES_TO(APPL(APPL(XOR, T), F), T); +ASSERT_REDUCES_TO(APPL(APPL(XOR, F), T), T); +ASSERT_REDUCES_TO(APPL(APPL(XOR, F), F), F); + +ASSERT_REDUCES_TO(APPL(APPL(APPL(IF, T), VAR(5)), VAR(6)), VAR(5)); +ASSERT_REDUCES_TO(APPL(APPL(APPL(IF, F), VAR(5)), VAR(6)), VAR(6)); +// } (Church booleans) + +// Church numerals { + +#define ZERO LAM(LAM(VAR(1))) +#define SUCC LAM(LAM(LAM(APPL(VAR(2), APPL(APPL(VAR(3), VAR(2)), VAR(1)))))) + +#define ONE APPL(SUCC, ZERO) +#define TWO APPL(SUCC, ONE) +#define THREE APPL(SUCC, TWO) +#define FOUR APPL(SUCC, THREE) + +#define ADD LAM(LAM(LAM(LAM(APPL(APPL(VAR(4), VAR(2)), APPL(APPL(VAR(3), VAR(2)), VAR(1))))))) +#define MUL LAM(LAM(LAM(LAM(APPL(APPL(VAR(4), APPL(VAR(3), VAR(2))), VAR(1)))))) + +ASSERT_REDUCES_TO(APPL(APPL(ADD, ZERO), ZERO), ZERO); +ASSERT_REDUCES_TO(APPL(APPL(ADD, ZERO), ONE), ONE); +ASSERT_REDUCES_TO(APPL(APPL(ADD, ONE), ZERO), ONE); +ASSERT_REDUCES_TO(APPL(APPL(ADD, ONE), TWO), THREE); + +ASSERT_REDUCES_TO(APPL(APPL(MUL, ZERO), ZERO), ZERO); +ASSERT_REDUCES_TO(APPL(APPL(MUL, ZERO), ONE), ZERO); +ASSERT_REDUCES_TO(APPL(APPL(MUL, ONE), ZERO), ZERO); +ASSERT_REDUCES_TO(APPL(APPL(MUL, TWO), TWO), FOUR); +// } (Church numerals) + +// Church pairs { + +#define PAIR LAM(LAM(LAM(APPL(APPL(VAR(1), VAR(3)), VAR(2))))) +#define FST LAM(APPL(VAR(1), T)) +#define SND LAM(APPL(VAR(1), F)) + +ASSERT_REDUCES_TO(APPL(FST, APPL(APPL(PAIR, VAR(5)), VAR(6))), VAR(5)); +ASSERT_REDUCES_TO(APPL(SND, APPL(APPL(PAIR, VAR(5)), VAR(6))), VAR(6)); +// } (Church pairs) + +// Church lists { + +#define NIL F +#define CONS PAIR +#define IS_NIL LAM(APPL(APPL(VAR(1), LAM(LAM(LAM(F)))), T)) + +#define LIST_1_2_3 APPL(APPL(CONS, VAR(1)), APPL(APPL(CONS, VAR(2)), APPL(APPL(CONS, VAR(3)), NIL))) + +ASSERT_REDUCES_TO(APPL(IS_NIL, NIL), T); +ASSERT_REDUCES_TO(APPL(IS_NIL, LIST_1_2_3), F); +// } (Church lists) + +// Recursion via self-application (or the Y combinator) is perfectly expressible, though when +// executed, it exhausts the Metalang99 recursion engine limit. + +int main(void) {} diff --git a/test/external/metalang99/examples/overload.c b/test/external/metalang99/examples/overload.c new file mode 100644 index 0000000..8b5d6fd --- /dev/null +++ b/test/external/metalang99/examples/overload.c @@ -0,0 +1,15 @@ +#include <metalang99.h> + +typedef struct { + double width, height; +} Rect; + +#define Rect_new(...) ML99_OVERLOAD(Rect_new_, __VA_ARGS__) +#define Rect_new_1(x) \ + { x, x } +#define Rect_new_2(x, y) \ + { x, y } + +static Rect _7x8 = Rect_new(7, 8), _10x10 = Rect_new(10); + +int main(void) {} diff --git a/test/external/metalang99/examples/rectangle.c b/test/external/metalang99/examples/rectangle.c new file mode 100644 index 0000000..1ab2bbf --- /dev/null +++ b/test/external/metalang99/examples/rectangle.c @@ -0,0 +1,25 @@ +// Computes the area of a rectangle. + +#include <metalang99.h> + +#define rect(width, height) ML99_tuple(width, height) +#define rectWidth ML99_tupleGet(0) +#define rectHeight ML99_tupleGet(1) + +#define rectArea(rect) ML99_mul(rectWidth(rect), rectHeight(rect)) + +/* + * 15 + * +------------------------------+ + * | | + * | | + * | | 7 + * | | + * | | + * +------------------------------+ + */ +#define RECTANGLE rect(v(15), v(7)) + +ML99_ASSERT_EQ(rectArea(RECTANGLE), v(15 * 7)); + +int main(void) {} diff --git a/test/external/metalang99/idioms.md b/test/external/metalang99/idioms.md new file mode 100644 index 0000000..3ed23c8 --- /dev/null +++ b/test/external/metalang99/idioms.md @@ -0,0 +1,44 @@ +# Idioms + +_This document describes common idioms when using Metalang99, i.e., code patterns that have not been reified into abstractions yet._ + +## Detecting a keyword followed by parentheses + +To detect something like `abracadabra(1, 2, 3)`, follow this simple pattern: + +```c +#define DETECT_ABRACADABRA(x) ML99_IS_TUPLE(ML99_CAT(DETECT_ABRACADABRA_, x)) +#define DETECT_ABRACADABRA_abracadabra(...) () + +// 1 +DETECT_ABRACADABRA(abracadabra(1, 2, 3)) + +// 0 +DETECT_ABRACADABRA(blah) +``` + +## Extracting a value of a keyword followed by parentheses + +To get `1, 2, 3` from `abracadabra(1, 2, 3)`: + +```c +#define EXTRACT_ABRACADABRA(x) ML99_CAT(EXTRACT_ABRACADABRA_, x) +#define EXTRACT_ABRACADABRA_abracadabra(...) __VA_ARGS__ + +// 1, 2, 3 +EXTRACT_ABRACADABRA(abracadabra(1, 2, 3)) +``` + +## Interspersing a comma + +To intersperse a comma between one or more elements, put a comma before each element and pass them all to `ML99_variadicsTail`: + +```c +#define ARRAY_SUBSCRIPTS(array, n) \ + ML99_EVAL(ML99_variadicsTail(ML99_repeat(v(n), ML99_appl(v(GEN_SUBSCRIPT), v(array))))) +#define GEN_SUBSCRIPT_IMPL(array, i) v(, (array)[i]) +#define GEN_SUBSCRIPT_ARITY 2 + +// (animals)[0], (animals)[1], (animals)[2] +ARRAY_SUBSCRIPTS(animals, 3) +``` diff --git a/test/external/metalang99/include/metalang99.h b/test/external/metalang99/include/metalang99.h new file mode 100644 index 0000000..714c525 --- /dev/null +++ b/test/external/metalang99/include/metalang99.h @@ -0,0 +1,33 @@ +#ifndef ML99_H +#define ML99_H + +#if defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL +#error Please, specify /Zc:preprocessor to enable a standard-compliant C99/C++11 preprocessor. +#endif + +#include <metalang99/assert.h> +#include <metalang99/bool.h> +#include <metalang99/choice.h> +#include <metalang99/either.h> +#include <metalang99/gen.h> +#include <metalang99/ident.h> +#include <metalang99/lang.h> +#include <metalang99/list.h> +#include <metalang99/maybe.h> +#include <metalang99/nat.h> +#include <metalang99/seq.h> +#include <metalang99/stmt.h> +#include <metalang99/tuple.h> +#include <metalang99/util.h> +#include <metalang99/variadics.h> + +#define ML99_MAJOR 1 +#define ML99_MINOR 13 +#define ML99_PATCH 5 + +#define ML99_VERSION_COMPATIBLE(x, y, z) \ + (ML99_MAJOR == (x) && ((ML99_MINOR == (y) && ML99_PATCH >= (z)) || (ML99_MINOR > (y)))) + +#define ML99_VERSION_EQ(x, y, z) (ML99_MAJOR == (x) && ML99_MINOR == (y) && ML99_PATCH == (z)) + +#endif // ML99_H diff --git a/test/external/metalang99/include/metalang99/assert.h b/test/external/metalang99/include/metalang99/assert.h new file mode 100644 index 0000000..bbaa89b --- /dev/null +++ b/test/external/metalang99/include/metalang99/assert.h @@ -0,0 +1,134 @@ +/** + * @file + * Static assertions. + * + * For the sake of convenience, this header automatically includes `metalang99/bool.h`. + * + * @note [C99] Any of the following assertion macros must **not** appear on the same line number + * twice with itself as well as with any other Metalang99 assertion macro. + * @note [C11] The following assertion macros expand to `_Static_assert` and, therefore, can be used + * on the same line twice. + */ + +#ifndef ML99_ASSERT_H +#define ML99_ASSERT_H + +#include <metalang99/priv/compiler_specific.h> + +#include <metalang99/bool.h> +#include <metalang99/lang.h> + +/** + * The same as #ML99_ASSERT but results in a Metalang99 term. + * + * It can be used inside other Metalang99-compliant macros, unlike #ML99_ASSERT, which uses + * #ML99_EVAL internally. + */ +#define ML99_assert(expr) ML99_call(ML99_assert, expr) + +/** + * Like #ML99_assert but compares @p lhs with @p rhs for equality (`==`). + */ +#define ML99_assertEq(lhs, rhs) ML99_call(ML99_assertEq, lhs, rhs) + +/** + * Asserts `ML99_EVAL(expr)` at compile-time. + * + * # Examples + * + * @code + * #include <metalang99/assert.h> + * + * ML99_ASSERT(v(123 == 123)); + * @endcode + */ +#define ML99_ASSERT(expr) ML99_ASSERT_EQ(expr, ML99_true()) + +/** + * Asserts `ML99_EVAL(lhs) == ML99_EVAL(rhs)` at compile-time. + * + * # Examples + * + * @code + * #include <metalang99/assert.h> + * + * ML99_ASSERT_EQ(v(123), v(123)); + * @endcode + */ +#define ML99_ASSERT_EQ(lhs, rhs) ML99_ASSERT_UNEVAL((ML99_EVAL(lhs)) == (ML99_EVAL(rhs))) + +/** + * Asserts the C constant expression @p expr; + * [static_assert](https://en.cppreference.com/w/c/error/static_assert) in pure C99. + * + * # Examples + * + * @code + * #include <metalang99/assert.h> + * + * ML99_ASSERT_UNEVAL(123 == 123); + * @endcode + */ +#define ML99_ASSERT_UNEVAL(expr) ML99_PRIV_ASSERT_UNEVAL_INNER(expr) + +/** + * Asserts that `ML99_EVAL(expr)` is emptiness. + * + * # Examples + * + * @code + * #include <metalang99/assert.h> + * + * // Passes: + * ML99_ASSERT_EMPTY(v()); + * + * // Fails: + * ML99_ASSERT_EMPTY(v(123)); + * @endcode + */ +#define ML99_ASSERT_EMPTY(expr) ML99_ASSERT_EMPTY_UNEVAL(ML99_EVAL(expr)) + +/** + * Asserts that @p expr is emptiness. + * + * # Examples + * + * @code + * #include <metalang99/assert.h> + * + * // Passes: + * ML99_ASSERT_EMPTY_UNEVAL(); + * + * // Fails: + * ML99_ASSERT_EMPTY_UNEVAL(123); + * @endcode + */ +#define ML99_ASSERT_EMPTY_UNEVAL(expr) \ + ML99_ASSERT_UNEVAL(ML99_PRIV_CAT(ML99_PRIV_ASSERT_EMPTY_, expr)) + +#ifndef DOXYGEN_IGNORE + +#define ML99_assert_IMPL(expr) v(ML99_ASSERT_UNEVAL(expr)) +#define ML99_assertEq_IMPL(lhs, rhs) v(ML99_ASSERT_UNEVAL((lhs) == (rhs))) + +#ifdef ML99_PRIV_C11_STATIC_ASSERT_AVAILABLE +#define ML99_PRIV_ASSERT_UNEVAL_INNER(expr) _Static_assert((expr), "Metalang99 assertion failed") +#else +// How to imitate static assertions in C99: <https://stackoverflow.com/a/3385694/13166656>. +#define ML99_PRIV_ASSERT_UNEVAL_INNER(expr) \ + static const char ML99_PRIV_CAT( \ + ml99_assert_, \ + __LINE__)[(expr) ? 1 : -1] ML99_PRIV_COMPILER_ATTR_UNUSED = {0} +#endif + +#define ML99_PRIV_ASSERT_EMPTY_ 1 + +// Arity specifiers { + +#define ML99_assert_ARITY 1 +#define ML99_assertEq_ARITY 2 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_ASSERT_H diff --git a/test/external/metalang99/include/metalang99/bool.h b/test/external/metalang99/include/metalang99/bool.h new file mode 100644 index 0000000..0213cb2 --- /dev/null +++ b/test/external/metalang99/include/metalang99/bool.h @@ -0,0 +1,246 @@ +/** + * @file + * Boolean algebra. + */ + +#ifndef ML99_BOOL_H +#define ML99_BOOL_H + +#include <metalang99/priv/bool.h> +#include <metalang99/priv/tuple.h> + +#include <metalang99/lang.h> + +/** + * Truth. + */ +#define ML99_true(...) ML99_callUneval(ML99_true, ) + +/** + * Falsehood. + */ +#define ML99_false(...) ML99_callUneval(ML99_false, ) + +/** + * Logical negation. + * + * # Examples + * + * @code + * #include <metalang99/bool.h> + * + * // 1 + * ML99_not(v(0)) + * + * // 0 + * ML99_not(v(1)) + * @endcode + */ +#define ML99_not(x) ML99_call(ML99_not, x) + +/** + * Logical conjunction. + * + * # Examples + * + * @code + * #include <metalang99/bool.h> + * + * // 0 + * ML99_and(v(0), v(0)) + * + * // 0 + * ML99_and(v(0), v(1)) + * + * // 0 + * ML99_and(v(1), v(0)) + * + * // 1 + * ML99_and(v(1), v(1)) + * @endcode + */ +#define ML99_and(x, y) ML99_call(ML99_and, x, y) + +/** + * Logical inclusive OR. + * + * # Examples + * @code + * #include <metalang99/bool.h> + * + * // 0 + * ML99_or(v(0), v(0)) + * + * // 1 + * ML99_or(v(0), v(1)) + * + * // 1 + * ML99_or(v(1), v(0)) + * + * // 1 + * ML99_or(v(1), v(1)) + * @endcode + */ +#define ML99_or(x, y) ML99_call(ML99_or, x, y) + +/** + * Logical exclusive OR. + * + * # Examples + * + * @code + * #include <metalang99/bool.h> + * + * // 0 + * ML99_xor(v(0), v(0)) + * + * // 1 + * ML99_xor(v(0), v(1)) + * + * // 1 + * ML99_xor(v(1), v(0)) + * + * // 0 + * ML99_xor(v(1), v(1)) + * @endcode + */ +#define ML99_xor(x, y) ML99_call(ML99_xor, x, y) + +/** + * Tests @p x and @p y for equality. + * + * # Examples + * + * @code + * #include <metalang99/bool.h> + * + * // 1 + * ML99_boolEq(v(0), v(0)) + * + * // 0 + * ML99_boolEq(v(0), v(1)) + * + * // 0 + * ML99_boolEq(v(1), v(0)) + * + * // 1 + * ML99_boolEq(v(1), v(1)) + * @endcode + */ +#define ML99_boolEq(x, y) ML99_call(ML99_boolEq, x, y) + +/** + * Matches @p x against the two cases: if it is 0 or 1. + * + * # Examples + * + * @code + * #include <metalang99/bool.h> + * + * #define MATCH_1_IMPL() v(Billie) + * #define MATCH_0_IMPL() v(Jean) + * + * // Billie + * ML99_boolMatch(v(1), v(MATCH_)) + * + * // Jean + * ML99_boolMatch(v(0), v(MATCH_)) + * @endcode + * + * @note This function calls @p f with #ML99_call, so no partial application occurs, and so + * arity specifiers are not needed. + */ +#define ML99_boolMatch(x, matcher) ML99_call(ML99_boolMatch, x, matcher) + +/** + * The same as #ML99_boolMatch but provides additional arguments to all branches. + * + * # Examples + * + * @code + * #include <metalang99/bool.h> + * + * #define MATCH_1_IMPL(x, y, z) v(Billie ~ x y z) + * #define MATCH_0_IMPL(x, y, z) v(Jean ~ x y z) + * + * // Billie ~ 1 2 3 + * ML99_boolMatchWithArgs(v(1), v(MATCH_), v(1, 2, 3)) + * + * // Jean ~ 1 2 3 + * ML99_boolMatchWithArgs(v(0), v(MATCH_), v(1, 2, 3)) + * @endcode + */ +#define ML99_boolMatchWithArgs(x, matcher, ...) \ + ML99_call(ML99_boolMatchWithArgs, x, matcher, __VA_ARGS__) + +/** + * If @p cond is true, evaluates to @p x, otherwise @p y. + * + * # Examples + * + * @code + * #include <metalang99/bool.h> + * + * // 123 + * ML99_if(v(1), v(123), v(18)) + * + * // 18 + * ML99_if(v(0), v(123), v(18)) + * @endcode + */ +#define ML99_if(cond, x, y) ML99_call(ML99_if, cond, x, y) + +/** + * The plain version of #ML99_if. + * + * This macro can imitate lazy evaluation: `ML99_IF(<cond>, <term>, <another-term>)` will expand to + * one of the two terms, which can be evaluated further; if `<cond>` is 0, then `<term>` will + * **not** be evaluated, and the same with `<another-term>`. + * + * @note @p x and @p y can possibly expand to commas. It means that you can supply `ML99_TERMS(...)` + * as a branch, for example. + */ +#define ML99_IF(cond, x, y) ML99_PRIV_UNTUPLE(ML99_PRIV_IF(cond, (x), (y))) + +#define ML99_TRUE(...) 1 +#define ML99_FALSE(...) 0 + +#define ML99_NOT(x) ML99_PRIV_NOT(x) +#define ML99_AND(x, y) ML99_PRIV_AND(x, y) +#define ML99_OR(x, y) ML99_PRIV_OR(x, y) +#define ML99_XOR(x, y) ML99_PRIV_XOR(x, y) +#define ML99_BOOL_EQ(x, y) ML99_PRIV_BOOL_EQ(x, y) + +#ifndef DOXYGEN_IGNORE + +#define ML99_true_IMPL(...) v(ML99_TRUE()) +#define ML99_false_IMPL(...) v(ML99_FALSE()) + +#define ML99_not_IMPL(x) v(ML99_NOT(x)) +#define ML99_and_IMPL(x, y) v(ML99_AND(x, y)) +#define ML99_or_IMPL(x, y) v(ML99_OR(x, y)) +#define ML99_xor_IMPL(x, y) v(ML99_XOR(x, y)) +#define ML99_boolEq_IMPL(x, y) v(ML99_BOOL_EQ(x, y)) + +#define ML99_boolMatch_IMPL(x, matcher) ML99_callUneval(matcher##x, ) +#define ML99_boolMatchWithArgs_IMPL(x, matcher, ...) ML99_callUneval(matcher##x, __VA_ARGS__) + +#define ML99_if_IMPL(cond, x, y) v(ML99_PRIV_IF(cond, x, y)) + +// Arity specifiers { + +#define ML99_true_ARITY 1 +#define ML99_false_ARITY 1 +#define ML99_not_ARITY 1 +#define ML99_and_ARITY 2 +#define ML99_or_ARITY 2 +#define ML99_xor_ARITY 2 +#define ML99_boolEq_ARITY 2 +#define ML99_boolMatch_ARITY 2 +#define ML99_boolMatchWithArgs_ARITY 3 +#define ML99_if_ARITY 3 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_BOOL_H diff --git a/test/external/metalang99/include/metalang99/choice.h b/test/external/metalang99/include/metalang99/choice.h new file mode 100644 index 0000000..fcdcf07 --- /dev/null +++ b/test/external/metalang99/include/metalang99/choice.h @@ -0,0 +1,129 @@ +/** + * @file + * Choice types: `(tag, ...)`. + * + * A choice type, also known as [tagged union], is represented as `(tag, ...)`, where `tag` is the + * type of a value and `...` is the value. Perhaps the most common example of a choice type is a + * binary tree: + * + * [[examples/binary_tree.c](https://github.com/hirrolot/metalang99/blob/master/examples/binary_tree.c)] + * @include binary_tree.c + * + * [tagged union]: https://en.wikipedia.org/wiki/Tagged_union + */ + +#ifndef ML99_CHOICE_H +#define ML99_CHOICE_H + +#include <metalang99/priv/util.h> + +#include <metalang99/lang.h> + +/** + * Constructs an instance of a choice type. + * + * # Examples + * + * See + * [examples/binary_tree.c](https://github.com/hirrolot/metalang99/blob/master/examples/binary_tree.c). + * + * @note Specify `~` if you do not want to supply data; then, to match it, write a `_` parameter to + * ignore. + */ +#define ML99_choice(tag, ...) ML99_call(ML99_choice, tag, __VA_ARGS__) + +/** + * Evaluates to the tag of @p choice. + * + * This macro is essentially the same as `ML99_tupleGet(0)`. + * + * # Examples + * + * @code + * #include <metalang99/choice.h> + * + * // foo + * ML99_choiceTag(ML99_choice(v(foo), v(1, 2, 3))) + * @endcode + */ +#define ML99_choiceTag(choice) ML99_call(ML99_choiceTag, choice) + +/** + * Evaluates to the data of @p choice. + * + * This macro is essentially the same as #ML99_tupleTail. + * + * # Examples + * + * @code + * #include <metalang99/choice.h> + * + * // 1, 2, 3 + * ML99_choiceData(ML99_choice(v(foo), v(1, 2, 3))) + * @endcode + */ +#define ML99_choiceData(choice) ML99_call(ML99_choiceData, choice) + +/** + * Matches the instance @p choice of a choice type. + * + * This macro results in `ML99_call(ML99_cat(matcher, ML99_choiceTag(choice)), <choice data>)`. + * + * # Examples + * + * See + * [examples/binary_tree.c](https://github.com/hirrolot/metalang99/blob/master/examples/binary_tree.c). + */ +#define ML99_match(choice, matcher) ML99_call(ML99_match, choice, matcher) + +/** + * The same as #ML99_match but supplies additional arguments to all branches. + * + * This macro results in `ML99_call(ML99_cat(matcher, ML99_choiceTag(choice)), <choice data>, + * args...)`. + * + * # Examples + * + * @code + * #include <metalang99/choice.h> + * + * #define MATCH_A_IMPL(x, y, z) v(x ~ y ~ z) + * + * // 123 ~ 456 ~ 789 + * ML99_matchWithArgs(ML99_choice(v(A), v(123)), v(MATCH_), v(456, 789)) + * @endcode + */ +#define ML99_matchWithArgs(choice, matcher, ...) \ + ML99_call(ML99_matchWithArgs, choice, matcher, __VA_ARGS__) + +#define ML99_CHOICE(tag, ...) (tag, __VA_ARGS__) +#define ML99_CHOICE_TAG(choice) ML99_PRIV_HEAD_AUX choice +#define ML99_CHOICE_DATA(choice) ML99_PRIV_TAIL_AUX choice + +#ifndef DOXYGEN_IGNORE + +#define ML99_choice_IMPL(tag, ...) v(ML99_CHOICE(tag, __VA_ARGS__)) +#define ML99_choiceTag_IMPL(choice) v(ML99_CHOICE_TAG(choice)) +#define ML99_choiceData_IMPL(choice) v(ML99_CHOICE_DATA(choice)) + +#define ML99_match_IMPL(choice, matcher) \ + ML99_callUneval(ML99_PRIV_CAT(matcher, ML99_PRIV_HEAD_AUX choice), ML99_PRIV_TAIL_AUX choice) + +#define ML99_matchWithArgs_IMPL(choice, matcher, ...) \ + ML99_callUneval( \ + ML99_PRIV_CAT(matcher, ML99_PRIV_HEAD_AUX choice), \ + ML99_PRIV_TAIL_AUX choice, \ + __VA_ARGS__) + +// Arity specifiers { + +#define ML99_choice_ARITY 2 +#define ML99_choiceTag_ARITY 1 +#define ML99_choiceData_ARITY 1 +#define ML99_match_ARITY 2 +#define ML99_matchWithArgs_ARITY 3 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_CHOICE_H diff --git a/test/external/metalang99/include/metalang99/control.h b/test/external/metalang99/include/metalang99/control.h new file mode 100644 index 0000000..13ed33b --- /dev/null +++ b/test/external/metalang99/include/metalang99/control.h @@ -0,0 +1,13 @@ +/** + * @file + * This module is deprecated and exists only for backwards compatibility. + */ + +#ifndef ML99_CONTROL_H +#define ML99_CONTROL_H + +#include <metalang99/bool.h> // ML99_if, ML99_IF +#include <metalang99/gen.h> // ML99_times, ML99_repeat +#include <metalang99/variadics.h> // ML99_OVERLOAD + +#endif // ML99_CONTROL_H diff --git a/test/external/metalang99/include/metalang99/either.h b/test/external/metalang99/include/metalang99/either.h new file mode 100644 index 0000000..c3b7732 --- /dev/null +++ b/test/external/metalang99/include/metalang99/either.h @@ -0,0 +1,170 @@ +/** + * @file + * A choice type with two cases. + */ + +#ifndef ML99_EITHER_H +#define ML99_EITHER_H + +#include <metalang99/priv/util.h> + +#include <metalang99/bool.h> +#include <metalang99/choice.h> +#include <metalang99/ident.h> + +/** + * The left value @p x. + */ +#define ML99_left(x) ML99_call(ML99_left, x) + +/** + * The right value @p x. + */ +#define ML99_right(x) ML99_call(ML99_right, x) + +/** + * `ML99_true()` if @p either contains a left value, otherwise `ML99_false()`. + * + * # Examples + * + * @code + * #include <metalang99/either.h> + * + * // 1 + * ML99_isLeft(ML99_left(v(123))) + * + * // 0 + * ML99_isLeft(ML99_right(v(123))) + * @endcode + */ +#define ML99_isLeft(either) ML99_call(ML99_isLeft, either) + +/** + * The inverse of #ML99_isLeft. + * + * # Examples + * + * @code + * #include <metalang99/either.h> + * + * // 1 + * ML99_isRight(ML99_right(v(123))) + * + * // 0 + * ML99_isRight(ML99_left(v(123))) + * @endcode + */ +#define ML99_isRight(either) ML99_call(ML99_isRight, either) + +/** + * Tests @p either and @p other for equality. + * + * # Examples + * + * @code + * #include <metalang99/either.h> + * #include <metalang99/nat.h> + * + * // 1 + * ML99_eitherEq(v(ML99_natEq), ML99_left(v(123)), ML99_left(v(123))) + * + * // 0 + * ML99_eitherEq(v(ML99_natEq), ML99_right(v(123)), ML99_left(v(8))) + * + * // 0 + * ML99_eitherEq(v(ML99_natEq), ML99_right(v(123)), ML99_left(v(123))) + * @endcode + */ +#define ML99_eitherEq(cmp, either, other) ML99_call(ML99_eitherEq, cmp, either, other) + +/** + * Returns the left value on `ML99_left(x)` or emits a fatal error on `ML99_right(y)`. + * + * # Examples + * + * @code + * #include <metalang99/either.h> + * + * // 123 + * ML99_unwrapLeft(ML99_left(v(123))) + * + * // Emits a fatal error. + * ML99_unwrapLeft(ML99_right(v(123))) + * @endcode + */ +#define ML99_unwrapLeft(either) ML99_call(ML99_unwrapLeft, either) + +/** + * The inverse of #ML99_unwrapLeft. + * + * # Examples + * + * @code + * #include <metalang99/either.h> + * + * // 123 + * ML99_unwrapRight(ML99_right(v(123))) + * + * // Emits a fatal error. + * ML99_unwrapRight(ML99_left(v(123))) + * @endcode + */ +#define ML99_unwrapRight(either) ML99_call(ML99_unwrapRight, either) + +#define ML99_LEFT(x) ML99_CHOICE(left, x) +#define ML99_RIGHT(x) ML99_CHOICE(right, x) +#define ML99_IS_LEFT(either) ML99_PRIV_IS_LEFT(either) +#define ML99_IS_RIGHT(either) ML99_NOT(ML99_IS_LEFT(either)) + +#ifndef DOXYGEN_IGNORE + +#define ML99_left_IMPL(x) v(ML99_LEFT(x)) +#define ML99_right_IMPL(x) v(ML99_RIGHT(x)) + +#define ML99_isLeft_IMPL(either) v(ML99_IS_LEFT(either)) +#define ML99_isRight_IMPL(either) v(ML99_IS_RIGHT(either)) + +// ML99_eitherEq_IMPL { + +#define ML99_eitherEq_IMPL(cmp, either, other) \ + ML99_matchWithArgs_IMPL(either, ML99_PRIV_eitherEq_, cmp, other) + +#define ML99_PRIV_eitherEq_left_IMPL(x, cmp, other) \ + ML99_matchWithArgs_IMPL(other, ML99_PRIV_eitherEq_left_, cmp, x) +#define ML99_PRIV_eitherEq_right_IMPL(x, cmp, other) \ + ML99_matchWithArgs_IMPL(other, ML99_PRIV_eitherEq_right_, cmp, x) + +#define ML99_PRIV_eitherEq_left_left_IMPL(y, cmp, x) ML99_appl2_IMPL(cmp, x, y) +#define ML99_PRIV_eitherEq_left_right_IMPL ML99_false_IMPL + +#define ML99_PRIV_eitherEq_right_left_IMPL ML99_false_IMPL +#define ML99_PRIV_eitherEq_right_right_IMPL(y, cmp, x) ML99_appl2_IMPL(cmp, x, y) +// } (ML99_eitherEq_IMPL) + +#define ML99_unwrapLeft_IMPL(either) ML99_match_IMPL(either, ML99_PRIV_unwrapLeft_) +#define ML99_PRIV_unwrapLeft_left_IMPL(x) v(x) +#define ML99_PRIV_unwrapLeft_right_IMPL(_x) \ + ML99_fatal(ML99_unwrapLeft, expected ML99_left but found ML99_right) + +#define ML99_unwrapRight_IMPL(either) ML99_match_IMPL(either, ML99_PRIV_unwrapRight_) +#define ML99_PRIV_unwrapRight_left_IMPL(_x) \ + ML99_fatal(ML99_unwrapRight, expected ML99_right but found ML99_left) +#define ML99_PRIV_unwrapRight_right_IMPL(x) v(x) + +#define ML99_PRIV_IS_LEFT(either) ML99_DETECT_IDENT(ML99_PRIV_IS_LEFT_, ML99_CHOICE_TAG(either)) +#define ML99_PRIV_IS_LEFT_left () + +// Arity specifiers { + +#define ML99_left_ARITY 1 +#define ML99_right_ARITY 1 +#define ML99_isLeft_ARITY 1 +#define ML99_isRight_ARITY 1 +#define ML99_eitherEq_ARITY 3 +#define ML99_unwrapLeft_ARITY 1 +#define ML99_unwrapRight_ARITY 1 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_EITHER_H diff --git a/test/external/metalang99/include/metalang99/eval/acc.h b/test/external/metalang99/include/metalang99/eval/acc.h new file mode 100644 index 0000000..cd284f2 --- /dev/null +++ b/test/external/metalang99/include/metalang99/eval/acc.h @@ -0,0 +1,14 @@ +#ifndef ML99_EVAL_ACC_H +#define ML99_EVAL_ACC_H + +#include <metalang99/priv/util.h> + +#define ML99_PRIV_EVAL_ACC (, ) +#define ML99_PRIV_EVAL_ACC_COMMA_SEP () + +#define ML99_PRIV_EVAL_0fspace(acc, ...) (ML99_PRIV_EXPAND acc __VA_ARGS__) +#define ML99_PRIV_EVAL_0fcomma(acc, ...) (ML99_PRIV_EXPAND acc, __VA_ARGS__) + +#define ML99_PRIV_EVAL_ACC_UNWRAP(_emptiness, ...) __VA_ARGS__ + +#endif // ML99_EVAL_ACC_H diff --git a/test/external/metalang99/include/metalang99/eval/eval.h b/test/external/metalang99/include/metalang99/eval/eval.h new file mode 100644 index 0000000..394a1e2 --- /dev/null +++ b/test/external/metalang99/include/metalang99/eval/eval.h @@ -0,0 +1,130 @@ +#ifndef ML99_EVAL_EVAL_H +#define ML99_EVAL_EVAL_H + +// Explanation is in the spec: <https://github.com/hirrolot/metalang99/blob/master/spec/spec.pdf>. + +#include <metalang99/priv/compiler_specific.h> +#include <metalang99/priv/util.h> + +#include <metalang99/eval/acc.h> +#include <metalang99/eval/rec.h> +#include <metalang99/eval/syntax_checker.h> + +#define ML99_PRIV_EVAL(...) \ + ML99_PRIV_REC_UNROLL(ML99_PRIV_EVAL_MATCH( \ + ML99_PRIV_REC_STOP, \ + (~), \ + 0fspace, \ + ML99_PRIV_EVAL_ACC, \ + __VA_ARGS__, \ + (0end, ~), \ + ~)) + +// Recursion hooks { + +#define ML99_PRIV_EVAL_MATCH_HOOK() ML99_PRIV_EVAL_MATCH +#define ML99_PRIV_EVAL_0v_K_HOOK() ML99_PRIV_EVAL_0v_K +#define ML99_PRIV_EVAL_0args_K_HOOK() ML99_PRIV_EVAL_0args_K +#define ML99_PRIV_EVAL_0op_K_HOOK() ML99_PRIV_EVAL_0op_K +#define ML99_PRIV_EVAL_0callUneval_K_HOOK() ML99_PRIV_EVAL_0callUneval_K +// } (Recursion hooks) + +#define ML99_PRIV_EVAL_MATCH(k, k_cx, folder, acc, head, ...) \ + ML99_PRIV_CHECK_TERM(head, ML99_PRIV_TERM_MATCH) \ + (head)(k, k_cx, folder, acc, (__VA_ARGS__), ML99_PRIV_TERM_DATA head) + +#define ML99_PRIV_TERM_MATCH(term) ML99_PRIV_CAT(ML99_PRIV_EVAL_, ML99_PRIV_TERM_KIND term) +#define ML99_PRIV_TERM_KIND(kind, ...) kind +#define ML99_PRIV_TERM_DATA(_kind, ...) __VA_ARGS__ + +// Reduction rules { + +#define ML99_PRIV_EVAL_0v ML99_PRIV_REC_CONTINUE(ML99_PRIV_EVAL_0v_K) +#define ML99_PRIV_EVAL_0args ML99_PRIV_REC_CONTINUE(ML99_PRIV_EVAL_0args_K) +#define ML99_PRIV_EVAL_0op ML99_PRIV_REC_CONTINUE(ML99_PRIV_EVAL_0op_K) +#define ML99_PRIV_EVAL_0callUneval ML99_PRIV_REC_CONTINUE(ML99_PRIV_EVAL_0callUneval_K) + +#define ML99_PRIV_EVAL_0fatal(...) ML99_PRIV_EVAL_0fatal_AUX(__VA_ARGS__) +#define ML99_PRIV_EVAL_0fatal_AUX(_k, _k_cx, _folder, _acc, _tail, f, message) \ + ML99_PRIV_REC_CONTINUE(ML99_PRIV_REC_STOP)((~), ML99_PRIV_FATAL_ERROR(f, message)) + +#ifdef ML99_PRIV_EMIT_ERROR +#define ML99_PRIV_FATAL_ERROR(f, message) ML99_PRIV_EMIT_ERROR(#f ": " message); +#else +// clang-format off +#define ML99_PRIV_FATAL_ERROR(f, message) !"Metalang99 error" (f): message +// clang-format on +#endif + +#define ML99_PRIV_EVAL_0abort(_k, k_cx, folder, acc, _tail, ...) \ + ML99_PRIV_REC_CONTINUE(ML99_PRIV_EVAL_MATCH) \ + (ML99_PRIV_REC_STOP, (~), 0fspace, ML99_PRIV_EVAL_ACC, __VA_ARGS__, (0end, ~), ~) + +#define ML99_PRIV_EVAL_0end(k, k_cx, _folder, acc, _tail, _) \ + ML99_PRIV_REC_CONTINUE(k) \ + (ML99_PRIV_EXPAND k_cx, ML99_PRIV_EVAL_ACC_UNWRAP acc) +// } (Reduction rules) + +// Continuations { + +#define ML99_PRIV_EVAL_0v_K(k, k_cx, folder, acc, tail, ...) \ + ML99_PRIV_MACHINE_REDUCE( \ + k, \ + k_cx, \ + folder, \ + ML99_PRIV_EVAL_##folder(acc, __VA_ARGS__), \ + ML99_PRIV_EXPAND tail) + +#define ML99_PRIV_EVAL_0args_K(k, k_cx, folder, acc, tail, op, ...) \ + ML99_PRIV_MACHINE_REDUCE( \ + ML99_PRIV_EVAL_0callUneval_K, \ + (k, k_cx, folder, acc, tail, op), \ + 0fcomma, \ + ML99_PRIV_EVAL_ACC_COMMA_SEP, \ + __VA_ARGS__, \ + (0end, ~), \ + ~) + +#define ML99_PRIV_EVAL_0op_K(k, k_cx, folder, acc, tail, op, ...) \ + ML99_PRIV_MACHINE_REDUCE( \ + ML99_PRIV_EVAL_0callUneval_K, \ + (k, k_cx, folder, acc, tail), \ + 0fcomma, \ + ML99_PRIV_EVAL_ACC_COMMA_SEP, \ + op, \ + __VA_ARGS__, \ + (0end, ~), \ + ~) + +/* + * In this subroutine, we employ the following optimization: + * + * - If `evaluated_op` expands to many terms, we first evaluate these terms and accumulate them + * (`ML99_PRIV_EVAL_0callUneval_K_1`). + * - Otherwise, we just paste a single term with the rest of the tail + * (`ML99_PRIV_EVAL_0callUneval_K_0`). + */ +#define ML99_PRIV_EVAL_0callUneval_K(k, k_cx, folder, acc, tail, evaluated_op, ...) \ + ML99_PRIV_EVAL_0callUneval_K_AUX(k, k_cx, folder, acc, tail, evaluated_op##_IMPL(__VA_ARGS__)) + +#define ML99_PRIV_EVAL_0callUneval_K_AUX(k, k_cx, folder, acc, tail, ...) \ + ML99_PRIV_CAT(ML99_PRIV_EVAL_0callUneval_K_, ML99_PRIV_CONTAINS_COMMA(__VA_ARGS__)) \ + (k, k_cx, folder, acc, tail, __VA_ARGS__) + +#define ML99_PRIV_EVAL_0callUneval_K_0(k, k_cx, folder, acc, tail, body) \ + ML99_PRIV_MACHINE_REDUCE(k, k_cx, folder, acc, body, ML99_PRIV_EXPAND tail) + +#define ML99_PRIV_EVAL_0callUneval_K_1(k, k_cx, folder, acc, tail, ...) \ + ML99_PRIV_MACHINE_REDUCE( \ + ML99_PRIV_EVAL_0v_K, \ + (k, k_cx, folder, acc, tail), \ + 0fspace, \ + ML99_PRIV_EVAL_ACC, \ + __VA_ARGS__, \ + (0end, ~), \ + ~) + +#define ML99_PRIV_MACHINE_REDUCE(...) ML99_PRIV_EVAL_MATCH(__VA_ARGS__) +// } (Continuations) + +#endif // ML99_EVAL_EVAL_H diff --git a/test/external/metalang99/include/metalang99/eval/rec.h b/test/external/metalang99/include/metalang99/eval/rec.h new file mode 100644 index 0000000..aab238a --- /dev/null +++ b/test/external/metalang99/include/metalang99/eval/rec.h @@ -0,0 +1,1098 @@ +/* + * This recursion engine takes its roots from map-macro [1] and Cloak [2], with a few improvements: + * + * - It can do many more expansions (roughly 1024 * 16 or 2^14). + * + * - The expansion chain is linear: `ML99_PRIV_REC_0` invokes `ML99_PRIV_REC_1`, `ML99_PRIV_REC_1` + * invokes `ML99_PRIV_REC_2`, and so on. + * + * - If a given metaprogram does not require more expansions, then it will stop expanding. I.e., + * perform only as many expansions as needed. This is controlled by `ML99_PRIV_REC_NEXT`: if + * `choice` is `0stop`, then just terminate the expansion chain. + * + * - The last expander `ML99_PRIV_REC_1023` really results in a deferred `ML99_PRIV_REC_0`, not to + * make it painted blue. Then, in `ML99_PRIV_REC_UNROLL_AUX`, this `ML99_PRIV_REC_0` is expanded + * once again 16 times. + * + * - It requires recursive macros to be written in CPS, continuation-passing style [3]. This is + * controlled by `ML99_PRIV_REC_CONTINUE`: the `k` parameter stands for "continuation". `k` must + * eventually expand to yet another `ML99_PRIV_REC_CONTINUE`. Also, there is a special continuation + * called `ML99_PRIV_REC_STOP` -- it terminates the engine. + * + * The minimal usage example is located at `tests/eval/rec.c`. + * + * [1] https://github.com/swansontec/map-macro + * [2] https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms#recursion + * [3] https://en.wikipedia.org/wiki/Continuation-passing_style + */ + +#ifndef ML99_EVAL_REC_H +#define ML99_EVAL_REC_H + +#define ML99_PRIV_REC_CONTINUE(k) 0continue, ML99_PRIV_REC_DEFER(k##_HOOK)() +#define ML99_PRIV_REC_STOP(_k_cx, ...) 0stop, __VA_ARGS__ +#define ML99_PRIV_REC_STOP_HOOK() ML99_PRIV_REC_STOP + +#define ML99_PRIV_REC_DEFER(op) op ML99_PRIV_REC_EMPTY +#define ML99_PRIV_REC_EMPTY +#define ML99_PRIV_REC_EXPAND(...) __VA_ARGS__ + +#define ML99_PRIV_REC_NEXT(next_lvl, choice) ML99_PRIV_REC_NEXT_##choice(next_lvl) +#define ML99_PRIV_REC_NEXT_0continue(next_lvl) ML99_PRIV_REC_##next_lvl +#define ML99_PRIV_REC_NEXT_0stop(_next_lvl) ML99_PRIV_REC_HALT + +#define ML99_PRIV_REC_HALT(...) __VA_ARGS__ + +#define ML99_PRIV_REC_UNROLL(...) ML99_PRIV_REC_UNROLL_AUX(__VA_ARGS__) + +// clang-format off +#define ML99_PRIV_REC_UNROLL_AUX(choice, ...) \ + /* Approximately 1024 * 16 reduction steps. */ \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_EXPAND( \ + ML99_PRIV_REC_NEXT(0, choice)(__VA_ARGS__) \ + )))))))))))))))) +// clang-format on + +#define ML99_PRIV_REC_0(choice, ...) ML99_PRIV_REC_NEXT(1, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1(choice, ...) ML99_PRIV_REC_NEXT(2, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_2(choice, ...) ML99_PRIV_REC_NEXT(3, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_3(choice, ...) ML99_PRIV_REC_NEXT(4, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_4(choice, ...) ML99_PRIV_REC_NEXT(5, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_5(choice, ...) ML99_PRIV_REC_NEXT(6, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_6(choice, ...) ML99_PRIV_REC_NEXT(7, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_7(choice, ...) ML99_PRIV_REC_NEXT(8, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_8(choice, ...) ML99_PRIV_REC_NEXT(9, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_9(choice, ...) ML99_PRIV_REC_NEXT(10, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_10(choice, ...) ML99_PRIV_REC_NEXT(11, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_11(choice, ...) ML99_PRIV_REC_NEXT(12, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_12(choice, ...) ML99_PRIV_REC_NEXT(13, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_13(choice, ...) ML99_PRIV_REC_NEXT(14, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_14(choice, ...) ML99_PRIV_REC_NEXT(15, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_15(choice, ...) ML99_PRIV_REC_NEXT(16, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_16(choice, ...) ML99_PRIV_REC_NEXT(17, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_17(choice, ...) ML99_PRIV_REC_NEXT(18, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_18(choice, ...) ML99_PRIV_REC_NEXT(19, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_19(choice, ...) ML99_PRIV_REC_NEXT(20, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_20(choice, ...) ML99_PRIV_REC_NEXT(21, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_21(choice, ...) ML99_PRIV_REC_NEXT(22, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_22(choice, ...) ML99_PRIV_REC_NEXT(23, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_23(choice, ...) ML99_PRIV_REC_NEXT(24, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_24(choice, ...) ML99_PRIV_REC_NEXT(25, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_25(choice, ...) ML99_PRIV_REC_NEXT(26, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_26(choice, ...) ML99_PRIV_REC_NEXT(27, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_27(choice, ...) ML99_PRIV_REC_NEXT(28, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_28(choice, ...) ML99_PRIV_REC_NEXT(29, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_29(choice, ...) ML99_PRIV_REC_NEXT(30, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_30(choice, ...) ML99_PRIV_REC_NEXT(31, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_31(choice, ...) ML99_PRIV_REC_NEXT(32, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_32(choice, ...) ML99_PRIV_REC_NEXT(33, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_33(choice, ...) ML99_PRIV_REC_NEXT(34, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_34(choice, ...) ML99_PRIV_REC_NEXT(35, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_35(choice, ...) ML99_PRIV_REC_NEXT(36, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_36(choice, ...) ML99_PRIV_REC_NEXT(37, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_37(choice, ...) ML99_PRIV_REC_NEXT(38, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_38(choice, ...) ML99_PRIV_REC_NEXT(39, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_39(choice, ...) ML99_PRIV_REC_NEXT(40, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_40(choice, ...) ML99_PRIV_REC_NEXT(41, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_41(choice, ...) ML99_PRIV_REC_NEXT(42, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_42(choice, ...) ML99_PRIV_REC_NEXT(43, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_43(choice, ...) ML99_PRIV_REC_NEXT(44, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_44(choice, ...) ML99_PRIV_REC_NEXT(45, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_45(choice, ...) ML99_PRIV_REC_NEXT(46, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_46(choice, ...) ML99_PRIV_REC_NEXT(47, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_47(choice, ...) ML99_PRIV_REC_NEXT(48, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_48(choice, ...) ML99_PRIV_REC_NEXT(49, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_49(choice, ...) ML99_PRIV_REC_NEXT(50, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_50(choice, ...) ML99_PRIV_REC_NEXT(51, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_51(choice, ...) ML99_PRIV_REC_NEXT(52, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_52(choice, ...) ML99_PRIV_REC_NEXT(53, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_53(choice, ...) ML99_PRIV_REC_NEXT(54, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_54(choice, ...) ML99_PRIV_REC_NEXT(55, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_55(choice, ...) ML99_PRIV_REC_NEXT(56, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_56(choice, ...) ML99_PRIV_REC_NEXT(57, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_57(choice, ...) ML99_PRIV_REC_NEXT(58, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_58(choice, ...) ML99_PRIV_REC_NEXT(59, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_59(choice, ...) ML99_PRIV_REC_NEXT(60, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_60(choice, ...) ML99_PRIV_REC_NEXT(61, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_61(choice, ...) ML99_PRIV_REC_NEXT(62, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_62(choice, ...) ML99_PRIV_REC_NEXT(63, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_63(choice, ...) ML99_PRIV_REC_NEXT(64, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_64(choice, ...) ML99_PRIV_REC_NEXT(65, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_65(choice, ...) ML99_PRIV_REC_NEXT(66, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_66(choice, ...) ML99_PRIV_REC_NEXT(67, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_67(choice, ...) ML99_PRIV_REC_NEXT(68, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_68(choice, ...) ML99_PRIV_REC_NEXT(69, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_69(choice, ...) ML99_PRIV_REC_NEXT(70, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_70(choice, ...) ML99_PRIV_REC_NEXT(71, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_71(choice, ...) ML99_PRIV_REC_NEXT(72, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_72(choice, ...) ML99_PRIV_REC_NEXT(73, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_73(choice, ...) ML99_PRIV_REC_NEXT(74, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_74(choice, ...) ML99_PRIV_REC_NEXT(75, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_75(choice, ...) ML99_PRIV_REC_NEXT(76, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_76(choice, ...) ML99_PRIV_REC_NEXT(77, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_77(choice, ...) ML99_PRIV_REC_NEXT(78, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_78(choice, ...) ML99_PRIV_REC_NEXT(79, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_79(choice, ...) ML99_PRIV_REC_NEXT(80, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_80(choice, ...) ML99_PRIV_REC_NEXT(81, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_81(choice, ...) ML99_PRIV_REC_NEXT(82, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_82(choice, ...) ML99_PRIV_REC_NEXT(83, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_83(choice, ...) ML99_PRIV_REC_NEXT(84, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_84(choice, ...) ML99_PRIV_REC_NEXT(85, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_85(choice, ...) ML99_PRIV_REC_NEXT(86, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_86(choice, ...) ML99_PRIV_REC_NEXT(87, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_87(choice, ...) ML99_PRIV_REC_NEXT(88, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_88(choice, ...) ML99_PRIV_REC_NEXT(89, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_89(choice, ...) ML99_PRIV_REC_NEXT(90, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_90(choice, ...) ML99_PRIV_REC_NEXT(91, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_91(choice, ...) ML99_PRIV_REC_NEXT(92, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_92(choice, ...) ML99_PRIV_REC_NEXT(93, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_93(choice, ...) ML99_PRIV_REC_NEXT(94, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_94(choice, ...) ML99_PRIV_REC_NEXT(95, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_95(choice, ...) ML99_PRIV_REC_NEXT(96, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_96(choice, ...) ML99_PRIV_REC_NEXT(97, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_97(choice, ...) ML99_PRIV_REC_NEXT(98, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_98(choice, ...) ML99_PRIV_REC_NEXT(99, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_99(choice, ...) ML99_PRIV_REC_NEXT(100, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_100(choice, ...) ML99_PRIV_REC_NEXT(101, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_101(choice, ...) ML99_PRIV_REC_NEXT(102, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_102(choice, ...) ML99_PRIV_REC_NEXT(103, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_103(choice, ...) ML99_PRIV_REC_NEXT(104, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_104(choice, ...) ML99_PRIV_REC_NEXT(105, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_105(choice, ...) ML99_PRIV_REC_NEXT(106, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_106(choice, ...) ML99_PRIV_REC_NEXT(107, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_107(choice, ...) ML99_PRIV_REC_NEXT(108, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_108(choice, ...) ML99_PRIV_REC_NEXT(109, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_109(choice, ...) ML99_PRIV_REC_NEXT(110, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_110(choice, ...) ML99_PRIV_REC_NEXT(111, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_111(choice, ...) ML99_PRIV_REC_NEXT(112, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_112(choice, ...) ML99_PRIV_REC_NEXT(113, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_113(choice, ...) ML99_PRIV_REC_NEXT(114, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_114(choice, ...) ML99_PRIV_REC_NEXT(115, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_115(choice, ...) ML99_PRIV_REC_NEXT(116, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_116(choice, ...) ML99_PRIV_REC_NEXT(117, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_117(choice, ...) ML99_PRIV_REC_NEXT(118, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_118(choice, ...) ML99_PRIV_REC_NEXT(119, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_119(choice, ...) ML99_PRIV_REC_NEXT(120, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_120(choice, ...) ML99_PRIV_REC_NEXT(121, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_121(choice, ...) ML99_PRIV_REC_NEXT(122, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_122(choice, ...) ML99_PRIV_REC_NEXT(123, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_123(choice, ...) ML99_PRIV_REC_NEXT(124, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_124(choice, ...) ML99_PRIV_REC_NEXT(125, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_125(choice, ...) ML99_PRIV_REC_NEXT(126, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_126(choice, ...) ML99_PRIV_REC_NEXT(127, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_127(choice, ...) ML99_PRIV_REC_NEXT(128, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_128(choice, ...) ML99_PRIV_REC_NEXT(129, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_129(choice, ...) ML99_PRIV_REC_NEXT(130, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_130(choice, ...) ML99_PRIV_REC_NEXT(131, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_131(choice, ...) ML99_PRIV_REC_NEXT(132, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_132(choice, ...) ML99_PRIV_REC_NEXT(133, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_133(choice, ...) ML99_PRIV_REC_NEXT(134, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_134(choice, ...) ML99_PRIV_REC_NEXT(135, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_135(choice, ...) ML99_PRIV_REC_NEXT(136, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_136(choice, ...) ML99_PRIV_REC_NEXT(137, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_137(choice, ...) ML99_PRIV_REC_NEXT(138, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_138(choice, ...) ML99_PRIV_REC_NEXT(139, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_139(choice, ...) ML99_PRIV_REC_NEXT(140, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_140(choice, ...) ML99_PRIV_REC_NEXT(141, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_141(choice, ...) ML99_PRIV_REC_NEXT(142, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_142(choice, ...) ML99_PRIV_REC_NEXT(143, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_143(choice, ...) ML99_PRIV_REC_NEXT(144, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_144(choice, ...) ML99_PRIV_REC_NEXT(145, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_145(choice, ...) ML99_PRIV_REC_NEXT(146, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_146(choice, ...) ML99_PRIV_REC_NEXT(147, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_147(choice, ...) ML99_PRIV_REC_NEXT(148, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_148(choice, ...) ML99_PRIV_REC_NEXT(149, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_149(choice, ...) ML99_PRIV_REC_NEXT(150, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_150(choice, ...) ML99_PRIV_REC_NEXT(151, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_151(choice, ...) ML99_PRIV_REC_NEXT(152, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_152(choice, ...) ML99_PRIV_REC_NEXT(153, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_153(choice, ...) ML99_PRIV_REC_NEXT(154, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_154(choice, ...) ML99_PRIV_REC_NEXT(155, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_155(choice, ...) ML99_PRIV_REC_NEXT(156, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_156(choice, ...) ML99_PRIV_REC_NEXT(157, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_157(choice, ...) ML99_PRIV_REC_NEXT(158, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_158(choice, ...) ML99_PRIV_REC_NEXT(159, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_159(choice, ...) ML99_PRIV_REC_NEXT(160, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_160(choice, ...) ML99_PRIV_REC_NEXT(161, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_161(choice, ...) ML99_PRIV_REC_NEXT(162, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_162(choice, ...) ML99_PRIV_REC_NEXT(163, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_163(choice, ...) ML99_PRIV_REC_NEXT(164, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_164(choice, ...) ML99_PRIV_REC_NEXT(165, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_165(choice, ...) ML99_PRIV_REC_NEXT(166, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_166(choice, ...) ML99_PRIV_REC_NEXT(167, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_167(choice, ...) ML99_PRIV_REC_NEXT(168, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_168(choice, ...) ML99_PRIV_REC_NEXT(169, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_169(choice, ...) ML99_PRIV_REC_NEXT(170, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_170(choice, ...) ML99_PRIV_REC_NEXT(171, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_171(choice, ...) ML99_PRIV_REC_NEXT(172, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_172(choice, ...) ML99_PRIV_REC_NEXT(173, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_173(choice, ...) ML99_PRIV_REC_NEXT(174, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_174(choice, ...) ML99_PRIV_REC_NEXT(175, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_175(choice, ...) ML99_PRIV_REC_NEXT(176, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_176(choice, ...) ML99_PRIV_REC_NEXT(177, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_177(choice, ...) ML99_PRIV_REC_NEXT(178, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_178(choice, ...) ML99_PRIV_REC_NEXT(179, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_179(choice, ...) ML99_PRIV_REC_NEXT(180, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_180(choice, ...) ML99_PRIV_REC_NEXT(181, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_181(choice, ...) ML99_PRIV_REC_NEXT(182, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_182(choice, ...) ML99_PRIV_REC_NEXT(183, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_183(choice, ...) ML99_PRIV_REC_NEXT(184, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_184(choice, ...) ML99_PRIV_REC_NEXT(185, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_185(choice, ...) ML99_PRIV_REC_NEXT(186, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_186(choice, ...) ML99_PRIV_REC_NEXT(187, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_187(choice, ...) ML99_PRIV_REC_NEXT(188, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_188(choice, ...) ML99_PRIV_REC_NEXT(189, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_189(choice, ...) ML99_PRIV_REC_NEXT(190, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_190(choice, ...) ML99_PRIV_REC_NEXT(191, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_191(choice, ...) ML99_PRIV_REC_NEXT(192, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_192(choice, ...) ML99_PRIV_REC_NEXT(193, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_193(choice, ...) ML99_PRIV_REC_NEXT(194, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_194(choice, ...) ML99_PRIV_REC_NEXT(195, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_195(choice, ...) ML99_PRIV_REC_NEXT(196, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_196(choice, ...) ML99_PRIV_REC_NEXT(197, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_197(choice, ...) ML99_PRIV_REC_NEXT(198, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_198(choice, ...) ML99_PRIV_REC_NEXT(199, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_199(choice, ...) ML99_PRIV_REC_NEXT(200, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_200(choice, ...) ML99_PRIV_REC_NEXT(201, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_201(choice, ...) ML99_PRIV_REC_NEXT(202, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_202(choice, ...) ML99_PRIV_REC_NEXT(203, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_203(choice, ...) ML99_PRIV_REC_NEXT(204, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_204(choice, ...) ML99_PRIV_REC_NEXT(205, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_205(choice, ...) ML99_PRIV_REC_NEXT(206, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_206(choice, ...) ML99_PRIV_REC_NEXT(207, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_207(choice, ...) ML99_PRIV_REC_NEXT(208, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_208(choice, ...) ML99_PRIV_REC_NEXT(209, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_209(choice, ...) ML99_PRIV_REC_NEXT(210, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_210(choice, ...) ML99_PRIV_REC_NEXT(211, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_211(choice, ...) ML99_PRIV_REC_NEXT(212, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_212(choice, ...) ML99_PRIV_REC_NEXT(213, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_213(choice, ...) ML99_PRIV_REC_NEXT(214, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_214(choice, ...) ML99_PRIV_REC_NEXT(215, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_215(choice, ...) ML99_PRIV_REC_NEXT(216, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_216(choice, ...) ML99_PRIV_REC_NEXT(217, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_217(choice, ...) ML99_PRIV_REC_NEXT(218, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_218(choice, ...) ML99_PRIV_REC_NEXT(219, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_219(choice, ...) ML99_PRIV_REC_NEXT(220, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_220(choice, ...) ML99_PRIV_REC_NEXT(221, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_221(choice, ...) ML99_PRIV_REC_NEXT(222, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_222(choice, ...) ML99_PRIV_REC_NEXT(223, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_223(choice, ...) ML99_PRIV_REC_NEXT(224, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_224(choice, ...) ML99_PRIV_REC_NEXT(225, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_225(choice, ...) ML99_PRIV_REC_NEXT(226, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_226(choice, ...) ML99_PRIV_REC_NEXT(227, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_227(choice, ...) ML99_PRIV_REC_NEXT(228, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_228(choice, ...) ML99_PRIV_REC_NEXT(229, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_229(choice, ...) ML99_PRIV_REC_NEXT(230, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_230(choice, ...) ML99_PRIV_REC_NEXT(231, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_231(choice, ...) ML99_PRIV_REC_NEXT(232, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_232(choice, ...) ML99_PRIV_REC_NEXT(233, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_233(choice, ...) ML99_PRIV_REC_NEXT(234, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_234(choice, ...) ML99_PRIV_REC_NEXT(235, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_235(choice, ...) ML99_PRIV_REC_NEXT(236, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_236(choice, ...) ML99_PRIV_REC_NEXT(237, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_237(choice, ...) ML99_PRIV_REC_NEXT(238, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_238(choice, ...) ML99_PRIV_REC_NEXT(239, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_239(choice, ...) ML99_PRIV_REC_NEXT(240, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_240(choice, ...) ML99_PRIV_REC_NEXT(241, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_241(choice, ...) ML99_PRIV_REC_NEXT(242, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_242(choice, ...) ML99_PRIV_REC_NEXT(243, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_243(choice, ...) ML99_PRIV_REC_NEXT(244, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_244(choice, ...) ML99_PRIV_REC_NEXT(245, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_245(choice, ...) ML99_PRIV_REC_NEXT(246, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_246(choice, ...) ML99_PRIV_REC_NEXT(247, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_247(choice, ...) ML99_PRIV_REC_NEXT(248, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_248(choice, ...) ML99_PRIV_REC_NEXT(249, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_249(choice, ...) ML99_PRIV_REC_NEXT(250, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_250(choice, ...) ML99_PRIV_REC_NEXT(251, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_251(choice, ...) ML99_PRIV_REC_NEXT(252, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_252(choice, ...) ML99_PRIV_REC_NEXT(253, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_253(choice, ...) ML99_PRIV_REC_NEXT(254, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_254(choice, ...) ML99_PRIV_REC_NEXT(255, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_255(choice, ...) ML99_PRIV_REC_NEXT(256, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_256(choice, ...) ML99_PRIV_REC_NEXT(257, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_257(choice, ...) ML99_PRIV_REC_NEXT(258, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_258(choice, ...) ML99_PRIV_REC_NEXT(259, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_259(choice, ...) ML99_PRIV_REC_NEXT(260, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_260(choice, ...) ML99_PRIV_REC_NEXT(261, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_261(choice, ...) ML99_PRIV_REC_NEXT(262, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_262(choice, ...) ML99_PRIV_REC_NEXT(263, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_263(choice, ...) ML99_PRIV_REC_NEXT(264, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_264(choice, ...) ML99_PRIV_REC_NEXT(265, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_265(choice, ...) ML99_PRIV_REC_NEXT(266, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_266(choice, ...) ML99_PRIV_REC_NEXT(267, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_267(choice, ...) ML99_PRIV_REC_NEXT(268, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_268(choice, ...) ML99_PRIV_REC_NEXT(269, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_269(choice, ...) ML99_PRIV_REC_NEXT(270, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_270(choice, ...) ML99_PRIV_REC_NEXT(271, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_271(choice, ...) ML99_PRIV_REC_NEXT(272, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_272(choice, ...) ML99_PRIV_REC_NEXT(273, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_273(choice, ...) ML99_PRIV_REC_NEXT(274, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_274(choice, ...) ML99_PRIV_REC_NEXT(275, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_275(choice, ...) ML99_PRIV_REC_NEXT(276, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_276(choice, ...) ML99_PRIV_REC_NEXT(277, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_277(choice, ...) ML99_PRIV_REC_NEXT(278, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_278(choice, ...) ML99_PRIV_REC_NEXT(279, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_279(choice, ...) ML99_PRIV_REC_NEXT(280, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_280(choice, ...) ML99_PRIV_REC_NEXT(281, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_281(choice, ...) ML99_PRIV_REC_NEXT(282, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_282(choice, ...) ML99_PRIV_REC_NEXT(283, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_283(choice, ...) ML99_PRIV_REC_NEXT(284, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_284(choice, ...) ML99_PRIV_REC_NEXT(285, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_285(choice, ...) ML99_PRIV_REC_NEXT(286, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_286(choice, ...) ML99_PRIV_REC_NEXT(287, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_287(choice, ...) ML99_PRIV_REC_NEXT(288, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_288(choice, ...) ML99_PRIV_REC_NEXT(289, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_289(choice, ...) ML99_PRIV_REC_NEXT(290, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_290(choice, ...) ML99_PRIV_REC_NEXT(291, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_291(choice, ...) ML99_PRIV_REC_NEXT(292, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_292(choice, ...) ML99_PRIV_REC_NEXT(293, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_293(choice, ...) ML99_PRIV_REC_NEXT(294, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_294(choice, ...) ML99_PRIV_REC_NEXT(295, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_295(choice, ...) ML99_PRIV_REC_NEXT(296, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_296(choice, ...) ML99_PRIV_REC_NEXT(297, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_297(choice, ...) ML99_PRIV_REC_NEXT(298, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_298(choice, ...) ML99_PRIV_REC_NEXT(299, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_299(choice, ...) ML99_PRIV_REC_NEXT(300, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_300(choice, ...) ML99_PRIV_REC_NEXT(301, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_301(choice, ...) ML99_PRIV_REC_NEXT(302, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_302(choice, ...) ML99_PRIV_REC_NEXT(303, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_303(choice, ...) ML99_PRIV_REC_NEXT(304, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_304(choice, ...) ML99_PRIV_REC_NEXT(305, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_305(choice, ...) ML99_PRIV_REC_NEXT(306, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_306(choice, ...) ML99_PRIV_REC_NEXT(307, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_307(choice, ...) ML99_PRIV_REC_NEXT(308, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_308(choice, ...) ML99_PRIV_REC_NEXT(309, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_309(choice, ...) ML99_PRIV_REC_NEXT(310, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_310(choice, ...) ML99_PRIV_REC_NEXT(311, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_311(choice, ...) ML99_PRIV_REC_NEXT(312, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_312(choice, ...) ML99_PRIV_REC_NEXT(313, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_313(choice, ...) ML99_PRIV_REC_NEXT(314, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_314(choice, ...) ML99_PRIV_REC_NEXT(315, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_315(choice, ...) ML99_PRIV_REC_NEXT(316, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_316(choice, ...) ML99_PRIV_REC_NEXT(317, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_317(choice, ...) ML99_PRIV_REC_NEXT(318, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_318(choice, ...) ML99_PRIV_REC_NEXT(319, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_319(choice, ...) ML99_PRIV_REC_NEXT(320, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_320(choice, ...) ML99_PRIV_REC_NEXT(321, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_321(choice, ...) ML99_PRIV_REC_NEXT(322, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_322(choice, ...) ML99_PRIV_REC_NEXT(323, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_323(choice, ...) ML99_PRIV_REC_NEXT(324, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_324(choice, ...) ML99_PRIV_REC_NEXT(325, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_325(choice, ...) ML99_PRIV_REC_NEXT(326, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_326(choice, ...) ML99_PRIV_REC_NEXT(327, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_327(choice, ...) ML99_PRIV_REC_NEXT(328, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_328(choice, ...) ML99_PRIV_REC_NEXT(329, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_329(choice, ...) ML99_PRIV_REC_NEXT(330, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_330(choice, ...) ML99_PRIV_REC_NEXT(331, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_331(choice, ...) ML99_PRIV_REC_NEXT(332, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_332(choice, ...) ML99_PRIV_REC_NEXT(333, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_333(choice, ...) ML99_PRIV_REC_NEXT(334, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_334(choice, ...) ML99_PRIV_REC_NEXT(335, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_335(choice, ...) ML99_PRIV_REC_NEXT(336, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_336(choice, ...) ML99_PRIV_REC_NEXT(337, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_337(choice, ...) ML99_PRIV_REC_NEXT(338, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_338(choice, ...) ML99_PRIV_REC_NEXT(339, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_339(choice, ...) ML99_PRIV_REC_NEXT(340, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_340(choice, ...) ML99_PRIV_REC_NEXT(341, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_341(choice, ...) ML99_PRIV_REC_NEXT(342, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_342(choice, ...) ML99_PRIV_REC_NEXT(343, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_343(choice, ...) ML99_PRIV_REC_NEXT(344, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_344(choice, ...) ML99_PRIV_REC_NEXT(345, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_345(choice, ...) ML99_PRIV_REC_NEXT(346, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_346(choice, ...) ML99_PRIV_REC_NEXT(347, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_347(choice, ...) ML99_PRIV_REC_NEXT(348, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_348(choice, ...) ML99_PRIV_REC_NEXT(349, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_349(choice, ...) ML99_PRIV_REC_NEXT(350, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_350(choice, ...) ML99_PRIV_REC_NEXT(351, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_351(choice, ...) ML99_PRIV_REC_NEXT(352, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_352(choice, ...) ML99_PRIV_REC_NEXT(353, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_353(choice, ...) ML99_PRIV_REC_NEXT(354, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_354(choice, ...) ML99_PRIV_REC_NEXT(355, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_355(choice, ...) ML99_PRIV_REC_NEXT(356, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_356(choice, ...) ML99_PRIV_REC_NEXT(357, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_357(choice, ...) ML99_PRIV_REC_NEXT(358, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_358(choice, ...) ML99_PRIV_REC_NEXT(359, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_359(choice, ...) ML99_PRIV_REC_NEXT(360, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_360(choice, ...) ML99_PRIV_REC_NEXT(361, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_361(choice, ...) ML99_PRIV_REC_NEXT(362, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_362(choice, ...) ML99_PRIV_REC_NEXT(363, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_363(choice, ...) ML99_PRIV_REC_NEXT(364, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_364(choice, ...) ML99_PRIV_REC_NEXT(365, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_365(choice, ...) ML99_PRIV_REC_NEXT(366, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_366(choice, ...) ML99_PRIV_REC_NEXT(367, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_367(choice, ...) ML99_PRIV_REC_NEXT(368, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_368(choice, ...) ML99_PRIV_REC_NEXT(369, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_369(choice, ...) ML99_PRIV_REC_NEXT(370, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_370(choice, ...) ML99_PRIV_REC_NEXT(371, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_371(choice, ...) ML99_PRIV_REC_NEXT(372, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_372(choice, ...) ML99_PRIV_REC_NEXT(373, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_373(choice, ...) ML99_PRIV_REC_NEXT(374, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_374(choice, ...) ML99_PRIV_REC_NEXT(375, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_375(choice, ...) ML99_PRIV_REC_NEXT(376, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_376(choice, ...) ML99_PRIV_REC_NEXT(377, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_377(choice, ...) ML99_PRIV_REC_NEXT(378, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_378(choice, ...) ML99_PRIV_REC_NEXT(379, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_379(choice, ...) ML99_PRIV_REC_NEXT(380, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_380(choice, ...) ML99_PRIV_REC_NEXT(381, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_381(choice, ...) ML99_PRIV_REC_NEXT(382, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_382(choice, ...) ML99_PRIV_REC_NEXT(383, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_383(choice, ...) ML99_PRIV_REC_NEXT(384, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_384(choice, ...) ML99_PRIV_REC_NEXT(385, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_385(choice, ...) ML99_PRIV_REC_NEXT(386, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_386(choice, ...) ML99_PRIV_REC_NEXT(387, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_387(choice, ...) ML99_PRIV_REC_NEXT(388, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_388(choice, ...) ML99_PRIV_REC_NEXT(389, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_389(choice, ...) ML99_PRIV_REC_NEXT(390, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_390(choice, ...) ML99_PRIV_REC_NEXT(391, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_391(choice, ...) ML99_PRIV_REC_NEXT(392, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_392(choice, ...) ML99_PRIV_REC_NEXT(393, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_393(choice, ...) ML99_PRIV_REC_NEXT(394, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_394(choice, ...) ML99_PRIV_REC_NEXT(395, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_395(choice, ...) ML99_PRIV_REC_NEXT(396, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_396(choice, ...) ML99_PRIV_REC_NEXT(397, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_397(choice, ...) ML99_PRIV_REC_NEXT(398, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_398(choice, ...) ML99_PRIV_REC_NEXT(399, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_399(choice, ...) ML99_PRIV_REC_NEXT(400, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_400(choice, ...) ML99_PRIV_REC_NEXT(401, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_401(choice, ...) ML99_PRIV_REC_NEXT(402, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_402(choice, ...) ML99_PRIV_REC_NEXT(403, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_403(choice, ...) ML99_PRIV_REC_NEXT(404, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_404(choice, ...) ML99_PRIV_REC_NEXT(405, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_405(choice, ...) ML99_PRIV_REC_NEXT(406, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_406(choice, ...) ML99_PRIV_REC_NEXT(407, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_407(choice, ...) ML99_PRIV_REC_NEXT(408, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_408(choice, ...) ML99_PRIV_REC_NEXT(409, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_409(choice, ...) ML99_PRIV_REC_NEXT(410, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_410(choice, ...) ML99_PRIV_REC_NEXT(411, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_411(choice, ...) ML99_PRIV_REC_NEXT(412, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_412(choice, ...) ML99_PRIV_REC_NEXT(413, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_413(choice, ...) ML99_PRIV_REC_NEXT(414, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_414(choice, ...) ML99_PRIV_REC_NEXT(415, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_415(choice, ...) ML99_PRIV_REC_NEXT(416, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_416(choice, ...) ML99_PRIV_REC_NEXT(417, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_417(choice, ...) ML99_PRIV_REC_NEXT(418, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_418(choice, ...) ML99_PRIV_REC_NEXT(419, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_419(choice, ...) ML99_PRIV_REC_NEXT(420, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_420(choice, ...) ML99_PRIV_REC_NEXT(421, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_421(choice, ...) ML99_PRIV_REC_NEXT(422, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_422(choice, ...) ML99_PRIV_REC_NEXT(423, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_423(choice, ...) ML99_PRIV_REC_NEXT(424, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_424(choice, ...) ML99_PRIV_REC_NEXT(425, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_425(choice, ...) ML99_PRIV_REC_NEXT(426, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_426(choice, ...) ML99_PRIV_REC_NEXT(427, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_427(choice, ...) ML99_PRIV_REC_NEXT(428, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_428(choice, ...) ML99_PRIV_REC_NEXT(429, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_429(choice, ...) ML99_PRIV_REC_NEXT(430, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_430(choice, ...) ML99_PRIV_REC_NEXT(431, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_431(choice, ...) ML99_PRIV_REC_NEXT(432, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_432(choice, ...) ML99_PRIV_REC_NEXT(433, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_433(choice, ...) ML99_PRIV_REC_NEXT(434, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_434(choice, ...) ML99_PRIV_REC_NEXT(435, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_435(choice, ...) ML99_PRIV_REC_NEXT(436, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_436(choice, ...) ML99_PRIV_REC_NEXT(437, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_437(choice, ...) ML99_PRIV_REC_NEXT(438, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_438(choice, ...) ML99_PRIV_REC_NEXT(439, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_439(choice, ...) ML99_PRIV_REC_NEXT(440, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_440(choice, ...) ML99_PRIV_REC_NEXT(441, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_441(choice, ...) ML99_PRIV_REC_NEXT(442, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_442(choice, ...) ML99_PRIV_REC_NEXT(443, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_443(choice, ...) ML99_PRIV_REC_NEXT(444, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_444(choice, ...) ML99_PRIV_REC_NEXT(445, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_445(choice, ...) ML99_PRIV_REC_NEXT(446, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_446(choice, ...) ML99_PRIV_REC_NEXT(447, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_447(choice, ...) ML99_PRIV_REC_NEXT(448, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_448(choice, ...) ML99_PRIV_REC_NEXT(449, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_449(choice, ...) ML99_PRIV_REC_NEXT(450, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_450(choice, ...) ML99_PRIV_REC_NEXT(451, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_451(choice, ...) ML99_PRIV_REC_NEXT(452, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_452(choice, ...) ML99_PRIV_REC_NEXT(453, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_453(choice, ...) ML99_PRIV_REC_NEXT(454, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_454(choice, ...) ML99_PRIV_REC_NEXT(455, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_455(choice, ...) ML99_PRIV_REC_NEXT(456, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_456(choice, ...) ML99_PRIV_REC_NEXT(457, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_457(choice, ...) ML99_PRIV_REC_NEXT(458, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_458(choice, ...) ML99_PRIV_REC_NEXT(459, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_459(choice, ...) ML99_PRIV_REC_NEXT(460, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_460(choice, ...) ML99_PRIV_REC_NEXT(461, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_461(choice, ...) ML99_PRIV_REC_NEXT(462, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_462(choice, ...) ML99_PRIV_REC_NEXT(463, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_463(choice, ...) ML99_PRIV_REC_NEXT(464, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_464(choice, ...) ML99_PRIV_REC_NEXT(465, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_465(choice, ...) ML99_PRIV_REC_NEXT(466, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_466(choice, ...) ML99_PRIV_REC_NEXT(467, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_467(choice, ...) ML99_PRIV_REC_NEXT(468, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_468(choice, ...) ML99_PRIV_REC_NEXT(469, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_469(choice, ...) ML99_PRIV_REC_NEXT(470, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_470(choice, ...) ML99_PRIV_REC_NEXT(471, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_471(choice, ...) ML99_PRIV_REC_NEXT(472, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_472(choice, ...) ML99_PRIV_REC_NEXT(473, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_473(choice, ...) ML99_PRIV_REC_NEXT(474, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_474(choice, ...) ML99_PRIV_REC_NEXT(475, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_475(choice, ...) ML99_PRIV_REC_NEXT(476, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_476(choice, ...) ML99_PRIV_REC_NEXT(477, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_477(choice, ...) ML99_PRIV_REC_NEXT(478, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_478(choice, ...) ML99_PRIV_REC_NEXT(479, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_479(choice, ...) ML99_PRIV_REC_NEXT(480, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_480(choice, ...) ML99_PRIV_REC_NEXT(481, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_481(choice, ...) ML99_PRIV_REC_NEXT(482, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_482(choice, ...) ML99_PRIV_REC_NEXT(483, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_483(choice, ...) ML99_PRIV_REC_NEXT(484, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_484(choice, ...) ML99_PRIV_REC_NEXT(485, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_485(choice, ...) ML99_PRIV_REC_NEXT(486, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_486(choice, ...) ML99_PRIV_REC_NEXT(487, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_487(choice, ...) ML99_PRIV_REC_NEXT(488, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_488(choice, ...) ML99_PRIV_REC_NEXT(489, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_489(choice, ...) ML99_PRIV_REC_NEXT(490, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_490(choice, ...) ML99_PRIV_REC_NEXT(491, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_491(choice, ...) ML99_PRIV_REC_NEXT(492, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_492(choice, ...) ML99_PRIV_REC_NEXT(493, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_493(choice, ...) ML99_PRIV_REC_NEXT(494, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_494(choice, ...) ML99_PRIV_REC_NEXT(495, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_495(choice, ...) ML99_PRIV_REC_NEXT(496, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_496(choice, ...) ML99_PRIV_REC_NEXT(497, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_497(choice, ...) ML99_PRIV_REC_NEXT(498, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_498(choice, ...) ML99_PRIV_REC_NEXT(499, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_499(choice, ...) ML99_PRIV_REC_NEXT(500, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_500(choice, ...) ML99_PRIV_REC_NEXT(501, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_501(choice, ...) ML99_PRIV_REC_NEXT(502, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_502(choice, ...) ML99_PRIV_REC_NEXT(503, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_503(choice, ...) ML99_PRIV_REC_NEXT(504, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_504(choice, ...) ML99_PRIV_REC_NEXT(505, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_505(choice, ...) ML99_PRIV_REC_NEXT(506, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_506(choice, ...) ML99_PRIV_REC_NEXT(507, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_507(choice, ...) ML99_PRIV_REC_NEXT(508, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_508(choice, ...) ML99_PRIV_REC_NEXT(509, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_509(choice, ...) ML99_PRIV_REC_NEXT(510, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_510(choice, ...) ML99_PRIV_REC_NEXT(511, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_511(choice, ...) ML99_PRIV_REC_NEXT(512, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_512(choice, ...) ML99_PRIV_REC_NEXT(513, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_513(choice, ...) ML99_PRIV_REC_NEXT(514, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_514(choice, ...) ML99_PRIV_REC_NEXT(515, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_515(choice, ...) ML99_PRIV_REC_NEXT(516, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_516(choice, ...) ML99_PRIV_REC_NEXT(517, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_517(choice, ...) ML99_PRIV_REC_NEXT(518, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_518(choice, ...) ML99_PRIV_REC_NEXT(519, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_519(choice, ...) ML99_PRIV_REC_NEXT(520, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_520(choice, ...) ML99_PRIV_REC_NEXT(521, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_521(choice, ...) ML99_PRIV_REC_NEXT(522, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_522(choice, ...) ML99_PRIV_REC_NEXT(523, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_523(choice, ...) ML99_PRIV_REC_NEXT(524, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_524(choice, ...) ML99_PRIV_REC_NEXT(525, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_525(choice, ...) ML99_PRIV_REC_NEXT(526, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_526(choice, ...) ML99_PRIV_REC_NEXT(527, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_527(choice, ...) ML99_PRIV_REC_NEXT(528, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_528(choice, ...) ML99_PRIV_REC_NEXT(529, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_529(choice, ...) ML99_PRIV_REC_NEXT(530, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_530(choice, ...) ML99_PRIV_REC_NEXT(531, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_531(choice, ...) ML99_PRIV_REC_NEXT(532, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_532(choice, ...) ML99_PRIV_REC_NEXT(533, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_533(choice, ...) ML99_PRIV_REC_NEXT(534, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_534(choice, ...) ML99_PRIV_REC_NEXT(535, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_535(choice, ...) ML99_PRIV_REC_NEXT(536, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_536(choice, ...) ML99_PRIV_REC_NEXT(537, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_537(choice, ...) ML99_PRIV_REC_NEXT(538, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_538(choice, ...) ML99_PRIV_REC_NEXT(539, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_539(choice, ...) ML99_PRIV_REC_NEXT(540, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_540(choice, ...) ML99_PRIV_REC_NEXT(541, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_541(choice, ...) ML99_PRIV_REC_NEXT(542, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_542(choice, ...) ML99_PRIV_REC_NEXT(543, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_543(choice, ...) ML99_PRIV_REC_NEXT(544, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_544(choice, ...) ML99_PRIV_REC_NEXT(545, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_545(choice, ...) ML99_PRIV_REC_NEXT(546, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_546(choice, ...) ML99_PRIV_REC_NEXT(547, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_547(choice, ...) ML99_PRIV_REC_NEXT(548, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_548(choice, ...) ML99_PRIV_REC_NEXT(549, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_549(choice, ...) ML99_PRIV_REC_NEXT(550, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_550(choice, ...) ML99_PRIV_REC_NEXT(551, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_551(choice, ...) ML99_PRIV_REC_NEXT(552, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_552(choice, ...) ML99_PRIV_REC_NEXT(553, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_553(choice, ...) ML99_PRIV_REC_NEXT(554, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_554(choice, ...) ML99_PRIV_REC_NEXT(555, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_555(choice, ...) ML99_PRIV_REC_NEXT(556, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_556(choice, ...) ML99_PRIV_REC_NEXT(557, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_557(choice, ...) ML99_PRIV_REC_NEXT(558, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_558(choice, ...) ML99_PRIV_REC_NEXT(559, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_559(choice, ...) ML99_PRIV_REC_NEXT(560, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_560(choice, ...) ML99_PRIV_REC_NEXT(561, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_561(choice, ...) ML99_PRIV_REC_NEXT(562, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_562(choice, ...) ML99_PRIV_REC_NEXT(563, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_563(choice, ...) ML99_PRIV_REC_NEXT(564, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_564(choice, ...) ML99_PRIV_REC_NEXT(565, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_565(choice, ...) ML99_PRIV_REC_NEXT(566, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_566(choice, ...) ML99_PRIV_REC_NEXT(567, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_567(choice, ...) ML99_PRIV_REC_NEXT(568, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_568(choice, ...) ML99_PRIV_REC_NEXT(569, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_569(choice, ...) ML99_PRIV_REC_NEXT(570, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_570(choice, ...) ML99_PRIV_REC_NEXT(571, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_571(choice, ...) ML99_PRIV_REC_NEXT(572, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_572(choice, ...) ML99_PRIV_REC_NEXT(573, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_573(choice, ...) ML99_PRIV_REC_NEXT(574, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_574(choice, ...) ML99_PRIV_REC_NEXT(575, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_575(choice, ...) ML99_PRIV_REC_NEXT(576, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_576(choice, ...) ML99_PRIV_REC_NEXT(577, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_577(choice, ...) ML99_PRIV_REC_NEXT(578, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_578(choice, ...) ML99_PRIV_REC_NEXT(579, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_579(choice, ...) ML99_PRIV_REC_NEXT(580, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_580(choice, ...) ML99_PRIV_REC_NEXT(581, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_581(choice, ...) ML99_PRIV_REC_NEXT(582, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_582(choice, ...) ML99_PRIV_REC_NEXT(583, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_583(choice, ...) ML99_PRIV_REC_NEXT(584, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_584(choice, ...) ML99_PRIV_REC_NEXT(585, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_585(choice, ...) ML99_PRIV_REC_NEXT(586, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_586(choice, ...) ML99_PRIV_REC_NEXT(587, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_587(choice, ...) ML99_PRIV_REC_NEXT(588, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_588(choice, ...) ML99_PRIV_REC_NEXT(589, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_589(choice, ...) ML99_PRIV_REC_NEXT(590, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_590(choice, ...) ML99_PRIV_REC_NEXT(591, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_591(choice, ...) ML99_PRIV_REC_NEXT(592, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_592(choice, ...) ML99_PRIV_REC_NEXT(593, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_593(choice, ...) ML99_PRIV_REC_NEXT(594, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_594(choice, ...) ML99_PRIV_REC_NEXT(595, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_595(choice, ...) ML99_PRIV_REC_NEXT(596, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_596(choice, ...) ML99_PRIV_REC_NEXT(597, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_597(choice, ...) ML99_PRIV_REC_NEXT(598, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_598(choice, ...) ML99_PRIV_REC_NEXT(599, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_599(choice, ...) ML99_PRIV_REC_NEXT(600, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_600(choice, ...) ML99_PRIV_REC_NEXT(601, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_601(choice, ...) ML99_PRIV_REC_NEXT(602, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_602(choice, ...) ML99_PRIV_REC_NEXT(603, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_603(choice, ...) ML99_PRIV_REC_NEXT(604, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_604(choice, ...) ML99_PRIV_REC_NEXT(605, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_605(choice, ...) ML99_PRIV_REC_NEXT(606, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_606(choice, ...) ML99_PRIV_REC_NEXT(607, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_607(choice, ...) ML99_PRIV_REC_NEXT(608, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_608(choice, ...) ML99_PRIV_REC_NEXT(609, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_609(choice, ...) ML99_PRIV_REC_NEXT(610, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_610(choice, ...) ML99_PRIV_REC_NEXT(611, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_611(choice, ...) ML99_PRIV_REC_NEXT(612, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_612(choice, ...) ML99_PRIV_REC_NEXT(613, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_613(choice, ...) ML99_PRIV_REC_NEXT(614, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_614(choice, ...) ML99_PRIV_REC_NEXT(615, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_615(choice, ...) ML99_PRIV_REC_NEXT(616, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_616(choice, ...) ML99_PRIV_REC_NEXT(617, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_617(choice, ...) ML99_PRIV_REC_NEXT(618, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_618(choice, ...) ML99_PRIV_REC_NEXT(619, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_619(choice, ...) ML99_PRIV_REC_NEXT(620, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_620(choice, ...) ML99_PRIV_REC_NEXT(621, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_621(choice, ...) ML99_PRIV_REC_NEXT(622, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_622(choice, ...) ML99_PRIV_REC_NEXT(623, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_623(choice, ...) ML99_PRIV_REC_NEXT(624, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_624(choice, ...) ML99_PRIV_REC_NEXT(625, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_625(choice, ...) ML99_PRIV_REC_NEXT(626, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_626(choice, ...) ML99_PRIV_REC_NEXT(627, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_627(choice, ...) ML99_PRIV_REC_NEXT(628, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_628(choice, ...) ML99_PRIV_REC_NEXT(629, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_629(choice, ...) ML99_PRIV_REC_NEXT(630, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_630(choice, ...) ML99_PRIV_REC_NEXT(631, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_631(choice, ...) ML99_PRIV_REC_NEXT(632, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_632(choice, ...) ML99_PRIV_REC_NEXT(633, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_633(choice, ...) ML99_PRIV_REC_NEXT(634, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_634(choice, ...) ML99_PRIV_REC_NEXT(635, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_635(choice, ...) ML99_PRIV_REC_NEXT(636, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_636(choice, ...) ML99_PRIV_REC_NEXT(637, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_637(choice, ...) ML99_PRIV_REC_NEXT(638, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_638(choice, ...) ML99_PRIV_REC_NEXT(639, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_639(choice, ...) ML99_PRIV_REC_NEXT(640, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_640(choice, ...) ML99_PRIV_REC_NEXT(641, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_641(choice, ...) ML99_PRIV_REC_NEXT(642, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_642(choice, ...) ML99_PRIV_REC_NEXT(643, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_643(choice, ...) ML99_PRIV_REC_NEXT(644, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_644(choice, ...) ML99_PRIV_REC_NEXT(645, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_645(choice, ...) ML99_PRIV_REC_NEXT(646, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_646(choice, ...) ML99_PRIV_REC_NEXT(647, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_647(choice, ...) ML99_PRIV_REC_NEXT(648, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_648(choice, ...) ML99_PRIV_REC_NEXT(649, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_649(choice, ...) ML99_PRIV_REC_NEXT(650, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_650(choice, ...) ML99_PRIV_REC_NEXT(651, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_651(choice, ...) ML99_PRIV_REC_NEXT(652, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_652(choice, ...) ML99_PRIV_REC_NEXT(653, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_653(choice, ...) ML99_PRIV_REC_NEXT(654, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_654(choice, ...) ML99_PRIV_REC_NEXT(655, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_655(choice, ...) ML99_PRIV_REC_NEXT(656, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_656(choice, ...) ML99_PRIV_REC_NEXT(657, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_657(choice, ...) ML99_PRIV_REC_NEXT(658, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_658(choice, ...) ML99_PRIV_REC_NEXT(659, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_659(choice, ...) ML99_PRIV_REC_NEXT(660, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_660(choice, ...) ML99_PRIV_REC_NEXT(661, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_661(choice, ...) ML99_PRIV_REC_NEXT(662, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_662(choice, ...) ML99_PRIV_REC_NEXT(663, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_663(choice, ...) ML99_PRIV_REC_NEXT(664, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_664(choice, ...) ML99_PRIV_REC_NEXT(665, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_665(choice, ...) ML99_PRIV_REC_NEXT(666, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_666(choice, ...) ML99_PRIV_REC_NEXT(667, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_667(choice, ...) ML99_PRIV_REC_NEXT(668, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_668(choice, ...) ML99_PRIV_REC_NEXT(669, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_669(choice, ...) ML99_PRIV_REC_NEXT(670, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_670(choice, ...) ML99_PRIV_REC_NEXT(671, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_671(choice, ...) ML99_PRIV_REC_NEXT(672, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_672(choice, ...) ML99_PRIV_REC_NEXT(673, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_673(choice, ...) ML99_PRIV_REC_NEXT(674, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_674(choice, ...) ML99_PRIV_REC_NEXT(675, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_675(choice, ...) ML99_PRIV_REC_NEXT(676, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_676(choice, ...) ML99_PRIV_REC_NEXT(677, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_677(choice, ...) ML99_PRIV_REC_NEXT(678, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_678(choice, ...) ML99_PRIV_REC_NEXT(679, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_679(choice, ...) ML99_PRIV_REC_NEXT(680, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_680(choice, ...) ML99_PRIV_REC_NEXT(681, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_681(choice, ...) ML99_PRIV_REC_NEXT(682, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_682(choice, ...) ML99_PRIV_REC_NEXT(683, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_683(choice, ...) ML99_PRIV_REC_NEXT(684, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_684(choice, ...) ML99_PRIV_REC_NEXT(685, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_685(choice, ...) ML99_PRIV_REC_NEXT(686, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_686(choice, ...) ML99_PRIV_REC_NEXT(687, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_687(choice, ...) ML99_PRIV_REC_NEXT(688, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_688(choice, ...) ML99_PRIV_REC_NEXT(689, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_689(choice, ...) ML99_PRIV_REC_NEXT(690, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_690(choice, ...) ML99_PRIV_REC_NEXT(691, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_691(choice, ...) ML99_PRIV_REC_NEXT(692, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_692(choice, ...) ML99_PRIV_REC_NEXT(693, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_693(choice, ...) ML99_PRIV_REC_NEXT(694, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_694(choice, ...) ML99_PRIV_REC_NEXT(695, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_695(choice, ...) ML99_PRIV_REC_NEXT(696, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_696(choice, ...) ML99_PRIV_REC_NEXT(697, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_697(choice, ...) ML99_PRIV_REC_NEXT(698, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_698(choice, ...) ML99_PRIV_REC_NEXT(699, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_699(choice, ...) ML99_PRIV_REC_NEXT(700, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_700(choice, ...) ML99_PRIV_REC_NEXT(701, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_701(choice, ...) ML99_PRIV_REC_NEXT(702, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_702(choice, ...) ML99_PRIV_REC_NEXT(703, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_703(choice, ...) ML99_PRIV_REC_NEXT(704, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_704(choice, ...) ML99_PRIV_REC_NEXT(705, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_705(choice, ...) ML99_PRIV_REC_NEXT(706, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_706(choice, ...) ML99_PRIV_REC_NEXT(707, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_707(choice, ...) ML99_PRIV_REC_NEXT(708, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_708(choice, ...) ML99_PRIV_REC_NEXT(709, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_709(choice, ...) ML99_PRIV_REC_NEXT(710, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_710(choice, ...) ML99_PRIV_REC_NEXT(711, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_711(choice, ...) ML99_PRIV_REC_NEXT(712, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_712(choice, ...) ML99_PRIV_REC_NEXT(713, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_713(choice, ...) ML99_PRIV_REC_NEXT(714, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_714(choice, ...) ML99_PRIV_REC_NEXT(715, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_715(choice, ...) ML99_PRIV_REC_NEXT(716, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_716(choice, ...) ML99_PRIV_REC_NEXT(717, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_717(choice, ...) ML99_PRIV_REC_NEXT(718, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_718(choice, ...) ML99_PRIV_REC_NEXT(719, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_719(choice, ...) ML99_PRIV_REC_NEXT(720, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_720(choice, ...) ML99_PRIV_REC_NEXT(721, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_721(choice, ...) ML99_PRIV_REC_NEXT(722, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_722(choice, ...) ML99_PRIV_REC_NEXT(723, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_723(choice, ...) ML99_PRIV_REC_NEXT(724, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_724(choice, ...) ML99_PRIV_REC_NEXT(725, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_725(choice, ...) ML99_PRIV_REC_NEXT(726, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_726(choice, ...) ML99_PRIV_REC_NEXT(727, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_727(choice, ...) ML99_PRIV_REC_NEXT(728, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_728(choice, ...) ML99_PRIV_REC_NEXT(729, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_729(choice, ...) ML99_PRIV_REC_NEXT(730, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_730(choice, ...) ML99_PRIV_REC_NEXT(731, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_731(choice, ...) ML99_PRIV_REC_NEXT(732, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_732(choice, ...) ML99_PRIV_REC_NEXT(733, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_733(choice, ...) ML99_PRIV_REC_NEXT(734, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_734(choice, ...) ML99_PRIV_REC_NEXT(735, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_735(choice, ...) ML99_PRIV_REC_NEXT(736, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_736(choice, ...) ML99_PRIV_REC_NEXT(737, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_737(choice, ...) ML99_PRIV_REC_NEXT(738, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_738(choice, ...) ML99_PRIV_REC_NEXT(739, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_739(choice, ...) ML99_PRIV_REC_NEXT(740, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_740(choice, ...) ML99_PRIV_REC_NEXT(741, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_741(choice, ...) ML99_PRIV_REC_NEXT(742, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_742(choice, ...) ML99_PRIV_REC_NEXT(743, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_743(choice, ...) ML99_PRIV_REC_NEXT(744, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_744(choice, ...) ML99_PRIV_REC_NEXT(745, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_745(choice, ...) ML99_PRIV_REC_NEXT(746, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_746(choice, ...) ML99_PRIV_REC_NEXT(747, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_747(choice, ...) ML99_PRIV_REC_NEXT(748, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_748(choice, ...) ML99_PRIV_REC_NEXT(749, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_749(choice, ...) ML99_PRIV_REC_NEXT(750, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_750(choice, ...) ML99_PRIV_REC_NEXT(751, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_751(choice, ...) ML99_PRIV_REC_NEXT(752, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_752(choice, ...) ML99_PRIV_REC_NEXT(753, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_753(choice, ...) ML99_PRIV_REC_NEXT(754, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_754(choice, ...) ML99_PRIV_REC_NEXT(755, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_755(choice, ...) ML99_PRIV_REC_NEXT(756, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_756(choice, ...) ML99_PRIV_REC_NEXT(757, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_757(choice, ...) ML99_PRIV_REC_NEXT(758, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_758(choice, ...) ML99_PRIV_REC_NEXT(759, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_759(choice, ...) ML99_PRIV_REC_NEXT(760, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_760(choice, ...) ML99_PRIV_REC_NEXT(761, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_761(choice, ...) ML99_PRIV_REC_NEXT(762, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_762(choice, ...) ML99_PRIV_REC_NEXT(763, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_763(choice, ...) ML99_PRIV_REC_NEXT(764, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_764(choice, ...) ML99_PRIV_REC_NEXT(765, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_765(choice, ...) ML99_PRIV_REC_NEXT(766, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_766(choice, ...) ML99_PRIV_REC_NEXT(767, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_767(choice, ...) ML99_PRIV_REC_NEXT(768, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_768(choice, ...) ML99_PRIV_REC_NEXT(769, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_769(choice, ...) ML99_PRIV_REC_NEXT(770, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_770(choice, ...) ML99_PRIV_REC_NEXT(771, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_771(choice, ...) ML99_PRIV_REC_NEXT(772, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_772(choice, ...) ML99_PRIV_REC_NEXT(773, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_773(choice, ...) ML99_PRIV_REC_NEXT(774, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_774(choice, ...) ML99_PRIV_REC_NEXT(775, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_775(choice, ...) ML99_PRIV_REC_NEXT(776, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_776(choice, ...) ML99_PRIV_REC_NEXT(777, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_777(choice, ...) ML99_PRIV_REC_NEXT(778, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_778(choice, ...) ML99_PRIV_REC_NEXT(779, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_779(choice, ...) ML99_PRIV_REC_NEXT(780, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_780(choice, ...) ML99_PRIV_REC_NEXT(781, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_781(choice, ...) ML99_PRIV_REC_NEXT(782, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_782(choice, ...) ML99_PRIV_REC_NEXT(783, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_783(choice, ...) ML99_PRIV_REC_NEXT(784, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_784(choice, ...) ML99_PRIV_REC_NEXT(785, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_785(choice, ...) ML99_PRIV_REC_NEXT(786, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_786(choice, ...) ML99_PRIV_REC_NEXT(787, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_787(choice, ...) ML99_PRIV_REC_NEXT(788, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_788(choice, ...) ML99_PRIV_REC_NEXT(789, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_789(choice, ...) ML99_PRIV_REC_NEXT(790, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_790(choice, ...) ML99_PRIV_REC_NEXT(791, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_791(choice, ...) ML99_PRIV_REC_NEXT(792, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_792(choice, ...) ML99_PRIV_REC_NEXT(793, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_793(choice, ...) ML99_PRIV_REC_NEXT(794, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_794(choice, ...) ML99_PRIV_REC_NEXT(795, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_795(choice, ...) ML99_PRIV_REC_NEXT(796, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_796(choice, ...) ML99_PRIV_REC_NEXT(797, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_797(choice, ...) ML99_PRIV_REC_NEXT(798, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_798(choice, ...) ML99_PRIV_REC_NEXT(799, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_799(choice, ...) ML99_PRIV_REC_NEXT(800, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_800(choice, ...) ML99_PRIV_REC_NEXT(801, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_801(choice, ...) ML99_PRIV_REC_NEXT(802, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_802(choice, ...) ML99_PRIV_REC_NEXT(803, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_803(choice, ...) ML99_PRIV_REC_NEXT(804, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_804(choice, ...) ML99_PRIV_REC_NEXT(805, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_805(choice, ...) ML99_PRIV_REC_NEXT(806, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_806(choice, ...) ML99_PRIV_REC_NEXT(807, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_807(choice, ...) ML99_PRIV_REC_NEXT(808, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_808(choice, ...) ML99_PRIV_REC_NEXT(809, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_809(choice, ...) ML99_PRIV_REC_NEXT(810, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_810(choice, ...) ML99_PRIV_REC_NEXT(811, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_811(choice, ...) ML99_PRIV_REC_NEXT(812, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_812(choice, ...) ML99_PRIV_REC_NEXT(813, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_813(choice, ...) ML99_PRIV_REC_NEXT(814, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_814(choice, ...) ML99_PRIV_REC_NEXT(815, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_815(choice, ...) ML99_PRIV_REC_NEXT(816, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_816(choice, ...) ML99_PRIV_REC_NEXT(817, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_817(choice, ...) ML99_PRIV_REC_NEXT(818, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_818(choice, ...) ML99_PRIV_REC_NEXT(819, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_819(choice, ...) ML99_PRIV_REC_NEXT(820, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_820(choice, ...) ML99_PRIV_REC_NEXT(821, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_821(choice, ...) ML99_PRIV_REC_NEXT(822, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_822(choice, ...) ML99_PRIV_REC_NEXT(823, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_823(choice, ...) ML99_PRIV_REC_NEXT(824, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_824(choice, ...) ML99_PRIV_REC_NEXT(825, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_825(choice, ...) ML99_PRIV_REC_NEXT(826, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_826(choice, ...) ML99_PRIV_REC_NEXT(827, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_827(choice, ...) ML99_PRIV_REC_NEXT(828, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_828(choice, ...) ML99_PRIV_REC_NEXT(829, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_829(choice, ...) ML99_PRIV_REC_NEXT(830, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_830(choice, ...) ML99_PRIV_REC_NEXT(831, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_831(choice, ...) ML99_PRIV_REC_NEXT(832, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_832(choice, ...) ML99_PRIV_REC_NEXT(833, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_833(choice, ...) ML99_PRIV_REC_NEXT(834, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_834(choice, ...) ML99_PRIV_REC_NEXT(835, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_835(choice, ...) ML99_PRIV_REC_NEXT(836, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_836(choice, ...) ML99_PRIV_REC_NEXT(837, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_837(choice, ...) ML99_PRIV_REC_NEXT(838, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_838(choice, ...) ML99_PRIV_REC_NEXT(839, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_839(choice, ...) ML99_PRIV_REC_NEXT(840, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_840(choice, ...) ML99_PRIV_REC_NEXT(841, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_841(choice, ...) ML99_PRIV_REC_NEXT(842, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_842(choice, ...) ML99_PRIV_REC_NEXT(843, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_843(choice, ...) ML99_PRIV_REC_NEXT(844, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_844(choice, ...) ML99_PRIV_REC_NEXT(845, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_845(choice, ...) ML99_PRIV_REC_NEXT(846, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_846(choice, ...) ML99_PRIV_REC_NEXT(847, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_847(choice, ...) ML99_PRIV_REC_NEXT(848, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_848(choice, ...) ML99_PRIV_REC_NEXT(849, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_849(choice, ...) ML99_PRIV_REC_NEXT(850, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_850(choice, ...) ML99_PRIV_REC_NEXT(851, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_851(choice, ...) ML99_PRIV_REC_NEXT(852, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_852(choice, ...) ML99_PRIV_REC_NEXT(853, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_853(choice, ...) ML99_PRIV_REC_NEXT(854, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_854(choice, ...) ML99_PRIV_REC_NEXT(855, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_855(choice, ...) ML99_PRIV_REC_NEXT(856, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_856(choice, ...) ML99_PRIV_REC_NEXT(857, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_857(choice, ...) ML99_PRIV_REC_NEXT(858, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_858(choice, ...) ML99_PRIV_REC_NEXT(859, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_859(choice, ...) ML99_PRIV_REC_NEXT(860, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_860(choice, ...) ML99_PRIV_REC_NEXT(861, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_861(choice, ...) ML99_PRIV_REC_NEXT(862, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_862(choice, ...) ML99_PRIV_REC_NEXT(863, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_863(choice, ...) ML99_PRIV_REC_NEXT(864, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_864(choice, ...) ML99_PRIV_REC_NEXT(865, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_865(choice, ...) ML99_PRIV_REC_NEXT(866, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_866(choice, ...) ML99_PRIV_REC_NEXT(867, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_867(choice, ...) ML99_PRIV_REC_NEXT(868, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_868(choice, ...) ML99_PRIV_REC_NEXT(869, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_869(choice, ...) ML99_PRIV_REC_NEXT(870, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_870(choice, ...) ML99_PRIV_REC_NEXT(871, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_871(choice, ...) ML99_PRIV_REC_NEXT(872, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_872(choice, ...) ML99_PRIV_REC_NEXT(873, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_873(choice, ...) ML99_PRIV_REC_NEXT(874, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_874(choice, ...) ML99_PRIV_REC_NEXT(875, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_875(choice, ...) ML99_PRIV_REC_NEXT(876, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_876(choice, ...) ML99_PRIV_REC_NEXT(877, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_877(choice, ...) ML99_PRIV_REC_NEXT(878, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_878(choice, ...) ML99_PRIV_REC_NEXT(879, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_879(choice, ...) ML99_PRIV_REC_NEXT(880, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_880(choice, ...) ML99_PRIV_REC_NEXT(881, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_881(choice, ...) ML99_PRIV_REC_NEXT(882, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_882(choice, ...) ML99_PRIV_REC_NEXT(883, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_883(choice, ...) ML99_PRIV_REC_NEXT(884, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_884(choice, ...) ML99_PRIV_REC_NEXT(885, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_885(choice, ...) ML99_PRIV_REC_NEXT(886, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_886(choice, ...) ML99_PRIV_REC_NEXT(887, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_887(choice, ...) ML99_PRIV_REC_NEXT(888, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_888(choice, ...) ML99_PRIV_REC_NEXT(889, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_889(choice, ...) ML99_PRIV_REC_NEXT(890, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_890(choice, ...) ML99_PRIV_REC_NEXT(891, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_891(choice, ...) ML99_PRIV_REC_NEXT(892, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_892(choice, ...) ML99_PRIV_REC_NEXT(893, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_893(choice, ...) ML99_PRIV_REC_NEXT(894, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_894(choice, ...) ML99_PRIV_REC_NEXT(895, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_895(choice, ...) ML99_PRIV_REC_NEXT(896, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_896(choice, ...) ML99_PRIV_REC_NEXT(897, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_897(choice, ...) ML99_PRIV_REC_NEXT(898, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_898(choice, ...) ML99_PRIV_REC_NEXT(899, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_899(choice, ...) ML99_PRIV_REC_NEXT(900, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_900(choice, ...) ML99_PRIV_REC_NEXT(901, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_901(choice, ...) ML99_PRIV_REC_NEXT(902, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_902(choice, ...) ML99_PRIV_REC_NEXT(903, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_903(choice, ...) ML99_PRIV_REC_NEXT(904, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_904(choice, ...) ML99_PRIV_REC_NEXT(905, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_905(choice, ...) ML99_PRIV_REC_NEXT(906, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_906(choice, ...) ML99_PRIV_REC_NEXT(907, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_907(choice, ...) ML99_PRIV_REC_NEXT(908, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_908(choice, ...) ML99_PRIV_REC_NEXT(909, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_909(choice, ...) ML99_PRIV_REC_NEXT(910, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_910(choice, ...) ML99_PRIV_REC_NEXT(911, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_911(choice, ...) ML99_PRIV_REC_NEXT(912, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_912(choice, ...) ML99_PRIV_REC_NEXT(913, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_913(choice, ...) ML99_PRIV_REC_NEXT(914, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_914(choice, ...) ML99_PRIV_REC_NEXT(915, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_915(choice, ...) ML99_PRIV_REC_NEXT(916, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_916(choice, ...) ML99_PRIV_REC_NEXT(917, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_917(choice, ...) ML99_PRIV_REC_NEXT(918, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_918(choice, ...) ML99_PRIV_REC_NEXT(919, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_919(choice, ...) ML99_PRIV_REC_NEXT(920, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_920(choice, ...) ML99_PRIV_REC_NEXT(921, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_921(choice, ...) ML99_PRIV_REC_NEXT(922, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_922(choice, ...) ML99_PRIV_REC_NEXT(923, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_923(choice, ...) ML99_PRIV_REC_NEXT(924, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_924(choice, ...) ML99_PRIV_REC_NEXT(925, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_925(choice, ...) ML99_PRIV_REC_NEXT(926, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_926(choice, ...) ML99_PRIV_REC_NEXT(927, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_927(choice, ...) ML99_PRIV_REC_NEXT(928, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_928(choice, ...) ML99_PRIV_REC_NEXT(929, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_929(choice, ...) ML99_PRIV_REC_NEXT(930, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_930(choice, ...) ML99_PRIV_REC_NEXT(931, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_931(choice, ...) ML99_PRIV_REC_NEXT(932, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_932(choice, ...) ML99_PRIV_REC_NEXT(933, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_933(choice, ...) ML99_PRIV_REC_NEXT(934, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_934(choice, ...) ML99_PRIV_REC_NEXT(935, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_935(choice, ...) ML99_PRIV_REC_NEXT(936, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_936(choice, ...) ML99_PRIV_REC_NEXT(937, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_937(choice, ...) ML99_PRIV_REC_NEXT(938, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_938(choice, ...) ML99_PRIV_REC_NEXT(939, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_939(choice, ...) ML99_PRIV_REC_NEXT(940, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_940(choice, ...) ML99_PRIV_REC_NEXT(941, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_941(choice, ...) ML99_PRIV_REC_NEXT(942, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_942(choice, ...) ML99_PRIV_REC_NEXT(943, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_943(choice, ...) ML99_PRIV_REC_NEXT(944, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_944(choice, ...) ML99_PRIV_REC_NEXT(945, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_945(choice, ...) ML99_PRIV_REC_NEXT(946, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_946(choice, ...) ML99_PRIV_REC_NEXT(947, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_947(choice, ...) ML99_PRIV_REC_NEXT(948, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_948(choice, ...) ML99_PRIV_REC_NEXT(949, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_949(choice, ...) ML99_PRIV_REC_NEXT(950, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_950(choice, ...) ML99_PRIV_REC_NEXT(951, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_951(choice, ...) ML99_PRIV_REC_NEXT(952, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_952(choice, ...) ML99_PRIV_REC_NEXT(953, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_953(choice, ...) ML99_PRIV_REC_NEXT(954, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_954(choice, ...) ML99_PRIV_REC_NEXT(955, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_955(choice, ...) ML99_PRIV_REC_NEXT(956, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_956(choice, ...) ML99_PRIV_REC_NEXT(957, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_957(choice, ...) ML99_PRIV_REC_NEXT(958, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_958(choice, ...) ML99_PRIV_REC_NEXT(959, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_959(choice, ...) ML99_PRIV_REC_NEXT(960, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_960(choice, ...) ML99_PRIV_REC_NEXT(961, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_961(choice, ...) ML99_PRIV_REC_NEXT(962, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_962(choice, ...) ML99_PRIV_REC_NEXT(963, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_963(choice, ...) ML99_PRIV_REC_NEXT(964, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_964(choice, ...) ML99_PRIV_REC_NEXT(965, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_965(choice, ...) ML99_PRIV_REC_NEXT(966, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_966(choice, ...) ML99_PRIV_REC_NEXT(967, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_967(choice, ...) ML99_PRIV_REC_NEXT(968, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_968(choice, ...) ML99_PRIV_REC_NEXT(969, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_969(choice, ...) ML99_PRIV_REC_NEXT(970, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_970(choice, ...) ML99_PRIV_REC_NEXT(971, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_971(choice, ...) ML99_PRIV_REC_NEXT(972, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_972(choice, ...) ML99_PRIV_REC_NEXT(973, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_973(choice, ...) ML99_PRIV_REC_NEXT(974, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_974(choice, ...) ML99_PRIV_REC_NEXT(975, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_975(choice, ...) ML99_PRIV_REC_NEXT(976, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_976(choice, ...) ML99_PRIV_REC_NEXT(977, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_977(choice, ...) ML99_PRIV_REC_NEXT(978, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_978(choice, ...) ML99_PRIV_REC_NEXT(979, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_979(choice, ...) ML99_PRIV_REC_NEXT(980, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_980(choice, ...) ML99_PRIV_REC_NEXT(981, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_981(choice, ...) ML99_PRIV_REC_NEXT(982, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_982(choice, ...) ML99_PRIV_REC_NEXT(983, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_983(choice, ...) ML99_PRIV_REC_NEXT(984, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_984(choice, ...) ML99_PRIV_REC_NEXT(985, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_985(choice, ...) ML99_PRIV_REC_NEXT(986, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_986(choice, ...) ML99_PRIV_REC_NEXT(987, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_987(choice, ...) ML99_PRIV_REC_NEXT(988, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_988(choice, ...) ML99_PRIV_REC_NEXT(989, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_989(choice, ...) ML99_PRIV_REC_NEXT(990, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_990(choice, ...) ML99_PRIV_REC_NEXT(991, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_991(choice, ...) ML99_PRIV_REC_NEXT(992, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_992(choice, ...) ML99_PRIV_REC_NEXT(993, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_993(choice, ...) ML99_PRIV_REC_NEXT(994, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_994(choice, ...) ML99_PRIV_REC_NEXT(995, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_995(choice, ...) ML99_PRIV_REC_NEXT(996, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_996(choice, ...) ML99_PRIV_REC_NEXT(997, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_997(choice, ...) ML99_PRIV_REC_NEXT(998, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_998(choice, ...) ML99_PRIV_REC_NEXT(999, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_999(choice, ...) ML99_PRIV_REC_NEXT(1000, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1000(choice, ...) ML99_PRIV_REC_NEXT(1001, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1001(choice, ...) ML99_PRIV_REC_NEXT(1002, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1002(choice, ...) ML99_PRIV_REC_NEXT(1003, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1003(choice, ...) ML99_PRIV_REC_NEXT(1004, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1004(choice, ...) ML99_PRIV_REC_NEXT(1005, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1005(choice, ...) ML99_PRIV_REC_NEXT(1006, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1006(choice, ...) ML99_PRIV_REC_NEXT(1007, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1007(choice, ...) ML99_PRIV_REC_NEXT(1008, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1008(choice, ...) ML99_PRIV_REC_NEXT(1009, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1009(choice, ...) ML99_PRIV_REC_NEXT(1010, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1010(choice, ...) ML99_PRIV_REC_NEXT(1011, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1011(choice, ...) ML99_PRIV_REC_NEXT(1012, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1012(choice, ...) ML99_PRIV_REC_NEXT(1013, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1013(choice, ...) ML99_PRIV_REC_NEXT(1014, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1014(choice, ...) ML99_PRIV_REC_NEXT(1015, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1015(choice, ...) ML99_PRIV_REC_NEXT(1016, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1016(choice, ...) ML99_PRIV_REC_NEXT(1017, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1017(choice, ...) ML99_PRIV_REC_NEXT(1018, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1018(choice, ...) ML99_PRIV_REC_NEXT(1019, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1019(choice, ...) ML99_PRIV_REC_NEXT(1020, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1020(choice, ...) ML99_PRIV_REC_NEXT(1021, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1021(choice, ...) ML99_PRIV_REC_NEXT(1022, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1022(choice, ...) ML99_PRIV_REC_NEXT(1023, choice)(__VA_ARGS__) +#define ML99_PRIV_REC_1023 ML99_PRIV_REC_DEFER(ML99_PRIV_REC_0_HOOK)() + +#define ML99_PRIV_REC_0_HOOK() ML99_PRIV_REC_0 + +#endif // ML99_EVAL_REC_H diff --git a/test/external/metalang99/include/metalang99/eval/syntax_checker.h b/test/external/metalang99/include/metalang99/eval/syntax_checker.h new file mode 100644 index 0000000..0f87bef --- /dev/null +++ b/test/external/metalang99/include/metalang99/eval/syntax_checker.h @@ -0,0 +1,42 @@ +#ifndef ML99_EVAL_SYNTAX_CHECKER_H +#define ML99_EVAL_SYNTAX_CHECKER_H + +#include <metalang99/priv/bool.h> +#include <metalang99/priv/compiler_specific.h> +#include <metalang99/priv/tuple.h> +#include <metalang99/priv/util.h> + +#include <metalang99/eval/rec.h> + +#define ML99_PRIV_CHECK_TERM(term, default) \ + ML99_PRIV_IF(ML99_PRIV_IS_UNTUPLE(term), ML99_PRIV_EMIT_SYNTAX_ERROR, default) + +// clang-format off +#define ML99_PRIV_EMIT_SYNTAX_ERROR(term) \ + ML99_PRIV_REC_CONTINUE(ML99_PRIV_REC_STOP)((~), ML99_PRIV_SYNTAX_ERROR(term)) \ + /* Consume arguments passed to ML99_PRIV_TERM_MATCH, see eval.h. */ \ + ML99_PRIV_EMPTY +// clang-format on + +#define ML99_PRIV_SYNTAX_ERROR(invalid_term) \ + ML99_PRIV_CAT(ML99_PRIV_SYNTAX_ERROR_, ML99_PRIV_IS_DOUBLE_TUPLE_BEGINNING(invalid_term)) \ + (invalid_term) + +#ifdef ML99_PRIV_EMIT_ERROR + +#define ML99_PRIV_SYNTAX_ERROR_0(invalid_term) \ + ML99_PRIV_EMIT_ERROR("invalid term `" #invalid_term "`"); +#define ML99_PRIV_SYNTAX_ERROR_1(invalid_term) \ + ML99_PRIV_EMIT_ERROR("invalid term `" #invalid_term "`, did you miss a comma?"); + +#else + +// clang-format off +#define ML99_PRIV_SYNTAX_ERROR_0(invalid_term) !"Metalang99 syntax error": {invalid_term} +#define ML99_PRIV_SYNTAX_ERROR_1(invalid_term) \ + !"Metalang99 syntax error (did you miss a comma?)": {invalid_term} +// clang-format on + +#endif + +#endif // ML99_EVAL_SYNTAX_CHECKER_H diff --git a/test/external/metalang99/include/metalang99/gen.h b/test/external/metalang99/include/metalang99/gen.h new file mode 100644 index 0000000..dbb7ca8 --- /dev/null +++ b/test/external/metalang99/include/metalang99/gen.h @@ -0,0 +1,407 @@ +/** + * @file + * Support for C language constructions. + * + * Some decent usage examples can be found in + * [datatype99/examples/derive](https://github.com/hirrolot/datatype99/tree/master/examples/derive). + */ + +#ifndef ML99_GEN_H +#define ML99_GEN_H + +#include <metalang99/priv/bool.h> + +#include <metalang99/choice.h> +#include <metalang99/lang.h> +#include <metalang99/list.h> +#include <metalang99/nat.h> +#include <metalang99/tuple.h> +#include <metalang99/variadics.h> + +#include <metalang99/stmt.h> // For backwards compatibility. +#include <metalang99/util.h> // For backwards compatibility: ML99_GEN_SYM, ML99_TRAILING_SEMICOLON. + +/** + * Puts a semicolon after provided arguments. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // int x = 5; + * ML99_semicoloned(v(int x = 5)) + * @endcode + */ +#define ML99_semicoloned(...) ML99_call(ML99_semicoloned, __VA_ARGS__) + +/** + * Puts provided arguments into braces. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // { int a, b, c; } + * ML99_braced(v(int a, b, c;)) + * @endcode + */ +#define ML99_braced(...) ML99_call(ML99_braced, __VA_ARGS__) + +/** + * Generates an assignment of provided variadic arguments to @p lhs. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // x = 5, 6, 7 + * ML99_assign(v(x), v(5, 6, 7)) + * @endcode + */ +#define ML99_assign(lhs, ...) ML99_call(ML99_assign, lhs, __VA_ARGS__) + +/** + * A shortcut for `ML99_assign(lhs, ML99_braced(...))`. + */ +#define ML99_assignInitializerList(lhs, ...) ML99_call(ML99_assignInitializerList, lhs, __VA_ARGS__) + +/** + * A shortcut for `ML99_semicoloned(ML99_assign(lhs, ...))`. + */ +#define ML99_assignStmt(lhs, ...) ML99_call(ML99_assignStmt, lhs, __VA_ARGS__) + +/** + * A shortcut for `ML99_assignStmt(lhs, ML99_braced(...))`. + */ +#define ML99_assignInitializerListStmt(lhs, ...) \ + ML99_call(ML99_assignInitializerListStmt, lhs, __VA_ARGS__) + +/** + * Generates a function/macro invocation. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // If you are on C11. + * ML99_invoke(v(_Static_assert), v(1 == 1, "Must be true")) + * @endcode + */ +#define ML99_invoke(f, ...) ML99_call(ML99_invoke, f, __VA_ARGS__) + +/** + * A shortcut for `ML99_semicoloned(ML99_invoke(f, ...))`. + */ +#define ML99_invokeStmt(f, ...) ML99_call(ML99_invokeStmt, f, __VA_ARGS__) + +/** + * Generates `prefix { code }`. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // if (1 == 1) { + * // printf("x = %d\n", x); + * // } + * ML99_prefixedBlock(v(if (1 == 1)), v(printf("x = %d\n", x);)) + * @endcode + */ +#define ML99_prefixedBlock(prefix, ...) ML99_call(ML99_prefixedBlock, prefix, __VA_ARGS__) + +/** + * Generates a type definition. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // typedef struct { int x, y; } Point; + * ML99_typedef(v(Point), v(struct { int x, y; })) + * @endcode + */ +#define ML99_typedef(ident, ...) ML99_call(ML99_typedef, ident, __VA_ARGS__) + +/** + * Generates a C structure. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // struct Point { int x, y; } + * ML99_struct(v(Point), v(int x, y;)) + * @endcode + */ +#define ML99_struct(ident, ...) ML99_call(ML99_struct, ident, __VA_ARGS__) + +/** + * Generates an anonymous C structure. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // struct { int x, y; } + * ML99_struct(v(int x, y;)) + * @endcode + */ +#define ML99_anonStruct(...) ML99_call(ML99_anonStruct, __VA_ARGS__) + +/** + * The same as #ML99_struct but generates a union. + */ +#define ML99_union(ident, ...) ML99_call(ML99_union, ident, __VA_ARGS__) + +/** + * The same as #ML99_anonStruct but generates a union. + */ +#define ML99_anonUnion(...) ML99_call(ML99_anonUnion, __VA_ARGS__) + +/** + * The same as #ML99_struct but generates an enumeration. + */ +#define ML99_enum(ident, ...) ML99_call(ML99_enum, ident, __VA_ARGS__) + +/** + * The same as #ML99_anonStruct but generates an enumeration. + */ +#define ML99_anonEnum(...) ML99_call(ML99_anonEnum, __VA_ARGS__) + +/** + * Generates a function pointer. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // int (*add)(int x, int y) + * ML99_fnPtr(v(int), v(add), v(int x), v(int y)) + * + * // const char *(*title)(void) + * ML99_fnPtr(v(const char *), v(title), v(void)) + * @endcode + */ +#define ML99_fnPtr(ret_ty, name, ...) ML99_call(ML99_fnPtr, ret_ty, name, __VA_ARGS__) + +/** + * A shortcut for `ML99_semicoloned(ML99_fnPtr(ret_ty, name, ...))`. + */ +#define ML99_fnPtrStmt(ret_ty, name, ...) ML99_call(ML99_fnPtrStmt, ret_ty, name, __VA_ARGS__) + +/** + * Pastes provided arguments @p n times. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // ~ ~ ~ ~ ~ + * ML99_times(v(5), v(~)) + * @endcode + */ +#define ML99_times(n, ...) ML99_call(ML99_times, n, __VA_ARGS__) + +/** + * Invokes @p f @p n times, providing an iteration index each time. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * #include <metalang99/util.h> + * + * // _0 _1 _2 + * ML99_repeat(v(3), ML99_appl(v(ML99_cat), v(_))) + * @endcode + */ +#define ML99_repeat(n, f) ML99_call(ML99_repeat, n, f) + +/** + * Generates \f$(T_0 \ \_0, ..., T_n \ \_n)\f$. + * + * If @p type_list is empty, this macro results in `(void)`. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // (int _0, long long _1, const char * _2) + * ML99_indexedParams(ML99_list(v(int, long long, const char *))) + * + * // (void) + * ML99_indexedParams(ML99_nil()) + * @endcode + */ +#define ML99_indexedParams(type_list) ML99_call(ML99_indexedParams, type_list) + +/** + * Generates \f$T_0 \ \_0; ...; T_n \ \_n\f$. + * + * If @p type_list is empty, this macro results in emptiness. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // int _0; long long _1; const char * _2; + * ML99_indexedFields(ML99_list(v(int, long long, const char *))) + * + * // ML99_empty() + * ML99_indexedFields(ML99_nil()) + * @endcode + */ +#define ML99_indexedFields(type_list) ML99_call(ML99_indexedFields, type_list) + +/** + * Generates \f$\{ \_0, ..., \_{n - 1} \}\f$. + * + * If @p n is 0, this macro results in `{ 0 }`. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // { _0, _1, _2 } + * ML99_indexedInitializerList(v(3)) + * + * // { 0 } + * ML99_indexedInitializerList(v(0)) + * @endcode + */ +#define ML99_indexedInitializerList(n) ML99_call(ML99_indexedInitializerList, n) + +/** + * Generates \f$\_0, ..., \_{n - 1}\f$. + * + * If @p n is 0, this macro results in emptiness. + * + * # Examples + * + * @code + * #include <metalang99/gen.h> + * + * // _0, _1, _2 + * ML99_indexedArgs(v(3)) + * + * // ML99_empty() + * ML99_indexedArgs(v(0)) + * @endcode + */ +#define ML99_indexedArgs(n) ML99_call(ML99_indexedArgs, n) + +#ifndef DOXYGEN_IGNORE + +#define ML99_semicoloned_IMPL(...) v(__VA_ARGS__;) +#define ML99_braced_IMPL(...) v({__VA_ARGS__}) +#define ML99_assign_IMPL(lhs, ...) v(lhs = __VA_ARGS__) +#define ML99_assignStmt_IMPL(lhs, ...) v(lhs = __VA_ARGS__;) +#define ML99_assignInitializerList_IMPL(lhs, ...) v(lhs = {__VA_ARGS__}) +#define ML99_assignInitializerListStmt_IMPL(lhs, ...) v(lhs = {__VA_ARGS__};) +#define ML99_invoke_IMPL(f, ...) v(f(__VA_ARGS__)) +#define ML99_invokeStmt_IMPL(f, ...) v(f(__VA_ARGS__);) +#define ML99_typedef_IMPL(ident, ...) v(typedef __VA_ARGS__ ident;) +#define ML99_fnPtr_IMPL(ret_ty, name, ...) v(ret_ty (*name)(__VA_ARGS__)) +#define ML99_fnPtrStmt_IMPL(ret_ty, name, ...) v(ret_ty (*name)(__VA_ARGS__);) + +// clang-format off +#define ML99_prefixedBlock_IMPL(prefix, ...) v(prefix {__VA_ARGS__}) +#define ML99_struct_IMPL(ident, ...) v(struct ident {__VA_ARGS__}) +#define ML99_anonStruct_IMPL(...) v(struct {__VA_ARGS__}) +#define ML99_union_IMPL(ident, ...) v(union ident {__VA_ARGS__}) +#define ML99_anonUnion_IMPL(...) v(union {__VA_ARGS__}) +#define ML99_enum_IMPL(ident, ...) v(enum ident {__VA_ARGS__}) +#define ML99_anonEnum_IMPL(...) v(enum {__VA_ARGS__}) +// clang-format on + +#define ML99_times_IMPL(n, ...) ML99_natMatchWithArgs_IMPL(n, ML99_PRIV_times_, __VA_ARGS__) +#define ML99_PRIV_times_Z_IMPL ML99_empty_IMPL +#define ML99_PRIV_times_S_IMPL(i, ...) ML99_TERMS(v(__VA_ARGS__), ML99_times_IMPL(i, __VA_ARGS__)) + +#define ML99_repeat_IMPL(n, f) ML99_natMatchWithArgs_IMPL(n, ML99_PRIV_repeat_, f) +#define ML99_PRIV_repeat_Z_IMPL ML99_empty_IMPL +#define ML99_PRIV_repeat_S_IMPL(i, f) ML99_TERMS(ML99_repeat_IMPL(i, f), ML99_appl_IMPL(f, i)) + +// ML99_indexedParams_IMPL { + +#define ML99_indexedParams_IMPL(type_list) \ + ML99_tuple(ML99_PRIV_IF( \ + ML99_IS_NIL(type_list), \ + v(void), \ + ML99_variadicsTail(ML99_PRIV_indexedParamsAux_IMPL(type_list, 0)))) + +#define ML99_PRIV_indexedParamsAux_IMPL(type_list, i) \ + ML99_matchWithArgs_IMPL(type_list, ML99_PRIV_indexedParams_, i) +#define ML99_PRIV_indexedParams_nil_IMPL ML99_empty_IMPL +#define ML99_PRIV_indexedParams_cons_IMPL(x, xs, i) \ + ML99_TERMS(v(, x _##i), ML99_PRIV_indexedParamsAux_IMPL(xs, ML99_INC(i))) +// } (ML99_indexedParams_IMPL) + +// ML99_indexedFields_IMPL { + +#define ML99_indexedFields_IMPL(type_list) ML99_PRIV_indexedFieldsAux_IMPL(type_list, 0) + +#define ML99_PRIV_indexedFieldsAux_IMPL(type_list, i) \ + ML99_matchWithArgs_IMPL(type_list, ML99_PRIV_indexedFields_, i) +#define ML99_PRIV_indexedFields_nil_IMPL ML99_empty_IMPL +#define ML99_PRIV_indexedFields_cons_IMPL(x, xs, i) \ + ML99_TERMS(v(x _##i;), ML99_PRIV_indexedFieldsAux_IMPL(xs, ML99_INC(i))) +// } (ML99_indexedFields_IMPL) + +#define ML99_indexedInitializerList_IMPL(n) ML99_braced(ML99_PRIV_INDEXED_ITEMS(n, v(0))) +#define ML99_indexedArgs_IMPL(n) ML99_PRIV_INDEXED_ITEMS(n, v(ML99_EMPTY())) + +#define ML99_PRIV_INDEXED_ITEMS(n, empty_case) \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(n, 0), \ + empty_case, \ + ML99_variadicsTail(ML99_repeat_IMPL(n, ML99_PRIV_indexedItem))) + +#define ML99_PRIV_indexedItem_IMPL(i) v(, _##i) + +// Arity specifiers { + +#define ML99_semicoloned_ARITY 1 +#define ML99_braced_ARITY 1 +#define ML99_assign_ARITY 2 +#define ML99_assignStmt_ARITY 2 +#define ML99_assignInitializerList_ARITY 2 +#define ML99_assignInitializerListStmt_ARITY 2 +#define ML99_invoke_ARITY 2 +#define ML99_invokeStmt_ARITY 2 +#define ML99_prefixedBlock_ARITY 2 +#define ML99_typedef_ARITY 2 +#define ML99_struct_ARITY 2 +#define ML99_anonStruct_ARITY 1 +#define ML99_union_ARITY 2 +#define ML99_anonUnion_ARITY 1 +#define ML99_enum_ARITY 2 +#define ML99_anonEnum_ARITY 1 +#define ML99_fnPtr_ARITY 3 +#define ML99_fnPtrStmt_ARITY 3 +#define ML99_repeat_ARITY 2 +#define ML99_times_ARITY 2 +#define ML99_indexedParams_ARITY 1 +#define ML99_indexedFields_ARITY 1 +#define ML99_indexedInitializerList_ARITY 1 +#define ML99_indexedArgs_ARITY 1 + +#define ML99_PRIV_indexedItem_ARITY 1 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_GEN_H diff --git a/test/external/metalang99/include/metalang99/ident.h b/test/external/metalang99/include/metalang99/ident.h new file mode 100644 index 0000000..f6bb67a --- /dev/null +++ b/test/external/metalang99/include/metalang99/ident.h @@ -0,0 +1,429 @@ +/** + * @file + * Identifiers: `[a-zA-Z0-9_]+`. + * + * An identifier is a sequence of characters. A character is one of: + * + * - digits (`0123456789`), + * - lowercase letters (`abcdefghijklmnopqrstuvwxyz`), + * - uppercase letters (`ABCDEFGHIJKLMNOPQRSTUVWXYZ`), + * - the underscore character (`_`). + * + * For example, here are identifiers: `_ak39A`, `192_iAjP_2`, `r9`. But these are **not** + * identifiers: `~18nA`, `o78*`, `3i#^hdd`. + */ + +#ifndef ML99_IDENT_H +#define ML99_IDENT_H + +#include <metalang99/priv/bool.h> +#include <metalang99/priv/tuple.h> +#include <metalang99/priv/util.h> + +#include <metalang99/lang.h> + +/** + * Tells whether @p ident belongs to a set of identifiers defined by @p prefix. + * + * If `ML99_cat(prefix, ident)` exists, it must be an object-like macro which expands to `()`. If + * so, `ML99_detectIdent(prefix, ident)` will expand to truth, otherwise (`ML99_cat(prefix, ident)` + * does **not** exist), `ML99_detectIdent(prefix, ident)` will expand to falsehood. + * + * # Predefined detectors + * + * - `ML99_UNDERSCORE_DETECTOR` detects the underscore character (`_`). + * + * # Examples + * + * @code + * #include <metalang99/ident.h> + * + * #define FOO_x () + * #define FOO_y () + * + * // 1 + * ML99_detectIdent(v(FOO_), v(x)) + * + * // 1 + * ML99_detectIdent(v(FOO_), v(y)) + * + * // 0 + * ML99_detectIdent(v(FOO_), v(z)) + * + * // 1 + * ML99_detectIdent(v(ML99_UNDERSCORE_DETECTOR), v(_)) + * @endcode + */ +#define ML99_detectIdent(prefix, ident) ML99_call(ML99_detectIdent, prefix, ident) + +/** + * Compares two identifiers @p x and @p y for equality. + * + * This macro is a shortcut to `ML99_detectIdent(ML99_cat3(prefix, x, v(_)), y)`. + * + * # Predefined detectors + * + * - `ML99_C_KEYWORD_DETECTOR` detects all the [C11 + * keywords](https://en.cppreference.com/w/c/keyword). + * - `ML99_LOWERCASE_DETECTOR` detects lowercase letters (`abcdefghijklmnopqrstuvwxyz`). + * - `ML99_UPPERCASE_DETECTOR` detects uppercase letters (`ABCDEFGHIJKLMNOPQRSTUVWXYZ`). + * - `ML99_DIGIT_DETECTOR` detects digits (`0123456789`). + * + * # Examples + * + * @code + * #include <metalang99/ident.h> + * + * #define FOO_x_x () + * #define FOO_y_y () + * + * // 1 + * ML99_identEq(v(FOO_), v(x), v(x)) + * + * // 1 + * ML99_identEq(v(FOO_), v(y), v(y)) + * + * // 0 + * ML99_identEq(v(FOO_), v(x), v(y)) + * + * // 1 + * ML99_identEq(v(ML99_C_KEYWORD_DETECTOR), v(while), v(while)) + * ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(x), v(x)) + * ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(X), v(X)) + * ML99_identEq(v(ML99_DIGIT_DETECTOR), v(5), v(5)) + * @endcode + */ +#define ML99_identEq(prefix, x, y) ML99_call(ML99_identEq, prefix, x, y) + +/** + * Compares two characters @p x and @p y for equality. + * + * @p x and @p y can be any identifiers, though this function evaluates to true only for characters. + * + * # Examples + * + * @code + * #include <metalang99/ident.h> + * + * // 1 + * ML99_charEq(v(t), v(t)) + * + * // 0 + * ML99_charEq(v(9), v(A)) + * + * // 0 + * ML99_charEq(v(9), v(abcd)) + * @endcode + */ +#define ML99_charEq(x, y) ML99_call(ML99_charEq, x, y) + +/** + * Tells whether the identifier @p x is a lowercase letter. + */ +#define ML99_isLowercase(x) ML99_call(ML99_isLowercase, x) + +/** + * Tells whether the identifier @p x is an uppercase letter. + */ +#define ML99_isUppercase(x) ML99_call(ML99_isUppercase, x) + +/** + * Tells whether the identifier @p x is a digit. + */ +#define ML99_isDigit(x) ML99_call(ML99_isDigit, x) + +/** + * Tells whether the identifier @p x is a character. + */ +#define ML99_isChar(x) ML99_call(ML99_isChar, x) + +/** + * Converts the Metalang99 character @p x to a C character literal. + * + * # Examples + * + * @code + * #include <metalang/ident.h> + * + * // 't' + * ML99_charLit(v(t)) + * + * // '9' + * ML99_charLit(v(9)) + * + * // '_' + * ML99_charLit(v(_)) + * @endcode + * + * @note The inverse of this function is impossible, i.e., you cannot get `q` from `'q'`. + */ +#define ML99_charLit(x) ML99_call(ML99_charLit, x) + +/** + * Expands to all comma-separated lowercase letters. + * + * This macro consumes all arguments. + * + * # Examples + * + * @code + * #include <metalang99/ident.h> + * #include <metalang99/variadics.h> + * + * #define F_IMPL(x) v([x]) + * #define F_ARITY 1 + * + * // [a] [b] [c] ... [x] [y] [z] + * ML99_variadicsForEach(v(F), v(ML99_LOWERCASE_CHARS())) + * @endcode + */ +#define ML99_LOWERCASE_CHARS(...) \ + a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z + +/** + * The same as #ML99_LOWERCASE_CHARS but for uppercase characters. + */ +#define ML99_UPPERCASE_CHARS(...) \ + A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z + +/** + * The same as #ML99_LOWERCASE_CHARS but for digits. + */ +#define ML99_DIGITS(...) 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 + +#define ML99_DETECT_IDENT(prefix, ident) ML99_PRIV_IS_TUPLE_FAST(ML99_PRIV_CAT(prefix, ident)) +#define ML99_IDENT_EQ(prefix, x, y) ML99_DETECT_IDENT(ML99_PRIV_CAT3(prefix, x, _), y) + +#define ML99_CHAR_EQ(x, y) \ + ML99_PRIV_IF( \ + ML99_DETECT_IDENT(ML99_UNDERSCORE_DETECTOR, x), \ + ML99_DETECT_IDENT(ML99_UNDERSCORE_DETECTOR, y), \ + ML99_PRIV_OR3( \ + ML99_IDENT_EQ(ML99_LOWERCASE_DETECTOR, x, y), \ + ML99_IDENT_EQ(ML99_UPPERCASE_DETECTOR, x, y), \ + ML99_IDENT_EQ(ML99_DIGIT_DETECTOR, x, y))) + +#define ML99_IS_LOWERCASE(x) ML99_IDENT_EQ(ML99_LOWERCASE_DETECTOR, x, x) +#define ML99_IS_UPPERCASE(x) ML99_IDENT_EQ(ML99_UPPERCASE_DETECTOR, x, x) +#define ML99_IS_DIGIT(x) ML99_IDENT_EQ(ML99_DIGIT_DETECTOR, x, x) + +#define ML99_IS_CHAR(x) \ + ML99_PRIV_OR4( \ + ML99_IS_LOWERCASE(x), \ + ML99_IS_UPPERCASE(x), \ + ML99_IS_DIGIT(x), \ + ML99_DETECT_IDENT(ML99_UNDERSCORE_DETECTOR, x)) + +#define ML99_CHAR_LIT(x) ML99_PRIV_CAT(ML99_PRIV_CHAR_LIT_, x) + +#ifndef DOXYGEN_IGNORE + +#define ML99_detectIdent_IMPL(prefix, ident) v(ML99_DETECT_IDENT(prefix, ident)) +#define ML99_identEq_IMPL(prefix, x, y) v(ML99_IDENT_EQ(prefix, x, y)) +#define ML99_charEq_IMPL(x, y) v(ML99_CHAR_EQ(x, y)) +#define ML99_isLowercase_IMPL(x) v(ML99_IS_LOWERCASE(x)) +#define ML99_isUppercase_IMPL(x) v(ML99_IS_UPPERCASE(x)) +#define ML99_isDigit_IMPL(x) v(ML99_IS_DIGIT(x)) +#define ML99_isChar_IMPL(x) v(ML99_IS_CHAR(x)) +#define ML99_charLit_IMPL(x) v(ML99_CHAR_LIT(x)) + +#define ML99_UNDERSCORE_DETECTOR ML99_PRIV_UNDERSCORE_DETECTOR_ +#define ML99_C_KEYWORD_DETECTOR ML99_PRIV_C_KEYWORD_DETECTOR_ +#define ML99_LOWERCASE_DETECTOR ML99_PRIV_LOWER_DETECTOR_ +#define ML99_UPPERCASE_DETECTOR ML99_PRIV_UPPER_DETECTOR_ +#define ML99_DIGIT_DETECTOR ML99_PRIV_DIGIT_DETECTOR_ + +#define ML99_PRIV_C_KEYWORD_DETECTOR_auto_auto () +#define ML99_PRIV_C_KEYWORD_DETECTOR_break_break () +#define ML99_PRIV_C_KEYWORD_DETECTOR_case_case () +#define ML99_PRIV_C_KEYWORD_DETECTOR_char_char () +#define ML99_PRIV_C_KEYWORD_DETECTOR_const_const () +#define ML99_PRIV_C_KEYWORD_DETECTOR_continue_continue () +#define ML99_PRIV_C_KEYWORD_DETECTOR_default_default () +#define ML99_PRIV_C_KEYWORD_DETECTOR_do_do () +#define ML99_PRIV_C_KEYWORD_DETECTOR_double_double () +#define ML99_PRIV_C_KEYWORD_DETECTOR_else_else () +#define ML99_PRIV_C_KEYWORD_DETECTOR_enum_enum () +#define ML99_PRIV_C_KEYWORD_DETECTOR_extern_extern () +#define ML99_PRIV_C_KEYWORD_DETECTOR_float_float () +#define ML99_PRIV_C_KEYWORD_DETECTOR_for_for () +#define ML99_PRIV_C_KEYWORD_DETECTOR_goto_goto () +#define ML99_PRIV_C_KEYWORD_DETECTOR_if_if () +#define ML99_PRIV_C_KEYWORD_DETECTOR_inline_inline () +#define ML99_PRIV_C_KEYWORD_DETECTOR_int_int () +#define ML99_PRIV_C_KEYWORD_DETECTOR_long_long () +#define ML99_PRIV_C_KEYWORD_DETECTOR_register_register () +#define ML99_PRIV_C_KEYWORD_DETECTOR_restrict_restrict () +#define ML99_PRIV_C_KEYWORD_DETECTOR_return_return () +#define ML99_PRIV_C_KEYWORD_DETECTOR_short_short () +#define ML99_PRIV_C_KEYWORD_DETECTOR_signed_signed () +#define ML99_PRIV_C_KEYWORD_DETECTOR_sizeof_sizeof () +#define ML99_PRIV_C_KEYWORD_DETECTOR_static_static () +#define ML99_PRIV_C_KEYWORD_DETECTOR_struct_struct () +#define ML99_PRIV_C_KEYWORD_DETECTOR_switch_switch () +#define ML99_PRIV_C_KEYWORD_DETECTOR_typedef_typedef () +#define ML99_PRIV_C_KEYWORD_DETECTOR_union_union () +#define ML99_PRIV_C_KEYWORD_DETECTOR_unsigned_unsigned () +#define ML99_PRIV_C_KEYWORD_DETECTOR_void_void () +#define ML99_PRIV_C_KEYWORD_DETECTOR_volatile_volatile () +#define ML99_PRIV_C_KEYWORD_DETECTOR_while_while () +#define ML99_PRIV_C_KEYWORD_DETECTOR__Alignas__Alignas () +#define ML99_PRIV_C_KEYWORD_DETECTOR__Alignof__Alignof () +#define ML99_PRIV_C_KEYWORD_DETECTOR__Atomic__Atomic () +#define ML99_PRIV_C_KEYWORD_DETECTOR__Bool__Bool () +#define ML99_PRIV_C_KEYWORD_DETECTOR__Complex__Complex () +#define ML99_PRIV_C_KEYWORD_DETECTOR__Generic__Generic () +#define ML99_PRIV_C_KEYWORD_DETECTOR__Imaginary__Imaginary () +#define ML99_PRIV_C_KEYWORD_DETECTOR__Noreturn__Noreturn () +#define ML99_PRIV_C_KEYWORD_DETECTOR__Static_assert__Static_assert () +#define ML99_PRIV_C_KEYWORD_DETECTOR__Thread_local__Thread_local () + +#define ML99_PRIV_UNDERSCORE_DETECTOR__ () + +#define ML99_PRIV_LOWER_DETECTOR_a_a () +#define ML99_PRIV_LOWER_DETECTOR_b_b () +#define ML99_PRIV_LOWER_DETECTOR_c_c () +#define ML99_PRIV_LOWER_DETECTOR_d_d () +#define ML99_PRIV_LOWER_DETECTOR_e_e () +#define ML99_PRIV_LOWER_DETECTOR_f_f () +#define ML99_PRIV_LOWER_DETECTOR_g_g () +#define ML99_PRIV_LOWER_DETECTOR_h_h () +#define ML99_PRIV_LOWER_DETECTOR_i_i () +#define ML99_PRIV_LOWER_DETECTOR_j_j () +#define ML99_PRIV_LOWER_DETECTOR_k_k () +#define ML99_PRIV_LOWER_DETECTOR_l_l () +#define ML99_PRIV_LOWER_DETECTOR_m_m () +#define ML99_PRIV_LOWER_DETECTOR_n_n () +#define ML99_PRIV_LOWER_DETECTOR_o_o () +#define ML99_PRIV_LOWER_DETECTOR_p_p () +#define ML99_PRIV_LOWER_DETECTOR_q_q () +#define ML99_PRIV_LOWER_DETECTOR_r_r () +#define ML99_PRIV_LOWER_DETECTOR_s_s () +#define ML99_PRIV_LOWER_DETECTOR_t_t () +#define ML99_PRIV_LOWER_DETECTOR_u_u () +#define ML99_PRIV_LOWER_DETECTOR_v_v () +#define ML99_PRIV_LOWER_DETECTOR_w_w () +#define ML99_PRIV_LOWER_DETECTOR_x_x () +#define ML99_PRIV_LOWER_DETECTOR_y_y () +#define ML99_PRIV_LOWER_DETECTOR_z_z () + +#define ML99_PRIV_UPPER_DETECTOR_A_A () +#define ML99_PRIV_UPPER_DETECTOR_B_B () +#define ML99_PRIV_UPPER_DETECTOR_C_C () +#define ML99_PRIV_UPPER_DETECTOR_D_D () +#define ML99_PRIV_UPPER_DETECTOR_E_E () +#define ML99_PRIV_UPPER_DETECTOR_F_F () +#define ML99_PRIV_UPPER_DETECTOR_G_G () +#define ML99_PRIV_UPPER_DETECTOR_H_H () +#define ML99_PRIV_UPPER_DETECTOR_I_I () +#define ML99_PRIV_UPPER_DETECTOR_J_J () +#define ML99_PRIV_UPPER_DETECTOR_K_K () +#define ML99_PRIV_UPPER_DETECTOR_L_L () +#define ML99_PRIV_UPPER_DETECTOR_M_M () +#define ML99_PRIV_UPPER_DETECTOR_N_N () +#define ML99_PRIV_UPPER_DETECTOR_O_O () +#define ML99_PRIV_UPPER_DETECTOR_P_P () +#define ML99_PRIV_UPPER_DETECTOR_Q_Q () +#define ML99_PRIV_UPPER_DETECTOR_R_R () +#define ML99_PRIV_UPPER_DETECTOR_S_S () +#define ML99_PRIV_UPPER_DETECTOR_T_T () +#define ML99_PRIV_UPPER_DETECTOR_U_U () +#define ML99_PRIV_UPPER_DETECTOR_V_V () +#define ML99_PRIV_UPPER_DETECTOR_W_W () +#define ML99_PRIV_UPPER_DETECTOR_X_X () +#define ML99_PRIV_UPPER_DETECTOR_Y_Y () +#define ML99_PRIV_UPPER_DETECTOR_Z_Z () + +#define ML99_PRIV_DIGIT_DETECTOR_0_0 () +#define ML99_PRIV_DIGIT_DETECTOR_1_1 () +#define ML99_PRIV_DIGIT_DETECTOR_2_2 () +#define ML99_PRIV_DIGIT_DETECTOR_3_3 () +#define ML99_PRIV_DIGIT_DETECTOR_4_4 () +#define ML99_PRIV_DIGIT_DETECTOR_5_5 () +#define ML99_PRIV_DIGIT_DETECTOR_6_6 () +#define ML99_PRIV_DIGIT_DETECTOR_7_7 () +#define ML99_PRIV_DIGIT_DETECTOR_8_8 () +#define ML99_PRIV_DIGIT_DETECTOR_9_9 () + +#define ML99_PRIV_CHAR_LIT_a 'a' +#define ML99_PRIV_CHAR_LIT_b 'b' +#define ML99_PRIV_CHAR_LIT_c 'c' +#define ML99_PRIV_CHAR_LIT_d 'd' +#define ML99_PRIV_CHAR_LIT_e 'e' +#define ML99_PRIV_CHAR_LIT_f 'f' +#define ML99_PRIV_CHAR_LIT_g 'g' +#define ML99_PRIV_CHAR_LIT_h 'h' +#define ML99_PRIV_CHAR_LIT_i 'i' +#define ML99_PRIV_CHAR_LIT_j 'j' +#define ML99_PRIV_CHAR_LIT_k 'k' +#define ML99_PRIV_CHAR_LIT_l 'l' +#define ML99_PRIV_CHAR_LIT_m 'm' +#define ML99_PRIV_CHAR_LIT_n 'n' +#define ML99_PRIV_CHAR_LIT_o 'o' +#define ML99_PRIV_CHAR_LIT_p 'p' +#define ML99_PRIV_CHAR_LIT_q 'q' +#define ML99_PRIV_CHAR_LIT_r 'r' +#define ML99_PRIV_CHAR_LIT_s 's' +#define ML99_PRIV_CHAR_LIT_t 't' +#define ML99_PRIV_CHAR_LIT_u 'u' +#define ML99_PRIV_CHAR_LIT_v 'v' +#define ML99_PRIV_CHAR_LIT_w 'w' +#define ML99_PRIV_CHAR_LIT_x 'x' +#define ML99_PRIV_CHAR_LIT_y 'y' +#define ML99_PRIV_CHAR_LIT_z 'z' + +#define ML99_PRIV_CHAR_LIT_A 'A' +#define ML99_PRIV_CHAR_LIT_B 'B' +#define ML99_PRIV_CHAR_LIT_C 'C' +#define ML99_PRIV_CHAR_LIT_D 'D' +#define ML99_PRIV_CHAR_LIT_E 'E' +#define ML99_PRIV_CHAR_LIT_F 'F' +#define ML99_PRIV_CHAR_LIT_G 'G' +#define ML99_PRIV_CHAR_LIT_H 'H' +#define ML99_PRIV_CHAR_LIT_I 'I' +#define ML99_PRIV_CHAR_LIT_J 'J' +#define ML99_PRIV_CHAR_LIT_K 'K' +#define ML99_PRIV_CHAR_LIT_L 'L' +#define ML99_PRIV_CHAR_LIT_M 'M' +#define ML99_PRIV_CHAR_LIT_N 'N' +#define ML99_PRIV_CHAR_LIT_O 'O' +#define ML99_PRIV_CHAR_LIT_P 'P' +#define ML99_PRIV_CHAR_LIT_Q 'Q' +#define ML99_PRIV_CHAR_LIT_R 'R' +#define ML99_PRIV_CHAR_LIT_S 'S' +#define ML99_PRIV_CHAR_LIT_T 'T' +#define ML99_PRIV_CHAR_LIT_U 'U' +#define ML99_PRIV_CHAR_LIT_V 'V' +#define ML99_PRIV_CHAR_LIT_W 'W' +#define ML99_PRIV_CHAR_LIT_X 'X' +#define ML99_PRIV_CHAR_LIT_Y 'Y' +#define ML99_PRIV_CHAR_LIT_Z 'Z' + +#define ML99_PRIV_CHAR_LIT_0 '0' +#define ML99_PRIV_CHAR_LIT_1 '1' +#define ML99_PRIV_CHAR_LIT_2 '2' +#define ML99_PRIV_CHAR_LIT_3 '3' +#define ML99_PRIV_CHAR_LIT_4 '4' +#define ML99_PRIV_CHAR_LIT_5 '5' +#define ML99_PRIV_CHAR_LIT_6 '6' +#define ML99_PRIV_CHAR_LIT_7 '7' +#define ML99_PRIV_CHAR_LIT_8 '8' +#define ML99_PRIV_CHAR_LIT_9 '9' + +#define ML99_PRIV_CHAR_LIT__ '_' + +// Arity specifiers { + +#define ML99_detectIdent_ARITY 2 +#define ML99_identEq_ARITY 3 +#define ML99_charEq_ARITY 2 +#define ML99_isLowercase_ARITY 1 +#define ML99_isUppercase_ARITY 1 +#define ML99_isDigit_ARITY 1 +#define ML99_isChar_ARITY 1 +#define ML99_charLit_ARITY 1 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_IDENT_H diff --git a/test/external/metalang99/include/metalang99/lang.h b/test/external/metalang99/include/metalang99/lang.h new file mode 100644 index 0000000..299f8d7 --- /dev/null +++ b/test/external/metalang99/include/metalang99/lang.h @@ -0,0 +1,246 @@ +/** + * @file + * The core metalanguage. + */ + +#ifndef ML99_LANG_H +#define ML99_LANG_H + +#include <metalang99/priv/bool.h> +#include <metalang99/priv/tuple.h> + +#include <metalang99/eval/eval.h> +#include <metalang99/lang/closure.h> + +/** + * Evaluates a metaprogram. + * + * # Examples + * + * @code + * #include <metalang99/lang.h> + * + * #define F_IMPL(x, y) v(x + y) + * + * ML99_EVAL(v(abc ~ 123), ML99_call(F, v(1, 2))) + * @endcode + */ +#define ML99_EVAL(...) ML99_PRIV_EVAL(__VA_ARGS__) + +/** + * Invokes a metafunction with arguments. + */ +#define ML99_call(op, ...) \ + (ML99_PRIV_IF(ML99_PRIV_IS_UNTUPLE_FAST(op), 0args, 0op), op, __VA_ARGS__) + +/** + * Invokes a metafunction @p ident with unevaluated arguments. + * + * It is semantically the same as `ML99_call(ident, v(...))` but performs one less reduction + * steps. + */ +#define ML99_callUneval(ident, ...) (0callUneval, ident, __VA_ARGS__) + +/** + * Applies arguments to @p f. + * + * This function implements [partial + * application](https://en.wikipedia.org/wiki/Partial_application): instead of invoking a + * metafunction with all arguments at once, you specify each argument separately. This concept + * allows better re-use of metafunctions by specifying some arguments immediately, and the other + * arguments later, even in different execution contexts (for example, see this [SO + * answer](https://stackoverflow.com/a/12414292/13166656)). + * + * @p f must be either a term reducing to a macro name or a term obtained via another call to + * #ML99_appl. If @p f is a macro name, then a macro named `<f>_ARITY` (its arity specifier) + * must denote how many times @p f will be applied to its arguments. (In Metalang99, an arity is an + * intentionally more flexible concept than just a number of parameters, see below.) Each time + * #ML99_appl is invoked, it accumulates provided variadic arguments and decrements the arity + * of @p f; when the arity of @p f is already 1, it eventually calls the initial @p f with all the + * accumulated arguments and provided variadic arguments. + * + * Most often, an arity specifier denotes a count of all named parameters plus 1 if a macro is + * variadic (all the functions in the standard library follow this pattern). However, feel free to + * specify arities as you wish, with regard to the aforementioned semantics; for example, you can + * have a macro accepting `x, y, z` with an arity specifier `2`, then you must invoke + * #ML99_appl exactly 2 times (either `x` + `y, z` or `x, y` + `z`). One common pattern is to + * match a head and a tail of variadic arguments: + * + * @code + * #include <metalang99/lang.h> + * + * #define F_IMPL(x, y, z, head, ...) // ... + * #define F_ARITY 4 + * @endcode + * + * In this case, `x`, `y`, and `z` can be specified separately but other arguments all at once. + * + * # Examples + * + * @code + * #include <metalang99/lang.h> + * + * #define F_IMPL(x, y) v(x##y) + * #define F_ARITY 2 + * + * // ab + * ML99_appl(ML99_appl(v(F), v(a)), v(b)) + * @endcode + * + * @note Currently, the maximum arity is #ML99_NAT_MAX. However, some compilers might not support + * more than 127 macro parameters. + */ +#define ML99_appl(f, ...) ML99_call(ML99_appl, f, __VA_ARGS__) + +/** + * Applies @p a and @p b to @p f. + * + * # Examples + * + * @code + * #include <metalang99/lang.h> + * + * #define F_IMPL(x, y) v(x##y) + * #define F_ARITY 2 + * + * // ab + * ML99_appl2(v(F), v(a), v(b)) + * @endcode + */ +#define ML99_appl2(f, a, b) ML99_call(ML99_appl2, f, a, b) + +/** + * Applies @p a, @p b, and @p c to @p f. + */ +#define ML99_appl3(f, a, b, c) ML99_call(ML99_appl3, f, a, b, c) + +/** + * Applies @p a, @p b, @p c, and @p d to @p f. + */ +#define ML99_appl4(f, a, b, c, d) ML99_call(ML99_appl4, f, a, b, c, d) + +/** + * Functional composition of @p f and @p g. + * + * # Examples + * + * @code + * #include <metalang99/lang.h> + * + * #define F_IMPL(x) v((x + 1)) + * #define G_IMPL(x) v((x * 8)) + * + * #define F_ARITY 1 + * #define G_ARITY 1 + * + * // ((3 * 8) + 1) + * ML99_appl(ML99_compose(v(F), v(G)), v(3)) + * @endcode + */ +#define ML99_compose(f, g) ML99_call(ML99_compose, f, g) + +/** + * A value that is pasted as-is; no evaluation occurs on provided arguments. + */ +#define v(...) (0v, __VA_ARGS__) + +// clang-format off +/** + * Emits a fatal error. + * + * @p f must be a macro name that has caused the error and the rest of arguments comprise the error + * message. + * + * #ML99_fatal interprets its variadic arguments without preprocessor expansion -- i.e., they are + * pasted as-is. This is intended because otherwise identifiers located in an error message may + * stand for other macros that will be unintentionally expanded. + * + * # Examples + * + * [`playground.c`] + * @code + * #include <metalang99/lang.h> + * + * ML99_EVAL(ML99_fatal(F, the description of your error)) + * @endcode + * + * [`/bin/sh`] + * @code{.txt} + * playground.c:3:1: error: static assertion failed: "F: the description of your error" + * 3 | ML99_EVAL(ML99_fatal(F, the description of your error)) + * | ^~~~~~~~~ + * @endcode + */ +#define ML99_fatal(f, ...) (0fatal, f, #__VA_ARGS__) +// clang-format on + +/** + * Immediately aborts the interpretation with evaluated arguments. + * + * # Examples + * + * @code + * #include <metalang99/lang.h> + * + * #define F_IMPL(x) v(~) + * + * // 123 + * ML99_call(F, ML99_abort(v(123))) + * @endcode + */ +#define ML99_abort(...) (0abort, __VA_ARGS__) + +/** + * A convenience macro to emphasize that your metafunction expands to more than one term. + * + * This macro just expands to provided arguments. + * + * # Examples + * + * @code + * #include <metalang99/lang.h> + * + * #define F_IMPL(x) ML99_TERMS(v(1), v(x), v(2)) + * @endcode + */ +#define ML99_TERMS(...) __VA_ARGS__ + +/** + * Delays evaluation for provided terms. + * + * `ML99_QUOTE(...)` is functionally equivalent to `v(...)`. + * + * # Examples + * + * @code + * #include <metalang99/lang.h> + * + * #define F_IMPL(x) v(~x) + * + * #define PROG ML99_TERMS(v(1), v(2), ML99_call(F, v(7))) + * + * // The same as `PROG` pasted into a source file. + * ML99_EVAL(ML99_QUOTE(PROG)) + * @endcode + */ +#define ML99_QUOTE(...) v(__VA_ARGS__) + +#ifndef DOXYGEN_IGNORE + +#define ML99_compose_IMPL(f, g) ML99_appl2_IMPL(ML99_PRIV_compose, f, g) +#define ML99_PRIV_compose_IMPL(f, g, x) ML99_appl(v(f), ML99_appl_IMPL(g, x)) + +// Arity specifiers { + +#define ML99_appl_ARITY 2 +#define ML99_appl2_ARITY 3 +#define ML99_appl3_ARITY 4 +#define ML99_appl4_ARITY 5 +#define ML99_compose_ARITY 2 + +#define ML99_PRIV_compose_ARITY 3 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_LANG_H diff --git a/test/external/metalang99/include/metalang99/lang/closure.h b/test/external/metalang99/include/metalang99/lang/closure.h new file mode 100644 index 0000000..3812df0 --- /dev/null +++ b/test/external/metalang99/include/metalang99/lang/closure.h @@ -0,0 +1,51 @@ +#ifndef ML99_LANG_CLOSURE_H +#define ML99_LANG_CLOSURE_H + +#include <metalang99/priv/bool.h> +#include <metalang99/priv/util.h> + +#include <metalang99/nat/dec.h> +#include <metalang99/nat/eq.h> + +/* + * A closure has the form `(arity, f, ...)`, where `arity` is how many times `ML99_appl` can + * be called for this closure, and `...` denotes the closure's environment. + * + * `ML99_appl` is described by the following algorithm: + * - If `f` is an identifier (like `FOO`): + * - If `f##_ARITY` is 1, then just call this function with provided arguments. + * - Otherwise, return `(f##_ARITY - 1, f, provided args...)`. + * - Otherwise (`f` is a closure): + * - If `arity` is 1, then just call `f` with its environment and provided arguments. + * - Otherwise, return `(arity - 1, f, env..., provided args...)`. + * + * Thus, each time except the last, `ML99_appl` extends a closure's environment with new + * arguments; the last time, it calls `f` with its environment. + */ + +#define ML99_appl_IMPL(f, ...) \ + ML99_PRIV_IF(ML99_PRIV_IS_UNTUPLE_FAST(f), ML99_PRIV_APPL_F, ML99_PRIV_APPL_CLOSURE) \ + (f, __VA_ARGS__) + +#define ML99_PRIV_APPL_F(f, ...) \ + ML99_PRIV_IF( \ + ML99_PRIV_NAT_EQ(f##_ARITY, 1), \ + ML99_callUneval(f, __VA_ARGS__), \ + v((ML99_PRIV_DEC(f##_ARITY), f, __VA_ARGS__))) + +#define ML99_PRIV_APPL_CLOSURE(closure, ...) \ + ML99_PRIV_APPL_CLOSURE_AUX(ML99_PRIV_EXPAND closure, __VA_ARGS__) + +#define ML99_PRIV_APPL_CLOSURE_AUX(...) ML99_PRIV_APPL_CLOSURE_AUX_AUX(__VA_ARGS__) + +#define ML99_PRIV_APPL_CLOSURE_AUX_AUX(arity, f, ...) \ + ML99_PRIV_IF( \ + ML99_PRIV_NAT_EQ(arity, 1), \ + ML99_callUneval(f, __VA_ARGS__), \ + v((ML99_PRIV_DEC(arity), f, __VA_ARGS__))) + +#define ML99_appl2_IMPL(f, a, b) ML99_appl(ML99_appl_IMPL(f, a), v(b)) +#define ML99_appl3_IMPL(f, a, b, c) ML99_appl(ML99_appl2_IMPL(f, a, b), v(c)) +#define ML99_appl4_IMPL(f, a, b, c, d) ML99_appl(ML99_appl3_IMPL(f, a, b, c), v(d)) + +#endif // ML99_LANG_CLOSURE_H diff --git a/test/external/metalang99/include/metalang99/list.h b/test/external/metalang99/include/metalang99/list.h new file mode 100644 index 0000000..bf62916 --- /dev/null +++ b/test/external/metalang99/include/metalang99/list.h @@ -0,0 +1,1129 @@ +/** + * @file + * Cons-lists. + */ + +#ifndef ML99_LIST_H +#define ML99_LIST_H + +#include <metalang99/priv/bool.h> +#include <metalang99/priv/util.h> + +#include <metalang99/bool.h> +#include <metalang99/choice.h> +#include <metalang99/nat.h> +#include <metalang99/seq.h> +#include <metalang99/util.h> +#include <metalang99/variadics.h> + +/** + * Prepends @p x to @p xs. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * ML99_cons(v(1), ML99_cons(v(2), ML99_nil())) + * @endcode + */ +#define ML99_cons(x, xs) ML99_call(ML99_cons, x, xs) + +/** + * The empty list. + */ +#define ML99_nil(...) ML99_callUneval(ML99_nil, ) + +/** + * Checks @p list for non-emptiness. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 1 + * ML99_isCons(ML99_list(v(1, 2, 3))) + * + * // 0 + * ML99_isCons(ML99_nil()) + * @endcode + */ +#define ML99_isCons(list) ML99_call(ML99_isCons, list) + +/** + * Checks @p list for emptiness. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 0 + * ML99_isNil(ML99_list(v(1, 2, 3))) + * + * // 1 + * ML99_isNil(ML99_nil()) + * @endcode + */ +#define ML99_isNil(list) ML99_call(ML99_isNil, list) + +/** + * Extracts the head from the non-empty list @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 1 + * ML99_listHead(ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listHead(list) ML99_call(ML99_listHead, list) + +/** + * Extracts the tail from the non-empty list @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 2, 3 + * ML99_listTail(ML99_list(v(1, 2, 3))) + * + * // ML99_nil() + * ML99_listTail(ML99_list(v(1))) + * @endcode + */ +#define ML99_listTail(list) ML99_call(ML99_listTail, list) + +/** + * Extracts the last element from the non-empty list @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 3 + * ML99_listLast(ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listLast(list) ML99_call(ML99_listLast, list) + +/** + * Extracts all the elements of the non-empty list @p list except the last one. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 1, 2 + * ML99_listInit(ML99_list(v(1, 2, 3))) + * + * // ML99_nil() + * ML99_listInit(ML99_list(v(1))) + * @endcode + */ +#define ML99_listInit(list) ML99_call(ML99_listInit, list) + +/** + * Constructs a list from its arguments. + * + * At most 63 arguments are acceptable. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 1, 2, 3 + * ML99_list(v(1, 2, 3)) + * @endcode + */ +#define ML99_list(...) ML99_call(ML99_list, __VA_ARGS__) + +/** + * Constructs a list from comma-separated [tuples](tuple.html). + * + * It sequentially applies @p f to each untupled argument, thus forming the resulting list. If some + * argument is not a tuple, a fatal error is emitted. + * + * The result is `ML99_list(ML99_appl(f, ML99_untuple(x1)), ..., ML99_appl(f, ML99_untuple(xN)))`. + * + * Each variadic argument inherits all the preconditions of #ML99_isUntuple. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * #define F_IMPL(x, y) v(x + y) + * #define F_ARITY 1 + * + * // ML99_list(v(1 + 2, 3 + 4, 5 + 6)) + * ML99_listFromTuples(v(F), v((1, 2), (3, 4), (5, 6))) + * @endcode + */ +#define ML99_listFromTuples(f, ...) ML99_call(ML99_listFromTuples, f, __VA_ARGS__) + +/** + * Constructs a list from the [sequence](seq.html) @p seq. + * + * Note that @p seq items must **not** contain commas. If you want commas in items, such as `(+, -, + * *, /)`, consider wrapping an item in parentheses: `((+, -, *, /))`. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // ML99_nil() + * ML99_listFromSeq(v()) + * + * // ML99_list(v(1, 2, 3)) + * ML99_listFromSeq(v((1)(2)(3))) + * @endcode + */ +#define ML99_listFromSeq(seq) ML99_call(ML99_listFromSeq, seq) + +/** + * Computes the length of @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 0 + * ML99_listLen(ML99_nil()) + * + * // 3 + * ML99_listLen(ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listLen(list) ML99_call(ML99_listLen, list) + +/** + * Evaluates a metaprogram that reduces to a list, then unwraps it. + * + * It behaves the same as the composition of #ML99_EVAL and #ML99_listUnwrap. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // Literally 1 2 3 + * ML99_LIST_EVAL(ML99_list(v(1, 2, 3))) + * @endcode + * + * @note This macro does not result in a Metalang99 term; it literally pastes list elements into a + * source file. + */ +#define ML99_LIST_EVAL(...) ML99_EVAL(ML99_call(ML99_listUnwrap, __VA_ARGS__)) + +/** + * The same as #ML99_LIST_EVAL but intersperses a comma between list items. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // Literally 1, 2, 3 + * ML99_LIST_EVAL_COMMA_SEP(ML99_list(v(1, 2, 3))) + * @endcode + * + * @note This macro does not result in a Metalang99 term; it literally pastes comma-separated list + * elements into a source file. + */ +#define ML99_LIST_EVAL_COMMA_SEP(...) ML99_EVAL(ML99_call(ML99_listUnwrapCommaSep, __VA_ARGS__)) + +/** + * Appends the list @p other to @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 1, 2, 3 + * ML99_listAppend(ML99_list(v(1)), ML99_list(v(2, 3))) + * @endcode + */ +#define ML99_listAppend(list, other) ML99_call(ML99_listAppend, list, other) + +/** + * Appends the item @p item to @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 1, 2, 3 + * ML99_listAppendItem(v(3), ML99_list(v(1, 2))) + * @endcode + */ +#define ML99_listAppendItem(item, list) ML99_call(ML99_listAppendItem, item, list) + +/** + * Places all the items in @p list as-is. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // Literally 1 2 3 + * ML99_listUnwrap(ML99_list(v(1, 2, 3))) + * @endcode + * + * @note The resulting value is still a valid Metalang99 term that need to be evaluated further. + * @see #ML99_LIST_EVAL + * @see #ML99_LIST_EVAL_COMMA_SEP + */ +#define ML99_listUnwrap(list) ML99_call(ML99_listUnwrap, list) + +/** + * Places all the items in @p list as-is, separated by commas. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // Literally 1, 2, 3 + * ML99_listUnwrapCommaSep(ML99_list(v(1, 2, 3))) + * @endcode + * + * @note The resulting value is still a valid Metalang99 term that need to be evaluated further. + * @see #ML99_LIST_EVAL + * @see #ML99_LIST_EVAL_COMMA_SEP + */ +#define ML99_listUnwrapCommaSep(list) ML99_call(ML99_listUnwrapCommaSep, list) + +/** + * Reverses the order of items in @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 3, 2, 1 + * ML99_listReverse(ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listReverse(list) ML99_call(ML99_listReverse, list) + +/** + * Extracts the @p i -indexed element. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 2 + * ML99_listGet(v(1), ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listGet(i, list) ML99_call(ML99_listGet, i, list) + +/** + * A right-associative fold over @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * #define ABCDEFG 123 + * + * // 7 + * ML99_listFoldr(v(ML99_cat), v(7), ML99_nil()) + * + * // 123 + * ML99_listFoldr(ML99_appl(v(ML99_flip), v(ML99_cat)), v(A), ML99_list(v(G, DEF, BC))) + * @endcode + */ +#define ML99_listFoldr(f, init, list) ML99_call(ML99_listFoldr, f, init, list) + +/** + * A left-associative fold over @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * #define ABCDEFG 123 + * + * // 7 + * ML99_listFoldl(v(ML99_cat), v(7), ML99_nil()) + * + * // 123 + * ML99_listFoldl(v(ML99_cat), v(A), ML99_list(v(BC, DEF, G))) + * @endcode + */ +#define ML99_listFoldl(f, init, list) ML99_call(ML99_listFoldl, f, init, list) + +/** + * The same as #ML99_listFoldl but treats the first element of @p list as the initial value. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * #define ABCDEFG 123 + * + * // 123 + * ML99_listFoldl1(v(ML99_cat), ML99_list(v(AB, CDEF, G))) + * @endcode + */ +#define ML99_listFoldl1(f, list) ML99_call(ML99_listFoldl1, f, list) + +/** + * Intersperses @p item between the items in @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 1, +, 2, +, 3 + * ML99_listIntersperse(v(+), ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listIntersperse(item, list) ML99_call(ML99_listIntersperse, item, list) + +/** + * Prepends @p item to all items in @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // +, 1, +, 2, +, 3 + * ML99_listPrependToAll(v(+), ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listPrependToAll(item, list) ML99_call(ML99_listPrependToAll, item, list) + +/** + * Maps all the elements in @p list with @p f. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * #include <metalang99/nat.h> + * + * // 4, 5, 6 + * ML99_listMap(ML99_appl(v(ML99_add), v(3)), ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listMap(f, list) ML99_call(ML99_listMap, f, list) + +/** + * The same as #ML99_listMap but provides an index of an element to @p f. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * #define F_IMPL(x, i) v(x[i]) + * #define F_ARITY 2 + * + * // a[0], b[1], c[2] + * ML99_listMapI(v(F), ML99_list(v(a, b, c))) + * @endcode + */ +#define ML99_listMapI(f, list) ML99_call(ML99_listMapI, f, list) + +/** + * A more efficient version of `ML99_listUnwrap(ML99_listMap(f, list))`. + * + * @note Unlike #ML99_listMap, @p f can evaluate to many terms. + */ +#define ML99_listMapInPlace(f, list) ML99_call(ML99_listMapInPlace, f, list) + +/** + * A more efficient version of `ML99_listUnwrap(ML99_listMapI(f, list))`. + * + * @note Unlike #ML99_listMapI, @p f can evaluate to many terms. + */ +#define ML99_listMapInPlaceI(f, list) ML99_call(ML99_listMapInPlaceI, f, list) + +/** + * The same as #ML99_listMap but with the reversed order of arguments. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * #include <metalang99/nat.h> + * + * // 4, 5, 6 + * ML99_listFor(ML99_list(v(1, 2, 3)), ML99_appl(v(ML99_add), v(3))) + * @endcode + */ +#define ML99_listFor(list, f) ML99_call(ML99_listFor, list, f) + +/** + * Maps the initial elements of the non-empty list @p list with @p f_init and the last element with + * @p f_last. + * + * # Examples + * + * @code + * // 4, 5, 10 + * ML99_listMapInitLast(ML99_appl(v(ML99_add), v(3)), ML99_appl(v(ML99_add), v(7)), ML99_list(v(1, + * 2, 3))) + * @endcode + */ +#define ML99_listMapInitLast(f_init, f_last, list) \ + ML99_call(ML99_listMapInitLast, f_init, f_last, list) + +/** + * The same as #ML99_listMapInitLast but accepts @p list as the first parameter. + * + * # Examples + * + * @code + * // 4, 5, 10 + * ML99_listForInitLast(ML99_list(v(1, 2, 3)), ML99_appl(v(ML99_add), v(3)), ML99_appl(v(ML99_add), + * v(7))) + * @endcode + */ +#define ML99_listForInitLast(list, f_init, f_last) \ + ML99_call(ML99_listForInitLast, list, f_init, f_last) + +/** + * Filters @p list with @p f. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * #include <metalang99/nat.h> + * + * // 9, 11, 6 + * ML99_listFilter(ML99_appl(v(ML99_lesser), v(5)), ML99_list(v(9, 1, 11, 6, 0, 4))) + * @endcode + */ +#define ML99_listFilter(f, list) ML99_call(ML99_listFilter, f, list) + +/** + * A combination of #ML99_listFilter and #ML99_listMap. + * + * It builds a new list by applying @p f to each element in @p list: if @p f yields `ML99_just(x)`, + * `x` is passed to the new list, otherwise (`ML99_nothing()`), the value is neglected. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * #include <metalang99/maybe.h> + * + * #define MAYBE_LIST ML99_list(ML99_just(v(5)), ML99_nothing(), ML99_just(v(7))) + * + * // 5, 7 + * ML99_listFilterMap(v(ML99_id), MAYBE_LIST) + * @endcode + */ +#define ML99_listFilterMap(f, list) ML99_call(ML99_listFilterMap, f, list) + +/** + * Tests @p list and @p other for equality. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * #include <metalang99/nat.h> + * + * // 0 + * ML99_listEq(v(ML99_natEq), ML99_list(v(1, 2, 3)), ML99_list(v(4, 5, 6))) + * + * // 1 + * ML99_listEq(v(ML99_natEq), ML99_list(v(1, 2, 3)), ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listEq(cmp, list, other) ML99_call(ML99_listEq, cmp, list, other) + +/** + * Checks whether @p item resides in @p list. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * #include <metalang99/nat.h> + * + * // 1 + * ML99_listContains(v(ML99_natEq), v(3), ML99_list(v(1, 2, 3))) + * + * // 0 + * ML99_listContains(v(ML99_natEq), v(456), ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listContains(cmp, item, list) ML99_call(ML99_listContains, cmp, item, list) + +/** + * Extracts the prefix of @p list of the length @p n. If @p n is greater than the length of @p list, + * the whole @p list is returned. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 1, 2 + * ML99_listTake(v(2), ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listTake(n, list) ML99_call(ML99_listTake, n, list) + +/** + * Extracts the items from @p list as long as @p f evaluates to `ML99_true()`. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * #include <metalang99/nat.h> + * + * // 1, 2, 3 + * ML99_listTakeWhile(ML99_appl(v(ML99_greater), v(4)), ML99_list(v(1, 2, 3, 4, 5, 6))) + * @endcode + */ +#define ML99_listTakeWhile(f, list) ML99_call(ML99_listTakeWhile, f, list) + +/** + * Removes the prefix of @p list of the length @p n. If @p n is greater than the length of @p list, + * `ML99_nil()` is returned. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // 2, 3 + * ML99_listDrop(v(1), ML99_list(v(1, 2, 3))) + * @endcode + */ +#define ML99_listDrop(n, list) ML99_call(ML99_listDrop, n, list) + +/** + * Removes the items from @p list as long as @p f evaluates to `ML99_true()`. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * #include <metalang99/nat.h> + * + * // 4, 5, 6 + * ML99_listDropWhile(ML99_appl(v(ML99_lesser), v(4)), ML99_list(v(1, 2, 3, 4, 5, 6))) + * @endcode + */ +#define ML99_listDropWhile(f, list) ML99_call(ML99_listDropWhile, f, list) + +/** + * Computes a list of two-place tuples of the corresponding items from @p list and @p other. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // (1, 4), (2, 5), (3, 6) + * ML99_listZip(ML99_list(v(1, 2, 3)), ML99_list(v(4, 5, 6))) + * @endcode + */ +#define ML99_listZip(list, other) ML99_call(ML99_listZip, list, other) + +/** + * Transforms a list of two-place tuples into a tuple of a list of the first components and a list + * of the second components. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * #include <metalang99/tuple.h> + * + * // ML99_tuple(ML99_list(v(1, 2, 3)), ML99_list(v(4, 5, 6))) + * ML99_listUnzip(ML99_list(ML99_tuple(v(1, 4)), ML99_tuple(v(2, 5)), ML99_tuple(v(3, 6)))) + * @endcode + */ +#define ML99_listUnzip(list) ML99_call(ML99_listUnzip, list) + +/** + * Computes a list of length @p n with each element @p item. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * + * // ~, ~, ~, ~, ~ + * ML99_listReplicate(v(5), v(~)) + * + * // ML99_nil() + * ML99_listReplicate(v(0), v(~)) + * @endcode + */ +#define ML99_listReplicate(n, item) ML99_call(ML99_listReplicate, n, item) + +/** + * Returns a two-place tuple of lists: those items of @p list the do and do not satisfy the + * predicate @p f, respectively. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * #include <metalang99/nat.h> + * + * // ML99_tuple(ML99_list(v(4, 7)), ML99_list(v(11, 12, 13))) + * ML99_listPartition(ML99_appl(v(ML99_greater), v(10)), ML99_list(v(11, 4, 12, 13, 7))) + * @endcode + */ +#define ML99_listPartition(f, list) ML99_call(ML99_listPartition, f, list) + +/** + * Applies all the items in @p list to @p f. + * + * If the list is empty, results in @p f as-is. + * + * # Examples + * + * @code + * #include <metalang99/list.h> + * #include <metalang99/nat.h> + * + * // ML99_add + * ML99_listAppl(v(ML99_add), ML99_nil()) + * + * // ML99_appl(v(ML99_add), v(1)) + * ML99_listAppl(v(ML99_add), ML99_list(v(1))) + * + * // ML99_appl2(v(ML99_add), v(1), v(2)) + * ML99_listAppl(v(ML99_add), ML99_list(v(1, 2))) + * @endcode + */ +#define ML99_listAppl(f, list) ML99_call(ML99_listAppl, f, list) + +#define ML99_CONS(x, xs) ML99_CHOICE(cons, x, xs) +#define ML99_NIL(...) ML99_CHOICE(nil, ~) +#define ML99_IS_CONS(list) ML99_NOT(ML99_IS_NIL(list)) +#define ML99_IS_NIL(list) ML99_PRIV_IS_NIL(list) + +#ifndef DOXYGEN_IGNORE + +#define ML99_cons_IMPL(x, xs) v(ML99_CONS(x, xs)) +#define ML99_nil_IMPL(...) v(ML99_NIL()) + +#define ML99_isCons_IMPL(list) v(ML99_IS_CONS(list)) +#define ML99_isNil_IMPL(list) v(ML99_IS_NIL(list)) + +#define ML99_listHead_IMPL(list) ML99_match_IMPL(list, ML99_PRIV_listHead_) +#define ML99_PRIV_listHead_nil_IMPL(_) ML99_PRIV_EMPTY_LIST_ERROR(listHead) +#define ML99_PRIV_listHead_cons_IMPL(x, _xs) v(x) + +#define ML99_listTail_IMPL(list) ML99_match_IMPL(list, ML99_PRIV_listTail_) +#define ML99_PRIV_listTail_nil_IMPL(_) ML99_PRIV_EMPTY_LIST_ERROR(listTail) +#define ML99_PRIV_listTail_cons_IMPL(_x, xs) v(xs) + +#define ML99_listLast_IMPL(list) ML99_match_IMPL(list, ML99_PRIV_listLast_) +#define ML99_PRIV_listLast_nil_IMPL(_) ML99_PRIV_EMPTY_LIST_ERROR(listLast) +#define ML99_PRIV_listLast_cons_IMPL(x, xs) \ + ML99_PRIV_IF(ML99_IS_NIL(xs), v(x), ML99_listLast_IMPL(xs)) + +#define ML99_listInit_IMPL(list) ML99_match_IMPL(list, ML99_PRIV_listInit_) +#define ML99_PRIV_listInit_nil_IMPL(_) ML99_PRIV_EMPTY_LIST_ERROR(listInit) +#define ML99_PRIV_listInit_cons_IMPL(x, xs) \ + ML99_PRIV_IF(ML99_IS_NIL(xs), v(ML99_NIL()), ML99_cons(v(x), ML99_listInit_IMPL(xs))) + +// ML99_list_IMPL { + +#define ML99_list_IMPL(...) \ + ML99_PRIV_listProgress_IMPL(ML99_VARIADICS_COUNT(__VA_ARGS__), __VA_ARGS__, ~) + +// Last 4 recursion steps unrolled. +#define ML99_PRIV_listProgress_IMPL(count, ...) \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(count, 4), \ + ML99_PRIV_listDone_4, \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(count, 3), \ + ML99_PRIV_listDone_3, \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(count, 2), \ + ML99_PRIV_listDone_2, \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(count, 1), \ + ML99_PRIV_listDone_1, \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(count, 0), \ + ML99_PRIV_listDone_0, \ + ML99_PRIV_listProgressAux))))) \ + (count, __VA_ARGS__) + +#define ML99_PRIV_listProgressAux(count, x, ...) \ + ML99_cons(v(x), ML99_callUneval(ML99_PRIV_listProgress, ML99_DEC(count), __VA_ARGS__)) + +#define ML99_PRIV_listDone_0(_count, _) v(ML99_NIL()) +#define ML99_PRIV_listDone_1(_count, a, _) v(ML99_CONS(a, ML99_NIL())) +#define ML99_PRIV_listDone_2(_count, a, b, _) v(ML99_CONS(a, ML99_CONS(b, ML99_NIL()))) +#define ML99_PRIV_listDone_3(_count, a, b, c, _) \ + v(ML99_CONS(a, ML99_CONS(b, ML99_CONS(c, ML99_NIL())))) +#define ML99_PRIV_listDone_4(_count, a, b, c, d, _) \ + v(ML99_CONS(a, ML99_CONS(b, ML99_CONS(c, ML99_CONS(d, ML99_NIL()))))) +// } (ML99_list_IMPL) + +// ML99_listFromTuples_IMPL { + +#define ML99_listFromTuples_IMPL(f, ...) ML99_PRIV_listFromTuplesAux_IMPL(f, __VA_ARGS__, ~) + +#define ML99_PRIV_listFromTuplesAux_IMPL(f, x, ...) \ + ML99_PRIV_CAT(ML99_PRIV_listFromTuples_, ML99_IS_UNTUPLE(x))(f, x, __VA_ARGS__) + +#define ML99_PRIV_listFromTuples_1(_f, x, ...) ML99_PRIV_NOT_TUPLE_ERROR(x) +#define ML99_PRIV_listFromTuples_0(f, x, ...) \ + ML99_cons( \ + ML99_appl_IMPL(f, ML99_UNTUPLE(x)), \ + ML99_PRIV_IF( \ + ML99_VARIADICS_IS_SINGLE(__VA_ARGS__), \ + v(ML99_NIL()), \ + ML99_callUneval(ML99_PRIV_listFromTuplesAux, f, __VA_ARGS__))) +// } (ML99_listFromTuples_IMPL) + +#define ML99_listFromSeq_IMPL(seq) \ + ML99_PRIV_CAT(ML99_PRIV_listFromSeq_, ML99_SEQ_IS_EMPTY(seq))(seq) +#define ML99_PRIV_listFromSeq_1 ML99_nil_IMPL +#define ML99_PRIV_listFromSeq_0(seq) \ + ML99_cons(v(ML99_SEQ_GET(0)(seq)), ML99_callUneval(ML99_listFromSeq, ML99_SEQ_TAIL(seq))) + +#define ML99_listLen_IMPL(list) ML99_match_IMPL(list, ML99_PRIV_listLen_) +#define ML99_PRIV_listLen_nil_IMPL(_) v(0) +#define ML99_PRIV_listLen_cons_IMPL(_x, xs) ML99_inc(ML99_listLen_IMPL(xs)) + +#define ML99_listAppend_IMPL(list, other) \ + ML99_matchWithArgs_IMPL(list, ML99_PRIV_listAppend_, other) +#define ML99_PRIV_listAppend_nil_IMPL(_, other) v(other) +#define ML99_PRIV_listAppend_cons_IMPL(x, xs, other) \ + ML99_cons(v(x), ML99_listAppend_IMPL(xs, other)) + +#define ML99_listAppendItem_IMPL(item, list) ML99_listAppend_IMPL(list, ML99_CONS(item, ML99_NIL())) + +#define ML99_listUnwrap_IMPL(list) ML99_match_IMPL(list, ML99_PRIV_listUnwrap_) +#define ML99_PRIV_listUnwrap_nil_IMPL ML99_empty_IMPL +#define ML99_PRIV_listUnwrap_cons_IMPL(x, xs) ML99_TERMS(v(x), ML99_listUnwrap_IMPL(xs)) + +#define ML99_listReverse_IMPL(list) ML99_match_IMPL(list, ML99_PRIV_listReverse_) +#define ML99_PRIV_listReverse_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listReverse_cons_IMPL(x, xs) ML99_listAppendItem(v(x), ML99_listReverse_IMPL(xs)) + +#define ML99_listGet_IMPL(i, list) ML99_matchWithArgs_IMPL(list, ML99_PRIV_listGet_, i) +#define ML99_PRIV_listGet_nil_IMPL(_, i) ML99_PRIV_EMPTY_LIST_ERROR(ML99_listGet) +#define ML99_PRIV_listGet_cons_IMPL(x, xs, i) \ + ML99_PRIV_IF(ML99_NAT_EQ(i, 0), v(x), ML99_listGet_IMPL(ML99_DEC(i), xs)) + +#define ML99_listFoldr_IMPL(f, init, list) \ + ML99_matchWithArgs_IMPL(list, ML99_PRIV_listFoldr_, f, init) +#define ML99_PRIV_listFoldr_nil_IMPL(_, _f, acc) v(acc) +#define ML99_PRIV_listFoldr_cons_IMPL(x, xs, f, acc) \ + ML99_call(ML99_appl2, v(f, x), ML99_listFoldr_IMPL(f, acc, xs)) + +#define ML99_listFoldl_IMPL(f, init, list) \ + ML99_matchWithArgs_IMPL(list, ML99_PRIV_listFoldl_, f, init) +#define ML99_PRIV_listFoldl_nil_IMPL(_, _f, acc) v(acc) +#define ML99_PRIV_listFoldl_cons_IMPL(x, xs, f, acc) \ + ML99_listFoldl(v(f), ML99_appl2_IMPL(f, acc, x), v(xs)) + +#define ML99_listFoldl1_IMPL(f, list) ML99_matchWithArgs_IMPL(list, ML99_PRIV_listFoldl1_, f) +#define ML99_PRIV_listFoldl1_nil_IMPL(_, _f) ML99_PRIV_EMPTY_LIST_ERROR(ML99_listFoldl1) +#define ML99_PRIV_listFoldl1_cons_IMPL(x, xs, f) ML99_listFoldl_IMPL(f, x, xs) + +#define ML99_listIntersperse_IMPL(item, list) \ + ML99_matchWithArgs_IMPL(list, ML99_PRIV_listIntersperse_, item) +#define ML99_PRIV_listIntersperse_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listIntersperse_cons_IMPL(x, xs, item) \ + ML99_cons(v(x), ML99_listPrependToAll_IMPL(item, xs)) + +#define ML99_listPrependToAll_IMPL(item, list) \ + ML99_matchWithArgs_IMPL(list, ML99_PRIV_listPrependToAll_, item) +#define ML99_PRIV_listPrependToAll_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listPrependToAll_cons_IMPL(x, xs, item) \ + ML99_cons(v(item), ML99_cons(v(x), ML99_listPrependToAll_IMPL(item, xs))) + +#define ML99_listMap_IMPL(f, list) ML99_matchWithArgs_IMPL(list, ML99_PRIV_listMap_, f) +#define ML99_PRIV_listMap_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listMap_cons_IMPL(x, xs, f) \ + ML99_cons(ML99_appl_IMPL(f, x), ML99_listMap_IMPL(f, xs)) + +#define ML99_listMapI_IMPL(f, list) ML99_PRIV_listMapIAux_IMPL(f, list, 0) +#define ML99_PRIV_listMapIAux_IMPL(f, list, i) \ + ML99_matchWithArgs_IMPL(list, ML99_PRIV_listMapI_, f, i) +#define ML99_PRIV_listMapI_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listMapI_cons_IMPL(x, xs, f, i) \ + ML99_cons(ML99_appl2_IMPL(f, x, i), ML99_PRIV_listMapIAux_IMPL(f, xs, ML99_INC(i))) + +#define ML99_listMapInPlace_IMPL(f, list) \ + ML99_matchWithArgs_IMPL(list, ML99_PRIV_listMapInPlace_, f) +#define ML99_PRIV_listMapInPlace_nil_IMPL ML99_empty_IMPL +#define ML99_PRIV_listMapInPlace_cons_IMPL(x, xs, f) \ + ML99_TERMS(ML99_appl_IMPL(f, x), ML99_listMapInPlace_IMPL(f, xs)) + +#define ML99_listMapInPlaceI_IMPL(f, list) ML99_PRIV_listMapInPlaceIAux_IMPL(f, list, 0) +#define ML99_PRIV_listMapInPlaceIAux_IMPL(f, list, i) \ + ML99_matchWithArgs_IMPL(list, ML99_PRIV_listMapInPlaceI_, f, i) +#define ML99_PRIV_listMapInPlaceI_nil_IMPL ML99_empty_IMPL +#define ML99_PRIV_listMapInPlaceI_cons_IMPL(x, xs, f, i) \ + ML99_TERMS(ML99_appl2_IMPL(f, x, i), ML99_PRIV_listMapInPlaceIAux_IMPL(f, xs, ML99_INC(i))) + +#define ML99_listFor_IMPL(list, f) ML99_listMap_IMPL(f, list) + +#define ML99_listMapInitLast_IMPL(f_init, f_last, list) \ + ML99_listAppendItem( \ + ML99_appl(v(f_last), ML99_listLast_IMPL(list)), \ + ML99_listMap(v(f_init), ML99_listInit_IMPL(list))) + +#define ML99_listForInitLast_IMPL(list, f_init, f_last) \ + ML99_listMapInitLast_IMPL(f_init, f_last, list) + +// ML99_listFilter_IMPL { + +#define ML99_listFilter_IMPL(f, list) ML99_matchWithArgs_IMPL(list, ML99_PRIV_listFilter_, f) + +#define ML99_PRIV_listFilter_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listFilter_cons_IMPL(x, xs, f) \ + ML99_call( \ + ML99_boolMatchWithArgs, \ + ML99_appl_IMPL(f, x), \ + v(ML99_PRIV_listFilter_cons_, x), \ + ML99_listFilter_IMPL(f, xs)) + +#define ML99_PRIV_listFilter_cons_1_IMPL(x, rest) v(ML99_CONS(x, rest)) +#define ML99_PRIV_listFilter_cons_0_IMPL(_x, rest) v(rest) +// } (ML99_listFilter_IMPL) + +// ML99_listFilterMap_IMPL { + +#define ML99_listFilterMap_IMPL(f, list) ML99_matchWithArgs_IMPL(list, ML99_PRIV_listFilterMap_, f) + +#define ML99_PRIV_listFilterMap_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listFilterMap_cons_IMPL(x, xs, f) \ + ML99_call(ML99_matchWithArgs, ML99_appl_IMPL(f, x), v(ML99_PRIV_listFilterMap_cons_, f, xs)) + +#define ML99_PRIV_listFilterMap_cons_just_IMPL(y, f, xs) \ + ML99_cons(v(y), ML99_listFilterMap_IMPL(f, xs)) +#define ML99_PRIV_listFilterMap_cons_nothing_IMPL(_, f, xs) ML99_listFilterMap_IMPL(f, xs) +// } (ML99_listFilterMap_IMPL) + +// ML99_listEq_IMPL { + +#define ML99_listEq_IMPL(cmp, list, other) \ + ML99_matchWithArgs_IMPL(list, ML99_PRIV_listEq_, other, cmp) + +#define ML99_PRIV_listEq_nil_IMPL(_, other, _cmp) v(ML99_IS_NIL(other)) +#define ML99_PRIV_listEq_cons_IMPL(x, xs, other, cmp) \ + ML99_matchWithArgs_IMPL(other, ML99_PRIV_listEq_cons_, x, xs, cmp) + +#define ML99_PRIV_listEq_cons_nil_IMPL ML99_false_IMPL +#define ML99_PRIV_listEq_cons_cons_IMPL(other_x, other_xs, x, xs, cmp) \ + ML99_call( \ + ML99_call(ML99_if, ML99_appl2_IMPL(cmp, x, other_x), v(ML99_listEq, ML99_false)), \ + v(cmp, xs, other_xs)) +// } (ML99_listEq_IMPL) + +#define ML99_listContains_IMPL(cmp, item, list) \ + ML99_matchWithArgs_IMPL(list, ML99_PRIV_listContains_, item, cmp) +#define ML99_PRIV_listContains_nil_IMPL ML99_false_IMPL +#define ML99_PRIV_listContains_cons_IMPL(x, xs, item, cmp) \ + ML99_call( \ + ML99_call(ML99_if, ML99_appl2_IMPL(cmp, x, item), v(ML99_true, ML99_listContains)), \ + v(cmp, item, xs)) + +#define ML99_listTake_IMPL(n, list) ML99_matchWithArgs_IMPL(list, ML99_PRIV_listTake_, n) +#define ML99_PRIV_listTake_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listTake_cons_IMPL(x, xs, i) \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(i, 0), \ + v(ML99_NIL()), \ + ML99_cons(v(x), ML99_listTake_IMPL(ML99_DEC(i), xs))) + +// ML99_listTakeWhile_IMPL { + +#define ML99_listTakeWhile_IMPL(f, list) ML99_matchWithArgs_IMPL(list, ML99_PRIV_listTakeWhile_, f) + +#define ML99_PRIV_listTakeWhile_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listTakeWhile_cons_IMPL(x, xs, f) \ + ML99_call( \ + ML99_boolMatchWithArgs, \ + ML99_appl_IMPL(f, x), \ + v(ML99_PRIV_listTakeWhile_cons_, x, xs, f)) + +#define ML99_PRIV_listTakeWhile_cons_1_IMPL(x, xs, f) \ + ML99_cons(v(x), ML99_listTakeWhile_IMPL(f, xs)) +#define ML99_PRIV_listTakeWhile_cons_0_IMPL ML99_nil_IMPL +// } (ML99_listTakeWhile_IMPL) + +#define ML99_listDrop_IMPL(n, list) ML99_matchWithArgs_IMPL(list, ML99_PRIV_listDrop_, n) +#define ML99_PRIV_listDrop_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listDrop_cons_IMPL(x, xs, i) \ + ML99_PRIV_IF(ML99_NAT_EQ(i, 0), v(ML99_CONS(x, xs)), ML99_listDrop_IMPL(ML99_DEC(i), xs)) + +// ML99_listDropWhile_IMPL { + +#define ML99_listDropWhile_IMPL(f, list) ML99_matchWithArgs_IMPL(list, ML99_PRIV_listDropWhile_, f) + +#define ML99_PRIV_listDropWhile_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listDropWhile_cons_IMPL(x, xs, f) \ + ML99_call( \ + ML99_boolMatchWithArgs, \ + ML99_appl_IMPL(f, x), \ + v(ML99_PRIV_listDropWhile_cons_, x, xs, f)) + +#define ML99_PRIV_listDropWhile_cons_0_IMPL(x, xs, _f) v(ML99_CONS(x, xs)) +#define ML99_PRIV_listDropWhile_cons_1_IMPL(_x, xs, f) ML99_listDropWhile_IMPL(f, xs) +// } (ML99_listDropWhile_IMPL) + +// ML99_listZip_IMPL { + +#define ML99_listZip_IMPL(list, other) ML99_matchWithArgs_IMPL(list, ML99_PRIV_listZip_, other) + +#define ML99_PRIV_listZip_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listZip_cons_IMPL(x, xs, other) \ + ML99_matchWithArgs_IMPL(other, ML99_PRIV_listZip_cons_, x, xs) + +#define ML99_PRIV_listZip_cons_nil_IMPL ML99_nil_IMPL +#define ML99_PRIV_listZip_cons_cons_IMPL(other_x, other_xs, x, xs) \ + ML99_cons(v(ML99_TUPLE(x, other_x)), ML99_listZip_IMPL(xs, other_xs)) +// } (ML99_listZip_IMPL) + +// ML99_listUnzip_IMPL { + +#define ML99_listUnzip_IMPL(list) ML99_match_IMPL(list, ML99_PRIV_listUnzip_) + +#define ML99_PRIV_listUnzip_nil_IMPL(_) v(ML99_TUPLE(ML99_NIL(), ML99_NIL())) +#define ML99_PRIV_listUnzip_cons_IMPL(x, xs) \ + ML99_call(ML99_PRIV_listUnzipProgress, v(x), ML99_listUnzip_IMPL(xs)) + +#define ML99_PRIV_listUnzipProgress_IMPL(x, rest) \ + v(ML99_TUPLE(ML99_PRIV_LIST_UNZIP_EXTEND(x, rest, 0), ML99_PRIV_LIST_UNZIP_EXTEND(x, rest, 1))) + +#define ML99_PRIV_LIST_UNZIP_EXTEND(x, rest, i) \ + ML99_CONS(ML99_TUPLE_GET(i)(x), ML99_TUPLE_GET(i)(rest)) +// } (ML99_listUnzip_IMPL) + +#define ML99_listReplicate_IMPL(n, item) \ + ML99_natMatchWithArgs_IMPL(n, ML99_PRIV_listReplicate_, item) +#define ML99_PRIV_listReplicate_Z_IMPL ML99_nil_IMPL +#define ML99_PRIV_listReplicate_S_IMPL(n, item) ML99_cons(v(item), ML99_listReplicate_IMPL(n, item)) + +// ML99_listPartition_IMPL { + +#define ML99_listPartition_IMPL(f, list) \ + ML99_listFoldr( \ + ML99_appl_IMPL(ML99_PRIV_listPartitionAux, f), \ + v(ML99_TUPLE(ML99_NIL(), ML99_NIL())), \ + v(list)) + +#define ML99_PRIV_listPartitionAux_IMPL(f, x, acc) \ + ML99_call( \ + ML99_boolMatchWithArgs, \ + ML99_appl_IMPL(f, x), \ + v(ML99_PRIV_listPartition_, x, ML99_UNTUPLE(acc))) + +#define ML99_PRIV_listPartition_1_IMPL(x, fst, snd) v(ML99_TUPLE(ML99_CONS(x, fst), snd)) +#define ML99_PRIV_listPartition_0_IMPL(x, fst, snd) v(ML99_TUPLE(fst, ML99_CONS(x, snd))) +// } (ML99_listPartition_IMPL) + +#define ML99_listAppl_IMPL(f, list) ML99_listFoldl_IMPL(ML99_appl, f, list) + +// ML99_listUnwrapCommaSep_IMPL { + +#define ML99_listUnwrapCommaSep_IMPL(list) \ + ML99_PRIV_IF( \ + ML99_IS_NIL(list), \ + v(ML99_EMPTY()), \ + ML99_variadicsTail(ML99_PRIV_listUnwrapCommaSepAux_IMPL(list))) + +#define ML99_PRIV_listUnwrapCommaSepAux_IMPL(xs) ML99_match_IMPL(xs, ML99_PRIV_listUnwrapCommaSep_) + +#define ML99_PRIV_listUnwrapCommaSep_nil_IMPL ML99_empty_IMPL +#define ML99_PRIV_listUnwrapCommaSep_cons_IMPL(x, xs) \ + ML99_TERMS(v(, x), ML99_PRIV_listUnwrapCommaSepAux_IMPL(xs)) +// } (ML99_listUnwrapCommaSep_IMPL) + +// clang-format off +#define ML99_PRIV_EMPTY_LIST_ERROR(f) ML99_fatal(ML99_##f, expected a non-empty list) +// clang-format on + +#define ML99_PRIV_IS_NIL(list) ML99_DETECT_IDENT(ML99_PRIV_IS_NIL_, ML99_CHOICE_TAG(list)) +#define ML99_PRIV_IS_NIL_nil () + +// Arity specifiers { + +#define ML99_cons_ARITY 2 +#define ML99_nil_ARITY 1 +#define ML99_isCons_ARITY 1 +#define ML99_isNil_ARITY 1 +#define ML99_listHead_ARITY 1 +#define ML99_listTail_ARITY 1 +#define ML99_listLast_ARITY 1 +#define ML99_listInit_ARITY 1 +#define ML99_list_ARITY 1 +#define ML99_listFromTuples_ARITY 2 +#define ML99_listFromSeq_ARITY 1 +#define ML99_listLen_ARITY 1 +#define ML99_listAppend_ARITY 2 +#define ML99_listAppendItem_ARITY 2 +#define ML99_listUnwrap_ARITY 1 +#define ML99_listUnwrapCommaSep_ARITY 1 +#define ML99_listReverse_ARITY 1 +#define ML99_listGet_ARITY 2 +#define ML99_listFoldr_ARITY 3 +#define ML99_listFoldl_ARITY 3 +#define ML99_listFoldl1_ARITY 2 +#define ML99_listIntersperse_ARITY 2 +#define ML99_listPrependToAll_ARITY 2 +#define ML99_listMap_ARITY 2 +#define ML99_listMapI_ARITY 2 +#define ML99_listMapInPlace_ARITY 2 +#define ML99_listMapInPlaceI_ARITY 2 +#define ML99_listFor_ARITY 2 +#define ML99_listMapInitLast_ARITY 3 +#define ML99_listForInitLast_ARITY 3 +#define ML99_listFilter_ARITY 2 +#define ML99_listFilterMap_ARITY 2 +#define ML99_listEq_ARITY 3 +#define ML99_listContains_ARITY 3 +#define ML99_listTake_ARITY 2 +#define ML99_listTakeWhile_ARITY 2 +#define ML99_listDrop_ARITY 2 +#define ML99_listDropWhile_ARITY 2 +#define ML99_listZip_ARITY 2 +#define ML99_listUnzip_ARITY 1 +#define ML99_listReplicate_ARITY 2 +#define ML99_listPartition_ARITY 2 +#define ML99_listAppl_ARITY 2 + +#define ML99_PRIV_listPartitionAux_ARITY 3 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_LIST_H diff --git a/test/external/metalang99/include/metalang99/logical.h b/test/external/metalang99/include/metalang99/logical.h new file mode 100644 index 0000000..9783944 --- /dev/null +++ b/test/external/metalang99/include/metalang99/logical.h @@ -0,0 +1,11 @@ +/** + * @file + * This module is deprecated and exists only for backwards compatibility. + */ + +#ifndef ML99_LOGICAL_H +#define ML99_LOGICAL_H + +#include <metalang99/bool.h> + +#endif // ML99_LOGICAL_H diff --git a/test/external/metalang99/include/metalang99/maybe.h b/test/external/metalang99/include/metalang99/maybe.h new file mode 100644 index 0000000..b51c4d2 --- /dev/null +++ b/test/external/metalang99/include/metalang99/maybe.h @@ -0,0 +1,143 @@ +/** + * @file + * An optional value. + */ + +#ifndef ML99_MAYBE_H +#define ML99_MAYBE_H + +#include <metalang99/priv/util.h> + +#include <metalang99/bool.h> +#include <metalang99/choice.h> +#include <metalang99/ident.h> + +/** + * Some value @p x. + */ +#define ML99_just(x) ML99_call(ML99_just, x) + +/** + * No value. + */ +#define ML99_nothing(...) ML99_callUneval(ML99_nothing, ) + +/** + * `ML99_true()` if @p maybe contains some value, otherwise `ML99_false()`. + * + * # Examples + * + * @code + * #include <metalang99/maybe.h> + * + * // 1 + * ML99_isJust(ML99_just(v(123))) + * + * // 0 + * ML99_isJust(ML99_nothing()) + * @endcode + */ +#define ML99_isJust(maybe) ML99_call(ML99_isJust, maybe) + +/** + * The inverse of #ML99_isJust. + * + * # Examples + * + * @code + * #include <metalang99/maybe.h> + * + * // 1 + * ML99_isNothing(ML99_nothing()) + * + * // 0 + * ML99_isNothing(ML99_just(v(123))) + * @endcode + */ +#define ML99_isNothing(maybe) ML99_call(ML99_isNothing, maybe) + +/** + * Tests @p maybe and @p other for equality. + * + * # Examples + * + * @code + * #include <metalang99/maybe.h> + * #include <metalang99/nat.h> + * + * // 1 + * ML99_maybeEq(v(ML99_natEq), ML99_just(v(123)), ML99_just(v(123))); + * + * // 0 + * ML99_maybeEq(v(ML99_natEq), ML99_just(v(4)), ML99_just(v(6))); + * + * // 0 + * ML99_maybeEq(v(ML99_natEq), ML99_just(v(4)), ML99_nothing()); + * @endcode + */ +#define ML99_maybeEq(cmp, maybe, other) ML99_call(ML99_maybeEq, cmp, maybe, other) + +/** + * Returns the contained value on `ML99_just(x)` or emits a fatal error on `ML99_nothing()`. + * + * # Examples + * + * @code + * #include <metalang99/maybe.h> + * + * // 123 + * ML99_maybeUnwrap(ML99_just(v(123))) + * + * // Emits a fatal error. + * ML99_maybeUnwrap(ML99_nothing()) + * @endcode + */ +#define ML99_maybeUnwrap(maybe) ML99_call(ML99_maybeUnwrap, maybe) + +#define ML99_JUST(x) ML99_CHOICE(just, x) +#define ML99_NOTHING(...) ML99_CHOICE(nothing, ~) +#define ML99_IS_JUST(maybe) ML99_PRIV_IS_JUST(maybe) +#define ML99_IS_NOTHING(maybe) ML99_NOT(ML99_IS_JUST(maybe)) + +#ifndef DOXYGEN_IGNORE + +#define ML99_just_IMPL(x) v(ML99_JUST(x)) +#define ML99_nothing_IMPL(...) v(ML99_NOTHING()) + +#define ML99_isJust_IMPL(maybe) v(ML99_IS_JUST(maybe)) +#define ML99_isNothing_IMPL(maybe) v(ML99_IS_NOTHING(maybe)) + +// ML99_maybeEq_IMPL { + +#define ML99_maybeEq_IMPL(cmp, maybe, other) \ + ML99_matchWithArgs_IMPL(maybe, ML99_PRIV_maybeEq_, cmp, other) + +#define ML99_PRIV_maybeEq_just_IMPL(x, cmp, other) \ + ML99_matchWithArgs_IMPL(other, ML99_PRIV_maybeEq_just_, cmp, x) +#define ML99_PRIV_maybeEq_nothing_IMPL(_, _cmp, other) v(ML99_IS_NOTHING(other)) + +#define ML99_PRIV_maybeEq_just_just_IMPL(y, cmp, x) ML99_appl2_IMPL(cmp, x, y) +#define ML99_PRIV_maybeEq_just_nothing_IMPL ML99_false_IMPL +// } (ML99_maybeEq_IMPL) + +#define ML99_maybeUnwrap_IMPL(maybe) ML99_match_IMPL(maybe, ML99_PRIV_maybeUnwrap_) +#define ML99_PRIV_maybeUnwrap_just_IMPL(x) v(x) +#define ML99_PRIV_maybeUnwrap_nothing_IMPL(_) \ + ML99_fatal(ML99_maybeUnwrap, expected ML99_just but found ML99_nothing) + +#define ML99_PRIV_IS_JUST(maybe) ML99_DETECT_IDENT(ML99_PRIV_IS_JUST_, ML99_CHOICE_TAG(maybe)) +#define ML99_PRIV_IS_JUST_just () + +// Arity specifiers { + +#define ML99_just_ARITY 1 +#define ML99_nothing_ARITY 1 +#define ML99_isJust_ARITY 1 +#define ML99_isNothing_ARITY 1 +#define ML99_maybeEq_ARITY 3 +#define ML99_maybeUnwrap_ARITY 1 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_MAYBE_H diff --git a/test/external/metalang99/include/metalang99/nat.h b/test/external/metalang99/include/metalang99/nat.h new file mode 100644 index 0000000..6c56076 --- /dev/null +++ b/test/external/metalang99/include/metalang99/nat.h @@ -0,0 +1,526 @@ +/** + * @file + * Natural numbers: [0; 255]. + * + * Most of the time, natural numbers are used for iteration; they are not meant for CPU-bound tasks + * such as Fibonacci numbers or factorials. + */ + +#ifndef ML99_NAT_H +#define ML99_NAT_H + +#include <metalang99/priv/bool.h> + +#include <metalang99/nat/dec.h> +#include <metalang99/nat/div.h> +#include <metalang99/nat/eq.h> +#include <metalang99/nat/inc.h> + +#include <metalang99/lang.h> + +/** + * \f$x + 1\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 6 + * ML99_inc(v(5)) + * @endcode + * + * @note If @p x is #ML99_NAT_MAX, the result is 0. + */ +#define ML99_inc(x) ML99_call(ML99_inc, x) + +/** + * \f$x - 1\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 4 + * ML99_dec(v(5)) + * @endcode + * + * @note If @p x is 0, the result is #ML99_NAT_MAX. + */ +#define ML99_dec(x) ML99_call(ML99_dec, x) + +/** + * Matches @p x against the two cases: if it is zero or positive. + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * #define MATCH_Z_IMPL() v(Billie) + * #define MATCH_S_IMPL(x) v(Jean ~ x) + * + * // Billie + * ML99_natMatch(v(0), v(MATCH_)) + * + * // Jean ~ 122 + * ML99_natMatch(v(123), v(MATCH_)) + * @endcode + * + * @note This function calls @p f with #ML99_call, so no partial application occurs, and so + * arity specifiers are not needed. + */ +#define ML99_natMatch(x, matcher) ML99_call(ML99_natMatch, x, matcher) + +/** + * The same as #ML99_natMatch but provides additional arguments to all branches. + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * #define MATCH_Z_IMPL(x, y, z) v(Billie ~ x y z) + * #define MATCH_S_IMPL(n, x, y, z) v(Jean ~ n ~ x y z) + * + * // Billie ~ 1 2 3 + * ML99_natMatchWithArgs(v(0), v(MATCH_), v(1, 2, 3)) + * + * // Jean ~ 122 ~ 1 2 3 + * ML99_natMatchWithArgs(v(123), v(MATCH_), v(1, 2, 3)) + * @endcode + */ +#define ML99_natMatchWithArgs(x, matcher, ...) \ + ML99_call(ML99_natMatchWithArgs, x, matcher, __VA_ARGS__) + +/** + * \f$x = y\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 1 + * ML99_natEq(v(5), v(5)) + * + * // 0 + * ML99_natEq(v(3), v(8)) + * @endcode + */ +#define ML99_natEq(x, y) ML99_call(ML99_natEq, x, y) + +/** + * \f$x \neq y\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 0 + * ML99_natNeq(v(5), v(5)) + * + * // 1 + * ML99_natNeq(v(3), v(8)) + * @endcode + */ +#define ML99_natNeq(x, y) ML99_call(ML99_natNeq, x, y) + +/** + * \f$x > y\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 1 + * ML99_greater(v(8), v(3)) + * + * // 0 + * ML99_greater(v(3), v(8)) + * @endcode + */ +#define ML99_greater(x, y) ML99_call(ML99_greater, x, y) + +/** + * \f$x \geq y\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 1 + * ML99_greaterEq(v(8), v(8)) + * + * // 0 + * ML99_greaterEq(v(3), v(8)) + * @endcode + */ +#define ML99_greaterEq(x, y) ML99_call(ML99_greaterEq, x, y) + +/** + * \f$x < y\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 1 + * ML99_lesser(v(3), v(8)) + * + * // 0 + * ML99_lesser(v(8), v(3)) + * @endcode + */ +#define ML99_lesser(x, y) ML99_call(ML99_lesser, x, y) + +/** + * \f$x \leq y\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 1 + * ML99_lesserEq(v(8), v(8)) + * + * // 0 + * ML99_lesserEq(v(8), v(3)) + * @endcode + */ +#define ML99_lesserEq(x, y) ML99_call(ML99_lesserEq, x, y) + +/** + * \f$x + y\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 11 + * ML99_add(v(5), v(6)) + * @endcode + */ +#define ML99_add(x, y) ML99_call(ML99_add, x, y) + +/** + * \f$x - y\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 6 + * ML99_sub(v(11), v(5)) + * @endcode + */ +#define ML99_sub(x, y) ML99_call(ML99_sub, x, y) + +/** + * \f$x * y\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 12 + * ML99_mul(v(3), v(4)) + * @endcode + */ +#define ML99_mul(x, y) ML99_call(ML99_mul, x, y) + +/** + * \f$\frac{x}{y}\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 3 + * ML99_div(v(12), v(4)) + * @endcode + * + * @note A compile-time error if \f$\frac{x}{y}\f$ is not a natural number. + */ +#define ML99_div(x, y) ML99_call(ML99_div, x, y) + +/** + * Like #ML99_div but returns `ML99_nothing()` is @p x is not divisible by @p y, + * otherwise `ML99_just(result)`. + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // ML99_just(3) + * ML99_divChecked(v(12), v(4)) + * + * // ML99_nothing() + * ML99_divChecked(v(14), v(5)) + * + * // ML99_nothing() + * ML99_divChecked(v(1), v(0)) + * @endcode + */ +#define ML99_divChecked(x, y) ML99_call(ML99_divChecked, x, y) + +/** + * Computes the remainder of division. + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 2 + * ML99_mod(v(8), v(3)) + * @endcode + * + * @note A compile-time error if @p y is 0. + */ +#define ML99_mod(x, y) ML99_call(ML99_mod, x, y) + +/** + * \f$x + y + z\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 15 + * ML99_add3(v(1), v(6), v(8)) + * @endcode + */ +#define ML99_add3(x, y, z) ML99_call(ML99_add3, x, y, z) + +/** + * \f$x - y - z\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 3 + * ML99_sub3(v(8), v(2), v(3)) + * @endcode + */ +#define ML99_sub3(x, y, z) ML99_call(ML99_sub3, x, y, z) + +/** + * \f$x * y * z\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 24 + * ML99_mul3(v(2), v(3), v(4)) + * @endcode + */ +#define ML99_mul3(x, y, z) ML99_call(ML99_mul3, x, y, z) + +/** + * \f$\frac{(\frac{x}{y})}{z}\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 5 + * ML99_div(v(30), v(3), v(2)) + * @endcode + * + * @note A compile-time error if \f$\frac{(\frac{x}{y})}{z}\f$ is not a natural number. + */ +#define ML99_div3(x, y, z) ML99_call(ML99_div3, x, y, z) + +/** + * \f$min(x, y)\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 5 + * ML99_min(v(5), v(7)) + * @endcode + */ +#define ML99_min(x, y) ML99_call(ML99_min, x, y) + +/** + * \f$max(x, y)\f$ + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * // 7 + * ML99_max(v(5), v(7)) + * @endcode + */ +#define ML99_max(x, y) ML99_call(ML99_max, x, y) + +/** + * Emits a fatal error if @p x is not a natural number, otherwise results in emptiness. + * + * # Examples + * + * @code + * #include <metalang99/nat.h> + * + * #define F_IMPL(x) ML99_TERMS(ML99_assertIsNat(v(x)), ML99_inc(v(x))) + * + * // 6 + * ML99_call(F, v(5)) + * + * // A compile-time number mismatch error. + * ML99_call(F, v(blah)) + * @endcode + */ +#define ML99_assertIsNat(x) ML99_call(ML99_assertIsNat, x) + +#define ML99_INC(x) ML99_PRIV_INC(x) +#define ML99_DEC(x) ML99_PRIV_DEC(x) +#define ML99_NAT_EQ(x, y) ML99_PRIV_NAT_EQ(x, y) +#define ML99_NAT_NEQ(x, y) ML99_PRIV_NOT(ML99_NAT_EQ(x, y)) +#define ML99_DIV_CHECKED(x, y) ML99_PRIV_DIV_CHECKED(x, y) + +/** + * The maximum value of a natural number, currently 255. + */ +#define ML99_NAT_MAX 255 + +#ifndef DOXYGEN_IGNORE + +// Pattern matching { + +#define ML99_natMatch_IMPL(x, matcher) \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(x, 0), \ + ML99_callUneval(matcher##Z, ), \ + ML99_callUneval(matcher##S, ML99_DEC(x))) + +#define ML99_natMatchWithArgs_IMPL(x, matcher, ...) \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(x, 0), \ + ML99_callUneval(matcher##Z, __VA_ARGS__), \ + ML99_callUneval(matcher##S, ML99_DEC(x), __VA_ARGS__)) +// } (Pattern matching) + +// Comparison operators { + +#define ML99_natEq_IMPL(x, y) v(ML99_NAT_EQ(x, y)) +#define ML99_natNeq_IMPL(x, y) v(ML99_NAT_NEQ(x, y)) + +#define ML99_lesser_IMPL(x, y) \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(y, 0), \ + v(ML99_PRIV_FALSE()), \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(x, ML99_DEC(y)), \ + v(ML99_PRIV_TRUE()), \ + ML99_callUneval(ML99_lesser, x, ML99_DEC(y)))) + +#define ML99_lesserEq_IMPL(x, y) ML99_greaterEq_IMPL(y, x) + +#define ML99_greater_IMPL(x, y) ML99_lesser_IMPL(y, x) +#define ML99_greaterEq_IMPL(x, y) \ + ML99_PRIV_IF(ML99_NAT_EQ(x, y), v(ML99_PRIV_TRUE()), ML99_greater_IMPL(x, y)) +// } (Comparison operators) + +// Arithmetical operators { + +#define ML99_inc_IMPL(x) v(ML99_INC(x)) +#define ML99_dec_IMPL(x) v(ML99_DEC(x)) + +#define ML99_add_IMPL(x, y) \ + ML99_PRIV_IF(ML99_NAT_EQ(y, 0), v(x), ML99_callUneval(ML99_add, ML99_INC(x), ML99_DEC(y))) +#define ML99_sub_IMPL(x, y) \ + ML99_PRIV_IF(ML99_NAT_EQ(y, 0), v(x), ML99_callUneval(ML99_sub, ML99_DEC(x), ML99_DEC(y))) +#define ML99_mul_IMPL(x, y) \ + ML99_PRIV_IF(ML99_NAT_EQ(y, 0), v(0), ML99_add(v(x), ML99_callUneval(ML99_mul, x, ML99_DEC(y)))) + +#define ML99_add3_IMPL(x, y, z) ML99_add(ML99_add_IMPL(x, y), v(z)) +#define ML99_sub3_IMPL(x, y, z) ML99_sub(ML99_sub_IMPL(x, y), v(z)) +#define ML99_mul3_IMPL(x, y, z) ML99_mul(ML99_mul_IMPL(x, y), v(z)) +#define ML99_div3_IMPL(x, y, z) ML99_div(ML99_div_IMPL(x, y), v(z)) + +#define ML99_min_IMPL(x, y) ML99_call(ML99_if, ML99_lesser_IMPL(x, y), v(x, y)) +#define ML99_max_IMPL(x, y) ML99_call(ML99_if, ML99_lesser_IMPL(x, y), v(y, x)) + +#define ML99_divChecked_IMPL(x, y) v(ML99_DIV_CHECKED(x, y)) + +// ML99_mod_IMPL { + +#define ML99_mod_IMPL(x, y) \ + ML99_PRIV_IF( \ + ML99_NAT_EQ(y, 0), \ + ML99_fatal(ML99_mod, modulo by 0), \ + ML99_PRIV_modAux_IMPL(x, y, 0)) + +#define ML99_PRIV_modAux_IMPL(x, y, acc) \ + ML99_PRIV_IF( \ + ML99_PRIV_OR(ML99_NAT_EQ(x, 0), ML99_IS_JUST(ML99_DIV_CHECKED(x, y))), \ + v(acc), \ + ML99_callUneval(ML99_PRIV_modAux, ML99_DEC(x), y, ML99_INC(acc))) +// } (ML99_mod_IMPL) + +// } (Arithmetical operators) + +#define ML99_assertIsNat_IMPL(x) \ + ML99_PRIV_IF( \ + ML99_PRIV_NAT_EQ(x, x), \ + v(ML99_PRIV_EMPTY()), \ + ML99_PRIV_ASSERT_IS_NAT_FATAL(x, ML99_NAT_MAX)) + +// clang-format off +#define ML99_PRIV_ASSERT_IS_NAT_FATAL(x, max) ML99_fatal(ML99_assertIsNat, x must be within [0; max]) +// clang-format on + +// Arity specifiers { + +#define ML99_inc_ARITY 1 +#define ML99_dec_ARITY 1 +#define ML99_natMatch_ARITY 2 +#define ML99_natMatchWithArgs_ARITY 3 +#define ML99_natEq_ARITY 2 +#define ML99_natNeq_ARITY 2 +#define ML99_greater_ARITY 2 +#define ML99_greaterEq_ARITY 2 +#define ML99_lesser_ARITY 2 +#define ML99_lesserEq_ARITY 2 +#define ML99_add_ARITY 2 +#define ML99_sub_ARITY 2 +#define ML99_mul_ARITY 2 +#define ML99_div_ARITY 2 +#define ML99_divChecked_ARITY 2 +#define ML99_mod_ARITY 2 +#define ML99_add3_ARITY 3 +#define ML99_sub3_ARITY 3 +#define ML99_mul3_ARITY 3 +#define ML99_div3_ARITY 3 +#define ML99_min_ARITY 2 +#define ML99_max_ARITY 2 +#define ML99_assertIsNat_ARITY 1 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_NAT_H diff --git a/test/external/metalang99/include/metalang99/nat/dec.h b/test/external/metalang99/include/metalang99/nat/dec.h new file mode 100644 index 0000000..f58dba8 --- /dev/null +++ b/test/external/metalang99/include/metalang99/nat/dec.h @@ -0,0 +1,264 @@ +#ifndef ML99_NAT_DEC_H +#define ML99_NAT_DEC_H + +#define ML99_PRIV_DEC(x) ML99_PRIV_DEC_AUX(x) +#define ML99_PRIV_DEC_AUX(x) ML99_PRIV_DEC_##x + +#define ML99_PRIV_DEC_0 255 +#define ML99_PRIV_DEC_1 0 +#define ML99_PRIV_DEC_2 1 +#define ML99_PRIV_DEC_3 2 +#define ML99_PRIV_DEC_4 3 +#define ML99_PRIV_DEC_5 4 +#define ML99_PRIV_DEC_6 5 +#define ML99_PRIV_DEC_7 6 +#define ML99_PRIV_DEC_8 7 +#define ML99_PRIV_DEC_9 8 +#define ML99_PRIV_DEC_10 9 +#define ML99_PRIV_DEC_11 10 +#define ML99_PRIV_DEC_12 11 +#define ML99_PRIV_DEC_13 12 +#define ML99_PRIV_DEC_14 13 +#define ML99_PRIV_DEC_15 14 +#define ML99_PRIV_DEC_16 15 +#define ML99_PRIV_DEC_17 16 +#define ML99_PRIV_DEC_18 17 +#define ML99_PRIV_DEC_19 18 +#define ML99_PRIV_DEC_20 19 +#define ML99_PRIV_DEC_21 20 +#define ML99_PRIV_DEC_22 21 +#define ML99_PRIV_DEC_23 22 +#define ML99_PRIV_DEC_24 23 +#define ML99_PRIV_DEC_25 24 +#define ML99_PRIV_DEC_26 25 +#define ML99_PRIV_DEC_27 26 +#define ML99_PRIV_DEC_28 27 +#define ML99_PRIV_DEC_29 28 +#define ML99_PRIV_DEC_30 29 +#define ML99_PRIV_DEC_31 30 +#define ML99_PRIV_DEC_32 31 +#define ML99_PRIV_DEC_33 32 +#define ML99_PRIV_DEC_34 33 +#define ML99_PRIV_DEC_35 34 +#define ML99_PRIV_DEC_36 35 +#define ML99_PRIV_DEC_37 36 +#define ML99_PRIV_DEC_38 37 +#define ML99_PRIV_DEC_39 38 +#define ML99_PRIV_DEC_40 39 +#define ML99_PRIV_DEC_41 40 +#define ML99_PRIV_DEC_42 41 +#define ML99_PRIV_DEC_43 42 +#define ML99_PRIV_DEC_44 43 +#define ML99_PRIV_DEC_45 44 +#define ML99_PRIV_DEC_46 45 +#define ML99_PRIV_DEC_47 46 +#define ML99_PRIV_DEC_48 47 +#define ML99_PRIV_DEC_49 48 +#define ML99_PRIV_DEC_50 49 +#define ML99_PRIV_DEC_51 50 +#define ML99_PRIV_DEC_52 51 +#define ML99_PRIV_DEC_53 52 +#define ML99_PRIV_DEC_54 53 +#define ML99_PRIV_DEC_55 54 +#define ML99_PRIV_DEC_56 55 +#define ML99_PRIV_DEC_57 56 +#define ML99_PRIV_DEC_58 57 +#define ML99_PRIV_DEC_59 58 +#define ML99_PRIV_DEC_60 59 +#define ML99_PRIV_DEC_61 60 +#define ML99_PRIV_DEC_62 61 +#define ML99_PRIV_DEC_63 62 +#define ML99_PRIV_DEC_64 63 +#define ML99_PRIV_DEC_65 64 +#define ML99_PRIV_DEC_66 65 +#define ML99_PRIV_DEC_67 66 +#define ML99_PRIV_DEC_68 67 +#define ML99_PRIV_DEC_69 68 +#define ML99_PRIV_DEC_70 69 +#define ML99_PRIV_DEC_71 70 +#define ML99_PRIV_DEC_72 71 +#define ML99_PRIV_DEC_73 72 +#define ML99_PRIV_DEC_74 73 +#define ML99_PRIV_DEC_75 74 +#define ML99_PRIV_DEC_76 75 +#define ML99_PRIV_DEC_77 76 +#define ML99_PRIV_DEC_78 77 +#define ML99_PRIV_DEC_79 78 +#define ML99_PRIV_DEC_80 79 +#define ML99_PRIV_DEC_81 80 +#define ML99_PRIV_DEC_82 81 +#define ML99_PRIV_DEC_83 82 +#define ML99_PRIV_DEC_84 83 +#define ML99_PRIV_DEC_85 84 +#define ML99_PRIV_DEC_86 85 +#define ML99_PRIV_DEC_87 86 +#define ML99_PRIV_DEC_88 87 +#define ML99_PRIV_DEC_89 88 +#define ML99_PRIV_DEC_90 89 +#define ML99_PRIV_DEC_91 90 +#define ML99_PRIV_DEC_92 91 +#define ML99_PRIV_DEC_93 92 +#define ML99_PRIV_DEC_94 93 +#define ML99_PRIV_DEC_95 94 +#define ML99_PRIV_DEC_96 95 +#define ML99_PRIV_DEC_97 96 +#define ML99_PRIV_DEC_98 97 +#define ML99_PRIV_DEC_99 98 +#define ML99_PRIV_DEC_100 99 +#define ML99_PRIV_DEC_101 100 +#define ML99_PRIV_DEC_102 101 +#define ML99_PRIV_DEC_103 102 +#define ML99_PRIV_DEC_104 103 +#define ML99_PRIV_DEC_105 104 +#define ML99_PRIV_DEC_106 105 +#define ML99_PRIV_DEC_107 106 +#define ML99_PRIV_DEC_108 107 +#define ML99_PRIV_DEC_109 108 +#define ML99_PRIV_DEC_110 109 +#define ML99_PRIV_DEC_111 110 +#define ML99_PRIV_DEC_112 111 +#define ML99_PRIV_DEC_113 112 +#define ML99_PRIV_DEC_114 113 +#define ML99_PRIV_DEC_115 114 +#define ML99_PRIV_DEC_116 115 +#define ML99_PRIV_DEC_117 116 +#define ML99_PRIV_DEC_118 117 +#define ML99_PRIV_DEC_119 118 +#define ML99_PRIV_DEC_120 119 +#define ML99_PRIV_DEC_121 120 +#define ML99_PRIV_DEC_122 121 +#define ML99_PRIV_DEC_123 122 +#define ML99_PRIV_DEC_124 123 +#define ML99_PRIV_DEC_125 124 +#define ML99_PRIV_DEC_126 125 +#define ML99_PRIV_DEC_127 126 +#define ML99_PRIV_DEC_128 127 +#define ML99_PRIV_DEC_129 128 +#define ML99_PRIV_DEC_130 129 +#define ML99_PRIV_DEC_131 130 +#define ML99_PRIV_DEC_132 131 +#define ML99_PRIV_DEC_133 132 +#define ML99_PRIV_DEC_134 133 +#define ML99_PRIV_DEC_135 134 +#define ML99_PRIV_DEC_136 135 +#define ML99_PRIV_DEC_137 136 +#define ML99_PRIV_DEC_138 137 +#define ML99_PRIV_DEC_139 138 +#define ML99_PRIV_DEC_140 139 +#define ML99_PRIV_DEC_141 140 +#define ML99_PRIV_DEC_142 141 +#define ML99_PRIV_DEC_143 142 +#define ML99_PRIV_DEC_144 143 +#define ML99_PRIV_DEC_145 144 +#define ML99_PRIV_DEC_146 145 +#define ML99_PRIV_DEC_147 146 +#define ML99_PRIV_DEC_148 147 +#define ML99_PRIV_DEC_149 148 +#define ML99_PRIV_DEC_150 149 +#define ML99_PRIV_DEC_151 150 +#define ML99_PRIV_DEC_152 151 +#define ML99_PRIV_DEC_153 152 +#define ML99_PRIV_DEC_154 153 +#define ML99_PRIV_DEC_155 154 +#define ML99_PRIV_DEC_156 155 +#define ML99_PRIV_DEC_157 156 +#define ML99_PRIV_DEC_158 157 +#define ML99_PRIV_DEC_159 158 +#define ML99_PRIV_DEC_160 159 +#define ML99_PRIV_DEC_161 160 +#define ML99_PRIV_DEC_162 161 +#define ML99_PRIV_DEC_163 162 +#define ML99_PRIV_DEC_164 163 +#define ML99_PRIV_DEC_165 164 +#define ML99_PRIV_DEC_166 165 +#define ML99_PRIV_DEC_167 166 +#define ML99_PRIV_DEC_168 167 +#define ML99_PRIV_DEC_169 168 +#define ML99_PRIV_DEC_170 169 +#define ML99_PRIV_DEC_171 170 +#define ML99_PRIV_DEC_172 171 +#define ML99_PRIV_DEC_173 172 +#define ML99_PRIV_DEC_174 173 +#define ML99_PRIV_DEC_175 174 +#define ML99_PRIV_DEC_176 175 +#define ML99_PRIV_DEC_177 176 +#define ML99_PRIV_DEC_178 177 +#define ML99_PRIV_DEC_179 178 +#define ML99_PRIV_DEC_180 179 +#define ML99_PRIV_DEC_181 180 +#define ML99_PRIV_DEC_182 181 +#define ML99_PRIV_DEC_183 182 +#define ML99_PRIV_DEC_184 183 +#define ML99_PRIV_DEC_185 184 +#define ML99_PRIV_DEC_186 185 +#define ML99_PRIV_DEC_187 186 +#define ML99_PRIV_DEC_188 187 +#define ML99_PRIV_DEC_189 188 +#define ML99_PRIV_DEC_190 189 +#define ML99_PRIV_DEC_191 190 +#define ML99_PRIV_DEC_192 191 +#define ML99_PRIV_DEC_193 192 +#define ML99_PRIV_DEC_194 193 +#define ML99_PRIV_DEC_195 194 +#define ML99_PRIV_DEC_196 195 +#define ML99_PRIV_DEC_197 196 +#define ML99_PRIV_DEC_198 197 +#define ML99_PRIV_DEC_199 198 +#define ML99_PRIV_DEC_200 199 +#define ML99_PRIV_DEC_201 200 +#define ML99_PRIV_DEC_202 201 +#define ML99_PRIV_DEC_203 202 +#define ML99_PRIV_DEC_204 203 +#define ML99_PRIV_DEC_205 204 +#define ML99_PRIV_DEC_206 205 +#define ML99_PRIV_DEC_207 206 +#define ML99_PRIV_DEC_208 207 +#define ML99_PRIV_DEC_209 208 +#define ML99_PRIV_DEC_210 209 +#define ML99_PRIV_DEC_211 210 +#define ML99_PRIV_DEC_212 211 +#define ML99_PRIV_DEC_213 212 +#define ML99_PRIV_DEC_214 213 +#define ML99_PRIV_DEC_215 214 +#define ML99_PRIV_DEC_216 215 +#define ML99_PRIV_DEC_217 216 +#define ML99_PRIV_DEC_218 217 +#define ML99_PRIV_DEC_219 218 +#define ML99_PRIV_DEC_220 219 +#define ML99_PRIV_DEC_221 220 +#define ML99_PRIV_DEC_222 221 +#define ML99_PRIV_DEC_223 222 +#define ML99_PRIV_DEC_224 223 +#define ML99_PRIV_DEC_225 224 +#define ML99_PRIV_DEC_226 225 +#define ML99_PRIV_DEC_227 226 +#define ML99_PRIV_DEC_228 227 +#define ML99_PRIV_DEC_229 228 +#define ML99_PRIV_DEC_230 229 +#define ML99_PRIV_DEC_231 230 +#define ML99_PRIV_DEC_232 231 +#define ML99_PRIV_DEC_233 232 +#define ML99_PRIV_DEC_234 233 +#define ML99_PRIV_DEC_235 234 +#define ML99_PRIV_DEC_236 235 +#define ML99_PRIV_DEC_237 236 +#define ML99_PRIV_DEC_238 237 +#define ML99_PRIV_DEC_239 238 +#define ML99_PRIV_DEC_240 239 +#define ML99_PRIV_DEC_241 240 +#define ML99_PRIV_DEC_242 241 +#define ML99_PRIV_DEC_243 242 +#define ML99_PRIV_DEC_244 243 +#define ML99_PRIV_DEC_245 244 +#define ML99_PRIV_DEC_246 245 +#define ML99_PRIV_DEC_247 246 +#define ML99_PRIV_DEC_248 247 +#define ML99_PRIV_DEC_249 248 +#define ML99_PRIV_DEC_250 249 +#define ML99_PRIV_DEC_251 250 +#define ML99_PRIV_DEC_252 251 +#define ML99_PRIV_DEC_253 252 +#define ML99_PRIV_DEC_254 253 +#define ML99_PRIV_DEC_255 254 + +#endif // ML99_NAT_DEC_H diff --git a/test/external/metalang99/include/metalang99/nat/div.h b/test/external/metalang99/include/metalang99/nat/div.h new file mode 100644 index 0000000..ebd0b13 --- /dev/null +++ b/test/external/metalang99/include/metalang99/nat/div.h @@ -0,0 +1,1172 @@ +#ifndef ML99_NAT_DIV_H +#define ML99_NAT_DIV_H + +#include <metalang99/priv/bool.h> +#include <metalang99/priv/util.h> + +#include <metalang99/maybe.h> +#include <metalang99/tuple.h> + +#define ML99_div_IMPL(x, y) \ + ML99_matchWithArgs_IMPL(ML99_PRIV_DIV_CHECKED(x, y), ML99_PRIV_DIV_, x, y) +#define ML99_PRIV_DIV_nothing_IMPL(_, x, y) ML99_fatal(ML99_div, x is not divisible by y) +#define ML99_PRIV_DIV_just_IMPL(n, _x, _y) v(n) + +#define ML99_PRIV_DIV_CHECKED(x, y) \ + ML99_PRIV_IF( \ + ML99_PRIV_NAT_EQ(y, 1), \ + ML99_JUST(x), \ + ML99_PRIV_IF( \ + ML99_PRIV_NAT_EQ(x, y), \ + ML99_JUST(1), \ + ML99_UNTUPLE(ML99_PRIV_SND(ML99_PRIV_DIV_##x##_##y, (ML99_NOTHING()))))) + +#define ML99_PRIV_DIV_4_2 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_6_2 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_6_3 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_8_2 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_8_4 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_9_3 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_10_2 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_10_5 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_12_2 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_12_3 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_12_4 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_12_6 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_14_2 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_14_7 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_15_3 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_15_5 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_16_2 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_16_4 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_16_8 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_18_2 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_18_3 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_18_6 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_18_9 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_20_2 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_20_4 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_20_5 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_20_10 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_21_3 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_21_7 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_22_2 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_22_11 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_24_2 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_24_3 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_24_4 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_24_6 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_24_8 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_24_12 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_25_5 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_26_2 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_26_13 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_27_3 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_27_9 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_28_2 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_28_4 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_28_7 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_28_14 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_30_2 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_30_3 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_30_5 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_30_6 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_30_10 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_30_15 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_32_2 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_32_4 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_32_8 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_32_16 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_33_3 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_33_11 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_34_2 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_34_17 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_35_5 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_35_7 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_36_2 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_36_3 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_36_4 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_36_6 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_36_9 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_36_12 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_36_18 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_38_2 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_38_19 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_39_3 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_39_13 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_40_2 ~, (ML99_JUST(20)) +#define ML99_PRIV_DIV_40_4 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_40_5 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_40_8 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_40_10 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_40_20 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_42_2 ~, (ML99_JUST(21)) +#define ML99_PRIV_DIV_42_3 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_42_6 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_42_7 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_42_14 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_42_21 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_44_2 ~, (ML99_JUST(22)) +#define ML99_PRIV_DIV_44_4 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_44_11 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_44_22 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_45_3 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_45_5 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_45_9 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_45_15 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_46_2 ~, (ML99_JUST(23)) +#define ML99_PRIV_DIV_46_23 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_48_2 ~, (ML99_JUST(24)) +#define ML99_PRIV_DIV_48_3 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_48_4 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_48_6 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_48_8 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_48_12 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_48_16 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_48_24 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_49_7 ~, (ML99_JUST(7)) + +#define ML99_PRIV_DIV_50_2 ~, (ML99_JUST(25)) +#define ML99_PRIV_DIV_50_5 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_50_10 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_50_25 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_51_3 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_51_17 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_52_2 ~, (ML99_JUST(26)) +#define ML99_PRIV_DIV_52_4 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_52_13 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_52_26 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_54_2 ~, (ML99_JUST(27)) +#define ML99_PRIV_DIV_54_3 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_54_6 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_54_9 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_54_18 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_54_27 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_55_5 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_55_11 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_56_2 ~, (ML99_JUST(28)) +#define ML99_PRIV_DIV_56_4 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_56_7 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_56_8 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_56_14 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_56_28 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_57_3 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_57_19 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_58_2 ~, (ML99_JUST(29)) +#define ML99_PRIV_DIV_58_29 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_60_2 ~, (ML99_JUST(30)) +#define ML99_PRIV_DIV_60_3 ~, (ML99_JUST(20)) +#define ML99_PRIV_DIV_60_4 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_60_5 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_60_6 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_60_10 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_60_12 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_60_15 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_60_20 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_60_30 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_62_2 ~, (ML99_JUST(31)) +#define ML99_PRIV_DIV_62_31 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_63_3 ~, (ML99_JUST(21)) +#define ML99_PRIV_DIV_63_7 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_63_9 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_63_21 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_64_2 ~, (ML99_JUST(32)) +#define ML99_PRIV_DIV_64_4 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_64_8 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_64_16 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_64_32 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_65_5 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_65_13 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_66_2 ~, (ML99_JUST(33)) +#define ML99_PRIV_DIV_66_3 ~, (ML99_JUST(22)) +#define ML99_PRIV_DIV_66_6 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_66_11 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_66_22 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_66_33 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_68_2 ~, (ML99_JUST(34)) +#define ML99_PRIV_DIV_68_4 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_68_17 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_68_34 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_69_3 ~, (ML99_JUST(23)) +#define ML99_PRIV_DIV_69_23 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_70_2 ~, (ML99_JUST(35)) +#define ML99_PRIV_DIV_70_5 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_70_7 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_70_10 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_70_14 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_70_35 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_72_2 ~, (ML99_JUST(36)) +#define ML99_PRIV_DIV_72_3 ~, (ML99_JUST(24)) +#define ML99_PRIV_DIV_72_4 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_72_6 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_72_8 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_72_9 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_72_12 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_72_18 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_72_24 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_72_36 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_74_2 ~, (ML99_JUST(37)) +#define ML99_PRIV_DIV_74_37 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_75_3 ~, (ML99_JUST(25)) +#define ML99_PRIV_DIV_75_5 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_75_15 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_75_25 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_76_2 ~, (ML99_JUST(38)) +#define ML99_PRIV_DIV_76_4 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_76_19 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_76_38 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_77_7 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_77_11 ~, (ML99_JUST(7)) + +#define ML99_PRIV_DIV_78_2 ~, (ML99_JUST(39)) +#define ML99_PRIV_DIV_78_3 ~, (ML99_JUST(26)) +#define ML99_PRIV_DIV_78_6 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_78_13 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_78_26 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_78_39 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_80_2 ~, (ML99_JUST(40)) +#define ML99_PRIV_DIV_80_4 ~, (ML99_JUST(20)) +#define ML99_PRIV_DIV_80_5 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_80_8 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_80_10 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_80_16 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_80_20 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_80_40 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_81_3 ~, (ML99_JUST(27)) +#define ML99_PRIV_DIV_81_9 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_81_27 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_82_2 ~, (ML99_JUST(41)) +#define ML99_PRIV_DIV_82_41 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_84_2 ~, (ML99_JUST(42)) +#define ML99_PRIV_DIV_84_3 ~, (ML99_JUST(28)) +#define ML99_PRIV_DIV_84_4 ~, (ML99_JUST(21)) +#define ML99_PRIV_DIV_84_6 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_84_7 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_84_12 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_84_14 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_84_21 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_84_28 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_84_42 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_85_5 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_85_17 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_86_2 ~, (ML99_JUST(43)) +#define ML99_PRIV_DIV_86_43 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_87_3 ~, (ML99_JUST(29)) +#define ML99_PRIV_DIV_87_29 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_88_2 ~, (ML99_JUST(44)) +#define ML99_PRIV_DIV_88_4 ~, (ML99_JUST(22)) +#define ML99_PRIV_DIV_88_8 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_88_11 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_88_22 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_88_44 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_90_2 ~, (ML99_JUST(45)) +#define ML99_PRIV_DIV_90_3 ~, (ML99_JUST(30)) +#define ML99_PRIV_DIV_90_5 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_90_6 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_90_9 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_90_10 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_90_15 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_90_18 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_90_30 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_90_45 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_91_7 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_91_13 ~, (ML99_JUST(7)) + +#define ML99_PRIV_DIV_92_2 ~, (ML99_JUST(46)) +#define ML99_PRIV_DIV_92_4 ~, (ML99_JUST(23)) +#define ML99_PRIV_DIV_92_23 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_92_46 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_93_3 ~, (ML99_JUST(31)) +#define ML99_PRIV_DIV_93_31 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_94_2 ~, (ML99_JUST(47)) +#define ML99_PRIV_DIV_94_47 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_95_5 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_95_19 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_96_2 ~, (ML99_JUST(48)) +#define ML99_PRIV_DIV_96_3 ~, (ML99_JUST(32)) +#define ML99_PRIV_DIV_96_4 ~, (ML99_JUST(24)) +#define ML99_PRIV_DIV_96_6 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_96_8 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_96_12 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_96_16 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_96_24 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_96_32 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_96_48 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_98_2 ~, (ML99_JUST(49)) +#define ML99_PRIV_DIV_98_7 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_98_14 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_98_49 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_99_3 ~, (ML99_JUST(33)) +#define ML99_PRIV_DIV_99_9 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_99_11 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_99_33 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_100_2 ~, (ML99_JUST(50)) +#define ML99_PRIV_DIV_100_4 ~, (ML99_JUST(25)) +#define ML99_PRIV_DIV_100_5 ~, (ML99_JUST(20)) +#define ML99_PRIV_DIV_100_10 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_100_20 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_100_25 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_100_50 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_102_2 ~, (ML99_JUST(51)) +#define ML99_PRIV_DIV_102_3 ~, (ML99_JUST(34)) +#define ML99_PRIV_DIV_102_6 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_102_17 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_102_34 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_102_51 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_104_2 ~, (ML99_JUST(52)) +#define ML99_PRIV_DIV_104_4 ~, (ML99_JUST(26)) +#define ML99_PRIV_DIV_104_8 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_104_13 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_104_26 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_104_52 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_105_3 ~, (ML99_JUST(35)) +#define ML99_PRIV_DIV_105_5 ~, (ML99_JUST(21)) +#define ML99_PRIV_DIV_105_7 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_105_15 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_105_21 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_105_35 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_106_2 ~, (ML99_JUST(53)) +#define ML99_PRIV_DIV_106_53 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_108_2 ~, (ML99_JUST(54)) +#define ML99_PRIV_DIV_108_3 ~, (ML99_JUST(36)) +#define ML99_PRIV_DIV_108_4 ~, (ML99_JUST(27)) +#define ML99_PRIV_DIV_108_6 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_108_9 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_108_12 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_108_18 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_108_27 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_108_36 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_108_54 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_110_2 ~, (ML99_JUST(55)) +#define ML99_PRIV_DIV_110_5 ~, (ML99_JUST(22)) +#define ML99_PRIV_DIV_110_10 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_110_11 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_110_22 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_110_55 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_111_3 ~, (ML99_JUST(37)) +#define ML99_PRIV_DIV_111_37 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_112_2 ~, (ML99_JUST(56)) +#define ML99_PRIV_DIV_112_4 ~, (ML99_JUST(28)) +#define ML99_PRIV_DIV_112_7 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_112_8 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_112_14 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_112_16 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_112_28 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_112_56 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_114_2 ~, (ML99_JUST(57)) +#define ML99_PRIV_DIV_114_3 ~, (ML99_JUST(38)) +#define ML99_PRIV_DIV_114_6 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_114_19 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_114_38 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_114_57 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_115_5 ~, (ML99_JUST(23)) +#define ML99_PRIV_DIV_115_23 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_116_2 ~, (ML99_JUST(58)) +#define ML99_PRIV_DIV_116_4 ~, (ML99_JUST(29)) +#define ML99_PRIV_DIV_116_29 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_116_58 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_117_3 ~, (ML99_JUST(39)) +#define ML99_PRIV_DIV_117_9 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_117_13 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_117_39 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_118_2 ~, (ML99_JUST(59)) +#define ML99_PRIV_DIV_118_59 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_119_7 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_119_17 ~, (ML99_JUST(7)) + +#define ML99_PRIV_DIV_120_2 ~, (ML99_JUST(60)) +#define ML99_PRIV_DIV_120_3 ~, (ML99_JUST(40)) +#define ML99_PRIV_DIV_120_4 ~, (ML99_JUST(30)) +#define ML99_PRIV_DIV_120_5 ~, (ML99_JUST(24)) +#define ML99_PRIV_DIV_120_6 ~, (ML99_JUST(20)) +#define ML99_PRIV_DIV_120_8 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_120_10 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_120_12 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_120_15 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_120_20 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_120_24 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_120_30 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_120_40 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_120_60 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_121_11 ~, (ML99_JUST(11)) + +#define ML99_PRIV_DIV_122_2 ~, (ML99_JUST(61)) +#define ML99_PRIV_DIV_122_61 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_123_3 ~, (ML99_JUST(41)) +#define ML99_PRIV_DIV_123_41 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_124_2 ~, (ML99_JUST(62)) +#define ML99_PRIV_DIV_124_4 ~, (ML99_JUST(31)) +#define ML99_PRIV_DIV_124_31 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_124_62 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_125_5 ~, (ML99_JUST(25)) +#define ML99_PRIV_DIV_125_25 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_126_2 ~, (ML99_JUST(63)) +#define ML99_PRIV_DIV_126_3 ~, (ML99_JUST(42)) +#define ML99_PRIV_DIV_126_6 ~, (ML99_JUST(21)) +#define ML99_PRIV_DIV_126_7 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_126_9 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_126_14 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_126_18 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_126_21 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_126_42 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_126_63 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_128_2 ~, (ML99_JUST(64)) +#define ML99_PRIV_DIV_128_4 ~, (ML99_JUST(32)) +#define ML99_PRIV_DIV_128_8 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_128_16 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_128_32 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_128_64 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_129_3 ~, (ML99_JUST(43)) +#define ML99_PRIV_DIV_129_43 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_130_2 ~, (ML99_JUST(65)) +#define ML99_PRIV_DIV_130_5 ~, (ML99_JUST(26)) +#define ML99_PRIV_DIV_130_10 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_130_13 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_130_26 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_130_65 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_132_2 ~, (ML99_JUST(66)) +#define ML99_PRIV_DIV_132_3 ~, (ML99_JUST(44)) +#define ML99_PRIV_DIV_132_4 ~, (ML99_JUST(33)) +#define ML99_PRIV_DIV_132_6 ~, (ML99_JUST(22)) +#define ML99_PRIV_DIV_132_11 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_132_12 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_132_22 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_132_33 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_132_44 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_132_66 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_133_7 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_133_19 ~, (ML99_JUST(7)) + +#define ML99_PRIV_DIV_134_2 ~, (ML99_JUST(67)) +#define ML99_PRIV_DIV_134_67 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_135_3 ~, (ML99_JUST(45)) +#define ML99_PRIV_DIV_135_5 ~, (ML99_JUST(27)) +#define ML99_PRIV_DIV_135_9 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_135_15 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_135_27 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_135_45 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_136_2 ~, (ML99_JUST(68)) +#define ML99_PRIV_DIV_136_4 ~, (ML99_JUST(34)) +#define ML99_PRIV_DIV_136_8 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_136_17 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_136_34 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_136_68 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_138_2 ~, (ML99_JUST(69)) +#define ML99_PRIV_DIV_138_3 ~, (ML99_JUST(46)) +#define ML99_PRIV_DIV_138_6 ~, (ML99_JUST(23)) +#define ML99_PRIV_DIV_138_23 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_138_46 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_138_69 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_140_2 ~, (ML99_JUST(70)) +#define ML99_PRIV_DIV_140_4 ~, (ML99_JUST(35)) +#define ML99_PRIV_DIV_140_5 ~, (ML99_JUST(28)) +#define ML99_PRIV_DIV_140_7 ~, (ML99_JUST(20)) +#define ML99_PRIV_DIV_140_10 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_140_14 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_140_20 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_140_28 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_140_35 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_140_70 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_141_3 ~, (ML99_JUST(47)) +#define ML99_PRIV_DIV_141_47 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_142_2 ~, (ML99_JUST(71)) +#define ML99_PRIV_DIV_142_71 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_143_11 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_143_13 ~, (ML99_JUST(11)) + +#define ML99_PRIV_DIV_144_2 ~, (ML99_JUST(72)) +#define ML99_PRIV_DIV_144_3 ~, (ML99_JUST(48)) +#define ML99_PRIV_DIV_144_4 ~, (ML99_JUST(36)) +#define ML99_PRIV_DIV_144_6 ~, (ML99_JUST(24)) +#define ML99_PRIV_DIV_144_8 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_144_9 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_144_12 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_144_16 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_144_18 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_144_24 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_144_36 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_144_48 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_144_72 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_145_5 ~, (ML99_JUST(29)) +#define ML99_PRIV_DIV_145_29 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_146_2 ~, (ML99_JUST(73)) +#define ML99_PRIV_DIV_146_73 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_147_3 ~, (ML99_JUST(49)) +#define ML99_PRIV_DIV_147_7 ~, (ML99_JUST(21)) +#define ML99_PRIV_DIV_147_21 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_147_49 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_148_2 ~, (ML99_JUST(74)) +#define ML99_PRIV_DIV_148_4 ~, (ML99_JUST(37)) +#define ML99_PRIV_DIV_148_37 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_148_74 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_150_2 ~, (ML99_JUST(75)) +#define ML99_PRIV_DIV_150_3 ~, (ML99_JUST(50)) +#define ML99_PRIV_DIV_150_5 ~, (ML99_JUST(30)) +#define ML99_PRIV_DIV_150_6 ~, (ML99_JUST(25)) +#define ML99_PRIV_DIV_150_10 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_150_15 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_150_25 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_150_30 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_150_50 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_150_75 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_152_2 ~, (ML99_JUST(76)) +#define ML99_PRIV_DIV_152_4 ~, (ML99_JUST(38)) +#define ML99_PRIV_DIV_152_8 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_152_19 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_152_38 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_152_76 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_153_3 ~, (ML99_JUST(51)) +#define ML99_PRIV_DIV_153_9 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_153_17 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_153_51 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_154_2 ~, (ML99_JUST(77)) +#define ML99_PRIV_DIV_154_7 ~, (ML99_JUST(22)) +#define ML99_PRIV_DIV_154_11 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_154_14 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_154_22 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_154_77 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_155_5 ~, (ML99_JUST(31)) +#define ML99_PRIV_DIV_155_31 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_156_2 ~, (ML99_JUST(78)) +#define ML99_PRIV_DIV_156_3 ~, (ML99_JUST(52)) +#define ML99_PRIV_DIV_156_4 ~, (ML99_JUST(39)) +#define ML99_PRIV_DIV_156_6 ~, (ML99_JUST(26)) +#define ML99_PRIV_DIV_156_12 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_156_13 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_156_26 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_156_39 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_156_52 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_156_78 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_158_2 ~, (ML99_JUST(79)) +#define ML99_PRIV_DIV_158_79 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_159_3 ~, (ML99_JUST(53)) +#define ML99_PRIV_DIV_159_53 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_160_2 ~, (ML99_JUST(80)) +#define ML99_PRIV_DIV_160_4 ~, (ML99_JUST(40)) +#define ML99_PRIV_DIV_160_5 ~, (ML99_JUST(32)) +#define ML99_PRIV_DIV_160_8 ~, (ML99_JUST(20)) +#define ML99_PRIV_DIV_160_10 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_160_16 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_160_20 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_160_32 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_160_40 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_160_80 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_161_7 ~, (ML99_JUST(23)) +#define ML99_PRIV_DIV_161_23 ~, (ML99_JUST(7)) + +#define ML99_PRIV_DIV_162_2 ~, (ML99_JUST(81)) +#define ML99_PRIV_DIV_162_3 ~, (ML99_JUST(54)) +#define ML99_PRIV_DIV_162_6 ~, (ML99_JUST(27)) +#define ML99_PRIV_DIV_162_9 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_162_18 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_162_27 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_162_54 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_162_81 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_164_2 ~, (ML99_JUST(82)) +#define ML99_PRIV_DIV_164_4 ~, (ML99_JUST(41)) +#define ML99_PRIV_DIV_164_41 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_164_82 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_165_3 ~, (ML99_JUST(55)) +#define ML99_PRIV_DIV_165_5 ~, (ML99_JUST(33)) +#define ML99_PRIV_DIV_165_11 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_165_15 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_165_33 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_165_55 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_166_2 ~, (ML99_JUST(83)) +#define ML99_PRIV_DIV_166_83 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_168_2 ~, (ML99_JUST(84)) +#define ML99_PRIV_DIV_168_3 ~, (ML99_JUST(56)) +#define ML99_PRIV_DIV_168_4 ~, (ML99_JUST(42)) +#define ML99_PRIV_DIV_168_6 ~, (ML99_JUST(28)) +#define ML99_PRIV_DIV_168_7 ~, (ML99_JUST(24)) +#define ML99_PRIV_DIV_168_8 ~, (ML99_JUST(21)) +#define ML99_PRIV_DIV_168_12 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_168_14 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_168_21 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_168_24 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_168_28 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_168_42 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_168_56 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_168_84 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_169_13 ~, (ML99_JUST(13)) + +#define ML99_PRIV_DIV_170_2 ~, (ML99_JUST(85)) +#define ML99_PRIV_DIV_170_5 ~, (ML99_JUST(34)) +#define ML99_PRIV_DIV_170_10 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_170_17 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_170_34 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_170_85 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_171_3 ~, (ML99_JUST(57)) +#define ML99_PRIV_DIV_171_9 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_171_19 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_171_57 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_172_2 ~, (ML99_JUST(86)) +#define ML99_PRIV_DIV_172_4 ~, (ML99_JUST(43)) +#define ML99_PRIV_DIV_172_43 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_172_86 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_174_2 ~, (ML99_JUST(87)) +#define ML99_PRIV_DIV_174_3 ~, (ML99_JUST(58)) +#define ML99_PRIV_DIV_174_6 ~, (ML99_JUST(29)) +#define ML99_PRIV_DIV_174_29 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_174_58 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_174_87 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_175_5 ~, (ML99_JUST(35)) +#define ML99_PRIV_DIV_175_7 ~, (ML99_JUST(25)) +#define ML99_PRIV_DIV_175_25 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_175_35 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_176_2 ~, (ML99_JUST(88)) +#define ML99_PRIV_DIV_176_4 ~, (ML99_JUST(44)) +#define ML99_PRIV_DIV_176_8 ~, (ML99_JUST(22)) +#define ML99_PRIV_DIV_176_11 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_176_16 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_176_22 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_176_44 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_176_88 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_177_3 ~, (ML99_JUST(59)) +#define ML99_PRIV_DIV_177_59 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_178_2 ~, (ML99_JUST(89)) +#define ML99_PRIV_DIV_178_89 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_180_2 ~, (ML99_JUST(90)) +#define ML99_PRIV_DIV_180_3 ~, (ML99_JUST(60)) +#define ML99_PRIV_DIV_180_4 ~, (ML99_JUST(45)) +#define ML99_PRIV_DIV_180_5 ~, (ML99_JUST(36)) +#define ML99_PRIV_DIV_180_6 ~, (ML99_JUST(30)) +#define ML99_PRIV_DIV_180_9 ~, (ML99_JUST(20)) +#define ML99_PRIV_DIV_180_10 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_180_12 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_180_15 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_180_18 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_180_20 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_180_30 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_180_36 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_180_45 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_180_60 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_180_90 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_182_2 ~, (ML99_JUST(91)) +#define ML99_PRIV_DIV_182_7 ~, (ML99_JUST(26)) +#define ML99_PRIV_DIV_182_13 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_182_14 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_182_26 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_182_91 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_183_3 ~, (ML99_JUST(61)) +#define ML99_PRIV_DIV_183_61 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_184_2 ~, (ML99_JUST(92)) +#define ML99_PRIV_DIV_184_4 ~, (ML99_JUST(46)) +#define ML99_PRIV_DIV_184_8 ~, (ML99_JUST(23)) +#define ML99_PRIV_DIV_184_23 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_184_46 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_184_92 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_185_5 ~, (ML99_JUST(37)) +#define ML99_PRIV_DIV_185_37 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_186_2 ~, (ML99_JUST(93)) +#define ML99_PRIV_DIV_186_3 ~, (ML99_JUST(62)) +#define ML99_PRIV_DIV_186_6 ~, (ML99_JUST(31)) +#define ML99_PRIV_DIV_186_31 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_186_62 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_186_93 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_187_11 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_187_17 ~, (ML99_JUST(11)) + +#define ML99_PRIV_DIV_188_2 ~, (ML99_JUST(94)) +#define ML99_PRIV_DIV_188_4 ~, (ML99_JUST(47)) +#define ML99_PRIV_DIV_188_47 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_188_94 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_189_3 ~, (ML99_JUST(63)) +#define ML99_PRIV_DIV_189_7 ~, (ML99_JUST(27)) +#define ML99_PRIV_DIV_189_9 ~, (ML99_JUST(21)) +#define ML99_PRIV_DIV_189_21 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_189_27 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_189_63 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_190_2 ~, (ML99_JUST(95)) +#define ML99_PRIV_DIV_190_5 ~, (ML99_JUST(38)) +#define ML99_PRIV_DIV_190_10 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_190_19 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_190_38 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_190_95 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_192_2 ~, (ML99_JUST(96)) +#define ML99_PRIV_DIV_192_3 ~, (ML99_JUST(64)) +#define ML99_PRIV_DIV_192_4 ~, (ML99_JUST(48)) +#define ML99_PRIV_DIV_192_6 ~, (ML99_JUST(32)) +#define ML99_PRIV_DIV_192_8 ~, (ML99_JUST(24)) +#define ML99_PRIV_DIV_192_12 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_192_16 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_192_24 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_192_32 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_192_48 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_192_64 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_192_96 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_194_2 ~, (ML99_JUST(97)) +#define ML99_PRIV_DIV_194_97 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_195_3 ~, (ML99_JUST(65)) +#define ML99_PRIV_DIV_195_5 ~, (ML99_JUST(39)) +#define ML99_PRIV_DIV_195_13 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_195_15 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_195_39 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_195_65 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_196_2 ~, (ML99_JUST(98)) +#define ML99_PRIV_DIV_196_4 ~, (ML99_JUST(49)) +#define ML99_PRIV_DIV_196_7 ~, (ML99_JUST(28)) +#define ML99_PRIV_DIV_196_14 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_196_28 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_196_49 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_196_98 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_198_2 ~, (ML99_JUST(99)) +#define ML99_PRIV_DIV_198_3 ~, (ML99_JUST(66)) +#define ML99_PRIV_DIV_198_6 ~, (ML99_JUST(33)) +#define ML99_PRIV_DIV_198_9 ~, (ML99_JUST(22)) +#define ML99_PRIV_DIV_198_11 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_198_18 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_198_22 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_198_33 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_198_66 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_198_99 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_200_2 ~, (ML99_JUST(100)) +#define ML99_PRIV_DIV_200_4 ~, (ML99_JUST(50)) +#define ML99_PRIV_DIV_200_5 ~, (ML99_JUST(40)) +#define ML99_PRIV_DIV_200_8 ~, (ML99_JUST(25)) +#define ML99_PRIV_DIV_200_10 ~, (ML99_JUST(20)) +#define ML99_PRIV_DIV_200_20 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_200_25 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_200_40 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_200_50 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_200_100 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_201_3 ~, (ML99_JUST(67)) +#define ML99_PRIV_DIV_201_67 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_202_2 ~, (ML99_JUST(101)) +#define ML99_PRIV_DIV_202_101 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_203_7 ~, (ML99_JUST(29)) +#define ML99_PRIV_DIV_203_29 ~, (ML99_JUST(7)) + +#define ML99_PRIV_DIV_204_2 ~, (ML99_JUST(102)) +#define ML99_PRIV_DIV_204_3 ~, (ML99_JUST(68)) +#define ML99_PRIV_DIV_204_4 ~, (ML99_JUST(51)) +#define ML99_PRIV_DIV_204_6 ~, (ML99_JUST(34)) +#define ML99_PRIV_DIV_204_12 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_204_17 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_204_34 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_204_51 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_204_68 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_204_102 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_205_5 ~, (ML99_JUST(41)) +#define ML99_PRIV_DIV_205_41 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_206_2 ~, (ML99_JUST(103)) +#define ML99_PRIV_DIV_206_103 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_207_3 ~, (ML99_JUST(69)) +#define ML99_PRIV_DIV_207_9 ~, (ML99_JUST(23)) +#define ML99_PRIV_DIV_207_23 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_207_69 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_208_2 ~, (ML99_JUST(104)) +#define ML99_PRIV_DIV_208_4 ~, (ML99_JUST(52)) +#define ML99_PRIV_DIV_208_8 ~, (ML99_JUST(26)) +#define ML99_PRIV_DIV_208_13 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_208_16 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_208_26 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_208_52 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_208_104 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_209_11 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_209_19 ~, (ML99_JUST(11)) + +#define ML99_PRIV_DIV_210_2 ~, (ML99_JUST(105)) +#define ML99_PRIV_DIV_210_3 ~, (ML99_JUST(70)) +#define ML99_PRIV_DIV_210_5 ~, (ML99_JUST(42)) +#define ML99_PRIV_DIV_210_6 ~, (ML99_JUST(35)) +#define ML99_PRIV_DIV_210_7 ~, (ML99_JUST(30)) +#define ML99_PRIV_DIV_210_10 ~, (ML99_JUST(21)) +#define ML99_PRIV_DIV_210_14 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_210_15 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_210_21 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_210_30 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_210_35 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_210_42 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_210_70 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_210_105 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_212_2 ~, (ML99_JUST(106)) +#define ML99_PRIV_DIV_212_4 ~, (ML99_JUST(53)) +#define ML99_PRIV_DIV_212_53 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_212_106 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_213_3 ~, (ML99_JUST(71)) +#define ML99_PRIV_DIV_213_71 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_214_2 ~, (ML99_JUST(107)) +#define ML99_PRIV_DIV_214_107 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_215_5 ~, (ML99_JUST(43)) +#define ML99_PRIV_DIV_215_43 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_216_2 ~, (ML99_JUST(108)) +#define ML99_PRIV_DIV_216_3 ~, (ML99_JUST(72)) +#define ML99_PRIV_DIV_216_4 ~, (ML99_JUST(54)) +#define ML99_PRIV_DIV_216_6 ~, (ML99_JUST(36)) +#define ML99_PRIV_DIV_216_8 ~, (ML99_JUST(27)) +#define ML99_PRIV_DIV_216_9 ~, (ML99_JUST(24)) +#define ML99_PRIV_DIV_216_12 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_216_18 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_216_24 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_216_27 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_216_36 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_216_54 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_216_72 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_216_108 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_217_7 ~, (ML99_JUST(31)) +#define ML99_PRIV_DIV_217_31 ~, (ML99_JUST(7)) + +#define ML99_PRIV_DIV_218_2 ~, (ML99_JUST(109)) +#define ML99_PRIV_DIV_218_109 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_219_3 ~, (ML99_JUST(73)) +#define ML99_PRIV_DIV_219_73 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_220_2 ~, (ML99_JUST(110)) +#define ML99_PRIV_DIV_220_4 ~, (ML99_JUST(55)) +#define ML99_PRIV_DIV_220_5 ~, (ML99_JUST(44)) +#define ML99_PRIV_DIV_220_10 ~, (ML99_JUST(22)) +#define ML99_PRIV_DIV_220_11 ~, (ML99_JUST(20)) +#define ML99_PRIV_DIV_220_20 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_220_22 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_220_44 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_220_55 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_220_110 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_221_13 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_221_17 ~, (ML99_JUST(13)) + +#define ML99_PRIV_DIV_222_2 ~, (ML99_JUST(111)) +#define ML99_PRIV_DIV_222_3 ~, (ML99_JUST(74)) +#define ML99_PRIV_DIV_222_6 ~, (ML99_JUST(37)) +#define ML99_PRIV_DIV_222_37 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_222_74 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_222_111 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_224_2 ~, (ML99_JUST(112)) +#define ML99_PRIV_DIV_224_4 ~, (ML99_JUST(56)) +#define ML99_PRIV_DIV_224_7 ~, (ML99_JUST(32)) +#define ML99_PRIV_DIV_224_8 ~, (ML99_JUST(28)) +#define ML99_PRIV_DIV_224_14 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_224_16 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_224_28 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_224_32 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_224_56 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_224_112 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_225_3 ~, (ML99_JUST(75)) +#define ML99_PRIV_DIV_225_5 ~, (ML99_JUST(45)) +#define ML99_PRIV_DIV_225_9 ~, (ML99_JUST(25)) +#define ML99_PRIV_DIV_225_15 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_225_25 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_225_45 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_225_75 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_226_2 ~, (ML99_JUST(113)) +#define ML99_PRIV_DIV_226_113 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_228_2 ~, (ML99_JUST(114)) +#define ML99_PRIV_DIV_228_3 ~, (ML99_JUST(76)) +#define ML99_PRIV_DIV_228_4 ~, (ML99_JUST(57)) +#define ML99_PRIV_DIV_228_6 ~, (ML99_JUST(38)) +#define ML99_PRIV_DIV_228_12 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_228_19 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_228_38 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_228_57 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_228_76 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_228_114 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_230_2 ~, (ML99_JUST(115)) +#define ML99_PRIV_DIV_230_5 ~, (ML99_JUST(46)) +#define ML99_PRIV_DIV_230_10 ~, (ML99_JUST(23)) +#define ML99_PRIV_DIV_230_23 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_230_46 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_230_115 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_231_3 ~, (ML99_JUST(77)) +#define ML99_PRIV_DIV_231_7 ~, (ML99_JUST(33)) +#define ML99_PRIV_DIV_231_11 ~, (ML99_JUST(21)) +#define ML99_PRIV_DIV_231_21 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_231_33 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_231_77 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_232_2 ~, (ML99_JUST(116)) +#define ML99_PRIV_DIV_232_4 ~, (ML99_JUST(58)) +#define ML99_PRIV_DIV_232_8 ~, (ML99_JUST(29)) +#define ML99_PRIV_DIV_232_29 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_232_58 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_232_116 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_234_2 ~, (ML99_JUST(117)) +#define ML99_PRIV_DIV_234_3 ~, (ML99_JUST(78)) +#define ML99_PRIV_DIV_234_6 ~, (ML99_JUST(39)) +#define ML99_PRIV_DIV_234_9 ~, (ML99_JUST(26)) +#define ML99_PRIV_DIV_234_13 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_234_18 ~, (ML99_JUST(13)) +#define ML99_PRIV_DIV_234_26 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_234_39 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_234_78 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_234_117 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_235_5 ~, (ML99_JUST(47)) +#define ML99_PRIV_DIV_235_47 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_236_2 ~, (ML99_JUST(118)) +#define ML99_PRIV_DIV_236_4 ~, (ML99_JUST(59)) +#define ML99_PRIV_DIV_236_59 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_236_118 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_237_3 ~, (ML99_JUST(79)) +#define ML99_PRIV_DIV_237_79 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_238_2 ~, (ML99_JUST(119)) +#define ML99_PRIV_DIV_238_7 ~, (ML99_JUST(34)) +#define ML99_PRIV_DIV_238_14 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_238_17 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_238_34 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_238_119 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_240_2 ~, (ML99_JUST(120)) +#define ML99_PRIV_DIV_240_3 ~, (ML99_JUST(80)) +#define ML99_PRIV_DIV_240_4 ~, (ML99_JUST(60)) +#define ML99_PRIV_DIV_240_5 ~, (ML99_JUST(48)) +#define ML99_PRIV_DIV_240_6 ~, (ML99_JUST(40)) +#define ML99_PRIV_DIV_240_8 ~, (ML99_JUST(30)) +#define ML99_PRIV_DIV_240_10 ~, (ML99_JUST(24)) +#define ML99_PRIV_DIV_240_12 ~, (ML99_JUST(20)) +#define ML99_PRIV_DIV_240_15 ~, (ML99_JUST(16)) +#define ML99_PRIV_DIV_240_16 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_240_20 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_240_24 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_240_30 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_240_40 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_240_48 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_240_60 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_240_80 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_240_120 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_242_2 ~, (ML99_JUST(121)) +#define ML99_PRIV_DIV_242_11 ~, (ML99_JUST(22)) +#define ML99_PRIV_DIV_242_22 ~, (ML99_JUST(11)) +#define ML99_PRIV_DIV_242_121 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_243_3 ~, (ML99_JUST(81)) +#define ML99_PRIV_DIV_243_9 ~, (ML99_JUST(27)) +#define ML99_PRIV_DIV_243_27 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_243_81 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_244_2 ~, (ML99_JUST(122)) +#define ML99_PRIV_DIV_244_4 ~, (ML99_JUST(61)) +#define ML99_PRIV_DIV_244_61 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_244_122 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_245_5 ~, (ML99_JUST(49)) +#define ML99_PRIV_DIV_245_7 ~, (ML99_JUST(35)) +#define ML99_PRIV_DIV_245_35 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_245_49 ~, (ML99_JUST(5)) + +#define ML99_PRIV_DIV_246_2 ~, (ML99_JUST(123)) +#define ML99_PRIV_DIV_246_3 ~, (ML99_JUST(82)) +#define ML99_PRIV_DIV_246_6 ~, (ML99_JUST(41)) +#define ML99_PRIV_DIV_246_41 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_246_82 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_246_123 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_247_13 ~, (ML99_JUST(19)) +#define ML99_PRIV_DIV_247_19 ~, (ML99_JUST(13)) + +#define ML99_PRIV_DIV_248_2 ~, (ML99_JUST(124)) +#define ML99_PRIV_DIV_248_4 ~, (ML99_JUST(62)) +#define ML99_PRIV_DIV_248_8 ~, (ML99_JUST(31)) +#define ML99_PRIV_DIV_248_31 ~, (ML99_JUST(8)) +#define ML99_PRIV_DIV_248_62 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_248_124 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_249_3 ~, (ML99_JUST(83)) +#define ML99_PRIV_DIV_249_83 ~, (ML99_JUST(3)) + +#define ML99_PRIV_DIV_250_2 ~, (ML99_JUST(125)) +#define ML99_PRIV_DIV_250_5 ~, (ML99_JUST(50)) +#define ML99_PRIV_DIV_250_10 ~, (ML99_JUST(25)) +#define ML99_PRIV_DIV_250_25 ~, (ML99_JUST(10)) +#define ML99_PRIV_DIV_250_50 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_250_125 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_252_2 ~, (ML99_JUST(126)) +#define ML99_PRIV_DIV_252_3 ~, (ML99_JUST(84)) +#define ML99_PRIV_DIV_252_4 ~, (ML99_JUST(63)) +#define ML99_PRIV_DIV_252_6 ~, (ML99_JUST(42)) +#define ML99_PRIV_DIV_252_7 ~, (ML99_JUST(36)) +#define ML99_PRIV_DIV_252_9 ~, (ML99_JUST(28)) +#define ML99_PRIV_DIV_252_12 ~, (ML99_JUST(21)) +#define ML99_PRIV_DIV_252_14 ~, (ML99_JUST(18)) +#define ML99_PRIV_DIV_252_18 ~, (ML99_JUST(14)) +#define ML99_PRIV_DIV_252_21 ~, (ML99_JUST(12)) +#define ML99_PRIV_DIV_252_28 ~, (ML99_JUST(9)) +#define ML99_PRIV_DIV_252_36 ~, (ML99_JUST(7)) +#define ML99_PRIV_DIV_252_42 ~, (ML99_JUST(6)) +#define ML99_PRIV_DIV_252_63 ~, (ML99_JUST(4)) +#define ML99_PRIV_DIV_252_84 ~, (ML99_JUST(3)) +#define ML99_PRIV_DIV_252_126 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_253_11 ~, (ML99_JUST(23)) +#define ML99_PRIV_DIV_253_23 ~, (ML99_JUST(11)) + +#define ML99_PRIV_DIV_254_2 ~, (ML99_JUST(127)) +#define ML99_PRIV_DIV_254_127 ~, (ML99_JUST(2)) + +#define ML99_PRIV_DIV_255_3 ~, (ML99_JUST(85)) +#define ML99_PRIV_DIV_255_5 ~, (ML99_JUST(51)) +#define ML99_PRIV_DIV_255_15 ~, (ML99_JUST(17)) +#define ML99_PRIV_DIV_255_17 ~, (ML99_JUST(15)) +#define ML99_PRIV_DIV_255_51 ~, (ML99_JUST(5)) +#define ML99_PRIV_DIV_255_85 ~, (ML99_JUST(3)) + +#endif // ML99_NAT_DIV_H diff --git a/test/external/metalang99/include/metalang99/nat/eq.h b/test/external/metalang99/include/metalang99/nat/eq.h new file mode 100644 index 0000000..d4164dd --- /dev/null +++ b/test/external/metalang99/include/metalang99/nat/eq.h @@ -0,0 +1,266 @@ +#ifndef ML99_NAT_EQ_H +#define ML99_NAT_EQ_H + +#include <metalang99/priv/tuple.h> + +#define ML99_PRIV_NAT_EQ(x, y) ML99_PRIV_NAT_EQ_AUX(x, y) +#define ML99_PRIV_NAT_EQ_AUX(x, y) ML99_PRIV_IS_TUPLE_FAST(ML99_PRIV_NAT_EQ_##x##_##y) + +#define ML99_PRIV_NAT_EQ_0_0 () +#define ML99_PRIV_NAT_EQ_1_1 () +#define ML99_PRIV_NAT_EQ_2_2 () +#define ML99_PRIV_NAT_EQ_3_3 () +#define ML99_PRIV_NAT_EQ_4_4 () +#define ML99_PRIV_NAT_EQ_5_5 () +#define ML99_PRIV_NAT_EQ_6_6 () +#define ML99_PRIV_NAT_EQ_7_7 () +#define ML99_PRIV_NAT_EQ_8_8 () +#define ML99_PRIV_NAT_EQ_9_9 () +#define ML99_PRIV_NAT_EQ_10_10 () +#define ML99_PRIV_NAT_EQ_11_11 () +#define ML99_PRIV_NAT_EQ_12_12 () +#define ML99_PRIV_NAT_EQ_13_13 () +#define ML99_PRIV_NAT_EQ_14_14 () +#define ML99_PRIV_NAT_EQ_15_15 () +#define ML99_PRIV_NAT_EQ_16_16 () +#define ML99_PRIV_NAT_EQ_17_17 () +#define ML99_PRIV_NAT_EQ_18_18 () +#define ML99_PRIV_NAT_EQ_19_19 () +#define ML99_PRIV_NAT_EQ_20_20 () +#define ML99_PRIV_NAT_EQ_21_21 () +#define ML99_PRIV_NAT_EQ_22_22 () +#define ML99_PRIV_NAT_EQ_23_23 () +#define ML99_PRIV_NAT_EQ_24_24 () +#define ML99_PRIV_NAT_EQ_25_25 () +#define ML99_PRIV_NAT_EQ_26_26 () +#define ML99_PRIV_NAT_EQ_27_27 () +#define ML99_PRIV_NAT_EQ_28_28 () +#define ML99_PRIV_NAT_EQ_29_29 () +#define ML99_PRIV_NAT_EQ_30_30 () +#define ML99_PRIV_NAT_EQ_31_31 () +#define ML99_PRIV_NAT_EQ_32_32 () +#define ML99_PRIV_NAT_EQ_33_33 () +#define ML99_PRIV_NAT_EQ_34_34 () +#define ML99_PRIV_NAT_EQ_35_35 () +#define ML99_PRIV_NAT_EQ_36_36 () +#define ML99_PRIV_NAT_EQ_37_37 () +#define ML99_PRIV_NAT_EQ_38_38 () +#define ML99_PRIV_NAT_EQ_39_39 () +#define ML99_PRIV_NAT_EQ_40_40 () +#define ML99_PRIV_NAT_EQ_41_41 () +#define ML99_PRIV_NAT_EQ_42_42 () +#define ML99_PRIV_NAT_EQ_43_43 () +#define ML99_PRIV_NAT_EQ_44_44 () +#define ML99_PRIV_NAT_EQ_45_45 () +#define ML99_PRIV_NAT_EQ_46_46 () +#define ML99_PRIV_NAT_EQ_47_47 () +#define ML99_PRIV_NAT_EQ_48_48 () +#define ML99_PRIV_NAT_EQ_49_49 () +#define ML99_PRIV_NAT_EQ_50_50 () +#define ML99_PRIV_NAT_EQ_51_51 () +#define ML99_PRIV_NAT_EQ_52_52 () +#define ML99_PRIV_NAT_EQ_53_53 () +#define ML99_PRIV_NAT_EQ_54_54 () +#define ML99_PRIV_NAT_EQ_55_55 () +#define ML99_PRIV_NAT_EQ_56_56 () +#define ML99_PRIV_NAT_EQ_57_57 () +#define ML99_PRIV_NAT_EQ_58_58 () +#define ML99_PRIV_NAT_EQ_59_59 () +#define ML99_PRIV_NAT_EQ_60_60 () +#define ML99_PRIV_NAT_EQ_61_61 () +#define ML99_PRIV_NAT_EQ_62_62 () +#define ML99_PRIV_NAT_EQ_63_63 () +#define ML99_PRIV_NAT_EQ_64_64 () +#define ML99_PRIV_NAT_EQ_65_65 () +#define ML99_PRIV_NAT_EQ_66_66 () +#define ML99_PRIV_NAT_EQ_67_67 () +#define ML99_PRIV_NAT_EQ_68_68 () +#define ML99_PRIV_NAT_EQ_69_69 () +#define ML99_PRIV_NAT_EQ_70_70 () +#define ML99_PRIV_NAT_EQ_71_71 () +#define ML99_PRIV_NAT_EQ_72_72 () +#define ML99_PRIV_NAT_EQ_73_73 () +#define ML99_PRIV_NAT_EQ_74_74 () +#define ML99_PRIV_NAT_EQ_75_75 () +#define ML99_PRIV_NAT_EQ_76_76 () +#define ML99_PRIV_NAT_EQ_77_77 () +#define ML99_PRIV_NAT_EQ_78_78 () +#define ML99_PRIV_NAT_EQ_79_79 () +#define ML99_PRIV_NAT_EQ_80_80 () +#define ML99_PRIV_NAT_EQ_81_81 () +#define ML99_PRIV_NAT_EQ_82_82 () +#define ML99_PRIV_NAT_EQ_83_83 () +#define ML99_PRIV_NAT_EQ_84_84 () +#define ML99_PRIV_NAT_EQ_85_85 () +#define ML99_PRIV_NAT_EQ_86_86 () +#define ML99_PRIV_NAT_EQ_87_87 () +#define ML99_PRIV_NAT_EQ_88_88 () +#define ML99_PRIV_NAT_EQ_89_89 () +#define ML99_PRIV_NAT_EQ_90_90 () +#define ML99_PRIV_NAT_EQ_91_91 () +#define ML99_PRIV_NAT_EQ_92_92 () +#define ML99_PRIV_NAT_EQ_93_93 () +#define ML99_PRIV_NAT_EQ_94_94 () +#define ML99_PRIV_NAT_EQ_95_95 () +#define ML99_PRIV_NAT_EQ_96_96 () +#define ML99_PRIV_NAT_EQ_97_97 () +#define ML99_PRIV_NAT_EQ_98_98 () +#define ML99_PRIV_NAT_EQ_99_99 () +#define ML99_PRIV_NAT_EQ_100_100 () +#define ML99_PRIV_NAT_EQ_101_101 () +#define ML99_PRIV_NAT_EQ_102_102 () +#define ML99_PRIV_NAT_EQ_103_103 () +#define ML99_PRIV_NAT_EQ_104_104 () +#define ML99_PRIV_NAT_EQ_105_105 () +#define ML99_PRIV_NAT_EQ_106_106 () +#define ML99_PRIV_NAT_EQ_107_107 () +#define ML99_PRIV_NAT_EQ_108_108 () +#define ML99_PRIV_NAT_EQ_109_109 () +#define ML99_PRIV_NAT_EQ_110_110 () +#define ML99_PRIV_NAT_EQ_111_111 () +#define ML99_PRIV_NAT_EQ_112_112 () +#define ML99_PRIV_NAT_EQ_113_113 () +#define ML99_PRIV_NAT_EQ_114_114 () +#define ML99_PRIV_NAT_EQ_115_115 () +#define ML99_PRIV_NAT_EQ_116_116 () +#define ML99_PRIV_NAT_EQ_117_117 () +#define ML99_PRIV_NAT_EQ_118_118 () +#define ML99_PRIV_NAT_EQ_119_119 () +#define ML99_PRIV_NAT_EQ_120_120 () +#define ML99_PRIV_NAT_EQ_121_121 () +#define ML99_PRIV_NAT_EQ_122_122 () +#define ML99_PRIV_NAT_EQ_123_123 () +#define ML99_PRIV_NAT_EQ_124_124 () +#define ML99_PRIV_NAT_EQ_125_125 () +#define ML99_PRIV_NAT_EQ_126_126 () +#define ML99_PRIV_NAT_EQ_127_127 () +#define ML99_PRIV_NAT_EQ_128_128 () +#define ML99_PRIV_NAT_EQ_129_129 () +#define ML99_PRIV_NAT_EQ_130_130 () +#define ML99_PRIV_NAT_EQ_131_131 () +#define ML99_PRIV_NAT_EQ_132_132 () +#define ML99_PRIV_NAT_EQ_133_133 () +#define ML99_PRIV_NAT_EQ_134_134 () +#define ML99_PRIV_NAT_EQ_135_135 () +#define ML99_PRIV_NAT_EQ_136_136 () +#define ML99_PRIV_NAT_EQ_137_137 () +#define ML99_PRIV_NAT_EQ_138_138 () +#define ML99_PRIV_NAT_EQ_139_139 () +#define ML99_PRIV_NAT_EQ_140_140 () +#define ML99_PRIV_NAT_EQ_141_141 () +#define ML99_PRIV_NAT_EQ_142_142 () +#define ML99_PRIV_NAT_EQ_143_143 () +#define ML99_PRIV_NAT_EQ_144_144 () +#define ML99_PRIV_NAT_EQ_145_145 () +#define ML99_PRIV_NAT_EQ_146_146 () +#define ML99_PRIV_NAT_EQ_147_147 () +#define ML99_PRIV_NAT_EQ_148_148 () +#define ML99_PRIV_NAT_EQ_149_149 () +#define ML99_PRIV_NAT_EQ_150_150 () +#define ML99_PRIV_NAT_EQ_151_151 () +#define ML99_PRIV_NAT_EQ_152_152 () +#define ML99_PRIV_NAT_EQ_153_153 () +#define ML99_PRIV_NAT_EQ_154_154 () +#define ML99_PRIV_NAT_EQ_155_155 () +#define ML99_PRIV_NAT_EQ_156_156 () +#define ML99_PRIV_NAT_EQ_157_157 () +#define ML99_PRIV_NAT_EQ_158_158 () +#define ML99_PRIV_NAT_EQ_159_159 () +#define ML99_PRIV_NAT_EQ_160_160 () +#define ML99_PRIV_NAT_EQ_161_161 () +#define ML99_PRIV_NAT_EQ_162_162 () +#define ML99_PRIV_NAT_EQ_163_163 () +#define ML99_PRIV_NAT_EQ_164_164 () +#define ML99_PRIV_NAT_EQ_165_165 () +#define ML99_PRIV_NAT_EQ_166_166 () +#define ML99_PRIV_NAT_EQ_167_167 () +#define ML99_PRIV_NAT_EQ_168_168 () +#define ML99_PRIV_NAT_EQ_169_169 () +#define ML99_PRIV_NAT_EQ_170_170 () +#define ML99_PRIV_NAT_EQ_171_171 () +#define ML99_PRIV_NAT_EQ_172_172 () +#define ML99_PRIV_NAT_EQ_173_173 () +#define ML99_PRIV_NAT_EQ_174_174 () +#define ML99_PRIV_NAT_EQ_175_175 () +#define ML99_PRIV_NAT_EQ_176_176 () +#define ML99_PRIV_NAT_EQ_177_177 () +#define ML99_PRIV_NAT_EQ_178_178 () +#define ML99_PRIV_NAT_EQ_179_179 () +#define ML99_PRIV_NAT_EQ_180_180 () +#define ML99_PRIV_NAT_EQ_181_181 () +#define ML99_PRIV_NAT_EQ_182_182 () +#define ML99_PRIV_NAT_EQ_183_183 () +#define ML99_PRIV_NAT_EQ_184_184 () +#define ML99_PRIV_NAT_EQ_185_185 () +#define ML99_PRIV_NAT_EQ_186_186 () +#define ML99_PRIV_NAT_EQ_187_187 () +#define ML99_PRIV_NAT_EQ_188_188 () +#define ML99_PRIV_NAT_EQ_189_189 () +#define ML99_PRIV_NAT_EQ_190_190 () +#define ML99_PRIV_NAT_EQ_191_191 () +#define ML99_PRIV_NAT_EQ_192_192 () +#define ML99_PRIV_NAT_EQ_193_193 () +#define ML99_PRIV_NAT_EQ_194_194 () +#define ML99_PRIV_NAT_EQ_195_195 () +#define ML99_PRIV_NAT_EQ_196_196 () +#define ML99_PRIV_NAT_EQ_197_197 () +#define ML99_PRIV_NAT_EQ_198_198 () +#define ML99_PRIV_NAT_EQ_199_199 () +#define ML99_PRIV_NAT_EQ_200_200 () +#define ML99_PRIV_NAT_EQ_201_201 () +#define ML99_PRIV_NAT_EQ_202_202 () +#define ML99_PRIV_NAT_EQ_203_203 () +#define ML99_PRIV_NAT_EQ_204_204 () +#define ML99_PRIV_NAT_EQ_205_205 () +#define ML99_PRIV_NAT_EQ_206_206 () +#define ML99_PRIV_NAT_EQ_207_207 () +#define ML99_PRIV_NAT_EQ_208_208 () +#define ML99_PRIV_NAT_EQ_209_209 () +#define ML99_PRIV_NAT_EQ_210_210 () +#define ML99_PRIV_NAT_EQ_211_211 () +#define ML99_PRIV_NAT_EQ_212_212 () +#define ML99_PRIV_NAT_EQ_213_213 () +#define ML99_PRIV_NAT_EQ_214_214 () +#define ML99_PRIV_NAT_EQ_215_215 () +#define ML99_PRIV_NAT_EQ_216_216 () +#define ML99_PRIV_NAT_EQ_217_217 () +#define ML99_PRIV_NAT_EQ_218_218 () +#define ML99_PRIV_NAT_EQ_219_219 () +#define ML99_PRIV_NAT_EQ_220_220 () +#define ML99_PRIV_NAT_EQ_221_221 () +#define ML99_PRIV_NAT_EQ_222_222 () +#define ML99_PRIV_NAT_EQ_223_223 () +#define ML99_PRIV_NAT_EQ_224_224 () +#define ML99_PRIV_NAT_EQ_225_225 () +#define ML99_PRIV_NAT_EQ_226_226 () +#define ML99_PRIV_NAT_EQ_227_227 () +#define ML99_PRIV_NAT_EQ_228_228 () +#define ML99_PRIV_NAT_EQ_229_229 () +#define ML99_PRIV_NAT_EQ_230_230 () +#define ML99_PRIV_NAT_EQ_231_231 () +#define ML99_PRIV_NAT_EQ_232_232 () +#define ML99_PRIV_NAT_EQ_233_233 () +#define ML99_PRIV_NAT_EQ_234_234 () +#define ML99_PRIV_NAT_EQ_235_235 () +#define ML99_PRIV_NAT_EQ_236_236 () +#define ML99_PRIV_NAT_EQ_237_237 () +#define ML99_PRIV_NAT_EQ_238_238 () +#define ML99_PRIV_NAT_EQ_239_239 () +#define ML99_PRIV_NAT_EQ_240_240 () +#define ML99_PRIV_NAT_EQ_241_241 () +#define ML99_PRIV_NAT_EQ_242_242 () +#define ML99_PRIV_NAT_EQ_243_243 () +#define ML99_PRIV_NAT_EQ_244_244 () +#define ML99_PRIV_NAT_EQ_245_245 () +#define ML99_PRIV_NAT_EQ_246_246 () +#define ML99_PRIV_NAT_EQ_247_247 () +#define ML99_PRIV_NAT_EQ_248_248 () +#define ML99_PRIV_NAT_EQ_249_249 () +#define ML99_PRIV_NAT_EQ_250_250 () +#define ML99_PRIV_NAT_EQ_251_251 () +#define ML99_PRIV_NAT_EQ_252_252 () +#define ML99_PRIV_NAT_EQ_253_253 () +#define ML99_PRIV_NAT_EQ_254_254 () +#define ML99_PRIV_NAT_EQ_255_255 () + +#endif // ML99_NAT_EQ_H diff --git a/test/external/metalang99/include/metalang99/nat/inc.h b/test/external/metalang99/include/metalang99/nat/inc.h new file mode 100644 index 0000000..1543900 --- /dev/null +++ b/test/external/metalang99/include/metalang99/nat/inc.h @@ -0,0 +1,264 @@ +#ifndef ML99_NAT_INC_H +#define ML99_NAT_INC_H + +#define ML99_PRIV_INC(x) ML99_PRIV_INC_AUX(x) +#define ML99_PRIV_INC_AUX(x) ML99_PRIV_INC_##x + +#define ML99_PRIV_INC_0 1 +#define ML99_PRIV_INC_1 2 +#define ML99_PRIV_INC_2 3 +#define ML99_PRIV_INC_3 4 +#define ML99_PRIV_INC_4 5 +#define ML99_PRIV_INC_5 6 +#define ML99_PRIV_INC_6 7 +#define ML99_PRIV_INC_7 8 +#define ML99_PRIV_INC_8 9 +#define ML99_PRIV_INC_9 10 +#define ML99_PRIV_INC_10 11 +#define ML99_PRIV_INC_11 12 +#define ML99_PRIV_INC_12 13 +#define ML99_PRIV_INC_13 14 +#define ML99_PRIV_INC_14 15 +#define ML99_PRIV_INC_15 16 +#define ML99_PRIV_INC_16 17 +#define ML99_PRIV_INC_17 18 +#define ML99_PRIV_INC_18 19 +#define ML99_PRIV_INC_19 20 +#define ML99_PRIV_INC_20 21 +#define ML99_PRIV_INC_21 22 +#define ML99_PRIV_INC_22 23 +#define ML99_PRIV_INC_23 24 +#define ML99_PRIV_INC_24 25 +#define ML99_PRIV_INC_25 26 +#define ML99_PRIV_INC_26 27 +#define ML99_PRIV_INC_27 28 +#define ML99_PRIV_INC_28 29 +#define ML99_PRIV_INC_29 30 +#define ML99_PRIV_INC_30 31 +#define ML99_PRIV_INC_31 32 +#define ML99_PRIV_INC_32 33 +#define ML99_PRIV_INC_33 34 +#define ML99_PRIV_INC_34 35 +#define ML99_PRIV_INC_35 36 +#define ML99_PRIV_INC_36 37 +#define ML99_PRIV_INC_37 38 +#define ML99_PRIV_INC_38 39 +#define ML99_PRIV_INC_39 40 +#define ML99_PRIV_INC_40 41 +#define ML99_PRIV_INC_41 42 +#define ML99_PRIV_INC_42 43 +#define ML99_PRIV_INC_43 44 +#define ML99_PRIV_INC_44 45 +#define ML99_PRIV_INC_45 46 +#define ML99_PRIV_INC_46 47 +#define ML99_PRIV_INC_47 48 +#define ML99_PRIV_INC_48 49 +#define ML99_PRIV_INC_49 50 +#define ML99_PRIV_INC_50 51 +#define ML99_PRIV_INC_51 52 +#define ML99_PRIV_INC_52 53 +#define ML99_PRIV_INC_53 54 +#define ML99_PRIV_INC_54 55 +#define ML99_PRIV_INC_55 56 +#define ML99_PRIV_INC_56 57 +#define ML99_PRIV_INC_57 58 +#define ML99_PRIV_INC_58 59 +#define ML99_PRIV_INC_59 60 +#define ML99_PRIV_INC_60 61 +#define ML99_PRIV_INC_61 62 +#define ML99_PRIV_INC_62 63 +#define ML99_PRIV_INC_63 64 +#define ML99_PRIV_INC_64 65 +#define ML99_PRIV_INC_65 66 +#define ML99_PRIV_INC_66 67 +#define ML99_PRIV_INC_67 68 +#define ML99_PRIV_INC_68 69 +#define ML99_PRIV_INC_69 70 +#define ML99_PRIV_INC_70 71 +#define ML99_PRIV_INC_71 72 +#define ML99_PRIV_INC_72 73 +#define ML99_PRIV_INC_73 74 +#define ML99_PRIV_INC_74 75 +#define ML99_PRIV_INC_75 76 +#define ML99_PRIV_INC_76 77 +#define ML99_PRIV_INC_77 78 +#define ML99_PRIV_INC_78 79 +#define ML99_PRIV_INC_79 80 +#define ML99_PRIV_INC_80 81 +#define ML99_PRIV_INC_81 82 +#define ML99_PRIV_INC_82 83 +#define ML99_PRIV_INC_83 84 +#define ML99_PRIV_INC_84 85 +#define ML99_PRIV_INC_85 86 +#define ML99_PRIV_INC_86 87 +#define ML99_PRIV_INC_87 88 +#define ML99_PRIV_INC_88 89 +#define ML99_PRIV_INC_89 90 +#define ML99_PRIV_INC_90 91 +#define ML99_PRIV_INC_91 92 +#define ML99_PRIV_INC_92 93 +#define ML99_PRIV_INC_93 94 +#define ML99_PRIV_INC_94 95 +#define ML99_PRIV_INC_95 96 +#define ML99_PRIV_INC_96 97 +#define ML99_PRIV_INC_97 98 +#define ML99_PRIV_INC_98 99 +#define ML99_PRIV_INC_99 100 +#define ML99_PRIV_INC_100 101 +#define ML99_PRIV_INC_101 102 +#define ML99_PRIV_INC_102 103 +#define ML99_PRIV_INC_103 104 +#define ML99_PRIV_INC_104 105 +#define ML99_PRIV_INC_105 106 +#define ML99_PRIV_INC_106 107 +#define ML99_PRIV_INC_107 108 +#define ML99_PRIV_INC_108 109 +#define ML99_PRIV_INC_109 110 +#define ML99_PRIV_INC_110 111 +#define ML99_PRIV_INC_111 112 +#define ML99_PRIV_INC_112 113 +#define ML99_PRIV_INC_113 114 +#define ML99_PRIV_INC_114 115 +#define ML99_PRIV_INC_115 116 +#define ML99_PRIV_INC_116 117 +#define ML99_PRIV_INC_117 118 +#define ML99_PRIV_INC_118 119 +#define ML99_PRIV_INC_119 120 +#define ML99_PRIV_INC_120 121 +#define ML99_PRIV_INC_121 122 +#define ML99_PRIV_INC_122 123 +#define ML99_PRIV_INC_123 124 +#define ML99_PRIV_INC_124 125 +#define ML99_PRIV_INC_125 126 +#define ML99_PRIV_INC_126 127 +#define ML99_PRIV_INC_127 128 +#define ML99_PRIV_INC_128 129 +#define ML99_PRIV_INC_129 130 +#define ML99_PRIV_INC_130 131 +#define ML99_PRIV_INC_131 132 +#define ML99_PRIV_INC_132 133 +#define ML99_PRIV_INC_133 134 +#define ML99_PRIV_INC_134 135 +#define ML99_PRIV_INC_135 136 +#define ML99_PRIV_INC_136 137 +#define ML99_PRIV_INC_137 138 +#define ML99_PRIV_INC_138 139 +#define ML99_PRIV_INC_139 140 +#define ML99_PRIV_INC_140 141 +#define ML99_PRIV_INC_141 142 +#define ML99_PRIV_INC_142 143 +#define ML99_PRIV_INC_143 144 +#define ML99_PRIV_INC_144 145 +#define ML99_PRIV_INC_145 146 +#define ML99_PRIV_INC_146 147 +#define ML99_PRIV_INC_147 148 +#define ML99_PRIV_INC_148 149 +#define ML99_PRIV_INC_149 150 +#define ML99_PRIV_INC_150 151 +#define ML99_PRIV_INC_151 152 +#define ML99_PRIV_INC_152 153 +#define ML99_PRIV_INC_153 154 +#define ML99_PRIV_INC_154 155 +#define ML99_PRIV_INC_155 156 +#define ML99_PRIV_INC_156 157 +#define ML99_PRIV_INC_157 158 +#define ML99_PRIV_INC_158 159 +#define ML99_PRIV_INC_159 160 +#define ML99_PRIV_INC_160 161 +#define ML99_PRIV_INC_161 162 +#define ML99_PRIV_INC_162 163 +#define ML99_PRIV_INC_163 164 +#define ML99_PRIV_INC_164 165 +#define ML99_PRIV_INC_165 166 +#define ML99_PRIV_INC_166 167 +#define ML99_PRIV_INC_167 168 +#define ML99_PRIV_INC_168 169 +#define ML99_PRIV_INC_169 170 +#define ML99_PRIV_INC_170 171 +#define ML99_PRIV_INC_171 172 +#define ML99_PRIV_INC_172 173 +#define ML99_PRIV_INC_173 174 +#define ML99_PRIV_INC_174 175 +#define ML99_PRIV_INC_175 176 +#define ML99_PRIV_INC_176 177 +#define ML99_PRIV_INC_177 178 +#define ML99_PRIV_INC_178 179 +#define ML99_PRIV_INC_179 180 +#define ML99_PRIV_INC_180 181 +#define ML99_PRIV_INC_181 182 +#define ML99_PRIV_INC_182 183 +#define ML99_PRIV_INC_183 184 +#define ML99_PRIV_INC_184 185 +#define ML99_PRIV_INC_185 186 +#define ML99_PRIV_INC_186 187 +#define ML99_PRIV_INC_187 188 +#define ML99_PRIV_INC_188 189 +#define ML99_PRIV_INC_189 190 +#define ML99_PRIV_INC_190 191 +#define ML99_PRIV_INC_191 192 +#define ML99_PRIV_INC_192 193 +#define ML99_PRIV_INC_193 194 +#define ML99_PRIV_INC_194 195 +#define ML99_PRIV_INC_195 196 +#define ML99_PRIV_INC_196 197 +#define ML99_PRIV_INC_197 198 +#define ML99_PRIV_INC_198 199 +#define ML99_PRIV_INC_199 200 +#define ML99_PRIV_INC_200 201 +#define ML99_PRIV_INC_201 202 +#define ML99_PRIV_INC_202 203 +#define ML99_PRIV_INC_203 204 +#define ML99_PRIV_INC_204 205 +#define ML99_PRIV_INC_205 206 +#define ML99_PRIV_INC_206 207 +#define ML99_PRIV_INC_207 208 +#define ML99_PRIV_INC_208 209 +#define ML99_PRIV_INC_209 210 +#define ML99_PRIV_INC_210 211 +#define ML99_PRIV_INC_211 212 +#define ML99_PRIV_INC_212 213 +#define ML99_PRIV_INC_213 214 +#define ML99_PRIV_INC_214 215 +#define ML99_PRIV_INC_215 216 +#define ML99_PRIV_INC_216 217 +#define ML99_PRIV_INC_217 218 +#define ML99_PRIV_INC_218 219 +#define ML99_PRIV_INC_219 220 +#define ML99_PRIV_INC_220 221 +#define ML99_PRIV_INC_221 222 +#define ML99_PRIV_INC_222 223 +#define ML99_PRIV_INC_223 224 +#define ML99_PRIV_INC_224 225 +#define ML99_PRIV_INC_225 226 +#define ML99_PRIV_INC_226 227 +#define ML99_PRIV_INC_227 228 +#define ML99_PRIV_INC_228 229 +#define ML99_PRIV_INC_229 230 +#define ML99_PRIV_INC_230 231 +#define ML99_PRIV_INC_231 232 +#define ML99_PRIV_INC_232 233 +#define ML99_PRIV_INC_233 234 +#define ML99_PRIV_INC_234 235 +#define ML99_PRIV_INC_235 236 +#define ML99_PRIV_INC_236 237 +#define ML99_PRIV_INC_237 238 +#define ML99_PRIV_INC_238 239 +#define ML99_PRIV_INC_239 240 +#define ML99_PRIV_INC_240 241 +#define ML99_PRIV_INC_241 242 +#define ML99_PRIV_INC_242 243 +#define ML99_PRIV_INC_243 244 +#define ML99_PRIV_INC_244 245 +#define ML99_PRIV_INC_245 246 +#define ML99_PRIV_INC_246 247 +#define ML99_PRIV_INC_247 248 +#define ML99_PRIV_INC_248 249 +#define ML99_PRIV_INC_249 250 +#define ML99_PRIV_INC_250 251 +#define ML99_PRIV_INC_251 252 +#define ML99_PRIV_INC_252 253 +#define ML99_PRIV_INC_253 254 +#define ML99_PRIV_INC_254 255 +#define ML99_PRIV_INC_255 0 + +#endif // ML99_NAT_INC_H diff --git a/test/external/metalang99/include/metalang99/priv/bool.h b/test/external/metalang99/include/metalang99/priv/bool.h new file mode 100644 index 0000000..d0b19d2 --- /dev/null +++ b/test/external/metalang99/include/metalang99/priv/bool.h @@ -0,0 +1,46 @@ +#ifndef ML99_PRIV_BOOL_H +#define ML99_PRIV_BOOL_H + +#define ML99_PRIV_TRUE(...) 1 +#define ML99_PRIV_FALSE(...) 0 + +#define ML99_PRIV_NOT(b) ML99_PRIV_LOGICAL_OVERLOAD_SINGLE(ML99_PRIV_NOT_, b) +#define ML99_PRIV_NOT_0 1 +#define ML99_PRIV_NOT_1 0 + +#define ML99_PRIV_AND(x, y) ML99_PRIV_LOGICAL_OVERLOAD(ML99_PRIV_AND_, x, y) +#define ML99_PRIV_AND_00 0 +#define ML99_PRIV_AND_01 0 +#define ML99_PRIV_AND_10 0 +#define ML99_PRIV_AND_11 1 + +#define ML99_PRIV_OR(x, y) ML99_PRIV_LOGICAL_OVERLOAD(ML99_PRIV_OR_, x, y) +#define ML99_PRIV_OR_00 0 +#define ML99_PRIV_OR_01 1 +#define ML99_PRIV_OR_10 1 +#define ML99_PRIV_OR_11 1 + +#define ML99_PRIV_OR3(a, b, c) ML99_PRIV_OR(a, ML99_PRIV_OR(b, c)) +#define ML99_PRIV_OR4(a, b, c, d) ML99_PRIV_OR3(a, b, ML99_PRIV_OR(c, d)) + +#define ML99_PRIV_XOR(x, y) ML99_PRIV_LOGICAL_OVERLOAD(ML99_PRIV_XOR_, x, y) +#define ML99_PRIV_XOR_00 0 +#define ML99_PRIV_XOR_01 1 +#define ML99_PRIV_XOR_10 1 +#define ML99_PRIV_XOR_11 0 + +#define ML99_PRIV_BOOL_EQ(x, y) ML99_PRIV_LOGICAL_OVERLOAD(ML99_PRIV_BOOL_EQ_, x, y) +#define ML99_PRIV_BOOL_EQ_00 1 +#define ML99_PRIV_BOOL_EQ_01 0 +#define ML99_PRIV_BOOL_EQ_10 0 +#define ML99_PRIV_BOOL_EQ_11 1 + +#define ML99_PRIV_LOGICAL_OVERLOAD(op, x, y) op##x##y +#define ML99_PRIV_LOGICAL_OVERLOAD_SINGLE(op, b) op##b + +#define ML99_PRIV_IF(cond, x, y) ML99_PRIV_IF_OVERLOAD(cond)(x, y) +#define ML99_PRIV_IF_OVERLOAD(cond) ML99_PRIV_IF_##cond +#define ML99_PRIV_IF_0(_x, y) y +#define ML99_PRIV_IF_1(x, _y) x + +#endif // ML99_PRIV_BOOL_H diff --git a/test/external/metalang99/include/metalang99/priv/compiler_specific.h b/test/external/metalang99/include/metalang99/priv/compiler_specific.h new file mode 100644 index 0000000..c334e21 --- /dev/null +++ b/test/external/metalang99/include/metalang99/priv/compiler_specific.h @@ -0,0 +1,69 @@ +#ifndef ML99_PRIV_COMPILER_SPECIFIC_H +#define ML99_PRIV_COMPILER_SPECIFIC_H + +#define ML99_PRIV_C11_VERSION 201112L + +// GCC 4.6 Release Series: <https://gcc.gnu.org/gcc-4.6/changes.html>. +#define ML99_PRIV_IS_GCC_4_6_OR_HIGHER ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || (__GNUC__ >= 5)) + +#ifdef __GNUC__ +#define ML99_PRIV_COMPILER_ATTR_UNUSED __attribute__((unused)) +#else +#define ML99_PRIV_COMPILER_ATTR_UNUSED +#endif + +// ML99_PRIV_C11_STATIC_ASSERT_AVAILABLE { + +#if __STDC__ && __STDC_VERSION__ >= ML99_PRIV_C11_VERSION + +#define ML99_PRIV_C11_STATIC_ASSERT_AVAILABLE + +/* + * On MSVC, `__STDC__` expands to 0 if the `\Za` option was not specified, but the thing is that it + * nevertheless supports C11's `_Static_assert`. + * + * MSVC Standard predefined macros: + * <https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros#standard-predefined-macros>. + */ +#elif defined(_MSC_VER) && __STDC_VERSION__ >= ML99_PRIV_C11_VERSION +#define ML99_PRIV_C11_STATIC_ASSERT_AVAILABLE +#endif +// } (ML99_PRIV_C11_STATIC_ASSERT_AVAILABLE) + +// ML99_PRIV_EMIT_ERROR { + +#ifdef ML99_PRIV_C11_STATIC_ASSERT_AVAILABLE +#define ML99_PRIV_EMIT_ERROR ML99_PRIV_STATIC_ASSERT_ERROR +#elif defined(__clang__) + +#if __has_extension(c_static_assert) +#define ML99_PRIV_EMIT_ERROR ML99_PRIV_STATIC_ASSERT_ERROR +#endif + +#elif defined(__GNUC__) + +#if ML99_PRIV_IS_GCC_4_6_OR_HIGHER +#define ML99_PRIV_EMIT_ERROR ML99_PRIV_STATIC_ASSERT_ERROR +#else + +// GCC Common Function Attributes: +// <https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html>. +#define ML99_PRIV_EMIT_ERROR(message) \ + void __attribute__((constructor, error(message))) ML99_CAT(ml99_error_, __LINE__)(void) { \ + ML99_CAT(ml99_error_, __LINE__)(); \ + } + +#endif + +#endif + +#if !defined(ML99_PRIV_EMIT_ERROR) && !defined(ML99_ALLOW_POOR_DIAGNOSTICS) +#error Your compiler doesn't support decent diagnostic messages. \ +You'll have to search for Metalang99 errors in a preprocessed-only file (-E) by yourself. \ +Define ML99_ALLOW_POOR_DIAGNOSTICS to suppress this error. +#endif + +#define ML99_PRIV_STATIC_ASSERT_ERROR(message) _Static_assert(0, message) +// } (ML99_PRIV_EMIT_ERROR) + +#endif // ML99_PRIV_COMPILER_SPECIFIC_H diff --git a/test/external/metalang99/include/metalang99/priv/tuple.h b/test/external/metalang99/include/metalang99/priv/tuple.h new file mode 100644 index 0000000..ea2fd19 --- /dev/null +++ b/test/external/metalang99/include/metalang99/priv/tuple.h @@ -0,0 +1,33 @@ +#ifndef ML99_PRIV_TUPLE_H +#define ML99_PRIV_TUPLE_H + +#include <metalang99/priv/bool.h> +#include <metalang99/priv/util.h> + +#define ML99_PRIV_IS_TUPLE(x) ML99_PRIV_NOT(ML99_PRIV_IS_UNTUPLE(x)) +#define ML99_PRIV_IS_TUPLE_FAST(x) ML99_PRIV_NOT(ML99_PRIV_IS_UNTUPLE_FAST(x)) + +#define ML99_PRIV_IS_UNTUPLE(x) \ + ML99_PRIV_IF( \ + ML99_PRIV_IS_DOUBLE_TUPLE_BEGINNING(x), \ + ML99_PRIV_TRUE, \ + ML99_PRIV_IS_UNTUPLE_FAST) \ + (x) + +#define ML99_PRIV_IS_UNTUPLE_FAST(x) ML99_PRIV_SND(ML99_PRIV_IS_UNTUPLE_FAST_TEST x, 1) +#define ML99_PRIV_IS_UNTUPLE_FAST_TEST(...) ~, 0 + +#define ML99_PRIV_UNTUPLE(x) ML99_PRIV_EXPAND x + +/** + * Checks whether @p x takes the form `(...) (...) ...`. + * + * This often happens when you miss a comma between items: + * - `v(123) v(456)` + * - `(Foo, int) (Bar, int)` (as in Datatype99) + * - etc. + */ +#define ML99_PRIV_IS_DOUBLE_TUPLE_BEGINNING(x) \ + ML99_PRIV_CONTAINS_COMMA(ML99_PRIV_EXPAND(ML99_PRIV_COMMA ML99_PRIV_EMPTY x)) + +#endif // ML99_PRIV_TUPLE_H diff --git a/test/external/metalang99/include/metalang99/priv/util.h b/test/external/metalang99/include/metalang99/priv/util.h new file mode 100644 index 0000000..80a5bc4 --- /dev/null +++ b/test/external/metalang99/include/metalang99/priv/util.h @@ -0,0 +1,27 @@ +#ifndef ML99_PRIV_UTIL_H +#define ML99_PRIV_UTIL_H + +#define ML99_PRIV_CAT(x, y) ML99_PRIV_PRIMITIVE_CAT(x, y) +#define ML99_PRIV_PRIMITIVE_CAT(x, y) x##y + +#define ML99_PRIV_CAT3(x, y, z) ML99_PRIV_PRIMITIVE_CAT3(x, y, z) +#define ML99_PRIV_PRIMITIVE_CAT3(x, y, z) x##y##z + +#define ML99_PRIV_EXPAND(...) __VA_ARGS__ +#define ML99_PRIV_EMPTY(...) +#define ML99_PRIV_COMMA(...) , + +#define ML99_PRIV_HEAD(...) ML99_PRIV_HEAD_AUX(__VA_ARGS__, ~) +#define ML99_PRIV_HEAD_AUX(x, ...) x + +#define ML99_PRIV_TAIL(...) ML99_PRIV_TAIL_AUX(__VA_ARGS__) +#define ML99_PRIV_TAIL_AUX(_x, ...) __VA_ARGS__ + +#define ML99_PRIV_SND(...) ML99_PRIV_SND_AUX(__VA_ARGS__, ~) +#define ML99_PRIV_SND_AUX(_x, y, ...) y + +#define ML99_PRIV_CONTAINS_COMMA(...) ML99_PRIV_X_AS_COMMA(__VA_ARGS__, ML99_PRIV_COMMA(), ~) +#define ML99_PRIV_X_AS_COMMA(_head, x, ...) ML99_PRIV_CONTAINS_COMMA_RESULT(x, 0, 1, ~) +#define ML99_PRIV_CONTAINS_COMMA_RESULT(x, _, result, ...) result + +#endif // ML99_PRIV_UTIL_H diff --git a/test/external/metalang99/include/metalang99/seq.h b/test/external/metalang99/include/metalang99/seq.h new file mode 100644 index 0000000..be2efae --- /dev/null +++ b/test/external/metalang99/include/metalang99/seq.h @@ -0,0 +1,204 @@ +/** + * @file + * Sequences: `(x)(y)(z)`. + * + * A sequence is represented as `(...) (...) ...`. For example, these are sequences: + * - `(~, ~, ~)` + * - `(1)(2)(3)` + * - `(+, -, *, /)(123)(~)` + * + * Sequences can represent syntax like `X(...) Y(...) Z(...)`, where `X`, `Y`, and `Z` expand to a + * [tuple](tuple.html), thereby forming a sequence. A perfect example is + * [Interface99](https://github.com/hirrolot/interface99), which allows a user to define a software + * interface via a number of `vfunc(...)` macro invocations: + * + * @code + * #define Shape_IFACE \ + * vfunc( int, perim, const VSelf) \ + * vfunc(void, scale, VSelf, int factor) + * + * interface(Shape); + * @endcode + * + * With `vfunc` being defined as follows (simplified): + * + * @code + * #define vfunc(ret_ty, name, ...) (ret_ty, name, __VA_ARGS__) + * @endcode + * + * @note Sequences are more time and space-efficient than lists, but export less functionality; if a + * needed function is missed, invoking #ML99_listFromSeq and then manipulating with the resulting + * Cons-list might be helpful. + */ + +#ifndef ML99_SEQ_H +#define ML99_SEQ_H + +#include <metalang99/nat/inc.h> +#include <metalang99/priv/tuple.h> +#include <metalang99/priv/util.h> + +#include <metalang99/lang.h> + +/** + * True iff @p seq contains no elements (which means an empty preprocessing lexeme). + * + * # Examples + * + * @code + * #include <metalang99/seq.h> + * + * // 1 + * ML99_seqIsEmpty(v()) + * + * // 0 + * ML99_seqIsEmpty(v((~)(~)(~))) + * @endcode + */ +#define ML99_seqIsEmpty(seq) ML99_call(ML99_seqIsEmpty, seq) + +/** + * Expands to a metafunction extracting the @p i -indexed element of @p seq. + * + * @p i can range from 0 to 7, inclusively. + * + * # Examples + * + * @code + * #include <metalang99/seq.h> + * + * // 2 + * ML99_seqGet(1)(v((1)(2)(3))) + * @endcode + */ +#define ML99_seqGet(i) ML99_PRIV_CAT(ML99_PRIV_seqGet_, i) + +/** + * Extracts the tail of @p seq. + * + * @p seq must contain at least one element. If @p seq contains **only** one element, the result is + * `ML99_empty()`. + * + * # Examples + * + * @code + * #include <metalang99/seq.h> + * + * // (2)(3) + * ML99_seqTail(v((1)(2)(3))) + * @endcode + */ +#define ML99_seqTail(seq) ML99_call(ML99_seqTail, seq) + +/** + * Applies @p f to each element in @p seq. + * + * The result is `ML99_appl(f, x1) ... ML99_appl(f, xN)`. + * + * # Examples + * + * @code + * #include <metalang99/seq.h> + * + * #define F_IMPL(x) v(@x) + * #define F_ARITY 1 + * + * // @x @y @z + * ML99_seqForEach(v(F), v((x)(y)(z))) + * @endcode + */ +#define ML99_seqForEach(f, seq) ML99_call(ML99_seqForEach, f, seq) + +/** + * Applies @p f to each element in @p seq with an index. + * + * The result is `ML99_appl2(f, 0, x1) ... ML99_appl2(f, N - 1, xN)`. + * + * @code + * #include <metalang99/seq.h> + * + * #define F_IMPL(i, x) v(@x##i) + * #define F_ARITY 2 + * + * // @x0 @y1 @z2 + * ML99_seqForEachI(v(F), v((x)(y)(z))) + * @endcode + */ +#define ML99_seqForEachI(f, seq) ML99_call(ML99_seqForEachI, f, seq) + +#define ML99_SEQ_IS_EMPTY(seq) ML99_PRIV_NOT(ML99_PRIV_CONTAINS_COMMA(ML99_PRIV_COMMA seq)) +#define ML99_SEQ_GET(i) ML99_PRIV_CAT(ML99_PRIV_SEQ_GET_, i) +#define ML99_SEQ_TAIL(seq) ML99_PRIV_TAIL(ML99_PRIV_COMMA seq) + +#ifndef DOXYGEN_IGNORE + +#define ML99_seqIsEmpty_IMPL(seq) v(ML99_SEQ_IS_EMPTY(seq)) + +#define ML99_PRIV_seqGet_0(seq) ML99_call(ML99_PRIV_seqGet_0, seq) +#define ML99_PRIV_seqGet_1(seq) ML99_call(ML99_PRIV_seqGet_1, seq) +#define ML99_PRIV_seqGet_2(seq) ML99_call(ML99_PRIV_seqGet_2, seq) +#define ML99_PRIV_seqGet_3(seq) ML99_call(ML99_PRIV_seqGet_3, seq) +#define ML99_PRIV_seqGet_4(seq) ML99_call(ML99_PRIV_seqGet_4, seq) +#define ML99_PRIV_seqGet_5(seq) ML99_call(ML99_PRIV_seqGet_5, seq) +#define ML99_PRIV_seqGet_6(seq) ML99_call(ML99_PRIV_seqGet_6, seq) +#define ML99_PRIV_seqGet_7(seq) ML99_call(ML99_PRIV_seqGet_7, seq) + +#define ML99_PRIV_seqGet_0_IMPL(seq) v(ML99_SEQ_GET(0)(seq)) +#define ML99_PRIV_seqGet_1_IMPL(seq) v(ML99_SEQ_GET(1)(seq)) +#define ML99_PRIV_seqGet_2_IMPL(seq) v(ML99_SEQ_GET(2)(seq)) +#define ML99_PRIV_seqGet_3_IMPL(seq) v(ML99_SEQ_GET(3)(seq)) +#define ML99_PRIV_seqGet_4_IMPL(seq) v(ML99_SEQ_GET(4)(seq)) +#define ML99_PRIV_seqGet_5_IMPL(seq) v(ML99_SEQ_GET(5)(seq)) +#define ML99_PRIV_seqGet_6_IMPL(seq) v(ML99_SEQ_GET(6)(seq)) +#define ML99_PRIV_seqGet_7_IMPL(seq) v(ML99_SEQ_GET(7)(seq)) + +#define ML99_PRIV_SEQ_GET_0(seq) ML99_PRIV_UNTUPLE(ML99_PRIV_HEAD(ML99_PRIV_SEQ_SEPARATE seq)) +#define ML99_PRIV_SEQ_GET_1(seq) ML99_PRIV_SEQ_GET_0(ML99_SEQ_TAIL(seq)) +#define ML99_PRIV_SEQ_GET_2(seq) ML99_PRIV_SEQ_GET_1(ML99_SEQ_TAIL(seq)) +#define ML99_PRIV_SEQ_GET_3(seq) ML99_PRIV_SEQ_GET_2(ML99_SEQ_TAIL(seq)) +#define ML99_PRIV_SEQ_GET_4(seq) ML99_PRIV_SEQ_GET_3(ML99_SEQ_TAIL(seq)) +#define ML99_PRIV_SEQ_GET_5(seq) ML99_PRIV_SEQ_GET_4(ML99_SEQ_TAIL(seq)) +#define ML99_PRIV_SEQ_GET_6(seq) ML99_PRIV_SEQ_GET_5(ML99_SEQ_TAIL(seq)) +#define ML99_PRIV_SEQ_GET_7(seq) ML99_PRIV_SEQ_GET_6(ML99_SEQ_TAIL(seq)) + +#define ML99_PRIV_SEQ_SEPARATE(...) (__VA_ARGS__), + +#define ML99_seqTail_IMPL(seq) v(ML99_SEQ_TAIL(seq)) + +#define ML99_seqForEach_IMPL(f, seq) \ + ML99_PRIV_CAT(ML99_PRIV_seqForEach_, ML99_SEQ_IS_EMPTY(seq))(f, seq) +#define ML99_PRIV_seqForEach_1(...) v(ML99_PRIV_EMPTY()) +#define ML99_PRIV_seqForEach_0(f, seq) \ + ML99_TERMS( \ + ML99_appl_IMPL(f, ML99_SEQ_GET(0)(seq)), \ + ML99_callUneval(ML99_seqForEach, f, ML99_SEQ_TAIL(seq))) + +#define ML99_seqForEachI_IMPL(f, seq) ML99_PRIV_seqForEachIAux_IMPL(f, 0, seq) +#define ML99_PRIV_seqForEachIAux_IMPL(f, i, seq) \ + ML99_PRIV_CAT(ML99_PRIV_seqForEachI_, ML99_SEQ_IS_EMPTY(seq))(f, i, seq) +#define ML99_PRIV_seqForEachI_1(...) v(ML99_PRIV_EMPTY()) +#define ML99_PRIV_seqForEachI_0(f, i, seq) \ + ML99_TERMS( \ + ML99_appl2_IMPL(f, i, ML99_SEQ_GET(0)(seq)), \ + ML99_callUneval(ML99_PRIV_seqForEachIAux, f, ML99_PRIV_INC(i), ML99_SEQ_TAIL(seq))) + +// Arity specifiers { + +#define ML99_seqIsEmpty_ARITY 1 +#define ML99_seqTail_ARITY 1 +#define ML99_seqForEach_ARITY 2 +#define ML99_seqForEachI_ARITY 2 + +#define ML99_PRIV_seqGet_0_ARITY 1 +#define ML99_PRIV_seqGet_1_ARITY 1 +#define ML99_PRIV_seqGet_2_ARITY 1 +#define ML99_PRIV_seqGet_3_ARITY 1 +#define ML99_PRIV_seqGet_4_ARITY 1 +#define ML99_PRIV_seqGet_5_ARITY 1 +#define ML99_PRIV_seqGet_6_ARITY 1 +#define ML99_PRIV_seqGet_7_ARITY 1 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_SEQ_H diff --git a/test/external/metalang99/include/metalang99/stmt.h b/test/external/metalang99/include/metalang99/stmt.h new file mode 100644 index 0000000..54bb28f --- /dev/null +++ b/test/external/metalang99/include/metalang99/stmt.h @@ -0,0 +1,167 @@ +/** + * @file + * Statement chaining. + * + * This module exports a bunch of so-called _statement chaining macros_: they expect a statement + * right after their invocation, and moreover, an invocation of such a macro with a statement + * afterwards altogether form a single statement. + * + * How can this be helpful? Imagine you are writing a macro with the following syntax: + * + * @code + * MY_MACRO(...) { bla bla bla } + * @endcode + * + * Then `MY_MACRO` must expand to a _statement prefix_, i.e., something that expects a statement + * after itself. One possible solution is to make `MY_MACRO` expand to a sequence of statement + * chaining macros like this: + * + * @code + * #define MY_MACRO(...) \ + * ML99_INTRODUCE_VAR_TO_STMT(int x = 5) \ + * ML99_CHAIN_EXPR_STMT(printf("%d\n", x)) \ + * // and so on... + * @endcode + * + * Here #ML99_INTRODUCE_VAR_TO_STMT accepts the statement formed by #ML99_CHAIN_EXPR_STMT, which, in + * turn, accepts the next statement and so on, until a caller of `MY_MACRO` specifies the final + * statement, thus completing the chain. + * + * @see https://www.chiark.greenend.org.uk/~sgtatham/mp/ for a more involved explanation. + */ + +#ifndef ML99_STMT_H +#define ML99_STMT_H + +#include <metalang99/util.h> + +/** + * A statement chaining macro that introduces several variable definitions to a statement right + * after its invocation. + * + * Variable definitions must be specified as in the first clause of the for-loop. + * + * Top-level `break`/`continue` inside a user-provided statement are prohibited. + * + * # Example + * + * @code + * #include <metalang99/stmt.h> + * + * for (int i = 0; i < 10; i++) + * ML99_INTRODUCE_VAR_TO_STMT(double x = 5.0, y = 7.0) + * if (i % 2 == 0) + * printf("i = %d, x = %f, y = %f\n", i, x, y); + * @endcode + */ +#define ML99_INTRODUCE_VAR_TO_STMT(...) ML99_PRIV_INTRODUCE_VAR_TO_STMT_INNER(__VA_ARGS__) + +/** + * The same as #ML99_INTRODUCE_VAR_TO_STMT but deals with a single non-`NULL` pointer. + * + * In comparison with #ML99_INTRODUCE_VAR_TO_STMT, this macro generates a little less code. It + * introduces a pointer to @p ty identified by @p name and initialized to @p init. + * + * Top-level `break`/`continue` inside a user-provided statement are prohibited. + * + * # Example + * + * @code + * #include <metalang99/stmt.h> + * + * double x = 5.0, y = 7.0; + * + * for (int i = 0; i < 10; i++) + * ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(double, x_ptr, &x) + * ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(double, y_ptr, &y) + * printf("i = %d, x = %f, y = %f\n", i, *x_ptr, *y_ptr); + * @endcode + * + * @note Unlike #ML99_INTRODUCE_VAR_TO_STMT, the generated pointer is guaranteed to be used at least + * once, meaning that you do not need to suppress the unused variable warning. + * @note @p init is guaranteed to be executed only once. + */ +#define ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(ty, name, init) \ + ML99_PRIV_SHADOWS(for (ty *name = (init); name != 0; name = 0)) + +/** + * A statement chaining macro that executes an expression statement derived from @p expr right + * before the next statement. + * + * Top-level `break`/`continue` inside a user-provided statement are prohibited. + * + * # Example + * + * @code + * #include <metalang99/stmt.h> + * + * int x; + * + * for(;;) + * ML99_CHAIN_EXPR_STMT(x = 5) + * ML99_CHAIN_EXPR_STMT(printf("%d\n", x)) + * puts("abc"); + * @endcode + */ +#define ML99_CHAIN_EXPR_STMT(expr) \ + ML99_PRIV_SHADOWS(for (int ml99_priv_expr_stmt_break = ((expr), 0); \ + ml99_priv_expr_stmt_break != 1; \ + ml99_priv_expr_stmt_break = 1)) + +/** + * The same as #ML99_CHAIN_EXPR_STMT but executes @p expr **after** the next statement. + */ +#define ML99_CHAIN_EXPR_STMT_AFTER(expr) \ + ML99_PRIV_SHADOWS(for (int ml99_priv_expr_stmt_after_break = 0; \ + ml99_priv_expr_stmt_after_break != 1; \ + ((expr), ml99_priv_expr_stmt_after_break = 1))) + +/** + * A statement chaining macro that suppresses the "unused X" warning right before a statement after + * its invocation. + * + * Top-level `break`/`continue` inside a user-provided statement are prohibited. + * + * # Example + * + * @code + * #include <metalang99/stmt.h> + * + * int x, y; + * + * for(;;) + * ML99_SUPPRESS_UNUSED_BEFORE_STMT(x) + * ML99_SUPPRESS_UNUSED_BEFORE_STMT(y) + * puts("abc"); + * @endcode + * + * @deprecated Use `ML99_CHAIN_EXPR_STMT((void)expr)` instead. + */ +#define ML99_SUPPRESS_UNUSED_BEFORE_STMT(expr) ML99_CHAIN_EXPR_STMT((void)expr) + +#ifndef DOXYGEN_IGNORE + +// See <https://github.com/hirrolot/metalang99/issues/25>. +#ifdef __cplusplus +#define ML99_PRIV_INTRODUCE_VAR_TO_STMT_INNER(...) \ + ML99_PRIV_SHADOWS(for (__VA_ARGS__, \ + *ml99_priv_break_arr[] = {0, 0}, \ + **ml99_priv_break = &ml99_priv_break_arr[0]; \ + ml99_priv_break == &ml99_priv_break_arr[0]; \ + ml99_priv_break++)) +#else +#define ML99_PRIV_INTRODUCE_VAR_TO_STMT_INNER(...) \ + ML99_PRIV_SHADOWS(for (__VA_ARGS__, *ml99_priv_break = (void *)0; \ + ml99_priv_break != (void *)1; \ + ml99_priv_break = (void *)1)) +#endif + +#define ML99_PRIV_SHADOWS(...) \ + ML99_CLANG_PRAGMA("clang diagnostic push") \ + ML99_CLANG_PRAGMA("clang diagnostic ignored \"-Wshadow\"") \ + __VA_ARGS__ \ + ML99_CLANG_PRAGMA("clang diagnostic pop") + +#endif // DOXYGEN_IGNORE + +#endif // ML99_STMT_H diff --git a/test/external/metalang99/include/metalang99/tuple.h b/test/external/metalang99/include/metalang99/tuple.h new file mode 100644 index 0000000..da92298 --- /dev/null +++ b/test/external/metalang99/include/metalang99/tuple.h @@ -0,0 +1,371 @@ +/** + * @file + * Tuples: `(x, y, z)`. + * + * A tuple is represented as `(x1, ..., xN)`. Tuples are a convenient way to deal with product + * types. For example: + * + * [[examples/rectangle.c](https://github.com/hirrolot/metalang99/blob/master/examples/rectangle.c)] + * @include rectangle.c + * + * @note Tuples are more time and space-efficient than lists, but export less functionality; if a + * needed function is missed, invoking #ML99_list and then manipulating with the resulting Cons-list + * might be helpful. + */ + +#ifndef ML99_TUPLE_H +#define ML99_TUPLE_H + +#include <metalang99/priv/bool.h> +#include <metalang99/priv/tuple.h> +#include <metalang99/priv/util.h> + +#include <metalang99/lang.h> +#include <metalang99/variadics.h> + +/** + * Transforms a sequence of arguments into `(...)`. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // (1, 2, 3) + * ML99_tuple(v(1, 2, 3)) + * @endcode + */ +#define ML99_tuple(...) ML99_call(ML99_tuple, __VA_ARGS__) + +/** + * Transforms a sequence of arguments into `(v(...))`. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // (v(1, 2, 3)) + * ML99_tupleEval(v(1, 2, 3)) + * @endcode + * + * @deprecated I have seen no single use case over time. Please, [open an + * issue](https://github.com/hirrolot/metalang99/issues/new/choose) if you need this function. + */ +#define ML99_tupleEval(...) ML99_call(ML99_tupleEval, __VA_ARGS__) + +/** + * Untuples the tuple @p x, leaving the result unevaluated. + * + * If @p x is not a tuple, it emits a fatal error. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // 1, 2, 3 + * ML99_untuple(v((1, 2, 3))) + * @endcode + */ +#define ML99_untuple(x) ML99_call(ML99_untuple, x) + +/** + * The same as #ML99_untuple. + * + * @deprecated Use #ML99_untuple instead. + */ +#define ML99_untupleChecked(x) ML99_call(ML99_untupleChecked, x) + +/** + * Untuples the tuple @p x and evaluates the result. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // 1, 2, 3 + * ML99_untupleEval(v((v(1, 2, 3)))) + * @endcode + * + * @deprecated For the same reason as #ML99_tupleEval. + */ +#define ML99_untupleEval(x) ML99_call(ML99_untupleEval, x) + +/** + * Tests whether @p x is inside parentheses or not. + * + * The preconditions are the same as of #ML99_isUntuple. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // 0 + * ML99_isTuple(v(123)) + * + * // 1 + * ML99_isTuple(v((123))) + * @endcode + */ +#define ML99_isTuple(x) ML99_call(ML99_isTuple, x) + +/** + * The inverse of #ML99_isTuple. + * + * @p x must be either of these forms: + * - `(...)` (reported as non-untupled) + * - `(...) (...) ...` (reported as untupled) + * - anything else not beginning with `(...)` (reported as untupled) + * + * For example (respectively): + * - `(~, ~, ~)` (non-untupled) + * - `(~, ~, ~) (~, ~, ~)` or `(~, ~, ~) (~, ~, ~) abc` (untupled) + * - `123` or `123 (~, ~, ~)` (untupled) + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // 1 + * ML99_isUntuple(v(123)) + * + * // 0 + * ML99_isUntuple(v((123))) + * + * // 1 + * ML99_isUntuple(v((123) (456) (789))) + * @endcode + */ +#define ML99_isUntuple(x) ML99_call(ML99_isUntuple, x) + +/** + * Computes the count of items in the tuple @p x. + * + * At most 63 items can be contained in @p x. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // 3 + * ML99_tupleCount(v((~, ~, ~))) + * + * // 1 + * ML99_tupleCount(v(())) + * @endcode + */ +#define ML99_tupleCount(x) ML99_call(ML99_tupleCount, x) + +/** + * Tells if the tuple @p x contains only one item or not. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // 1 + * ML99_tupleIsSingle(v((~))) + * + * // 0 + * ML99_tupleIsSingle(v((~, ~, ~))) + * @endcode + */ +#define ML99_tupleIsSingle(x) ML99_call(ML99_tupleIsSingle, x) + +/** + * Expands to a metafunction extracting the @p i -indexed element of a tuple. + * + * @p i can range from 0 to 7, inclusively. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // 2 + * ML99_tupleGet(1)(v((1, 2, 3))) + * @endcode + */ +#define ML99_tupleGet(i) ML99_PRIV_CAT(ML99_PRIV_tupleGet_, i) + +/** + * Extracts the tuple's tail. + * + * @p x must contain at least two elements. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // 2, 3 + * ML99_tupleTail(v((1, 2, 3))) + * @endcode + */ +#define ML99_tupleTail(x) ML99_call(ML99_tupleTail, x) + +/** + * Appends provided variadic arguments to the tuple @p x. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // (1, 2, 3) + * ML99_tupleAppend(ML99_tuple(v(1)), v(2, 3)) + * @endcode + */ +#define ML99_tupleAppend(x, ...) ML99_call(ML99_tupleAppend, x, __VA_ARGS__) + +/** + * Prepends provided variadic arguments to the tuple @p x. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * // (1, 2, 3) + * ML99_tuplePrepend(ML99_tuple(v(3)), v(1, 2)) + * @endcode + */ +#define ML99_tuplePrepend(x, ...) ML99_call(ML99_tuplePrepend, x, __VA_ARGS__) + +/** + * A shortcut for `ML99_variadicsForEach(f, ML99_untuple(x))`. + */ +#define ML99_tupleForEach(f, x) ML99_call(ML99_tupleForEach, f, x) + +/** + * A shortcut for `ML99_variadicsForEachI(f, ML99_untuple(x))`. + */ +#define ML99_tupleForEachI(f, x) ML99_call(ML99_tupleForEachI, f, x) + +/** + * Emits a fatal error if @p x is not a tuple, otherwise results in emptiness. + * + * # Examples + * + * @code + * #include <metalang99/tuple.h> + * + * #define F_IMPL(x) ML99_TERMS(ML99_assertIsTuple(v(x)), ML99_untuple(v(x))) + * + * // 1, 2, 3 + * ML99_call(F, v((1, 2, 3))) + * + * // A compile-time tuple mismatch error. + * ML99_call(F, v(123)) + * @endcode + */ +#define ML99_assertIsTuple(x) ML99_call(ML99_assertIsTuple, x) + +#define ML99_TUPLE(...) (__VA_ARGS__) +#define ML99_UNTUPLE(x) ML99_PRIV_EXPAND x +#define ML99_IS_TUPLE(x) ML99_PRIV_IS_TUPLE(x) +#define ML99_IS_UNTUPLE(x) ML99_PRIV_IS_UNTUPLE(x) +#define ML99_TUPLE_COUNT(x) ML99_VARIADICS_COUNT(ML99_UNTUPLE(x)) +#define ML99_TUPLE_IS_SINGLE(x) ML99_VARIADICS_IS_SINGLE(ML99_UNTUPLE(x)) +#define ML99_TUPLE_GET(i) ML99_PRIV_CAT(ML99_PRIV_TUPLE_GET_, i) +#define ML99_TUPLE_TAIL(x) ML99_VARIADICS_TAIL(ML99_UNTUPLE(x)) +#define ML99_TUPLE_APPEND(x, ...) (ML99_UNTUPLE(x), __VA_ARGS__) +#define ML99_TUPLE_PREPEND(x, ...) (__VA_ARGS__, ML99_UNTUPLE(x)) + +#ifndef DOXYGEN_IGNORE + +#define ML99_tuple_IMPL(...) v(ML99_TUPLE(__VA_ARGS__)) +#define ML99_tupleEval_IMPL(...) v((v(__VA_ARGS__))) +#define ML99_untuple_IMPL(x) \ + ML99_PRIV_IF(ML99_IS_TUPLE(x), ML99_PRIV_UNTUPLE_TERM, ML99_PRIV_NOT_TUPLE_ERROR)(x) +#define ML99_untupleChecked_IMPL(x) ML99_untuple_IMPL(x) +#define ML99_untupleEval_IMPL(x) ML99_PRIV_EXPAND x +#define ML99_isTuple_IMPL(x) v(ML99_IS_TUPLE(x)) +#define ML99_isUntuple_IMPL(x) v(ML99_IS_UNTUPLE(x)) +#define ML99_tupleCount_IMPL(x) v(ML99_TUPLE_COUNT(x)) +#define ML99_tupleIsSingle_IMPL(x) v(ML99_TUPLE_IS_SINGLE(x)) + +#define ML99_PRIV_UNTUPLE_TERM(x) v(ML99_UNTUPLE(x)) + +#define ML99_PRIV_tupleGet_0(x) ML99_call(ML99_PRIV_tupleGet_0, x) +#define ML99_PRIV_tupleGet_1(x) ML99_call(ML99_PRIV_tupleGet_1, x) +#define ML99_PRIV_tupleGet_2(x) ML99_call(ML99_PRIV_tupleGet_2, x) +#define ML99_PRIV_tupleGet_3(x) ML99_call(ML99_PRIV_tupleGet_3, x) +#define ML99_PRIV_tupleGet_4(x) ML99_call(ML99_PRIV_tupleGet_4, x) +#define ML99_PRIV_tupleGet_5(x) ML99_call(ML99_PRIV_tupleGet_5, x) +#define ML99_PRIV_tupleGet_6(x) ML99_call(ML99_PRIV_tupleGet_6, x) +#define ML99_PRIV_tupleGet_7(x) ML99_call(ML99_PRIV_tupleGet_7, x) + +#define ML99_PRIV_tupleGet_0_IMPL(x) v(ML99_TUPLE_GET(0)(x)) +#define ML99_PRIV_tupleGet_1_IMPL(x) v(ML99_TUPLE_GET(1)(x)) +#define ML99_PRIV_tupleGet_2_IMPL(x) v(ML99_TUPLE_GET(2)(x)) +#define ML99_PRIV_tupleGet_3_IMPL(x) v(ML99_TUPLE_GET(3)(x)) +#define ML99_PRIV_tupleGet_4_IMPL(x) v(ML99_TUPLE_GET(4)(x)) +#define ML99_PRIV_tupleGet_5_IMPL(x) v(ML99_TUPLE_GET(5)(x)) +#define ML99_PRIV_tupleGet_6_IMPL(x) v(ML99_TUPLE_GET(6)(x)) +#define ML99_PRIV_tupleGet_7_IMPL(x) v(ML99_TUPLE_GET(7)(x)) + +#define ML99_PRIV_TUPLE_GET_0(x) ML99_VARIADICS_GET(0)(ML99_UNTUPLE(x)) +#define ML99_PRIV_TUPLE_GET_1(x) ML99_VARIADICS_GET(1)(ML99_UNTUPLE(x)) +#define ML99_PRIV_TUPLE_GET_2(x) ML99_VARIADICS_GET(2)(ML99_UNTUPLE(x)) +#define ML99_PRIV_TUPLE_GET_3(x) ML99_VARIADICS_GET(3)(ML99_UNTUPLE(x)) +#define ML99_PRIV_TUPLE_GET_4(x) ML99_VARIADICS_GET(4)(ML99_UNTUPLE(x)) +#define ML99_PRIV_TUPLE_GET_5(x) ML99_VARIADICS_GET(5)(ML99_UNTUPLE(x)) +#define ML99_PRIV_TUPLE_GET_6(x) ML99_VARIADICS_GET(6)(ML99_UNTUPLE(x)) +#define ML99_PRIV_TUPLE_GET_7(x) ML99_VARIADICS_GET(7)(ML99_UNTUPLE(x)) + +#define ML99_tupleTail_IMPL(x) v(ML99_TUPLE_TAIL(x)) + +#define ML99_tupleAppend_IMPL(x, ...) v(ML99_TUPLE_APPEND(x, __VA_ARGS__)) +#define ML99_tuplePrepend_IMPL(x, ...) v(ML99_TUPLE_PREPEND(x, __VA_ARGS__)) +#define ML99_tupleForEach_IMPL(f, x) ML99_variadicsForEach_IMPL(f, ML99_UNTUPLE(x)) +#define ML99_tupleForEachI_IMPL(f, x) ML99_variadicsForEachI_IMPL(f, ML99_UNTUPLE(x)) + +#define ML99_assertIsTuple_IMPL(x) \ + ML99_PRIV_IF(ML99_IS_UNTUPLE(x), ML99_PRIV_NOT_TUPLE_ERROR(x), v(ML99_PRIV_EMPTY())) + +// clang-format off +#define ML99_PRIV_NOT_TUPLE_ERROR(x) \ + ML99_PRIV_IF( \ + ML99_PRIV_IS_DOUBLE_TUPLE_BEGINNING(x), \ + ML99_fatal(ML99_assertIsTuple, x must be (x1, ..., xN), did you miss a comma?), \ + ML99_fatal(ML99_assertIsTuple, x must be (x1, ..., xN))) +// clang-format on + +// Arity specifiers { + +#define ML99_tuple_ARITY 1 +#define ML99_tupleEval_ARITY 1 +#define ML99_untuple_ARITY 1 +#define ML99_untupleChecked_ARITY 1 +#define ML99_untupleEval_ARITY 1 +#define ML99_isTuple_ARITY 1 +#define ML99_isUntuple_ARITY 1 +#define ML99_tupleCount_ARITY 1 +#define ML99_tupleIsSingle_ARITY 1 +#define ML99_tupleTail_ARITY 1 +#define ML99_tupleAppend_ARITY 2 +#define ML99_tuplePrepend_ARITY 2 +#define ML99_tupleForEach_ARITY 2 +#define ML99_tupleForEachI_ARITY 2 +#define ML99_assertIsTuple_ARITY 1 + +#define ML99_PRIV_tupleGet_0_ARITY 1 +#define ML99_PRIV_tupleGet_1_ARITY 1 +#define ML99_PRIV_tupleGet_2_ARITY 1 +#define ML99_PRIV_tupleGet_3_ARITY 1 +#define ML99_PRIV_tupleGet_4_ARITY 1 +#define ML99_PRIV_tupleGet_5_ARITY 1 +#define ML99_PRIV_tupleGet_6_ARITY 1 +#define ML99_PRIV_tupleGet_7_ARITY 1 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_TUPLE_H diff --git a/test/external/metalang99/include/metalang99/util.h b/test/external/metalang99/include/metalang99/util.h new file mode 100644 index 0000000..b4be573 --- /dev/null +++ b/test/external/metalang99/include/metalang99/util.h @@ -0,0 +1,444 @@ +/** + * @file + * Utilitary stuff. + */ + +#ifndef ML99_UTIL_H +#define ML99_UTIL_H + +#include <metalang99/priv/util.h> + +#include <metalang99/ident.h> // For backwards compatibility. +#include <metalang99/lang.h> + +/** + * Concatenates @p a with @p b and evaluates the result. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * #define ABC123 v(Billie Jean) + * + * // Billie Jean + * ML99_catEval(v(ABC), v(123)) + * + * // ERROR: 123ABC is not a valid Metalang99 term. + * ML99_catEval(v(123), v(ABC)) + * @endcode + * + * @deprecated I have seen no single use case over time. Please, [open an + * issue](https://github.com/hirrolot/metalang99/issues/new/choose) if you need this function. + */ +#define ML99_catEval(a, b) ML99_call(ML99_catEval, a, b) + +/** + * Concatenates @p a with @p b, leaving the result unevaluated. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * #define ABC123 Billie Jean + * + * // Billie Jean + * ML99_cat(v(ABC), v(123)) + * + * // 123ABC + * ML99_cat(v(123), v(ABC)) + * @endcode + */ +#define ML99_cat(a, b) ML99_call(ML99_cat, a, b) + +/** + * The same as #ML99_cat but deals with 3 parameters. + */ +#define ML99_cat3(a, b, c) ML99_call(ML99_cat3, a, b, c) + +/** + * The same as #ML99_cat but deals with 4 parameters. + */ +#define ML99_cat4(a, b, c, d) ML99_call(ML99_cat4, a, b, c, d) + +/** + * Stringifies provided arguments. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // "Billie Jean" + * ML99_stringify(v(Billie Jean)) + * @endcode + */ +#define ML99_stringify(...) ML99_call(ML99_stringify, __VA_ARGS__) + +/** + * Evaluates to nothing. + */ +#define ML99_empty(...) ML99_callUneval(ML99_empty, ) + +/** + * Evaluates to its arguments. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // 1, 2, 3 + * ML99_id(v(1, 2, 3)) + * @endcode + */ +#define ML99_id(...) ML99_call(ML99_id, __VA_ARGS__) + +/** + * Evaluates to @p x, skipping @p a. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // 123 + * ML99_const(v(123), v(5)) + * @endcode + */ +#define ML99_const(x, a) ML99_call(ML99_const, x, a) + +/** + * Reverses the order of arguments of the binary function @p f. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // ABC123 + * ML99_appl2(ML99_flip(v(ML99_catUnevaluated)), v(123), v(ABC)) + * @endcode + */ +#define ML99_flip(f) ML99_call(ML99_flip, f) + +/** + * Accepts terms and evaluates them with the space-separator. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // 1 2 3 + * ML99_uncomma(ML99_QUOTE(v(1), v(2), v(3))) + * @endcode + */ +#define ML99_uncomma(...) ML99_call(ML99_uncomma, __VA_ARGS__) + +/** + * Turns @p f into a Metalang99-compliant metafunction with the arity of 1, which can be then called + * by #ML99_appl. + * + * @p f can be any C function or function-like macro. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * #include <metalang99/variadics.h> + * + * #define F(x) @x + * + * // @1 @2 @3 + * ML99_variadicsForEach(ML99_reify(v(F)), v(1, 2, 3)) + * @endcode + * + * Without #ML99_reify, you would need to write some additional boilerplate: + * + * @code + * #define F_IMPL(x) v(@x) + * #define F_ARITY 1 + * @endcode + */ +#define ML99_reify(f) ML99_call(ML99_reify, f) + +/** + * Indicates not yet implemented functionality of the macro @p f. + * + * #ML99_todo is the same as #ML99_unimplemented except that the former conveys an intent that the + * functionality is to be implemented later but #ML99_unimplemented makes no such claims. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // A not-yet implemented error. + * ML99_todo(v(F)) + * @endcode + * + * @see [Rust's std::todo\!](https://doc.rust-lang.org/core/macro.todo.html) (thanks for the idea!) + */ +#define ML99_todo(f) ML99_call(ML99_todo, f) + +/** + * The same as #ML99_todo but emits a caller-supplied message. + * + * @p message must be a string literal. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // A not-yet-implemented error. + * ML99_todoWithMsg(v(F), v("your message")) + * @endcode + */ +#define ML99_todoWithMsg(f, message) ML99_call(ML99_todoWithMsg, f, message) + +/** + * Indicates unimplemented functionality of the macro @p f. + * + * #ML99_unimplemented is the same as #ML99_todo except that the latter conveys an intent that the + * functionality is to be implemented later but #ML99_unimplemented makes no such claims. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // A not-implemented error. + * ML99_unimplemented(v(F)) + * @endcode + * + * @see [Rust's std::unimplemented\!](https://doc.rust-lang.org/core/macro.unimplemented.html) + * (thanks for the idea!) + */ +#define ML99_unimplemented(f) ML99_call(ML99_unimplemented, f) + +/** + * The same as #ML99_unimplemented but emits a caller-supplied message. + * + * @p message must be a string literal. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // A not-implemented error. + * ML99_unimplementedWithMsg(v(F), v("your message")) + * @endcode + */ +#define ML99_unimplementedWithMsg(f, message) ML99_call(ML99_unimplementedWithMsg, f, message) + +#ifdef __COUNTER__ + +/** + * Generates a unique identifier @p id in the namespace @p prefix. + * + * Let `FOO` be the name of an enclosing macro. Then `FOO_` must be specified for @p prefix, and @p + * id should be given any meaningful name (this makes debugging easier). + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * #define FOO(...) FOO_NAMED(ML99_GEN_SYM(FOO_, x), __VA_ARGS__) + * #define FOO_NAMED(x_sym, ...) \ + * do { int x_sym = 5; __VA_ARGS__ } while (0) + * + * // `x` here will not conflict with the `x` inside `FOO`. + * FOO({ + * int x = 7; + * printf("x is %d\n", x); // x is 7 + * }); + * @endcode + * + * @note Two identical calls to #ML99_GEN_SYM will yield different identifiers, therefore, to refer + * to the result later, you must save it in an auxiliary macro's parameter, as shown in the example + * above. + * @note #ML99_GEN_SYM is defined only if `__COUNTER__` is defined, which must be a macro yielding + * integral literals starting from 0 incremented by 1 each time it is called. Currently, it is + * supported at least by Clang, GCC, TCC, and MSVC. + * @see https://en.wikipedia.org/wiki/Hygienic_macro + */ +#define ML99_GEN_SYM(prefix, id) ML99_CAT4(prefix, id, _, __COUNTER__) + +#endif // __COUNTER__ + +/** + * Forces a caller to put a trailing semicolon. + * + * It is useful when defining macros, to make them formatted as complete statements. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * #define MY_MACRO(fn_name, val_ty, val) \ + * inline static val_ty fn_name(void) { return val; } \ + * ML99_TRAILING_SEMICOLON() + * + * // Defines a function that always returns 0. + * MY_MACRO(zero, int, 0); + * @endcode + * + * @note #ML99_TRAILING_SEMICOLON is to be used outside of functions: unlike the `do { ... } while + * (0)` idiom, this macro expands to a C declaration. + */ +#define ML99_TRAILING_SEMICOLON(...) struct ml99_priv_trailing_semicolon + +/** + * Concatenates @p a with @p b as-is, without expanding them. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // This macro will not be expanded. + * #define ABC 7 + * + * // ABC123 + * ML99_CAT_PRIMITIVE(ABC, 123) + * @endcode + */ +#define ML99_CAT_PRIMITIVE(a, b) a##b + +/** + * The same as #ML99_CAT_PRIMITIVE but deals with 3 parameters. + */ +#define ML99_CAT3_PRIMITIVE(a, b, c) a##b##c + +/** + * The same as #ML99_CAT_PRIMITIVE but deals with 4 parameters. + */ +#define ML99_CAT4_PRIMITIVE(a, b, c, d) a##b##c##d + +/** + * Stringifies @p x as-is, without expanding it. + * + * # Examples + * + * @code + * #include <metalang99/util.h> + * + * // This macro will not be expanded. + * #define ABC 7 + * + * // "ABC" + * ML99_STRINGIFY_PRIMITIVE(ABC) + * @endcode + */ +#define ML99_STRINGIFY_PRIMITIVE(...) #__VA_ARGS__ + +/** + * Expands to an opening parenthesis (`(`). + * + * This is helpful when you want to delay macro arguments passing: just type `BAR ML99_LPAREN() + * initial args...` at the end of some macro `FOO` and complete the invocation of `BAR` with + * `the rest of args...)` in future. + * + * This macro consumes all its arguments. + * + * @deprecated This macro results in code that is difficult to reason about. + */ +#define ML99_LPAREN(...) ( + +/** + * The same as #ML99_LPAREN but emits a closing parenthesis. + * + * @deprecated For the same reason as #ML99_LPAREN. + */ +#define ML99_RPAREN(...) ) + +/** + * Expands to a single comma, consuming all arguments. + */ +#define ML99_COMMA(...) , + +/** + * If you are compiling on GCC, this macro expands to `_Pragma(str)`, otherwise to emptiness. + */ +#define ML99_GCC_PRAGMA(str) ML99_PRIV_GCC_PRAGMA(str) + +/** + * The same as #ML99_GCC_PRAGMA but for Clang. + */ +#define ML99_CLANG_PRAGMA(str) ML99_PRIV_CLANG_PRAGMA(str) + +#define ML99_CAT(a, b) ML99_CAT_PRIMITIVE(a, b) +#define ML99_CAT3(a, b, c) ML99_CAT3_PRIMITIVE(a, b, c) +#define ML99_CAT4(a, b, c, d) ML99_CAT4_PRIMITIVE(a, b, c, d) +#define ML99_STRINGIFY(...) ML99_STRINGIFY_PRIMITIVE(__VA_ARGS__) +#define ML99_EMPTY(...) +#define ML99_ID(...) __VA_ARGS__ + +#ifndef DOXYGEN_IGNORE + +#define ML99_catEval_IMPL(a, b) a##b +#define ML99_cat_IMPL(a, b) v(a##b) +#define ML99_cat3_IMPL(a, b, c) v(a##b##c) +#define ML99_cat4_IMPL(a, b, c, d) v(a##b##c##d) +#define ML99_stringify_IMPL(...) v(ML99_STRINGIFY(__VA_ARGS__)) +#define ML99_empty_IMPL(...) v(ML99_EMPTY()) +#define ML99_id_IMPL(...) v(ML99_ID(__VA_ARGS__)) +#define ML99_const_IMPL(x, _a) v(x) +#define ML99_flip_IMPL(f) ML99_appl_IMPL(ML99_PRIV_flip, f) +#define ML99_PRIV_flip_IMPL(f, a, b) ML99_appl2_IMPL(f, b, a) +#define ML99_uncomma_IMPL(...) __VA_ARGS__ + +#define ML99_reify_IMPL(f) ML99_appl_IMPL(ML99_PRIV_reify, f) +#define ML99_PRIV_reify_IMPL(f, ...) v(f(__VA_ARGS__)) + +// clang-format off +#define ML99_todo_IMPL(f) ML99_fatal(f, not yet implemented) +#define ML99_todoWithMsg_IMPL(f, message) ML99_fatal(f, not yet implemented: message) + +#define ML99_unimplemented_IMPL(f) ML99_fatal(f, not implemented) +#define ML99_unimplementedWithMsg_IMPL(f, message) ML99_fatal(f, not implemented: message) +// clang-format on + +#if defined(__GNUC__) && !defined(__clang__) +#define ML99_PRIV_GCC_PRAGMA(str) _Pragma(str) +#else +#define ML99_PRIV_GCC_PRAGMA(str) +#endif + +#if defined(__clang__) +#define ML99_PRIV_CLANG_PRAGMA(str) _Pragma(str) +#else +#define ML99_PRIV_CLANG_PRAGMA(str) +#endif + +// Arity specifiers { + +#define ML99_catEval_ARITY 2 +#define ML99_cat_ARITY 2 +#define ML99_cat3_ARITY 3 +#define ML99_cat4_ARITY 4 +#define ML99_stringify_ARITY 1 +#define ML99_empty_ARITY 1 +#define ML99_id_ARITY 1 +#define ML99_const_ARITY 2 +#define ML99_flip_ARITY 1 +#define ML99_uncomma_ARITY 1 +#define ML99_reify_ARITY 1 +#define ML99_todo_ARITY 1 +#define ML99_todoWithMsg_ARITY 2 +#define ML99_unimplemented_ARITY 1 +#define ML99_unimplementedWithMsg_ARITY 2 + +#define ML99_PRIV_flip_ARITY 3 +#define ML99_PRIV_reify_ARITY 2 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_UTIL_H diff --git a/test/external/metalang99/include/metalang99/variadics.h b/test/external/metalang99/include/metalang99/variadics.h new file mode 100644 index 0000000..59b52c4 --- /dev/null +++ b/test/external/metalang99/include/metalang99/variadics.h @@ -0,0 +1,274 @@ +/** + * @file + * Variadic arguments: `x, y, z`. + * + * @note Variadics are more time and space-efficient than lists, but export less functionality; if a + * needed function is missed, invoking #ML99_list and then manipulating with the resulting Cons-list + * might be helpful. + */ + +#ifndef ML99_VARIADICS_H +#define ML99_VARIADICS_H + +#include <metalang99/nat/inc.h> +#include <metalang99/priv/util.h> + +#include <metalang99/lang.h> + +/** + * Computes a count of its arguments. + * + * At most 63 arguments are acceptable. + * + * # Examples + * + * @code + * #include <metalang99/variadics.h> + * + * // 3 + * ML99_variadicsCount(v(~, ~, ~)) + * + * // 1 + * ML99_variadicsCount() + * @endcode + */ +#define ML99_variadicsCount(...) ML99_call(ML99_variadicsCount, __VA_ARGS__) + +/** + * Tells if it received only one argument or not. + * + * # Examples + * + * @code + * #include <metalang99/variadics.h> + * + * // 1 + * ML99_variadicsIsSingle(v(~)) + * + * // 0 + * ML99_variadicsIsSingle(v(~, ~, ~)) + * @endcode + */ +#define ML99_variadicsIsSingle(...) ML99_call(ML99_variadicsIsSingle, __VA_ARGS__) + +/** + * Expands to a metafunction extracting the @p i -indexed argument. + * + * @p i can range from 0 to 7, inclusively. + * + * # Examples + * + * @code + * #include <metalang99/variadics.h> + * + * // 2 + * ML99_variadicsGet(1)(v(1, 2, 3)) + * @endcode + */ +#define ML99_variadicsGet(i) ML99_PRIV_CAT(ML99_PRIV_variadicsGet_, i) + +/** + * Extracts the tail of its arguments. + * + * At least two arguments must be specified. + * + * # Examples + * + * @code + * #include <metalang99/variadics.h> + * + * // 2, 3 + * ML99_variadicsTail(v(1, 2, 3)) + * @endcode + */ +#define ML99_variadicsTail(...) ML99_call(ML99_variadicsTail, __VA_ARGS__) + +/** + * Applies @p f to each argument. + * + * The result is `ML99_appl(f, x1) ... ML99_appl(f, xN)`. + * + * # Examples + * + * @code + * #include <metalang99/variadics.h> + * + * #define F_IMPL(x) v(@x) + * #define F_ARITY 1 + * + * // @x @y @z + * ML99_variadicsForEach(v(F), v(x, y, z)) + * @endcode + */ +#define ML99_variadicsForEach(f, ...) ML99_call(ML99_variadicsForEach, f, __VA_ARGS__) + +/** + * Applies @p f to each argument with an index. + * + * The result is `ML99_appl2(f, x1, 0) ... ML99_appl2(f, xN, N - 1)`. + * + * @code + * #include <metalang99/variadics.h> + * + * #define F_IMPL(x, i) v(@x##i) + * #define F_ARITY 2 + * + * // @x0 @y1 @z2 + * ML99_variadicsForEachI(v(F), v(x, y, z)) + * @endcode + */ +#define ML99_variadicsForEachI(f, ...) ML99_call(ML99_variadicsForEachI, f, __VA_ARGS__) + +/** + * Overloads @p f on a number of arguments. + * + * This function counts the number of provided arguments, appends it to @p f and calls the resulting + * macro identifier with provided arguments. + * + * At most 63 variadic arguments are acceptable. + * + * # Examples + * + * @code + * #include <metalang99/variadics.h> + * + * #define X(...) ML99_OVERLOAD(X_, __VA_ARGS__) + * #define X_1(a) Billie & a + * #define X_2(a, b) Jean & a & b + * + * // Billie & 4 + * X(4) + * + * // Jean & 5 & 6 + * X(5, 6) + * @endcode + * + * @note @p f need not be postfixed with `_IMPL`. It is literally invoked as `ML99_CAT(f, + * ML99_VARIADICS_COUNT(...))(...)`. + */ +#define ML99_OVERLOAD(f, ...) ML99_PRIV_CAT(f, ML99_PRIV_VARIADICS_COUNT(__VA_ARGS__))(__VA_ARGS__) + +#define ML99_VARIADICS_COUNT(...) ML99_PRIV_VARIADICS_COUNT(__VA_ARGS__) +#define ML99_VARIADICS_IS_SINGLE(...) ML99_PRIV_NOT(ML99_PRIV_CONTAINS_COMMA(__VA_ARGS__)) +#define ML99_VARIADICS_GET(i) ML99_PRIV_CAT(ML99_PRIV_VARIADICS_GET_, i) +#define ML99_VARIADICS_TAIL(...) ML99_PRIV_TAIL(__VA_ARGS__) + +#ifndef DOXYGEN_IGNORE + +#define ML99_variadicsCount_IMPL(...) v(ML99_VARIADICS_COUNT(__VA_ARGS__)) +#define ML99_variadicsIsSingle_IMPL(...) v(ML99_VARIADICS_IS_SINGLE(__VA_ARGS__)) + +#define ML99_PRIV_variadicsGet_0(...) ML99_call(ML99_PRIV_variadicsGet_0, __VA_ARGS__) +#define ML99_PRIV_variadicsGet_1(...) ML99_call(ML99_PRIV_variadicsGet_1, __VA_ARGS__) +#define ML99_PRIV_variadicsGet_2(...) ML99_call(ML99_PRIV_variadicsGet_2, __VA_ARGS__) +#define ML99_PRIV_variadicsGet_3(...) ML99_call(ML99_PRIV_variadicsGet_3, __VA_ARGS__) +#define ML99_PRIV_variadicsGet_4(...) ML99_call(ML99_PRIV_variadicsGet_4, __VA_ARGS__) +#define ML99_PRIV_variadicsGet_5(...) ML99_call(ML99_PRIV_variadicsGet_5, __VA_ARGS__) +#define ML99_PRIV_variadicsGet_6(...) ML99_call(ML99_PRIV_variadicsGet_6, __VA_ARGS__) +#define ML99_PRIV_variadicsGet_7(...) ML99_call(ML99_PRIV_variadicsGet_7, __VA_ARGS__) + +#define ML99_PRIV_variadicsGet_0_IMPL(...) v(ML99_VARIADICS_GET(0)(__VA_ARGS__)) +#define ML99_PRIV_variadicsGet_1_IMPL(...) v(ML99_VARIADICS_GET(1)(__VA_ARGS__)) +#define ML99_PRIV_variadicsGet_2_IMPL(...) v(ML99_VARIADICS_GET(2)(__VA_ARGS__)) +#define ML99_PRIV_variadicsGet_3_IMPL(...) v(ML99_VARIADICS_GET(3)(__VA_ARGS__)) +#define ML99_PRIV_variadicsGet_4_IMPL(...) v(ML99_VARIADICS_GET(4)(__VA_ARGS__)) +#define ML99_PRIV_variadicsGet_5_IMPL(...) v(ML99_VARIADICS_GET(5)(__VA_ARGS__)) +#define ML99_PRIV_variadicsGet_6_IMPL(...) v(ML99_VARIADICS_GET(6)(__VA_ARGS__)) +#define ML99_PRIV_variadicsGet_7_IMPL(...) v(ML99_VARIADICS_GET(7)(__VA_ARGS__)) + +#define ML99_PRIV_VARIADICS_GET_0(...) ML99_PRIV_VARIADICS_GET_AUX_0(__VA_ARGS__, ~) +#define ML99_PRIV_VARIADICS_GET_1(...) ML99_PRIV_VARIADICS_GET_AUX_1(__VA_ARGS__, ~) +#define ML99_PRIV_VARIADICS_GET_2(...) ML99_PRIV_VARIADICS_GET_AUX_2(__VA_ARGS__, ~) +#define ML99_PRIV_VARIADICS_GET_3(...) ML99_PRIV_VARIADICS_GET_AUX_3(__VA_ARGS__, ~) +#define ML99_PRIV_VARIADICS_GET_4(...) ML99_PRIV_VARIADICS_GET_AUX_4(__VA_ARGS__, ~) +#define ML99_PRIV_VARIADICS_GET_5(...) ML99_PRIV_VARIADICS_GET_AUX_5(__VA_ARGS__, ~) +#define ML99_PRIV_VARIADICS_GET_6(...) ML99_PRIV_VARIADICS_GET_AUX_6(__VA_ARGS__, ~) +#define ML99_PRIV_VARIADICS_GET_7(...) ML99_PRIV_VARIADICS_GET_AUX_7(__VA_ARGS__, ~) + +#define ML99_PRIV_VARIADICS_GET_AUX_0(a, ...) a +#define ML99_PRIV_VARIADICS_GET_AUX_1(_a, b, ...) b +#define ML99_PRIV_VARIADICS_GET_AUX_2(_a, _b, c, ...) c +#define ML99_PRIV_VARIADICS_GET_AUX_3(_a, _b, _c, d, ...) d +#define ML99_PRIV_VARIADICS_GET_AUX_4(_a, _b, _c, _d, e, ...) e +#define ML99_PRIV_VARIADICS_GET_AUX_5(_a, _b, _c, _d, _e, f, ...) f +#define ML99_PRIV_VARIADICS_GET_AUX_6(_a, _b, _c, _d, _e, _f, g, ...) g +#define ML99_PRIV_VARIADICS_GET_AUX_7(_a, _b, _c, _d, _e, _f, _g, h, ...) h + +#define ML99_variadicsTail_IMPL(...) v(ML99_VARIADICS_TAIL(__VA_ARGS__)) + +// ML99_variadicsForEach_IMPL { + +#define ML99_variadicsForEach_IMPL(f, ...) \ + ML99_PRIV_CAT(ML99_PRIV_variadicsForEach_, ML99_VARIADICS_IS_SINGLE(__VA_ARGS__)) \ + (f, __VA_ARGS__) +#define ML99_PRIV_variadicsForEach_1(f, x) ML99_appl_IMPL(f, x) +#define ML99_PRIV_variadicsForEach_0(f, x, ...) \ + ML99_TERMS(ML99_appl_IMPL(f, x), ML99_callUneval(ML99_variadicsForEach, f, __VA_ARGS__)) +// } (ML99_variadicsForEach_IMPL) + +// ML99_variadicsForEachI_IMPL { + +#define ML99_variadicsForEachI_IMPL(f, ...) ML99_PRIV_variadicsForEachIAux_IMPL(f, 0, __VA_ARGS__) + +#define ML99_PRIV_variadicsForEachIAux_IMPL(f, i, ...) \ + ML99_PRIV_CAT(ML99_PRIV_variadicsForEachI_, ML99_VARIADICS_IS_SINGLE(__VA_ARGS__)) \ + (f, i, __VA_ARGS__) + +#define ML99_PRIV_variadicsForEachI_1(f, i, x) ML99_appl2_IMPL(f, x, i) +#define ML99_PRIV_variadicsForEachI_0(f, i, x, ...) \ + ML99_TERMS( \ + ML99_appl2_IMPL(f, x, i), \ + ML99_callUneval(ML99_PRIV_variadicsForEachIAux, f, ML99_PRIV_INC(i), __VA_ARGS__)) +// } (ML99_variadicsForEachI_IMPL) + +/* + * The StackOverflow solution: <https://stackoverflow.com/a/2124385/13166656>. + * + * This macro supports at most 63 arguments because C99 allows implementations to handle only 127 + * parameters/arguments per macro definition/invocation (C99 | 5.2.4 Environmental limits), and + * `ML99_PRIV_VARIADICS_COUNT_AUX` already accepts 64 arguments. + */ +// clang-format off +#define ML99_PRIV_VARIADICS_COUNT(...) \ + ML99_PRIV_VARIADICS_COUNT_AUX( \ + __VA_ARGS__, \ + 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, \ + 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, \ + 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, \ + 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, \ + 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, \ + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, \ + 3, 2, 1, ~) + +#define ML99_PRIV_VARIADICS_COUNT_AUX( \ + _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \ + _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \ + _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, \ + _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, \ + _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, \ + _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, \ + _61, _62, _63, x, ...) \ + x +// clang-format on + +// Arity specifiers { + +#define ML99_variadicsCount_ARITY 1 +#define ML99_variadicsIsSingle_ARITY 1 +#define ML99_variadicsTail_ARITY 1 +#define ML99_variadicsForEach_ARITY 2 +#define ML99_variadicsForEachI_ARITY 2 + +#define ML99_PRIV_variadicsGet_0_ARITY 1 +#define ML99_PRIV_variadicsGet_1_ARITY 1 +#define ML99_PRIV_variadicsGet_2_ARITY 1 +#define ML99_PRIV_variadicsGet_3_ARITY 1 +#define ML99_PRIV_variadicsGet_4_ARITY 1 +#define ML99_PRIV_variadicsGet_5_ARITY 1 +#define ML99_PRIV_variadicsGet_6_ARITY 1 +#define ML99_PRIV_variadicsGet_7_ARITY 1 +// } (Arity specifiers) + +#endif // DOXYGEN_IGNORE + +#endif // ML99_VARIADICS_H diff --git a/test/external/metalang99/optimization_tips.md b/test/external/metalang99/optimization_tips.md new file mode 100644 index 0000000..261cbe8 --- /dev/null +++ b/test/external/metalang99/optimization_tips.md @@ -0,0 +1,24 @@ +# Optimization tips + +_This document describes a few optimization tips when using Metalang99._ + +Generally speaking, the fewer reduction steps you perform, the faster you become. A reduction step is a concept defined formally by the [specification]. Here is its informal (and imprecise) description: + + - Every `v(...)` is a reduction step. + - Every `ML99_call(op, ...)` induces as many reduction steps as required to evaluate `op` and `...`. + +To perform fewer reduction steps, you can: + + - use `ML99_callUneval`, + - use plain macros (e.g., `ML99_CAT` instead of `ML99_cat`), + - use optimized versions (e.g., `ML99_listMapInPlace`), + - use tuples/variadics instead of lists, + - call a macro as `<X>_IMPL(...)`, if all the arguments are already evaluated. + +<details> + <summary>Be careful with the last trick!</summary> + +I strongly recommend to use the last trick only if `X` is defined locally to a caller so that you can control the correctness of expansion. For example, `X` can become painted blue, it can emit unexpected commas, the `#` and `##` operators can block expansion of parameters, and a plenty of other nasty things. +</details> + +[specification]: spec/spec.pdf diff --git a/test/external/metalang99/scripts/bench.sh b/test/external/metalang99/scripts/bench.sh new file mode 100755 index 0000000..4b26aba --- /dev/null +++ b/test/external/metalang99/scripts/bench.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -e + +bench() { + echo $1 + time gcc bench/$1 -ftrack-macro-expansion=0 -Iinclude -E -P >/dev/null + echo "" +} + +bench "compare_25_items.c" +bench "list_of_63_items.c" +bench "100_v.c" +bench "100_call.c" +bench "many_call_in_arg_pos.c" +bench "filter_map.c" diff --git a/test/external/metalang99/scripts/check-arities.py b/test/external/metalang99/scripts/check-arities.py new file mode 100644 index 0000000..c745a0b --- /dev/null +++ b/test/external/metalang99/scripts/check-arities.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 + +# Make sure that arity specifiers of public metafunctions are consistent with their signatures. + +import os +import re +import xml.etree.ElementTree as ET +import subprocess + +subprocess.call("doxygen > /dev/null 2> /dev/null", shell=True) + + +def check_module(module): + print(f"Checking {module}.h ...") + + tree = ET.parse(f"xml/{module}_8h.xml") + root = tree.getroot() + + arity_specifiers = gather_arity_specifiers(root) + + for metafunction_name, arity in gather_metafunctions(root).items(): + expected_arity = int(arity) + actual_arity = int(arity_specifiers[metafunction_name]) + assert expected_arity == actual_arity + + +def gather_metafunctions(root): + metafunctions = {} + + for definition in root.findall("./compounddef/sectiondef/memberdef"): + macro_name = definition.find("name").text + is_metalang99_compliant = re.search("ML99_[a-z]", macro_name) + + exceptions = { + "ML99_call", "ML99_callUneval", "ML99_fatal", "ML99_abort", "ML99_tupleGet", "ML99_variadicsGet", "ML99_seqGet"} + is_exceptional = macro_name in exceptions + + if (is_metalang99_compliant and not is_exceptional): + arity = len(list(definition.findall("param"))) + metafunctions[macro_name] = arity + + return metafunctions + + +def gather_arity_specifiers(root): + arity_specifiers = {} + + for definition in root.findall("./compounddef/programlisting/codeline/highlight[@class='preprocessor']"): + m = re.match(r"#define(\w+)_ARITY(\d)", "".join(definition.itertext())) + if m is not None: + metafunction_name = m.groups()[0] + arity = m.groups()[1] + arity_specifiers[metafunction_name] = arity + + return arity_specifiers + + +for path in os.listdir("include/metalang99"): + if path.endswith(".h"): + module = path.replace(".h", "") + check_module(module) diff --git a/test/external/metalang99/scripts/check-fmt.sh b/test/external/metalang99/scripts/check-fmt.sh new file mode 100755 index 0000000..a3342c6 --- /dev/null +++ b/test/external/metalang99/scripts/check-fmt.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +./run-clang-format/run-clang-format.py \ + --exclude examples/build \ + --exclude tests/build \ + -r include tests examples bench diff --git a/test/external/metalang99/scripts/docs.sh b/test/external/metalang99/scripts/docs.sh new file mode 100755 index 0000000..957faa2 --- /dev/null +++ b/test/external/metalang99/scripts/docs.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +sphinx-build -b html docs _build/html diff --git a/test/external/metalang99/scripts/fmt.sh b/test/external/metalang99/scripts/fmt.sh new file mode 100755 index 0000000..5f550b6 --- /dev/null +++ b/test/external/metalang99/scripts/fmt.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +find include tests examples bench \ + \( -path examples/build -o -path tests/build \) -prune -false -o \ + \( -iname "*.h" \) -or \( -iname "*.c" \) | xargs clang-format -i diff --git a/test/external/metalang99/scripts/open-docs.sh b/test/external/metalang99/scripts/open-docs.sh new file mode 100755 index 0000000..ae3e4b5 --- /dev/null +++ b/test/external/metalang99/scripts/open-docs.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +xdg-open _build/html/index.html diff --git a/test/external/metalang99/scripts/open-spec.sh b/test/external/metalang99/scripts/open-spec.sh new file mode 100755 index 0000000..921e122 --- /dev/null +++ b/test/external/metalang99/scripts/open-spec.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +xdg-open spec/spec.pdf diff --git a/test/external/metalang99/scripts/spec.sh b/test/external/metalang99/scripts/spec.sh new file mode 100755 index 0000000..8da58e4 --- /dev/null +++ b/test/external/metalang99/scripts/spec.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +set -e + +cd spec + +pdflatex -shell-escape spec.tex +biber spec +pdflatex -shell-escape spec.tex +pdflatex -shell-escape spec.tex + +cd .. diff --git a/test/external/metalang99/scripts/test-all.sh b/test/external/metalang99/scripts/test-all.sh new file mode 100755 index 0000000..c4adc73 --- /dev/null +++ b/test/external/metalang99/scripts/test-all.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +set -e + +./scripts/test.sh +./scripts/test-examples.sh diff --git a/test/external/metalang99/scripts/test-examples.sh b/test/external/metalang99/scripts/test-examples.sh new file mode 100755 index 0000000..fb0db8a --- /dev/null +++ b/test/external/metalang99/scripts/test-examples.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -e + +mkdir -p examples/build +cd examples/build +cmake .. +cmake --build . diff --git a/test/external/metalang99/scripts/test.sh b/test/external/metalang99/scripts/test.sh new file mode 100755 index 0000000..ced5f53 --- /dev/null +++ b/test/external/metalang99/scripts/test.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -e + +mkdir -p tests/build +cd tests/build +cmake .. +cmake --build . + +if [[ "$OSTYPE" == "linux-gnu" ]]; then + echo "Testing ./gen ..." + ./gen + + echo "Testing ./stmt ..." + ./stmt +fi diff --git a/test/external/metalang99/spec/.gitignore b/test/external/metalang99/spec/.gitignore new file mode 100644 index 0000000..859f705 --- /dev/null +++ b/test/external/metalang99/spec/.gitignore @@ -0,0 +1,276 @@ +## Core latex/pdflatex auxiliary files: +*.aux +*.lof +*.log +*.lot +*.fls +*.out +*.toc +*.fmt +*.fot +*.cb +*.cb2 +.*.lb + +## Intermediate documents: +*.dvi +*.xdv +*-converted-to.* +# these rules might exclude image files for figures etc. +# *.ps +# *.eps +# *.pdf + +## Generated if empty string is given at "Please type another file name for output:" +.pdf + +## Bibliography auxiliary files (bibtex/biblatex/biber): +*.bbl +*.bcf +*.blg +*-blx.aux +*-blx.bib +*.run.xml + +## Build tool auxiliary files: +*.fdb_latexmk +*.synctex +*.synctex(busy) +*.synctex.gz +*.synctex.gz(busy) +*.pdfsync + +## Build tool directories for auxiliary files +# latexrun +latex.out/ + +## Auxiliary and intermediate files from other packages: +# algorithms +*.alg +*.loa + +# achemso +acs-*.bib + +# amsthm +*.thm + +# beamer +*.nav +*.pre +*.snm +*.vrb + +# changes +*.soc + +# comment +*.cut + +# cprotect +*.cpt + +# elsarticle (documentclass of Elsevier journals) +*.spl + +# endnotes +*.ent + +# fixme +*.lox + +# feynmf/feynmp +*.mf +*.mp +*.t[1-9] +*.t[1-9][0-9] +*.tfm + +#(r)(e)ledmac/(r)(e)ledpar +*.end +*.?end +*.[1-9] +*.[1-9][0-9] +*.[1-9][0-9][0-9] +*.[1-9]R +*.[1-9][0-9]R +*.[1-9][0-9][0-9]R +*.eledsec[1-9] +*.eledsec[1-9]R +*.eledsec[1-9][0-9] +*.eledsec[1-9][0-9]R +*.eledsec[1-9][0-9][0-9] +*.eledsec[1-9][0-9][0-9]R + +# glossaries +*.acn +*.acr +*.glg +*.glo +*.gls +*.glsdefs +*.lzo +*.lzs + +# uncomment this for glossaries-extra (will ignore makeindex's style files!) +# *.ist + +# gnuplottex +*-gnuplottex-* + +# gregoriotex +*.gaux +*.gtex + +# htlatex +*.4ct +*.4tc +*.idv +*.lg +*.trc +*.xref + +# hyperref +*.brf + +# knitr +*-concordance.tex +# TODO Comment the next line if you want to keep your tikz graphics files +*.tikz +*-tikzDictionary + +# listings +*.lol + +# luatexja-ruby +*.ltjruby + +# makeidx +*.idx +*.ilg +*.ind + +# minitoc +*.maf +*.mlf +*.mlt +*.mtc[0-9]* +*.slf[0-9]* +*.slt[0-9]* +*.stc[0-9]* + +# minted +_minted* +*.pyg + +# morewrites +*.mw + +# nomencl +*.nlg +*.nlo +*.nls + +# pax +*.pax + +# pdfpcnotes +*.pdfpc + +# sagetex +*.sagetex.sage +*.sagetex.py +*.sagetex.scmd + +# scrwfile +*.wrt + +# sympy +*.sout +*.sympy +sympy-plots-for-*.tex/ + +# pdfcomment +*.upa +*.upb + +# pythontex +*.pytxcode +pythontex-files-*/ + +# tcolorbox +*.listing + +# thmtools +*.loe + +# TikZ & PGF +*.dpth +*.md5 +*.auxlock + +# todonotes +*.tdo + +# vhistory +*.hst +*.ver + +# easy-todo +*.lod + +# xcolor +*.xcp + +# xmpincl +*.xmpi + +# xindy +*.xdy + +# xypic precompiled matrices and outlines +*.xyc +*.xyd + +# endfloat +*.ttt +*.fff + +# Latexian +TSWLatexianTemp* + +## Editors: +# WinEdt +*.bak +*.sav + +# Texpad +.texpadtmp + +# LyX +*.lyx~ + +# Kile +*.backup + +# gummi +.*.swp + +# KBibTeX +*~[0-9]* + +# TeXnicCenter +*.tps + +# auto folder when using emacs and auctex +./auto/* +*.el + +# expex forward references with \gathertags +*-tags.tex + +# standalone packages +*.sta + +# Makeindex log files +*.lpz diff --git a/test/external/metalang99/spec/references.bib b/test/external/metalang99/spec/references.bib new file mode 100644 index 0000000..adcb68a --- /dev/null +++ b/test/external/metalang99/spec/references.bib @@ -0,0 +1,17 @@ +@online{Metalang99, + author = "hirrolot", + title = "Full-blown preprocessor metaprogramming", + url = "https://github.com/hirrolot/metalang99", +} + +@online{ApplicativeEvaluationStrategy, + author = "Wikipedia", + title = "Applicative order", + url = "https://en.wikipedia.org/wiki/Evaluation_strategy#Applicative_order", +} + +@online{Bluepainting, + author = "", + title = "C99 draft, section 6.10.3.4, paragraph 2 -- Rescanning and further replacement", + url = "http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf", +} diff --git a/test/external/metalang99/spec/spec.pdf b/test/external/metalang99/spec/spec.pdf Binary files differnew file mode 100644 index 0000000..de1a062 --- /dev/null +++ b/test/external/metalang99/spec/spec.pdf diff --git a/test/external/metalang99/spec/spec.tex b/test/external/metalang99/spec/spec.tex new file mode 100644 index 0000000..99fb7e4 --- /dev/null +++ b/test/external/metalang99/spec/spec.tex @@ -0,0 +1,289 @@ +\documentclass[12pt]{article} + +\usepackage{hyperref} +\usepackage{float} +\usepackage{bussproofs} +\usepackage{minted} +\usepackage{amsmath} +\usepackage{amssymb} +\usepackage[standard,thmmarks]{ntheorem} +\usepackage{biblatex} +\usepackage{csquotes} +\usepackage{mathtools} +\usepackage{tabularx} +\usepackage[english]{babel} + +\theoremstyle{break} +\newtheorem{notation}{Notation} + +\addbibresource{references.bib} + +\floatstyle{boxed} +\restylefloat{figure} +\allowdisplaybreaks + +\begin{document} + +\title{Metalang99 Specification (v1.13.5)} +\date{\today} +\author{\texttt{hirrolot} \\ e-mail: \href{mailto:hirrolot@gmail.com}{hirrolot@gmail.com}} +\maketitle + +\begin{abstract} +This paper formally describes the syntax and semantics of metaprograms written in Metalang99, +a metalanguage aimed at full-blown C99 preprocessor metaprogramming. For the motivation and +a user-friendly overview, please see the official repository \cite{Metalang99}. +\end{abstract} + +\tableofcontents + +\newpage + +\section{EBNF Grammar} + +\begin{figure}[H] + \caption{Grammar rules} + +\begin{minted}{bnf} +<eval> ::= "ML99_EVAL(" <term-seq> ")" ; + +<term-seq> ::= <term> { "," <term> }* ; + +<term> ::= + "ML99_call(" <op> "," <term-seq> ")" + | "ML99_callUneval(" <ident> "," <pp-token-list> ")" + | "ML99_abort(" <term-seq> ")" + | "ML99_fatal(" <ident> "," <pp-token-list> ")" + | "v(" <pp-token-list> ")" ; + +<op> ::= <ident> | <term> ; +\end{minted} + +\end{figure} + +Notes: + +\begin{itemize} + \item \texttt{<pp-token-list>} stands for a list of preprocessor tokens (e.g., \texttt{a 123, hello!}). + \item The grammar above describes metaprograms already expanded by the preprocessor, + except for \texttt{ML99\_EVAL}, \texttt{ML99\_call}, \texttt{ML99\_callUneval}, \\ + \texttt{ML99\_abort}, \texttt{ML99\_fatal}, and \texttt{v}. + \item \texttt{ML99\_call} accepts \texttt{op} either as an identifier or as a term that + reduces to an identifier. + \item \texttt{ML99\_callUneval} accepts an operation strictly as an identifier. +\end{itemize} + +The \texttt{ML99\_call} syntax hurts IDE support (no parameters documentation highlighting) and is also +less natural. The workaround is to define a wrapper around an implementation macro like this: + +\begin{minted}{c} +/// The documentation string. +#define FOO(a, b, c) ML99_call(FOO, a, b, c) +#define FOO_IMPL(a, b, c) // The implementation. +\end{minted} + +Then \texttt{FOO} can be conveniently called as \texttt{FOO(v(1), v(2), v(3))}. + +\section{Notations} + +\begin{notation}[Sequence] + \begin{itemize} + \item $\overline{x} \coloneqq x_1 \ldots x_n$. Examples: + \begin{itemize} + \item Metalang99 terms: \texttt{v(abc), ML99\_call(FOO, v(123)), v(u 8 9)} + \item Preprocessor tokens: \texttt{abc 13 "hello" + -} + \end{itemize} + \item $()$ denotes the empty sequence. + \item Appending to a sequence: + \begin{itemize} + \item Appending an element: $S \ y \coloneqq x_1 \ldots x_n \ y$, where $S = x_1 \ldots x_n$ + \item Appending a sequence: $S_1 \ S_2 \coloneqq x_1 \ldots x_n \ y_1 \ldots y_m$, where $S_1 = x_1 \ldots x_n$ + and $S_2 = y_1 \ldots y_m$ + \end{itemize} + \end{itemize} +\end{notation} + +\begin{notation}[Reduction step] + $\to$ denotes a single step of reduction (computation, evaluation). +\end{notation} + +\begin{notation}[Metavariables] + \ \\ + \begin{tabular}{|c|c|} + \hline + \texttt{tok} & preprocessor token \\ + \texttt{ident} & preprocessor identifier \\ + \texttt{t} & Metalang99 term \\ + \texttt{a} & Metalang99 term used as an argument \\ + \hline + \end{tabular} +\end{notation} + +\section{Reduction Semantics} + +We define a reduction semantics for Metalang99 \ref{ReductionSemantics}. The abstract +machine executes configurations of the form $\langle K; F; A; C \rangle$: + +\begin{itemize} + \item $K$ is a continuation of the form $\langle K; F; A; C \rangle$, where + $C$ includes the $?$ sign denoting a result passed into the continuation. + For example, let $K$ be $\langle K'; (1, 2, 3); v(x), \ ? \rangle$, + then $K(v(y))$ is $\langle K'; (1, 2, 3); v(x), v(y) \rangle$. A special + continuation $halt$ terminates the abstract machine and substitutes itself + with a provided result. For example, when the abstract machine encounters + $halt(1 + 2)$, it will just stop and paste $1 + 2$. + + \item $F$ is a left folder of the form $(acc, \overline{tok}) \to acc$. It is used + to flexibly append a newly evaluated term to an accumulator without extra reduction + steps. There are the only two folders: + \begin{itemize} + \item $fspace(acc, \overline{tok}) \coloneqq acc \ \overline{tok}$ + \item $fcomma(acc, \overline{tok}) \coloneqq if (acc \ is \ ()) \ then \ \overline{tok} \ else \ acc \ "," \ \overline{tok}$ + \end{itemize} + + \item $A$ (accumulator) is a sequence of already computed results. + + \item $C$ (control) is a sequence of terms upon which the abstract + machine is operating right now. +\end{itemize} + +\begin{figure} + \caption{Reduction Semantics} + + \begin{align*} + (v): & \ \langle K; F; A; \texttt{v}(\overline{tok}), \overline{t} \rangle \to + \langle K; F; F(A, \overline{tok}); \overline{t} \rangle \\ + (op): & \ \langle K; F; A; \texttt{ML99\_call}(t, \overline{a}), \overline{t'} \rangle \to \langle \\ + & \ \ \ \ \langle K; F; A; \texttt{ML99\_call}(?), \overline{t'} \rangle; \\ + & \ \ \ \ fcomma; \\ + & \ \ \ \ (); \\ + & \ \ \ \ t, \overline{a} \rangle \\ + (args): & \ \langle K; F; A; \texttt{ML99\_call}(ident, \overline{a}), \overline{t} \rangle \to \langle \\ + & \ \ \ \ \langle \langle K; F; F(A, ?); \overline{t} \rangle; fspace; (); ident\texttt{\_IMPL}(?) \rangle; \\ + & \ \ \ \ fcomma; \\ + & \ \ \ \ (); \\ + & \ \ \ \ \overline{a} \rangle \\ + (callUneval): & \ \langle K; F; A; \texttt{ML99\_callUneval}(ident, \overline{tok}), \overline{t} \rangle \to \langle \\ + & \ \ \ \ \langle K; F; F(A, ?); \overline{t} \rangle; \\ + & \ \ \ \ fspace; \\ + & \ \ \ \ (); \\ + & \ \ \ \ ident\texttt{\_IMPL}(\overline{tok}) \rangle \\ + (abort): & \ \langle K; F; A; \texttt{ML99\_abort}(\overline{t}), \overline{t'} \rangle \to \langle halt; fspace; (); \overline{t} \rangle \\ + (fatal): & \ \langle K; F; A; \texttt{ML99\_fatal}(ident, \overline{tok}), \overline{t} \rangle \to halt(\ldots) \\ + (end): & \ \langle K; F; A; () \rangle \to K(A) \\ + (start): & \ \texttt{ML99\_call}(\overline{t}) \to \langle halt; fspace; (); \overline{t} \rangle + \end{align*} + \label{ReductionSemantics} +\end{figure} + +Notes: + +\begin{itemize} + \item Metalang99 follows applicative evaluation strategy \cite{ApplicativeEvaluationStrategy}. + + \item $(args)$ Metalang99 generates a usual C-style macro invocation with + fully evaluated arguments, which will be then expanded by the preprocessor, resulting + in yet another concrete sequence of Metalang99 terms to be evaluated by the computational + rules. + \item $(args)$ Metalang99 appends \texttt{\_IMPL} to every macro identifier called using + \texttt{ML99\_call} -- it makes easier to follow the convention that all implementations + of metafunctions must have the postfix \texttt{\_IMPL}. + \item $(callUneval)$ \texttt{ML99\_callUneval} is used when an operation and all + arguments are already evaluated. It is semantically the same as \\ \texttt{ML99\_call(ident, v(...))} + but performs one less reduction steps to benefit in performance. + \item $(fatal)$ The ellipsis means that an implementation is free to provide + diagnostics in any format. + \item $(fatal)$ interprets its variadic arguments without preprocessor expansion -- i.e., + they are pasted as-is. This is intended because otherwise identifiers located in an + error message may stand for other macros that will be unintentionally expanded. + \item The number of reduction steps is finite and may vary from version to version. If + the limit is exceeded, Metalang99 will not be able to perform reduction of a given + metaprogram anymore. +\end{itemize} + +\subsection{Examples} + +Take the following code: + +\begin{minted}{c} +#define X_IMPL(op) ML99_call(op, v(123)) +#define CALL_X_IMPL(_123) ML99_call(X, v(ID)) +#define ID_IMPL(x) v(x) +\end{minted} + +See how \texttt{ML99\_call(X, v(CALL\_X))} is evaluated: + +\begin{example}[Evaluation of terms] +\begin{align*} + \texttt{ML99\_EVAL}(\texttt{ML99\_call}(X, \texttt{v}(\texttt{CALL\_X}))) & \ \underrightarrow{(start)} \\ + \langle halt; fspace; (); \texttt{ML99\_call}(X, \texttt{v}(\texttt{CALL\_X})) \rangle & \ \underrightarrow{(args)} \\ + \langle \langle halt; fspace; (); \texttt{X}(?) \rangle; fcomma; (); \texttt{v}(\texttt{CALL\_X}) \rangle & \ \underrightarrow{(v)} \\ + \langle \langle halt; fspace; (); \texttt{X}(?) \rangle; fcomma; \texttt{CALL\_X}; () \rangle & \ \underrightarrow{(end)} \\ + \langle halt; fspace; (); \texttt{ML99\_call}(\texttt{CALL\_X}, \texttt{v}(123)) \rangle & \ \underrightarrow{(args)} \\ + \langle \langle halt; fspace; (); \texttt{CALL\_X}(?) \rangle; fcomma; (); \texttt{v}(123) \rangle & \ \underrightarrow{(v)} \\ + \langle \langle halt; fspace; (); \texttt{CALL\_X}(?) \rangle; fcomma; 123; () \rangle & \ \underrightarrow{(end)} \\ + \langle halt; fspace; (); \texttt{ML99\_call}(X, \texttt{v}(\texttt{ID})) \rangle & \ \underrightarrow{(args)} \\ + \langle \langle halt; fspace; (); \texttt{X}(?) \rangle; fcomma; (); \texttt{v}(\texttt{ID}) \rangle & \ \underrightarrow{(v)} \\ + \langle \langle halt; fspace; (); \texttt{X}(?) \rangle; fcomma; \texttt{ID}; \rangle & \ \underrightarrow{(end)} \\ + \langle halt; fspace; (); \texttt{ML99\_call}(\texttt{ID}, \texttt{v}(123)) \rangle & \ \underrightarrow{(args)} \\ + \langle \langle halt; fspace; (); \texttt{ID}(?) \rangle; fcomma; (); \texttt{v}(123) \rangle & \ \underrightarrow{(v)} \\ + \langle \langle halt; fspace; (); \texttt{ID}(?) \rangle; fcomma; 123; () \rangle & \ \underrightarrow{(end)} \\ + \langle halt; fspace; (); \texttt{v}(123) \rangle & \ \underrightarrow{(v)} \\ + \langle halt; fspace; 123; () \rangle & \ \underrightarrow{(end)} \\ + halt(123) & +\end{align*} +\end{example} + +The analogous version written in ordinary C looks like this: + +\begin{minted}{c} +#define X(op) op(123) +#define CALL_X(_123) X(ID) +#define ID(x) x +\end{minted} + +However, unlike the Metalang99 version above, \texttt{X(CALL\_X)} gets blocked \cite{Bluepainting} due to the +second call to \texttt{X}. The trick is that Metalang99 performs evaluation step-by-step, +unlike the preprocessor: + +\begin{itemize} + \item The Metalang99 version: \texttt{X(CALL\_X)} expands to \texttt{ML99\_call(\\ CALL\_X, v(123))}. + This expansion does not contain \texttt{X}, and therefore \texttt{X} is \textbf{not} + blocked by the preprocessor. + + \item The ordinary version: \texttt{X(CALL\_X)} expands to \texttt{X(ID)}. This expansion + does contains \texttt{X}, and therefore \texttt{X} is blocked by the preprocessor. +\end{itemize} + +\section{Properties} + +\subsection{Progress} + +\begin{proposition}[Progress] +Either $\langle K; F; A; \overline{t} \rangle \to \langle K; F; A; \overline{t'} \rangle$ or \\ +$\langle K; F; A; \overline{t} \rangle \to halt(\overline{x})$. +\end{proposition} + +\begin{proof} +By inspection of \ref{ReductionSemantics}. +\end{proof} + +\section{Caveats} + +\begin{itemize} +\item Consider this scenario: + \begin{itemize} + \item You call \texttt{FOO(1, 2, 3)} + \item It gets expanded by the preprocessor (not by Metalang99) + \item Its expansion contains \texttt{FOO} + \end{itemize} +Then \texttt{FOO} gets blocked \cite{Bluepainting} by the preprocessor, i.e. Metalang99 cannot handle ordinary +macro recursion; you must use \texttt{ML99\_call} to be sure that recursive calls +will behave as expected. I therefore recommend to use only primitive C-style macros, e.g. +for performance reasons or because of you cannot express them in terms of Metalang99. +\end{itemize} + +\emergencystretch=1em +\printbibliography + +\end{document} diff --git a/test/external/metalang99/tests/.gitignore b/test/external/metalang99/tests/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/test/external/metalang99/tests/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/test/external/metalang99/tests/CMakeLists.txt b/test/external/metalang99/tests/CMakeLists.txt new file mode 100644 index 0000000..95153b7 --- /dev/null +++ b/test/external/metalang99/tests/CMakeLists.txt @@ -0,0 +1,38 @@ +cmake_minimum_required(VERSION 3.16) +project(test LANGUAGES C) + +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + add_compile_options(-Wall -Wextra -pedantic -std=c99 + -ftrack-macro-expansion=0) +elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang") + add_compile_options("-fmacro-backtrace-limit=1") +elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") + # Enable a standard-conforming C99/C11 preprocessor. + add_compile_options("/std:c11") +elseif(CMAKE_C_COMPILER_ID STREQUAL "TinyCC") + add_compile_definitions(ML99_ALLOW_POOR_DIAGNOSTICS) +endif() + +include_directories(../include) + +add_executable(metalang99 metalang99.c) +add_executable(assert assert.c) +add_executable(choice choice.c) +add_executable(either either.c) +add_executable(gen gen.c) +add_executable(stmt stmt.c) +add_executable(lang lang.c) +add_executable(list list.c) +add_executable(bool bool.c) +add_executable(maybe maybe.c) +add_executable(nat nat.c) +add_executable(ident ident.c) +add_executable(tuple tuple.c) +add_executable(util util.c) +add_executable(variadics variadics.c) +add_executable(seq seq.c) +add_executable(rec eval/rec.c) + +foreach(TARGET ${BUILDSYSTEM_TARGETS}) + set_target_properties(TARGET PROPERTIES C_STANDARD 99 C_STANDARD_REQUIRED ON) +endforeach() diff --git a/test/external/metalang99/tests/assert.c b/test/external/metalang99/tests/assert.c new file mode 100644 index 0000000..44033cb --- /dev/null +++ b/test/external/metalang99/tests/assert.c @@ -0,0 +1,19 @@ +#include <metalang99/assert.h> + +// This is used to check that `1 == 1` is put into parentheses automatically. +#define COND 1 == 1 + +ML99_EVAL(ML99_assert(v(COND))); +ML99_EVAL(ML99_assertEq(v(COND), v(COND))); + +ML99_ASSERT(v(COND)); +ML99_ASSERT_EQ(v(COND), v(COND)); + +ML99_ASSERT_UNEVAL(COND); + +#undef COND + +ML99_ASSERT_EMPTY(v()); +ML99_ASSERT_EMPTY_UNEVAL(); + +int main(void) {} diff --git a/test/external/metalang99/tests/bool.c b/test/external/metalang99/tests/bool.c new file mode 100644 index 0000000..e974920 --- /dev/null +++ b/test/external/metalang99/tests/bool.c @@ -0,0 +1,121 @@ +#include <metalang99/assert.h> +#include <metalang99/bool.h> + +int main(void) { + + // ML99_true, ML99_false + { + ML99_ASSERT_EQ(ML99_true(), v(1)); + ML99_ASSERT_EQ(ML99_true(~, ~, ~), v(1)); + + ML99_ASSERT_EQ(ML99_false(), v(0)); + ML99_ASSERT_EQ(ML99_false(~, ~, ~), v(0)); + } + + // ML99_not + { + ML99_ASSERT_EQ(ML99_not(v(0)), v(1)); + ML99_ASSERT_EQ(ML99_not(v(1)), v(0)); + } + + // ML99_and + { + ML99_ASSERT_EQ(ML99_and(v(0), v(0)), v(0)); + ML99_ASSERT_EQ(ML99_and(v(0), v(1)), v(0)); + ML99_ASSERT_EQ(ML99_and(v(1), v(0)), v(0)); + ML99_ASSERT_EQ(ML99_and(v(1), v(1)), v(1)); + } + + // ML99_or + { + ML99_ASSERT_EQ(ML99_or(v(0), v(0)), v(0)); + ML99_ASSERT_EQ(ML99_or(v(0), v(1)), v(1)); + ML99_ASSERT_EQ(ML99_or(v(1), v(0)), v(1)); + ML99_ASSERT_EQ(ML99_or(v(1), v(1)), v(1)); + } + + // ML99_xor + { + ML99_ASSERT_EQ(ML99_xor(v(0), v(0)), v(0)); + ML99_ASSERT_EQ(ML99_xor(v(0), v(1)), v(1)); + ML99_ASSERT_EQ(ML99_xor(v(1), v(0)), v(1)); + ML99_ASSERT_EQ(ML99_xor(v(1), v(1)), v(0)); + } + + // ML99_boolEq + { + ML99_ASSERT_EQ(ML99_boolEq(v(0), v(0)), v(1)); + ML99_ASSERT_EQ(ML99_boolEq(v(0), v(1)), v(0)); + ML99_ASSERT_EQ(ML99_boolEq(v(1), v(0)), v(0)); + ML99_ASSERT_EQ(ML99_boolEq(v(1), v(1)), v(1)); + } + +#define MATCH_1_IMPL(...) v(12) // `...` due to the TCC's bug. +#define MATCH_0_IMPL(...) v(9) + + // ML99_boolMatch + { + ML99_ASSERT_EQ(ML99_boolMatch(v(1), v(MATCH_)), v(12)); + ML99_ASSERT_EQ(ML99_boolMatch(v(0), v(MATCH_)), v(9)); + } + +#undef MATCH_1_IMPL +#undef MATCH_0_IMPL + +#define MATCH_1_IMPL(x, y, z) v(ML99_ASSERT_UNEVAL(x == 1 && y == 2 && z == 3)) +#define MATCH_0_IMPL(x, y, z) v(ML99_ASSERT_UNEVAL(x == 1 && y == 2 && z == 3)) + + // ML99_boolMatchWithArgs + { + ML99_EVAL(ML99_boolMatchWithArgs(v(1), v(MATCH_), v(1, 2, 3))); + ML99_EVAL(ML99_boolMatchWithArgs(v(0), v(MATCH_), v(1, 2, 3))); + } + +#undef MATCH_1_IMPL +#undef MATCH_0_IMPL + + // ML99_if + { + ML99_ASSERT_EQ(ML99_if(ML99_true(), v(24), v(848)), v(24)); + ML99_ASSERT_EQ(ML99_if(ML99_true(), v(1549), v(1678)), v(1549)); + + ML99_ASSERT_EQ(ML99_if(ML99_false(), v(516), v(115)), v(115)); + ML99_ASSERT_EQ(ML99_if(ML99_false(), v(10), v(6)), v(6)); + } + +#define CHECK(...) CHECK_AUX(__VA_ARGS__) +#define CHECK_AUX(a, b, c) ML99_ASSERT_UNEVAL(a == 1 && b == 2 && c == 3) + +#define X 1, 2, 3 + + // ML99_IF + { + ML99_ASSERT_UNEVAL(ML99_IF(ML99_TRUE(), 24, 848) == 24); + ML99_ASSERT_UNEVAL(ML99_IF(ML99_FALSE(), 516, 115) == 115); + + // Ensure that a branch can expand to multiple commas (`X`). + CHECK(ML99_IF(ML99_TRUE(), X, ~)); + CHECK(ML99_IF(ML99_FALSE(), ~, X)); + } + +#undef CHECK +#undef CHECK_AUX +#undef X + + // Plain macros + { + ML99_ASSERT_UNEVAL(ML99_TRUE()); + ML99_ASSERT_UNEVAL(ML99_TRUE(~, ~, ~)); + + ML99_ASSERT_UNEVAL(!ML99_FALSE()); + ML99_ASSERT_UNEVAL(!ML99_FALSE(~, ~, ~)); + + ML99_ASSERT_UNEVAL(ML99_NOT(0) == 1); + ML99_ASSERT_UNEVAL(ML99_NOT(1) == 0); + + ML99_ASSERT_UNEVAL(ML99_AND(0, 1) == 0); + ML99_ASSERT_UNEVAL(ML99_OR(0, 1) == 1); + ML99_ASSERT_UNEVAL(ML99_XOR(0, 1) == 1); + ML99_ASSERT_UNEVAL(ML99_BOOL_EQ(0, 1) == 0); + } +} diff --git a/test/external/metalang99/tests/choice.c b/test/external/metalang99/tests/choice.c new file mode 100644 index 0000000..93f4fb5 --- /dev/null +++ b/test/external/metalang99/tests/choice.c @@ -0,0 +1,64 @@ +#include <metalang99/assert.h> +#include <metalang99/choice.h> + +int main(void) { + +#define MATCH_IMPL(foo) ML99_match(v(foo), v(MATCH_)) +#define MATCH_FooA_IMPL(x) v(ML99_ASSERT_UNEVAL(x == 19)) +#define MATCH_FooB_IMPL(x) v(ML99_ASSERT_UNEVAL(x == 1756)) +#define MATCH_FooC_IMPL(_) v(ML99_ASSERT_UNEVAL(1)) + + // ML99_match + { + ML99_EVAL(ML99_call(MATCH, ML99_choice(v(FooA), v(19)))); + ML99_EVAL(ML99_call(MATCH, ML99_choice(v(FooB), v(1756)))); + ML99_EVAL(ML99_call(MATCH, ML99_choice(v(FooC), v(~)))); + } + +#undef MATCH_IMPL +#undef MATCH_FooA_IMPL +#undef MATCH_FooB_IMPL +#undef MATCH_FooC_IMPL + +#define MATCH_IMPL(foo) ML99_matchWithArgs(v(foo), v(MATCH_), v(3, 8)) +#define MATCH_FooA_IMPL(x, _3, _8) v(ML99_ASSERT_UNEVAL(x == 19 && _3 == 3 && _8 == 8)) +#define MATCH_FooB_IMPL(x, _3, _8) v(ML99_ASSERT_UNEVAL(x == 1756 && _3 == 3 && _8 == 8)) +#define MATCH_FooC_IMPL(_, _3, _8) v(ML99_ASSERT_UNEVAL(_3 == 3 && _8 == 8)) + + // ML99_matchWithArgs + { + ML99_EVAL(ML99_call(MATCH, ML99_choice(v(FooA), v(19)))); + ML99_EVAL(ML99_call(MATCH, ML99_choice(v(FooB), v(1756)))); + ML99_EVAL(ML99_call(MATCH, ML99_choice(v(FooC), v(~)))); + } + +#undef MATCH_IMPL +#undef MATCH_FooA_IMPL +#undef MATCH_FooB_IMPL +#undef MATCH_FooC_IMPL + +#define CHECK(x, y, z) ML99_ASSERT_UNEVAL(x == 1 && y == 2 && z == 3) +#define CHECK_EXPAND(args) CHECK(args) + + // ML99_choiceTag, ML99_choiceData + { + ML99_ASSERT_EQ(ML99_choiceTag(ML99_choice(v(5), v(1, 2, 3))), v(5)); + CHECK_EXPAND(ML99_EVAL(ML99_choiceData(ML99_choice(v(5), v(1, 2, 3))))); + } + + // ML99_CHOICE, ML99_CHOICE_TAG, ML99_CHOICE_DATA + { + ML99_ASSERT_UNEVAL(ML99_CHOICE_TAG(ML99_CHOICE(5, 1, 2, 3)) == 5); + CHECK_EXPAND(ML99_CHOICE_DATA(ML99_CHOICE(5, 1, 2, 3))); + } + +#undef CHECK +#undef CHECK_EXPAND + +#define CHECK(tag, x, y, z) tag == 5 && x == 1 && y == 2 && z == 3 + + // Representation + { ML99_ASSERT_UNEVAL(CHECK ML99_CHOICE(5, 1, 2, 3)); } + +#undef CHECK +} diff --git a/test/external/metalang99/tests/either.c b/test/external/metalang99/tests/either.c new file mode 100644 index 0000000..4a29fb9 --- /dev/null +++ b/test/external/metalang99/tests/either.c @@ -0,0 +1,66 @@ +#include <metalang99/assert.h> +#include <metalang99/either.h> +#include <metalang99/nat.h> + +int main(void) { + +#define MATCH_IMPL(either) ML99_match(v(either), v(MATCH_)) +#define MATCH_left_IMPL(x) v(ML99_ASSERT_UNEVAL(x == 18)) +#define MATCH_right_IMPL(x) v(ML99_ASSERT_UNEVAL(x == 4)) + + // Pattern matching + { + ML99_EVAL(ML99_call(MATCH, ML99_left(v(18)))); + ML99_EVAL(ML99_call(MATCH, ML99_right(v(4)))); + } + +#undef MATCH_IMPL +#undef MATCH_left_IMPL +#undef MATCH_right_IMPL + +#define VAL v(abc ? +-148 % "hello world") + + // ML99_isLeft + { + ML99_ASSERT(ML99_isLeft(ML99_left(VAL))); + ML99_ASSERT(ML99_not(ML99_isLeft(ML99_right(VAL)))); + } + + // ML99_IS_LEFT + { + ML99_ASSERT_UNEVAL(ML99_IS_LEFT(ML99_LEFT(VAL))); + ML99_ASSERT_UNEVAL(!ML99_IS_LEFT(ML99_RIGHT(VAL))); + } + + // ML99_isRight + { + ML99_ASSERT(ML99_isRight(ML99_right(VAL))); + ML99_ASSERT(ML99_not(ML99_isRight(ML99_left(VAL)))); + } + + // ML99_IS_RIGHT + { + ML99_ASSERT_UNEVAL(ML99_IS_RIGHT(ML99_RIGHT(VAL))); + ML99_ASSERT_UNEVAL(!ML99_IS_RIGHT(ML99_LEFT(VAL))); + } + + // ML99_eitherEq + { + ML99_ASSERT(ML99_eitherEq(v(ML99_natEq), ML99_left(v(123)), ML99_left(v(123)))); + ML99_ASSERT(ML99_not(ML99_eitherEq(v(ML99_natEq), ML99_left(v(18)), ML99_left(v(123))))); + + ML99_ASSERT(ML99_eitherEq(v(ML99_natEq), ML99_right(v(123)), ML99_right(v(123)))); + ML99_ASSERT(ML99_not(ML99_eitherEq(v(ML99_natEq), ML99_right(v(18)), ML99_right(v(123))))); + + ML99_ASSERT(ML99_not(ML99_eitherEq(v(ML99_natEq), ML99_left(v(123)), ML99_right(v(123))))); + ML99_ASSERT(ML99_not(ML99_eitherEq(v(ML99_natEq), ML99_left(v(123)), ML99_right(v(4))))); + ML99_ASSERT(ML99_not(ML99_eitherEq(v(ML99_natEq), ML99_right(v(123)), ML99_left(v(123))))); + ML99_ASSERT(ML99_not(ML99_eitherEq(v(ML99_natEq), ML99_right(v(123)), ML99_left(v(4))))); + } + + // ML99_unwrapLeft + { ML99_ASSERT_EQ(ML99_unwrapLeft(ML99_left(v(123))), v(123)); } + + // ML99_unwrapRight + { ML99_ASSERT_EQ(ML99_unwrapRight(ML99_right(v(123))), v(123)); } +} diff --git a/test/external/metalang99/tests/eval/rec.c b/test/external/metalang99/tests/eval/rec.c new file mode 100644 index 0000000..aff7390 --- /dev/null +++ b/test/external/metalang99/tests/eval/rec.c @@ -0,0 +1,25 @@ +#include <metalang99/eval/rec.h> + +#include <metalang99/assert.h> + +#include <metalang99/priv/util.h> + +#include <metalang99/nat/eq.h> +#include <metalang99/nat/inc.h> + +#define F(acc, i) ML99_PRIV_IF(ML99_PRIV_NAT_EQ(i, 10), F_DONE, F_PROGRESS)(acc, i) +#define F_DONE(acc, _i) ML99_PRIV_REC_CONTINUE(ML99_PRIV_REC_STOP)(~, acc) +#define F_PROGRESS(acc, i) ML99_PRIV_REC_CONTINUE(F)(acc##X, ML99_PRIV_INC(i)) +#define F_HOOK() F + +#define XXXXXXXXXX 678 + +ML99_ASSERT_UNEVAL(ML99_PRIV_REC_UNROLL(F(, 0)) == 678); + +#undef F +#undef F_DONE +#undef F_PROGRESS +#undef F_HOOK +#undef XXXXXXXXXX + +int main(void) {} diff --git a/test/external/metalang99/tests/gen.c b/test/external/metalang99/tests/gen.c new file mode 100644 index 0000000..bb1e163 --- /dev/null +++ b/test/external/metalang99/tests/gen.c @@ -0,0 +1,283 @@ +#include <metalang99/assert.h> +#include <metalang99/gen.h> +#include <metalang99/ident.h> +#include <metalang99/list.h> +#include <metalang99/tuple.h> + +#include <assert.h> + +// clang-format off +static void + test_indexed_params ML99_EVAL(ML99_indexedParams(ML99_list(v(int, long long, const char *)))) +// clang-format on +{ + int i = _0; + long long ll = _1; + const char *str = _2; + + (void)i; + (void)ll; + (void)str; +} + +static int test_fn_ptr(const char *str, long long x) { + (void)str; + (void)x; + return 123; +} + +int main(void) { + + // ML99_braced + { struct TestBraced ML99_EVAL(ML99_braced(v(int a, b, c;))); } + + // ML99_semicoloned + { + ML99_EVAL(ML99_semicoloned(v(struct TestSemicoloned { int a, b, c; }))); + } + + // ML99_assign(Stmt) + { + int x = 0; + + ML99_EVAL(ML99_assign(v(x), v(5))); + assert(5 == x); + + ML99_EVAL(ML99_assignStmt(v(x), v(7))) + assert(7 == x); + } + + // ML99_assignInitializerList(Stmt) + { + typedef struct { + int x, y; + } Point; + + ML99_EVAL(ML99_assignInitializerList(v(Point p1), v(.x = 2, .y = 3))); + assert(2 == p1.x); + assert(3 == p1.y); + + ML99_EVAL(ML99_assignInitializerListStmt(v(Point p2), v(.x = 5, .y = 7))) + assert(5 == p2.x); + assert(7 == p2.y); + } + +#define F(a, b, c) ML99_ASSERT_UNEVAL(a == 1 && b == 2 && c == 3) + + // ML99_invoke(Stmt) + { + ML99_EVAL(ML99_invoke(v(F), v(1, 2, 3))); + ML99_EVAL(ML99_invokeStmt(v(F), v(1, 2, 3))) + } + +#undef F + + // ML99_prefixedBlock + { + + ML99_EVAL(ML99_prefixedBlock(v(if (1)), v(goto end_prefixed_block;))) + + // Unreachable code. + assert(0); + + end_prefixed_block:; + } + + // ML99_typedef + { + + ML99_EVAL(ML99_typedef(v(Point), v(struct { int x, y; }))); + + Point point = {5, 7}; + point.x = 1; + point.y = 2; + + (void)point; + } + + // ML99_struct + { + + ML99_EVAL(ML99_struct(v(Point), v(int x, y;))); + + struct Point point = {5, 7}; + point.x = 1; + point.y = 2; + + (void)point; + } + + // ML99_anonStruct + { + typedef ML99_EVAL(ML99_anonStruct(v(int x, y;))) + Point; + + Point point = {5, 7}; + point.x = 1; + point.y = 2; + + (void)point; + } + + // ML99_union + { + ML99_EVAL(ML99_union(v(Point), v(int x, y;))); + + union Point point; + point.x = 1; + point.y = 2; + + (void)point; + } + + // ML99_anonUnion + { + typedef ML99_EVAL(ML99_anonUnion(v(int x, y;))) + Point; + + Point point; + point.x = 1; + point.y = 2; + + (void)point; + } + + // ML99_enum + { + ML99_EVAL(ML99_enum(v(MyEnum), v(Foo, Bar))); + + enum MyEnum foo = Foo, bar = Bar; + (void)foo; + (void)bar; + } + + // ML99_anonEnum + { + typedef ML99_EVAL(ML99_anonEnum(v(Foo, Bar))) + MyEnum; + + MyEnum foo = Foo, bar = Bar; + (void)foo; + (void)bar; + } + + // ML99_fnPtr(Stmt) + { + { + ML99_EVAL(ML99_fnPtr(v(int), v(ptr), v(const char *str), v(long long x))) + = test_fn_ptr; + assert(test_fn_ptr == ptr); + } + + { + ML99_EVAL(ML99_fnPtrStmt(v(int), v(ptr), v(const char *str), v(long long x))) + ptr = test_fn_ptr; + (void)ptr; + } + } + +#define CHECK_EXPAND(args) CHECK(args) + +#define CHECK(_, x, y, z) ML99_ASSERT_UNEVAL(x == 0 && y == 1 && z == 2) +#define F_IMPL(x) v(, x) +#define F_ARITY 1 + + // ML99_repeat + { CHECK_EXPAND(ML99_EVAL(ML99_repeat(v(3), v(F)))); } + +#undef CHECK +#undef F_IMPL +#undef F_ARITY + +#define CHECK(_, x, y, z) ML99_ASSERT_UNEVAL(x == 5 && y == 5 && z == 5) + + // ML99_times + { CHECK_EXPAND(ML99_EVAL(ML99_times(v(3), v(, 5)))); } + +#undef CHECK + +#undef CHECK_EXPAND + + // ML99_indexedParams + { + ML99_ASSERT_UNEVAL(ML99_IDENT_EQ( + ML99_C_KEYWORD_DETECTOR, + void, + ML99_EVAL(ML99_untuple(ML99_indexedParams(ML99_nil()))))); + + (void)test_indexed_params; + } + + // ML99_indexedFields + { + ML99_ASSERT_EMPTY(ML99_indexedFields(ML99_nil())); + + struct { + ML99_EVAL(ML99_indexedFields(ML99_list(v(int, long long, const char *)))) + } data = {0}; + + int i = data._0; + long long ll = data._1; + const char *str = data._2; + + (void)i; + (void)ll; + (void)str; + } + + // clang-format off + + // ML99_indexedInitializerList + { + // When N=0. + { + const struct { + int _0; + long long _1; + const char *_2; + } test = ML99_EVAL(ML99_indexedInitializerList(v(0))); + + assert(0 == test._0); + assert(0 == test._1); + assert(0 == test._2); + } + + // When N>0. + { + int _0 = 123; + long long _1 = 149494456; + const char *_2 = "abc"; + + struct { + int i; + long long ll; + const char *str; + } data = ML99_EVAL(ML99_indexedInitializerList(v(3))); + + (void)data; + } + } + + // ML99_indexedArgs + { + ML99_ASSERT_EMPTY(ML99_indexedArgs(v(0))); + + int _0 = 123; + long long _1 = 149494456; + const char *_2 = "abc"; + + const struct { + int i; + long long ll; + const char *str; + } test = { ML99_EVAL(ML99_indexedArgs(v(3))) }; + + assert(test.i == _0); + assert(test.ll == _1); + assert(test.str == _2); + } + + // clang-format on + + return 0; +} diff --git a/test/external/metalang99/tests/ident.c b/test/external/metalang99/tests/ident.c new file mode 100644 index 0000000..5f32f16 --- /dev/null +++ b/test/external/metalang99/tests/ident.c @@ -0,0 +1,395 @@ +#include <metalang99/assert.h> +#include <metalang99/bool.h> +#include <metalang99/ident.h> + +int main(void) { + +#define EMPTY + +#define FOO_x () +#define FOO_y () + + // ML99_detectIdent + { + ML99_ASSERT(ML99_detectIdent(v(FOO_), v(x))); + ML99_ASSERT(ML99_detectIdent(v(FOO_), v(y))); + ML99_ASSERT(ML99_not(ML99_detectIdent(v(FOO_), v(z)))); + + ML99_ASSERT(ML99_not(ML99_detectIdent(v(BAR_), v(x)))); + ML99_ASSERT(ML99_not(ML99_detectIdent(v(BAR_), v(abc)))); + ML99_ASSERT(ML99_not(ML99_detectIdent(v(BAR_), v(defghi)))); + } + + // ML99_DETECT_IDENT + { + ML99_ASSERT_UNEVAL(ML99_DETECT_IDENT(FOO_, x)); + ML99_ASSERT_UNEVAL(!ML99_DETECT_IDENT(BAR_, x)); + } + +#undef FOO_x +#undef FOO_y + +#define FOO_x_x () +#define FOO_y_y () + + // ML99_identEq + { + ML99_ASSERT(ML99_identEq(v(FOO_), v(x), v(x))); + ML99_ASSERT(ML99_identEq(v(FOO_), v(y), v(y))); + + ML99_ASSERT(ML99_not(ML99_identEq(v(FOO_), v(x), v(y)))); + ML99_ASSERT(ML99_not(ML99_identEq(v(FOO_), v(abc), v(d)))); + ML99_ASSERT(ML99_not(ML99_identEq(v(FOO_), v(x), v(EMPTY)))); + ML99_ASSERT(ML99_not(ML99_identEq(v(FOO_), v(EMPTY), v(y)))); + ML99_ASSERT(ML99_not(ML99_identEq(v(FOO_), v(EMPTY), v(EMPTY)))); + } + + // ML99_IDENT_EQ + { + ML99_ASSERT_UNEVAL(ML99_IDENT_EQ(FOO_, x, x)); + ML99_ASSERT_UNEVAL(!ML99_IDENT_EQ(FOO_, x, y)); + } + +#undef FOO_x_x +#undef FOO_y_y + + // ML99_charEq + { + ML99_ASSERT(ML99_charEq(v(a), v(a))); + ML99_ASSERT(ML99_charEq(v(x), v(x))); + ML99_ASSERT(ML99_charEq(v(e), v(e))); + + ML99_ASSERT(ML99_charEq(v(T), v(T))); + ML99_ASSERT(ML99_charEq(v(J), v(J))); + ML99_ASSERT(ML99_charEq(v(D), v(D))); + + ML99_ASSERT(ML99_charEq(v(0), v(0))); + ML99_ASSERT(ML99_charEq(v(5), v(5))); + ML99_ASSERT(ML99_charEq(v(9), v(9))); + + ML99_ASSERT(ML99_not(ML99_charEq(v(a), v(idf2)))); + ML99_ASSERT(ML99_not(ML99_charEq(v(T), v(abracadabra)))); + ML99_ASSERT(ML99_not(ML99_charEq(v(0), v(123)))); + ML99_ASSERT(ML99_not(ML99_charEq(v(abracadabra), v(abracadabra)))); + } + + // ML99_CHAR_EQ + { + ML99_ASSERT_UNEVAL(ML99_CHAR_EQ(x, x)); + ML99_ASSERT_UNEVAL(!ML99_CHAR_EQ(x, 0)); + } + + // ML99_C_KEYWORD_DETECTOR + { + +#define TEST(keyword) \ + ML99_ASSERT_UNEVAL( \ + ML99_IDENT_EQ(ML99_C_KEYWORD_DETECTOR, keyword, keyword) && \ + !ML99_IDENT_EQ(ML99_C_KEYWORD_DETECTOR, keyword, blah) && \ + !ML99_IDENT_EQ(ML99_C_KEYWORD_DETECTOR, keyword, EMPTY) && \ + !ML99_IDENT_EQ(ML99_C_KEYWORD_DETECTOR, EMPTY, keyword)) + + TEST(auto); + TEST(break); + TEST(case); + TEST(char); + TEST(const); + TEST(continue); + TEST(default); + TEST(do); + TEST(double); + TEST(else); + TEST(enum); + TEST(extern); + TEST(float); + TEST(for); + TEST(goto); + TEST(if); + TEST(inline); + TEST(int); + TEST(long); + TEST(register); + TEST(restrict); + // clang-format off + TEST(return); + // clang-format on + TEST(short); + TEST(signed); + TEST(sizeof); + TEST(static); + TEST(struct); + TEST(switch); + TEST(typedef); + TEST(union); + TEST(unsigned); + TEST(void); + TEST(volatile); + TEST(while); + TEST(_Alignas); + TEST(_Alignof); + TEST(_Atomic); + TEST(_Bool); + TEST(_Complex); + TEST(_Generic); + TEST(_Imaginary); + TEST(_Noreturn); + TEST(_Static_assert); + TEST(_Thread_local); + +#undef TEST + + ML99_ASSERT_UNEVAL(!ML99_IDENT_EQ(ML99_C_KEYWORD_DETECTOR, restrict, void)); + ML99_ASSERT_UNEVAL(!ML99_IDENT_EQ(ML99_C_KEYWORD_DETECTOR, case, while)); + ML99_ASSERT_UNEVAL(!ML99_IDENT_EQ(ML99_C_KEYWORD_DETECTOR, volatile, _Alignof)); + ML99_ASSERT_UNEVAL(!ML99_IDENT_EQ(ML99_C_KEYWORD_DETECTOR, _Generic, _Alignas)); + + ML99_ASSERT(ML99_identEq(v(ML99_C_KEYWORD_DETECTOR), v(_Bool), v(_Bool))); + ML99_ASSERT(ML99_not(ML99_identEq(v(ML99_C_KEYWORD_DETECTOR), v(_Atomic), v(_Bool)))); + } + + // ML99_UNDERSCORE_DETECTOR + { + ML99_ASSERT(ML99_detectIdent(v(ML99_UNDERSCORE_DETECTOR), v(_))); + ML99_ASSERT(ML99_not(ML99_detectIdent(v(ML99_UNDERSCORE_DETECTOR), v(blah)))); + ML99_ASSERT(ML99_not(ML99_detectIdent(v(ML99_UNDERSCORE_DETECTOR), v()))); + } + + // ML99_LOWERCASE_DETECTOR + { + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(a), v(a))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(b), v(b))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(c), v(c))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(d), v(d))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(e), v(e))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(f), v(f))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(g), v(g))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(h), v(h))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(i), v(i))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(j), v(j))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(k), v(k))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(l), v(l))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(m), v(m))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(n), v(n))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(o), v(o))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(p), v(p))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(q), v(q))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(r), v(r))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(s), v(s))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(t), v(t))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(u), v(u))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(v), v(v))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(w), v(w))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(x), v(x))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(y), v(y))); + ML99_ASSERT(ML99_identEq(v(ML99_LOWERCASE_DETECTOR), v(z), v(z))); + } + + // ML99_UPPERCASE_DETECTOR + { + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(A), v(A))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(B), v(B))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(C), v(C))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(D), v(D))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(E), v(E))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(F), v(F))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(G), v(G))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(H), v(H))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(I), v(I))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(J), v(J))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(K), v(K))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(L), v(L))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(M), v(M))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(N), v(N))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(O), v(O))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(P), v(P))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(Q), v(Q))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(R), v(R))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(S), v(S))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(T), v(T))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(U), v(U))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(V), v(V))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(W), v(W))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(X), v(X))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(Y), v(Y))); + ML99_ASSERT(ML99_identEq(v(ML99_UPPERCASE_DETECTOR), v(Z), v(Z))); + } + + // ML99_DIGIT_DETECTOR + { + ML99_ASSERT(ML99_identEq(v(ML99_DIGIT_DETECTOR), v(0), v(0))); + ML99_ASSERT(ML99_identEq(v(ML99_DIGIT_DETECTOR), v(1), v(1))); + ML99_ASSERT(ML99_identEq(v(ML99_DIGIT_DETECTOR), v(2), v(2))); + ML99_ASSERT(ML99_identEq(v(ML99_DIGIT_DETECTOR), v(3), v(3))); + ML99_ASSERT(ML99_identEq(v(ML99_DIGIT_DETECTOR), v(4), v(4))); + ML99_ASSERT(ML99_identEq(v(ML99_DIGIT_DETECTOR), v(5), v(5))); + ML99_ASSERT(ML99_identEq(v(ML99_DIGIT_DETECTOR), v(6), v(6))); + ML99_ASSERT(ML99_identEq(v(ML99_DIGIT_DETECTOR), v(7), v(7))); + ML99_ASSERT(ML99_identEq(v(ML99_DIGIT_DETECTOR), v(8), v(8))); + ML99_ASSERT(ML99_identEq(v(ML99_DIGIT_DETECTOR), v(9), v(9))); + } + + // ML99_IS_LOWERCASE + { + ML99_ASSERT_UNEVAL(ML99_IS_LOWERCASE(a)); + ML99_ASSERT_UNEVAL(ML99_IS_LOWERCASE(j)); + ML99_ASSERT_UNEVAL(ML99_IS_LOWERCASE(z)); + + ML99_ASSERT_UNEVAL(!ML99_IS_LOWERCASE(8)); + ML99_ASSERT_UNEVAL(!ML99_IS_LOWERCASE(I)); + ML99_ASSERT_UNEVAL(!ML99_IS_LOWERCASE(_)); + ML99_ASSERT_UNEVAL(!ML99_IS_LOWERCASE(abracadabra)); + + ML99_ASSERT(ML99_isLowercase(v(z))); + ML99_ASSERT(ML99_not(ML99_isLowercase(v(8)))); + } + + // ML99_IS_UPPERCASE + { + ML99_ASSERT_UNEVAL(ML99_IS_UPPERCASE(A)); + ML99_ASSERT_UNEVAL(ML99_IS_UPPERCASE(J)); + ML99_ASSERT_UNEVAL(ML99_IS_UPPERCASE(Z)); + + ML99_ASSERT_UNEVAL(!ML99_IS_UPPERCASE(8)); + ML99_ASSERT_UNEVAL(!ML99_IS_UPPERCASE(i)); + ML99_ASSERT_UNEVAL(!ML99_IS_UPPERCASE(_)); + ML99_ASSERT_UNEVAL(!ML99_IS_UPPERCASE(abracadabra)); + + ML99_ASSERT(ML99_isUppercase(v(Z))); + ML99_ASSERT(ML99_not(ML99_isUppercase(v(8)))); + } + + // ML99_isDigit + { + ML99_ASSERT(ML99_isDigit(v(0))); + ML99_ASSERT(ML99_isDigit(v(2))); + ML99_ASSERT(ML99_isDigit(v(9))); + + ML99_ASSERT(ML99_not(ML99_isDigit(v(U)))); + ML99_ASSERT(ML99_not(ML99_isDigit(v(i)))); + ML99_ASSERT(ML99_not(ML99_isDigit(v(_)))); + ML99_ASSERT(ML99_not(ML99_isDigit(v(abracadabra)))); + } + + // ML99_IS_DIGIT + { + ML99_ASSERT_UNEVAL(ML99_IS_DIGIT(7)); + ML99_ASSERT_UNEVAL(!ML99_IS_DIGIT(k)); + } + + // ML99_isChar + { + ML99_ASSERT(ML99_isChar(v(0))); + ML99_ASSERT(ML99_isChar(v(4))); + ML99_ASSERT(ML99_isChar(v(8))); + + ML99_ASSERT(ML99_isChar(v(a))); + ML99_ASSERT(ML99_isChar(v(b))); + ML99_ASSERT(ML99_isChar(v(c))); + + ML99_ASSERT(ML99_isChar(v(A))); + ML99_ASSERT(ML99_isChar(v(B))); + ML99_ASSERT(ML99_isChar(v(C))); + + ML99_ASSERT(ML99_isChar(v(_))); + + ML99_ASSERT(ML99_not(ML99_isChar(v(kk)))); + ML99_ASSERT(ML99_not(ML99_isChar(v(0abc)))); + ML99_ASSERT(ML99_not(ML99_isChar(v(abracadabra)))); + } + + // ML99_IS_CHAR + { + ML99_ASSERT_UNEVAL(ML99_IS_CHAR(z)); + ML99_ASSERT_UNEVAL(!ML99_IS_CHAR(xyz)); + } + + // ML99_charLit + { + ML99_ASSERT_EQ(ML99_charLit(v(a)), v('a')); + ML99_ASSERT_EQ(ML99_charLit(v(b)), v('b')); + ML99_ASSERT_EQ(ML99_charLit(v(c)), v('c')); + ML99_ASSERT_EQ(ML99_charLit(v(d)), v('d')); + ML99_ASSERT_EQ(ML99_charLit(v(e)), v('e')); + ML99_ASSERT_EQ(ML99_charLit(v(f)), v('f')); + ML99_ASSERT_EQ(ML99_charLit(v(g)), v('g')); + ML99_ASSERT_EQ(ML99_charLit(v(h)), v('h')); + ML99_ASSERT_EQ(ML99_charLit(v(i)), v('i')); + ML99_ASSERT_EQ(ML99_charLit(v(j)), v('j')); + ML99_ASSERT_EQ(ML99_charLit(v(k)), v('k')); + ML99_ASSERT_EQ(ML99_charLit(v(l)), v('l')); + ML99_ASSERT_EQ(ML99_charLit(v(m)), v('m')); + ML99_ASSERT_EQ(ML99_charLit(v(n)), v('n')); + ML99_ASSERT_EQ(ML99_charLit(v(o)), v('o')); + ML99_ASSERT_EQ(ML99_charLit(v(p)), v('p')); + ML99_ASSERT_EQ(ML99_charLit(v(q)), v('q')); + ML99_ASSERT_EQ(ML99_charLit(v(r)), v('r')); + ML99_ASSERT_EQ(ML99_charLit(v(s)), v('s')); + ML99_ASSERT_EQ(ML99_charLit(v(t)), v('t')); + ML99_ASSERT_EQ(ML99_charLit(v(u)), v('u')); + ML99_ASSERT_EQ(ML99_charLit(v(v)), v('v')); + ML99_ASSERT_EQ(ML99_charLit(v(w)), v('w')); + ML99_ASSERT_EQ(ML99_charLit(v(x)), v('x')); + ML99_ASSERT_EQ(ML99_charLit(v(y)), v('y')); + ML99_ASSERT_EQ(ML99_charLit(v(z)), v('z')); + + ML99_ASSERT_EQ(ML99_charLit(v(A)), v('A')); + ML99_ASSERT_EQ(ML99_charLit(v(B)), v('B')); + ML99_ASSERT_EQ(ML99_charLit(v(C)), v('C')); + ML99_ASSERT_EQ(ML99_charLit(v(D)), v('D')); + ML99_ASSERT_EQ(ML99_charLit(v(E)), v('E')); + ML99_ASSERT_EQ(ML99_charLit(v(F)), v('F')); + ML99_ASSERT_EQ(ML99_charLit(v(G)), v('G')); + ML99_ASSERT_EQ(ML99_charLit(v(H)), v('H')); + ML99_ASSERT_EQ(ML99_charLit(v(I)), v('I')); + ML99_ASSERT_EQ(ML99_charLit(v(J)), v('J')); + ML99_ASSERT_EQ(ML99_charLit(v(K)), v('K')); + ML99_ASSERT_EQ(ML99_charLit(v(L)), v('L')); + ML99_ASSERT_EQ(ML99_charLit(v(M)), v('M')); + ML99_ASSERT_EQ(ML99_charLit(v(N)), v('N')); + ML99_ASSERT_EQ(ML99_charLit(v(O)), v('O')); + ML99_ASSERT_EQ(ML99_charLit(v(P)), v('P')); + ML99_ASSERT_EQ(ML99_charLit(v(Q)), v('Q')); + ML99_ASSERT_EQ(ML99_charLit(v(R)), v('R')); + ML99_ASSERT_EQ(ML99_charLit(v(S)), v('S')); + ML99_ASSERT_EQ(ML99_charLit(v(T)), v('T')); + ML99_ASSERT_EQ(ML99_charLit(v(U)), v('U')); + ML99_ASSERT_EQ(ML99_charLit(v(V)), v('V')); + ML99_ASSERT_EQ(ML99_charLit(v(W)), v('W')); + ML99_ASSERT_EQ(ML99_charLit(v(X)), v('X')); + ML99_ASSERT_EQ(ML99_charLit(v(Y)), v('Y')); + ML99_ASSERT_EQ(ML99_charLit(v(Z)), v('Z')); + + ML99_ASSERT_EQ(ML99_charLit(v(0)), v('0')); + ML99_ASSERT_EQ(ML99_charLit(v(1)), v('1')); + ML99_ASSERT_EQ(ML99_charLit(v(2)), v('2')); + ML99_ASSERT_EQ(ML99_charLit(v(3)), v('3')); + ML99_ASSERT_EQ(ML99_charLit(v(4)), v('4')); + ML99_ASSERT_EQ(ML99_charLit(v(5)), v('5')); + ML99_ASSERT_EQ(ML99_charLit(v(6)), v('6')); + ML99_ASSERT_EQ(ML99_charLit(v(7)), v('7')); + ML99_ASSERT_EQ(ML99_charLit(v(8)), v('8')); + ML99_ASSERT_EQ(ML99_charLit(v(9)), v('9')); + + ML99_ASSERT_EQ(ML99_charLit(v(_)), v('_')); + } + + // ML99_CHAR_LIT + { + ML99_ASSERT_UNEVAL(ML99_CHAR_LIT(r) == 'r'); + ML99_ASSERT_UNEVAL(ML99_CHAR_LIT(8) == '8'); + ML99_ASSERT_UNEVAL(ML99_CHAR_LIT(_) == '_'); + } + +#define FST(...) FST_AUX(__VA_ARGS__) +#define FST_AUX(x, ...) x + + // ML99_LOWERCASE_CHARS, ML99_UPPERCASE_CHARS, ML99_DIGITS + { + ML99_ASSERT_UNEVAL(ML99_CHAR_EQ(a, FST(ML99_LOWERCASE_CHARS(~, ~, ~)))); + ML99_ASSERT_UNEVAL(ML99_CHAR_EQ(A, FST(ML99_UPPERCASE_CHARS(~, ~, ~)))); + ML99_ASSERT_UNEVAL(FST(ML99_DIGITS(~, ~, ~)) == 0); + } + +#undef FST +#undef FST_AUX +} diff --git a/test/external/metalang99/tests/lang.c b/test/external/metalang99/tests/lang.c new file mode 100644 index 0000000..df76c3d --- /dev/null +++ b/test/external/metalang99/tests/lang.c @@ -0,0 +1,165 @@ +// `...` is sometimes used to workaround a TCC bug, see +// <https://github.com/hirrolot/datatype99/issues/10#issuecomment-830813172>. + +#include <metalang99/assert.h> +#include <metalang99/util.h> + +int main(void) { + + ML99_ASSERT_EMPTY_UNEVAL(ML99_EVAL(v())); + +#ifndef __TINYC__ +#define F_IMPL() v(123) +#else +#define F_IMPL(...) v(123) // `...` due to the TCC's bug. +#endif + + // A function with zero arguments + { + ML99_ASSERT_EQ(ML99_call(F, v()), v(123)); + ML99_ASSERT_EQ(ML99_call(v(F), v()), v(123)); + ML99_ASSERT_EQ(ML99_callUneval(F, ), v(123)); + } + +#undef F_IMPL + +#define F_IMPL(x, y, z) v(x##y##z) +#define BAR_IMPL(x, y) v(x + y) + + // Regular usage of the metalanguage + { + ML99_ASSERT_EQ(ML99_call(BAR, v(5), v(7)), v(5 + 7)); + ML99_ASSERT_EQ(ML99_call(ML99_call(F, v(B), v(A), v(R)), v(6), v(11)), v(6 + 11)); + + ML99_ASSERT_EQ(ML99_call(BAR, v(5, 7)), v(5 + 7)); + ML99_ASSERT_EQ(ML99_call(ML99_call(F, v(B, A, R)), v(6, 11)), v(6 + 11)); + + ML99_ASSERT_EQ(ML99_callUneval(BAR, 5, 7), v(5 + 7)); + } + +#undef F_IMPL +#undef BAR_IMPL + +// Even if a term in the argument position evaluates to more than one terms, they should be appended +// to each other but not interspersed with a comma. +#define F_IMPL(...) ML99_TERMS(v(1), v(2), v(3)) // `...` due to the TCC's bug. +#define BAR_IMPL(x) v() + + ML99_EVAL(ML99_call(BAR, ML99_call(F, v()))) + +#undef F_IMPL +#undef BAR_IMPL + +// Recursion might arise from a higher-order macro, if `op` invokes `F`, but nonetheless the +// second call to `F` must be performed as expected. +#define F_IMPL(op) ML99_call(op, v(123)) +#define OP_IMPL(x) ML99_call(F, v(ID)) +#define ID_IMPL(x) v(x) + + ML99_ASSERT_EQ(ML99_call(F, v(OP)), v(123)); + +#undef F_IMPL +#undef OP_IMPL +#undef ID_IMPL + + // ML99_abort + { + ML99_ASSERT_EMPTY(ML99_abort(v())); + ML99_ASSERT_EQ(ML99_abort(v(815057)), v(815057)); + ML99_ASSERT_UNEVAL(ML99_EVAL(v(~), ML99_abort(v(123)), v(~)) == 123); + +// Ensure that `ML99_abort` also works correctly after some evaluations. +#define F_IMPL(...) ML99_call(G, v(1, 2), ML99_call(H, v(123))) // `...` due to the TCC's bug. +#define G_IMPL(_1, _2, _123_plus_1) \ + ML99_abort(v(ML99_ASSERT_UNEVAL(_1 == 1 && _2 == 2 && _123_plus_1 == 123 + 1))) +#define H_IMPL(a) v(a + 1) + + ML99_EVAL(ML99_call(F, v())); + +#undef F_IMPL +#undef G_IMPL +#undef H_IMPL + + // Ensure that `ML99_abort` immediately aborts interpretation even in an argument position. + ML99_ASSERT_EQ(ML99_call(NonExistingF, ML99_abort(v(123))), v(123)); + } + + // Partial application + { + +#ifndef __TINYC__ +#define F_IMPL() v(123) +#else +#define F_IMPL(...) v(123) // // `...` due to the TCC's bug. +#endif + +#define F_ARITY 1 + + // The arity of a function with zero arguments must be 1 + { ML99_ASSERT_EQ(ML99_appl(v(F), v()), v(123)); } + +#undef F_IMPL +#undef F_ARITY + +#define F_IMPL(a, b, c, d) v(a##b##c##d) +#define F_ARITY 4 + + // Regular usage of partial application + { + ML99_ASSERT_EQ( + ML99_appl(ML99_appl(ML99_appl(ML99_appl(v(F), v(10)), v(5)), v(7)), v(8)), + v(10578)); + ML99_ASSERT_EQ( + ML99_appl(ML99_appl(ML99_appl2(v(F), v(10), v(5)), v(7)), v(8)), + v(10578)); + ML99_ASSERT_EQ(ML99_appl(ML99_appl3(v(F), v(10), v(5), v(7)), v(8)), v(10578)); + ML99_ASSERT_EQ(ML99_appl4(v(F), v(10), v(5), v(7), v(8)), v(10578)); + } + +#undef F_IMPL +#undef F_ARITY + +#define F_ARITY 255 + + // The maximum arity + { + ML99_EVAL(ML99_empty(ML99_appl(v(F), v(~)))) + ML99_EVAL(ML99_empty(ML99_appl2(v(F), v(~), v(~)))) + ML99_EVAL(ML99_empty(ML99_appl3(v(F), v(~), v(~), v(~)))) + } + +#undef F_ARITY + } + +#define F_IMPL(x) v((x + 1)) +#define G_IMPL(x) v((x * 8)) + +#define F_ARITY 1 +#define G_ARITY 1 + + // ML99_compose + { ML99_ASSERT_EQ(ML99_appl(ML99_compose(v(F), v(G)), v(3)), v((3 * 8) + 1)); } + +#undef F_IMPL +#undef G_IMPL + +#undef F_ARITY +#undef G_ARITY + +#define F_IMPL(x) v(x) + +#define PROG ML99_TERMS(v(1), v(, ), v(2), v(, ), ML99_call(F, v(7))) + +#define CHECK(...) CHECK_AUX(__VA_ARGS__) +#define CHECK_AUX(a, b, c) ML99_ASSERT_UNEVAL(a == 1 && b == 2 && c == 7) + + // ML99_QUOTE + { CHECK(ML99_EVAL(ML99_EVAL(ML99_QUOTE(PROG)))); } + +#undef F_IMPL + +#undef PROG + +#undef CHECK +#undef CHECK_AUX +} diff --git a/test/external/metalang99/tests/list.c b/test/external/metalang99/tests/list.c new file mode 100644 index 0000000..dcaeed6 --- /dev/null +++ b/test/external/metalang99/tests/list.c @@ -0,0 +1,528 @@ +#include <metalang99/assert.h> +#include <metalang99/list.h> +#include <metalang99/maybe.h> +#include <metalang99/nat.h> +#include <metalang99/tuple.h> +#include <metalang99/util.h> + +int main(void) { + +#define CMP_NATURALS(lhs, rhs) ML99_listEq(v(ML99_natEq), lhs, rhs) + + // ML99_list, ML99_cons, ML99_nil + { + ML99_ASSERT(CMP_NATURALS(ML99_nil(v(~, ~, ~)), ML99_nil())); + + ML99_ASSERT(ML99_listEq( + v(ML99_natEq), + ML99_list(v(1, 2, 3, 4, 5, 6, 7)), + ML99_cons( + v(1), + ML99_cons( + v(2), + ML99_cons( + v(3), + ML99_cons( + v(4), + ML99_cons(v(5), ML99_cons(v(6), ML99_cons(v(7), ML99_nil()))))))))); + } + +#define F_IMPL(x, y) ML99_add(v(x), v(y)) +#define F_ARITY 1 + + // ML99_listFromTuples + { + ML99_ASSERT(CMP_NATURALS(ML99_listFromTuples(v(F), v((1, 2))), ML99_list(v(3)))); + ML99_ASSERT(CMP_NATURALS( + ML99_listFromTuples(v(F), v((1, 2), (3, 4), (5, 6))), + ML99_list(v(3, 7, 11)))); + } + +#undef F_IMPL +#undef F_ARITY + + // ML99_listFromSeq + { + ML99_ASSERT(ML99_isNil(ML99_listFromSeq(ML99_empty()))); + ML99_ASSERT(CMP_NATURALS(ML99_listFromSeq(v((1))), ML99_list(v(1)))); + ML99_ASSERT(CMP_NATURALS(ML99_listFromSeq(v((1)(2))), ML99_list(v(1, 2)))); + ML99_ASSERT(CMP_NATURALS(ML99_listFromSeq(v((1)(2)(3))), ML99_list(v(1, 2, 3)))); + } + + // ML99_listHead + { + ML99_ASSERT_EQ(ML99_listHead(ML99_list(v(1))), v(1)); + ML99_ASSERT_EQ(ML99_listHead(ML99_list(v(1, 2))), v(1)); + ML99_ASSERT_EQ(ML99_listHead(ML99_list(v(1, 2, 3))), v(1)); + } + + // ML99_listTail + { + ML99_ASSERT(CMP_NATURALS(ML99_listTail(ML99_list(v(1))), ML99_nil())); + ML99_ASSERT(CMP_NATURALS(ML99_listTail(ML99_list(v(1, 2))), ML99_list(v(2)))); + ML99_ASSERT(CMP_NATURALS(ML99_listTail(ML99_list(v(1, 2, 3))), ML99_list(v(2, 3)))); + } + + // ML99_listLast + { + ML99_ASSERT_EQ(ML99_listLast(ML99_list(v(1))), v(1)); + ML99_ASSERT_EQ(ML99_listLast(ML99_list(v(1, 2))), v(2)); + ML99_ASSERT_EQ(ML99_listLast(ML99_list(v(1, 2, 3))), v(3)); + } + + // ML99_listInit + { + ML99_ASSERT(CMP_NATURALS(ML99_listInit(ML99_list(v(1))), ML99_nil())); + ML99_ASSERT(CMP_NATURALS(ML99_listInit(ML99_list(v(1, 2))), ML99_list(v(1)))); + ML99_ASSERT(CMP_NATURALS(ML99_listInit(ML99_list(v(1, 2, 3))), ML99_list(v(1, 2)))); + } + + // ML99_listLen + { + ML99_ASSERT_EQ(ML99_listLen(ML99_nil()), v(0)); + ML99_ASSERT_EQ(ML99_listLen(ML99_list(v(123))), v(1)); + ML99_ASSERT_EQ(ML99_listLen(ML99_list(v(123, 222))), v(2)); + ML99_ASSERT_EQ(ML99_listLen(ML99_list(v(123, 222, 18))), v(3)); + } + + // ML99_listAppend + { + ML99_ASSERT(CMP_NATURALS(ML99_listAppend(ML99_nil(), ML99_nil()), ML99_nil())); + ML99_ASSERT(CMP_NATURALS( + ML99_listAppend(ML99_nil(), ML99_list(v(1, 2, 3))), + ML99_list(v(1, 2, 3)))); + ML99_ASSERT(CMP_NATURALS( + ML99_listAppend(ML99_list(v(1, 2, 3)), ML99_nil()), + ML99_list(v(1, 2, 3)))); + + ML99_ASSERT(CMP_NATURALS( + ML99_listAppend(ML99_list(v(1, 2, 3)), ML99_list(v(4, 5, 6))), + ML99_list(v(1, 2, 3, 4, 5, 6)))); + } + + // ML99_listAppendItem + { + ML99_ASSERT(CMP_NATURALS(ML99_listAppendItem(v(123), ML99_nil()), ML99_list(v(123)))); + ML99_ASSERT(CMP_NATURALS( + ML99_listAppendItem(v(222), ML99_list(v(1, 2, 3))), + ML99_list(v(1, 2, 3, 222)))); + } + + // ML99_listReverse + { + ML99_ASSERT(CMP_NATURALS(ML99_listReverse(ML99_nil()), ML99_nil())); + ML99_ASSERT(CMP_NATURALS(ML99_listReverse(ML99_list(v(1, 2, 3))), ML99_list(v(3, 2, 1)))); + } + + // ML99_listContains + { + ML99_ASSERT(ML99_not(ML99_listContains(v(ML99_natEq), v(1), ML99_nil()))); + ML99_ASSERT(ML99_listContains(v(ML99_natEq), v(1), ML99_list(v(1, 2, 3)))); + ML99_ASSERT(ML99_listContains(v(ML99_natEq), v(2), ML99_list(v(1, 2, 3)))); + ML99_ASSERT(ML99_listContains(v(ML99_natEq), v(3), ML99_list(v(1, 2, 3)))); + ML99_ASSERT(ML99_not(ML99_listContains(v(ML99_natEq), v(187), ML99_list(v(1, 2, 3))))); + } + + // ML99_listUnwrap + { + ML99_ASSERT_EMPTY(ML99_listUnwrap(ML99_nil())); + ML99_ASSERT_EQ(ML99_listUnwrap(ML99_list(v(18, +, 3, +, 6))), v(18 + 3 + 6)); + } + + // ML99_LIST_EVAL + { + ML99_ASSERT_EMPTY_UNEVAL(ML99_LIST_EVAL(ML99_nil())); + ML99_ASSERT_UNEVAL(ML99_LIST_EVAL(ML99_list(v(19, +, 6))) == 19 + 6); + } + +#define CHECK(a, b, c) ML99_ASSERT_UNEVAL(a == 1 && b == 2 && c == 3) +#define CHECK_EXPAND(args) CHECK(args) + + // ML99_listUnwrapCommaSep + { + ML99_ASSERT_EMPTY(ML99_listUnwrapCommaSep(ML99_nil())); + CHECK_EXPAND(ML99_EVAL(ML99_listUnwrapCommaSep(ML99_list(v(1, 2, 3))))); + } + + // ML99_LIST_EVAL_COMMA_SEP + { + ML99_ASSERT_EMPTY_UNEVAL(ML99_LIST_EVAL_COMMA_SEP(ML99_nil())); + CHECK_EXPAND(ML99_EVAL(v(ML99_LIST_EVAL_COMMA_SEP(ML99_list(v(1, 2, 3)))))); + } + +#undef CHECK +#undef CHECK_EXPAND + + // ML99_isNil + { + ML99_ASSERT(ML99_isNil(ML99_nil())); + ML99_ASSERT(ML99_not(ML99_isNil(ML99_list(v(123))))); + ML99_ASSERT(ML99_not(ML99_isNil(ML99_list(v(8, 214, 10, 0, 122))))); + } + + // ML99_IS_NIL + { + ML99_ASSERT_UNEVAL(ML99_IS_NIL(ML99_NIL())); + ML99_ASSERT_UNEVAL(ML99_NOT(ML99_IS_NIL(ML99_CONS(123, ML99_NIL())))); + ML99_ASSERT_UNEVAL(ML99_NOT(ML99_IS_NIL(ML99_EVAL(ML99_list(v(8, 214, 10, 0, 122)))))); + } + + // ML99_isCons + { + ML99_ASSERT(ML99_not(ML99_isCons(ML99_nil()))); + ML99_ASSERT(ML99_isCons(ML99_list(v(123)))); + ML99_ASSERT(ML99_isCons(ML99_list(v(8, 214, 10, 0, 122)))); + } + + // ML99_IS_CONS + { + ML99_ASSERT_UNEVAL(ML99_NOT(ML99_IS_CONS(ML99_NIL()))); + ML99_ASSERT_UNEVAL(ML99_IS_CONS(ML99_CONS(123, ML99_NIL()))); + ML99_ASSERT_UNEVAL(ML99_IS_CONS(ML99_EVAL(ML99_list(v(8, 214, 10, 0, 122))))); + } + + // ML99_listGet + { + ML99_ASSERT_EQ(ML99_listGet(v(0), ML99_list(v(123, 222))), v(123)); + ML99_ASSERT_EQ(ML99_listGet(v(1), ML99_list(v(123, 222))), v(222)); + } + + // ML99_listTake + { + ML99_ASSERT(CMP_NATURALS(ML99_listTake(v(1), ML99_nil()), ML99_nil())); + ML99_ASSERT(CMP_NATURALS(ML99_listTake(v(200), ML99_nil()), ML99_nil())); + + ML99_ASSERT(CMP_NATURALS(ML99_listTake(v(1), ML99_list(v(1, 2, 3))), ML99_list(v(1)))); + ML99_ASSERT(CMP_NATURALS(ML99_listTake(v(2), ML99_list(v(1, 2, 3))), ML99_list(v(1, 2)))); + ML99_ASSERT( + CMP_NATURALS(ML99_listTake(v(3), ML99_list(v(1, 2, 3))), ML99_list(v(1, 2, 3)))); + } + + // ML99_listTakeWhile + { + ML99_ASSERT(CMP_NATURALS( + ML99_listTakeWhile(ML99_appl(v(ML99_lesser), v(5)), ML99_nil()), + ML99_nil())); + ML99_ASSERT(CMP_NATURALS( + ML99_listTakeWhile(ML99_appl(v(ML99_greater), v(5)), ML99_list(v(7))), + ML99_nil())); + ML99_ASSERT(CMP_NATURALS( + ML99_listTakeWhile(ML99_appl(v(ML99_greater), v(5)), ML99_list(v(1, 9, 7))), + ML99_list(v(1)))); + ML99_ASSERT(CMP_NATURALS( + ML99_listTakeWhile(ML99_appl(v(ML99_greater), v(5)), ML99_list(v(4, 9, 2, 3))), + ML99_list(v(4)))); + ML99_ASSERT(CMP_NATURALS( + ML99_listTakeWhile(ML99_appl(v(ML99_greater), v(5)), ML99_list(v(2, 4, 7, 9, 28))), + ML99_list(v(2, 4)))); + } + + // ML99_listDrop + { + ML99_ASSERT(CMP_NATURALS(ML99_listDrop(v(1), ML99_nil()), ML99_nil())); + ML99_ASSERT(CMP_NATURALS(ML99_listDrop(v(200), ML99_nil()), ML99_nil())); + + ML99_ASSERT(CMP_NATURALS(ML99_listDrop(v(1), ML99_list(v(1, 2, 3))), ML99_list(v(2, 3)))); + ML99_ASSERT(CMP_NATURALS(ML99_listDrop(v(2), ML99_list(v(1, 2, 3))), ML99_list(v(3)))); + ML99_ASSERT(CMP_NATURALS(ML99_listDrop(v(3), ML99_list(v(1, 2, 3))), ML99_nil())); + } + + // ML99_listDropWhile + { + ML99_ASSERT(CMP_NATURALS( + ML99_listDropWhile(ML99_appl(v(ML99_lesser), v(5)), ML99_nil()), + ML99_nil())); + ML99_ASSERT(CMP_NATURALS( + ML99_listDropWhile(ML99_appl(v(ML99_greater), v(5)), ML99_list(v(7))), + ML99_list(v(7)))); + ML99_ASSERT(CMP_NATURALS( + ML99_listDropWhile(ML99_appl(v(ML99_greater), v(5)), ML99_list(v(1, 9, 7))), + ML99_list(v(9, 7)))); + ML99_ASSERT(CMP_NATURALS( + ML99_listDropWhile(ML99_appl(v(ML99_greater), v(5)), ML99_list(v(4, 9, 2, 3))), + ML99_list(v(9, 2, 3)))); + ML99_ASSERT(CMP_NATURALS( + ML99_listDropWhile(ML99_appl(v(ML99_greater), v(5)), ML99_list(v(2, 4, 7, 9, 28))), + ML99_list(v(7, 9, 28)))); + } + +#define EQ_IMPL(x, y) \ + v(ML99_AND( \ + ML99_NAT_EQ(ML99_TUPLE_GET(0)(x), ML99_TUPLE_GET(0)(y)), \ + ML99_NAT_EQ(ML99_TUPLE_GET(1)(x), ML99_TUPLE_GET(1)(y)))) +#define EQ_ARITY 2 + + // ML99_listZip + { + ML99_ASSERT(ML99_listEq(v(EQ), ML99_listZip(ML99_nil(), ML99_nil()), ML99_nil())); + ML99_ASSERT( + ML99_listEq(v(EQ), ML99_listZip(ML99_list(v(1, 2, 3)), ML99_nil()), ML99_nil())); + ML99_ASSERT( + ML99_listEq(v(EQ), ML99_listZip(ML99_nil(), ML99_list(v(1, 2, 3))), ML99_nil())); + + ML99_ASSERT(ML99_listEq( + v(EQ), + ML99_listZip(ML99_list(v(1, 2, 3)), ML99_list(v(4, 5, 6))), + ML99_list(ML99_tuple(v(1, 4)), ML99_tuple(v(2, 5)), ML99_tuple(v(3, 6))))); + + ML99_ASSERT(ML99_listEq( + v(EQ), + ML99_listZip(ML99_list(v(1, 2, 3)), ML99_list(v(4, 5))), + ML99_list(ML99_tuple(v(1, 4)), ML99_tuple(v(2, 5))))); + + ML99_ASSERT(ML99_listEq( + v(EQ), + ML99_listZip(ML99_list(v(1, 2)), ML99_list(v(4, 5, 6))), + ML99_list(ML99_tuple(v(1, 4)), ML99_tuple(v(2, 5))))); + } + +#undef EQ_IMPL +#undef EQ_ARITY + + // ML99_listUnzip & ML99_listZip + { +#define UNZIPPED ML99_listUnzip(ML99_nil()) + + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(0)(UNZIPPED), ML99_nil())); + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(1)(UNZIPPED), ML99_nil())); + +#undef UNZIPPED + +#define UNZIPPED ML99_listUnzip(ML99_listZip(ML99_list(v(1, 2)), ML99_list(v(4, 5)))) + + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(0)(UNZIPPED), ML99_list(v(1, 2)))); + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(1)(UNZIPPED), ML99_list(v(4, 5)))); + +#undef UNZIPPED + } + + // ML99_listEq + { + ML99_ASSERT(CMP_NATURALS(ML99_nil(), ML99_nil())); + ML99_ASSERT(ML99_not(CMP_NATURALS(ML99_nil(), ML99_list(v(25, 88, 1))))); + ML99_ASSERT(ML99_not(CMP_NATURALS(ML99_list(v(25, 88, 1)), ML99_nil()))); + + ML99_ASSERT(CMP_NATURALS(ML99_list(v(1, 2, 3)), ML99_list(v(1, 2, 3)))); + ML99_ASSERT(ML99_not(CMP_NATURALS(ML99_list(v(1, 2, 3)), ML99_list(v(1))))); + ML99_ASSERT(ML99_not(CMP_NATURALS(ML99_list(v(1)), ML99_list(v(1, 2, 3))))); + ML99_ASSERT(ML99_not(CMP_NATURALS(ML99_list(v(0, 5, 6, 6)), ML99_list(v(6, 7))))); + } + + // ML99_listAppl + { + ML99_ASSERT_EQ(ML99_call(ML99_listAppl(v(ML99_add), ML99_nil()), v(6, 9)), v(6 + 9)); + ML99_ASSERT_EQ(ML99_appl(ML99_listAppl(v(ML99_add), ML99_list(v(6))), v(9)), v(6 + 9)); + ML99_ASSERT_EQ(ML99_listAppl(v(ML99_add), ML99_list(v(6, 9))), v(6 + 9)); + } + + // ML99_listPrependToAll + { + ML99_ASSERT(CMP_NATURALS(ML99_listPrependToAll(v(+), ML99_nil()), ML99_nil())); + ML99_ASSERT(CMP_NATURALS( + ML99_listPrependToAll(v(111), ML99_list(v(5, 9, 22))), + ML99_list(v(111, 5, 111, 9, 111, 22)))); + } + + // ML99_listIntersperse + { + ML99_ASSERT(CMP_NATURALS(ML99_listIntersperse(v(+), ML99_nil()), ML99_nil())); + ML99_ASSERT(CMP_NATURALS( + ML99_listIntersperse(v(111), ML99_list(v(5, 9, 22))), + ML99_list(v(5, 111, 9, 111, 22)))); + } + +#define ABCDEFG ML99_TRUE() + + // ML99_listFoldr + { + ML99_ASSERT_EQ(ML99_listFoldr(v(ML99_cat), v(7), ML99_nil()), v(7)); + ML99_ASSERT( + ML99_listFoldr(ML99_appl(v(ML99_flip), v(ML99_cat)), v(A), ML99_list(v(G, DEF, BC)))); + } + + // ML99_listFoldl + { + ML99_ASSERT_EQ(ML99_listFoldl(v(ML99_cat), v(7), ML99_nil()), v(7)); + ML99_ASSERT(ML99_listFoldl(v(ML99_cat), v(A), ML99_list(v(BC, DEF, G)))); + } + + // ML99_listFoldl1 + { ML99_ASSERT(ML99_listFoldl1(v(ML99_cat), ML99_list(v(AB, CDEF, G)))); } + +#undef ABCDEFG + + // ML99_listMap + { + ML99_ASSERT( + CMP_NATURALS(ML99_listMap(ML99_appl(v(ML99_add), v(3)), ML99_nil()), ML99_nil())); + ML99_ASSERT(CMP_NATURALS( + ML99_listMap(ML99_appl(v(ML99_add), v(3)), ML99_list(v(1, 2, 3))), + ML99_list(v(4, 5, 6)))); + } + +#define A0 19 +#define B1 6 +#define C2 11 + + // ML99_listMapI + { + ML99_ASSERT(CMP_NATURALS(ML99_listMapI(v(ML99_cat), ML99_nil()), ML99_nil())); + ML99_ASSERT(CMP_NATURALS( + ML99_listMapI(v(ML99_cat), ML99_list(v(A, B, C))), + ML99_list(v(19, 6, 11)))); + } + +#undef A0 +#undef B1 +#undef C2 + +#define FOO_x +#define FOO_y +#define FOO_z + + // ML99_listMapInPlace + { + ML99_ASSERT_EMPTY(ML99_listMapInPlace(v(NonExistingF), ML99_nil())); + ML99_EVAL(ML99_listMapInPlace(ML99_appl(v(ML99_cat), v(FOO_)), ML99_list(v(x, y, z)))) + } + +#undef FOO_x +#undef FOO_y +#undef FOO_z + +#define FOO_x0 +#define FOO_y1 +#define FOO_z2 + +#define MY_CAT_IMPL(x, i) v(FOO_##x##i) +#define MY_CAT_ARITY 2 + + // ML99_listMapInPlaceI + { + ML99_ASSERT_EMPTY(ML99_listMapInPlaceI(v(NonExistingF), ML99_nil())); + ML99_EVAL(ML99_listMapInPlaceI(v(MY_CAT), ML99_list(v(x, y, z)))) + } + +#undef MY_CAT_IMPL +#undef MY_CAT_ARITY + +#undef FOO_x +#undef FOO_y +#undef FOO_z + + // ML99_listFor + { + ML99_ASSERT( + CMP_NATURALS(ML99_listFor(ML99_nil(), ML99_appl(v(ML99_add), v(3))), ML99_nil())); + ML99_ASSERT(CMP_NATURALS( + ML99_listFor(ML99_list(v(1, 2, 3)), ML99_appl(v(ML99_add), v(3))), + ML99_list(v(4, 5, 6)))); + } + + // ML99_listMapInitLast + { + ML99_ASSERT(CMP_NATURALS( + ML99_listMapInitLast( + ML99_appl(v(ML99_add), v(3)), + ML99_appl(v(ML99_add), v(19)), + ML99_list(v(4))), + ML99_list(v(23)))); + ML99_ASSERT(CMP_NATURALS( + ML99_listMapInitLast( + ML99_appl(v(ML99_add), v(3)), + ML99_appl(v(ML99_add), v(7)), + ML99_list(v(1, 2, 3))), + ML99_list(v(4, 5, 10)))); + } + + // ML99_listForInitLast + { + ML99_ASSERT(CMP_NATURALS( + ML99_listForInitLast( + ML99_list(v(4)), + ML99_appl(v(ML99_add), v(3)), + ML99_appl(v(ML99_add), v(19))), + ML99_list(v(23)))); + ML99_ASSERT(CMP_NATURALS( + ML99_listForInitLast( + ML99_list(v(1, 2, 3)), + ML99_appl(v(ML99_add), v(3)), + ML99_appl(v(ML99_add), v(7))), + ML99_list(v(4, 5, 10)))); + } + + // ML99_listFilter + { + ML99_ASSERT( + CMP_NATURALS(ML99_listFilter(ML99_appl(v(ML99_add), v(3)), ML99_nil()), ML99_nil())); + ML99_ASSERT(CMP_NATURALS( + ML99_listFilter(ML99_appl(v(ML99_lesser), v(3)), ML99_list(v(14, 0, 1, 7, 2, 65, 3))), + ML99_list(v(14, 7, 65)))); + } + + // ML99_listFilterMap + { +#define LIST ML99_list(v(5, 7, 3, 12)) + +#define F_IMPL(x) ML99_if(ML99_lesserEq(v(x), v(5)), ML99_just(v(x)), ML99_nothing()) +#define F_ARITY 1 + + ML99_ASSERT(CMP_NATURALS(ML99_listFilterMap(v(F), LIST), ML99_list(v(5, 3)))); + +#undef F_IMPL +#undef F_ARITY + +#undef LIST + } + + // ML99_listReplicate + { + ML99_ASSERT(CMP_NATURALS(ML99_listReplicate(v(0), v(~)), ML99_nil())); + ML99_ASSERT(CMP_NATURALS(ML99_listReplicate(v(3), v(7)), ML99_list(v(7, 7, 7)))); + } + + // ML99_listPartition + { + + // Partitioning ML99_nil() + { +#define PARTITIONED ML99_listPartition(ML99_appl(v(ML99_greater), v(10)), ML99_nil()) + + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(0)(PARTITIONED), ML99_nil())); + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(1)(PARTITIONED), ML99_nil())); + +#undef PARTITIONED + } + + // Only the second list contains items + { +#define PARTITIONED ML99_listPartition(ML99_appl(v(ML99_greater), v(10)), ML99_list(v(11, 12, 13))) + + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(0)(PARTITIONED), ML99_nil())); + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(1)(PARTITIONED), ML99_list(v(11, 12, 13)))); + +#undef PARTITIONED + } + + // Only the first list contains items + { +#define PARTITIONED ML99_listPartition(ML99_appl(v(ML99_greater), v(10)), ML99_list(v(4, 7))) + + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(0)(PARTITIONED), ML99_list(v(4, 7)))); + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(1)(PARTITIONED), ML99_nil())); + +#undef PARTITIONED + } + + // Both lists contain items + { +#define PARTITIONED \ + ML99_listPartition(ML99_appl(v(ML99_greater), v(10)), ML99_list(v(11, 4, 12, 13, 7))) + + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(0)(PARTITIONED), ML99_list(v(4, 7)))); + ML99_ASSERT(CMP_NATURALS(ML99_tupleGet(1)(PARTITIONED), ML99_list(v(11, 12, 13)))); + +#undef PARTITIONED + } + } +} diff --git a/test/external/metalang99/tests/maybe.c b/test/external/metalang99/tests/maybe.c new file mode 100644 index 0000000..f8b169b --- /dev/null +++ b/test/external/metalang99/tests/maybe.c @@ -0,0 +1,58 @@ +#include <metalang99/assert.h> +#include <metalang99/maybe.h> +#include <metalang99/nat.h> + +int main(void) { + +#define MATCH_IMPL(maybe) ML99_match(v(maybe), v(MATCH_)) +#define MATCH_just_IMPL(x) v(ML99_ASSERT_UNEVAL(x == 87)) +#define MATCH_nothing_IMPL(_) v(ML99_ASSERT_UNEVAL(1)) + + // Pattern matching + { + ML99_EVAL(ML99_call(MATCH, ML99_just(v(87)))); + ML99_EVAL(ML99_call(MATCH, ML99_nothing(~, ~, ~))); + } + +#undef MATCH_IMPL +#undef MATCH_just_IMPL +#undef MATCH_nothing_IMPL + +#define VAL v(abc ? +-148 % "hello world") + + // ML99_isJust + { + ML99_ASSERT(ML99_isJust(ML99_just(VAL))); + ML99_ASSERT(ML99_not(ML99_isJust(ML99_nothing()))); + } + + // ML99_IS_JUST + { + ML99_ASSERT_UNEVAL(ML99_IS_JUST(ML99_JUST(VAL))); + ML99_ASSERT_UNEVAL(!ML99_IS_JUST(ML99_NOTHING())); + } + + // ML99_isNothing + { + ML99_ASSERT(ML99_isNothing(ML99_nothing())); + ML99_ASSERT(ML99_not(ML99_isNothing(ML99_just(VAL)))); + } + + // ML99_IS_NOTHING + { + ML99_ASSERT_UNEVAL(ML99_IS_NOTHING(ML99_NOTHING())); + ML99_ASSERT_UNEVAL(!ML99_IS_NOTHING(ML99_JUST(VAL))); + } + + // ML99_maybeEq + { + ML99_ASSERT(ML99_maybeEq(v(ML99_natEq), ML99_just(v(123)), ML99_just(v(123)))); + + ML99_ASSERT(ML99_not(ML99_maybeEq(v(ML99_natEq), ML99_just(v(123)), ML99_just(v(4))))); + ML99_ASSERT(ML99_not(ML99_maybeEq(v(ML99_natEq), ML99_just(v(123)), ML99_nothing()))); + ML99_ASSERT(ML99_not(ML99_maybeEq(v(ML99_natEq), ML99_nothing(), ML99_just(v(123))))); + } + + // ML99_maybeUnwrap + { ML99_ASSERT_EQ(ML99_maybeUnwrap(ML99_just(v(123))), v(123)); } +} diff --git a/test/external/metalang99/tests/metalang99.c b/test/external/metalang99/tests/metalang99.c new file mode 100644 index 0000000..b469885 --- /dev/null +++ b/test/external/metalang99/tests/metalang99.c @@ -0,0 +1,51 @@ +#include <metalang99.h> +#include <metalang99/assert.h> + +int main(void) { + +#undef ML99_MAJOR +#undef ML99_MINOR +#undef ML99_PATCH + +#define ML99_MAJOR 1 +#define ML99_MINOR 2 +#define ML99_PATCH 3 + + // ML99_VERSION_COMPATIBLE + { + + ML99_ASSERT_UNEVAL(ML99_VERSION_COMPATIBLE(1, 0, 0)); + ML99_ASSERT_UNEVAL(ML99_VERSION_COMPATIBLE(1, 1, 0)); + ML99_ASSERT_UNEVAL(ML99_VERSION_COMPATIBLE(1, 1, 1)); + + ML99_ASSERT_UNEVAL(ML99_VERSION_COMPATIBLE(1, 2, 0)); + ML99_ASSERT_UNEVAL(ML99_VERSION_COMPATIBLE(1, 2, 1)); + ML99_ASSERT_UNEVAL(ML99_VERSION_COMPATIBLE(1, 2, 2)); + ML99_ASSERT_UNEVAL(ML99_VERSION_COMPATIBLE(1, 2, 3)); + + // Major-incompatible. + ML99_ASSERT_UNEVAL(!ML99_VERSION_COMPATIBLE(2, 0, 0)); + ML99_ASSERT_UNEVAL(!ML99_VERSION_COMPATIBLE(7, 1, 2)); + + // Minor-incompatible. + ML99_ASSERT_UNEVAL(!ML99_VERSION_COMPATIBLE(1, 3, 0)); + ML99_ASSERT_UNEVAL(!ML99_VERSION_COMPATIBLE(1, 4, 9)); + + // Patch-incompatible. + ML99_ASSERT_UNEVAL(!ML99_VERSION_COMPATIBLE(1, 2, 4)); + ML99_ASSERT_UNEVAL(!ML99_VERSION_COMPATIBLE(1, 2, 5)); + } + + // ML99_VERSION_EQ + { + ML99_ASSERT_UNEVAL(ML99_VERSION_EQ(1, 2, 3)); + + ML99_ASSERT_UNEVAL(!ML99_VERSION_EQ(1, 2, 7)); + ML99_ASSERT_UNEVAL(!ML99_VERSION_EQ(1, 7, 3)); + ML99_ASSERT_UNEVAL(!ML99_VERSION_EQ(7, 2, 3)); + } + +#undef ML99_MAJOR +#undef ML99_MINOR +#undef ML99_PATCH +} diff --git a/test/external/metalang99/tests/nat.c b/test/external/metalang99/tests/nat.c new file mode 100644 index 0000000..0509d8e --- /dev/null +++ b/test/external/metalang99/tests/nat.c @@ -0,0 +1,260 @@ +// `...` is sometimes used to workaround a TCC bug, see +// <https://github.com/hirrolot/datatype99/issues/10#issuecomment-830813172>. + +#include <metalang99/assert.h> +#include <metalang99/nat.h> + +int main(void) { + +#define MATCH_Z_IMPL(...) v(88) // `...` due to the TCC's bug. +#define MATCH_S_IMPL(x) v(x) + + // ML99_natMatch + { + ML99_ASSERT_EQ(ML99_natMatch(v(0), v(MATCH_)), v(88)); + ML99_ASSERT_EQ(ML99_natMatch(v(123), v(MATCH_)), v(122)); + } + +#undef MATCH_Z_IMPL +#undef MATCH_S_IMPL + +#define MATCH_Z_IMPL(x, y, z) v(ML99_ASSERT_UNEVAL(x == 1 && y == 2 && z == 3)) +#define MATCH_S_IMPL(n, x, y, z) v(ML99_ASSERT_UNEVAL(n == 122 && x == 1 && y == 2 && z == 3)) + + // ML99_natMatchWithArgs + { + ML99_EVAL(ML99_natMatchWithArgs(v(0), v(MATCH_), v(1, 2, 3))); + ML99_EVAL(ML99_natMatchWithArgs(v(123), v(MATCH_), v(1, 2, 3))); + } + +#undef MATCH_Z_IMPL +#undef MATCH_S_IMPL + + // ML99_inc + { + ML99_ASSERT_EQ(ML99_inc(v(0)), v(1)); + ML99_ASSERT_EQ(ML99_inc(v(15)), v(16)); + ML99_ASSERT_EQ(ML99_inc(v(198)), v(199)); + ML99_ASSERT_EQ(ML99_inc(v(254)), v(ML99_NAT_MAX)); + ML99_ASSERT_EQ(ML99_inc(v(ML99_NAT_MAX)), v(0)); + } + + // ML99_INC + { + ML99_ASSERT_UNEVAL(ML99_INC(0) == 1); + ML99_ASSERT_UNEVAL(ML99_INC(15) == 16); + ML99_ASSERT_UNEVAL(ML99_INC(254) == ML99_NAT_MAX); + } + + // ML99_dec + { + ML99_ASSERT_EQ(ML99_dec(v(0)), v(ML99_NAT_MAX)); + ML99_ASSERT_EQ(ML99_dec(v(1)), v(0)); + ML99_ASSERT_EQ(ML99_dec(v(71)), v(70)); + ML99_ASSERT_EQ(ML99_dec(v(201)), v(200)); + ML99_ASSERT_EQ(ML99_dec(v(ML99_NAT_MAX)), v(254)); + } + + // ML99_DEC + { + ML99_ASSERT_UNEVAL(ML99_DEC(0) == ML99_NAT_MAX); + ML99_ASSERT_UNEVAL(ML99_DEC(1) == 0); + ML99_ASSERT_UNEVAL(ML99_DEC(ML99_NAT_MAX) == 254); + } + + // ML99_natEq + { + ML99_ASSERT(ML99_natEq(v(0), v(0))); + ML99_ASSERT(ML99_natEq(v(18), v(18))); + ML99_ASSERT(ML99_natEq(v(183), v(183))); + ML99_ASSERT(ML99_natEq(v(ML99_NAT_MAX), v(ML99_NAT_MAX))); + + ML99_ASSERT(ML99_not(ML99_natEq(v(0), v(1)))); + ML99_ASSERT(ML99_not(ML99_natEq(v(198), v(91)))); + } + + // ML99_NAT_EQ + { + ML99_ASSERT_UNEVAL(ML99_NAT_EQ(18, 18)); + ML99_ASSERT_UNEVAL(!ML99_NAT_EQ(198, 91)); + } + + // ML99_natNeq + { + ML99_ASSERT(ML99_natNeq(v(0), v(1))); + ML99_ASSERT(ML99_natNeq(v(0), v(168))); + ML99_ASSERT(ML99_natNeq(v(1), v(34))); + ML99_ASSERT(ML99_natNeq(v(184), v(381))); + ML99_ASSERT(ML99_natNeq(v(3), v(101))); + + ML99_ASSERT(ML99_not(ML99_natNeq(v(0), v(0)))); + ML99_ASSERT(ML99_not(ML99_natNeq(v(101), v(101)))); + } + + // ML99_NAT_NEQ + { + ML99_ASSERT_UNEVAL(ML99_NAT_NEQ(0, 168)); + ML99_ASSERT_UNEVAL(!ML99_NAT_NEQ(101, 101)); + } + + // ML99_greater + { + ML99_ASSERT(ML99_greater(v(1), v(0))); + ML99_ASSERT(ML99_greater(v(ML99_NAT_MAX), v(0))); + ML99_ASSERT(ML99_greater(v(5), v(4))); + ML99_ASSERT(ML99_greater(v(147), v(80))); + ML99_ASSERT(ML99_greater(v(217), v(209))); + + ML99_ASSERT(ML99_not(ML99_greater(v(0), v(13)))); + ML99_ASSERT(ML99_not(ML99_greater(v(17), v(120)))); + } + + // ML99_lesser + { + ML99_ASSERT(ML99_lesser(v(0), v(1))); + ML99_ASSERT(ML99_lesser(v(0), v(ML99_NAT_MAX))); + ML99_ASSERT(ML99_lesser(v(19), v(25))); + ML99_ASSERT(ML99_lesser(v(109), v(110))); + ML99_ASSERT(ML99_lesser(v(10), v(208))); + + ML99_ASSERT(ML99_not(ML99_lesser(v(12), v(0)))); + ML99_ASSERT(ML99_not(ML99_lesser(v(123), v(123)))); + } + + // ML99_greaterEq + { + ML99_ASSERT(ML99_greaterEq(v(0), v(0))); + ML99_ASSERT(ML99_greaterEq(v(18), v(18))); + ML99_ASSERT(ML99_greaterEq(v(175), v(175))); + ML99_ASSERT(ML99_greaterEq(v(ML99_NAT_MAX), v(ML99_NAT_MAX))); + + ML99_ASSERT(ML99_greaterEq(v(1), v(0))); + ML99_ASSERT(ML99_greaterEq(v(ML99_NAT_MAX), v(0))); + ML99_ASSERT(ML99_greaterEq(v(19), v(10))); + ML99_ASSERT(ML99_greaterEq(v(178), v(177))); + + ML99_ASSERT(ML99_not(ML99_greaterEq(v(0), v(7)))); + ML99_ASSERT(ML99_not(ML99_greaterEq(v(1), v(19)))); + } + + // ML99_lesserEq + { + ML99_ASSERT(ML99_lesserEq(v(0), v(0))); + ML99_ASSERT(ML99_lesserEq(v(2), v(2))); + ML99_ASSERT(ML99_lesserEq(v(1), v(1))); + ML99_ASSERT(ML99_lesserEq(v(25), v(25))); + ML99_ASSERT(ML99_lesserEq(v(198), v(198))); + + ML99_ASSERT(ML99_lesserEq(v(0), v(1))); + ML99_ASSERT(ML99_lesserEq(v(0), v(ML99_NAT_MAX))); + ML99_ASSERT(ML99_lesserEq(v(18), v(27))); + ML99_ASSERT(ML99_lesserEq(v(82), v(90))); + ML99_ASSERT(ML99_lesserEq(v(145), v(146))); + ML99_ASSERT(ML99_lesserEq(v(181), v(ML99_NAT_MAX))); + + ML99_ASSERT(ML99_not(ML99_lesserEq(v(7), v(0)))); + ML99_ASSERT(ML99_not(ML99_lesserEq(v(182), v(181)))); + } + + // ML99_add + { + ML99_ASSERT_EQ(ML99_add(v(0), v(0)), v(0)); + ML99_ASSERT_EQ(ML99_add(v(19), v(83)), v(19 + 83)); + ML99_ASSERT_EQ(ML99_add(v(8), v(4)), v(8 + 4)); + ML99_ASSERT_EQ(ML99_add(v(1), v(254)), v(1 + 254)); + } + + // ML99_sub + { + ML99_ASSERT_EQ(ML99_sub(v(1), v(1)), v(1 - 1)); + ML99_ASSERT_EQ(ML99_sub(v(5), v(3)), v(5 - 3)); + ML99_ASSERT_EQ(ML99_sub(v(105), v(19)), v(105 - 19)); + ML99_ASSERT_EQ(ML99_sub(v(ML99_NAT_MAX), v(40)), v(ML99_NAT_MAX - 40)); + } + + // ML99_mul + { + ML99_ASSERT_EQ(ML99_mul(v(11), v(0)), v(0)); + ML99_ASSERT_EQ(ML99_mul(v(0), v(11)), v(0)); + ML99_ASSERT_EQ(ML99_mul(v(15), v(8)), v(15 * 8)); + ML99_ASSERT_EQ(ML99_mul(v(ML99_NAT_MAX), v(1)), v(ML99_NAT_MAX * 1)); + } + + // ML99_div + { + ML99_ASSERT_EQ(ML99_div(v(15), v(1)), v(15)); + ML99_ASSERT_EQ(ML99_div(v(15), v(15)), v(1)); + ML99_ASSERT_EQ(ML99_div(v(45), v(3)), v(45 / 3)); + ML99_ASSERT_EQ(ML99_div(v(ML99_NAT_MAX), v(5)), v(ML99_NAT_MAX / 5)); + } + + // ML99_divChecked + { + ML99_ASSERT(ML99_maybeEq(v(ML99_natEq), ML99_divChecked(v(15), v(1)), ML99_just(v(15)))); + ML99_ASSERT(ML99_maybeEq(v(ML99_natEq), ML99_divChecked(v(15), v(15)), ML99_just(v(1)))); + ML99_ASSERT(ML99_maybeEq(v(ML99_natEq), ML99_divChecked(v(45), v(3)), ML99_just(v(15)))); + ML99_ASSERT( + ML99_maybeEq(v(ML99_natEq), ML99_divChecked(v(ML99_NAT_MAX), v(5)), ML99_just(v(51)))); + + ML99_ASSERT(ML99_maybeEq(v(ML99_natEq), ML99_divChecked(v(4), v(0)), ML99_nothing())); + ML99_ASSERT(ML99_maybeEq(v(ML99_natEq), ML99_divChecked(v(3), v(27)), ML99_nothing())); + ML99_ASSERT(ML99_maybeEq(v(ML99_natEq), ML99_divChecked(v(166), v(9)), ML99_nothing())); + ML99_ASSERT(ML99_maybeEq(v(ML99_natEq), ML99_divChecked(v(0), v(11)), ML99_nothing())); + } + + // ML99_DIV_CHECKED + { + ML99_ASSERT(ML99_maybeEq(v(ML99_natEq), v(ML99_DIV_CHECKED(15, 1)), ML99_just(v(15)))); + ML99_ASSERT(ML99_maybeEq(v(ML99_natEq), v(ML99_DIV_CHECKED(4, 0)), ML99_nothing())); + } + + // ML99_mod + { + ML99_ASSERT_EQ(ML99_mod(v(0), v(1)), v(0 % 1)); + ML99_ASSERT_EQ(ML99_mod(v(0), v(123)), v(0 % 123)); + + ML99_ASSERT_EQ(ML99_mod(v(1), v(28)), v(1 % 28)); + ML99_ASSERT_EQ(ML99_mod(v(1), v(123)), v(1 % 123)); + + ML99_ASSERT_EQ(ML99_mod(v(1), v(1)), v(0)); + ML99_ASSERT_EQ(ML99_mod(v(16), v(4)), v(0)); + ML99_ASSERT_EQ(ML99_mod(v(ML99_NAT_MAX), v(ML99_NAT_MAX)), v(0)); + + ML99_ASSERT_EQ(ML99_mod(v(8), v(3)), v(8 % 3)); + ML99_ASSERT_EQ(ML99_mod(v(10), v(4)), v(10 % 4)); + ML99_ASSERT_EQ(ML99_mod(v(101), v(7)), v(101 % 7)); + + ML99_ASSERT_EQ(ML99_mod(v(13), v(14)), v(13 % 14)); + ML99_ASSERT_EQ(ML99_mod(v(20), v(36)), v(20 % 36)); + ML99_ASSERT_EQ(ML99_mod(v(16), v(ML99_NAT_MAX)), v(16 % ML99_NAT_MAX)); + } + + // ML99_add3, ML99_sub3, ML99_mul3, ML99_div3 + { + ML99_ASSERT_EQ(ML99_add3(v(8), v(2), v(4)), v(8 + 2 + 4)); + ML99_ASSERT_EQ(ML99_sub3(v(14), v(1), v(7)), v(14 - 1 - 7)); + ML99_ASSERT_EQ(ML99_mul3(v(3), v(2), v(6)), v(3 * 2 * 6)); + ML99_ASSERT_EQ(ML99_div3(v(30), v(2), v(3)), v(30 / 2 / 3)); + } + + // ML99_min + { + ML99_ASSERT_EQ(ML99_min(v(0), v(1)), v(0)); + ML99_ASSERT_EQ(ML99_min(v(5), v(7)), v(5)); + ML99_ASSERT_EQ(ML99_min(v(200), v(ML99_NAT_MAX)), v(200)); + } + + // ML99_max + { + ML99_ASSERT_EQ(ML99_max(v(0), v(1)), v(1)); + ML99_ASSERT_EQ(ML99_max(v(5), v(7)), v(7)); + ML99_ASSERT_EQ(ML99_max(v(200), v(ML99_NAT_MAX)), v(ML99_NAT_MAX)); + } + + // ML99_assertIsNat + { + ML99_EVAL(ML99_assertIsNat(v(0))) + ML99_EVAL(ML99_assertIsNat(v(13))) + ML99_EVAL(ML99_assertIsNat(v(255))) + } +} diff --git a/test/external/metalang99/tests/seq.c b/test/external/metalang99/tests/seq.c new file mode 100644 index 0000000..eea6f0f --- /dev/null +++ b/test/external/metalang99/tests/seq.c @@ -0,0 +1,100 @@ +#include <metalang99/assert.h> +#include <metalang99/seq.h> + +int main(void) { + + // ML99_seqGet + { + ML99_ASSERT_EQ(ML99_seqGet(0)(v((19))), v(19)); + ML99_ASSERT_EQ(ML99_seqGet(0)(v((19)(8))), v(19)); + ML99_ASSERT_EQ(ML99_seqGet(0)(v((19)(8)(7378))), v(19)); + + ML99_ASSERT_EQ(ML99_seqGet(1)(v((19)(8))), v(8)); + ML99_ASSERT_EQ(ML99_seqGet(2)(v((19)(8)(7378))), v(7378)); + ML99_ASSERT_EQ(ML99_seqGet(3)(v((19)(8)(7378)(10))), v(10)); + ML99_ASSERT_EQ(ML99_seqGet(4)(v((19)(8)(7378)(10)(121))), v(121)); + ML99_ASSERT_EQ(ML99_seqGet(5)(v((19)(8)(7378)(10)(121)(1))), v(1)); + ML99_ASSERT_EQ(ML99_seqGet(6)(v((19)(8)(7378)(10)(121)(1)(80))), v(80)); + ML99_ASSERT_EQ(ML99_seqGet(7)(v((19)(8)(7378)(10)(121)(1)(80)(23))), v(23)); + } + + // ML99_SEQ_GET + { + ML99_ASSERT_UNEVAL(ML99_SEQ_GET(0)((19)) == 19); + ML99_ASSERT_UNEVAL(ML99_SEQ_GET(0)((19)(8)) == 19); + ML99_ASSERT_UNEVAL(ML99_SEQ_GET(0)((19)(8)(7378)) == 19); + + ML99_ASSERT_UNEVAL(ML99_SEQ_GET(1)((19)(8)) == 8); + ML99_ASSERT_UNEVAL(ML99_SEQ_GET(1)((19)(8)(7378)) == 8); + } + +#define CHECK_TAIL(a) a == 51 && CHECK_TAIL_AUX_0 +#define CHECK_TAIL_AUX_0(b) b == 3 && CHECK_TAIL_AUX_1 +#define CHECK_TAIL_AUX_1(c) c == 9 + + // ML99_seqTail + { + ML99_ASSERT_UNEVAL(CHECK_TAIL ML99_EVAL(ML99_seqTail(v((9191)(51)(3)(9))))); + ML99_ASSERT_EMPTY(ML99_seqTail(v((~, ~, ~)))); + } + + // ML99_SEQ_TAIL + { + ML99_ASSERT_UNEVAL(CHECK_TAIL ML99_SEQ_TAIL((9191)(51)(3)(9))); + ML99_ASSERT_EMPTY_UNEVAL(ML99_SEQ_TAIL((~, ~, ~))); + } + +#undef CHECK_TAIL +#undef CHECK_TAIL_AUX_0 +#undef CHECK_TAIL_AUX_1 + + // ML99_seqIsEmpty + { + ML99_ASSERT(ML99_seqIsEmpty(v())); + + ML99_ASSERT(ML99_not(ML99_seqIsEmpty(v((~, ~, ~))))); + ML99_ASSERT(ML99_not(ML99_seqIsEmpty(v((~)(~))))); + ML99_ASSERT(ML99_not(ML99_seqIsEmpty(v((~)(~)(~))))); + } + + // ML99_SEQ_IS_EMPTY + { + ML99_ASSERT_UNEVAL(ML99_SEQ_IS_EMPTY()); + + ML99_ASSERT_UNEVAL(ML99_NOT(ML99_SEQ_IS_EMPTY((~, ~, ~)))); + ML99_ASSERT_UNEVAL(ML99_NOT(ML99_SEQ_IS_EMPTY((~)(~)))); + ML99_ASSERT_UNEVAL(ML99_NOT(ML99_SEQ_IS_EMPTY((~)(~)(~)))); + } + +#define CHECK_EXPAND(...) CHECK(__VA_ARGS__) + +#define CHECK(_, x, y, z) ML99_ASSERT_UNEVAL(x == 1987 && y == 2987 && z == 3987) +#define F_IMPL(x) v(, x##987) +#define F_ARITY 1 + + // ML99_seqForEach + { + ML99_ASSERT_EMPTY(ML99_seqForEach(v(F), v())); + CHECK_EXPAND(ML99_EVAL(ML99_seqForEach(v(F), v((1)(2)(3))))); + } + +#undef CHECK +#undef F_IMPL +#undef F_ARITY + +#define CHECK(_, x, y, z) ML99_ASSERT_UNEVAL(x == 10 && y == 21 && z == 32) +#define F_IMPL(i, x) v(, ), v(x##i) +#define F_ARITY 2 + + // ML99_seqForEachI + { + ML99_ASSERT_EMPTY(ML99_seqForEachI(v(F), v())); + CHECK_EXPAND(ML99_EVAL(ML99_seqForEachI(v(F), v((1)(2)(3))))); + } + +#undef CHECK +#undef F_IMPL +#undef F_ARITY + +#undef CHECK_EXPAND +} diff --git a/test/external/metalang99/tests/stmt.c b/test/external/metalang99/tests/stmt.c new file mode 100644 index 0000000..cc00b1b --- /dev/null +++ b/test/external/metalang99/tests/stmt.c @@ -0,0 +1,114 @@ +#include <metalang99/stmt.h> + +#include <assert.h> + +int main(void) { + + // ML99_INTRODUCE_VAR_TO_STMT + { + if (1) + ML99_INTRODUCE_VAR_TO_STMT(int x = 5, y = 7) { + assert(5 == x); + assert(7 == y); + } + } + + // ML99_INTRODUCE_NON_NULL_PTR_TO_STMT + { + int x = 5, y = 7; + + // clang-format off + if (1) + ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(int, x_ptr, &x) + ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(int, y_ptr, &y) { + assert(x == *x_ptr); + assert(y == *y_ptr); + } + // clang-format on + } + + // ML99_CHAIN_EXPR_STMT + { + int x, y; + + // clang-format off + if (1) + ML99_CHAIN_EXPR_STMT(x = 1) + ML99_CHAIN_EXPR_STMT(y = 2) { + assert(1 == x); + assert(2 == y); + } + // clang-format on + + // Test -Wunused suppression via ML99_CHAIN_EXPR_STMT. + int z; + + if (1) + ML99_CHAIN_EXPR_STMT((void)z); + } + + // ML99_CHAIN_EXPR_STMT_AFTER + { + int x = 5, y = 7; + + if (1) { + assert(5 == x); + assert(7 == y); + + ML99_CHAIN_EXPR_STMT_AFTER(x = 1) { + assert(5 == x); + assert(7 == y); + + ML99_CHAIN_EXPR_STMT_AFTER(y = 2) { + assert(5 == x); + assert(7 == y); + } + + assert(5 == x); + assert(2 == y); + } + + assert(1 == x); + assert(2 == y); + } + } + + // ML99_SUPPRESS_UNUSED_BEFORE_STMT + { + int x, y; + + // clang-format off + if (1) + ML99_SUPPRESS_UNUSED_BEFORE_STMT(x) + ML99_SUPPRESS_UNUSED_BEFORE_STMT(y) + ; + // clang-format on + } + + // Clang-Format breaks with the following sequence of statements so they are put into a macro. + // clang-format off + +#define STMT_CHAINING \ + ML99_INTRODUCE_VAR_TO_STMT(int x = 5) \ + ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(int, x_ptr, &x) { \ + assert(x == *x_ptr); \ + \ + ML99_CHAIN_EXPR_STMT(x = 7) \ + ML99_INTRODUCE_VAR_TO_STMT(int y = 5) \ + ML99_SUPPRESS_UNUSED_BEFORE_STMT(y) { \ + ML99_CHAIN_EXPR_STMT_AFTER(x = 123) { \ + assert(7 == x); \ + } \ + \ + assert(123 == x); \ + } \ + } + + // clang-format on + + { STMT_CHAINING } + +#undef STMT_CHAINING + + return 0; +} diff --git a/test/external/metalang99/tests/tuple.c b/test/external/metalang99/tests/tuple.c new file mode 100644 index 0000000..af92350 --- /dev/null +++ b/test/external/metalang99/tests/tuple.c @@ -0,0 +1,184 @@ +#include <metalang99/assert.h> +#include <metalang99/tuple.h> + +int main(void) { + +#define CHECK(x, y) ML99_ASSERT_UNEVAL(x == 518 && y == 1910) +#define CHECK_EXPAND(args) CHECK args + + // ML99_tuple + { CHECK_EXPAND(ML99_EVAL(ML99_tuple(v(518, 1910)))); } + + // ML99_TUPLE + { CHECK_EXPAND(ML99_TUPLE(518, 1910)); } + +#undef CHECK +#undef CHECK_EXPAND + + // ML99_untupleEval + { ML99_ASSERT_EQ(ML99_untupleEval(v((v(198)))), v(198)); } + + // ML99_untuple(Checked) + { + ML99_ASSERT_EQ(ML99_untuple(v((198))), v(198)); + ML99_ASSERT_EQ(ML99_untupleChecked(v((198))), v(198)); + } + + // ML99_UNTUPLE + { ML99_ASSERT_UNEVAL(ML99_UNTUPLE((198)) == 198); } + + // ML99_tupleEval + ML99_untupleEval + { ML99_ASSERT_EQ(ML99_untupleEval(ML99_tupleEval(v(187))), v(187)); } + + // ML99_tuple + ML99_untuple + { ML99_ASSERT_EQ(ML99_untuple(ML99_tuple(v(187))), v(187)); } + + // ML99_isTuple + { + ML99_ASSERT(ML99_isTuple(v((1, 2, 3)))); + ML99_ASSERT(ML99_not(ML99_isTuple(v(123)))); + } + + // ML99_IS_TUPLE + { + ML99_ASSERT_UNEVAL(ML99_IS_TUPLE((1, 2, 3))); + ML99_ASSERT_UNEVAL(!ML99_IS_TUPLE(123)); + } + + // ML99_isUntuple + { + ML99_ASSERT(ML99_not(ML99_isUntuple(v((1, 2, 3))))); + + ML99_ASSERT(ML99_isUntuple(v(123))); + ML99_ASSERT(ML99_isUntuple(v(123()))); + ML99_ASSERT(ML99_isUntuple(v(123(~)))); + ML99_ASSERT(ML99_isUntuple(v(123(~, ~, ~)))); + + ML99_ASSERT(ML99_isUntuple(v(()()))); + ML99_ASSERT(ML99_isUntuple(v(()() ~))); + + ML99_ASSERT(ML99_isUntuple(v((~)(~)))); + ML99_ASSERT(ML99_isUntuple(v((~)(~) ~))); + + ML99_ASSERT(ML99_isUntuple(v((~, ~, ~)(~, ~, ~)))); + ML99_ASSERT(ML99_isUntuple(v((~, ~, ~)(~, ~, ~) ~))); + + ML99_ASSERT(ML99_isUntuple(v((~, ~, ~)(~, ~, ~)(~, ~, ~)))); + ML99_ASSERT(ML99_isUntuple(v((~, ~, ~)(~, ~, ~)(~, ~, ~) ~))); + } + + // ML99_IS_UNTUPLE + { + ML99_ASSERT_UNEVAL(!ML99_IS_UNTUPLE((1, 2, 3))); + ML99_ASSERT_UNEVAL(ML99_IS_UNTUPLE(123)); + ML99_ASSERT_UNEVAL(ML99_IS_UNTUPLE((~)(~))); + } + + // ML99_tupleCount + { + ML99_ASSERT_EQ(ML99_tupleCount(v((1, 2, 3))), v(3)); + ML99_ASSERT_EQ(ML99_tupleCount(v((*))), v(1)); + } + + // ML99_TUPLE_COUNT + { + ML99_ASSERT_UNEVAL(ML99_TUPLE_COUNT((1, 2, 3)) == 3); + ML99_ASSERT_UNEVAL(ML99_TUPLE_COUNT((*)) == 1); + } + + // ML99_tupleIsSingle + { + ML99_ASSERT(ML99_not(ML99_tupleIsSingle(v((1, 2, 3))))); + ML99_ASSERT(ML99_tupleIsSingle(v((*)))); + } + + // ML99_TUPLE_IS_SINGLE + { + ML99_ASSERT_UNEVAL(!ML99_TUPLE_IS_SINGLE((1, 2, 3))); + ML99_ASSERT_UNEVAL(ML99_TUPLE_IS_SINGLE((*))); + } + + // ML99_tupleGet + { + ML99_ASSERT_EMPTY(ML99_tupleGet(0)(v(()))); + ML99_ASSERT_EQ(ML99_tupleGet(0)(v((19))), v(19)); + ML99_ASSERT_EQ(ML99_tupleGet(0)(v((19, 8))), v(19)); + ML99_ASSERT_EQ(ML99_tupleGet(0)(v((19, 8, 7378))), v(19)); + + ML99_ASSERT_EQ(ML99_tupleGet(1)(v((19, 8))), v(8)); + ML99_ASSERT_EQ(ML99_tupleGet(2)(v((19, 8, 7378))), v(7378)); + ML99_ASSERT_EQ(ML99_tupleGet(3)(v((19, 8, 7378, 10))), v(10)); + ML99_ASSERT_EQ(ML99_tupleGet(4)(v((19, 8, 7378, 10, 121))), v(121)); + ML99_ASSERT_EQ(ML99_tupleGet(5)(v((19, 8, 7378, 10, 121, 1))), v(1)); + ML99_ASSERT_EQ(ML99_tupleGet(6)(v((19, 8, 7378, 10, 121, 1, 80))), v(80)); + ML99_ASSERT_EQ(ML99_tupleGet(7)(v((19, 8, 7378, 10, 121, 1, 80, 23))), v(23)); + } + + // ML99_TUPLE_GET + { + ML99_ASSERT_EMPTY_UNEVAL(ML99_TUPLE_GET(0)(())); + + ML99_ASSERT_UNEVAL(ML99_TUPLE_GET(0)((19)) == 19); + ML99_ASSERT_UNEVAL(ML99_TUPLE_GET(0)((19, 8)) == 19); + ML99_ASSERT_UNEVAL(ML99_TUPLE_GET(0)((19, 8, 7378)) == 19); + } + +#define CHECK_TAIL(...) CHECK_TAIL_AUX(__VA_ARGS__) +#define CHECK_TAIL_AUX(a, b, c) ML99_ASSERT_UNEVAL(a == 51 && b == 3 && c == 9) + + // ML99_tupleTail + { CHECK_TAIL(ML99_EVAL(ML99_tupleTail(v((9191, 51, 3, 9))))); } + + // ML99_TUPLE_TAIL + { CHECK_TAIL(ML99_TUPLE_TAIL((9191, 51, 3, 9))); } + +#undef CHECK_TAIL +#undef CHECK_TAIL_AUX + +#define CHECK(a, b, c) ML99_ASSERT_UNEVAL(a == 1 && b == 2 && c == 3) +#define CHECK_EXPAND(args) CHECK args + + // ML99_tuple(Append|Prepend) + { + CHECK_EXPAND(ML99_EVAL(ML99_tupleAppend(ML99_tuple(v(1)), v(2, 3)))); + CHECK_EXPAND(ML99_EVAL(ML99_tuplePrepend(ML99_tuple(v(3)), v(1, 2)))); + } + + // ML99_TUPLE(APPEND|PREPEND) + { + CHECK_EXPAND(ML99_TUPLE_APPEND((1), 2, 3)); + CHECK_EXPAND(ML99_TUPLE_PREPEND((3), 1, 2)); + } + +#undef CHECK +#undef CHECK_EXPAND + +#define CHECK_EXPAND(...) CHECK(__VA_ARGS__) + +#define CHECK(_, x, y, z) ML99_ASSERT_UNEVAL(x == 1987 && y == 2987 && z == 3987) +#define F_IMPL(x) v(, x##987) +#define F_ARITY 1 + + // ML99_tupleForEach + { CHECK_EXPAND(ML99_EVAL(ML99_tupleForEach(v(F), v((1, 2, 3))))); } + +#undef CHECK +#undef F_IMPL +#undef F_ARITY + +#define CHECK(_, x, y, z) ML99_ASSERT_UNEVAL(x == 10 && y == 21 && z == 32) +#define F_IMPL(x, i) v(, ), v(x##i) +#define F_ARITY 2 + + // ML99_tupleForEachI + { CHECK_EXPAND(ML99_EVAL(ML99_tupleForEachI(v(F), v((1, 2, 3))))); } + +#undef CHECK +#undef F_IMPL +#undef F_ARITY + +#undef CHECK_EXPAND + + // ML99_assertIsTuple + { ML99_EVAL(ML99_assertIsTuple(ML99_tuple(v(1, 2, 3)))); } +} diff --git a/test/external/metalang99/tests/util.c b/test/external/metalang99/tests/util.c new file mode 100644 index 0000000..8b42ff9 --- /dev/null +++ b/test/external/metalang99/tests/util.c @@ -0,0 +1,137 @@ +#include <metalang99/assert.h> +#include <metalang99/util.h> + +int main(void) { + + // ML99_cat(Eval), ML99_cat(3|4) + { + ML99_ASSERT_EQ(ML99_cat(v(12), v(345)), v(12345)); + ML99_ASSERT_EQ(ML99_cat3(v(12), v(3), v(45)), v(12345)); + ML99_ASSERT_EQ(ML99_cat4(v(12), v(3), v(4), v(5)), v(12345)); + +#define ABC v(123) + + ML99_ASSERT_EQ(ML99_catEval(v(A), v(BC)), v(123)); + +#undef ABC + } + + // ML99_CAT, ML99_CAT(3|4) + { + ML99_ASSERT_UNEVAL(ML99_CAT(12, 345) == 12345); + ML99_ASSERT_UNEVAL(ML99_CAT3(12, 3, 45) == 12345); + ML99_ASSERT_UNEVAL(ML99_CAT4(12, 3, 4, 5) == 12345); + } + +#define CHECK(x, y) ML99_ASSERT_UNEVAL(x == 518 && y == 1910) +#define CHECK_EXPAND(args) CHECK args + + // ML99_id + { + ML99_ASSERT_EMPTY(ML99_id(v())); + CHECK_EXPAND(ML99_EVAL(ML99_id(v((518, 1910))))); + ML99_ASSERT_EQ(ML99_appl(ML99_compose(v(ML99_id), v(ML99_id)), v(181)), v(181)); + } + +#undef CHECK +#undef CHECK_EXPAND + + // ML99_ID + { + ML99_ASSERT_EMPTY_UNEVAL(ML99_ID()); + ML99_ASSERT_UNEVAL(ML99_ID(123) == 123); + } + + // ML99_const + { ML99_ASSERT_EQ(ML99_appl2(v(ML99_const), v(1810), v(~)), v(1810)); } + +#define ABC ML99_TRUE() + + // ML99_flip + { ML99_ASSERT(ML99_appl2(ML99_flip(v(ML99_cat)), v(C), v(AB))); } + +#undef ABC + + // ML99_uncomma + { + ML99_ASSERT_EMPTY(ML99_uncomma(ML99_QUOTE(v()))); + ML99_ASSERT_EQ(ML99_uncomma(ML99_QUOTE(v(1), v(+), v(2), v(+), v(3))), v(1 + 2 + 3)); + } + +#define F(x, y, z) x + y + z + + // ML99_reify + { ML99_ASSERT_EQ(ML99_appl(ML99_reify(v(F)), v(1, 2, 3)), v(1 + 2 + 3)); } + +#undef F + + // ML99_empty + { + ML99_ASSERT_EMPTY(ML99_empty(v())); + ML99_ASSERT_EMPTY(ML99_empty(v(1, 2, 3))); + } + + // ML99_EMPTY + { + ML99_ASSERT_EMPTY_UNEVAL(ML99_EMPTY()); + ML99_ASSERT_EMPTY_UNEVAL(ML99_EMPTY(1, 2, 3)); + } + +#define F 3 ML99_RPAREN(~, ~, ~) + G ML99_LPAREN(~, ~, ~) 1, 2, +#define G(_1, _2, _3) _1##_2##_3 + + // ML99_LPAREN, ML99_RPAREN + { + + // G(1, 2, 3) + G(1, 2, 3) + G(1, 2, 3) + G(1, 2, 3) + ML99_ASSERT_UNEVAL(ML99_ID(G ML99_LPAREN() 1, 2, F F F 3 ML99_RPAREN() == 123 * 4)); + } + +#undef F +#undef G + +#define CHECK(x, y, z) ML99_ASSERT_UNEVAL(x == 5 && y == 6 && z == 7) +#define CHECK_EXPAND(args) CHECK(args) + + // ML99_COMMA + { CHECK_EXPAND(5 ML99_COMMA() 6 ML99_COMMA(~, ~, ~) 7); } + +#undef CHECK +#undef CHECK_EXPAND + + // ML99_GEN_SYM + { + +#define TEST(...) TEST_NAMED(ML99_GEN_SYM(TEST_, x), __VA_ARGS__) +#define TEST_NAMED(x_sym, ...) \ + do { \ + int x_sym = 5; \ + (void)x_sym; \ + __VA_ARGS__ \ + } while (0) + + // `x` here will not conflict the the `x` inside `TEST`. + TEST(int x = 123; (void)x;); + +#undef TEST +#undef TEST_NAMED + +// Two identical calls to `ML99_GEN_SYM` must yield different identifiers. +#define TEST(x1_sym, x2_sym) \ + do { \ + int x1_sym, x2_sym; \ + (void)x1_sym; \ + (void)x2_sym; \ + } while (0) + + TEST(ML99_GEN_SYM(TEST_, x), ML99_GEN_SYM(TEST_, x)); + +#undef TEST + } + + // ML99_TRAILING_SEMICOLON + { + ML99_TRAILING_SEMICOLON(); + ML99_TRAILING_SEMICOLON(~, ~, ~); + } +} diff --git a/test/external/metalang99/tests/variadics.c b/test/external/metalang99/tests/variadics.c new file mode 100644 index 0000000..111faa8 --- /dev/null +++ b/test/external/metalang99/tests/variadics.c @@ -0,0 +1,137 @@ +#include <metalang99/assert.h> +#include <metalang99/variadics.h> + +int main(void) { + + // ML99_variadicsGet + { + ML99_ASSERT_EMPTY(ML99_variadicsGet(0)(v())); + ML99_ASSERT_EQ(ML99_variadicsGet(0)(v(19)), v(19)); + ML99_ASSERT_EQ(ML99_variadicsGet(0)(v(19, 8)), v(19)); + ML99_ASSERT_EQ(ML99_variadicsGet(0)(v(19, 8, 7378)), v(19)); + + ML99_ASSERT_EQ(ML99_variadicsGet(1)(v(19, 8)), v(8)); + ML99_ASSERT_EQ(ML99_variadicsGet(2)(v(19, 8, 7378)), v(7378)); + ML99_ASSERT_EQ(ML99_variadicsGet(3)(v(19, 8, 7378, 10)), v(10)); + ML99_ASSERT_EQ(ML99_variadicsGet(4)(v(19, 8, 7378, 10, 121)), v(121)); + ML99_ASSERT_EQ(ML99_variadicsGet(5)(v(19, 8, 7378, 10, 121, 1)), v(1)); + ML99_ASSERT_EQ(ML99_variadicsGet(6)(v(19, 8, 7378, 10, 121, 1, 80)), v(80)); + ML99_ASSERT_EQ(ML99_variadicsGet(7)(v(19, 8, 7378, 10, 121, 1, 80, 23)), v(23)); + } + + // ML99_VARIADICS_GET + { + ML99_ASSERT_EMPTY_UNEVAL(ML99_VARIADICS_GET(0)()); + + ML99_ASSERT_UNEVAL(ML99_VARIADICS_GET(0)(19) == 19); + ML99_ASSERT_UNEVAL(ML99_VARIADICS_GET(0)(19, 8) == 19); + ML99_ASSERT_UNEVAL(ML99_VARIADICS_GET(0)(19, 8, 7378) == 19); + + ML99_ASSERT_UNEVAL(ML99_VARIADICS_GET(1)(19, 8) == 8); + ML99_ASSERT_UNEVAL(ML99_VARIADICS_GET(1)(19, 8, 7378) == 8); + } + +#define CHECK_TAIL(...) CHECK_TAIL_AUX(__VA_ARGS__) +#define CHECK_TAIL_AUX(a, b, c) ML99_ASSERT_UNEVAL(a == 51 && b == 3 && c == 9) + + // ML99_variadicsTail + { CHECK_TAIL(ML99_EVAL(ML99_variadicsTail(v(9191, 51, 3, 9)))); } + + // ML99_VARIADICS_TAIL + { CHECK_TAIL(ML99_VARIADICS_TAIL(9191, 51, 3, 9)); } + +#undef CHECK_TAIL +#undef CHECK_TAIL_AUX + +#define _5_ARGS v(~, ~, ~, ~, ~) +#define _10_ARGS _5_ARGS, _5_ARGS +#define _50_ARGS _10_ARGS, _10_ARGS, _10_ARGS, _10_ARGS, _10_ARGS + + // ML99_variadicsCount + { + ML99_ASSERT_EQ(ML99_variadicsCount(v()), v(1)); + ML99_ASSERT_EQ(ML99_variadicsCount(v(~)), v(1)); + ML99_ASSERT_EQ(ML99_variadicsCount(v(~, ~)), v(2)); + ML99_ASSERT_EQ(ML99_variadicsCount(v(~, ~, ~)), v(3)); + ML99_ASSERT_EQ(ML99_variadicsCount(v(~, ~, ~, ~)), v(4)); + ML99_ASSERT_EQ(ML99_variadicsCount(_5_ARGS), v(5)); + ML99_ASSERT_EQ(ML99_variadicsCount(_5_ARGS, v(~)), v(6)); + ML99_ASSERT_EQ(ML99_variadicsCount(_5_ARGS, v(~, ~)), v(7)); + ML99_ASSERT_EQ(ML99_variadicsCount(_5_ARGS, v(~, ~, ~)), v(8)); + ML99_ASSERT_EQ(ML99_variadicsCount(_5_ARGS, v(~, ~, ~, ~)), v(9)); + ML99_ASSERT_EQ(ML99_variadicsCount(_10_ARGS), v(10)); + ML99_ASSERT_EQ(ML99_variadicsCount(_10_ARGS, v(~)), v(11)); + ML99_ASSERT_EQ(ML99_variadicsCount(_50_ARGS, _10_ARGS, v(~, ~, ~)), v(63)); + } + +#define X(...) ML99_OVERLOAD(X_, __VA_ARGS__) +#define X_1(a) ML99_ASSERT_UNEVAL(a == 123) +#define X_2(a, b) ML99_ASSERT_UNEVAL(a == 93145 && b == 456) +#define X_7(a, b, c, d, e, f, g) \ + ML99_ASSERT_UNEVAL(a == 1516 && b == 1 && c == 9 && d == 111 && e == 119 && f == 677 && g == 62) + + // ML99_OVERLOAD + { + X(123); + X(93145, 456); + X(1516, 1, 9, 111, 119, 677, 62); + } + +#undef X_IMPL +#undef X_1_IMPL +#undef X_2_IMPL +#undef X_7_IMPL + + // ML99_VARIADICS_COUNT + { + ML99_ASSERT_EQ(v(ML99_VARIADICS_COUNT()), v(1)); + ML99_ASSERT_EQ(v(ML99_VARIADICS_COUNT(~)), v(1)); + ML99_ASSERT_EQ(v(ML99_VARIADICS_COUNT(~, ~)), v(2)); + ML99_ASSERT_EQ(v(ML99_VARIADICS_COUNT(~, ~, ~)), v(3)); + } + +#undef _5_ARGS +#undef _10_ARGS +#undef _50_ARGS +#undef _100_ARGS + + // ML99_variadicsIsSingle + { + ML99_ASSERT(ML99_variadicsIsSingle(v())); + ML99_ASSERT(ML99_variadicsIsSingle(v(~))); + ML99_ASSERT(ML99_not(ML99_variadicsIsSingle(v(~, ~, ~)))); + } + + // ML99_VARIADICS_IS_SINGLE + { + ML99_ASSERT_UNEVAL(ML99_VARIADICS_IS_SINGLE()); + ML99_ASSERT_UNEVAL(ML99_VARIADICS_IS_SINGLE(~)); + ML99_ASSERT_UNEVAL(ML99_NOT(ML99_VARIADICS_IS_SINGLE(~, ~, ~))); + } + +#define CHECK_EXPAND(...) CHECK(__VA_ARGS__) + +#define CHECK(_, x, y, z) ML99_ASSERT_UNEVAL(x == 1987 && y == 2987 && z == 3987) +#define F_IMPL(x) v(, x##987) +#define F_ARITY 1 + + // ML99_variadicsForEach + { CHECK_EXPAND(ML99_EVAL(ML99_variadicsForEach(v(F), v(1, 2, 3)))); } + +#undef CHECK +#undef F_IMPL +#undef F_ARITY + +#define CHECK(_, x, y, z) ML99_ASSERT_UNEVAL(x == 10 && y == 21 && z == 32) +#define F_IMPL(x, i) v(, ), v(x##i) +#define F_ARITY 2 + + // ML99_variadicsForEachI + { CHECK_EXPAND(ML99_EVAL(ML99_variadicsForEachI(v(F), v(1, 2, 3)))); } + +#undef CHECK +#undef F_IMPL +#undef F_ARITY + +#undef CHECK_EXPAND +} diff --git a/test/metalang99.sh b/test/metalang99.sh new file mode 100755 index 0000000..feac485 --- /dev/null +++ b/test/metalang99.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +cd $(dirname "$0")/external/metalang99/ + +cc=$(realpath ../../../antcc) + + +echo ' -- examples --' +mkdir -p examples/build +cd examples/build +cmake --fresh .. -DCMAKE_C_COMPILER="$cc" +cmake --build . + +cd ../.. +echo ' -- tests --' +set -e +mkdir -p tests/build +cd tests/build +cmake --fresh .. -DCMAKE_C_COMPILER="$cc" +cmake --build . + +if [[ "$OSTYPE" == "linux-gnu" ]]; then + echo " Testing ./gen ..." + ./gen + + echo " Testing ./stmt ..." + ./stmt +fi |