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.

868 lines
24 KiB

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