ivprogProcessor.js 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450
  1. import { Store } from "./store/store";
  2. import { Modes } from "./modes";
  3. import { Context } from "./context";
  4. import { Types } from "./../typeSystem/types";
  5. import { Operators } from "./../ast/operators";
  6. import { LanguageDefinedFunction } from "./definedFunctions";
  7. import {
  8. resultTypeAfterInfixOp,
  9. resultTypeAfterUnaryOp,
  10. } from "./compatibilityTable";
  11. import * as Commands from "./../ast/commands/";
  12. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  13. import { Command } from "./../ast/commands/command";
  14. import * as Expressions from "./../ast/expressions/";
  15. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  16. import { Expression } from "./../ast/expressions/expression";
  17. import * as Utils from "./../util/utils";
  18. import { ArrayType } from "./../typeSystem/array_type";
  19. import { convertToString, toInt } from "../typeSystem/parsers";
  20. import { Config } from "../util/config";
  21. import { ProcessorErrorFactory } from "./error/processorErrorFactory";
  22. import { RuntimeError } from "./error/runtimeError";
  23. import { Location } from "../memory/location";
  24. import { StoreValue } from "./store/value/store_value";
  25. import { StoreValueRef } from "./store/value/store_value_ref";
  26. import { ArrayStoreValue } from "./store/value/array_store_value";
  27. import { ArrayStoreValueRef } from "./store/value/array_store_value_ref";
  28. import { StoreValueAddress } from "./store/value/store_value_address";
  29. import { LocalizedStrings } from "../services/localizedStringsService";
  30. export class IVProgProcessor {
  31. static get MAIN_INTERNAL_ID() {
  32. return "$main";
  33. }
  34. constructor(ast) {
  35. this.ast = ast;
  36. this.globalStore = new Store("$global");
  37. this.stores = [this.globalStore];
  38. this.context = [Context.BASE];
  39. this.input = null;
  40. this.forceKill = false;
  41. this.output = null;
  42. this.mode = Modes.RUN;
  43. /**
  44. * Stores the sourceInfo of every function call, command or expression
  45. */
  46. this.function_call_stack = [];
  47. this.instruction_count = 0;
  48. this.function_call_count = 0;
  49. }
  50. registerInput(input) {
  51. if (this.input !== null) this.input = null;
  52. this.input = input;
  53. }
  54. registerOutput(output) {
  55. if (this.output !== null) this.output = null;
  56. this.output = output;
  57. }
  58. checkContext(context) {
  59. return this.context[this.context.length - 1] === context;
  60. }
  61. ignoreSwitchCases(store) {
  62. if (store.mode === Modes.RETURN) {
  63. return true;
  64. } else if (store.mode === Modes.BREAK) {
  65. return true;
  66. } else {
  67. return false;
  68. }
  69. }
  70. prepareState() {
  71. if (this.stores !== null) {
  72. for (let i = 0; i < this.stores.length; i++) {
  73. delete this.stores[i];
  74. }
  75. this.stores = null;
  76. }
  77. if (this.globalStore !== null) this.globalStore = null;
  78. this.globalStore = new Store("$global");
  79. this.stores = [this.globalStore];
  80. this.context = [Context.BASE];
  81. this.instruction_count = 0;
  82. this.mode = Modes.RUN;
  83. }
  84. async interpretAST() {
  85. this.prepareState();
  86. Location.clear();
  87. await this.initGlobal();
  88. const mainFunc = this.findMainFunction();
  89. if (mainFunc === null) {
  90. throw ProcessorErrorFactory.main_missing();
  91. }
  92. return this.runFunction(mainFunc, [], this.globalStore);
  93. }
  94. async initGlobal() {
  95. if (!this.checkContext(Context.BASE)) {
  96. return ProcessorErrorFactory.invalid_global_var();
  97. }
  98. return this.executeCommands(this.globalStore, this.ast.global);
  99. }
  100. findMainFunction() {
  101. return this.ast.functions.find((v) => v.isMain);
  102. }
  103. findFunction(name) {
  104. if (name.match(/^\$.+$/)) {
  105. if (name === IVProgProcessor.MAIN_INTERNAL_ID) {
  106. return this.findMainFunction();
  107. }
  108. const fun = LanguageDefinedFunction.getFunction(name);
  109. if (!fun) {
  110. throw ProcessorErrorFactory.not_implemented(name);
  111. }
  112. return fun;
  113. } else {
  114. const val = this.ast.functions.find((v) => v.name === name);
  115. if (!val) {
  116. throw ProcessorErrorFactory.function_missing(name);
  117. }
  118. return val;
  119. }
  120. }
  121. async runFunction(func, actualParameters, store) {
  122. const funcName = func.isMain ? IVProgProcessor.MAIN_INTERNAL_ID : func.name;
  123. const funcStore = new Store(funcName);
  124. funcStore.extendStore(this.globalStore);
  125. await this.associateParameters(
  126. func.formalParameters,
  127. actualParameters,
  128. store,
  129. funcStore
  130. );
  131. this.context.push(Context.FUNCTION);
  132. this.stores.push(funcStore);
  133. const stoWithVars = await this.executeCommands(
  134. funcStore,
  135. func.variablesDeclarations
  136. );
  137. const finalSto = this.executeCommands(stoWithVars, func.commands);
  138. this.stores.pop();
  139. this.context.pop();
  140. return finalSto;
  141. }
  142. async associateParameters(
  143. formal_params,
  144. effective_params,
  145. caller_store,
  146. callee_store
  147. ) {
  148. const funcName =
  149. callee_store.name === IVProgProcessor.MAIN_INTERNAL_ID
  150. ? LanguageDefinedFunction.getMainFunctionName()
  151. : callee_store.name;
  152. if (formal_params.length != effective_params.length) {
  153. throw ProcessorErrorFactory.invalid_parameters_size(
  154. funcName,
  155. formal_params.length,
  156. effective_params.length
  157. );
  158. }
  159. for (let i = 0; i < effective_params.length; i += 1) {
  160. const actualParam = effective_params[i];
  161. const actualValue = await this.evaluateExpression(
  162. caller_store,
  163. actualParam
  164. );
  165. const exp = effective_params[i];
  166. let shouldTypeCast = false;
  167. const formalParameter = formal_params[i];
  168. if (!formalParameter.type.isCompatible(actualValue.type)) {
  169. if (
  170. Config.enable_type_casting &&
  171. !formalParameter.byRef &&
  172. Store.canImplicitTypeCast(formalParameter.type, actualValue.type)
  173. ) {
  174. shouldTypeCast = true;
  175. } else {
  176. throw ProcessorErrorFactory.invalid_parameter_type(
  177. funcName,
  178. exp.toString()
  179. );
  180. }
  181. }
  182. if (formalParameter.byRef && !actualValue.inStore()) {
  183. throw ProcessorErrorFactory.invalid_ref(funcName, exp.toString());
  184. }
  185. if (formalParameter.byRef) {
  186. const realObj = caller_store.getStoreObject(actualValue.id);
  187. let ref = null;
  188. if (actualValue instanceof ArrayStoreValue) {
  189. // it's a vector or matrix...
  190. const values = actualValue.get();
  191. const array_type = actualValue.type;
  192. const addresses = values.map((v) =>
  193. realObj.getLocAddressOf(v.line, v.column)
  194. );
  195. const columns = actualValue.isVector() ? 0 : actualValue.columns;
  196. ref = new ArrayStoreValueRef(
  197. array_type,
  198. values,
  199. addresses,
  200. actualValue.lines,
  201. columns,
  202. realObj.id
  203. );
  204. } else {
  205. if (actualValue instanceof StoreValueAddress) {
  206. const line = actualValue.line;
  207. const column = actualValue.column;
  208. ref = new StoreValueRef(
  209. actualValue.type,
  210. actualValue.get(),
  211. realObj.getLocAddressOf(line, column),
  212. realObj.id
  213. );
  214. ref.setReferenceDimension(realObj.type.dimensions);
  215. } else {
  216. ref = new StoreValueRef(
  217. actualValue.type,
  218. actualValue.get(),
  219. realObj.locAddress,
  220. realObj.id
  221. );
  222. }
  223. }
  224. callee_store.insertStore(formalParameter.id, ref);
  225. } else {
  226. let realValue = actualValue;
  227. if (shouldTypeCast) {
  228. realValue = Store.doImplicitCasting(formalParameter.type, realValue);
  229. }
  230. callee_store.insertStore(formalParameter.id, realValue);
  231. }
  232. }
  233. return callee_store;
  234. }
  235. /**
  236. *
  237. * @param {Store} store
  238. * @param {Command[]} cmds
  239. *
  240. * @returns {Promise<Store>}
  241. */
  242. async executeCommands(store, cmds) {
  243. // helper to partially apply a function, in this case executeCommand
  244. let sto = store;
  245. for (let i = 0; i < cmds.length; i += 1) {
  246. sto = await this.executeCommand(sto, cmds[i]);
  247. }
  248. return sto;
  249. }
  250. /**
  251. *
  252. * @param {Store} store
  253. * @param {Command} cmd
  254. *
  255. * @returns {Promise<Store>}
  256. */
  257. async executeCommand(store, cmd) {
  258. this.instruction_count += 1;
  259. if (this.instruction_count % Config.suspend_threshold == 0) {
  260. //every Config.suspend_threshold instruction should briefly delay its execution in order to allow the browser to process other things
  261. await Utils.sleep(5);
  262. }
  263. // Checks if it must interrupt the execution for some reason
  264. if (this.instruction_count >= Config.max_instruction_count) {
  265. throw ProcessorErrorFactory.exceed_max_instructions();
  266. } else if (this.forceKill) {
  267. throw "FORCED_KILL!";
  268. } else if (store.mode === Modes.PAUSE) {
  269. return this.executeCommand(store, cmd);
  270. } else if (store.mode === Modes.RETURN) {
  271. return store;
  272. } else if (
  273. this.checkContext(Context.BREAKABLE) &&
  274. store.mode === Modes.BREAK
  275. ) {
  276. return store;
  277. } else if (this.mode === Modes.ABORT) {
  278. throw LocalizedStrings.getMessage("aborted_execution");
  279. }
  280. if (cmd instanceof Commands.Declaration) {
  281. return this.executeDeclaration(store, cmd);
  282. } else if (cmd instanceof Commands.ArrayIndexAssign) {
  283. return this.executeArrayIndexAssign(store, cmd);
  284. } else if (cmd instanceof Commands.Assign) {
  285. return this.executeAssign(store, cmd);
  286. } else if (cmd instanceof Commands.Break) {
  287. return this.executeBreak(store, cmd);
  288. } else if (cmd instanceof Commands.Return) {
  289. return this.executeReturn(store, cmd);
  290. } else if (cmd instanceof Commands.IfThenElse) {
  291. return this.executeIfThenElse(store, cmd);
  292. } else if (cmd instanceof Commands.RepeatUntil) {
  293. return this.executeRepeatUntil(store, cmd);
  294. } else if (cmd instanceof Commands.While) {
  295. return this.executeWhile(store, cmd);
  296. } else if (cmd instanceof Commands.For) {
  297. return this.executeFor(store, cmd);
  298. } else if (cmd instanceof Commands.Switch) {
  299. return this.executeSwitch(store, cmd);
  300. } else if (cmd instanceof Expressions.FunctionCall) {
  301. return this.executeFunctionCall(store, cmd);
  302. } else if (cmd instanceof Commands.SysCall) {
  303. return this.executeSysCall(store, cmd);
  304. } else {
  305. throw ProcessorErrorFactory.unknown_command(cmd.sourceInfo);
  306. }
  307. }
  308. /**
  309. *
  310. * @param {Store} store
  311. * @param {Commands.SysCall} cmd
  312. *
  313. * @returns {Promise<Store>}
  314. */
  315. async executeSysCall(store, cmd) {
  316. const func = cmd.langFunc.bind(this);
  317. return func(store, cmd);
  318. }
  319. /**
  320. *
  321. * @param {Store} store
  322. * @param {Commands.FunctionCall} cmd
  323. *
  324. * @returns {Promise<Store>}
  325. */
  326. async executeFunctionCall(store, cmd) {
  327. let func = null;
  328. if (cmd.isMainCall) {
  329. func = this.findMainFunction();
  330. } else {
  331. func = this.findFunction(cmd.id);
  332. }
  333. this.function_call_stack.push(cmd.sourceInfo);
  334. const sto = await this.runFunction(func, cmd.actualParameters, store);
  335. sto.destroy();
  336. if (
  337. !Types.VOID.isCompatible(func.returnType) &&
  338. sto.mode !== Modes.RETURN
  339. ) {
  340. const funcName =
  341. func.name === IVProgProcessor.MAIN_INTERNAL_ID
  342. ? LanguageDefinedFunction.getMainFunctionName()
  343. : func.name;
  344. throw ProcessorErrorFactory.function_no_return(funcName);
  345. } else {
  346. this.function_call_stack.pop();
  347. return store;
  348. }
  349. }
  350. /**
  351. *
  352. * @param {Store} store
  353. * @param {Commands.Switch} cmd
  354. *
  355. * @returns {Promise<Store>}
  356. */
  357. async executeSwitch(store, cmd) {
  358. this.context.push(Context.BREAKABLE);
  359. const switchCases = cmd.cases;
  360. let lastStore = store;
  361. let lastCaseCheckResult = false;
  362. for (
  363. let i = 0;
  364. i < switchCases.length && !this.ignoreSwitchCases(lastStore);
  365. i += 1
  366. ) {
  367. const switchCase = switchCases[i];
  368. if (lastCaseCheckResult || switchCase.isDefault) {
  369. lastStore = await this.executeCommands(lastStore, switchCase.commands);
  370. } else {
  371. const equalityInfixApp = new Expressions.InfixApp(
  372. Operators.EQ,
  373. cmd.expression,
  374. switchCase.expression
  375. );
  376. equalityInfixApp.sourceInfo = switchCase.sourceInfo;
  377. const result = await this.evaluateExpression(
  378. lastStore,
  379. equalityInfixApp
  380. );
  381. if (result.get()) {
  382. lastStore = await this.executeCommands(
  383. lastStore,
  384. switchCase.commands
  385. );
  386. }
  387. lastCaseCheckResult = result.get();
  388. }
  389. }
  390. this.context.pop();
  391. if (lastStore.mode === Modes.BREAK) {
  392. lastStore.mode = Modes.RUN;
  393. }
  394. return lastStore;
  395. }
  396. /**
  397. *
  398. * @param {Store} store
  399. * @param {Commands.For} cmd
  400. *
  401. * @returns {Promise<Store>}
  402. */
  403. async executeFor(store, cmd) {
  404. //BEGIN for -> while rewrite
  405. const initCmd = new Commands.Assign(cmd.for_id.id, cmd.for_from);
  406. initCmd.sourceInfo = cmd.sourceInfo;
  407. // Assume for is iterating forward and that pass is not missing
  408. let passValue = cmd.for_pass;
  409. let condition = new Expressions.InfixApp(
  410. Operators.LT,
  411. cmd.for_id,
  412. cmd.for_to
  413. );
  414. if (cmd.for_pass == null) {
  415. passValue = new Expressions.IntLiteral(toInt(1));
  416. const checkEndGTBegin = await this.evaluateExpression(
  417. store,
  418. new Expressions.InfixApp(Operators.GE, cmd.for_to, cmd.for_from)
  419. );
  420. if (!checkEndGTBegin.get()) {
  421. passValue = new Expressions.IntLiteral(toInt(-1));
  422. condition = new Expressions.InfixApp(
  423. Operators.GT,
  424. cmd.for_id,
  425. cmd.for_to
  426. );
  427. }
  428. } else {
  429. const isForward = await this.evaluateExpression(
  430. store,
  431. new Expressions.InfixApp(
  432. Operators.GE,
  433. cmd.for_pass,
  434. new Expressions.IntLiteral(toInt(0))
  435. )
  436. );
  437. if (!isForward.get()) {
  438. condition = new Expressions.InfixApp(
  439. Operators.GT,
  440. cmd.for_id,
  441. cmd.for_to
  442. );
  443. }
  444. }
  445. condition.sourceInfo = cmd.sourceInfo;
  446. const increment = new Commands.Assign(
  447. cmd.for_id.id,
  448. new Expressions.InfixApp(Operators.ADD, cmd.for_id, passValue)
  449. );
  450. increment.sourceInfo = cmd.sourceInfo;
  451. const whileBlock = new Commands.CommandBlock(
  452. [],
  453. cmd.commands.concat(increment)
  454. );
  455. const forAsWhile = new Commands.While(condition, whileBlock);
  456. forAsWhile.sourceInfo = cmd.sourceInfo;
  457. //END for -> while rewrite
  458. const newCmdList = [initCmd, forAsWhile];
  459. return this.executeCommands(store, newCmdList);
  460. }
  461. /**
  462. *
  463. * @param {Store} store
  464. * @param {Commands.RepeatUntil} cmd
  465. *
  466. * @returns {Promise<Store>}
  467. */
  468. async executeRepeatUntil(store, cmd) {
  469. this.context.push(Context.BREAKABLE);
  470. const sto = await this.executeCommands(store, cmd.commands);
  471. if (sto.mode === Modes.BREAK) {
  472. this.context.pop();
  473. sto.mode = Modes.RUN;
  474. return sto;
  475. }
  476. const checkCondition = await this.evaluateExpression(sto, cmd.expression);
  477. if (!checkCondition.type.isCompatible(Types.BOOLEAN)) {
  478. throw ProcessorErrorFactory.loop_condition_type_full(cmd.sourceInfo);
  479. }
  480. this.context.pop();
  481. if (checkCondition.get()) {
  482. return sto;
  483. } else {
  484. return this.executeCommand(sto, cmd);
  485. }
  486. }
  487. /**
  488. *
  489. * @param {Store} store
  490. * @param {Commands.While} cmd
  491. *
  492. * @returns {Promise<Store>}
  493. */
  494. async executeWhile(store, cmd) {
  495. this.context.push(Context.BREAKABLE);
  496. const checkCondition = await this.evaluateExpression(store, cmd.expression);
  497. if (!checkCondition.type.isCompatible(Types.BOOLEAN)) {
  498. throw ProcessorErrorFactory.loop_condition_type_full(
  499. cmd.expression.toString(),
  500. cmd.sourceInfo
  501. );
  502. }
  503. if (checkCondition.get()) {
  504. const sto = await this.executeCommands(store, cmd.commands);
  505. this.context.pop();
  506. if (sto.mode === Modes.BREAK) {
  507. sto.mode = Modes.RUN;
  508. return sto;
  509. }
  510. return this.executeCommand(sto, cmd);
  511. } else {
  512. this.context.pop();
  513. return store;
  514. }
  515. }
  516. /**
  517. *
  518. * @param {Store} store
  519. * @param {Commands.IfThenElse} cmd
  520. *
  521. * @returns {Promise<Store>}
  522. */
  523. async executeIfThenElse(store, cmd) {
  524. const isTrue = await this.evaluateExpression(store, cmd.condition);
  525. if (!isTrue.type.isCompatible(Types.BOOLEAN)) {
  526. throw ProcessorErrorFactory.if_condition_type_full(
  527. cmd.condition.toString(),
  528. cmd.sourceInfo
  529. );
  530. }
  531. if (isTrue.get()) {
  532. return this.executeCommands(store, cmd.ifTrue.commands);
  533. } else if (cmd.ifFalse !== null) {
  534. if (cmd.ifFalse instanceof Commands.IfThenElse) {
  535. return this.executeCommand(store, cmd.ifFalse);
  536. } else {
  537. return this.executeCommands(store, cmd.ifFalse.commands);
  538. }
  539. } else {
  540. return store;
  541. }
  542. }
  543. /**
  544. *
  545. * @param {Store} store
  546. * @param {Commands.Return} cmd
  547. *
  548. * @returns {Promise<Store>}
  549. */
  550. async executeReturn(store, cmd) {
  551. const funcName =
  552. store.name === IVProgProcessor.MAIN_INTERNAL_ID
  553. ? LanguageDefinedFunction.getMainFunctionName()
  554. : store.name;
  555. // console.log(funcName, store.name === IVProgProcessor.MAIN_INTERNAL_ID);
  556. const func = this.findFunction(store.name);
  557. const funcType = func.returnType;
  558. const value = await this.evaluateExpression(store, cmd.expression);
  559. if (value === null && funcType.isCompatible(Types.VOID)) {
  560. store.mode = Modes.RETURN;
  561. return store;
  562. }
  563. let real_value = value;
  564. if (value === null || !funcType.isCompatible(value.type)) {
  565. if (
  566. !Config.enable_type_casting ||
  567. !Store.canImplicitTypeCast(funcType, value.type)
  568. ) {
  569. const stringInfo = funcType.stringInfo();
  570. const info = stringInfo[0];
  571. throw ProcessorErrorFactory.invalid_return_type_full(
  572. funcName,
  573. info.type,
  574. info.dim,
  575. cmd.sourceInfo
  576. );
  577. }
  578. real_value = Store.doImplicitCasting(funcType, value);
  579. }
  580. store.insertStore("$", real_value);
  581. store.mode = Modes.RETURN;
  582. return store;
  583. }
  584. /**
  585. *
  586. * @param {Store} store
  587. * @param {Commands.Break} cmd
  588. *
  589. * @returns {Promise<Store>}
  590. */
  591. async executeBreak(store, cmd) {
  592. if (this.checkContext(Context.BREAKABLE)) {
  593. store.mode = Modes.BREAK;
  594. return store;
  595. } else {
  596. throw ProcessorErrorFactory.unexpected_break_command_full(cmd.sourceInfo);
  597. }
  598. }
  599. /**
  600. *
  601. * @param {Store} store
  602. * @param {Commands.Assign} cmd
  603. *
  604. * @returns {Promise<Store>}
  605. */
  606. async executeAssign(store, cmd) {
  607. const inStore = store.applyStore(cmd.id);
  608. if (inStore.isConst) {
  609. throw ProcessorErrorFactory.invalid_const_assignment_full(
  610. cmd.id,
  611. cmd.sourceInfo
  612. );
  613. }
  614. const value = await this.evaluateExpression(store, cmd.expression);
  615. let realValue = value;
  616. if (!inStore.type.isCompatible(realValue.type)) {
  617. if (
  618. Config.enable_type_casting &&
  619. Store.canImplicitTypeCast(inStore.type, value.type)
  620. ) {
  621. realValue = Store.doImplicitCasting(inStore.type, realValue);
  622. } else {
  623. const stringInfo = inStore.type.stringInfo();
  624. const info = stringInfo[0];
  625. const exp_type_string_info = value.type.stringInfo();
  626. const exp_type_info = exp_type_string_info[0];
  627. const exp = cmd.expression.toString();
  628. throw ProcessorErrorFactory.incompatible_types_full(
  629. info.type,
  630. info.dim,
  631. exp_type_info.type,
  632. exp_type_info.dim,
  633. exp,
  634. cmd.sourceInfo
  635. );
  636. }
  637. }
  638. if (inStore instanceof ArrayStoreValue) {
  639. const columns = realValue.columns == null ? 0 : realValue.columns;
  640. if (inStore.lines !== realValue.lines || inStore.columns !== columns) {
  641. const exp = cmd.expression.toString();
  642. if (inStore.isVector()) {
  643. throw ProcessorErrorFactory.invalid_vector_assignment_full(
  644. cmd.id,
  645. inStore.lines,
  646. exp,
  647. realValue.lines,
  648. cmd.sourceInfo
  649. );
  650. } else {
  651. throw ProcessorErrorFactory.invalid_matrix_assignment_full(
  652. cmd.id,
  653. inStore.lines,
  654. inStore.columns,
  655. exp,
  656. realValue.lines,
  657. realValue.columns,
  658. cmd.sourceInfo
  659. );
  660. }
  661. }
  662. }
  663. store.updateStore(cmd.id, realValue);
  664. return store;
  665. }
  666. /**
  667. *
  668. * @param {Store} store
  669. * @param {Commands.ArrayIndexAssign} cmd
  670. *
  671. * @returns {Promise<Store>}
  672. */
  673. async executeArrayIndexAssign(store, cmd) {
  674. const mustBeArray = store.applyStore(cmd.id);
  675. let used_dims = 0;
  676. if (mustBeArray.isConst) {
  677. throw ProcessorErrorFactory.invalid_const_assignment_full(
  678. cmd.id,
  679. cmd.sourceInfo
  680. );
  681. }
  682. if (!(mustBeArray.type instanceof ArrayType)) {
  683. throw ProcessorErrorFactory.invalid_array_access_full(
  684. cmd.id,
  685. cmd.sourceInfo
  686. );
  687. }
  688. const lineSV = await this.evaluateExpression(store, cmd.line);
  689. if (!Types.INTEGER.isCompatible(lineSV.type)) {
  690. throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
  691. }
  692. used_dims += 1;
  693. const line = lineSV.get().toNumber();
  694. const columnSV = await this.evaluateExpression(store, cmd.column);
  695. let column = null;
  696. if (columnSV != null) {
  697. if (!Types.INTEGER.isCompatible(columnSV.type)) {
  698. throw ProcessorErrorFactory.array_dimension_not_int_full(
  699. cmd.sourceInfo
  700. );
  701. }
  702. column = columnSV.get().toNumber();
  703. used_dims += 1;
  704. }
  705. const value = await this.evaluateExpression(store, cmd.expression);
  706. let actualValue = value;
  707. if (line >= mustBeArray.lines) {
  708. if (mustBeArray.isVector) {
  709. throw ProcessorErrorFactory.vector_line_outbounds_full(
  710. cmd.id,
  711. line,
  712. mustBeArray.lines,
  713. cmd.sourceInfo
  714. );
  715. } else {
  716. throw ProcessorErrorFactory.matrix_line_outbounds_full(
  717. cmd.id,
  718. line,
  719. mustBeArray.lines,
  720. cmd.sourceInfo
  721. );
  722. }
  723. } else if (line < 0) {
  724. throw ProcessorErrorFactory.array_dimension_not_positive_full(
  725. cmd.sourceInfo
  726. );
  727. }
  728. if (column != null && mustBeArray.columns === 0) {
  729. throw ProcessorErrorFactory.vector_not_matrix_full(
  730. cmd.id,
  731. cmd.sourceInfo
  732. );
  733. }
  734. if (column != null) {
  735. if (column >= mustBeArray.columns) {
  736. throw ProcessorErrorFactory.matrix_column_outbounds_full(
  737. cmd.id,
  738. column,
  739. mustBeArray.columns,
  740. cmd.sourceInfo
  741. );
  742. } else if (column < 0) {
  743. throw ProcessorErrorFactory.array_dimension_not_positive_full(
  744. cmd.sourceInfo
  745. );
  746. }
  747. }
  748. if (!mustBeArray.type.canAccept(value.type, used_dims)) {
  749. if (
  750. !Config.enable_type_casting ||
  751. !Store.canImplicitTypeCast(mustBeArray.type.innerType, value.type)
  752. ) {
  753. const type = mustBeArray.type.innerType;
  754. const stringInfo = type.stringInfo();
  755. const info = stringInfo[0];
  756. const exp_type_string_info = value.type.stringInfo();
  757. const exp_type_info = exp_type_string_info[0];
  758. const exp = cmd.expression.toString();
  759. throw ProcessorErrorFactory.incompatible_types_full(
  760. info.type,
  761. info.dim,
  762. exp_type_info.type,
  763. exp_type_info.dim,
  764. exp,
  765. cmd.sourceInfo
  766. );
  767. }
  768. actualValue = Store.doImplicitCasting(mustBeArray.type.innerType, value);
  769. }
  770. const current_value = mustBeArray.getAt(line, column);
  771. if (current_value instanceof ArrayStoreValue) {
  772. if (
  773. current_value.lines !== actualValue.lines ||
  774. current_value.columns !== actualValue.columns
  775. ) {
  776. const exp = cmd.expression.toString();
  777. throw ProcessorErrorFactory.invalid_matrix_index_assign_full(
  778. cmd.id,
  779. line,
  780. current_value.lines,
  781. exp,
  782. actualValue.lines,
  783. cmd.sourceInfo
  784. );
  785. }
  786. }
  787. return store.updateStoreArray(cmd.id, actualValue, line, column);
  788. }
  789. /**
  790. *
  791. * @param {Store} store
  792. * @param {Commands.Declaration} cmd
  793. *
  794. * @returns {Promise<Store>}
  795. */
  796. async executeDeclaration(store, cmd) {
  797. if (cmd instanceof Commands.ArrayDeclaration) {
  798. return this.executeArrayDeclaration(store, cmd);
  799. } else {
  800. let temp = new StoreValue(cmd.type, null, null, cmd.isConst);
  801. if (cmd.initial !== null) {
  802. const value = await this.evaluateExpression(store, cmd.initial);
  803. let realValue = value;
  804. if (!value.type.isCompatible(cmd.type)) {
  805. if (
  806. Config.enable_type_casting &&
  807. Store.canImplicitTypeCast(cmd.type, value.type)
  808. ) {
  809. realValue = Store.doImplicitCasting(cmd.type, realValue);
  810. } else {
  811. const stringInfo = value.type.stringInfo();
  812. const info = stringInfo[0];
  813. const exp_type_string_info = value.type.stringInfo();
  814. const exp_type_info = exp_type_string_info[0];
  815. const exp = cmd.expression.toString();
  816. throw ProcessorErrorFactory.incompatible_types_full(
  817. info.type,
  818. info.dim,
  819. exp_type_info.type,
  820. exp_type_info.dim,
  821. exp,
  822. cmd.sourceInfo
  823. );
  824. }
  825. }
  826. temp = new StoreValue(cmd.type, realValue.get(), null, cmd.isConst);
  827. }
  828. store.insertStore(cmd.id, temp);
  829. return store;
  830. }
  831. }
  832. /**
  833. *
  834. * @param {Store} store
  835. * @param {Commands.ArrayDeclaration} cmd
  836. *
  837. * @returns {Promise<Store>}
  838. */
  839. async executeArrayDeclaration(store, cmd) {
  840. const linesSV = await this.evaluateExpression(store, cmd.lines);
  841. if (!Types.INTEGER.isCompatible(linesSV.type)) {
  842. throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
  843. }
  844. const line = linesSV.get().toNumber();
  845. const columnsSV = await this.evaluateExpression(store, cmd.columns);
  846. let column = null;
  847. if (columnsSV !== null) {
  848. if (!Types.INTEGER.isCompatible(columnsSV.type)) {
  849. throw ProcessorErrorFactory.array_dimension_not_int_full(
  850. cmd.sourceInfo
  851. );
  852. }
  853. column = columnsSV.get().toNumber();
  854. if (column < 0) {
  855. throw ProcessorErrorFactory.array_dimension_not_positive_full(
  856. cmd.sourceInfo
  857. );
  858. }
  859. }
  860. let temp = new ArrayStoreValue(
  861. cmd.type,
  862. [],
  863. line,
  864. column,
  865. null,
  866. cmd.isConst
  867. );
  868. if (cmd.initial !== null) {
  869. // array can only be initialized by a literal....
  870. const valueList = await this.evaluateArrayLiteral(
  871. store,
  872. cmd.initial,
  873. cmd.type,
  874. line,
  875. column
  876. );
  877. temp = new ArrayStoreValue(
  878. cmd.type,
  879. valueList,
  880. line,
  881. column,
  882. null,
  883. cmd.isConst
  884. );
  885. }
  886. store.insertStore(cmd.id, temp);
  887. return store;
  888. }
  889. /**
  890. *
  891. * @param {Store} store
  892. * @param {Expression} exp
  893. *
  894. * @returns {Promise<import('./store/value/istore_value').IStoreValue>}
  895. */
  896. async evaluateExpression(store, exp) {
  897. this.instruction_count += 1;
  898. if (this.instruction_count % Config.suspend_threshold == 0) {
  899. //every Config.suspend_threshold instruction should briefly delay its execution in order to allow the browser to process other things
  900. await Utils.sleep(5);
  901. }
  902. if (this.mode === Modes.ABORT) {
  903. throw LocalizedStrings.getMessage("aborted_execution");
  904. }
  905. if (this.instruction_count >= Config.max_instruction_count) {
  906. throw new Error(
  907. "Número de instruções excedeu o limite definido. Verifique se seu código não possui laços infinitos ou muitas chamadas de funções recursivas."
  908. );
  909. }
  910. if (exp instanceof Expressions.UnaryApp) {
  911. return this.evaluateUnaryApp(store, exp);
  912. } else if (exp instanceof Expressions.InfixApp) {
  913. return this.evaluateInfixApp(store, exp);
  914. } else if (exp instanceof Expressions.ArrayAccess) {
  915. return this.evaluateArrayAccess(store, exp);
  916. } else if (exp instanceof Expressions.VariableLiteral) {
  917. return this.evaluateVariableLiteral(store, exp);
  918. } else if (exp instanceof Expressions.IntLiteral) {
  919. return this.evaluateLiteral(store, exp);
  920. } else if (exp instanceof Expressions.RealLiteral) {
  921. return this.evaluateLiteral(store, exp);
  922. } else if (exp instanceof Expressions.BoolLiteral) {
  923. return this.evaluateLiteral(store, exp);
  924. } else if (exp instanceof Expressions.StringLiteral) {
  925. return this.evaluateLiteral(store, exp);
  926. } else if (exp instanceof Expressions.ArrayLiteral) {
  927. throw new Error(
  928. "Internal Error: The system should not eval an array literal."
  929. );
  930. } else if (exp instanceof Expressions.FunctionCall) {
  931. return this.evaluateFunctionCall(store, exp);
  932. }
  933. return null;
  934. }
  935. async evaluateFunctionCall(store, exp) {
  936. if (exp.isMainCall) {
  937. throw ProcessorErrorFactory.void_in_expression_full(
  938. LanguageDefinedFunction.getMainFunctionName(),
  939. exp.sourceInfo
  940. );
  941. }
  942. const func = this.findFunction(exp.id);
  943. if (Types.VOID.isCompatible(func.returnType)) {
  944. throw ProcessorErrorFactory.void_in_expression_full(
  945. exp.id,
  946. exp.sourceInfo
  947. );
  948. }
  949. if (this.function_call_stack.length >= Config.max_call_stack) {
  950. throw ProcessorErrorFactory.exceeded_recursive_calls(exp.sourceInfo);
  951. }
  952. this.function_call_stack.push(exp.sourceInfo);
  953. const sto = await this.runFunction(func, exp.actualParameters, store);
  954. if (sto.mode !== Modes.RETURN) {
  955. throw new Error(
  956. "!!!Internal error: the function that was called did not have a return command or did not set the store mode properly -> " +
  957. exp.id
  958. );
  959. }
  960. const val = sto.applyStore("$");
  961. sto.destroy();
  962. this.function_call_stack.pop();
  963. return val;
  964. }
  965. /**
  966. *
  967. * @param {Store} store
  968. * @param {Expressions.ArrayLiteral} exp
  969. * @param {ArrayType} type
  970. *
  971. * @returns {Promise<StoreValue[]>}
  972. */
  973. async evaluateArrayLiteral(store, exp, type, lines, columns) {
  974. if (!exp.isVector) {
  975. if (columns == null) {
  976. throw new Error(
  977. "This should never happen: Vector cannot be initialized by a matrix"
  978. );
  979. }
  980. const storeValueMatrix = await this.evaluateMatrix(
  981. store,
  982. exp,
  983. type,
  984. lines,
  985. columns
  986. );
  987. return storeValueMatrix.reduce((prev, next) => prev.concat(next), []);
  988. } else {
  989. if (columns != null) {
  990. throw new Error(
  991. "This should never happen: Matrix cannot be initialized by a vector"
  992. );
  993. }
  994. return this.evaluateVector(store, exp, type, lines);
  995. }
  996. }
  997. /**
  998. * Evalautes a list of literals and expression composing the vector
  999. * @param {Store} store
  1000. * @param {Expressions.ArrayLiteral} exps
  1001. * @param {ArrayType} type
  1002. * @param {number} n_elements
  1003. *
  1004. * @returns {Promise<StoreValue[]>} store object list
  1005. */
  1006. async evaluateVector(store, exps, type, n_elements) {
  1007. const values = exps.value;
  1008. if (n_elements !== values.length) {
  1009. throw ProcessorErrorFactory.invalid_number_elements_vector(
  1010. n_elements,
  1011. exps.toString(),
  1012. values.length,
  1013. exps.sourceInfo
  1014. );
  1015. }
  1016. const actualValues = await Promise.all(
  1017. values.map((exp) => this.evaluateExpression(store, exp))
  1018. );
  1019. return actualValues.map((v, index) => {
  1020. if (!type.canAccept(v.type, 1)) {
  1021. if (
  1022. !Config.enable_type_casting ||
  1023. !Store.canImplicitTypeCast(type.innerType, v.type)
  1024. ) {
  1025. // const stringInfo = v.type.stringInfo();
  1026. // const info = stringInfo[0];
  1027. const exp_str = values[index].toString();
  1028. // TODO - fix error message
  1029. throw ProcessorErrorFactory.invalid_array_literal_type_full(
  1030. exp_str,
  1031. values[index].sourceInfo
  1032. );
  1033. }
  1034. const newValue = Store.doImplicitCasting(type.innerType, v);
  1035. return newValue;
  1036. }
  1037. return v;
  1038. });
  1039. }
  1040. /**
  1041. * Evaluates a list of array literals composing the matrix
  1042. * @param {Store} store
  1043. * @param {Expressions.ArrayLiteral} exps
  1044. * @param {ArrayType} type
  1045. *
  1046. * @returns {Promise<StoreValue[][]>}
  1047. */
  1048. async evaluateMatrix(store, exps, type, lines, columns) {
  1049. const values = exps.value;
  1050. if (values.length !== lines) {
  1051. throw ProcessorErrorFactory.invalid_number_lines_matrix(
  1052. lines,
  1053. exps.toString(),
  1054. values.length,
  1055. exps.sourceInfo
  1056. );
  1057. }
  1058. const vectors = values.map((vector) => {
  1059. const vec_type = new ArrayType(type.innerType, 1);
  1060. return this.evaluateVector(store, vector, vec_type, columns);
  1061. });
  1062. return await Promise.all(vectors);
  1063. }
  1064. /**
  1065. *
  1066. * @param {Store} _
  1067. * @param {import('../ast/expressions/literal').Literal} exp
  1068. *
  1069. * @returns {import('./store/value/istore_value').IStoreValue}
  1070. */
  1071. async evaluateLiteral(_, exp) {
  1072. return new StoreValue(exp.type, exp.value);
  1073. }
  1074. /**
  1075. *
  1076. * @param {Store} store
  1077. * @param {Expressions.VariableLiteral} exp
  1078. *
  1079. * @returns {import('./store/value/istore_value').IStoreValue}
  1080. */
  1081. async evaluateVariableLiteral(store, exp) {
  1082. const val = store.applyStore(exp.id);
  1083. return val;
  1084. }
  1085. /**
  1086. *
  1087. * @param {Store} store
  1088. * @param {Expressions.ArrayAccess} exp
  1089. *
  1090. * @returns {import('./store/value/istore_value').IStoreValue}
  1091. */
  1092. async evaluateArrayAccess(store, exp) {
  1093. const mustBeArray = store.getStoreObject(exp.id);
  1094. if (!(mustBeArray.type instanceof ArrayType)) {
  1095. throw ProcessorErrorFactory.invalid_array_access_full(
  1096. exp.id,
  1097. exp.sourceInfo
  1098. );
  1099. }
  1100. const lineSV = await this.evaluateExpression(store, exp.line);
  1101. if (!Types.INTEGER.isCompatible(lineSV.type)) {
  1102. throw ProcessorErrorFactory.array_dimension_not_int_full(exp.sourceInfo);
  1103. }
  1104. const line = lineSV.get().toNumber();
  1105. const columnSV = await this.evaluateExpression(store, exp.column);
  1106. let column = null;
  1107. if (columnSV !== null) {
  1108. if (!Types.INTEGER.isCompatible(columnSV.type)) {
  1109. throw ProcessorErrorFactory.array_dimension_not_int_full(
  1110. exp.sourceInfo
  1111. );
  1112. }
  1113. column = columnSV.get().toNumber();
  1114. }
  1115. if (line >= mustBeArray.lines) {
  1116. if (mustBeArray.isVector) {
  1117. throw ProcessorErrorFactory.vector_line_outbounds_full(
  1118. exp.id,
  1119. line,
  1120. mustBeArray.lines,
  1121. exp.sourceInfo
  1122. );
  1123. } else {
  1124. throw ProcessorErrorFactory.matrix_line_outbounds_full(
  1125. exp.id,
  1126. line,
  1127. mustBeArray.lines,
  1128. exp.sourceInfo
  1129. );
  1130. }
  1131. } else if (line < 0) {
  1132. throw ProcessorErrorFactory.array_dimension_not_positive_full(
  1133. exp.sourceInfo
  1134. );
  1135. }
  1136. if (column !== null && mustBeArray.columns === 0) {
  1137. throw ProcessorErrorFactory.vector_not_matrix_full(
  1138. exp.id,
  1139. exp.sourceInfo
  1140. );
  1141. }
  1142. if (column !== null) {
  1143. if (column >= mustBeArray.columns) {
  1144. throw ProcessorErrorFactory.matrix_column_outbounds_full(
  1145. exp.id,
  1146. column,
  1147. mustBeArray.columns,
  1148. exp.sourceInfo
  1149. );
  1150. } else if (column < 0) {
  1151. throw ProcessorErrorFactory.array_dimension_not_positive_full(
  1152. exp.sourceInfo
  1153. );
  1154. }
  1155. }
  1156. const result = mustBeArray.getAt(line, column);
  1157. const type = mustBeArray.type.innerType;
  1158. if (Array.isArray(result)) {
  1159. const values = result.map((val, col) => {
  1160. return new StoreValueAddress(
  1161. type,
  1162. val,
  1163. line,
  1164. col,
  1165. mustBeArray.id,
  1166. mustBeArray.readOnly
  1167. );
  1168. });
  1169. return new ArrayStoreValue(
  1170. new ArrayType(type, 1),
  1171. values,
  1172. mustBeArray.columns,
  1173. null,
  1174. mustBeArray.id,
  1175. mustBeArray.readOnly
  1176. );
  1177. } else {
  1178. return new StoreValueAddress(
  1179. type,
  1180. result,
  1181. line,
  1182. column,
  1183. mustBeArray.id,
  1184. mustBeArray.readOnly
  1185. );
  1186. }
  1187. }
  1188. /**
  1189. *
  1190. * @param {Store} store
  1191. * @param {Expressions.UnaryApp} unaryApp
  1192. *
  1193. * @returns {import('./store/value/istore_value').IStoreValue}
  1194. */
  1195. async evaluateUnaryApp(store, unaryApp) {
  1196. const left = await this.evaluateExpression(store, unaryApp.left);
  1197. const resultType = resultTypeAfterUnaryOp(unaryApp.op, left.type);
  1198. if (Types.UNDEFINED.isCompatible(resultType)) {
  1199. const stringInfo = left.type.stringInfo();
  1200. const info = stringInfo[0];
  1201. throw ProcessorErrorFactory.invalid_unary_op_full(
  1202. unaryApp.op,
  1203. info.type,
  1204. info.dim,
  1205. unaryApp.sourceInfo
  1206. );
  1207. }
  1208. switch (unaryApp.op.ord) {
  1209. case Operators.ADD.ord:
  1210. return new StoreValue(resultType, left.get());
  1211. case Operators.SUB.ord:
  1212. return new StoreValue(resultType, left.get().negated());
  1213. case Operators.NOT.ord:
  1214. return new StoreValue(resultType, !left.get());
  1215. default:
  1216. throw new RuntimeError("!!!Critical Invalid UnaryApp " + unaryApp.op);
  1217. }
  1218. }
  1219. /**
  1220. *
  1221. * @param {Store} store
  1222. * @param {Expressions.InfixApp} infixApp
  1223. *
  1224. * @returns {import('./store/value/istore_value').IStoreValue}
  1225. */
  1226. async evaluateInfixApp(store, infixApp) {
  1227. const left = await this.evaluateExpression(store, infixApp.left);
  1228. const right = await this.evaluateExpression(store, infixApp.right);
  1229. let shouldImplicitCast = false;
  1230. let resultType = resultTypeAfterInfixOp(infixApp.op, left.type, right.type);
  1231. if (Types.UNDEFINED.isCompatible(resultType)) {
  1232. if (
  1233. Config.enable_type_casting &&
  1234. Store.canImplicitTypeCast(left.type, right.type)
  1235. ) {
  1236. shouldImplicitCast = true;
  1237. } else {
  1238. const stringInfoLeft = left.type.stringInfo();
  1239. const infoLeft = stringInfoLeft[0];
  1240. const stringInfoRight = right.type.stringInfo();
  1241. const infoRight = stringInfoRight[0];
  1242. throw ProcessorErrorFactory.invalid_infix_op_full(
  1243. infixApp.op,
  1244. infoLeft.type,
  1245. infoLeft.dim,
  1246. infoRight.type,
  1247. infoRight.dim,
  1248. infixApp.sourceInfo
  1249. );
  1250. }
  1251. }
  1252. let result = null;
  1253. switch (infixApp.op.ord) {
  1254. case Operators.ADD.ord: {
  1255. if (Types.STRING.isCompatible(left.type)) {
  1256. const rightStr = convertToString(right.get(), right.type);
  1257. return new StoreValue(resultType, left.get() + rightStr);
  1258. } else if (Types.STRING.isCompatible(right.type)) {
  1259. const leftStr = convertToString(left.get(), left.type);
  1260. return new StoreValue(resultType, leftStr + right.get());
  1261. } else {
  1262. return new StoreValue(resultType, left.get().plus(right.get()));
  1263. }
  1264. }
  1265. case Operators.SUB.ord:
  1266. return new StoreValue(resultType, left.get().minus(right.get()));
  1267. case Operators.MULT.ord: {
  1268. result = left.get().times(right.get());
  1269. return new StoreValue(resultType, result);
  1270. }
  1271. case Operators.DIV.ord: {
  1272. if (right.get() == 0) {
  1273. throw ProcessorErrorFactory.divsion_by_zero_full(
  1274. infixApp.toString(),
  1275. infixApp.sourceInfo
  1276. );
  1277. }
  1278. if (Types.INTEGER.isCompatible(resultType))
  1279. result = left.get().divToInt(right.get());
  1280. else result = left.get().div(right.get());
  1281. return new StoreValue(resultType, result);
  1282. }
  1283. case Operators.MOD.ord: {
  1284. let leftValue = left.get();
  1285. let rightValue = right.get();
  1286. if (shouldImplicitCast) {
  1287. resultType = Types.INTEGER;
  1288. leftValue = leftValue.trunc();
  1289. rightValue = rightValue.trunc();
  1290. }
  1291. result = leftValue.modulo(rightValue);
  1292. return new StoreValue(resultType, result);
  1293. }
  1294. case Operators.GT.ord: {
  1295. let leftValue = left.get();
  1296. let rightValue = right.get();
  1297. if (Types.STRING.isCompatible(left.type)) {
  1298. result = leftValue.length > rightValue.length;
  1299. } else {
  1300. if (shouldImplicitCast) {
  1301. resultType = Types.BOOLEAN;
  1302. leftValue = leftValue.trunc();
  1303. rightValue = rightValue.trunc();
  1304. }
  1305. result = leftValue.gt(rightValue);
  1306. }
  1307. return new StoreValue(resultType, result);
  1308. }
  1309. case Operators.GE.ord: {
  1310. let leftValue = left.get();
  1311. let rightValue = right.get();
  1312. if (Types.STRING.isCompatible(left.type)) {
  1313. result = leftValue.length >= rightValue.length;
  1314. } else {
  1315. if (shouldImplicitCast) {
  1316. resultType = Types.BOOLEAN;
  1317. leftValue = leftValue.trunc();
  1318. rightValue = rightValue.trunc();
  1319. }
  1320. result = leftValue.gte(rightValue);
  1321. }
  1322. return new StoreValue(resultType, result);
  1323. }
  1324. case Operators.LT.ord: {
  1325. let leftValue = left.get();
  1326. let rightValue = right.get();
  1327. if (Types.STRING.isCompatible(left.type)) {
  1328. result = leftValue.length < rightValue.length;
  1329. } else {
  1330. if (shouldImplicitCast) {
  1331. resultType = Types.BOOLEAN;
  1332. leftValue = leftValue.trunc();
  1333. rightValue = rightValue.trunc();
  1334. }
  1335. result = leftValue.lt(rightValue);
  1336. }
  1337. return new StoreValue(resultType, result);
  1338. }
  1339. case Operators.LE.ord: {
  1340. let leftValue = left.get();
  1341. let rightValue = right.get();
  1342. if (Types.STRING.isCompatible(left.type)) {
  1343. result = leftValue.length <= rightValue.length;
  1344. } else {
  1345. if (shouldImplicitCast) {
  1346. resultType = Types.BOOLEAN;
  1347. leftValue = leftValue.trunc();
  1348. rightValue = rightValue.trunc();
  1349. }
  1350. result = leftValue.lte(rightValue);
  1351. }
  1352. return new StoreValue(resultType, result);
  1353. }
  1354. case Operators.EQ.ord: {
  1355. let leftValue = left.get();
  1356. let rightValue = right.get();
  1357. if (
  1358. Types.INTEGER.isCompatible(left.type) ||
  1359. Types.REAL.isCompatible(left.type)
  1360. ) {
  1361. if (shouldImplicitCast) {
  1362. resultType = Types.BOOLEAN;
  1363. leftValue = leftValue.trunc();
  1364. rightValue = rightValue.trunc();
  1365. }
  1366. result = leftValue.eq(rightValue);
  1367. } else {
  1368. result = leftValue === rightValue;
  1369. }
  1370. return new StoreValue(resultType, result);
  1371. }
  1372. case Operators.NEQ.ord: {
  1373. let leftValue = left.get();
  1374. let rightValue = right.get();
  1375. if (
  1376. Types.INTEGER.isCompatible(left.type) ||
  1377. Types.REAL.isCompatible(left.type)
  1378. ) {
  1379. if (shouldImplicitCast) {
  1380. resultType = Types.BOOLEAN;
  1381. leftValue = leftValue.trunc();
  1382. rightValue = rightValue.trunc();
  1383. }
  1384. result = !leftValue.eq(rightValue);
  1385. } else {
  1386. result = leftValue !== rightValue;
  1387. }
  1388. return new StoreValue(resultType, result);
  1389. }
  1390. case Operators.AND.ord:
  1391. return new StoreValue(resultType, left.get() && right.get());
  1392. case Operators.OR.ord:
  1393. return new StoreValue(resultType, left.get() || right.get());
  1394. default:
  1395. throw new RuntimeError("!!!Critical Invalid InfixApp " + infixApp.op);
  1396. }
  1397. }
  1398. }