reactor-c 1.0
C Runtime for Lingua Franca
Loading...
Searching...
No Matches
reaction_macros.h
Go to the documentation of this file.
1
25
26// Prevent inclusion twice in a row without an intervening inclusion of reaction_macros_undef.h.
27#ifndef REACTION_MACROS_H
28#define REACTION_MACROS_H
29
30// NOTE: According to the "Swallowing the Semicolon" section on this page:
31// https://gcc.gnu.org/onlinedocs/gcc-3.0.1/cpp_3.html
32// some of the following macros should use an odd do-while construct to avoid
33// problems with if ... else statements that do not use braces around the
34// two branches. Specifically, if the macro expands to more than one statement,
35// then the odd construct is needed.
36
48#define lf_set_present(out) lf_set_present((lf_port_base_t*)out)
49
73#define lf_set(out, val) \
74 do { \
75 out->value = val; \
76 lf_set_present(out); \
77 if (((token_template_t*)out)->token != NULL) { \
78 /* The cast "*((void**) &out->value)" is a hack to make the code */ \
79 /* compile with non-token types where value is not a pointer. */ \
80 lf_token_t* token = _lf_initialize_token_with_value((token_template_t*)out, *((void**)&out->value), 1); \
81 out->token = token; \
82 } \
83 } while (0)
84
98#ifndef __cplusplus
99#define lf_set_array(out, val, len) \
100 do { \
101 lf_set_present(out); \
102 lf_token_t* token = _lf_initialize_token_with_value((token_template_t*)out, val, len); \
103 out->token = token; \
104 out->value = token->value; \
105 out->length = len; \
106 } while (0)
107#else
108#define lf_set_array(out, val, len) \
109 do { \
110 lf_set_present(out); \
111 lf_token_t* token = _lf_initialize_token_with_value((token_template_t*)out, val, len); \
112 out->token = token; \
113 out->value = static_cast<decltype(out->value)>(token->value); \
114 out->length = len; \
115 } while (0)
116#endif
117
129#ifndef __cplusplus
130#define lf_set_token(out, newtoken) \
131 do { \
132 lf_set_present(out); \
133 _lf_replace_template_token((token_template_t*)out, newtoken); \
134 out->value = newtoken->value; \
135 out->length = newtoken->length; \
136 } while (0)
137#else
138#define lf_set_token(out, newtoken) \
139 do { \
140 lf_set_present(out); \
141 _lf_replace_template_token((token_template_t*)out, newtoken); \
142 out->value = static_cast<decltype(out->value)>(newtoken->value); \
143 out->length = newtoken->length; \
144 } while (0)
145#endif
146
158#define lf_set_destructor(out, dtor) ((token_type_t*)out)->destructor = dtor
159
171#define lf_set_copy_constructor(out, cpy_ctor) ((token_type_t*)out)->copy_constructor = cpy_ctor
172
173#ifdef MODAL_REACTORS
174
185#define lf_set_mode(mode) _LF_SET_MODE_WITH_TYPE(mode, _lf_##mode##_change_type)
186
187#endif // MODAL_REACTORS
188
190// For simplicity and backward compatability, don't require the environment-pointer when calling the timing API.
191// As long as this is done from the context of a reaction, `self` is in scope and is a pointer to the self-struct
192// of the current reactor.
193
198#define lf_tag() lf_tag(self->base.environment)
199
204#define lf_time_logical() lf_time_logical(self->base.environment)
205
211#define lf_time_logical_elapsed() lf_time_logical_elapsed(self->base.environment)
212
222#define lf_reactor_name(reactor) lf_reactor_name(&reactor->base)
223
234#define lf_reactor_full_name(reactor) lf_reactor_full_name(&reactor->base)
235
236#endif // REACTION_MACROS_H