/* * Copyright (c) 2021 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "script_context.h" #include #include #include #include "script_expression.h" #include "script_interpreter.h" #include "script_utils.h" using namespace std; using namespace Updater; namespace Uscript { static uint32_t g_contextId = 0; int32_t UScriptInstructionContext::PushParam(int32_t value) { UScriptValuePtr valuePtr = std::make_shared(value); if (valuePtr == nullptr) { USCRIPT_LOGE("Failed to create value"); return USCRIPT_ERROR_CREATE_OBJ; } outParam_.push_back(valuePtr); return USCRIPT_SUCCESS; } int32_t UScriptInstructionContext::PushParam(float value) { UScriptValuePtr valuePtr = std::make_shared(value); if (valuePtr == nullptr) { USCRIPT_LOGE("Failed to create value"); return USCRIPT_ERROR_CREATE_OBJ; } outParam_.push_back(valuePtr); return USCRIPT_SUCCESS; } int32_t UScriptInstructionContext::PushParam(const std::string& value) { UScriptValuePtr valuePtr = std::make_shared(value); if (valuePtr == nullptr) { USCRIPT_LOGE("Failed to create value"); return USCRIPT_ERROR_CREATE_OBJ; } outParam_.push_back(valuePtr); return USCRIPT_SUCCESS; } int32_t UScriptInstructionContext::GetParamCount() { return innerParam_.size(); } int32_t UScriptInstructionContext::GetParam(int32_t index, int32_t &value) { return GetParam(index, value); } int32_t UScriptInstructionContext::GetParam(int32_t index, float &value) { return GetParam(index, value); } int32_t UScriptInstructionContext::GetParam(int32_t index, std::string &value) { return GetParam(index, value); } template int32_t UScriptInstructionContext::GetParam(int32_t index, T &value) { if (static_cast(index) >= this->innerParam_.size()) { LOG(ERROR) << "Invalid index " << index; return UScriptContext::PARAM_TYPE_INVALID; } // check whether TWapper's type is same with inner param's type TWapper v {T {}}; if (innerParam_[index].get()->GetValueType() != v.GetValueType()) { LOG(ERROR) << "Invalid index " << index; return USCRIPT_INVALID_PARAM; } // then perform cast between innerparam and TWapper TWapper* inter = static_cast(innerParam_[index].get()); value = inter->GetValue(); return USCRIPT_SUCCESS; } UScriptContext::ParamType UScriptInstructionContext::GetParamType(int32_t index) { if (static_cast(index) >= this->innerParam_.size()) { USCRIPT_LOGE("Invalid index %d", index); return UScriptContext::PARAM_TYPE_INVALID; } UScriptValue::UScriptValueType type = innerParam_[index]->GetValueType(); return (UScriptContext::ParamType)type; } int32_t UScriptInstructionContext::AddInputParam(UScriptValuePtr value) { innerParam_.push_back(value); return USCRIPT_SUCCESS; } UScriptValuePtr UScriptInterpretContext::FindVariable(const ScriptInterpreter &inter, std::string id) { INTERPRETER_LOGI(inter, this, "FindVariable varName:%s ", id.c_str()); if (localVariables_.find(id) != localVariables_.end()) { return localVariables_[id]; } return nullptr; } UScriptInterpretContext::UScriptInterpretContext(bool top) : top_(top) { contextId_ = ++g_contextId; } void UScriptInterpretContext::UpdateVariable(const ScriptInterpreter &inter, std::string id, UScriptValuePtr value) { INTERPRETER_LOGI(inter, this, " Update varName:%s value: %s", id.c_str(), UScriptValue::ScriptToString(value).c_str()); localVariables_[id] = value; } void UScriptInterpretContext::UpdateVariables(const ScriptInterpreter &inter, UScriptValuePtr value, std::vector ids, size_t &startIndex) { if (value->GetValueType() != UScriptValue::VALUE_TYPE_LIST) { if (startIndex >= ids.size()) { USCRIPT_LOGE("Invalid startIndex %d", startIndex); return; } UpdateVariable(inter, ids[startIndex], value); startIndex++; return; } ReturnValue* values = (ReturnValue*)(value.get()); for (auto out : values->GetValues()) { if (startIndex >= ids.size()) { USCRIPT_LOGE("Invalid startIndex %d", startIndex); return; } UpdateVariable(inter, ids[startIndex], out); startIndex++; } } UScriptValuePtr UScriptValue::Computer(int32_t action, UScriptValuePtr value) { return std::make_shared(USCRIPT_ERROR_INTERPRET); } #define INTEGER_INTEGER_COMPUTER(op, rightValue) do { \ IntegerValue* value = static_cast((rightValue).get()); \ if (value == nullptr) { \ USCRIPT_LOGE("Failed to cast "); \ } else { \ retValue = make_shared(this->GetValue() op value->GetValue()); \ } \ } while (0) #define INTEGER_FLOAT_MATH_COMPUTER(op, rightValue) do { \ FloatValue* value = static_cast((rightValue).get()); \ if (value == nullptr) { \ USCRIPT_LOGE("Failed to cast "); \ } else { \ retValue = make_shared(this->GetValue() op value->GetValue()); \ } \ } while (0) #define INTEGER_MATH_COMPUTER(op, rightValue) do { \ if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \ INTEGER_INTEGER_COMPUTER(op, (rightValue)); \ } else if ((rightValue)->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \ INTEGER_FLOAT_MATH_COMPUTER(op, (rightValue)); \ } \ } while (0) #define INTEGER_FLOAT_LOGIC_COMPUTER(op, rightValue) do { \ FloatValue* value = static_cast((rightValue).get()); \ if (value == nullptr) { \ USCRIPT_LOGE("Failed to cast "); \ } else { \ retValue = make_shared(this->GetValue() op value->GetValue()); \ } \ } while (0) #define INTEGER_LOGIC_COMPUTER(op, rightValue) do { \ if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \ INTEGER_INTEGER_COMPUTER(op, (rightValue)); \ } else if ((rightValue)->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \ INTEGER_FLOAT_LOGIC_COMPUTER(op, (rightValue)); \ } \ } while (0) #define INTEGER_INTEGER_MATH_COMPUTER_DIV(rightValue) do { \ IntegerValue* value = static_cast((rightValue).get()); \ if (value == nullptr || value->GetValue() == 0) { \ USCRIPT_LOGE("Failed to cast "); \ } else { \ retValue = make_shared(this->GetValue() / value->GetValue()); \ } \ } while (0) #define INTEGER_FLOAT_MATH_COMPUTER_DIV(rightValue) do { \ FloatValue* value = static_cast((rightValue).get()); \ if (value == nullptr || value->GetValue() == 0) { \ USCRIPT_LOGE("Failed to cast "); \ } else { \ retValue = make_shared(this->GetValue() / value->GetValue()); \ } \ } while (0) #define INTEGER_MATH_COMPUTER_DIV(rightValue) do { \ if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \ INTEGER_INTEGER_MATH_COMPUTER_DIV((rightValue)); \ } else if ((rightValue)->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \ INTEGER_FLOAT_MATH_COMPUTER_DIV((rightValue)); \ } \ } while (0) UScriptValuePtr IntegerValue::Computer(int32_t action, UScriptValuePtr value) { UScriptValuePtr rightValue = UScriptValue::GetRightCompluteValue(value); UScriptValuePtr retValue = std::make_shared(USCRIPT_ERROR_INTERPRET); if (rightValue == nullptr) { USCRIPT_LOGE("Check param error"); return retValue; } switch (action) { case UScriptExpression::ADD_OPERATOR: INTEGER_MATH_COMPUTER(+, rightValue); break; case UScriptExpression::SUB_OPERATOR: INTEGER_MATH_COMPUTER(-, rightValue); break; case UScriptExpression::MUL_OPERATOR: INTEGER_MATH_COMPUTER(*, rightValue); break; case UScriptExpression::DIV_OPERATOR: INTEGER_MATH_COMPUTER_DIV(rightValue); break; case UScriptExpression::GT_OPERATOR: INTEGER_LOGIC_COMPUTER(>, rightValue); break; case UScriptExpression::GE_OPERATOR: INTEGER_LOGIC_COMPUTER(>=, rightValue); break; case UScriptExpression::LT_OPERATOR: INTEGER_LOGIC_COMPUTER(<, rightValue); break; case UScriptExpression::LE_OPERATOR: INTEGER_LOGIC_COMPUTER(<=, rightValue); break; case UScriptExpression::EQ_OPERATOR: INTEGER_LOGIC_COMPUTER(==, rightValue); break; case UScriptExpression::NE_OPERATOR: INTEGER_LOGIC_COMPUTER(!=, rightValue); break; case UScriptExpression::AND_OPERATOR: INTEGER_LOGIC_COMPUTER(&&, rightValue); break; case UScriptExpression::OR_OPERATOR: INTEGER_LOGIC_COMPUTER(||, rightValue); break; default: break; } return retValue; } #define FLOAT_INTEGER_COMPUTER(op, rightValue) do { \ IntegerValue* value = static_cast((rightValue).get()); \ if (value == nullptr) { \ USCRIPT_LOGE("Failed to cast "); \ } else { \ retValue = make_shared(this->GetValue() op value->GetValue()); \ } \ } while (0) #define FLOAT_FLOAT_MATH_COMPUTER(op, rightValue) do { \ FloatValue* value = static_cast((rightValue).get()); \ if (value == nullptr) { \ USCRIPT_LOGE("Failed to cast "); \ } else { \ retValue = make_shared(this->GetValue() op value->GetValue()); \ } \ } while (0) #define FLOAT_MATH_COMPUTER(op, rightValue) do { \ if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \ FLOAT_INTEGER_COMPUTER(op, (rightValue)); \ } else if ((rightValue)->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \ FLOAT_FLOAT_LOGIC_COMPUTER(op, (rightValue)); \ } \ } while (0) #define FLOAT_FLOAT_LOGIC_COMPUTER(op, rightValue) do { \ FloatValue* value = static_cast((rightValue).get()); \ if (value == nullptr) { \ USCRIPT_LOGE("Failed to cast "); \ } else { \ retValue = make_shared(this->GetValue() op value->GetValue()); \ } \ } while (0) #define FLOAT_LOGIC_COMPUTER(op, rightValue) do { \ if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \ FLOAT_INTEGER_COMPUTER(op, (rightValue)); \ } else if ((rightValue)->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \ FLOAT_FLOAT_LOGIC_COMPUTER(op, (rightValue)); \ } \ } while (0) #define FLOAT_INTEGER_MATH_COMPUTER_DIV(rightValue) do { \ IntegerValue* value = static_cast((rightValue).get()); \ if (value == nullptr || value->GetValue() == 0) { \ USCRIPT_LOGE("Failed to cast "); \ } else { \ retValue = make_shared(this->GetValue() / value->GetValue()); \ } \ } while (0) #define FLOAT_MATH_COMPUTER_DIV(rightValue) do { \ if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \ FLOAT_INTEGER_MATH_COMPUTER_DIV((rightValue)); \ } else if ((rightValue)->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \ INTEGER_FLOAT_MATH_COMPUTER_DIV((rightValue)); \ } \ } while (0) UScriptValuePtr FloatValue::Computer(int32_t action, UScriptValuePtr value) { UScriptValuePtr rightValue = UScriptValue::GetRightCompluteValue(value); UScriptValuePtr retValue = std::make_shared(USCRIPT_ERROR_INTERPRET); if (rightValue == nullptr) { USCRIPT_LOGE("Check param error"); return retValue; } switch (action) { case UScriptExpression::ADD_OPERATOR: FLOAT_MATH_COMPUTER(+, rightValue); break; case UScriptExpression::SUB_OPERATOR: FLOAT_MATH_COMPUTER(-, rightValue); break; case UScriptExpression::MUL_OPERATOR: FLOAT_MATH_COMPUTER(*, rightValue); break; case UScriptExpression::DIV_OPERATOR: FLOAT_MATH_COMPUTER_DIV(rightValue); break; case UScriptExpression::GT_OPERATOR: FLOAT_LOGIC_COMPUTER(>, rightValue); break; case UScriptExpression::GE_OPERATOR: FLOAT_LOGIC_COMPUTER(>=, rightValue); break; case UScriptExpression::LT_OPERATOR: FLOAT_LOGIC_COMPUTER(<, rightValue); break; case UScriptExpression::LE_OPERATOR: FLOAT_LOGIC_COMPUTER(<=, rightValue); break; case UScriptExpression::EQ_OPERATOR: return make_shared(ComputerEqual(rightValue)); case UScriptExpression::NE_OPERATOR: return make_shared(!ComputerEqual(rightValue)); case UScriptExpression::AND_OPERATOR: FLOAT_LOGIC_COMPUTER(&&, rightValue); break; case UScriptExpression::OR_OPERATOR: FLOAT_LOGIC_COMPUTER(||, rightValue); break; default: break; } return retValue; } bool FloatValue::ComputerEqual(const UScriptValuePtr rightValue) { if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { IntegerValue* value = (IntegerValue*)(rightValue.get()); if (value == nullptr) { USCRIPT_LOGE("Failed to cast "); return 0; } float v2 = value->GetValue(); USCRIPT_LOGI("ComputerEqual %f v2: %f", GetValue(), v2); float diff = GetValue() - v2; diff = abs(diff); return diff < 0.0001f; } else if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { FloatValue* value = (FloatValue*)(rightValue.get()); if (value == nullptr) { USCRIPT_LOGE("Failed to cast "); return 0; } float diff = GetValue() - value->GetValue(); diff = abs(diff); USCRIPT_LOGI("ComputerEqual %f %f diff: %f", GetValue(), value->GetValue(), diff); return diff < 0.0001f; } return 0; } UScriptValuePtr StringValue::ComputerReturn(int32_t action, UScriptValuePtr rightValue, UScriptValuePtr defReturn) const { switch (action) { case UScriptExpression::GT_OPERATOR: { return make_shared(ComputerLogic(rightValue) > 0); } case UScriptExpression::GE_OPERATOR: { return make_shared(ComputerLogic(rightValue) >= 0); } case UScriptExpression::LT_OPERATOR: { return make_shared(ComputerLogic(rightValue) < 0); } case UScriptExpression::LE_OPERATOR: { return make_shared(ComputerLogic(rightValue) <= 0); } case UScriptExpression::EQ_OPERATOR: { return make_shared(ComputerLogic(rightValue) == 0); } case UScriptExpression::NE_OPERATOR: { return make_shared(ComputerLogic(rightValue) != 0); } case UScriptExpression::AND_OPERATOR: return defReturn; case UScriptExpression::OR_OPERATOR: return defReturn; default: break; } return std::make_shared(USCRIPT_ERROR_INTERPRET); } UScriptValuePtr StringValue::Computer(int32_t action, UScriptValuePtr value) { UScriptValuePtr rightValue = UScriptValue::GetRightCompluteValue(value); UScriptValuePtr defReturn = std::make_shared(USCRIPT_ERROR_INTERPRET); if (rightValue == nullptr) { USCRIPT_LOGE("Check param error"); return defReturn; } std::string str; if (action == UScriptExpression::ADD_OPERATOR) { if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { IntegerValue* integerValue = (IntegerValue*)(rightValue.get()); if (integerValue == nullptr) { USCRIPT_LOGE("Failed to cast "); return defReturn; } str.assign(this->GetValue()); return make_shared(str + to_string(integerValue->GetValue())); } else if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { FloatValue* floatValue = (FloatValue*)(rightValue.get()); if (floatValue == nullptr) { USCRIPT_LOGE("Failed to cast "); return defReturn; } str.assign(this->GetValue()); return make_shared(str + to_string(floatValue->GetValue())); } else { StringValue* stringValue = (StringValue*)(rightValue.get()); if (stringValue == nullptr) { USCRIPT_LOGE("Failed to cast "); return defReturn; } str.assign(this->GetValue()); return make_shared(str + stringValue->GetValue()); } } if (rightValue->GetValueType() != UScriptValue::VALUE_TYPE_STRING) { return defReturn; } return ComputerReturn(action, rightValue, defReturn); } int32_t StringValue::ComputerLogic(UScriptValuePtr rightValue) const { StringValue* value = (StringValue*)(rightValue.get()); if (value == nullptr) { USCRIPT_LOGE("Failed to cast "); return -1; } std::string str; str.assign(this->GetValue()); return str.compare(value->GetValue()); } std::string UScriptValue::ToString() { return std::string("null"); } UScriptValuePtr ReturnValue::Computer(int32_t action, UScriptValuePtr value) { UScriptValuePtr defReturn = std::make_shared(USCRIPT_ERROR_INTERPRET); // 只支持一个返回值时参与数值计算 if (values_.size() == 0 || values_.size() > 1) { return defReturn; } return values_[0]->Computer(action, value); } void ReturnValue::AddValue(const UScriptValuePtr value) { if (value != nullptr) { values_.push_back(value); } } void ReturnValue::AddValues(const std::vector values) { for (auto out : values) { values_.push_back(out); } } std::vector ReturnValue::GetValues() const { return values_; } std::string IntegerValue::ToString() { return to_string(value_); } std::string FloatValue::ToString() { return to_string(value_); } std::string StringValue::ToString() { return value_; } std::string ErrorValue::ToString() { return to_string(retCode_); } std::string ReturnValue::ToString() { std::string str; for (size_t index = 0; index < values_.size(); index++) { if (values_[index]->GetValueType() != VALUE_TYPE_RETURN) { str += " [" + to_string(index) + "] = " + values_[index]->ToString(); } else { str += "error type"; } } return str; } std::string UScriptValue::ScriptToString(UScriptValuePtr value) { if (value == nullptr) { std::string str("null"); return str; } static std::map typsMaps = { {VALUE_TYPE_INTEGER, "type: Integer "}, {VALUE_TYPE_FLOAT, "type: Float "}, {VALUE_TYPE_STRING, "type: String "}, {VALUE_TYPE_ERROR, "type: Error "}, {VALUE_TYPE_LIST, "type: List "}, {VALUE_TYPE_RETURN, "type: Return "} }; std::string str = typsMaps[value->GetValueType()]; return str + value->ToString(); } UScriptValuePtr UScriptValue::GetRightCompluteValue(UScriptValuePtr rightValue) { if (rightValue->GetValueType() == VALUE_TYPE_LIST) { ReturnValue* value = (ReturnValue*)(rightValue.get()); std::vector retValues = value->GetValues(); if (retValues.size() == 0 || retValues.size() > 1) { return nullptr; } return retValues[0]; } return rightValue; } } // namespace Uscript