Ver Fonte

Merge branch 'langDefFuns' of igorfelix/ivprog into master

Lucas de Souza há 6 anos atrás
pai
commit
737042e460
48 ficheiros alterados com 1074 adições e 120 exclusões
  1. 3 1
      grammar/en/ivprog.g4
  2. 27 1
      grammar/en/langFunctions.js
  3. 10 0
      grammar/en/langLibs.js
  4. 3 1
      grammar/es/ivprog.g4
  5. 27 1
      grammar/es/langFunctions.js
  6. 10 0
      grammar/es/langLibs.js
  7. 6 3
      grammar/index.js
  8. 3 1
      grammar/pt/ivprog.g4
  9. 27 1
      grammar/pt/langFunctions.js
  10. 10 0
      grammar/pt/langLibs.js
  11. 1 0
      i18n/pt/error.json
  12. 5 1
      js/ast/error/syntaxErrorFactory.js
  13. 34 10
      js/ast/ivprogParser.js
  14. 6 7
      js/ast/types.js
  15. 3 0
      js/jquery.json-editor.min.js
  16. 92 50
      js/processor/definedFunctions.js
  17. 36 26
      js/processor/ivprogProcessor.js
  18. 52 0
      js/processor/lib/arrays.js
  19. 55 0
      js/processor/lib/io.js
  20. 191 0
      js/processor/lib/lang.js
  21. 188 0
      js/processor/lib/math.js
  22. 88 0
      js/processor/lib/strings.js
  23. 2 2
      js/processor/semantic/semanticAnalyser.js
  24. 1 0
      js/processor/store/store.js
  25. 10 0
      js/processor/store/storeObject.js
  26. 8 0
      js/services/languageService.js
  27. 5 0
      package-lock.json
  28. 1 0
      package.json
  29. 1 1
      tests/test19.spec.js
  30. 3 1
      tests/test20.spec.js
  31. 1 1
      tests/test21.spec.js
  32. 1 1
      tests/test24.spec.js
  33. 1 1
      tests/test25.spec.js
  34. 1 1
      tests/test27.spec.js
  35. 1 1
      tests/test28.spec.js
  36. 1 1
      tests/test29.spec.js
  37. 1 1
      tests/test30.spec.js
  38. 1 1
      tests/test31.spec.js
  39. 1 1
      tests/test33.spec.js
  40. 1 1
      tests/test34.spec.js
  41. 1 1
      tests/test35.spec.js
  42. 1 1
      tests/test37.spec.js
  43. 1 1
      tests/test43.spec.js
  44. 32 0
      tests/test53.spec.js
  45. 32 0
      tests/test54.spec.js
  46. 25 0
      tests/test55.spec.js
  47. 32 0
      tests/test56.spec.js
  48. 32 0
      tests/test57.spec.js

+ 3 - 1
grammar/en/ivprog.g4

@@ -164,7 +164,9 @@ ID
   : [a-zA-Z_] [a-zA-Z0-9_]*
   ;
 
-// ID_BIBLIOTECA     : ID '.' ID;
+LIB_ID
+  : ID '.' ID
+  ;
 
 INTEGER
   : [0-9]+

+ 27 - 1
grammar/en/langFunctions.js

@@ -3,5 +3,31 @@
 export default {
   main_function: "start",
   $read: "read",
-  $write: "write"
+  $write: "write",
+  $numElements: "numero_elementos",
+  $matrixLines: "matriz_linhas",
+  $matrixColumns: "matriz_colunas",
+  $substring: "subcadeia",
+  $length: "comprimento",
+  $uppercase: "caixa_alta",
+  $lowercase: "caixa_baixa",
+  $charAt: "char_at",
+  $isReal: "e_real",
+  $isInt: "e_inteiro",
+  $isBool: "e_logico",
+  $castReal: "como_real",
+  $castInt: "como_inteiro",
+  $castBool: "como_logico",
+  $castString: "como_cadeia",
+  $sin: "sen",
+  $cos: "cos",
+  $tan: "tan",
+  $sqrt: "raiz_quadrada",
+  $pow: "pot",
+  $log: "log",
+  $abs: "modulo",
+  $negate: "trocar_sinal",
+  $invert: "inverter_valor",
+  $max: "maximo",
+  $min: "minimo"
 }

+ 10 - 0
grammar/en/langLibs.js

@@ -0,0 +1,10 @@
+/**
+ * This is the dictionary of the language defined libraries
+ */
+export default {
+  $mathLib: "Matematica",
+  $ioLib: "ES",
+  $strLib: "Texto",
+  $arrayLib: "Arranjo",
+  $langLib: "IV"
+}

+ 3 - 1
grammar/es/ivprog.g4

@@ -164,7 +164,9 @@ ID
   : [a-zA-Z_] [a-zA-Z0-9_]*
   ;
 
-// ID_BIBLIOTECA     : ID '.' ID;
+LIB_ID
+  : ID '.' ID
+  ;
 
 INTEGER
   : [0-9]+

+ 27 - 1
grammar/es/langFunctions.js

@@ -3,5 +3,31 @@
 export default {
   main_function: "inicio",
   $read: "leia",
-  $write: "escreva"
+  $write: "escreva",
+  $numElements: "numero_elementos",
+  $matrixLines: "matriz_linhas",
+  $matrixColumns: "matriz_colunas",
+  $substring: "subcadeia",
+  $length: "comprimento",
+  $uppercase: "caixa_alta",
+  $lowercase: "caixa_baixa",
+  $charAt: "char_at",
+  $isReal: "e_real",
+  $isInt: "e_inteiro",
+  $isBool: "e_logico",
+  $castReal: "como_real",
+  $castInt: "como_inteiro",
+  $castBool: "como_logico",
+  $castString: "como_cadeia",
+  $sin: "sen",
+  $cos: "cos",
+  $tan: "tan",
+  $sqrt: "raiz_quadrada",
+  $pow: "pot",
+  $log: "log",
+  $abs: "modulo",
+  $negate: "trocar_sinal",
+  $invert: "inverter_valor",
+  $max: "maximo",
+  $min: "minimo"
 }

+ 10 - 0
grammar/es/langLibs.js

@@ -0,0 +1,10 @@
+/**
+ * This is the dictionary of the language defined libraries
+ */
+export default {
+  $mathLib: "Matematica",
+  $ioLib: "ES",
+  $strLib: "Texto",
+  $arrayLib: "Arranjo",
+  $langLib: "IV"
+}

+ 6 - 3
grammar/index.js

@@ -1,10 +1,13 @@
 import * as PT from './pt/ivprog.g4';
 import PTFuncs from './pt/langFunctions';
+import PTLibs from './pt/langLibs';
 import * as EN from './en/ivprog.g4';
 import ENFuncs from './en/langFunctions';
+import ENLibs from './en/langLibs';
 import * as ES from './es/ivprog.g4';
 import ESFuncs from './es/langFunctions';
+import ESLibs from './es/langLibs';
 
-exports.pt = {lexer: PT.ivprog, langFuncs: PTFuncs};
-exports.en = {lexer: EN.ivprog, langFuncs: ENFuncs};
-exports.es = {lexer: ES.ivprog, langFuncs: ESFuncs};
+exports.pt = {lexer: PT.ivprog, langFuncs: PTFuncs, langLibs: PTLibs};
+exports.en = {lexer: EN.ivprog, langFuncs: ENFuncs, langLibs: ENLibs};
+exports.es = {lexer: ES.ivprog, langFuncs: ESFuncs, langLibs: ESLibs};

