eĿlipsis
a language independent preprocessor
 
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Loading...
Searching...
No Matches
ellipsis-contracts.h
Go to the documentation of this file.
1#unit ellipsis∷contracts
2#once
3
4#ifndef DOXYGEN_SPECIAL
5
6extern thread_local bool volatile ¤∷⸤ignore⸥∷⸤dynamic⸥;
7extern thread_local bool volatile ¤∷⸤proceed⸥∷⸤dynamic⸥;
8extern thread_local bool volatile ¤∷⸤verbose⸥∷⸤dynamic⸥;
9
10typedef struct ellipsis∷contracts∷is_ice ellipsis∷contracts∷is_ice;
11
12#endif
13
14%%include <stdio.h>
15%%include <stdlib.h>
16%%include <stdint.h>
17
18#include_directives <ellipsis-contracts-macros.h>
19
20// Assert variants always have defined behavior. The expression must
21// always parse correctly and generally leads to abortion, if not
22// fulfilled. If the arguments are an ICE, the decision is taken at
23// compile time; if it is unequal to zero, everything is optimized
24// out. But the assertion can also be ignored and the continuation of
25// the execution instead of abortion can be forced.
26#define ELLIPSIS_CONTRACT_ASSERT_IMPL(CTYPE, COND, CSTR, ...) \
27 ELLIPSIS_CONTRACT(__COUNTER__, COND, abort, true, CSTR, CTYPE __VA_OPT__(,) __VA_ARGS__)
28
29
30// Assume variants always have undefined behavior if the condition is
31// not an ICE and doesn't hold. If the arguments are an ICE, the
32// decision is taken at compile time; if it is unequal to zero,
33// everything is optimized out. The expression is always evaluated. A
34// verbose diagnostic in case of failure can be forced, after that,
35// the behavior is UB, regardless.
36#define ELLIPSIS_CONTRACT_ASSUME_IMPL(CTYPE, COND, CSTR, ...) \
37 ELLIPSIS_CONTRACT(__COUNTER__, COND, unreachable, false, CSTR, CTYPE __VA_OPT__(,) __VA_ARGS__)
38
39#ifndef DOXYGEN_SPECIAL
40
41%%define STRINGIFY(...) STRINGIFY_(__VA_ARGS__)
42%%define STRINGIFY_(...) #__VA_ARGS__
43
44%%define ELLIPSIS_CONTRACT_VIOLATION(COUNT, VERB, CTYPE, CSTR, …) \
45({ \
46 static char const contract_format_ ## COUNT[] = \
47 ⸤__FILE__⸥ ":" ⸤STRINGIFY⸥(⸤__LINE__⸥) ": violation of " CTYPE " `" CSTR "`" __VA_OPT__(", ") __VA_ARGS__ "\n"; \
48 (VERB \
49 ? fputs(contract_format_ ## COUNT, stderr) \
50 : 0); \
51 })
52
53%%define ELLIPSIS_CONTRACT_IMPL(COUNT, COND, ACTION, VERB, CSTR, CTYPE, …) \
54((ellipsis_contracts_ignore() ∨ (COND)) \
55 ? (void)0 \
56 : (ELLIPSIS_CONTRACT_VIOLATION(COUNT, VERB, CTYPE, CSTR __VA_OPT__(,) __VA_ARGS__) \
57 , (ellipsis_contracts_proceed() \
58 ? (void)0 \
59 : ACTION())))
60
61// if argument is ICE, this is a ICE cast to void*, thus a NPC. The
62// intermediate cast to uintptr_t is only here to silence overeager
63// diagnostics that this might loose bits.
64/* %%ifdef UINTPTR_MAX */
65/* %% define CONV_SILENCE (uintptr_t) */
66/* %%else */
67/* %% define CONV_SILENCE */
68/* %%endif */
69%%define ELLIPSIS_TO_VOIDS(…) ((void*)((uintptr_t)((__VA_ARGS__)-(__VA_ARGS__))))
70// if argument is ICE, this has type is_ice*. Otherwise void* but still is never evaluated.
71%%define ELLIPSIS_TEST_ICE(…) (false ? ELLIPSIS_TO_VOIDS(__VA_ARGS__) : (ellipsis∷contracts∷is_ice*)nullptr)
72
73// If argument is ICE, return the argument, otherwise return true
75 _Generic( \
76 ELLIPSIS_TEST_ICE(__VA_ARGS__), \
77 ellipsis∷contracts∷is_ice*: (__VA_ARGS__), \
78 default: true)
79
80
81// if arguments are ICE of value 0, complain. Otherwise do never anything.
82%%define ELLIPSIS_CONTRACT_CHECK_STATIC(CTYPE, COND, CSTR, ...) \
83 ({ \
84 static_assert(ELLIPSIS_CONTRACT_ICE_OR_TRUE(COND), \
85 "compile time violation of " CTYPE " " CSTR \
86 __VA_OPT__(", ") __VA_ARGS__ ); \
87 })
88
89
90// if arguments are ICE: if value is 0, error out at compile time;
91// otherwise do nothing and optimize out. If arguments are not ICE,
92// apply MACRO.
93%%define ELLIPSIS_CONTRACT(COUNT, COND, ACTION, VERB, CSTR, CTYPE, …) \
94ELLIPSIS_MARK_LINE/*^ checking CTYPE CSTR ^*/ \
95 ⸤do {⸥ \
96 ⸤_Generic⸥( \
97 ELLIPSIS_TEST_ICE(COND), \
98 ⸤ellipsis∷contracts∷is_ice*:⸥ ELLIPSIS_CONTRACT_CHECK_STATIC(CTYPE, COND, CSTR __VA_OPT__(,) __VA_ARGS__), \
99 ⸤default:⸥ ELLIPSIS_CONTRACT_IMPL(COUNT, COND, ACTION, VERB, CSTR, CTYPE __VA_OPT__(,) __VA_ARGS__)); \
100 ⸤} while(false)⸥
101
102#endif
__directive__ define
The define directive as specified by the C standard.
Definition directives.c:33
__directive__ include
The include directive as specified by the C standard plus extensions.
Definition directives.c:67
#define true
The constant true made accessible to the preprocessor.
Definition ellipsis-builtins.dirs:32
#define false
The constant false made accessible to the preprocessor.
Definition ellipsis-builtins.dirs:33
#define ELLIPSIS_MARK_LINE
A hook to add code that puts line number information into the output stream.
Definition ellipsis-environment.dirs:64
#define ELLIPSIS_CONTRACT(COUNT, COND, ACTION, VERB, CSTR, CTYPE,...)
Definition ellipsis-expression.c:67
#define ELLIPSIS_TEST_ICE(...)
Definition ellipsis-expression.c:52
#define ELLIPSIS_CONTRACT_ICE_OR_TRUE(...)
Definition ellipsis-expression.c:54
#define STRINGIFY(...)
Definition ellipsis-expression.c:30
#define ELLIPSIS_CONTRACT_VIOLATION(COUNT, VERB, CTYPE, CSTR,...)
Definition ellipsis-expression.c:33
#define ELLIPSIS_CONTRACT_CHECK_STATIC(CTYPE, COND, CSTR,...)
Definition ellipsis-expression.c:60
#define STRINGIFY_(...)
Definition ellipsis-expression.c:31
#define ELLIPSIS_TO_VOIDS(...)
Definition ellipsis-expression.c:50
#define ELLIPSIS_CONTRACT_IMPL(COUNT, COND, ACTION, VERB, CSTR, CTYPE,...)
Definition ellipsis-expression.c:42
#define __VA_OPT__
A pseudo macro that cannot be redefined.
Definition ellipsis-predefined.dirs:89