blob: aeb445e69aded2ff92980cbd6e8963199b8f62d6 [file] [log] [blame]
/*
* 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_VARDECLARATIONS
#define SKSL_VARDECLARATIONS
#include "include/private/SkSLProgramElement.h"
#include "include/private/SkSLStatement.h"
#include "src/sksl/ir/SkSLExpression.h"
#include "src/sksl/ir/SkSLVariable.h"
namespace SkSL {
namespace dsl {
class DSLCore;
}
/**
* A single variable declaration statement. Multiple variables declared together are expanded to
* separate (sequential) statements. For instance, the SkSL 'int x = 2, y[3];' produces two
* VarDeclaration instances (wrapped in an unscoped Block).
*/
class VarDeclaration final : public Statement {
public:
inline static constexpr Kind kStatementKind = Kind::kVarDeclaration;
VarDeclaration(const Variable* var,
const Type* baseType,
int arraySize,
std::unique_ptr<Expression> value)
: INHERITED(var->fLine, kStatementKind)
, fVar(var)
, fBaseType(*baseType)
, fArraySize(arraySize)
, fValue(std::move(value)) {}
~VarDeclaration() override {
// Unhook this VarDeclaration from its associated Variable, since we're being deleted.
if (fVar) {
fVar->detachDeadVarDeclaration();
}
}
// Checks the modifiers, baseType, and storage for compatibility with one another and reports
// errors if needed. This method is implicitly called during Convert(), but is also explicitly
// called while processing interface block fields.
static void ErrorCheck(const Context& context, int line, const Modifiers& modifiers,
const Type* baseType, Variable::Storage storage);
// Does proper error checking and type coercion; reports errors via ErrorReporter.
static std::unique_ptr<Statement> Convert(const Context& context, std::unique_ptr<Variable> var,
std::unique_ptr<Expression> value, bool addToSymbolTable = true);
// Reports errors via ASSERT.
static std::unique_ptr<Statement> Make(const Context& context,
Variable* var,
const Type* baseType,
int arraySize,
std::unique_ptr<Expression> value);
const Type& baseType() const {
return fBaseType;
}
const Variable& var() const {
// This should never be called after the Variable has been deleted.
SkASSERT(fVar);
return *fVar;
}
void setVar(const Variable* var) {
fVar = var;
}
int arraySize() const {
return fArraySize;
}
std::unique_ptr<Expression>& value() {
return fValue;
}
const std::unique_ptr<Expression>& value() const {
return fValue;
}
std::unique_ptr<Statement> clone() const override;
String description() const override;
private:
static bool ErrorCheckAndCoerce(const Context& context, const Variable& var,
std::unique_ptr<Expression>& value);
const Variable* fVar;
const Type& fBaseType;
int fArraySize; // zero means "not an array"
std::unique_ptr<Expression> fValue;
friend class IRGenerator;
using INHERITED = Statement;
};
/**
* A variable declaration appearing at global scope. A global declaration like 'int x, y;' produces
* two GlobalVarDeclaration elements, each containing the declaration of one variable.
*/
class GlobalVarDeclaration final : public ProgramElement {
public:
inline static constexpr Kind kProgramElementKind = Kind::kGlobalVar;
GlobalVarDeclaration(std::unique_ptr<Statement> decl)
: INHERITED(decl->fLine, kProgramElementKind)
, fDeclaration(std::move(decl)) {
SkASSERT(this->declaration()->is<VarDeclaration>());
}
std::unique_ptr<Statement>& declaration() {
return fDeclaration;
}
const std::unique_ptr<Statement>& declaration() const {
return fDeclaration;
}
std::unique_ptr<ProgramElement> clone() const override {
return std::make_unique<GlobalVarDeclaration>(this->declaration()->clone());
}
String description() const override {
return this->declaration()->description();
}
private:
std::unique_ptr<Statement> fDeclaration;
using INHERITED = ProgramElement;
};
} // namespace SkSL
#endif