/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SKSL_STANDALONE

#include "SkSLInterpreter.h"
#include "ir/SkSLBinaryExpression.h"
#include "ir/SkSLExpressionStatement.h"
#include "ir/SkSLForStatement.h"
#include "ir/SkSLFunctionCall.h"
#include "ir/SkSLFunctionReference.h"
#include "ir/SkSLIfStatement.h"
#include "ir/SkSLIndexExpression.h"
#include "ir/SkSLPostfixExpression.h"
#include "ir/SkSLPrefixExpression.h"
#include "ir/SkSLProgram.h"
#include "ir/SkSLStatement.h"
#include "ir/SkSLTernaryExpression.h"
#include "ir/SkSLVarDeclarations.h"
#include "ir/SkSLVarDeclarationsStatement.h"
#include "ir/SkSLVariableReference.h"
#include "SkRasterPipeline.h"
#include "../jumper/SkJumper.h"

namespace SkSL {

void Interpreter::run() {
    for (const auto& e : *fProgram) {
        if (ProgramElement::kFunction_Kind == e.fKind) {
            const FunctionDefinition& f = (const FunctionDefinition&) e;
            if ("appendStages" == f.fDeclaration.fName) {
                this->run(f);
                return;
            }
        }
    }
    ASSERT(false);
}

static int SizeOf(const Type& type) {
    return 1;
}

void Interpreter::run(const FunctionDefinition& f) {
    fVars.emplace_back();
    StackIndex current = (StackIndex) fStack.size();
    for (int i = f.fDeclaration.fParameters.size() - 1; i >= 0; --i) {
        current -= SizeOf(f.fDeclaration.fParameters[i]->fType);
        fVars.back()[f.fDeclaration.fParameters[i]] = current;
    }
    fCurrentIndex.push_back({ f.fBody.get(), 0 });
    while (fCurrentIndex.size()) {
        this->runStatement();
    }
}

void Interpreter::push(Value value) {
    fStack.push_back(value);
}

Interpreter::Value Interpreter::pop() {
    auto iter = fStack.end() - 1;
    Value result = *iter;
    fStack.erase(iter);
    return result;
}

