/* * 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_interpreter.h" #include #include #include "dump.h" #include "script_context.h" #include "script_manager_impl.h" #include "scanner.h" #include "script_utils.h" using namespace std; namespace Uscript { static int32_t g_instanceId = 0; int32_t ScriptInterpreter::ExecuteScript(ScriptManagerImpl *manager, Hpackage::PkgManager::StreamPtr pkgStream) { if (pkgStream == nullptr) { USCRIPT_LOGE("Param error"); UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM); return USCRIPT_INVALID_PARAM; } USCRIPT_LOGI("ExecuteScript %s", pkgStream->GetFileName().c_str()); auto inter = new (std::nothrow) ScriptInterpreter(manager); if (inter == nullptr) { USCRIPT_LOGE("Fail to create ScriptInterpreter for script %s", pkgStream->GetFileName().c_str()); UPDATER_LAST_WORD(USCRIPT_ERROR_CREATE_OBJ); return USCRIPT_ERROR_CREATE_OBJ; } int32_t ret = inter->LoadScript(pkgStream); if (ret != USCRIPT_SUCCESS) { USCRIPT_LOGE("Fail to loadScript script %s", pkgStream->GetFileName().c_str()); UPDATER_LAST_WORD(USCRIPT_ERROR_CREATE_OBJ); return ret; } ret = inter->Execute(); delete inter; inter = nullptr; USCRIPT_LOGI("ExecuteScript finish ret: %d script: %s ", ret, pkgStream->GetFileName().c_str()); return ret; } ScriptInterpreter::ScriptInterpreter(ScriptManagerImpl *manager) : scriptManager_(manager) { instanceId_ = g_instanceId++; } ScriptInterpreter::~ScriptInterpreter() { delete statements_; auto iter = functions_.begin(); while (iter != functions_.end()) { auto entry = iter->second; if (entry) { delete entry; } iter = functions_.erase(iter); } functions_.clear(); contextStack_.clear(); } int32_t ScriptInterpreter::LoadScript(Hpackage::PkgManager::StreamPtr pkgStream) { scanner_ = std::make_unique(this); parser_ = std::make_unique(scanner_.get(), this); scanner_->set_debug(0); scanner_->SetPkgStream(pkgStream); int32_t ret = parser_->parse(); return ret; } int32_t ScriptInterpreter::Execute() { UScriptContextPtr context = std::make_shared(true); UScriptStatementResult result = statements_->Execute(*this, context); INTERPRETER_LOGD(*this, context, "statements_ execute result %s ", UScriptStatementResult::ScriptToString(&result).c_str()); if (result.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR) { return result.GetError(); } return USCRIPT_SUCCESS; } int32_t ScriptInterpreter::AddFunction(ScriptFunction *function) { if (functions_.find(function->GetFunctionName()) != functions_.end()) { USCRIPT_LOGI("Fail to add function %s, function exist", function->GetFunctionName().c_str()); return USCRIPT_SUCCESS; } functions_[function->GetFunctionName()] = function; return USCRIPT_SUCCESS; } ScriptFunction* ScriptInterpreter::FindFunction(const std::string &name) { if (functions_.find(name) != functions_.end()) { return functions_[name]; } return nullptr; } UScriptValuePtr ScriptInterpreter::ExecuteFunction(UScriptContextPtr context, const std::string &name, ScriptParams *params) { ScriptFunction *function = FindFunction(name); if (function == nullptr) { USCRIPT_LOGI("Fail to find function %s", name.c_str()); return std::make_shared(USCRIPT_NOTEXIST_INSTRUCTION); } else { return function->Execute(*this, context, params); } } UScriptValuePtr ScriptInterpreter::FindVariable(UScriptContextPtr local, std::string id) { for (auto context = contextStack_.rbegin(); context != contextStack_.rend(); context++) { UScriptValuePtr variable = (*context)->FindVariable(*this, id); if (variable != nullptr) { return variable; } if ((*context)->IsTop()) { break; } } return nullptr; } UScriptValuePtr ScriptInterpreter::UpdateVariable(UScriptContextPtr local, std::string id, UScriptValuePtr var) { for (auto context = contextStack_.rbegin(); context != contextStack_.rend(); context++) { UScriptValuePtr variable = (*context)->FindVariable(*this, id); if (variable != nullptr) { (*context)->UpdateVariable(*this, id, var); } if ((*context)->IsTop()) { break; } } return nullptr; } void ScriptInterpreter::AddStatement(UScriptStatement *statement) { if (statements_ == nullptr) { statements_ = UScriptStatementList::CreateInstance(statement); } else { statements_->AddScriptStatement(statement); } } bool ScriptInterpreter::IsNativeFunction(std::string name) { return scriptManager_->FindInstruction(name) != nullptr; } UScriptValuePtr ScriptInterpreter::ExecuteNativeFunc(UScriptContextPtr context, const std::string &name, ScriptParams *params) { std::shared_ptr error = std::make_shared(USCRIPT_ERROR_INTERPRET); std::shared_ptr retValue = std::make_shared(); INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s ", name.c_str()); UScriptInstruction* instruction = scriptManager_->FindInstruction(name); if (instruction == nullptr) { USCRIPT_LOGE("Fail to find instruction %s", name.c_str()); return error; } std::shared_ptr funcContext = std::make_shared(); if (funcContext == nullptr) { USCRIPT_LOGE("Fail to create context %s", name.c_str()); return error; } if (params == nullptr) { int32_t ret = instruction->Execute(*scriptManager_->GetScriptEnv(name), *funcContext.get()); if (ret != USCRIPT_SUCCESS) { error->SetValue(ret); return error; } retValue->AddValues(funcContext->GetOutVar()); INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s result: %d", name.c_str(), ret); return retValue; } for (auto id : params->GetParams()) { UScriptValuePtr result = id->Execute(*this, context); if (result == nullptr || result->GetValueType() == UScriptValue::VALUE_TYPE_ERROR) { INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s ", name.c_str()); return error; } if (result->GetValueType() != UScriptValue::VALUE_TYPE_LIST) { funcContext->AddInputParam(result); } else { ReturnValue* values = (ReturnValue*)(result.get()); for (auto out : values->GetValues()) { funcContext->AddInputParam(out); } } } int32_t ret = instruction->Execute(*scriptManager_->GetScriptEnv(name), *funcContext.get()); INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s result: %d", name.c_str(), ret); if (ret != USCRIPT_SUCCESS) { error->SetValue(ret); return error; } retValue->AddValues(funcContext->GetOutVar()); return retValue; } } // namespace Uscript