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