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