Major rearchitecture of SkSL parsing, focused on improving performance.
Bug: skia:
Change-Id: I83e3a094d26085fc4d586e5d2581e0d61c55634e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/145080
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp b/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
index c07fd73..b7fd93b 100644
--- a/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrAlphaThresholdFragmentProcessor.cpp
@@ -46,8 +46,8 @@
"half4 color = %s;\nhalf4 mask_color = texture(%s, %s).%s;\nif (mask_color.w < "
"0.5) {\n if (color.w > %s) {\n half scale = %s / color.w;\n "
"color.xyz *= scale;\n color.w = %s;\n }\n} else if (color.w < %s) {\n "
- " half scale = %s / max(0.001, color.w);\n color.xyz *= scale;\n color.w = "
- "%s;\n}\n%s = color;\n",
+ " half scale = %s / max(0.0010000000474974513, color.w);\n color.xyz *= "
+ "scale;\n color.w = %s;\n}\n%s = color;\n",
args.fInputColor,
fragBuilder->getProgramBuilder()->samplerVariable(args.fTexSamplers[0]).c_str(),
sk_TransformedCoords2D_0.c_str(),
diff --git a/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp b/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp
index c2b3ef3..f286f0e 100644
--- a/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrBlurredEdgeFragmentProcessor.cpp
@@ -28,7 +28,7 @@
(void)mode;
fragBuilder->codeAppendf(
"half factor = 1.0 - %s.w;\n@switch (%d) {\n case 0:\n factor = "
- "exp((-factor * factor) * 4.0) - 0.017999999999999999;\n break;\n case "
+ "exp((-factor * factor) * 4.0) - 0.017999999225139618;\n break;\n case "
"1:\n factor = smoothstep(1.0, 0.0, factor);\n break;\n}\n%s = "
"half4(factor);\n",
args.fInputColor, (int)_outer.mode, args.fOutputColor);
diff --git a/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp b/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
index d0f6b00..8afed91 100644
--- a/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrColorMatrixFragmentProcessor.cpp
@@ -38,7 +38,7 @@
vVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType, "v");
fragBuilder->codeAppendf(
"half4 inputColor = %s;\n@if (%s) {\n half nonZeroAlpha = max(inputColor.w, "
- "0.0001);\n inputColor = half4(inputColor.xyz / nonZeroAlpha, "
+ "9.9999997473787516e-05);\n inputColor = half4(inputColor.xyz / nonZeroAlpha, "
"nonZeroAlpha);\n}\n%s = %s * inputColor + %s;\n@if (%s) {\n %s = clamp(%s, "
"0.0, 1.0);\n} else {\n %s.w = clamp(%s.w, 0.0, 1.0);\n}\n@if (%s) {\n "
"%s.xyz *= %s.w;\n}\n",
diff --git a/src/gpu/effects/generated/GrEllipseEffect.cpp b/src/gpu/effects/generated/GrEllipseEffect.cpp
index 269e95f..b28f961 100644
--- a/src/gpu/effects/generated/GrEllipseEffect.cpp
+++ b/src/gpu/effects/generated/GrEllipseEffect.cpp
@@ -42,20 +42,21 @@
"%s;\nfloat2 d = sk_FragCoord.xy - %s.xy;\n@if (medPrecision) {\n d *= "
"%s.y;\n}\nfloat2 Z = d * %s.zw;\nfloat implicit = dot(Z, d) - 1.0;\nfloat "
"grad_dot = 4.0 * dot(Z, Z);\n@if (medPrecision) {\n grad_dot = max(grad_dot, "
- "6.1036000000000003e-05);\n} else {\n grad_dot = max(grad_dot, "
- "1.1755e-38);\n}\nfloat approx_dist = implicit * inversesqrt(grad_dot);\n@if "
- "(medPrecision) {\n approx_dist *= %s.x;\n}\nhalf alpha;\n@switch ",
+ "6.1036000261083245e-05);\n} else {\n grad_dot = max(grad_dot, "
+ "1.1754999560161448e-38);\n}\nfloat approx_dist = implicit * "
+ "inversesqrt(grad_dot);\n@if (medPrecision) {\n approx_dist *= %s.x;\n}\nhalf "
+ "alph",
prevRadii.fX, prevRadii.fY, (medPrecision ? "true" : "false"),
args.fUniformHandler->getUniformCStr(ellipseVar),
scaleVar.isValid() ? args.fUniformHandler->getUniformCStr(scaleVar) : "float2(0)",
args.fUniformHandler->getUniformCStr(ellipseVar),
scaleVar.isValid() ? args.fUniformHandler->getUniformCStr(scaleVar) : "float2(0)");
fragBuilder->codeAppendf(
- "(%d) {\n case 0:\n alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n "
- "break;\n case 1:\n alpha = clamp(0.5 - half(approx_dist), 0.0, 1.0);\n "
- " break;\n case 2:\n alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n "
- " break;\n case 3:\n alpha = clamp(0.5 + half(approx_dist), 0.0, 1.0);\n "
- " break;\n default:\n discard;\n}\n%s = %s * alpha;\n",
+ "a;\n@switch (%d) {\n case 0:\n alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n "
+ " break;\n case 1:\n alpha = clamp(0.5 - half(approx_dist), 0.0, "
+ "1.0);\n break;\n case 2:\n alpha = approx_dist > 0.0 ? 1.0 : "
+ "0.0;\n break;\n case 3:\n alpha = clamp(0.5 + half(approx_dist), "
+ "0.0, 1.0);\n break;\n default:\n discard;\n}\n%s = %s * alpha;\n",
(int)_outer.edgeType, args.fOutputColor, args.fInputColor);
}
diff --git a/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp b/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp
index 337173c..3c9f24d 100644
--- a/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp
+++ b/src/gpu/effects/generated/GrLumaColorFilterEffect.cpp
@@ -24,8 +24,8 @@
const GrLumaColorFilterEffect& _outer = args.fFp.cast<GrLumaColorFilterEffect>();
(void)_outer;
fragBuilder->codeAppendf(
- "\nhalf luma = clamp(dot(half3(0.21260000000000001, 0.71519999999999995, 0.0722), "
- "%s.xyz), 0.0, 1.0);\n%s = half4(0.0, 0.0, 0.0, luma);\n",
+ "\nhalf luma = clamp(dot(half3(0.2125999927520752, 0.71520000696182251, "
+ "0.072200000286102295), %s.xyz), 0.0, 1.0);\n%s = half4(0.0, 0.0, 0.0, luma);\n",
args.fInputColor, args.fOutputColor);
}
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index b1b61e8..6d67623 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3380,7 +3380,6 @@
return false;
}
- const char* version = shaderCaps->versionDeclString();
GrShaderVar aVertex("a_vertex", kHalf2_GrSLType, GrShaderVar::kIn_TypeModifier);
GrShaderVar uTexCoordXform("u_texCoordXform", kHalf4_GrSLType,
GrShaderVar::kUniform_TypeModifier);
@@ -3395,7 +3394,7 @@
};
GrShaderVar oFragColor("o_FragColor", kHalf4_GrSLType,GrShaderVar::kOut_TypeModifier);
- SkString vshaderTxt(version);
+ SkString vshaderTxt;
if (shaderCaps->noperspectiveInterpolationSupport()) {
if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
vshaderTxt.appendf("#extension %s : require\n", extension);
@@ -3448,7 +3447,7 @@
vshaderTxt.append("}");
- SkString fshaderTxt(version);
+ SkString fshaderTxt;
if (shaderCaps->noperspectiveInterpolationSupport()) {
if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
fshaderTxt.appendf("#extension %s : require\n", extension);
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.cpp b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
index a8d7812..bd30080 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
@@ -239,7 +239,6 @@
void GrGLSLShaderBuilder::finalize(uint32_t visibility) {
SkASSERT(!fFinalized);
- this->versionDecl() = fProgramBuilder->shaderCaps()->versionDeclString();
this->compileAndAppendLayoutQualifiers();
SkASSERT(visibility);
fProgramBuilder->appendUniformDecls((GrShaderFlags) visibility, &this->uniforms());
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h
index a203d3a..0086e85 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -198,7 +198,6 @@
fCodeIndex++;
}
- SkString& versionDecl() { return fShaderStrings[kVersionDecl]; }
SkString& extensions() { return fShaderStrings[kExtensions]; }
SkString& definitions() { return fShaderStrings[kDefinitions]; }
SkString& precisionQualifier() { return fShaderStrings[kPrecisionQualifier]; }
@@ -213,7 +212,6 @@
virtual void onFinalize() = 0;
enum {
- kVersionDecl,
kExtensions,
kDefinitions,
kPrecisionQualifier,
diff --git a/src/gpu/gradients/generated/GrLinearGradientLayout.cpp b/src/gpu/gradients/generated/GrLinearGradientLayout.cpp
index da6b293..28e7da8 100644
--- a/src/gpu/gradients/generated/GrLinearGradientLayout.cpp
+++ b/src/gpu/gradients/generated/GrLinearGradientLayout.cpp
@@ -27,7 +27,7 @@
(void)gradientMatrix;
SkString sk_TransformedCoords2D_0 = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
fragBuilder->codeAppendf(
- "half t = half(%s.x) + 1.0000000000000001e-05;\n%s = half4(t, 1.0, 0.0, 0.0);\n",
+ "half t = half(%s.x) + 9.9999997473787516e-06;\n%s = half4(t, 1.0, 0.0, 0.0);\n",
sk_TransformedCoords2D_0.c_str(), args.fOutputColor);
}
diff --git a/src/gpu/gradients/generated/GrSweepGradientLayout.cpp b/src/gpu/gradients/generated/GrSweepGradientLayout.cpp
index 9d1157b..18b4739 100644
--- a/src/gpu/gradients/generated/GrSweepGradientLayout.cpp
+++ b/src/gpu/gradients/generated/GrSweepGradientLayout.cpp
@@ -36,7 +36,7 @@
fragBuilder->codeAppendf(
"half angle;\nif (sk_Caps.atan2ImplementedAsAtanYOverX) {\n angle = half(2.0 * "
"atan(-%s.y, length(%s) - %s.x));\n} else {\n angle = half(atan(-%s.y, "
- "-%s.x));\n}\nhalf t = ((angle * 0.15915494309180001 + 0.5) + %s) * %s;\n%s = "
+ "-%s.x));\n}\nhalf t = ((angle * 0.15915493667125702 + 0.5) + %s) * %s;\n%s = "
"half4(t, 1.0, 0.0, 0.0);\n",
sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(),
sk_TransformedCoords2D_0.c_str(), sk_TransformedCoords2D_0.c_str(),
diff --git a/src/sksl/SkSLASTFile.h b/src/sksl/SkSLASTFile.h
new file mode 100644
index 0000000..71fb8eb
--- /dev/null
+++ b/src/sksl/SkSLASTFile.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_ASTFILE
+#define SKSL_ASTFILE
+
+#include "src/sksl/SkSLASTNode.h"
+
+namespace SkSL {
+
+struct ASTFile {
+ ASTFile()
+ : fRoot(ASTNode::ID::Invalid()) {}
+
+ ASTNode& root() {
+ return fNodes[fRoot.fValue];
+ }
+
+private:
+ std::vector<ASTNode> fNodes;
+
+ ASTNode::ID fRoot;
+
+ friend class IRGenerator;
+ friend class Parser;
+};
+
+} // namespace
+
+#endif
diff --git a/src/sksl/SkSLASTNode.cpp b/src/sksl/SkSLASTNode.cpp
new file mode 100644
index 0000000..34e59eb
--- /dev/null
+++ b/src/sksl/SkSLASTNode.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/sksl/SkSLASTNode.h"
+#include "src/sksl/SkSLCompiler.h"
+#include "src/sksl/SkSLString.h"
+
+namespace SkSL {
+
+String ASTNode::description() const {
+ switch (fKind) {
+ case Kind::kNull: return "";
+ case Kind::kBinary:
+ return "(" + this->begin()->description() + " " +
+ Compiler::OperatorName(getToken().fKind) + " " +
+ (this->begin() + 1)->description() + ")";
+ case Kind::kBlock: {
+ String result = "{\n";
+ for (const auto& c : *this) {
+ result += c.description();
+ result += "\n";
+ }
+ result += "}";
+ return result;
+ }
+ case Kind::kBool:
+ return getBool() ? "true" : "false";
+ case Kind::kBreak:
+ return "break";
+ case Kind::kCall: {
+ auto iter = this->begin();
+ String result = iter->description();
+ result += "(";
+ const char* separator = "";
+ while (iter != this->end()) {
+ result += separator;
+ result += (iter++)->description();
+ separator = ",";
+ }
+ result += ")";
+ return result;
+ }
+ case Kind::kContinue:
+ return "continue";
+ case Kind::kDiscard:
+ return "discard";
+ case Kind::kDo:
+ return "do " + this->begin()->description() + " while (" +
+ (this->begin() + 1)->description() + ")";
+ case Kind::kEnum: {
+ String result = "enum ";
+ result += getString();
+ result += " {\n";
+ for (const auto& c : *this) {
+ result += c.description();
+ result += "\n";
+ }
+ result += "};";
+ return result;
+ }
+ case Kind::kEnumCase:
+ if (this->begin() != this->end()) {
+ return String(getString()) + " = " + this->begin()->description();
+ }
+ return getString();
+ case Kind::kExtension:
+ return "#extension " + getString();
+ case Kind::kField:
+ return this->begin()->description() + "." + getString();
+ case Kind::kFile: {
+ String result;
+ for (const auto& c : *this) {
+ result += c.description();
+ result += "\n";
+ }
+ return result;
+ }
+ case Kind::kFloat:
+ return to_string(getFloat());
+ case Kind::kFor:
+ return "for (" + this->begin()->description() + "; " +
+ (this->begin() + 1)->description() + "; " + (this->begin() + 2)->description() +
+ ") " + (this->begin() + 3)->description();
+ case Kind::kFunction: {
+ FunctionData fd = getFunctionData();
+ String result = fd.fModifiers.description();
+ if (result.size()) {
+ result += " ";
+ }
+ auto iter = this->begin();
+ result += (iter++)->description() + " " + fd.fName + "(";
+ const char* separator = "";
+ for (size_t i = 0; i < fd.fParameterCount; ++i) {
+ result += separator;
+ result += (iter++)->description();
+ separator = ", ";
+ }
+ result += ")";
+ if (iter != this->end()) {
+ result += " " + (iter++)->description();
+ SkASSERT(iter == this->end());
+ }
+ else {
+ result += ";";
+ }
+ return result;
+ }
+ case Kind::kIdentifier:
+ return getString();
+ case Kind::kIndex:
+ return this->begin()->description() + "[" + (this->begin() + 1)->description() + "]";
+ case Kind::kIf: {
+ String result;
+ if (getBool()) {
+ result = "@";
+ }
+ auto iter = this->begin();
+ result += "if (" + (iter++)->description() + ") ";
+ result += (iter++)->description();
+ if (iter != this->end()) {
+ result += " else " + (iter++)->description();
+ SkASSERT(iter == this->end());
+ }
+ return result;
+ }
+ case Kind::kInt:
+ return to_string(getInt());
+ case Kind::kInterfaceBlock: {
+ InterfaceBlockData id = getInterfaceBlockData();
+ String result = id.fModifiers.description() + " " + id.fTypeName + " {\n";
+ auto iter = this->begin();
+ for (size_t i = 0; i < id.fDeclarationCount; ++i) {
+ result += (iter++)->description() + "\n";
+ }
+ result += "} ";
+ result += id.fInstanceName;
+ for (size_t i = 0; i < id.fSizeCount; ++i) {
+ result += "[" + (iter++)->description() + "]";
+ }
+ SkASSERT(iter == this->end());
+ result += ";";
+ return result;
+ }
+ case Kind::kModifiers:
+ return getModifiers().description();
+ case Kind::kParameter: {
+ ParameterData pd = getParameterData();
+ auto iter = this->begin();
+ String result = (iter++)->description() + " " + pd.fName;
+ for (size_t i = 0; i < pd.fSizeCount; ++i) {
+ result += "[" + (iter++)->description() + "]";
+ }
+ if (iter != this->end()) {
+ result += " = " + (iter++)->description();
+ SkASSERT(iter == this->end());
+ }
+ return result;
+ }
+ case Kind::kPostfix:
+ return this->begin()->description() + Compiler::OperatorName(getToken().fKind);
+ case Kind::kPrefix:
+ return Compiler::OperatorName(getToken().fKind) + this->begin()->description();
+ case Kind::kReturn:
+ if (this->begin() != this->end()) {
+ return "return " + this->begin()->description() + ";";
+ }
+ return "return;";
+ case Kind::kSection:
+ return "@section { ... }";
+ case Kind::kSwitchCase: {
+ auto iter = this->begin();
+ String result;
+ if (*iter) {
+ result.appendf("case %s:\n", iter->description().c_str());
+ } else {
+ result = "default:\n";
+ }
+ for (++iter; iter != this->end(); ++iter) {
+ result += "\n" + iter->description();
+ }
+ return result;
+ }
+ case Kind::kSwitch: {
+ auto iter = this->begin();
+ String result;
+ if (getBool()) {
+ result = "@";
+ }
+ result += "switch (" + (iter++)->description() + ") {";
+ for (; iter != this->end(); ++iter) {
+ result += iter->description() + "\n";
+ }
+ result += "}";
+ return result;
+ }
+ case Kind::kTernary:
+ return "(" + this->begin()->description() + " ? " + (this->begin() + 1)->description() +
+ " : " + (this->begin() + 2)->description() + ")";
+ case Kind::kType:
+ return String(getTypeData().fName);
+ case Kind::kVarDeclaration: {
+ VarData vd = getVarData();
+ String result = vd.fName;
+ auto iter = this->begin();
+ for (size_t i = 0; i < vd.fSizeCount; ++i) {
+ result += "[" + (iter++)->description() + "]";
+ }
+ if (iter != this->end()) {
+ result += " = " + (iter++)->description();
+ SkASSERT(iter == this->end());
+ }
+ return result;
+ }
+ case Kind::kVarDeclarations: {
+ auto iter = this->begin();
+ String result = (iter++)->description();
+ if (result.size()) {
+ result += " ";
+ }
+ result += (iter++)->description();
+ const char* separator = " ";
+ for (; iter != this->end(); ++iter) {
+ result += separator + iter->description();
+ separator = ", ";
+ }
+ return result;
+ }
+ default:
+ SkASSERT(false);
+ return "<error>";
+ }
+}
+
+} // namespace
diff --git a/src/sksl/SkSLASTNode.h b/src/sksl/SkSLASTNode.h
new file mode 100644
index 0000000..59005a1
--- /dev/null
+++ b/src/sksl/SkSLASTNode.h
@@ -0,0 +1,635 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_ASTNODE
+#define SKSL_ASTNODE
+
+#include "src/sksl/SkSLLexer.h"
+#include "src/sksl/SkSLString.h"
+#include "src/sksl/ir/SkSLModifiers.h"
+
+#include <vector>
+
+namespace SkSL {
+
+// std::max isn't constexpr in some compilers
+static constexpr size_t Max(size_t a, size_t b) {
+ return a > b ? a : b;
+}
+
+/**
+ * Represents a node in the abstract syntax tree (AST). The AST is based directly on the parse tree;
+ * it is a parsed-but-not-yet-analyzed version of the program.
+ */
+struct ASTNode {
+ class ID {
+ public:
+ static ID Invalid() {
+ return ID();
+ }
+
+ bool operator==(const ID& other) {
+ return fValue == other.fValue;
+ }
+
+ bool operator!=(const ID& other) {
+ return fValue != other.fValue;
+ }
+
+ operator bool() const { return fValue >= 0; }
+
+ private:
+ ID()
+ : fValue(-1) {}
+
+ ID(int value)
+ : fValue(value) {}
+
+ int fValue;
+
+ friend struct ASTFile;
+ friend struct ASTNode;
+ friend class Parser;
+ };
+
+ enum class Kind {
+ // data: operator(Token), children: left, right
+ kBinary,
+ // children: statements
+ kBlock,
+ // data: value(bool)
+ kBool,
+ kBreak,
+ // children: target, arg1, arg2...
+ kCall,
+ kContinue,
+ kDiscard,
+ // children: statement, test
+ kDo,
+ // data: name(StringFragment), children: enumCases
+ kEnum,
+ // data: name(StringFragment), children: value?
+ kEnumCase,
+ // data: name(StringFragment)
+ kExtension,
+ // data: field(StringFragment), children: base
+ kField,
+ // children: declarations
+ kFile,
+ // data: value(float)
+ kFloat,
+ // children: init, test, next, statement
+ kFor,
+ // data: FunctionData, children: returnType, parameters, statement?
+ kFunction,
+ // data: name(StringFragment)
+ kIdentifier,
+ // children: base, index?
+ kIndex,
+ // data: isStatic(bool), children: test, ifTrue, ifFalse?
+ kIf,
+ // value(data): int
+ kInt,
+ // data: InterfaceBlockData, children: declaration1, declaration2, ..., size1, size2, ...
+ kInterfaceBlock,
+ // data: Modifiers
+ kModifiers,
+ kNull,
+ // data: ParameterData, children: type, arraySize1, arraySize2, ..., value?
+ kParameter,
+ // data: operator(Token), children: operand
+ kPostfix,
+ // data: operator(Token), children: operand
+ kPrefix,
+ // children: value
+ kReturn,
+ // ...
+ kSection,
+ // children: value, statement 1, statement 2...
+ kSwitchCase,
+ // children: value, case 1, case 2...
+ kSwitch,
+ // children: test, ifTrue, ifFalse
+ kTernary,
+ // data: TypeData, children: sizes
+ kType,
+ // data: VarData, children: arraySize1, arraySize2, ..., value?
+ kVarDeclaration,
+ // children: modifiers, type, varDeclaration1, varDeclaration2, ...
+ kVarDeclarations,
+ // children: test, statement
+ kWhile,
+ };
+
+ class iterator {
+ public:
+ iterator operator++() {
+ SkASSERT(fID);
+ fID = (**this).fNext;
+ return *this;
+ }
+
+ iterator operator++(int) {
+ SkASSERT(fID);
+ iterator old = *this;
+ fID = (**this).fNext;
+ return old;
+ }
+
+ iterator operator+=(int count) {
+ SkASSERT(count >= 0);
+ for (; count > 0; --count) {
+ ++(*this);
+ }
+ return *this;
+ }
+
+ iterator operator+(int count) {
+ iterator result(*this);
+ return result += count;
+ }
+
+ bool operator==(const iterator& other) const {
+ return fID == other.fID;
+ }
+
+ bool operator!=(const iterator& other) const {
+ return fID != other.fID;
+ }
+
+ ASTNode& operator*() {
+ SkASSERT(fID);
+ return (*fNodes)[fID.fValue];
+ }
+
+ ASTNode* operator->() {
+ SkASSERT(fID);
+ return &(*fNodes)[fID.fValue];
+ }
+
+ private:
+ iterator(std::vector<ASTNode>* nodes, ID id)
+ : fNodes(nodes)
+ , fID(id) {}
+
+ std::vector<ASTNode>* fNodes;
+
+ ID fID;
+
+ friend struct ASTNode;
+ };
+
+ struct TypeData {
+ TypeData() {}
+
+ TypeData(StringFragment name, bool isStructDeclaration, bool isNullable)
+ : fName(name)
+ , fIsStructDeclaration(isStructDeclaration)
+ , fIsNullable(isNullable) {}
+
+ StringFragment fName;
+ bool fIsStructDeclaration;
+ bool fIsNullable;
+ };
+
+ struct ParameterData {
+ ParameterData() {}
+
+ ParameterData(Modifiers modifiers, StringFragment name, size_t sizeCount)
+ : fModifiers(modifiers)
+ , fName(name)
+ , fSizeCount(sizeCount) {}
+
+ Modifiers fModifiers;
+ StringFragment fName;
+ size_t fSizeCount;
+ };
+
+ struct VarData {
+ VarData() {}
+
+ VarData(StringFragment name, size_t sizeCount)
+ : fName(name)
+ , fSizeCount(sizeCount) {}
+
+ StringFragment fName;
+ size_t fSizeCount;
+ };
+
+ struct FunctionData {
+ FunctionData() {}
+
+ FunctionData(Modifiers modifiers, StringFragment name, size_t parameterCount)
+ : fModifiers(modifiers)
+ , fName(name)
+ , fParameterCount(parameterCount) {}
+
+ Modifiers fModifiers;
+ StringFragment fName;
+ size_t fParameterCount;
+ };
+
+ struct InterfaceBlockData {
+ InterfaceBlockData() {}
+
+ InterfaceBlockData(Modifiers modifiers, StringFragment typeName, size_t declarationCount,
+ StringFragment instanceName, size_t sizeCount)
+ : fModifiers(modifiers)
+ , fTypeName(typeName)
+ , fDeclarationCount(declarationCount)
+ , fInstanceName(instanceName)
+ , fSizeCount(sizeCount) {}
+
+ Modifiers fModifiers;
+ StringFragment fTypeName;
+ size_t fDeclarationCount;
+ StringFragment fInstanceName;
+ size_t fSizeCount;
+ };
+
+ struct SectionData {
+ SectionData() {}
+
+ SectionData(StringFragment name, StringFragment argument, StringFragment text)
+ : fName(name)
+ , fArgument(argument)
+ , fText(text) {}
+
+ StringFragment fName;
+ StringFragment fArgument;
+ StringFragment fText;
+ };
+
+ struct NodeData {
+ char fBytes[Max(sizeof(Token),
+ Max(sizeof(StringFragment),
+ Max(sizeof(bool),
+ Max(sizeof(SKSL_INT),
+ Max(sizeof(SKSL_FLOAT),
+ Max(sizeof(Modifiers),
+ Max(sizeof(TypeData),
+ Max(sizeof(FunctionData),
+ Max(sizeof(ParameterData),
+ Max(sizeof(VarData),
+ Max(sizeof(InterfaceBlockData),
+ sizeof(SectionData))))))))))))];
+
+ enum class Kind {
+ kToken,
+ kStringFragment,
+ kBool,
+ kInt,
+ kFloat,
+ kModifiers,
+ kTypeData,
+ kFunctionData,
+ kParameterData,
+ kVarData,
+ kInterfaceBlockData,
+ kSectionData
+ } fKind;
+
+ NodeData() = default;
+
+ NodeData(Token data)
+ : fKind(Kind::kToken) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+
+ NodeData(StringFragment data)
+ : fKind(Kind::kStringFragment) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+
+ NodeData(bool data)
+ : fKind(Kind::kBool) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+
+ NodeData(SKSL_INT data)
+ : fKind(Kind::kInt) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+
+ NodeData(SKSL_FLOAT data)
+ : fKind(Kind::kFloat) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+
+ NodeData(Modifiers data)
+ : fKind(Kind::kModifiers) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+
+ NodeData(TypeData data)
+ : fKind(Kind::kTypeData) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+
+ NodeData(FunctionData data)
+ : fKind(Kind::kFunctionData) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+
+ NodeData(VarData data)
+ : fKind(Kind::kVarData) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+
+ NodeData(ParameterData data)
+ : fKind(Kind::kParameterData) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+
+ NodeData(InterfaceBlockData data)
+ : fKind(Kind::kInterfaceBlockData) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+
+ NodeData(SectionData data)
+ : fKind(Kind::kSectionData) {
+ memcpy(fBytes, &data, sizeof(data));
+ }
+ };
+
+ ASTNode()
+ : fOffset(-1)
+ , fKind(Kind::kNull) {}
+
+ ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind)
+ : fNodes(nodes)
+ , fOffset(offset)
+ , fKind(kind) {
+ switch (kind) {
+ case Kind::kBinary:
+ case Kind::kPostfix:
+ case Kind::kPrefix:
+ fData.fKind = NodeData::Kind::kToken;
+ break;
+
+ case Kind::kBool:
+ case Kind::kIf:
+ case Kind::kSwitch:
+ fData.fKind = NodeData::Kind::kBool;
+ break;
+
+ case Kind::kEnum:
+ case Kind::kEnumCase:
+ case Kind::kExtension:
+ case Kind::kField:
+ case Kind::kIdentifier:
+ fData.fKind = NodeData::Kind::kStringFragment;
+ break;
+
+ case Kind::kFloat:
+ fData.fKind = NodeData::Kind::kFloat;
+ break;
+
+ case Kind::kFunction:
+ fData.fKind = NodeData::Kind::kFunctionData;
+ break;
+
+ case Kind::kInt:
+ fData.fKind = NodeData::Kind::kInt;
+ break;
+
+ case Kind::kInterfaceBlock:
+ fData.fKind = NodeData::Kind::kInterfaceBlockData;
+ break;
+
+ case Kind::kModifiers:
+ fData.fKind = NodeData::Kind::kModifiers;
+ break;
+
+ case Kind::kParameter:
+ fData.fKind = NodeData::Kind::kParameterData;
+ break;
+
+ case Kind::kVarDeclaration:
+ fData.fKind = NodeData::Kind::kVarData;
+ break;
+
+ case Kind::kType:
+ fData.fKind = NodeData::Kind::kTypeData;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, Token t)
+ : fNodes(nodes)
+ , fData(t)
+ , fOffset(offset)
+ , fKind(kind) {}
+
+ ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, StringFragment s)
+ : fNodes(nodes)
+ , fData(s)
+ , fOffset(offset)
+ , fKind(kind) {}
+
+ ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, const char* s)
+ : fNodes(nodes)
+ , fData(StringFragment(s))
+ , fOffset(offset)
+ , fKind(kind) {}
+
+ ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, bool b)
+ : fNodes(nodes)
+ , fData(b)
+ , fOffset(offset)
+ , fKind(kind) {}
+
+ ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, SKSL_INT i)
+ : fNodes(nodes)
+ , fData(i)
+ , fOffset(offset)
+ , fKind(kind) {}
+
+ ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, SKSL_FLOAT f)
+ : fNodes(nodes)
+ , fData(f)
+ , fOffset(offset)
+ , fKind(kind) {}
+
+ ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, Modifiers m)
+ : fNodes(nodes)
+ , fData(m)
+ , fOffset(offset)
+ , fKind(kind) {}
+
+ ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, TypeData td)
+ : fNodes(nodes)
+ , fData(td)
+ , fOffset(offset)
+ , fKind(kind) {}
+
+ ASTNode(std::vector<ASTNode>* nodes, int offset, Kind kind, SectionData s)
+ : fNodes(nodes)
+ , fData(s)
+ , fOffset(offset)
+ , fKind(kind) {}
+
+ operator bool() const {
+ return fKind != Kind::kNull;
+ }
+
+ Token getToken() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kToken);
+ Token result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ bool getBool() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kBool);
+ bool result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ SKSL_INT getInt() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kInt);
+ SKSL_INT result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ SKSL_FLOAT getFloat() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kFloat);
+ SKSL_FLOAT result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ StringFragment getString() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kStringFragment);
+ StringFragment result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ Modifiers getModifiers() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kModifiers);
+ Modifiers result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ void setModifiers(const Modifiers& m) {
+ memcpy(fData.fBytes, &m, sizeof(m));
+ }
+
+ TypeData getTypeData() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kTypeData);
+ TypeData result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ void setTypeData(const ASTNode::TypeData& td) {
+ SkASSERT(fData.fKind == NodeData::Kind::kTypeData);
+ memcpy(fData.fBytes, &td, sizeof(td));
+ }
+
+ ParameterData getParameterData() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kParameterData);
+ ParameterData result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ void setParameterData(const ASTNode::ParameterData& pd) {
+ SkASSERT(fData.fKind == NodeData::Kind::kParameterData);
+ memcpy(fData.fBytes, &pd, sizeof(pd));
+ }
+
+ VarData getVarData() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kVarData);
+ VarData result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ void setVarData(const ASTNode::VarData& vd) {
+ SkASSERT(fData.fKind == NodeData::Kind::kVarData);
+ memcpy(fData.fBytes, &vd, sizeof(vd));
+ }
+
+ FunctionData getFunctionData() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kFunctionData);
+ FunctionData result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ void setFunctionData(const ASTNode::FunctionData& fd) {
+ SkASSERT(fData.fKind == NodeData::Kind::kFunctionData);
+ memcpy(fData.fBytes, &fd, sizeof(fd));
+ }
+
+ InterfaceBlockData getInterfaceBlockData() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kInterfaceBlockData);
+ InterfaceBlockData result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ void setInterfaceBlockData(const ASTNode::InterfaceBlockData& id) {
+ SkASSERT(fData.fKind == NodeData::Kind::kInterfaceBlockData);
+ memcpy(fData.fBytes, &id, sizeof(id));
+ }
+
+ SectionData getSectionData() const {
+ SkASSERT(fData.fKind == NodeData::Kind::kSectionData);
+ SectionData result;
+ memcpy(&result, fData.fBytes, sizeof(result));
+ return result;
+ }
+
+ void addChild(ID id) {
+ SkASSERT(!(*fNodes)[id.fValue].fNext);
+ if (fLastChild) {
+ SkASSERT(!(*fNodes)[fLastChild.fValue].fNext);
+ (*fNodes)[fLastChild.fValue].fNext = id;
+ } else {
+ fFirstChild = id;
+ }
+ fLastChild = id;
+ SkASSERT(!(*fNodes)[fLastChild.fValue].fNext);
+ }
+
+ iterator begin() const {
+ return iterator(fNodes, fFirstChild);
+ }
+
+ iterator end() const {
+ return iterator(fNodes, ID(-1));
+ }
+
+ String description() const;
+
+ std::vector<ASTNode>* fNodes;
+
+ NodeData fData;
+
+ int fOffset;
+
+ Kind fKind;
+
+ ID fFirstChild;
+
+ ID fLastChild;
+
+ ID fNext;
+};
+
+} // namespace
+
+#endif
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index 350fcaf..e07769d 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -315,7 +315,7 @@
String var = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
HCodeGenerator::FieldName(name.c_str()).c_str());
String code;
- if (ref.fVariable.fModifiers.fLayout.fWhen.size()) {
+ if (ref.fVariable.fModifiers.fLayout.fWhen.fLength) {
code = String::printf("%sVar.isValid() ? %s : \"%s\"",
HCodeGenerator::FieldName(name.c_str()).c_str(),
var.c_str(),
@@ -561,14 +561,14 @@
ABORT("unsupported uniform type: %s %s;\n", String(var.fType.fName).c_str(),
String(var.fName).c_str());
}
- if (var.fModifiers.fLayout.fWhen.size()) {
- this->writef(" if (%s) {\n ", var.fModifiers.fLayout.fWhen.c_str());
+ if (var.fModifiers.fLayout.fWhen.fLength) {
+ this->writef(" if (%s) {\n ", String(var.fModifiers.fLayout.fWhen).c_str());
}
String name(var.fName);
this->writef(" %sVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, %s, "
"\"%s\");\n", HCodeGenerator::FieldName(name.c_str()).c_str(), type,
name.c_str());
- if (var.fModifiers.fLayout.fWhen.size()) {
+ if (var.fModifiers.fLayout.fWhen.fLength) {
this->write(" }\n");
}
}
@@ -1111,8 +1111,8 @@
}
switch (param->fModifiers.fLayout.fKey) {
case Layout::kKey_Key:
- if (param->fModifiers.fLayout.fWhen.size()) {
- this->writef("if (%s) {", param->fModifiers.fLayout.fWhen.c_str());
+ if (param->fModifiers.fLayout.fWhen.fLength) {
+ this->writef("if (%s) {", String(param->fModifiers.fLayout.fWhen).c_str());
}
if (param->fType == *fContext.fFloat4x4_Type) {
ABORT("no automatic key handling for float4x4\n");
@@ -1145,7 +1145,7 @@
this->writef(" b->add32((int32_t) %s);\n",
HCodeGenerator::FieldName(name).c_str());
}
- if (param->fModifiers.fLayout.fWhen.size()) {
+ if (param->fModifiers.fLayout.fWhen.fLength) {
this->write("}");
}
break;
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 802e5b3..52d943e 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -12,12 +12,6 @@
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLParser.h"
-#include "src/sksl/ast/SkSLASTBoolLiteral.h"
-#include "src/sksl/ast/SkSLASTFieldSuffix.h"
-#include "src/sksl/ast/SkSLASTFloatLiteral.h"
-#include "src/sksl/ast/SkSLASTIndexSuffix.h"
-#include "src/sksl/ast/SkSLASTIntLiteral.h"
-#include "src/sksl/ast/SkSLASTNullLiteral.h"
#include "src/sksl/ir/SkSLAppendStage.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
@@ -179,22 +173,42 @@
}
}
-std::unique_ptr<Extension> IRGenerator::convertExtension(const ASTExtension& extension) {
- return std::unique_ptr<Extension>(new Extension(extension.fOffset, extension.fName));
+std::unique_ptr<Extension> IRGenerator::convertExtension(int offset, StringFragment name) {
+ return std::unique_ptr<Extension>(new Extension(offset, name));
}
-std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTStatement& statement) {
+void IRGenerator::finish() {
+ this->popSymbolTable();
+ fSettings = nullptr;
+}
+
+std::unique_ptr<Statement> IRGenerator::convertStatement(const ASTNode& statement) {
switch (statement.fKind) {
- case ASTStatement::kBlock_Kind:
- return this->convertBlock((ASTBlock&) statement);
- case ASTStatement::kVarDeclaration_Kind:
- return this->convertVarDeclarationStatement((ASTVarDeclarationStatement&) statement);
- case ASTStatement::kExpression_Kind: {
- std::unique_ptr<Statement> result =
- this->convertExpressionStatement((ASTExpressionStatement&) statement);
- if (!result) {
- return nullptr;
- }
+ case ASTNode::Kind::kBlock:
+ return this->convertBlock(statement);
+ case ASTNode::Kind::kVarDeclarations:
+ return this->convertVarDeclarationStatement(statement);
+ case ASTNode::Kind::kIf:
+ return this->convertIf(statement);
+ case ASTNode::Kind::kFor:
+ return this->convertFor(statement);
+ case ASTNode::Kind::kWhile:
+ return this->convertWhile(statement);
+ case ASTNode::Kind::kDo:
+ return this->convertDo(statement);
+ case ASTNode::Kind::kSwitch:
+ return this->convertSwitch(statement);
+ case ASTNode::Kind::kReturn:
+ return this->convertReturn(statement);
+ case ASTNode::Kind::kBreak:
+ return this->convertBreak(statement);
+ case ASTNode::Kind::kContinue:
+ return this->convertContinue(statement);
+ case ASTNode::Kind::kDiscard:
+ return this->convertDiscard(statement);
+ default:
+ // it's an expression
+ std::unique_ptr<Statement> result = this->convertExpressionStatement(statement);
if (fRTAdjust && Program::kGeometry_Kind == fKind) {
SkASSERT(result->fKind == Statement::kExpression_Kind);
Expression& expr = *((ExpressionStatement&) *result).fExpression;
@@ -211,35 +225,15 @@
}
}
return result;
- }
- case ASTStatement::kIf_Kind:
- return this->convertIf((ASTIfStatement&) statement);
- case ASTStatement::kFor_Kind:
- return this->convertFor((ASTForStatement&) statement);
- case ASTStatement::kWhile_Kind:
- return this->convertWhile((ASTWhileStatement&) statement);
- case ASTStatement::kDo_Kind:
- return this->convertDo((ASTDoStatement&) statement);
- case ASTStatement::kSwitch_Kind:
- return this->convertSwitch((ASTSwitchStatement&) statement);
- case ASTStatement::kReturn_Kind:
- return this->convertReturn((ASTReturnStatement&) statement);
- case ASTStatement::kBreak_Kind:
- return this->convertBreak((ASTBreakStatement&) statement);
- case ASTStatement::kContinue_Kind:
- return this->convertContinue((ASTContinueStatement&) statement);
- case ASTStatement::kDiscard_Kind:
- return this->convertDiscard((ASTDiscardStatement&) statement);
- default:
- ABORT("unsupported statement type: %d\n", statement.fKind);
}
}
-std::unique_ptr<Block> IRGenerator::convertBlock(const ASTBlock& block) {
+std::unique_ptr<Block> IRGenerator::convertBlock(const ASTNode& block) {
+ SkASSERT(block.fKind == ASTNode::Kind::kBlock);
AutoSymbolTable table(this);
std::vector<std::unique_ptr<Statement>> statements;
- for (size_t i = 0; i < block.fStatements.size(); i++) {
- std::unique_ptr<Statement> statement = this->convertStatement(*block.fStatements[i]);
+ for (const auto& child : block) {
+ std::unique_ptr<Statement> statement = this->convertStatement(child);
if (!statement) {
return nullptr;
}
@@ -248,51 +242,59 @@
return std::unique_ptr<Block>(new Block(block.fOffset, std::move(statements), fSymbolTable));
}
-std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
- const ASTVarDeclarationStatement& s) {
- auto decl = this->convertVarDeclarations(*s.fDeclarations, Variable::kLocal_Storage);
+std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(const ASTNode& s) {
+ SkASSERT(s.fKind == ASTNode::Kind::kVarDeclarations);
+ auto decl = this->convertVarDeclarations(s, Variable::kLocal_Storage);
if (!decl) {
return nullptr;
}
return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
}
-std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVarDeclarations& decl,
+std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTNode& decls,
Variable::Storage storage) {
+ SkASSERT(decls.fKind == ASTNode::Kind::kVarDeclarations);
+ auto iter = decls.begin();
+ const Modifiers& modifiers = iter++->getModifiers();
+ const ASTNode& rawType = *(iter++);
std::vector<std::unique_ptr<VarDeclaration>> variables;
- const Type* baseType = this->convertType(*decl.fType);
+ const Type* baseType = this->convertType(rawType);
if (!baseType) {
return nullptr;
}
if (fKind != Program::kFragmentProcessor_Kind &&
- (decl.fModifiers.fFlags & Modifiers::kIn_Flag) &&
+ (modifiers.fFlags & Modifiers::kIn_Flag) &&
baseType->kind() == Type::Kind::kMatrix_Kind) {
- fErrors.error(decl.fOffset, "'in' variables may not have matrix type");
+ fErrors.error(decls.fOffset, "'in' variables may not have matrix type");
}
- if (decl.fModifiers.fLayout.fWhen.length() && fKind != Program::kFragmentProcessor_Kind &&
+ if (modifiers.fLayout.fWhen.fLength && fKind != Program::kFragmentProcessor_Kind &&
fKind != Program::kPipelineStage_Kind) {
- fErrors.error(decl.fOffset, "'when' is only permitted within fragment processors");
+ fErrors.error(decls.fOffset, "'when' is only permitted within fragment processors");
}
- if (decl.fModifiers.fLayout.fKey) {
+ if (modifiers.fLayout.fKey) {
if (fKind != Program::kFragmentProcessor_Kind && fKind != Program::kPipelineStage_Kind) {
- fErrors.error(decl.fOffset, "'key' is only permitted within fragment processors");
+ fErrors.error(decls.fOffset, "'key' is only permitted within fragment processors");
}
- if ((decl.fModifiers.fFlags & Modifiers::kUniform_Flag) != 0) {
- fErrors.error(decl.fOffset, "'key' is not permitted on 'uniform' variables");
+ if ((modifiers.fFlags & Modifiers::kUniform_Flag) != 0) {
+ fErrors.error(decls.fOffset, "'key' is not permitted on 'uniform' variables");
}
}
- for (const auto& varDecl : decl.fVars) {
- if (decl.fModifiers.fLayout.fLocation == 0 && decl.fModifiers.fLayout.fIndex == 0 &&
- (decl.fModifiers.fFlags & Modifiers::kOut_Flag) && fKind == Program::kFragment_Kind &&
- varDecl.fName != "sk_FragColor") {
- fErrors.error(decl.fOffset,
+ for (; iter != decls.end(); ++iter) {
+ const ASTNode& varDecl = *iter;
+ if (modifiers.fLayout.fLocation == 0 && modifiers.fLayout.fIndex == 0 &&
+ (modifiers.fFlags & Modifiers::kOut_Flag) && fKind == Program::kFragment_Kind &&
+ varDecl.getVarData().fName != "sk_FragColor") {
+ fErrors.error(varDecl.fOffset,
"out location=0, index=0 is reserved for sk_FragColor");
}
+ const ASTNode::VarData& varData = varDecl.getVarData();
const Type* type = baseType;
std::vector<std::unique_ptr<Expression>> sizes;
- for (const auto& rawSize : varDecl.fSizes) {
+ auto iter = varDecl.begin();
+ for (size_t i = 0; i < varData.fSizeCount; ++i, ++iter) {
+ const ASTNode& rawSize = *iter;
if (rawSize) {
- auto size = this->coerce(this->convertExpression(*rawSize), *fContext.fInt_Type);
+ auto size = this->coerce(this->convertExpression(rawSize), *fContext.fInt_Type);
if (!size) {
return nullptr;
}
@@ -323,16 +325,16 @@
sizes.push_back(nullptr);
}
}
- auto var = std::unique_ptr<Variable>(new Variable(decl.fOffset, decl.fModifiers,
- varDecl.fName, *type, storage));
+ auto var = std::unique_ptr<Variable>(new Variable(varDecl.fOffset, modifiers,
+ varData.fName, *type, storage));
if (var->fName == Compiler::RTADJUST_NAME) {
SkASSERT(!fRTAdjust);
SkASSERT(var->fType == *fContext.fFloat4_Type);
fRTAdjust = var.get();
}
std::unique_ptr<Expression> value;
- if (varDecl.fValue) {
- value = this->convertExpression(*varDecl.fValue);
+ if (iter != varDecl.end()) {
+ value = this->convertExpression(*iter);
if (!value) {
return nullptr;
}
@@ -343,29 +345,30 @@
var->fWriteCount = 1;
var->fInitialValue = value.get();
}
- if (storage == Variable::kGlobal_Storage && varDecl.fName == "sk_FragColor" &&
- (*fSymbolTable)[varDecl.fName]) {
+ if (storage == Variable::kGlobal_Storage && var->fName == "sk_FragColor" &&
+ (*fSymbolTable)[var->fName]) {
// already defined, ignore
- } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] &&
- (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Kind &&
- ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLayout.fBuiltin >= 0) {
+ } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[var->fName] &&
+ (*fSymbolTable)[var->fName]->fKind == Symbol::kVariable_Kind &&
+ ((Variable*) (*fSymbolTable)[var->fName])->fModifiers.fLayout.fBuiltin >= 0) {
// already defined, just update the modifiers
- Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName];
+ Variable* old = (Variable*) (*fSymbolTable)[var->fName];
old->fModifiers = var->fModifiers;
} else {
variables.emplace_back(new VarDeclaration(var.get(), std::move(sizes),
std::move(value)));
- fSymbolTable->add(varDecl.fName, std::move(var));
+ StringFragment name = var->fName;
+ fSymbolTable->add(name, std::move(var));
}
}
- return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fOffset,
+ return std::unique_ptr<VarDeclarations>(new VarDeclarations(decls.fOffset,
baseType,
std::move(variables)));
}
-std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(
- const ASTModifiersDeclaration& m) {
- Modifiers modifiers = m.fModifiers;
+std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(const ASTNode& m) {
+ SkASSERT(m.fKind == ASTNode::Kind::kModifiers);
+ Modifiers modifiers = m.getModifiers();
if (modifiers.fLayout.fInvocations != -1) {
if (fKind != Program::kGeometry_Kind) {
fErrors.error(m.fOffset, "'invocations' is only legal in geometry shaders");
@@ -390,19 +393,21 @@
return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers));
}
-std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
- std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
+std::unique_ptr<Statement> IRGenerator::convertIf(const ASTNode& n) {
+ SkASSERT(n.fKind == ASTNode::Kind::kIf);
+ auto iter = n.begin();
+ std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
*fContext.fBool_Type);
if (!test) {
return nullptr;
}
- std::unique_ptr<Statement> ifTrue = this->convertStatement(*s.fIfTrue);
+ std::unique_ptr<Statement> ifTrue = this->convertStatement(*(iter++));
if (!ifTrue) {
return nullptr;
}
std::unique_ptr<Statement> ifFalse;
- if (s.fIfFalse) {
- ifFalse = this->convertStatement(*s.fIfFalse);
+ if (iter != n.end()) {
+ ifFalse = this->convertStatement(*(iter++));
if (!ifFalse) {
return nullptr;
}
@@ -411,45 +416,50 @@
// static boolean value, fold down to a single branch
if (((BoolLiteral&) *test).fValue) {
return ifTrue;
- } else if (s.fIfFalse) {
+ } else if (ifFalse) {
return ifFalse;
} else {
// False & no else clause. Not an error, so don't return null!
std::vector<std::unique_ptr<Statement>> empty;
- return std::unique_ptr<Statement>(new Block(s.fOffset, std::move(empty),
+ return std::unique_ptr<Statement>(new Block(n.fOffset, std::move(empty),
fSymbolTable));
}
}
- return std::unique_ptr<Statement>(new IfStatement(s.fOffset, s.fIsStatic, std::move(test),
+ return std::unique_ptr<Statement>(new IfStatement(n.fOffset, n.getBool(), std::move(test),
std::move(ifTrue), std::move(ifFalse)));
}
-std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) {
+std::unique_ptr<Statement> IRGenerator::convertFor(const ASTNode& f) {
+ SkASSERT(f.fKind == ASTNode::Kind::kFor);
AutoLoopLevel level(this);
AutoSymbolTable table(this);
std::unique_ptr<Statement> initializer;
- if (f.fInitializer) {
- initializer = this->convertStatement(*f.fInitializer);
+ auto iter = f.begin();
+ if (*iter) {
+ initializer = this->convertStatement(*iter);
if (!initializer) {
return nullptr;
}
}
+ ++iter;
std::unique_ptr<Expression> test;
- if (f.fTest) {
- test = this->coerce(this->convertExpression(*f.fTest), *fContext.fBool_Type);
+ if (*iter) {
+ test = this->coerce(this->convertExpression(*iter), *fContext.fBool_Type);
if (!test) {
return nullptr;
}
}
+ ++iter;
std::unique_ptr<Expression> next;
- if (f.fNext) {
- next = this->convertExpression(*f.fNext);
+ if (*iter) {
+ next = this->convertExpression(*iter);
if (!next) {
return nullptr;
}
this->checkValid(*next);
}
- std::unique_ptr<Statement> statement = this->convertStatement(*f.fStatement);
+ ++iter;
+ std::unique_ptr<Statement> statement = this->convertStatement(*iter);
if (!statement) {
return nullptr;
}
@@ -458,14 +468,16 @@
std::move(statement), fSymbolTable));
}
-std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) {
+std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTNode& w) {
+ SkASSERT(w.fKind == ASTNode::Kind::kWhile);
AutoLoopLevel level(this);
- std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest),
+ auto iter = w.begin();
+ std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
*fContext.fBool_Type);
if (!test) {
return nullptr;
}
- std::unique_ptr<Statement> statement = this->convertStatement(*w.fStatement);
+ std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
if (!statement) {
return nullptr;
}
@@ -473,24 +485,28 @@
std::move(statement)));
}
-std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
+std::unique_ptr<Statement> IRGenerator::convertDo(const ASTNode& d) {
+ SkASSERT(d.fKind == ASTNode::Kind::kDo);
AutoLoopLevel level(this);
- std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*d.fTest),
- *fContext.fBool_Type);
- if (!test) {
+ auto iter = d.begin();
+ std::unique_ptr<Statement> statement = this->convertStatement(*(iter++));
+ if (!statement) {
return nullptr;
}
- std::unique_ptr<Statement> statement = this->convertStatement(*d.fStatement);
- if (!statement) {
+ std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
+ *fContext.fBool_Type);
+ if (!test) {
return nullptr;
}
return std::unique_ptr<Statement>(new DoStatement(d.fOffset, std::move(statement),
std::move(test)));
}
-std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTSwitchStatement& s) {
+std::unique_ptr<Statement> IRGenerator::convertSwitch(const ASTNode& s) {
+ SkASSERT(s.fKind == ASTNode::Kind::kSwitch);
AutoSwitchLevel level(this);
- std::unique_ptr<Expression> value = this->convertExpression(*s.fValue);
+ auto iter = s.begin();
+ std::unique_ptr<Expression> value = this->convertExpression(*(iter++));
if (!value) {
return nullptr;
}
@@ -503,10 +519,13 @@
AutoSymbolTable table(this);
std::unordered_set<int> caseValues;
std::vector<std::unique_ptr<SwitchCase>> cases;
- for (const auto& c : s.fCases) {
+ for (; iter != s.end(); ++iter) {
+ const ASTNode& c = *iter;
+ SkASSERT(c.fKind == ASTNode::Kind::kSwitchCase);
std::unique_ptr<Expression> caseValue;
- if (c->fValue) {
- caseValue = this->convertExpression(*c->fValue);
+ auto childIter = c.begin();
+ if (*childIter) {
+ caseValue = this->convertExpression(*childIter);
if (!caseValue) {
return nullptr;
}
@@ -525,25 +544,25 @@
}
caseValues.insert(v);
}
+ ++childIter;
std::vector<std::unique_ptr<Statement>> statements;
- for (const auto& s : c->fStatements) {
- std::unique_ptr<Statement> converted = this->convertStatement(*s);
+ for (; childIter != c.end(); ++childIter) {
+ std::unique_ptr<Statement> converted = this->convertStatement(*childIter);
if (!converted) {
return nullptr;
}
statements.push_back(std::move(converted));
}
- cases.emplace_back(new SwitchCase(c->fOffset, std::move(caseValue),
+ cases.emplace_back(new SwitchCase(c.fOffset, std::move(caseValue),
std::move(statements)));
}
- return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.fIsStatic,
+ return std::unique_ptr<Statement>(new SwitchStatement(s.fOffset, s.getBool(),
std::move(value), std::move(cases),
fSymbolTable));
}
-std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(
- const ASTExpressionStatement& s) {
- std::unique_ptr<Expression> e = this->convertExpression(*s.fExpression);
+std::unique_ptr<Statement> IRGenerator::convertExpressionStatement(const ASTNode& s) {
+ std::unique_ptr<Expression> e = this->convertExpression(s);
if (!e) {
return nullptr;
}
@@ -551,14 +570,15 @@
return std::unique_ptr<Statement>(new ExpressionStatement(std::move(e)));
}
-std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTReturnStatement& r) {
+std::unique_ptr<Statement> IRGenerator::convertReturn(const ASTNode& r) {
+ SkASSERT(r.fKind == ASTNode::Kind::kReturn);
SkASSERT(fCurrentFunction);
// early returns from a vertex main function will bypass the sk_Position normalization, so
// SkASSERT that we aren't doing that. It is of course possible to fix this by adding a
// normalization before each return, but it will probably never actually be necessary.
SkASSERT(Program::kVertex_Kind != fKind || !fRTAdjust || "main" != fCurrentFunction->fName);
- if (r.fExpression) {
- std::unique_ptr<Expression> result = this->convertExpression(*r.fExpression);
+ if (r.begin() != r.end()) {
+ std::unique_ptr<Expression> result = this->convertExpression(*r.begin());
if (!result) {
return nullptr;
}
@@ -580,7 +600,8 @@
}
}
-std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTBreakStatement& b) {
+std::unique_ptr<Statement> IRGenerator::convertBreak(const ASTNode& b) {
+ SkASSERT(b.fKind == ASTNode::Kind::kBreak);
if (fLoopLevel > 0 || fSwitchLevel > 0) {
return std::unique_ptr<Statement>(new BreakStatement(b.fOffset));
} else {
@@ -589,7 +610,8 @@
}
}
-std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTContinueStatement& c) {
+std::unique_ptr<Statement> IRGenerator::convertContinue(const ASTNode& c) {
+ SkASSERT(c.fKind == ASTNode::Kind::kContinue);
if (fLoopLevel > 0) {
return std::unique_ptr<Statement>(new ContinueStatement(c.fOffset));
} else {
@@ -598,7 +620,8 @@
}
}
-std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTDiscardStatement& d) {
+std::unique_ptr<Statement> IRGenerator::convertDiscard(const ASTNode& d) {
+ SkASSERT(d.fKind == ASTNode::Kind::kDiscard);
return std::unique_ptr<Statement>(new DiscardStatement(d.fOffset));
}
@@ -628,7 +651,7 @@
*loopIdx,
VariableReference::kReadWrite_RefKind)),
Token::PLUSPLUS));
- ASTIdentifier endPrimitiveID = ASTIdentifier(-1, "EndPrimitive");
+ ASTNode endPrimitiveID(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier, "EndPrimitive");
std::unique_ptr<Expression> endPrimitive = this->convertExpression(endPrimitiveID);
SkASSERT(endPrimitive);
@@ -692,19 +715,25 @@
return std::unique_ptr<Statement>(new ExpressionStatement(std::move(result)));
}
-void IRGenerator::convertFunction(const ASTFunction& f) {
- const Type* returnType = this->convertType(*f.fReturnType);
+void IRGenerator::convertFunction(const ASTNode& f) {
+ auto iter = f.begin();
+ const Type* returnType = this->convertType(*(iter++));
if (!returnType) {
return;
}
+ const ASTNode::FunctionData& fd = f.getFunctionData();
std::vector<const Variable*> parameters;
- for (const auto& param : f.fParameters) {
- const Type* type = this->convertType(*param->fType);
+ for (size_t i = 0; i < fd.fParameterCount; ++i) {
+ const ASTNode& param = *(iter++);
+ SkASSERT(param.fKind == ASTNode::Kind::kParameter);
+ ASTNode::ParameterData pd = param.getParameterData();
+ auto paramIter = param.begin();
+ const Type* type = this->convertType(*(paramIter++));
if (!type) {
return;
}
- for (int j = (int) param->fSizes.size() - 1; j >= 0; j--) {
- int size = param->fSizes[j];
+ for (int j = (int) pd.fSizeCount; j >= 1; j--) {
+ int size = (param.begin() + j)->getInt();
String name = type->name() + "[" + to_string(size) + "]";
type = (Type*) fSymbolTable->takeOwnership(
std::unique_ptr<Symbol>(new Type(std::move(name),
@@ -712,17 +741,17 @@
*type,
size)));
}
- StringFragment name = param->fName;
+ StringFragment name = pd.fName;
Variable* var = (Variable*) fSymbolTable->takeOwnership(
- std::unique_ptr<Symbol>(new Variable(param->fOffset,
- param->fModifiers,
+ std::unique_ptr<Symbol>(new Variable(param.fOffset,
+ pd.fModifiers,
name,
*type,
Variable::kParameter_Storage)));
parameters.push_back(var);
}
- if (f.fName == "main") {
+ if (fd.fName == "main") {
switch (fKind) {
case Program::kPipelineStage_Kind: {
bool valid;
@@ -762,7 +791,7 @@
// find existing declaration
const FunctionDeclaration* decl = nullptr;
- auto entry = (*fSymbolTable)[f.fName];
+ auto entry = (*fSymbolTable)[fd.fName];
if (entry) {
std::vector<const FunctionDeclaration*> functions;
switch (entry->fKind) {
@@ -773,11 +802,11 @@
functions.push_back((FunctionDeclaration*) entry);
break;
default:
- fErrors.error(f.fOffset, "symbol '" + f.fName + "' was already defined");
+ fErrors.error(f.fOffset, "symbol '" + fd.fName + "' was already defined");
return;
}
for (const auto& other : functions) {
- SkASSERT(other->fName == f.fName);
+ SkASSERT(other->fName == fd.fName);
if (parameters.size() == other->fParameters.size()) {
bool match = true;
for (size_t i = 0; i < parameters.size(); i++) {
@@ -788,7 +817,7 @@
}
if (match) {
if (*returnType != other->fReturnType) {
- FunctionDeclaration newDecl(f.fOffset, f.fModifiers, f.fName, parameters,
+ FunctionDeclaration newDecl(f.fOffset, fd.fModifiers, fd.fName, parameters,
*returnType);
fErrors.error(f.fOffset, "functions '" + newDecl.description() +
"' and '" + other->description() +
@@ -817,20 +846,21 @@
if (!decl) {
// couldn't find an existing declaration
auto newDecl = std::unique_ptr<FunctionDeclaration>(new FunctionDeclaration(f.fOffset,
- f.fModifiers,
- f.fName,
+ fd.fModifiers,
+ fd.fName,
parameters,
*returnType));
decl = newDecl.get();
fSymbolTable->add(decl->fName, std::move(newDecl));
}
- if (f.fBody) {
+ if (iter != f.end()) {
+ // compile body
SkASSERT(!fCurrentFunction);
fCurrentFunction = decl;
decl->fDefined = true;
std::shared_ptr<SymbolTable> old = fSymbolTable;
AutoSymbolTable table(this);
- if (f.fName == "main" && fKind == Program::kPipelineStage_Kind) {
+ if (fd.fName == "main" && fKind == Program::kPipelineStage_Kind) {
if (parameters.size() == 3) {
parameters[0]->fModifiers.fLayout.fBuiltin = SK_MAIN_X_BUILTIN;
parameters[1]->fModifiers.fLayout.fBuiltin = SK_MAIN_Y_BUILTIN;
@@ -843,11 +873,11 @@
for (size_t i = 0; i < parameters.size(); i++) {
fSymbolTable->addWithoutOwnership(parameters[i]->fName, decl->fParameters[i]);
}
- bool needInvocationIDWorkaround = fInvocations != -1 && f.fName == "main" &&
+ bool needInvocationIDWorkaround = fInvocations != -1 && fd.fName == "main" &&
fSettings->fCaps &&
!fSettings->fCaps->gsInvocationsSupport();
SkASSERT(!fExtraVars.size());
- std::unique_ptr<Block> body = this->convertBlock(*f.fBody);
+ std::unique_ptr<Block> body = this->convertBlock(*iter);
for (auto& v : fExtraVars) {
body->fStatements.insert(body->fStatements.begin(), std::move(v));
}
@@ -861,7 +891,7 @@
}
// conservatively assume all user-defined functions have side effects
((Modifiers&) decl->fModifiers).fFlags |= Modifiers::kHasSideEffects_Flag;
- if (Program::kVertex_Kind == fKind && f.fName == "main" && fRTAdjust) {
+ if (Program::kVertex_Kind == fKind && fd.fName == "main" && fRTAdjust) {
body->fStatements.insert(body->fStatements.end(), this->getNormalizeSkPositionCode());
}
fProgramElements->push_back(std::unique_ptr<FunctionDefinition>(
@@ -869,16 +899,19 @@
}
}
-std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) {
+std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode& intf) {
+ SkASSERT(intf.fKind == ASTNode::Kind::kInterfaceBlock);
+ ASTNode::InterfaceBlockData id = intf.getInterfaceBlockData();
std::shared_ptr<SymbolTable> old = fSymbolTable;
this->pushSymbolTable();
std::shared_ptr<SymbolTable> symbols = fSymbolTable;
std::vector<Type::Field> fields;
bool haveRuntimeArray = false;
bool foundRTAdjust = false;
- for (size_t i = 0; i < intf.fDeclarations.size(); i++) {
+ auto iter = intf.begin();
+ for (size_t i = 0; i < id.fDeclarationCount; ++i) {
std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
- *intf.fDeclarations[i],
+ *(iter++),
Variable::kInterfaceBlock_Storage);
if (!decl) {
return nullptr;
@@ -902,10 +935,10 @@
"initializers are not permitted on interface block fields");
}
if (vd.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag |
- Modifiers::kOut_Flag |
- Modifiers::kUniform_Flag |
- Modifiers::kBuffer_Flag |
- Modifiers::kConst_Flag)) {
+ Modifiers::kOut_Flag |
+ Modifiers::kUniform_Flag |
+ Modifiers::kBuffer_Flag |
+ Modifiers::kConst_Flag)) {
fErrors.error(decl->fOffset,
"interface block fields may not have storage qualifiers");
}
@@ -917,12 +950,13 @@
}
this->popSymbolTable();
Type* type = (Type*) old->takeOwnership(std::unique_ptr<Symbol>(new Type(intf.fOffset,
- intf.fTypeName,
+ id.fTypeName,
fields)));
std::vector<std::unique_ptr<Expression>> sizes;
- for (const auto& size : intf.fSizes) {
+ for (size_t i = 0; i < id.fSizeCount; ++i) {
+ const ASTNode& size = *(iter++);
if (size) {
- std::unique_ptr<Expression> converted = this->convertExpression(*size);
+ std::unique_ptr<Expression> converted = this->convertExpression(size);
if (!converted) {
return nullptr;
}
@@ -955,15 +989,15 @@
}
Variable* var = (Variable*) old->takeOwnership(std::unique_ptr<Symbol>(
new Variable(intf.fOffset,
- intf.fModifiers,
- intf.fInstanceName.fLength ? intf.fInstanceName : intf.fTypeName,
+ id.fModifiers,
+ id.fInstanceName.fLength ? id.fInstanceName : id.fTypeName,
*type,
Variable::kGlobal_Storage)));
if (foundRTAdjust) {
fRTAdjustInterfaceBlock = var;
}
- if (intf.fInstanceName.fLength) {
- old->addWithoutOwnership(intf.fInstanceName, var);
+ if (id.fInstanceName.fLength) {
+ old->addWithoutOwnership(id.fInstanceName, var);
} else {
for (size_t i = 0; i < fields.size(); i++) {
old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fOffset, *var,
@@ -972,8 +1006,8 @@
}
return std::unique_ptr<InterfaceBlock>(new InterfaceBlock(intf.fOffset,
var,
- intf.fTypeName,
- intf.fInstanceName,
+ id.fTypeName,
+ id.fInstanceName,
std::move(sizes),
symbols));
}
@@ -996,19 +1030,23 @@
}
}
-void IRGenerator::convertEnum(const ASTEnum& e) {
+void IRGenerator::convertEnum(const ASTNode& e) {
+ SkASSERT(e.fKind == ASTNode::Kind::kEnum);
std::vector<Variable*> variables;
int64_t currentValue = 0;
Layout layout;
- ASTType enumType(e.fOffset, e.fTypeName, ASTType::kIdentifier_Kind, {}, false);
+ ASTNode enumType(e.fNodes, e.fOffset, ASTNode::Kind::kType,
+ ASTNode::TypeData(e.getString(), false, false));
const Type* type = this->convertType(enumType);
Modifiers modifiers(layout, Modifiers::kConst_Flag);
std::shared_ptr<SymbolTable> symbols(new SymbolTable(fSymbolTable, &fErrors));
fSymbolTable = symbols;
- for (size_t i = 0; i < e.fNames.size(); i++) {
+ for (auto iter = e.begin(); iter != e.end(); ++iter) {
+ const ASTNode& child = *iter;
+ SkASSERT(child.fKind == ASTNode::Kind::kEnumCase);
std::unique_ptr<Expression> value;
- if (e.fValues[i]) {
- value = this->convertExpression(*e.fValues[i]);
+ if (child.begin() != child.end()) {
+ value = this->convertExpression(*child.begin());
if (!value) {
fSymbolTable = symbols->fParent;
return;
@@ -1017,25 +1055,26 @@
}
value = std::unique_ptr<Expression>(new IntLiteral(fContext, e.fOffset, currentValue));
++currentValue;
- auto var = std::unique_ptr<Variable>(new Variable(e.fOffset, modifiers, e.fNames[i],
+ auto var = std::unique_ptr<Variable>(new Variable(e.fOffset, modifiers, child.getString(),
*type, Variable::kGlobal_Storage,
value.get()));
variables.push_back(var.get());
- symbols->add(e.fNames[i], std::move(var));
+ symbols->add(child.getString(), std::move(var));
symbols->takeOwnership(std::move(value));
}
- fProgramElements->push_back(std::unique_ptr<ProgramElement>(new Enum(e.fOffset, e.fTypeName,
+ fProgramElements->push_back(std::unique_ptr<ProgramElement>(new Enum(e.fOffset, e.getString(),
symbols)));
fSymbolTable = symbols->fParent;
}
-const Type* IRGenerator::convertType(const ASTType& type) {
- const Symbol* result = (*fSymbolTable)[type.fName];
+const Type* IRGenerator::convertType(const ASTNode& type) {
+ ASTNode::TypeData td = type.getTypeData();
+ const Symbol* result = (*fSymbolTable)[td.fName];
if (result && result->fKind == Symbol::kType_Kind) {
- if (type.fNullable) {
+ if (td.fIsNullable) {
if (((Type&) *result) == *fContext.fFragmentProcessor_Type) {
- if (type.fSizes.size()) {
- fErrors.error(type.fOffset, "type '" + type.fName + "' may not be used in "
+ if (type.begin() != type.end()) {
+ fErrors.error(type.fOffset, "type '" + td.fName + "' may not be used in "
"an array");
}
result = fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
@@ -1043,14 +1082,14 @@
Type::kNullable_Kind,
(const Type&) *result)));
} else {
- fErrors.error(type.fOffset, "type '" + type.fName + "' may not be nullable");
+ fErrors.error(type.fOffset, "type '" + td.fName + "' may not be nullable");
}
}
- for (int size : type.fSizes) {
+ for (const auto& size : type) {
String name(result->fName);
name += "[";
- if (size != -1) {
- name += to_string(size);
+ if (size) {
+ name += to_string(size.getInt());
}
name += "]";
result = (Type*) fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
@@ -1061,42 +1100,49 @@
}
return (const Type*) result;
}
- fErrors.error(type.fOffset, "unknown type '" + type.fName + "'");
+ fErrors.error(type.fOffset, "unknown type '" + td.fName + "'");
return nullptr;
}
-std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTExpression& expr) {
+std::unique_ptr<Expression> IRGenerator::convertExpression(const ASTNode& expr) {
switch (expr.fKind) {
- case ASTExpression::kIdentifier_Kind:
- return this->convertIdentifier((ASTIdentifier&) expr);
- case ASTExpression::kBool_Kind:
+ case ASTNode::Kind::kBinary:
+ return this->convertBinaryExpression(expr);
+ case ASTNode::Kind::kBool:
return std::unique_ptr<Expression>(new BoolLiteral(fContext, expr.fOffset,
- ((ASTBoolLiteral&) expr).fValue));
- case ASTExpression::kInt_Kind:
- return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset,
- ((ASTIntLiteral&) expr).fValue));
- case ASTExpression::kFloat_Kind:
+ expr.getBool()));
+ case ASTNode::Kind::kCall:
+ return this->convertCallExpression(expr);
+ case ASTNode::Kind::kField:
+ return this->convertFieldExpression(expr);
+ case ASTNode::Kind::kFloat:
return std::unique_ptr<Expression>(new FloatLiteral(fContext, expr.fOffset,
- ((ASTFloatLiteral&) expr).fValue));
- case ASTExpression::kBinary_Kind:
- return this->convertBinaryExpression((ASTBinaryExpression&) expr);
- case ASTExpression::kNull_Kind:
+ expr.getFloat()));
+ case ASTNode::Kind::kIdentifier:
+ return this->convertIdentifier(expr);
+ case ASTNode::Kind::kIndex:
+ return this->convertIndexExpression(expr);
+ case ASTNode::Kind::kInt:
+ return std::unique_ptr<Expression>(new IntLiteral(fContext, expr.fOffset,
+ expr.getInt()));
+ case ASTNode::Kind::kNull:
return std::unique_ptr<Expression>(new NullLiteral(fContext, expr.fOffset));
- case ASTExpression::kPrefix_Kind:
- return this->convertPrefixExpression((ASTPrefixExpression&) expr);
- case ASTExpression::kSuffix_Kind:
- return this->convertSuffixExpression((ASTSuffixExpression&) expr);
- case ASTExpression::kTernary_Kind:
- return this->convertTernaryExpression((ASTTernaryExpression&) expr);
+ case ASTNode::Kind::kPostfix:
+ return this->convertPostfixExpression(expr);
+ case ASTNode::Kind::kPrefix:
+ return this->convertPrefixExpression(expr);
+ case ASTNode::Kind::kTernary:
+ return this->convertTernaryExpression(expr);
default:
- ABORT("unsupported expression type: %d\n", expr.fKind);
+ ABORT("unsupported expression: %s\n", expr.description().c_str());
}
}
-std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier& identifier) {
- const Symbol* result = (*fSymbolTable)[identifier.fText];
+std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTNode& identifier) {
+ SkASSERT(identifier.fKind == ASTNode::Kind::kIdentifier);
+ const Symbol* result = (*fSymbolTable)[identifier.getString()];
if (!result) {
- fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.fText + "'");
+ fErrors.error(identifier.fOffset, "unknown identifier '" + identifier.getString() + "'");
return nullptr;
}
switch (result->fKind) {
@@ -1165,8 +1211,10 @@
}
}
-std::unique_ptr<Section> IRGenerator::convertSection(const ASTSection& s) {
- return std::unique_ptr<Section>(new Section(s.fOffset, s.fName, s.fArgument, s.fText));
+std::unique_ptr<Section> IRGenerator::convertSection(const ASTNode& s) {
+ ASTNode::SectionData section = s.getSectionData();
+ return std::unique_ptr<Section>(new Section(s.fOffset, section.fName, section.fArgument,
+ section.fText));
}
@@ -1192,11 +1240,14 @@
args.push_back(std::move(expr));
std::unique_ptr<Expression> ctor;
if (type == *fContext.fFloatLiteral_Type) {
- ctor = this->convertIdentifier(ASTIdentifier(-1, "float"));
+ ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
+ "float"));
} else if (type == *fContext.fIntLiteral_Type) {
- ctor = this->convertIdentifier(ASTIdentifier(-1, "int"));
+ ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
+ "int"));
} else {
- ctor = this->convertIdentifier(ASTIdentifier(-1, type.fName));
+ ctor = this->convertIdentifier(ASTNode(&fFile->fNodes, -1, ASTNode::Kind::kIdentifier,
+ type.fName));
}
if (!ctor) {
printf("error, null identifier: %s\n", String(type.fName).c_str());
@@ -1550,13 +1601,14 @@
return nullptr;
}
-std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
- const ASTBinaryExpression& expression) {
- std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft);
+std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(const ASTNode& expression) {
+ SkASSERT(expression.fKind == ASTNode::Kind::kBinary);
+ auto iter = expression.begin();
+ std::unique_ptr<Expression> left = this->convertExpression(*(iter++));
if (!left) {
return nullptr;
}
- std::unique_ptr<Expression> right = this->convertExpression(*expression.fRight);
+ std::unique_ptr<Expression> right = this->convertExpression(*(iter++));
if (!right) {
return nullptr;
}
@@ -1575,49 +1627,48 @@
} else {
rawRightType = &right->fType;
}
- if (!determine_binary_type(fContext, expression.fOperator, *rawLeftType, *rawRightType,
- &leftType, &rightType, &resultType,
- !Compiler::IsAssignment(expression.fOperator))) {
+ Token::Kind op = expression.getToken().fKind;
+ if (!determine_binary_type(fContext, op, *rawLeftType, *rawRightType, &leftType, &rightType,
+ &resultType, !Compiler::IsAssignment(op))) {
fErrors.error(expression.fOffset, String("type mismatch: '") +
- Compiler::OperatorName(expression.fOperator) +
+ Compiler::OperatorName(expression.getToken().fKind) +
"' cannot operate on '" + left->fType.description() +
"', '" + right->fType.description() + "'");
return nullptr;
}
- if (Compiler::IsAssignment(expression.fOperator)) {
- this->setRefKind(*left, expression.fOperator != Token::EQ ?
- VariableReference::kReadWrite_RefKind :
- VariableReference::kWrite_RefKind);
+ if (Compiler::IsAssignment(op)) {
+ this->setRefKind(*left, op != Token::EQ ? VariableReference::kReadWrite_RefKind :
+ VariableReference::kWrite_RefKind);
}
left = this->coerce(std::move(left), *leftType);
right = this->coerce(std::move(right), *rightType);
if (!left || !right) {
return nullptr;
}
- std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator,
- *right.get());
+ std::unique_ptr<Expression> result = this->constantFold(*left.get(), op, *right.get());
if (!result) {
result = std::unique_ptr<Expression>(new BinaryExpression(expression.fOffset,
std::move(left),
- expression.fOperator,
+ op,
std::move(right),
*resultType));
}
return result;
}
-std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
- const ASTTernaryExpression& expression) {
- std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
+std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(const ASTNode& node) {
+ SkASSERT(node.fKind == ASTNode::Kind::kTernary);
+ auto iter = node.begin();
+ std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*(iter++)),
*fContext.fBool_Type);
if (!test) {
return nullptr;
}
- std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIfTrue);
+ std::unique_ptr<Expression> ifTrue = this->convertExpression(*(iter++));
if (!ifTrue) {
return nullptr;
}
- std::unique_ptr<Expression> ifFalse = this->convertExpression(*expression.fIfFalse);
+ std::unique_ptr<Expression> ifFalse = this->convertExpression(*(iter++));
if (!ifFalse) {
return nullptr;
}
@@ -1626,9 +1677,9 @@
const Type* resultType;
if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
&falseType, &resultType, true) || trueType != falseType) {
- fErrors.error(expression.fOffset, "ternary operator result mismatch: '" +
- ifTrue->fType.description() + "', '" +
- ifFalse->fType.description() + "'");
+ fErrors.error(node.fOffset, "ternary operator result mismatch: '" +
+ ifTrue->fType.description() + "', '" +
+ ifFalse->fType.description() + "'");
return nullptr;
}
ifTrue = this->coerce(std::move(ifTrue), *trueType);
@@ -1647,7 +1698,7 @@
return ifFalse;
}
}
- return std::unique_ptr<Expression>(new TernaryExpression(expression.fOffset,
+ return std::unique_ptr<Expression>(new TernaryExpression(node.fOffset,
std::move(test),
std::move(ifTrue),
std::move(ifFalse)));
@@ -1925,13 +1976,13 @@
}
}
-std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
- const ASTPrefixExpression& expression) {
- std::unique_ptr<Expression> base = this->convertExpression(*expression.fOperand);
+std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode& expression) {
+ SkASSERT(expression.fKind == ASTNode::Kind::kPrefix);
+ std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
if (!base) {
return nullptr;
}
- switch (expression.fOperator) {
+ switch (expression.getToken().fKind) {
case Token::PLUS:
if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind &&
base->fType != *fContext.fFloatLiteral_Type) {
@@ -1959,7 +2010,7 @@
case Token::PLUSPLUS:
if (!base->fType.isNumber()) {
fErrors.error(expression.fOffset,
- String("'") + Compiler::OperatorName(expression.fOperator) +
+ String("'") + Compiler::OperatorName(expression.getToken().fKind) +
"' cannot operate on '" + base->fType.description() + "'");
return nullptr;
}
@@ -1968,7 +2019,7 @@
case Token::MINUSMINUS:
if (!base->fType.isNumber()) {
fErrors.error(expression.fOffset,
- String("'") + Compiler::OperatorName(expression.fOperator) +
+ String("'") + Compiler::OperatorName(expression.getToken().fKind) +
"' cannot operate on '" + base->fType.description() + "'");
return nullptr;
}
@@ -1977,7 +2028,7 @@
case Token::LOGICALNOT:
if (base->fType != *fContext.fBool_Type) {
fErrors.error(expression.fOffset,
- String("'") + Compiler::OperatorName(expression.fOperator) +
+ String("'") + Compiler::OperatorName(expression.getToken().fKind) +
"' cannot operate on '" + base->fType.description() + "'");
return nullptr;
}
@@ -1989,7 +2040,7 @@
case Token::BITWISENOT:
if (base->fType != *fContext.fInt_Type) {
fErrors.error(expression.fOffset,
- String("'") + Compiler::OperatorName(expression.fOperator) +
+ String("'") + Compiler::OperatorName(expression.getToken().fKind) +
"' cannot operate on '" + base->fType.description() + "'");
return nullptr;
}
@@ -1997,21 +2048,19 @@
default:
ABORT("unsupported prefix operator\n");
}
- return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator,
+ return std::unique_ptr<Expression>(new PrefixExpression(expression.getToken().fKind,
std::move(base)));
}
std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression> base,
- const ASTExpression& index) {
+ const ASTNode& index) {
if (base->fKind == Expression::kTypeReference_Kind) {
- if (index.fKind == ASTExpression::kInt_Kind) {
+ if (index.fKind == ASTNode::Kind::kInt) {
const Type& oldType = ((TypeReference&) *base).fValue;
- int64_t size = ((const ASTIntLiteral&) index).fValue;
+ SKSL_INT size = index.getInt();
Type* newType = (Type*) fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
new Type(oldType.name() + "[" + to_string(size) + "]",
- Type::kArray_Kind,
- oldType,
- size)));
+ Type::kArray_Kind, oldType, size)));
return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
*newType));
@@ -2158,7 +2207,8 @@
if (e->fKind == ProgramElement::kEnum_Kind && type.name() == ((Enum&) *e).fTypeName) {
std::shared_ptr<SymbolTable> old = fSymbolTable;
fSymbolTable = ((Enum&) *e).fSymbols;
- result = convertIdentifier(ASTIdentifier(offset, field));
+ result = convertIdentifier(ASTNode(&fFile->fNodes, offset, ASTNode::Kind::kIdentifier,
+ field));
fSymbolTable = old;
}
}
@@ -2170,13 +2220,13 @@
}
std::unique_ptr<Expression> IRGenerator::convertAppend(int offset,
- const std::vector<std::unique_ptr<ASTExpression>>& args) {
+ const std::vector<ASTNode>& args) {
#ifndef SKSL_STANDALONE
if (args.size() < 2) {
fErrors.error(offset, "'append' requires at least two arguments");
return nullptr;
}
- std::unique_ptr<Expression> pipeline = this->convertExpression(*args[0]);
+ std::unique_ptr<Expression> pipeline = this->convertExpression(args[0]);
if (!pipeline) {
return nullptr;
}
@@ -2184,16 +2234,16 @@
fErrors.error(offset, "first argument of 'append' must have type 'SkRasterPipeline'");
return nullptr;
}
- if (ASTExpression::kIdentifier_Kind != args[1]->fKind) {
- fErrors.error(offset, "'" + args[1]->description() + "' is not a valid stage");
+ if (ASTNode::Kind::kIdentifier != args[1].fKind) {
+ fErrors.error(offset, "'" + args[1].description() + "' is not a valid stage");
return nullptr;
}
- StringFragment name = ((const ASTIdentifier&) *args[1]).fText;
+ StringFragment name = args[1].getString();
SkRasterPipeline::StockStage stage = SkRasterPipeline::premul;
std::vector<std::unique_ptr<Expression>> stageArgs;
stageArgs.push_back(std::move(pipeline));
for (size_t i = 2; i < args.size(); ++i) {
- std::unique_ptr<Expression> arg = this->convertExpression(*args[i]);
+ std::unique_ptr<Expression> arg = this->convertExpression(args[i]);
if (!arg) {
return nullptr;
}
@@ -2254,96 +2304,93 @@
#endif
}
-std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
- const ASTSuffixExpression& expression) {
- std::unique_ptr<Expression> base = this->convertExpression(*expression.fBase);
+std::unique_ptr<Expression> IRGenerator::convertIndexExpression(const ASTNode& index) {
+ SkASSERT(index.fKind == ASTNode::Kind::kIndex);
+ auto iter = index.begin();
+ std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
if (!base) {
return nullptr;
}
- switch (expression.fSuffix->fKind) {
- case ASTSuffix::kIndex_Kind: {
- const ASTExpression* expr = ((ASTIndexSuffix&) *expression.fSuffix).fExpression.get();
- if (expr) {
- return this->convertIndex(std::move(base), *expr);
- } else if (base->fKind == Expression::kTypeReference_Kind) {
- const Type& oldType = ((TypeReference&) *base).fValue;
- Type* newType = (Type*) fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
+ if (iter != index.end()) {
+ return this->convertIndex(std::move(base), *(iter++));
+ } else if (base->fKind == Expression::kTypeReference_Kind) {
+ const Type& oldType = ((TypeReference&) *base).fValue;
+ Type* newType = (Type*) fSymbolTable->takeOwnership(std::unique_ptr<Symbol>(
new Type(oldType.name() + "[]",
Type::kArray_Kind,
oldType,
-1)));
- return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
- *newType));
- } else {
- fErrors.error(expression.fOffset, "'[]' must follow a type name");
- return nullptr;
- }
- }
- case ASTSuffix::kCall_Kind: {
- auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
- if (Expression::kFunctionReference_Kind == base->fKind &&
- "append" == ((const FunctionReference&) *base).fFunctions[0]->fName) {
- return convertAppend(expression.fOffset, *rawArguments);
- }
- std::vector<std::unique_ptr<Expression>> arguments;
- for (size_t i = 0; i < rawArguments->size(); i++) {
- std::unique_ptr<Expression> converted =
- this->convertExpression(*(*rawArguments)[i]);
- if (!converted) {
- return nullptr;
- }
- arguments.push_back(std::move(converted));
- }
- return this->call(expression.fOffset, std::move(base), std::move(arguments));
- }
- case ASTSuffix::kField_Kind: {
- StringFragment field = ((ASTFieldSuffix&) *expression.fSuffix).fField;
- if (base->fType == *fContext.fSkCaps_Type) {
- return this->getCap(expression.fOffset, field);
- }
- if (base->fType == *fContext.fSkArgs_Type) {
- return this->getArg(expression.fOffset, field);
- }
- if (base->fKind == Expression::kTypeReference_Kind) {
- return this->convertTypeField(base->fOffset, ((TypeReference&) *base).fValue,
- field);
- }
- if (base->fKind == Expression::kExternalValue_Kind) {
- return this->convertField(std::move(base), field);
- }
- switch (base->fType.kind()) {
- case Type::kVector_Kind:
- return this->convertSwizzle(std::move(base), field);
- case Type::kOther_Kind:
- case Type::kStruct_Kind:
- return this->convertField(std::move(base), field);
- default:
- fErrors.error(base->fOffset, "cannot swizzle value of type '" +
- base->fType.description() + "'");
- return nullptr;
- }
- }
- case ASTSuffix::kPostIncrement_Kind:
- if (!base->fType.isNumber()) {
- fErrors.error(expression.fOffset,
- "'++' cannot operate on '" + base->fType.description() + "'");
- return nullptr;
- }
- this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
- return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
- Token::PLUSPLUS));
- case ASTSuffix::kPostDecrement_Kind:
- if (!base->fType.isNumber()) {
- fErrors.error(expression.fOffset,
- "'--' cannot operate on '" + base->fType.description() + "'");
- return nullptr;
- }
- this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
- return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
- Token::MINUSMINUS));
- default:
- ABORT("unsupported suffix operator");
+ return std::unique_ptr<Expression>(new TypeReference(fContext, base->fOffset,
+ *newType));
}
+ fErrors.error(index.fOffset, "'[]' must follow a type name");
+ return nullptr;
+}
+
+std::unique_ptr<Expression> IRGenerator::convertCallExpression(const ASTNode& callNode) {
+ SkASSERT(callNode.fKind == ASTNode::Kind::kCall);
+ auto iter = callNode.begin();
+ std::unique_ptr<Expression> base = this->convertExpression(*(iter++));
+ if (!base) {
+ return nullptr;
+ }
+ std::vector<std::unique_ptr<Expression>> arguments;
+ for (; iter != callNode.end(); ++iter) {
+ std::unique_ptr<Expression> converted = this->convertExpression(*iter);
+ if (!converted) {
+ return nullptr;
+ }
+ arguments.push_back(std::move(converted));
+ }
+ return this->call(callNode.fOffset, std::move(base), std::move(arguments));
+}
+
+std::unique_ptr<Expression> IRGenerator::convertFieldExpression(const ASTNode& fieldNode) {
+ std::unique_ptr<Expression> base = this->convertExpression(*fieldNode.begin());
+ if (!base) {
+ return nullptr;
+ }
+ StringFragment field = fieldNode.getString();
+ if (base->fType == *fContext.fSkCaps_Type) {
+ return this->getCap(fieldNode.fOffset, field);
+ }
+ if (base->fType == *fContext.fSkArgs_Type) {
+ return this->getArg(fieldNode.fOffset, field);
+ }
+ if (base->fKind == Expression::kTypeReference_Kind) {
+ return this->convertTypeField(base->fOffset, ((TypeReference&) *base).fValue,
+ field);
+ }
+ if (base->fKind == Expression::kExternalValue_Kind) {
+ return this->convertField(std::move(base), field);
+ }
+ switch (base->fType.kind()) {
+ case Type::kVector_Kind:
+ return this->convertSwizzle(std::move(base), field);
+ case Type::kOther_Kind:
+ case Type::kStruct_Kind:
+ return this->convertField(std::move(base), field);
+ default:
+ fErrors.error(base->fOffset, "cannot swizzle value of type '" +
+ base->fType.description() + "'");
+ return nullptr;
+ }
+}
+
+std::unique_ptr<Expression> IRGenerator::convertPostfixExpression(const ASTNode& expression) {
+ std::unique_ptr<Expression> base = this->convertExpression(*expression.begin());
+ if (!base) {
+ return nullptr;
+ }
+ if (!base->fType.isNumber()) {
+ fErrors.error(expression.fOffset,
+ "'" + String(Compiler::OperatorName(expression.getToken().fKind)) +
+ "' cannot operate on '" + base->fType.description() + "'");
+ return nullptr;
+ }
+ this->setRefKind(*base, VariableReference::kReadWrite_RefKind);
+ return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
+ expression.getToken().fKind));
}
void IRGenerator::checkValid(const Expression& expr) {
@@ -2431,55 +2478,54 @@
fKind = kind;
fProgramElements = out;
Parser parser(text, length, types, fErrors);
- std::vector<std::unique_ptr<ASTDeclaration>> parsed = parser.file();
+ fFile = parser.file();
if (fErrors.errorCount()) {
return;
}
- for (size_t i = 0; i < parsed.size(); i++) {
- ASTDeclaration& decl = *parsed[i];
+ SkASSERT(fFile);
+ for (const auto& decl : fFile->root()) {
switch (decl.fKind) {
- case ASTDeclaration::kVar_Kind: {
+ case ASTNode::Kind::kVarDeclarations: {
std::unique_ptr<VarDeclarations> s = this->convertVarDeclarations(
- (ASTVarDeclarations&) decl,
+ decl,
Variable::kGlobal_Storage);
if (s) {
fProgramElements->push_back(std::move(s));
}
break;
}
- case ASTDeclaration::kEnum_Kind: {
- this->convertEnum((ASTEnum&) decl);
+ case ASTNode::Kind::kEnum: {
+ this->convertEnum(decl);
break;
}
- case ASTDeclaration::kFunction_Kind: {
- this->convertFunction((ASTFunction&) decl);
+ case ASTNode::Kind::kFunction: {
+ this->convertFunction(decl);
break;
}
- case ASTDeclaration::kModifiers_Kind: {
- std::unique_ptr<ModifiersDeclaration> f = this->convertModifiersDeclaration(
- (ASTModifiersDeclaration&) decl);
+ case ASTNode::Kind::kModifiers: {
+ std::unique_ptr<ModifiersDeclaration> f = this->convertModifiersDeclaration(decl);
if (f) {
fProgramElements->push_back(std::move(f));
}
break;
}
- case ASTDeclaration::kInterfaceBlock_Kind: {
- std::unique_ptr<InterfaceBlock> i = this->convertInterfaceBlock(
- (ASTInterfaceBlock&) decl);
+ case ASTNode::Kind::kInterfaceBlock: {
+ std::unique_ptr<InterfaceBlock> i = this->convertInterfaceBlock(decl);
if (i) {
fProgramElements->push_back(std::move(i));
}
break;
}
- case ASTDeclaration::kExtension_Kind: {
- std::unique_ptr<Extension> e = this->convertExtension((ASTExtension&) decl);
+ case ASTNode::Kind::kExtension: {
+ std::unique_ptr<Extension> e = this->convertExtension(decl.fOffset,
+ decl.getString());
if (e) {
fProgramElements->push_back(std::move(e));
}
break;
}
- case ASTDeclaration::kSection_Kind: {
- std::unique_ptr<Section> s = this->convertSection((ASTSection&) decl);
+ case ASTNode::Kind::kSection: {
+ std::unique_ptr<Section> s = this->convertSection(decl);
if (s) {
fProgramElements->push_back(std::move(s));
}
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index 00934e7..4aafaeb 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -9,33 +9,8 @@
#define SKSL_IRGENERATOR
#include "src/sksl/SkSLErrorReporter.h"
-#include "src/sksl/ast/SkSLASTBinaryExpression.h"
-#include "src/sksl/ast/SkSLASTBlock.h"
-#include "src/sksl/ast/SkSLASTBreakStatement.h"
-#include "src/sksl/ast/SkSLASTCallSuffix.h"
-#include "src/sksl/ast/SkSLASTContinueStatement.h"
-#include "src/sksl/ast/SkSLASTDiscardStatement.h"
-#include "src/sksl/ast/SkSLASTDoStatement.h"
-#include "src/sksl/ast/SkSLASTEnum.h"
-#include "src/sksl/ast/SkSLASTExpression.h"
-#include "src/sksl/ast/SkSLASTExpressionStatement.h"
-#include "src/sksl/ast/SkSLASTExtension.h"
-#include "src/sksl/ast/SkSLASTForStatement.h"
-#include "src/sksl/ast/SkSLASTFunction.h"
-#include "src/sksl/ast/SkSLASTIdentifier.h"
-#include "src/sksl/ast/SkSLASTIfStatement.h"
-#include "src/sksl/ast/SkSLASTInterfaceBlock.h"
-#include "src/sksl/ast/SkSLASTModifiersDeclaration.h"
-#include "src/sksl/ast/SkSLASTPrefixExpression.h"
-#include "src/sksl/ast/SkSLASTReturnStatement.h"
-#include "src/sksl/ast/SkSLASTSection.h"
-#include "src/sksl/ast/SkSLASTStatement.h"
-#include "src/sksl/ast/SkSLASTSuffixExpression.h"
-#include "src/sksl/ast/SkSLASTSwitchStatement.h"
-#include "src/sksl/ast/SkSLASTTernaryExpression.h"
-#include "src/sksl/ast/SkSLASTVarDeclaration.h"
-#include "src/sksl/ast/SkSLASTVarDeclarationStatement.h"
-#include "src/sksl/ast/SkSLASTWhileStatement.h"
+#include "src/sksl/SkSLASTFile.h"
+#include "src/sksl/SkSLASTNode.h"
#include "src/sksl/ir/SkSLBlock.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLExtension.h"
@@ -103,15 +78,14 @@
void pushSymbolTable();
void popSymbolTable();
- std::unique_ptr<VarDeclarations> convertVarDeclarations(const ASTVarDeclarations& decl,
+ std::unique_ptr<VarDeclarations> convertVarDeclarations(const ASTNode& decl,
Variable::Storage storage);
- void convertFunction(const ASTFunction& f);
- std::unique_ptr<Statement> convertStatement(const ASTStatement& statement);
- std::unique_ptr<Expression> convertExpression(const ASTExpression& expression);
- std::unique_ptr<ModifiersDeclaration> convertModifiersDeclaration(
- const ASTModifiersDeclaration& m);
+ void convertFunction(const ASTNode& f);
+ std::unique_ptr<Statement> convertStatement(const ASTNode& statement);
+ std::unique_ptr<Expression> convertExpression(const ASTNode& expression);
+ std::unique_ptr<ModifiersDeclaration> convertModifiersDeclaration(const ASTNode& m);
- const Type* convertType(const ASTType& type);
+ const Type* convertType(const ASTNode& type);
std::unique_ptr<Expression> call(int offset,
const FunctionDeclaration& function,
std::vector<std::unique_ptr<Expression>> arguments);
@@ -121,10 +95,9 @@
std::vector<std::unique_ptr<Expression>> arguments);
int coercionCost(const Expression& expr, const Type& type);
std::unique_ptr<Expression> coerce(std::unique_ptr<Expression> expr, const Type& type);
- std::unique_ptr<Expression> convertAppend(int offset,
- const std::vector<std::unique_ptr<ASTExpression>>& args);
- std::unique_ptr<Block> convertBlock(const ASTBlock& block);
- std::unique_ptr<Statement> convertBreak(const ASTBreakStatement& b);
+ std::unique_ptr<Expression> convertAppend(int offset, const std::vector<ASTNode>& args);
+ std::unique_ptr<Block> convertBlock(const ASTNode& block);
+ std::unique_ptr<Statement> convertBreak(const ASTNode& b);
std::unique_ptr<Expression> convertNumberConstructor(
int offset,
const Type& type,
@@ -136,35 +109,38 @@
std::unique_ptr<Expression> convertConstructor(int offset,
const Type& type,
std::vector<std::unique_ptr<Expression>> params);
- std::unique_ptr<Statement> convertContinue(const ASTContinueStatement& c);
- std::unique_ptr<Statement> convertDiscard(const ASTDiscardStatement& d);
- std::unique_ptr<Statement> convertDo(const ASTDoStatement& d);
- std::unique_ptr<Statement> convertSwitch(const ASTSwitchStatement& s);
- std::unique_ptr<Expression> convertBinaryExpression(const ASTBinaryExpression& expression);
- std::unique_ptr<Extension> convertExtension(const ASTExtension& e);
- std::unique_ptr<Statement> convertExpressionStatement(const ASTExpressionStatement& s);
- std::unique_ptr<Statement> convertFor(const ASTForStatement& f);
- std::unique_ptr<Expression> convertIdentifier(const ASTIdentifier& identifier);
- std::unique_ptr<Statement> convertIf(const ASTIfStatement& s);
+ std::unique_ptr<Statement> convertContinue(const ASTNode& c);
+ std::unique_ptr<Statement> convertDiscard(const ASTNode& d);
+ std::unique_ptr<Statement> convertDo(const ASTNode& d);
+ std::unique_ptr<Statement> convertSwitch(const ASTNode& s);
+ std::unique_ptr<Expression> convertBinaryExpression(const ASTNode& expression);
+ std::unique_ptr<Extension> convertExtension(int offset, StringFragment name);
+ std::unique_ptr<Statement> convertExpressionStatement(const ASTNode& s);
+ std::unique_ptr<Statement> convertFor(const ASTNode& f);
+ std::unique_ptr<Expression> convertIdentifier(const ASTNode& identifier);
+ std::unique_ptr<Statement> convertIf(const ASTNode& s);
std::unique_ptr<Expression> convertIndex(std::unique_ptr<Expression> base,
- const ASTExpression& index);
- std::unique_ptr<InterfaceBlock> convertInterfaceBlock(const ASTInterfaceBlock& s);
+ const ASTNode& index);
+ std::unique_ptr<InterfaceBlock> convertInterfaceBlock(const ASTNode& s);
Modifiers convertModifiers(const Modifiers& m);
- std::unique_ptr<Expression> convertPrefixExpression(const ASTPrefixExpression& expression);
- std::unique_ptr<Statement> convertReturn(const ASTReturnStatement& r);
- std::unique_ptr<Section> convertSection(const ASTSection& e);
+ std::unique_ptr<Expression> convertPrefixExpression(const ASTNode& expression);
+ std::unique_ptr<Statement> convertReturn(const ASTNode& r);
+ std::unique_ptr<Section> convertSection(const ASTNode& e);
std::unique_ptr<Expression> getCap(int offset, String name);
- std::unique_ptr<Expression> convertSuffixExpression(const ASTSuffixExpression& expression);
+ std::unique_ptr<Expression> convertCallExpression(const ASTNode& expression);
+ std::unique_ptr<Expression> convertFieldExpression(const ASTNode& expression);
+ std::unique_ptr<Expression> convertIndexExpression(const ASTNode& expression);
+ std::unique_ptr<Expression> convertPostfixExpression(const ASTNode& expression);
std::unique_ptr<Expression> convertTypeField(int offset, const Type& type,
StringFragment field);
std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base,
StringFragment field);
std::unique_ptr<Expression> convertSwizzle(std::unique_ptr<Expression> base,
StringFragment fields);
- std::unique_ptr<Expression> convertTernaryExpression(const ASTTernaryExpression& expression);
- std::unique_ptr<Statement> convertVarDeclarationStatement(const ASTVarDeclarationStatement& s);
- std::unique_ptr<Statement> convertWhile(const ASTWhileStatement& w);
- void convertEnum(const ASTEnum& e);
+ std::unique_ptr<Expression> convertTernaryExpression(const ASTNode& expression);
+ std::unique_ptr<Statement> convertVarDeclarationStatement(const ASTNode& s);
+ std::unique_ptr<Statement> convertWhile(const ASTNode& w);
+ void convertEnum(const ASTNode& e);
std::unique_ptr<Block> applyInvocationIDWorkaround(std::unique_ptr<Block> main);
// returns a statement which converts sk_Position from device to normalized coordinates
std::unique_ptr<Statement> getNormalizeSkPositionCode();
@@ -174,6 +150,7 @@
void getConstantInt(const Expression& value, int64_t* out);
bool checkSwizzleWrite(const Swizzle& swizzle);
+ std::unique_ptr<ASTFile> fFile;
const FunctionDeclaration* fCurrentFunction;
std::unordered_map<String, Program::Settings::Value> fCapsMap;
std::shared_ptr<SymbolTable> fRootSymbolTable;
diff --git a/src/sksl/SkSLLexer.cpp b/src/sksl/SkSLLexer.cpp
index 0ec3286..2815408 100644
--- a/src/sksl/SkSLLexer.cpp
+++ b/src/sksl/SkSLLexer.cpp
@@ -1034,4 +1034,4 @@
return Token(kind, startOffset, fOffset - startOffset);
}
-} // namespace SkSL
+} // namespace
diff --git a/src/sksl/SkSLLexer.h b/src/sksl/SkSLLexer.h
index 9a16696..233ccf9 100644
--- a/src/sksl/SkSLLexer.h
+++ b/src/sksl/SkSLLexer.h
@@ -241,5 +241,5 @@
int32_t fOffset;
};
-} // namespace SkSL
+} // namespace
#endif
diff --git a/src/sksl/SkSLParser.cpp b/src/sksl/SkSLParser.cpp
index f9299fc..d260f0a 100644
--- a/src/sksl/SkSLParser.cpp
+++ b/src/sksl/SkSLParser.cpp
@@ -7,42 +7,7 @@
#include "stdio.h"
#include "src/sksl/SkSLParser.h"
-#include "src/sksl/ast/SkSLASTBinaryExpression.h"
-#include "src/sksl/ast/SkSLASTBlock.h"
-#include "src/sksl/ast/SkSLASTBoolLiteral.h"
-#include "src/sksl/ast/SkSLASTBreakStatement.h"
-#include "src/sksl/ast/SkSLASTCallSuffix.h"
-#include "src/sksl/ast/SkSLASTContinueStatement.h"
-#include "src/sksl/ast/SkSLASTDiscardStatement.h"
-#include "src/sksl/ast/SkSLASTDoStatement.h"
-#include "src/sksl/ast/SkSLASTEnum.h"
-#include "src/sksl/ast/SkSLASTExpression.h"
-#include "src/sksl/ast/SkSLASTExpressionStatement.h"
-#include "src/sksl/ast/SkSLASTExtension.h"
-#include "src/sksl/ast/SkSLASTFieldSuffix.h"
-#include "src/sksl/ast/SkSLASTFloatLiteral.h"
-#include "src/sksl/ast/SkSLASTForStatement.h"
-#include "src/sksl/ast/SkSLASTFunction.h"
-#include "src/sksl/ast/SkSLASTIdentifier.h"
-#include "src/sksl/ast/SkSLASTIfStatement.h"
-#include "src/sksl/ast/SkSLASTIndexSuffix.h"
-#include "src/sksl/ast/SkSLASTIntLiteral.h"
-#include "src/sksl/ast/SkSLASTInterfaceBlock.h"
-#include "src/sksl/ast/SkSLASTModifiersDeclaration.h"
-#include "src/sksl/ast/SkSLASTNullLiteral.h"
-#include "src/sksl/ast/SkSLASTParameter.h"
-#include "src/sksl/ast/SkSLASTPrefixExpression.h"
-#include "src/sksl/ast/SkSLASTReturnStatement.h"
-#include "src/sksl/ast/SkSLASTSection.h"
-#include "src/sksl/ast/SkSLASTStatement.h"
-#include "src/sksl/ast/SkSLASTSuffixExpression.h"
-#include "src/sksl/ast/SkSLASTSwitchCase.h"
-#include "src/sksl/ast/SkSLASTSwitchStatement.h"
-#include "src/sksl/ast/SkSLASTTernaryExpression.h"
-#include "src/sksl/ast/SkSLASTType.h"
-#include "src/sksl/ast/SkSLASTVarDeclaration.h"
-#include "src/sksl/ast/SkSLASTVarDeclarationStatement.h"
-#include "src/sksl/ast/SkSLASTWhileStatement.h"
+#include "src/sksl/SkSLASTNode.h"
#include "src/sksl/ir/SkSLModifiers.h"
#include "src/sksl/ir/SkSLSymbolTable.h"
#include "src/sksl/ir/SkSLType.h"
@@ -144,36 +109,68 @@
(void) layoutMapInitialized;
}
+#define CREATE_NODE(result, ...) \
+ ASTNode::ID result(fFile->fNodes.size()); \
+ fFile->fNodes.emplace_back(&fFile->fNodes, __VA_ARGS__)
+
+#define RETURN_NODE(...) \
+ do { \
+ CREATE_NODE(result, __VA_ARGS__); \
+ return result; \
+ } while (false)
+
+#define CREATE_CHILD(child, target, ...) \
+ CREATE_NODE(child, __VA_ARGS__); \
+ fFile->fNodes[target.fValue].addChild(child)
+
+#define CREATE_EMPTY_CHILD(target) \
+ do { \
+ ASTNode::ID child(fFile->fNodes.size()); \
+ fFile->fNodes.emplace_back(); \
+ fFile->fNodes[target.fValue].addChild(child); \
+ } while (false)
+
/* (directive | section | declaration)* END_OF_FILE */
-std::vector<std::unique_ptr<ASTDeclaration>> Parser::file() {
- std::vector<std::unique_ptr<ASTDeclaration>> result;
+std::unique_ptr<ASTFile> Parser::file() {
+ fFile.reset(new ASTFile());
+ CREATE_NODE(result, 0, ASTNode::Kind::kFile);
+ fFile->fRoot = result;
for (;;) {
switch (this->peek().fKind) {
case Token::END_OF_FILE:
- return result;
+ return std::move(fFile);
case Token::DIRECTIVE: {
- std::unique_ptr<ASTDeclaration> decl = this->directive();
- if (decl) {
- result.push_back(std::move(decl));
+ ASTNode::ID dir = this->directive();
+ if (fErrors.errorCount()) {
+ return nullptr;
+ }
+ if (dir) {
+ getNode(result).addChild(dir);
}
break;
}
case Token::SECTION: {
- std::unique_ptr<ASTDeclaration> section = this->section();
+ ASTNode::ID section = this->section();
+ if (fErrors.errorCount()) {
+ return nullptr;
+ }
if (section) {
- result.push_back(std::move(section));
+ getNode(result).addChild(section);
}
break;
}
default: {
- std::unique_ptr<ASTDeclaration> decl = this->declaration();
- if (!decl) {
- continue;
+ ASTNode::ID decl = this->declaration();
+ if (fErrors.errorCount()) {
+ return nullptr;
}
- result.push_back(std::move(decl));
+ if (decl) {
+ getNode(result).addChild(decl);
+ }
}
}
}
+ return std::move(fFile);
}
Token Parser::nextRawToken() {
@@ -254,65 +251,58 @@
/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
-std::unique_ptr<ASTDeclaration> Parser::directive() {
+ASTNode::ID Parser::directive() {
Token start;
if (!this->expect(Token::DIRECTIVE, "a directive", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
StringFragment text = this->text(start);
- if (text == "#version") {
- this->expect(Token::INT_LITERAL, "a version number");
- Token next = this->peek();
- StringFragment nextText = this->text(next);
- if (nextText == "es" || nextText == "compatibility") {
- this->nextToken();
- }
- // version is ignored for now; it will eventually become an error when we stop pretending
- // to be GLSL
- return nullptr;
- } else if (text == "#extension") {
+ if (text == "#extension") {
Token name;
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::COLON, "':'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
// FIXME: need to start paying attention to this token
if (!this->expect(Token::IDENTIFIER, "an identifier")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fOffset,
- String(this->text(name))));
+ RETURN_NODE(start.fOffset, ASTNode::Kind::kExtension, this->text(name));
} else {
this->error(start, "unsupported directive '" + this->text(start) + "'");
- return nullptr;
+ return ASTNode::ID::Invalid();
}
}
/* SECTION LBRACE (LPAREN IDENTIFIER RPAREN)? <any sequence of tokens with balanced braces>
RBRACE */
-std::unique_ptr<ASTDeclaration> Parser::section() {
+ASTNode::ID Parser::section() {
Token start;
if (!this->expect(Token::SECTION, "a section token", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- String argument;
+ StringFragment argument;
if (this->peek().fKind == Token::LPAREN) {
this->nextToken();
Token argToken;
if (!this->expect(Token::IDENTIFIER, "an identifier", &argToken)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
argument = this->text(argToken);
if (!this->expect(Token::RPAREN, "')'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
}
if (!this->expect(Token::LBRACE, "'{'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- String text;
+ StringFragment text;
+ Token codeStart = this->nextRawToken();
+ size_t startOffset = codeStart.fOffset;
+ this->pushback(codeStart);
+ text.fChars = fText + startOffset;
int level = 1;
for (;;) {
Token next = this->nextRawToken();
@@ -325,87 +315,83 @@
break;
case Token::END_OF_FILE:
this->error(start, "reached end of file while parsing section");
- return nullptr;
+ return ASTNode::ID::Invalid();
default:
break;
}
if (!level) {
+ text.fLength = next.fOffset - startOffset;
break;
}
- text += this->text(next);
}
StringFragment name = this->text(start);
++name.fChars;
--name.fLength;
- return std::unique_ptr<ASTDeclaration>(new ASTSection(start.fOffset,
- String(name),
- argument,
- text));
+ RETURN_NODE(start.fOffset, ASTNode::Kind::kSection,
+ ASTNode::SectionData(name, argument, text));
}
/* ENUM CLASS IDENTIFIER LBRACE (IDENTIFIER (EQ expression)? (COMMA IDENTIFIER (EQ expression))*)?
RBRACE */
-std::unique_ptr<ASTDeclaration> Parser::enumDeclaration() {
+ASTNode::ID Parser::enumDeclaration() {
Token start;
if (!this->expect(Token::ENUM, "'enum'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::CLASS, "'class'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token name;
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::LBRACE, "'{'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
fTypes.add(this->text(name), std::unique_ptr<Symbol>(new Type(this->text(name),
Type::kEnum_Kind)));
- std::vector<StringFragment> names;
- std::vector<std::unique_ptr<ASTExpression>> values;
+ CREATE_NODE(result, name.fOffset, ASTNode::Kind::kEnum, this->text(name));
if (!this->checkNext(Token::RBRACE)) {
Token id;
if (!this->expect(Token::IDENTIFIER, "an identifier", &id)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- names.push_back(this->text(id));
if (this->checkNext(Token::EQ)) {
- std::unique_ptr<ASTExpression> value = this->assignmentExpression();
+ ASTNode::ID value = this->assignmentExpression();
if (!value) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- values.push_back(std::move(value));
+ CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
+ getNode(child).addChild(value);
} else {
- values.push_back(nullptr);
+ CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
}
while (!this->checkNext(Token::RBRACE)) {
if (!this->expect(Token::COMMA, "','")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::IDENTIFIER, "an identifier", &id)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- names.push_back(this->text(id));
if (this->checkNext(Token::EQ)) {
- std::unique_ptr<ASTExpression> value = this->assignmentExpression();
+ ASTNode::ID value = this->assignmentExpression();
if (!value) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- values.push_back(std::move(value));
+ CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
+ getNode(child).addChild(value);
} else {
- values.push_back(nullptr);
+ CREATE_CHILD(child, result, id.fOffset, ASTNode::Kind::kEnumCase, this->text(id));
}
}
}
this->expect(Token::SEMICOLON, "';'");
- return std::unique_ptr<ASTDeclaration>(new ASTEnum(name.fOffset, this->text(name), names,
- std::move(values)));
+ return result;
}
/* enumDeclaration | modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
(COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
-std::unique_ptr<ASTDeclaration> Parser::declaration() {
+ASTNode::ID Parser::declaration() {
Token lookahead = this->peek();
if (lookahead.fKind == Token::ENUM) {
return this->enumDeclaration();
@@ -421,92 +407,98 @@
}
if (lookahead.fKind == Token::SEMICOLON) {
this->nextToken();
- return std::unique_ptr<ASTDeclaration>(new ASTModifiersDeclaration(modifiers));
+ RETURN_NODE(lookahead.fOffset, ASTNode::Kind::kModifiers, modifiers);
}
- std::unique_ptr<ASTType> type(this->type());
+ ASTNode::ID type = this->type();
if (!type) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- if (type->fKind == ASTType::kStruct_Kind && this->checkNext(Token::SEMICOLON)) {
- return nullptr;
+ if (getNode(type).getTypeData().fIsStructDeclaration && this->checkNext(Token::SEMICOLON)) {
+ return ASTNode::ID::Invalid();
}
Token name;
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (this->checkNext(Token::LPAREN)) {
- std::vector<std::unique_ptr<ASTParameter>> parameters;
- while (this->peek().fKind != Token::RPAREN) {
- if (parameters.size() > 0) {
- if (!this->expect(Token::COMMA, "','")) {
- return nullptr;
+ CREATE_NODE(result, name.fOffset, ASTNode::Kind::kFunction);
+ ASTNode::FunctionData fd(modifiers, this->text(name), 0);
+ getNode(result).addChild(type);
+ if (this->peek().fKind != Token::RPAREN) {
+ for (;;) {
+ ASTNode::ID parameter = this->parameter();
+ if (!parameter) {
+ return ASTNode::ID::Invalid();
+ }
+ ++fd.fParameterCount;
+ getNode(result).addChild(parameter);
+ if (!this->checkNext(Token::COMMA)) {
+ break;
}
}
- std::unique_ptr<ASTParameter> parameter = this->parameter();
- if (!parameter) {
- return nullptr;
- }
- parameters.push_back(std::move(parameter));
}
- this->nextToken();
- std::unique_ptr<ASTBlock> body;
+ getNode(result).setFunctionData(fd);
+ if (!this->expect(Token::RPAREN, "')'")) {
+ return ASTNode::ID::Invalid();
+ }
+ ASTNode::ID body;
if (!this->checkNext(Token::SEMICOLON)) {
body = this->block();
if (!body) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ getNode(result).addChild(body);
}
- return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fOffset,
- modifiers,
- std::move(type),
- this->text(name),
- std::move(parameters),
- std::move(body)));
+ return result;
} else {
- return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
+ return this->varDeclarationEnd(modifiers, type, this->text(name));
}
}
/* modifiers type IDENTIFIER varDeclarationEnd */
-std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() {
+ASTNode::ID Parser::varDeclarations() {
Modifiers modifiers = this->modifiers();
- std::unique_ptr<ASTType> type(this->type());
+ ASTNode::ID type = this->type();
if (!type) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token name;
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
+ return this->varDeclarationEnd(modifiers, type, this->text(name));
}
/* STRUCT IDENTIFIER LBRACE varDeclaration* RBRACE */
-std::unique_ptr<ASTType> Parser::structDeclaration() {
+ASTNode::ID Parser::structDeclaration() {
if (!this->expect(Token::STRUCT, "'struct'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token name;
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::LBRACE, "'{'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
std::vector<Type::Field> fields;
while (this->peek().fKind != Token::RBRACE) {
- std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
- if (!decl) {
- return nullptr;
+ ASTNode::ID decls = this->varDeclarations();
+ if (!decls) {
+ return ASTNode::ID::Invalid();
}
- for (const auto& var : decl->fVars) {
- auto type = (const Type*) fTypes[decl->fType->fName];
- for (int i = (int) var.fSizes.size() - 1; i >= 0; i--) {
- if (!var.fSizes[i] || var.fSizes[i]->fKind != ASTExpression::kInt_Kind) {
- this->error(decl->fOffset, "array size in struct field must be a constant");
- return nullptr;
+ ASTNode& declsNode = getNode(decls);
+ auto type = (const Type*) fTypes[(declsNode.begin() + 1)->getTypeData().fName];
+ for (auto iter = declsNode.begin() + 2; iter != declsNode.end(); ++iter) {
+ ASTNode& var = *iter;
+ ASTNode::VarData vd = var.getVarData();
+ for (int j = vd.fSizeCount - 1; j >= 0; j--) {
+ const ASTNode& size = *(var.begin() + j);
+ if (!size || size.fKind != ASTNode::Kind::kInt) {
+ this->error(declsNode.fOffset, "array size in struct field must be a constant");
+ return ASTNode::ID::Invalid();
}
- uint64_t columns = ((ASTIntLiteral&) *var.fSizes[i]).fValue;
+ uint64_t columns = size.getInt();
String name = type->name() + "[" + to_string(columns) + "]";
type = (Type*) fTypes.takeOwnership(std::unique_ptr<Symbol>(
new Type(name,
@@ -514,136 +506,134 @@
*type,
(int) columns)));
}
- fields.push_back(Type::Field(decl->fModifiers, var.fName, type));
- if (var.fValue) {
- this->error(decl->fOffset, "initializers are not permitted on struct fields");
+ fields.push_back(Type::Field(declsNode.begin()->getModifiers(), vd.fName, type));
+ if (vd.fSizeCount ? (var.begin() + (vd.fSizeCount - 1))->fNext : var.fFirstChild) {
+ this->error(declsNode.fOffset, "initializers are not permitted on struct fields");
}
}
}
if (!this->expect(Token::RBRACE, "'}'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
fTypes.add(this->text(name), std::unique_ptr<Type>(new Type(name.fOffset, this->text(name),
fields)));
- return std::unique_ptr<ASTType>(new ASTType(name.fOffset, this->text(name),
- ASTType::kStruct_Kind, std::vector<int>(), false));
+ RETURN_NODE(name.fOffset, ASTNode::Kind::kType,
+ ASTNode::TypeData(this->text(name), true, false));
}
/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
-std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(Modifiers modifiers) {
- std::unique_ptr<ASTType> type = this->structDeclaration();
+ASTNode::ID Parser::structVarDeclaration(Modifiers modifiers) {
+ ASTNode::ID type = this->structDeclaration();
if (!type) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token name;
if (this->checkNext(Token::IDENTIFIER, &name)) {
- std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers,
- std::move(type),
- this->text(name));
- if (result) {
- for (const auto& var : result->fVars) {
- if (var.fValue) {
- this->error(var.fValue->fOffset,
- "struct variables cannot be initialized");
- }
- }
- }
- return result;
+ return this->varDeclarationEnd(modifiers, std::move(type), this->text(name));
}
this->expect(Token::SEMICOLON, "';'");
- return nullptr;
+ return ASTNode::ID::Invalid();
}
/* (LBRACKET expression? RBRACKET)* (EQ assignmentExpression)? (COMMA IDENTIFER
(LBRACKET expression? RBRACKET)* (EQ assignmentExpression)?)* SEMICOLON */
-std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods,
- std::unique_ptr<ASTType> type,
- StringFragment name) {
- std::vector<ASTVarDeclaration> vars;
- std::vector<std::unique_ptr<ASTExpression>> currentVarSizes;
+ASTNode::ID Parser::varDeclarationEnd(Modifiers mods, ASTNode::ID type, StringFragment name) {
+ CREATE_NODE(result, -1, ASTNode::Kind::kVarDeclarations);
+ CREATE_CHILD(modifiers, result, -1, ASTNode::Kind::kModifiers, mods);
+ getNode(result).addChild(type);
+ CREATE_NODE(currentVar, -1, ASTNode::Kind::kVarDeclaration);
+ ASTNode::VarData vd(name, 0);
+ getNode(result).addChild(currentVar);
while (this->checkNext(Token::LBRACKET)) {
if (this->checkNext(Token::RBRACKET)) {
- currentVarSizes.push_back(nullptr);
+ CREATE_EMPTY_CHILD(currentVar);
} else {
- std::unique_ptr<ASTExpression> size(this->expression());
+ ASTNode::ID size = this->expression();
if (!size) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- currentVarSizes.push_back(std::move(size));
+ getNode(currentVar).addChild(size);
if (!this->expect(Token::RBRACKET, "']'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
}
+ ++vd.fSizeCount;
}
- std::unique_ptr<ASTExpression> value;
+ getNode(currentVar).setVarData(vd);
if (this->checkNext(Token::EQ)) {
- value = this->assignmentExpression();
+ ASTNode::ID value = this->assignmentExpression();
if (!value) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ getNode(currentVar).addChild(value);
}
- vars.emplace_back(name, std::move(currentVarSizes), std::move(value));
while (this->checkNext(Token::COMMA)) {
Token name;
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- currentVarSizes.clear();
- value.reset();
+ currentVar = ASTNode::ID(fFile->fNodes.size());
+ vd = ASTNode::VarData(this->text(name), 0);
+ fFile->fNodes.emplace_back(&fFile->fNodes, -1, ASTNode::Kind::kVarDeclaration);
+ getNode(result).addChild(currentVar);
while (this->checkNext(Token::LBRACKET)) {
if (this->checkNext(Token::RBRACKET)) {
- currentVarSizes.push_back(nullptr);
+ CREATE_EMPTY_CHILD(currentVar);
} else {
- std::unique_ptr<ASTExpression> size(this->expression());
+ ASTNode::ID size = this->expression();
if (!size) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- currentVarSizes.push_back(std::move(size));
+ getNode(currentVar).addChild(size);
if (!this->expect(Token::RBRACKET, "']'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
}
+ ++vd.fSizeCount;
}
+ getNode(currentVar).setVarData(vd);
if (this->checkNext(Token::EQ)) {
- value = this->assignmentExpression();
+ ASTNode::ID value = this->assignmentExpression();
if (!value) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ getNode(currentVar).addChild(value);
}
- vars.emplace_back(this->text(name), std::move(currentVarSizes), std::move(value));
}
if (!this->expect(Token::SEMICOLON, "';'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return std::unique_ptr<ASTVarDeclarations>(new ASTVarDeclarations(std::move(mods),
- std::move(type),
- std::move(vars)));
+ return result;
}
/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
-std::unique_ptr<ASTParameter> Parser::parameter() {
+ASTNode::ID Parser::parameter() {
Modifiers modifiers = this->modifiersWithDefaults(0);
- std::unique_ptr<ASTType> type = this->type();
+ ASTNode::ID type = this->type();
if (!type) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token name;
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::vector<int> sizes;
+ CREATE_NODE(result, name.fOffset, ASTNode::Kind::kParameter);
+ ASTNode::ParameterData pd(modifiers, this->text(name), 0);
+ getNode(result).addChild(type);
while (this->checkNext(Token::LBRACKET)) {
Token sizeToken;
if (!this->expect(Token::INT_LITERAL, "a positive integer", &sizeToken)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- sizes.push_back(SkSL::stoi(this->text(sizeToken)));
+ CREATE_CHILD(child, result, sizeToken.fOffset, ASTNode::Kind::kInt,
+ SkSL::stoi(this->text(sizeToken)));
if (!this->expect(Token::RBRACKET, "']'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ ++pd.fSizeCount;
}
- return std::unique_ptr<ASTParameter>(new ASTParameter(name.fOffset, modifiers, std::move(type),
- this->text(name), std::move(sizes)));
+ getNode(result).setParameterData(pd);
+ return result;
}
/** EQ INT_LITERAL */
@@ -672,13 +662,14 @@
/** EQ <any sequence of tokens with balanced parentheses and no top-level comma> */
-String Parser::layoutCode() {
+StringFragment Parser::layoutCode() {
if (!this->expect(Token::EQ, "'='")) {
return "";
}
Token start = this->nextRawToken();
this->pushback(start);
- String code;
+ StringFragment code;
+ code.fChars = fText + start.fOffset;
int level = 1;
bool done = false;
while (!done) {
@@ -705,11 +696,9 @@
done = true;
}
if (done) {
+ code.fLength = next.fOffset - start.fOffset;
this->pushback(std::move(next));
}
- else {
- code += this->text(next);
- }
}
return code;
}
@@ -778,7 +767,7 @@
Layout::Primitive primitive = Layout::kUnspecified_Primitive;
int maxVertices = -1;
int invocations = -1;
- String when;
+ StringFragment when;
Layout::Key key = Layout::kNo_Key;
Layout::CType ctype = Layout::CType::kDefault;
if (this->checkNext(Token::LAYOUT)) {
@@ -1024,7 +1013,7 @@
}
/* ifStatement | forStatement | doStatement | whileStatement | block | expression */
-std::unique_ptr<ASTStatement> Parser::statement() {
+ASTNode::ID Parser::statement() {
Token start = this->peek();
switch (start.fKind) {
case Token::IF: // fall through
@@ -1051,23 +1040,12 @@
return this->block();
case Token::SEMICOLON:
this->nextToken();
- return std::unique_ptr<ASTStatement>(new ASTBlock(start.fOffset,
- std::vector<std::unique_ptr<ASTStatement>>()));
- case Token::CONST: {
- auto decl = this->varDeclarations();
- if (!decl) {
- return nullptr;
- }
- return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(std::move(decl)));
- }
+ RETURN_NODE(start.fOffset, ASTNode::Kind::kBlock);
+ case Token::CONST:
+ return this->varDeclarations();
case Token::IDENTIFIER:
if (this->isType(this->text(start))) {
- auto decl = this->varDeclarations();
- if (!decl) {
- return nullptr;
- }
- return std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
- std::move(decl)));
+ return this->varDeclarations();
}
// fall through
default:
@@ -1076,227 +1054,232 @@
}
/* IDENTIFIER(type) (LBRACKET intLiteral? RBRACKET)* QUESTION? */
-std::unique_ptr<ASTType> Parser::type() {
+ASTNode::ID Parser::type() {
Token type;
if (!this->expect(Token::IDENTIFIER, "a type", &type)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->isType(this->text(type))) {
this->error(type, ("no type named '" + this->text(type) + "'").c_str());
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::vector<int> sizes;
+ CREATE_NODE(result, type.fOffset, ASTNode::Kind::kType);
+ ASTNode::TypeData td(this->text(type), false, false);
while (this->checkNext(Token::LBRACKET)) {
if (this->peek().fKind != Token::RBRACKET) {
- int64_t i;
+ SKSL_INT i;
if (this->intLiteral(&i)) {
- sizes.push_back(i);
+ CREATE_CHILD(child, result, -1, ASTNode::Kind::kInt, i);
} else {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
} else {
- sizes.push_back(-1);
+ CREATE_EMPTY_CHILD(result);
}
this->expect(Token::RBRACKET, "']'");
}
- bool nullable = this->checkNext(Token::QUESTION);
- return std::unique_ptr<ASTType>(new ASTType(type.fOffset, this->text(type),
- ASTType::kIdentifier_Kind, sizes, nullable));
+ td.fIsNullable = this->checkNext(Token::QUESTION);
+ getNode(result).setTypeData(td);
+ return result;
}
/* IDENTIFIER LBRACE varDeclaration* RBRACE (IDENTIFIER (LBRACKET expression? RBRACKET)*)? */
-std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) {
+ASTNode::ID Parser::interfaceBlock(Modifiers mods) {
Token name;
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (peek().fKind != Token::LBRACE) {
// we only get into interfaceBlock if we found a top-level identifier which was not a type.
// 99% of the time, the user was not actually intending to create an interface block, so
// it's better to report it as an unknown type
this->error(name, "no type named '" + this->text(name) + "'");
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ CREATE_NODE(result, name.fOffset, ASTNode::Kind::kInterfaceBlock);
+ ASTNode::InterfaceBlockData id(mods, this->text(name), 0, "", 0);
this->nextToken();
- std::vector<std::unique_ptr<ASTVarDeclarations>> decls;
while (this->peek().fKind != Token::RBRACE) {
- std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
+ ASTNode::ID decl = this->varDeclarations();
if (!decl) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- decls.push_back(std::move(decl));
+ getNode(result).addChild(decl);
+ ++id.fDeclarationCount;
}
this->nextToken();
- std::vector<std::unique_ptr<ASTExpression>> sizes;
+ std::vector<ASTNode> sizes;
StringFragment instanceName;
Token instanceNameToken;
if (this->checkNext(Token::IDENTIFIER, &instanceNameToken)) {
+ id.fInstanceName = this->text(instanceNameToken);
while (this->checkNext(Token::LBRACKET)) {
if (this->peek().fKind != Token::RBRACKET) {
- std::unique_ptr<ASTExpression> size = this->expression();
+ ASTNode::ID size = this->expression();
if (!size) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- sizes.push_back(std::move(size));
+ getNode(result).addChild(size);
} else {
- sizes.push_back(nullptr);
+ CREATE_EMPTY_CHILD(result);
}
+ ++id.fSizeCount;
this->expect(Token::RBRACKET, "']'");
}
instanceName = this->text(instanceNameToken);
}
+ getNode(result).setInterfaceBlockData(id);
this->expect(Token::SEMICOLON, "';'");
- return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fOffset, mods,
- this->text(name),
- std::move(decls),
- instanceName,
- std::move(sizes)));
+ return result;
}
/* IF LPAREN expression RPAREN statement (ELSE statement)? */
-std::unique_ptr<ASTIfStatement> Parser::ifStatement() {
+ASTNode::ID Parser::ifStatement() {
Token start;
bool isStatic = this->checkNext(Token::STATIC_IF, &start);
if (!isStatic && !this->expect(Token::IF, "'if'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ CREATE_NODE(result, start.fOffset, ASTNode::Kind::kIf, isStatic);
if (!this->expect(Token::LPAREN, "'('")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTExpression> test(this->expression());
+ ASTNode::ID test = this->expression();
if (!test) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ getNode(result).addChild(test);
if (!this->expect(Token::RPAREN, "')'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTStatement> ifTrue(this->statement());
+ ASTNode::ID ifTrue = this->statement();
if (!ifTrue) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTStatement> ifFalse;
+ getNode(result).addChild(ifTrue);
+ ASTNode::ID ifFalse;
if (this->checkNext(Token::ELSE)) {
ifFalse = this->statement();
if (!ifFalse) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ getNode(result).addChild(ifFalse);
}
- return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fOffset,
- isStatic,
- std::move(test),
- std::move(ifTrue),
- std::move(ifFalse)));
+ return result;
}
/* DO statement WHILE LPAREN expression RPAREN SEMICOLON */
-std::unique_ptr<ASTDoStatement> Parser::doStatement() {
+ASTNode::ID Parser::doStatement() {
Token start;
if (!this->expect(Token::DO, "'do'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTStatement> statement(this->statement());
+ CREATE_NODE(result, start.fOffset, ASTNode::Kind::kDo);
+ ASTNode::ID statement = this->statement();
if (!statement) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ getNode(result).addChild(statement);
if (!this->expect(Token::WHILE, "'while'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::LPAREN, "'('")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTExpression> test(this->expression());
+ ASTNode::ID test = this->expression();
if (!test) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ getNode(result).addChild(test);
if (!this->expect(Token::RPAREN, "')'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::SEMICOLON, "';'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fOffset,
- std::move(statement),
- std::move(test)));
+ return result;
}
/* WHILE LPAREN expression RPAREN STATEMENT */
-std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
+ASTNode::ID Parser::whileStatement() {
Token start;
if (!this->expect(Token::WHILE, "'while'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::LPAREN, "'('")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTExpression> test(this->expression());
+ CREATE_NODE(result, start.fOffset, ASTNode::Kind::kWhile);
+ ASTNode::ID test = this->expression();
if (!test) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ getNode(result).addChild(test);
if (!this->expect(Token::RPAREN, "')'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTStatement> statement(this->statement());
+ ASTNode::ID statement = this->statement();
if (!statement) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fOffset,
- std::move(test),
- std::move(statement)));
+ getNode(result).addChild(statement);
+ return result;
}
/* CASE expression COLON statement* */
-std::unique_ptr<ASTSwitchCase> Parser::switchCase() {
+ASTNode::ID Parser::switchCase() {
Token start;
if (!this->expect(Token::CASE, "'case'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTExpression> value = this->expression();
+ CREATE_NODE(result, start.fOffset, ASTNode::Kind::kSwitchCase);
+ ASTNode::ID value = this->expression();
if (!value) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::COLON, "':'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::vector<std::unique_ptr<ASTStatement>> statements;
+ getNode(result).addChild(value);
while (this->peek().fKind != Token::RBRACE && this->peek().fKind != Token::CASE &&
this->peek().fKind != Token::DEFAULT) {
- std::unique_ptr<ASTStatement> s = this->statement();
+ ASTNode::ID s = this->statement();
if (!s) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- statements.push_back(std::move(s));
+ getNode(result).addChild(s);
}
- return std::unique_ptr<ASTSwitchCase>(new ASTSwitchCase(start.fOffset, std::move(value),
- std::move(statements)));
+ return result;
}
/* SWITCH LPAREN expression RPAREN LBRACE switchCase* (DEFAULT COLON statement*)? RBRACE */
-std::unique_ptr<ASTStatement> Parser::switchStatement() {
+ASTNode::ID Parser::switchStatement() {
Token start;
bool isStatic = this->checkNext(Token::STATIC_SWITCH, &start);
if (!isStatic && !this->expect(Token::SWITCH, "'switch'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::LPAREN, "'('")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTExpression> value(this->expression());
+ ASTNode::ID value = this->expression();
if (!value) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::RPAREN, "')'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::LBRACE, "'{'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::vector<std::unique_ptr<ASTSwitchCase>> cases;
+ CREATE_NODE(result, start.fOffset, ASTNode::Kind::kSwitch, isStatic);
+ getNode(result).addChild(value);
while (this->peek().fKind == Token::CASE) {
- std::unique_ptr<ASTSwitchCase> c = this->switchCase();
+ ASTNode::ID c = this->switchCase();
if (!c) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- cases.push_back(std::move(c));
+ getNode(result).addChild(c);
}
// Requiring default: to be last (in defiance of C and GLSL) was a deliberate decision. Other
// parts of the compiler may rely upon this assumption.
@@ -1304,218 +1287,215 @@
Token defaultStart;
SkAssertResult(this->expect(Token::DEFAULT, "'default'", &defaultStart));
if (!this->expect(Token::COLON, "':'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::vector<std::unique_ptr<ASTStatement>> statements;
+ CREATE_CHILD(defaultCase, result, defaultStart.fOffset, ASTNode::Kind::kSwitchCase);
+ CREATE_EMPTY_CHILD(defaultCase); // empty test to signify default case
while (this->peek().fKind != Token::RBRACE) {
- std::unique_ptr<ASTStatement> s = this->statement();
+ ASTNode::ID s = this->statement();
if (!s) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- statements.push_back(std::move(s));
+ getNode(defaultCase).addChild(s);
}
- cases.emplace_back(new ASTSwitchCase(defaultStart.fOffset, nullptr,
- std::move(statements)));
}
if (!this->expect(Token::RBRACE, "'}'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return std::unique_ptr<ASTStatement>(new ASTSwitchStatement(start.fOffset,
- isStatic,
- std::move(value),
- std::move(cases)));
+ return result;
}
/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
STATEMENT */
-std::unique_ptr<ASTForStatement> Parser::forStatement() {
+ASTNode::ID Parser::forStatement() {
Token start;
if (!this->expect(Token::FOR, "'for'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::LPAREN, "'('")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTStatement> initializer;
+ CREATE_NODE(result, start.fOffset, ASTNode::Kind::kFor);
+ ASTNode::ID initializer;
Token nextToken = this->peek();
switch (nextToken.fKind) {
case Token::SEMICOLON:
this->nextToken();
+ CREATE_EMPTY_CHILD(result);
break;
case Token::CONST: {
- std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
- if (!vd) {
- return nullptr;
+ initializer = this->varDeclarations();
+ if (!initializer) {
+ return ASTNode::ID::Invalid();
}
- initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
- std::move(vd)));
+ getNode(result).addChild(initializer);
break;
}
case Token::IDENTIFIER: {
if (this->isType(this->text(nextToken))) {
- std::unique_ptr<ASTVarDeclarations> vd = this->varDeclarations();
- if (!vd) {
- return nullptr;
+ initializer = this->varDeclarations();
+ if (!initializer) {
+ return ASTNode::ID::Invalid();
}
- initializer = std::unique_ptr<ASTStatement>(new ASTVarDeclarationStatement(
- std::move(vd)));
+ getNode(result).addChild(initializer);
break;
}
} // fall through
default:
initializer = this->expressionStatement();
+ if (!initializer) {
+ return ASTNode::ID::Invalid();
+ }
+ getNode(result).addChild(initializer);
}
- std::unique_ptr<ASTExpression> test;
+ ASTNode::ID test;
if (this->peek().fKind != Token::SEMICOLON) {
test = this->expression();
if (!test) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ getNode(result).addChild(test);
+ } else {
+ CREATE_EMPTY_CHILD(result);
}
if (!this->expect(Token::SEMICOLON, "';'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTExpression> next;
+ ASTNode::ID next;
if (this->peek().fKind != Token::RPAREN) {
next = this->expression();
if (!next) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ getNode(result).addChild(next);
+ } else {
+ CREATE_EMPTY_CHILD(result);
}
if (!this->expect(Token::RPAREN, "')'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTStatement> statement(this->statement());
+ ASTNode::ID statement = this->statement();
if (!statement) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fOffset,
- std::move(initializer),
- std::move(test), std::move(next),
- std::move(statement)));
+ getNode(result).addChild(statement);
+ return result;
}
/* RETURN expression? SEMICOLON */
-std::unique_ptr<ASTReturnStatement> Parser::returnStatement() {
+ASTNode::ID Parser::returnStatement() {
Token start;
if (!this->expect(Token::RETURN, "'return'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::unique_ptr<ASTExpression> expression;
+ CREATE_NODE(result, start.fOffset, ASTNode::Kind::kReturn);
if (this->peek().fKind != Token::SEMICOLON) {
- expression = this->expression();
+ ASTNode::ID expression = this->expression();
if (!expression) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
+ getNode(result).addChild(expression);
}
if (!this->expect(Token::SEMICOLON, "';'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fOffset,
- std::move(expression)));
+ return result;
}
/* BREAK SEMICOLON */
-std::unique_ptr<ASTBreakStatement> Parser::breakStatement() {
+ASTNode::ID Parser::breakStatement() {
Token start;
if (!this->expect(Token::BREAK, "'break'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::SEMICOLON, "';'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return std::unique_ptr<ASTBreakStatement>(new ASTBreakStatement(start.fOffset));
+ RETURN_NODE(start.fOffset, ASTNode::Kind::kBreak);
}
/* CONTINUE SEMICOLON */
-std::unique_ptr<ASTContinueStatement> Parser::continueStatement() {
+ASTNode::ID Parser::continueStatement() {
Token start;
if (!this->expect(Token::CONTINUE, "'continue'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::SEMICOLON, "';'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return std::unique_ptr<ASTContinueStatement>(new ASTContinueStatement(start.fOffset));
+ RETURN_NODE(start.fOffset, ASTNode::Kind::kContinue);
}
/* DISCARD SEMICOLON */
-std::unique_ptr<ASTDiscardStatement> Parser::discardStatement() {
+ASTNode::ID Parser::discardStatement() {
Token start;
if (!this->expect(Token::DISCARD, "'continue'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (!this->expect(Token::SEMICOLON, "';'")) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return std::unique_ptr<ASTDiscardStatement>(new ASTDiscardStatement(start.fOffset));
+ RETURN_NODE(start.fOffset, ASTNode::Kind::kDiscard);
}
/* LBRACE statement* RBRACE */
-std::unique_ptr<ASTBlock> Parser::block() {
+ASTNode::ID Parser::block() {
AutoDepth depth(this);
if (!depth.checkValid()) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token start;
if (!this->expect(Token::LBRACE, "'{'", &start)) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- std::vector<std::unique_ptr<ASTStatement>> statements;
+ CREATE_NODE(result, start.fOffset, ASTNode::Kind::kBlock);
for (;;) {
switch (this->peek().fKind) {
case Token::RBRACE:
this->nextToken();
- return std::unique_ptr<ASTBlock>(new ASTBlock(start.fOffset,
- std::move(statements)));
+ return result;
case Token::END_OF_FILE:
this->error(this->peek(), "expected '}', but found end of file");
- return nullptr;
+ return ASTNode::ID::Invalid();
default: {
- std::unique_ptr<ASTStatement> statement = this->statement();
+ ASTNode::ID statement = this->statement();
if (!statement) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- statements.push_back(std::move(statement));
+ getNode(result).addChild(statement);
}
}
}
+ return result;
}
/* expression SEMICOLON */
-std::unique_ptr<ASTExpressionStatement> Parser::expressionStatement() {
- std::unique_ptr<ASTExpression> expr = this->expression();
+ASTNode::ID Parser::expressionStatement() {
+ ASTNode::ID expr = this->expression();
if (expr) {
if (this->expect(Token::SEMICOLON, "';'")) {
- ASTExpressionStatement* result = new ASTExpressionStatement(std::move(expr));
- return std::unique_ptr<ASTExpressionStatement>(result);
+ return expr;
}
}
- return nullptr;
-}
-
-/* commaExpression */
-std::unique_ptr<ASTExpression> Parser::expression() {
- AutoDepth depth(this);
- if (!depth.checkValid()) {
- return nullptr;
- }
- return this->commaExpression();
+ return ASTNode::ID::Invalid();
}
/* assignmentExpression (COMMA assignmentExpression)* */
-std::unique_ptr<ASTExpression> Parser::commaExpression() {
- std::unique_ptr<ASTExpression> result = this->assignmentExpression();
+ASTNode::ID Parser::expression() {
+ ASTNode::ID result = this->assignmentExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token t;
while (this->checkNext(Token::COMMA, &t)) {
- std::unique_ptr<ASTExpression> right = this->commaExpression();
+ ASTNode::ID right = this->assignmentExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t), std::move(right)));
+ CREATE_NODE(newResult, t.fOffset, ASTNode::Kind::kBinary, std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
}
return result;
}
@@ -1524,10 +1504,10 @@
BITWISEANDEQ | BITWISEXOREQ | BITWISEOREQ | LOGICALANDEQ | LOGICALXOREQ | LOGICALOREQ)
assignmentExpression)*
*/
-std::unique_ptr<ASTExpression> Parser::assignmentExpression() {
- std::unique_ptr<ASTExpression> result = this->ternaryExpression();
+ASTNode::ID Parser::assignmentExpression() {
+ ASTNode::ID result = this->ternaryExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
for (;;) {
switch (this->peek().fKind) {
@@ -1546,14 +1526,16 @@
case Token::LOGICALXOREQ: // fall through
case Token::LOGICALOREQ: {
Token t = this->nextToken();
- std::unique_ptr<ASTExpression> right = this->assignmentExpression();
+ ASTNode::ID right = this->assignmentExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result = std::unique_ptr<ASTExpression>(new ASTBinaryExpression(std::move(result),
- std::move(t),
- std::move(right)));
- return result;
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
+ std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
+ break;
}
default:
return result;
@@ -1562,145 +1544,172 @@
}
/* logicalOrExpression ('?' expression ':' assignmentExpression)? */
-std::unique_ptr<ASTExpression> Parser::ternaryExpression() {
- std::unique_ptr<ASTExpression> result = this->logicalOrExpression();
- if (!result) {
- return nullptr;
+ASTNode::ID Parser::ternaryExpression() {
+ ASTNode::ID base = this->logicalOrExpression();
+ if (!base) {
+ return ASTNode::ID::Invalid();
}
if (this->checkNext(Token::QUESTION)) {
- std::unique_ptr<ASTExpression> trueExpr = this->expression();
+ ASTNode::ID trueExpr = this->expression();
if (!trueExpr) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
if (this->expect(Token::COLON, "':'")) {
- std::unique_ptr<ASTExpression> falseExpr = this->assignmentExpression();
- return std::unique_ptr<ASTExpression>(new ASTTernaryExpression(std::move(result),
- std::move(trueExpr),
- std::move(falseExpr)));
+ ASTNode::ID falseExpr = this->assignmentExpression();
+ if (!falseExpr) {
+ return ASTNode::ID::Invalid();
+ }
+ CREATE_NODE(ternary, getNode(base).fOffset, ASTNode::Kind::kTernary);
+ getNode(ternary).addChild(base);
+ getNode(ternary).addChild(trueExpr);
+ getNode(ternary).addChild(falseExpr);
+ return ternary;
}
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return result;
+ return base;
}
/* logicalXorExpression (LOGICALOR logicalXorExpression)* */
-std::unique_ptr<ASTExpression> Parser::logicalOrExpression() {
- std::unique_ptr<ASTExpression> result = this->logicalXorExpression();
+ASTNode::ID Parser::logicalOrExpression() {
+ ASTNode::ID result = this->logicalXorExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token t;
while (this->checkNext(Token::LOGICALOR, &t)) {
- std::unique_ptr<ASTExpression> right = this->logicalXorExpression();
+ ASTNode::ID right = this->logicalXorExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t), std::move(right)));
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
}
return result;
}
/* logicalAndExpression (LOGICALXOR logicalAndExpression)* */
-std::unique_ptr<ASTExpression> Parser::logicalXorExpression() {
- std::unique_ptr<ASTExpression> result = this->logicalAndExpression();
+ASTNode::ID Parser::logicalXorExpression() {
+ ASTNode::ID result = this->logicalAndExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token t;
while (this->checkNext(Token::LOGICALXOR, &t)) {
- std::unique_ptr<ASTExpression> right = this->logicalAndExpression();
+ ASTNode::ID right = this->logicalAndExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t), std::move(right)));
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
}
return result;
}
/* bitwiseOrExpression (LOGICALAND bitwiseOrExpression)* */
-std::unique_ptr<ASTExpression> Parser::logicalAndExpression() {
- std::unique_ptr<ASTExpression> result = this->bitwiseOrExpression();
+ASTNode::ID Parser::logicalAndExpression() {
+ ASTNode::ID result = this->bitwiseOrExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token t;
while (this->checkNext(Token::LOGICALAND, &t)) {
- std::unique_ptr<ASTExpression> right = this->bitwiseOrExpression();
+ ASTNode::ID right = this->bitwiseOrExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t), std::move(right)));
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
}
return result;
}
/* bitwiseXorExpression (BITWISEOR bitwiseXorExpression)* */
-std::unique_ptr<ASTExpression> Parser::bitwiseOrExpression() {
- std::unique_ptr<ASTExpression> result = this->bitwiseXorExpression();
+ASTNode::ID Parser::bitwiseOrExpression() {
+ ASTNode::ID result = this->bitwiseXorExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token t;
while (this->checkNext(Token::BITWISEOR, &t)) {
- std::unique_ptr<ASTExpression> right = this->bitwiseXorExpression();
+ ASTNode::ID right = this->bitwiseXorExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t), std::move(right)));
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
}
return result;
}
/* bitwiseAndExpression (BITWISEXOR bitwiseAndExpression)* */
-std::unique_ptr<ASTExpression> Parser::bitwiseXorExpression() {
- std::unique_ptr<ASTExpression> result = this->bitwiseAndExpression();
+ASTNode::ID Parser::bitwiseXorExpression() {
+ ASTNode::ID result = this->bitwiseAndExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token t;
while (this->checkNext(Token::BITWISEXOR, &t)) {
- std::unique_ptr<ASTExpression> right = this->bitwiseAndExpression();
+ ASTNode::ID right = this->bitwiseAndExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t), std::move(right)));
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
}
return result;
}
/* equalityExpression (BITWISEAND equalityExpression)* */
-std::unique_ptr<ASTExpression> Parser::bitwiseAndExpression() {
- std::unique_ptr<ASTExpression> result = this->equalityExpression();
+ASTNode::ID Parser::bitwiseAndExpression() {
+ ASTNode::ID result = this->equalityExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token t;
while (this->checkNext(Token::BITWISEAND, &t)) {
- std::unique_ptr<ASTExpression> right = this->equalityExpression();
+ ASTNode::ID right = this->equalityExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t), std::move(right)));
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary, std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
}
return result;
}
/* relationalExpression ((EQEQ | NEQ) relationalExpression)* */
-std::unique_ptr<ASTExpression> Parser::equalityExpression() {
- std::unique_ptr<ASTExpression> result = this->relationalExpression();
+ASTNode::ID Parser::equalityExpression() {
+ ASTNode::ID result = this->relationalExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
for (;;) {
switch (this->peek().fKind) {
case Token::EQEQ: // fall through
case Token::NEQ: {
Token t = this->nextToken();
- std::unique_ptr<ASTExpression> right = this->relationalExpression();
+ ASTNode::ID right = this->relationalExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t), std::move(right)));
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
+ std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
break;
}
default:
@@ -1710,10 +1719,10 @@
}
/* shiftExpression ((LT | GT | LTEQ | GTEQ) shiftExpression)* */
-std::unique_ptr<ASTExpression> Parser::relationalExpression() {
- std::unique_ptr<ASTExpression> result = this->shiftExpression();
+ASTNode::ID Parser::relationalExpression() {
+ ASTNode::ID result = this->shiftExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
for (;;) {
switch (this->peek().fKind) {
@@ -1722,12 +1731,15 @@
case Token::LTEQ: // fall through
case Token::GTEQ: {
Token t = this->nextToken();
- std::unique_ptr<ASTExpression> right = this->shiftExpression();
+ ASTNode::ID right = this->shiftExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t),
- std::move(right)));
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
+ std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
break;
}
default:
@@ -1737,22 +1749,25 @@
}
/* additiveExpression ((SHL | SHR) additiveExpression)* */
-std::unique_ptr<ASTExpression> Parser::shiftExpression() {
- std::unique_ptr<ASTExpression> result = this->additiveExpression();
+ASTNode::ID Parser::shiftExpression() {
+ ASTNode::ID result = this->additiveExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
for (;;) {
switch (this->peek().fKind) {
case Token::SHL: // fall through
case Token::SHR: {
Token t = this->nextToken();
- std::unique_ptr<ASTExpression> right = this->additiveExpression();
+ ASTNode::ID right = this->additiveExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t),
- std::move(right)));
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
+ std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
break;
}
default:
@@ -1762,22 +1777,25 @@
}
/* multiplicativeExpression ((PLUS | MINUS) multiplicativeExpression)* */
-std::unique_ptr<ASTExpression> Parser::additiveExpression() {
- std::unique_ptr<ASTExpression> result = this->multiplicativeExpression();
+ASTNode::ID Parser::additiveExpression() {
+ ASTNode::ID result = this->multiplicativeExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
for (;;) {
switch (this->peek().fKind) {
case Token::PLUS: // fall through
case Token::MINUS: {
Token t = this->nextToken();
- std::unique_ptr<ASTExpression> right = this->multiplicativeExpression();
+ ASTNode::ID right = this->multiplicativeExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t),
- std::move(right)));
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
+ std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
break;
}
default:
@@ -1787,10 +1805,10 @@
}
/* unaryExpression ((STAR | SLASH | PERCENT) unaryExpression)* */
-std::unique_ptr<ASTExpression> Parser::multiplicativeExpression() {
- std::unique_ptr<ASTExpression> result = this->unaryExpression();
+ASTNode::ID Parser::multiplicativeExpression() {
+ ASTNode::ID result = this->unaryExpression();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
for (;;) {
switch (this->peek().fKind) {
@@ -1798,12 +1816,15 @@
case Token::SLASH: // fall through
case Token::PERCENT: {
Token t = this->nextToken();
- std::unique_ptr<ASTExpression> right = this->unaryExpression();
+ ASTNode::ID right = this->unaryExpression();
if (!right) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- result.reset(new ASTBinaryExpression(std::move(result), std::move(t),
- std::move(right)));
+ CREATE_NODE(newResult, getNode(result).fOffset, ASTNode::Kind::kBinary,
+ std::move(t));
+ getNode(newResult).addChild(result);
+ getNode(newResult).addChild(right);
+ result = newResult;
break;
}
default:
@@ -1813,7 +1834,7 @@
}
/* postfixExpression | (PLUS | MINUS | NOT | PLUSPLUS | MINUSMINUS) unaryExpression */
-std::unique_ptr<ASTExpression> Parser::unaryExpression() {
+ASTNode::ID Parser::unaryExpression() {
switch (this->peek().fKind) {
case Token::PLUS: // fall through
case Token::MINUS: // fall through
@@ -1823,15 +1844,16 @@
case Token::MINUSMINUS: {
AutoDepth depth(this);
if (!depth.checkValid()) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
Token t = this->nextToken();
- std::unique_ptr<ASTExpression> expr = this->unaryExpression();
+ ASTNode::ID expr = this->unaryExpression();
if (!expr) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- return std::unique_ptr<ASTExpression>(new ASTPrefixExpression(std::move(t),
- std::move(expr)));
+ CREATE_NODE(result, t.fOffset, ASTNode::Kind::kPrefix, std::move(t));
+ getNode(result).addChild(expr);
+ return result;
}
default:
return this->postfixExpression();
@@ -1839,10 +1861,10 @@
}
/* term suffix* */
-std::unique_ptr<ASTExpression> Parser::postfixExpression() {
- std::unique_ptr<ASTExpression> result = this->term();
+ASTNode::ID Parser::postfixExpression() {
+ ASTNode::ID result = this->term();
if (!result) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
for (;;) {
switch (this->peek().fKind) {
@@ -1851,14 +1873,9 @@
case Token::LPAREN: // fall through
case Token::PLUSPLUS: // fall through
case Token::MINUSMINUS: // fall through
- case Token::COLONCOLON: {
- std::unique_ptr<ASTSuffix> s = this->suffix();
- if (!s) {
- return nullptr;
- }
- result.reset(new ASTSuffixExpression(std::move(result), std::move(s)));
+ case Token::COLONCOLON:
+ result = this->suffix(result);
break;
- }
default:
return result;
}
@@ -1867,84 +1884,89 @@
/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
PLUSPLUS | MINUSMINUS | COLONCOLON IDENTIFIER */
-std::unique_ptr<ASTSuffix> Parser::suffix() {
+ASTNode::ID Parser::suffix(ASTNode::ID base) {
Token next = this->nextToken();
switch (next.fKind) {
case Token::LBRACKET: {
if (this->checkNext(Token::RBRACKET)) {
- return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(next.fOffset));
+ CREATE_NODE(result, next.fOffset, ASTNode::Kind::kIndex);
+ getNode(result).addChild(base);
+ return result;
}
- std::unique_ptr<ASTExpression> e = this->expression();
+ ASTNode::ID e = this->expression();
if (!e) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
this->expect(Token::RBRACKET, "']' to complete array access expression");
- return std::unique_ptr<ASTSuffix>(new ASTIndexSuffix(std::move(e)));
+ CREATE_NODE(result, next.fOffset, ASTNode::Kind::kIndex);
+ getNode(result).addChild(base);
+ getNode(result).addChild(e);
+ return result;
}
case Token::DOT: // fall through
case Token::COLONCOLON: {
int offset = this->peek().fOffset;
StringFragment text;
if (this->identifier(&text)) {
- return std::unique_ptr<ASTSuffix>(new ASTFieldSuffix(offset, std::move(text)));
+ CREATE_NODE(result, offset, ASTNode::Kind::kField, std::move(text));
+ getNode(result).addChild(base);
+ return result;
}
- return nullptr;
+ return ASTNode::ID::Invalid();
}
case Token::LPAREN: {
- std::vector<std::unique_ptr<ASTExpression>> parameters;
+ CREATE_NODE(result, next.fOffset, ASTNode::Kind::kCall);
+ getNode(result).addChild(base);
if (this->peek().fKind != Token::RPAREN) {
for (;;) {
- std::unique_ptr<ASTExpression> expr = this->assignmentExpression();
+ ASTNode::ID expr = this->assignmentExpression();
if (!expr) {
- return nullptr;
+ return ASTNode::ID::Invalid();
}
- parameters.push_back(std::move(expr));
+ getNode(result).addChild(expr);
if (!this->checkNext(Token::COMMA)) {
break;
}
}
}
this->expect(Token::RPAREN, "')' to complete function parameters");
- return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fOffset,
- std::move(parameters)));
+ return result;
}
- case Token::PLUSPLUS:
- return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fOffset,
- ASTSuffix::kPostIncrement_Kind));
- case Token::MINUSMINUS:
- return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fOffset,
- ASTSuffix::kPostDecrement_Kind));
+ case Token::PLUSPLUS: // fall through
+ case Token::MINUSMINUS: {
+ CREATE_NODE(result, next.fOffset, ASTNode::Kind::kPostfix, next);
+ getNode(result).addChild(base);
+ return result;
+ }
default: {
this->error(next, "expected expression suffix, but found '" + this->text(next) +
"'\n");
- return nullptr;
+ return ASTNode::ID::Invalid();
}
}
}
/* IDENTIFIER | intLiteral | floatLiteral | boolLiteral | NULL_LITERAL | '(' expression ')' */
-std::unique_ptr<ASTExpression> Parser::term() {
- std::unique_ptr<ASTExpression> result;
+ASTNode::ID Parser::term() {
Token t = this->peek();
switch (t.fKind) {
case Token::IDENTIFIER: {
StringFragment text;
if (this->identifier(&text)) {
- result.reset(new ASTIdentifier(t.fOffset, std::move(text)));
+ RETURN_NODE(t.fOffset, ASTNode::Kind::kIdentifier, std::move(text));
}
- break;
}
case Token::INT_LITERAL: {
- int64_t i;
+ SKSL_INT i;
if (this->intLiteral(&i)) {
- result.reset(new ASTIntLiteral(t.fOffset, i));
+ RETURN_NODE(t.fOffset, ASTNode::Kind::kInt, i);
}
break;
}
case Token::FLOAT_LITERAL: {
- double f;
+ SKSL_FLOAT f;
if (this->floatLiteral(&f)) {
- result.reset(new ASTFloatLiteral(t.fOffset, f));
+ RETURN_NODE(t.fOffset, ASTNode::Kind::kFloat, f);
}
break;
}
@@ -1952,32 +1974,31 @@
case Token::FALSE_LITERAL: {
bool b;
if (this->boolLiteral(&b)) {
- result.reset(new ASTBoolLiteral(t.fOffset, b));
+ RETURN_NODE(t.fOffset, ASTNode::Kind::kBool, b);
}
break;
}
case Token::NULL_LITERAL:
this->nextToken();
- result.reset(new ASTNullLiteral(t.fOffset));
- break;
+ RETURN_NODE(t.fOffset, ASTNode::Kind::kNull);
case Token::LPAREN: {
this->nextToken();
- result = this->expression();
+ ASTNode::ID result = this->expression();
if (result) {
this->expect(Token::RPAREN, "')' to complete expression");
+ return result;
}
break;
}
default:
this->nextToken();
this->error(t.fOffset, "expected expression, but found '" + this->text(t) + "'\n");
- result = nullptr;
}
- return result;
+ return ASTNode::ID::Invalid();
}
/* INT_LITERAL */
-bool Parser::intLiteral(int64_t* dest) {
+bool Parser::intLiteral(SKSL_INT* dest) {
Token t;
if (this->expect(Token::INT_LITERAL, "integer literal", &t)) {
*dest = SkSL::stol(this->text(t));
@@ -1987,7 +2008,7 @@
}
/* FLOAT_LITERAL */
-bool Parser::floatLiteral(double* dest) {
+bool Parser::floatLiteral(SKSL_FLOAT* dest) {
Token t;
if (this->expect(Token::FLOAT_LITERAL, "float literal", &t)) {
*dest = SkSL::stod(this->text(t));
diff --git a/src/sksl/SkSLParser.h b/src/sksl/SkSLParser.h
index 9f69ac5..a9eaa49 100644
--- a/src/sksl/SkSLParser.h
+++ b/src/sksl/SkSLParser.h
@@ -12,8 +12,10 @@
#include <memory>
#include <unordered_map>
#include <unordered_set>
+#include "src/sksl/SkSLASTFile.h"
#include "src/sksl/SkSLErrorReporter.h"
#include "src/sksl/SkSLLexer.h"
+#include "src/sksl/SkSLASTNode.h"
#include "src/sksl/ir/SkSLLayout.h"
struct yy_buffer_state;
@@ -22,27 +24,6 @@
namespace SkSL {
-struct ASTBlock;
-struct ASTBreakStatement;
-struct ASTContinueStatement;
-struct ASTDeclaration;
-struct ASTDiscardStatement;
-struct ASTDoStatement;
-struct ASTExpression;
-struct ASTExpressionStatement;
-struct ASTForStatement;
-struct ASTIfStatement;
-struct ASTInterfaceBlock;
-struct ASTParameter;
-struct ASTPrecision;
-struct ASTReturnStatement;
-struct ASTStatement;
-struct ASTSuffix;
-struct ASTSwitchCase;
-struct ASTSwitchStatement;
-struct ASTType;
-struct ASTWhileStatement;
-struct ASTVarDeclarations;
struct Modifiers;
class SymbolTable;
@@ -105,11 +86,10 @@
Parser(const char* text, size_t length, SymbolTable& types, ErrorReporter& errors);
/**
- * Consumes a complete .sksl file and produces a list of declarations. Errors are reported via
- * the ErrorReporter; the return value may contain some declarations even when errors have
- * occurred.
+ * Consumes a complete .sksl file and returns the parse tree. Errors are reported via the
+ * ErrorReporter; the return value may contain some declarations even when errors have occurred.
*/
- std::vector<std::unique_ptr<ASTDeclaration>> file();
+ std::unique_ptr<ASTFile> file();
StringFragment text(Token token);
@@ -166,37 +146,40 @@
*/
bool isType(StringFragment name);
+ // The pointer to the node may be invalidated by modifying the fNodes vector
+ ASTNode& getNode(ASTNode::ID id) {
+ return fFile->fNodes[id.fValue];
+ }
+
// these functions parse individual grammar rules from the current parse position; you probably
// don't need to call any of these outside of the parser. The function declarations in the .cpp
// file have comments describing the grammar rules.
- std::unique_ptr<ASTDeclaration> precision();
+ ASTNode::ID precision();
- std::unique_ptr<ASTDeclaration> directive();
+ ASTNode::ID directive();
- std::unique_ptr<ASTDeclaration> section();
+ ASTNode::ID section();
- std::unique_ptr<ASTDeclaration> enumDeclaration();
+ ASTNode::ID enumDeclaration();
- std::unique_ptr<ASTDeclaration> declaration();
+ ASTNode::ID declaration();
- std::unique_ptr<ASTVarDeclarations> varDeclarations();
+ ASTNode::ID varDeclarations();
- std::unique_ptr<ASTType> structDeclaration();
+ ASTNode::ID structDeclaration();
- std::unique_ptr<ASTVarDeclarations> structVarDeclaration(Modifiers modifiers);
+ ASTNode::ID structVarDeclaration(Modifiers modifiers);
- std::unique_ptr<ASTVarDeclarations> varDeclarationEnd(Modifiers modifiers,
- std::unique_ptr<ASTType> type,
- StringFragment name);
+ ASTNode::ID varDeclarationEnd(Modifiers modifiers, ASTNode::ID type, StringFragment name);
- std::unique_ptr<ASTParameter> parameter();
+ ASTNode::ID parameter();
int layoutInt();
StringFragment layoutIdentifier();
- String layoutCode();
+ StringFragment layoutCode();
Layout::Key layoutKey();
@@ -208,77 +191,75 @@
Modifiers modifiersWithDefaults(int defaultFlags);
- std::unique_ptr<ASTStatement> statement();
+ ASTNode::ID statement();
- std::unique_ptr<ASTType> type();
+ ASTNode::ID type();
- std::unique_ptr<ASTDeclaration> interfaceBlock(Modifiers mods);
+ ASTNode::ID interfaceBlock(Modifiers mods);
- std::unique_ptr<ASTIfStatement> ifStatement();
+ ASTNode::ID ifStatement();
- std::unique_ptr<ASTDoStatement> doStatement();
+ ASTNode::ID doStatement();
- std::unique_ptr<ASTWhileStatement> whileStatement();
+ ASTNode::ID whileStatement();
- std::unique_ptr<ASTForStatement> forStatement();
+ ASTNode::ID forStatement();
- std::unique_ptr<ASTSwitchCase> switchCase();
+ ASTNode::ID switchCase();
- std::unique_ptr<ASTStatement> switchStatement();
+ ASTNode::ID switchStatement();
- std::unique_ptr<ASTReturnStatement> returnStatement();
+ ASTNode::ID returnStatement();
- std::unique_ptr<ASTBreakStatement> breakStatement();
+ ASTNode::ID breakStatement();
- std::unique_ptr<ASTContinueStatement> continueStatement();
+ ASTNode::ID continueStatement();
- std::unique_ptr<ASTDiscardStatement> discardStatement();
+ ASTNode::ID discardStatement();
- std::unique_ptr<ASTBlock> block();
+ ASTNode::ID block();
- std::unique_ptr<ASTExpressionStatement> expressionStatement();
+ ASTNode::ID expressionStatement();
- std::unique_ptr<ASTExpression> expression();
+ ASTNode::ID expression();
- std::unique_ptr<ASTExpression> commaExpression();
+ ASTNode::ID assignmentExpression();
- std::unique_ptr<ASTExpression> assignmentExpression();
+ ASTNode::ID ternaryExpression();
- std::unique_ptr<ASTExpression> ternaryExpression();
+ ASTNode::ID logicalOrExpression();
- std::unique_ptr<ASTExpression> logicalOrExpression();
+ ASTNode::ID logicalXorExpression();
- std::unique_ptr<ASTExpression> logicalXorExpression();
+ ASTNode::ID logicalAndExpression();
- std::unique_ptr<ASTExpression> logicalAndExpression();
+ ASTNode::ID bitwiseOrExpression();
- std::unique_ptr<ASTExpression> bitwiseOrExpression();
+ ASTNode::ID bitwiseXorExpression();
- std::unique_ptr<ASTExpression> bitwiseXorExpression();
+ ASTNode::ID bitwiseAndExpression();
- std::unique_ptr<ASTExpression> bitwiseAndExpression();
+ ASTNode::ID equalityExpression();
- std::unique_ptr<ASTExpression> equalityExpression();
+ ASTNode::ID relationalExpression();
- std::unique_ptr<ASTExpression> relationalExpression();
+ ASTNode::ID shiftExpression();
- std::unique_ptr<ASTExpression> shiftExpression();
+ ASTNode::ID additiveExpression();
- std::unique_ptr<ASTExpression> additiveExpression();
+ ASTNode::ID multiplicativeExpression();
- std::unique_ptr<ASTExpression> multiplicativeExpression();
+ ASTNode::ID unaryExpression();
- std::unique_ptr<ASTExpression> unaryExpression();
+ ASTNode::ID postfixExpression();
- std::unique_ptr<ASTExpression> postfixExpression();
+ ASTNode::ID suffix(ASTNode::ID base);
- std::unique_ptr<ASTSuffix> suffix();
+ ASTNode::ID term();
- std::unique_ptr<ASTExpression> term();
+ bool intLiteral(SKSL_INT* dest);
- bool intLiteral(int64_t* dest);
-
- bool floatLiteral(double* dest);
+ bool floatLiteral(SKSL_FLOAT* dest);
bool boolLiteral(bool* dest);
@@ -296,6 +277,8 @@
SymbolTable& fTypes;
ErrorReporter& fErrors;
+ std::unique_ptr<ASTFile> fFile;
+
friend class AutoDepth;
friend class HCodeGenerator;
};
diff --git a/src/sksl/SkSLPosition.h b/src/sksl/SkSLPosition.h
index d1569d4..96a2f4b 100644
--- a/src/sksl/SkSLPosition.h
+++ b/src/sksl/SkSLPosition.h
@@ -8,6 +8,7 @@
#ifndef SKSL_POSITION
#define SKSL_POSITION
+#include "src/sksl/SkSLString.h"
#include "src/sksl/SkSLUtil.h"
namespace SkSL {
diff --git a/src/sksl/SkSLSPIRVCodeGenerator.h b/src/sksl/SkSLSPIRVCodeGenerator.h
index 97266db..5fd7e38 100644
--- a/src/sksl/SkSLSPIRVCodeGenerator.h
+++ b/src/sksl/SkSLSPIRVCodeGenerator.h
@@ -40,6 +40,7 @@
#include "src/sksl/ir/SkSLVarDeclarationsStatement.h"
#include "src/sksl/ir/SkSLVariableReference.h"
#include "src/sksl/ir/SkSLWhileStatement.h"
+#include "src/sksl/SkSLStringStream.h"
#include "src/sksl/spirv.h"
union ConstantValue {
diff --git a/src/sksl/SkSLString.cpp b/src/sksl/SkSLString.cpp
index b0efd77..cc58764 100644
--- a/src/sksl/SkSLString.cpp
+++ b/src/sksl/SkSLString.cpp
@@ -263,16 +263,16 @@
return String(buffer.str().c_str());
}
-int stoi(const String& s) {
+SKSL_INT stoi(const String& s) {
char* p;
SkDEBUGCODE(errno = 0;)
long result = strtoul(s.c_str(), &p, 0);
SkASSERT(*p == 0);
SkASSERT(!errno);
- return (int) result;
+ return result;
}
-double stod(const String& s) {
+SKSL_FLOAT stod(const String& s) {
double result;
std::string str(s.c_str(), s.size());
std::stringstream buffer(str);
diff --git a/src/sksl/SkSLString.h b/src/sksl/SkSLString.h
index 81c2fef..091634d 100644
--- a/src/sksl/SkSLString.h
+++ b/src/sksl/SkSLString.h
@@ -22,6 +22,8 @@
#include "include/core/SkString.h"
#endif
+#include "SkSLUtil.h"
+
namespace SkSL {
// Represents a (not necessarily null-terminated) slice of a string.
@@ -127,9 +129,9 @@
String to_string(uint64_t value);
-int stoi(const String& s);
+SKSL_INT stoi(const String& s);
-double stod(const String& s);
+SKSL_FLOAT stod(const String& s);
long stol(const String& s);
diff --git a/src/sksl/SkSLStringStream.h b/src/sksl/SkSLStringStream.h
index 8de1d40..d34d08d 100644
--- a/src/sksl/SkSLStringStream.h
+++ b/src/sksl/SkSLStringStream.h
@@ -9,6 +9,7 @@
#define SKSL_STRINGSTREAM
#include "src/sksl/SkSLOutputStream.h"
+#include "src/sksl/SkSLString.h"
#ifdef SKSL_STANDALONE
diff --git a/src/sksl/SkSLUtil.cpp b/src/sksl/SkSLUtil.cpp
index 19f5f5a..e8b2d1b 100644
--- a/src/sksl/SkSLUtil.cpp
+++ b/src/sksl/SkSLUtil.cpp
@@ -7,6 +7,8 @@
#include "src/sksl/SkSLUtil.h"
+#include "SkSLStringStream.h"
+
#ifndef __STDC_FORMAT_MACROS
#define __STDC_FORMAT_MACROS
#endif
diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h
index 7655cb6..e92e38d 100644
--- a/src/sksl/SkSLUtil.h
+++ b/src/sksl/SkSLUtil.h
@@ -14,8 +14,6 @@
#include "string.h"
#include "src/sksl/SkSLDefines.h"
#include "src/sksl/SkSLLexer.h"
-#include "src/sksl/SkSLString.h"
-#include "src/sksl/SkSLStringStream.h"
#ifndef SKSL_STANDALONE
#include "include/core/SkTypes.h"
@@ -25,6 +23,9 @@
#endif // SK_SUPPORT_GPU
#endif // SKSL_STANDALONE
+using SKSL_INT = uint32_t;
+using SKSL_FLOAT = float;
+
class GrShaderCaps;
namespace SkSL {
diff --git a/src/sksl/ast/SkSLASTBinaryExpression.h b/src/sksl/ast/SkSLASTBinaryExpression.h
deleted file mode 100644
index 6a573b5..0000000
--- a/src/sksl/ast/SkSLASTBinaryExpression.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTBINARYEXPRESSION
-#define SKSL_ASTBINARYEXPRESSION
-
-#include "src/sksl/SkSLCompiler.h"
-#include "src/sksl/SkSLLexer.h"
-#include "src/sksl/ast/SkSLASTExpression.h"
-
-namespace SkSL {
-
-/**
- * Represents a binary operation, with the operator represented by the token's type.
- */
-struct ASTBinaryExpression : public ASTExpression {
- ASTBinaryExpression(std::unique_ptr<ASTExpression> left, Token op,
- std::unique_ptr<ASTExpression> right)
- : INHERITED(op.fOffset, kBinary_Kind)
- , fLeft(std::move(left))
- , fOperator(op.fKind)
- , fRight(std::move(right)) {}
-
- String description() const override {
- return "(" + fLeft->description() + " " + Compiler::OperatorName(fOperator) + " " +
- fRight->description() + ")";
- }
-
- const std::unique_ptr<ASTExpression> fLeft;
- const Token::Kind fOperator;
- const std::unique_ptr<ASTExpression> fRight;
-
- typedef ASTExpression INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTBlock.h b/src/sksl/ast/SkSLASTBlock.h
deleted file mode 100644
index 69995cb..0000000
--- a/src/sksl/ast/SkSLASTBlock.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTBLOCK
-#define SKSL_ASTBLOCK
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-
-namespace SkSL {
-
-/**
- * Represents a curly-braced block of statements.
- */
-struct ASTBlock : public ASTStatement {
- ASTBlock(int offset, std::vector<std::unique_ptr<ASTStatement>> statements)
- : INHERITED(offset, kBlock_Kind)
- , fStatements(std::move(statements)) {}
-
- String description() const override {
- String result("{");
- for (size_t i = 0; i < fStatements.size(); i++) {
- result += "\n";
- result += fStatements[i]->description();
- }
- result += "\n}\n";
- return result;
- }
-
- const std::vector<std::unique_ptr<ASTStatement>> fStatements;
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTBoolLiteral.h b/src/sksl/ast/SkSLASTBoolLiteral.h
deleted file mode 100644
index 2fff338..0000000
--- a/src/sksl/ast/SkSLASTBoolLiteral.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTBOOLLITERAL
-#define SKSL_ASTBOOLLITERAL
-
-#include "src/sksl/ast/SkSLASTExpression.h"
-
-namespace SkSL {
-
-/**
- * Represents "true" or "false".
- */
-struct ASTBoolLiteral : public ASTExpression {
- ASTBoolLiteral(int offset, bool value)
- : INHERITED(offset, kBool_Kind)
- , fValue(value) {}
-
- String description() const override {
- return String(fValue ? "true" : "false");
- }
-
- const bool fValue;
-
- typedef ASTExpression INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTBreakStatement.h b/src/sksl/ast/SkSLASTBreakStatement.h
deleted file mode 100644
index 1335ede..0000000
--- a/src/sksl/ast/SkSLASTBreakStatement.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTBREAKSTATEMENT
-#define SKSL_ASTBREAKSTATEMENT
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-
-namespace SkSL {
-
-/**
- * A 'break' statement.
- */
-struct ASTBreakStatement : public ASTStatement {
- ASTBreakStatement(int offset)
- : INHERITED(offset, kBreak_Kind) {}
-
- String description() const override {
- return String("break;");
- }
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTCallSuffix.h b/src/sksl/ast/SkSLASTCallSuffix.h
deleted file mode 100644
index b249f27..0000000
--- a/src/sksl/ast/SkSLASTCallSuffix.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTCALLSUFFIX
-#define SKSL_ASTCALLSUFFIX
-
-#include <vector>
-#include "src/sksl/ast/SkSLASTSuffix.h"
-
-namespace SkSL {
-
-/**
- * A parenthesized list of arguments following an expression, indicating a function call.
- */
-struct ASTCallSuffix : public ASTSuffix {
- ASTCallSuffix(int offset, std::vector<std::unique_ptr<ASTExpression>> arguments)
- : INHERITED(offset, ASTSuffix::kCall_Kind)
- , fArguments(std::move(arguments)) {}
-
- String description() const override {
- String result("(");
- String separator;
- for (size_t i = 0; i < fArguments.size(); ++i) {
- result += separator;
- separator = ", ";
- result += fArguments[i]->description();
- }
- result += ")";
- return result;
- }
-
- std::vector<std::unique_ptr<ASTExpression>> fArguments;
-
- typedef ASTSuffix INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTContinueStatement.h b/src/sksl/ast/SkSLASTContinueStatement.h
deleted file mode 100644
index 6866b00..0000000
--- a/src/sksl/ast/SkSLASTContinueStatement.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTCONTINUESTATEMENT
-#define SKSL_ASTCONTINUESTATEMENT
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-
-namespace SkSL {
-
-/**
- * A 'continue' statement.
- */
-struct ASTContinueStatement : public ASTStatement {
- ASTContinueStatement(int offset)
- : INHERITED(offset, kContinue_Kind) {}
-
- String description() const override {
- return String("continue;");
- }
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTDeclaration.h b/src/sksl/ast/SkSLASTDeclaration.h
deleted file mode 100644
index 9f260f3..0000000
--- a/src/sksl/ast/SkSLASTDeclaration.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTDECLARATION
-#define SKSL_ASTDECLARATION
-
-#include "src/sksl/ast/SkSLASTPositionNode.h"
-
-namespace SkSL {
-
-/**
- * Abstract supertype of declarations such as variables and functions.
- */
-struct ASTDeclaration : public ASTPositionNode {
- enum Kind {
- kVar_Kind,
- kFunction_Kind,
- kInterfaceBlock_Kind,
- kExtension_Kind,
- kPrecision_Kind,
- kModifiers_Kind,
- kSection_Kind,
- kEnum_Kind
- };
-
- ASTDeclaration(int offset, Kind kind)
- : INHERITED(offset)
- , fKind(kind) {}
-
- Kind fKind;
-
- typedef ASTPositionNode INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTDiscardStatement.h b/src/sksl/ast/SkSLASTDiscardStatement.h
deleted file mode 100644
index 3cae08a..0000000
--- a/src/sksl/ast/SkSLASTDiscardStatement.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTDISCARDSTATEMENT
-#define SKSL_ASTDISCARDSTATEMENT
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-
-namespace SkSL {
-
-/**
- * A 'discard' statement.
- */
-struct ASTDiscardStatement : public ASTStatement {
- ASTDiscardStatement(int offset)
- : INHERITED(offset, kDiscard_Kind) {}
-
- String description() const override {
- return String("discard;");
- }
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTDoStatement.h b/src/sksl/ast/SkSLASTDoStatement.h
deleted file mode 100644
index 22fcca2..0000000
--- a/src/sksl/ast/SkSLASTDoStatement.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTDOSTATEMENT
-#define SKSL_ASTDOSTATEMENT
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-
-namespace SkSL {
-
-/**
- * A 'do' loop.
- */
-struct ASTDoStatement : public ASTStatement {
- ASTDoStatement(int offset, std::unique_ptr<ASTStatement> statement,
- std::unique_ptr<ASTExpression> test)
- : INHERITED(offset, kDo_Kind)
- , fStatement(std::move(statement))
- , fTest(std::move(test)) {}
-
- String description() const override {
- return "do " + fStatement->description() + " while (" + fTest->description() + ");";
- }
-
- const std::unique_ptr<ASTStatement> fStatement;
- const std::unique_ptr<ASTExpression> fTest;
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTEnum.h b/src/sksl/ast/SkSLASTEnum.h
deleted file mode 100644
index 16f9c62..0000000
--- a/src/sksl/ast/SkSLASTEnum.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTENUM
-#define SKSL_ASTENUM
-
-#include "src/sksl/ast/SkSLASTDeclaration.h"
-namespace SkSL {
-
-struct ASTEnum : public ASTDeclaration {
- ASTEnum(int offset, StringFragment typeName, std::vector<StringFragment> names,
- std::vector<std::unique_ptr<ASTExpression>> values)
- : INHERITED(offset, kEnum_Kind)
- , fTypeName(typeName)
- , fNames(std::move(names))
- , fValues(std::move(values)) {
- SkASSERT(fNames.size() == fValues.size());
- }
-
- String description() const override {
- String result = "enum class " + fTypeName + " {\n";
- String separator;
- for (StringFragment name : fNames) {
- result += separator + " " + name;
- separator = ",\n";
- }
- result += "};";
- return result;
- }
-
- const StringFragment fTypeName;
- const std::vector<StringFragment> fNames;
- const std::vector<std::unique_ptr<ASTExpression>> fValues;
-
- typedef ASTDeclaration INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTExpression.h b/src/sksl/ast/SkSLASTExpression.h
deleted file mode 100644
index efff173..0000000
--- a/src/sksl/ast/SkSLASTExpression.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTEXPRESSION
-#define SKSL_ASTEXPRESSION
-
-#include "src/sksl/ast/SkSLASTPositionNode.h"
-
-namespace SkSL {
-
-/**
- * Abstract supertype of all expressions.
- */
-struct ASTExpression : public ASTPositionNode {
- enum Kind {
- kBinary_Kind,
- kBool_Kind,
- kFloat_Kind,
- kIdentifier_Kind,
- kInt_Kind,
- kNull_Kind,
- kPrefix_Kind,
- kSuffix_Kind,
- kTernary_Kind
- };
-
- ASTExpression(int offset, Kind kind)
- : INHERITED(offset)
- , fKind(kind) {}
-
- const Kind fKind;
-
- typedef ASTPositionNode INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTExpressionStatement.h b/src/sksl/ast/SkSLASTExpressionStatement.h
deleted file mode 100644
index 0e18d2e..0000000
--- a/src/sksl/ast/SkSLASTExpressionStatement.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTEXPRESSIONSTATEMENT
-#define SKSL_ASTEXPRESSIONSTATEMENT
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-
-namespace SkSL {
-
-/**
- * A lone expression being used as a statement.
- */
-struct ASTExpressionStatement : public ASTStatement {
- ASTExpressionStatement(std::unique_ptr<ASTExpression> expression)
- : INHERITED(expression->fOffset, kExpression_Kind)
- , fExpression(std::move(expression)) {}
-
- String description() const override {
- return fExpression->description() + ";";
- }
-
- const std::unique_ptr<ASTExpression> fExpression;
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTExtension.h b/src/sksl/ast/SkSLASTExtension.h
deleted file mode 100644
index 39865bf..0000000
--- a/src/sksl/ast/SkSLASTExtension.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTEXTENSION
-#define SKSL_ASTEXTENSION
-
-#include "src/sksl/ast/SkSLASTDeclaration.h"
-
-namespace SkSL {
-
-/**
- * An extension declaration.
- */
-struct ASTExtension : public ASTDeclaration {
- ASTExtension(int offset, String name)
- : INHERITED(offset, kExtension_Kind)
- , fName(std::move(name)) {}
-
- String description() const override {
- return "#extension " + fName + " : enable";
- }
-
- const String fName;
-
- typedef ASTDeclaration INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTFieldSuffix.h b/src/sksl/ast/SkSLASTFieldSuffix.h
deleted file mode 100644
index 48653ca..0000000
--- a/src/sksl/ast/SkSLASTFieldSuffix.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTFIELDSUFFIX
-#define SKSL_ASTFIELDSUFFIX
-
-#include "src/sksl/ast/SkSLASTSuffix.h"
-
-namespace SkSL {
-
-/**
- * A dotted identifier of the form ".foo". We refer to these as "fields" at parse time even if it is
- * actually vector swizzle (which looks the same to the parser).
- */
-struct ASTFieldSuffix : public ASTSuffix {
- ASTFieldSuffix(int offset, StringFragment field)
- : INHERITED(offset, ASTSuffix::kField_Kind)
- , fField(field) {}
-
- String description() const override {
- return "." + fField;
- }
-
- StringFragment fField;
-
- typedef ASTSuffix INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTFloatLiteral.h b/src/sksl/ast/SkSLASTFloatLiteral.h
deleted file mode 100644
index e05aeb4..0000000
--- a/src/sksl/ast/SkSLASTFloatLiteral.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTFLOATLITERAL
-#define SKSL_ASTFLOATLITERAL
-
-#include "src/sksl/ast/SkSLASTExpression.h"
-
-namespace SkSL {
-
-/**
- * A literal floating point number.
- */
-struct ASTFloatLiteral : public ASTExpression {
- ASTFloatLiteral(int offset, double value)
- : INHERITED(offset, kFloat_Kind)
- , fValue(value) {}
-
- String description() const override {
- return to_string(fValue);
- }
-
- const double fValue;
-
- typedef ASTExpression INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTForStatement.h b/src/sksl/ast/SkSLASTForStatement.h
deleted file mode 100644
index 2597257..0000000
--- a/src/sksl/ast/SkSLASTForStatement.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTFORSTATEMENT
-#define SKSL_ASTFORSTATEMENT
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-
-namespace SkSL {
-
-/**
- * A 'for' loop.
- */
-struct ASTForStatement : public ASTStatement {
- ASTForStatement(int offset, std::unique_ptr<ASTStatement> initializer,
- std::unique_ptr<ASTExpression> test, std::unique_ptr<ASTExpression> next,
- std::unique_ptr<ASTStatement> statement)
- : INHERITED(offset, kFor_Kind)
- , fInitializer(std::move(initializer))
- , fTest(std::move(test))
- , fNext(std::move(next))
- , fStatement(std::move(statement)) {}
-
- String description() const override {
- String result("for (");
- if (fInitializer) {
- result.append(fInitializer->description());
- }
- result += " ";
- if (fTest) {
- result.append(fTest->description());
- }
- result += "; ";
- if (fNext) {
- result.append(fNext->description());
- }
- result += ") ";
- result += fStatement->description();
- return result;
- }
-
- const std::unique_ptr<ASTStatement> fInitializer;
- const std::unique_ptr<ASTExpression> fTest;
- const std::unique_ptr<ASTExpression> fNext;
- const std::unique_ptr<ASTStatement> fStatement;
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTFunction.h b/src/sksl/ast/SkSLASTFunction.h
deleted file mode 100644
index f03631b..0000000
--- a/src/sksl/ast/SkSLASTFunction.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTFUNCTION
-#define SKSL_ASTFUNCTION
-
-#include "src/sksl/ast/SkSLASTBlock.h"
-#include "src/sksl/ast/SkSLASTDeclaration.h"
-#include "src/sksl/ast/SkSLASTParameter.h"
-#include "src/sksl/ast/SkSLASTType.h"
-
-namespace SkSL {
-
-/**
- * A function declaration or definition. The fBody field will be null for declarations.
- */
-struct ASTFunction : public ASTDeclaration {
- ASTFunction(int offset, Modifiers modifiers, std::unique_ptr<ASTType> returnType,
- StringFragment name, std::vector<std::unique_ptr<ASTParameter>> parameters,
- std::unique_ptr<ASTBlock> body)
- : INHERITED(offset, kFunction_Kind)
- , fModifiers(modifiers)
- , fReturnType(std::move(returnType))
- , fName(name)
- , fParameters(std::move(parameters))
- , fBody(std::move(body)) {}
-
- String description() const override {
- String result = fReturnType->description() + " " + fName + "(";
- for (size_t i = 0; i < fParameters.size(); i++) {
- if (i > 0) {
- result += ", ";
- }
- result += fParameters[i]->description();
- }
- if (fBody) {
- result += ") " + fBody->description();
- } else {
- result += ");";
- }
- return result;
- }
-
- const Modifiers fModifiers;
- const std::unique_ptr<ASTType> fReturnType;
- const StringFragment fName;
- const std::vector<std::unique_ptr<ASTParameter>> fParameters;
- const std::unique_ptr<ASTBlock> fBody;
-
- typedef ASTDeclaration INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTIdentifier.h b/src/sksl/ast/SkSLASTIdentifier.h
deleted file mode 100644
index 47f4296..0000000
--- a/src/sksl/ast/SkSLASTIdentifier.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTIDENTIFIER
-#define SKSL_ASTIDENTIFIER
-
-#include "src/sksl/ast/SkSLASTExpression.h"
-
-namespace SkSL {
-
-/**
- * An identifier in an expression context.
- */
-struct ASTIdentifier : public ASTExpression {
- ASTIdentifier(int offset, StringFragment text)
- : INHERITED(offset, kIdentifier_Kind)
- , fText(text) {}
-
- String description() const override {
- return String(fText);
- }
-
- const StringFragment fText;
-
- typedef ASTExpression INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTIfStatement.h b/src/sksl/ast/SkSLASTIfStatement.h
deleted file mode 100644
index 64da88a..0000000
--- a/src/sksl/ast/SkSLASTIfStatement.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTIFSTATEMENT
-#define SKSL_ASTIFSTATEMENT
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-
-namespace SkSL {
-
-/**
- * An 'if' statement.
- */
-struct ASTIfStatement : public ASTStatement {
- ASTIfStatement(int offset, bool isStatic, std::unique_ptr<ASTExpression> test,
- std::unique_ptr<ASTStatement> ifTrue, std::unique_ptr<ASTStatement> ifFalse)
- : INHERITED(offset, kIf_Kind)
- , fIsStatic(isStatic)
- , fTest(std::move(test))
- , fIfTrue(std::move(ifTrue))
- , fIfFalse(std::move(ifFalse)) {}
-
- String description() const override {
- String result;
- if (fIsStatic) {
- result += "@";
- }
- result += "if (";
- result += fTest->description();
- result += ") ";
- result += fIfTrue->description();
- if (fIfFalse) {
- result += " else ";
- result += fIfFalse->description();
- }
- return result;
- }
-
- const bool fIsStatic;
- const std::unique_ptr<ASTExpression> fTest;
- const std::unique_ptr<ASTStatement> fIfTrue;
- const std::unique_ptr<ASTStatement> fIfFalse;
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTIndexSuffix.h b/src/sksl/ast/SkSLASTIndexSuffix.h
deleted file mode 100644
index d192d2c..0000000
--- a/src/sksl/ast/SkSLASTIndexSuffix.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTINDEXSUFFIX
-#define SKSL_ASTINDEXSUFFIX
-
-#include "src/sksl/ast/SkSLASTExpression.h"
-#include "src/sksl/ast/SkSLASTSuffix.h"
-
-namespace SkSL {
-
-/**
- * A bracketed expression, as in '[0]', indicating an array access. Empty brackets (as occur in
- * 'float[](5, 6)' are represented with a null fExpression.
- */
-struct ASTIndexSuffix : public ASTSuffix {
- ASTIndexSuffix(int offset)
- : INHERITED(offset, ASTSuffix::kIndex_Kind)
- , fExpression(nullptr) {}
-
- ASTIndexSuffix(std::unique_ptr<ASTExpression> expression)
- : INHERITED(expression ? expression->fOffset : -1, ASTSuffix::kIndex_Kind)
- , fExpression(std::move(expression)) {}
-
- String description() const override {
- if (fExpression) {
- return "[" + fExpression->description() + "]";
- } else {
- return String("[]");
- }
- }
-
- // may be null
- std::unique_ptr<ASTExpression> fExpression;
-
- typedef ASTSuffix INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTIntLiteral.h b/src/sksl/ast/SkSLASTIntLiteral.h
deleted file mode 100644
index 6554d51..0000000
--- a/src/sksl/ast/SkSLASTIntLiteral.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTINTLITERAL
-#define SKSL_ASTINTLITERAL
-
-#include "src/sksl/ast/SkSLASTExpression.h"
-
-namespace SkSL {
-
-/**
- * A literal integer. At the AST level, integer literals are always positive; a negative number will
- * appear as a unary minus being applied to an integer literal.
- */
-struct ASTIntLiteral : public ASTExpression {
- ASTIntLiteral(int offset, uint64_t value)
- : INHERITED(offset, kInt_Kind)
- , fValue(value) {}
-
- String description() const override {
- return to_string(fValue);
- }
-
- const uint64_t fValue;
-
- typedef ASTExpression INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTInterfaceBlock.h b/src/sksl/ast/SkSLASTInterfaceBlock.h
deleted file mode 100644
index 6fae28c..0000000
--- a/src/sksl/ast/SkSLASTInterfaceBlock.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTINTERFACEBLOCK
-#define SKSL_ASTINTERFACEBLOCK
-
-#include "src/sksl/ast/SkSLASTVarDeclaration.h"
-#include "src/sksl/ir/SkSLModifiers.h"
-
-namespace SkSL {
-
-/**
- * An interface block, as in:
- *
- * out sk_PerVertex {
- * layout(builtin=0) float4 sk_Position;
- * layout(builtin=1) float sk_PointSize;
- * };
- */
-struct ASTInterfaceBlock : public ASTDeclaration {
- // valueName is empty when it was not present in the source
- ASTInterfaceBlock(int offset,
- Modifiers modifiers,
- StringFragment typeName,
- std::vector<std::unique_ptr<ASTVarDeclarations>> declarations,
- StringFragment instanceName,
- std::vector<std::unique_ptr<ASTExpression>> sizes)
- : INHERITED(offset, kInterfaceBlock_Kind)
- , fModifiers(modifiers)
- , fTypeName(typeName)
- , fDeclarations(std::move(declarations))
- , fInstanceName(instanceName)
- , fSizes(std::move(sizes)) {}
-
- String description() const override {
- String result = fModifiers.description() + fTypeName + " {\n";
- for (size_t i = 0; i < fDeclarations.size(); i++) {
- result += fDeclarations[i]->description() + "\n";
- }
- result += "}";
- if (fInstanceName.fLength) {
- result += " " + fInstanceName;
- for (const auto& size : fSizes) {
- result += "[";
- if (size) {
- result += size->description();
- }
- result += "]";
- }
- }
- return result + ";";
- }
-
- const Modifiers fModifiers;
- const StringFragment fTypeName;
- const std::vector<std::unique_ptr<ASTVarDeclarations>> fDeclarations;
- const StringFragment fInstanceName;
- const std::vector<std::unique_ptr<ASTExpression>> fSizes;
-
- typedef ASTDeclaration INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTModifiersDeclaration.h b/src/sksl/ast/SkSLASTModifiersDeclaration.h
deleted file mode 100644
index dd1531a..0000000
--- a/src/sksl/ast/SkSLASTModifiersDeclaration.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTMODIFIERDECLARATION
-#define SKSL_ASTMODIFIERDECLARATION
-
-#include "src/sksl/ast/SkSLASTDeclaration.h"
-#include "src/sksl/ir/SkSLModifiers.h"
-
-namespace SkSL {
-
-/**
- * A declaration that consists only of modifiers, e.g.:
- *
- * layout(blend_support_all_equations) out;
- */
-struct ASTModifiersDeclaration : public ASTDeclaration {
- ASTModifiersDeclaration(Modifiers modifiers)
- : INHERITED(-1, kModifiers_Kind)
- , fModifiers(modifiers) {}
-
- String description() const {
- return fModifiers.description() + ";";
- }
-
- Modifiers fModifiers;
-
- typedef ASTDeclaration INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTNode.h b/src/sksl/ast/SkSLASTNode.h
deleted file mode 100644
index 1b5f2bd..0000000
--- a/src/sksl/ast/SkSLASTNode.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTNODE
-#define SKSL_ASTNODE
-
-#include "src/sksl/SkSLString.h"
-
-namespace SkSL {
-
-/**
- * Represents a node in the abstract syntax tree (AST). The AST is based directly on the parse tree;
- * it is a parsed-but-not-yet-analyzed version of the program.
- */
-struct ASTNode {
- virtual ~ASTNode() {}
-
- virtual String description() const = 0;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTNullLiteral.h b/src/sksl/ast/SkSLASTNullLiteral.h
deleted file mode 100644
index 6ea27dc..0000000
--- a/src/sksl/ast/SkSLASTNullLiteral.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTNULLLITERAL
-#define SKSL_ASTNULLLITERAL
-
-#include "src/sksl/ast/SkSLASTExpression.h"
-
-namespace SkSL {
-
-/**
- * Represents "null".
- */
-struct ASTNullLiteral : public ASTExpression {
- ASTNullLiteral(int offset)
- : INHERITED(offset, kNull_Kind) {}
-
- String description() const override {
- return "null";
- }
-
- typedef ASTExpression INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTParameter.h b/src/sksl/ast/SkSLASTParameter.h
deleted file mode 100644
index d5ba55a..0000000
--- a/src/sksl/ast/SkSLASTParameter.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTPARAMETER
-#define SKSL_ASTPARAMETER
-
-#include "src/sksl/ast/SkSLASTPositionNode.h"
-#include "src/sksl/ast/SkSLASTType.h"
-#include "src/sksl/ir/SkSLModifiers.h"
-
-namespace SkSL {
-
-/**
- * A declaration of a parameter, as part of a function declaration.
- */
-struct ASTParameter : public ASTPositionNode {
- // 'sizes' is a list of the array sizes appearing on a parameter, in source order.
- // e.g. int x[3][1] would have sizes [3, 1].
- ASTParameter(int offset, Modifiers modifiers, std::unique_ptr<ASTType> type,
- StringFragment name, std::vector<int> sizes)
- : INHERITED(offset)
- , fModifiers(modifiers)
- , fType(std::move(type))
- , fName(name)
- , fSizes(std::move(sizes)) {}
-
- String description() const override {
- String result = fModifiers.description() + fType->description() + " " + fName;
- for (int size : fSizes) {
- result += "[" + to_string(size) + "]";
- }
- return result;
- }
-
- const Modifiers fModifiers;
- const std::unique_ptr<ASTType> fType;
- const StringFragment fName;
- const std::vector<int> fSizes;
-
- typedef ASTPositionNode INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTPositionNode.h b/src/sksl/ast/SkSLASTPositionNode.h
deleted file mode 100644
index a9e3d54..0000000
--- a/src/sksl/ast/SkSLASTPositionNode.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTPOSITIONNODE
-#define SKSL_ASTPOSITIONNODE
-
-#include "src/sksl/SkSLPosition.h"
-#include "src/sksl/ast/SkSLASTNode.h"
-
-namespace SkSL {
-
-/**
- * An AST node with an associated position in the source.
- */
-struct ASTPositionNode : public ASTNode {
- ASTPositionNode(int offset)
- : fOffset(offset) {}
-
- // character offset of this element within the program being compiled, for error reporting
- // purposes
- const int fOffset;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTPrecision.h b/src/sksl/ast/SkSLASTPrecision.h
deleted file mode 100644
index 06d083d..0000000
--- a/src/sksl/ast/SkSLASTPrecision.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTPRECISION
-#define SKSL_ASTPRECISION
-
-#include "src/sksl/ast/SkSLASTDeclaration.h"
-#include "src/sksl/ir/SkSLModifiers.h"
-
-namespace SkSL {
-
-/**
- * Represents a precision declaration (e.g. 'precision mediump float;').
- */
-struct ASTPrecision : public ASTDeclaration {
- // FIXME handle the type
- ASTPrecision(int offset, Modifiers::Flag precision)
- : INHERITED(offset, kPrecision_Kind)
- , fPrecision(precision) {}
-
- String description() const {
- switch (fPrecision) {
- case Modifiers::kLowp_Flag: return String("precision lowp float;");
- case Modifiers::kMediump_Flag: return String("precision mediump float;");
- case Modifiers::kHighp_Flag: return String("precision highp float;");
- default:
- SkASSERT(false);
- return String("<error>");
- }
- SkASSERT(false);
- return String("<error>");
- }
-
- const Modifiers::Flag fPrecision;
-
- typedef ASTDeclaration INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTPrefixExpression.h b/src/sksl/ast/SkSLASTPrefixExpression.h
deleted file mode 100644
index 53150f8..0000000
--- a/src/sksl/ast/SkSLASTPrefixExpression.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTPREFIXEXPRESSION
-#define SKSL_ASTPREFIXEXPRESSION
-
-#include "src/sksl/SkSLCompiler.h"
-#include "src/sksl/SkSLLexer.h"
-#include "src/sksl/ast/SkSLASTExpression.h"
-
-namespace SkSL {
-
-/**
- * An expression modified by a unary operator appearing in front of it, such as '-x' or '!inside'.
- */
-struct ASTPrefixExpression : public ASTExpression {
- ASTPrefixExpression(Token op, std::unique_ptr<ASTExpression> operand)
- : INHERITED(op.fOffset, kPrefix_Kind)
- , fOperator(op.fKind)
- , fOperand(std::move(operand)) {}
-
- String description() const override {
- return Compiler::OperatorName(fOperator) + fOperand->description();
- }
-
- const Token::Kind fOperator;
- const std::unique_ptr<ASTExpression> fOperand;
-
- typedef ASTExpression INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTReturnStatement.h b/src/sksl/ast/SkSLASTReturnStatement.h
deleted file mode 100644
index 77b6970..0000000
--- a/src/sksl/ast/SkSLASTReturnStatement.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTRETURNSTATEMENT
-#define SKSL_ASTRETURNSTATEMENT
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-
-namespace SkSL {
-
-/**
- * A 'return' statement.
- */
-struct ASTReturnStatement : public ASTStatement {
- // expression may be null
- ASTReturnStatement(int offset, std::unique_ptr<ASTExpression> expression)
- : INHERITED(offset, kReturn_Kind)
- , fExpression(std::move(expression)) {}
-
- String description() const override {
- String result("return");
- if (fExpression) {
- result += " " + fExpression->description();
- }
- return result + ";";
- }
-
- const std::unique_ptr<ASTExpression> fExpression;
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTSection.h b/src/sksl/ast/SkSLASTSection.h
deleted file mode 100644
index bd4655c..0000000
--- a/src/sksl/ast/SkSLASTSection.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTSECTION
-#define SKSL_ASTSECTION
-
-#include "src/sksl/ast/SkSLASTDeclaration.h"
-
-namespace SkSL {
-
-/**
- * A section declaration (e.g. @body { body code here })..
- */
-struct ASTSection : public ASTDeclaration {
- ASTSection(int offset, String name, String arg, String text)
- : INHERITED(offset, kSection_Kind)
- , fName(std::move(name))
- , fArgument(std::move(arg))
- , fText(std::move(text)) {}
-
- String description() const override {
- String result = "@" + fName;
- if (fArgument.size()) {
- result += "(" + fArgument + ")";
- }
- result += " { " + fText + " }";
- return result;
- }
-
- const String fName;
- const String fArgument;
- const String fText;
-
- typedef ASTDeclaration INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTStatement.h b/src/sksl/ast/SkSLASTStatement.h
deleted file mode 100644
index d672e22..0000000
--- a/src/sksl/ast/SkSLASTStatement.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTSTATEMENT
-#define SKSL_ASTSTATEMENT
-
-#include <vector>
-#include "src/sksl/ast/SkSLASTExpression.h"
-#include "src/sksl/ast/SkSLASTPositionNode.h"
-
-namespace SkSL {
-
-/**
- * Abstract supertype of all statements.
- */
-struct ASTStatement : public ASTPositionNode {
- enum Kind {
- kBlock_Kind,
- kVarDeclaration_Kind,
- kExpression_Kind,
- kIf_Kind,
- kFor_Kind,
- kWhile_Kind,
- kDo_Kind,
- kSwitch_Kind,
- kReturn_Kind,
- kBreak_Kind,
- kContinue_Kind,
- kDiscard_Kind
- };
-
- ASTStatement(int offset, Kind kind)
- : INHERITED(offset)
- , fKind(kind) {}
-
- Kind fKind;
-
- typedef ASTPositionNode INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTSuffix.h b/src/sksl/ast/SkSLASTSuffix.h
deleted file mode 100644
index 2d44d60..0000000
--- a/src/sksl/ast/SkSLASTSuffix.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTSUFFIX
-#define SKSL_ASTSUFFIX
-
-#include "src/sksl/ast/SkSLASTExpression.h"
-#include "src/sksl/ast/SkSLASTPositionNode.h"
-
-namespace SkSL {
-
-/**
- * This and its subclasses represents expression suffixes, such as '[0]' or '.rgb'. Suffixes are not
- * expressions in and of themselves; they are attached to expressions to modify them.
- */
-struct ASTSuffix : public ASTPositionNode {
- enum Kind {
- kIndex_Kind,
- kCall_Kind,
- kField_Kind,
- kPostIncrement_Kind,
- kPostDecrement_Kind
- };
-
- ASTSuffix(int offset, Kind kind)
- : INHERITED(offset)
- , fKind(kind) {}
-
- String description() const override {
- switch (fKind) {
- case kPostIncrement_Kind:
- return String("++");
- case kPostDecrement_Kind:
- return String("--");
- default:
- ABORT("unsupported suffix operator");
- }
- }
-
- Kind fKind;
-
- typedef ASTPositionNode INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTSuffixExpression.h b/src/sksl/ast/SkSLASTSuffixExpression.h
deleted file mode 100644
index cbafe4e..0000000
--- a/src/sksl/ast/SkSLASTSuffixExpression.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTSUFFIXEXPRESSION
-#define SKSL_ASTSUFFIXEXPRESSION
-
-#include "src/sksl/ast/SkSLASTExpression.h"
-#include "src/sksl/ast/SkSLASTSuffix.h"
-
-namespace SkSL {
-
-/**
- * An expression with an associated suffix.
- */
-struct ASTSuffixExpression : public ASTExpression {
- ASTSuffixExpression(std::unique_ptr<ASTExpression> base, std::unique_ptr<ASTSuffix> suffix)
- : INHERITED(base->fOffset, kSuffix_Kind)
- , fBase(std::move(base))
- , fSuffix(std::move(suffix)) {}
-
- String description() const override {
- return fBase->description() + fSuffix->description();
- }
-
- const std::unique_ptr<ASTExpression> fBase;
- const std::unique_ptr<ASTSuffix> fSuffix;
-
- typedef ASTExpression INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTSwitchCase.h b/src/sksl/ast/SkSLASTSwitchCase.h
deleted file mode 100644
index 9bbab39..0000000
--- a/src/sksl/ast/SkSLASTSwitchCase.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTSWITCHCASE
-#define SKSL_ASTSWITCHCASE
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-
-namespace SkSL {
-
-/**
- * A single case of a 'switch' statement.
- */
-struct ASTSwitchCase : public ASTStatement {
- // a null value means "default:"
- ASTSwitchCase(int offset, std::unique_ptr<ASTExpression> value,
- std::vector<std::unique_ptr<ASTStatement>> statements)
- : INHERITED(offset, kSwitch_Kind)
- , fValue(std::move(value))
- , fStatements(std::move(statements)) {}
-
- String description() const override {
- String result;
- if (fValue) {
- result.appendf("case %s:\n", fValue->description().c_str());
- } else {
- result += "default:\n";
- }
- for (const auto& s : fStatements) {
- result += s->description() + "\n";
- }
- return result;
- }
-
- // null value implies "default" case
- const std::unique_ptr<ASTExpression> fValue;
- const std::vector<std::unique_ptr<ASTStatement>> fStatements;
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTSwitchStatement.h b/src/sksl/ast/SkSLASTSwitchStatement.h
deleted file mode 100644
index af0c05d..0000000
--- a/src/sksl/ast/SkSLASTSwitchStatement.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2017 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTSWITCHSTATEMENT
-#define SKSL_ASTSWITCHSTATEMENT
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-#include "src/sksl/ast/SkSLASTSwitchCase.h"
-
-namespace SkSL {
-
-/**
- * A 'switch' statement.
- */
-struct ASTSwitchStatement : public ASTStatement {
- ASTSwitchStatement(int offset, bool isStatic, std::unique_ptr<ASTExpression> value,
- std::vector<std::unique_ptr<ASTSwitchCase>> cases)
- : INHERITED(offset, kSwitch_Kind)
- , fIsStatic(isStatic)
- , fValue(std::move(value))
- , fCases(std::move(cases)) {}
-
- String description() const override {
- String result;
- if (fIsStatic) {
- result += "@";
- }
- result += String::printf("switch (%s) {\n", fValue->description().c_str());
- for (const auto& c : fCases) {
- result += c->description();
- }
- result += "}";
- return result;
- }
-
- bool fIsStatic;
- const std::unique_ptr<ASTExpression> fValue;
- const std::vector<std::unique_ptr<ASTSwitchCase>> fCases;
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTTernaryExpression.h b/src/sksl/ast/SkSLASTTernaryExpression.h
deleted file mode 100644
index b78acb1..0000000
--- a/src/sksl/ast/SkSLASTTernaryExpression.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTTERNARYEXPRESSION
-#define SKSL_ASTTERNARYEXPRESSION
-
-#include "src/sksl/ast/SkSLASTExpression.h"
-
-namespace SkSL {
-
-/**
- * A ternary expression (test ? ifTrue : ifFalse).
- */
-struct ASTTernaryExpression : public ASTExpression {
- ASTTernaryExpression(std::unique_ptr<ASTExpression> test,
- std::unique_ptr<ASTExpression> ifTrue,
- std::unique_ptr<ASTExpression> ifFalse)
- : INHERITED(test->fOffset, kTernary_Kind)
- , fTest(std::move(test))
- , fIfTrue(std::move(ifTrue))
- , fIfFalse(std::move(ifFalse)) {}
-
- String description() const override {
- return "(" + fTest->description() + " ? " + fIfTrue->description() + " : " +
- fIfFalse->description() + ")";
- }
-
- const std::unique_ptr<ASTExpression> fTest;
- const std::unique_ptr<ASTExpression> fIfTrue;
- const std::unique_ptr<ASTExpression> fIfFalse;
-
- typedef ASTExpression INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTType.h b/src/sksl/ast/SkSLASTType.h
deleted file mode 100644
index 56660b9..0000000
--- a/src/sksl/ast/SkSLASTType.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTTYPE
-#define SKSL_ASTTYPE
-
-#include "src/sksl/ast/SkSLASTPositionNode.h"
-
-namespace SkSL {
-
-/**
- * A type, such as 'int' or 'struct foo'.
- */
-struct ASTType : public ASTPositionNode {
- enum Kind {
- kIdentifier_Kind,
- kStruct_Kind
- };
-
- ASTType(int offset, StringFragment name, Kind kind, std::vector<int> sizes, bool nullable)
- : INHERITED(offset)
- , fName(name)
- , fKind(kind)
- , fSizes(std::move(sizes))
- , fNullable(nullable) {}
-
- String description() const override {
- return fName;
- }
-
- const StringFragment fName;
-
- const Kind fKind;
-
- // array sizes, -1 meaning unspecified
- const std::vector<int> fSizes;
-
- bool fNullable;
-
- typedef ASTPositionNode INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTVarDeclaration.h b/src/sksl/ast/SkSLASTVarDeclaration.h
deleted file mode 100644
index 880ea2d..0000000
--- a/src/sksl/ast/SkSLASTVarDeclaration.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTVARDECLARATIONS
-#define SKSL_ASTVARDECLARATIONS
-
-#include "src/sksl/SkSLUtil.h"
-#include "src/sksl/ast/SkSLASTDeclaration.h"
-#include "src/sksl/ast/SkSLASTStatement.h"
-#include "src/sksl/ast/SkSLASTType.h"
-#include "src/sksl/ir/SkSLModifiers.h"
-
-namespace SkSL {
-
-/**
- * A single variable declaration within a var declaration statement. For instance, the statement
- * 'int x = 2, y[3];' is an ASTVarDeclarations statement containing two individual ASTVarDeclaration
- * instances.
- */
-struct ASTVarDeclaration {
- ASTVarDeclaration(StringFragment name,
- std::vector<std::unique_ptr<ASTExpression>> sizes,
- std::unique_ptr<ASTExpression> value)
- : fName(name)
- , fSizes(std::move(sizes))
- , fValue(std::move(value)) {}
-
- String description() const {
- String result(fName);
- for (const auto& size : fSizes) {
- if (size) {
- result += "[" + size->description() + "]";
- } else {
- result += "[]";
- }
- }
- if (fValue) {
- result += " = " + fValue->description();
- }
- return result;
- }
-
- StringFragment fName;
-
- // array sizes, if any. e.g. 'foo[3][]' has sizes [3, null]
- std::vector<std::unique_ptr<ASTExpression>> fSizes;
-
- // initial value, may be null
- std::unique_ptr<ASTExpression> fValue;
-};
-
-/**
- * A variable declaration statement, which may consist of one or more individual variables.
- */
-struct ASTVarDeclarations : public ASTDeclaration {
- ASTVarDeclarations(Modifiers modifiers,
- std::unique_ptr<ASTType> type,
- std::vector<ASTVarDeclaration> vars)
- : INHERITED(type->fOffset, kVar_Kind)
- , fModifiers(modifiers)
- , fType(std::move(type))
- , fVars(std::move(vars)) {}
-
- String description() const override {
- String result = fModifiers.description() + fType->description() + " ";
- String separator;
- for (const auto& var : fVars) {
- result += separator;
- separator = ", ";
- result += var.description();
- }
- return result;
- }
-
- const Modifiers fModifiers;
- const std::unique_ptr<ASTType> fType;
- const std::vector<ASTVarDeclaration> fVars;
-
- typedef ASTDeclaration INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTVarDeclarationStatement.h b/src/sksl/ast/SkSLASTVarDeclarationStatement.h
deleted file mode 100644
index 48edef3..0000000
--- a/src/sksl/ast/SkSLASTVarDeclarationStatement.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTVARDECLARATIONSTATEMENT
-#define SKSL_ASTVARDECLARATIONSTATEMENT
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-#include "src/sksl/ast/SkSLASTVarDeclaration.h"
-
-namespace SkSL {
-
-/**
- * A variable declaration appearing as a statement within a function.
- */
-struct ASTVarDeclarationStatement : public ASTStatement {
- ASTVarDeclarationStatement(std::unique_ptr<ASTVarDeclarations> decl)
- : INHERITED(decl->fOffset, kVarDeclaration_Kind)
- , fDeclarations(std::move(decl)) {}
-
- String description() const override {
- return fDeclarations->description() + ";";
- }
-
- std::unique_ptr<ASTVarDeclarations> fDeclarations;
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ast/SkSLASTWhileStatement.h b/src/sksl/ast/SkSLASTWhileStatement.h
deleted file mode 100644
index 450aa05..0000000
--- a/src/sksl/ast/SkSLASTWhileStatement.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SKSL_ASTWHILESTATEMENT
-#define SKSL_ASTWHILESTATEMENT
-
-#include "src/sksl/ast/SkSLASTStatement.h"
-
-namespace SkSL {
-
-/**
- * A 'while' statement.
- */
-struct ASTWhileStatement : public ASTStatement {
- ASTWhileStatement(int offset, std::unique_ptr<ASTExpression> test,
- std::unique_ptr<ASTStatement> statement)
- : INHERITED(offset, kWhile_Kind)
- , fTest(std::move(test))
- , fStatement(std::move(statement)) {}
-
- String description() const override {
- return "while (" + fTest->description() + ") " + fStatement->description();
- }
-
- const std::unique_ptr<ASTExpression> fTest;
- const std::unique_ptr<ASTStatement> fStatement;
-
- typedef ASTStatement INHERITED;
-};
-
-} // namespace
-
-#endif
diff --git a/src/sksl/ir/SkSLBinaryExpression.h b/src/sksl/ir/SkSLBinaryExpression.h
index f4c61fb..4ab25d2 100644
--- a/src/sksl/ir/SkSLBinaryExpression.h
+++ b/src/sksl/ir/SkSLBinaryExpression.h
@@ -8,6 +8,7 @@
#ifndef SKSL_BINARYEXPRESSION
#define SKSL_BINARYEXPRESSION
+#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLLexer.h"
#include "src/sksl/ir/SkSLExpression.h"
diff --git a/src/sksl/ir/SkSLLayout.h b/src/sksl/ir/SkSLLayout.h
index 9916f47..d4b1cb6 100644
--- a/src/sksl/ir/SkSLLayout.h
+++ b/src/sksl/ir/SkSLLayout.h
@@ -181,7 +181,7 @@
Layout(int flags, int location, int offset, int binding, int index, int set, int builtin,
int inputAttachmentIndex, Format format, Primitive primitive, int maxVertices,
- int invocations, String when, Key key, CType ctype)
+ int invocations, StringFragment when, Key key, CType ctype)
: fFlags(flags)
, fLocation(location)
, fOffset(offset)
@@ -369,7 +369,7 @@
result += separator + "invocations = " + to_string(fInvocations);
separator = ", ";
}
- if (fWhen.size()) {
+ if (fWhen.fLength) {
result += separator + "when = " + fWhen;
separator = ", ";
}
@@ -417,7 +417,7 @@
Primitive fPrimitive;
int fMaxVertices;
int fInvocations;
- String fWhen;
+ StringFragment fWhen;
Key fKey;
CType fCType;
};
diff --git a/src/sksl/ir/SkSLPrefixExpression.h b/src/sksl/ir/SkSLPrefixExpression.h
index 304830a..3cdd1fa 100644
--- a/src/sksl/ir/SkSLPrefixExpression.h
+++ b/src/sksl/ir/SkSLPrefixExpression.h
@@ -8,6 +8,7 @@
#ifndef SKSL_PREFIXEXPRESSION
#define SKSL_PREFIXEXPRESSION
+#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLIRGenerator.h"
#include "src/sksl/SkSLLexer.h"
#include "src/sksl/ir/SkSLExpression.h"