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