Browse Source

Implement Location and Address to emulate memory allocation/deallocation to facilitate refference usage inside the program and other future improvements

Implement temporary garbage collection function

Implement initial code for StoreValue(value available for computation) and StoreObject(value stored in a location address, actual vars)

Rewrite the type system from js to typescript
Lucas de Souza 4 years ago
parent
commit
ce0a504f75

+ 1 - 0
.gitignore

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

+ 17 - 0
js/memory/address.ts

@@ -0,0 +1,17 @@
+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) {
+    this.id = id;
+    this.value = value;
+    this.is_var = is_var;
+  }
+}

+ 129 - 0
js/memory/location.ts

@@ -0,0 +1,129 @@
+
+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;
+    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 | null {
+    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 null;
+  }
+
+  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, is_var = false): 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 () {
+    for (let i = 0; i < this.data.length; i += 1) {
+      delete this.data[i];
+    }
+    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({
+  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),
+  gc: inner_ref.gc.bind(inner_ref),
+  size: () => inner_ref.data.length
+});

+ 49 - 38
js/processor/ivprogProcessor.js

@@ -15,11 +15,9 @@ import { StoreObjectArrayAddressRef } from './store/storeObjectArrayAddressRef';
 import { ArrayType } from './../typeSystem/array_type';
 import { convertToString } from '../typeSystem/parsers';
 import { Config } from '../util/config';
-import Decimal from 'decimal.js';
 import { ProcessorErrorFactory } from './error/processorErrorFactory';
 import { RuntimeError } from './error/runtimeError';
