1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2020 Google LLC
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/sksl/DSLCore.h"
9cb93a386Sopenharmony_ci
10cb93a386Sopenharmony_ci#include "include/private/SkSLDefines.h"
11cb93a386Sopenharmony_ci#include "include/sksl/DSLSymbols.h"
12cb93a386Sopenharmony_ci#include "include/sksl/DSLVar.h"
13cb93a386Sopenharmony_ci#include "src/sksl/SkSLCompiler.h"
14cb93a386Sopenharmony_ci#include "src/sksl/SkSLThreadContext.h"
15cb93a386Sopenharmony_ci#include "src/sksl/dsl/priv/DSLWriter.h"
16cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLBlock.h"
17cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLBreakStatement.h"
18cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLContinueStatement.h"
19cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLDiscardStatement.h"
20cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLDoStatement.h"
21cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLExtension.h"
22cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLField.h"
23cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLForStatement.h"
24cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLFunctionCall.h"
25cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLIfStatement.h"
26cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLInterfaceBlock.h"
27cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLModifiersDeclaration.h"
28cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLReturnStatement.h"
29cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLStructDefinition.h"
30cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSwitchStatement.h"
31cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLSwizzle.h"
32cb93a386Sopenharmony_ci#include "src/sksl/ir/SkSLTernaryExpression.h"
33cb93a386Sopenharmony_ci#include "src/sksl/transform/SkSLTransform.h"
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_cinamespace SkSL {
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_cinamespace dsl {
38cb93a386Sopenharmony_ci
39cb93a386Sopenharmony_civoid Start(SkSL::Compiler* compiler, ProgramKind kind) {
40cb93a386Sopenharmony_ci    Start(compiler, kind, ProgramSettings());
41cb93a386Sopenharmony_ci}
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_civoid Start(SkSL::Compiler* compiler, ProgramKind kind, const ProgramSettings& settings) {
44cb93a386Sopenharmony_ci    ThreadContext::SetInstance(std::make_unique<ThreadContext>(compiler, kind, settings,
45cb93a386Sopenharmony_ci            compiler->moduleForProgramKind(kind), /*isModule=*/false));
46cb93a386Sopenharmony_ci}
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_civoid StartModule(SkSL::Compiler* compiler, ProgramKind kind, const ProgramSettings& settings,
49cb93a386Sopenharmony_ci                 SkSL::ParsedModule baseModule) {
50cb93a386Sopenharmony_ci    ThreadContext::SetInstance(std::make_unique<ThreadContext>(compiler, kind, settings,
51cb93a386Sopenharmony_ci            baseModule, /*isModule=*/true));
52cb93a386Sopenharmony_ci}
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_civoid End() {
55cb93a386Sopenharmony_ci    SkASSERTF(!ThreadContext::InFragmentProcessor(),
56cb93a386Sopenharmony_ci              "more calls to StartFragmentProcessor than to EndFragmentProcessor");
57cb93a386Sopenharmony_ci    ThreadContext::SetInstance(nullptr);
58cb93a386Sopenharmony_ci}
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_ciErrorReporter& GetErrorReporter() {
61cb93a386Sopenharmony_ci    return ThreadContext::GetErrorReporter();
62cb93a386Sopenharmony_ci}
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_civoid SetErrorReporter(ErrorReporter* errorReporter) {
65cb93a386Sopenharmony_ci    SkASSERT(errorReporter);
66cb93a386Sopenharmony_ci    ThreadContext::SetErrorReporter(errorReporter);
67cb93a386Sopenharmony_ci}
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ciclass DSLCore {
70cb93a386Sopenharmony_cipublic:
71cb93a386Sopenharmony_ci    static std::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<String> source) {
72cb93a386Sopenharmony_ci        ThreadContext& instance = ThreadContext::Instance();
73cb93a386Sopenharmony_ci        SkSL::Compiler& compiler = *instance.fCompiler;
74cb93a386Sopenharmony_ci        const SkSL::Context& context = *compiler.fContext;
75cb93a386Sopenharmony_ci        // Variables defined in the pre-includes need their declaring elements added to the program
76cb93a386Sopenharmony_ci        if (!instance.fConfig->fIsBuiltinCode && context.fIntrinsics) {
77cb93a386Sopenharmony_ci            Transform::FindAndDeclareBuiltinVariables(context, instance.fConfig->fKind,
78cb93a386Sopenharmony_ci                    instance.fSharedElements);
79cb93a386Sopenharmony_ci        }
80cb93a386Sopenharmony_ci        Pool* pool = instance.fPool.get();
81cb93a386Sopenharmony_ci        auto result = std::make_unique<SkSL::Program>(std::move(source),
82cb93a386Sopenharmony_ci                                                      std::move(instance.fConfig),
83cb93a386Sopenharmony_ci                                                      compiler.fContext,
84cb93a386Sopenharmony_ci                                                      std::move(instance.fProgramElements),
85cb93a386Sopenharmony_ci                                                      std::move(instance.fSharedElements),
86cb93a386Sopenharmony_ci                                                      std::move(instance.fModifiersPool),
87cb93a386Sopenharmony_ci                                                      std::move(compiler.fSymbolTable),
88cb93a386Sopenharmony_ci                                                      std::move(instance.fPool),
89cb93a386Sopenharmony_ci                                                      instance.fInputs);
90cb93a386Sopenharmony_ci        bool success = false;
91cb93a386Sopenharmony_ci        if (!compiler.finalize(*result)) {
92cb93a386Sopenharmony_ci            // Do not return programs that failed to compile.
93cb93a386Sopenharmony_ci        } else if (!compiler.optimize(*result)) {
94cb93a386Sopenharmony_ci            // Do not return programs that failed to optimize.
95cb93a386Sopenharmony_ci        } else {
96cb93a386Sopenharmony_ci            // We have a successful program!
97cb93a386Sopenharmony_ci            success = true;
98cb93a386Sopenharmony_ci        }
99cb93a386Sopenharmony_ci        if (!success) {
100cb93a386Sopenharmony_ci            ThreadContext::ReportErrors(PositionInfo());
101cb93a386Sopenharmony_ci        }
102cb93a386Sopenharmony_ci        if (pool) {
103cb93a386Sopenharmony_ci            pool->detachFromThread();
104cb93a386Sopenharmony_ci        }
105cb93a386Sopenharmony_ci        SkASSERT(instance.fProgramElements.empty());
106cb93a386Sopenharmony_ci        SkASSERT(!ThreadContext::SymbolTable());
107cb93a386Sopenharmony_ci        return success ? std::move(result) : nullptr;
108cb93a386Sopenharmony_ci    }
109cb93a386Sopenharmony_ci
110cb93a386Sopenharmony_ci    static DSLGlobalVar sk_FragColor() {
111cb93a386Sopenharmony_ci        return DSLGlobalVar("sk_FragColor");
112cb93a386Sopenharmony_ci    }
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci    static DSLGlobalVar sk_FragCoord() {
115cb93a386Sopenharmony_ci        return DSLGlobalVar("sk_FragCoord");
116cb93a386Sopenharmony_ci    }
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci    static DSLExpression sk_Position() {
119cb93a386Sopenharmony_ci        return DSLExpression(Symbol("sk_Position"));
120cb93a386Sopenharmony_ci    }
121cb93a386Sopenharmony_ci
122cb93a386Sopenharmony_ci    template <typename... Args>
123cb93a386Sopenharmony_ci    static DSLPossibleExpression Call(const char* name, Args... args) {
124cb93a386Sopenharmony_ci        SkSL::ExpressionArray argArray;
125cb93a386Sopenharmony_ci        argArray.reserve_back(sizeof...(args));
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ci        // in C++17, we could just do:
128cb93a386Sopenharmony_ci        // (argArray.push_back(args.release()), ...);
129cb93a386Sopenharmony_ci        int unused[] = {0, (static_cast<void>(argArray.push_back(args.release())), 0)...};
130cb93a386Sopenharmony_ci        static_cast<void>(unused);
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_ci        return SkSL::FunctionCall::Convert(ThreadContext::Context(), /*line=*/-1,
133cb93a386Sopenharmony_ci                ThreadContext::Compiler().convertIdentifier(-1, name), std::move(argArray));
134cb93a386Sopenharmony_ci    }
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_ci    static DSLStatement Break(PositionInfo pos) {
137cb93a386Sopenharmony_ci        return SkSL::BreakStatement::Make(pos.line());
138cb93a386Sopenharmony_ci    }
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci    static DSLStatement Continue(PositionInfo pos) {
141cb93a386Sopenharmony_ci        return SkSL::ContinueStatement::Make(pos.line());
142cb93a386Sopenharmony_ci    }
143cb93a386Sopenharmony_ci
144cb93a386Sopenharmony_ci    static void Declare(const DSLModifiers& modifiers) {
145cb93a386Sopenharmony_ci        ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::ModifiersDeclaration>(
146cb93a386Sopenharmony_ci                ThreadContext::Modifiers(modifiers.fModifiers)));
147cb93a386Sopenharmony_ci    }
148cb93a386Sopenharmony_ci
149cb93a386Sopenharmony_ci    static DSLStatement Declare(DSLVar& var, PositionInfo pos) {
150cb93a386Sopenharmony_ci        if (var.fDeclared) {
151cb93a386Sopenharmony_ci            ThreadContext::ReportError("variable has already been declared", pos);
152cb93a386Sopenharmony_ci        }
153cb93a386Sopenharmony_ci        var.fDeclared = true;
154cb93a386Sopenharmony_ci        return DSLWriter::Declaration(var);
155cb93a386Sopenharmony_ci    }
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_ci    static DSLStatement Declare(SkTArray<DSLVar>& vars, PositionInfo pos) {
158cb93a386Sopenharmony_ci        StatementArray statements;
159cb93a386Sopenharmony_ci        for (DSLVar& v : vars) {
160cb93a386Sopenharmony_ci            statements.push_back(Declare(v, pos).release());
161cb93a386Sopenharmony_ci        }
162cb93a386Sopenharmony_ci        return SkSL::Block::MakeUnscoped(pos.line(), std::move(statements));
163cb93a386Sopenharmony_ci    }
164cb93a386Sopenharmony_ci
165cb93a386Sopenharmony_ci    static void Declare(DSLGlobalVar& var, PositionInfo pos) {
166cb93a386Sopenharmony_ci        if (var.fDeclared) {
167cb93a386Sopenharmony_ci            ThreadContext::ReportError("variable has already been declared", pos);
168cb93a386Sopenharmony_ci        }
169cb93a386Sopenharmony_ci        var.fDeclared = true;
170cb93a386Sopenharmony_ci        std::unique_ptr<SkSL::Statement> stmt = DSLWriter::Declaration(var);
171cb93a386Sopenharmony_ci        if (stmt) {
172cb93a386Sopenharmony_ci            if (!stmt->isEmpty()) {
173cb93a386Sopenharmony_ci                ThreadContext::ProgramElements().push_back(
174cb93a386Sopenharmony_ci                        std::make_unique<SkSL::GlobalVarDeclaration>(std::move(stmt)));
175cb93a386Sopenharmony_ci            }
176cb93a386Sopenharmony_ci        } else if (var.fName == SkSL::Compiler::FRAGCOLOR_NAME) {
177cb93a386Sopenharmony_ci            // sk_FragColor can end up with a null declaration despite no error occurring due to
178cb93a386Sopenharmony_ci            // specific treatment in the compiler. Ignore the null and just grab the existing
179cb93a386Sopenharmony_ci            // variable from the symbol table.
180cb93a386Sopenharmony_ci            const SkSL::Symbol* alreadyDeclared = (*ThreadContext::SymbolTable())[var.fName];
181cb93a386Sopenharmony_ci            if (alreadyDeclared && alreadyDeclared->is<Variable>()) {
182cb93a386Sopenharmony_ci                var.fVar = &alreadyDeclared->as<Variable>();
183cb93a386Sopenharmony_ci                var.fInitialized = true;
184cb93a386Sopenharmony_ci            }
185cb93a386Sopenharmony_ci        }
186cb93a386Sopenharmony_ci    }
187cb93a386Sopenharmony_ci
188cb93a386Sopenharmony_ci    static void Declare(SkTArray<DSLGlobalVar>& vars, PositionInfo pos) {
189cb93a386Sopenharmony_ci        for (DSLGlobalVar& v : vars) {
190cb93a386Sopenharmony_ci            Declare(v, pos);
191cb93a386Sopenharmony_ci        }
192cb93a386Sopenharmony_ci    }
193cb93a386Sopenharmony_ci
194cb93a386Sopenharmony_ci    static DSLStatement Discard(PositionInfo pos) {
195cb93a386Sopenharmony_ci        return SkSL::DiscardStatement::Make(pos.line());
196cb93a386Sopenharmony_ci    }
197cb93a386Sopenharmony_ci
198cb93a386Sopenharmony_ci    static DSLPossibleStatement Do(DSLStatement stmt, DSLExpression test) {
199cb93a386Sopenharmony_ci        return DoStatement::Convert(ThreadContext::Context(), stmt.release(), test.release());
200cb93a386Sopenharmony_ci    }
201cb93a386Sopenharmony_ci
202cb93a386Sopenharmony_ci    static DSLPossibleStatement For(DSLStatement initializer, DSLExpression test,
203cb93a386Sopenharmony_ci                                    DSLExpression next, DSLStatement stmt, PositionInfo pos) {
204cb93a386Sopenharmony_ci        return ForStatement::Convert(ThreadContext::Context(), pos.line(),
205cb93a386Sopenharmony_ci                                     initializer.releaseIfPossible(), test.releaseIfPossible(),
206cb93a386Sopenharmony_ci                                     next.releaseIfPossible(), stmt.release(),
207cb93a386Sopenharmony_ci                                     ThreadContext::SymbolTable());
208cb93a386Sopenharmony_ci    }
209cb93a386Sopenharmony_ci
210cb93a386Sopenharmony_ci    static DSLPossibleStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse,
211cb93a386Sopenharmony_ci                                   bool isStatic) {
212cb93a386Sopenharmony_ci        return IfStatement::Convert(ThreadContext::Context(), /*line=*/-1, isStatic, test.release(),
213cb93a386Sopenharmony_ci                                    ifTrue.release(), ifFalse.releaseIfPossible());
214cb93a386Sopenharmony_ci    }
215cb93a386Sopenharmony_ci
216cb93a386Sopenharmony_ci    static void FindRTAdjust(SkSL::InterfaceBlock& intf, PositionInfo pos) {
217cb93a386Sopenharmony_ci        const std::vector<SkSL::Type::Field>& fields =
218cb93a386Sopenharmony_ci                intf.variable().type().componentType().fields();
219cb93a386Sopenharmony_ci        const Context& context = ThreadContext::Context();
220cb93a386Sopenharmony_ci        for (size_t i = 0; i < fields.size(); ++i) {
221cb93a386Sopenharmony_ci            const SkSL::Type::Field& f = fields[i];
222cb93a386Sopenharmony_ci            if (f.fName == SkSL::Compiler::RTADJUST_NAME) {
223cb93a386Sopenharmony_ci                if (*f.fType == *context.fTypes.fFloat4) {
224cb93a386Sopenharmony_ci                    ThreadContext::RTAdjustData& rtAdjust = ThreadContext::RTAdjustState();
225cb93a386Sopenharmony_ci                    rtAdjust.fInterfaceBlock = &intf.variable();
226cb93a386Sopenharmony_ci                    rtAdjust.fFieldIndex = i;
227cb93a386Sopenharmony_ci                } else {
228cb93a386Sopenharmony_ci                    ThreadContext::ReportError("sk_RTAdjust must have type 'float4'", pos);
229cb93a386Sopenharmony_ci                }
230cb93a386Sopenharmony_ci                break;
231cb93a386Sopenharmony_ci            }
232cb93a386Sopenharmony_ci        }
233cb93a386Sopenharmony_ci    }
234cb93a386Sopenharmony_ci
235cb93a386Sopenharmony_ci    static DSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers, skstd::string_view typeName,
236cb93a386Sopenharmony_ci                                       SkTArray<DSLField> fields, skstd::string_view varName,
237cb93a386Sopenharmony_ci                                       int arraySize, PositionInfo pos) {
238cb93a386Sopenharmony_ci        // We need to create a new struct type for the interface block, but we don't want it in the
239cb93a386Sopenharmony_ci        // symbol table. Since dsl::Struct automatically sticks it in the symbol table, we create it
240cb93a386Sopenharmony_ci        // the old fashioned way with MakeStructType.
241cb93a386Sopenharmony_ci        std::vector<SkSL::Type::Field> skslFields;
242cb93a386Sopenharmony_ci        skslFields.reserve(fields.count());
243cb93a386Sopenharmony_ci        for (const DSLField& field : fields) {
244cb93a386Sopenharmony_ci            const SkSL::Type* baseType = &field.fType.skslType();
245cb93a386Sopenharmony_ci            if (baseType->isArray()) {
246cb93a386Sopenharmony_ci                baseType = &baseType->componentType();
247cb93a386Sopenharmony_ci            }
248cb93a386Sopenharmony_ci            SkSL::VarDeclaration::ErrorCheck(ThreadContext::Context(), pos.line(),
249cb93a386Sopenharmony_ci                    field.fModifiers.fModifiers, baseType, Variable::Storage::kInterfaceBlock);
250cb93a386Sopenharmony_ci            GetErrorReporter().reportPendingErrors(field.fPosition);
251cb93a386Sopenharmony_ci            skslFields.push_back(SkSL::Type::Field(field.fModifiers.fModifiers, field.fName,
252cb93a386Sopenharmony_ci                                                   &field.fType.skslType()));
253cb93a386Sopenharmony_ci        }
254cb93a386Sopenharmony_ci        const SkSL::Type* structType = ThreadContext::SymbolTable()->takeOwnershipOfSymbol(
255cb93a386Sopenharmony_ci                SkSL::Type::MakeStructType(pos.line(), typeName, std::move(skslFields)));
256cb93a386Sopenharmony_ci        DSLType varType = arraySize > 0 ? Array(structType, arraySize) : DSLType(structType);
257cb93a386Sopenharmony_ci        DSLGlobalVar var(modifiers, varType, !varName.empty() ? varName : typeName, DSLExpression(),
258cb93a386Sopenharmony_ci                pos);
259cb93a386Sopenharmony_ci        // Interface blocks can't be declared, so we always need to mark the var declared ourselves.
260cb93a386Sopenharmony_ci        // We do this only when fDSLMarkVarDeclared is false, so we don't double-declare it.
261cb93a386Sopenharmony_ci        if (!ThreadContext::Settings().fDSLMarkVarsDeclared) {
262cb93a386Sopenharmony_ci            DSLWriter::MarkDeclared(var);
263cb93a386Sopenharmony_ci        }
264cb93a386Sopenharmony_ci        const SkSL::Variable* skslVar = DSLWriter::Var(var);
265cb93a386Sopenharmony_ci        if (skslVar) {
266cb93a386Sopenharmony_ci            auto intf = std::make_unique<SkSL::InterfaceBlock>(pos.line(),
267cb93a386Sopenharmony_ci                    *skslVar, typeName, varName, arraySize, ThreadContext::SymbolTable());
268cb93a386Sopenharmony_ci            FindRTAdjust(*intf, pos);
269cb93a386Sopenharmony_ci            ThreadContext::ProgramElements().push_back(std::move(intf));
270cb93a386Sopenharmony_ci            if (varName.empty()) {
271cb93a386Sopenharmony_ci                const std::vector<SkSL::Type::Field>& structFields = structType->fields();
272cb93a386Sopenharmony_ci                for (size_t i = 0; i < structFields.size(); ++i) {
273cb93a386Sopenharmony_ci                    ThreadContext::SymbolTable()->add(std::make_unique<SkSL::Field>(pos.line(),
274cb93a386Sopenharmony_ci                                                                                    skslVar,
275cb93a386Sopenharmony_ci                                                                                    i));
276cb93a386Sopenharmony_ci                }
277cb93a386Sopenharmony_ci            } else {
278cb93a386Sopenharmony_ci                AddToSymbolTable(var);
279cb93a386Sopenharmony_ci            }
280cb93a386Sopenharmony_ci        }
281cb93a386Sopenharmony_ci        GetErrorReporter().reportPendingErrors(pos);
282cb93a386Sopenharmony_ci        return var;
283cb93a386Sopenharmony_ci    }
284cb93a386Sopenharmony_ci
285cb93a386Sopenharmony_ci    static DSLStatement Return(DSLExpression value, PositionInfo pos) {
286cb93a386Sopenharmony_ci        // Note that because Return is called before the function in which it resides exists, at
287cb93a386Sopenharmony_ci        // this point we do not know the function's return type. We therefore do not check for
288cb93a386Sopenharmony_ci        // errors, or coerce the value to the correct type, until the return statement is actually
289cb93a386Sopenharmony_ci        // added to a function. (This is done in FunctionDefinition::Convert.)
290cb93a386Sopenharmony_ci        return SkSL::ReturnStatement::Make(pos.line(), value.releaseIfPossible());
291cb93a386Sopenharmony_ci    }
292cb93a386Sopenharmony_ci
293cb93a386Sopenharmony_ci    static DSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a,
294cb93a386Sopenharmony_ci                                 PositionInfo pos) {
295cb93a386Sopenharmony_ci        return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
296cb93a386Sopenharmony_ci                                              ComponentArray{a}),
297cb93a386Sopenharmony_ci                             pos);
298cb93a386Sopenharmony_ci    }
299cb93a386Sopenharmony_ci
300cb93a386Sopenharmony_ci    static DSLExpression Swizzle(DSLExpression base,
301cb93a386Sopenharmony_ci                                 SkSL::SwizzleComponent::Type a,
302cb93a386Sopenharmony_ci                                 SkSL::SwizzleComponent::Type b,
303cb93a386Sopenharmony_ci                                 PositionInfo pos) {
304cb93a386Sopenharmony_ci        return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
305cb93a386Sopenharmony_ci                                              ComponentArray{a, b}),
306cb93a386Sopenharmony_ci                             pos);
307cb93a386Sopenharmony_ci    }
308cb93a386Sopenharmony_ci
309cb93a386Sopenharmony_ci    static DSLExpression Swizzle(DSLExpression base,
310cb93a386Sopenharmony_ci                                 SkSL::SwizzleComponent::Type a,
311cb93a386Sopenharmony_ci                                 SkSL::SwizzleComponent::Type b,
312cb93a386Sopenharmony_ci                                 SkSL::SwizzleComponent::Type c,
313cb93a386Sopenharmony_ci                                 PositionInfo pos) {
314cb93a386Sopenharmony_ci        return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
315cb93a386Sopenharmony_ci                                              ComponentArray{a, b, c}),
316cb93a386Sopenharmony_ci                             pos);
317cb93a386Sopenharmony_ci    }
318cb93a386Sopenharmony_ci
319cb93a386Sopenharmony_ci    static DSLExpression Swizzle(DSLExpression base,
320cb93a386Sopenharmony_ci                                 SkSL::SwizzleComponent::Type a,
321cb93a386Sopenharmony_ci                                 SkSL::SwizzleComponent::Type b,
322cb93a386Sopenharmony_ci                                 SkSL::SwizzleComponent::Type c,
323cb93a386Sopenharmony_ci                                 SkSL::SwizzleComponent::Type d,
324cb93a386Sopenharmony_ci                                 PositionInfo pos) {
325cb93a386Sopenharmony_ci        return DSLExpression(Swizzle::Convert(ThreadContext::Context(), base.release(),
326cb93a386Sopenharmony_ci                                              ComponentArray{a,b,c,d}),
327cb93a386Sopenharmony_ci                             pos);
328cb93a386Sopenharmony_ci    }
329cb93a386Sopenharmony_ci
330cb93a386Sopenharmony_ci    static DSLPossibleExpression Select(DSLExpression test, DSLExpression ifTrue,
331cb93a386Sopenharmony_ci                                        DSLExpression ifFalse) {
332cb93a386Sopenharmony_ci        return TernaryExpression::Convert(ThreadContext::Context(), test.release(),
333cb93a386Sopenharmony_ci                                          ifTrue.release(), ifFalse.release());
334cb93a386Sopenharmony_ci    }
335cb93a386Sopenharmony_ci
336cb93a386Sopenharmony_ci    static DSLPossibleStatement Switch(DSLExpression value, SkTArray<DSLCase> cases,
337cb93a386Sopenharmony_ci                                       bool isStatic) {
338cb93a386Sopenharmony_ci        ExpressionArray values;
339cb93a386Sopenharmony_ci        values.reserve_back(cases.count());
340cb93a386Sopenharmony_ci        StatementArray caseBlocks;
341cb93a386Sopenharmony_ci        caseBlocks.reserve_back(cases.count());
342cb93a386Sopenharmony_ci        for (DSLCase& c : cases) {
343cb93a386Sopenharmony_ci            values.push_back(c.fValue.releaseIfPossible());
344cb93a386Sopenharmony_ci            caseBlocks.push_back(SkSL::Block::Make(/*line=*/-1,
345cb93a386Sopenharmony_ci                    std::move(c.fStatements), /*symbols=*/nullptr, /*isScope=*/false));
346cb93a386Sopenharmony_ci        }
347cb93a386Sopenharmony_ci        return SwitchStatement::Convert(ThreadContext::Context(), /*line=*/-1, isStatic,
348cb93a386Sopenharmony_ci                value.release(), std::move(values), std::move(caseBlocks),
349cb93a386Sopenharmony_ci                ThreadContext::SymbolTable());
350cb93a386Sopenharmony_ci    }
351cb93a386Sopenharmony_ci
352cb93a386Sopenharmony_ci    static DSLPossibleStatement While(DSLExpression test, DSLStatement stmt) {
353cb93a386Sopenharmony_ci        return ForStatement::ConvertWhile(ThreadContext::Context(), /*line=*/-1, test.release(),
354cb93a386Sopenharmony_ci                                          stmt.release(), ThreadContext::SymbolTable());
355cb93a386Sopenharmony_ci    }
356cb93a386Sopenharmony_ci};
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_cistd::unique_ptr<SkSL::Program> ReleaseProgram(std::unique_ptr<String> source) {
359cb93a386Sopenharmony_ci    return DSLCore::ReleaseProgram(std::move(source));
360cb93a386Sopenharmony_ci}
361cb93a386Sopenharmony_ci
362cb93a386Sopenharmony_ciDSLGlobalVar sk_FragColor() {
363cb93a386Sopenharmony_ci    return DSLCore::sk_FragColor();
364cb93a386Sopenharmony_ci}
365cb93a386Sopenharmony_ci
366cb93a386Sopenharmony_ciDSLGlobalVar sk_FragCoord() {
367cb93a386Sopenharmony_ci    return DSLCore::sk_FragCoord();
368cb93a386Sopenharmony_ci}
369cb93a386Sopenharmony_ci
370cb93a386Sopenharmony_ciDSLExpression sk_Position() {
371cb93a386Sopenharmony_ci    return DSLCore::sk_Position();
372cb93a386Sopenharmony_ci}
373cb93a386Sopenharmony_ci
374cb93a386Sopenharmony_civoid AddExtension(skstd::string_view name, PositionInfo pos) {
375cb93a386Sopenharmony_ci    ThreadContext::ProgramElements().push_back(std::make_unique<SkSL::Extension>(pos.line(), name));
376cb93a386Sopenharmony_ci    ThreadContext::ReportErrors(pos);
377cb93a386Sopenharmony_ci}
378cb93a386Sopenharmony_ci
379cb93a386Sopenharmony_ciDSLStatement Break(PositionInfo pos) {
380cb93a386Sopenharmony_ci    return DSLCore::Break(pos);
381cb93a386Sopenharmony_ci}
382cb93a386Sopenharmony_ci
383cb93a386Sopenharmony_ciDSLStatement Continue(PositionInfo pos) {
384cb93a386Sopenharmony_ci    return DSLCore::Continue(pos);
385cb93a386Sopenharmony_ci}
386cb93a386Sopenharmony_ci
387cb93a386Sopenharmony_civoid Declare(const DSLModifiers& modifiers, PositionInfo pos) {
388cb93a386Sopenharmony_ci    SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind;
389cb93a386Sopenharmony_ci    if (kind != ProgramKind::kFragment &&
390cb93a386Sopenharmony_ci        kind != ProgramKind::kVertex) {
391cb93a386Sopenharmony_ci        ThreadContext::ReportError("layout qualifiers are not allowed in this kind of program",
392cb93a386Sopenharmony_ci                pos);
393cb93a386Sopenharmony_ci        return;
394cb93a386Sopenharmony_ci    }
395cb93a386Sopenharmony_ci    DSLCore::Declare(modifiers);
396cb93a386Sopenharmony_ci}
397cb93a386Sopenharmony_ci
398cb93a386Sopenharmony_ci// Logically, we'd want the variable's initial value to appear on here in Declare, since that
399cb93a386Sopenharmony_ci// matches how we actually write code (and in fact that was what our first attempt looked like).
400cb93a386Sopenharmony_ci// Unfortunately, C++ doesn't guarantee execution order between arguments, and Declare() can appear
401cb93a386Sopenharmony_ci// as a function argument in constructs like Block(Declare(x, 0), foo(x)). If these are executed out
402cb93a386Sopenharmony_ci// of order, we will evaluate the reference to x before we evaluate Declare(x, 0), and thus the
403cb93a386Sopenharmony_ci// variable's initial value is unknown at the point of reference. There are probably some other
404cb93a386Sopenharmony_ci// issues with this as well, but it is particularly dangerous when x is const, since SkSL will
405cb93a386Sopenharmony_ci// expect its value to be known when it is referenced and will end up asserting, dereferencing a
406cb93a386Sopenharmony_ci// null pointer, or possibly doing something else awful.
407cb93a386Sopenharmony_ci//
408cb93a386Sopenharmony_ci// So, we put the initial value onto the Var itself instead of the Declare to guarantee that it is
409cb93a386Sopenharmony_ci// always executed in the correct order.
410cb93a386Sopenharmony_ciDSLStatement Declare(DSLVar& var, PositionInfo pos) {
411cb93a386Sopenharmony_ci    return DSLCore::Declare(var, pos);
412cb93a386Sopenharmony_ci}
413cb93a386Sopenharmony_ci
414cb93a386Sopenharmony_ciDSLStatement Declare(SkTArray<DSLVar>& vars, PositionInfo pos) {
415cb93a386Sopenharmony_ci    return DSLCore::Declare(vars, pos);
416cb93a386Sopenharmony_ci}
417cb93a386Sopenharmony_ci
418cb93a386Sopenharmony_civoid Declare(DSLGlobalVar& var, PositionInfo pos) {
419cb93a386Sopenharmony_ci    DSLCore::Declare(var, pos);
420cb93a386Sopenharmony_ci}
421cb93a386Sopenharmony_ci
422cb93a386Sopenharmony_civoid Declare(SkTArray<DSLGlobalVar>& vars, PositionInfo pos) {
423cb93a386Sopenharmony_ci    DSLCore::Declare(vars, pos);
424cb93a386Sopenharmony_ci}
425cb93a386Sopenharmony_ci
426cb93a386Sopenharmony_ciDSLStatement Discard(PositionInfo pos) {
427cb93a386Sopenharmony_ci    if (ThreadContext::GetProgramConfig()->fKind != ProgramKind::kFragment) {
428cb93a386Sopenharmony_ci        ThreadContext::ReportError("discard statement is only permitted in fragment shaders", pos);
429cb93a386Sopenharmony_ci    }
430cb93a386Sopenharmony_ci    return DSLCore::Discard(pos);
431cb93a386Sopenharmony_ci}
432cb93a386Sopenharmony_ci
433cb93a386Sopenharmony_ciDSLStatement Do(DSLStatement stmt, DSLExpression test, PositionInfo pos) {
434cb93a386Sopenharmony_ci    return DSLStatement(DSLCore::Do(std::move(stmt), std::move(test)), pos);
435cb93a386Sopenharmony_ci}
436cb93a386Sopenharmony_ci
437cb93a386Sopenharmony_ciDSLStatement For(DSLStatement initializer, DSLExpression test, DSLExpression next,
438cb93a386Sopenharmony_ci                 DSLStatement stmt, PositionInfo pos) {
439cb93a386Sopenharmony_ci    return DSLStatement(DSLCore::For(std::move(initializer), std::move(test), std::move(next),
440cb93a386Sopenharmony_ci                                     std::move(stmt), pos), pos);
441cb93a386Sopenharmony_ci}
442cb93a386Sopenharmony_ci
443cb93a386Sopenharmony_ciDSLStatement If(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse, PositionInfo pos) {
444cb93a386Sopenharmony_ci    return DSLStatement(DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse),
445cb93a386Sopenharmony_ci                                    /*isStatic=*/false),
446cb93a386Sopenharmony_ci                        pos);
447cb93a386Sopenharmony_ci}
448cb93a386Sopenharmony_ci
449cb93a386Sopenharmony_ciDSLGlobalVar InterfaceBlock(const DSLModifiers& modifiers,  skstd::string_view typeName,
450cb93a386Sopenharmony_ci                            SkTArray<DSLField> fields, skstd::string_view varName, int arraySize,
451cb93a386Sopenharmony_ci                            PositionInfo pos) {
452cb93a386Sopenharmony_ci    SkSL::ProgramKind kind = ThreadContext::GetProgramConfig()->fKind;
453cb93a386Sopenharmony_ci    if (kind != ProgramKind::kFragment &&
454cb93a386Sopenharmony_ci        kind != ProgramKind::kVertex) {
455cb93a386Sopenharmony_ci        ThreadContext::ReportError("interface blocks are not allowed in this kind of program", pos);
456cb93a386Sopenharmony_ci        return DSLGlobalVar();
457cb93a386Sopenharmony_ci    }
458cb93a386Sopenharmony_ci    return DSLCore::InterfaceBlock(modifiers, typeName, std::move(fields), varName, arraySize, pos);
459cb93a386Sopenharmony_ci}
460cb93a386Sopenharmony_ci
461cb93a386Sopenharmony_ciDSLStatement Return(DSLExpression expr, PositionInfo pos) {
462cb93a386Sopenharmony_ci    return DSLCore::Return(std::move(expr), pos);
463cb93a386Sopenharmony_ci}
464cb93a386Sopenharmony_ci
465cb93a386Sopenharmony_ciDSLExpression Select(DSLExpression test, DSLExpression ifTrue, DSLExpression ifFalse,
466cb93a386Sopenharmony_ci                     PositionInfo pos) {
467cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Select(std::move(test), std::move(ifTrue), std::move(ifFalse)),
468cb93a386Sopenharmony_ci                         pos);
469cb93a386Sopenharmony_ci}
470cb93a386Sopenharmony_ci
471cb93a386Sopenharmony_ciDSLStatement StaticIf(DSLExpression test, DSLStatement ifTrue, DSLStatement ifFalse,
472cb93a386Sopenharmony_ci                      PositionInfo pos) {
473cb93a386Sopenharmony_ci    return DSLStatement(DSLCore::If(std::move(test), std::move(ifTrue), std::move(ifFalse),
474cb93a386Sopenharmony_ci                                    /*isStatic=*/true),
475cb93a386Sopenharmony_ci                         pos);
476cb93a386Sopenharmony_ci}
477cb93a386Sopenharmony_ci
478cb93a386Sopenharmony_ciDSLPossibleStatement PossibleStaticSwitch(DSLExpression value, SkTArray<DSLCase> cases) {
479cb93a386Sopenharmony_ci    return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/true);
480cb93a386Sopenharmony_ci}
481cb93a386Sopenharmony_ci
482cb93a386Sopenharmony_ciDSLStatement StaticSwitch(DSLExpression value, SkTArray<DSLCase> cases, PositionInfo pos) {
483cb93a386Sopenharmony_ci    return DSLStatement(PossibleStaticSwitch(std::move(value), std::move(cases)), pos);
484cb93a386Sopenharmony_ci}
485cb93a386Sopenharmony_ci
486cb93a386Sopenharmony_ciDSLPossibleStatement PossibleSwitch(DSLExpression value, SkTArray<DSLCase> cases) {
487cb93a386Sopenharmony_ci    return DSLCore::Switch(std::move(value), std::move(cases), /*isStatic=*/false);
488cb93a386Sopenharmony_ci}
489cb93a386Sopenharmony_ci
490cb93a386Sopenharmony_ciDSLStatement Switch(DSLExpression value, SkTArray<DSLCase> cases, PositionInfo pos) {
491cb93a386Sopenharmony_ci    return DSLStatement(PossibleSwitch(std::move(value), std::move(cases)), pos);
492cb93a386Sopenharmony_ci}
493cb93a386Sopenharmony_ci
494cb93a386Sopenharmony_ciDSLStatement While(DSLExpression test, DSLStatement stmt, PositionInfo pos) {
495cb93a386Sopenharmony_ci    return DSLStatement(DSLCore::While(std::move(test), std::move(stmt)), pos);
496cb93a386Sopenharmony_ci}
497cb93a386Sopenharmony_ci
498cb93a386Sopenharmony_ciDSLExpression Abs(DSLExpression x, PositionInfo pos) {
499cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("abs", std::move(x)), pos);
500cb93a386Sopenharmony_ci}
501cb93a386Sopenharmony_ci
502cb93a386Sopenharmony_ciDSLExpression All(DSLExpression x, PositionInfo pos) {
503cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("all", std::move(x)), pos);
504cb93a386Sopenharmony_ci}
505cb93a386Sopenharmony_ci
506cb93a386Sopenharmony_ciDSLExpression Any(DSLExpression x, PositionInfo pos) {
507cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("any", std::move(x)), pos);
508cb93a386Sopenharmony_ci}
509cb93a386Sopenharmony_ci
510cb93a386Sopenharmony_ciDSLExpression Atan(DSLExpression y_over_x, PositionInfo pos) {
511cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("atan", std::move(y_over_x)), pos);
512cb93a386Sopenharmony_ci}
513cb93a386Sopenharmony_ci
514cb93a386Sopenharmony_ciDSLExpression Atan(DSLExpression y, DSLExpression x, PositionInfo pos) {
515cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("atan", std::move(y), std::move(x)), pos);
516cb93a386Sopenharmony_ci}
517cb93a386Sopenharmony_ci
518cb93a386Sopenharmony_ciDSLExpression Ceil(DSLExpression x, PositionInfo pos) {
519cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("ceil", std::move(x)), pos);
520cb93a386Sopenharmony_ci}
521cb93a386Sopenharmony_ci
522cb93a386Sopenharmony_ciDSLExpression Clamp(DSLExpression x, DSLExpression min, DSLExpression max, PositionInfo pos) {
523cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("clamp", std::move(x), std::move(min), std::move(max)), pos);
524cb93a386Sopenharmony_ci}
525cb93a386Sopenharmony_ci
526cb93a386Sopenharmony_ciDSLExpression Cos(DSLExpression x, PositionInfo pos) {
527cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("cos", std::move(x)), pos);
528cb93a386Sopenharmony_ci}
529cb93a386Sopenharmony_ci
530cb93a386Sopenharmony_ciDSLExpression Cross(DSLExpression x, DSLExpression y, PositionInfo pos) {
531cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("cross", std::move(x), std::move(y)), pos);
532cb93a386Sopenharmony_ci}
533cb93a386Sopenharmony_ci
534cb93a386Sopenharmony_ciDSLExpression Degrees(DSLExpression x, PositionInfo pos) {
535cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("degrees", std::move(x)), pos);
536cb93a386Sopenharmony_ci}
537cb93a386Sopenharmony_ci
538cb93a386Sopenharmony_ciDSLExpression Distance(DSLExpression x, DSLExpression y, PositionInfo pos) {
539cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("distance", std::move(x), std::move(y)), pos);
540cb93a386Sopenharmony_ci}
541cb93a386Sopenharmony_ci
542cb93a386Sopenharmony_ciDSLExpression Dot(DSLExpression x, DSLExpression y, PositionInfo pos) {
543cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("dot", std::move(x), std::move(y)), pos);
544cb93a386Sopenharmony_ci}
545cb93a386Sopenharmony_ci
546cb93a386Sopenharmony_ciDSLExpression Equal(DSLExpression x, DSLExpression y, PositionInfo pos) {
547cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("equal", std::move(x), std::move(y)), pos);
548cb93a386Sopenharmony_ci}
549cb93a386Sopenharmony_ci
550cb93a386Sopenharmony_ciDSLExpression Exp(DSLExpression x, PositionInfo pos) {
551cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("exp", std::move(x)), pos);
552cb93a386Sopenharmony_ci}
553cb93a386Sopenharmony_ci
554cb93a386Sopenharmony_ciDSLExpression Exp2(DSLExpression x, PositionInfo pos) {
555cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("exp2", std::move(x)), pos);
556cb93a386Sopenharmony_ci}
557cb93a386Sopenharmony_ci
558cb93a386Sopenharmony_ciDSLExpression Faceforward(DSLExpression n, DSLExpression i, DSLExpression nref, PositionInfo pos) {
559cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("faceforward", std::move(n), std::move(i), std::move(nref)),
560cb93a386Sopenharmony_ci                         pos);
561cb93a386Sopenharmony_ci}
562cb93a386Sopenharmony_ci
563cb93a386Sopenharmony_ciDSLExpression Fract(DSLExpression x, PositionInfo pos) {
564cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("fract", std::move(x)), pos);
565cb93a386Sopenharmony_ci}
566cb93a386Sopenharmony_ci
567cb93a386Sopenharmony_ciDSLExpression Floor(DSLExpression x, PositionInfo pos) {
568cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("floor", std::move(x)), pos);
569cb93a386Sopenharmony_ci}
570cb93a386Sopenharmony_ci
571cb93a386Sopenharmony_ciDSLExpression GreaterThan(DSLExpression x, DSLExpression y, PositionInfo pos) {
572cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("greaterThan", std::move(x), std::move(y)), pos);
573cb93a386Sopenharmony_ci}
574cb93a386Sopenharmony_ci
575cb93a386Sopenharmony_ciDSLExpression GreaterThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
576cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("greaterThanEqual", std::move(x), std::move(y)), pos);
577cb93a386Sopenharmony_ci}
578cb93a386Sopenharmony_ci
579cb93a386Sopenharmony_ciDSLExpression Inverse(DSLExpression x, PositionInfo pos) {
580cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("inverse", std::move(x)), pos);
581cb93a386Sopenharmony_ci}
582cb93a386Sopenharmony_ci
583cb93a386Sopenharmony_ciDSLExpression Inversesqrt(DSLExpression x, PositionInfo pos) {
584cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("inversesqrt", std::move(x)), pos);
585cb93a386Sopenharmony_ci}
586cb93a386Sopenharmony_ci
587cb93a386Sopenharmony_ciDSLExpression Length(DSLExpression x, PositionInfo pos) {
588cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("length", std::move(x)), pos);
589cb93a386Sopenharmony_ci}
590cb93a386Sopenharmony_ci
591cb93a386Sopenharmony_ciDSLExpression LessThan(DSLExpression x, DSLExpression y, PositionInfo pos) {
592cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("lessThan", std::move(x), std::move(y)), pos);
593cb93a386Sopenharmony_ci}
594cb93a386Sopenharmony_ci
595cb93a386Sopenharmony_ciDSLExpression LessThanEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
596cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("lessThanEqual", std::move(x), std::move(y)), pos);
597cb93a386Sopenharmony_ci}
598cb93a386Sopenharmony_ci
599cb93a386Sopenharmony_ciDSLExpression Log(DSLExpression x, PositionInfo pos) {
600cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("log", std::move(x)), pos);
601cb93a386Sopenharmony_ci}
602cb93a386Sopenharmony_ci
603cb93a386Sopenharmony_ciDSLExpression Log2(DSLExpression x, PositionInfo pos) {
604cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("log2", std::move(x)), pos);
605cb93a386Sopenharmony_ci}
606cb93a386Sopenharmony_ci
607cb93a386Sopenharmony_ciDSLExpression Max(DSLExpression x, DSLExpression y, PositionInfo pos) {
608cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("max", std::move(x), std::move(y)), pos);
609cb93a386Sopenharmony_ci}
610cb93a386Sopenharmony_ci
611cb93a386Sopenharmony_ciDSLExpression Min(DSLExpression x, DSLExpression y, PositionInfo pos) {
612cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("min", std::move(x), std::move(y)), pos);
613cb93a386Sopenharmony_ci}
614cb93a386Sopenharmony_ci
615cb93a386Sopenharmony_ciDSLExpression Mix(DSLExpression x, DSLExpression y, DSLExpression a, PositionInfo pos) {
616cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("mix", std::move(x), std::move(y), std::move(a)), pos);
617cb93a386Sopenharmony_ci}
618cb93a386Sopenharmony_ci
619cb93a386Sopenharmony_ciDSLExpression Mod(DSLExpression x, DSLExpression y, PositionInfo pos) {
620cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("mod", std::move(x), std::move(y)), pos);
621cb93a386Sopenharmony_ci}
622cb93a386Sopenharmony_ci
623cb93a386Sopenharmony_ciDSLExpression Normalize(DSLExpression x, PositionInfo pos) {
624cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("normalize", std::move(x)), pos);
625cb93a386Sopenharmony_ci}
626cb93a386Sopenharmony_ci
627cb93a386Sopenharmony_ciDSLExpression NotEqual(DSLExpression x, DSLExpression y, PositionInfo pos) {
628cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("notEqual", std::move(x), std::move(y)), pos);
629cb93a386Sopenharmony_ci}
630cb93a386Sopenharmony_ci
631cb93a386Sopenharmony_ciDSLExpression Pow(DSLExpression x, DSLExpression y, PositionInfo pos) {
632cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("pow", std::move(x), std::move(y)), pos);
633cb93a386Sopenharmony_ci}
634cb93a386Sopenharmony_ci
635cb93a386Sopenharmony_ciDSLExpression Radians(DSLExpression x, PositionInfo pos) {
636cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("radians", std::move(x)), pos);
637cb93a386Sopenharmony_ci}
638cb93a386Sopenharmony_ci
639cb93a386Sopenharmony_ciDSLExpression Reflect(DSLExpression i, DSLExpression n, PositionInfo pos) {
640cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("reflect", std::move(i), std::move(n)), pos);
641cb93a386Sopenharmony_ci}
642cb93a386Sopenharmony_ci
643cb93a386Sopenharmony_ciDSLExpression Refract(DSLExpression i, DSLExpression n, DSLExpression eta, PositionInfo pos) {
644cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("refract", std::move(i), std::move(n), std::move(eta)), pos);
645cb93a386Sopenharmony_ci}
646cb93a386Sopenharmony_ci
647cb93a386Sopenharmony_ciDSLExpression Round(DSLExpression x, PositionInfo pos) {
648cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("round", std::move(x)), pos);
649cb93a386Sopenharmony_ci}
650cb93a386Sopenharmony_ci
651cb93a386Sopenharmony_ciDSLExpression Saturate(DSLExpression x, PositionInfo pos) {
652cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("saturate", std::move(x)), pos);
653cb93a386Sopenharmony_ci}
654cb93a386Sopenharmony_ci
655cb93a386Sopenharmony_ciDSLExpression Sign(DSLExpression x, PositionInfo pos) {
656cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("sign", std::move(x)), pos);
657cb93a386Sopenharmony_ci}
658cb93a386Sopenharmony_ci
659cb93a386Sopenharmony_ciDSLExpression Sin(DSLExpression x, PositionInfo pos) {
660cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("sin", std::move(x)), pos);
661cb93a386Sopenharmony_ci}
662cb93a386Sopenharmony_ci
663cb93a386Sopenharmony_ciDSLExpression Smoothstep(DSLExpression edge1, DSLExpression edge2, DSLExpression x,
664cb93a386Sopenharmony_ci                         PositionInfo pos) {
665cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("smoothstep", std::move(edge1), std::move(edge2),
666cb93a386Sopenharmony_ci                                       std::move(x)),
667cb93a386Sopenharmony_ci                         pos);
668cb93a386Sopenharmony_ci}
669cb93a386Sopenharmony_ci
670cb93a386Sopenharmony_ciDSLExpression Sqrt(DSLExpression x, PositionInfo pos) {
671cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("sqrt", std::move(x)), pos);
672cb93a386Sopenharmony_ci}
673cb93a386Sopenharmony_ci
674cb93a386Sopenharmony_ciDSLExpression Step(DSLExpression edge, DSLExpression x, PositionInfo pos) {
675cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("step", std::move(edge), std::move(x)), pos);
676cb93a386Sopenharmony_ci}
677cb93a386Sopenharmony_ci
678cb93a386Sopenharmony_ciDSLExpression Swizzle(DSLExpression base, SkSL::SwizzleComponent::Type a,
679cb93a386Sopenharmony_ci                      PositionInfo pos) {
680cb93a386Sopenharmony_ci    return DSLCore::Swizzle(std::move(base), a, pos);
681cb93a386Sopenharmony_ci}
682cb93a386Sopenharmony_ci
683cb93a386Sopenharmony_ciDSLExpression Swizzle(DSLExpression base,
684cb93a386Sopenharmony_ci                      SkSL::SwizzleComponent::Type a,
685cb93a386Sopenharmony_ci                      SkSL::SwizzleComponent::Type b,
686cb93a386Sopenharmony_ci                      PositionInfo pos) {
687cb93a386Sopenharmony_ci    return DSLCore::Swizzle(std::move(base), a, b, pos);
688cb93a386Sopenharmony_ci}
689cb93a386Sopenharmony_ci
690cb93a386Sopenharmony_ciDSLExpression Swizzle(DSLExpression base,
691cb93a386Sopenharmony_ci                      SkSL::SwizzleComponent::Type a,
692cb93a386Sopenharmony_ci                      SkSL::SwizzleComponent::Type b,
693cb93a386Sopenharmony_ci                      SkSL::SwizzleComponent::Type c,
694cb93a386Sopenharmony_ci                      PositionInfo pos) {
695cb93a386Sopenharmony_ci    return DSLCore::Swizzle(std::move(base), a, b, c, pos);
696cb93a386Sopenharmony_ci}
697cb93a386Sopenharmony_ci
698cb93a386Sopenharmony_ciDSLExpression Swizzle(DSLExpression base,
699cb93a386Sopenharmony_ci                      SkSL::SwizzleComponent::Type a,
700cb93a386Sopenharmony_ci                      SkSL::SwizzleComponent::Type b,
701cb93a386Sopenharmony_ci                      SkSL::SwizzleComponent::Type c,
702cb93a386Sopenharmony_ci                      SkSL::SwizzleComponent::Type d,
703cb93a386Sopenharmony_ci                      PositionInfo pos) {
704cb93a386Sopenharmony_ci    return DSLCore::Swizzle(std::move(base), a, b, c, d, pos);
705cb93a386Sopenharmony_ci}
706cb93a386Sopenharmony_ci
707cb93a386Sopenharmony_ciDSLExpression Tan(DSLExpression x, PositionInfo pos) {
708cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("tan", std::move(x)), pos);
709cb93a386Sopenharmony_ci}
710cb93a386Sopenharmony_ci
711cb93a386Sopenharmony_ciDSLExpression Unpremul(DSLExpression x, PositionInfo pos) {
712cb93a386Sopenharmony_ci    return DSLExpression(DSLCore::Call("unpremul", std::move(x)), pos);
713cb93a386Sopenharmony_ci}
714cb93a386Sopenharmony_ci
715cb93a386Sopenharmony_ci} // namespace dsl
716cb93a386Sopenharmony_ci
717cb93a386Sopenharmony_ci} // namespace SkSL
718