MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
FieldSource.hpp
Go to the documentation of this file.
1#pragma once
2
3namespace MayaFlux::Kinesis {
4
5/**
6 * @struct FieldSource
7 * @brief Parsed representation of a stringified field lambda.
8 *
9 * Produced by MF_FIELD, which stringifies the lambda text at the call site.
10 * Shares an input shape with Portal::Graphics::KernelSource but not a consumer,
11 * and differs in one respect: the parameter list is retained verbatim rather
12 * than stripped to identifiers, because a field is emitted as a standalone GLSL
13 * function above main() where the signature needs types. KernelSource strips
14 * them because a main-injected body receives its operands as file-scope
15 * declarations.
16 *
17 * Nothing here knows about ShaderSpec. The four members map onto the four
18 * arguments of ShaderSpec::Assemble::function(), and that call happens at the
19 * site assembling a spec, which is above both Kinesis and Portal.
20 *
21 * @code
22 * auto spec = ShaderSpec::Assemble{}
23 * .ssbo("pos", BindingDirection::InOut, Kakshya::GpuDataFormat::VEC4_F32)
24 * .function(swirl.source.return_type, swirl.source.name,
25 * swirl.source.params, swirl.source.body)
26 * .kernel(MF_KERNEL(...))
27 * .build();
28 * @endcode
29 */
31 std::string name;
32 std::string return_type;
33 std::string params;
34 std::string body;
35
36 /**
37 * @brief Extract return type, parameter list and body from lambda text.
38 *
39 * Requires a trailing return type: the return type is read from between the
40 * arrow and the opening brace. A lambda without one yields an empty
41 * return_type, which valid() reports as a parse failure.
42 *
43 * @param fn_name Name the emitted GLSL function will carry.
44 * @param text Raw text produced by MF_FIELD.
45 * @return Populated FieldSource.
46 */
47 [[nodiscard]] static FieldSource parse(std::string fn_name, std::string_view text)
48 {
49 FieldSource fs;
50 fs.name = std::move(fn_name);
51
52 const auto bracket = text.find('[');
53 const auto paren_open = text.find('(', bracket);
54 if (paren_open == std::string_view::npos)
55 return fs;
56
57 std::size_t depth = 1;
58 std::size_t paren_close = paren_open + 1;
59 while (paren_close < text.size() && depth > 0) {
60 if (text[paren_close] == '(') {
61 ++depth;
62 } else if (text[paren_close] == ')') {
63 --depth;
64 }
65 ++paren_close;
66 }
67 --paren_close;
68
69 fs.params = std::string(text.substr(paren_open + 1, paren_close - paren_open - 1));
70
71 const auto arrow = text.find("->", paren_close);
72 const auto brace_open = text.find('{', paren_close);
73 if (brace_open == std::string_view::npos)
74 return fs;
75
76 if (arrow != std::string_view::npos && arrow < brace_open) {
77 auto rt = text.substr(arrow + 2, brace_open - arrow - 2);
78 const auto b = rt.find_first_not_of(" \t\n\r");
79 const auto e = rt.find_last_not_of(" \t\n\r");
80 if (b != std::string_view::npos)
81 fs.return_type = std::string(rt.substr(b, e - b + 1));
82 }
83
84 depth = 1;
85 std::size_t brace_close = brace_open + 1;
86 while (brace_close < text.size() && depth > 0) {
87 if (text[brace_close] == '{') {
88 ++depth;
89 } else if (text[brace_close] == '}') {
90 --depth;
91 }
92 ++brace_close;
93 }
94 --brace_close;
95
96 fs.body = std::string(text.substr(brace_open + 1, brace_close - brace_open - 1));
97 return fs;
98 }
99
100 /**
101 * @brief Number of parameters the authored function takes.
102 *
103 * One for a spatial field, two with time, three with time and a parameter
104 * block. MF_FIELD, MF_FIELD_T and MF_FIELD_P enforce those shapes, so this
105 * identifies which of them produced the source.
106 */
107 [[nodiscard]] size_t parameter_count() const noexcept
108 {
109 return params.empty() ? 0 : static_cast<size_t>(std::ranges::count(params, ',')) + 1;
110 }
111
112 /**
113 * @brief Whether parsing produced a usable function definition.
114 */
115 [[nodiscard]] bool valid() const noexcept
116 {
117 return !name.empty() && !return_type.empty() && !body.empty();
118 }
119};
120
121} // namespace MayaFlux::Kinesis
size_t b
uint32_t depth
static FieldSource parse(std::string fn_name, std::string_view text)
Extract return type, parameter list and body from lambda text.
size_t parameter_count() const noexcept
Number of parameters the authored function takes.
bool valid() const noexcept
Whether parsing produced a usable function definition.
Parsed representation of a stringified field lambda.