22#ifndef MTROPOLIS_COROUTINES_H
23#define MTROPOLIS_COROUTINES_H
25#include "mtropolis/coroutine_protos.h"
26#include "mtropolis/miniscript_protos.h"
27#include "mtropolis/vthread.h"
32struct CoroutineRuntimeState;
34typedef VThreadState (*CoroutineFragmentFunction_t)(CoroutineRuntimeState &coroState);
42 MiniscriptInstructionOutcome _miniscriptOutcome;
54 CoroutineFrameConstructor_t _frameConstructor;
55 CoroutineGetFrameParametersFunction_t _getFrameParameters;
59 uint _numInstructions;
70 VThreadState execute(
VThread *thread)
override;
122 virtual void defineFunction(CoroutineFrameConstructor_t frameConstructor, CoroutineGetFrameParametersFunction_t frameGetParams) = 0;
123 virtual void addOp(CoroOps op, CoroutineFragmentFunction_t fragmentFunc) = 0;
126#define CORO_START_CODE_BLOCK(op) \
127 compiler->addOp(op, [](CoroutineRuntimeState &coroRuntime) -> VThreadState { \
128 Params *params = &static_cast<CoroStackFrame *>(coroRuntime._frame)->_params; \
129 Locals *locals = &static_cast<CoroStackFrame *>(coroRuntime._frame)->_locals; \
130 CoroutineReturnValueRef<ReturnValue_t> coroReturnValueRef = (static_cast<CoroStackFrame *>(coroRuntime._frame)->_rvRef);
132#define CORO_AWAIT_PUSHED_TASK \
133 return kVThreadReturn
135#define CORO_DISUSE_CODE_BLOCK_VARS \
138 (void)coroReturnValueRef;
140#define CORO_END_CODE_BLOCK \
141 CORO_DISUSE_CODE_BLOCK_VARS \
142 return kVThreadReturn; \
145#define CORO_BEGIN_DEFINITION(type) \
146CompiledCoroutine *type::ms_compiledCoro = nullptr;\
147void type::compileCoroutine(ICoroutineCompiler *compiler) {
149#define CORO_END_DEFINITION \
152#define CORO_BEGIN_FUNCTION \
153 struct CoroStackFrame : public CoroutineStackFrame2 {\
156 CoroutineReturnValueRef<ReturnValue_t> _rvRef;\
157 explicit CoroStackFrame(const CompiledCoroutine *compiledCoro, const Params ¶ms, const CoroutineReturnValueRef<ReturnValue_t> &rvRef)\
158 : CoroutineStackFrame2(compiledCoro), _params(params), _rvRef(rvRef) {\
160 static CoroutineStackFrame2 *constructFrame(void *ptr, const CompiledCoroutine *compiledCoro, const CoroutineParamsBase ¶ms, const CoroutineReturnValueRefBase &returnValueRef) {\
161 return new (ptr) CoroStackFrame(compiledCoro, static_cast<const Params &>(params), static_cast<const CoroutineReturnValueRef<ReturnValue_t>&>(returnValueRef));\
163 static void getFrameParameters(size_t &outSize, size_t &outAlignment) { \
164 outSize = sizeof(CoroStackFrame); \
165 outAlignment = alignof(CoroStackFrame); \
168 compiler->defineFunction(CoroStackFrame::constructFrame, CoroStackFrame::getFrameParameters); \
169 CORO_START_CODE_BLOCK(CoroOps::BeginFunction)
171#define CORO_END_FUNCTION \
172 CORO_END_CODE_BLOCK \
173 CORO_START_CODE_BLOCK(CoroOps::EndFunction) \
176#define CORO_AWAIT(expr) \
178 CORO_END_CODE_BLOCK \
179 CORO_START_CODE_BLOCK(CoroOps::YieldToFunction) \
180 CORO_END_CODE_BLOCK \
181 CORO_START_CODE_BLOCK(CoroOps::Code)
183#define CORO_AWAIT_MINISCRIPT(expr) \
184 coroRuntime._miniscriptOutcome = ((expr)); \
185 CORO_END_CODE_BLOCK \
186 CORO_START_CODE_BLOCK(CoroOps::CheckMiniscript) \
187 CORO_END_CODE_BLOCK \
188 CORO_START_CODE_BLOCK(CoroOps::Code)
190#define CORO_IF(expr) \
191 CORO_END_CODE_BLOCK \
192 CORO_START_CODE_BLOCK(CoroOps::IfCond) \
193 coroRuntime._condition = !!(expr); \
194 CORO_END_CODE_BLOCK \
195 CORO_START_CODE_BLOCK(CoroOps::IfBody)
198 CORO_END_CODE_BLOCK \
199 CORO_START_CODE_BLOCK(CoroOps::Else)
201#define CORO_ELSE_IF(expr) \
202 CORO_END_CODE_BLOCK \
203 CORO_START_CODE_BLOCK(CoroOps::ElseIfCond) \
204 coroRuntime._condition = !!(expr); \
205 CORO_END_CODE_BLOCK \
206 CORO_START_CODE_BLOCK(CoroOps::ElseIfBody)
209 CORO_END_CODE_BLOCK \
210 CORO_START_CODE_BLOCK(CoroOps::EndIf)
212#define CORO_WHILE(expr) \
213 CORO_END_CODE_BLOCK \
214 CORO_START_CODE_BLOCK(CoroOps::WhileCond) \
215 coroRuntime._condition = !!(expr); \
216 CORO_END_CODE_BLOCK \
217 CORO_START_CODE_BLOCK(CoroOps::WhileBody)
219#define CORO_END_WHILE \
220 CORO_END_CODE_BLOCK \
221 CORO_START_CODE_BLOCK(CoroOps::EndWhile)
224 CORO_END_CODE_BLOCK \
225 CORO_START_CODE_BLOCK(CoroOps::Do)
227#define CORO_DO_WHILE(expr) \
228 CORO_END_CODE_BLOCK \
229 CORO_START_CODE_BLOCK(CoroOps::DoWhileCond) \
230 coroCondition = !(expr); \
231 CORO_END_CODE_BLOCK \
232 CORO_START_CODE_BLOCK(CoroOps::DoWhile)
234#define CORO_FOR(initExpr, condExpr, nextExpr) \
236 CORO_END_CODE_BLOCK \
237 CORO_START_CODE_BLOCK(CoroOps::ForNext) \
239 CORO_END_CODE_BLOCK \
240 CORO_START_CODE_BLOCK(CoroOps::ForCond) \
241 coroRuntime._condition = !!(condExpr); \
242 CORO_END_CODE_BLOCK \
243 CORO_START_CODE_BLOCK(CoroOps::ForBody)
245#define CORO_END_FOR \
246 CORO_END_CODE_BLOCK \
247 CORO_START_CODE_BLOCK(CoroOps::EndFor)
249#define CORO_RETURN_VALUE(expr) \
250 coroReturnValueRef.set((expr)); \
251 CORO_END_CODE_BLOCK \
252 CORO_START_CODE_BLOCK(CoroOps::Return)
255 CORO_END_CODE_BLOCK \
256 CORO_START_CODE_BLOCK(CoroOps::Error)
260 coroReturnValueRef.voidSet(); \
261 CORO_END_CODE_BLOCK \
262 CORO_START_CODE_BLOCK(CoroOps::Return)
264#define CORO_RETURN_CALL(func, ...) \
265 coroFrame->pushFrame<CoroAutoFrame<func> >(coroReturnValueRef._returnValue, __VA_ARGS__); \
266 CORO_END_CODE_BLOCK \
267 CORO_START_CODE_BLOCK(CoroOps::YieldToFunction) \
268 CORO_END_CODE_BLOCK \
269 CORO_START_CODE_BLOCK(CoroOps::Return)
271#define CORO_SET_CALL(dest, func, ...) \
272 CORO_AWAIT(coroRuntime._vthread->pushCoroutineWithReturn<func>(&(dest), __VA_ARGS__))
274#define CORO_CALL(func, ...) \
275 CORO_AWAIT(coroRuntime._vthread->pushCoroutine<func>(__VA_ARGS__))
Definition: vthread.h:133
Definition: coroutines.h:50
Definition: coroutine_exec.h:42
Definition: coroutines.h:36
Definition: coroutines.h:66
Definition: coroutines.h:119