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