#ifndef BREEZE_LAMBDA_H #define BREEZE_LAMBDA_H #include "../memory/memory.h" typedef struct BzLambda BzLambda; typedef void (*BzLambdaFn)(BzLambda *lambda, ...); #define BZ_LAMBDA_STACK_SIZE 52 struct BzLambda { BzLambdaFn fn; i32 captureSize; /* stack contents */ u8 stack[BZ_LAMBDA_STACK_SIZE]; }; static_assert(sizeof(BzLambda) == 64, ""); #define BZ_LAMBDA(lambdaName) \ (BzLambda) { \ .fn = (BzLambdaFn) lambdaName \ } #define BZ_LAMBDA_BEGIN_CAPTURE(lambda) \ do { \ BzLambda *_lam = (lambda); \ _lam->captureSize = 0; \ } while (0) #define BZ_LAMBDA_CAPTURE(lambda, var) \ do { \ BzLambda *_lam = (lambda); \ i32 _stackSize = _lam->captureSize; \ i32 _varSize = sizeof(var); \ assert(_stackSize + _varSize < (i32) sizeof(_lam->stack)); \ void *_location = &(var); \ bzMemCpy(&_lam->stack[_stackSize], _location, _varSize); \ _lam->captureSize += _varSize; \ } while (0) #define BZ_LAMBDA_UNPACK_START() int32_t _stackOffset = 0 #define BZ_LAMBDA_UNPACK(type, name) \ type name = (_stackOffset += sizeof(type), \ assert(_stackOffset <= _lam->captureSize), \ *(type *) &_lam->stack[_stackOffset - sizeof(type)]) #define BZ_LAMBDA_CAST_RET(retType) (retType(*)(BzLambda *, ...)) /* * Note: C99 requires at least one argument for "..." in variadic macro, * so we need to have 2 variants of CLAMBDA_CALL and CLAMBDA_DECL. */ #define BZ_LAMBDA_CALL(lambda, retType, ...) ((BZ_LAMBDA_CAST_RET(retType)((lambda)->fn))(lambda, ##__VA_ARGS__)) #define BZ_LAMBDA_NOP_CALL(lambda, retType) ((BZ_LAMBDA_CAST_RET(retType)((lambda)->fn))(lambda)) #define BZ_LAMBDA_DECL(lambdaName, ...) lambdaName(BzLambda *_lam, ##__VA_ARGS__) #define BZ_LAMBDA_NOP_DECL(lambdaName) lambdaName(BzLambda *_lam) #endif // BREEZE_LAMBDA_H