| 
					
				 | 
			
			
				@@ -4,7 +4,7 @@ import { StoreObjectArray } from './store/storeObjectArray'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { StoreObjectRef } from './store/storeObjectRef'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { Modes } from './modes'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { Context } from './context'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import { Types } from './../ast/types'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { Types } from './../typeSystem/types'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { Operators } from './../ast/operators'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { LanguageDefinedFunction } from './definedFunctions'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { resultTypeAfterInfixOp, resultTypeAfterUnaryOp } from './compatibilityTable'; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -12,6 +12,7 @@ import * as Commands from './../ast/commands/'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import * as Expressions from './../ast/expressions/'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { StoreObjectArrayAddress } from './store/storeObjectArrayAddress'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import { StoreObjectArrayAddressRef } from './store/storeObjectArrayAddressRef'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import { CompoundType } from './../typeSystem/compoundType'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -117,73 +118,24 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       for (let i = 0; i < values.length; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const stoObj = values[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const formalParameter = formalList[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        switch (formalParameter.dimensions) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          case 1: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (stoObj.lines > 0 && stoObj.columns === null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              && stoObj.subtype === formalParameter.type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              if(formalParameter.byRef && !stoObj.inStore) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                throw new Error('You must inform a variable as parameter'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              if(formalParameter.byRef) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                const ref = new StoreObjectArrayAddressRef(stoObj); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                calleeStore.insertStore(formalParameter.id, ref); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                calleeStore.insertStore(formalParameter.id, stoObj); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              // TODO: Better error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              throw new Error(`Parameter ${formalParameter.id} is not compatible with the value given.`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          case 2: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (stoObj.lines > 0 && stoObj.columns > 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              && stoObj.subtype === formalParameter.type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              if(formalParameter.byRef && !stoObj.inStore) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                throw new Error('You must inform a variable as parameter'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              if(formalParameter.byRef) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                const ref = new StoreObjectArrayAddressRef(stoObj); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                calleeStore.insertStore(formalParameter.id, ref); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                calleeStore.insertStore(formalParameter.id, stoObj); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              // TODO: Better error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              throw new Error(`Parameter ${formalParameter.id} is not compatible with the value given.`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(formalParameter.type.isCompatible(stoObj.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if(formalParameter.byRef && !stoObj.inStore) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new Error('You must inform a variable as parameter'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          case 0: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if(formalParameter.byRef && !stoObj.inStore) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              throw new Error('You must inform a variable as parameter'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } else if (formalParameter.type !== Types.ALL && stoObj.type !== formalParameter.type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              // TODO: Better error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              throw new Error(`Parameter ${formalParameter.id} is not compatible with ${stoObj.type}.`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if(formalParameter.byRef) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let ref = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (stoObj instanceof StoreObjectArrayAddress) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              ref = new StoreObjectArrayAddressRef(stoObj); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              if(formalParameter.byRef) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                let ref = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (stoObj instanceof StoreObjectArrayAddress) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  ref = new StoreObjectArrayAddressRef(stoObj); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  ref = new StoreObjectRef(stoObj.id, callerStore); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                calleeStore.insertStore(formalParameter.id, ref); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                calleeStore.insertStore(formalParameter.id, stoObj); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              ref = new StoreObjectRef(stoObj.id, callerStore); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            calleeStore.insertStore(formalParameter.id, ref); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            calleeStore.insertStore(formalParameter.id, stoObj); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          throw new Error(`Parameter ${formalParameter.id} is not compatible with the value given.`); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return calleeStore; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -332,7 +284,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const $value = this.evaluateExpression(sto, cmd.expression); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return $value.then(vl => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (vl.type !== Types.BOOLEAN) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (!vl.type.isCompatible(Types.BOOLEAN)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // TODO: Better error message -- Inform line and column from token!!!! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // THIS IF SHOULD BE IN A SEMANTIC ANALYSER 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return Promise.reject(new Error(`DoWhile expression must be of type boolean`)); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -356,7 +308,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       this.context.push(Context.BREAKABLE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const $value = this.evaluateExpression(store, cmd.expression); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return $value.then(vl => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(vl.type === Types.BOOLEAN) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(vl.type.isCompatible(Types.BOOLEAN)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           if(vl.value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             const $newStore = this.executeCommands(store, cmd.commands); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return $newStore.then(sto => { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -386,7 +338,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const $value = this.evaluateExpression(store, cmd.condition); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return $value.then(vl => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(vl.type === Types.BOOLEAN) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(vl.type.isCompatible(Types.BOOLEAN)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           if(vl.value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return this.executeCommands(store, cmd.ifTrue.commands); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } else if( cmd.ifFalse !== null){ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -416,11 +368,11 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const funcName = store.applyStore('$name'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return $value.then(vl => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(vl === null && funcType === Types.VOID) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(vl === null && funcType.isCompatible(Types.VOID)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return Promise.resolve(store); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (vl === null || funcType.type !== vl.type) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (vl === null || !funcType.type.isCompatible(vl.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           // TODO: Better error message -- Inform line and column from token!!!! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           // THIS IF SHOULD BE IN A SEMANTIC ANALYSER 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return Promise.reject(new Error(`Function ${funcName.value} must return ${funcType.type} instead of ${vl.type}.`)); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -459,7 +411,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   executeArrayIndexAssign (store, cmd) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return new Promise((resolve, reject) => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const mustBeArray = store.applyStore(cmd.id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if(mustBeArray.type !== Types.ARRAY) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if(!(mustBeArray.type instanceof CompoundType)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         reject(new Error(cmd.id + " is not a vector/matrix")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -468,7 +420,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const value$ =  this.evaluateExpression(store, cmd.expression); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       Promise.all([line$, column$, value$]).then(results => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const lineSO = results[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(lineSO.type !== Types.INTEGER) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(!Types.INTEGER.isCompatible(lineSO.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           // TODO: better error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           reject(new Error("Array dimension must be of type int")); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -478,7 +430,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const columnSO = results[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         let column = null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (columnSO !== null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if(columnSO.type !== Types.INTEGER) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if(!Types.INTEGER.isCompatible(columnSO.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // TODO: better error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             reject(new Error("Array dimension must be of type int")); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -502,14 +454,14 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const newArray = Object.assign(new StoreObjectArray(null,null,null), mustBeArray); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if (column !== null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         if (value.type === Types.ARRAY) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         if (value.type instanceof CompoundType) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				            reject(new Error("Invalid operation. This must be a value: line "+cmd.sourceInfo.line)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          newArray.value[line].value[column] = value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          store.updateStore(cmd.id, newArray); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-         if(mustBeArray.columns !== null && value.type !== Types.ARRAY) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         if(mustBeArray.columns !== null && value.type instanceof CompoundType) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           reject(new Error("Invalid operation. This must be a vector: line "+cmd.sourceInfo.line)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -529,7 +481,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const $columns = cmd.columns === null ? null: this.evaluateExpression(store, cmd.columns); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return Promise.all([$lines, $columns, $value]).then(values => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           const lineSO = values[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if(lineSO.type !== Types.INTEGER) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if(!Types.INTEGER.isCompatible(lineSO.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // TODO: better error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return Promise.reject(new Error("Array dimension must be of type int")); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -538,7 +490,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           const columnSO = values[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           let column = null 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           if (columnSO !== null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if(columnSO.type !== Types.INTEGER) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(!Types.INTEGER.isCompatible(columnSO.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               // TODO: better error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               return Promise.reject(new Error("Array dimension must be of type int")); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -546,10 +498,18 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             column = columnSO.number; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           const value = values[2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          const temp = new StoreObjectArray(cmd.subtype, line, column, null, cmd.isConst); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          const temp = new StoreObjectArray(cmd.type, line, column, null, cmd.isConst); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           store.insertStore(cmd.id, temp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if(value !== null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            store.updateStore(cmd.id, value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (value !== null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let realValue = value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(value instanceof StoreObjectArrayAddress) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              if(value.type instanceof CompoundType) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                realValue = Object.assign(new StoreObjectArray(null,null,null), value.refValue); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                realValue = Object.assign(new StoreObject(null,null), value.refValue); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            store.updateStore(cmd.id, realValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return store; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -558,8 +518,17 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const temp = new StoreObject(cmd.type, null, cmd.isConst); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         store.insertStore(cmd.id, temp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return $value.then(vl => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (vl !== null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            store.updateStore(cmd.id, vl) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (vl !== null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            let realValue = vl; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if(vl instanceof StoreObjectArrayAddress) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              if(vl.type instanceof CompoundType) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                realValue = Object.assign(new StoreObjectArray(null,null,null), vl.refValue); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                realValue = Object.assign(new StoreObject(null,null), vl.refValue); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+              } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            store.updateStore(cmd.id, realValue) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return store; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -597,14 +566,14 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   evaluateFunctionCall (store, exp) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const func = this.findFunction(exp.id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if(func.returnType === Types.VOID) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(Types.VOID.isCompatible(func.returnType)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // TODO: better error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return Promise.reject(new Error(`Function ${exp.id} cannot be used inside an expression`)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const $newStore = this.runFunction(func, exp.actualParameters, store); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return $newStore.then( sto => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const val = sto.applyStore('$'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (val.type === Types.ARRAY) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      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)); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -616,7 +585,8 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(!exp.isVector) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const $matrix = this.evaluateMatrix(store, exp.value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return $matrix.then(list => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        const arr = new StoreObjectArray(list[0].subtype, list.length, list[0].lines, list); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const type = new CompoundType(list[0].type.innerType, 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const arr = new StoreObjectArray(type, list.length, list[0].lines, list); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(arr.isValid) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return Promise.resolve(arr); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         else 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -624,7 +594,8 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return this.evaluateVector(store, exp.value).then(list => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        const stoArray = new StoreObjectArray(list[0].type, list.length, null, list); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const type = new CompoundType(list[0].type, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const stoArray = new StoreObjectArray(type, list.length, null, list); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(stoArray.isValid) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return Promise.resolve(stoArray); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         else 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -640,7 +611,10 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   evaluateMatrix (store, exps) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return Promise.all(exps.map( vector => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const $vector = this.evaluateVector(store, vector.value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      return $vector.then(list => new StoreObjectArray(list[0].type, list.length, null, list)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      return $vector.then(list => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        const type = new CompoundType(list[0].type, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return new StoreObjectArray(type, list.length, null, list) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } )); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -651,7 +625,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   evaluateVariableLiteral (store, exp) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const val = store.applyStore(exp.id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (val.type === Types.ARRAY) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      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)); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -663,8 +637,9 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   evaluateArrayAccess (store, exp) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const mustBeArray = store.applyStore(exp.id); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (mustBeArray.type !== Types.ARRAY) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!(mustBeArray.type instanceof CompoundType)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       // TODO: better error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      console.log(mustBeArray.type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return Promise.reject(new Error(`${exp.id} is not of type array`)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const $line = this.evaluateExpression(store, exp.line); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -672,7 +647,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return Promise.all([$line, $column]).then(values => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const lineSO = values[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const columnSO = values[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if(lineSO.type !== Types.INTEGER) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if(!Types.INTEGER.isCompatible(lineSO.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // TODO: better error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return Promise.reject(new Error("Array dimension must be of type int")); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -680,7 +655,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const line = lineSO.number; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       let column = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       if(columnSO !== null) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(columnSO.type !== Types.INTEGER) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if(!Types.INTEGER.isCompatible(columnSO.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           // TODO: better error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           //SHOULD NOT BE HERE. IT MUST HAVE A SEMANTIC ANALYSIS 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return Promise.reject(new Error("Array dimension must be of type int")); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -708,7 +683,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const $left = this.evaluateExpression(store, unaryApp.left); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return $left.then( left => { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const resultType = resultTypeAfterUnaryOp(unaryApp.op, left.type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (resultType === Types.UNDEFINED) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (Types.UNDEFINED.isCompatible(resultType)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // TODO: better urgent error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return Promise.reject(new Error(`Cannot use this op to ${left.type}`)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -732,9 +707,9 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const left = values[0]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const right = values[1]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       const resultType = resultTypeAfterInfixOp(infixApp.op, left.type, right.type); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      if (resultType === Types.UNDEFINED) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (Types.UNDEFINED.isCompatible(resultType)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // TODO: better urgent error message 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return Promise.reject(new Error(`Cannot use this ${infixApp.op.value} to ${left.type.value} and ${right.type.value}`)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return Promise.reject(new Error(`Cannot use this ${infixApp.op} to ${left.type} and ${right.type}`)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       let result = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       switch (infixApp.op.ord) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -746,7 +721,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return new StoreObject(resultType, left.value.times(right.value)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case Operators.DIV.ord: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           result = left.value / right.value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (resultType === Types.INTEGER) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (Types.INTEGER.isCompatible(resultType)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value.idiv(right.value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value.div(right.value); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -755,7 +730,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case Operators.MOD.ord: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return new StoreObject(resultType, left.value.modulo(right.value)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case Operators.GT.ord: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (left.type === Types.STRING) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (Types.STRING.isCompatible(left.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value.length > right.value.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value.gt(right.value); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -763,7 +738,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return new StoreObject(resultType, result); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case Operators.GE.ord: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (left.type === Types.STRING) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (Types.STRING.isCompatible(left.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value.length >= right.value.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value.gte(right.value); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -771,7 +746,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return new StoreObject(resultType, result); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case Operators.LT.ord: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (left.type === Types.STRING) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (Types.STRING.isCompatible(left.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value.length < right.value.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value.lt(right.value); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -779,7 +754,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return new StoreObject(resultType, result); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case Operators.LE.ord: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (left.type === Types.STRING) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (Types.STRING.isCompatible(left.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value.length <= right.value.length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value.lte(right.value); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -787,7 +762,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return new StoreObject(resultType, result); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case Operators.EQ.ord: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (left.type === Types.INTEGER || left.type === Types.REAL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (Types.INTEGER.isCompatible(left.type) || Types.REAL.isCompatible(left.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value.eq(right.value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value === right.value; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -795,7 +770,7 @@ export class IVProgProcessor { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           return new StoreObject(resultType, result); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         case Operators.NEQ.ord: { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          if (left.type === Types.INTEGER || left.type === Types.REAL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          if (Types.INTEGER.isCompatible(left.type) || Types.REAL.isCompatible(left.type)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = !left.value.eq(right.value); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             result = left.value !== right.value; 
			 |