소스 검색

Fix StoreObjectRef losing access to the referenced variable

-Include read test case
-Implement language defined function parsing
-Include a proxy in the commands folder to the FunctionCall expression
Lucas de Souza 5 년 전
부모
커밋
b19a470bd6
6개의 변경된 파일89개의 추가작업 그리고 21개의 파일을 삭제
  1. 3 1
      js/ast/commands/index.js
  2. 24 4
      js/ast/ivprogParser.js
  3. 22 9
      js/processor/ivprogProcessor.js
  4. 4 0
      js/processor/store/store.js
  5. 7 7
      js/processor/store/storeObjectRef.js
  6. 29 0
      tests/test37.spec.js

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

@@ -13,6 +13,7 @@ import { Switch } from './switch';
 import { Case } from './case';
 import { SysCall } from './sysCall';
 import { FormalParameter } from './formalParameter';
+import { FunctionCall } from './../expressions/functionCall'; //Proxy to expression since they do exatcly the same thing
 
 export {
   Break,
@@ -29,5 +30,6 @@ export {
   Switch,
   Case,
   SysCall,
-  FormalParameter
+  FormalParameter,
+  FunctionCall
 };

+ 24 - 4
js/ast/ivprogParser.js

@@ -4,6 +4,7 @@ import * as Commands from './commands/';
 import { Types, toInt, toString } from './types';
 import { convertFromString } from './operators';
 import { SyntaxError } from './SyntaxError';
+import { NAMES } from './../processor/definedFunctions';
 
 export class IVProgParser {
 
@@ -700,10 +701,10 @@ export class IVProgParser {
       this.pos++;
       return (new Commands.Assign(id, exp));
     } else if (equalOrParenthesis.type === this.lexerClass.OPEN_PARENTHESIS) {
-      const actualParameters = this.parseActualParameters();
+      const funcCall = this.parseFunctionCallCommand(id);
       this.checkEOS();
       this.pos++;
-      return (new Expressions.FunctionCall(id, actualParameters));
+      return funcCall;
     } else {
       throw SyntaxError.createError("= or (", equalOrParenthesis);
     }
@@ -909,14 +910,33 @@ export class IVProgParser {
       return new Expressions.ArrayAccess(id, firstIndex, secondIndex);
 
     } else if (this.checkOpenParenthesis(true)) {
-      const actualParameters = this.parseActualParameters();
-      return new Expressions.FunctionCall(id, actualParameters);
+      return this.parseFunctionCallExpression(id);
     } else {
       this.pos = last;
       return new Expressions.VariableLiteral(id);
     }
   }
 
+  getFunctionName (id) {
+    if (id === this.lexerClass.READ_FUNCTION_NAME) {
+      return NAMES.READ;
+    } else if (id === this.lexerClass.WRITE_FUNCTION_NAME) {
+      return NAMES.WRITE;
+    } else {
+      return id;
+    }
+  }
+
+  parseFunctionCallExpression (id) {
+    const actualParameters = this.parseActualParameters();
+    const funcName = this.getFunctionName(id);
+    return new Expressions.FunctionCall(funcName, actualParameters);
+  }
+
+  parseFunctionCallCommand (id) {
+    return this.parseFunctionCallExpression(id);
+  }
+
   parseParenthesisExp () {
     this.checkOpenParenthesis();
     this.pos++;

+ 22 - 9
js/processor/ivprogProcessor.js

@@ -6,7 +6,7 @@ import { Modes } from './modes';
 import { Context } from './context';
 import { Types, toInt } from './../ast/types';
 import { Operators } from './../ast/operators';
-import { NAMES } from './definedFunctions';
+import { NAMES, LanguageDefinedFunction } from './definedFunctions';
 import { canApplyInfixOp, canApplyUnaryOp } from './compatibilityTable';
 import * as Commands from './../ast/commands/';
 import * as Expressions from './../ast/expressions/';
@@ -68,12 +68,20 @@ export class IVProgProcessor {
   }
 
   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.`);
+    if(name.match(/^\$.+$/)) {
+      const fun = LanguageDefinedFunction[name];
+      if(!!!fun) {
+        throw new Error("!!!Internal Error. Language defined function not implemented -> " + name + "!!!");
+      }
+      return fun;
+    } else {
+      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;
     }
-    return val;
   }
 
   runFunction (func, actualParameters, store) {
@@ -162,6 +170,8 @@ export class IVProgProcessor {
 
               if(formalParameter.byRef) {
                 const ref = new StoreObjectRef(stoObj.id, callerStore);
+                console.log('it\'s a ref...');
+                console.log(ref);
                 calleeStore.insertStore(formalParameter.id, ref);
               } else {
                 calleeStore.insertStore(formalParameter.id, stoObj);
@@ -271,9 +281,12 @@ export class IVProgProcessor {
   }
 
   executeFunctionCall (store, cmd) {
-    const func = this.findFunction(cmd.id);
-    this.runFunction(func, cmd.actualParameters, store);
-    return Promise.resolve(store);
+    return new Promise((resolve, reject) => {
+      const func = this.findFunction(cmd.id);
+      this.runFunction(func, cmd.actualParameters, store)
+        .then(_ => resolve(store))
+        .catch(err => reject(err));
+    }); 
   }
 
   executeSwitch (store, cmd) {

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

@@ -57,6 +57,10 @@ export class Store {
     }
   }
 
+  //In case of future use of ref, it needs to have a special function to update the storeRefObject
+  // and no the StoreObject refferenced by it
+  // updateStoreRef(id, stoObjAddress) {...}
+
   insertStore (id, stoObj) {
     if (this.store[id]) {
       // TODO: better error message

+ 7 - 7
js/processor/store/storeObjectRef.js

@@ -2,9 +2,9 @@ import { StoreObject } from './storeObject';
 
 export class StoreObjectRef extends StoreObject {
 
-  constructor (id, store) {
+  constructor (refID, store) {
     super(null, null, false);
-    this.setID(id);
+    this.refID = refID;
     this.store = store;
   }
 
@@ -13,22 +13,22 @@ export class StoreObjectRef extends StoreObject {
   }
 
   get type () {
-    return this.store.applyStore(this.id).type;
+    return this.store.applyStore(this.refID).type;
   }
 
   get value () {
-    return this.store.applyStore(this.id).value;
+    return this.store.applyStore(this.refID).value;
   }
 
   getRefObj () {
-    return this.store.applyStore(this.id);
+    return this.store.applyStore(this.refID);
   }
 
   updateRef (stoObj) {
-    this.store.updateStore(this.id, stoObj);
+    this.store.updateStore(this.refID, stoObj);
   }
 
   isCompatible (another) {
-    return this.store.applyStore(this.id).isCompatible(another);
+    return this.store.applyStore(this.refID).isCompatible(another);
   }
 }

+ 29 - 0
tests/test37.spec.js

@@ -0,0 +1,29 @@
+import Lexers from './../grammar/';
+import { IVProgParser } from './../js/ast/ivprogParser';
+import { IVProgProcessor} from './../js/processor/ivprogProcessor'
+import { InputTest } from './../js/util/inputTest';
+
+describe('The read function', function () {
+
+  const code = `programa {
+
+    funcao inicio() {
+      inteiro a;
+      leia(a);
+    }
+  }`;
+
+  const input = new InputTest(['0xff']);
+
+  const lexer = Lexers['pt_br'];
+
+  it(`should read data from the input and convert it to the appropriate type`, function (done) {
+    const parser = new IVProgParser(code, lexer);
+    const exec = new IVProgProcessor(parser.parseTree());
+    exec.registerInput(input);
+    exec.interpretAST().then(sto => {
+      expect(sto.applyStore('a').value).toEqual(255);
+      done();
+    }).catch( err => done(err));
+  });
+});