Bläddra i källkod

Refactor SysCall class to receive a function as parameter

-Now language defined functions doesn't need to be defined inside the processor
-Fix a bug with boolean type parser
-Implement the localized boolean value type parser
Lucas de Souza 5 år sedan
förälder
incheckning
a1b9bd34fb
5 ändrade filer med 52 tillägg och 41 borttagningar
  1. 3 3
      js/ast/ivprogParser.js
  2. 13 1
      js/ast/types.js
  3. 30 3
      js/processor/definedFunctions.js
  4. 4 32
      js/processor/ivprogProcessor.js
  5. 2 2
      tests/test43.spec.js

+ 3 - 3
js/ast/ivprogParser.js

@@ -1,7 +1,7 @@
 import { CommonTokenStream, InputStream } from 'antlr4/index';
 import * as Expressions from './expressions/';
 import * as Commands from './commands/';
-import { Types, toInt, toString } from './types';
+import { Types, toInt, toString, toBool } from './types';
 import { convertFromString } from './operators';
 import { SyntaxErrorFactory } from './error/syntaxErrorFactory';
 import { LanguageDefinedFunction } from './../processor/definedFunctions';
@@ -334,7 +334,7 @@ export class IVProgParser {
   }
 
   getBoolLiteral (token) {
-    const val = token.type === this.lexerClass.RK_TRUE ? true : false;
+    const val = toBool(token.text);
     return new Expressions.BoolLiteral(val);
   }
 
@@ -469,7 +469,7 @@ export class IVProgParser {
       switch(token.type) {
         case this.lexerClass.RK_INTEGER:
           return Types.INTEGER;
-        case this.lexerClass.RK_LOGIC:
+        case this.lexerClass.RK_BOOLEAN:
           return Types.BOOLEAN;
         case this.lexerClass.RK_REAL:
           return Types.REAL;

+ 13 - 1
js/ast/types.js

@@ -1,3 +1,5 @@
+import { LanguageService } from "../services/languageService";
+
 export const Types = Object.freeze({
   INTEGER: {value: "int", ord: 0},
   REAL: {value: "real", ord: 1},
@@ -33,5 +35,15 @@ export function toString (str) {
 }
 
 export function toBool (str) {
-  return true;
+  const val = "'" + str + "'";
+  const lexer = LanguageService.getCurrentLexer();
+  const instance = new lexer(null);
+  if (instance.literalNames[lexer.RK_TRUE] === val) {
+    return true;
+  } else if (instance.literalNames[lexer.RK_FALSE] === val) {
+    return false;
+  } else {
+    // TODO: better error message
+    throw new Error(str + "not a valid boolean");
+  }
 }

+ 30 - 3
js/processor/definedFunctions.js

@@ -1,9 +1,15 @@
 import * as Commands from './../ast/commands';
-import {Types} from './../ast/types';
+import {Types, toInt, toString, toBool} from './../ast/types';
 import { LanguageService } from '../services/languageService';
+import { StoreObject } from './store/storeObject';
 
 function createOutputFun () {
-  const block = new Commands.CommandBlock([], [new Commands.SysCall('$write')]);
+  const writeFunction = function (store, _) {
+    const val = store.applyStore('p1');
+    this.output.sendOutput(''+val.value);
+    return Promise.resolve(store);
+  }
+  const block = new Commands.CommandBlock([], [new Commands.SysCall(writeFunction)]);
   const func = new Commands.Function('$write', Types.VOID,
     [new Commands.FormalParameter(Types.ALL, 'p1', 0, false)],
     block);
@@ -11,7 +17,28 @@ function createOutputFun () {
 }
 
 function createInputFun () {
-  const block = new Commands.CommandBlock([],  [new Commands.SysCall('$read')]);
+  const readFunction = function (store, _) {
+    const request = new Promise((resolve, _) => {
+      this.input.requestInput(resolve);
+    });
+    return request.then(text => {
+      const typeToConvert = store.applyStore('p1').type;
+      let stoObj = null;
+      if (typeToConvert === Types.INTEGER) {
+        const val = toInt(text);
+        stoObj = new StoreObject(Types.INTEGER, val);
+      } else if (typeToConvert === Types.REAL) {
+        stoObj = new StoreObject(Types.REAL, parseFloat(text));
+      } else if (typeToConvert === Types.BOOLEAN) {
+        stoObj = new StoreObject(Types.BOOLEAN, toBool(text));
+      } else if (typeToConvert === Types.STRING) {
+        stoObj = new StoreObject(Types.STRING, toString(text));
+      }
+      store.updateStore('p1', stoObj);
+      return Promise.resolve(store);
+    });
+  }
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(readFunction)]);
   const func = new Commands.Function('$read', Types.VOID,
     [new Commands.FormalParameter(Types.ALL, 'p1', 0, true)],
     block);

+ 4 - 32
js/processor/ivprogProcessor.js

@@ -232,41 +232,13 @@ export class IVProgProcessor {
   }
 
   executeSysCall (store, cmd) {
-    if (cmd.id === "$write") {
-      return this.runWriteFunction(store)
-    } else if (cmd.id === "$read") {
-      return this.runReadFunction(store);
+    if (typeof cmd.id === 'function') {
+      return cmd.id.bind(this)(store, cmd);
+    } else {
+      throw new Error("invalid internal function impl.");
     }
   }
 
-  runWriteFunction (store) {
-    const val = store.applyStore('p1');
-    this.output.sendOutput(''+val.value);
-    return Promise.resolve(store);
-  }
-
-  runReadFunction (store) {
-    const request = new Promise((resolve, _) => {
-      this.input.requestInput(resolve);
-    });
-    return request.then(text => {
-      const typeToConvert = store.applyStore('p1').type;
-      let stoObj = null;
-      if (typeToConvert === Types.INTEGER) {
-        const val = toInt(text);
-        stoObj = new StoreObject(Types.INTEGER, val);
-      } else if (typeToConvert === Types.REAL) {
-        stoObj = new StoreObject(Types.REAL, parseFloat(text));
-      } else if (typeToConvert === Types.BOOLEAN) {
-        stoObj = new StoreObject(Types.BOOLEAN, true);
-      } else if (typeToConvert === Types.STRING) {
-        stoObj = new StoreObject(Types.STRING, text);
-      }
-      store.updateStore('p1', stoObj);
-      return Promise.resolve(store);
-    });
-  }
-
   executeFunctionCall (store, cmd) {
     return new Promise((resolve, reject) => {
       const func = this.findFunction(cmd.id);

+ 2 - 2
tests/test43.spec.js

@@ -8,8 +8,8 @@ describe('The sum of a real and a integer', function () {
   const code = `programa {
 
     funcao inicio() {
-      real a;
-      leia(a);
+      real a
+      leia(a)
       a = a + 0xff
     }
   }`;