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

#include "SkSLVariableReference.h"

#include "SkSLConstructor.h"
#include "SkSLFloatLiteral.h"
#include "SkSLIRGenerator.h"
#include "SkSLSetting.h"

namespace SkSL {

VariableReference::VariableReference(int offset, const Variable& variable, RefKind refKind)
: INHERITED(offset, kVariableReference_Kind, variable.fType)
, fVariable(variable)
, fRefKind(refKind) {
    if (refKind != kRead_RefKind) {
        fVariable.fWriteCount++;
    }
    if (refKind != kWrite_RefKind) {
        fVariable.fReadCount++;
    }
}

VariableReference::~VariableReference() {
    if (fRefKind != kRead_RefKind) {
        fVariable.fWriteCount--;
    }
    if (fRefKind != kWrite_RefKind) {
        fVariable.fReadCount--;
    }
}

void VariableReference::setRefKind(RefKind refKind) {
    if (fRefKind != kRead_RefKind) {
        fVariable.fWriteCount--;
    }
    if (fRefKind != kWrite_RefKind) {
        fVariable.fReadCount--;
    }
    if (refKind != kRead_RefKind) {
        fVariable.fWriteCount++;
    }
    if (refKind != kWrite_RefKind) {
        fVariable.fReadCount++;
    }
    fRefKind = refKind;
}

std::unique_ptr<Expression> VariableReference::copy_constant(const IRGenerator& irGenerator,
                                                             const Expression* expr) {
    SkASSERT(expr->isConstant());
    switch (expr->fKind) {
        case Expression::kIntLiteral_Kind:
            return std::unique_ptr<Expression>(new IntLiteral(irGenerator.fContext,
                                                              -1,
                                                              ((IntLiteral*) expr)->fValue));
        case Expression::kFloatLiteral_Kind:
            return std::unique_ptr<Expression>(new FloatLiteral(
                                                               irGenerator.fContext,
                                                               -1,
                                                               ((FloatLiteral*) expr)->fValue));
        case Expression::kBoolLiteral_Kind:
            return std::unique_ptr<Expression>(new BoolLiteral(irGenerator.fContext,
                                                               -1,
                                                               ((BoolLiteral*) expr)->fValue));
        case Expression::kConstructor_Kind: {
            const Constructor* c = (const Constructor*) expr;
            std::vector<std::unique_ptr<Expression>> args;
            for (const auto& arg : c->fArguments) {
                args.push_back(copy_constant(irGenerator, arg.get()));
            }
            return std::unique_ptr<Expression>(new Constructor(-1, c->fType,
                                                               std::move(args)));
        }
        case Expression::kSetting_Kind: {
            const Setting* s = (const Setting*) expr;
            return std::unique_ptr<Expression>(new Setting(-1, s->fName,
                                                           copy_constant(irGenerator,
                                                                         s->fValue.get())));
        }
        default:
            ABORT("unsupported constant\n");
    }
}

std::unique_ptr<Expression> VariableReference::constantPropagate(const IRGenerator& irGenerator,
                                                                 const DefinitionMap& definitions) {
    if (fRefKind != kRead_RefKind) {
        return nullptr;
    }
    if ((fVariable.fModifiers.fFlags & Modifiers::kConst_Flag) && fVariable.fInitialValue &&
        fVariable.fInitialValue->isConstant()) {
        return copy_constant(irGenerator, fVariable.fInitialValue);
    }
    auto exprIter = definitions.find(&fVariable);
    if (exprIter != definitions.end() && exprIter->second &&
        (*exprIter->second)->isConstant()) {
        return copy_constant(irGenerator, exprIter->second->get());
    }
    return nullptr;
}

} // namespace