+ 3 - 1
grammar/pt/ivprog.g4

@@ -164,7 +164,9 @@ ID
   : [a-zA-Z_] [a-zA-Z0-9_]*
   ;
 
-// ID_BIBLIOTECA     : ID '.' ID;
+LIB_ID
+  : ID '.' ID
+  ;
 
 INTEGER
   : [0-9]+

+ 27 - 1
grammar/pt/langFunctions.js

@@ -3,5 +3,31 @@
 export default {
   main_function: "inicio",
   $read: "leia",
-  $write: "escreva"
+  $write: "escreva",
+  $numElements: "numero_elementos",
+  $matrixLines: "matriz_linhas",
+  $matrixColumns: "matriz_colunas",
+  $substring: "subcadeia",
+  $length: "comprimento",
+  $uppercase: "caixa_alta",
+  $lowercase: "caixa_baixa",
+  $charAt: "char_at",
+  $isReal: "e_real",
+  $isInt: "e_inteiro",
+  $isBool: "e_logico",
+  $castReal: "como_real",
+  $castInt: "como_inteiro",
+  $castBool: "como_logico",
+  $castString: "como_cadeia",
+  $sin: "sen",
+  $cos: "cos",
+  $tan: "tan",
+  $sqrt: "raiz_quadrada",
+  $pow: "pot",
+  $log: "log",
+  $abs: "modulo",
+  $negate: "trocar_sinal",
+  $invert: "inverter_valor",
+  $max: "maximo",
+  $min: "minimo"
 }

+ 10 - 0
grammar/pt/langLibs.js

@@ -0,0 +1,10 @@
+/**
+ * This is the dictionary of the language defined libraries
+ */
+export default {
+  $mathLib: "Matematica",
+  $ioLib: "ES",
+  $strLib: "Texto",
+  $arrayLib: "Arranjo",
+  $langLib: "IV"
+}

+ 1 - 0
i18n/pt/error.json

@@ -12,6 +12,7 @@
   "invalid_terminal": "Não é possível utilizar $0 na expressão da linha: $1, coluna: $2. Tente um valor númerico, variável ou chamada de função.",
   "const_not_init": "Erro na linha: $0, coluna: $1. Uma variável declarada como const deve ser inicializada",
   "id_missing": "Esperava-se um identificador, mas encontrou-se $0 na linha: $1, coluna: $2",
+  "invalid_id_format": "$0 na linha: $1, coluna: $2 não é um identificador válido. O símbolo '.' não é permitido neste contexto.",
   "main_missing": "A função principal não foi encontrada",
   "invalid_global_var": "Erro crítico: Chamada inválida da função initGlobal fora do contexto BASE",
   "not_implemented": "Erro interno crítico: A função definida pelo sistema $0 não foi implementada.",

+ 5 - 1
js/ast/error/syntaxErrorFactory.js

