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 "script_context.h"
20  #include "script_manager_impl.h"
21  #include "scanner.h"
22  #include "script_utils.h"
23  
24  using namespace std;
25  
26  namespace Uscript {
27  static int32_t g_instanceId = 0;
28  
ExecuteScript(ScriptManagerImpl * manager,Hpackage::PkgManager::StreamPtr pkgStream)29  int32_t ScriptInterpreter::ExecuteScript(ScriptManagerImpl *manager, Hpackage::PkgManager::StreamPtr pkgStream)
30  {
31      if (pkgStream == nullptr) {
32          USCRIPT_LOGE("Param error");
33          UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM);
34          return USCRIPT_INVALID_PARAM;
35      }
36      USCRIPT_LOGI("ExecuteScript %s", pkgStream->GetFileName().c_str());
37      auto inter = new (std::nothrow) ScriptInterpreter(manager);
38      if (inter == nullptr) {
39          USCRIPT_LOGE("Fail to create ScriptInterpreter for script %s", pkgStream->GetFileName().c_str());
40          UPDATER_LAST_WORD(USCRIPT_ERROR_CREATE_OBJ);
41          return USCRIPT_ERROR_CREATE_OBJ;
42      }
43      int32_t ret = inter->LoadScript(pkgStream);
44      if (ret != USCRIPT_SUCCESS) {
45          USCRIPT_LOGE("Fail to loadScript script %s", pkgStream->GetFileName().c_str());
46          UPDATER_LAST_WORD(USCRIPT_ERROR_CREATE_OBJ);
47          return ret;
48      }
49      ret = inter->Execute();
50      delete inter;
51      inter = nullptr;
52      USCRIPT_LOGI("ExecuteScript finish ret: %d  script: %s ",
53          ret, pkgStream->GetFileName().c_str());
54      return ret;
55  }
56  
ScriptInterpreter(ScriptManagerImpl * manager)57  ScriptInterpreter::ScriptInterpreter(ScriptManagerImpl *manager) : scriptManager_(manager)
58  {
59      instanceId_ = g_instanceId++;
60  }
61  
~ScriptInterpreter()62  ScriptInterpreter::~ScriptInterpreter()
63  {
64      delete statements_;
65      auto iter = functions_.begin();
66      while (iter != functions_.end()) {
67          auto entry = iter->second;
68          if (entry) {
69              delete entry;
70          }
71          iter = functions_.erase(iter);
72      }
73      functions_.clear();
74      contextStack_.clear();
75  }
76  
LoadScript(Hpackage::PkgManager::StreamPtr pkgStream)77  int32_t ScriptInterpreter::LoadScript(Hpackage::PkgManager::StreamPtr pkgStream)
78  {
79      scanner_ = std::make_unique<Scanner>(this);
80      parser_ = std::make_unique<Parser>(scanner_.get(), this);
81      scanner_->set_debug(0);
82      scanner_->SetPkgStream(pkgStream);
83      int32_t ret = parser_->parse();
84      return ret;
85  }
86  
Execute()87  int32_t ScriptInterpreter::Execute()
88  {
89      UScriptContextPtr context = std::make_shared<UScriptInterpretContext>(true);
90      UScriptStatementResult result = statements_->Execute(*this, context);
91      INTERPRETER_LOGD(*this, context, "statements_ execute result %s ",
92          UScriptStatementResult::ScriptToString(&result).c_str());
93      if (result.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR) {
94          return result.GetError();
95      }
96      return USCRIPT_SUCCESS;
97  }
98  
AddFunction(ScriptFunction * function)99  int32_t ScriptInterpreter::AddFunction(ScriptFunction *function)
100  {
101      if (functions_.find(function->GetFunctionName()) != functions_.end()) {
102          USCRIPT_LOGI("Fail to add function %s, function exist", function->GetFunctionName().c_str());
103          return USCRIPT_SUCCESS;
104      }
105      functions_[function->GetFunctionName()] = function;
106      return USCRIPT_SUCCESS;
107  }
108  
FindFunction(const std::string & name)109  ScriptFunction* ScriptInterpreter::FindFunction(const std::string &name)
110  {
111      if (functions_.find(name) != functions_.end()) {
112          return functions_[name];
113      }
114      return nullptr;
115  }
116  
ExecuteFunction(UScriptContextPtr context,const std::string & name,ScriptParams * params)117  UScriptValuePtr ScriptInterpreter::ExecuteFunction(UScriptContextPtr context, const std::string &name,
118      ScriptParams *params)
119  {
120      ScriptFunction *function = FindFunction(name);
121      if (function == nullptr) {
122          USCRIPT_LOGI("Fail to find function %s", name.c_str());
123          return std::make_shared<ErrorValue>(USCRIPT_NOTEXIST_INSTRUCTION);
124      } else {
125          return function->Execute(*this, context, params);
126      }
127  }
128  
FindVariable(UScriptContextPtr local,std::string id)129  UScriptValuePtr ScriptInterpreter::FindVariable(UScriptContextPtr local, std::string id)
130  {
131      for (auto context = contextStack_.rbegin(); context != contextStack_.rend(); context++) {
132          UScriptValuePtr variable = (*context)->FindVariable(*this, id);
133          if (variable != nullptr) {
134              return variable;
135          }
136          if ((*context)->IsTop()) {
137              break;
138          }
139      }
140      return nullptr;
141  }
142  
UpdateVariable(UScriptContextPtr local,std::string id,UScriptValuePtr var)143  UScriptValuePtr ScriptInterpreter::UpdateVariable(UScriptContextPtr local, std::string id, UScriptValuePtr var)
144  {
145      for (auto context = contextStack_.rbegin(); context != contextStack_.rend(); context++) {
146          UScriptValuePtr variable = (*context)->FindVariable(*this, id);
147          if (variable != nullptr) {
148              (*context)->UpdateVariable(*this, id, var);
149          }
150          if ((*context)->IsTop()) {
151              break;
152          }
153      }
154      return nullptr;
155  }
156  
AddStatement(UScriptStatement * statement)157  void ScriptInterpreter::AddStatement(UScriptStatement *statement)
158  {
159      if (statements_ == nullptr) {
160          statements_ = UScriptStatementList::CreateInstance(statement);
161      } else {
162          statements_->AddScriptStatement(statement);
163      }
164  }
165  
IsNativeFunction(std::string name)166  bool ScriptInterpreter::IsNativeFunction(std::string name)
167  {
168      return scriptManager_->FindInstruction(name) != nullptr;
169  }
170  
ExecuteNativeFunc(UScriptContextPtr context,const std::string & name,ScriptParams * params)171  UScriptValuePtr ScriptInterpreter::ExecuteNativeFunc(UScriptContextPtr context,
172      const std::string &name, ScriptParams *params)
173  {
174      std::shared_ptr<ErrorValue> error = std::make_shared<ErrorValue>(USCRIPT_ERROR_INTERPRET);
175      std::shared_ptr<ReturnValue> retValue = std::make_shared<ReturnValue>();
176      INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s ", name.c_str());
177      UScriptInstruction* instruction = scriptManager_->FindInstruction(name);
178      if (instruction == nullptr) {
179          USCRIPT_LOGE("Fail to find instruction %s", name.c_str());
180          return error;
181      }
182  
183      std::shared_ptr<UScriptInstructionContext> funcContext = std::make_shared<UScriptInstructionContext>();
184      if (funcContext == nullptr) {
185          USCRIPT_LOGE("Fail to create context %s", name.c_str());
186          return error;
187      }
188      if (params == nullptr) {
189          int32_t ret = instruction->Execute(*scriptManager_->GetScriptEnv(name), *funcContext.get());
190          if (ret != USCRIPT_SUCCESS) {
191              error->SetValue(ret);
192              return error;
193          }
194          retValue->AddValues(funcContext->GetOutVar());
195          INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s result: %d", name.c_str(), ret);
196          return retValue;
197      }
198  
199      for (auto id : params->GetParams()) {
200          UScriptValuePtr result = id->Execute(*this, context);
201          if (result == nullptr || result->GetValueType() == UScriptValue::VALUE_TYPE_ERROR) {
202              INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s ", name.c_str());
203              return error;
204          }
205  
206          if (result->GetValueType() != UScriptValue::VALUE_TYPE_LIST) {
207              funcContext->AddInputParam(result);
208          } else {
209              ReturnValue* values = (ReturnValue*)(result.get());
210              for (auto out : values->GetValues()) {
211                  funcContext->AddInputParam(out);
212              }
213          }
214      }
215  
216      int32_t ret = instruction->Execute(*scriptManager_->GetScriptEnv(name), *funcContext.get());
217      INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s result: %d", name.c_str(), ret);
218      if (ret != USCRIPT_SUCCESS) {
219          error->SetValue(ret);
220          return error;
221      }
222      retValue->AddValues(funcContext->GetOutVar());
223      return retValue;
224  }
225  } // namespace Uscript
226