Browse Source

Rewrite some function from ivprogProcessor.js using async/await pattern

Update .eslintrc.json to include node modules env

Add @babel/runtime and @babel/plugin-trasform-runtime

Implement sleep function to suspend instruction execution in the async/await function
Lucas de Souza 4 years ago
parent
commit
0ec63862df
6 changed files with 214 additions and 209 deletions
  1. 3 0
      .babelrc
  2. 2 1
      .eslintrc.json
  3. 186 205
      js/processor/ivprogProcessor.js
  4. 8 0
      js/util/utils.js
  5. 13 3
      package-lock.json
  6. 2 0
      package.json

+ 3 - 0
.babelrc

@@ -0,0 +1,3 @@
+{
+  "plugins": ["@babel/plugin-transform-runtime"]
+}

+ 2 - 1
.eslintrc.json

@@ -1,7 +1,8 @@
 {
     "env": {
         "browser": true,
-        "es6": true
+        "es6": true,
+        "node": true
     },
     "parser": "@typescript-eslint/parser",
     "plugins": ["@typescript-eslint"],

+ 186 - 205
js/processor/ivprogProcessor.js

@@ -6,7 +6,10 @@ import { Operators } from './../ast/operators';
 import { LanguageDefinedFunction } from './definedFunctions';
 import { resultTypeAfterInfixOp, resultTypeAfterUnaryOp } from './compatibilityTable';
 import * as Commands from './../ast/commands/';
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+import { Command } from './../ast/commands/command'
 import * as Expressions from './../ast/expressions/';
+import * as Utils from './../util/utils';
 import { ArrayType } from './../typeSystem/array_type';
 import { convertToString, toInt } from '../typeSystem/parsers';
 import { Config } from '../util/config';
@@ -85,21 +88,20 @@ export class IVProgProcessor {
     this.mode = Modes.RUN;
   }
 
-  interpretAST () {
+  async interpretAST () {
     this.prepareState();
     Location.clear();
-    return this.initGlobal().then( _ => {
-      const mainFunc = this.findMainFunction();
-      if(mainFunc === null) {
-        return Promise.reject(ProcessorErrorFactory.main_missing())
-      }
-      return this.runFunction(mainFunc, [], this.globalStore);
-    });
+    await this.initGlobal();
+    const mainFunc = this.findMainFunction();
+    if (mainFunc === null) {
+      throw ProcessorErrorFactory.main_missing();
+    }
+    return this.runFunction(mainFunc, [], this.globalStore);
   }
 
-  initGlobal () {
+  async initGlobal () {
     if(!this.checkContext(Context.BASE)) {
-      return Promise.reject(ProcessorErrorFactory.invalid_global_var())
+      return ProcessorErrorFactory.invalid_global_var();
     }
     return this.executeCommands(this.globalStore, this.ast.global);
   }
@@ -127,154 +129,147 @@ export class IVProgProcessor {
     }
   }
 
-  runFunction (func, actualParameters, store) {
+  async runFunction (func, actualParameters, store) {
     const funcName = func.isMain ? IVProgProcessor.MAIN_INTERNAL_ID : func.name;
     const funcStore = new Store(funcName);
     funcStore.extendStore(this.globalStore);
-    return new Promise((resolve, reject) => {
-      const run_lambda = () => {
-        const newFuncStore$ = this.associateParameters(func.formalParameters, actualParameters, store, funcStore);
-        newFuncStore$.then(sto => {
-          this.context.push(Context.FUNCTION);
-          this.stores.push(sto);
-          return this.executeCommands(sto, func.variablesDeclarations)
-            .then(stoWithVars => this.executeCommands(stoWithVars, func.commands)).then(finalSto => {
-              this.stores.pop();
-              this.context.pop();
-              return finalSto;
-            });
-        }).then(resolve)
-        .catch(reject);
-      }
-      run_lambda();
-    });
-
+    await this.associateParameters(func.formalParameters, actualParameters, store, funcStore);
+    this.context.push(Context.FUNCTION);
+    this.stores.push(funcStore);
+    const stoWithVars = await this.executeCommands(funcStore, func.variablesDeclarations);
+    const finalSto = this.executeCommands(stoWithVars, func.commands);
+    this.stores.pop();
+    this.context.pop();
+    return finalSto;
   }
 
-  associateParameters (formal_params, effective_params, caller_store, callee_store) {
+  async associateParameters (formal_params, effective_params, caller_store, callee_store) {
     const funcName = callee_store.name === IVProgProcessor.MAIN_INTERNAL_ID ?
       LanguageDefinedFunction.getMainFunctionName() : callee_store.name;
 
     if (formal_params.length != effective_params.length) {
-      return Promise.reject(ProcessorErrorFactory.invalid_parameters_size(funcName, formal_params.length, effective_params.length))
+      throw ProcessorErrorFactory.invalid_parameters_size(funcName, formal_params.length, effective_params.length);
     }
-    const promises$ = effective_params.map(actual_param => this.evaluateExpression(caller_store, actual_param));
-    return Promise.all(promises$).then(values => {
-      for (let i = 0; i < values.length; i++) {
-        const sto_value = values[i];
-        // console.log(callee_store.name);
-        // console.log(sto_value);
-        const exp = effective_params[i];
-        let shouldTypeCast = false;
-        const formalParameter = formal_params[i];
-        if(!formalParameter.type.isCompatible(sto_value.type)) {
-          if (Config.enable_type_casting && !formalParameter.byRef
-            && Store.canImplicitTypeCast(formalParameter.type, sto_value.type)) {
-              shouldTypeCast =  true;
-          } else {
-            return Promise.reject(ProcessorErrorFactory.invalid_parameter_type(funcName, exp.toString()))
-          }
+    for (let i = 0; i < effective_params.length; i += 1) {
+      const actualParam = effective_params[i];
+      const actualValue = await this.evaluateExpression(caller_store, actualParam);
+      const exp = effective_params[i];
+      let shouldTypeCast = false;
+      const formalParameter = formal_params[i];
+      if(!formalParameter.type.isCompatible(actualValue.type)) {
+        if (Config.enable_type_casting && !formalParameter.byRef
+          && Store.canImplicitTypeCast(formalParameter.type, actualValue.type)) {
+            shouldTypeCast =  true;
+        } else {
+          throw ProcessorErrorFactory.invalid_parameter_type(funcName, exp.toString());
         }
+      }
 
-        if(formalParameter.byRef && !sto_value.inStore()) {
-          return Promise.reject(ProcessorErrorFactory.invalid_ref(funcName, exp.toString()))
-        }
+      if(formalParameter.byRef && !actualValue.inStore()) {
+        throw ProcessorErrorFactory.invalid_ref(funcName, exp.toString());
+      }
 
-        if(formalParameter.byRef) {
-          const realObj = caller_store.getStoreObject(sto_value.id);
-          let ref = null;
-          if(sto_value instanceof ArrayStoreValue) {
-            // it's a vector or matrix...
-            const values = sto_value.get();
-            const array_type = sto_value.type;
-            const addresses = values.map( v => realObj.getLocAddressOf(v.line, v.column));
-            const columns = sto_value.isVector() ? 0 : sto_value.columns;
-            ref = new ArrayStoreValueRef(array_type, values, addresses, sto_value.lines, columns, realObj.id);
-          } else {
-            if(sto_value instanceof StoreValueAddress) {
-              const line = sto_value.line;
-              const column = sto_value.column;
-              ref = new StoreValueRef(sto_value.type, sto_value.get(),
-                realObj.getLocAddressOf(line, column), realObj.id);
-              ref.setReferenceDimension(realObj.type.dimensions);
-            } else {
-              ref = new StoreValueRef(sto_value.type, sto_value.get(), realObj.locAddress, realObj.id);
-            }
-          }
-          callee_store.insertStore(formalParameter.id, ref);
+      if(formalParameter.byRef) {
+        const realObj = caller_store.getStoreObject(actualValue.id);
+        let ref = null;
+        if(actualValue instanceof ArrayStoreValue) {
+          // it's a vector or matrix...
+          const values = actualValue.get();
+          const array_type = actualValue.type;
+          const addresses = values.map( v => realObj.getLocAddressOf(v.line, v.column));
+          const columns = actualValue.isVector() ? 0 : actualValue.columns;
+          ref = new ArrayStoreValueRef(array_type, values, addresses, actualValue.lines, columns, realObj.id);
         } else {
-          let realValue = sto_value;
-          if (shouldTypeCast) {
-            realValue = Store.doImplicitCasting(formalParameter.type, realValue);
+          if(actualValue instanceof StoreValueAddress) {
+            const line = actualValue.line;
+            const column = actualValue.column;
+            ref = new StoreValueRef(actualValue.type, actualValue.get(),
+              realObj.getLocAddressOf(line, column), realObj.id);
+            ref.setReferenceDimension(realObj.type.dimensions);
+          } else {
+            ref = new StoreValueRef(actualValue.type, actualValue.get(), realObj.locAddress, realObj.id);
           }
-          callee_store.insertStore(formalParameter.id, realValue);
         }
+        callee_store.insertStore(formalParameter.id, ref);
+      } else {
+        let realValue = actualValue;
+        if (shouldTypeCast) {
+          realValue = Store.doImplicitCasting(formalParameter.type, realValue);
+        }
+        callee_store.insertStore(formalParameter.id, realValue);
       }
-      return callee_store;
-    });
+    }
+    return callee_store;
   }
 
-  executeCommands (store, cmds) {
+  /**
+   * 
+   * @param {Store} store 
+   * @param {Command[]} cmds 
+   */
+  async executeCommands (store, cmds) {
     // helper to partially apply a function, in this case executeCommand
-    const partial = (fun, cmd) => (sto) => fun(sto, cmd);
-    return cmds.reduce((lastCommand, next) => {
-      const nextCommand = partial(this.executeCommand.bind(this), next);
-      return lastCommand.then(nextCommand);
-    }, Promise.resolve(store));
+    let sto = store;
+    for (let i = 0; i < cmds.length; i += 1) {
+      sto = await this.executeCommand(sto, cmds[i]);
+    }
+    return sto;
   }
 
-  executeCommand (store, cmd) {
+  /**
+   * 
+   * @param {Store} store 
+   * @param {Command} cmd
+   */
+  async executeCommand (store, cmd) {
     this.instruction_count += 1;
-    return new Promise((resolve, reject) => {
-      const command_lambda = () => {
-        if(this.instruction_count >= Config.max_instruction_count) {
-          return reject(ProcessorErrorFactory.exceed_max_instructions());
-        } else if(this.forceKill) {
-          return reject("FORCED_KILL!");
-        } else if (store.mode === Modes.PAUSE) {
-          return resolve(this.executeCommand(store, cmd));
-        } else if(store.mode === Modes.RETURN) {
-          return resolve(store);
-        } else if(this.checkContext(Context.BREAKABLE) && store.mode === Modes.BREAK) {
-          return resolve(store);
-        } else if (this.mode === Modes.ABORT) {
-          return reject(LocalizedStrings.getMessage('aborted_execution'));
-        }
-        if (cmd instanceof Commands.Declaration) {
-          return resolve(this.executeDeclaration(store, cmd));
-        } else if (cmd instanceof Commands.ArrayIndexAssign) {
-          return resolve(this.executeArrayIndexAssign(store, cmd));
-        } else if (cmd instanceof Commands.Assign) {
-          return resolve(this.executeAssign(store, cmd));
-        } else if (cmd instanceof Commands.Break) {
-          return resolve(this.executeBreak(store, cmd));
-        } else if (cmd instanceof Commands.Return) {
-          return resolve(this.executeReturn(store, cmd));
-        } else if (cmd instanceof Commands.IfThenElse) {
-          return resolve(this.executeIfThenElse(store, cmd));
-        } else if (cmd instanceof Commands.RepeatUntil) {
-          return resolve(this.executeRepeatUntil(store, cmd));
-        } else if (cmd instanceof Commands.While) {
-          return resolve(this.executeWhile(store, cmd));
-        } else if (cmd instanceof Commands.For) {
-          return resolve(this.executeFor(store, cmd));
-        } else if (cmd instanceof Commands.Switch) {
-          return resolve(this.executeSwitch(store, cmd));
-        } else if (cmd instanceof Expressions.FunctionCall) {
-          return resolve(this.executeFunctionCall(store, cmd));
-        } else if (cmd instanceof Commands.SysCall) {
-          return resolve(this.executeSysCall(store, cmd));
-        } else {
-          return reject(ProcessorErrorFactory.unknown_command(cmd.sourceInfo))
-        }
-      };
-      if(this.instruction_count % Config.suspend_threshold == 0) {
-        //every 100th command should briefly delay its execution in order to allow the browser to process other things
-        setTimeout(command_lambda, 5);
-      } else {
-        command_lambda();
-      }
-    })
+    if(this.instruction_count % Config.suspend_threshold == 0) {
+      //every Config.suspend_threshold instruction should briefly delay its execution in order to allow the browser to process other things
+      await Utils.sleep(5)
+    }
+
+    // Checks if it must interrupt the execution for some reason
+    if(this.instruction_count >= Config.max_instruction_count) {
+      throw ProcessorErrorFactory.exceed_max_instructions();
+    } else if(this.forceKill) {
+      throw "FORCED_KILL!";
+    } else if (store.mode === Modes.PAUSE) {
+      return this.executeCommand(store, cmd);
+    } else if(store.mode === Modes.RETURN) {
+      return store;
+    } else if (this.checkContext(Context.BREAKABLE) && store.mode === Modes.BREAK) {
+      return store;
+    } else if (this.mode === Modes.ABORT) {
+      throw LocalizedStrings.getMessage('aborted_execution');
+    }
+
+    if (cmd instanceof Commands.Declaration) {
+      return this.executeDeclaration(store, cmd);
+    } else if (cmd instanceof Commands.ArrayIndexAssign) {
+      return this.executeArrayIndexAssign(store, cmd);
+    } else if (cmd instanceof Commands.Assign) {
+      return this.executeAssign(store, cmd);
+    } else if (cmd instanceof Commands.Break) {
+      return this.executeBreak(store, cmd);
+    } else if (cmd instanceof Commands.Return) {
+      return this.executeReturn(store, cmd);
+    } else if (cmd instanceof Commands.IfThenElse) {
+      return this.executeIfThenElse(store, cmd);
+    } else if (cmd instanceof Commands.RepeatUntil) {
+      return this.executeRepeatUntil(store, cmd);
+    } else if (cmd instanceof Commands.While) {
+      return this.executeWhile(store, cmd);
+    } else if (cmd instanceof Commands.For) {
+      return this.executeFor(store, cmd);
+    } else if (cmd instanceof Commands.Switch) {
+      return this.executeSwitch(store, cmd);
+    } else if (cmd instanceof Expressions.FunctionCall) {
+      return this.executeFunctionCall(store, cmd);
+    } else if (cmd instanceof Commands.SysCall) {
+      return this.executeSysCall(store, cmd);
+    } else {
+      throw ProcessorErrorFactory.unknown_command(cmd.sourceInfo);
+    }
   }
 
   executeSysCall (store, cmd) {
@@ -282,29 +277,24 @@ export class IVProgProcessor {
     return func(store, cmd);
   }
 
-  executeFunctionCall (store, cmd) {
+  async executeFunctionCall (store, cmd) {
     let func = null;
     if(cmd.isMainCall) {
       func = this.findMainFunction();
     } else {
       func = this.findFunction(cmd.id);
     }
-    // if(this.function_call_stack.length >= Config.max_call_stack) {
-    //   return Promise.reject(ProcessorErrorFactory.exceeded_recursive_calls(cmd.sourceInfo));
-    // }
     this.function_call_stack.push(cmd.sourceInfo);
-    return this.runFunction(func, cmd.actualParameters, store)
-      .then(sto => {
-        sto.destroy();
-        if(!Types.VOID.isCompatible(func.returnType) && sto.mode !== Modes.RETURN) {
-          const funcName = func.name === IVProgProcessor.MAIN_INTERNAL_ID ?
-            LanguageDefinedFunction.getMainFunctionName() : func.name;
-          return Promise.reject(ProcessorErrorFactory.function_no_return(funcName));
-        } else {
-          this.function_call_stack.pop();
-          return store;
-        }
-      });
+    const sto = await this.runFunction(func, cmd.actualParameters, store);
+    sto.destroy();
+    if(!Types.VOID.isCompatible(func.returnType) && sto.mode !== Modes.RETURN) {
+      const funcName = func.name === IVProgProcessor.MAIN_INTERNAL_ID ?
+        LanguageDefinedFunction.getMainFunctionName() : func.name;
+      throw ProcessorErrorFactory.function_no_return(funcName);
+    } else {
+      this.function_call_stack.pop();
+      return store;
+    }
   }
 
   executeSwitch (store, cmd) {
@@ -732,71 +722,62 @@ export class IVProgProcessor {
     });
   }
 
-  evaluateExpression (store, exp) {
+  async evaluateExpression (store, exp) {
     this.instruction_count += 1;
-    return new Promise((resolve, reject) => {
-      const expression_lambda = () => {
-        if (this.mode === Modes.ABORT) {
-          return reject(LocalizedStrings.getMessage('aborted_execution'));
-        }
-        if(this.instruction_count >= Config.max_instruction_count) {
-          return reject(new Error("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."))
-        }
-        if (exp instanceof Expressions.UnaryApp) {
-          return resolve(this.evaluateUnaryApp(store, exp));
-        } else if (exp instanceof Expressions.InfixApp) {
-          return resolve(this.evaluateInfixApp(store, exp));
-        } else if (exp instanceof Expressions.ArrayAccess) {
-          return resolve(this.evaluateArrayAccess(store, exp));
-        } else if (exp instanceof Expressions.VariableLiteral) {
-          return resolve(this.evaluateVariableLiteral(store, exp));
-        } else if (exp instanceof Expressions.IntLiteral) {
-          return resolve(this.evaluateLiteral(store, exp));
-        } else if (exp instanceof Expressions.RealLiteral) {
-          return resolve(this.evaluateLiteral(store, exp));
-        } else if (exp instanceof Expressions.BoolLiteral) {
-          return resolve(this.evaluateLiteral(store, exp));
-        } else if (exp instanceof Expressions.StringLiteral) {
-          return resolve(this.evaluateLiteral(store, exp));
-        } else if (exp instanceof Expressions.ArrayLiteral) {
-          return reject(new Error("Internal Error: The system should not eval an array literal."))
-        } else if (exp instanceof Expressions.FunctionCall) {
-          return resolve(this.evaluateFunctionCall(store, exp));
-        }
-        return resolve(null);
-      };
-      if(this.instruction_count % Config.suspend_threshold == 0) {
-        //every 100th command should briefly delay its execution in order to allow the browser to process other things
-        setTimeout(expression_lambda, 5);
-      } else {
-        expression_lambda();
-      }
-    });
-
+    if(this.instruction_count % Config.suspend_threshold == 0) {
+      //every Config.suspend_threshold instruction should briefly delay its execution in order to allow the browser to process other things
+      await Utils.sleep(5);
+    }
+    if (this.mode === Modes.ABORT) {
+      throw LocalizedStrings.getMessage('aborted_execution');
+    }
+    if(this.instruction_count >= Config.max_instruction_count) {
+      throw new Error("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.");
+    }
+    if (exp instanceof Expressions.UnaryApp) {
+      return this.evaluateUnaryApp(store, exp);
+    } else if (exp instanceof Expressions.InfixApp) {
+      return this.evaluateInfixApp(store, exp);
+    } else if (exp instanceof Expressions.ArrayAccess) {
+      return this.evaluateArrayAccess(store, exp);
+    } else if (exp instanceof Expressions.VariableLiteral) {
+      return this.evaluateVariableLiteral(store, exp);
+    } else if (exp instanceof Expressions.IntLiteral) {
+      return this.evaluateLiteral(store, exp);
+    } else if (exp instanceof Expressions.RealLiteral) {
+      return this.evaluateLiteral(store, exp);
+    } else if (exp instanceof Expressions.BoolLiteral) {
+      return this.evaluateLiteral(store, exp);
+    } else if (exp instanceof Expressions.StringLiteral) {
+      return this.evaluateLiteral(store, exp);
+    } else if (exp instanceof Expressions.ArrayLiteral) {
+      throw new Error("Internal Error: The system should not eval an array literal.");
+    } else if (exp instanceof Expressions.FunctionCall) {
+      return this.evaluateFunctionCall(store, exp);
+    }
+    return null;
   }
 
-  evaluateFunctionCall (store, exp) {
+  async evaluateFunctionCall (store, exp) {
     if(exp.isMainCall) {
-      return Promise.reject(ProcessorErrorFactory.void_in_expression_full(LanguageDefinedFunction.getMainFunctionName(), exp.sourceInfo));
+      throw ProcessorErrorFactory.void_in_expression_full(LanguageDefinedFunction.getMainFunctionName(), exp.sourceInfo);
     }
     const func = this.findFunction(exp.id);
     if(Types.VOID.isCompatible(func.returnType)) {
-      return Promise.reject(ProcessorErrorFactory.void_in_expression_full(exp.id, exp.sourceInfo));
+      throw ProcessorErrorFactory.void_in_expression_full(exp.id, exp.sourceInfo);
     }
     if(this.function_call_stack.length >= Config.max_call_stack) {
-      return Promise.reject(ProcessorErrorFactory.exceeded_recursive_calls(exp.sourceInfo));
+      throw ProcessorErrorFactory.exceeded_recursive_calls(exp.sourceInfo);
     }
     this.function_call_stack.push(exp.sourceInfo);
-    const $newStore = this.runFunction(func, exp.actualParameters, store);
-    return $newStore.then( sto => {
-      if(sto.mode !== Modes.RETURN) {
-        return Promise.reject(new Error("!!!Internal error: the function that was called did not have a return command or did not set the store mode properly -> "+exp.id));
-      }
-      const val = sto.applyStore('$');
-      sto.destroy();
-      this.function_call_stack.pop();
-      return Promise.resolve(val);
-    });
+    const sto = await this.runFunction(func, exp.actualParameters, store);
+    if(sto.mode !== Modes.RETURN) {
+      throw new Error("!!!Internal error: the function that was called did not have a return command or did not set the store mode properly -> "+exp.id);
+    }
+    const val = sto.applyStore('$');
+    sto.destroy();
+    this.function_call_stack.pop();
+    return val;
   }
 
   /**

+ 8 - 0
js/util/utils.js

@@ -272,3 +272,11 @@ export function openAssessmentDetail (event) {
 export function range (size, startAt = 0) {
   return [...Array(size).keys()].map(i => i + startAt);
 }
+
+/**
+ * 
+ * @param {number} ms 
+ */
+export async function sleep (ms) {
+    return new Promise( (res, _) => setTimeout(res, ms));
+  }

+ 13 - 3
package-lock.json

@@ -748,6 +748,18 @@
         "@babel/helper-plugin-utils": "^7.8.3"
       }
     },
+    "@babel/plugin-transform-runtime": {
+      "version": "7.9.0",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.9.0.tgz",
+      "integrity": "sha512-pUu9VSf3kI1OqbWINQ7MaugnitRss1z533436waNXp+0N3ur3zfut37sXiQMxkuCF4VUjwZucen/quskCh7NHw==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-module-imports": "^7.8.3",
+        "@babel/helper-plugin-utils": "^7.8.3",
+        "resolve": "^1.8.1",
+        "semver": "^5.5.1"
+      }
+    },
     "@babel/plugin-transform-shorthand-properties": {
       "version": "7.8.3",
       "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz",
@@ -890,7 +902,6 @@
       "version": "7.9.2",
       "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.9.2.tgz",
       "integrity": "sha512-NE2DtOdufG7R5vnfQUTehdTfNycfUANEtCa9PssN9O/xmTzP4E08UI797ixaei6hBEVL9BI/PsdJS5x7mWoB9Q==",
-      "dev": true,
       "requires": {
         "regenerator-runtime": "^0.13.4"
       }
@@ -7191,8 +7202,7 @@
     "regenerator-runtime": {
       "version": "0.13.5",
       "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.5.tgz",
-      "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA==",
-      "dev": true
+      "integrity": "sha512-ZS5w8CpKFinUzOwW3c83oPeVXoNsrLsaCoLtJvAClH135j/R77RuymhiSErhm2lKcwSCIpmvIWSbDkIfAqKQlA=="
     },
     "regenerator-transform": {
       "version": "0.14.4",

+ 2 - 0
package.json

@@ -27,6 +27,7 @@
   "homepage": "https://git.lcalion.com/ivprog#readme",
   "devDependencies": {
     "@babel/core": "^7.6.2",
+    "@babel/plugin-transform-runtime": "^7.9.0",
     "@babel/preset-env": "^7.6.2",
     "@typescript-eslint/eslint-plugin": "^2.3.2",
     "@typescript-eslint/parser": "^2.3.2",
@@ -43,6 +44,7 @@
     "webpack-cli": "3.x"
   },
   "dependencies": {
+    "@babel/runtime": "^7.9.2",
     "antlr4": "^4.7.2",
     "codemirror": "^5.49.0",
     "csv-parser": "^2.3.1",