-import { Type } from '../typeSystem/type';
-import { Literal } from '../ast/expressions/literal';
+import { Location } from '../memory/location';
 
 export class IVProgProcessor {
 
@@ -88,6 +86,7 @@ export class IVProgProcessor {
 
   interpretAST () {
     this.prepareState();
+    Location.clear();
     return this.initGlobal().then( _ => {
       const mainFunc = this.findMainFunction();
       if(mainFunc === null) {
@@ -111,13 +110,13 @@ export class IVProgProcessor {
   findFunction (name) {
     if(name.match(/^\$.+$/)) {
       const fun = LanguageDefinedFunction.getFunction(name);
-      if(!!!fun) {
+      if(!fun) {
         throw ProcessorErrorFactory.not_implemented(name);
       }
       return fun;
     } else {
       const val = this.ast.functions.find( v => v.name === name);
-      if (!!!val) {
+      if (!val) {
         throw ProcessorErrorFactory.function_missing(name);
       }
       return val;
@@ -136,7 +135,7 @@ export class IVProgProcessor {
         returnStoreObject = new StoreObjectArray(func.returnType,-1,null,[]);
       }
     } else {
-      returnStoreObject = new StoreObject(func.returnType, null);
+      returnStoreObject = new StoreObject(func.returnType, Location.allocate(null));
     }
     funcStore.insertStore('$', returnStoreObject);
     const newFuncStore$ = this.associateParameters(func.formalParameters, actualParameters, store, funcStore);
@@ -187,7 +186,7 @@ export class IVProgProcessor {
           if (stoObj instanceof StoreObjectArrayAddress) {
             ref = new StoreObjectArrayAddressRef(stoObj);
           } else {
-            ref = new StoreObjectRef(stoObj.id, callerStore);
+            ref = new StoreObjectRef(stoObj);
           }
           calleeStore.insertStore(formalParameter.id, ref);
         } else {
@@ -195,7 +194,7 @@ export class IVProgProcessor {
           if (shouldTypeCast) {
             realValue = Store.doImplicitCasting(formalParameter.type, realValue);
           }
-          calleeStore.insertStore(formalParameter.id, realValue);
+          calleeStore.insertStore(formalParameter.id, realValue.copy());
         }
       }
       return calleeStore;
@@ -222,7 +221,9 @@ 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) {
@@ -244,8 +245,7 @@ export class IVProgProcessor {
     } else if (cmd instanceof Commands.Switch) {
       return this.executeSwitch(store, cmd);
     } else if (cmd instanceof Expressions.FunctionCall) {
-      
-      return this.executeFunctionCall(store, cmd);
+      return this.executeFunctionCall(store, cmd);     
     } else if (cmd instanceof Commands.SysCall) {
       return this.executeSysCall(store, cmd);
     } else {
@@ -267,6 +267,11 @@ 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();
+          }
+        }
         if(!Types.VOID.isCompatible(func.returnType) && sto.mode !== Modes.RETURN) {
           const funcName = func.name === IVProgProcessor.MAIN_INTERNAL_ID ? 
             LanguageDefinedFunction.getMainFunctionName() : func.name;
@@ -618,6 +623,7 @@ export class IVProgProcessor {
               if(value.type instanceof ArrayType) {
                 realValue = Object.assign(new StoreObjectArray(null,null,null), value.refValue);
               } else {
+                // TODO - update StoObj
                 realValue = Object.assign(new StoreObject(null,null), value.refValue);
               }
             }
@@ -638,7 +644,7 @@ export class IVProgProcessor {
         if(cmd.initial !== null) {
           $value = this.evaluateExpression(store, cmd.initial);
         }
-        const temp = new StoreObject(cmd.type, null);
+        const temp = new StoreObject(cmd.type, Location.allocate(null));
         store.insertStore(cmd.id, temp);
         return $value.then(vl => {
           let realValue = vl;
@@ -647,7 +653,7 @@ export class IVProgProcessor {
               if(Config.enable_type_casting && Store.canImplicitTypeCast(cmd.type, vl.type)) {
                 realValue = Store.doImplicitCasting(cmd.type, realValue);
               } else {
-                const stringInfo = typeInfo.type.stringInfo();
+                const stringInfo = vl.type.stringInfo();
                 const info = stringInfo[0];
                 return Promise.reject(ProcessorErrorFactory.incompatible_types_full(info.type, info.dim, cmd.sourceInfo));
               }
@@ -656,11 +662,12 @@ export class IVProgProcessor {
               if(vl.type instanceof ArrayType) {
                 return Promise.reject(new Error("!!!Critical Error: Compatibility check failed, a Type accepts a ArrayType"))
               } else {
+                // TODO - update StoObj
                 realValue = Object.assign(new StoreObject(null,null), vl.refValue);
               }
             }
           } else {
-            realValue = new StoreObject(cmd.type, 0);
+            realValue = new StoreObject(cmd.type, Location.allocate(0));
           }
           realValue.readOnly = cmd.isConst;
           store.updateStore(cmd.id, realValue);
@@ -672,8 +679,7 @@ export class IVProgProcessor {
     }
   }
 
-   evaluateExpression (store, exp) {
-
+  evaluateExpression (store, exp) {
     if (exp instanceof Expressions.UnaryApp) {
       return this.evaluateUnaryApp(store, exp);
     } else if (exp instanceof Expressions.InfixApp) {
@@ -712,10 +718,15 @@ export class IVProgProcessor {
         return Promise.reject(new Error("The function that was called did not had 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();
+        }
+      }
       if (val instanceof StoreObjectArray) {
         return Promise.resolve(Object.assign(new StoreObjectArray(null,null,null,null,null), val));
       } else {
-        return Promise.resolve(Object.assign(new StoreObject(null,null), val));
+        return val;
       }
     });
   }
@@ -825,7 +836,7 @@ export class IVProgProcessor {
   }
 
   evaluateLiteral (_, exp) {
-    return Promise.resolve(new StoreObject(exp.type, exp.value));
+    return Promise.resolve(new StoreObject(exp.type, Location.allocate(exp.value)));
   }
 
   evaluateVariableLiteral (store, exp) {
@@ -834,7 +845,7 @@ export class IVProgProcessor {
       if (val instanceof StoreObjectArray) {
         return Promise.resolve(Object.assign(new StoreObjectArray(null,null,null,null), val));
       } else {
-        return Promise.resolve(Object.assign(new StoreObject(null,null), val));
+        return Promise.resolve(val);
       }
     } catch (error) {
       return Promise.reject(error);
@@ -898,11 +909,11 @@ export class IVProgProcessor {
       }
       switch (unaryApp.op.ord) {
         case Operators.ADD.ord:
-          return new StoreObject(resultType, left.value);
+          return new StoreObject(resultType, Location.allocate(left.value));
         case Operators.SUB.ord:
-          return new StoreObject(resultType, left.value.negated());
+          return new StoreObject(resultType, Location.allocate(left.value.negated()));
         case Operators.NOT.ord:
-          return new StoreObject(resultType, !left.value);
+          return new StoreObject(resultType, Location.allocate(!left.value));
         default:
           return Promise.reject(new RuntimeError('!!!Critical Invalid UnaryApp '+ unaryApp.op));
       }
@@ -934,22 +945,22 @@ export class IVProgProcessor {
         case Operators.ADD.ord: {
           if(Types.STRING.isCompatible(left.type)) {
             const rightStr = convertToString(right.value, right.type);
-            return new StoreObject(resultType, left.value + rightStr);
+            return new StoreObject(resultType, Location.allocate(left.value + rightStr));
           } else if (Types.STRING.isCompatible(right.type)) {
             const leftStr = convertToString(left.value, left.type);
-            return new StoreObject(resultType, leftStr + right.value);
+            return new StoreObject(resultType, Location.allocate(leftStr + right.value));
           } else {
-            return new StoreObject(resultType, left.value.plus(right.value));
+            return new StoreObject(resultType, Location.allocate(left.value.plus(right.value)));
           }
         }
         case Operators.SUB.ord:
-          return new StoreObject(resultType, left.value.minus(right.value));
+          return new StoreObject(resultType, Location.allocate(left.value.minus(right.value)));
         case Operators.MULT.ord: {
           result = left.value.times(right.value);
           // if(result.dp() > Config.decimalPlaces) {
           //   result = new Decimal(result.toFixed(Config.decimalPlaces));
           // }
-          return new StoreObject(resultType, result);
+          return new StoreObject(resultType, Location.allocate(result));
         }
         case Operators.DIV.ord: {
           if (Types.INTEGER.isCompatible(resultType))
@@ -959,7 +970,7 @@ export class IVProgProcessor {
           // if(result.dp() > Config.decimalPlaces) {
           //   result = new Decimal(result.toFixed(Config.decimalPlaces));
           // }
-          return new StoreObject(resultType, result);
+          return new StoreObject(resultType, Location.allocate(result));
         }
         case Operators.MOD.ord: {
           let leftValue = left.value;
@@ -973,7 +984,7 @@ export class IVProgProcessor {
           // if(result.dp() > Config.decimalPlaces) {
           //   result = new Decimal(result.toFixed(Config.decimalPlaces));
           // }
-          return new StoreObject(resultType, result);
+          return new StoreObject(resultType, Location.allocate(result));
         }          
         case Operators.GT.ord: {
           let leftValue = left.value;
@@ -988,7 +999,7 @@ export class IVProgProcessor {
             }
             result = leftValue.gt(rightValue);
           }
-          return new StoreObject(resultType, result);
+          return new StoreObject(resultType, Location.allocate(result));
         }
         case Operators.GE.ord: {
           let leftValue = left.value;
@@ -1003,7 +1014,7 @@ export class IVProgProcessor {
             }
             result = leftValue.gte(rightValue);
           }
-          return new StoreObject(resultType, result);
+          return new StoreObject(resultType, Location.allocate(result));
         }
         case Operators.LT.ord: {
           let leftValue = left.value;
@@ -1018,7 +1029,7 @@ export class IVProgProcessor {
             }
             result = leftValue.lt(rightValue);
           }
-          return new StoreObject(resultType, result);
+          return new StoreObject(resultType, Location.allocate(result));
         }
         case Operators.LE.ord: {
           let leftValue = left.value;
@@ -1033,7 +1044,7 @@ export class IVProgProcessor {
             }
             result = leftValue.lte(rightValue);
           }
-          return new StoreObject(resultType, result);
+          return new StoreObject(resultType, Location.allocate(result));
         }
         case Operators.EQ.ord: {
           let leftValue = left.value;
@@ -1048,7 +1059,7 @@ export class IVProgProcessor {
           } else {
             result = left.value === right.value;
           }
-          return new StoreObject(resultType, result);
+          return new StoreObject(resultType, Location.allocate(result));
         }
         case Operators.NEQ.ord: {
           let leftValue = left.value;
@@ -1063,12 +1074,12 @@ export class IVProgProcessor {
           } else {
             result = left.value !== right.value;
           }
-          return new StoreObject(resultType, result);
+          return new StoreObject(resultType, Location.allocate(result));
         }
         case Operators.AND.ord:
-          return new StoreObject(resultType, left.value && right.value);
+          return new StoreObject(resultType, Location.allocate(left.value && right.value));
         case Operators.OR.ord:
-          return new StoreObject(resultType, left.value || right.value);
+          return new StoreObject(resultType, Location.allocate(left.value || right.value));
         default:
           return Promise.reject(new RuntimeError('!!!Critical Invalid InfixApp '+ infixApp.op));
       }
@@ -1077,7 +1088,7 @@ export class IVProgProcessor {
 
   parseStoreObjectValue (vl) {
     let realValue = vl;
-    if(vl instanceof StoreObjectArrayAddress) {      
+    if(vl instanceof StoreObjectArrayAddress) {
       if(vl.type instanceof ArrayType) {
         switch(vl.type.dimensions) {
           case 1: {

+ 14 - 8
js/processor/lib/io.js

@@ -5,6 +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';
 
 export function createOutputFun () {
   const writeFunction = function (store, _) {
@@ -27,20 +28,24 @@ 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");
@@ -52,7 +57,8 @@ export function createInputFun () {
         const error = ProcessorErrorFactory.invalid_read_type(text, stringInfo.type, stringInfo.dim, store.applyStore('p1').id);
         return Promise.reject(error);
       }
-      this.loopTimers.splice(0,this.loopTimers.length)
+      this.loopTimers.splice(0, this.loopTimers.length)
+      const stoObj = new StoreObject(type, Location.allocate(result));
       store.updateStore('p1', stoObj);
       store.mode = Modes.RETURN;
       return Promise.resolve(store);

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


+ 35 - 0
js/processor/store/array_store_value.ts

@@ -0,0 +1,35 @@
+import { IStoreValue } from "./istore_value";
+import { Type } from "../../typeSystem/type";
+
+export class ArrayStoreValue implements IStoreValue {
+
+  public type: Type; 
+  public id: String | null;
+  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) {
+    this.type = type;
+    this.id = id;
+    this.isConst = isConst
+    this.values = values;
+    this.lines = lines;
+    this.columns = columns;
+  }
+
+  get (): any[] {
+    return this.values;
+  }
+
+  getAt (line: number, column = 0): any {
+    const pos = column * this.lines + line;
+    return this.values[pos];
+  }
+
+  setAt (value: any, line:number, column = 0): any {
+    const pos = column * this.lines + line;
+    this.values[pos] = value;
+  }
+}

+ 8 - 0
js/processor/store/istore_value.ts

@@ -0,0 +1,8 @@
+import { Type } from "./../../typeSystem/type";
+
+export interface IStoreValue {
+  type: Type;
+  get () : any;
+  id : String | null;
+  isConst: boolean;
+}

+ 6 - 3
js/processor/store/store.js

@@ -69,8 +69,11 @@ export class Store {
         oldObj.updateRef(stoObj);
         return this;
       } else if(oldObj.isCompatible(stoObj)) {
-        stoObj.setID(id);
-        this.store[id] = Object.freeze(stoObj);
+        const newObj = stoObj.copy();
+        stoObj.destroy();
+        newObj.setID(id);
+        this.store[id].destroy();
+        this.store[id] = newObj;
         return this;
       } else {
         const oldType = oldObj.type;
@@ -91,7 +94,7 @@ export class Store {
       throw new Error(`${id} is already defined`);
     }
     stoObj.setID(id);
-    this.store[id] = Object.freeze(stoObj);
+    this.store[id] = stoObj;
     return 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;
-  }
-}

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

@@ -0,0 +1,82 @@
+import { Location } from "../../memory/location";
+import { Type } from '../../typeSystem/type';
+
+export class StoreObject {
+
+  private _type: Type;
+  private _loc_address: number;
+  private _readOnly: boolean;
+  private _id : String | null;
+
+  /**
+   * 
+   * @param {Type} type 
+   * @param {Number} loc_address 
+   * @param {Boolean} readOnly 
+   */
+  constructor (type: Type, loc_address: number, readOnly = false) {
+    this._loc_address = loc_address;
+    this._type = type;
+    this._readOnly = readOnly;
+    this._id = null;
+  }
+
+  setID (id: String | null) {
+    this._id = id;
+    Location.updateAddress(this._loc_address, this.value, true);
+  }
+
+  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: StoreObject) {
+    return this.type.isCompatible(another.type);
+  }
+
+  destroy () {
+    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 - 0
js/processor/store/storeObjectArray.js

@@ -73,4 +73,5 @@ export class StoreObjectArray extends StoreObject {
     } 
     return [];
   }
+
 }

+ 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);
-  }
-}

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

@@ -0,0 +1,32 @@
+import { StoreObject } from './storeObject';
+import { Location } from '../../memory/location';
+
+export class StoreObjectRef extends StoreObject {
+
+  private refObj: StoreObject;
+
+  /**
+   * 
+   * @param {StoreObject} stoObj 
+   */
+  constructor (stoObj: StoreObject) {
+    super(stoObj.type, stoObj.locAddress, false);
+    this.refObj = stoObj;
+  }
+
+  get isRef () {
+    return true;
+  }
+
+  getRefObj () {
+    return this.refObj;
+  }
+
+  updateRef (stoObj: StoreObject) {
+    Location.updateAddress(this.locAddress, stoObj.value);
+  }
+
+  destroy () {
+    return false;
+  }
+}

+ 22 - 0
js/processor/store/store_value.ts

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

+ 4 - 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,12 @@ 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 => {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());
     }
     
   });

+ 16 - 7
js/typeSystem/array_type.js

@@ -1,18 +1,19 @@
+import { IType } from "./itype";
 import { Type } from "./type";
 
-export class ArrayType extends Type {
+export class ArrayType implements IType {
 
-  constructor (type, dimensions) {
-    super(null);
+  public innerType: IType;
+
+  constructor (type: Type, public dimensions: number) {
     this.innerType = type;
-    this.dimensions = dimensions;
   }
 
   get isVector () {
     return this.dimensions == 1;
   }
 
-  isCompatible (another) {
+  isCompatible (another: IType): boolean {
     if(another instanceof ArrayType){
       if(this.dimensions !== another.dimensions) {
         return false;
@@ -30,9 +31,17 @@ export class ArrayType extends Type {
     return list;
   }
 
-  canAccept (another) {
+  get value () {
+    return null;
+  }
+
+  get ord () {
+    return null;
+  }
+
+  canAccept (another: IType) {
     if(another instanceof ArrayType) {
-      return false;// return this.dimensions > another.dimensions && this.innerType.isCompatible(another.innerType);
+      return false; // return this.dimensions > another.dimensions && this.innerType.isCompatible(another.innerType);
     } else {
       return this.dimensions == 1 && 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 | null;
+
+  ord: number | null;
+
+  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 null;
+  }
+
+  get ord () {
+    return null;
+  }
+
+  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
-});

+ 20 - 0
js/typeSystem/types.ts

@@ -0,0 +1,20 @@
+import { Type } from "./type";
+import { MultiType } from "./multiType";
+
+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]);
+
+export const Types = Object.freeze({
+  INTEGER: INTEGER,
+  REAL: REAL,
+  STRING: STRING,
+  BOOLEAN: BOOLEAN,
+  VOID: VOID,
+  UNDEFINED: UNDEFINED,
+  ALL: ALL
+});

+ 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);
+}

+ 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
     },