@@ -9,7 +9,7 @@ export const SyntaxErrorFactory = Object.freeze({
   },
   token_missing_list: (expectedList, token) => {
     const line = expectedList.join(LocalizedStrings.getOR());
-    return SyntaxErrorCodes.token_missing_one(line, token);
+    return SyntaxErrorFactory.token_missing_one(line, token);
   },
   id_missing: (token) => {
     const context = [token.text, token.line, token.column];
@@ -51,5 +51,9 @@ export const SyntaxErrorFactory = Object.freeze({
   const_not_init: (token) => {
     const context = [token.line, token.column];
     return new SyntaxError(LocalizedStrings.getError("const_not_init", context));
+  },
+  invalid_id_format: (token) => {
+    const context = [token.text, token.line, token.column];
+    return new SyntaxError(LocalizedStrings.getError("invalid_id_format", context));
   }
 });

+ 34 - 10
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, toBool } from './types';
+import { Types, toInt, toString, toBool, toReal } from './types';
 import { SourceInfo } from './sourceInfo';
 import { convertFromString } from './operators';
 import { SyntaxErrorFactory } from './error/syntaxErrorFactory';
@@ -10,6 +10,11 @@ import { LanguageService } from '../services/languageService';
 
 export class IVProgParser {
 
+  static createParser (input) {
+    const lexerClass = LanguageService.getCurrentLexer();
+    return new IVProgParser(input, lexerClass);
+  }
+
   // <BEGIN scope consts>
   static get BASE () {
     return 0;
@@ -336,7 +341,7 @@ export class IVProgParser {
 
   getRealLiteral (token) {
     const sourceInfo = SourceInfo.createSourceInfo(token);
-    const exp = new Expressions.RealLiteral(parseFloat(token.text));
+    const exp = new Expressions.RealLiteral(toReal(token.text));
     exp.sourceInfo = sourceInfo;
     return exp;
   }
@@ -472,7 +477,7 @@ export class IVProgParser {
     const token = this.getToken();
     if(token.type !== this.lexerClass.ID) {
       throw SyntaxErrorFactory.id_missing(token);
-    } 
+    }
     this.pos++;
     if (this.insideScope(IVProgParser.FUNCTION)) {
       if (token.text === LanguageDefinedFunction.getMainFunctionName()){
@@ -482,6 +487,15 @@ export class IVProgParser {
     return token.text;
   }
 
+  parseMaybeLibID () {
+    const token = this.getToken();
+    if(token.type !== this.lexerClass.ID && token.type !== this.lexerClass.LIB_ID) {
+      throw SyntaxErrorFactory.id_missing(token);
+    } 
+    this.pos++;
+    return token.text;
+  }
+
   parseType () {
     const token = this.getToken();
     if(token.type === this.lexerClass.ID && this.insideScope(IVProgParser.FUNCTION)) {
@@ -555,6 +569,8 @@ export class IVProgParser {
       return cmd;
     } else if (token.type === this.lexerClass.ID) {
       return this.parseIDCommand();
+    } else if (token.type === this.lexerClass.LIB_ID) {
+      return this.parseIDCommand();
     } else if (token.type === this.lexerClass.RK_RETURN) {
       return this.parseReturn();
     } else if (token.type === this.lexerClass.RK_WHILE) {
@@ -723,9 +739,11 @@ export class IVProgParser {
   }
 
   parseIDCommand () {
-    const id = this.parseID();
+    const refToken = this.getToken();
+    const isID = refToken.type === this.lexerClass.ID;
+    const id = this.parseMaybeLibID();
     const equalOrParenthesis = this.getToken();
-    if (equalOrParenthesis.type === this.lexerClass.EQUAL) {
+    if (isID && equalOrParenthesis.type === this.lexerClass.EQUAL) {
       const sourceInfo = SourceInfo.createSourceInfo(this.getToken());
       this.pos++
       const exp = this.parseExpressionOR();
@@ -739,8 +757,10 @@ export class IVProgParser {
       this.checkEOS();
       this.pos++;
       return funcCall;
-    } else {
+    } else if (isID) {
       throw SyntaxErrorFactory.token_missing_list(['=','('], equalOrParenthesis);
+    } else {
+      throw SyntaxErrorFactory.invalid_id_format(refToken);
     }
   }
 
@@ -936,6 +956,7 @@ export class IVProgParser {
       case this.lexerClass.OPEN_CURLY:
         return this.parseArrayLiteral();
       case this.lexerClass.ID:
+      case this.lexerClass.LIB_ID:
         return this.parseIDTerm();
       case this.lexerClass.OPEN_PARENTHESIS:
         return this.parseParenthesisExp();
@@ -945,9 +966,10 @@ export class IVProgParser {
   }
 
   parseIDTerm () {
-    const id = this.parseID();
-    const tokenA = this.getToken(this.pos - 1);
-    if(this.checkOpenBrace(true)) {
+    const tokenA = this.getToken();
+    const id = this.parseMaybeLibID();
+    const isID = tokenA.type === this.lexerClass.ID;
+    if(isID && this.checkOpenBrace(true)) {
       let tokenB = null;
       this.pos++;
       const firstIndex = this.parseExpression();
@@ -971,11 +993,13 @@ export class IVProgParser {
 
     } else if (this.checkOpenParenthesis(true)) {
       return this.parseFunctionCallExpression(id);
-    } else {
+    } else if (isID) {
       const sourceInfo = SourceInfo.createSourceInfo(tokenA);
       const exp = new Expressions.VariableLiteral(id);
       exp.sourceInfo = sourceInfo;
       return exp;
+    } else {
+      throw SyntaxErrorFactory.invalid_id_format(tokenA);
     }
   }
 

+ 6 - 7
js/ast/types.js

@@ -1,4 +1,5 @@
 import { LanguageService } from "../services/languageService";
+import { BigNumber } from 'bignumber.js'
 
 export const Types = Object.freeze({
   INTEGER: {value: "int", ord: 0},
@@ -12,13 +13,7 @@ export const Types = Object.freeze({
 });
 
 export function toInt (str) {
-  if(str.match('^0b|^0B')) {
-    return parseInt(str.substring(2), 2);
-  } else if (str.match('^0x|^0X')) {
-    return parseInt(str.substring(2), 16);
-  } else {
-    return parseInt(str);
-  }
+  return new BigNumber(str);
 }
 
 export function toString (str) {
@@ -34,6 +29,10 @@ export function toString (str) {
   return value;
 }
 
+export function toReal (value) {
+  return new BigNumber(value);
+}
+
 export function toBool (str) {
   const val = "'" + str + "'";
   const lexer = LanguageService.getCurrentLexer();

+ 3 - 0
js/jquery.json-editor.min.js

@@ -35,6 +35,9 @@ function(e) {
               s += "</ol>]"
           } else s += "[]";
       else if ("object" == typeof e) {
+          if (e['_type'] && (e['_type'].value === 'real' || e['_type'].value === 'int')) {
+            e._value = e._value.toNumber();
+          }
           var a = Object.keys(e).length;
           if (a > 0) {
               s += '{<ul class="json-dict">';

+ 92 - 50
js/processor/definedFunctions.js

@@ -1,49 +1,20 @@
-import * as Commands from './../ast/commands';
-import {Types, toInt, toString, toBool} from './../ast/types';
 import { LanguageService } from '../services/languageService';
-import { StoreObject } from './store/storeObject';
-
-function createOutputFun () {
-  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);
-  return func;
-}
-
-function createInputFun () {
-  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);
-  return func;
-}
+import {createInputFun, createOutputFun} from './lib/io';
+import {createLengthFun, createLowercaseFun,
+  createrCharAtFun, createSubstringFun,
+  createUppercaseFun} from './lib/strings';
+import {createMatrixColumnsFun, createMatrixLinesFun,
+  createNumElementsFun} from './lib/arrays';
+import {createCastBoolFun, createCastIntFun,
+  createCastRealFun, createCastStringFun,
+  createIsBoolFun, createIsIntFun,
+  createIsRealFun} from './lib/lang';
+import {createAbsFun, createCosFun,
+  createInvertFun, createLogFun,
+  createMaxFun, createMinFun,
+  createNegateFun, createPowFun,
+  createSinFun, createSqrtFun,
+  createTanFun} from './lib/math';
 
 function valueToKey (value, object) {
   for (const key in object) {
@@ -56,13 +27,84 @@ function valueToKey (value, object) {
   return null;
 }
 
-const funcsObject = {
-  $read: createInputFun(),
-  $write: createOutputFun()
+function concatObjects (...objs) {
+  let result = {};
+  for (let i = 0; i < objs.length; i++) {
+    const obj = objs[i];
+    for(const key in obj) {
+      if(obj.hasOwnProperty(key)) {
+        result[key] = obj[key];
+      }
+    }
+  }
+  return result;
+}
+
+const libsObject = {
+  $mathLib: {
+    $sin: createSinFun(),
+    $cos: createCosFun(),
+    $tan: createTanFun(),
+    $sqrt: createSqrtFun(),
+    $pow: createPowFun(),
+    $log: createLogFun(),
+    $abs: createAbsFun(),
+    $negate: createNegateFun(),
+    $invert: createInvertFun(),
+    $max: createMaxFun(),
+    $min: createMinFun()
+  },
+  $ioLib: {
+    $read: createInputFun(),
+    $write: createOutputFun()
+  },
+  $strLib: {
+    $substring: createSubstringFun(),
+    $length: createLengthFun(),
+    $uppercase: createUppercaseFun(),
+    $lowercase: createLowercaseFun(),
+    $charAt: createrCharAtFun(),
+  },
+  $arrayLib: {
+    $numElements: createNumElementsFun(),
+    $matrixLines: createMatrixLinesFun(),
+    $matrixColumns: createMatrixColumnsFun()
+  },
+  $langLib: {
+    $isReal: createIsRealFun(),
+    $isInt: createIsIntFun(),
+    $isBool: createIsBoolFun(),
+    $castReal: createCastRealFun(),
+    $castInt: createCastIntFun(),
+    $castBool: createCastBoolFun(),
+    $castString: createCastStringFun()
+  }
 }
 
+const funcsObject = concatObjects(libsObject.$ioLib, libsObject.$langLib,
+  libsObject.$strLib, libsObject.$arrayLib);
+
 export const LanguageDefinedFunction = Object.freeze({
   getMainFunctionName: () => LanguageService.getCurrentLangFuncs().main_function,
-  getInternalName: (localName) => valueToKey(localName, LanguageService.getCurrentLangFuncs()),
-  getFunction: (internalName) => funcsObject[internalName],
+  getInternalName: (localName) => {
+    if (localName.indexOf(".") !== -1) {
+      const names = localName.split(".");
+      const lib = valueToKey(names[0], LanguageService.getCurrentLangLibs());
+      const internalName = valueToKey(names[1], LanguageService.getCurrentLangFuncs());
+      if (lib === null || internalName === null) {
+        return null;
+      }
+      return lib + "." + internalName;
+    }
+    return valueToKey(localName, LanguageService.getCurrentLangFuncs());
+  },
+  getFunction: (internalName) => {
+    if (internalName.indexOf(".") !== -1) {
+      const names = internalName.split(".");
+      const libName = names[0];
+      const funName = names[1];
+      return libsObject[libName][funName];
+    }
+    return funcsObject[internalName];
+  },
 });

+ 36 - 26
js/processor/ivprogProcessor.js

@@ -4,7 +4,7 @@ import { StoreObjectArray } from './store/storeObjectArray';
 import { StoreObjectRef } from './store/storeObjectRef';
 import { Modes } from './modes';
 import { Context } from './context';
-import { Types, toInt } from './../ast/types';
+import { Types } from './../ast/types';
 import { Operators } from './../ast/operators';
 import { LanguageDefinedFunction } from './definedFunctions';
 import { resultTypeAfterInfixOp, resultTypeAfterUnaryOp } from './compatibilityTable';
@@ -460,7 +460,7 @@ export class IVProgProcessor {
             //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS
             return Promise.reject(new Error("Array dimension must be of type int"));
           }
-          const line = lineSO.value;
+          const line = lineSO.number;
           const columnSO = values[1];
           let column = null
           if (columnSO !== null) {
@@ -469,7 +469,7 @@ export class IVProgProcessor {
               //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS
               return Promise.reject(new Error("Array dimension must be of type int"));
             }
-            column = columnSO.value;
+            column = columnSO.number;
           }
           const value = values[2];
           const temp = new StoreObjectArray(cmd.subtype, line, column, null, cmd.isConst);
@@ -603,7 +603,7 @@ export class IVProgProcessor {
         //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS
         return Promise.reject(new Error("Array dimension must be of type int"));
       }
-      const line = lineSO.value;
+      const line = lineSO.number;
       let column = null;
       if(columnSO !== null) {
         if(columnSO.type !== Types.INTEGER) {
@@ -611,7 +611,7 @@ export class IVProgProcessor {
           //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS
           return Promise.reject(new Error("Array dimension must be of type int"));
         }
-        column = columnSO.value;
+        column = columnSO.number;
       }
 
       if (line >= mustBeArray.lines) {
@@ -645,9 +645,9 @@ export class IVProgProcessor {
       }
       switch (unaryApp.op.ord) {
         case Operators.ADD.ord:
-          return new StoreObject(resultType, +left.value);
+          return new StoreObject(resultType, left.value);
         case Operators.SUB.ord:
-          return new StoreObject(resultType, -left.value);
+          return new StoreObject(resultType, left.value.negated());
         case Operators.NOT.ord:
           return new StoreObject(resultType, !left.value);
         default:
@@ -665,33 +665,31 @@ export class IVProgProcessor {
       const resultType = resultTypeAfterInfixOp(infixApp.op, left.type, right.type);
       if (resultType === Types.UNDEFINED) {
         // TODO: better urgent error message
-        return Promise.reject(new Error(`Cannot use this op to ${left.type} and ${right.type}`));
+        return Promise.reject(new Error(`Cannot use this ${infixApp.op.value} to ${left.type.value} and ${right.type.value}`));
       }
       let result = null;
       switch (infixApp.op.ord) {
         case Operators.ADD.ord:
-          return new StoreObject(resultType, left.value + right.value);
+          return new StoreObject(resultType, left.value.plus(right.value));
         case Operators.SUB.ord:
-          return new StoreObject(resultType, left.value - right.value);
-        case Operators.MULT.ord: {
-          result = left.value * right.value;
-          if (resultType === Types.INTEGER)
-            result = Math.trunc(result);
-          return new StoreObject(resultType, result);
-        }
+          return new StoreObject(resultType, left.value.minus(right.value));
+        case Operators.MULT.ord:
+          return new StoreObject(resultType, left.value.times(right.value));
         case Operators.DIV.ord: {
           result = left.value / right.value;
           if (resultType === Types.INTEGER)
-            result = Math.trunc(result);
+            result = left.value.idiv(right.value);
+          else
+            result = left.value.div(right.value);
           return new StoreObject(resultType, result);
         }
         case Operators.MOD.ord:
-          return new StoreObject(resultType, left.value % right.value);
+          return new StoreObject(resultType, left.value.modulo(right.value));
         case Operators.GT.ord: {
           if (left.type === Types.STRING) {
             result = left.value.length > right.value.length;
           } else {
-            result = left.value > right.value;
+            result = left.value.gt(right.value);
           }
           return new StoreObject(resultType, result);
         }
@@ -699,7 +697,7 @@ export class IVProgProcessor {
           if (left.type === Types.STRING) {
             result = left.value.length >= right.value.length;
           } else {
-            result = left.value >= right.value;
+            result = left.value.gte(right.value);
           }
           return new StoreObject(resultType, result);
         }
@@ -707,7 +705,7 @@ export class IVProgProcessor {
           if (left.type === Types.STRING) {
             result = left.value.length < right.value.length;
           } else {
-            result = left.value < right.value;
+            result = left.value.lt(right.value);
           }
           return new StoreObject(resultType, result);
         }
@@ -715,14 +713,26 @@ export class IVProgProcessor {
           if (left.type === Types.STRING) {
             result = left.value.length <= right.value.length;
           } else {
-            result = left.value <= right.value;
+            result = left.value.lte(right.value);
+          }
+          return new StoreObject(resultType, result);
+        }
+        case Operators.EQ.ord: {
+          if (left.type === Types.INTEGER || left.type === Types.REAL) {
+            result = left.value.eq(right.value);
+          } else {
+            result = left.value === right.value;
+          }
+          return new StoreObject(resultType, result);
+        }
+        case Operators.NEQ.ord: {
+          if (left.type === Types.INTEGER || left.type === Types.REAL) {
+            result = !left.value.eq(right.value);
+          } else {
+            result = left.value !== right.value;
           }
           return new StoreObject(resultType, result);
         }
-        case Operators.EQ.ord:
-          return new StoreObject(resultType, left.value === right.value);
-        case Operators.NEQ.ord:
-          return new StoreObject(resultType, left.value !== right.value);
         case Operators.AND.ord:
           return new StoreObject(resultType, left.value && right.value);
         case Operators.OR.ord:

+ 52 - 0
js/processor/lib/arrays.js

@@ -0,0 +1,52 @@
+import { StoreObject } from '../store/storeObject';
+import * as Commands from './../../ast/commands';
+import { Types, toInt } from './../../ast/types';
+
+/**
+ * num_elements
+ * matrix_lines
+ * matrix_columns
+ */
+
+export function createNumElementsFun () {
+  const numElementsFun = (sto, _) => {
+    const vector  = sto.applyStore("vector");
+    const temp = new StoreObject(Types.INTEGER, toInt(vector.lines));
+    return Promise.resolve(sto.updateStore("$", temp));
+  }
+
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(numElementsFun)]);
+  const func = new Commands.Function('$numElements', Types.INTEGER,
+    [new Commands.FormalParameter(Types.ALL, 'vector', 1, false)],
+    block);
+  return func;
+ }
+
+export function createMatrixLinesFun () {
+  const matrixLinesFun = (sto, _) => {
+    const matrix  = sto.applyStore("matrix");
+    const temp = new StoreObject(Types.INTEGER, toInt(matrix.lines));
+    return Promise.resolve(sto.updateStore("$", temp));
+  }
+
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(matrixLinesFun)]);
+  const func = new Commands.Function('$matrixLines', Types.INTEGER,
+    [new Commands.FormalParameter(Types.ALL, 'matrix', 2, false)],
+    block);
+  return func;
+ }
+
+export function createMatrixColumnsFun () {
+  const matrixColumnsFun = (sto, _) => {
+    const matrix  = sto.applyStore("matrix");
+    const temp = new StoreObject(Types.INTEGER, toInt(matrix.columns));
+    return Promise.resolve(sto.updateStore("$", temp));
+  }
+
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(matrixColumnsFun)]);
+  const func = new Commands.Function('$matrixColumns', Types.INTEGER,
+    [new Commands.FormalParameter(Types.ALL, 'matrix', 2, false)],
+    block);
+  return func;
+ }
+ 

+ 55 - 0
js/processor/lib/io.js

@@ -0,0 +1,55 @@
+import { StoreObject } from './../store/storeObject';
+import * as Commands from './../../ast/commands';
+import {Types, toInt, toString, toBool, toReal} from './../../ast/types';
+
+export function createOutputFun () {
+  const writeFunction = function (store, _) {
+    const val = store.applyStore('p1');
+    if(val.type === Types.INTEGER) {
+      this.output.sendOutput(val.value.toString());
+    } else if (val.type === Types.REAL) {
+      if (val.value.dp() <= 0) {
+        this.output.sendOutput(val.value.toFixed(1));  
+      } else {
+        this.output.sendOutput(val.value.toString());
+      }
+    } else {
+      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);
+  return func;
+}
+
+export function createInputFun () {
+  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, toReal(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);
+  return func;
+}

+ 191 - 0
js/processor/lib/lang.js

@@ -0,0 +1,191 @@
+import { StoreObject } from '../store/storeObject';
+import * as Commands from './../../ast/commands';
+import { Types, toReal } from './../../ast/types';
+import { IVProgParser } from '../../ast/ivprogParser';
+import { RealLiteral, IntLiteral, BoolLiteral } from '../../ast/expressions';
+
+/**
+ * 
+ * is_real
+ * is_int
+ * is_bool
+ * cast_real
+ * cast_int
+ * cast_bool
+ * cast_string
+ */
+
+export function createIsRealFun () {
+  const isRealFun = (sto, _) => {
+    const str = sto.applyStore("str");
+    const parser = IVProgParser.createParser(str.value);
+    let result = false;
+    try {
+      const val = parser.parseTerm();
+      if (val instanceof RealLiteral) {
+        result = true;
+      }
+    } catch (error) { }
+    const temp = new StoreObject(Types.BOOLEAN, result);
+    return Promise.resolve(sto.updateStore("$", temp));
+  }
+
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(isRealFun)]);
+  const func = new Commands.Function('$isReal', Types.BOOLEAN,
+    [new Commands.FormalParameter(Types.STRING, 'str', 0, false)],
+    block);
+  return func;
+}
+
+export function createIsIntFun () {
+  const isIntFun = (sto, _) => {
+    const str = sto.applyStore("str");
+    const parser = IVProgParser.createParser(str.value);
+    let result = false;
+    try {
+      const val = parser.parseTerm();
+      if (val instanceof IntLiteral) {
+        result = true;
+      }
+    } catch (error) { }
+    const temp = new StoreObject(Types.BOOLEAN, result);
+    return Promise.resolve(sto.updateStore("$", temp));
+  }
+
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(isIntFun)]);
+  const func = new Commands.Function('$isInt', Types.BOOLEAN,
+    [new Commands.FormalParameter(Types.STRING, 'str', 0, false)],
+    block);
+  return func;
+}
+
+export function createIsBoolFun () {
+  const isBoolFun = (sto, _) => {
+    const str = sto.applyStore("str");
+    const parser = IVProgParser.createParser(str.value);
+    let result = false;
+    try {
+      const val = parser.parseTerm();
+      if (val instanceof BoolLiteral) {
+        result = true;
+      }
+    } catch (error) { }
+    const temp = new StoreObject(Types.BOOLEAN, result);
+    return Promise.resolve(sto.updateStore("$", temp));
+  }
+
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(isBoolFun)]);
+  const func = new Commands.Function('$isBool', Types.BOOLEAN,
+    [new Commands.FormalParameter(Types.STRING, 'str', 0, false)],
+    block);
+  return func;
+}
+
+export function createCastRealFun () {
+  const castRealFun = (sto, _) => {
+    const val = sto.applyStore("val");
+    switch (val.type.ord) {
+      case Types.INTEGER.ord: {
+        const temp = new StoreObject(Types.REAL, toReal(val.number));
+        return Promise.resolve(sto.updateStore("$", temp));
+      }
+      case Types.STRING.ord: {
+        const parser = IVProgParser.createParser(val.value);
+        try {
+          const result = parser.parseTerm();
+          if (result instanceof RealLiteral) {
+            const temp = new StoreObject(Types.REAL, result.value);
+            return Promise.resolve(sto.updateStore("$", temp));
+          }
+        } catch (error) { 
+          return Promise.reject("cannot convert string to real");
+        }
+      }
+    }
+  }
+
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(castRealFun)]);
+  const func = new Commands.Function('$castReal', Types.REAL,
+    [new Commands.FormalParameter(Types.ALL, 'val', 0, false)],
+    block);
+  return func;
+}
+
+export function createCastIntFun () {
+  const castIntFun = (sto, _) => {
+    const val = sto.applyStore("val");
+    switch (val.type.ord) {
+      case Types.REAL.ord: {
+        const temp = new StoreObject(Types.INTEGER, Math.floor(val.number));
+        return Promise.resolve(sto.updateStore("$", temp));
+      }
+      case Types.STRING.ord: {
+        const parser = IVProgParser.createParser(val.value);
+        try {
+          const result = parser.parseTerm();
+          if (result instanceof IntLiteral) {
+            const temp = new StoreObject(Types.INTEGER, result.value);
+            return Promise.resolve(sto.updateStore("$", temp));
+          }
+        } catch (error) { 
+          return Promise.reject("cannot convert string to real");
+        }
+      }
+    }
+  }
+
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(castIntFun)]);
+  const func = new Commands.Function('$castInt', Types.INTEGER,
+    [new Commands.FormalParameter(Types.ALL, 'val', 0, false)],
+    block);
+  return func;
+}
+
+export function createCastBoolFun () {
+  const castBoolFun = (sto, _) => {
+    const str = sto.applyStore("str");
+    const parser = IVProgParser.createParser(str.value);
+    try {
+      const val = parser.parseTerm();
+      if (val instanceof BoolLiteral) {
+        const temp = new StoreObject(Types.BOOLEAN, val.value);
+        return Promise.resolve(sto.updateStore("$", temp));
+      }
+    } catch (error) { }
+    return Promise.reject("cannot convert " + str.value + " to boolean");
+  }
+
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(castBoolFun)]);
+  const func = new Commands.Function('$castBool', Types.BOOLEAN,
+    [new Commands.FormalParameter(Types.STRING, 'str', 0, false)],
+    block);
+  return func;
+}
+
+export function createCastStringFun () {
+  const castStringFun = function (store, _) {
+    const val = store.applyStore('str');
+    switch (val.type.ord) {
+      case Types.INTEGER.ord:
+        this.output.sendOutput(val.number);  
+        break;
+      case Types.REAL.ord: {
+        if (val.value.dp() <= 0) {
+          this.output.sendOutput(val.value.toFixed(1));  
+        } else {
+          this.output.sendOutput(val.number);
+        }
+        break;
+      }
+      default:
+        this.output.sendOutput(val.value);
+        break;
+    }
+    return Promise.resolve(store);
+  }
+  const block = new Commands.CommandBlock([], [new Commands.SysCall(castStringFun)]);
+  const func = new Commands.Function('$castString', Types.STRING,
+    [new Commands.FormalParameter(Types.ALL, 'str', 0, false)],
+    block);
+  return func;
+}

+ 188 - 0
js/processor/lib/math.js

@@ -0,0 +1,188 @@
+import { StoreObject } from '../store/storeObject';
+import * as Commands from './../../ast/commands';
+import { Types, toReal } from './../../ast/types';
+import { BigNumber } from 'bignumber.js';
+
+/**
+ * sin
+ * cos
+ * tan
+ * sqrt
+ * pow
+ * log
+ * abs
+ * negate
+ * invert
+ * max
+ * min
+ */
+
+export function createSinFun () {
+   const sinFun = (sto, _) => {
+     const x = sto.applyStore('x');
+     const result = toReal(Math.sin(x.number));
+     const temp = new StoreObject(Types.REAL, result);
+     return Promise.resolve(sto.updateStore('$', temp));
+   };
+
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(sinFun)]);
+  const func = new Commands.Function('$sin', Types.REAL,
+    [new Commands.FormalParameter(Types.REAL, 'x', 0, false)],
+    block);
+  return func;
+}
+
+export function createCosFun () {
+  const cosFun = (sto, _) => {
+    const x = sto.applyStore('x');
+    const result = toReal(Math.cos(x.number));
+    const temp = new StoreObject(Types.REAL, result);
+    return Promise.resolve(sto.updateStore('$', temp));
+  };
+
+ const block = new Commands.CommandBlock([],  [new Commands.SysCall(cosFun)]);
+ const func = new Commands.Function('$cos', Types.REAL,
+   [new Commands.FormalParameter(Types.REAL, 'x', 0, false)],
+   block);
+ return func;
+}
+
+export function createTanFun () {
+  const tanFun = (sto, _) => {
+    const x = sto.applyStore('x');
+    const result = toReal(Math.tan(x.number));
+    const temp = new StoreObject(Types.REAL, result);
+    return Promise.resolve(sto.updateStore('$', temp));
+  };
+
+ const block = new Commands.CommandBlock([],  [new Commands.SysCall(tanFun)]);
+ const func = new Commands.Function('$tan', Types.REAL,
+   [new Commands.FormalParameter(Types.REAL, 'x', 0, false)],
+   block);
+ return func;
+}
+
+export function createSqrtFun () {
+  const sqrtFun = (sto, _) => {
+    const x = sto.applyStore('x');
+    const result = x.value.sqrt();
+    const temp = new StoreObject(Types.REAL, result);
+    return Promise.resolve(sto.updateStore('$', temp));
+  };
+
+ const block = new Commands.CommandBlock([],  [new Commands.SysCall(sqrtFun)]);
+ const func = new Commands.Function('$sqrt', Types.REAL,
+   [new Commands.FormalParameter(Types.REAL, 'x', 0, false)],
+   block);
+ return func;
+}
+
+export function createPowFun () {
+  const powFun = (sto, _) => {
+    const x = sto.applyStore('x');
+    const y = sto.applyStore('y');
+    const result = toReal(Math.pow(x.number, y.number));
+    const temp = new StoreObject(Types.REAL, result);
+    return Promise.resolve(sto.updateStore('$', temp));
+  };
+
+ const block = new Commands.CommandBlock([],  [new Commands.SysCall(powFun)]);
+ const func = new Commands.Function('$pow', Types.REAL,
+   [new Commands.FormalParameter(Types.REAL, 'x', 0, false),
+    new Commands.FormalParameter(Types.REAL, 'y', 0, false)],
+   block);
+ return func;
+}
+
+export function createLogFun () {
+  const logFun = (sto, _) => {
+    const x = sto.applyStore('x');
+    if (x.value.isNegative()) {
+      return Promise.reject("the value passed to log function cannot be negative");
+    }
+    const result = toReal(Math.log10(x.number));
+    const temp = new StoreObject(Types.REAL, result);
+    return Promise.resolve(sto.updateStore('$', temp));
+  };
+
+ const block = new Commands.CommandBlock([],  [new Commands.SysCall(logFun)]);
+ const func = new Commands.Function('$log', Types.REAL,
+   [new Commands.FormalParameter(Types.REAL, 'x', 0, false)],
+   block);
+ return func;
+}
+
+export function createAbsFun () {
+  const absFun = (sto, _) => {
+    const x = sto.applyStore('x');
+    const result = x.value.abs();
+    const temp = new StoreObject(Types.REAL, result);
+    return Promise.resolve(sto.updateStore('$', temp));
+  };
+
+ const block = new Commands.CommandBlock([],  [new Commands.SysCall(absFun)]);
+ const func = new Commands.Function('$abs', Types.REAL,
+   [new Commands.FormalParameter(Types.REAL, 'x', 0, false)],
+   block);
+ return func;
+}
+
+export function createNegateFun () {
+  const negateFun = (sto, _) => {
+    const x = sto.applyStore('x');
+    const result = x.value.negated();
+    const temp = new StoreObject(Types.REAL, result);
+    return Promise.resolve(sto.updateStore('$', temp));
+  };
+
+ const block = new Commands.CommandBlock([],  [new Commands.SysCall(negateFun)]);
+ const func = new Commands.Function('$negate', Types.REAL,
+   [new Commands.FormalParameter(Types.REAL, 'x', 0, false)],
+   block);
+ return func;
+}
+
+export function createInvertFun () {
+  const invertFun = (sto, _) => {
+    const x = sto.applyStore('x');
+    const result = toReal(1).dividedBy(x.value);
+    const temp = new StoreObject(Types.REAL, result);
+    return Promise.resolve(sto.updateStore('$', temp));
+  };
+
+ const block = new Commands.CommandBlock([],  [new Commands.SysCall(invertFun)]);
+ const func = new Commands.Function('$invert', Types.REAL,
+   [new Commands.FormalParameter(Types.REAL, 'x', 0, false)],
+   block);
+ return func;
+}
+
+export function createMaxFun () {
+  const maxFun = (sto, _) => {
+    const x = sto.applyStore('x');
+    const result = BigNumber.max(x.value);
+    const temp = new StoreObject(x.subtype, result);
+    return Promise.resolve(sto.updateStore('$', temp));
+  };
+
+ const block = new Commands.CommandBlock([],  [new Commands.SysCall(maxFun)]);
+ const func = new Commands.Function('$max', Types.ALL,
+   [new Commands.FormalParameter(Types.ALL, 'x', 1, false)],
+   block);
+ return func;
+}
+
+export function createMinFun () {
+  const minFun = (sto, _) => {
+    const x = sto.applyStore('x');
+    const result = BigNumber.max(x.value);
+    const temp = new StoreObject(x.subtype, result);
+    return Promise.resolve(sto.updateStore('$', temp));
+  };
+
+ const block = new Commands.CommandBlock([],  [new Commands.SysCall(minFun)]);
+ const func = new Commands.Function('$min', Types.ALL,
+   [new Commands.FormalParameter(Types.ALL, 'x', 1, false)],
+   block);
+ return func;
+}

+ 88 - 0
js/processor/lib/strings.js

@@ -0,0 +1,88 @@
+import { StoreObject } from '../store/storeObject';
+import * as Commands from './../../ast/commands';
+import { Types, toInt } from './../../ast/types';
+
+
+/*
+*  substring
+*  length
+*  uppercase
+*  lowercase
+*  charAt
+**/
+
+export function createSubstringFun () {
+  const substringFun = (sto, _) => {
+    const str = sto.applyStore("str");
+    const start = sto.applyStore("start");
+    const end = sto.applyStore("end");
+    const result = str.value.substring(start.value, end.value);
+    const temp = new StoreObject(Types.STRING, result);
+    return Promise.resolve(sto.updateStore("$", temp));
+  };
+
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(substringFun)]);
+  const func = new Commands.Function('$substring', Types.STRING,
+    [new Commands.FormalParameter(Types.STRING, 'str', 0, false),
+    new Commands.FormalParameter(Types.INTEGER, 'start', 0, false),
+    new Commands.FormalParameter(Types.INTEGER, 'end', 0, false)],
+    block);
+  return func;
+}
+
+export function createLengthFun () {
+  const lengthFun = (sto, _) => {
+    const str = sto.applyStore("str");
+    const temp = new StoreObject(Types.INTEGER, toInt(value.length));
+    return Promise.resolve(sto.updateStore("$", temp));
+  }
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(lengthFun)]);
+  const func = new Commands.Function('$length', Types.INTEGER,
+    [new Commands.FormalParameter(Types.STRING, 'str', 0, false)],
+    block);
+  return func;
+}
+
+export function createUppercaseFun () {
+  const uppercaseFun = (sto, _) => {
+    const str = sto.applyStore("str");
+    const temp = new StoreObject(Types.STRING, str.value.toUpperCase());
+    return Promise.resolve(sto.updateStore("$", temp));
+  }
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(uppercaseFun)]);
+  const func = new Commands.Function('$uppercase', Types.STRING,
+    [new Commands.FormalParameter(Types.STRING, 'str', 0, false)],
+    block);
+  return func;
+}
+
+export function createLowercaseFun () {
+  const lowercaseFun = (sto, _) => {
+    const str = sto.applyStore("str");
+    const temp = new StoreObject(Types.STRING, str.value.toLowerCase());
+    return Promise.resolve(sto.updateStore("$", temp));
+  }
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(lowercaseFun)]);
+  const func = new Commands.Function('$lowercase', Types.STRING,
+    [new Commands.FormalParameter(Types.STRING, 'str', 0, false)],
+    block);
+  return func;
+}
+
+export function createrCharAtFun () {
+  const charAtFun = (sto, _) => {
+    const str = sto.applyStore("str");
+    const idx = sto.applyStore("index");
+    if (idx.value < 0 || idx.value >= str.value.length) {
+      return Promise.reject(new Error("invalid string position"));
+    }
+    const temp = new StoreObject(Types.STRING, str.value.charAt(idx.value));
+    return Promise.resolve(sto.updateStore("$", temp));
+  }
+  const block = new Commands.CommandBlock([],  [new Commands.SysCall(charAtFun)]);
+  const func = new Commands.Function('$charAt', Types.STRING,
+    [new Commands.FormalParameter(Types.STRING, 'str', 0, false),
+    new Commands.FormalParameter(Types.INTEGER, 'index', 0, false)],
+    block);
+  return func;
+}