 Interpreter::StackIndex Interpreter::stackAlloc(int count) {
    int result = fStack.size();
    for (int i = 0; i < count; ++i) {
        fStack.push_back(Value((int) 0xDEADBEEF));
    }
    return result;
}

void Interpreter::runStatement() {
    const Statement& stmt = *fCurrentIndex.back().fStatement;
    const size_t index = fCurrentIndex.back().fIndex;
    fCurrentIndex.pop_back();
    switch (stmt.fKind) {
        case Statement::kBlock_Kind: {
            const Block& b = (const Block&) stmt;
            if (!b.fStatements.size()) {
                break;
            }
            ASSERT(index < b.fStatements.size());
            if (index < b.fStatements.size() - 1) {
                fCurrentIndex.push_back({ &b, index + 1 });
            }
            fCurrentIndex.push_back({ b.fStatements[index].get(), 0 });
            break;
        }
        case Statement::kBreak_Kind:
            ASSERT(index == 0);
            abort();
        case Statement::kContinue_Kind:
            ASSERT(index == 0);
            abort();
        case Statement::kDiscard_Kind:
            ASSERT(index == 0);
            abort();
        case Statement::kDo_Kind:
            abort();
        case Statement::kExpression_Kind:
            ASSERT(index == 0);
            this->evaluate(*((const ExpressionStatement&) stmt).fExpression);
            break;
        case Statement::kFor_Kind: {
            ForStatement& f = (ForStatement&) stmt;
            switch (index) {
                case 0:
                    // initializer
                    fCurrentIndex.push_back({ &f, 1 });
                    if (f.fInitializer) {
                        fCurrentIndex.push_back({ f.fInitializer.get(), 0 });
                    }
                    break;
                case 1:
                    // test & body
                    if (f.fTest && !evaluate(*f.fTest).fBool) {
                        break;
                    } else {
                        fCurrentIndex.push_back({ &f, 2 });
                        fCurrentIndex.push_back({ f.fStatement.get(), 0 });
                    }
                    break;
                case 2:
                    // next
                    if (f.fNext) {
                        this->evaluate(*f.fNext);
                    }
                    fCurrentIndex.push_back({ &f, 1 });
                    break;
                default:
                    ASSERT(false);
            }
            break;
        }
        case Statement::kGroup_Kind:
            abort();
        case Statement::kIf_Kind: {
            IfStatement& i = (IfStatement&) stmt;
            if (evaluate(*i.fTest).fBool) {
                fCurrentIndex.push_back({ i.fIfTrue.get(), 0 });
            } else if (i.fIfFalse) {
                fCurrentIndex.push_back({ i.fIfFalse.get(), 0 });
            }
            break;
        }
        case Statement::kNop_Kind:
            ASSERT(index == 0);
            break;
        case Statement::kReturn_Kind:
            ASSERT(index == 0);
            abort();
        case Statement::kSwitch_Kind:
            abort();
        case Statement::kVarDeclarations_Kind:
            ASSERT(index == 0);
            for (const auto& decl :((const VarDeclarationsStatement&) stmt).fDeclaration->fVars) {
                const Variable* var = ((VarDeclaration&) *decl).fVar;
                StackIndex pos = this->stackAlloc(SizeOf(var->fType));
                fVars.back()[var] = pos;
                if (var->fInitialValue) {
                    fStack[pos] = this->evaluate(*var->fInitialValue);
                }
            }
            break;
        case Statement::kWhile_Kind:
            abort();
        default:
            abort();
    }
}

static Interpreter::TypeKind type_kind(const Type& type) {
    if (type.fName == "int") {
        return Interpreter::kInt_TypeKind;
    } else if (type.fName == "float") {
        return Interpreter::kFloat_TypeKind;
    }
    ABORT("unsupported type: %s\n", type.description().c_str());
}

Interpreter::StackIndex Interpreter::getLValue(const Expression& expr) {
    switch (expr.fKind) {
        case Expression::kFieldAccess_Kind:
            break;
        case Expression::kIndex_Kind: {
            const IndexExpression& idx = (const IndexExpression&) expr;
            return this->evaluate(*idx.fBase).fInt + this->evaluate(*idx.fIndex).fInt;
        }
        case Expression::kSwizzle_Kind:
            break;
        case Expression::kVariableReference_Kind:
            ASSERT(fVars.size());
            ASSERT(fVars.back().find(&((VariableReference&) expr).fVariable) !=
                   fVars.back().end());
            return fVars.back()[&((VariableReference&) expr).fVariable];
        case Expression::kTernary_Kind: {
            const TernaryExpression& t = (const TernaryExpression&) expr;
            return this->getLValue(this->evaluate(*t.fTest).fBool ? *t.fIfTrue : *t.fIfFalse);
        }
        case Expression::kTypeReference_Kind:
            break;
        default:
            break;
    }
    ABORT("unsupported lvalue");
}

struct CallbackCtx : public SkJumper_CallbackCtx {
    Interpreter* fInterpreter;
    const FunctionDefinition* fFunction;
};

static void do_callback(SkJumper_CallbackCtx* raw, int activePixels) {
    CallbackCtx& ctx = (CallbackCtx&) *raw;
    for (int i = 0; i < activePixels; ++i) {
        ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 0]));
        ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 1]));
        ctx.fInterpreter->push(Interpreter::Value(ctx.rgba[i * 4 + 2]));
        ctx.fInterpreter->run(*ctx.fFunction);
        ctx.read_from[i * 4 + 2] = ctx.fInterpreter->pop().fFloat;
        ctx.read_from[i * 4 + 1] = ctx.fInterpreter->pop().fFloat;
        ctx.read_from[i * 4 + 0] = ctx.fInterpreter->pop().fFloat;
    }
}

void Interpreter::appendStage(const AppendStage& a) {
    switch (a.fStage) {
        case SkRasterPipeline::matrix_4x5: {
            ASSERT(a.fArguments.size() == 1);
            StackIndex transpose = evaluate(*a.fArguments[0]).fInt;
            fPipeline.append(SkRasterPipeline::matrix_4x5, &fStack[transpose]);
            break;
        }
        case SkRasterPipeline::callback: {
            ASSERT(a.fArguments.size() == 1);
            CallbackCtx* ctx = new CallbackCtx();
            ctx->fInterpreter = this;
            ctx->fn = do_callback;
            for (const auto& e : *fProgram) {
                if (ProgramElement::kFunction_Kind == e.fKind) {
                    const FunctionDefinition& f = (const FunctionDefinition&) e;
                    if (&f.fDeclaration ==
                                      ((const FunctionReference&) *a.fArguments[0]).fFunctions[0]) {
                        ctx->fFunction = &f;
                    }
                }
            }
            fPipeline.append(SkRasterPipeline::callback, ctx);
            break;
        }
        default:
            fPipeline.append(a.fStage);
    }
}

