Переглянути джерело

Merge branch 'store-rework' of LInE/ivprog into master

Lucas de Souza 5 роки тому
батько
коміт
86af582b4f
51 змінених файлів з 1687 додано та 1092 видалено
  1. 17 1
      .eslintrc.json
  2. 1 0
      .gitignore
  3. 3 1
      i18n/pt/error.json
  4. 4 0
      js/ast/commands/arrayDeclaration.js
  5. 5 5
      js/ast/ivprogParser.js
  6. 15 0
      js/memory/address.ts
  7. 117 0
      js/memory/location.ts
  8. 0 0
      js/processor/context.ts
  9. 12 0
      js/processor/error/processorErrorFactory.js
  10. 305 358
      js/processor/ivprogProcessor.js
  11. 10 7
      js/processor/lib/arrays.js
  12. 22 16
      js/processor/lib/io.js
  13. 53 32
      js/processor/lib/lang.js
  14. 52 61
      js/processor/lib/math.js
  15. 19 13
      js/processor/lib/strings.js
  16. 0 0
      js/processor/modes.ts
  17. 25 11
      js/processor/semantic/semanticAnalyser.js
  18. 0 111
      js/processor/store/store.js
  19. 253 0
      js/processor/store/store.ts
  20. 0 54
      js/processor/store/storeObject.js
  21. 77 0
      js/processor/store/storeObject.ts
  22. 0 76
      js/processor/store/storeObjectArray.js
  23. 140 0
      js/processor/store/storeObjectArray.ts
  24. 0 101
      js/processor/store/storeObjectArrayAddress.js
  25. 0 43
      js/processor/store/storeObjectArrayAddressRef.js
  26. 0 43
      js/processor/store/storeObjectRef.js
  27. 34 0
      js/processor/store/storeObjectRef.ts
  28. 24 0
      js/processor/store/store_object_array_ref.ts
  29. 97 0
      js/processor/store/value/array_store_value.ts
  30. 24 0
      js/processor/store/value/array_store_value_ref.ts
  31. 9 0
      js/processor/store/value/istore_value.ts
  32. 26 0
      js/processor/store/value/store_value.ts
  33. 9 0
      js/processor/store/value/store_value_address.ts
  34. 32 0
      js/processor/store/value/store_value_ref.ts
  35. 11 2
      js/runner.js
  36. 0 40
      js/typeSystem/array_type.js
  37. 50 0
      js/typeSystem/array_type.ts
  38. 0 27
      js/typeSystem/baseTypes.js
  39. 11 0
      js/typeSystem/itype.ts
  40. 0 38
      js/typeSystem/multiType.js
  41. 35 0
      js/typeSystem/multiType.ts
  42. 0 28
      js/typeSystem/type.js
  43. 14 0
      js/typeSystem/type.ts
  44. 0 21
      js/typeSystem/types.js
  45. 36 0
      js/typeSystem/types.ts
  46. 37 0
      js/util/maybe.ts
  47. 4 0
      js/util/utils.js
  48. 84 3
      package-lock.json
  49. 2 0
      package.json
  50. 10 0
      tsconfig.json
  51. 8 0
      webpack.config.js

+ 17 - 1
.eslintrc.json

@@ -3,7 +3,9 @@
         "browser": true,
         "es6": true
     },
-    "extends": "eslint:recommended",
+    "parser": "@typescript-eslint/parser",
+    "plugins": ["@typescript-eslint"],
+    "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
     "globals": {
         "Atomics": "readonly",
         "SharedArrayBuffer": "readonly"
@@ -13,5 +15,19 @@
         "sourceType": "module"
     },
     "rules": {
+        "camelcase": "off",
+        "no-unused-vars": "off",
+        "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
+        "@typescript-eslint/camelcase": "off"
     }
+    ,
+    "overrides": [
+        {
+            "files": ["*.js", "*.jsx"],
+            "rules": {
+                "@typescript-eslint/explicit-member-accessibility": 0,
+                "@typescript-eslint/explicit-function-return-type": 0
+            }
+        }
+    ]    
 }

+ 1 - 0
.gitignore

@@ -1,5 +1,6 @@
 #compiled files
 /build
+/dist
 .ima_version.json
 ivprog.tar.gz
 # dependencies

+ 3 - 1
i18n/pt/error.json

@@ -104,5 +104,7 @@
   "matrix_to_vector_attr":  "Erro na linha $0: $1 representa uma matriz e não pode ser atribuída ao vetor $2.",
   "vector_to_matrix_attr":  "Err na linha $0: $1 representa um vetor e não pode ser atribuído a matriz $2.",
   "invalid_const_ref_full": "A variável $0 fornecida como parâmetro para a função $1 na linha $2 é uma constante e não pode ser usada neste contexto. Use uma variável ou posição de vetor.",
-  "invalid_const_ref": "A variável $0 fornecida como parâmetro para a função $1 é uma constante e não pode ser usada neste contexto. Use uma variável ou posição de vetor."
+  "invalid_const_ref": "A variável $0 fornecida como parâmetro para a função $1 é uma constante e não pode ser usada neste contexto. Use uma variável ou posição de vetor.",
+  "invalid_const_assignment_full": "Erro na linha $0: $1 é uma constante e portanto não pode ter seu valor alterado",
+  "invalid_const_assignment": "$0 é uma constante e portanto não pode ter seu valor alterado"
 }

+ 4 - 0
js/ast/commands/arrayDeclaration.js

@@ -7,4 +7,8 @@ export class ArrayDeclaration extends Declaration {
     this.lines = lines;
     this.columns = columns;
   }
+
+  get isVector () {
+    return this.columns == null;
+  }
 }

+ 5 - 5
js/ast/ivprogParser.js

@@ -1,14 +1,14 @@
 import { CommonTokenStream, InputStream } from 'antlr4/index';
-import * as Expressions from './expressions/';
-import * as Commands from './commands/';
+import * as Expressions from './expressions';
+import * as Commands from './commands';
 import * as AstHelpers from "./ast_helpers";
-import { toInt, toString, toBool, toReal } from './../typeSystem/parsers';
-import { Types } from "./../typeSystem/types";
+import { toInt, toString, toBool, toReal } from '../typeSystem/parsers';
+import { Types } from "../typeSystem/types";
 import { ArrayType } from "../typeSystem/array_type";
 import { SourceInfo } from './sourceInfo';
 import { convertFromString } from './operators';
 import { SyntaxErrorFactory } from './error/syntaxErrorFactory';