+ 2 - 2
js/processor/semantic/semanticAnalyser.js

@@ -192,7 +192,7 @@ export class SemanticAnalyser {
         if (dimType !== Types.INTEGER) {
           throw new Error("dim must be int");
         }
-        if ((lines instanceof IntLiteral) && lines.value !== literal.value.length) {
+        if ((lines instanceof IntLiteral) && !lines.value.eq(literal.value.length)) {
           throw new Error("invalid array size");
         }
         literal.value.reduce((last, next) => {
@@ -208,7 +208,7 @@ export class SemanticAnalyser {
         if (dimType !== Types.INTEGER) {
           throw new Error("dim must be int");
         }
-        if ((columns instanceof IntLiteral) && columns.value !== literal.value.length) {
+        if ((columns instanceof IntLiteral) && !columns.value.eq(literal.value.length)) {
           throw new Error("invalid array size");
         }
         for (let i = 0; i < columns; i++) {

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

@@ -1,4 +1,5 @@
 import { Modes } from './../modes';
+
 export class Store {
 
   constructor() {

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

@@ -1,3 +1,5 @@
+import { BigNumber } from 'bignumber.js'
+
 export class StoreObject {
 
   constructor (type, value, readOnly = false) {
@@ -26,6 +28,14 @@ export class StoreObject {
   get value () {
     return this._value;
   }
+  
+  get number () {
+    if (this._value instanceof BigNumber) {
+      return this._value.toNumber();
+    } else {
+      return null;
+    }
+  }
 
   get readOnly () {
     return this._readOnly;

+ 8 - 0
js/services/languageService.js

@@ -33,6 +33,14 @@ export const LanguageService  = Object.freeze({
     } else {
       return langInfo.langFuncs;
     }
+  },
+
+  getCurrentLangLibs: () => {
+    const langInfo = Lexers[LanguageService.getLang()];
+    if(langInfo === null || langInfo === undefined) {
+      return Lexers[DEFAULT_LANG].langLibs;
+    }
+    return langInfo.langLibs;
   }
 
 });

+ 5 - 0
package-lock.json

@@ -1401,6 +1401,11 @@
       "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
       "dev": true
     },
+    "bignumber.js": {
+      "version": "7.2.1",
+      "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-7.2.1.tgz",
+      "integrity": "sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ=="
+    },
     "binary-extensions": {
       "version": "1.11.0",
       "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz",

+ 1 - 0
package.json

@@ -44,6 +44,7 @@
   },
   "dependencies": {
     "antlr4": "^4.7.1",
+    "bignumber.js": "^7.2.1",
     "jquery": "^3.3.1"
   }
 }

+ 1 - 1
tests/test19.spec.js

@@ -18,7 +18,7 @@ describe('Multi(*) operation', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(8);
+      expect(sto.applyStore('a').number).toEqual(8);
       done();
     }).catch( err => done(err));
   });

+ 3 - 1
tests/test20.spec.js

@@ -19,7 +19,9 @@ describe('An Array initialization with expressions', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect([sto.applyStore('a').value[0].value,sto.applyStore('a').value[1].value]).toEqual(result);
+      expect([sto.applyStore('a').value[0].number,
+        sto.applyStore('a').value[1].number
+      ]).toEqual(result);
       done();
     });
   });

+ 1 - 1
tests/test21.spec.js

@@ -23,7 +23,7 @@ describe('A call to a function that returns a valid type', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(result);
+      expect(sto.applyStore('a').number).toEqual(result);
       done();
     }).catch(err => done(err));
   });

