Browse Source

Implement atomic variables StoreValue and StoreValueRef types

Rewrite Store implementation to update the value at the address defined by the StoreObject instead of allocation a new area

Remove StoreObjectRef updateRef method

Fix I/O lib error handler not correctly accessing the _refed_ var
Lucas de Souza 4 years ago
parent
commit
320394a16f

+ 1 - 0
.eslintrc.json

@@ -13,5 +13,6 @@
         "sourceType": "module"
     },
     "rules": {
+        "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }]
     }
 }

+ 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 {

+ 1 - 3
js/memory/address.ts

@@ -2,16 +2,14 @@ export class Address {
 
   public id: number;
   public value: any;
-  public is_var: boolean; // TODO Remove this line
 
   /**
    * 
    * @param {Number} id the address id
    * @param {*} value the value stored at this address
    */
-  constructor (id: number, value: any, is_var = false) {
+  constructor (id: number, value: any) {
     this.id = id;
     this.value = value;
-    this.is_var = is_var;
   }
 }

+ 5 - 17
js/memory/location.ts

@@ -18,6 +18,7 @@ class LocationHolder {
    */
   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;
@@ -43,7 +44,7 @@ class LocationHolder {
    * @param {Number} id 
    * @returns {Address} the address identified by id
    */
-  find (id: number): Address | null {
+  find (id: number): Address | undefined {
     let beg = 0
     let end = this.data.length;
     // console.log("Finding address "+id);
@@ -58,7 +59,7 @@ class LocationHolder {
         end = med
       }
     }
-    return null;
+    return undefined;
   }
 
   getAddressAt (pos: number): Address {
@@ -87,13 +88,12 @@ class LocationHolder {
     return -1;
   }
 
-  updateAddress (id: number, value: any, is_var = false): void {
+  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;
-    this.data[index].is_var = is_var;
   }
 
   clear () {
@@ -103,19 +103,8 @@ class LocationHolder {
     this.data = [];
     this.address_id = 0;
   }
-
-  gc (): number {
-    const to_remove = [];
-    for (let i = 0; i < this.data.length; i += 1) {
-      const address = this.data[i];
-      if (!address.is_var) {
-        to_remove.push(address.id);
-      }
-    }
-    to_remove.forEach(x => this.deallocate(x), this);
-    return to_remove.length;
-  }
 }
+
 const inner_ref = new LocationHolder();
 
 export const Location = Object.freeze({
@@ -124,6 +113,5 @@ export const Location = Object.freeze({
   find: inner_ref.find.bind(inner_ref),
   updateAddress: inner_ref.updateAddress.bind(inner_ref),
   clear: inner_ref.clear.bind(inner_ref),
-  gc: inner_ref.gc.bind(inner_ref),
   size: () => inner_ref.data.length
 });

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


+ 76 - 85
js/processor/ivprogProcessor.js

@@ -1,7 +1,6 @@
 import { Store } from './store/store';
 import { StoreObject } from './store/storeObject';
 import { StoreObjectArray } from './store/storeObjectArray';
-import { StoreObjectRef } from './store/storeObjectRef';
 import { Modes } from './modes';
 import { Context } from './context';
 import { Types } from './../typeSystem/types';
@@ -18,6 +17,8 @@ import { Config } from '../util/config';
 import { ProcessorErrorFactory } from './error/processorErrorFactory';
 import { RuntimeError } from './error/runtimeError';
 import { Location } from '../memory/location';
+import { StoreValue } from './store/store_value';
+import { StoreValueRef } from './store/store_value_ref';
 
 export class IVProgProcessor {
 
@@ -135,7 +136,7 @@ export class IVProgProcessor {
         returnStoreObject = new StoreObjectArray(func.returnType,-1,null,[]);
       }
     } else {
-      returnStoreObject = new StoreObject(func.returnType, Location.allocate(null));
+      returnStoreObject = new StoreValue(func.returnType, null, null);//new StoreObject(func.returnType, Location.allocate(null));
     }
     funcStore.insertStore('$', returnStoreObject);
     const newFuncStore$ = this.associateParameters(func.formalParameters, actualParameters, store, funcStore);
@@ -177,24 +178,25 @@ export class IVProgProcessor {
           }
         }
 
-        if(formalParameter.byRef && !stoObj.inStore) {
+        if(formalParameter.byRef && !stoObj.inStore()) {
           throw ProcessorErrorFactory.invalid_ref(funcName, exp.toString());
         }
 
         if(formalParameter.byRef) {
           let ref = null;
           if (stoObj instanceof StoreObjectArrayAddress) {
-            ref = new StoreObjectArrayAddressRef(stoObj);
+            ref = new StoreObjectArrayAddressRef(callerStore.getStoreObject(stoObj.id));
           } else {
-            ref = new StoreObjectRef(stoObj);
+            const realObj = callerStore.getStoreObject(stoObj.id);
+            ref = new StoreValueRef(realObj.type, realObj.value, realObj.locAddress, realObj.id);
           }
           calleeStore.insertStore(formalParameter.id, ref);
         } else {
-          let realValue = this.parseStoreObjectValue(stoObj);
+          let realValue = stoObj;
           if (shouldTypeCast) {
             realValue = Store.doImplicitCasting(formalParameter.type, realValue);
           }
-          calleeStore.insertStore(formalParameter.id, realValue.copy());
+          calleeStore.insertStore(formalParameter.id, realValue);
         }
       }
       return calleeStore;
@@ -221,9 +223,6 @@ export class IVProgProcessor {
     } else if(this.checkContext(Context.BREAKABLE) && store.mode === Modes.BREAK) {
       return Promise.resolve(store);
     }
-    if (Location.size() % 100 == 0) {
-      Location.gc();
-    }
     if (cmd instanceof Commands.Declaration) {
       return this.executeDeclaration(store, cmd);
     } else if (cmd instanceof Commands.ArrayIndexAssign) {
@@ -267,11 +266,7 @@ export class IVProgProcessor {
     }
     return this.runFunction(func, cmd.actualParameters, store)
       .then(sto => {
-        for(let id in sto.store) {
-          if (Object.prototype.hasOwnProperty.call(sto.store, id)) {
-            sto.store[id].destroy();
-          }
-        }
+        sto.destroy();
         if(!Types.VOID.isCompatible(func.returnType) && sto.mode !== Modes.RETURN) {
           const funcName = func.name === IVProgProcessor.MAIN_INTERNAL_ID ? 
             LanguageDefinedFunction.getMainFunctionName() : func.name;
@@ -279,7 +274,7 @@ export class IVProgProcessor {
         } else {
           return store;
         }
-      })
+      });
   }
 
   executeSwitch (store, cmd) {
@@ -295,7 +290,7 @@ export class IVProgProcessor {
         } else {
           const equalityInfixApp = new Expressions.InfixApp(Operators.EQ, cmd.expression, next.expression);
           equalityInfixApp.sourceInfo = next.sourceInfo;
-          return outerRef.evaluateExpression(tuple[1],equalityInfixApp).then(stoObj => stoObj.value)
+          return outerRef.evaluateExpression(tuple[1],equalityInfixApp).then(stoObj => stoObj.get())
             .then(isEqual => {
               if (isEqual) {
                 return this.executeCommands(tuple[1], next.commands)
@@ -353,10 +348,10 @@ export class IVProgProcessor {
           if (!vl.type.isCompatible(Types.BOOLEAN)) {
             return Promise.reject(ProcessorErrorFactory.loop_condition_type_full(cmd.sourceInfo));
           }
-          if (vl.value) {
+          if (vl.get()) {
             outerRef.context.pop();
-            for (let i = 0; i < outerRef.loopTimers.length; i++) {
-              const time = outerRef.loopTimers[i];
+            if(outerRef.loopTimers.length > 0) {
+              const time = outerRef.loopTimers[0];
               if(Date.now() - time >= IVProgProcessor.LOOP_TIMEOUT) {
                 outerRef.forceKill = true;
                 return Promise.reject(ProcessorErrorFactory.endless_loop_full(cmd.sourceInfo));
@@ -383,7 +378,7 @@ export class IVProgProcessor {
       const $value = outerRef.evaluateExpression(store, cmd.expression);
       return $value.then(vl => {
         if(vl.type.isCompatible(Types.BOOLEAN)) {
-          if(vl.value) {
+          if(vl.get()) {
             const $newStore = outerRef.executeCommands(store, cmd.commands);
             return $newStore.then(sto => {
               outerRef.context.pop();
@@ -392,8 +387,8 @@ export class IVProgProcessor {
                 sto.mode = Modes.RUN;
                 return sto;
               }
-              for (let i = 0; i < outerRef.loopTimers.length; i++) {
-                const time = outerRef.loopTimers[i];
+              if (outerRef.loopTimers.length > 0) {
+                const time = outerRef.loopTimers[0];
                 if(Date.now() - time >= IVProgProcessor.LOOP_TIMEOUT) {
                   outerRef.forceKill = true;
                   return Promise.reject(ProcessorErrorFactory.endless_loop_full(cmd.sourceInfo));
@@ -421,7 +416,7 @@ export class IVProgProcessor {
       const $value = this.evaluateExpression(store, cmd.condition);
       return $value.then(vl => {
         if(vl.type.isCompatible(Types.BOOLEAN)) {
-          if(vl.value) {
+          if(vl.get()) {
             return this.executeCommands(store, cmd.ifTrue.commands);
           } else if( cmd.ifFalse !== null){
             if(cmd.ifFalse instanceof Commands.IfThenElse) {
@@ -516,14 +511,14 @@ export class IVProgProcessor {
       if(!Types.INTEGER.isCompatible(lineSO.type)) {
         return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
       }
-      const line = lineSO.number;
+      const line = lineSO.get();
       const columnSO = results[1];
       let column = null
       if (columnSO !== null) {
         if(!Types.INTEGER.isCompatible(columnSO.type)) {
           return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
         }
-        column = columnSO.number;
+        column = columnSO.get();
       }
       const value = this.parseStoreObjectValue(results[2]);
       let actualValue = value;
@@ -599,7 +594,7 @@ export class IVProgProcessor {
           if(!Types.INTEGER.isCompatible(lineSO.type)) {
             return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
           }
-          const line = lineSO.number;
+          const line = lineSO.get();
           if(line < 0) {
             throw ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo);
           }
@@ -609,7 +604,7 @@ export class IVProgProcessor {
             if(!Types.INTEGER.isCompatible(columnSO.type)) {
               return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(cmd.sourceInfo));
             }
-            column = columnSO.number;
+            column = columnSO.get();
             if(column < 0) {
               throw ProcessorErrorFactory.array_dimension_not_positive_full(cmd.sourceInfo);
             }
@@ -644,7 +639,7 @@ export class IVProgProcessor {
         if(cmd.initial !== null) {
           $value = this.evaluateExpression(store, cmd.initial);
         }
-        const temp = new StoreObject(cmd.type, Location.allocate(null));
+        const temp = new StoreValue(cmd.type, null);
         store.insertStore(cmd.id, temp);
         return $value.then(vl => {
           let realValue = vl;
@@ -667,9 +662,9 @@ export class IVProgProcessor {
               }
             }
           } else {
-            realValue = new StoreObject(cmd.type, Location.allocate(0));
+            realValue = new StoreValue(cmd.type, 0);
           }
-          realValue.readOnly = cmd.isConst;
+          realValue.isConst = cmd.isConst;
           store.updateStore(cmd.id, realValue);
           return store;
         });
@@ -715,14 +710,10 @@ export class IVProgProcessor {
     const $newStore = this.runFunction(func, exp.actualParameters, store);
     return $newStore.then( sto => {
       if(sto.mode !== Modes.RETURN) {
-        return Promise.reject(new Error("The function that was called did not had a return command: "+exp.id));
+        return Promise.reject(new Error("The function that was called did not have a return command: "+exp.id));
       }
       const val = sto.applyStore('$');
-      for(let id in sto.store) {
-        if (Object.prototype.hasOwnProperty.call(sto.store, id)) {
-          sto.store[id].destroy();
-        }
-      }
+      sto.destroy();
       if (val instanceof StoreObjectArray) {
         return Promise.resolve(Object.assign(new StoreObjectArray(null,null,null,null,null), val));
       } else {
@@ -836,7 +827,7 @@ export class IVProgProcessor {
   }
 
   evaluateLiteral (_, exp) {
-    return Promise.resolve(new StoreObject(exp.type, Location.allocate(exp.value)));
+    return Promise.resolve(new StoreValue(exp.type, exp.value));
   }
 
   evaluateVariableLiteral (store, exp) {
@@ -865,13 +856,13 @@ export class IVProgProcessor {
       if(!Types.INTEGER.isCompatible(lineSO.type)) {
         return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(exp.sourceInfo));
       }
-      const line = lineSO.number;
+      const line = lineSO.get();
       let column = null;
       if(columnSO !== null) {
         if(!Types.INTEGER.isCompatible(columnSO.type)) {
           return Promise.reject(ProcessorErrorFactory.array_dimension_not_int_full(exp.sourceInfo));
         }
-        column = columnSO.number;
+        column = columnSO.get();
       }
 
       if (line >= mustBeArray.lines) {
@@ -909,11 +900,11 @@ export class IVProgProcessor {
       }
       switch (unaryApp.op.ord) {
         case Operators.ADD.ord:
-          return new StoreObject(resultType, Location.allocate(left.value));
+          return new StoreValue(resultType, left.get());
         case Operators.SUB.ord:
-          return new StoreObject(resultType, Location.allocate(left.value.negated()));
+          return new StoreValue(resultType, left.get().negated());
         case Operators.NOT.ord:
-          return new StoreObject(resultType, Location.allocate(!left.value));
+          return new StoreValue(resultType, !left.get());
         default:
           return Promise.reject(new RuntimeError('!!!Critical Invalid UnaryApp '+ unaryApp.op));
       }
@@ -944,37 +935,37 @@ export class IVProgProcessor {
       switch (infixApp.op.ord) {
         case Operators.ADD.ord: {
           if(Types.STRING.isCompatible(left.type)) {
-            const rightStr = convertToString(right.value, right.type);
-            return new StoreObject(resultType, Location.allocate(left.value + rightStr));
+            const rightStr = convertToString(right.get(), right.type);
+            return new StoreValue(resultType, (left.get() + rightStr));
           } else if (Types.STRING.isCompatible(right.type)) {
-            const leftStr = convertToString(left.value, left.type);
-            return new StoreObject(resultType, Location.allocate(leftStr + right.value));
+            const leftStr = convertToString(left.get(), left.type);
+            return new StoreValue(resultType, (leftStr + right.get()));
           } else {
-            return new StoreObject(resultType, Location.allocate(left.value.plus(right.value)));
+            return new StoreValue(resultType, (left.get().plus(right.get())));
           }
         }
         case Operators.SUB.ord:
-          return new StoreObject(resultType, Location.allocate(left.value.minus(right.value)));
+          return new StoreValue(resultType, (left.get().minus(right.get())));
         case Operators.MULT.ord: {
-          result = left.value.times(right.value);
+          result = left.get().times(right.get());
           // if(result.dp() > Config.decimalPlaces) {
           //   result = new Decimal(result.toFixed(Config.decimalPlaces));
           // }
-          return new StoreObject(resultType, Location.allocate(result));
+          return new StoreValue(resultType, result);
         }
         case Operators.DIV.ord: {
           if (Types.INTEGER.isCompatible(resultType))
-            result = left.value.divToInt(right.value);
+            result = left.get().divToInt(right.get());
           else
-            result = left.value.div(right.value);
+            result = left.get().div(right.get());
           // if(result.dp() > Config.decimalPlaces) {
           //   result = new Decimal(result.toFixed(Config.decimalPlaces));
           // }
-          return new StoreObject(resultType, Location.allocate(result));
+          return new StoreValue(resultType, (result));
         }
         case Operators.MOD.ord: {
-          let leftValue = left.value;
-          let rightValue = right.value;
+          let leftValue = left.get();
+          let rightValue = right.get();
           if(shouldImplicitCast) {
             resultType = Types.INTEGER;
             leftValue = leftValue.trunc();
@@ -984,13 +975,13 @@ export class IVProgProcessor {
           // if(result.dp() > Config.decimalPlaces) {
           //   result = new Decimal(result.toFixed(Config.decimalPlaces));
           // }
-          return new StoreObject(resultType, Location.allocate(result));
+          return new StoreValue(resultType, (result));
         }          
         case Operators.GT.ord: {
-          let leftValue = left.value;
-          let rightValue = right.value;
+          let leftValue = left.get();
+          let rightValue = right.get();
           if (Types.STRING.isCompatible(left.type)) {
-            result = left.value.length > right.value.length;
+            result = leftValue.length > rightValue.length;
           } else {
             if (shouldImplicitCast) {
               resultType = Types.BOOLEAN;
@@ -999,13 +990,13 @@ export class IVProgProcessor {
             }
             result = leftValue.gt(rightValue);
           }
-          return new StoreObject(resultType, Location.allocate(result));
+          return new StoreValue(resultType, result);
         }
         case Operators.GE.ord: {
-          let leftValue = left.value;
-          let rightValue = right.value;
+          let leftValue = left.get();
+          let rightValue = right.get();
           if (Types.STRING.isCompatible(left.type)) {
-            result = left.value.length >= right.value.length;
+            result = leftValue.length >= rightValue.length;
           } else {
             if (shouldImplicitCast) {
               resultType = Types.BOOLEAN;
@@ -1014,13 +1005,13 @@ export class IVProgProcessor {
             }
             result = leftValue.gte(rightValue);
           }
-          return new StoreObject(resultType, Location.allocate(result));
+          return new StoreValue(resultType, result);
         }
         case Operators.LT.ord: {
-          let leftValue = left.value;
-          let rightValue = right.value;
+          let leftValue = left.get();
+          let rightValue = right.get();
           if (Types.STRING.isCompatible(left.type)) {
-            result = left.value.length < right.value.length;
+            result = leftValue.length < rightValue.length;
           } else {
             if (shouldImplicitCast) {
               resultType = Types.BOOLEAN;
@@ -1029,13 +1020,13 @@ export class IVProgProcessor {
             }
             result = leftValue.lt(rightValue);
           }
-          return new StoreObject(resultType, Location.allocate(result));
+          return new StoreValue(resultType, (result));
         }
         case Operators.LE.ord: {
-          let leftValue = left.value;
-          let rightValue = right.value;
+          let leftValue = left.get();
+          let rightValue = right.get();
           if (Types.STRING.isCompatible(left.type)) {
-            result = left.value.length <= right.value.length;
+            result = leftValue.length <= rightValue.length;
           } else {
             if (shouldImplicitCast) {
               resultType = Types.BOOLEAN;
@@ -1044,11 +1035,11 @@ export class IVProgProcessor {
             }
             result = leftValue.lte(rightValue);
           }
-          return new StoreObject(resultType, Location.allocate(result));
+          return new StoreValue(resultType, result);
         }
         case Operators.EQ.ord: {
-          let leftValue = left.value;
-          let rightValue = right.value;
+          let leftValue = left.get();
+          let rightValue = right.get();
           if (Types.INTEGER.isCompatible(left.type) || Types.REAL.isCompatible(left.type)) {
             if (shouldImplicitCast) {
               resultType = Types.BOOLEAN;
@@ -1057,13 +1048,13 @@ export class IVProgProcessor {
             }
             result = leftValue.eq(rightValue);
           } else {
-            result = left.value === right.value;
+            result = leftValue === rightValue;
           }
-          return new StoreObject(resultType, Location.allocate(result));
+          return new StoreValue(resultType, result);
         }
         case Operators.NEQ.ord: {
-          let leftValue = left.value;
-          let rightValue = right.value;
+          let leftValue = left.get();
+          let rightValue = right.get();
           if (Types.INTEGER.isCompatible(left.type) || Types.REAL.isCompatible(left.type)) {
             if (shouldImplicitCast) {
               resultType = Types.BOOLEAN;
@@ -1072,14 +1063,14 @@ export class IVProgProcessor {
             }
             result = !leftValue.eq(rightValue);
           } else {
-            result = left.value !== right.value;
+            result = leftValue !== rightValue;
           }
-          return new StoreObject(resultType, Location.allocate(result));
+          return new StoreValue(resultType, result);
         }
         case Operators.AND.ord:
-          return new StoreObject(resultType, Location.allocate(left.value && right.value));
+          return new StoreValue(resultType, (left.get() && right.get()));
         case Operators.OR.ord:
-          return new StoreObject(resultType, Location.allocate(left.value || right.value));
+          return new StoreValue(resultType, (left.get() || right.get()));
         default:
           return Promise.reject(new RuntimeError('!!!Critical Invalid InfixApp '+ infixApp.op));
       }
@@ -1092,7 +1083,7 @@ export class IVProgProcessor {
       if(vl.type instanceof ArrayType) {
         switch(vl.type.dimensions) {
           case 1: {
-            realValue = new StoreObjectArray(vl.type, vl.value.length, null, vl.value);
+            realValue = new StoreObjectArray(vl.type, vl.get().length, null, vl.get());
             break;
           }
           default: {
@@ -1100,7 +1091,7 @@ export class IVProgProcessor {
           }
         }
       } else {
-        realValue = new StoreObject(vl.type, vl.value);
+        realValue = new StoreValue(vl.type, vl.get());
       }
     }
     return realValue;

+ 5 - 5
js/processor/lib/io.js

@@ -5,7 +5,7 @@ import {toInt, toString, toBool, toReal, convertToString} from './../../typeSyst
 import { Types } from './../../typeSystem/types';
 import { ProcessorErrorFactory } from "./../error/processorErrorFactory";
 import { StoreObjectArrayAddressRef } from '../store/storeObjectArrayAddressRef';
-import { Location } from '../../memory/location';
+import { StoreValue } from '../store/store_value';
 
 export function createOutputFun () {
   const writeFunction = function (store, _) {
@@ -46,7 +46,7 @@ export function createInputFun () {
         } else {
           return Promise.reject(new Error("!!!!Critical error: Unknown type in readFunction!!!!"));
         }
-      } catch (_) {
+      } catch (_) {StoreObject
         const stringInfo = typeToConvert.stringInfo()[0]
         const realObject = store.getStoreObject("p1");
         if (realObject instanceof StoreObjectArrayAddressRef) {
@@ -54,12 +54,12 @@ export function createInputFun () {
           const error = ProcessorErrorFactory.invalid_read_type_array(text, stringInfo.type, stringInfo.dim, realObject.address.refID, arrayInfo.type, arrayInfo.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)
-      const stoObj = new StoreObject(type, Location.allocate(result));
-      store.updateStore('p1', stoObj);
+      const stoValue = new StoreValue(type, result);
+      store.updateStore('p1', stoValue);
       store.mode = Modes.RETURN;
       return Promise.resolve(store);
     });

+ 6 - 2
js/processor/store/array_store_value.ts

@@ -4,13 +4,13 @@ import { Type } from "../../typeSystem/type";
 export class ArrayStoreValue implements IStoreValue {
 
   public type: Type; 
-  public id: String | null;
+  public id?: String;
   public isConst: boolean;
   public lines: number;
   public columns: number;
   public values: any[];
 
-  constructor(type: Type, values: any[], id: String | null, lines: number, columns: number, isConst = false) {
+  constructor(type: Type, values: any[], lines: number, columns: number, id?: String, isConst = false) {
     this.type = type;
     this.id = id;
     this.isConst = isConst
@@ -32,4 +32,8 @@ export class ArrayStoreValue implements IStoreValue {
     const pos = column * this.lines + line;
     this.values[pos] = value;
   }
+
+  inStore () {
+    return this.id != null;
+  }
 }

+ 2 - 1
js/processor/store/istore_value.ts

@@ -3,6 +3,7 @@ import { Type } from "./../../typeSystem/type";
 export interface IStoreValue {
   type: Type;
   get () : any;
-  id : String | null;
+  id? : String;
   isConst: boolean;
+  inStore: () => boolean;
 }

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

@@ -1,114 +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 = new Map();
-    this.nextStore = null;
-    this.mode = Modes.RUN; 
-  }
-
-  extendStore (nextStore) {
-    this.nextStore = nextStore;
-  }
-
-  applyStore (id) {
-    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);
-    if (val.isRef) {
-      return val.getRefObj();
-    }
-    return val;
-  }
-
-  updateStore (id, stoObj) {
-    if(!this.store.has(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.get(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)) {
-        const newObj = stoObj.copy();
-        stoObj.destroy();
-        newObj.setID(id);
-        this.store.get(id).destroy();
-        this.store.set(id, newObj);
-        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.has(id)) {
-      // TODO: better error message
-      throw new Error(`${id} is already defined`);
-    }
-    stoObj.setID(id);
-    this.store.set(id, 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.has(id)) {
-      if (this.nextStore !== null) {
-        return this.nextStore.getStoreObject(id);
-      } else {
-        throw new Error(`Variable ${id} not found.`);
-      }
-    }
-    return this.store.get(id);
-  }
-}

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

@@ -0,0 +1,145 @@
+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 './array_store_value';
+import { IStoreValue } from './istore_value';
+import { StoreValue } from './store_value';
+import { Location } from '../../memory/location';
+import { StoreValueRef } from './store_value_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) {
+      result = new ArrayStoreValue(val.type, val.value, 0, 0, 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.type instanceof ArrayType) {
+        // oldObj.updateRef(stoValue);
+        return this;
+      } else if (oldObj.isCompatible(stoValue)) {
+        // TODO check for array....
+        // const loc_address = Location.allocate(stoValue.get());
+        // const newObj = new StoreObject(stoValue.type, loc_address, stoValue.isConst);
+        // newObj.setID(id);
+        // this.store.get(id)!.destroy();
+        // this.store.set(id, newObj);
+        const loc_address = oldObj.locAddress;
+        Location.updateAddress(loc_address, stoValue.get());
+        return this;
+      } else {
+        const oldType = oldObj.type;
+        const stoType = stoValue.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: 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) {
+      // TODO check for array....
+      newObj = new StoreObjectRef(stoValue, stoValue.getRefAddress());
+    } 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);
+  }
+}

+ 6 - 10
js/processor/store/storeObject.ts

@@ -1,12 +1,13 @@
 import { Location } from "../../memory/location";
 import { Type } from '../../typeSystem/type';
+import { IStoreValue } from "./istore_value";
 
 export class StoreObject {
 
   private _type: Type;
   private _loc_address: number;
   private _readOnly: boolean;
-  private _id : String | null;
+  private _id?: String;
 
   /**
    * 
@@ -18,12 +19,12 @@ export class StoreObject {
     this._loc_address = loc_address;
     this._type = type;
     this._readOnly = readOnly;
-    this._id = null;
+    this._id = undefined;
   }
 
-  setID (id: String | null) {
+  setID (id: String) {
     this._id = id;
-    Location.updateAddress(this._loc_address, this.value, true);
+    Location.updateAddress(this._loc_address, this.value);
   }
 
   get id () {
@@ -63,7 +64,7 @@ export class StoreObject {
     this._readOnly = value;
   }
 
-  isCompatible (another: StoreObject) {
+  isCompatible (another: IStoreValue) {
     return this.type.isCompatible(another.type);
   }
 
@@ -71,11 +72,6 @@ export class StoreObject {
     return Location.deallocate(this._loc_address);
   }
 
-  copy () {
-    const clone = new StoreObject(this.type, Location.allocate(this.value), this.readOnly);
-    return clone;
-  }
-
   get locAddress () {
     return this._loc_address;
   }

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

@@ -46,7 +46,7 @@ export class StoreObjectArray extends StoreObject {
     if (this.value !== null) {
       if( this.isVector) {
         if(this.value.length !== this.lines) {
-          return [StoreObjectArray.WRONG_LINE_NUMBER, this.value.length];;
+          return [StoreObjectArray.WRONG_LINE_NUMBER, this.value.length];
         }
         // const mustBeNull = this.value.find(v => !this.type.canAccept(v.type) );
         // if(!!mustBeNull) {

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

@@ -1,31 +1,28 @@
 import { StoreObject } from './storeObject';
 import { Location } from '../../memory/location';
+import { IStoreValue } from './istore_value';
 
 export class StoreObjectRef extends StoreObject {
 
-  private refObj: StoreObject;
+  private refObj: String;
 
   /**
    * 
-   * @param {StoreObject} stoObj 
+   * @param {StoreObject} stoValue 
    */
-  constructor (stoObj: StoreObject) {
-    super(stoObj.type, stoObj.locAddress, false);
-    this.refObj = stoObj;
+  constructor (stoValue: IStoreValue, loc_address: number) {
+    super(stoValue.type, loc_address, false);
+    this.refObj = stoValue.id!;
   }
 
   get isRef () {
     return true;
   }
 
-  getRefObj () {
+  getRefObj (): String {
     return this.refObj;
   }
 
-  updateRef (stoObj: StoreObject) {
-    Location.updateAddress(this.locAddress, stoObj.value);
-  }
-
   destroy () {
     return false;
   }

+ 6 - 2
js/processor/store/store_value.ts

@@ -4,11 +4,11 @@ import { Type } from "../../typeSystem/type";
 export class StoreValue implements IStoreValue {
   
   public type: Type;
-  public id: String;
+  public id?: String;
   public isConst: boolean;
   public value: any;
 
-  constructor(type: Type, value: any, id:String, isConst = false) {
+  constructor(type: Type, value: any, id?:String, isConst = false) {
     this.type = type;
     this.id = id;
     this.isConst = isConst
@@ -19,4 +19,8 @@ export class StoreValue implements IStoreValue {
     return this.value;
   }
 
+  inStore () {
+    return this.id != null;
+  }
+
 }

+ 23 - 0
js/processor/store/store_value_ref.ts

@@ -0,0 +1,23 @@
+import { IStoreValue } from "./istore_value";
+import { Type } from "../../typeSystem/type";
+
+export class StoreValueRef implements IStoreValue {
+
+  public isConst = false;
+
+  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;
+  }
+}