-import { LanguageDefinedFunction } from './../processor/definedFunctions';
+import { LanguageDefinedFunction } from '../processor/definedFunctions';
 import { LanguageService } from '../services/languageService';
 
 export class IVProgParser {

+ 15 - 0
js/memory/address.ts

@@ -0,0 +1,15 @@
+export class Address {
+
+  public id: number;
+  public value: any;
+
+  /**
+   * 
+   * @param {Number} id the address id
+   * @param {*} value the value stored at this address
+   */
+  constructor (id: number, value: any) {
+    this.id = id;
+    this.value = value;
+  }
+}

+ 117 - 0
js/memory/location.ts

@@ -0,0 +1,117 @@
+
+import { Address } from "./address";
+
+class LocationHolder {
+
+  public data: Address[];
+  private address_id: number
+
+  constructor () {
+    this.data = [];
+    this.address_id = 0;
+  }
+
+  /**
+   * 
+   * @param {*} value the value to be allocated
+   * @returns {Number} - the address id
+   */
+  allocate (value:any) : number {
+    const id = this.address_id;
+    // console.log("Allocation address "+ id);
+    const address = new Address(id, value);
+    this.data.push(address);
+    this.address_id += 1;
+    return id;
+  }
+
+  /**
+   * 
+   * @param {Number} id 
+   */
+  deallocate (id: number) : boolean {
+    const index = this.findIndex(id);
+    // console.log("Deallocation address "+ id);
+    if(index !== -1) {
+      this.data.splice(index, 1);
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * 
+   * @param {Number} id 
+   * @returns {Address} the address identified by id
+   */
+  find (id: number): Address | undefined {
+    let beg = 0
+    let end = this.data.length;
+    // console.log("Finding address "+id);
+    while (beg < end) {
+      const med = Math.floor((beg + end)/2);
+      const address = this.getAddressAt(med);
+      if(address.id === id) {
+        return address;
+      } else if (id > address.id) {
+        beg = med;
+      } else {
+        end = med
+      }
+    }
+    return undefined;
+  }
+
+  getAddressAt (pos: number): Address {
+    return this.data[pos];
+  }
+
+  /**
+   * 
+   * @param {Number} id address id
+   * @returns {Number} the index of the address identified by id
+   */
+  findIndex (id: number) : number {
+    let beg = 0
+    let end = this.data.length;
+    while (beg < end) {
+      const med = Math.floor((beg + end)/2);
+      const address = this.getAddressAt(med);
+      if(address.id === id) {
+        return med;
+      } else if (id > address.id) {
+        beg = med;
+      } else {
+        end = med
+      }
+    }
+    return -1;
+  }
+
+  updateAddress (id: number, value: any): void {
+    const index = this.findIndex(id);
+    if(index === -1) {
+      throw new Error("Invalid address..." + id);
+    }
+    this.data[index].value = value;
+  }
+
+  clear () {
+    for (let i = 0; i < this.data.length; i += 1) {
+      delete this.data[i];
+    }
+    this.data = [];
+    this.address_id = 0;
+  }
+}
+
+const inner_ref = new LocationHolder();
+
+export const Location = Object.freeze({
+  allocate: inner_ref.allocate.bind(inner_ref),
+  deallocate: inner_ref.deallocate.bind(inner_ref),
+  find: inner_ref.find.bind(inner_ref),
+  updateAddress: inner_ref.updateAddress.bind(inner_ref),
+  clear: inner_ref.clear.bind(inner_ref),
+  size: () => inner_ref.data.length
+});

js/processor/context.js → js/processor/context.ts


+ 12 - 0
js/processor/error/processorErrorFactory.js

@@ -399,5 +399,17 @@ export const ProcessorErrorFactory  = Object.freeze({
   invalid_const_ref: (fun_name, exp) => {
     const context = [exp, LanguageDefinedFunction.getLocalName(fun_name)];
     return new SemanticError(LocalizedStrings.getError("invalid_const_ref", context));
+  },
+  invalid_const_assignment_full: (var_id, source_info) => {
+    if(source_info) {
+      const context = [source_info.line, var_id];
+      return new SemanticError(LocalizedStrings.getError("invalid_const_assignment_full", context));
+    } else {
+      return ProcessorErrorFactory.invalid_const_assignment(var_id);
+    }
+  },
+  invalid_const_assignment: (var_id) => {
+    const context = [var_id];
+    return new SemanticError(LocalizedStrings.getError("invalid_const_assignment", context));
   }
 });

Різницю між файлами не показано, бо вона завелика
+ 305 - 358
js/processor/ivprogProcessor.js


+ 10 - 7
js/processor/lib/arrays.js

@@ -1,9 +1,9 @@
-import { StoreObject } from '../store/storeObject';
 import * as Commands from './../../ast/commands';
 import { Types } from './../../typeSystem/types';
 import { toInt } from "./../../typeSystem/parsers";
 import { ArrayType } from '../../typeSystem/array_type';
 import { Modes } from '../modes';
+import { StoreValue } from '../store/value/store_value';
 
 /**
  * num_elements
@@ -14,9 +14,10 @@ import { Modes } from '../modes';
 export function createNumElementsFun () {
   const numElementsFun = (sto, _) => {
     const vector  = sto.applyStore("vector");
-    const temp = new StoreObject(Types.INTEGER, toInt(vector.lines));
+    const temp = new StoreValue(Types.INTEGER, toInt(vector.lines));
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", temp));
+    sto.insertStore("$", temp);
+    return Promise.resolve(sto);
   }
 
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(numElementsFun)]);
@@ -29,9 +30,10 @@ export function createNumElementsFun () {
 export function createMatrixLinesFun () {
   const matrixLinesFun = (sto, _) => {
     const matrix  = sto.applyStore("matrix");
-    const temp = new StoreObject(Types.INTEGER, toInt(matrix.lines));
+    const temp = new StoreValue(Types.INTEGER, toInt(matrix.lines));
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", temp));
+    sto.insertStore("$", temp);
+    return Promise.resolve(sto);
   }
 
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(matrixLinesFun)]);
@@ -44,9 +46,10 @@ export function createMatrixLinesFun () {
 export function createMatrixColumnsFun () {
   const matrixColumnsFun = (sto, _) => {
     const matrix  = sto.applyStore("matrix");
-    const temp = new StoreObject(Types.INTEGER, toInt(matrix.columns));
+    const temp = new StoreValue(Types.INTEGER, toInt(matrix.columns));
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", temp));
+    sto.insertStore("$", temp);
+    return Promise.resolve(sto);
   }
 
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(matrixColumnsFun)]);

+ 22 - 16
js/processor/lib/io.js

@@ -1,15 +1,14 @@
-import { StoreObject } from './../store/storeObject';
 import * as Commands from './../../ast/commands';
 import { Modes } from '../modes';
 import {toInt, toString, toBool, toReal, convertToString} from './../../typeSystem/parsers';
 import { Types } from './../../typeSystem/types';
 import { ProcessorErrorFactory } from "./../error/processorErrorFactory";
-import { StoreObjectArrayAddressRef } from '../store/storeObjectArrayAddressRef';
+import { StoreValue } from '../store/value/store_value';
 
 export function createOutputFun () {
   const writeFunction = function (store, _) {
     const val = store.applyStore('p1');
-    this.output.sendOutput(convertToString(val.value, val.type));
+    this.output.sendOutput(convertToString(val.get(), val.type));
     store.mode = Modes.RETURN;
     return Promise.resolve(store);
   }
@@ -27,33 +26,40 @@ export function createInputFun () {
     });
     return request.then(text => {
       const typeToConvert = store.applyStore('p1').type;
-      let stoObj = null;
+      let type = null
+      let result = null;
       try {
         if (typeToConvert.isCompatible(Types.INTEGER)) {
-          const val = toInt(text);
-          stoObj = new StoreObject(Types.INTEGER, val.trunc());
+          result = toInt(text).trunc();
+          type = Types.INTEGER;
         } else if (typeToConvert.isCompatible(Types.REAL)) {
-          stoObj = new StoreObject(Types.REAL, toReal(text));
+          result = toReal(text)
+          type = Types.REAL;
         } else if (typeToConvert.isCompatible(Types.BOOLEAN)) {
-          stoObj = new StoreObject(Types.BOOLEAN, toBool(text));
+          result = toBool(text)
+          type = Types.BOOLEAN;
         } else if (typeToConvert.isCompatible(Types.STRING)) {
-          stoObj = new StoreObject(Types.STRING, toString(text));
+          result = toString(text)
+          type  = Types.STRING;
         } else {
           return Promise.reject(new Error("!!!!Critical error: Unknown type in readFunction!!!!"));
-        }  
+        }
       } catch (_) {
         const stringInfo = typeToConvert.stringInfo()[0]
         const realObject = store.getStoreObject("p1");
-        if (realObject instanceof StoreObjectArrayAddressRef) {
-          const arrayInfo = realObject.address.getArrayObject().type.stringInfo()[0];
-          const error = ProcessorErrorFactory.invalid_read_type_array(text, stringInfo.type, stringInfo.dim, realObject.address.refID, arrayInfo.type, arrayInfo.dim);
+        console.log(realObject);
+        if (realObject.getReferenceDimension() > 0) {
+          const arrayInfo = realObject.type.stringInfo()[0];
+          const dim = realObject.getReferenceDimension();
+          const error = ProcessorErrorFactory.invalid_read_type_array(text, stringInfo.type, stringInfo.dim, realObject.getRefObj(), arrayInfo.type, dim);
           return Promise.reject(error);
         }
-        const error = ProcessorErrorFactory.invalid_read_type(text, stringInfo.type, stringInfo.dim, store.applyStore('p1').id);
+        const error = ProcessorErrorFactory.invalid_read_type(text, stringInfo.type, stringInfo.dim, realObject.getRefObj());
         return Promise.reject(error);
       }
-      this.loopTimers.splice(0,this.loopTimers.length)
-      store.updateStore('p1', stoObj);
+      this.loopTimers.splice(0, this.loopTimers.length)
+      const stoValue = new StoreValue(type, result);
+      store.updateStore('p1', stoValue);
       store.mode = Modes.RETURN;
       return Promise.resolve(store);
     });

+ 53 - 32
js/processor/lib/lang.js

@@ -1,4 +1,3 @@
-import { StoreObject } from '../store/storeObject';
 import * as Commands from './../../ast/commands';
 import { Types } from './../../typeSystem/types';
 import { toReal, convertToString } from "./../../typeSystem/parsers";
@@ -7,6 +6,7 @@ import { RealLiteral, IntLiteral, BoolLiteral } from '../../ast/expressions';
 import { Modes } from '../modes';
 import { MultiType } from '../../typeSystem/multiType';
 import { ProcessorErrorFactory } from '../error/processorErrorFactory';
+import { StoreValue } from '../store/value/store_value';
 
 /**
  * 
@@ -22,17 +22,20 @@ import { ProcessorErrorFactory } from '../error/processorErrorFactory';
 export function createIsRealFun () {
   const isRealFun = (sto, _) => {
     const str = sto.applyStore("str");
-    const parser = IVProgParser.createParser(str.value);
+    const parser = IVProgParser.createParser(str.get());
     let result = false;
     try {
       const val = parser.parseTerm();
       if (val instanceof RealLiteral) {
         result = true;
       }
-    } catch (error) { }
-    const temp = new StoreObject(Types.BOOLEAN, result);
+    } catch (error) {
+      // ignore
+     }
+    const temp = new StoreValue(Types.BOOLEAN, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", temp));
+    return Promise.resolve(sto);
   }
 
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(isRealFun)]);
@@ -45,17 +48,20 @@ export function createIsRealFun () {
 export function createIsIntFun () {
   const isIntFun = (sto, _) => {
     const str = sto.applyStore("str");
-    const parser = IVProgParser.createParser(str.value);
+    const parser = IVProgParser.createParser(str.get());
     let result = false;
     try {
       const val = parser.parseTerm();
       if (val instanceof IntLiteral) {
         result = true;
       }
-    } catch (error) { }
-    const temp = new StoreObject(Types.BOOLEAN, result);
+    } catch { 
+      // ignore
+    }
+    const temp = new StoreValue(Types.BOOLEAN, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", temp));
+    return Promise.resolve(sto);
   }
 
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(isIntFun)]);
@@ -68,17 +74,20 @@ export function createIsIntFun () {
 export function createIsBoolFun () {
   const isBoolFun = (sto, _) => {
     const str = sto.applyStore("str");
-    const parser = IVProgParser.createParser(str.value);
+    const parser = IVProgParser.createParser(str.get());
     let result = false;
     try {
       const val = parser.parseTerm();
       if (val instanceof BoolLiteral) {
         result = true;
       }
-    } catch (error) { }
-    const temp = new StoreObject(Types.BOOLEAN, result);
+    } catch (error) { 
+      // ignore
+    }
+    const temp = new StoreValue(Types.BOOLEAN, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", temp));
+    return Promise.resolve(sto);
   }
 
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(isBoolFun)]);
@@ -91,24 +100,28 @@ export function createIsBoolFun () {
 export function createCastRealFun () {
   const castRealFun = (sto, _) => {
     const val = sto.applyStore("val");
-    let value = val.value;
+    let value = val.get();
     switch (val.type.ord) {
       case Types.INTEGER.ord: {
         value = value.toNumber();
-        const temp = new StoreObject(Types.REAL, toReal(value));
+        const temp = new StoreValue(Types.REAL, toReal(value));
+        sto.insertStore("$", temp);
         sto.mode = Modes.RETURN;
-        return Promise.resolve(sto.updateStore("$", temp));
+        return Promise.resolve(sto);
       }
       case Types.STRING.ord: {
         const parser = IVProgParser.createParser(value);
         try {
           const result = parser.parseTerm();
           if (result instanceof RealLiteral) {
-            const temp = new StoreObject(Types.REAL, result.value);
+            const temp = new StoreValue(Types.REAL, result.value);
+            sto.insertStore("$", temp);
             sto.mode = Modes.RETURN;
-            return Promise.resolve(sto.updateStore("$", temp));
+            return Promise.resolve(sto);
           }
-        } catch (error) { }
+        } catch (error) {
+          // ignore
+         }
       }
     }
     const typeStringInfoArray = Types.REAL.stringInfo();
@@ -126,24 +139,28 @@ export function createCastRealFun () {
 export function createCastIntFun () {
   const castIntFun = (sto, _) => {
     const val = sto.applyStore("val");
-    let value = val.value;
+    let value = val.get();
     switch (val.type.ord) {
       case Types.REAL.ord: {
         value = value.toNumber();
-        const temp = new StoreObject(Types.INTEGER, Math.floor(value));
+        const temp = new StoreValue(Types.INTEGER, Math.floor(value));
+        sto.insertStore("$", temp);
         sto.mode = Modes.RETURN;
-        return Promise.resolve(sto.updateStore("$", temp));
+        return Promise.resolve(sto);
       }
       case Types.STRING.ord: {
         const parser = IVProgParser.createParser(value);
         try {
           const result = parser.parseTerm();
           if (result instanceof IntLiteral) {
-            const temp = new StoreObject(Types.INTEGER, result.value);
+            const temp = new StoreValue(Types.INTEGER, result.value);
+            sto.insertStore("$", temp);
             sto.mode = Modes.RETURN;
-            return Promise.resolve(sto.updateStore("$", temp));
+            return Promise.resolve(sto);
           }
-        } catch (error) { }
+        } catch (error) { 
+          // ignore
+        }
       }
     }
     const typeStringInfoArray = Types.INTEGER.stringInfo();
@@ -161,16 +178,19 @@ export function createCastIntFun () {
 export function createCastBoolFun () {
   const castBoolFun = (sto, _) => {
     const str = sto.applyStore("str");
-    let value = str.value; 
+    const value = str.get(); 
     const parser = IVProgParser.createParser(value);
     try {
       const val = parser.parseTerm();
       if (val instanceof BoolLiteral) {
-        const temp = new StoreObject(Types.BOOLEAN, val.value);
+        const temp = new StoreValue(Types.BOOLEAN, val.value);
+        sto.insertStore("$", temp);
         sto.mode = Modes.RETURN;
-        return Promise.resolve(sto.updateStore("$", temp));
+        return Promise.resolve(sto);
       }
-    } catch (error) { }
+    } catch (error) { 
+      // ignore
+    }
     const typeStringInfoArray = Types.BOOLEAN.stringInfo();
     const typeInfo = typeStringInfoArray[0];
     return Promise.reject(ProcessorErrorFactory.invalid_type_conversion(value, typeInfo.type, typeInfo.dim));
@@ -186,10 +206,11 @@ export function createCastBoolFun () {
 export function createCastStringFun () {
   const castStringFun = function (store, _) {
     const val = store.applyStore('str');
-    let result = convertToString(val, val.type);
-    const temp = new StoreObject(Types.STRING, result);
+    const result = convertToString(val.get(), val.type);
+    const temp = new StoreValue(Types.STRING, result);
+    store.insertStore("$", temp);
     store.mode = Modes.RETURN;
-    return Promise.resolve(store.updateStore("$", temp));
+    return Promise.resolve(store);
   }
   const block = new Commands.CommandBlock([], [new Commands.SysCall(castStringFun)]);
   const func = new Commands.Function('$castString', Types.STRING,

+ 52 - 61
js/processor/lib/math.js

@@ -1,4 +1,3 @@
-import { StoreObject } from '../store/storeObject';
 import * as Commands from './../../ast/commands';
 import { Types } from './../../typeSystem/types';
 import { toReal } from "./../../typeSystem/parsers";
@@ -6,7 +5,7 @@ import { Decimal } from 'decimal.js';
 import { MultiType } from '../../typeSystem/multiType';
 import { ArrayType } from '../../typeSystem/array_type';
 import { Modes } from '../modes';
-import { Config } from '../../util/config';
+import { StoreValue } from '../store/value/store_value';
 
 /**
  * sin
@@ -29,7 +28,7 @@ function convertToRadians (degrees) {
 export function createSinFun () {
    const sinFun = (sto, _) => {
      const x = sto.applyStore('x');
-     const angle = x.value.mod(360);
+     const angle = x.get().mod(360);
      let result = null;
      if(angle.eq(90)) {
        result = new Decimal(1);
@@ -40,12 +39,10 @@ export function createSinFun () {
      } else {
        result = Decimal.sin(convertToRadians(angle));
      }
-    //  if(result.dp() > Config.decimalPlaces) {
-    //   result = new Decimal(result.toFixed(Config.decimalPlaces));
-    // }
-     const temp = new StoreObject(Types.REAL, result);
+     const temp = new StoreValue(Types.REAL, result);
+     sto.insertStore("$", temp);
      sto.mode = Modes.RETURN;
-     return Promise.resolve(sto.updateStore('$', temp));
+     return Promise.resolve(sto);
    };
 
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(sinFun)]);
@@ -58,7 +55,7 @@ export function createSinFun () {
 export function createCosFun () {
   const cosFun = (sto, _) => {
     const x = sto.applyStore('x');
-    const angle = x.value.mod(360);
+    const angle = x.get().mod(360);
     let result = null;
     if(angle.eq(90)) {
       result = new Decimal(0);
@@ -68,12 +65,10 @@ export function createCosFun () {
       result = new Decimal(0)
     }
     result = Decimal.cos(convertToRadians(angle));
-    // if(result.dp() > Config.decimalPlaces) {
-    //   result = new Decimal(result.toFixed(Config.decimalPlaces));
-    // }
-    const temp = new StoreObject(Types.REAL, result);
+    const temp = new StoreValue(Types.REAL, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore('$', temp));
+    return Promise.resolve(sto);
   };
 
  const block = new Commands.CommandBlock([],  [new Commands.SysCall(cosFun)]);
@@ -86,17 +81,16 @@ export function createCosFun () {
 export function createTanFun () {
   const tanFun = (sto, _) => {
     const x = sto.applyStore('x');
-    const angle = x.value.mod(360);
+    const angle = x.get().mod(360);
     if(angle.eq(90) || angle.eq(270)) {
-      return Promise.reject("Tangent of "+x.value.toNumber()+"° is undefined.");
+      // TODO better error message
+      return Promise.reject("Tangent of "+x.get().toNumber()+"° is undefined.");
     }
-    let result = Decimal.tan(convertToRadians(angle));
-    // if(result.dp() > Config.decimalPlaces) {
-    //   result = new Decimal(result.toFixed(Config.decimalPlaces));
-    // }
-    const temp = new StoreObject(Types.REAL, result);
+    const result = Decimal.tan(convertToRadians(angle));
+    const temp = new StoreValue(Types.REAL, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore('$', temp));
+    return Promise.resolve(sto);
   };
 
  const block = new Commands.CommandBlock([],  [new Commands.SysCall(tanFun)]);
@@ -109,13 +103,11 @@ export function createTanFun () {
 export function createSqrtFun () {
   const sqrtFun = (sto, _) => {
     const x = sto.applyStore('x');
-    let result = x.value.sqrt();
-    // if(result.dp() > Config.decimalPlaces) {
-    //   result = new Decimal(result.toFixed(Config.decimalPlaces));
-    // }
-    const temp = new StoreObject(Types.REAL, result);
+    const result = x.get().sqrt();
+    const temp = new StoreValue(Types.REAL, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore('$', temp));
+    return Promise.resolve(sto);
   };
 
  const block = new Commands.CommandBlock([],  [new Commands.SysCall(sqrtFun)]);
@@ -129,13 +121,11 @@ export function createPowFun () {
   const powFun = (sto, _) => {
     const x = sto.applyStore('x');
     const y = sto.applyStore('y');
-    let result = x.value.pow(y.value);
-    // if(result.dp() > Config.decimalPlaces) {
-    //   result = new Decimal(result.toFixed(Config.decimalPlaces));
-    // }
-    const temp = new StoreObject(Types.REAL, result);
+    const result = x.get().pow(y.get());
+    const temp = new StoreValue(Types.REAL, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore('$', temp));
+    return Promise.resolve(sto);
   };
 
  const block = new Commands.CommandBlock([],  [new Commands.SysCall(powFun)]);
@@ -149,16 +139,15 @@ export function createPowFun () {
 export function createLogFun () {
   const logFun = (sto, _) => {
     const x = sto.applyStore('x');
-    if (x.value.isNegative()) {
+    if (x.get().isNegative()) {
+      // TODO better error message
       return Promise.reject(new Error("the value passed to log function cannot be negative"));
     }
-    let result = Decimal.log10(x.value);
-    // if(result.dp() > Config.decimalPlaces) {
-    //   result = new Decimal(result.toFixed(Config.decimalPlaces));
-    // }
-    const temp = new StoreObject(Types.REAL, result);
+    const result = Decimal.log10(x.get());
+    const temp = new StoreValue(Types.REAL, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore('$', temp));
+    return Promise.resolve(sto);
   };
 
  const block = new Commands.CommandBlock([],  [new Commands.SysCall(logFun)]);
@@ -171,9 +160,9 @@ export function createLogFun () {
 export function createAbsFun () {
   const absFun = (sto, _) => {
     const x = sto.applyStore('x');
-    const result = x.value.abs();
-    const temp = new StoreObject(x.type, result);
-    sto.updateStore('$', temp)
+    const result = x.get().abs();
+    const temp = new StoreValue(x.type, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
     return Promise.resolve(sto);
   };
@@ -188,10 +177,11 @@ export function createAbsFun () {
 export function createNegateFun () {
   const negateFun = (sto, _) => {
     const x = sto.applyStore('x');
-    const result = x.value.negated();
-    const temp = new StoreObject(x.type, result);
+    const result = x.get().negated();
+    const temp = new StoreValue(x.type, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore('$', temp));
+    return Promise.resolve(sto);
   };
 
  const block = new Commands.CommandBlock([],  [new Commands.SysCall(negateFun)]);
@@ -204,13 +194,11 @@ export function createNegateFun () {
 export function createInvertFun () {
   const invertFun = (sto, _) => {
     const x = sto.applyStore('x');
-    let result = toReal(1).dividedBy(x.value);
-    // if(result.dp() > Config.decimalPlaces) {
-    //   result = new Decimal(result.toFixed(Config.decimalPlaces));
-    // }
-    const temp = new StoreObject(Types.REAL, result);
+    const result = toReal(1).dividedBy(x.get());
+    const temp = new StoreValue(Types.REAL, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore('$', temp));
+    return Promise.resolve(sto);
   };
 
  const block = new Commands.CommandBlock([],  [new Commands.SysCall(invertFun)]);
@@ -223,11 +211,12 @@ export function createInvertFun () {
 export function createMaxFun () {
   const maxFun = (sto, _) => {
     const x = sto.applyStore('x');
-    const numbers = x.value.map(stoObj => stoObj.value);
+    const numbers = x.get().map(sto_addrs => sto_addrs.get());
     const result = Decimal.max(...numbers);
-    const temp = new StoreObject(x.type.innerType, result);
+    const temp = new StoreValue(x.type.innerType, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore('$', temp));
+    return Promise.resolve(sto);
   };
  const paramType = new ArrayType(new MultiType([Types.INTEGER, Types.REAL]), 1);
  const block = new Commands.CommandBlock([],  [new Commands.SysCall(maxFun)]);
@@ -240,11 +229,12 @@ export function createMaxFun () {
 export function createMinFun () {
   const minFun = (sto, _) => {
     const x = sto.applyStore('x');
-    const numbers = x.value.map(stoObj => stoObj.value);
+    const numbers = x.get().map(sto_addrs => sto_addrs.get());
     const result = Decimal.min(...numbers);
-    const temp = new StoreObject(x.type.innerType, result);
+    const temp = new StoreValue(x.type.innerType, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore('$', temp));
+    return Promise.resolve(sto);
   };
  const paramType = new ArrayType(new MultiType([Types.INTEGER, Types.REAL]), 1);
  const block = new Commands.CommandBlock([],  [new Commands.SysCall(minFun)]);
@@ -257,9 +247,10 @@ export function createMinFun () {
 export function createRandFun () {
   const randFun = (sto, _) => {
     const val = Math.random();
-    const result = new StoreObject(Types.REAL, new Decimal(val));
+    const temp = new StoreValue(Types.REAL, new Decimal(val));
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", result));
+    return Promise.resolve(sto);
   };
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(randFun)]);
   const func = new Commands.Function('$rand', Types.REAL, [], block);

+ 19 - 13
js/processor/lib/strings.js

@@ -1,8 +1,8 @@
-import { StoreObject } from '../store/storeObject';
 import * as Commands from './../../ast/commands';
 import { Types } from './../../typeSystem/types';
 import { toInt } from "./../../typeSystem/parsers";
 import { Modes } from '../modes';
+import { StoreValue } from '../store/value/store_value';
 
 /*
 *  substring
@@ -17,10 +17,11 @@ export function createSubstringFun () {
     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);
+    const result = str.get().substring(start.get(), end.get());
+    const temp = new StoreValue(Types.STRING, result);
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", temp));
+    return Promise.resolve(sto);
   };
 
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(substringFun)]);
@@ -35,9 +36,10 @@ export function createSubstringFun () {
 export function createLengthFun () {
   const lengthFun = (sto, _) => {
     const str = sto.applyStore("str");
-    const temp = new StoreObject(Types.INTEGER, toInt(str.value.length));
+    const temp = new StoreValue(Types.INTEGER, toInt(str.value.length));
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", temp));
+    return Promise.resolve(sto);
   }
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(lengthFun)]);
   const func = new Commands.Function('$length', Types.INTEGER,
@@ -49,9 +51,10 @@ export function createLengthFun () {
 export function createUppercaseFun () {
   const uppercaseFun = (sto, _) => {
     const str = sto.applyStore("str");
-    const temp = new StoreObject(Types.STRING, str.value.toUpperCase());
+    const temp = new StoreValue(Types.STRING, str.get().toUpperCase());
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", temp));
+    return Promise.resolve(sto);
   }
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(uppercaseFun)]);
   const func = new Commands.Function('$uppercase', Types.STRING,
@@ -63,9 +66,10 @@ export function createUppercaseFun () {
 export function createLowercaseFun () {
   const lowercaseFun = (sto, _) => {
     const str = sto.applyStore("str");
-    const temp = new StoreObject(Types.STRING, str.value.toLowerCase());
+    const temp = new StoreValue(Types.STRING, str.get().toLowerCase());
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", temp));
+    return Promise.resolve(sto);
   }
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(lowercaseFun)]);
   const func = new Commands.Function('$lowercase', Types.STRING,
@@ -78,12 +82,14 @@ export function createrCharAtFun () {
   const charAtFun = (sto, _) => {
     const str = sto.applyStore("str");
     const idx = sto.applyStore("index");
-    if (idx.value.toNumber() < 0 || idx.value.toNumber() >= str.value.length) {
+    if (idx.get().toNumber() < 0 || idx.get().toNumber() >= str.get().length) {
+      // TODO better error message
       return Promise.reject(new Error("invalid string position"));
     }
-    const temp = new StoreObject(Types.STRING, str.value.charAt(idx.value.toNumber()));
+    const temp = new StoreValue(Types.STRING, str.get().charAt(idx.get().toNumber()));
+    sto.insertStore("$", temp);
     sto.mode = Modes.RETURN;
-    return Promise.resolve(sto.updateStore("$", temp));
+    return Promise.resolve(sto);
   }
   const block = new Commands.CommandBlock([],  [new Commands.SysCall(charAtFun)]);
   const func = new Commands.Function('$charAt', Types.STRING,

js/processor/modes.js → js/processor/modes.ts


+ 25 - 11
js/processor/semantic/semanticAnalyser.js

@@ -104,7 +104,8 @@ export class SemanticAnalyser {
   assertDeclaration (declaration) {
     if (declaration instanceof ArrayDeclaration) {
       this.assertArrayDeclaration(declaration);
-      this.insertSymbol(declaration.id, {id: declaration.id, lines: declaration.lines, columns: declaration.columns, type: declaration.type});
+      this.insertSymbol(declaration.id, {id: declaration.id, lines: declaration.lines,
+        columns: declaration.columns, type: declaration.type, isConst: declaration.isConst});
 
     } else {
       if(declaration.initial === null) {
@@ -272,6 +273,7 @@ export class SemanticAnalyser {
   evaluateArrayLiteral (arrayDeclaration) {
     const type =  arrayDeclaration.type;
     const literal = arrayDeclaration.initial;
+    console.log(arrayDeclaration);
     if(arrayDeclaration.isVector) {
       this.evaluateVectorLiteralType(literal, type);
     } else {
@@ -353,10 +355,14 @@ export class SemanticAnalyser {
 
     } else if (cmd instanceof ArrayIndexAssign) {
       // TODO - rework!!!!!
+      let used_dims = 0;
       const typeInfo = this.findSymbol(cmd.id, this.symbolMap);
       if(typeInfo === null) {
         throw ProcessorErrorFactory.symbol_not_found_full(cmd.id, cmd.sourceInfo);
       }
+      if(typeInfo.isConst) {
+        throw ProcessorErrorFactory.invalid_const_assignment_full(cmd.id, cmd.sourceInfo);
+      }
       if(!(typeInfo.type instanceof ArrayType)) {
         throw ProcessorErrorFactory.invalid_array_access_full(cmd.id, cmd.sourceInfo);
       }
@@ -366,31 +372,35 @@ export class SemanticAnalyser {
       if (!lineType.isCompatible(Types.INTEGER)) {
         throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
       }
+      used_dims += 1;
       const columnExp = cmd.column;
       if (typeInfo.columns === null && columnExp !== null) {
         throw ProcessorErrorFactory.invalid_matrix_access_full(cmd.id, cmd.sourceInfo);
-      } else if (!typeInfo.type.isVector && columnExp == null) {
-        throw new Error("Cannot assign to matrix line");      
       } else if (columnExp !== null) {
         const columnType = this.evaluateExpressionType(columnExp);
         if (!columnType.isCompatible(Types.INTEGER)) {
           throw ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo);
         }
+        used_dims += 1;
       }
       // exp a single value exp or an array access
       const exp_type = this.evaluateExpressionType(exp);
-      if(exp_type instanceof ArrayType) {
-        // TODO better error message
-        throw new Error("Cannot assign a matrix/vector");
-      }
+      const access_type = typeInfo.type;
+
       let compatible = false;
       if(exp_type instanceof MultiType) {
-        compatible = exp_type.isCompatible(typeInfo.type.innerType);
+        let type = access_type;
+        if(access_type.dimensions - used_dims == 0) {
+          type = access_type.innerType
+        } else {
+          type = new ArrayType(access_type.innerType, Math.max(0, access_type.dimensions - used_dims));
+        }
+        compatible = exp_type.isCompatible(type);
       } else {
-        compatible = typeInfo.type.canAccept(exp_type);
+        compatible = access_type.canAccept(exp_type, used_dims);
       }
       if(!compatible) {
-        if(!Config.enable_type_casting || !Store.canImplicitTypeCast(typeInfo.type.innerType, exp_type)) {
+        if(!Config.enable_type_casting || !Store.canImplicitTypeCast(access_type, exp_type)) {
           throw new Error("invalid vector element type");
         }
       }
@@ -401,6 +411,9 @@ export class SemanticAnalyser {
       if(typeInfo === null) {
         throw ProcessorErrorFactory.symbol_not_found_full(cmd.id, cmd.sourceInfo);
       }
+      if(typeInfo.isConst) {
+        throw ProcessorErrorFactory.invalid_const_assignment_full(cmd.id, cmd.sourceInfo);
+      }
       const exp = cmd.expression;
       const exp_type = this.evaluateExpressionType(exp);
       if(exp_type instanceof ArrayType) {
@@ -545,6 +558,7 @@ export class SemanticAnalyser {
   }
 
   evaluateVectorLiteralType (literal, type) {
+    console.log(literal);
     for(let i = 0; i < literal.value.length; i+=1) {
       const exp = literal.value[i];
       const expType = this.evaluateExpressionType(exp);
@@ -552,7 +566,7 @@ export class SemanticAnalyser {
       if(expType instanceof MultiType) {
         compatible = expType.isCompatible(type.innerType);
       } else {
-        compatible = type.canAccept(expType);
+        compatible = type.canAccept(expType, 1);
       }
       if(!compatible) {
         // vector wrong type

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

@@ -1,111 +0,0 @@
-import { Modes } from './../modes';
-import { Types } from "./../../typeSystem/types";
-import { StoreObject } from './storeObject';
-
-export class Store {
-
-  static canImplicitTypeCast (castType, sourceType) {
-    if (castType.isCompatible(Types.INTEGER) || castType.isCompatible(Types.REAL)) {
-      if (sourceType.isCompatible(Types.INTEGER) || sourceType.isCompatible(Types.REAL)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  static doImplicitCasting (castType, stoObj) {
-    if(!Store.canImplicitTypeCast(castType, stoObj.type)) {
-      throw new Error("!!!Critical error: attempted to type cast invalid types");
-    }
-    if(castType.isCompatible(Types.INTEGER)) {
-      return new StoreObject(Types.INTEGER, stoObj.value.trunc());
-    } else {
-      return new StoreObject(Types.REAL, stoObj.value);
-    }
-  }
-
-  constructor(name) {
-    this.name = name;
-    this.store = {};
-    this.nextStore = null;
-    this.mode = Modes.RUN; 
-  }
-
-  extendStore (nextStore) {
-    this.nextStore = nextStore;
-  }
-
-  applyStore (id) {
-    if(!this.store[id]) {
-      if (this.nextStore !== null) {
-        return this.nextStore.applyStore(id);
-      } else {
-        throw new Error(`Variable ${id} not found.`);
-      }
-    }
-    const val = this.store[id];
-    if (val.isRef) {
-      return val.getRefObj();
-    }
-    return this.store[id];
-  }
-
-  updateStore (id, stoObj) {
-    if(!this.store[id]) {
-      if(this.nextStore !== null) {
-        this.nextStore.updateStore(id, stoObj);
-        return this;
-      } else {
-        // TODO: better error message
-        throw new Error(`Variable ${id} not found.`);
-      }
-    } else {
-      const oldObj = this.store[id];
-      if(oldObj.readOnly) {
-        // TODO: better error message
-        throw new Error("Cannot change value of a read only variable: " + id);
-      }
-      if(oldObj.isRef) {
-        oldObj.updateRef(stoObj);
-        return this;
-      } else if(oldObj.isCompatible(stoObj)) {
-        stoObj.setID(id);
-        this.store[id] = Object.freeze(stoObj);
-        return this;
-      } else {
-        const oldType = oldObj.type;
-        const stoType = stoObj.type;
-        // TODO: better error message
-        throw new Error(`${oldType} is not compatible with type ${stoType} given`);
-      }
-    }
-  }
-
-  //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
-      throw new Error(`${id} is already defined`);
-    }
-    stoObj.setID(id);
-    this.store[id] = Object.freeze(stoObj);
-    return this;
-  }
-  /**
-   * Helper function similar to applyStore. But it returns the actual object in the store be it ref or not
-   * applyStore will return the refferenced object if the object in the store is a ref
-   */
-  getStoreObject (id) {
-    if(!this.store[id]) {
-      if (this.nextStore !== null) {
-        return this.nextStore.getStoreObject(id);
-      } else {
-        throw new Error(`Variable ${id} not found.`);
-      }
-    }
-    return this.store[id];
-  }
-}

+ 253 - 0
js/processor/store/store.ts

@@ -0,0 +1,253 @@
+import { Modes } from '../modes';
+import { Types } from "../../typeSystem/types";
+import { StoreObject } from './storeObject';
+import { IType } from '../../typeSystem/itype';
+import { StoreObjectRef } from './storeObjectRef';
+import { ArrayType } from '../../typeSystem/array_type';
+import { ArrayStoreValue } from './value/array_store_value';
+import { Location } from '../../memory/location';
+import { StoreObjectArray } from './storeObjectArray';
+import { IStoreValue } from './value/istore_value';
+import { StoreValue } from './value/store_value';
+import { StoreValueAddress } from './value/store_value_address';
+import { StoreValueRef } from './value/store_value_ref';
+import { ArrayStoreValueRef } from './value/array_store_value_ref';
+import { StoreObjectArrayRef } from './store_object_array_ref';
+
+export class Store {
+
+  static canImplicitTypeCast (castType: IType, sourceType: IType) {
+    if (castType.isCompatible(Types.INTEGER) || castType.isCompatible(Types.REAL)) {
+      if (sourceType.isCompatible(Types.INTEGER) || sourceType.isCompatible(Types.REAL)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  static doImplicitCasting (castType: IType, stoObj: IStoreValue) {
+    if(!Store.canImplicitTypeCast(castType, stoObj.type)) {
+      throw new Error("!!!Critical error: attempted to type cast invalid types");
+    }
+    if(castType.isCompatible(Types.INTEGER)) {
+      return new StoreValue(Types.INTEGER, stoObj.get().trunc());
+    } else {
+      return new StoreValue(Types.REAL, stoObj.get());
+    }
+  }
+
+  private store: Map<String, StoreObject>;
+  public nextStore?: Store
+  public mode: Symbol;
+
+  constructor(public name: String) {
+    this.store = new Map<String, StoreObject>();
+    this.mode = Modes.RUN; 
+  }
+
+  extendStore (nextStore: Store) {
+    this.nextStore = nextStore;
+  }
+
+  applyStore (id: String): IStoreValue {
+    if (!this.store.has(id)) {
+      if (this.nextStore != null) {
+        return this.nextStore.applyStore(id);
+      } else {
+        throw new Error(`Variable ${id} not found.`);
+      }
+    }
+    const val = this.store.get(id)!;
+    let result = null
+    if (val.type instanceof ArrayType) {
+      const array = val as StoreObjectArray;
+      const array_type = array.type as ArrayType;
+      let l = 0, c = 0;
+      const values = array.value.map( v => {
+        if(array.isVector) {
+          return new StoreValueAddress(array_type.innerType, v, l++, undefined, array.id, array.readOnly);  
+        } else {
+          if(c >= array.columns) {
+            c = 0;
+            l += 1;
+          }
+          return new StoreValueAddress(array_type.innerType, v, l, c++, array.id, array.readOnly);  
+        }
+      });
+      result = new ArrayStoreValue(array_type, values, array.lines, array.columns, val.id, val.readOnly);
+    } else {
+      result = new StoreValue(val.type, val.value, val.id, val.readOnly);
+    }
+    
+    return result;
+  }
+
+  updateStore (id: string, stoValue: IStoreValue): Store {
+    if (!this.store.has(id)) {
+      if (this.nextStore != null) {
+        this.nextStore.updateStore(id, stoValue);
+        return this;
+      } else {
+        // TODO: better error message
+        throw new Error(`Variable ${id} not found.`);
+      }
+    } else {
+      const oldObj = this.store.get(id)!;
+      if (oldObj.readOnly) {
+        // TODO: better error message
+        throw new Error("Cannot change value of a read only variable: " + id);
+      }
+
+      if (oldObj instanceof StoreObjectArray) {
+        const array_value = stoValue as ArrayStoreValue;
+        if(oldObj.isCompatible(array_value)) {
+          if(oldObj.isVector) {
+            array_value.get().forEach((val, index) => {
+              oldObj.setAt(val, index, undefined);
+            });
+          } else {
+            let line = 0;
+            let column = 0;
+            array_value.get().forEach((val) => {
+              oldObj.setAt(val, line, column);
+              column += 1;
+              if(column >= oldObj.columns) {
+                line += 1;
+                column = 0;
+              }
+            });
+          }
+          return this;
+        }
+      } else if (oldObj.isCompatible(stoValue)) {
+        const loc_address = oldObj.locAddress;
+        Location.updateAddress(loc_address, stoValue.get());
+        return this;
+      }
+      const oldType = oldObj.type;
+      const stoType = stoValue.type;
+      // TODO: better error message
+      throw new Error(`${oldType.value} is not compatible with type ${stoType.value} given`);
+      
+    }
+  }
+
+  /**
+   * Method used to update regions of an array (vector or matrix). The should only be used when update an specific
+   * possition since it will only update the required addresses.
+   * @param {string} id the variable id to be updated
+   * @param {IStoreValue} sto_value the value to be used in the update process
+   * @param {number} line the line address of the vector/matrix
+   * @param {number} column the matrix column, which can be undefined
+   */
+  updateStoreArray (id:string, sto_value: IStoreValue, line:number, column?:number): Store {
+    if (!this.store.has(id)) {
+      if (this.nextStore != null) {
+        this.nextStore.updateStoreArray(id, sto_value, line, column);
+        return this;
+      } else {
+        // TODO: better error message
+        throw new Error(`Variable ${id} not found.`);
+      }
+    } else {
+      const oldObj = this.store.get(id)!;
+      if (oldObj.readOnly) {
+        // TODO: better error message
+        throw new Error("Cannot change value of a read only variable: " + id);
+      }
+
+      if (oldObj instanceof StoreObjectArray) {
+        if(sto_value instanceof ArrayStoreValue) {
+          // this must be a vector  or matrix line update
+          const actual_values =  sto_value.get();
+          if(oldObj.isVector && sto_value.isVector()) {
+            for(let i = 0;i < sto_value.lines; i += 1) {
+              const val = actual_values[i]
+              oldObj.setAt(val, i, undefined);
+            }
+          } else if(!oldObj.isVector && column == null && sto_value.isVector()) {
+            for(let i = 0;i < oldObj.columns; i += 1) {
+              const val = actual_values[i]
+              oldObj.setAt(val, line, i);
+            }
+          } else {
+            // TODO: better error message
+            throw new Error(`Attempting to assign an invalid value to array ${id}`);
+          }
+        } else {
+          if(!oldObj.isVector && column == null) {
+            // TODO: better error message
+            throw new Error(`Attempting to assign an invalid value to array ${id}`);
+          }
+          oldObj.setAt(sto_value as StoreValue, line, column);
+        }
+      } else {
+        throw new Error("Cannot update a non-array variable using updateStoreArray");
+      }
+      // const oldType = oldObj.type;
+      // const stoType = sto_value.type;
+      // // TODO: better error message
+      // throw new Error(`${oldType.value} is not compatible with type ${stoType.value} given`);
+      return this;
+    }
+  }
+
+  //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: String, stoValue: IStoreValue) {
+    if (this.store.has(id)) {
+      // TODO: better error message
+      throw new Error(`${id} is already defined`);
+    }
+    // TODO check for array....
+    let newObj:StoreObject;
+    if(stoValue instanceof StoreValueRef) {
+      newObj = new StoreObjectRef(stoValue);
+    } else if (stoValue instanceof ArrayStoreValueRef) {
+      newObj = new StoreObjectArrayRef(stoValue, stoValue.lines, stoValue.columns);
+    } else if (stoValue instanceof ArrayStoreValue) {
+      const columns = stoValue.isVector() ? 0 : stoValue.columns!;
+      const addresses: number[] = [];
+      const all_values = stoValue.get();
+      if(all_values.length > 0) {
+        for(let i = 0; i < stoValue.get().length; i += 1) {
+          const val = all_values[i].get();
+          addresses.push(Location.allocate(val));
+        }
+      } else {
+        let total = stoValue.lines;
+        total = stoValue.isVector() ? total : total * columns;
+        for(let i = 0; i < total; i += 1) {
+          addresses.push(Location.allocate(null));
+        }
+      }
+      newObj = new StoreObjectArray(stoValue.type as ArrayType, stoValue.lines, columns, addresses, stoValue.isConst);
+    } else {
+      const loc_address = Location.allocate(stoValue.get());
+      newObj = new StoreObject(stoValue.type, loc_address, stoValue.isConst);
+    }
+    newObj.setID(id);
+    this.store.set(id, newObj);
+    return this;
+  }
+  /**
+   * Helper function similar to applyStore. But it returns the actual object in the store be it ref or not
+   * applyStore will return the refferenced object if the object in the store is a ref
+   */
+  getStoreObject (id: String): StoreObject {
+    if (!this.store.has(id)) {
+      if (this.nextStore != null) {
+        return this.nextStore.getStoreObject(id);
+      } else {
+        throw new Error(`Variable ${id} not found.`);
+      }
+    }
+    return this.store.get(id)!;
+  }
+
+  destroy (): void {
+    this.store.forEach(sto => sto.destroy(), this);
+  }
+}

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

@@ -1,54 +0,0 @@
-import Decimal from 'decimal.js';
-
-export class StoreObject {
-
-  constructor (type, value, readOnly = false) {
-    this._type = type;
-    this._value = value;
-    this._readOnly = readOnly;
-    this._id = null;
-  }
-
-  setID (id) {
-    this._id = id;
-  }
-
-  get id () {
-    return this._id;
-  }
-
-  get inStore () {
-    return this.id !== null;
-  }
-
-  get type () {
-    return this._type;
-  }
-
-  get value () {
-    return this._value;
-  }
-  
-  get number () {
-    if (this._value instanceof Decimal) {
-      return this._value.toNumber();
-    } else {
-      return null;
-    }
-  }
-
-  get readOnly () {
-    return this._readOnly;
-  }
-
-  set readOnly (value) {
-    this._readOnly = value;
-  }
-
-  isCompatible (another) {
-    if( another instanceof StoreObject) {
-      return this.type.isCompatible(another.type);
-    }
-    return false;
-  }
-}

+ 77 - 0
js/processor/store/storeObject.ts

@@ -0,0 +1,77 @@
+import { Location } from "../../memory/location";
+import { IType } from "../../typeSystem/itype";
+import { IStoreValue } from "./value/istore_value";
+
+export class StoreObject {
+
+  private _type: IType;
+  private _loc_address: number;
+  private _readOnly: boolean;
+  private _id?: String;
+
+  /**
+   * 
+   * @param {Type} type 
+   * @param {Number} loc_address 
+   * @param {Boolean} readOnly 
+   */
+  constructor (type: IType, loc_address: number, readOnly = false) {
+    this._loc_address = loc_address;
+    this._type = type;
+    this._readOnly = readOnly;
+    this._id = undefined;
+  }
+
+  setID (id: String) {
+    this._id = id;
+  }
+
+  get id () {
+    return this._id;
+  }
+
+  get inStore () {
+    return this.id !== null;
+  }
+
+  get type () {
+    return this._type;
+  }
+
+  /**
+   * Returns the actual value stored at the loccation address present in this object.
+   * The returned value is compatible with @prop{StoreObject.type}
+  */
+  get value () {
+    const address = Location.find(this._loc_address);
+    if (address != null) {
+      return address.value
+    } else {
+      throw new Error("!!!Critical Error: variable "+this.id+" does not have a valid address. Loc-Address "+ this.locAddress);
+    }
+  }
+  
+  get number () {
+    throw new Error("DOT NOT USE THIS PROPERTY!");
+  }
+
+  get readOnly () {
+    return this._readOnly;
+  }
+
+  set readOnly (value) {
+    this._readOnly = value;
+  }
+
+  isCompatible (another: IStoreValue) {
+    return this.type.isCompatible(another.type);
+  }
+
+  destroy () {
+    return Location.deallocate(this._loc_address);
+  }
+
+  get locAddress () {
+    return this._loc_address;
+  }
+}

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

@@ -1,76 +0,0 @@
-import { StoreObject } from './storeObject';
-
-export class StoreObjectArray extends StoreObject {
-
-  static get WRONG_LINE_NUMBER () {
-    return 1;
-  }
-
-  static get WRONG_TYPE () {
-    return 2;
-  }
-
-  static get WRONG_COLUMN_NUMBER () {
-    return 3;
-  }
-
-  constructor (type, lines, columns, value = null, readOnly = false) {
-    super(type, value, readOnly);
-    this._lines = lines;
-    this._columns = columns;
-  }
-
-  get lines () {
-    return this._lines;
-  }
-
-  get columns () {
-    return this._columns;
-  }
-
-  isCompatible (another) {
-    if(another instanceof StoreObjectArray) {
-      if((this.isVector && another.isVector) ||
-        (!this.isVector && !another.isVector)) {
-          return super.isCompatible(another);
-      }
-    }
-    return false;
-  }
-
-  get isVector () {
-    return this.type.dimensions === 1;
-  }
-
-  get isValid () {
-    if (this.value !== null) {
-      if( this.isVector) {
-        if(this.value.length !== this.lines) {
-          return [StoreObjectArray.WRONG_LINE_NUMBER, this.value.length];;
-        }
-        // const mustBeNull = this.value.find(v => !this.type.canAccept(v.type) );
-        // if(!!mustBeNull) {
-        //   return [StoreObjectArray.WRONG_TYPE, this.value.indexOf(mustBeNull)];;
-        // }
-        return [];
-      } else if(this.lines !== this.value.length) {
-        return [StoreObjectArray.WRONG_LINE_NUMBER, this.value.length];
-      }
-      for (let i = 0; i < this.lines; i += 1) {
-        const thisRef = this;
-        const arrayObject = this.value[i];
-        if(arrayObject.lines !== this.columns) {
-          return [StoreObjectArray.WRONG_COLUMN_NUMBER, this.columns, arrayObject.lines];
-        }
-        // const mustBeNull = arrayObject.value.find(v => !arrayObject.type.canAccept(v.type) );
-        // if(!!mustBeNull) {
-        //   console.log(mustBeNull);
-        //   console.log(thisRef.type.canAccept(mustBeNull));
-        //   console.log(thisRef.type);
-        //   return [StoreObjectArray.WRONG_TYPE, i, arrayObject.value.indexOf(mustBeNull)];
-        // }
-      }
-    } 
-    return [];
-  }
-}

+ 140 - 0
js/processor/store/storeObjectArray.ts

@@ -0,0 +1,140 @@
+import { StoreObject } from './storeObject';
+import { ArrayType } from '../../typeSystem/array_type';
+import { ArrayStoreValue } from './value/array_store_value';
+import { Location } from "../../memory/location";
+import { IStoreValue } from './value/istore_value';
+import { StoreValue } from './value/store_value';
+
+export class StoreObjectArray extends StoreObject {
+
+  constructor (type: ArrayType, private _lines:number, private _columns:number, private loc_addresses: number[], readOnly = false) {
+    super(type, -1, readOnly);
+  }
+
+  get lines () {
+    return this._lines;
+  }
+
+  get columns () {
+    return this._columns;
+  }
+
+  isCompatible (another: IStoreValue): boolean {
+    if(another instanceof ArrayStoreValue) {
+      const cols = another.columns == null ? 0 :  another.columns;
+      if(this.lines === another.lines && this.columns === cols) {
+          return super.isCompatible(another);
+      }
+    }
+    return false;
+  }
+
+  get isVector () {
+    return (this.type as ArrayType).dimensions === 1;
+  }
+
+  /**@override 
+     * Returns the list of values stored by this array.
+     * All returned values are compatible with @prop{StoreObject.type}
+    */
+  get value () {
+    const values = [];
+    for(let i = 0; i < this.addresses.length; i += 1) {
+      const address = Location.find(this.addresses[i]);
+      if (address != null) {
+        values.push(address.value);
+      } else {
+        throw new Error("!!!Critical Error: variable "+this.id+" does not have a valid address. Loc-Address "+ this.locAddress);
+      }
+    }
+    return values;
+  }
+
+  destroy () {
+    let bool =  true;
+    for(let i = 0; i < this.addresses.length; i += 1) {
+      bool = bool && Location.deallocate(this.addresses[i]);
+    }
+    return bool;
+  }
+
+  /**
+   * @override
+   * 
+   * Returns the address that contains a list of all addresses of the values present in the array
+   */
+  get locAddress (): number {
+    throw new Error("!!!Internal Error: Cannot invoke locAddress on StoreObjectArray");
+  }
+
+  protected get addresses (): number[] {
+    return this.loc_addresses;
+  }
+
+  getAt (line: number, column?: number): any {
+    if(this.isVector) {
+      if(column != null) {
+        throw new Error(this.id + " is not a matrix!");
+      }
+      column = line;
+      line = 0;
+    } else if (column == null) {
+      // this is a whole line...
+      const values = [];
+      for(let col = 0; col < this.columns; col += 1) {
+        const index = this.getIndexOf(line, col);
+        const address = Location.find(this.addresses[index])!;
+        values.push(address.value);
+      }
+      return values;
+    }
+    const index = this.getIndexOf(line, column);
+    const address = Location.find(this.addresses[index])!;
+    return address.value;
+  }
+
+  setAt (value: StoreValue, line:number, column?: number): void {
+    let used_dims = 1;
+    if(column != null) {
+      used_dims += 1;
+    }
+    if(!(this.type as ArrayType).canAccept(value.type, used_dims)) {
+      throw new Error("!!!Internal Error: Attempting to insert an invalid value inside array "+this.id);
+    }
+    if(this.isVector) {
+      if(column != null) {
+        throw new Error(this.id + " is not a matrix!");
+      }
+      column = line;
+      line = 0;
+    } else if (column == null) {
+      throw new Error("!!!Internal Error: Attempting to insert a line into matrix "+ this.id );
+    }
+    const pos = this.getIndexOf(line, column);
+    Location.updateAddress(this.addresses[pos], value.get());
+  }
+
+  protected getIndexOf (line: number, column: number): number {
+    return line * this.columns + column;
+  }
+
+  getLocAddressOf (line: number, column?: number): number | number[] {
+    if(this.isVector) {
+      if(column != null) {
+        throw new Error(this.id + " is not a matrix!");
+      }
+      column = line;
+      line = 0;
+    } else if (column == null) {
+      // this is a whole line...
+      const values: number[] = [];
+      for(let col = 0; col < this.columns; col += 1) {
+        const index = this.getIndexOf(line, col);
+        values.push(this.addresses[index]);
+      }
+      return values;
+    }
+    const index = this.getIndexOf(line, column);
+    return this.addresses[index];
+  }
+}

+ 0 - 101
js/processor/store/storeObjectArrayAddress.js

@@ -1,101 +0,0 @@
-import { StoreObject } from './storeObject';
-import { StoreObjectArray } from './storeObjectArray';
-import { ArrayType } from '../../typeSystem/array_type';
-import { ProcessorErrorFactory } from '../error/processorErrorFactory';
-
-export class StoreObjectArrayAddress extends StoreObject {
-
-  constructor (refID, line, column, store) {
-    super(null, null, false);
-    this.refID = refID;
-    this.store = store;
-    this.line = line;
-    this.column = column;
-  }
-
-  get isRef () {
-    return false;
-  }
-
-  get inStore () {
-    return true;
-  }
-
-  get refValue () {
-    const refLine = this.store.applyStore(this.refID).value[this.line];
-    if(!refLine) {
-      if(this.getArrayObject().isVector) {
-        throw ProcessorErrorFactory.vector_line_outbounds(this.refID, this.line, this.getArrayObject().lines);
-      } else {
-        throw ProcessorErrorFactory.matrix_line_outbounds(this.refID, this.line, this.getArrayObject().lines);
-      }
-    }
-    if (this.column !== null) {
-      const refColumn = refLine.value[this.column];
-      if(!refColumn) {
-        if(this.getArrayObject().isVector) {
-          throw ProcessorErrorFactory.vector_not_matrix(this.refID);
-        } else {
-          throw ProcessorErrorFactory.matrix_column_outbounds(this.refID, this.column, this.getArrayObject().columns);
-        }
-      }
-      return refColumn;
-    }
-    return refLine;
-  }
-
-  get value () {
-    return this.refValue.value;
-  }
-
-  get type () {
-    return this.refValue.type;
-  }
-
-  get lines () {
-    if(!(this.type instanceof ArrayType)) {
-      return null;
-    }
-    return this.refValue.value.length;
-  }
-
-  get columns () {
-    switch (this.type.dimensions) {
-      case 2:
-        return this.refValue.value[0].value.length;
-      default:
-        return null;
-    }
-  }
-
-  getArrayObject () {
-    return this.store.applyStore(this.refID);
-  }
-
-  updateArrayObject (stoObj) {
-    const anArray =  this.getArrayObject();
-    const newArray = Object.assign(new StoreObjectArray(null,null,null), anArray);
-    if(!stoObj.type.isCompatible(this.type)) {
-      throw new Error(`Invalid operation: cannot assign the value given to ${this.refID}`);
-    } else if (this.type instanceof ArrayType && this.type.canAccept(stoObj.type)) {
-      throw new Error(`Invalid operation: cannot assign the value given to ${this.refID}`);
-    }
-    if (this.column !== null) {
-     newArray.value[this.line].value[this.column] = stoObj;
-     return newArray;
-    } else {
-     newArray.value[this.line] = stoObj;
-     return newArray;
-    }
-  }
-
-  isCompatible (another) {
-    if(this.type.isCompatible(another.type)) {
-      if(another.type instanceof ArrayType) {
-        return this.lines === another.lines && this.columns === another.columns;
-      } else {
-        this.refValue.isCompatible(another);
-      }
-    }
-  }
-}

+ 0 - 43
js/processor/store/storeObjectArrayAddressRef.js

@@ -1,43 +0,0 @@
-import { StoreObject } from './storeObject';
-import Decimal from 'decimal.js';
-
-export class StoreObjectArrayAddressRef extends StoreObject {
-
-  constructor (address) {
-    super(null, null, false);
-    this.address = address;
-  }
-
-  get isRef () {
-    return true;
-  }
-
-  get type () {
-    return this.address.type;
-  }
-
-  get value () {
-    return this.address.value;
-  }
-
-  get number () {
-    if (this.value instanceof Decimal) {
-      return this.value.toNumber();
-    } else {
-      return null;
-    }
-  }
-
-  getRefObj () {
-    return this.address.refValue;
-  }
-
-  updateRef (stoObj) {
-    const newArray = this.address.updateArrayObject(stoObj);
-    this.address.store.updateStore(this.address.refID, newArray);
-  }
-
-  isCompatible (another) {
-    return this.address.isCompatible(another);
-  }
-}

+ 0 - 43
js/processor/store/storeObjectRef.js

@@ -1,43 +0,0 @@
-import { StoreObject } from './storeObject';
-import Decimal from 'decimal.js';
-
-export class StoreObjectRef extends StoreObject {
-
-  constructor (refID, store) {
-    super(null, null, false);
-    this.refID = refID;
-    this.store = store;
-  }
-
-  get isRef () {
-    return true;
-  }
-
-  get type () {
-    return this.store.applyStore(this.refID).type;
-  }
-
-  get value () {
-    return this.store.applyStore(this.refID).value;
-  }
-
-  get number () {
-    if (this.value instanceof Decimal) {
-      return this.value.toNumber();
-    } else {
-      return null;
-    }
-  }
-
-  getRefObj () {
-    return this.store.applyStore(this.refID);
-  }
-
-  updateRef (stoObj) {
-    this.store.updateStore(this.refID, stoObj);
-  }
-
-  isCompatible (another) {
-    return this.store.applyStore(this.refID).isCompatible(another);
-  }
-}

+ 34 - 0
js/processor/store/storeObjectRef.ts

@@ -0,0 +1,34 @@
+import { StoreObject } from './storeObject';
+import { StoreValueRef } from './value/store_value_ref';
+
+export class StoreObjectRef extends StoreObject {
+
+  private refObj: String;
+  private reference_dimension: number;
+
+  /**
+   * 
+   * @param {StoreObject} stoValue 
+   */
+  constructor (stoValue: StoreValueRef) {
+    super(stoValue.type, stoValue.getRefAddress(), false);
+    this.refObj = stoValue.id!;
+    this.reference_dimension = stoValue.getReferenceDimension();
+  }
+
+  get isRef () {
+    return true;
+  }
+
+  getRefObj (): String {
+    return this.refObj;
+  }
+
+  getReferenceDimension (): number {
+    return this.reference_dimension;
+  }
+
+  destroy () {
+    return false;
+  }
+}

+ 24 - 0
js/processor/store/store_object_array_ref.ts

@@ -0,0 +1,24 @@
+import { StoreObjectArray } from "./storeObjectArray";
+import { ArrayStoreValueRef } from "./value/array_store_value_ref";
+
+export class StoreObjectArrayRef extends StoreObjectArray {
+
+  private refObj: String;
+
+  constructor(stoValue: ArrayStoreValueRef, lines:number, columns:number) {
+    super(stoValue.type, lines, columns, stoValue.getAddresses(), false);
+    this.refObj = stoValue.id;
+  }
+
+  get isRef () {
+    return true;
+  }
+
+  getRefObj (): String {
+    return this.refObj;
+  }
+
+  destroy () {
+    return false;
+  }
+}

+ 97 - 0
js/processor/store/value/array_store_value.ts

@@ -0,0 +1,97 @@
+import { IStoreValue } from "./istore_value";
+import { ArrayType } from "../../../typeSystem/array_type";
+import { IType } from "../../../typeSystem/itype";
+import { Type } from "../../../typeSystem/type";
+import { StoreValueAddress } from "./store_value_address";
+
+export class ArrayStoreValue implements IStoreValue {
+
+  public type: IType; 
+  public id?: String;
+  public isConst: boolean;
+  public lines: number;
+  public columns?: number;
+  public values: StoreValueAddress[];
+
+  constructor(type: ArrayType, values: StoreValueAddress[], lines: number, columns?: number, id?: String, isConst = false) {
+    this.type = type;
+    this.id = id;
+    this.isConst = isConst
+    this.values = values;
+    this.lines = lines;
+    this.columns = columns;
+  }
+
+  get (): StoreValueAddress[] {
+    return this.values;
+  }
+
+  /**
+   * @deprecated
+   * Potential not necessary since array access is occuring directly in the StoreObject
+   * @param line 
+   * @param column 
+   */
+  getAt (line: number, column?: number): IStoreValue {
+    console.log("Column ", column);
+    if(this.isVector()) {
+      if(column != null) {
+        throw new Error(this.id + " is not a matrix!");
+      }
+      column = line;
+      line = 0;
+    } else if (column == null) {
+      const values: StoreValueAddress[] = [];
+      for(let col = 0; col < this.columns!; col += 1) {
+        const index = line * this.lines + col;
+        values.push(this.values[index]);
+      }
+      const array_type = this.type as ArrayType
+      const vector_type = new ArrayType(array_type.innerType as Type, array_type.dimensions - 1);
+      return new ArrayStoreValue(vector_type, values, this.columns!, 0, this.id, this.isConst);
+    }
+    const index = line * this.lines + column;
+    console.log("Get at: ",index);
+    return this.values[index];
+  }
+
+  setAt (value: IStoreValue, line:number, column?: number): void {
+    let used_dims = 1;
+    if(column != null) {
+      used_dims += 1;
+    }
+    let actual_line = line;
+    let actual_column = column;
+    if(!(this.type as ArrayType).canAccept(value.type, used_dims)) {
+      throw new Error("!!!Internal Error: Attempting to insert an invalid value inside array "+this.id);
+    }
+    if(this.isVector) {
+      if(column != null) {
+        throw new Error(this.id + " is not a matrix!");
+      }
+      actual_column = actual_line;
+      actual_line = 0;
+    } else if (column == null) {
+      if(!(value instanceof ArrayStoreValue)) {
+        throw new Error("Attempting to insert a single value as a line of matrix " + this.id);
+      }
+      const actual_values = value.get()
+      for(let i = 0; i < this.columns!; i += 1) {
+        const pos = actual_line * this.columns! + i;
+        const val = actual_values[i]
+        this.values[pos] = new StoreValueAddress(value.type, val.get(), actual_line, i, this.id, this.isConst);
+      }
+    }
+    const columns =  this.columns == null ? 0 : this.columns;
+    const pos = actual_line * columns + actual_column!;
+    this.values[pos] = new StoreValueAddress(value.type, value.get(), line, column, this.id, this.isConst);
+  }
+
+  inStore () {
+    return this.id != null;
+  }
+
+  isVector (): boolean {
+    return (this.type as ArrayType).dimensions == 1;
+  }
+}

+ 24 - 0
js/processor/store/value/array_store_value_ref.ts

@@ -0,0 +1,24 @@
+import { IStoreValue } from "./istore_value";
+import { StoreValueAddress } from "./store_value_address";
+import { ArrayType } from "../../../typeSystem/array_type";
+
+export class ArrayStoreValueRef implements IStoreValue {
+
+  public isConst = false;
+
+  constructor(public type: ArrayType, private values: StoreValueAddress[],
+    private addresses: number[], public lines: number, public columns:number,
+    public id:String) { }
+
+  get () {
+    return this.values;
+  }
+
+  getAddresses (): number[] {
+    return this.addresses;
+  }
+
+  inStore () {
+    return this.id != null;
+  }
+}

+ 9 - 0
js/processor/store/value/istore_value.ts

@@ -0,0 +1,9 @@
+import { IType } from "../../../typeSystem/itype";
+
+export interface IStoreValue {
+  type: IType;
+  get () : any;
+  id? : String;
+  isConst: boolean;
+  inStore: () => boolean;
+}

+ 26 - 0
js/processor/store/value/store_value.ts

@@ -0,0 +1,26 @@
+import { IStoreValue } from "./istore_value";
+import { IType } from "../../../typeSystem/itype";
+
+export class StoreValue implements IStoreValue {
+  
+  public type: IType;
+  public id?: String;
+  public isConst: boolean;
+  public value: any;
+
+  constructor(type: IType, value: any, id?:String, isConst = false) {
+    this.type = type;
+    this.id = id;
+    this.isConst = isConst
+    this.value = value;
+  }
+
+  get (): any {
+    return this.value;
+  }
+
+  inStore () {
+    return this.id != null;
+  }
+
+}

+ 9 - 0
js/processor/store/value/store_value_address.ts

@@ -0,0 +1,9 @@
+import { StoreValue } from "./store_value";
+import { IType } from "../../../typeSystem/itype";
+
+export class StoreValueAddress extends StoreValue {
+
+  constructor (type: IType, value: any, public line: number, public column?: number, id?:String, isConst = false)  {
+    super(type,value,id, isConst);
+  }
+}

+ 32 - 0
js/processor/store/value/store_value_ref.ts

@@ -0,0 +1,32 @@
+import { IStoreValue } from "./istore_value";
+import { Type } from "../../../typeSystem/type";
+
+export class StoreValueRef implements IStoreValue {
+
+  public isConst = false;
+  private reference_dimesion = 0;
+
+  constructor(public type: Type, public value: any, private loc_address: number, public id:String) {
+
+  }
+
+  get () {
+    return this.value;
+  }
+
+  getRefAddress () : number {
+    return this.loc_address;
+  }
+
+  inStore () {
+    return this.id != null;
+  }
+
+  getReferenceDimension (): number {
+    return this.reference_dimesion;
+  }
+
+  setReferenceDimension (dimension: number):void {
+    this.reference_dimesion = dimension;
+  }
+}

+ 11 - 2
js/runner.js

@@ -3,6 +3,7 @@ import { IVProgProcessor } from './processor/ivprogProcessor';
 import {DOMConsole} from './io/domConsole';
 import { LanguageService } from './services/languageService';
 import { SemanticAnalyser } from './processor/semantic/semanticAnalyser';
+import { Location } from "./memory/location";
 
 export function runner () {
 const ivprogLexer = LanguageService.getCurrentLexer();
@@ -36,11 +37,19 @@ try {
       proc.registerInput(domConsole);
       domConsole.clear();
       proc.registerOutput(domConsole);
-      proc.interpretAST().then(sto => editor.load(sto.store))
-        .catch( e => {alert(e); console.log(e)});
+      proc.interpretAST().then(sto => {
+        console.log(sto);
+        editor.load(sto.store);
+        console.log(Location.size());
+      }).catch( e => {
+        alert(e);
+        console.log(e);
+        console.log(Location.size());
+      });
     } catch (error) {
       alert(error);
       console.log(error);
+      console.log(Location.size());
     }
     
   });

+ 0 - 40
js/typeSystem/array_type.js

@@ -1,40 +0,0 @@
-import { Type } from "./type";
-
-export class ArrayType extends Type {
-
-  constructor (type, dimensions) {
-    super(null);
-    this.innerType = type;
-    this.dimensions = dimensions;
-  }
-
-  get isVector () {
-    return this.dimensions == 1;
-  }
-
-  isCompatible (another) {
-    if(another instanceof ArrayType){
-      if(this.dimensions !== another.dimensions) {
-        return false;
-      }
-      return this.innerType.isCompatible(another.innerType);
-    }
-    return false;
-  }
-
-  stringInfo () {
-    const list = this.innerType.stringInfo();
-    list.forEach(v => {
-      v.dim = this.dimensions;
-    });
-    return list;
-  }
-
-  canAccept (another) {
-    if(another instanceof ArrayType) {
-      return false;// return this.dimensions > another.dimensions && this.innerType.isCompatible(another.innerType);
-    } else {
-      return this.dimensions == 1 && this.innerType.isCompatible(another);
-    }
-  }
-}

+ 50 - 0
js/typeSystem/array_type.ts

@@ -0,0 +1,50 @@
+import { IType } from "./itype";
+import { Type } from "./type";
+
+export class ArrayType implements IType {
+
+  public innerType: IType;
+
+  constructor (type: Type, public dimensions: number) {
+    this.innerType = type;
+  }
+
+  get isVector () {
+    return this.dimensions == 1;
+  }
+
+  isCompatible (another: IType): boolean {
+    if(another instanceof ArrayType){
+      if(this.dimensions !== another.dimensions) {
+        return false;
+      }
+      return this.innerType.isCompatible(another.innerType);
+    }
+    return false;
+  }
+
+  stringInfo () {
+    const list = this.innerType.stringInfo();
+    list.forEach(v => {
+      v.dim = this.dimensions;
+    });
+    return list;
+  }
+
+  get value () {
+    return undefined;
+  }
+
+  get ord () {
+    return undefined;
+  }
+
+  canAccept (another: IType, used_dims: number) {
+    const free_dims = this.dimensions - used_dims;
+    if(another instanceof ArrayType) {
+      return free_dims == another.dimensions && this.innerType.isCompatible(another.innerType);
+    } else {
+      return free_dims == 0 && this.innerType.isCompatible(another);
+    }
+  }
+}

+ 0 - 27
js/typeSystem/baseTypes.js

@@ -1,27 +0,0 @@
-class BaseType {
-  constructor(name, ord) {
-    this.name = name;
-    this.ord = ord;
-  }
-
-  get value () {
-    return this.name;
-  }
-
-  isCompatible (another) {
-    if(another instanceof BaseType) {
-      return this.name === another.name && this.ord === another.ord;
-    }
-    return false;
-  }
-}
-
-// Base types names are the same as i18n ui type keys
-export const BaseTypes = Object.freeze({
-  INTEGER: new BaseType("integer", 0),
-  REAL: new BaseType("real", 1),
-  STRING: new BaseType("text", 2),
-  BOOLEAN: new BaseType("boolean", 3),
-  VOID: new BaseType("void", 4),
-  UNDEFINED: new BaseType("undefined", 5)
-})

+ 11 - 0
js/typeSystem/itype.ts

@@ -0,0 +1,11 @@
+export interface IType {
+
+  value?: String;
+
+  ord?: number;
+
+  stringInfo (): any[];
+
+  isCompatible (another: IType): boolean;
+
+}

+ 0 - 38
js/typeSystem/multiType.js

@@ -1,38 +0,0 @@
-import { Type } from "./type";
-
-export class MultiType extends Type {
-
-  constructor (types) {
-    super(null);
-    this.types = types;
-  }
-
-  get value () {
-    return null;
-  }
-
-  get ord () {
-    return null;
-  }
-
-  stringInfo () {
-    let list = [];
-    for (let i = 0; i < this.types.length; i++) {
-      const t = this.types[i];
-      list = list.concat(t.stringInfo());
-    }
-    return list;
-  }
-
-  isCompatible (another) {
-    if(another instanceof Type) {
-      for (let i = 0; i < this.types.length; i++) {
-        const t = this.types[i];
-        if (another.isCompatible(t)) {
-          return true;
-        }
-      }
-    }
-    return false;
-  }
-}

+ 35 - 0
js/typeSystem/multiType.ts

@@ -0,0 +1,35 @@
+import { Type } from "./type";
+import { IType } from "./itype";
+
+export class MultiType implements IType {
+
+  constructor (public types: Type[]) {
+  }
+
+  get value () {
+    return undefined;
+  }
+
+  get ord () {
+    return undefined;
+  }
+
+  stringInfo () {
+    let list: any[] = [];
+    for (let i = 0; i < this.types.length; i++) {
+      const t = this.types[i];
+      list = list.concat(t.stringInfo());
+    }
+    return list;
+  }
+
+  isCompatible (another: Type) {
+    for (let i = 0; i < this.types.length; i++) {
+      const t = this.types[i];
+      if (another.isCompatible(t)) {
+        return true;
+      }
+    }
+    return false;
+  }
+}

+ 0 - 28
js/typeSystem/type.js

@@ -1,28 +0,0 @@
-import { Config } from "../util/config";
-import { BaseTypes } from "./baseTypes";
-
-export class Type {
-
-  constructor(baseType) {
-    this.baseType = baseType;
-  }
-
-  get value () {
-    return this.baseType.value;
-  }
-
-  get ord () {
-    return this.baseType.ord;
-  }
-
-  stringInfo () {
-    return [{type: this.baseType.name, dim: 0}];
-  }
-
-  isCompatible (another) {
-    if(another instanceof Type) {
-      return this.baseType.isCompatible(another.baseType);
-    }
-    return false;
-  }
-}

+ 14 - 0
js/typeSystem/type.ts

@@ -0,0 +1,14 @@
+import { IType } from "./itype";
+
+export class Type implements IType {
+
+  constructor(public value: String, public ord: number) { }
+
+  stringInfo () {
+    return [{type: this.value, dim: 0}];
+  }
+
+  isCompatible (another: IType) {
+    return this.value === another.value && this.ord === another.ord;
+  }
+}

+ 0 - 21
js/typeSystem/types.js

@@ -1,21 +0,0 @@
-import { BaseTypes } from './baseTypes';
-import { Type } from "./type";
-import { MultiType } from "./multiType";
-
-const INTEGER = new Type(BaseTypes.INTEGER);
-const REAL = new Type(BaseTypes.REAL);
-const STRING = new Type(BaseTypes.STRING);
-const BOOLEAN = new Type(BaseTypes.BOOLEAN);
-const VOID = new Type(BaseTypes.VOID);
-const UNDEFINED = new Type(BaseTypes.UNDEFINED);
-const ALL = new MultiType([INTEGER, REAL, STRING, BOOLEAN]);
-
-export const Types = Object.freeze({
-  INTEGER: INTEGER,
-  REAL: REAL,
-  STRING: STRING,
-  BOOLEAN: BOOLEAN,
-  VOID: VOID,
-  UNDEFINED: UNDEFINED,
-  ALL: ALL
-});

+ 36 - 0
js/typeSystem/types.ts

@@ -0,0 +1,36 @@
+import { Type } from "./type";
+import { MultiType } from "./multiType";
+import { IType } from "./itype";
+import { Maybe } from "../util/maybe";
+
+const INTEGER = new Type("integer", 0);
+const REAL = new Type("real", 1);
+const STRING = new Type("text", 2);
+const BOOLEAN =new Type("boolean", 3);
+const VOID = new Type("void", 4);
+const UNDEFINED = new Type("undefined", 5);
+const ALL = new MultiType([INTEGER, REAL, STRING, BOOLEAN]);
+
+interface TypeMap {
+  [key: string]: IType
+}
+
+export const Types = Object.freeze({
+  INTEGER: INTEGER,
+  REAL: REAL,
+  STRING: STRING,
+  BOOLEAN: BOOLEAN,
+  VOID: VOID,
+  UNDEFINED: UNDEFINED,
+  ALL: ALL
+});
+
+export function fromOrdToType (ord:number): Maybe<IType> {
+  const typeMap = Types as TypeMap;
+  for(let t in typeMap) {
+    if(typeMap[t].ord! === ord){
+      return Maybe.some<IType>(typeMap[t]);
+    }
+  }
+  return Maybe.none<IType>();
+}

+ 37 - 0
js/util/maybe.ts

@@ -0,0 +1,37 @@
+/**
+*
+*  Maybe Monad
+*  @Source: https://codewithstyle.info/advanced-functional-programming-in-typescript-maybe-monad/
+*  @Modified by: @lucascalion - 28/08/2019
+*
+**/
+export class Maybe<T> {
+  private constructor(private value: T | null) {}
+
+  static some<T>(value: T) {
+      if (!value) {
+          throw Error("Provided value must not be empty");
+      }
+      return new Maybe(value);
+  }
+
+  static none<T>() {
+      return new Maybe<T>(null);
+  }
+
+  static fromValue<T>(value: T) {
+      return value ? Maybe.some(value) : Maybe.none<T>();
+  }
+
+  getOrElse(defaultValue: T) {
+      return this.value === null ? defaultValue : this.value;
+  }
+
+  map<R>(f: (wrapped: T) => R): Maybe<R> {
+    if (this.value === null) {
+        return Maybe.none<R>();
+    } else {
+        return Maybe.fromValue(f(this.value));
+    }
+}
+}

+ 4 - 0
js/util/utils.js

@@ -266,3 +266,7 @@ export function openAssessmentDetail (event) {
   win.document.write(page_code);
   win.document.close();
 }
+
+export function range (size, startAt = 0) {
+  return [...Array(size).keys()].map(i => i + startAt);
+}

+ 84 - 3
package-lock.json

@@ -826,6 +826,72 @@
         "@types/babel-types": "*"
       }
     },
+    "@types/eslint-visitor-keys": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+      "integrity": "sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag==",
+      "dev": true
+    },
+    "@types/json-schema": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.3.tgz",
+      "integrity": "sha512-Il2DtDVRGDcqjDtE+rF8iqg1CArehSK84HZJCT7AMITlyXRBpuPhqGLDQMowraqqu1coEaimg4ZOqggt6L6L+A==",
+      "dev": true
+    },
+    "@typescript-eslint/eslint-plugin": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.0.0.tgz",
+      "integrity": "sha512-Mo45nxTTELODdl7CgpZKJISvLb+Fu64OOO2ZFc2x8sYSnUpFrBUW3H+H/ZGYmEkfnL6VkdtOSxgdt+Av79j0sA==",
+      "dev": true,
+      "requires": {
+        "@typescript-eslint/experimental-utils": "2.0.0",
+        "eslint-utils": "^1.4.0",
+        "functional-red-black-tree": "^1.0.1",
+        "regexpp": "^2.0.1",
+        "tsutils": "^3.14.0"
+      }
+    },
+    "@typescript-eslint/experimental-utils": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-2.0.0.tgz",
+      "integrity": "sha512-XGJG6GNBXIEx/mN4eTRypN/EUmsd0VhVGQ1AG+WTgdvjHl0G8vHhVBHrd/5oI6RRYBRnedNymSYWW1HAdivtmg==",
+      "dev": true,
+      "requires": {
+        "@types/json-schema": "^7.0.3",
+        "@typescript-eslint/typescript-estree": "2.0.0",
+        "eslint-scope": "^4.0.0"
+      }
+    },
+    "@typescript-eslint/parser": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-2.0.0.tgz",
+      "integrity": "sha512-ibyMBMr0383ZKserIsp67+WnNVoM402HKkxqXGlxEZsXtnGGurbnY90pBO3e0nBUM7chEEOcxUhgw9aPq7fEBA==",
+      "dev": true,
+      "requires": {
+        "@types/eslint-visitor-keys": "^1.0.0",
+        "@typescript-eslint/experimental-utils": "2.0.0",
+        "@typescript-eslint/typescript-estree": "2.0.0",
+        "eslint-visitor-keys": "^1.0.0"
+      }
+    },
+    "@typescript-eslint/typescript-estree": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-2.0.0.tgz",
+      "integrity": "sha512-NXbmzA3vWrSgavymlzMWNecgNOuiMMp62MO3kI7awZRLRcsA1QrYWo6q08m++uuAGVbXH/prZi2y1AWuhSu63w==",
+      "dev": true,
+      "requires": {
+        "lodash.unescape": "4.0.1",
+        "semver": "^6.2.0"
+      },
+      "dependencies": {
+        "semver": {
+          "version": "6.3.0",
+          "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
+          "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
+          "dev": true
+        }
+      }
+    },
     "@webassemblyjs/ast": {
       "version": "1.8.5",
       "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.8.5.tgz",
@@ -3150,9 +3216,9 @@
       }
     },
     "eslint-utils": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.0.tgz",
