1fb299fa2Sopenharmony_ci/* 2fb299fa2Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at 6fb299fa2Sopenharmony_ci * 7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb299fa2Sopenharmony_ci * 9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and 13fb299fa2Sopenharmony_ci * limitations under the License. 14fb299fa2Sopenharmony_ci */ 15fb299fa2Sopenharmony_ci#include "script_interpreter.h" 16fb299fa2Sopenharmony_ci#include <algorithm> 17fb299fa2Sopenharmony_ci#include <fstream> 18fb299fa2Sopenharmony_ci#include "dump.h" 19fb299fa2Sopenharmony_ci#include "script_context.h" 20fb299fa2Sopenharmony_ci#include "script_manager_impl.h" 21fb299fa2Sopenharmony_ci#include "scanner.h" 22fb299fa2Sopenharmony_ci#include "script_utils.h" 23fb299fa2Sopenharmony_ci 24fb299fa2Sopenharmony_ciusing namespace std; 25fb299fa2Sopenharmony_ci 26fb299fa2Sopenharmony_cinamespace Uscript { 27fb299fa2Sopenharmony_cistatic int32_t g_instanceId = 0; 28fb299fa2Sopenharmony_ci 29fb299fa2Sopenharmony_ciint32_t ScriptInterpreter::ExecuteScript(ScriptManagerImpl *manager, Hpackage::PkgManager::StreamPtr pkgStream) 30fb299fa2Sopenharmony_ci{ 31fb299fa2Sopenharmony_ci if (pkgStream == nullptr) { 32fb299fa2Sopenharmony_ci USCRIPT_LOGE("Param error"); 33fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM); 34fb299fa2Sopenharmony_ci return USCRIPT_INVALID_PARAM; 35fb299fa2Sopenharmony_ci } 36fb299fa2Sopenharmony_ci USCRIPT_LOGI("ExecuteScript %s", pkgStream->GetFileName().c_str()); 37fb299fa2Sopenharmony_ci auto inter = new (std::nothrow) ScriptInterpreter(manager); 38fb299fa2Sopenharmony_ci if (inter == nullptr) { 39fb299fa2Sopenharmony_ci USCRIPT_LOGE("Fail to create ScriptInterpreter for script %s", pkgStream->GetFileName().c_str()); 40fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(USCRIPT_ERROR_CREATE_OBJ); 41fb299fa2Sopenharmony_ci return USCRIPT_ERROR_CREATE_OBJ; 42fb299fa2Sopenharmony_ci } 43fb299fa2Sopenharmony_ci int32_t ret = inter->LoadScript(pkgStream); 44fb299fa2Sopenharmony_ci if (ret != USCRIPT_SUCCESS) { 45fb299fa2Sopenharmony_ci USCRIPT_LOGE("Fail to loadScript script %s", pkgStream->GetFileName().c_str()); 46fb299fa2Sopenharmony_ci UPDATER_LAST_WORD(USCRIPT_ERROR_CREATE_OBJ); 47fb299fa2Sopenharmony_ci return ret; 48fb299fa2Sopenharmony_ci } 49fb299fa2Sopenharmony_ci ret = inter->Execute(); 50fb299fa2Sopenharmony_ci delete inter; 51fb299fa2Sopenharmony_ci inter = nullptr; 52fb299fa2Sopenharmony_ci USCRIPT_LOGI("ExecuteScript finish ret: %d script: %s ", 53fb299fa2Sopenharmony_ci ret, pkgStream->GetFileName().c_str()); 54fb299fa2Sopenharmony_ci return ret; 55fb299fa2Sopenharmony_ci} 56fb299fa2Sopenharmony_ci 57fb299fa2Sopenharmony_ciScriptInterpreter::ScriptInterpreter(ScriptManagerImpl *manager) : scriptManager_(manager) 58fb299fa2Sopenharmony_ci{ 59fb299fa2Sopenharmony_ci instanceId_ = g_instanceId++; 60fb299fa2Sopenharmony_ci} 61fb299fa2Sopenharmony_ci 62fb299fa2Sopenharmony_ciScriptInterpreter::~ScriptInterpreter() 63fb299fa2Sopenharmony_ci{ 64fb299fa2Sopenharmony_ci delete statements_; 65fb299fa2Sopenharmony_ci auto iter = functions_.begin(); 66fb299fa2Sopenharmony_ci while (iter != functions_.end()) { 67fb299fa2Sopenharmony_ci auto entry = iter->second; 68fb299fa2Sopenharmony_ci if (entry) { 69fb299fa2Sopenharmony_ci delete entry; 70fb299fa2Sopenharmony_ci } 71fb299fa2Sopenharmony_ci iter = functions_.erase(iter); 72fb299fa2Sopenharmony_ci } 73fb299fa2Sopenharmony_ci functions_.clear(); 74fb299fa2Sopenharmony_ci contextStack_.clear(); 75fb299fa2Sopenharmony_ci} 76fb299fa2Sopenharmony_ci 77fb299fa2Sopenharmony_ciint32_t ScriptInterpreter::LoadScript(Hpackage::PkgManager::StreamPtr pkgStream) 78fb299fa2Sopenharmony_ci{ 79fb299fa2Sopenharmony_ci scanner_ = std::make_unique<Scanner>(this); 80fb299fa2Sopenharmony_ci parser_ = std::make_unique<Parser>(scanner_.get(), this); 81fb299fa2Sopenharmony_ci scanner_->set_debug(0); 82fb299fa2Sopenharmony_ci scanner_->SetPkgStream(pkgStream); 83fb299fa2Sopenharmony_ci int32_t ret = parser_->parse(); 84fb299fa2Sopenharmony_ci return ret; 85fb299fa2Sopenharmony_ci} 86fb299fa2Sopenharmony_ci 87fb299fa2Sopenharmony_ciint32_t ScriptInterpreter::Execute() 88fb299fa2Sopenharmony_ci{ 89fb299fa2Sopenharmony_ci UScriptContextPtr context = std::make_shared<UScriptInterpretContext>(true); 90fb299fa2Sopenharmony_ci UScriptStatementResult result = statements_->Execute(*this, context); 91fb299fa2Sopenharmony_ci INTERPRETER_LOGD(*this, context, "statements_ execute result %s ", 92fb299fa2Sopenharmony_ci UScriptStatementResult::ScriptToString(&result).c_str()); 93fb299fa2Sopenharmony_ci if (result.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR) { 94fb299fa2Sopenharmony_ci return result.GetError(); 95fb299fa2Sopenharmony_ci } 96fb299fa2Sopenharmony_ci return USCRIPT_SUCCESS; 97fb299fa2Sopenharmony_ci} 98fb299fa2Sopenharmony_ci 99fb299fa2Sopenharmony_ciint32_t ScriptInterpreter::AddFunction(ScriptFunction *function) 100fb299fa2Sopenharmony_ci{ 101fb299fa2Sopenharmony_ci if (functions_.find(function->GetFunctionName()) != functions_.end()) { 102fb299fa2Sopenharmony_ci USCRIPT_LOGI("Fail to add function %s, function exist", function->GetFunctionName().c_str()); 103fb299fa2Sopenharmony_ci return USCRIPT_SUCCESS; 104fb299fa2Sopenharmony_ci } 105fb299fa2Sopenharmony_ci functions_[function->GetFunctionName()] = function; 106fb299fa2Sopenharmony_ci return USCRIPT_SUCCESS; 107fb299fa2Sopenharmony_ci} 108fb299fa2Sopenharmony_ci 109fb299fa2Sopenharmony_ciScriptFunction* ScriptInterpreter::FindFunction(const std::string &name) 110fb299fa2Sopenharmony_ci{ 111fb299fa2Sopenharmony_ci if (functions_.find(name) != functions_.end()) { 112fb299fa2Sopenharmony_ci return functions_[name]; 113fb299fa2Sopenharmony_ci } 114fb299fa2Sopenharmony_ci return nullptr; 115fb299fa2Sopenharmony_ci} 116fb299fa2Sopenharmony_ci 117fb299fa2Sopenharmony_ciUScriptValuePtr ScriptInterpreter::ExecuteFunction(UScriptContextPtr context, const std::string &name, 118fb299fa2Sopenharmony_ci ScriptParams *params) 119fb299fa2Sopenharmony_ci{ 120fb299fa2Sopenharmony_ci ScriptFunction *function = FindFunction(name); 121fb299fa2Sopenharmony_ci if (function == nullptr) { 122fb299fa2Sopenharmony_ci USCRIPT_LOGI("Fail to find function %s", name.c_str()); 123fb299fa2Sopenharmony_ci return std::make_shared<ErrorValue>(USCRIPT_NOTEXIST_INSTRUCTION); 124fb299fa2Sopenharmony_ci } else { 125fb299fa2Sopenharmony_ci return function->Execute(*this, context, params); 126fb299fa2Sopenharmony_ci } 127fb299fa2Sopenharmony_ci} 128fb299fa2Sopenharmony_ci 129fb299fa2Sopenharmony_ciUScriptValuePtr ScriptInterpreter::FindVariable(UScriptContextPtr local, std::string id) 130fb299fa2Sopenharmony_ci{ 131fb299fa2Sopenharmony_ci for (auto context = contextStack_.rbegin(); context != contextStack_.rend(); context++) { 132fb299fa2Sopenharmony_ci UScriptValuePtr variable = (*context)->FindVariable(*this, id); 133fb299fa2Sopenharmony_ci if (variable != nullptr) { 134fb299fa2Sopenharmony_ci return variable; 135fb299fa2Sopenharmony_ci } 136fb299fa2Sopenharmony_ci if ((*context)->IsTop()) { 137fb299fa2Sopenharmony_ci break; 138fb299fa2Sopenharmony_ci } 139fb299fa2Sopenharmony_ci } 140fb299fa2Sopenharmony_ci return nullptr; 141fb299fa2Sopenharmony_ci} 142fb299fa2Sopenharmony_ci 143fb299fa2Sopenharmony_ciUScriptValuePtr ScriptInterpreter::UpdateVariable(UScriptContextPtr local, std::string id, UScriptValuePtr var) 144fb299fa2Sopenharmony_ci{ 145fb299fa2Sopenharmony_ci for (auto context = contextStack_.rbegin(); context != contextStack_.rend(); context++) { 146fb299fa2Sopenharmony_ci UScriptValuePtr variable = (*context)->FindVariable(*this, id); 147fb299fa2Sopenharmony_ci if (variable != nullptr) { 148fb299fa2Sopenharmony_ci (*context)->UpdateVariable(*this, id, var); 149fb299fa2Sopenharmony_ci } 150fb299fa2Sopenharmony_ci if ((*context)->IsTop()) { 151fb299fa2Sopenharmony_ci break; 152fb299fa2Sopenharmony_ci } 153fb299fa2Sopenharmony_ci } 154fb299fa2Sopenharmony_ci return nullptr; 155fb299fa2Sopenharmony_ci} 156fb299fa2Sopenharmony_ci 157fb299fa2Sopenharmony_civoid ScriptInterpreter::AddStatement(UScriptStatement *statement) 158fb299fa2Sopenharmony_ci{ 159fb299fa2Sopenharmony_ci if (statements_ == nullptr) { 160fb299fa2Sopenharmony_ci statements_ = UScriptStatementList::CreateInstance(statement); 161fb299fa2Sopenharmony_ci } else { 162fb299fa2Sopenharmony_ci statements_->AddScriptStatement(statement); 163fb299fa2Sopenharmony_ci } 164fb299fa2Sopenharmony_ci} 165fb299fa2Sopenharmony_ci 166fb299fa2Sopenharmony_cibool ScriptInterpreter::IsNativeFunction(std::string name) 167fb299fa2Sopenharmony_ci{ 168fb299fa2Sopenharmony_ci return scriptManager_->FindInstruction(name) != nullptr; 169fb299fa2Sopenharmony_ci} 170fb299fa2Sopenharmony_ci 171fb299fa2Sopenharmony_ciUScriptValuePtr ScriptInterpreter::ExecuteNativeFunc(UScriptContextPtr context, 172fb299fa2Sopenharmony_ci const std::string &name, ScriptParams *params) 173fb299fa2Sopenharmony_ci{ 174fb299fa2Sopenharmony_ci std::shared_ptr<ErrorValue> error = std::make_shared<ErrorValue>(USCRIPT_ERROR_INTERPRET); 175fb299fa2Sopenharmony_ci std::shared_ptr<ReturnValue> retValue = std::make_shared<ReturnValue>(); 176fb299fa2Sopenharmony_ci INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s ", name.c_str()); 177fb299fa2Sopenharmony_ci UScriptInstruction* instruction = scriptManager_->FindInstruction(name); 178fb299fa2Sopenharmony_ci if (instruction == nullptr) { 179fb299fa2Sopenharmony_ci USCRIPT_LOGE("Fail to find instruction %s", name.c_str()); 180fb299fa2Sopenharmony_ci return error; 181fb299fa2Sopenharmony_ci } 182fb299fa2Sopenharmony_ci 183fb299fa2Sopenharmony_ci std::shared_ptr<UScriptInstructionContext> funcContext = std::make_shared<UScriptInstructionContext>(); 184fb299fa2Sopenharmony_ci if (funcContext == nullptr) { 185fb299fa2Sopenharmony_ci USCRIPT_LOGE("Fail to create context %s", name.c_str()); 186fb299fa2Sopenharmony_ci return error; 187fb299fa2Sopenharmony_ci } 188fb299fa2Sopenharmony_ci if (params == nullptr) { 189fb299fa2Sopenharmony_ci int32_t ret = instruction->Execute(*scriptManager_->GetScriptEnv(name), *funcContext.get()); 190fb299fa2Sopenharmony_ci if (ret != USCRIPT_SUCCESS) { 191fb299fa2Sopenharmony_ci error->SetValue(ret); 192fb299fa2Sopenharmony_ci return error; 193fb299fa2Sopenharmony_ci } 194fb299fa2Sopenharmony_ci retValue->AddValues(funcContext->GetOutVar()); 195fb299fa2Sopenharmony_ci INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s result: %d", name.c_str(), ret); 196fb299fa2Sopenharmony_ci return retValue; 197fb299fa2Sopenharmony_ci } 198fb299fa2Sopenharmony_ci 199fb299fa2Sopenharmony_ci for (auto id : params->GetParams()) { 200fb299fa2Sopenharmony_ci UScriptValuePtr result = id->Execute(*this, context); 201fb299fa2Sopenharmony_ci if (result == nullptr || result->GetValueType() == UScriptValue::VALUE_TYPE_ERROR) { 202fb299fa2Sopenharmony_ci INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s ", name.c_str()); 203fb299fa2Sopenharmony_ci return error; 204fb299fa2Sopenharmony_ci } 205fb299fa2Sopenharmony_ci 206fb299fa2Sopenharmony_ci if (result->GetValueType() != UScriptValue::VALUE_TYPE_LIST) { 207fb299fa2Sopenharmony_ci funcContext->AddInputParam(result); 208fb299fa2Sopenharmony_ci } else { 209fb299fa2Sopenharmony_ci ReturnValue* values = (ReturnValue*)(result.get()); 210fb299fa2Sopenharmony_ci for (auto out : values->GetValues()) { 211fb299fa2Sopenharmony_ci funcContext->AddInputParam(out); 212fb299fa2Sopenharmony_ci } 213fb299fa2Sopenharmony_ci } 214fb299fa2Sopenharmony_ci } 215fb299fa2Sopenharmony_ci 216fb299fa2Sopenharmony_ci int32_t ret = instruction->Execute(*scriptManager_->GetScriptEnv(name), *funcContext.get()); 217fb299fa2Sopenharmony_ci INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s result: %d", name.c_str(), ret); 218fb299fa2Sopenharmony_ci if (ret != USCRIPT_SUCCESS) { 219fb299fa2Sopenharmony_ci error->SetValue(ret); 220fb299fa2Sopenharmony_ci return error; 221fb299fa2Sopenharmony_ci } 222fb299fa2Sopenharmony_ci retValue->AddValues(funcContext->GetOutVar()); 223fb299fa2Sopenharmony_ci return retValue; 224fb299fa2Sopenharmony_ci} 225fb299fa2Sopenharmony_ci} // namespace Uscript 226