Metalang99 1.13.3
Full-blown preprocessor metaprogramming
Loading...
Searching...
No Matches
nat.h
Go to the documentation of this file.
1
9#ifndef ML99_NAT_H
10#define ML99_NAT_H
11
12#include <metalang99/priv/bool.h>
13
14#include <metalang99/nat/dec.h>
15#include <metalang99/nat/div.h>
16#include <metalang99/nat/eq.h>
17#include <metalang99/nat/inc.h>
18
19#include <metalang99/lang.h>
20
35#define ML99_inc(x) ML99_call(ML99_inc, x)
36
51#define ML99_dec(x) ML99_call(ML99_dec, x)
52
74#define ML99_natMatch(x, matcher) ML99_call(ML99_natMatch, x, matcher)
75
94#define ML99_natMatchWithArgs(x, matcher, ...) \
95 ML99_call(ML99_natMatchWithArgs, x, matcher, __VA_ARGS__)
96
112#define ML99_natEq(x, y) ML99_call(ML99_natEq, x, y)
113
129#define ML99_natNeq(x, y) ML99_call(ML99_natNeq, x, y)
130
146#define ML99_greater(x, y) ML99_call(ML99_greater, x, y)
147
163#define ML99_greaterEq(x, y) ML99_call(ML99_greaterEq, x, y)
164
180#define ML99_lesser(x, y) ML99_call(ML99_lesser, x, y)
181
197#define ML99_lesserEq(x, y) ML99_call(ML99_lesserEq, x, y)
198
211#define ML99_add(x, y) ML99_call(ML99_add, x, y)
212
225#define ML99_sub(x, y) ML99_call(ML99_sub, x, y)
226
239#define ML99_mul(x, y) ML99_call(ML99_mul, x, y)
240
255#define ML99_div(x, y) ML99_call(ML99_div, x, y)
256
276#define ML99_divChecked(x, y) ML99_call(ML99_divChecked, x, y)
277
292#define ML99_mod(x, y) ML99_call(ML99_mod, x, y)
293
306#define ML99_add3(x, y, z) ML99_call(ML99_add3, x, y, z)
307
320#define ML99_sub3(x, y, z) ML99_call(ML99_sub3, x, y, z)
321
334#define ML99_mul3(x, y, z) ML99_call(ML99_mul3, x, y, z)
335
350#define ML99_div3(x, y, z) ML99_call(ML99_div3, x, y, z)
351
364#define ML99_min(x, y) ML99_call(ML99_min, x, y)
365
378#define ML99_max(x, y) ML99_call(ML99_max, x, y)
379
397#define ML99_assertIsNat(x) ML99_call(ML99_assertIsNat, x)
398
399#define ML99_INC(x) ML99_PRIV_INC(x)
400#define ML99_DEC(x) ML99_PRIV_DEC(x)
401#define ML99_NAT_EQ(x, y) ML99_PRIV_NAT_EQ(x, y)
402#define ML99_NAT_NEQ(x, y) ML99_PRIV_NOT(ML99_NAT_EQ(x, y))
403#define ML99_DIV_CHECKED(x, y) ML99_PRIV_DIV_CHECKED(x, y)
404
408#define ML99_NAT_MAX 255
409
410#ifndef DOXYGEN_IGNORE
411
412// Pattern matching {
413
414#define ML99_natMatch_IMPL(x, matcher) \
415 ML99_PRIV_IF( \
416 ML99_NAT_EQ(x, 0), \
417 ML99_callUneval(matcher##Z, ), \
418 ML99_callUneval(matcher##S, ML99_DEC(x)))
419
420#define ML99_natMatchWithArgs_IMPL(x, matcher, ...) \
421 ML99_PRIV_IF( \
422 ML99_NAT_EQ(x, 0), \
423 ML99_callUneval(matcher##Z, __VA_ARGS__), \
424 ML99_callUneval(matcher##S, ML99_DEC(x), __VA_ARGS__))
425// } (Pattern matching)
426
427// Comparison operators {
428
429#define ML99_natEq_IMPL(x, y) v(ML99_NAT_EQ(x, y))
430#define ML99_natNeq_IMPL(x, y) v(ML99_NAT_NEQ(x, y))
431
432#define ML99_lesser_IMPL(x, y) \
433 ML99_PRIV_IF( \
434 ML99_NAT_EQ(y, 0), \
435 v(ML99_PRIV_FALSE()), \
436 ML99_PRIV_IF( \
437 ML99_NAT_EQ(x, ML99_DEC(y)), \
438 v(ML99_PRIV_TRUE()), \
439 ML99_callUneval(ML99_lesser, x, ML99_DEC(y))))
440
441#define ML99_lesserEq_IMPL(x, y) ML99_greaterEq_IMPL(y, x)
442
443#define ML99_greater_IMPL(x, y) ML99_lesser_IMPL(y, x)
444#define ML99_greaterEq_IMPL(x, y) \
445 ML99_PRIV_IF(ML99_NAT_EQ(x, y), v(ML99_PRIV_TRUE()), ML99_greater_IMPL(x, y))
446// } (Comparison operators)
447
448// Arithmetical operators {
449
450#define ML99_inc_IMPL(x) v(ML99_INC(x))
451#define ML99_dec_IMPL(x) v(ML99_DEC(x))
452
453#define ML99_add_IMPL(x, y) \
454 ML99_PRIV_IF(ML99_NAT_EQ(y, 0), v(x), ML99_callUneval(ML99_add, ML99_INC(x), ML99_DEC(y)))
455#define ML99_sub_IMPL(x, y) \
456 ML99_PRIV_IF(ML99_NAT_EQ(y, 0), v(x), ML99_callUneval(ML99_sub, ML99_DEC(x), ML99_DEC(y)))
457#define ML99_mul_IMPL(x, y) \
458 ML99_PRIV_IF(ML99_NAT_EQ(y, 0), v(0), ML99_add(v(x), ML99_callUneval(ML99_mul, x, ML99_DEC(y))))
459
460#define ML99_add3_IMPL(x, y, z) ML99_add(ML99_add_IMPL(x, y), v(z))
461#define ML99_sub3_IMPL(x, y, z) ML99_sub(ML99_sub_IMPL(x, y), v(z))
462#define ML99_mul3_IMPL(x, y, z) ML99_mul(ML99_mul_IMPL(x, y), v(z))
463#define ML99_div3_IMPL(x, y, z) ML99_div(ML99_div_IMPL(x, y), v(z))
464
465#define ML99_min_IMPL(x, y) ML99_call(ML99_if, ML99_lesser_IMPL(x, y), v(x, y))
466#define ML99_max_IMPL(x, y) ML99_call(ML99_if, ML99_lesser_IMPL(x, y), v(y, x))
467
468#define ML99_divChecked_IMPL(x, y) v(ML99_DIV_CHECKED(x, y))
469
470// ML99_mod_IMPL {
471
472#define ML99_mod_IMPL(x, y) \
473 ML99_PRIV_IF( \
474 ML99_NAT_EQ(y, 0), \
475 ML99_fatal(ML99_mod, modulo by 0), \
476 ML99_PRIV_modAux_IMPL(x, y, 0))
477
478#define ML99_PRIV_modAux_IMPL(x, y, acc) \
479 ML99_PRIV_IF( \
480 ML99_PRIV_OR(ML99_NAT_EQ(x, 0), ML99_IS_JUST(ML99_DIV_CHECKED(x, y))), \
481 v(acc), \
482 ML99_callUneval(ML99_PRIV_modAux, ML99_DEC(x), y, ML99_INC(acc)))
483// } (ML99_mod_IMPL)
484
485// } (Arithmetical operators)
486
487#define ML99_assertIsNat_IMPL(x) \
488 ML99_PRIV_IF( \
489 ML99_PRIV_NAT_EQ(x, x), \
490 v(ML99_PRIV_EMPTY()), \
491 ML99_PRIV_ASSERT_IS_NAT_FATAL(x, ML99_NAT_MAX))
492
493// clang-format off
494#define ML99_PRIV_ASSERT_IS_NAT_FATAL(x, max) ML99_fatal(ML99_assertIsNat, x must be within [0; max])
495// clang-format on
496
497// Arity specifiers {
498
499#define ML99_inc_ARITY 1
500#define ML99_dec_ARITY 1
501#define ML99_natMatch_ARITY 2
502#define ML99_natMatchWithArgs_ARITY 3
503#define ML99_natEq_ARITY 2
504#define ML99_natNeq_ARITY 2
505#define ML99_greater_ARITY 2
506#define ML99_greaterEq_ARITY 2
507#define ML99_lesser_ARITY 2
508#define ML99_lesserEq_ARITY 2
509#define ML99_add_ARITY 2
510#define ML99_sub_ARITY 2
511#define ML99_mul_ARITY 2
512#define ML99_div_ARITY 2
513#define ML99_divChecked_ARITY 2
514#define ML99_mod_ARITY 2
515#define ML99_add3_ARITY 3
516#define ML99_sub3_ARITY 3
517#define ML99_mul3_ARITY 3
518#define ML99_div3_ARITY 3
519#define ML99_min_ARITY 2
520#define ML99_max_ARITY 2
521#define ML99_assertIsNat_ARITY 1
522// } (Arity specifiers)
523
524#endif // DOXYGEN_IGNORE
525
526#endif // ML99_NAT_H
The core metalanguage.