• 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 "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 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_LOGI(*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         retValue->AddValues(funcContext->GetOutVar());
191         INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s result: %d", name.c_str(), ret);
192         return retValue;
193     }
194 
195     for (auto id : params->GetParams()) {
196         UScriptValuePtr result = id->Execute(*this, context);
197         if (result == nullptr || result->GetValueType() == UScriptValue::VALUE_TYPE_ERROR) {
198             INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s ", name.c_str());
199             return error;
200         }
201 
202         if (result->GetValueType() != UScriptValue::VALUE_TYPE_LIST) {
203             funcContext->AddInputParam(result);
204         } else {
205             ReturnValue* values = (ReturnValue*)(result.get());
206             for (auto out : values->GetValues()) {
207                 funcContext->AddInputParam(out);
208             }
209         }
210     }
211 
212     int32_t ret = instruction->Execute(*scriptManager_->GetScriptEnv(name), *funcContext.get());
213     INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s result: %d", name.c_str(), ret);
214     if (ret != USCRIPT_SUCCESS) {
215         error->SetValue(ret);
216         return error;
217     }
218     retValue->AddValues(funcContext->GetOutVar());
219     return retValue;
220 }
221 } // namespace Uscript
222