-      "integrity": "sha512-7ehnzPaP5IIEh1r1tkjuIrxqhNkzUJa9z3R92tLJdZIVdWaczEhr3EbhGtsMrVxi1KeR8qA7Off6SWc5WNQqyQ==",
+      "version": "1.4.2",
+      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.2.tgz",
+      "integrity": "sha512-eAZS2sEUMlIeCjBeubdj45dmBHQwPHWyBcT1VSYB7o9x9WRRqKxyUoiXlRjyAwzN7YEzHJlYg0NmzDRWx6GP4Q==",
       "dev": true,
       "requires": {
         "eslint-visitor-keys": "^1.0.0"
@@ -5501,6 +5567,12 @@
       "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
       "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168="
     },
+    "lodash.unescape": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/lodash.unescape/-/lodash.unescape-4.0.1.tgz",
+      "integrity": "sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw=",
+      "dev": true
+    },
     "log": {
       "version": "1.4.0",
       "resolved": "http://registry.npmjs.org/log/-/log-1.4.0.tgz",
@@ -8049,6 +8121,15 @@
       "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.5.tgz",
       "integrity": "sha1-fcSjOvcVgatDN9qR2FylQn69mpc="
     },
+    "tsutils": {
+      "version": "3.17.1",
+      "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.17.1.tgz",
+      "integrity": "sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g==",
+      "dev": true,
+      "requires": {
+        "tslib": "^1.8.1"
+      }
+    },
     "tty-browserify": {
       "version": "0.0.0",
       "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",

+ 2 - 0
package.json

@@ -28,6 +28,8 @@
   "devDependencies": {
     "@babel/core": "^7.4.3",
     "@babel/preset-env": "^7.4.3",
+    "@typescript-eslint/eslint-plugin": "^2.0.0",
+    "@typescript-eslint/parser": "^2.0.0",
     "antlr4-webpack-loader": "^0.1.1",
     "babel-loader": "^8.0.5",
     "clean-webpack-plugin": "^2.0.1",

+ 10 - 0
tsconfig.json

@@ -0,0 +1,10 @@
+{
+  "compilerOptions": {
+    "target": "es2015",
+    "noImplicitAny": true,
+    "module": "commonjs",
+    "declaration": true,
+    "outDir": "./dist",
+    "strict": true
+  }
+}

+ 8 - 0
webpack.config.js

@@ -34,9 +34,17 @@ module.exports = {
               use: {
                 loader:'antlr4-webpack-loader'
               }
+            },
+            {
+              test: /\.tsx?$/,
+              use: 'ts-loader',
+              exclude: /node_modules/
             }
         ]
     },
+    resolve: {
+      extensions: [ '.tsx', '.ts', '.js' ]
+    },
     stats: {
         colors: true
     },