Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2018 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
| 7 | |
| 8 | #ifndef SKSL_STANDALONE |
| 9 | |
| 10 | #include "SkSLInterpreter.h" |
| 11 | #include "ir/SkSLBinaryExpression.h" |
| 12 | #include "ir/SkSLExpressionStatement.h" |
| 13 | #include "ir/SkSLForStatement.h" |
| 14 | #include "ir/SkSLFunctionCall.h" |
| 15 | #include "ir/SkSLFunctionReference.h" |
| 16 | #include "ir/SkSLIfStatement.h" |
| 17 | #include "ir/SkSLIndexExpression.h" |
| 18 | #include "ir/SkSLPostfixExpression.h" |
| 19 | #include "ir/SkSLPrefixExpression.h" |
| 20 | #include "ir/SkSLProgram.h" |
| 21 | #include "ir/SkSLStatement.h" |
| 22 | #include "ir/SkSLTernaryExpression.h" |
| 23 | #include "ir/SkSLVarDeclarations.h" |
| 24 | #include "ir/SkSLVarDeclarationsStatement.h" |
| 25 | #include "ir/SkSLVariableReference.h" |
| 26 | #include "SkRasterPipeline.h" |
| 27 | #include "../jumper/SkJumper.h" |
| 28 | |
| 29 | namespace SkSL { |
| 30 | |
| 31 | void Interpreter::run() { |
Ethan Nicholas | 3c6ae62 | 2018-04-24 13:06:09 -0400 | [diff] [blame] | 32 | for (const auto& e : *fProgram) { |
| 33 | if (ProgramElement::kFunction_Kind == e.fKind) { |
| 34 | const FunctionDefinition& f = (const FunctionDefinition&) e; |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 35 | if ("appendStages" == f.fDeclaration.fName) { |
| 36 | this->run(f); |
| 37 | return; |
| 38 | } |
| 39 | } |
| 40 | } |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 41 | SkASSERT(false); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 42 | } |
| 43 | |
| 44 | static int SizeOf(const Type& type) { |
| 45 | return 1; |
| 46 | } |
| 47 | |
| 48 | void Interpreter::run(const FunctionDefinition& f) { |
| 49 | fVars.emplace_back(); |
| 50 | StackIndex current = (StackIndex) fStack.size(); |
| 51 | for (int i = f.fDeclaration.fParameters.size() - 1; i >= 0; --i) { |
| 52 | current -= SizeOf(f.fDeclaration.fParameters[i]->fType); |
| 53 | fVars.back()[f.fDeclaration.fParameters[i]] = current; |
| 54 | } |
| 55 | fCurrentIndex.push_back({ f.fBody.get(), 0 }); |
| 56 | while (fCurrentIndex.size()) { |
| 57 | this->runStatement(); |
| 58 | } |
| 59 | } |
| 60 | |
| 61 | void Interpreter::push(Value value) { |
| 62 | fStack.push_back(value); |
| 63 | } |
| 64 | |
| 65 | Interpreter::Value Interpreter::pop() { |
| 66 | auto iter = fStack.end() - 1; |
| 67 | Value result = *iter; |
| 68 | fStack.erase(iter); |
| 69 | return result; |
| 70 | } |
| 71 | |
| 72 | Interpreter::StackIndex Interpreter::stackAlloc(int count) { |
| 73 | int result = fStack.size(); |
| 74 | for (int i = 0; i < count; ++i) { |
| 75 | fStack.push_back(Value((int) 0xDEADBEEF)); |
| 76 | } |
| 77 | return result; |
| 78 | } |
| 79 | |
| 80 | void Interpreter::runStatement() { |
| 81 | const Statement& stmt = *fCurrentIndex.back().fStatement; |
| 82 | const size_t index = fCurrentIndex.back().fIndex; |
| 83 | fCurrentIndex.pop_back(); |
| 84 | switch (stmt.fKind) { |
| 85 | case Statement::kBlock_Kind: { |
| 86 | const Block& b = (const Block&) stmt; |
| 87 | if (!b.fStatements.size()) { |
| 88 | break; |
| 89 | } |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 90 | SkASSERT(index < b.fStatements.size()); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 91 | if (index < b.fStatements.size() - 1) { |
| 92 | fCurrentIndex.push_back({ &b, index + 1 }); |
| 93 | } |
| 94 | fCurrentIndex.push_back({ b.fStatements[index].get(), 0 }); |
| 95 | break; |
| 96 | } |
| 97 | case Statement::kBreak_Kind: |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 98 | SkASSERT(index == 0); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 99 | abort(); |
| 100 | case Statement::kContinue_Kind: |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 101 | SkASSERT(index == 0); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 102 | abort(); |
| 103 | case Statement::kDiscard_Kind: |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 104 | SkASSERT(index == 0); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 105 | abort(); |
| 106 | case Statement::kDo_Kind: |
| 107 | abort(); |
| 108 | case Statement::kExpression_Kind: |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 109 | SkASSERT(index == 0); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 110 | this->evaluate(*((const ExpressionStatement&) stmt).fExpression); |
| 111 | break; |
| 112 | case Statement::kFor_Kind: { |
| 113 | ForStatement& f = (ForStatement&) stmt; |
| 114 | switch (index) { |
| 115 | case 0: |
| 116 | // initializer |
| 117 | fCurrentIndex.push_back({ &f, 1 }); |
| 118 | if (f.fInitializer) { |
| 119 | fCurrentIndex.push_back({ f.fInitializer.get(), 0 }); |
| 120 | } |
| 121 | break; |
| 122 | case 1: |
| 123 | // test & body |
| 124 | if (f.fTest && !evaluate(*f.fTest).fBool) { |
| 125 | break; |
| 126 | } else { |
| 127 | fCurrentIndex.push_back({ &f, 2 }); |
| 128 | fCurrentIndex.push_back({ f.fStatement.get(), 0 }); |
| 129 | } |
| 130 | break; |
| 131 | case 2: |
| 132 | // next |
| 133 | if (f.fNext) { |
| 134 | this->evaluate(*f.fNext); |
| 135 | } |
| 136 | fCurrentIndex.push_back({ &f, 1 }); |
| 137 | break; |
| 138 | default: |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 139 | SkASSERT(false); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 140 | } |
| 141 | break; |
| 142 | } |
| 143 | case Statement::kGroup_Kind: |
| 144 | abort(); |
| 145 | case Statement::kIf_Kind: { |
| 146 | IfStatement& i = (IfStatement&) stmt; |
| 147 | if (evaluate(*i.fTest).fBool) { |
| 148 | fCurrentIndex.push_back({ i.fIfTrue.get(), 0 }); |
| 149 | } else if (i.fIfFalse) { |
| 150 | fCurrentIndex.push_back({ i.fIfFalse.get(), 0 }); |
| 151 | } |
| 152 | break; |
| 153 | } |
| 154 | case Statement::kNop_Kind: |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 155 | SkASSERT(index == 0); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 156 | break; |
| 157 | case Statement::kReturn_Kind: |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 158 | SkASSERT(index == 0); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 159 | abort(); |
| 160 | case Statement::kSwitch_Kind: |
| 161 | abort(); |
| 162 | case Statement::kVarDeclarations_Kind: |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 163 | SkASSERT(index == 0); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 164 | for (const auto& decl :((const VarDeclarationsStatement&) stmt).fDeclaration->fVars) { |
| 165 | const Variable* var = ((VarDeclaration&) *decl).fVar; |
| 166 | StackIndex pos = this->stackAlloc(SizeOf(var->fType)); |
| 167 | fVars.back()[var] = pos; |
| 168 | if (var->fInitialValue) { |
| 169 | fStack[pos] = this->evaluate(*var->fInitialValue); |
| 170 | } |
| 171 | } |
| 172 | break; |
| 173 | case Statement::kWhile_Kind: |
| 174 | abort(); |
| 175 | default: |
| 176 | abort(); |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | static Interpreter::TypeKind type_kind(const Type& type) { |
| 181 | if (type.fName == "int") { |
| 182 | return Interpreter::kInt_TypeKind; |
| 183 | } else if (type.fName == "float") { |
| 184 | return Interpreter::kFloat_TypeKind; |
| 185 | } |
| 186 | ABORT("unsupported type: %s\n", type.description().c_str()); |
| 187 | } |
| 188 | |
| 189 | Interpreter::StackIndex Interpreter::getLValue(const Expression& expr) { |
| 190 | switch (expr.fKind) { |
| 191 | case Expression::kFieldAccess_Kind: |
| 192 | break; |
| 193 | case Expression::kIndex_Kind: { |
| 194 | const IndexExpression& idx = (const IndexExpression&) expr; |
| 195 | return this->evaluate(*idx.fBase).fInt + this->evaluate(*idx.fIndex).fInt; |
| 196 | } |
| 197 | case Expression::kSwizzle_Kind: |
| 198 | break; |
| 199 | case Expression::kVariableReference_Kind: |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 200 | SkASSERT(fVars.size()); |
| 201 | SkASSERT(fVars.back().find(&((VariableReference&) expr).fVariable) != |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 202 | fVars.back().end()); |
| 203 | return fVars.back()[&((VariableReference&) expr).fVariable]; |
| 204 | case Expression::kTernary_Kind: { |
| 205 | const TernaryExpression& t = (const TernaryExpression&) expr; |
| 206 | return this->getLValue(this->evaluate(*t.fTest).fBool ? *t.fIfTrue : *t.fIfFalse); |
| 207 | } |
| 208 | case Expression::kTypeReference_Kind: |
| 209 | break; |
| 210 | default: |
| 211 | break; |
| 212 | } |
| 213 | ABORT("unsupported lvalue"); |
| 214 | } |
| 215 | |
| 216 | struct CallbackCtx : public SkJumper_CallbackCtx { |
| 217 | Interpreter* fInterpreter; |
| 218 | const FunctionDefinition* fFunction; |
| 219 | }; |
| 220 | |
| 221 | static void do_callback(SkJumper_CallbackCtx* raw, int activePixels) { |
| 222 | CallbackCtx& ctx = (CallbackCtx&) *raw; |
| 223 | for (int i = 0; i < activePixels; ++i) { |
| 224 | ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 0])); |
| 225 | ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 1])); |
| 226 | ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 2])); |
| 227 | ctx.fInterpreter->run(*ctx.fFunction); |
| 228 | ctx.read_from[i * 4 + 2] = ctx.fInterpreter->pop().fFloat; |
| 229 | ctx.read_from[i * 4 + 1] = ctx.fInterpreter->pop().fFloat; |
| 230 | ctx.read_from[i * 4 + 0] = ctx.fInterpreter->pop().fFloat; |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | void Interpreter::appendStage(const AppendStage& a) { |
| 235 | switch (a.fStage) { |
| 236 | case SkRasterPipeline::matrix_4x5: { |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 237 | SkASSERT(a.fArguments.size() == 1); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 238 | StackIndex transpose = evaluate(*a.fArguments[0]).fInt; |
| 239 | fPipeline.append(SkRasterPipeline::matrix_4x5, &fStack[transpose]); |
| 240 | break; |
| 241 | } |
| 242 | case SkRasterPipeline::callback: { |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 243 | SkASSERT(a.fArguments.size() == 1); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 244 | CallbackCtx* ctx = new CallbackCtx(); |
| 245 | ctx->fInterpreter = this; |
| 246 | ctx->fn = do_callback; |
Ethan Nicholas | 3c6ae62 | 2018-04-24 13:06:09 -0400 | [diff] [blame] | 247 | for (const auto& e : *fProgram) { |
| 248 | if (ProgramElement::kFunction_Kind == e.fKind) { |
| 249 | const FunctionDefinition& f = (const FunctionDefinition&) e; |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 250 | if (&f.fDeclaration == |
| 251 | ((const FunctionReference&) *a.fArguments[0]).fFunctions[0]) { |
| 252 | ctx->fFunction = &f; |
| 253 | } |
| 254 | } |
| 255 | } |
| 256 | fPipeline.append(SkRasterPipeline::callback, ctx); |
| 257 | break; |
| 258 | } |
| 259 | default: |
| 260 | fPipeline.append(a.fStage); |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | Interpreter::Value Interpreter::call(const FunctionCall& c) { |
| 265 | abort(); |
| 266 | } |
| 267 | |
| 268 | Interpreter::Value Interpreter::evaluate(const Expression& expr) { |
| 269 | switch (expr.fKind) { |
| 270 | case Expression::kAppendStage_Kind: |
| 271 | this->appendStage((const AppendStage&) expr); |
| 272 | return Value((int) 0xDEADBEEF); |
| 273 | case Expression::kBinary_Kind: { |
| 274 | #define ARITHMETIC(op) { \ |
| 275 | Value left = this->evaluate(*b.fLeft); \ |
| 276 | Value right = this->evaluate(*b.fRight); \ |
| 277 | switch (type_kind(b.fLeft->fType)) { \ |
| 278 | case kFloat_TypeKind: \ |
| 279 | return Value(left.fFloat op right.fFloat); \ |
| 280 | case kInt_TypeKind: \ |
| 281 | return Value(left.fInt op right.fInt); \ |
| 282 | default: \ |
| 283 | abort(); \ |
| 284 | } \ |
| 285 | } |
| 286 | #define BITWISE(op) { \ |
| 287 | Value left = this->evaluate(*b.fLeft); \ |
| 288 | Value right = this->evaluate(*b.fRight); \ |
| 289 | switch (type_kind(b.fLeft->fType)) { \ |
| 290 | case kInt_TypeKind: \ |
| 291 | return Value(left.fInt op right.fInt); \ |
| 292 | default: \ |
| 293 | abort(); \ |
| 294 | } \ |
| 295 | } |
| 296 | #define LOGIC(op) { \ |
| 297 | Value left = this->evaluate(*b.fLeft); \ |
| 298 | Value right = this->evaluate(*b.fRight); \ |
| 299 | switch (type_kind(b.fLeft->fType)) { \ |
| 300 | case kFloat_TypeKind: \ |
| 301 | return Value(left.fFloat op right.fFloat); \ |
| 302 | case kInt_TypeKind: \ |
| 303 | return Value(left.fInt op right.fInt); \ |
| 304 | default: \ |
| 305 | abort(); \ |
| 306 | } \ |
| 307 | } |
| 308 | #define COMPOUND_ARITHMETIC(op) { \ |
| 309 | StackIndex left = this->getLValue(*b.fLeft); \ |
| 310 | Value right = this->evaluate(*b.fRight); \ |
| 311 | Value result = fStack[left]; \ |
| 312 | switch (type_kind(b.fLeft->fType)) { \ |
| 313 | case kFloat_TypeKind: \ |
| 314 | result.fFloat op right.fFloat; \ |
| 315 | break; \ |
| 316 | case kInt_TypeKind: \ |
| 317 | result.fInt op right.fInt; \ |
| 318 | break; \ |
| 319 | default: \ |
| 320 | abort(); \ |
| 321 | } \ |
| 322 | fStack[left] = result; \ |
| 323 | return result; \ |
| 324 | } |
| 325 | #define COMPOUND_BITWISE(op) { \ |
| 326 | StackIndex left = this->getLValue(*b.fLeft); \ |
| 327 | Value right = this->evaluate(*b.fRight); \ |
| 328 | Value result = fStack[left]; \ |
| 329 | switch (type_kind(b.fLeft->fType)) { \ |
| 330 | case kInt_TypeKind: \ |
| 331 | result.fInt op right.fInt; \ |
| 332 | break; \ |
| 333 | default: \ |
| 334 | abort(); \ |
| 335 | } \ |
| 336 | fStack[left] = result; \ |
| 337 | return result; \ |
| 338 | } |
| 339 | const BinaryExpression& b = (const BinaryExpression&) expr; |
| 340 | switch (b.fOperator) { |
| 341 | case Token::PLUS: ARITHMETIC(+) |
| 342 | case Token::MINUS: ARITHMETIC(-) |
| 343 | case Token::STAR: ARITHMETIC(*) |
| 344 | case Token::SLASH: ARITHMETIC(/) |
| 345 | case Token::BITWISEAND: BITWISE(&) |
| 346 | case Token::BITWISEOR: BITWISE(|) |
| 347 | case Token::BITWISEXOR: BITWISE(^) |
| 348 | case Token::LT: LOGIC(<) |
| 349 | case Token::GT: LOGIC(>) |
| 350 | case Token::LTEQ: LOGIC(<=) |
| 351 | case Token::GTEQ: LOGIC(>=) |
| 352 | case Token::LOGICALAND: { |
| 353 | Value result = this->evaluate(*b.fLeft); |
| 354 | if (result.fBool) { |
| 355 | result = this->evaluate(*b.fRight); |
| 356 | } |
| 357 | return result; |
| 358 | } |
| 359 | case Token::LOGICALOR: { |
| 360 | Value result = this->evaluate(*b.fLeft); |
| 361 | if (!result.fBool) { |
| 362 | result = this->evaluate(*b.fRight); |
| 363 | } |
| 364 | return result; |
| 365 | } |
| 366 | case Token::EQ: { |
| 367 | StackIndex left = this->getLValue(*b.fLeft); |
| 368 | Value right = this->evaluate(*b.fRight); |
| 369 | fStack[left] = right; |
| 370 | return right; |
| 371 | } |
| 372 | case Token::PLUSEQ: COMPOUND_ARITHMETIC(+=) |
| 373 | case Token::MINUSEQ: COMPOUND_ARITHMETIC(-=) |
| 374 | case Token::STAREQ: COMPOUND_ARITHMETIC(*=) |
| 375 | case Token::SLASHEQ: COMPOUND_ARITHMETIC(/=) |
| 376 | case Token::BITWISEANDEQ: COMPOUND_BITWISE(&=) |
| 377 | case Token::BITWISEOREQ: COMPOUND_BITWISE(|=) |
| 378 | case Token::BITWISEXOREQ: COMPOUND_BITWISE(^=) |
| 379 | default: |
| 380 | ABORT("unsupported operator: %s\n", expr.description().c_str()); |
| 381 | } |
| 382 | break; |
| 383 | } |
| 384 | case Expression::kBoolLiteral_Kind: |
| 385 | return Value(((const BoolLiteral&) expr).fValue); |
| 386 | case Expression::kConstructor_Kind: |
| 387 | break; |
| 388 | case Expression::kIntLiteral_Kind: |
| 389 | return Value((int) ((const IntLiteral&) expr).fValue); |
| 390 | case Expression::kFieldAccess_Kind: |
| 391 | break; |
| 392 | case Expression::kFloatLiteral_Kind: |
| 393 | return Value((float) ((const FloatLiteral&) expr).fValue); |
| 394 | case Expression::kFunctionCall_Kind: |
| 395 | return this->call((const FunctionCall&) expr); |
| 396 | case Expression::kIndex_Kind: { |
| 397 | const IndexExpression& idx = (const IndexExpression&) expr; |
| 398 | StackIndex pos = this->evaluate(*idx.fBase).fInt + |
| 399 | this->evaluate(*idx.fIndex).fInt; |
| 400 | return fStack[pos]; |
| 401 | } |
| 402 | case Expression::kPrefix_Kind: { |
| 403 | const PrefixExpression& p = (const PrefixExpression&) expr; |
| 404 | switch (p.fOperator) { |
| 405 | case Token::MINUS: { |
| 406 | Value base = this->evaluate(*p.fOperand); |
| 407 | switch (type_kind(p.fType)) { |
| 408 | case kFloat_TypeKind: |
| 409 | return Value(-base.fFloat); |
| 410 | case kInt_TypeKind: |
| 411 | return Value(-base.fInt); |
| 412 | default: |
| 413 | abort(); |
| 414 | } |
| 415 | } |
| 416 | case Token::LOGICALNOT: { |
| 417 | Value base = this->evaluate(*p.fOperand); |
| 418 | return Value(!base.fBool); |
| 419 | } |
| 420 | default: |
| 421 | abort(); |
| 422 | } |
| 423 | } |
| 424 | case Expression::kPostfix_Kind: { |
| 425 | const PostfixExpression& p = (const PostfixExpression&) expr; |
| 426 | StackIndex lvalue = this->getLValue(*p.fOperand); |
| 427 | Value result = fStack[lvalue]; |
| 428 | switch (type_kind(p.fType)) { |
| 429 | case kFloat_TypeKind: |
| 430 | if (Token::PLUSPLUS == p.fOperator) { |
| 431 | ++fStack[lvalue].fFloat; |
| 432 | } else { |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 433 | SkASSERT(Token::MINUSMINUS == p.fOperator); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 434 | --fStack[lvalue].fFloat; |
| 435 | } |
| 436 | break; |
| 437 | case kInt_TypeKind: |
| 438 | if (Token::PLUSPLUS == p.fOperator) { |
| 439 | ++fStack[lvalue].fInt; |
| 440 | } else { |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 441 | SkASSERT(Token::MINUSMINUS == p.fOperator); |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 442 | --fStack[lvalue].fInt; |
| 443 | } |
| 444 | break; |
| 445 | default: |
| 446 | abort(); |
| 447 | } |
| 448 | return result; |
| 449 | } |
| 450 | case Expression::kSetting_Kind: |
| 451 | break; |
| 452 | case Expression::kSwizzle_Kind: |
| 453 | break; |
| 454 | case Expression::kVariableReference_Kind: |
Ethan Nicholas | d9d33c3 | 2018-06-12 11:05:59 -0400 | [diff] [blame^] | 455 | SkASSERT(fVars.size()); |
| 456 | SkASSERT(fVars.back().find(&((VariableReference&) expr).fVariable) != |
Ethan Nicholas | 26a9aad | 2018-03-27 14:10:52 -0400 | [diff] [blame] | 457 | fVars.back().end()); |
| 458 | return fStack[fVars.back()[&((VariableReference&) expr).fVariable]]; |
| 459 | case Expression::kTernary_Kind: { |
| 460 | const TernaryExpression& t = (const TernaryExpression&) expr; |
| 461 | return this->evaluate(this->evaluate(*t.fTest).fBool ? *t.fIfTrue : *t.fIfFalse); |
| 462 | } |
| 463 | case Expression::kTypeReference_Kind: |
| 464 | break; |
| 465 | default: |
| 466 | break; |
| 467 | } |
| 468 | ABORT("unsupported expression: %s\n", expr.description().c_str()); |
| 469 | } |
| 470 | |
| 471 | } // namespace |
| 472 | |
| 473 | #endif |