Bladeren bron

Revert "Merge branch 'switchBug' of igorfelix/ivprog into master"

This reverts commit 8b2a3d4b995bebca99f0b762d81c78ed7974eac6, reversing
changes made to 3bd4a2f19a58593e948fc7e755ae1ad1601b11ef.
Lucas de Souza 5 jaren geleden
bovenliggende
commit
ea55924253

+ 2 - 2
js/ast/commands/arrayDeclaration.js

@@ -1,9 +1,9 @@
 import { Declaration } from './declaration';
-import {Types} from './../types';
+
 export class ArrayDeclaration extends Declaration {
 
   constructor (id, subtype, lines, columns, initial, isConst)   {
-    super(id, Types.ARRAY, initial, isConst);
+    super(id, 'array', initial, isConst);
     this.subtype = subtype;
     this.lines = lines;
     this.columns = columns;

+ 2 - 2
js/ast/commands/doWhile.js

@@ -2,8 +2,8 @@ import { While } from './while';
 
 export class DoWhile extends While {
 
-  constructor(expression, commandBlock) {
-    super(expression, commandBlock);
+  constructor(condition, commandBlock) {
+    super(condition, commandBlock);
   }
 
   get testFirst () {

+ 2 - 2
js/ast/commands/for.js

@@ -1,6 +1,6 @@
 export class For {
-  constructor (assignment, condition, increment, commandBlock) {
-    this.assignment = assignment;
+  constructor (attribution, condition, increment, commandBlock) {
+    this.attribution = attribution;
     this.condition = condition;
     this.increment = increment;
     this.commandBlock = commandBlock;

+ 1 - 4
js/ast/commands/index.js

@@ -11,8 +11,6 @@ import { CommandBlock } from './commandBlock';
 import { DoWhile } from './doWhile';
 import { Switch } from './switch';
 import { Case } from './case';
-// A Proxy to the expression which do what is required. No need to write a new one
-import { FunctionCall } from './../expressions/functionCall';
 
 export {
   Break,
@@ -27,6 +25,5 @@ export {
   CommandBlock,
   DoWhile,
   Switch,
-  Case,
-  FunctionCall
+  Case
 };

+ 1 - 2
js/ast/commands/switch.js

@@ -1,7 +1,6 @@
 export class Switch {
   
-  constructor (expression, cases) {
-    this.expression = expression;
+  constructor (cases) {
     this.cases = cases;
   }
 }

+ 2 - 2
js/ast/ivprogParser.js

@@ -587,7 +587,7 @@ export class IVProgParser {
     this.consumeNewLines();
 
     this.popScope();
-    return new Commands.Switch(exp, casesList);
+    return new Commands.Switch(casesList);
   }
 
   parseDoWhile () {
@@ -717,7 +717,7 @@ export class IVProgParser {
       const actualParameters = this.parseActualParameters();
       this.checkEOS();
       this.pos++;
-      return (new Commands.FunctionCall(id, actualParameters));
+      return (new Expressions.FunctionCall(id, actualParameters));
     } else {
       throw SyntaxError.createError("= or (", equalOrParenthesis);
     }

+ 1 - 2
js/ast/types.js

@@ -3,6 +3,5 @@ export const Types = Object.freeze({
   REAL: Symbol("real"),
   STRING: Symbol("string"),
   BOOLEAN: Symbol("bool"),
-  VOID: Symbol("void"),
-  ARRAY: Symbol("array")
+  VOID: Symbol("void")
 });

+ 0 - 7
js/processor/context.js

@@ -1,7 +0,0 @@
-export const Context = Object.freeze({
-  BASE: Symbol("context:base");
-  FUNCTION: Symbol("context:function"),
-  BREAKABLE: Symbol("context:breakable"),
-  INPUT: Symbol("context:input"),
-  OUTPUT: Symbol("context:output")
-});

+ 0 - 365
js/processor/ivprogProcessor.js

@@ -1,365 +0,0 @@
-import { Store } from './store/store';
-import { StoreObject } from './store/storeObject';
-import { StoreObjectArray } from './store/storeObjectArray';
-import { Modes } from './mode';
-import { Context } from './context';
-import { Types } from './../ast/types';
-import * as Commands from './../ast/commands/';
-import * as Expressions from './../ast/expressions/';
-
-export class IVProgProcessor {
-
-  constructor(ast) {
-    this.ast = ast;
-    this.globalStore = new Store();
-    this.stores = [this.globalStore];
-    this.context = [Context.BASE];
-    this.input = null;
-    this.output = null;
-  }
-
-  registerInput (input) {
-    this.input = input;
-  }
-
-  registerOutput (output) {
-    this.output = output;
-  }
-
-  checkContext(context) {
-    return this.context[this.context.length] === context;
-  }
-
-  ignoreSwitchCases (store) {
-    if (store.mode === Modes.RETURN) {
-      return true;
-    } else if (store.mode === Modes.BREAK) {
-      return true;
-    } else {
-      return false;
-    }
-  }
-
-  interpretAST () {
-    this.initGlobal();
-    const mainFunc = this.findMainFunction();
-    if(mainFunc === null) {
-      // TODO: Better error message
-      throw new Error("Missing main funciton.");
-    }
-    return this.runFunction(mainFunc, [], this.globalStore);
-  }
-
-  initGlobal () {
-    if(!this.checkContext(Context.BASE)) {
-      throw new Error("!!!CRITICAL: Invalid call to initGlobal outside BASE context!!!");
-    }
-    this.ast.global.forEach(decl => {
-      this.executeCommand(this.globalStore, decl).then(v => this.globalStore = v);
-    });
-  }
-
-  findMainFunction () {
-    return this.ast.functions.find(v => v.isMain);
-  }
-
-  findFunction (name) {
-    const val = this.ast.functions.find( v => v.name === name);
-    if (!!!val) {
-      // TODO: better error message;
-      throw new Error(`Function ${name} is not defined.`);
-    }
-    return val;
-  }
-
-  runFunction (func, actualParameters, store) {
-    let funcStore = new Store();
-    funcStore.extendStore(this.globalStore);
-    const returnStoreObject = new StoreObject(func.returnType, null);
-    const funcName = func.isMain ? 'main' : func.name;
-    const funcNameStoreObject = new StoreObject(Types.STRING, funcName, true);
-    funcStore.insertStore('$', returnStoreObject);
-    funcStore.insertStore('$name', funcNameStoreObject);
-    funcStore = this.associateParameters(func.formalParameters, actualParameters, store, funcStore);
-    this.context.push(Context.FUNCTION);
-    this.stores.push(funcStore);
-    const result = this.executeCommands(funcStore, func.commands);
-    this.stores.pop();
-    this.context.pop();
-    return result;
-  }
-
-  associateParameters (formalList, actualList, callerStore, calleeStore) {
-    if (formalList.length != actualList.length) {
-      // TODO: Better error message
-      throw new Error("Numbers of parameters doesn't match");
-    }
-    formalList.forEach((v, i) => {
-      const val = this.evaluateExpression(callerStore, actualList[i]);
-      switch (v.dimensions) {
-        case 1: {
-          if (val.lines > 0 && val.columns === null) {
-            calleeStore.insertStore(v.id, val);
-          } else {
-            // TODO: Better error message
-            throw new Error(`Parameter ${v.id} is not compatible with the value given.`);
-          }
-          break;
-        }
-        case 2: {
-          if (val.lines > 0 && val.columns > 0) {
-            calleeStore.insertStore(v.id, val);
-          } else {
-            // TODO: Better error message
-            throw new Error(`Parameter ${v.id} is not compatible with the value given.`);
-          }
-          break;
-        }
-        case 0: {
-          if (val.type !== v.type) {
-            // TODO: Better error message
-            throw new Error(`Parameter ${v.id} is not compatible with ${val.type}.`);
-          } else {
-            calleeStore.insertStore(v.id, val);
-          }
-        }
-      }
-    });
-    return calleeStore;
-  }
-
-  executeCommands (store, cmds) {
-    return cmds.reduce((promise, cmd) => promise.then( sto => {
-      while (sto.mode === Modes.PAUSE) {
-        continue;
-      }
-      if(sto.mode === Modes.RETURN) {
-        return Promise.resolve(sto);
-      } else if (this.checkContext(Context.BREAKABLE && 
-        sto.mode === Modes.BREAK)) {
-          return Promise.resolve(sto);
-      }
-      return this.executeCommand(sto, cmd);
-    }), Promise.resolve(store));
-  }
-
-  executeCommand (store, cmd) {
-
-    while (store.mode === Modes.PAUSE) {
-      continue;
-    }
-
-    if(store.mode === Modes.RETURN) {
-      return Promise.resolve(store);
-    } else if(this.checkContext(Context.BREAKABLE) && store.mode === Modes.BREAK) {
-      return Promise.resolve(store);
-    }
-
-    if (cmd instanceof Commands.Declaration) {
-      return this.executeDeclaration(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.While) {
-      return this.executeWhile(store, cmd);
-    } else if (cmd instanceof Commands.DoWhile) {
-      return this.executeDoWhile(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 Commands.FunctionCall) {
-      return this.executeFunctionCall(store, cmd);
-    } else {
-      throw new Error("!!!CRITICAL A unknown command was found!!!\n" + cmd);
-    }
-  }
-
-  executeFunctionCall (store, cmd) {
-    const func = this.findFunction(cmd.id);
-    this.runFunction(func, cmd.actualParameters, store);
-    return Promise.resolve(store);
-  }
-
-  executeSwitch (store, cmd) {
-    const auxCaseFun = (promise, switchExp, aCase) => {
-      return promise.then( result => {
-        const sto = result.sto;
-        if (this.ignoreSwitchCases(sto)) {
-          return Promise.resolve(result);
-        } else if (result.wasTrue || aCase.isDefault) {
-          const newSto = this.executeCommand(result.sto,aCase.commands);
-          return Promise.resolve({wasTrue: true, sto: newSto});
-        } else {
-          const value = this.evaluateExpression(sto,
-            new Expressions.InfixApp('==', switchExp, aCase.expression));
-          if (value.value) {
-            const newSto = this.executeCommand(result.sto,aCase.commands);
-            return Promise.resolve({wasTrue: true, sto: newSto});
-          } else {
-            return Promise.resolve({wasTrue: false, sto: newSto});
-          }
-        }
-      });
-    }
-
-    try {
-      this.context.push(Context.BREAKABLE);
-      let breakLoop = false;
-      const case0 = cmd.cases[0];
-      let result = auxCaseFun(Promise.resolve({wasTrue: false, sto: store}),
-          cmd.expression,
-          case0);
-      for (let index = 1; index < cmd.cases.length && !breakLoop; index++) {
-        const aCase = cmd.cases[index];
-        result = auxCaseFun(result, cmd.expression, aCase);
-        result.then( r => breakLoop = this.ignoreSwitchCases(r.sto));
-      }
-      this.context.pop();
-      return result.then(r => r.sto);
-    } catch (error) {
-      return Promise.reject(error);
-    }
-  }
-
-  executeFor (store, cmd) {
-    try {
-      //BEGIN for -> while rewrite
-      const initCmd = cmd.assignment;
-      const condition = cmd.condition;
-      const increment = cmd.increment;
-      const whileBlock = new Commands.CommandBlock([],
-        cmd.commands.concat(increment));
-      const forAsWhile = new Commands.While(condition, whileBlock);
-      //END for -> while rewrite
-      const newCmdList = [initCmd,forAsWhile];
-      return Promise.resolve(this.executeCommands(store, newCmdList));
-    } catch (error) {
-      return Promise.reject(error);
-    }
-  }
-
-  executeDoWhile (store, cmd) {
-    try {
-      this.context.push(Context.BREAKABLE);
-      const newStore = this.executeCommands(store, cmd.commands);
-      const value = this.evaluateExpression(newStore, cmd.expression);
-      if (value.type !== Types.BOOLEAN) {
-        // TODO: Better error message -- Inform line and column from token!!!!
-        // THIS IF SHOULD BE IN A SEMANTIC ANALYSER
-        return Promise.reject(new Error(`DoWhile expression must be of type boolean`));
-      }
-      if (value.value) {
-        return Promise.resolve(this.executeCommand(newStore, cmd));
-      } else {
-        return Promise.resolve(newStore);
-      }
-    } catch (error) {
-      return Promise.reject(error)
-    }
-  }
-
-  executeWhile (store, cmd) {
-    try {
-      this.context.push(Context.BREAKABLE);
-      const value = this.evaluateExpression(store, cmd.expression);
-      if(value.type === Types.BOOLEAN) {
-        if(value.value) {
-          const newStore = this.executeCommands(store, cmd.commands);
-          this.context.pop();
-          return Promise.resolve(this.executeCommand(newStore, cmd));
-        } else {
-          this.context.pop();
-          return Promise.resolve(store);
-        }
-      } else {
-        // TODO: Better error message -- Inform line and column from token!!!!
-        // THIS IF SHOULD BE IN A SEMANTIC ANALYSER
-        return Promise.reject(new Error(`Loop condition must be of type boolean`));
-      }
-    } catch (error) {
-      return Promise.reject(error);
-    }
-  }
-
-  executeIfThenElse (store, cmd) {
-    try {
-      const value = this.evaluateExpression(cmd.condition);
-      if(value.type === Types.BOOLEAN) {
-        if(value.value) {
-          return Promise.resolve(this.executeCommand(store, cmd.ifTrue));
-        } else {
-          return Promise.resolve(this.executeCommand(store, cmd.ifFalse));
-        }
-      } else {
-        // TODO: Better error message -- Inform line and column from token!!!!
-        // THIS IF SHOULD BE IN A SEMANTIC ANALYSER
-        return Promise.reject(new Error(`If expression must be of type boolean`));
-      }
-    } catch (error) {
-      return Promise.reject(error);
-    }
-  }
-
-  executeReturn (store, cmd) {
-    try {
-      const funcType = store.applyStore('$');
-      const value = this.evaluateExpression(store, cmd.expression);
-      const funcName = store.applyStore('$name');
-      if (funcType.type !== value.type) {
-        // TODO: Better error message -- Inform line and column from token!!!!
-        // THIS IF SHOULD BE IN A SEMANTIC ANALYSER
-        return Promise.reject(new Error(`Function ${funcName.value} must return ${funcType.type} instead of ${value.type}.`));
-      } else {
-        store.updateStore('$', value);
-        store.mode = Modes.RETURN;
-        return Promise.resolve(store);
-      }
-    } catch (error) {
-      return Promise.reject(error);
-    }
-  }
-
-  executeBreak (store, cmd) {
-    if(this.checkContext(Context.BREAKABLE)) {
-      store.mode = Modes.BREAK;
-      return Promise.resolve(store);
-    } else {
-      return Promise.reject(new Error("!!!CRITIAL: Break command outside Loop/Switch scope!!!"));
-    }
-  }
-
-  executeAssign (store, cmd) {
-    try {
-      const value = this.evaluateExpression(store, cmd.expression);
-      store.updateStore(cmd.id, value);
-      return Promise.resolve(store);
-    } catch (error) {
-      return Promise.reject(error);
-    }
-  }
-
-  executeDeclaration (store, cmd) {
-    try {
-      const value = this.evaluateExpression(store, cmd.initial);
-      if(cmd instanceof Commands.ArrayDeclaration) {
-        const temp = new StoreObjectArray(decl.subtype, decl.lines, decl.columns, null, decl.isConst);
-        store.insertStore(decl.id, temp);
-        store.updateStore(decl.id, value);
-      } else {
-        const temp = new StoreObject(decl.type, null, decl.isConst);
-        store.insertStore(decl.id, temp);
-        store.updateStore(decl.id, value);   
-      }
-      return Promise.resolve(store);
-    } catch (e) {
-      return Promise.reject(e);
-    }
-  }
-
-}

+ 0 - 6
js/processor/mode.js

@@ -1,6 +0,0 @@
-export const Modes = Object.freeze({
-  RUN: Symbol("mode:run"),
-  RETURN: Symbol("mode:return"),
-  PAUSE: Symbol("mode:pause"),
-  BREAK: Symbol("mode:break")
-});

+ 0 - 70
js/processor/store/store.js

@@ -1,70 +0,0 @@
-import { Modes } from './../mode';
-export class Store {
-
-  constructor () {
-    this.store = {};
-    this.nextStore = null;
-    this.mode = Modes.RUN;
-  }
-
-  cloneStore () {
-    return Object.assign(new Store(), this);
-  }
-
-  extendStore (nextStore) {
-   this.nextStore = nextStore;
-  }
-
-  applyStore (id) {
-    if(!this.store[id]) {
-      if (this.nextStore === null) {
-        // TODO: better error message
-        throw new Error(`Variable ${id} is not defined.`);
-      } else {
-        return this.nextStore.applyStore(id);
-      }
-    }
-    return this.store[id];
-  }
-
-  isDefined (id) {
-    if(!this.store[id]) {
-      if (this.nextStore === null) {
-        return false;
-      } else {
-        return this.nextStore.isDefined(id);
-      }
-    }
-    return true;
-  }
-
-  updateStore (id, storeObj) {
-    if(!this.store[id]) {
-      if (this.nextStore !== null) {
-        this.nextStore.updateStore(id, storeObj);
-      } else {
-        throw new Error(`Variable ${id} is not defined.`);  
-      }
-    } else {
-      const old = this.applyStore(id);
-      if (!old.isCompatible(storeObj)) {
-        // TODO: better error message
-        throw new Error(`${storeObj.value} is not compatible with ${id} of type ${old.type}`);
-      } else if (old.readOnly) {
-        // TODO: better error message
-        throw new Error(`Cannot change value, ${id} is read-only`);
-      } else {
-        this.store[id] = Object.freeze(storeObj);
-      }
-    }
-  }
-
-  insertStore (id, storeObj) {
-    if(this.store(id)) {
-      // TODO: Better error message
-      throw new Error(`Variable ${id} is already defined.`);
-    } else {
-      this.store[id] = Object.freeze(storeObj)
-    }
-  }
-}

+ 0 - 14
js/processor/store/storeObject.js

@@ -1,14 +0,0 @@
-export class StoreObject {
-
-  constructor(type, value, readOnly = false) {
-    this.type = type;
-    this.value = value;
-    this.readOnly = readOnly;
-  }
-
-  isCompatible (another) {
-    if (another instanceof StoreObject)
-     return this.type === another.type;
-    return false;
-  }
-}

+ 0 - 23
js/processor/store/storeObjectArray.js

@@ -1,23 +0,0 @@
-import { StoreObject } from './storeObject';
-import { Types } from './../../ast/types';
-
-export class StoreObjectArray extends StoreObject {
-
-  constructor (subtype, lines, columns, value, readonly) {
-    super(Types.ARRAY, value, readonly);
-    this.subtype = subtype;
-    this.lines = lines;
-    this.columns = columns;
-  }
-
-  isCompatible (another) {
-    if (another instanceof StoreObjectArray) {
-      if (this.subtype === another.subtype &&
-        this.lines === another.lines &&
-        this.columns === another.columns) {
-        return super.isCompatible(another);
-      }
-    }
-    return false;
-  }
-}