You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

875 lines
24 KiB

  1. #include "UserScript/interpreter.h"
  2. namespace scripting {
  3. void to_null(script_value& value, auto on_value, auto on_error) {
  4. if(std::holds_alternative<null>(value)) {
  5. on_value(std::get<null>(value));
  6. } else {
  7. on_error(value);
  8. }
  9. }
  10. void to_int(script_value& value, auto on_value, auto on_error) {
  11. if(std::holds_alternative<int32_t>(value)) {
  12. on_value(std::get<int32_t>(value));
  13. } else {
  14. on_error(value);
  15. }
  16. }
  17. void to_string(script_value& value, auto on_value, auto on_error) {
  18. if(std::holds_alternative<std::string>(value)) {
  19. on_value(std::get<std::string>(value));
  20. } else {
  21. on_error(value);
  22. }
  23. }
  24. void to_array(script_value& value, auto on_value, auto on_error) {
  25. if(std::holds_alternative<array>(value)) {
  26. on_value(std::get<array>(value));
  27. } else {
  28. on_error(value);
  29. }
  30. }
  31. namespace wizardry {
  32. // taken from cppreference: https://en.cppreference.com/w/cpp/utility/variant/visit
  33. template<class... Ts>
  34. struct overloaded : Ts ... {
  35. using Ts::operator()...;
  36. };
  37. // explicit deduction guide (not needed as of C++20)
  38. template<class... Ts>
  39. overloaded(Ts...) -> overloaded<Ts...>;
  40. }
  41. bool ByteCodeInterpreter::step(std::optional<script_error>& error) {
  42. if(instruction_ptr >= bytecode.size()) return true;
  43. auto& curr_op = bytecode[instruction_ptr];
  44. auto& instr = curr_op.element;
  45. bool ret = std::visit(wizardry::overloaded{
  46. [&](script_value& v){
  47. execution_stack.push_back(v);
  48. return false;
  49. },
  50. [&](variable_tag& v){
  51. execution_stack.push_back(script_variable{.name = v.name});
  52. return false;
  53. },
  54. [&](ByteCodeInterpreter::operator_t& v){
  55. big_f_ing_switch(curr_op, error);
  56. return v == ByteCodeInterpreter::operator_t::INTERNAL_jump or v == ByteCodeInterpreter::operator_t::INTERNAL_jump_if;
  57. },
  58. [&](ByteCodeInterpreter::function_tag& v){
  59. if(v.arity > execution_stack.size()) {
  60. error = script_error{.location = bytecode[instruction_ptr].location, .message = "INTERNAL ERROR: invalid amount of argument found in stack, please warn the devs, this is bad and should never happen"};
  61. return true;
  62. }
  63. auto it = functions.find(v.name);
  64. if(it == functions.end()) {
  65. for(auto arity = v.arity; arity != 0; arity--) {
  66. execution_stack.pop_back();
  67. }
  68. execution_stack.push_back(argument{script_value{}});
  69. // Invalid function is not an error
  70. return true;
  71. }
  72. auto args_in_situ = std::span{execution_stack}.subspan(execution_stack.size() - v.arity);
  73. std::vector<argument> arguments{args_in_situ.begin(), args_in_situ.end()};
  74. auto item = (*it).second->apply(this, arguments, error);
  75. if(item) {
  76. execution_stack.emplace_back(item.value());
  77. }
  78. return true;
  79. },
  80. }, instr);
  81. instruction_ptr = instruction_ptr + 1;
  82. return instruction_ptr >= bytecode.size() || error || ret;
  83. }
  84. std::unique_ptr<UserScript> prepare_interpreter(const std::string& code) {
  85. auto script = std::make_unique<ByteCodeInterpreter>();
  86. script->prepare(code);
  87. return script;
  88. }
  89. /// BIG FUCKING SWITCH
  90. void ByteCodeInterpreter::big_f_ing_switch(operand& op, std::optional<script_error>& error) {
  91. switch (get<ByteCodeInterpreter::operator_t>(op.element)) {
  92. case operator_t::logical_not: {
  93. auto v = resolve_and_pop();
  94. // TODO: strings and arrays to booleans?
  95. to_int(
  96. v,
  97. [&](int32_t &value) {
  98. execution_stack.push_back(script_value{int32_t(!value)});
  99. },
  100. [&](auto &other) {
  101. to_null(
  102. other,
  103. [&](null &) {
  104. execution_stack.push_back(script_value{int32_t(1)});
  105. },
  106. [&](auto &) {
  107. error = script_error{
  108. op.location,
  109. "! operator requires an integer or null"
  110. };
  111. execution_stack.push_back(script_value{});
  112. }
  113. );
  114. }
  115. );
  116. break;
  117. }
  118. case operator_t::binary_not: {
  119. auto v = resolve_and_pop();
  120. to_int(
  121. v,
  122. [&](int32_t &value) {
  123. execution_stack.push_back(script_value{int32_t(~value)});
  124. },
  125. [&](auto &other) {
  126. error = script_error{
  127. op.location,
  128. "~ operator requires an integer"
  129. };
  130. execution_stack.push_back(script_value{});
  131. }
  132. );
  133. break;
  134. }
  135. case operator_t::unary_plus: {
  136. auto v = resolve_and_pop();
  137. error = script_error{
  138. op.location,
  139. "unary + operator is unimplemented"
  140. };
  141. execution_stack.push_back(script_value{});
  142. break;
  143. }
  144. case operator_t::unary_minus: {
  145. auto rhs = resolve_and_pop();
  146. error = script_error{
  147. op.location,
  148. "unary - operator is unimplemented"
  149. };
  150. execution_stack.push_back(script_value{});
  151. break;
  152. }
  153. case operator_t::divide: {
  154. auto rhs = resolve_and_pop();
  155. auto lhs = resolve_and_pop();
  156. to_int(
  157. rhs,
  158. [&](int32_t &value_rhs) {
  159. to_int(
  160. lhs,
  161. [&](int32_t &value_lhs) {
  162. if (value_rhs == 0) {
  163. error = script_error{
  164. op.location,
  165. "Division by zero: / operator requires an non-zero integer as right hand side"
  166. };
  167. execution_stack.push_back(script_value{});
  168. return;
  169. }// TODO: this should be `value_` versions of the variables
  170. execution_stack.push_back(script_value{value_lhs / value_rhs});
  171. },
  172. [&](auto &other) {
  173. error = script_error {
  174. op.location,
  175. "/ operator requires an integer as left hand side"
  176. };
  177. execution_stack.push_back(script_value{});
  178. }
  179. );
  180. },
  181. [&](auto &other) {
  182. error = script_error{
  183. op.location,
  184. "/ operator requires an integer as right hand side"
  185. };
  186. execution_stack.push_back(script_value{});
  187. }
  188. );
  189. break;
  190. }
  191. case operator_t::modulo: {
  192. auto rhs = resolve_and_pop();
  193. auto lhs = resolve_and_pop();
  194. to_int(
  195. rhs,
  196. [&](int32_t &value_rhs) {
  197. to_int(
  198. lhs,
  199. [&](int32_t &value_lhs) {
  200. if (value_rhs == 0) {
  201. error = script_error{
  202. op.location,
  203. "Division by zero: % operator requires an non-zero integer as right hand side"
  204. };
  205. execution_stack.push_back(script_value{});
  206. return;
  207. }
  208. execution_stack.push_back(script_value{value_lhs % value_rhs});
  209. },
  210. [&](auto &other) {
  211. error = script_error{
  212. op.location,
  213. "% operator requires an integer as left hand side"
  214. };
  215. execution_stack.push_back(script_value{});
  216. }
  217. );
  218. },
  219. [&](auto &other) {
  220. error = script_error{
  221. op.location,
  222. "% operator requires an integer as right hand side"
  223. };
  224. execution_stack.push_back(script_value{});
  225. }
  226. );
  227. break;
  228. }
  229. case operator_t::multiply: {
  230. auto rhs = resolve_and_pop();
  231. auto lhs = resolve_and_pop();
  232. to_int(
  233. rhs,
  234. [&](int32_t &value_rhs) {
  235. to_int(
  236. lhs,
  237. [&](int32_t &value_lhs) {
  238. execution_stack.push_back(script_value{value_lhs * value_rhs});
  239. },
  240. [&](auto &other) {
  241. error = script_error{
  242. op.location,
  243. "* operator requires an integer as left hand side"
  244. };
  245. execution_stack.push_back(script_value{});
  246. }
  247. );
  248. },
  249. [&](auto &other) {
  250. error = script_error{
  251. op.location,
  252. "* operator requires an integer as right hand side"
  253. };
  254. execution_stack.push_back(script_value{});
  255. }
  256. );
  257. break;
  258. }
  259. case operator_t::subtract: {
  260. auto rhs = resolve_and_pop();
  261. auto lhs = resolve_and_pop();
  262. to_int(
  263. rhs,
  264. [&](int32_t &value_rhs) {
  265. to_int(
  266. lhs,
  267. [&](int32_t &value_lhs) {
  268. execution_stack.push_back(script_value{value_lhs - value_rhs});
  269. },
  270. [&](auto &other) {
  271. error = script_error{
  272. op.location,
  273. "- operator requires an integer as left hand side"
  274. };
  275. execution_stack.push_back(script_value{});
  276. }
  277. );
  278. },
  279. [&](auto &other) {
  280. error = script_error{
  281. op.location,
  282. "- operator requires an integer as right hand side"
  283. };
  284. execution_stack.push_back(script_value{});
  285. }
  286. );
  287. break;
  288. }
  289. case operator_t::add: {
  290. auto rhs = resolve_and_pop();
  291. auto lhs = resolve_and_pop();
  292. // TODO: strings and arrays concats?
  293. to_int(
  294. rhs,
  295. [&](int32_t &value_rhs) {
  296. to_int(
  297. lhs,
  298. [&](int32_t &value_lhs) {
  299. execution_stack.push_back(script_value{value_lhs + value_rhs});
  300. },
  301. [&](auto &other) {
  302. error = script_error{
  303. op.location,
  304. "+ operator requires an integer as left hand side"
  305. };
  306. execution_stack.push_back(script_value{});
  307. }
  308. );
  309. },
  310. [&](auto &other) {
  311. error = script_error{
  312. op.location,
  313. "+ operator requires an integer as right hand side"
  314. };
  315. execution_stack.push_back(script_value{});
  316. }
  317. );
  318. break;
  319. }
  320. case operator_t::bitshift_left: {
  321. auto rhs = resolve_and_pop();
  322. auto lhs = resolve_and_pop();
  323. // TODO: strings and arrays shifts and rotates?
  324. to_int(
  325. rhs,
  326. [&](int32_t &value_rhs) {
  327. to_int(
  328. lhs,
  329. [&](int32_t &value_lhs) {
  330. if (value_rhs < 0 or value_rhs > 32) {
  331. error = script_error{
  332. op.location,
  333. "bad shift: shift must be between 0 and 32 bits"
  334. };
  335. execution_stack.push_back(script_value{});
  336. return;
  337. }
  338. uint32_t true_lhs = *reinterpret_cast<uint32_t *>(&value_lhs), true_rhs = *reinterpret_cast<uint32_t *>(&value_rhs);
  339. execution_stack.push_back(script_value{static_cast<int32_t>(true_lhs << true_rhs)});
  340. },
  341. [&](auto &other) {
  342. error = script_error{
  343. op.location,
  344. "<< operator requires an integer as left hand side"
  345. };
  346. execution_stack.push_back(script_value{});
  347. }
  348. );
  349. },
  350. [&](auto &other) {
  351. error = script_error{
  352. op.location,
  353. "<< operator requires an integer as right hand side"
  354. };
  355. execution_stack.push_back(script_value{});
  356. }
  357. );
  358. break;
  359. }
  360. case operator_t::bitshift_right: {
  361. auto rhs = resolve_and_pop();
  362. auto lhs = resolve_and_pop();
  363. // TODO: strings and arrays shifts and rotates?
  364. to_int(
  365. rhs,
  366. [&](int32_t &value_rhs) {
  367. to_int(
  368. lhs,
  369. [&](int32_t &value_lhs) {
  370. if (value_rhs < 0 or value_rhs > 32) {
  371. error = script_error{
  372. op.location,
  373. "bad shift: shift must be between 0 and 32 bits"
  374. };
  375. execution_stack.push_back(script_value{});
  376. return;
  377. }
  378. uint32_t true_lhs = *reinterpret_cast<uint32_t *>(&lhs), true_rhs = *reinterpret_cast<uint32_t *>(&rhs);
  379. execution_stack.push_back(script_value{static_cast<int32_t>(true_lhs >> true_rhs)});
  380. },
  381. [&](auto &other) {
  382. error = script_error{
  383. op.location,
  384. ">> operator requires an integer as left hand side"
  385. };
  386. execution_stack.push_back(script_value{});
  387. }
  388. );
  389. },
  390. [&](auto &other) {
  391. error = script_error{
  392. op.location,
  393. ">> operator requires an integer as right hand side"
  394. };
  395. execution_stack.push_back(script_value{});
  396. }
  397. );
  398. break;
  399. }
  400. case operator_t::rotate_left: {
  401. auto rhs = resolve_and_pop();
  402. auto lhs = resolve_and_pop();
  403. // TODO: strings and arrays shifts and rotates?
  404. to_int(
  405. rhs,
  406. [&](int32_t &value_rhs) {
  407. to_int(
  408. lhs,
  409. [&](int32_t &value_lhs) {
  410. if (value_rhs < 0 or value_rhs > 32) {
  411. error = script_error{
  412. op.location,
  413. "bad rotate: rotate must be between 0 and 32 bits"
  414. };
  415. execution_stack.push_back(script_value{});
  416. return;
  417. }
  418. uint32_t true_lhs = *reinterpret_cast<uint32_t *>(&value_lhs), true_rhs = *reinterpret_cast<uint32_t *>(&value_rhs);
  419. execution_stack.push_back(script_value{static_cast<int32_t>(std::rotl(true_lhs, true_rhs))});
  420. },
  421. [&](auto &other) {
  422. error = script_error{
  423. op.location,
  424. "<<< operator requires an integer as left hand side"
  425. };
  426. execution_stack.push_back(script_value{});
  427. }
  428. );
  429. },
  430. [&](auto &other) {
  431. error = script_error{
  432. op.location,
  433. "<<< operator requires an integer as right hand side"
  434. };
  435. execution_stack.push_back(script_value{});
  436. }
  437. );
  438. break;
  439. }
  440. case operator_t::rotate_right: {
  441. auto rhs = resolve_and_pop();
  442. auto lhs = resolve_and_pop();
  443. // TODO: strings and arrays shifts and rotates?
  444. to_int(
  445. rhs,
  446. [&](int32_t &value_rhs) {
  447. to_int(
  448. lhs,
  449. [&](int32_t &value_lhs) {
  450. if (value_rhs < 0 or value_rhs > 32) {
  451. error = script_error{
  452. op.location,
  453. "bad rotate: rotate must be between 0 and 32 bits"
  454. };
  455. execution_stack.push_back(script_value{});
  456. return;
  457. }
  458. uint32_t true_lhs = *reinterpret_cast<uint32_t *>(&value_lhs), true_rhs = *reinterpret_cast<uint32_t *>(&value_rhs);
  459. execution_stack.push_back(script_value{static_cast<int32_t>(std::rotr(true_lhs, true_rhs))});
  460. },
  461. [&](auto &other) {
  462. error = script_error{
  463. op.location,
  464. ">>> operator requires an integer as left hand side"
  465. };
  466. execution_stack.push_back(script_value{});
  467. }
  468. );
  469. },
  470. [&](auto &other) {
  471. error = script_error{
  472. op.location,
  473. ">>> operator requires an integer as right hand side"
  474. };
  475. execution_stack.push_back(script_value{});
  476. }
  477. );
  478. break;
  479. }
  480. case operator_t::less_than: {
  481. auto rhs = resolve_and_pop();
  482. auto lhs = resolve_and_pop();
  483. // TODO: lexicographical strings and arrays shifts comparisons
  484. to_int(
  485. rhs,
  486. [&](int32_t &value_rhs) {
  487. to_int(
  488. lhs,
  489. [&](int32_t &value_lhs) {
  490. execution_stack.push_back(script_value{value_lhs < value_rhs});
  491. },
  492. [&](auto &other) {
  493. error = script_error{
  494. op.location,
  495. "< operator requires an integer as left hand side"
  496. };
  497. execution_stack.push_back(script_value{});
  498. }
  499. );
  500. },
  501. [&](auto &other) {
  502. error = script_error{
  503. op.location,
  504. "< operator requires an integer as right hand side"
  505. };
  506. execution_stack.push_back(script_value{});
  507. }
  508. );
  509. break;
  510. }
  511. case operator_t::greater_than: {
  512. auto rhs = resolve_and_pop();
  513. auto lhs = resolve_and_pop();
  514. // TODO: lexicographical strings and arrays shifts comparisons
  515. to_int(
  516. rhs,
  517. [&](int32_t &value_rhs) {
  518. to_int(
  519. lhs,
  520. [&](int32_t &value_lhs) {
  521. execution_stack.push_back(script_value{value_lhs > value_rhs});
  522. },
  523. [&](auto &other) {
  524. error = script_error{
  525. op.location,
  526. "> operator requires an integer as left hand side"
  527. };
  528. execution_stack.push_back(script_value{});
  529. }
  530. );
  531. },
  532. [&](auto &other) {
  533. error = script_error{
  534. op.location,
  535. "> operator requires an integer as right hand side"
  536. };
  537. execution_stack.push_back(script_value{});
  538. }
  539. );
  540. break;
  541. }
  542. case operator_t::less_or_equal_than: {
  543. auto rhs = resolve_and_pop();
  544. auto lhs = resolve_and_pop();
  545. // TODO: lexicographical strings and arrays shifts comparisons
  546. to_int(
  547. rhs,
  548. [&](int32_t &value_rhs) {
  549. to_int(
  550. lhs,
  551. [&](int32_t &value_lhs) {
  552. execution_stack.push_back(script_value{value_lhs <= value_rhs});
  553. },
  554. [&](auto &other) {
  555. error = script_error{
  556. op.location,
  557. "<= operator requires an integer as left hand side"
  558. };
  559. execution_stack.push_back(script_value{});
  560. }
  561. );
  562. },
  563. [&](auto &other) {
  564. error = script_error{
  565. op.location,
  566. "<= operator requires an integer as right hand side"
  567. };
  568. execution_stack.push_back(script_value{});
  569. }
  570. );
  571. break;
  572. }
  573. case operator_t::greater_or_equal_than: {
  574. auto rhs = resolve_and_pop();
  575. auto lhs = resolve_and_pop();
  576. // TODO: lexicographical strings and arrays shifts comparisons
  577. to_int(
  578. rhs,
  579. [&](int32_t &value_rhs) {
  580. to_int(
  581. lhs,
  582. [&](int32_t &value_lhs) {
  583. execution_stack.push_back(script_value{value_lhs >= value_rhs});
  584. },
  585. [&](auto &other) {
  586. error = script_error{
  587. op.location,
  588. ">= operator requires an integer as left hand side"
  589. };
  590. execution_stack.push_back(script_value{});
  591. }
  592. );
  593. },
  594. [&](auto &other) {
  595. error = script_error{
  596. op.location,
  597. ">= operator requires an integer as right hand side"
  598. };
  599. execution_stack.push_back(script_value{});
  600. }
  601. );
  602. break;
  603. }
  604. case operator_t::equals: {
  605. auto rhs = resolve_and_pop();
  606. auto lhs = resolve_and_pop();
  607. // TODO: error reporting (got degraded)
  608. // TODO: compare arrays
  609. if(rhs.index() != lhs.index()) {
  610. execution_stack.push_back(script_value{0});
  611. } else if(holds_alternative<null>(rhs)) {
  612. execution_stack.push_back(script_value{1});
  613. } else if(holds_alternative<int32_t>(rhs)) {
  614. execution_stack.push_back(script_value{get<int32_t>(rhs) == get<int32_t>(lhs)});
  615. } else if(holds_alternative<std::string>(rhs)) {
  616. execution_stack.push_back(script_value{get<std::string>(rhs) == get<std::string>(lhs)});
  617. } else if(holds_alternative<array>(rhs)) {
  618. execution_stack.push_back(script_value{0});
  619. //execution_stack.push_back(script_value{get<array>(rhs).value == get<array>(lhs).value});
  620. }
  621. break;
  622. }
  623. case operator_t::different: {
  624. auto rhs = resolve_and_pop();
  625. auto lhs = resolve_and_pop();
  626. // TODO: strings and arrays different
  627. to_int(
  628. rhs,
  629. [&](int32_t &value_rhs) {
  630. to_int(
  631. lhs,
  632. [&](int32_t &value_lhs) {
  633. execution_stack.push_back(script_value{value_lhs != value_rhs});
  634. },
  635. [&](auto &other) {
  636. error = script_error{
  637. op.location,
  638. "!= operator requires an integer as left hand side"
  639. };
  640. execution_stack.push_back(script_value{});
  641. }
  642. );
  643. },
  644. [&](auto &other) {
  645. error = script_error{
  646. op.location,
  647. "!= operator requires an integer as right hand side"
  648. };
  649. execution_stack.push_back(script_value{});
  650. }
  651. );
  652. break;
  653. }
  654. case operator_t::binary_and: {
  655. auto rhs = resolve_and_pop();
  656. auto lhs = resolve_and_pop();
  657. to_int(
  658. rhs,
  659. [&](int32_t &value_rhs) {
  660. to_int(
  661. lhs,
  662. [&](int32_t &value_lhs) {
  663. uint32_t true_lhs = *reinterpret_cast<uint32_t *>(&value_lhs), true_rhs = *reinterpret_cast<uint32_t *>(&value_rhs);
  664. execution_stack.push_back(script_value{static_cast<int32_t>(true_lhs & true_rhs)});
  665. },
  666. [&](auto &other) {
  667. error = script_error{
  668. op.location,
  669. "& operator requires an integer as left hand side"
  670. };
  671. execution_stack.push_back(script_value{});
  672. }
  673. );
  674. },
  675. [&](auto &other) {
  676. error = script_error{
  677. op.location,
  678. "& operator requires an integer as right hand side"
  679. };
  680. execution_stack.push_back(script_value{});
  681. }
  682. );
  683. break;
  684. }
  685. case operator_t::binary_or: {
  686. auto rhs = resolve_and_pop();
  687. auto lhs = resolve_and_pop();
  688. to_int(
  689. rhs,
  690. [&](int32_t &value_rhs) {
  691. to_int(
  692. lhs,
  693. [&](int32_t &value_lhs) {
  694. uint32_t true_lhs = *reinterpret_cast<uint32_t *>(&value_lhs), true_rhs = *reinterpret_cast<uint32_t *>(&value_rhs);
  695. execution_stack.push_back(script_value{static_cast<int32_t>(true_lhs | true_rhs)});
  696. },
  697. [&](auto &other) {
  698. error = script_error{
  699. op.location,
  700. "| operator requires an integer as left hand side"
  701. };
  702. execution_stack.push_back(script_value{});
  703. }
  704. );
  705. },
  706. [&](auto &other) {
  707. error = script_error{
  708. op.location,
  709. "| operator requires an integer as right hand side"
  710. };
  711. execution_stack.push_back(script_value{});
  712. }
  713. );
  714. break;
  715. }
  716. case operator_t::binary_xor: {
  717. auto rhs = resolve_and_pop();
  718. auto lhs = resolve_and_pop();
  719. // TODO: XORing strings maybe?
  720. to_int(
  721. rhs,
  722. [&](int32_t &value_rhs) {
  723. to_int(
  724. lhs,
  725. [&](int32_t &value_lhs) {
  726. uint32_t true_lhs = *reinterpret_cast<uint32_t *>(&value_lhs), true_rhs = *reinterpret_cast<uint32_t *>(&value_rhs);
  727. execution_stack.push_back(script_value{static_cast<int32_t>(true_lhs ^ true_rhs)});
  728. },
  729. [&](auto &other) {
  730. error = script_error{
  731. op.location,
  732. "^ operator requires an integer as left hand side"
  733. };
  734. execution_stack.push_back(script_value{});
  735. }
  736. );
  737. },
  738. [&](auto &other) {
  739. error = script_error{
  740. op.location,
  741. "^ operator requires an integer as right hand side"
  742. };
  743. execution_stack.push_back(script_value{});
  744. }
  745. );
  746. break;
  747. }
  748. case operator_t::logical_and: {
  749. auto rhs = resolve_and_pop();
  750. auto lhs = resolve_and_pop();
  751. // TODO: strings and arrays to booleans?
  752. to_int(
  753. rhs,
  754. [&](int32_t &value_rhs) {
  755. to_int(
  756. lhs,
  757. [&](int32_t &value_lhs) {
  758. uint32_t true_lhs = *reinterpret_cast<uint32_t *>(&value_lhs), true_rhs = *reinterpret_cast<uint32_t *>(&value_rhs);
  759. execution_stack.push_back(script_value{static_cast<int32_t>(true_lhs && true_rhs)});
  760. },
  761. [&](auto &other) {
  762. error = script_error{
  763. op.location,
  764. "&& operator requires an integer as left hand side"
  765. };
  766. execution_stack.push_back(script_value{});
  767. }
  768. );
  769. },
  770. [&](auto &other) {
  771. error = script_error{
  772. op.location,
  773. "&& operator requires an integer as right hand side"
  774. };
  775. execution_stack.push_back(script_value{});
  776. }
  777. );
  778. break;
  779. }
  780. case operator_t::logical_or: {
  781. auto rhs = resolve_and_pop();
  782. auto lhs = resolve_and_pop();
  783. // TODO: strings and arrays to booleans?
  784. to_int(
  785. rhs,
  786. [&](int32_t &value_rhs) {
  787. to_int(
  788. lhs,
  789. [&](int32_t &value_lhs) {
  790. uint32_t true_lhs = *reinterpret_cast<uint32_t *>(&value_lhs), true_rhs = *reinterpret_cast<uint32_t *>(&value_rhs);
  791. execution_stack.push_back(script_value{static_cast<int32_t>(true_lhs || true_rhs)});
  792. },
  793. [&](auto &other) {
  794. error = script_error{
  795. op.location,
  796. "|| operator requires an integer as left hand side"
  797. };
  798. execution_stack.push_back(script_value{});
  799. }
  800. );
  801. },
  802. [&](auto &other) {
  803. error = script_error{
  804. op.location,
  805. "|| operator requires an integer as right hand side"
  806. };
  807. execution_stack.push_back(script_value{});
  808. }
  809. );
  810. break;
  811. }
  812. case operator_t::INTERNAL_jump: {
  813. auto location = resolve_and_pop();
  814. to_int(
  815. location,
  816. [&](int32_t &instruction_target) {
  817. instruction_ptr = instruction_target;
  818. },
  819. [&](auto &instruction_target) {
  820. error = script_error{
  821. op.location,
  822. "Jump to invalid location"
  823. };
  824. }
  825. );
  826. break;
  827. }
  828. case operator_t::INTERNAL_jump_if: {
  829. auto location = resolve_and_pop();
  830. auto condition = resolve_and_pop();
  831. // TODO: handle null as the condition
  832. to_int(
  833. condition,
  834. [&](int32_t &condition_value) {
  835. // CAUTION: the condition is inverted, this should really be called jump_if_not
  836. // TODO: rename to jump_if_not appropriately
  837. if (not condition_value) {
  838. to_int(
  839. location,
  840. [&](int32_t &instruction_target) {
  841. instruction_ptr = instruction_target;
  842. },
  843. [&](auto &instruction_target) {
  844. error = script_error{
  845. op.location,
  846. "JumpIf to invalid location "
  847. };
  848. }
  849. );
  850. }
  851. },
  852. [&](auto &instruction_target) {
  853. error = script_error{
  854. op.location,
  855. "Condition is not an integer"
  856. };
  857. }
  858. );
  859. break;
  860. }
  861. case operator_t::INTERNAL_stack_cls: {
  862. execution_stack.clear();
  863. break;
  864. }
  865. }
  866. }
  867. }