+ 1 - 1
tests/test24.spec.js

@@ -20,7 +20,7 @@ describe('Command Do...While', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(5);
+      expect(sto.applyStore('a').number).toEqual(5);
       done();
     }).catch( err => done(err));
   });

+ 1 - 1
tests/test25.spec.js

@@ -18,7 +18,7 @@ describe('Assigning an ID to another variable', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('b').value).toEqual(5);
+      expect(sto.applyStore('b').number).toEqual(5);
       done();
     }).catch( err => done(err));
   });

+ 1 - 1
tests/test27.spec.js

@@ -22,7 +22,7 @@ describe('A finite while loop', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(5);
+      expect(sto.applyStore('a').number).toEqual(5);
       done();
     }).catch( err => done(err));
   });

+ 1 - 1
tests/test28.spec.js

@@ -24,7 +24,7 @@ describe('A break command inside a inner while loop', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(5);
+      expect(sto.applyStore('a').number).toEqual(5);
       done();
     }).catch( err => done(err));
   });

+ 1 - 1
tests/test29.spec.js

@@ -20,7 +20,7 @@ describe('A break command inside a for loop', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(0);
+      expect(sto.applyStore('a').number).toEqual(0);
       done();
     }).catch( err => done(err));
   });

+ 1 - 1
tests/test30.spec.js

