VapourSynth-llvmexpr
Loading...
Searching...
No Matches
Builtins.cpp
Go to the documentation of this file.
1
19
20#include "Builtins.hpp"
21#include "AST.hpp"
22#include "CodeGenerator.hpp"
23#include "PostfixBuilder.hpp"
24
25#include <format>
26#include <string>
27
28namespace infix2postfix {
29
30namespace {
31
32PostfixBuilder handle_dyn_expr_3args(CodeGenerator* codegen,
33 const CallExpr& expr) {
34 // Signature: dyn($clip, x, y)
35 // Default boundary mode is clamped.
37 b.append(codegen->generateExpr(expr.args[1].get()).postfix);
38 b.append(codegen->generateExpr(expr.args[2].get()).postfix);
39
40 auto clip_res = codegen->generateExpr(expr.args[0].get());
41 std::string clip_name = clip_res.postfix.getExpression();
42
43 b.addDynPixelAccessExpr(clip_name, ":c");
44 return b;
45}
46
47PostfixBuilder handle_dyn_expr_4args(CodeGenerator* codegen,
48 const CallExpr& expr) {
49 // Signature: dyn($clip, x, y, boundary_mode)
51 b.append(codegen->generateExpr(expr.args[1].get()).postfix);
52 b.append(codegen->generateExpr(expr.args[2].get()).postfix);
53
54 auto clip_res = codegen->generateExpr(expr.args[0].get());
55 std::string clip_name = clip_res.postfix.getExpression();
56
57 auto* boundary_expr = get_if<NumberExpr>(expr.args[3].get());
58 int boundary_mode = std::stoi(boundary_expr->value.value);
59 std::string suffix;
60 switch (boundary_mode) {
61 case 0: // global
62 suffix = "";
63 break;
64 case 1: // mirrored
65 suffix = ":m";
66 break;
67 case 2: // clamped
68 suffix = ":c";
69 break;
70 default:
71 throw CodeGenError(
72 std::format("Invalid boundary mode '{}' for dyn()", boundary_mode),
73 expr.range);
74 }
75 b.addDynPixelAccessExpr(clip_name, suffix);
76 return b;
77}
78
79PostfixBuilder handle_dyn_single(CodeGenerator* codegen, const CallExpr& expr) {
80 // Signature: dyn($clip, x, y, plane)
81 auto clip_res = codegen->generateExpr(expr.args[0].get());
82 std::string clip_name = clip_res.postfix.getExpression();
83
84 auto* plane_expr = get_if<NumberExpr>(expr.args[3].get());
85 std::string plane_idx = plane_expr->value.value;
86
88 b.append(codegen->generateExpr(expr.args[1].get()).postfix);
89 b.append(codegen->generateExpr(expr.args[2].get()).postfix);
90 b.addDynPixelAccessSingle(clip_name, plane_idx);
91 return b;
92}
93
94PostfixBuilder handle_store_expr(CodeGenerator* codegen, const CallExpr& expr) {
95 // store(x, y, val)
97 b.append(codegen->generateExpr(expr.args[2].get()).postfix);
98 b.append(codegen->generateExpr(expr.args[0].get()).postfix);
99 b.append(codegen->generateExpr(expr.args[1].get()).postfix);
100 b.addStoreExpr();
101 return b;
102}
103
104PostfixBuilder handle_store_single(CodeGenerator* codegen,
105 const CallExpr& expr) {
106 // store(x, y, plane, value)
107 auto* plane_expr = get_if<NumberExpr>(expr.args[2].get());
108 std::string plane_idx = plane_expr->value.value;
109
111 b.append(codegen->generateExpr(expr.args[3].get()).postfix);
112 b.append(codegen->generateExpr(expr.args[0].get()).postfix);
113 b.append(codegen->generateExpr(expr.args[1].get()).postfix);
114 b.addStoreSingle(plane_idx);
115 return b;
116}
117
118PostfixBuilder handle_set_prop_typed(CodeGenerator* codegen,
119 const CallExpr& expr,
120 const std::string& suffix) {
121 // set_prop*(prop_name, value)
122 auto* prop_name_expr = get_if<VariableExpr>(expr.args[0].get());
123
125 b.append(codegen->generateExpr(expr.args[1].get()).postfix);
126 b.addSetProp(prop_name_expr->name.value, suffix);
127 return b;
128}
129
130const auto handle_set_propf = [](CodeGenerator* codegen, const CallExpr& expr) {
131 return handle_set_prop_typed(codegen, expr, "f");
132};
133
134const auto handle_set_propi = [](CodeGenerator* codegen, const CallExpr& expr) {
135 return handle_set_prop_typed(codegen, expr, "i");
136};
137
138const auto handle_set_propaf = [](CodeGenerator* codegen,
139 const CallExpr& expr) {
140 return handle_set_prop_typed(codegen, expr, "af");
141};
142
143const auto handle_set_propai = [](CodeGenerator* codegen,
144 const CallExpr& expr) {
145 return handle_set_prop_typed(codegen, expr, "ai");
146};
147
148PostfixBuilder handle_remove_prop([[maybe_unused]] CodeGenerator* codegen,
149 const CallExpr& expr) {
150 // remove_prop(prop_name)
151 auto* prop_name_expr = get_if<VariableExpr>(expr.args[0].get());
152
154 b.addDeleteProp(prop_name_expr->name.value);
155 return b;
156}
157
158PostfixBuilder handle_exit([[maybe_unused]] CodeGenerator* codegen,
159 [[maybe_unused]] const CallExpr& expr) {
161 b.addExitMarker();
162 return b;
163}
164
165PostfixBuilder handle_is_prop_exist(CodeGenerator* codegen,
166 const CallExpr& expr) {
167 // is_prop_exist(clip, prop_name)
168 auto clip_res = codegen->generateExpr(expr.args[0].get());
169 std::string clip_name = clip_res.postfix.getExpression();
170
171 auto* prop_name_expr = get_if<VariableExpr>(expr.args[1].get());
172
174 b.addPropExist(clip_name, prop_name_expr->name.value);
175 return b;
176}
177
178// nth_N functions are not handled here
179const std::map<std::string, std::vector<BuiltinFunction>> builtin_functions = {
180 // Standard math
181 {"sin",
182 {BuiltinFunction{.name = "sin",
183 .arity = 1,
184 .mode_restriction = std::nullopt,
185 .param_types = {Type::Value}}}},
186 {"cos",
187 {BuiltinFunction{.name = "cos",
188 .arity = 1,
189 .mode_restriction = std::nullopt,
190 .param_types = {Type::Value}}}},
191 {"tan",
192 {BuiltinFunction{.name = "tan",
193 .arity = 1,
194 .mode_restriction = std::nullopt,
195 .param_types = {Type::Value}}}},
196 {"asin",
197 {BuiltinFunction{.name = "asin",
198 .arity = 1,
199 .mode_restriction = std::nullopt,
200 .param_types = {Type::Value}}}},
201 {"acos",
202 {BuiltinFunction{.name = "acos",
203 .arity = 1,
204 .mode_restriction = std::nullopt,
205 .param_types = {Type::Value}}}},
206 {"atan",
207 {BuiltinFunction{.name = "atan",
208 .arity = 1,
209 .mode_restriction = std::nullopt,
210 .param_types = {Type::Value}}}},
211 {"atan2",
212 {BuiltinFunction{.name = "atan2",
213 .arity = 2,
214 .mode_restriction = std::nullopt,
215 .param_types = {Type::Value, Type::Value}}}},
216 {"exp",
217 {BuiltinFunction{.name = "exp",
218 .arity = 1,
219 .mode_restriction = std::nullopt,
220 .param_types = {Type::Value}}}},
221 {"exp2",
222 {BuiltinFunction{.name = "exp2",
223 .arity = 1,
224 .mode_restriction = std::nullopt,
225 .param_types = {Type::Value}}}},
226 {"log",
227 {BuiltinFunction{.name = "log",
228 .arity = 1,
229 .mode_restriction = std::nullopt,
230 .param_types = {Type::Value}}}},
231 {"log2",
232 {BuiltinFunction{.name = "log2",
233 .arity = 1,
234 .mode_restriction = std::nullopt,
235 .param_types = {Type::Value}}}},
236 {"log10",
237 {BuiltinFunction{.name = "log10",
238 .arity = 1,
239 .mode_restriction = std::nullopt,
240 .param_types = {Type::Value}}}},
241 {"sqrt",
242 {BuiltinFunction{.name = "sqrt",
243 .arity = 1,
244 .mode_restriction = std::nullopt,
245 .param_types = {Type::Value}}}},
246 {"abs",
247 {BuiltinFunction{.name = "abs",
248 .arity = 1,
249 .mode_restriction = std::nullopt,
250 .param_types = {Type::Value}}}},
251 {"sgn",
252 {BuiltinFunction{.name = "sgn",
253 .arity = 1,
254 .mode_restriction = std::nullopt,
255 .param_types = {Type::Value}}}},
256 {"floor",
257 {BuiltinFunction{.name = "floor",
258 .arity = 1,
259 .mode_restriction = std::nullopt,
260 .param_types = {Type::Value}}}},
261 {"ceil",
262 {BuiltinFunction{.name = "ceil",
263 .arity = 1,
264 .mode_restriction = std::nullopt,
265 .param_types = {Type::Value}}}},
266 {"round",
267 {BuiltinFunction{.name = "round",
268 .arity = 1,
269 .mode_restriction = std::nullopt,
270 .param_types = {Type::Value}}}},
271 {"trunc",
272 {BuiltinFunction{.name = "trunc",
273 .arity = 1,
274 .mode_restriction = std::nullopt,
275 .param_types = {Type::Value}}}},
276 {"min",
277 {BuiltinFunction{.name = "min",
278 .arity = 2,
279 .mode_restriction = std::nullopt,
280 .param_types = {Type::Value, Type::Value}}}},
281 {"max",
282 {BuiltinFunction{.name = "max",
283 .arity = 2,
284 .mode_restriction = std::nullopt,
285 .param_types = {Type::Value, Type::Value}}}},
286 {"copysign",
287 {BuiltinFunction{.name = "copysign",
288 .arity = 2,
289 .mode_restriction = std::nullopt,
290 .param_types = {Type::Value, Type::Value}}}},
291 {"clamp",
292 {BuiltinFunction{.name = "clamp",
293 .arity = 3,
294 .mode_restriction = std::nullopt,
295 .param_types = {Type::Value, Type::Value, Type::Value}}}},
296 {"fma",
297 {BuiltinFunction{.name = "fma",
298 .arity = 3,
299 .mode_restriction = std::nullopt,
300 .param_types = {Type::Value, Type::Value, Type::Value}}}},
301
302 // Mode-specific & special handling
303 {"set_prop",
304 {BuiltinFunction{.name = "set_prop",
305 .arity = 2,
306 .mode_restriction = Mode::Single,
307 .param_types = {Type::LiteralString, Type::Value},
308 .special_handler =
309 handle_set_propf, // alias for set_propf
310 .returns_value = false}}},
311 {"set_propf",
312 {BuiltinFunction{.name = "set_propf",
313 .arity = 2,
314 .mode_restriction = Mode::Single,
315 .param_types = {Type::LiteralString, Type::Value},
316 .special_handler = handle_set_propf,
317 .returns_value = false}}},
318 {"set_propi",
319 {BuiltinFunction{.name = "set_propi",
320 .arity = 2,
321 .mode_restriction = Mode::Single,
322 .param_types = {Type::LiteralString, Type::Value},
323 .special_handler = handle_set_propi,
324 .returns_value = false}}},
325 {"set_propaf",
326 {BuiltinFunction{.name = "set_propaf",
327 .arity = 2,
328 .mode_restriction = Mode::Single,
329 .param_types = {Type::LiteralString, Type::Value},
330 .special_handler = handle_set_propaf,
331 .returns_value = false}}},
332 {"set_propai",
333 {BuiltinFunction{.name = "set_propai",
334 .arity = 2,
335 .mode_restriction = Mode::Single,
336 .param_types = {Type::LiteralString, Type::Value},
337 .special_handler = handle_set_propai,
338 .returns_value = false}}},
339 {"remove_prop",
340 {BuiltinFunction{.name = "remove_prop",
341 .arity = 1,
342 .mode_restriction = Mode::Single,
343 .param_types = {Type::LiteralString},
344 .special_handler = handle_remove_prop,
345 .returns_value = false}}},
346 {"is_prop_exist",
347 {BuiltinFunction{.name = "is_prop_exist",
348 .arity = 2,
349 .mode_restriction = std::nullopt,
350 .param_types = {Type::Clip, Type::LiteralString},
351 .special_handler = handle_is_prop_exist}}},
352 {"dyn",
353 {
354 BuiltinFunction{.name = "dyn",
355 .arity = 3,
356 .mode_restriction = Mode::Expr,
357 .param_types = {Type::Clip, Type::Value, Type::Value},
358 .special_handler = &handle_dyn_expr_3args},
359 BuiltinFunction{.name = "dyn",
360 .arity = 4,
361 .mode_restriction = Mode::Expr,
362 .param_types = {Type::Clip, Type::Value, Type::Value,
364 .special_handler = &handle_dyn_expr_4args},
365 BuiltinFunction{.name = "dyn",
366 .arity = 4,
367 .mode_restriction = Mode::Single,
368 .param_types = {Type::Clip, Type::Value, Type::Value,
370 .special_handler = &handle_dyn_single},
371 }},
372 {"store",
373 {
374 BuiltinFunction{.name = "store",
375 .arity = 3,
376 .mode_restriction = Mode::Expr,
377 .param_types = {Type::Value, Type::Value, Type::Value},
378 .special_handler = &handle_store_expr,
379 .returns_value = false},
380 BuiltinFunction{.name = "store",
381 .arity = 4,
382 .mode_restriction = Mode::Single,
383 .param_types = {Type::Value, Type::Value,
385 .special_handler = &handle_store_single,
386 .returns_value = false},
387 }},
388 {"exit",
389 {BuiltinFunction{.name = "exit",
390 .arity = 0,
391 .mode_restriction = Mode::Expr,
392 .param_types = {},
393 .special_handler = &handle_exit,
394 .returns_value = false}}},
395};
396
397} // namespace
398
399const std::map<std::string, std::vector<BuiltinFunction>>&
401 return builtin_functions;
402}
403
404} // namespace infix2postfix
void addPropExist(const std::string &clip_name, const std::string &prop_name)
void addDeleteProp(const std::string &prop_name)
std::string getExpression() const
void append(const PostfixBuilder &other)
auto get_if(Wrapper *wrapper) -> decltype(std::get_if< T >(&wrapper->value))
Definition AST.hpp:442
const std::map< std::string, std::vector< BuiltinFunction > > & get_builtin_functions()
Definition Builtins.cpp:400