diff options
| author | hachem <im@hachem.wtf> | 2026-09-19 22:22:26 +0200 |
|---|---|---|
| committer | hachem <im@hachem.wtf> | 2026-09-19 22:22:26 +0200 |
| commit | 4bcc54914d059e950cab79164fb13ed67376ee5d (patch) | |
| tree | ca4df456c92247a950be7e5ebc5da49ff96b7b3d | |
| parent | 2da2c56c72e7085bd9a52f848df90c6fc701de7f (diff) | |
docs: README + LICENSE
| -rw-r--r-- | LICENSE | 20 | ||||
| -rw-r--r-- | README | 90 | ||||
| -rw-r--r-- | examples/xs.sfinae | 36 |
3 files changed, 107 insertions, 39 deletions
@@ -0,0 +1,20 @@ +MIT License + +Copyright (c) 2026 hachem + +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 USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -1,13 +1,13 @@ # sfinae -Substitution Failure Is Not An Error. Everything else is. -A toy language which takes' C++ template metaprogramming to another level. +Substitution Failure Is Not An Error. everything else is. +a toy language which takes' C++ template metaprogramming to another level. ## build make release build, ./sfinae in the root, objects in bin/ make debug rebuild with address and undefined sanitizers - make check run examples/ against their .expected files + make check run every program in examples/ and tutorial/ make format clang-format the sources make lint clang-tidy naming check make clean @@ -15,3 +15,87 @@ A toy language which takes' C++ template metaprogramming to another level. ## run ./sfinae examples/hello.sfinae + +## learning it + +six lessons under tutorial/, each a program that runs and explains itself in +its comments. read them in order: + + 01_hello.sfinae there are no strings, a string is a tuple of characters + 02_numbers.sfinae there are no numbers, a number is the distance between two characters + 03_variables.sfinae a variable holds a type, and there is no assignment + 04_conditions.sfinae nothing is a condition until you say ::value + 05_loops.sfinae ::repeat, and counting with the undeclare dance + 06_functions.sfinae functions take types, return types, and see only their parameters + +examples/ has more, including fib(0) to fib(10). + +## the rules + +- every notion starts with `::` and every statement ends with `::commit;`. + nothing happens until it is committed +- there are no numeric literals. a digit is a lexer error. the only way to get + a number is to subtract two characters: `::difference<'F', 'A'>` is 5 +- there are no strings. a string is a `::tuple` of `::integral_constant<::char, N>` + types, one per character, each its own distance from `'\0'` +- names are lists of characters: `::name<'f', 'i', 'b'>`, at most 15 of them +- a variable holds a type, and the type must be a `::decltype(...)` of a value or + it cannot be declared +- reassignment does not exist. `::undeclare` it, then `::declare` it again +- conditions are not conditions until you say `::value` +- loop, if and function bodies are a `::sequence<...>` of committed statements, + separated by commas +- functions take types, return types, and see nothing but their parameters +- comments are `//` to the end of the line + +## statements + + ::declare<NAME, TYPE>::commit; + ::undeclare<NAME>::commit; + ::emit<TYPE>::commit; prints what the type says, then a newline + ::repeat<VALUE, SEQUENCE>::commit; + ::enable_if_t<COND, SEQUENCE>::commit; + ::static_assert<COND>::commit; fails at runtime + ::define<NAME, ::parameters<NAME, ...>, SEQUENCE>::commit; + ::return<TYPE>::commit; only inside a function + +## types + + ::void ::int32_t ::byte ::size_t ::char + ::remove_cv_t<TYPE> does nothing + ::array<TYPE, VALUE> an array type with an extent + ::conditional_t<COND, TYPE, TYPE> + ::decltype(VALUE) the only type that carries a value + ::integral_constant<::char, VALUE> a character + ::tuple<TYPE, ...> says what its elements say, in order + ::invoke_result_t<NAME, ::arguments<TYPE, ...>> a call + +## values + + ::difference<'c', 'c'> the one and only literal + ::sum<V, V> ::product<V, V> ::quotient<V, V> + ::value_of<NAME> + ::extent<TYPE>::value an array's extent, 0 otherwise + ::tuple_size<TYPE>::value same thing, longer + ::integral_constant<::size_t, V>::value also does nothing + ::conditional<COND, V, V> + ::declval<TYPE>() the value inside a decltype + +## conditions + + ::true_type::value ::false_type::value + ::is_same<TYPE, TYPE>::value + ::equal<V, V>::value ::less<V, V>::value + +## what emit prints + + ::decltype(V) the number + ::integral_constant<::char, V> the character + ::tuple<...> its elements, glued together + ::array<T, N> array[N] + ::void nothing, not even a newline + anything else the type's name + +## license + +MIT, see LICENSE. diff --git a/examples/xs.sfinae b/examples/xs.sfinae deleted file mode 100644 index e140252..0000000 --- a/examples/xs.sfinae +++ /dev/null @@ -1,36 +0,0 @@ -::declare< - ::name<'x', 's'>, - ::conditional_t< - ::true_type::value, - ::decltype( - ::extent< - ::array< - ::array< - ::remove_cv_t< - ::int32_t - >, - ::integral_constant< - ::size_t, - ::tuple_size< - ::array< - ::byte, - ::difference<'Z', 'F'> - > - >::value - >::value - >, - ::integral_constant< - ::size_t, - ::difference<'Z', 'F'> - >::value - > - >::value - ), - ::void - > ->::commit; - -::emit<::decltype(::value_of<::name<'x', 's'>>)>::commit; - -// an array type says its extent, a bare type says its name -::emit<::array<::byte, ::value_of<::name<'x', 's'>>>>::commit; |
