1fb299fa2Sopenharmony_ci/*
2fb299fa2Sopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3fb299fa2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4fb299fa2Sopenharmony_ci * you may not use this file except in compliance with the License.
5fb299fa2Sopenharmony_ci * You may obtain a copy of the License at
6fb299fa2Sopenharmony_ci *
7fb299fa2Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
8fb299fa2Sopenharmony_ci *
9fb299fa2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10fb299fa2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11fb299fa2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fb299fa2Sopenharmony_ci * See the License for the specific language governing permissions and
13fb299fa2Sopenharmony_ci * limitations under the License.
14fb299fa2Sopenharmony_ci */
15fb299fa2Sopenharmony_ci#include "script_interpreter.h"
16fb299fa2Sopenharmony_ci#include <algorithm>
17fb299fa2Sopenharmony_ci#include <fstream>
18fb299fa2Sopenharmony_ci#include "dump.h"
19fb299fa2Sopenharmony_ci#include "script_context.h"
20fb299fa2Sopenharmony_ci#include "script_manager_impl.h"
21fb299fa2Sopenharmony_ci#include "scanner.h"
22fb299fa2Sopenharmony_ci#include "script_utils.h"
23fb299fa2Sopenharmony_ci
24fb299fa2Sopenharmony_ciusing namespace std;
25fb299fa2Sopenharmony_ci
26fb299fa2Sopenharmony_cinamespace Uscript {
27fb299fa2Sopenharmony_cistatic int32_t g_instanceId = 0;
28fb299fa2Sopenharmony_ci
29fb299fa2Sopenharmony_ciint32_t ScriptInterpreter::ExecuteScript(ScriptManagerImpl *manager, Hpackage::PkgManager::StreamPtr pkgStream)
30fb299fa2Sopenharmony_ci{
31fb299fa2Sopenharmony_ci    if (pkgStream == nullptr) {
32fb299fa2Sopenharmony_ci        USCRIPT_LOGE("Param error");
33fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_INVALID_PARAM);
34fb299fa2Sopenharmony_ci        return USCRIPT_INVALID_PARAM;
35fb299fa2Sopenharmony_ci    }
36fb299fa2Sopenharmony_ci    USCRIPT_LOGI("ExecuteScript %s", pkgStream->GetFileName().c_str());
37fb299fa2Sopenharmony_ci    auto inter = new (std::nothrow) ScriptInterpreter(manager);
38fb299fa2Sopenharmony_ci    if (inter == nullptr) {
39fb299fa2Sopenharmony_ci        USCRIPT_LOGE("Fail to create ScriptInterpreter for script %s", pkgStream->GetFileName().c_str());
40fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_ERROR_CREATE_OBJ);
41fb299fa2Sopenharmony_ci        return USCRIPT_ERROR_CREATE_OBJ;
42fb299fa2Sopenharmony_ci    }
43fb299fa2Sopenharmony_ci    int32_t ret = inter->LoadScript(pkgStream);
44fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
45fb299fa2Sopenharmony_ci        USCRIPT_LOGE("Fail to loadScript script %s", pkgStream->GetFileName().c_str());
46fb299fa2Sopenharmony_ci        UPDATER_LAST_WORD(USCRIPT_ERROR_CREATE_OBJ);
47fb299fa2Sopenharmony_ci        return ret;
48fb299fa2Sopenharmony_ci    }
49fb299fa2Sopenharmony_ci    ret = inter->Execute();
50fb299fa2Sopenharmony_ci    delete inter;
51fb299fa2Sopenharmony_ci    inter = nullptr;
52fb299fa2Sopenharmony_ci    USCRIPT_LOGI("ExecuteScript finish ret: %d  script: %s ",
53fb299fa2Sopenharmony_ci        ret, pkgStream->GetFileName().c_str());
54fb299fa2Sopenharmony_ci    return ret;
55fb299fa2Sopenharmony_ci}
56fb299fa2Sopenharmony_ci
57fb299fa2Sopenharmony_ciScriptInterpreter::ScriptInterpreter(ScriptManagerImpl *manager) : scriptManager_(manager)
58fb299fa2Sopenharmony_ci{
59fb299fa2Sopenharmony_ci    instanceId_ = g_instanceId++;
60fb299fa2Sopenharmony_ci}
61fb299fa2Sopenharmony_ci
62fb299fa2Sopenharmony_ciScriptInterpreter::~ScriptInterpreter()
63fb299fa2Sopenharmony_ci{
64fb299fa2Sopenharmony_ci    delete statements_;
65fb299fa2Sopenharmony_ci    auto iter = functions_.begin();
66fb299fa2Sopenharmony_ci    while (iter != functions_.end()) {
67fb299fa2Sopenharmony_ci        auto entry = iter->second;
68fb299fa2Sopenharmony_ci        if (entry) {
69fb299fa2Sopenharmony_ci            delete entry;
70fb299fa2Sopenharmony_ci        }
71fb299fa2Sopenharmony_ci        iter = functions_.erase(iter);
72fb299fa2Sopenharmony_ci    }
73fb299fa2Sopenharmony_ci    functions_.clear();
74fb299fa2Sopenharmony_ci    contextStack_.clear();
75fb299fa2Sopenharmony_ci}
76fb299fa2Sopenharmony_ci
77fb299fa2Sopenharmony_ciint32_t ScriptInterpreter::LoadScript(Hpackage::PkgManager::StreamPtr pkgStream)
78fb299fa2Sopenharmony_ci{
79fb299fa2Sopenharmony_ci    scanner_ = std::make_unique<Scanner>(this);
80fb299fa2Sopenharmony_ci    parser_ = std::make_unique<Parser>(scanner_.get(), this);
81fb299fa2Sopenharmony_ci    scanner_->set_debug(0);
82fb299fa2Sopenharmony_ci    scanner_->SetPkgStream(pkgStream);
83fb299fa2Sopenharmony_ci    int32_t ret = parser_->parse();
84fb299fa2Sopenharmony_ci    return ret;
85fb299fa2Sopenharmony_ci}
86fb299fa2Sopenharmony_ci
87fb299fa2Sopenharmony_ciint32_t ScriptInterpreter::Execute()
88fb299fa2Sopenharmony_ci{
89fb299fa2Sopenharmony_ci    UScriptContextPtr context = std::make_shared<UScriptInterpretContext>(true);
90fb299fa2Sopenharmony_ci    UScriptStatementResult result = statements_->Execute(*this, context);
91fb299fa2Sopenharmony_ci    INTERPRETER_LOGD(*this, context, "statements_ execute result %s ",
92fb299fa2Sopenharmony_ci        UScriptStatementResult::ScriptToString(&result).c_str());
93fb299fa2Sopenharmony_ci    if (result.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR) {
94fb299fa2Sopenharmony_ci        return result.GetError();
95fb299fa2Sopenharmony_ci    }
96fb299fa2Sopenharmony_ci    return USCRIPT_SUCCESS;
97fb299fa2Sopenharmony_ci}
98fb299fa2Sopenharmony_ci
99fb299fa2Sopenharmony_ciint32_t ScriptInterpreter::AddFunction(ScriptFunction *function)
100fb299fa2Sopenharmony_ci{
101fb299fa2Sopenharmony_ci    if (functions_.find(function->GetFunctionName()) != functions_.end()) {
102fb299fa2Sopenharmony_ci        USCRIPT_LOGI("Fail to add function %s, function exist", function->GetFunctionName().c_str());
103fb299fa2Sopenharmony_ci        return USCRIPT_SUCCESS;
104fb299fa2Sopenharmony_ci    }
105fb299fa2Sopenharmony_ci    functions_[function->GetFunctionName()] = function;
106fb299fa2Sopenharmony_ci    return USCRIPT_SUCCESS;
107fb299fa2Sopenharmony_ci}
108fb299fa2Sopenharmony_ci
109fb299fa2Sopenharmony_ciScriptFunction* ScriptInterpreter::FindFunction(const std::string &name)
110fb299fa2Sopenharmony_ci{
111fb299fa2Sopenharmony_ci    if (functions_.find(name) != functions_.end()) {
112fb299fa2Sopenharmony_ci        return functions_[name];
113fb299fa2Sopenharmony_ci    }
114fb299fa2Sopenharmony_ci    return nullptr;
115fb299fa2Sopenharmony_ci}
116fb299fa2Sopenharmony_ci
117fb299fa2Sopenharmony_ciUScriptValuePtr ScriptInterpreter::ExecuteFunction(UScriptContextPtr context, const std::string &name,
118fb299fa2Sopenharmony_ci    ScriptParams *params)
119fb299fa2Sopenharmony_ci{
120fb299fa2Sopenharmony_ci    ScriptFunction *function = FindFunction(name);
121fb299fa2Sopenharmony_ci    if (function == nullptr) {
122fb299fa2Sopenharmony_ci        USCRIPT_LOGI("Fail to find function %s", name.c_str());
123fb299fa2Sopenharmony_ci        return std::make_shared<ErrorValue>(USCRIPT_NOTEXIST_INSTRUCTION);
124fb299fa2Sopenharmony_ci    } else {
125fb299fa2Sopenharmony_ci        return function->Execute(*this, context, params);
126fb299fa2Sopenharmony_ci    }
127fb299fa2Sopenharmony_ci}
128fb299fa2Sopenharmony_ci
129fb299fa2Sopenharmony_ciUScriptValuePtr ScriptInterpreter::FindVariable(UScriptContextPtr local, std::string id)
130fb299fa2Sopenharmony_ci{
131fb299fa2Sopenharmony_ci    for (auto context = contextStack_.rbegin(); context != contextStack_.rend(); context++) {
132fb299fa2Sopenharmony_ci        UScriptValuePtr variable = (*context)->FindVariable(*this, id);
133fb299fa2Sopenharmony_ci        if (variable != nullptr) {
134fb299fa2Sopenharmony_ci            return variable;
135fb299fa2Sopenharmony_ci        }
136fb299fa2Sopenharmony_ci        if ((*context)->IsTop()) {
137fb299fa2Sopenharmony_ci            break;
138fb299fa2Sopenharmony_ci        }
139fb299fa2Sopenharmony_ci    }
140fb299fa2Sopenharmony_ci    return nullptr;
141fb299fa2Sopenharmony_ci}
142fb299fa2Sopenharmony_ci
143fb299fa2Sopenharmony_ciUScriptValuePtr ScriptInterpreter::UpdateVariable(UScriptContextPtr local, std::string id, UScriptValuePtr var)
144fb299fa2Sopenharmony_ci{
145fb299fa2Sopenharmony_ci    for (auto context = contextStack_.rbegin(); context != contextStack_.rend(); context++) {
146fb299fa2Sopenharmony_ci        UScriptValuePtr variable = (*context)->FindVariable(*this, id);
147fb299fa2Sopenharmony_ci        if (variable != nullptr) {
148fb299fa2Sopenharmony_ci            (*context)->UpdateVariable(*this, id, var);
149fb299fa2Sopenharmony_ci        }
150fb299fa2Sopenharmony_ci        if ((*context)->IsTop()) {
151fb299fa2Sopenharmony_ci            break;
152fb299fa2Sopenharmony_ci        }
153fb299fa2Sopenharmony_ci    }
154fb299fa2Sopenharmony_ci    return nullptr;
155fb299fa2Sopenharmony_ci}
156fb299fa2Sopenharmony_ci
157fb299fa2Sopenharmony_civoid ScriptInterpreter::AddStatement(UScriptStatement *statement)
158fb299fa2Sopenharmony_ci{
159fb299fa2Sopenharmony_ci    if (statements_ == nullptr) {
160fb299fa2Sopenharmony_ci        statements_ = UScriptStatementList::CreateInstance(statement);
161fb299fa2Sopenharmony_ci    } else {
162fb299fa2Sopenharmony_ci        statements_->AddScriptStatement(statement);
163fb299fa2Sopenharmony_ci    }
164fb299fa2Sopenharmony_ci}
165fb299fa2Sopenharmony_ci
166fb299fa2Sopenharmony_cibool ScriptInterpreter::IsNativeFunction(std::string name)
167fb299fa2Sopenharmony_ci{
168fb299fa2Sopenharmony_ci    return scriptManager_->FindInstruction(name) != nullptr;
169fb299fa2Sopenharmony_ci}
170fb299fa2Sopenharmony_ci
171fb299fa2Sopenharmony_ciUScriptValuePtr ScriptInterpreter::ExecuteNativeFunc(UScriptContextPtr context,
172fb299fa2Sopenharmony_ci    const std::string &name, ScriptParams *params)
173fb299fa2Sopenharmony_ci{
174fb299fa2Sopenharmony_ci    std::shared_ptr<ErrorValue> error = std::make_shared<ErrorValue>(USCRIPT_ERROR_INTERPRET);
175fb299fa2Sopenharmony_ci    std::shared_ptr<ReturnValue> retValue = std::make_shared<ReturnValue>();
176fb299fa2Sopenharmony_ci    INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s ", name.c_str());
177fb299fa2Sopenharmony_ci    UScriptInstruction* instruction = scriptManager_->FindInstruction(name);
178fb299fa2Sopenharmony_ci    if (instruction == nullptr) {
179fb299fa2Sopenharmony_ci        USCRIPT_LOGE("Fail to find instruction %s", name.c_str());
180fb299fa2Sopenharmony_ci        return error;
181fb299fa2Sopenharmony_ci    }
182fb299fa2Sopenharmony_ci
183fb299fa2Sopenharmony_ci    std::shared_ptr<UScriptInstructionContext> funcContext = std::make_shared<UScriptInstructionContext>();
184fb299fa2Sopenharmony_ci    if (funcContext == nullptr) {
185fb299fa2Sopenharmony_ci        USCRIPT_LOGE("Fail to create context %s", name.c_str());
186fb299fa2Sopenharmony_ci        return error;
187fb299fa2Sopenharmony_ci    }
188fb299fa2Sopenharmony_ci    if (params == nullptr) {
189fb299fa2Sopenharmony_ci        int32_t ret = instruction->Execute(*scriptManager_->GetScriptEnv(name), *funcContext.get());
190fb299fa2Sopenharmony_ci        if (ret != USCRIPT_SUCCESS) {
191fb299fa2Sopenharmony_ci            error->SetValue(ret);
192fb299fa2Sopenharmony_ci            return error;
193fb299fa2Sopenharmony_ci        }
194fb299fa2Sopenharmony_ci        retValue->AddValues(funcContext->GetOutVar());
195fb299fa2Sopenharmony_ci        INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s result: %d", name.c_str(), ret);
196fb299fa2Sopenharmony_ci        return retValue;
197fb299fa2Sopenharmony_ci    }
198fb299fa2Sopenharmony_ci
199fb299fa2Sopenharmony_ci    for (auto id : params->GetParams()) {
200fb299fa2Sopenharmony_ci        UScriptValuePtr result = id->Execute(*this, context);
201fb299fa2Sopenharmony_ci        if (result == nullptr || result->GetValueType() == UScriptValue::VALUE_TYPE_ERROR) {
202fb299fa2Sopenharmony_ci            INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s ", name.c_str());
203fb299fa2Sopenharmony_ci            return error;
204fb299fa2Sopenharmony_ci        }
205fb299fa2Sopenharmony_ci
206fb299fa2Sopenharmony_ci        if (result->GetValueType() != UScriptValue::VALUE_TYPE_LIST) {
207fb299fa2Sopenharmony_ci            funcContext->AddInputParam(result);
208fb299fa2Sopenharmony_ci        } else {
209fb299fa2Sopenharmony_ci            ReturnValue* values = (ReturnValue*)(result.get());
210fb299fa2Sopenharmony_ci            for (auto out : values->GetValues()) {
211fb299fa2Sopenharmony_ci                funcContext->AddInputParam(out);
212fb299fa2Sopenharmony_ci            }
213fb299fa2Sopenharmony_ci        }
214fb299fa2Sopenharmony_ci    }
215fb299fa2Sopenharmony_ci
216fb299fa2Sopenharmony_ci    int32_t ret = instruction->Execute(*scriptManager_->GetScriptEnv(name), *funcContext.get());
217fb299fa2Sopenharmony_ci    INTERPRETER_LOGI(*this, context, "ExecuteNativeFunc::Execute %s result: %d", name.c_str(), ret);
218fb299fa2Sopenharmony_ci    if (ret != USCRIPT_SUCCESS) {
219fb299fa2Sopenharmony_ci        error->SetValue(ret);
220fb299fa2Sopenharmony_ci        return error;
221fb299fa2Sopenharmony_ci    }
222fb299fa2Sopenharmony_ci    retValue->AddValues(funcContext->GetOutVar());
223fb299fa2Sopenharmony_ci    return retValue;
224fb299fa2Sopenharmony_ci}
225fb299fa2Sopenharmony_ci} // namespace Uscript
226