unified ASTLayout/Layout and ASTModifiers/Modifiers
BUG=skia: Change-Id: Ib4c2c94401e586e93e926776e13c0f7c12212f7e Reviewed-on: https://skia-review.googlesource.com/5268 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
2b3dab62bc
commit
11d5397431
@ -4,7 +4,7 @@
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#include "SkSLIRGenerator.h"
|
||||
|
||||
#include "limits.h"
|
||||
@ -51,7 +51,7 @@ namespace SkSL {
|
||||
|
||||
class AutoSymbolTable {
|
||||
public:
|
||||
AutoSymbolTable(IRGenerator* ir)
|
||||
AutoSymbolTable(IRGenerator* ir)
|
||||
: fIR(ir)
|
||||
, fPrevious(fIR->fSymbolTable) {
|
||||
fIR->pushSymbolTable();
|
||||
@ -68,7 +68,7 @@ public:
|
||||
|
||||
class AutoLoopLevel {
|
||||
public:
|
||||
AutoLoopLevel(IRGenerator* ir)
|
||||
AutoLoopLevel(IRGenerator* ir)
|
||||
: fIR(ir) {
|
||||
fIR->fLoopLevel++;
|
||||
}
|
||||
@ -80,7 +80,7 @@ public:
|
||||
IRGenerator* fIR;
|
||||
};
|
||||
|
||||
IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
|
||||
IRGenerator::IRGenerator(const Context* context, std::shared_ptr<SymbolTable> symbolTable,
|
||||
ErrorReporter& errorReporter)
|
||||
: fContext(*context)
|
||||
, fCurrentFunction(nullptr)
|
||||
@ -162,10 +162,6 @@ std::unique_ptr<Statement> IRGenerator::convertVarDeclarationStatement(
|
||||
return std::unique_ptr<Statement>(new VarDeclarationsStatement(std::move(decl)));
|
||||
}
|
||||
|
||||
Modifiers IRGenerator::convertModifiers(const ASTModifiers& modifiers) {
|
||||
return Modifiers(modifiers);
|
||||
}
|
||||
|
||||
std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVarDeclarations& decl,
|
||||
Variable::Storage storage) {
|
||||
std::vector<VarDeclaration> variables;
|
||||
@ -174,7 +170,6 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa
|
||||
return nullptr;
|
||||
}
|
||||
for (const auto& varDecl : decl.fVars) {
|
||||
Modifiers modifiers = this->convertModifiers(decl.fModifiers);
|
||||
const Type* type = baseType;
|
||||
ASSERT(type->kind() != Type::kArray_Kind);
|
||||
std::vector<std::unique_ptr<Expression>> sizes;
|
||||
@ -205,8 +200,8 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa
|
||||
sizes.push_back(nullptr);
|
||||
}
|
||||
}
|
||||
auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, modifiers, varDecl.fName,
|
||||
*type, storage));
|
||||
auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, decl.fModifiers,
|
||||
varDecl.fName, *type, storage));
|
||||
std::unique_ptr<Expression> value;
|
||||
if (varDecl.fValue) {
|
||||
value = this->convertExpression(*varDecl.fValue);
|
||||
@ -215,7 +210,7 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa
|
||||
}
|
||||
value = this->coerce(std::move(value), *type);
|
||||
}
|
||||
if (storage == Variable::kGlobal_Storage && varDecl.fName == SkString("sk_FragColor") &&
|
||||
if (storage == Variable::kGlobal_Storage && varDecl.fName == SkString("sk_FragColor") &&
|
||||
(*fSymbolTable)[varDecl.fName]) {
|
||||
// already defined, ignore
|
||||
} else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDecl.fName] &&
|
||||
@ -229,19 +224,18 @@ std::unique_ptr<VarDeclarations> IRGenerator::convertVarDeclarations(const ASTVa
|
||||
fSymbolTable->add(varDecl.fName, std::move(var));
|
||||
}
|
||||
}
|
||||
return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition,
|
||||
return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition,
|
||||
baseType,
|
||||
std::move(variables)));
|
||||
}
|
||||
|
||||
std::unique_ptr<ModifiersDeclaration> IRGenerator::convertModifiersDeclaration(
|
||||
const ASTModifiersDeclaration& m) {
|
||||
Modifiers modifiers = this->convertModifiers(m.fModifiers);
|
||||
return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(modifiers));
|
||||
return std::unique_ptr<ModifiersDeclaration>(new ModifiersDeclaration(m.fModifiers));
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
|
||||
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
|
||||
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*s.fTest),
|
||||
*fContext.fBool_Type);
|
||||
if (!test) {
|
||||
return nullptr;
|
||||
@ -266,11 +260,11 @@ std::unique_ptr<Statement> IRGenerator::convertIf(const ASTIfStatement& s) {
|
||||
} 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.fPosition, std::move(empty),
|
||||
return std::unique_ptr<Statement>(new Block(s.fPosition, std::move(empty),
|
||||
fSymbolTable));
|
||||
}
|
||||
}
|
||||
return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(test),
|
||||
return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(test),
|
||||
std::move(ifTrue), std::move(ifFalse)));
|
||||
}
|
||||
|
||||
@ -303,14 +297,14 @@ std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) {
|
||||
if (!statement) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer),
|
||||
return std::unique_ptr<Statement>(new ForStatement(f.fPosition, std::move(initializer),
|
||||
std::move(test), std::move(next),
|
||||
std::move(statement), fSymbolTable));
|
||||
}
|
||||
|
||||
std::unique_ptr<Statement> IRGenerator::convertWhile(const ASTWhileStatement& w) {
|
||||
AutoLoopLevel level(this);
|
||||
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest),
|
||||
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*w.fTest),
|
||||
*fContext.fBool_Type);
|
||||
if (!test) {
|
||||
return nullptr;
|
||||
@ -334,7 +328,7 @@ std::unique_ptr<Statement> IRGenerator::convertDo(const ASTDoStatement& d) {
|
||||
if (!statement) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(statement),
|
||||
return std::unique_ptr<Statement>(new DoStatement(d.fPosition, std::move(statement),
|
||||
std::move(test)));
|
||||
}
|
||||
|
||||
@ -414,9 +408,8 @@ std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFuncti
|
||||
type = newType;
|
||||
}
|
||||
SkString name = param->fName;
|
||||
Modifiers modifiers = this->convertModifiers(param->fModifiers);
|
||||
Position pos = param->fPosition;
|
||||
Variable* var = new Variable(pos, modifiers, std::move(name), *type,
|
||||
Variable* var = new Variable(pos, param->fModifiers, std::move(name), *type,
|
||||
Variable::kParameter_Storage);
|
||||
fSymbolTable->takeOwnership(var);
|
||||
parameters.push_back(var);
|
||||
@ -452,22 +445,22 @@ std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFuncti
|
||||
if (*returnType != other->fReturnType) {
|
||||
FunctionDeclaration newDecl(f.fPosition, f.fName, parameters, *returnType);
|
||||
fErrors.error(f.fPosition, "functions '" + newDecl.description() +
|
||||
"' and '" + other->description() +
|
||||
"' and '" + other->description() +
|
||||
"' differ only in return type");
|
||||
return nullptr;
|
||||
}
|
||||
decl = other;
|
||||
for (size_t i = 0; i < parameters.size(); i++) {
|
||||
if (parameters[i]->fModifiers != other->fParameters[i]->fModifiers) {
|
||||
fErrors.error(f.fPosition, "modifiers on parameter " +
|
||||
to_string((uint64_t) i + 1) +
|
||||
fErrors.error(f.fPosition, "modifiers on parameter " +
|
||||
to_string((uint64_t) i + 1) +
|
||||
" differ between declaration and "
|
||||
"definition");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (other->fDefined) {
|
||||
fErrors.error(f.fPosition, "duplicate definition of " +
|
||||
fErrors.error(f.fPosition, "duplicate definition of " +
|
||||
other->description());
|
||||
}
|
||||
break;
|
||||
@ -498,7 +491,7 @@ std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFuncti
|
||||
if (!body) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f.fPosition, *decl,
|
||||
return std::unique_ptr<FunctionDefinition>(new FunctionDefinition(f.fPosition, *decl,
|
||||
std::move(body)));
|
||||
}
|
||||
return nullptr;
|
||||
@ -507,20 +500,19 @@ std::unique_ptr<FunctionDefinition> IRGenerator::convertFunction(const ASTFuncti
|
||||
std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInterfaceBlock& intf) {
|
||||
std::shared_ptr<SymbolTable> old = fSymbolTable;
|
||||
AutoSymbolTable table(this);
|
||||
Modifiers mods = this->convertModifiers(intf.fModifiers);
|
||||
std::vector<Type::Field> fields;
|
||||
for (size_t i = 0; i < intf.fDeclarations.size(); i++) {
|
||||
std::unique_ptr<VarDeclarations> decl = this->convertVarDeclarations(
|
||||
*intf.fDeclarations[i],
|
||||
*intf.fDeclarations[i],
|
||||
Variable::kGlobal_Storage);
|
||||
if (!decl) {
|
||||
return nullptr;
|
||||
}
|
||||
for (const auto& var : decl->fVars) {
|
||||
fields.push_back(Type::Field(var.fVar->fModifiers, var.fVar->fName,
|
||||
fields.push_back(Type::Field(var.fVar->fModifiers, var.fVar->fName,
|
||||
&var.fVar->fType));
|
||||
if (var.fValue) {
|
||||
fErrors.error(decl->fPosition,
|
||||
fErrors.error(decl->fPosition,
|
||||
"initializers are not permitted on interface block fields");
|
||||
}
|
||||
if (var.fVar->fModifiers.fFlags & (Modifiers::kIn_Flag |
|
||||
@ -530,18 +522,19 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTInte
|
||||
fErrors.error(decl->fPosition,
|
||||
"interface block fields may not have storage qualifiers");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Type* type = new Type(intf.fInterfaceName, fields);
|
||||
fSymbolTable->takeOwnership(type);
|
||||
SkString name = intf.fValueName.size() > 0 ? intf.fValueName : intf.fInterfaceName;
|
||||
Variable* var = new Variable(intf.fPosition, mods, name, *type, Variable::kGlobal_Storage);
|
||||
Variable* var = new Variable(intf.fPosition, intf.fModifiers, name, *type,
|
||||
Variable::kGlobal_Storage);
|
||||
fSymbolTable->takeOwnership(var);
|
||||
if (intf.fValueName.size()) {
|
||||
old->addWithoutOwnership(intf.fValueName, var);
|
||||
} else {
|
||||
for (size_t i = 0; i < fields.size(); i++) {
|
||||
old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var,
|
||||
old->add(fields[i].fName, std::unique_ptr<Field>(new Field(intf.fPosition, *var,
|
||||
(int) i)));
|
||||
}
|
||||
}
|
||||
@ -620,7 +613,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier&
|
||||
}
|
||||
case Symbol::kType_Kind: {
|
||||
const Type* t = (const Type*) result;
|
||||
return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fPosition,
|
||||
return std::unique_ptr<TypeReference>(new TypeReference(fContext, identifier.fPosition,
|
||||
*t));
|
||||
}
|
||||
default:
|
||||
@ -629,7 +622,7 @@ std::unique_ptr<Expression> IRGenerator::convertIdentifier(const ASTIdentifier&
|
||||
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
|
||||
std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
|
||||
const Type& type) {
|
||||
if (!expr) {
|
||||
return nullptr;
|
||||
@ -642,7 +635,7 @@ std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr
|
||||
return nullptr;
|
||||
}
|
||||
if (!expr->fType.canCoerceTo(type)) {
|
||||
fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" +
|
||||
fErrors.error(expr->fPosition, "expected '" + type.description() + "', but found '" +
|
||||
expr->fType.description() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -681,7 +674,7 @@ static bool is_assignment(Token::Kind op) {
|
||||
case Token::BITWISEANDEQ: // fall through
|
||||
case Token::LOGICALOREQ: // fall through
|
||||
case Token::LOGICALXOREQ: // fall through
|
||||
case Token::LOGICALANDEQ:
|
||||
case Token::LOGICALANDEQ:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@ -692,10 +685,10 @@ static bool is_assignment(Token::Kind op) {
|
||||
* Determines the operand and result types of a binary expression. Returns true if the expression is
|
||||
* legal, false otherwise. If false, the values of the out parameters are undefined.
|
||||
*/
|
||||
static bool determine_binary_type(const Context& context,
|
||||
Token::Kind op,
|
||||
const Type& left,
|
||||
const Type& right,
|
||||
static bool determine_binary_type(const Context& context,
|
||||
Token::Kind op,
|
||||
const Type& left,
|
||||
const Type& right,
|
||||
const Type** outLeftType,
|
||||
const Type** outRightType,
|
||||
const Type** outResultType,
|
||||
@ -729,18 +722,18 @@ static bool determine_binary_type(const Context& context,
|
||||
*outLeftType = context.fBool_Type.get();
|
||||
*outRightType = context.fBool_Type.get();
|
||||
*outResultType = context.fBool_Type.get();
|
||||
return left.canCoerceTo(*context.fBool_Type) &&
|
||||
return left.canCoerceTo(*context.fBool_Type) &&
|
||||
right.canCoerceTo(*context.fBool_Type);
|
||||
case Token::STAR: // fall through
|
||||
case Token::STAREQ:
|
||||
case Token::STAREQ:
|
||||
if (is_matrix_multiply(left, right)) {
|
||||
// determine final component type
|
||||
if (determine_binary_type(context, Token::STAR, left.componentType(),
|
||||
right.componentType(), outLeftType, outRightType,
|
||||
outResultType, false)) {
|
||||
*outLeftType = &(*outResultType)->toCompound(context, left.columns(),
|
||||
*outLeftType = &(*outResultType)->toCompound(context, left.columns(),
|
||||
left.rows());;
|
||||
*outRightType = &(*outResultType)->toCompound(context, right.columns(),
|
||||
*outRightType = &(*outResultType)->toCompound(context, right.columns(),
|
||||
right.rows());;
|
||||
int leftColumns = left.columns();
|
||||
int leftRows = left.rows();
|
||||
@ -787,7 +780,7 @@ static bool determine_binary_type(const Context& context,
|
||||
}
|
||||
bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
|
||||
// FIXME: incorrect for shift
|
||||
if (right.canCoerceTo(left) && (left.kind() == Type::kScalar_Kind ||
|
||||
if (right.canCoerceTo(left) && (left.kind() == Type::kScalar_Kind ||
|
||||
(isVectorOrMatrix && validMatrixOrVectorOp))) {
|
||||
*outLeftType = &left;
|
||||
*outRightType = &left;
|
||||
@ -798,13 +791,13 @@ static bool determine_binary_type(const Context& context,
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
|
||||
if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
|
||||
(right.kind() == Type::kScalar_Kind)) {
|
||||
if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
|
||||
if (determine_binary_type(context, op, left.componentType(), right, outLeftType,
|
||||
outRightType, outResultType, false)) {
|
||||
*outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
|
||||
if (!isLogical) {
|
||||
*outResultType = &(*outResultType)->toCompound(context, left.columns(),
|
||||
*outResultType = &(*outResultType)->toCompound(context, left.columns(),
|
||||
left.rows());
|
||||
}
|
||||
return true;
|
||||
@ -812,7 +805,7 @@ static bool determine_binary_type(const Context& context,
|
||||
return false;
|
||||
}
|
||||
if (tryFlipped) {
|
||||
return determine_binary_type(context, op, right, left, outRightType, outLeftType,
|
||||
return determine_binary_type(context, op, right, left, outRightType, outLeftType,
|
||||
outResultType, false);
|
||||
}
|
||||
return false;
|
||||
@ -830,7 +823,7 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
|
||||
// precision to calculate the results and hope the result makes sense. The plan is to move the
|
||||
// Skia caps into SkSL, so we have access to all of them including the precisions of the various
|
||||
// types, which will let us be more intelligent about this.
|
||||
if (left.fKind == Expression::kBoolLiteral_Kind &&
|
||||
if (left.fKind == Expression::kBoolLiteral_Kind &&
|
||||
right.fKind == Expression::kBoolLiteral_Kind) {
|
||||
bool leftVal = ((BoolLiteral&) left).fValue;
|
||||
bool rightVal = ((BoolLiteral&) right).fValue;
|
||||
@ -868,7 +861,7 @@ std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left,
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
if (left.fKind == Expression::kFloatLiteral_Kind &&
|
||||
if (left.fKind == Expression::kFloatLiteral_Kind &&
|
||||
right.fKind == Expression::kFloatLiteral_Kind) {
|
||||
double leftVal = ((FloatLiteral&) left).fValue;
|
||||
double rightVal = ((FloatLiteral&) right).fValue;
|
||||
@ -905,9 +898,9 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
|
||||
const Type* resultType;
|
||||
if (!determine_binary_type(fContext, expression.fOperator, left->fType, right->fType, &leftType,
|
||||
&rightType, &resultType, !is_assignment(expression.fOperator))) {
|
||||
fErrors.error(expression.fPosition, "type mismatch: '" +
|
||||
Token::OperatorName(expression.fOperator) +
|
||||
"' cannot operate on '" + left->fType.fName +
|
||||
fErrors.error(expression.fPosition, "type mismatch: '" +
|
||||
Token::OperatorName(expression.fOperator) +
|
||||
"' cannot operate on '" + left->fType.fName +
|
||||
"', '" + right->fType.fName + "'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -919,7 +912,7 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
|
||||
if (!left || !right) {
|
||||
return nullptr;
|
||||
}
|
||||
std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator,
|
||||
std::unique_ptr<Expression> result = this->constantFold(*left.get(), expression.fOperator,
|
||||
*right.get());
|
||||
if (!result) {
|
||||
result = std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition,
|
||||
@ -931,9 +924,9 @@ std::unique_ptr<Expression> IRGenerator::convertBinaryExpression(
|
||||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
|
||||
std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
|
||||
const ASTTernaryExpression& expression) {
|
||||
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
|
||||
std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*expression.fTest),
|
||||
*fContext.fBool_Type);
|
||||
if (!test) {
|
||||
return nullptr;
|
||||
@ -951,8 +944,8 @@ std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
|
||||
const Type* resultType;
|
||||
if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fType, &trueType,
|
||||
&falseType, &resultType, true)) {
|
||||
fErrors.error(expression.fPosition, "ternary operator result mismatch: '" +
|
||||
ifTrue->fType.fName + "', '" +
|
||||
fErrors.error(expression.fPosition, "ternary operator result mismatch: '" +
|
||||
ifTrue->fType.fName + "', '" +
|
||||
ifFalse->fType.fName + "'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -967,18 +960,18 @@ std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
|
||||
return ifFalse;
|
||||
}
|
||||
}
|
||||
return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition,
|
||||
return std::unique_ptr<Expression>(new TernaryExpression(expression.fPosition,
|
||||
std::move(test),
|
||||
std::move(ifTrue),
|
||||
std::move(ifTrue),
|
||||
std::move(ifFalse)));
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::call(Position position,
|
||||
const FunctionDeclaration& function,
|
||||
std::unique_ptr<Expression> IRGenerator::call(Position position,
|
||||
const FunctionDeclaration& function,
|
||||
std::vector<std::unique_ptr<Expression>> arguments) {
|
||||
if (function.fParameters.size() != arguments.size()) {
|
||||
SkString msg = "call to '" + function.fName + "' expected " +
|
||||
to_string((uint64_t) function.fParameters.size()) +
|
||||
SkString msg = "call to '" + function.fName + "' expected " +
|
||||
to_string((uint64_t) function.fParameters.size()) +
|
||||
" argument";
|
||||
if (function.fParameters.size() != 1) {
|
||||
msg += "s";
|
||||
@ -1015,11 +1008,11 @@ std::unique_ptr<Expression> IRGenerator::call(Position position,
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the cost of coercing the arguments of a function to the required types. Returns true
|
||||
* if the cost could be computed, false if the call is not valid. Cost has no particular meaning
|
||||
* Determines the cost of coercing the arguments of a function to the required types. Returns true
|
||||
* if the cost could be computed, false if the call is not valid. Cost has no particular meaning
|
||||
* other than "lower costs are preferred".
|
||||
*/
|
||||
bool IRGenerator::determineCallCost(const FunctionDeclaration& function,
|
||||
bool IRGenerator::determineCallCost(const FunctionDeclaration& function,
|
||||
const std::vector<std::unique_ptr<Expression>>& arguments,
|
||||
int* outCost) {
|
||||
if (function.fParameters.size() != arguments.size()) {
|
||||
@ -1043,12 +1036,12 @@ bool IRGenerator::determineCallCost(const FunctionDeclaration& function,
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::call(Position position,
|
||||
std::unique_ptr<Expression> functionValue,
|
||||
std::unique_ptr<Expression> IRGenerator::call(Position position,
|
||||
std::unique_ptr<Expression> functionValue,
|
||||
std::vector<std::unique_ptr<Expression>> arguments) {
|
||||
if (functionValue->fKind == Expression::kTypeReference_Kind) {
|
||||
return this->convertConstructor(position,
|
||||
((TypeReference&) *functionValue).fValue,
|
||||
return this->convertConstructor(position,
|
||||
((TypeReference&) *functionValue).fValue,
|
||||
std::move(arguments));
|
||||
}
|
||||
if (functionValue->fKind != Expression::kFunctionReference_Kind) {
|
||||
@ -1084,17 +1077,17 @@ std::unique_ptr<Expression> IRGenerator::call(Position position,
|
||||
}
|
||||
|
||||
std::unique_ptr<Expression> IRGenerator::convertConstructor(
|
||||
Position position,
|
||||
const Type& type,
|
||||
Position position,
|
||||
const Type& type,
|
||||
std::vector<std::unique_ptr<Expression>> args) {
|
||||
// FIXME: add support for structs and arrays
|
||||
Type::Kind kind = type.kind();
|
||||
if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind &&
|
||||
if (!type.isNumber() && kind != Type::kVector_Kind && kind != Type::kMatrix_Kind &&
|
||||
kind != Type::kArray_Kind) {
|
||||
fErrors.error(position, "cannot construct '" + type.description() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
if (type == *fContext.fFloat_Type && args.size() == 1 &&
|
||||
if (type == *fContext.fFloat_Type && args.size() == 1 &&
|
||||
args[0]->fKind == Expression::kIntLiteral_Kind) {
|
||||
int64_t value = ((IntLiteral&) *args[0]).fValue;
|
||||
return std::unique_ptr<Expression>(new FloatLiteral(fContext, position, (double) value));
|
||||
@ -1105,7 +1098,7 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
|
||||
}
|
||||
if (type.isNumber()) {
|
||||
if (args.size() != 1) {
|
||||
fErrors.error(position, "invalid arguments to '" + type.description() +
|
||||
fErrors.error(position, "invalid arguments to '" + type.description() +
|
||||
"' constructor, (expected exactly 1 argument, but found " +
|
||||
to_string((uint64_t) args.size()) + ")");
|
||||
return nullptr;
|
||||
@ -1116,17 +1109,17 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
|
||||
return std::unique_ptr<Expression>(
|
||||
new TernaryExpression(position, std::move(args[0]),
|
||||
this->coerce(std::move(one), type),
|
||||
this->coerce(std::move(zero),
|
||||
this->coerce(std::move(zero),
|
||||
type)));
|
||||
} else if (!args[0]->fType.isNumber()) {
|
||||
fErrors.error(position, "invalid argument to '" + type.description() +
|
||||
fErrors.error(position, "invalid argument to '" + type.description() +
|
||||
"' constructor (expected a number or bool, but found '" +
|
||||
args[0]->fType.description() + "')");
|
||||
}
|
||||
if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
|
||||
if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext.fInt_Type ||
|
||||
type == *fContext.fUInt_Type)) {
|
||||
return std::unique_ptr<Expression>(new IntLiteral(fContext,
|
||||
position,
|
||||
return std::unique_ptr<Expression>(new IntLiteral(fContext,
|
||||
position,
|
||||
((IntLiteral&) *args[0]).fValue,
|
||||
&type));
|
||||
}
|
||||
@ -1170,9 +1163,9 @@ std::unique_ptr<Expression> IRGenerator::convertConstructor(
|
||||
int max = type.columns() > 1 ? INT_MAX : min;
|
||||
if ((actual < min || actual > max) &&
|
||||
!((kind == Type::kVector_Kind || kind == Type::kMatrix_Kind) && (actual == 1))) {
|
||||
fErrors.error(position, "invalid arguments to '" + type.description() +
|
||||
"' constructor (expected " + to_string(min) + " scalar" +
|
||||
(min == 1 ? "" : "s") + ", but found " + to_string(actual) +
|
||||
fErrors.error(position, "invalid arguments to '" + type.description() +
|
||||
"' constructor (expected " + to_string(min) + " scalar" +
|
||||
(min == 1 ? "" : "s") + ", but found " + to_string(actual) +
|
||||
")");
|
||||
return nullptr;
|
||||
}
|
||||
@ -1189,14 +1182,14 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
|
||||
switch (expression.fOperator) {
|
||||
case Token::PLUS:
|
||||
if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
|
||||
fErrors.error(expression.fPosition,
|
||||
fErrors.error(expression.fPosition,
|
||||
"'+' cannot operate on '" + base->fType.description() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
return base;
|
||||
case Token::MINUS:
|
||||
if (!base->fType.isNumber() && base->fType.kind() != Type::kVector_Kind) {
|
||||
fErrors.error(expression.fPosition,
|
||||
fErrors.error(expression.fPosition,
|
||||
"'-' cannot operate on '" + base->fType.description() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -1206,23 +1199,23 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
|
||||
}
|
||||
if (base->fKind == Expression::kFloatLiteral_Kind) {
|
||||
double value = -((FloatLiteral&) *base).fValue;
|
||||
return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fPosition,
|
||||
return std::unique_ptr<Expression>(new FloatLiteral(fContext, base->fPosition,
|
||||
value));
|
||||
}
|
||||
return std::unique_ptr<Expression>(new PrefixExpression(Token::MINUS, std::move(base)));
|
||||
case Token::PLUSPLUS:
|
||||
if (!base->fType.isNumber()) {
|
||||
fErrors.error(expression.fPosition,
|
||||
"'" + Token::OperatorName(expression.fOperator) +
|
||||
fErrors.error(expression.fPosition,
|
||||
"'" + Token::OperatorName(expression.fOperator) +
|
||||
"' cannot operate on '" + base->fType.description() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
this->markWrittenTo(*base);
|
||||
break;
|
||||
case Token::MINUSMINUS:
|
||||
case Token::MINUSMINUS:
|
||||
if (!base->fType.isNumber()) {
|
||||
fErrors.error(expression.fPosition,
|
||||
"'" + Token::OperatorName(expression.fOperator) +
|
||||
fErrors.error(expression.fPosition,
|
||||
"'" + Token::OperatorName(expression.fOperator) +
|
||||
"' cannot operate on '" + base->fType.description() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -1230,8 +1223,8 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
|
||||
break;
|
||||
case Token::LOGICALNOT:
|
||||
if (base->fType != *fContext.fBool_Type) {
|
||||
fErrors.error(expression.fPosition,
|
||||
"'" + Token::OperatorName(expression.fOperator) +
|
||||
fErrors.error(expression.fPosition,
|
||||
"'" + Token::OperatorName(expression.fOperator) +
|
||||
"' cannot operate on '" + base->fType.description() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -1242,16 +1235,16 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(
|
||||
break;
|
||||
case Token::BITWISENOT:
|
||||
if (base->fType != *fContext.fInt_Type) {
|
||||
fErrors.error(expression.fPosition,
|
||||
"'" + Token::OperatorName(expression.fOperator) +
|
||||
fErrors.error(expression.fPosition,
|
||||
"'" + Token::OperatorName(expression.fOperator) +
|
||||
"' cannot operate on '" + base->fType.description() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
ABORT("unsupported prefix operator\n");
|
||||
}
|
||||
return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator,
|
||||
return std::unique_ptr<Expression>(new PrefixExpression(expression.fOperator,
|
||||
std::move(base)));
|
||||
}
|
||||
|
||||
@ -1259,7 +1252,7 @@ std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression
|
||||
const ASTExpression& index) {
|
||||
if (base->fType.kind() != Type::kArray_Kind && base->fType.kind() != Type::kMatrix_Kind &&
|
||||
base->fType.kind() != Type::kVector_Kind) {
|
||||
fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() +
|
||||
fErrors.error(base->fPosition, "expected array, but found '" + base->fType.description() +
|
||||
"'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -1273,7 +1266,7 @@ std::unique_ptr<Expression> IRGenerator::convertIndex(std::unique_ptr<Expression
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
|
||||
return std::unique_ptr<Expression>(new IndexExpression(fContext, std::move(base),
|
||||
std::move(converted)));
|
||||
}
|
||||
|
||||
@ -1301,7 +1294,7 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi
|
||||
switch (fields[i]) {
|
||||
case 'x': // fall through
|
||||
case 'r': // fall through
|
||||
case 's':
|
||||
case 's':
|
||||
swizzleComponents.push_back(0);
|
||||
break;
|
||||
case 'y': // fall through
|
||||
@ -1314,7 +1307,7 @@ std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expressi
|
||||
// fall through
|
||||
case 'z': // fall through
|
||||
case 'b': // fall through
|
||||
case 'p':
|
||||
case 'p':
|
||||
if (base->fType.columns() >= 3) {
|
||||
swizzleComponents.push_back(2);
|
||||
break;
|
||||
@ -1354,7 +1347,7 @@ std::unique_ptr<Expression> IRGenerator::getCap(Position position, SkString name
|
||||
return std::unique_ptr<Expression>(new BoolLiteral(fContext, position,
|
||||
(bool) found->second.fValue));
|
||||
case CapValue::kInt_Kind:
|
||||
return std::unique_ptr<Expression>(new IntLiteral(fContext, position,
|
||||
return std::unique_ptr<Expression>(new IntLiteral(fContext, position,
|
||||
found->second.fValue));
|
||||
}
|
||||
ASSERT(false);
|
||||
@ -1374,10 +1367,10 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
|
||||
return this->convertIndex(std::move(base), *expr);
|
||||
} else if (base->fKind == Expression::kTypeReference_Kind) {
|
||||
const Type& oldType = ((TypeReference&) *base).fValue;
|
||||
Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType,
|
||||
Type* newType = new Type(oldType.name() + "[]", Type::kArray_Kind, oldType,
|
||||
-1);
|
||||
fSymbolTable->takeOwnership(newType);
|
||||
return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition,
|
||||
return std::unique_ptr<Expression>(new TypeReference(fContext, base->fPosition,
|
||||
*newType));
|
||||
} else {
|
||||
fErrors.error(expression.fPosition, "'[]' must follow a type name");
|
||||
@ -1388,7 +1381,7 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
|
||||
auto rawArguments = &((ASTCallSuffix&) *expression.fSuffix).fArguments;
|
||||
std::vector<std::unique_ptr<Expression>> arguments;
|
||||
for (size_t i = 0; i < rawArguments->size(); i++) {
|
||||
std::unique_ptr<Expression> converted =
|
||||
std::unique_ptr<Expression> converted =
|
||||
this->convertExpression(*(*rawArguments)[i]);
|
||||
if (!converted) {
|
||||
return nullptr;
|
||||
@ -1404,34 +1397,34 @@ std::unique_ptr<Expression> IRGenerator::convertSuffixExpression(
|
||||
}
|
||||
switch (base->fType.kind()) {
|
||||
case Type::kVector_Kind:
|
||||
return this->convertSwizzle(std::move(base),
|
||||
return this->convertSwizzle(std::move(base),
|
||||
((ASTFieldSuffix&) *expression.fSuffix).fField);
|
||||
case Type::kStruct_Kind:
|
||||
return this->convertField(std::move(base),
|
||||
((ASTFieldSuffix&) *expression.fSuffix).fField);
|
||||
default:
|
||||
fErrors.error(base->fPosition, "cannot swizzle value of type '" +
|
||||
fErrors.error(base->fPosition, "cannot swizzle value of type '" +
|
||||
base->fType.description() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
case ASTSuffix::kPostIncrement_Kind:
|
||||
if (!base->fType.isNumber()) {
|
||||
fErrors.error(expression.fPosition,
|
||||
fErrors.error(expression.fPosition,
|
||||
"'++' cannot operate on '" + base->fType.description() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
this->markWrittenTo(*base);
|
||||
return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
|
||||
return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
|
||||
Token::PLUSPLUS));
|
||||
case ASTSuffix::kPostDecrement_Kind:
|
||||
if (!base->fType.isNumber()) {
|
||||
fErrors.error(expression.fPosition,
|
||||
fErrors.error(expression.fPosition,
|
||||
"'--' cannot operate on '" + base->fType.description() + "'");
|
||||
return nullptr;
|
||||
}
|
||||
this->markWrittenTo(*base);
|
||||
return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
|
||||
return std::unique_ptr<Expression>(new PostfixExpression(std::move(base),
|
||||
Token::MINUSMINUS));
|
||||
default:
|
||||
ABORT("unsupported suffix operator");
|
||||
@ -1475,7 +1468,7 @@ void IRGenerator::markWrittenTo(const Expression& expr) {
|
||||
case Expression::kVariableReference_Kind: {
|
||||
const Variable& var = ((VariableReference&) expr).fVariable;
|
||||
if (var.fModifiers.fFlags & (Modifiers::kConst_Flag | Modifiers::kUniform_Flag)) {
|
||||
fErrors.error(expr.fPosition,
|
||||
fErrors.error(expr.fPosition,
|
||||
"cannot modify immutable variable '" + var.fName + "'");
|
||||
}
|
||||
var.fIsWrittenTo = true;
|
||||
@ -1486,7 +1479,7 @@ void IRGenerator::markWrittenTo(const Expression& expr) {
|
||||
break;
|
||||
case Expression::kSwizzle_Kind:
|
||||
if (has_duplicates((Swizzle&) expr)) {
|
||||
fErrors.error(expr.fPosition,
|
||||
fErrors.error(expr.fPosition,
|
||||
"cannot write to the same swizzle field more than once");
|
||||
}
|
||||
this->markWrittenTo(*((Swizzle&) expr).fBase);
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SKSL_IRGENERATOR
|
||||
#define SKSL_IRGENERATOR
|
||||
|
||||
@ -24,7 +24,6 @@
|
||||
#include "ast/SkSLASTIdentifier.h"
|
||||
#include "ast/SkSLASTIfStatement.h"
|
||||
#include "ast/SkSLASTInterfaceBlock.h"
|
||||
#include "ast/SkSLASTModifiers.h"
|
||||
#include "ast/SkSLASTModifiersDeclaration.h"
|
||||
#include "ast/SkSLASTPrefixExpression.h"
|
||||
#include "ast/SkSLASTReturnStatement.h"
|
||||
@ -72,15 +71,15 @@ struct CapValue {
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs semantic analysis on an abstract syntax tree (AST) and produces the corresponding
|
||||
* Performs semantic analysis on an abstract syntax tree (AST) and produces the corresponding
|
||||
* (unoptimized) intermediate representation (IR).
|
||||
*/
|
||||
class IRGenerator {
|
||||
public:
|
||||
IRGenerator(const Context* context, std::shared_ptr<SymbolTable> root,
|
||||
IRGenerator(const Context* context, std::shared_ptr<SymbolTable> root,
|
||||
ErrorReporter& errorReporter);
|
||||
|
||||
std::unique_ptr<VarDeclarations> convertVarDeclarations(const ASTVarDeclarations& decl,
|
||||
std::unique_ptr<VarDeclarations> convertVarDeclarations(const ASTVarDeclarations& decl,
|
||||
Variable::Storage storage);
|
||||
std::unique_ptr<FunctionDefinition> convertFunction(const ASTFunction& f);
|
||||
std::unique_ptr<Statement> convertStatement(const ASTStatement& statement);
|
||||
@ -104,25 +103,25 @@ private:
|
||||
void popSymbolTable();
|
||||
|
||||
const Type* convertType(const ASTType& type);
|
||||
std::unique_ptr<Expression> call(Position position,
|
||||
const FunctionDeclaration& function,
|
||||
std::unique_ptr<Expression> call(Position position,
|
||||
const FunctionDeclaration& function,
|
||||
std::vector<std::unique_ptr<Expression>> arguments);
|
||||
bool determineCallCost(const FunctionDeclaration& function,
|
||||
bool determineCallCost(const FunctionDeclaration& function,
|
||||
const std::vector<std::unique_ptr<Expression>>& arguments,
|
||||
int* outCost);
|
||||
std::unique_ptr<Expression> call(Position position, std::unique_ptr<Expression> function,
|
||||
std::unique_ptr<Expression> call(Position position, std::unique_ptr<Expression> function,
|
||||
std::vector<std::unique_ptr<Expression>> arguments);
|
||||
std::unique_ptr<Expression> coerce(std::unique_ptr<Expression> expr, const Type& type);
|
||||
std::unique_ptr<Block> convertBlock(const ASTBlock& block);
|
||||
std::unique_ptr<Statement> convertBreak(const ASTBreakStatement& b);
|
||||
std::unique_ptr<Expression> convertConstructor(Position position,
|
||||
const Type& type,
|
||||
std::unique_ptr<Expression> convertConstructor(Position position,
|
||||
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<Expression> convertBinaryExpression(const ASTBinaryExpression& expression);
|
||||
// Returns null if it cannot fold the expression. Note that unlike most other functions here, a
|
||||
// Returns null if it cannot fold the expression. Note that unlike most other functions here, a
|
||||
// null return does not represent a compilation error.
|
||||
std::unique_ptr<Expression> constantFold(const Expression& left,
|
||||
Token::Kind op,
|
||||
@ -135,12 +134,12 @@ private:
|
||||
std::unique_ptr<Expression> convertIndex(std::unique_ptr<Expression> base,
|
||||
const ASTExpression& index);
|
||||
std::unique_ptr<InterfaceBlock> convertInterfaceBlock(const ASTInterfaceBlock& s);
|
||||
Modifiers convertModifiers(const ASTModifiers& m);
|
||||
Modifiers convertModifiers(const Modifiers& m);
|
||||
std::unique_ptr<Expression> convertPrefixExpression(const ASTPrefixExpression& expression);
|
||||
std::unique_ptr<Statement> convertReturn(const ASTReturnStatement& r);
|
||||
std::unique_ptr<Expression> getCap(Position position, SkString name);
|
||||
std::unique_ptr<Expression> convertSuffixExpression(const ASTSuffixExpression& expression);
|
||||
std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base,
|
||||
std::unique_ptr<Expression> convertField(std::unique_ptr<Expression> base,
|
||||
const SkString& field);
|
||||
std::unique_ptr<Expression> convertSwizzle(std::unique_ptr<Expression> base,
|
||||
const SkString& fields);
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#include "stdio.h"
|
||||
#include "SkSLParser.h"
|
||||
#include "SkSLToken.h"
|
||||
@ -69,6 +69,7 @@
|
||||
#include "ast/SkSLASTVarDeclarationStatement.h"
|
||||
#include "ast/SkSLASTWhileStatement.h"
|
||||
#include "ir/SkSLSymbolTable.h"
|
||||
#include "ir/SkSLModifiers.h"
|
||||
#include "ir/SkSLType.h"
|
||||
|
||||
namespace SkSL {
|
||||
@ -98,7 +99,7 @@ private:
|
||||
Parser* fParser;
|
||||
};
|
||||
|
||||
Parser::Parser(SkString text, SymbolTable& types, ErrorReporter& errors)
|
||||
Parser::Parser(SkString text, SymbolTable& types, ErrorReporter& errors)
|
||||
: fPushback(Position(-1, -1), Token::INVALID_TOKEN, SkString())
|
||||
, fTypes(types)
|
||||
, fErrors(errors) {
|
||||
@ -229,7 +230,7 @@ std::unique_ptr<ASTDeclaration> Parser::precision() {
|
||||
result = Modifiers::kHighp_Flag;
|
||||
break;
|
||||
default:
|
||||
this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" +
|
||||
this->error(p.fPosition, "expected 'lowp', 'mediump', or 'highp', but found '" +
|
||||
p.fText + "'");
|
||||
return nullptr;
|
||||
}
|
||||
@ -241,7 +242,7 @@ std::unique_ptr<ASTDeclaration> Parser::precision() {
|
||||
return std::unique_ptr<ASTDeclaration>(new ASTPrecision(p.fPosition, result));
|
||||
}
|
||||
|
||||
/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
|
||||
/* DIRECTIVE(#version) INT_LITERAL ("es" | "compatibility")? |
|
||||
DIRECTIVE(#extension) IDENTIFIER COLON IDENTIFIER */
|
||||
std::unique_ptr<ASTDeclaration> Parser::directive() {
|
||||
Token start;
|
||||
@ -269,7 +270,7 @@ std::unique_ptr<ASTDeclaration> Parser::directive() {
|
||||
if (!this->expect(Token::IDENTIFIER, "an identifier")) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition,
|
||||
return std::unique_ptr<ASTDeclaration>(new ASTExtension(start.fPosition,
|
||||
std::move(name.fText)));
|
||||
} else {
|
||||
this->error(start.fPosition, "unsupported directive '" + start.fText + "'");
|
||||
@ -277,10 +278,10 @@ std::unique_ptr<ASTDeclaration> Parser::directive() {
|
||||
}
|
||||
}
|
||||
|
||||
/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
|
||||
/* modifiers (structVarDeclaration | type IDENTIFIER ((LPAREN parameter
|
||||
(COMMA parameter)* RPAREN (block | SEMICOLON)) | SEMICOLON) | interfaceBlock) */
|
||||
std::unique_ptr<ASTDeclaration> Parser::declaration() {
|
||||
ASTModifiers modifiers = this->modifiers();
|
||||
Modifiers modifiers = this->modifiers();
|
||||
Token lookahead = this->peek();
|
||||
if (lookahead.fKind == Token::IDENTIFIER && !this->isType(lookahead.fText)) {
|
||||
// we have an identifier that's not a type, could be the start of an interface block
|
||||
@ -330,9 +331,9 @@ std::unique_ptr<ASTDeclaration> Parser::declaration() {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition, std::move(type),
|
||||
std::move(name.fText),
|
||||
std::move(parameters),
|
||||
return std::unique_ptr<ASTDeclaration>(new ASTFunction(name.fPosition, std::move(type),
|
||||
std::move(name.fText),
|
||||
std::move(parameters),
|
||||
std::move(body)));
|
||||
} else {
|
||||
return this->varDeclarationEnd(modifiers, std::move(type), name.fText);
|
||||
@ -341,7 +342,7 @@ std::unique_ptr<ASTDeclaration> Parser::declaration() {
|
||||
|
||||
/* modifiers type IDENTIFIER varDeclarationEnd */
|
||||
std::unique_ptr<ASTVarDeclarations> Parser::varDeclarations() {
|
||||
ASTModifiers modifiers = this->modifiers();
|
||||
Modifiers modifiers = this->modifiers();
|
||||
std::unique_ptr<ASTType> type(this->type());
|
||||
if (!type) {
|
||||
return nullptr;
|
||||
@ -393,25 +394,25 @@ std::unique_ptr<ASTType> Parser::structDeclaration() {
|
||||
return nullptr;
|
||||
}
|
||||
fTypes.add(name.fText, std::unique_ptr<Type>(new Type(name.fText, fields)));
|
||||
return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText,
|
||||
return std::unique_ptr<ASTType>(new ASTType(name.fPosition, name.fText,
|
||||
ASTType::kStruct_Kind));
|
||||
}
|
||||
|
||||
/* structDeclaration ((IDENTIFIER varDeclarationEnd) | SEMICOLON) */
|
||||
std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(ASTModifiers modifiers) {
|
||||
std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(Modifiers modifiers) {
|
||||
std::unique_ptr<ASTType> type = this->structDeclaration();
|
||||
if (!type) {
|
||||
return nullptr;
|
||||
}
|
||||
if (peek().fKind == Token::IDENTIFIER) {
|
||||
Token name = this->nextToken();
|
||||
std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers,
|
||||
std::move(type),
|
||||
std::unique_ptr<ASTVarDeclarations> result = this->varDeclarationEnd(modifiers,
|
||||
std::move(type),
|
||||
std::move(name.fText));
|
||||
if (result) {
|
||||
for (const auto& var : result->fVars) {
|
||||
if (var.fValue) {
|
||||
this->error(var.fValue->fPosition,
|
||||
this->error(var.fValue->fPosition,
|
||||
"struct variables cannot be initialized");
|
||||
}
|
||||
}
|
||||
@ -422,9 +423,9 @@ std::unique_ptr<ASTVarDeclarations> Parser::structVarDeclaration(ASTModifiers mo
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* (LBRACKET expression? RBRACKET)* (EQ expression)? (COMMA IDENTIFER
|
||||
/* (LBRACKET expression? RBRACKET)* (EQ expression)? (COMMA IDENTIFER
|
||||
(LBRACKET expression? RBRACKET)* (EQ expression)?)* SEMICOLON */
|
||||
std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(ASTModifiers mods,
|
||||
std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(Modifiers mods,
|
||||
std::unique_ptr<ASTType> type,
|
||||
SkString name) {
|
||||
std::vector<ASTVarDeclaration> vars;
|
||||
@ -497,7 +498,7 @@ std::unique_ptr<ASTVarDeclarations> Parser::varDeclarationEnd(ASTModifiers mods,
|
||||
|
||||
/* modifiers type IDENTIFIER (LBRACKET INT_LITERAL RBRACKET)? */
|
||||
std::unique_ptr<ASTParameter> Parser::parameter() {
|
||||
ASTModifiers modifiers = this->modifiersWithDefaults(ASTModifiers::kIn_Flag);
|
||||
Modifiers modifiers = this->modifiersWithDefaults(Modifiers::kIn_Flag);
|
||||
std::unique_ptr<ASTType> type = this->type();
|
||||
if (!type) {
|
||||
return nullptr;
|
||||
@ -518,8 +519,8 @@ std::unique_ptr<ASTParameter> Parser::parameter() {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers,
|
||||
std::move(type), name.fText,
|
||||
return std::unique_ptr<ASTParameter>(new ASTParameter(name.fPosition, modifiers,
|
||||
std::move(type), name.fText,
|
||||
std::move(sizes)));
|
||||
}
|
||||
|
||||
@ -536,7 +537,7 @@ int Parser::layoutInt() {
|
||||
}
|
||||
|
||||
/* LAYOUT LPAREN IDENTIFIER (EQ INT_LITERAL)? (COMMA IDENTIFIER (EQ INT_LITERAL)?)* RPAREN */
|
||||
ASTLayout Parser::layout() {
|
||||
Layout Parser::layout() {
|
||||
int location = -1;
|
||||
int binding = -1;
|
||||
int index = -1;
|
||||
@ -546,14 +547,14 @@ ASTLayout Parser::layout() {
|
||||
bool originUpperLeft = false;
|
||||
bool overrideCoverage = false;
|
||||
bool blendSupportAllEquations = false;
|
||||
ASTLayout::Format format = ASTLayout::Format::kUnspecified;
|
||||
Layout::Format format = Layout::Format::kUnspecified;
|
||||
bool pushConstant = false;
|
||||
if (this->peek().fKind == Token::LAYOUT) {
|
||||
this->nextToken();
|
||||
if (!this->expect(Token::LPAREN, "'('")) {
|
||||
return ASTLayout(location, binding, index, set, builtin, inputAttachmentIndex,
|
||||
originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
|
||||
pushConstant);
|
||||
return Layout(location, binding, index, set, builtin, inputAttachmentIndex,
|
||||
originUpperLeft, overrideCoverage, blendSupportAllEquations, format,
|
||||
pushConstant);
|
||||
}
|
||||
for (;;) {
|
||||
Token t = this->nextToken();
|
||||
@ -575,7 +576,7 @@ ASTLayout Parser::layout() {
|
||||
overrideCoverage = true;
|
||||
} else if (t.fText == "blend_support_all_equations") {
|
||||
blendSupportAllEquations = true;
|
||||
} else if (ASTLayout::ReadFormat(t.fText, &format)) {
|
||||
} else if (Layout::ReadFormat(t.fText, &format)) {
|
||||
// AST::ReadFormat stored the result in 'format'.
|
||||
} else if (t.fText == "push_constant") {
|
||||
pushConstant = true;
|
||||
@ -592,68 +593,68 @@ ASTLayout Parser::layout() {
|
||||
}
|
||||
}
|
||||
}
|
||||
return ASTLayout(location, binding, index, set, builtin, inputAttachmentIndex, originUpperLeft,
|
||||
return Layout(location, binding, index, set, builtin, inputAttachmentIndex, originUpperLeft,
|
||||
overrideCoverage, blendSupportAllEquations, format, pushConstant);
|
||||
}
|
||||
|
||||
/* layout? (UNIFORM | CONST | IN | OUT | INOUT | LOWP | MEDIUMP | HIGHP | FLAT | NOPERSPECTIVE)* */
|
||||
ASTModifiers Parser::modifiers() {
|
||||
ASTLayout layout = this->layout();
|
||||
Modifiers Parser::modifiers() {
|
||||
Layout layout = this->layout();
|
||||
int flags = 0;
|
||||
for (;;) {
|
||||
// TODO: handle duplicate / incompatible flags
|
||||
switch (peek().fKind) {
|
||||
case Token::UNIFORM:
|
||||
this->nextToken();
|
||||
flags |= ASTModifiers::kUniform_Flag;
|
||||
flags |= Modifiers::kUniform_Flag;
|
||||
break;
|
||||
case Token::CONST:
|
||||
this->nextToken();
|
||||
flags |= ASTModifiers::kConst_Flag;
|
||||
flags |= Modifiers::kConst_Flag;
|
||||
break;
|
||||
case Token::IN:
|
||||
this->nextToken();
|
||||
flags |= ASTModifiers::kIn_Flag;
|
||||
flags |= Modifiers::kIn_Flag;
|
||||
break;
|
||||
case Token::OUT:
|
||||
this->nextToken();
|
||||
flags |= ASTModifiers::kOut_Flag;
|
||||
flags |= Modifiers::kOut_Flag;
|
||||
break;
|
||||
case Token::INOUT:
|
||||
this->nextToken();
|
||||
flags |= ASTModifiers::kIn_Flag;
|
||||
flags |= ASTModifiers::kOut_Flag;
|
||||
flags |= Modifiers::kIn_Flag;
|
||||
flags |= Modifiers::kOut_Flag;
|
||||
break;
|
||||
case Token::LOWP:
|
||||
this->nextToken();
|
||||
flags |= ASTModifiers::kLowp_Flag;
|
||||
flags |= Modifiers::kLowp_Flag;
|
||||
break;
|
||||
case Token::MEDIUMP:
|
||||
this->nextToken();
|
||||
flags |= ASTModifiers::kMediump_Flag;
|
||||
flags |= Modifiers::kMediump_Flag;
|
||||
break;
|
||||
case Token::HIGHP:
|
||||
this->nextToken();
|
||||
flags |= ASTModifiers::kHighp_Flag;
|
||||
flags |= Modifiers::kHighp_Flag;
|
||||
break;
|
||||
case Token::FLAT:
|
||||
this->nextToken();
|
||||
flags |= ASTModifiers::kFlat_Flag;
|
||||
flags |= Modifiers::kFlat_Flag;
|
||||
break;
|
||||
case Token::NOPERSPECTIVE:
|
||||
this->nextToken();
|
||||
flags |= ASTModifiers::kNoPerspective_Flag;
|
||||
flags |= Modifiers::kNoPerspective_Flag;
|
||||
break;
|
||||
default:
|
||||
return ASTModifiers(layout, flags);
|
||||
return Modifiers(layout, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASTModifiers Parser::modifiersWithDefaults(int defaultFlags) {
|
||||
ASTModifiers result = this->modifiers();
|
||||
Modifiers Parser::modifiersWithDefaults(int defaultFlags) {
|
||||
Modifiers result = this->modifiers();
|
||||
if (!result.fFlags) {
|
||||
return ASTModifiers(result.fLayout, defaultFlags);
|
||||
return Modifiers(result.fLayout, defaultFlags);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -681,8 +682,8 @@ std::unique_ptr<ASTStatement> Parser::statement() {
|
||||
case Token::LBRACE:
|
||||
return this->block();
|
||||
case Token::SEMICOLON:
|
||||
this->nextToken();
|
||||
return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition,
|
||||
this->nextToken();
|
||||
return std::unique_ptr<ASTStatement>(new ASTBlock(start.fPosition,
|
||||
std::vector<std::unique_ptr<ASTStatement>>()));
|
||||
case Token::CONST: // fall through
|
||||
case Token::HIGHP: // fall through
|
||||
@ -706,7 +707,7 @@ std::unique_ptr<ASTStatement> Parser::statement() {
|
||||
// fall through
|
||||
default:
|
||||
return this->expressionStatement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* IDENTIFIER(type) */
|
||||
@ -719,25 +720,25 @@ std::unique_ptr<ASTType> Parser::type() {
|
||||
this->error(type.fPosition, ("no type named '" + type.fText + "'").c_str());
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText),
|
||||
return std::unique_ptr<ASTType>(new ASTType(type.fPosition, std::move(type.fText),
|
||||
ASTType::kIdentifier_Kind));
|
||||
}
|
||||
|
||||
/* IDENTIFIER LBRACE varDeclaration* RBRACE */
|
||||
std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(ASTModifiers mods) {
|
||||
std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(Modifiers mods) {
|
||||
Token name;
|
||||
if (!this->expect(Token::IDENTIFIER, "an identifier", &name)) {
|
||||
return nullptr;
|
||||
}
|
||||
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
|
||||
// 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.fPosition, "no type named '" + name.fText + "'");
|
||||
return nullptr;
|
||||
}
|
||||
this->nextToken();
|
||||
std::vector<std::unique_ptr<ASTVarDeclarations>> decls;
|
||||
std::vector<std::unique_ptr<ASTVarDeclarations>> decls;
|
||||
while (this->peek().fKind != Token::RBRACE) {
|
||||
std::unique_ptr<ASTVarDeclarations> decl = this->varDeclarations();
|
||||
if (!decl) {
|
||||
@ -751,7 +752,7 @@ std::unique_ptr<ASTDeclaration> Parser::interfaceBlock(ASTModifiers mods) {
|
||||
valueName = this->nextToken().fText;
|
||||
}
|
||||
this->expect(Token::SEMICOLON, "';'");
|
||||
return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods,
|
||||
return std::unique_ptr<ASTDeclaration>(new ASTInterfaceBlock(name.fPosition, mods,
|
||||
name.fText, std::move(valueName),
|
||||
std::move(decls)));
|
||||
}
|
||||
@ -784,8 +785,8 @@ std::unique_ptr<ASTIfStatement> Parser::ifStatement() {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, std::move(test),
|
||||
std::move(ifTrue),
|
||||
return std::unique_ptr<ASTIfStatement>(new ASTIfStatement(start.fPosition, std::move(test),
|
||||
std::move(ifTrue),
|
||||
std::move(ifFalse)));
|
||||
}
|
||||
|
||||
@ -815,7 +816,7 @@ std::unique_ptr<ASTDoStatement> Parser::doStatement() {
|
||||
if (!this->expect(Token::SEMICOLON, "';'")) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition,
|
||||
return std::unique_ptr<ASTDoStatement>(new ASTDoStatement(start.fPosition,
|
||||
std::move(statement),
|
||||
std::move(test)));
|
||||
}
|
||||
@ -840,12 +841,12 @@ std::unique_ptr<ASTWhileStatement> Parser::whileStatement() {
|
||||
if (!statement) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition,
|
||||
std::move(test),
|
||||
return std::unique_ptr<ASTWhileStatement>(new ASTWhileStatement(start.fPosition,
|
||||
std::move(test),
|
||||
std::move(statement)));
|
||||
}
|
||||
|
||||
/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
|
||||
/* FOR LPAREN (declaration | expression)? SEMICOLON expression? SEMICOLON expression? RPAREN
|
||||
STATEMENT */
|
||||
std::unique_ptr<ASTForStatement> Parser::forStatement() {
|
||||
Token start;
|
||||
@ -858,7 +859,7 @@ std::unique_ptr<ASTForStatement> Parser::forStatement() {
|
||||
std::unique_ptr<ASTStatement> initializer;
|
||||
Token nextToken = this->peek();
|
||||
switch (nextToken.fKind) {
|
||||
case Token::SEMICOLON:
|
||||
case Token::SEMICOLON:
|
||||
this->nextToken();
|
||||
break;
|
||||
case Token::CONST: {
|
||||
@ -908,7 +909,7 @@ std::unique_ptr<ASTForStatement> Parser::forStatement() {
|
||||
if (!statement) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition,
|
||||
return std::unique_ptr<ASTForStatement>(new ASTForStatement(start.fPosition,
|
||||
std::move(initializer),
|
||||
std::move(test), std::move(next),
|
||||
std::move(statement)));
|
||||
@ -930,7 +931,7 @@ std::unique_ptr<ASTReturnStatement> Parser::returnStatement() {
|
||||
if (!this->expect(Token::SEMICOLON, "';'")) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition,
|
||||
return std::unique_ptr<ASTReturnStatement>(new ASTReturnStatement(start.fPosition,
|
||||
std::move(expression)));
|
||||
}
|
||||
|
||||
@ -983,11 +984,11 @@ std::unique_ptr<ASTBlock> Parser::block() {
|
||||
std::vector<std::unique_ptr<ASTStatement>> statements;
|
||||
for (;;) {
|
||||
switch (this->peek().fKind) {
|
||||
case Token::RBRACE:
|
||||
case Token::RBRACE:
|
||||
this->nextToken();
|
||||
return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition,
|
||||
return std::unique_ptr<ASTBlock>(new ASTBlock(start.fPosition,
|
||||
std::move(statements)));
|
||||
case Token::END_OF_FILE:
|
||||
case Token::END_OF_FILE:
|
||||
this->error(this->peek().fPosition, "expected '}', but found end of file");
|
||||
return nullptr;
|
||||
default: {
|
||||
@ -1052,8 +1053,8 @@ std::unique_ptr<ASTExpression> Parser::assignmentExpression() {
|
||||
if (!right) {
|
||||
return nullptr;
|
||||
}
|
||||
result = std::unique_ptr<ASTExpression>(new ASTBinaryExpression(std::move(result),
|
||||
t,
|
||||
result = std::unique_ptr<ASTExpression>(new ASTBinaryExpression(std::move(result),
|
||||
t,
|
||||
std::move(right)));
|
||||
}
|
||||
default:
|
||||
@ -1076,8 +1077,8 @@ std::unique_ptr<ASTExpression> Parser::ternaryExpression() {
|
||||
}
|
||||
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),
|
||||
return std::unique_ptr<ASTExpression>(new ASTTernaryExpression(std::move(result),
|
||||
std::move(trueExpr),
|
||||
std::move(falseExpr)));
|
||||
}
|
||||
return nullptr;
|
||||
@ -1357,7 +1358,7 @@ std::unique_ptr<ASTExpression> Parser::postfixExpression() {
|
||||
}
|
||||
}
|
||||
|
||||
/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
|
||||
/* LBRACKET expression? RBRACKET | DOT IDENTIFIER | LPAREN parameters RPAREN |
|
||||
PLUSPLUS | MINUSMINUS */
|
||||
std::unique_ptr<ASTSuffix> Parser::suffix() {
|
||||
Token next = this->nextToken();
|
||||
@ -1398,17 +1399,17 @@ std::unique_ptr<ASTSuffix> Parser::suffix() {
|
||||
}
|
||||
}
|
||||
this->expect(Token::RPAREN, "')' to complete function parameters");
|
||||
return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition,
|
||||
return std::unique_ptr<ASTSuffix>(new ASTCallSuffix(next.fPosition,
|
||||
std::move(parameters)));
|
||||
}
|
||||
case Token::PLUSPLUS:
|
||||
return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
|
||||
return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
|
||||
ASTSuffix::kPostIncrement_Kind));
|
||||
case Token::MINUSMINUS:
|
||||
return std::unique_ptr<ASTSuffix>(new ASTSuffix(next.fPosition,
|
||||
ASTSuffix::kPostDecrement_Kind));
|
||||
default: {
|
||||
this->error(next.fPosition, "expected expression suffix, but found '" + next.fText +
|
||||
this->error(next.fPosition, "expected expression suffix, but found '" + next.fText +
|
||||
"'\n");
|
||||
return nullptr;
|
||||
}
|
||||
@ -1505,7 +1506,7 @@ bool Parser::boolLiteral(bool* dest) {
|
||||
bool Parser::identifier(SkString* dest) {
|
||||
Token t;
|
||||
if (this->expect(Token::IDENTIFIER, "identifier", &t)) {
|
||||
*dest = t.fText;
|
||||
*dest = t.fText;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SKSL_PARSER
|
||||
#define SKSL_PARSER
|
||||
|
||||
@ -31,8 +31,6 @@ struct ASTExpressionStatement;
|
||||
struct ASTForStatement;
|
||||
struct ASTIfStatement;
|
||||
struct ASTInterfaceBlock;
|
||||
struct ASTLayout;
|
||||
struct ASTModifiers;
|
||||
struct ASTParameter;
|
||||
struct ASTPrecision;
|
||||
struct ASTReturnStatement;
|
||||
@ -41,6 +39,8 @@ struct ASTSuffix;
|
||||
struct ASTType;
|
||||
struct ASTWhileStatement;
|
||||
struct ASTVarDeclarations;
|
||||
struct Layout;
|
||||
struct Modifiers;
|
||||
class SymbolTable;
|
||||
|
||||
/**
|
||||
@ -73,7 +73,7 @@ private:
|
||||
void pushback(Token t);
|
||||
|
||||
/**
|
||||
* Returns the next token without consuming it from the stream.
|
||||
* Returns the next token without consuming it from the stream.
|
||||
*/
|
||||
Token peek();
|
||||
|
||||
@ -91,7 +91,7 @@ private:
|
||||
|
||||
void error(Position p, const char* msg);
|
||||
void error(Position p, SkString msg);
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if the 'name' identifier refers to a type name. For instance, isType("int") will
|
||||
* always return true.
|
||||
@ -112,27 +112,27 @@ private:
|
||||
|
||||
std::unique_ptr<ASTType> structDeclaration();
|
||||
|
||||
std::unique_ptr<ASTVarDeclarations> structVarDeclaration(ASTModifiers modifiers);
|
||||
std::unique_ptr<ASTVarDeclarations> structVarDeclaration(Modifiers modifiers);
|
||||
|
||||
std::unique_ptr<ASTVarDeclarations> varDeclarationEnd(ASTModifiers modifiers,
|
||||
std::unique_ptr<ASTType> type,
|
||||
std::unique_ptr<ASTVarDeclarations> varDeclarationEnd(Modifiers modifiers,
|
||||
std::unique_ptr<ASTType> type,
|
||||
SkString name);
|
||||
|
||||
std::unique_ptr<ASTParameter> parameter();
|
||||
|
||||
int layoutInt();
|
||||
|
||||
ASTLayout layout();
|
||||
|
||||
Layout layout();
|
||||
|
||||
ASTModifiers modifiers();
|
||||
Modifiers modifiers();
|
||||
|
||||
ASTModifiers modifiersWithDefaults(int defaultFlags);
|
||||
Modifiers modifiersWithDefaults(int defaultFlags);
|
||||
|
||||
std::unique_ptr<ASTStatement> statement();
|
||||
|
||||
std::unique_ptr<ASTType> type();
|
||||
|
||||
std::unique_ptr<ASTDeclaration> interfaceBlock(ASTModifiers mods);
|
||||
std::unique_ptr<ASTDeclaration> interfaceBlock(Modifiers mods);
|
||||
|
||||
std::unique_ptr<ASTIfStatement> ifStatement();
|
||||
|
||||
@ -157,7 +157,7 @@ private:
|
||||
std::unique_ptr<ASTExpression> expression();
|
||||
|
||||
std::unique_ptr<ASTExpression> assignmentExpression();
|
||||
|
||||
|
||||
std::unique_ptr<ASTExpression> ternaryExpression();
|
||||
|
||||
std::unique_ptr<ASTExpression> logicalOrExpression();
|
||||
|
@ -4,11 +4,12 @@
|
||||
* 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 "SkSLASTVarDeclaration.h"
|
||||
#include "../ir/SkSLModifiers.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
@ -23,9 +24,9 @@ namespace SkSL {
|
||||
struct ASTInterfaceBlock : public ASTDeclaration {
|
||||
// valueName is empty when it was not present in the source
|
||||
ASTInterfaceBlock(Position position,
|
||||
ASTModifiers modifiers,
|
||||
SkString interfaceName,
|
||||
SkString valueName,
|
||||
Modifiers modifiers,
|
||||
SkString interfaceName,
|
||||
SkString valueName,
|
||||
std::vector<std::unique_ptr<ASTVarDeclarations>> declarations)
|
||||
: INHERITED(position, kInterfaceBlock_Kind)
|
||||
, fModifiers(modifiers)
|
||||
@ -45,7 +46,7 @@ struct ASTInterfaceBlock : public ASTDeclaration {
|
||||
return result + ";";
|
||||
}
|
||||
|
||||
const ASTModifiers fModifiers;
|
||||
const Modifiers fModifiers;
|
||||
const SkString fInterfaceName;
|
||||
const SkString fValueName;
|
||||
const std::vector<std::unique_ptr<ASTVarDeclarations>> fDeclarations;
|
||||
|
@ -1,164 +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_ASTLAYOUT
|
||||
#define SKSL_ASTLAYOUT
|
||||
|
||||
#include "SkSLASTNode.h"
|
||||
#include "SkSLUtil.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
/**
|
||||
* Represents a layout block appearing before a variable declaration, as in:
|
||||
*
|
||||
* layout (location = 0) int x;
|
||||
*/
|
||||
struct ASTLayout : public ASTNode {
|
||||
// These are used by images in GLSL. We only support a subset of what GL supports.
|
||||
enum class Format {
|
||||
kUnspecified = -1,
|
||||
kRGBA32F,
|
||||
kR32F,
|
||||
kRGBA16F,
|
||||
kR16F,
|
||||
kRGBA8,
|
||||
kR8,
|
||||
kRGBA8I,
|
||||
kR8I,
|
||||
};
|
||||
|
||||
static const char* FormatToStr(Format format) {
|
||||
switch (format) {
|
||||
case Format::kUnspecified: return "";
|
||||
case Format::kRGBA32F: return "rgba32f";
|
||||
case Format::kR32F: return "r32f";
|
||||
case Format::kRGBA16F: return "rgba16f";
|
||||
case Format::kR16F: return "r16f";
|
||||
case Format::kRGBA8: return "rgba8";
|
||||
case Format::kR8: return "r8";
|
||||
case Format::kRGBA8I: return "rgba8i";
|
||||
case Format::kR8I: return "r8i";
|
||||
}
|
||||
SkFAIL("Unexpected format");
|
||||
return "";
|
||||
}
|
||||
|
||||
static bool ReadFormat(SkString str, Format* format) {
|
||||
if (str == "rgba32f") {
|
||||
*format = Format::kRGBA32F;
|
||||
return true;
|
||||
} else if (str == "r32f") {
|
||||
*format = Format::kR32F;
|
||||
return true;
|
||||
} else if (str == "rgba16f") {
|
||||
*format = Format::kRGBA16F;
|
||||
return true;
|
||||
} else if (str == "r16f") {
|
||||
*format = Format::kR16F;
|
||||
return true;
|
||||
} else if (str == "rgba8") {
|
||||
*format = Format::kRGBA8;
|
||||
return true;
|
||||
} else if (str == "r8") {
|
||||
*format = Format::kR8;
|
||||
return true;
|
||||
} else if (str == "rgba8i") {
|
||||
*format = Format::kRGBA8I;
|
||||
return true;
|
||||
} else if (str == "r8i") {
|
||||
*format = Format::kR8I;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// For int parameters, a -1 means no value
|
||||
ASTLayout(int location, int binding, int index, int set, int builtin, int inputAttachmentIndex,
|
||||
bool originUpperLeft, bool overrideCoverage, bool blendSupportAllEquations,
|
||||
Format format, bool pushConstant)
|
||||
: fLocation(location)
|
||||
, fBinding(binding)
|
||||
, fIndex(index)
|
||||
, fSet(set)
|
||||
, fBuiltin(builtin)
|
||||
, fInputAttachmentIndex(inputAttachmentIndex)
|
||||
, fOriginUpperLeft(originUpperLeft)
|
||||
, fOverrideCoverage(overrideCoverage)
|
||||
, fBlendSupportAllEquations(blendSupportAllEquations)
|
||||
, fFormat(format)
|
||||
, fPushConstant(pushConstant) {}
|
||||
|
||||
SkString description() const {
|
||||
SkString result;
|
||||
SkString separator;
|
||||
if (fLocation >= 0) {
|
||||
result += separator + "location = " + to_string(fLocation);
|
||||
separator = ", ";
|
||||
}
|
||||
if (fBinding >= 0) {
|
||||
result += separator + "binding = " + to_string(fBinding);
|
||||
separator = ", ";
|
||||
}
|
||||
if (fIndex >= 0) {
|
||||
result += separator + "index = " + to_string(fIndex);
|
||||
separator = ", ";
|
||||
}
|
||||
if (fSet >= 0) {
|
||||
result += separator + "set = " + to_string(fSet);
|
||||
separator = ", ";
|
||||
}
|
||||
if (fBuiltin >= 0) {
|
||||
result += separator + "builtin = " + to_string(fBuiltin);
|
||||
separator = ", ";
|
||||
}
|
||||
if (fInputAttachmentIndex >= 0) {
|
||||
result += separator + "input_attachment_index = " + to_string(fBuiltin);
|
||||
separator = ", ";
|
||||
}
|
||||
if (fOriginUpperLeft) {
|
||||
result += separator + "origin_upper_left";
|
||||
separator = ", ";
|
||||
}
|
||||
if (fOverrideCoverage) {
|
||||
result += separator + "override_coverage";
|
||||
separator = ", ";
|
||||
}
|
||||
if (fBlendSupportAllEquations) {
|
||||
result += separator + "blend_support_all_equations";
|
||||
separator = ", ";
|
||||
}
|
||||
if (fFormat != Format::kUnspecified) {
|
||||
result += separator + FormatToStr(fFormat);
|
||||
separator = ", ";
|
||||
}
|
||||
if (fPushConstant) {
|
||||
result += separator + "push_constant";
|
||||
separator = ", ";
|
||||
}
|
||||
if (result.size() > 0) {
|
||||
result = "layout (" + result + ")";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const int fLocation;
|
||||
const int fBinding;
|
||||
const int fIndex;
|
||||
const int fSet;
|
||||
const int fBuiltin;
|
||||
const int fInputAttachmentIndex;
|
||||
const bool fOriginUpperLeft;
|
||||
const bool fOverrideCoverage;
|
||||
const bool fBlendSupportAllEquations;
|
||||
const Format fFormat;
|
||||
const bool fPushConstant;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
@ -1,78 +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_ASTMODIFIERS
|
||||
#define SKSL_ASTMODIFIERS
|
||||
|
||||
#include "SkSLASTLayout.h"
|
||||
#include "SkSLASTNode.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
/**
|
||||
* A set of modifier keywords (in, out, uniform, etc.) appearing before a declaration.
|
||||
*/
|
||||
struct ASTModifiers : public ASTNode {
|
||||
enum Flag {
|
||||
kNo_Flag = 0,
|
||||
kConst_Flag = 1,
|
||||
kIn_Flag = 2,
|
||||
kOut_Flag = 4,
|
||||
kLowp_Flag = 8,
|
||||
kMediump_Flag = 16,
|
||||
kHighp_Flag = 32,
|
||||
kUniform_Flag = 64,
|
||||
kFlat_Flag = 128,
|
||||
kNoPerspective_Flag = 256
|
||||
};
|
||||
|
||||
ASTModifiers(ASTLayout layout, int flags)
|
||||
: fLayout(layout)
|
||||
, fFlags(flags) {}
|
||||
|
||||
SkString description() const override {
|
||||
SkString result = fLayout.description();
|
||||
if (fFlags & kUniform_Flag) {
|
||||
result += "uniform ";
|
||||
}
|
||||
if (fFlags & kConst_Flag) {
|
||||
result += "const ";
|
||||
}
|
||||
if (fFlags & kLowp_Flag) {
|
||||
result += "lowp ";
|
||||
}
|
||||
if (fFlags & kMediump_Flag) {
|
||||
result += "mediump ";
|
||||
}
|
||||
if (fFlags & kHighp_Flag) {
|
||||
result += "highp ";
|
||||
}
|
||||
if (fFlags & kFlat_Flag) {
|
||||
result += "flat ";
|
||||
}
|
||||
if (fFlags & kNoPerspective_Flag) {
|
||||
result += "noperspective ";
|
||||
}
|
||||
|
||||
if ((fFlags & kIn_Flag) && (fFlags & kOut_Flag)) {
|
||||
result += "inout ";
|
||||
} else if (fFlags & kIn_Flag) {
|
||||
result += "in ";
|
||||
} else if (fFlags & kOut_Flag) {
|
||||
result += "out ";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const ASTLayout fLayout;
|
||||
const int fFlags;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
@ -4,12 +4,12 @@
|
||||
* 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 "SkSLASTDeclaration.h"
|
||||
#include "SkSLASTModifiers.h"
|
||||
#include "../ir/SkSLModifiers.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
@ -19,7 +19,7 @@ namespace SkSL {
|
||||
* layout(blend_support_all_equations) out;
|
||||
*/
|
||||
struct ASTModifiersDeclaration : public ASTDeclaration {
|
||||
ASTModifiersDeclaration(ASTModifiers modifiers)
|
||||
ASTModifiersDeclaration(Modifiers modifiers)
|
||||
: INHERITED(Position(), kModifiers_Kind)
|
||||
, fModifiers(modifiers) {}
|
||||
|
||||
@ -27,7 +27,7 @@ struct ASTModifiersDeclaration : public ASTDeclaration {
|
||||
return fModifiers.description() + ";";
|
||||
}
|
||||
|
||||
ASTModifiers fModifiers;
|
||||
Modifiers fModifiers;
|
||||
|
||||
typedef ASTDeclaration INHERITED;
|
||||
};
|
||||
|
@ -4,12 +4,12 @@
|
||||
* 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 "SkSLASTModifiers.h"
|
||||
#include "SkSLASTType.h"
|
||||
#include "../ir/SkSLModifiers.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
@ -17,9 +17,9 @@ 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.
|
||||
// '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(Position position, ASTModifiers modifiers, std::unique_ptr<ASTType> type,
|
||||
ASTParameter(Position position, Modifiers modifiers, std::unique_ptr<ASTType> type,
|
||||
SkString name, std::vector<int> sizes)
|
||||
: INHERITED(position)
|
||||
, fModifiers(modifiers)
|
||||
@ -35,7 +35,7 @@ struct ASTParameter : public ASTPositionNode {
|
||||
return result;
|
||||
}
|
||||
|
||||
const ASTModifiers fModifiers;
|
||||
const Modifiers fModifiers;
|
||||
const std::unique_ptr<ASTType> fType;
|
||||
const SkString fName;
|
||||
const std::vector<int> fSizes;
|
||||
|
@ -4,21 +4,21 @@
|
||||
* 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 "SkSLASTDeclaration.h"
|
||||
#include "SkSLASTModifiers.h"
|
||||
#include "SkSLASTStatement.h"
|
||||
#include "SkSLASTType.h"
|
||||
#include "../SkSLUtil.h"
|
||||
#include "../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
|
||||
* 'int x = 2, y[3];' is an ASTVarDeclarations statement containing two individual ASTVarDeclaration
|
||||
* instances.
|
||||
*/
|
||||
struct ASTVarDeclaration {
|
||||
@ -41,7 +41,7 @@ struct ASTVarDeclaration {
|
||||
if (fValue) {
|
||||
result += " = " + fValue->description();
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
SkString fName;
|
||||
@ -57,8 +57,8 @@ struct ASTVarDeclaration {
|
||||
* A variable declaration statement, which may consist of one or more individual variables.
|
||||
*/
|
||||
struct ASTVarDeclarations : public ASTDeclaration {
|
||||
ASTVarDeclarations(ASTModifiers modifiers,
|
||||
std::unique_ptr<ASTType> type,
|
||||
ASTVarDeclarations(Modifiers modifiers,
|
||||
std::unique_ptr<ASTType> type,
|
||||
std::vector<ASTVarDeclaration> vars)
|
||||
: INHERITED(type->fPosition, kVar_Kind)
|
||||
, fModifiers(modifiers)
|
||||
@ -76,7 +76,7 @@ struct ASTVarDeclarations : public ASTDeclaration {
|
||||
return result;
|
||||
}
|
||||
|
||||
const ASTModifiers fModifiers;
|
||||
const Modifiers fModifiers;
|
||||
const std::unique_ptr<ASTType> fType;
|
||||
const std::vector<ASTVarDeclaration> fVars;
|
||||
|
||||
|
@ -4,10 +4,13 @@
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SKSL_LAYOUT
|
||||
#define SKSL_LAYOUT
|
||||
|
||||
#include "SkString.h"
|
||||
#include "SkSLUtil.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
/**
|
||||
@ -16,22 +19,67 @@ namespace SkSL {
|
||||
* layout (location = 0) int x;
|
||||
*/
|
||||
struct Layout {
|
||||
Layout(const ASTLayout& layout)
|
||||
: fLocation(layout.fLocation)
|
||||
, fBinding(layout.fBinding)
|
||||
, fIndex(layout.fIndex)
|
||||
, fSet(layout.fSet)
|
||||
, fBuiltin(layout.fBuiltin)
|
||||
, fInputAttachmentIndex(layout.fInputAttachmentIndex)
|
||||
, fOriginUpperLeft(layout.fOriginUpperLeft)
|
||||
, fOverrideCoverage(layout.fOverrideCoverage)
|
||||
, fBlendSupportAllEquations(layout.fBlendSupportAllEquations)
|
||||
, fFormat(layout.fFormat)
|
||||
, fPushConstant(layout.fPushConstant) {}
|
||||
// These are used by images in GLSL. We only support a subset of what GL supports.
|
||||
enum class Format {
|
||||
kUnspecified = -1,
|
||||
kRGBA32F,
|
||||
kR32F,
|
||||
kRGBA16F,
|
||||
kR16F,
|
||||
kRGBA8,
|
||||
kR8,
|
||||
kRGBA8I,
|
||||
kR8I,
|
||||
};
|
||||
|
||||
static const char* FormatToStr(Format format) {
|
||||
switch (format) {
|
||||
case Format::kUnspecified: return "";
|
||||
case Format::kRGBA32F: return "rgba32f";
|
||||
case Format::kR32F: return "r32f";
|
||||
case Format::kRGBA16F: return "rgba16f";
|
||||
case Format::kR16F: return "r16f";
|
||||
case Format::kRGBA8: return "rgba8";
|
||||
case Format::kR8: return "r8";
|
||||
case Format::kRGBA8I: return "rgba8i";
|
||||
case Format::kR8I: return "r8i";
|
||||
}
|
||||
SkFAIL("Unexpected format");
|
||||
return "";
|
||||
}
|
||||
|
||||
static bool ReadFormat(SkString str, Format* format) {
|
||||
if (str == "rgba32f") {
|
||||
*format = Format::kRGBA32F;
|
||||
return true;
|
||||
} else if (str == "r32f") {
|
||||
*format = Format::kR32F;
|
||||
return true;
|
||||
} else if (str == "rgba16f") {
|
||||
*format = Format::kRGBA16F;
|
||||
return true;
|
||||
} else if (str == "r16f") {
|
||||
*format = Format::kR16F;
|
||||
return true;
|
||||
} else if (str == "rgba8") {
|
||||
*format = Format::kRGBA8;
|
||||
return true;
|
||||
} else if (str == "r8") {
|
||||
*format = Format::kR8;
|
||||
return true;
|
||||
} else if (str == "rgba8i") {
|
||||
*format = Format::kRGBA8I;
|
||||
return true;
|
||||
} else if (str == "r8i") {
|
||||
*format = Format::kR8I;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Layout(int location, int binding, int index, int set, int builtin, int inputAttachmentIndex,
|
||||
bool originUpperLeft, bool overrideCoverage, bool blendSupportAllEquations,
|
||||
ASTLayout::Format format, bool pushconstant)
|
||||
Format format, bool pushconstant)
|
||||
: fLocation(location)
|
||||
, fBinding(binding)
|
||||
, fIndex(index)
|
||||
@ -54,7 +102,7 @@ struct Layout {
|
||||
, fOriginUpperLeft(false)
|
||||
, fOverrideCoverage(false)
|
||||
, fBlendSupportAllEquations(false)
|
||||
, fFormat(ASTLayout::Format::kUnspecified)
|
||||
, fFormat(Format::kUnspecified)
|
||||
, fPushConstant(false) {}
|
||||
|
||||
SkString description() const {
|
||||
@ -96,8 +144,8 @@ struct Layout {
|
||||
result += separator + "blend_support_all_equations";
|
||||
separator = ", ";
|
||||
}
|
||||
if (ASTLayout::Format::kUnspecified != fFormat) {
|
||||
result += separator + ASTLayout::FormatToStr(fFormat);
|
||||
if (Format::kUnspecified != fFormat) {
|
||||
result += separator + FormatToStr(fFormat);
|
||||
separator = ", ";
|
||||
}
|
||||
if (fPushConstant) {
|
||||
@ -140,7 +188,7 @@ struct Layout {
|
||||
bool fOriginUpperLeft;
|
||||
bool fOverrideCoverage;
|
||||
bool fBlendSupportAllEquations;
|
||||
ASTLayout::Format fFormat;
|
||||
Format fFormat;
|
||||
bool fPushConstant;
|
||||
};
|
||||
|
||||
|
@ -4,40 +4,35 @@
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SKSL_MODIFIERS
|
||||
#define SKSL_MODIFIERS
|
||||
|
||||
#include "../ast/SkSLASTModifiers.h"
|
||||
#include "SkSLLayout.h"
|
||||
|
||||
namespace SkSL {
|
||||
|
||||
/**
|
||||
* A set of modifier keywords (in, out, uniform, etc.) appearing before a declaration.
|
||||
* A set of modifier keywords (in, out, uniform, etc.) appearing before a declaration.
|
||||
*/
|
||||
struct Modifiers {
|
||||
enum Flag {
|
||||
kNo_Flag = ASTModifiers::kNo_Flag,
|
||||
kConst_Flag = ASTModifiers::kConst_Flag,
|
||||
kIn_Flag = ASTModifiers::kIn_Flag,
|
||||
kOut_Flag = ASTModifiers::kOut_Flag,
|
||||
kLowp_Flag = ASTModifiers::kLowp_Flag,
|
||||
kMediump_Flag = ASTModifiers::kMediump_Flag,
|
||||
kHighp_Flag = ASTModifiers::kHighp_Flag,
|
||||
kUniform_Flag = ASTModifiers::kUniform_Flag,
|
||||
kFlat_Flag = ASTModifiers::kFlat_Flag,
|
||||
kNoPerspective_Flag = ASTModifiers::kNoPerspective_Flag
|
||||
kNo_Flag = 0,
|
||||
kConst_Flag = 1,
|
||||
kIn_Flag = 2,
|
||||
kOut_Flag = 4,
|
||||
kLowp_Flag = 8,
|
||||
kMediump_Flag = 16,
|
||||
kHighp_Flag = 32,
|
||||
kUniform_Flag = 64,
|
||||
kFlat_Flag = 128,
|
||||
kNoPerspective_Flag = 256
|
||||
};
|
||||
|
||||
Modifiers()
|
||||
: fLayout(Layout())
|
||||
, fFlags(0) {}
|
||||
|
||||
Modifiers(const ASTModifiers& modifiers)
|
||||
: fLayout(modifiers.fLayout)
|
||||
, fFlags(modifiers.fFlags) {}
|
||||
|
||||
Modifiers(Layout& layout, int flags)
|
||||
: fLayout(layout)
|
||||
, fFlags(flags) {}
|
||||
|
Loading…
Reference in New Issue
Block a user