@@ -30,7 +30,7 @@ describe('A break command inside a switch..case', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(-5);
+      expect(sto.applyStore('a').number).toEqual(-5);
       done();
     }).catch( err => done(err));
   });

+ 1 - 1
tests/test31.spec.js

@@ -29,7 +29,7 @@ describe('A case without return/break', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(6);
+      expect(sto.applyStore('a').number).toEqual(6);
       done();
     }).catch( err => done(err));
   });

+ 1 - 1
tests/test33.spec.js

@@ -30,7 +30,7 @@ describe('A non-const global variable', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(13);
+      expect(sto.applyStore('a').number).toEqual(13);
       done();
     }).catch( err => done(err));
   });

+ 1 - 1
tests/test34.spec.js

@@ -23,7 +23,7 @@ describe('IfThenElse command ', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(10);
+      expect(sto.applyStore('a').number).toEqual(10);
       done();
     }).catch( err => done(err));
   });

+ 1 - 1
tests/test35.spec.js

@@ -27,7 +27,7 @@ describe('A recursive call', function () {
     const parser = new IVProgParser(input, lexer);
     const exec = new IVProgProcessor(parser.parseTree());
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(2);
+      expect(sto.applyStore('a').number).toEqual(2);
       done();
     }).catch( err => done(err));
   });

