reactor-c
C Runtime for Lingua Franca
Loading...
Searching...
No Matches
reaction_macros.h
Go to the documentation of this file.
1
27// Prevent inclusion twice in a row without an intervening inclusion of reaction_macros_undef.h.
28#ifndef REACTION_MACROS_H
29#define REACTION_MACROS_H
30
31// NOTE: According to the "Swallowing the Semicolon" section on this page:
32// https://gcc.gnu.org/onlinedocs/gcc-3.0.1/cpp_3.html
33// some of the following macros should use an odd do-while construct to avoid
34// problems with if ... else statements that do not use braces around the
35// two branches. Specifically, if the macro expands to more than one statement,
36// then the odd construct is needed.
37
48#define lf_set_present(out) lf_set_present((lf_port_base_t*)out)
49
72#define lf_set(out, val) \
73 do { \
74 out->value = val; \
75 lf_set_present(out); \
76 if (((token_template_t*)out)->token != NULL) { \
77 /* The cast "*((void**) &out->value)" is a hack to make the code */ \
78 /* compile with non-token types where value is not a pointer. */ \
79 lf_token_t* token = _lf_initialize_token_with_value((token_template_t*)out, *((void**)&out->value), 1); \
80 out->token = token; \
81 } \
82 } while (0)
83
96#ifndef __cplusplus
97#define lf_set_array(out, val, len) \
98 do { \
99 lf_set_present(out); \
100 lf_token_t* token = _lf_initialize_token_with_value((token_template_t*)out, val, len); \
101 out->token = token; \
102 out->value = token->value; \
103 out->length = len; \
104 } while (0)
105#else
106#define lf_set_array(out, val, len) \
107 do { \
108 lf_set_present(out); \
109 lf_token_t* token = _lf_initialize_token_with_value((token_template_t*)out, val, len); \
110 out->token = token; \
111 out->value = static_cast<decltype(out->value)>(token->value); \
112 out->length = len; \
113 } while (0)
114#endif
115
126#ifndef __cplusplus
127#define lf_set_token(out, newtoken) \
128 do { \
129 lf_set_present(out); \
130 _lf_replace_template_token((token_template_t*)out, newtoken); \
131 out->value = newtoken->value; \
132 out->length = newtoken->length; \
133 } while (0)
134#else
135#define lf_set_token(out, newtoken) \
136 do { \
137 lf_set_present(out); \
138 _lf_replace_template_token((token_template_t*)out, newtoken); \
139 out->value = static_cast<decltype(out->value)>(newtoken->value); \
140 out->length = newtoken->length; \
141 } while (0)
142#endif
143
154#define lf_set_destructor(out, dtor) ((token_type_t*)out)->destructor = dtor
155
166#define lf_set_copy_constructor(out, cpy_ctor) ((token_type_t*)out)->copy_constructor = cpy_ctor
167
168#ifdef MODAL_REACTORS
169
177#define lf_set_mode(mode) _LF_SET_MODE_WITH_TYPE(mode, _lf_##mode##_change_type)
178
179#endif // MODAL_REACTORS
180
182// For simplicity and backward compatability, don't require the environment-pointer when calling the timing API.
183// As long as this is done from the context of a reaction, `self` is in scope and is a pointer to the self-struct
184// of the current reactor.
185
189#define lf_tag() lf_tag(self->base.environment)
190
194#define lf_time_logical() lf_time_logical(self->base.environment)
195
200#define lf_time_logical_elapsed() lf_time_logical_elapsed(self->base.environment)
201
202#endif // REACTION_MACROS_H