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