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_context.h"
16 #include <iostream>
17 #include <typeinfo>
18 #include <cmath>
19 #include "script_expression.h"
20 #include "script_interpreter.h"
21 #include "script_utils.h"
22
23 using namespace std;
24
25 namespace uscript {
26 static uint32_t g_contextId = 0;
27
PushParam(int32_t value)28 int32_t UScriptInstructionContext::PushParam(int32_t value)
29 {
30 UScriptValuePtr valuePtr = std::make_shared<IntegerValue>(value);
31 USCRIPT_CHECK(valuePtr != nullptr, return USCRIPT_ERROR_CREATE_OBJ, "Failed to create value");
32 outParam_.push_back(valuePtr);
33 return USCRIPT_SUCCESS;
34 }
35
PushParam(float value)36 int32_t UScriptInstructionContext::PushParam(float value)
37 {
38 UScriptValuePtr valuePtr = std::make_shared<FloatValue>(value);
39 USCRIPT_CHECK(valuePtr != nullptr, return USCRIPT_ERROR_CREATE_OBJ, "Failed to create value");
40 outParam_.push_back(valuePtr);
41 return USCRIPT_SUCCESS;
42 }
43
PushParam(const std::string & value)44 int32_t UScriptInstructionContext::PushParam(const std::string& value)
45 {
46 UScriptValuePtr valuePtr = std::make_shared<StringValue>(value);
47 USCRIPT_CHECK(valuePtr != nullptr, return USCRIPT_ERROR_CREATE_OBJ, "Failed to create value");
48 outParam_.push_back(valuePtr);
49 return USCRIPT_SUCCESS;
50 }
51
GetParamCount()52 int32_t UScriptInstructionContext::GetParamCount()
53 {
54 return innerParam_.size();
55 }
56
GetParam(int32_t index,int & value)57 int32_t UScriptInstructionContext::GetParam(int32_t index, int &value)
58 {
59 return GetParam<int32_t, IntegerValue>(index, value);
60 }
61
GetParam(int32_t index,float & value)62 int32_t UScriptInstructionContext::GetParam(int32_t index, float &value)
63 {
64 return GetParam<float, FloatValue>(index, value);
65 }
66
GetParam(int32_t index,std::string & value)67 int32_t UScriptInstructionContext::GetParam(int32_t index, std::string &value)
68 {
69 return GetParam<std::string, StringValue>(index, value);
70 }
71
72 template<class T, class TWapper>
GetParam(int32_t index,T & value)73 int32_t UScriptInstructionContext::GetParam(int32_t index, T &value)
74 {
75 USCRIPT_CHECK(static_cast<size_t>(index) < this->innerParam_.size(),
76 return UScriptContext::PARAM_TYPE_INVALID, "Invalid index %d", index);
77 TWapper* inter = (TWapper*)(innerParam_[index].get());
78 USCRIPT_CHECK(inter != nullptr, return USCRIPT_INVALID_PARAM, "Invalid index %d", index);
79 value = inter->GetValue();
80 return USCRIPT_SUCCESS;
81 }
82
GetParamType(int32_t index)83 UScriptContext::ParamType UScriptInstructionContext::GetParamType(int32_t index)
84 {
85 USCRIPT_CHECK(static_cast<size_t>(index) < this->innerParam_.size(),
86 return UScriptContext::PARAM_TYPE_INVALID, "Invalid index %d", index);
87 UScriptValue::UScriptValueType type = innerParam_[index]->GetValueType();
88 return (UScriptContext::ParamType)type;
89 }
90
AddInputParam(UScriptValuePtr value)91 int32_t UScriptInstructionContext::AddInputParam(UScriptValuePtr value)
92 {
93 innerParam_.push_back(value);
94 return USCRIPT_SUCCESS;
95 }
96
FindVariable(const ScriptInterpreter & inter,std::string id)97 UScriptValuePtr UScriptInterpretContext::FindVariable(const ScriptInterpreter &inter, std::string id)
98 {
99 INTERPRETER_LOGI(inter, this, "FindVariable varName:%s ", id.c_str());
100 if (localVariables_.find(id) != localVariables_.end()) {
101 return localVariables_[id];
102 }
103 return nullptr;
104 }
105
UScriptInterpretContext(bool top)106 UScriptInterpretContext::UScriptInterpretContext(bool top) : top_(top)
107 {
108 contextId_ = ++g_contextId;
109 }
110
UpdateVariable(const ScriptInterpreter & inter,std::string id,UScriptValuePtr value)111 void UScriptInterpretContext::UpdateVariable(const ScriptInterpreter &inter, std::string id,
112 UScriptValuePtr value)
113 {
114 INTERPRETER_LOGI(inter, this, " Update varName:%s value: %s", id.c_str(),
115 UScriptValue::ScriptToString(value).c_str());
116 localVariables_[id] = value;
117 }
118
UpdateVariables(const ScriptInterpreter & inter,UScriptValuePtr value,std::vector<std::string> ids,size_t & startIndex)119 void UScriptInterpretContext::UpdateVariables(const ScriptInterpreter &inter,
120 UScriptValuePtr value,
121 std::vector<std::string> ids,
122 size_t &startIndex)
123 {
124 if (value->GetValueType() != UScriptValue::VALUE_TYPE_LIST) {
125 USCRIPT_CHECK(startIndex < ids.size(), return, "Invalid startIndex %d", startIndex);
126 UpdateVariable(inter, ids[startIndex], value);
127 startIndex++;
128 return;
129 }
130
131 ReturnValue* values = (ReturnValue*)(value.get());
132 for (auto out : values->GetValues()) {
133 USCRIPT_CHECK(startIndex < ids.size(), return, "Invalid startIndex %d", startIndex);
134 UpdateVariable(inter, ids[startIndex], out);
135 startIndex++;
136 }
137 }
138
Computer(int32_t action,UScriptValuePtr rightValue)139 UScriptValuePtr UScriptValue::Computer(int32_t action, UScriptValuePtr rightValue)
140 {
141 return std::make_shared<ErrorValue>(USCRIPT_ERROR_INTERPRET);
142 }
143
144 #define INTEGER_MATH_COMPUTER(op, rightValue) \
145 do { \
146 if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \
147 IntegerValue* value = (IntegerValue*)(rightValue.get()); \
148 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
149 return make_shared<IntegerValue>(GetValue() op value->GetValue()); \
150 } else if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \
151 FloatValue* value = (FloatValue*)(rightValue.get()); \
152 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
153 return make_shared<FloatValue>(GetValue() op value->GetValue()); \
154 } \
155 } while (0)
156
157 #define INTEGER_LOGIC_COMPUTER(op, rightValue) \
158 do { \
159 if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \
160 IntegerValue* value = (IntegerValue*)(rightValue.get()); \
161 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
162 return make_shared<IntegerValue>(GetValue() op value->GetValue()); \
163 } else if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \
164 FloatValue* value = (FloatValue*)(rightValue.get()); \
165 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
166 return make_shared<IntegerValue>(GetValue() op value->GetValue()); \
167 } \
168 } while (0)
169
170 #define INTEGER_MATH_COMPUTER_DIV(rightValue) \
171 do { \
172 if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \
173 IntegerValue* value = (IntegerValue*)(rightValue.get()); \
174 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
175 if (value->GetValue() == 0) { \
176 return defReturn; \
177 } \
178 return make_shared<IntegerValue>(this->GetValue() / value->GetValue()); \
179 } else if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \
180 FloatValue* value = (FloatValue*)(rightValue.get()); \
181 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
182 if (value->GetValue() == 0) { \
183 return defReturn; \
184 } \
185 return make_shared<FloatValue>(this->GetValue() / value->GetValue()); \
186 } \
187 } while (0)
188
Computer(int32_t action,UScriptValuePtr value)189 UScriptValuePtr IntegerValue::Computer(int32_t action, UScriptValuePtr value)
190 {
191 UScriptValuePtr rightValue = UScriptValue::GetRightCompluteValue(value);
192 UScriptValuePtr defReturn = std::make_shared<ErrorValue>(USCRIPT_ERROR_INTERPRET);
193 USCRIPT_CHECK(rightValue != nullptr, return defReturn, "Check param error");
194 switch (action) {
195 case UScriptExpression::ADD_OPERATOR: {
196 INTEGER_MATH_COMPUTER(+, rightValue);
197 break;
198 }
199 case UScriptExpression::SUB_OPERATOR: {
200 INTEGER_MATH_COMPUTER(-, rightValue);
201 break;
202 }
203 case UScriptExpression::MUL_OPERATOR: {
204 INTEGER_MATH_COMPUTER(*, rightValue);
205 break;
206 }
207 case UScriptExpression::DIV_OPERATOR: {
208 INTEGER_MATH_COMPUTER_DIV(rightValue);
209 break;
210 }
211 case UScriptExpression::GT_OPERATOR:
212 INTEGER_LOGIC_COMPUTER(>, rightValue);
213 break;
214 case UScriptExpression::GE_OPERATOR:
215 INTEGER_LOGIC_COMPUTER(>=, rightValue);
216 break;
217 case UScriptExpression::LT_OPERATOR:
218 INTEGER_LOGIC_COMPUTER(<, rightValue);
219 break;
220 case UScriptExpression::LE_OPERATOR:
221 INTEGER_LOGIC_COMPUTER(<=, rightValue);
222 break;
223 case UScriptExpression::EQ_OPERATOR:
224 INTEGER_LOGIC_COMPUTER(==, rightValue);
225 break;
226 case UScriptExpression::NE_OPERATOR:
227 INTEGER_LOGIC_COMPUTER(!=, rightValue);
228 break;
229 case UScriptExpression::AND_OPERATOR:
230 INTEGER_LOGIC_COMPUTER(&&, rightValue);
231 break;
232 case UScriptExpression::OR_OPERATOR:
233 INTEGER_LOGIC_COMPUTER(||, rightValue);
234 break;
235 default:
236 break;
237 }
238 return defReturn;
239 }
240
241 #define FLOAT_MATH_COMPUTER(op, rightValue) \
242 do { \
243 if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \
244 IntegerValue* value = (IntegerValue*)(rightValue.get()); \
245 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
246 return make_shared<FloatValue>(GetValue() op value->GetValue()); \
247 } else if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \
248 FloatValue* value = (FloatValue*)(rightValue.get()); \
249 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
250 return make_shared<FloatValue>(GetValue() op value->GetValue()); \
251 } \
252 } while (0)
253
254 #define FLOAT_LOGIC_COMPUTER(op, rightValue) \
255 do { \
256 if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \
257 IntegerValue* value = (IntegerValue*)(rightValue.get()); \
258 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
259 return make_shared<FloatValue>(GetValue() op value->GetValue()); \
260 } else if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \
261 FloatValue* value = (FloatValue*)(rightValue.get()); \
262 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
263 return make_shared<IntegerValue>(GetValue() op value->GetValue()); \
264 } \
265 } while (0)
266
267 #define FLOAT_MATH_COMPUTER_DIV(rightValue) \
268 do { \
269 if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) { \
270 IntegerValue* value = (IntegerValue*)(rightValue.get()); \
271 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
272 UPDATER_CHECK_ONLY_RETURN (value->GetValue() != 0, break); \
273 return make_shared<FloatValue>(this->GetValue() / value->GetValue()); \
274 } else if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) { \
275 FloatValue* value = (FloatValue*)(rightValue.get()); \
276 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast "); \
277 UPDATER_CHECK_ONLY_RETURN (value->GetValue() != 0, break); \
278 return make_shared<FloatValue>(this->GetValue() / value->GetValue()); \
279 } \
280 } while (0)
281
Computer(int32_t action,UScriptValuePtr value)282 UScriptValuePtr FloatValue::Computer(int32_t action, UScriptValuePtr value)
283 {
284 UScriptValuePtr rightValue = UScriptValue::GetRightCompluteValue(value);
285 UScriptValuePtr defReturn = std::make_shared<ErrorValue>(USCRIPT_ERROR_INTERPRET);
286 USCRIPT_CHECK(rightValue != nullptr, return defReturn, "Check param error");
287 switch (action) {
288 case UScriptExpression::ADD_OPERATOR: {
289 FLOAT_MATH_COMPUTER(+, rightValue);
290 break;
291 }
292 case UScriptExpression::SUB_OPERATOR: {
293 FLOAT_MATH_COMPUTER(-, rightValue);
294 break;
295 }
296 case UScriptExpression::MUL_OPERATOR: {
297 FLOAT_MATH_COMPUTER(*, rightValue);
298 break;
299 }
300 case UScriptExpression::DIV_OPERATOR: {
301 FLOAT_MATH_COMPUTER_DIV(rightValue);
302 break;
303 }
304 case UScriptExpression::GT_OPERATOR:
305 FLOAT_LOGIC_COMPUTER(>, rightValue);
306 break;
307 case UScriptExpression::GE_OPERATOR:
308 FLOAT_LOGIC_COMPUTER(>=, rightValue);
309 break;
310 case UScriptExpression::LT_OPERATOR:
311 FLOAT_LOGIC_COMPUTER(<, rightValue);
312 break;
313 case UScriptExpression::LE_OPERATOR:
314 FLOAT_LOGIC_COMPUTER(<=, rightValue);
315 break;
316 case UScriptExpression::EQ_OPERATOR:
317 return make_shared<IntegerValue>(ComputerEqual(rightValue));
318 case UScriptExpression::NE_OPERATOR:
319 return make_shared<IntegerValue>(!ComputerEqual(rightValue));
320 case UScriptExpression::AND_OPERATOR:
321 FLOAT_LOGIC_COMPUTER(&&, rightValue);
322 break;
323 case UScriptExpression::OR_OPERATOR:
324 FLOAT_LOGIC_COMPUTER(||, rightValue);
325 break;
326 default:
327 break;
328 }
329 return defReturn;
330 }
331
ComputerEqual(UScriptValuePtr rightValue)332 bool FloatValue::ComputerEqual(UScriptValuePtr rightValue)
333 {
334 if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) {
335 IntegerValue* value = (IntegerValue*)(rightValue.get());
336 USCRIPT_CHECK(value != nullptr, return 0, "Failed to cast ");
337 float v2 = value->GetValue();
338 USCRIPT_LOGI("ComputerEqual %f v2: %f", GetValue(), v2);
339 float diff = GetValue() - v2;
340 diff = abs(diff);
341 return diff < 0.0001f;
342 } else if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) {
343 FloatValue* value = (FloatValue*)(rightValue.get());
344 USCRIPT_CHECK(value != nullptr, return 0, "Failed to cast ");
345 float diff = GetValue() - value->GetValue();
346 diff = abs(diff);
347 USCRIPT_LOGI("ComputerEqual %f %f diff: %f", GetValue(), value->GetValue(), diff);
348 return diff < 0.0001f;
349 }
350 return 0;
351 }
352
ComputerReturn(int32_t action,UScriptValuePtr rightValue,UScriptValuePtr defReturn) const353 UScriptValuePtr StringValue::ComputerReturn(int32_t action, UScriptValuePtr rightValue,
354 UScriptValuePtr defReturn) const
355 {
356 switch (action) {
357 case UScriptExpression::GT_OPERATOR: {
358 return make_shared<IntegerValue>(ComputerLogic(rightValue) > 0);
359 }
360 case UScriptExpression::GE_OPERATOR: {
361 return make_shared<IntegerValue>(ComputerLogic(rightValue) >= 0);
362 }
363 case UScriptExpression::LT_OPERATOR: {
364 return make_shared<IntegerValue>(ComputerLogic(rightValue) < 0);
365 }
366 case UScriptExpression::LE_OPERATOR: {
367 return make_shared<IntegerValue>(ComputerLogic(rightValue) <= 0);
368 }
369 case UScriptExpression::EQ_OPERATOR: {
370 return make_shared<IntegerValue>(ComputerLogic(rightValue) == 0);
371 }
372 case UScriptExpression::NE_OPERATOR: {
373 return make_shared<IntegerValue>(ComputerLogic(rightValue) != 0);
374 }
375 case UScriptExpression::AND_OPERATOR:
376 return defReturn;
377 case UScriptExpression::OR_OPERATOR:
378 return defReturn;
379 default:
380 break;
381 }
382 return std::make_shared<ErrorValue>(USCRIPT_ERROR_INTERPRET);
383 }
384
Computer(int32_t action,UScriptValuePtr value)385 UScriptValuePtr StringValue::Computer(int32_t action, UScriptValuePtr value)
386 {
387 UScriptValuePtr rightValue = UScriptValue::GetRightCompluteValue(value);
388 UScriptValuePtr defReturn = std::make_shared<ErrorValue>(USCRIPT_ERROR_INTERPRET);
389 USCRIPT_CHECK(rightValue != nullptr, return defReturn, "Check param error");
390
391 std::string str;
392 if (action == UScriptExpression::ADD_OPERATOR) {
393 if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_INTEGER) {
394 IntegerValue* value = (IntegerValue*)(rightValue.get());
395 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast ");
396 str.assign(this->GetValue());
397 return make_shared<StringValue>(str + to_string(value->GetValue()));
398 } else if (rightValue->GetValueType() == UScriptValue::VALUE_TYPE_FLOAT) {
399 FloatValue* value = (FloatValue*)(rightValue.get());
400 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast ");
401 str.assign(this->GetValue());
402 return make_shared<StringValue>(str + to_string(value->GetValue()));
403 } else {
404 StringValue* value = (StringValue*)(rightValue.get());
405 USCRIPT_CHECK(value != nullptr, return defReturn, "Failed to cast ");
406 str.assign(this->GetValue());
407 return make_shared<StringValue>(str + value->GetValue());
408 }
409 }
410 if (rightValue->GetValueType() != UScriptValue::VALUE_TYPE_STRING) {
411 return defReturn;
412 }
413
414 return ComputerReturn(action, rightValue, defReturn);
415 }
416
ComputerLogic(UScriptValuePtr rightValue) const417 int32_t StringValue::ComputerLogic(UScriptValuePtr rightValue) const
418 {
419 StringValue* value = (StringValue*)(rightValue.get());
420 USCRIPT_CHECK(value != nullptr, return -1, "Failed to cast ");
421 std::string str;
422 str.assign(this->GetValue());
423 return str.compare(value->GetValue());
424 }
425
ToString()426 std::string UScriptValue::ToString()
427 {
428 return std::string("null");
429 }
430
Computer(int32_t action,UScriptValuePtr value)431 UScriptValuePtr ReturnValue::Computer(int32_t action, UScriptValuePtr value)
432 {
433 UScriptValuePtr defReturn = std::make_shared<ErrorValue>(USCRIPT_ERROR_INTERPRET);
434 // 只支持一个返回值时参与数值计算
435 if (values_.size() == 0 || values_.size() > 1) {
436 return defReturn;
437 }
438 return values_[0]->Computer(action, value);
439 }
440
AddValue(const UScriptValuePtr value)441 void ReturnValue::AddValue(const UScriptValuePtr value)
442 {
443 if (value != nullptr) {
444 values_.push_back(value);
445 }
446 }
447
AddValues(const std::vector<UScriptValuePtr> values)448 void ReturnValue::AddValues(const std::vector<UScriptValuePtr> values)
449 {
450 for (auto out : values) {
451 values_.push_back(out);
452 }
453 }
454
GetValues() const455 std::vector<UScriptValuePtr> ReturnValue::GetValues() const
456 {
457 return values_;
458 }
459
ToString()460 std::string IntegerValue::ToString()
461 {
462 return to_string(value_);
463 }
464
ToString()465 std::string FloatValue::ToString()
466 {
467 return to_string(value_);
468 }
469
ToString()470 std::string StringValue::ToString()
471 {
472 return value_;
473 }
474
ToString()475 std::string ErrorValue::ToString()
476 {
477 return to_string(retCode_);
478 }
479
ToString()480 std::string ReturnValue::ToString()
481 {
482 std::string str;
483 for (size_t index = 0; index < values_.size(); index++) {
484 if (values_[index]->GetValueType() != VALUE_TYPE_RETURN) {
485 str += " [" + to_string(index) + "] = " + values_[index]->ToString();
486 } else {
487 str += "error type";
488 }
489 }
490 return str;
491 }
492
ScriptToString(UScriptValuePtr value)493 std::string UScriptValue::ScriptToString(UScriptValuePtr value)
494 {
495 if (value == nullptr) {
496 std::string str("null");
497 return str;
498 }
499 static std::map<int8_t, std::string> typsMaps = {
500 {VALUE_TYPE_INTEGER, "type: Integer "},
501 {VALUE_TYPE_FLOAT, "type: Float "},
502 {VALUE_TYPE_STRING, "type: String "},
503 {VALUE_TYPE_ERROR, "type: Error "},
504 {VALUE_TYPE_LIST, "type: List "},
505 {VALUE_TYPE_RETURN, "type: Return "}
506 };
507 std::string str = typsMaps[value->GetValueType()];
508 return str + value->ToString();
509 }
510
GetRightCompluteValue(UScriptValuePtr rightValue)511 UScriptValuePtr UScriptValue::GetRightCompluteValue(UScriptValuePtr rightValue)
512 {
513 if (rightValue->GetValueType() == VALUE_TYPE_LIST) {
514 ReturnValue* value = (ReturnValue*)(rightValue.get());
515 std::vector<UScriptValuePtr> retValues = value->GetValues();
516 if (retValues.size() == 0 || retValues.size() > 1) {
517 return nullptr;
518 }
519 return retValues[0];
520 }
521 return rightValue;
522 }
523 } // namespace uscript
524