Interpreter::Value Interpreter::call(const FunctionCall& c) {
    abort();
}

Interpreter::Value Interpreter::evaluate(const Expression& expr) {
    switch (expr.fKind) {
        case Expression::kAppendStage_Kind:
            this->appendStage((const AppendStage&) expr);
            return Value((int) 0xDEADBEEF);
        case Expression::kBinary_Kind: {
            #define ARITHMETIC(op) {                               \
                Value left = this->evaluate(*b.fLeft);             \
                Value right = this->evaluate(*b.fRight);           \
                switch (type_kind(b.fLeft->fType)) {               \
                    case kFloat_TypeKind:                          \
                        return Value(left.fFloat op right.fFloat); \
                    case kInt_TypeKind:                            \
                        return Value(left.fInt op right.fInt);     \
                    default:                                       \
                        abort();                                   \
                }                                                  \
            }
            #define BITWISE(op) {                                  \
                Value left = this->evaluate(*b.fLeft);             \
                Value right = this->evaluate(*b.fRight);           \
                switch (type_kind(b.fLeft->fType)) {               \
                    case kInt_TypeKind:                            \
                        return Value(left.fInt op right.fInt);     \
                    default:                                       \
                        abort();                                   \
                }                                                  \
            }
            #define LOGIC(op) {                                    \
                Value left = this->evaluate(*b.fLeft);             \
                Value right = this->evaluate(*b.fRight);           \
                switch (type_kind(b.fLeft->fType)) {               \
                    case kFloat_TypeKind:                          \
                        return Value(left.fFloat op right.fFloat); \
                    case kInt_TypeKind:                            \
                        return Value(left.fInt op right.fInt);     \
                    default:                                       \
                        abort();                                   \
                }                                                  \
            }
            #define COMPOUND_ARITHMETIC(op) {                      \
                StackIndex left = this->getLValue(*b.fLeft);       \
                Value right = this->evaluate(*b.fRight);           \
                Value result = fStack[left];                       \
                switch (type_kind(b.fLeft->fType)) {               \
                    case kFloat_TypeKind:                          \
                        result.fFloat op right.fFloat;             \
                        break;                                     \
                    case kInt_TypeKind:                            \
                        result.fInt op right.fInt;                 \
                        break;                                     \
                    default:                                       \
                        abort();                                   \
                }                                                  \
                fStack[left] = result;                             \
                return result;                                     \
            }
            #define COMPOUND_BITWISE(op) {                         \
                StackIndex left = this->getLValue(*b.fLeft);       \
                Value right = this->evaluate(*b.fRight);           \
                Value result = fStack[left];                       \
                switch (type_kind(b.fLeft->fType)) {               \
                    case kInt_TypeKind:                            \
                        result.fInt op right.fInt;                 \
                        break;                                     \
                    default:                                       \
                        abort();                                   \
                }                                                  \
                fStack[left] = result;                             \
                return result;                                     \
            }
            const BinaryExpression& b = (const BinaryExpression&) expr;
            switch (b.fOperator) {
                case Token::PLUS:       ARITHMETIC(+)
                case Token::MINUS:      ARITHMETIC(-)
                case Token::STAR:       ARITHMETIC(*)
                case Token::SLASH:      ARITHMETIC(/)
                case Token::BITWISEAND: BITWISE(&)
                case Token::BITWISEOR:  BITWISE(|)
                case Token::BITWISEXOR: BITWISE(^)
                case Token::LT:         LOGIC(<)
                case Token::GT:         LOGIC(>)
                case Token::LTEQ:       LOGIC(<=)
                case Token::GTEQ:       LOGIC(>=)
                case Token::LOGICALAND: {
                    Value result = this->evaluate(*b.fLeft);
                    if (result.fBool) {
                        result = this->evaluate(*b.fRight);
                    }
                    return result;
                }
                case Token::LOGICALOR: {
                    Value result = this->evaluate(*b.fLeft);
                    if (!result.fBool) {
                        result = this->evaluate(*b.fRight);
                    }
                    return result;
                }
                case Token::EQ: {
                    StackIndex left = this->getLValue(*b.fLeft);
                    Value right = this->evaluate(*b.fRight);
                    fStack[left] = right;
                    return right;
                }
                case Token::PLUSEQ:       COMPOUND_ARITHMETIC(+=)
                case Token::MINUSEQ:      COMPOUND_ARITHMETIC(-=)
                case Token::STAREQ:       COMPOUND_ARITHMETIC(*=)
                case Token::SLASHEQ:      COMPOUND_ARITHMETIC(/=)
                case Token::BITWISEANDEQ: COMPOUND_BITWISE(&=)
                case Token::BITWISEOREQ:  COMPOUND_BITWISE(|=)
                case Token::BITWISEXOREQ: COMPOUND_BITWISE(^=)
                default:
                    ABORT("unsupported operator: %s\n", expr.description().c_str());
            }
            break;
        }
        case Expression::kBoolLiteral_Kind:
            return Value(((const BoolLiteral&) expr).fValue);
        case Expression::kConstructor_Kind:
            break;
        case Expression::kIntLiteral_Kind:
            return Value((int) ((const IntLiteral&) expr).fValue);
        case Expression::kFieldAccess_Kind:
            break;
        case Expression::kFloatLiteral_Kind:
            return Value((float) ((const FloatLiteral&) expr).fValue);
        case Expression::kFunctionCall_Kind:
            return this->call((const FunctionCall&) expr);
        case Expression::kIndex_Kind: {
            const IndexExpression& idx = (const IndexExpression&) expr;
            StackIndex pos = this->evaluate(*idx.fBase).fInt +
                             this->evaluate(*idx.fIndex).fInt;
            return fStack[pos];
        }
        case Expression::kPrefix_Kind: {
            const PrefixExpression& p = (const PrefixExpression&) expr;
            switch (p.fOperator) {
                case Token::MINUS: {
                    Value base = this->evaluate(*p.fOperand);
                    switch (type_kind(p.fType)) {
                        case kFloat_TypeKind:
                            return Value(-base.fFloat);
                        case kInt_TypeKind:
                            return Value(-base.fInt);
                        default:
                            abort();
                    }
                }
                case Token::LOGICALNOT: {
                    Value base = this->evaluate(*p.fOperand);
                    return Value(!base.fBool);
                }
                default:
                    abort();
            }
        }
        case Expression::kPostfix_Kind: {
            const PostfixExpression& p = (const PostfixExpression&) expr;
            StackIndex lvalue = this->getLValue(*p.fOperand);
            Value result = fStack[lvalue];
            switch (type_kind(p.fType)) {
                case kFloat_TypeKind:
                    if (Token::PLUSPLUS == p.fOperator) {
                        ++fStack[lvalue].fFloat;
                    } else {
                        ASSERT(Token::MINUSMINUS == p.fOperator);
                        --fStack[lvalue].fFloat;
                    }
                    break;
                case kInt_TypeKind:
                    if (Token::PLUSPLUS == p.fOperator) {
                        ++fStack[lvalue].fInt;
                    } else {
                        ASSERT(Token::MINUSMINUS == p.fOperator);
                        --fStack[lvalue].fInt;
                    }
                    break;
                default:
                    abort();
            }
            return result;
        }
        case Expression::kSetting_Kind:
            break;
        case Expression::kSwizzle_Kind:
            break;
        case Expression::kVariableReference_Kind:
            ASSERT(fVars.size());
            ASSERT(fVars.back().find(&((VariableReference&) expr).fVariable) !=
                   fVars.back().end());
            return fStack[fVars.back()[&((VariableReference&) expr).fVariable]];
        case Expression::kTernary_Kind: {
            const TernaryExpression& t = (const TernaryExpression&) expr;
            return this->evaluate(this->evaluate(*t.fTest).fBool ? *t.fIfTrue : *t.fIfFalse);
        }
        case Expression::kTypeReference_Kind:
            break;
        default:
            break;
    }
    ABORT("unsupported expression: %s\n", expr.description().c_str());
}

} // namespace

#endif
