• 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     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