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_statement.h"
16 #include "script_context.h"
17 #include "script_expression.h"
18 #include "script_interpreter.h"
19 #include "script_utils.h"
20
21 using namespace std;
22
23 namespace Uscript {
UpdateStatementResult(UScriptValuePtr value)24 void UScriptStatementResult::UpdateStatementResult(UScriptValuePtr value)
25 {
26 if (value == nullptr) {
27 USCRIPT_LOGE("Invalid value");
28 SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR);
29 SetError(USCRIPT_INVALID_PARAM);
30 return;
31 }
32 switch (value->GetValueType()) {
33 case UScriptValue::VALUE_TYPE_INTEGER:
34 /* fallthrough */
35 case UScriptValue::VALUE_TYPE_FLOAT:
36 /* fallthrough */
37 case UScriptValue::VALUE_TYPE_STRING:
38 SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_NORMAL);
39 SetResultValue(value);
40 break;
41 case UScriptValue::VALUE_TYPE_ERROR:
42 SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR);
43 SetError(USCRIPT_ERROR_INTERPRET);
44 if (value->GetValueType() == UScriptValue::VALUE_TYPE_ERROR) {
45 SetError((static_cast<ErrorValue*>(value.get()))->GetValue());
46 }
47 break;
48 case UScriptValue::VALUE_TYPE_LIST:
49 SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_NORMAL);
50 SetResultValue(value);
51 break;
52 case UScriptValue::VALUE_TYPE_RETURN:
53 SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_RTN);
54 SetResultValue(value);
55 break;
56 default:
57 SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR);
58 SetError(USCRIPT_INVALID_SCRIPT);
59 break;
60 }
61 return;
62 }
63
ScriptToString(UScriptStatementResult * result)64 std::string UScriptStatementResult::ScriptToString(UScriptStatementResult *result)
65 {
66 std::string str;
67 USCRIPT_CHECK(result != nullptr, return str, "null value");
68
69 str.append("type: " + to_string(result->GetResultType()));
70 if (result->GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR) {
71 str.append(" errorCode : " + std::to_string(result->GetError()));
72 } else {
73 str.append(" value : " + UScriptValue::ScriptToString(result->GetResultValue()));
74 }
75 return str;
76 }
77
CreateStatement(UScriptStatement::StatementType type)78 UScriptStatement* UScriptStatement::CreateStatement(UScriptStatement::StatementType type)
79 {
80 return new UScriptStatementCtrl(type);
81 }
82
83 // ExpressionStatement
CreateExpressionStatement(UScriptExpression * expression)84 UScriptStatement* UScriptStatement::CreateExpressionStatement(UScriptExpression *expression)
85 {
86 return new UScriptExpressionStatement(expression);
87 }
88
89 // IFStatement
CreateIfStatement(UScriptExpression * condition,UScriptStatementList * list1,UScriptStatementList * list2,UScriptStatement * nextIfState)90 UScriptStatement* UScriptStatement::CreateIfStatement(UScriptExpression *condition,
91 UScriptStatementList *list1,
92 UScriptStatementList *list2,
93 UScriptStatement *nextIfState)
94 {
95 auto ifStatement = new(std::nothrow) UScriptIfStatement(condition, list1);
96 USCRIPT_CHECK(ifStatement != nullptr, return nullptr, "Create if statement failed ");
97 ifStatement->AddFalseStatementList(list2);
98 ifStatement->AddNextStatement(reinterpret_cast<UScriptIfStatement*>(nextIfState));
99 return ifStatement;
100 }
101
102 // FORStatement
CreateForStatement(UScriptExpression * before,UScriptExpression * condition,UScriptExpression * after,UScriptStatementList * list)103 UScriptStatement* UScriptStatement::CreateForStatement(UScriptExpression *before,
104 UScriptExpression *condition,
105 UScriptExpression *after,
106 UScriptStatementList *list)
107 {
108 return new UScriptForStatement(before, condition, after, list);
109 }
110
CreateWhileStatement(UScriptExpression * condition,UScriptStatementList * list)111 UScriptStatement* UScriptStatement::CreateWhileStatement(UScriptExpression *condition,
112 UScriptStatementList *list)
113 {
114 return new UScriptWhileStatement(condition, list);
115 }
116
CreateInstance(UScriptStatement * statement)117 UScriptStatementList* UScriptStatementList::CreateInstance(UScriptStatement *statement)
118 {
119 auto list = new(std::nothrow) UScriptStatementList();
120 USCRIPT_CHECK(list != nullptr, return nullptr, "Failed to create statement list ");
121 list->AddScriptStatement(statement);
122 return list;
123 }
124
~UScriptStatementList()125 UScriptStatementList::~UScriptStatementList()
126 {
127 for (auto iter = statements_.begin(); iter != statements_.end();) {
128 delete *iter;
129 iter = statements_.erase(iter);
130 }
131 statements_.clear();
132 }
133
AddScriptStatement(UScriptStatement * statement)134 void UScriptStatementList::AddScriptStatement(UScriptStatement *statement)
135 {
136 statements_.push_back(statement);
137 }
138
Execute(ScriptInterpreter & interpreter,UScriptContextPtr context)139 UScriptStatementResult UScriptStatementCtrl::Execute(ScriptInterpreter &interpreter, UScriptContextPtr context)
140 {
141 UScriptStatementResult result;
142 switch (GetType()) {
143 case STATEMENT_TYPE_BREAK:
144 result.SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_BREAK);
145 break;
146 case STATEMENT_TYPE_RTN:
147 result.SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_RTN);
148 break;
149 case STATEMENT_TYPE_CONTINUE:
150 result.SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_CONTINUE);
151 break;
152 default:
153 result.SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR);
154 result.SetError(USCRIPT_INVALID_STATEMENT);
155 break;
156 }
157 INTERPRETER_LOGI(interpreter, context, "UScriptStatementList::statement result :%s",
158 UScriptStatementResult::ScriptToString(&result).c_str());
159 return result;
160 }
161
Execute(ScriptInterpreter & interpreter,UScriptContextPtr context)162 UScriptStatementResult UScriptExpressionStatement::Execute(ScriptInterpreter &interpreter,
163 UScriptContextPtr context)
164 {
165 UScriptStatementResult result(UScriptStatementResult::STATEMENT_RESULT_TYPE_NORMAL, nullptr);
166 INTERPRETER_LOGI(interpreter, context, "UScriptExpressionStatement::statement ");
167 UScriptValuePtr value = expression_->Execute(interpreter, context);
168 result.UpdateStatementResult(value);
169 INTERPRETER_LOGI(interpreter, context, "UScriptExpressionStatement::Execute result: %s",
170 UScriptStatementResult::ScriptToString(&result).c_str());
171 return result;
172 }
173
Execute(ScriptInterpreter & interpreter,UScriptContextPtr context)174 UScriptStatementResult UScriptForStatement::Execute(ScriptInterpreter &interpreter, UScriptContextPtr context)
175 {
176 INTERPRETER_LOGI(interpreter, context, "UScriptForStatement::statement ");
177 UScriptStatementResult result(UScriptStatementResult::STATEMENT_RESULT_TYPE_NORMAL, nullptr);
178 if (before_ != nullptr) {
179 INTERPRETER_LOGE(interpreter, context, "Execute before");
180 before_->Execute(interpreter, context);
181 }
182
183 while (1) {
184 if (condition_ != nullptr) {
185 UScriptValuePtr v = condition_->Execute(interpreter, context);
186 if (v == nullptr || v->GetValueType() == UScriptValue::VALUE_TYPE_ERROR) {
187 INTERPRETER_LOGE(interpreter, context, "Execute for condition failed: %s",
188 UScriptValue::ScriptToString(v).c_str());
189 result.SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR);
190 result.SetError(USCRIPT_INVALID_PARAM);
191 return result;
192 }
193 if (!v->IsTrue()) {
194 break;
195 }
196 }
197 UScriptStatementResult centerResult = statements_->Execute(interpreter, context);
198 INTERPRETER_LOGI(interpreter, context, "Execute statements result %s ",
199 UScriptStatementResult::ScriptToString(¢erResult).c_str());
200 if (centerResult.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_BREAK) {
201 break;
202 }
203 if (centerResult.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_RTN ||
204 centerResult.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR) {
205 return centerResult;
206 }
207
208 if (after_ != nullptr) {
209 INTERPRETER_LOGI(interpreter, context, "Execute after");
210 after_->Execute(interpreter, context);
211 }
212 }
213 return result;
214 }
215
Execute(ScriptInterpreter & interpreter,UScriptContextPtr context)216 UScriptStatementResult UScriptWhileStatement::Execute(ScriptInterpreter &interpreter, UScriptContextPtr context)
217 {
218 INTERPRETER_LOGI(interpreter, context, "UScriptStatementResult::statement ");
219 UScriptStatementResult result(UScriptStatementResult::STATEMENT_RESULT_TYPE_NORMAL, nullptr);
220 while (1) {
221 if (condition_ != nullptr) {
222 UScriptValuePtr v = condition_->Execute(interpreter, context);
223 if (v == nullptr || v->GetValueType() == UScriptValue::VALUE_TYPE_ERROR) {
224 INTERPRETER_LOGE(interpreter, context, "Execute while condition failed: %s",
225 UScriptValue::ScriptToString(v).c_str());
226 result.SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR);
227 result.SetError(USCRIPT_INVALID_PARAM);
228 return result;
229 }
230 if (!v->IsTrue()) {
231 break;
232 }
233 }
234 UScriptStatementResult centerResult = statements_->Execute(interpreter, context);
235 INTERPRETER_LOGI(interpreter, context, "Execute statements result %s ",
236 UScriptStatementResult::ScriptToString(¢erResult).c_str());
237 if (centerResult.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_BREAK) {
238 break;
239 }
240 if (centerResult.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_CONTINUE) {
241 continue;
242 }
243 if (centerResult.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_RTN ||
244 centerResult.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR) {
245 return centerResult;
246 }
247 }
248 return result;
249 }
250
Execute(ScriptInterpreter & interpreter,UScriptContextPtr context)251 UScriptStatementResult UScriptIfStatement::Execute(ScriptInterpreter &interpreter, UScriptContextPtr context)
252 {
253 UScriptStatementResult result(UScriptStatementResult::STATEMENT_RESULT_TYPE_NORMAL, nullptr);
254 UScriptValuePtr v = expression_->Execute(interpreter, context);
255 if (v == nullptr || v->GetValueType() == UScriptValue::VALUE_TYPE_ERROR) {
256 INTERPRETER_LOGE(interpreter, context, "Execute for condition failed: %s",
257 UScriptValue::ScriptToString(v).c_str());
258 result.SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR);
259 result.SetError(USCRIPT_INVALID_PARAM);
260 return result;
261 }
262
263 if (v->IsTrue()) {
264 if (trueStatements_ == nullptr) {
265 return result;
266 }
267 UScriptContextPtr local = std::make_shared<UScriptInterpretContext>();
268 return trueStatements_->Execute(interpreter, local);
269 } else if (falseStatements_ != nullptr) {
270 UScriptContextPtr local = std::make_shared<UScriptInterpretContext>();
271 return falseStatements_->Execute(interpreter, local);
272 } else if (nextStatement_ != nullptr) {
273 return nextStatement_->Execute(interpreter, context);
274 }
275 return result;
276 }
277
Execute(ScriptInterpreter & inter,UScriptContextPtr context)278 UScriptStatementResult UScriptStatementList::Execute(ScriptInterpreter &inter, UScriptContextPtr context)
279 {
280 INTERPRETER_LOGI(inter, context, "UScriptStatementList::Execute ");
281 inter.ContextPush(context);
282 UScriptStatementResult result(UScriptStatementResult::STATEMENT_RESULT_TYPE_NORMAL, nullptr);
283 for (auto statement : statements_) {
284 result = statement->Execute(inter, context);
285 if (result.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_BREAK) {
286 break;
287 } else if (result.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_CONTINUE) {
288 break;
289 } else if (result.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_RTN) {
290 break;
291 } else if (result.GetResultType() == UScriptStatementResult::STATEMENT_RESULT_TYPE_ERROR) {
292 break;
293 }
294 }
295 inter.ContextPop();
296 INTERPRETER_LOGI(inter, context, "UScriptStatementList finish %s",
297 UScriptStatementResult::ScriptToString(&result).c_str());
298 return result;
299 }
300
~UScriptExpressionStatement()301 UScriptExpressionStatement::~UScriptExpressionStatement()
302 {
303 delete expression_;
304 }
305
~UScriptIfStatement()306 UScriptIfStatement::~UScriptIfStatement()
307 {
308 delete expression_;
309 delete trueStatements_;
310 delete falseStatements_;
311 delete nextStatement_;
312 }
313
~UScriptForStatement()314 UScriptForStatement::~UScriptForStatement()
315 {
316 delete before_;
317 delete condition_;
318 delete after_;
319 delete statements_;
320 }
321
~UScriptWhileStatement()322 UScriptWhileStatement::~UScriptWhileStatement()
323 {
324 delete condition_;
325 delete statements_;
326 }
327
328
~UScriptReturnStatement()329 UScriptReturnStatement::~UScriptReturnStatement()
330 {
331 delete params_;
332 }
333
CreateStatement(ScriptParams * params)334 UScriptReturnStatement* UScriptReturnStatement::CreateStatement(ScriptParams *params)
335 {
336 auto statement = new(std::nothrow) UScriptReturnStatement();
337 USCRIPT_CHECK(statement != nullptr, return nullptr, "Create statement failed");
338 if (params != nullptr) {
339 statement->AddParams(params);
340 }
341 return statement;
342 }
343
Execute(ScriptInterpreter & interpreter,UScriptContextPtr context)344 UScriptStatementResult UScriptReturnStatement::Execute(ScriptInterpreter &interpreter, UScriptContextPtr context)
345 {
346 UScriptStatementResult result(UScriptStatementResult::STATEMENT_RESULT_TYPE_RTN, nullptr);
347 USCRIPT_CHECK(params_ != nullptr, return result, "Invalid parm");
348
349 std::shared_ptr<ReturnValue> retValue = std::make_shared<ReturnValue>();
350 USCRIPT_CHECK(retValue != nullptr, return result, "Create ret value failed");
351 for (auto id : params_->GetParams()) {
352 UScriptValuePtr var = id->Execute(interpreter, context);
353 INTERPRETER_LOGI(interpreter, context, "params result: %s", UScriptValue::ScriptToString(var).c_str());
354 if (var->GetValueType() == UScriptValue::VALUE_TYPE_LIST) {
355 retValue->AddValues((static_cast<ReturnValue*>(var.get()))->GetValues());
356 } else {
357 retValue->AddValue(var);
358 }
359 }
360 result.SetResultType(UScriptStatementResult::STATEMENT_RESULT_TYPE_RTN);
361 result.SetResultValue(retValue);
362 return result;
363 }
364 } // namespace Uscript
365