+ 1 - 1
tests/test37.spec.js

@@ -22,7 +22,7 @@ describe('The read function', function () {
     const exec = new IVProgProcessor(parser.parseTree());
     exec.registerInput(input);
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(255);
+      expect(sto.applyStore('a').number).toEqual(255);
       done();
     }).catch( err => done(err));
   });

+ 1 - 1
tests/test43.spec.js

@@ -24,7 +24,7 @@ describe('The sum of a real and a integer', function () {
     const exec = new IVProgProcessor(parser.parseTree());
     exec.registerInput(input);
     exec.interpretAST().then(sto => {
-      expect(sto.applyStore('a').value).toEqual(5.8 + 0xff);
+      expect(sto.applyStore('a').number).toEqual(5.8 + 0xff);
       localStorage.removeItem('ivprog.lang');
       done();
     }).catch( err => done(err));

+ 32 - 0
tests/test53.spec.js

@@ -0,0 +1,32 @@
+import { IVProgParser } from './../js/ast/ivprogParser';
+import { SemanticAnalyser } from './../js/processor/semantic/semanticAnalyser';
+import { LanguageService } from '../js/services/languageService';
+import { OutputTest } from '../js/util/outputTest';
+import { IVProgProcessor } from '../js/processor/ivprogProcessor';
+
+describe('Math lib modulo function ', function () {
+
+  const code = `programa {
+
+    funcao inicio() {
+      real a = -1.0
+      escreva(Matematica.modulo(a))
+    }
+  }`;
+
+  localStorage.setItem('ivprog.lang', 'pt');
+
+  const lexer = LanguageService.getCurrentLexer();
+  const out = new OutputTest();
+
+  it(`should be executed with no exception`, function (done) {
+    const parser = new IVProgParser(code, lexer);
+    const sem = new SemanticAnalyser(parser.parseTree());
+    const exec = new IVProgProcessor(sem.analyseTree());
+    exec.registerOutput(out);
+    exec.interpretAST().then(_ => {
+      expect(out.list).toEqual(['1.0']);
+      done();
+    }).catch(err => done(err));
+  });
+});

+ 32 - 0
tests/test54.spec.js

@@ -0,0 +1,32 @@
+import { IVProgParser } from './../js/ast/ivprogParser';
+import { SemanticAnalyser } from './../js/processor/semantic/semanticAnalyser';
+import { LanguageService } from '../js/services/languageService';
+import { OutputTest } from '../js/util/outputTest';
+import { IVProgProcessor } from '../js/processor/ivprogProcessor';
+
+describe('A Math lib function ', function () {
+
+  const code = `programa {
+
+    funcao inicio() {
+      real a = 1.0
+      escreva(Matematica.trocar_sinal(a))
+    }
+  }`;
+
+  localStorage.setItem('ivprog.lang', 'pt');
+
+  const lexer = LanguageService.getCurrentLexer();
+  const out = new OutputTest();
+
+  it(`should be executed with no exception`, function (done) {
+    const parser = new IVProgParser(code, lexer);
+    const sem = new SemanticAnalyser(parser.parseTree());
+    const exec = new IVProgProcessor(sem.analyseTree());
+    exec.registerOutput(out);
+    exec.interpretAST().then(_ => {
+      expect(out.list).toEqual(['-1.0']);
+      done();
+    }).catch(err => done(err));
+  });
+});

+ 25 - 0
tests/test55.spec.js

@@ -0,0 +1,25 @@
+import { IVProgParser } from './../js/ast/ivprogParser';
+import { SemanticAnalyser } from './../js/processor/semantic/semanticAnalyser';
+import { LanguageService } from '../js/services/languageService';
+
+describe('Math lib with no Lib mention ', function () {
+
+  const code = `programa {
+
+    funcao inicio() {
+      real a = 1.0
+      escreva(trocar_sinal(a))
+    }
+  }`;
+
+  localStorage.setItem('ivprog.lang', 'pt');
+
+  const lexer = LanguageService.getCurrentLexer();
+
+  it(`should throw an exception`, function () {
+    const parser = new IVProgParser(code, lexer);
+    const sem = new SemanticAnalyser(parser.parseTree());
+    const fun = sem.analyseTree.bind(sem);
+    expect(fun).toThrow();
+  });
+});

+ 32 - 0
tests/test56.spec.js

@@ -0,0 +1,32 @@
+import { IVProgParser } from './../js/ast/ivprogParser';
+import { SemanticAnalyser } from './../js/processor/semantic/semanticAnalyser';
+import { LanguageService } from '../js/services/languageService';
+import { OutputTest } from '../js/util/outputTest';
+import { IVProgProcessor } from '../js/processor/ivprogProcessor';
+
+describe('Cast to int function ', function () {
+
+  const code = `programa {
+
+    funcao inicio() {
+      cadeia a = "1"
+      escreva(como_inteiro(a))
+    }
+  }`;
+
+  localStorage.setItem('ivprog.lang', 'pt');
+
+  const lexer = LanguageService.getCurrentLexer();
+  const out = new OutputTest();
+
+  it(`should be executed with no exception`, function (done) {
+    const parser = new IVProgParser(code, lexer);
+    const sem = new SemanticAnalyser(parser.parseTree());
+    const exec = new IVProgProcessor(sem.analyseTree());
+    exec.registerOutput(out);
+    exec.interpretAST().then(_ => {
+      expect(out.list).toEqual(['1']);
+      done();
+    }).catch(err => done(err));
+  });
+});

+ 32 - 0
tests/test57.spec.js

@@ -0,0 +1,32 @@
+import { IVProgParser } from './../js/ast/ivprogParser';
+import { SemanticAnalyser } from './../js/processor/semantic/semanticAnalyser';
+import { LanguageService } from '../js/services/languageService';
+import { OutputTest } from '../js/util/outputTest';
+import { IVProgProcessor } from '../js/processor/ivprogProcessor';
+
+describe('Is_Real function ', function () {
+
+  const code = `programa {
+
+    funcao inicio() {
+      cadeia a = "1.2"
+      escreva(e_real(a))
+    }
+  }`;
+
+  localStorage.setItem('ivprog.lang', 'pt');
+
+  const lexer = LanguageService.getCurrentLexer();
+  const out = new OutputTest();
+
+  it(`should return true if the string is valid real representation`, function (done) {
+    const parser = new IVProgParser(code, lexer);
+    const sem = new SemanticAnalyser(parser.parseTree());
+    const exec = new IVProgProcessor(sem.analyseTree());
+    exec.registerOutput(out);
+    exec.interpretAST().then(_ => {
+      expect(out.list).toEqual([true]);
+      done();
+    }).catch(err => done(err));
+  });
+});