//Compiler Version 0.4 beta Mon Sep 22 15:31:21 2008
// Reflection System
var inafn:=false;
var initfntext:=new ArrayList[];
var fnparallel:=false;
var SemExpPhase:=0;
var BaseC:=0;
var functioncallnest:=0;	// this is for calling a function from within another function - before called the generateCode lots when used in a scope block
var totalprocesses:=1;
var currentprocesses:=1;
var blockparreset:=0;
var synccount:=0;
var holdtotal:=false;
var conditionalisunknown:=false;
var unknownconditionalrevert:=new ArrayList[];
var MPIWindowcount:=0;
var MPIstatuscnt:=0;
var ignoreinterference:=false;
var lastproc;
var syncs:=new syncclass[];
var currentparallelprocess:=0;
var parallelgeneratecounter:=0;
var output:=new textcollection[];
var methodeval:=0;
var mpirequestid:=0;
var commerrorcnt:=0;
var intry:=false;
var scopeinfo;
var typeblockenabled:=false;
var optimiseblockenabled:=false;
var sharedpoolsizeneeded:=0;
var returntype;
var insideloop:=0;
var sharedpoolids:=0;
var insideparblock:=false;
var parlastid;
var variabletypes;
var inmodtype:=false;
var MESH:= class Reflection  (
/*
	Specialist sync method, due to a bug atm we need to have another exp with it i.e. sync null
	First written 10/4/07 by Nick Brown
*/
var inclass SemUserExp1:= class (superclass.SemUserExp1) 
(
        name:= "sync";     
        var totsync:=0;
        var dynamic mysyncid:=0;
        var dynamic neededtodo:=false;   
        var eval:=method[] att start[];
        var checkParallel:=method[]
        (
        	// dont do much, just init the sync id :)
        	mysyncid:=totsync;
        	totsync=totsync + 1;
        );
        var checkSequential:=method[] checkParallel[];
        var checkExpression:=method[] errors.SExpressionError[];
        var checkType:=method[] skip;       	        
       	
       	var generateCode:=method[]
       	{       		           		
       		if (e==null)
       		(
       			output.add["MESHSyncAll();"];
       			misc.cleanDirtyValues[];
       		) else (
       			output.add["MESHSyncWithVariableName(\""];
       			e.setDirty[false];
       			misc.cleanDirtyLink[e];       			
       			e.generateName[];
       			output.add["\\0\");"];       	
       			if (insideparblock==true)
       			(
       				if (parallelgeneratecounter==parlastid + 1)
       				(
       					if (misc.checkIsASync[e]==false)
       					(
       						warnings.add[];
       						warnings.addtext["Sync number "];
       						warnings.addtext[mysyncid];
       						warnings.addtext[" for variable "];
       						warnings.addtext[e.getName[]];
       						warnings.addtext[" is pointless"];        						
       					) else (
       						misc.clearSync[e];
       					);
       				);
       			) else (
       				if (misc.checkIsASync[e]==false)
       				(
       					warnings.add[];
       					warnings.addtext["Sync number "];
       					warnings.addtext[mysyncid];
       					warnings.addtext[" for variable "];
       					warnings.addtext[e.getName[]];
       					warnings.addtext[" is pointless"];        					
       				) else (
       					misc.clearSync[e]; 
       				);
       			);        			
       		);
       		output.newline[];		
       	};
);/*
	Par loop method
	First written 10/4/07 by Nick Brown
*/
var inclass SemPar:= class (superclass.SemPar) 
( 
        var eval := method [] start[];
        var checkSequential:=method[] att checkParallel[];
        var dynamic fromnum;
        var dynamic tonum;
        var dynamic startparallel:=0;
        
        var checkParallel:= method [] 
        {                  
        	if ((variable.getCurrentType[]).check[Null])
        	(
        		/*
        			If there is no type e.g. var p; before, then set the type to be
        			Int - this is so p can be then refered to and worked with
        		*/
        		var alloc:=new allocated[];
				alloc.allocationtype:=new multiple[];
				alloc + Int.clone[];
				var constv:=new const[];
				constv.assigned:=true;
				constv + alloc;
        		variable.setstoredtype[constv];
        	);
	    	variable.checkVariable[];	    	  
            e1.checkExpression[];
            e2.checkExpression[];           
            body.checkSequential[];                    
        };     
        
        var generateCode:=method[]
        {
        	// extend so that doesnt start from zero text wise and then reset to zer
        	// change so that will be from the start process number
			var oldvariable:=variable.getValue[];
        	var i;
        	var startedfrom:=output.getSelect[];
        	var startc:=parallelgeneratecounter;
        	//parallelgeneratecounter:= ((e1.getValue[]).a);
        	//print parallelgeneratecounter;
        	variabletypes:=new HashMap[];
        	insideparblock:=true;
        	output.setUpParBlock[fromnum.a,tonum.a];
        	parlastid:=tonum.a;
        	for i from fromnum.a to tonum.a
        	(	        	
        		parallelgeneratecounter:=parallelgeneratecounter + 1;         		       		
	        	var y:=variable.getValue[];
	        	y.a:=i;
	        	y.b:=i;
	        	variable.setValue[y];
	        	output.setParSelect[i + 1];        		
        		output.add["{"];
        		output.newline[];
        		variable.generateCode[];
        		output.add["="];
        		output.add[i];
        		output.add[";"];
        		output.newline[];
        		body.generateCode[];
        		output.newline[];
        		output.add["}"];       	  
        		output.setSelect[0];      			
        	);
        	insideparblock:=false;
        	variabletypes:=null;
        	//output.setSelect[startedfrom];
        	variable.setValue[oldvariable];
        	parallelgeneratecounter:=startc;
        };                 
        
        var optimise:=method[]
		{
			if ((tonum==null) || (tonum :: unknown))
			(
				checkType[];
			);
		
			if (inafn) fnparallel:=true;
			startparallel:=blockparreset;
			var e1val:=e1.getValue[];
			var e2val:=e2.getValue[];
			e1val.b:=e2val.b;
			variable.setValue[e1val];
			
			//currentparallelprocess:=new Range[(e1val.a) + startparallel, (e2val.a) + startparallel];						
			
			fromnum:=e1.getValue[];            
            tonum:=e2.getValue[];      
                
            if ((tonum.a !=tonum.b) || (fromnum.a !=fromnum.b))
            (
            	// the range number is varied - therefore not deterministic
            	errors.DetermineError[];
            );
            /*
            	This determines the number of processes required. Atm there is an issue meaning that if the variable
            	is declared inside any form of block i.e. conditional, for loop then the results are not defined
            	This is to avoid analysis at this stage
            */	
            var oldp:=currentparallelprocess;
            var i;
            var oldy:=variable.getValue[];         
            variabletypes:=new HashMap[];   
            insideparblock:=true;
            for i from fromnum.a to tonum.a
        	(
        		currentparallelprocess:=currentparallelprocess + 1;
        		syncs.resetWrite[];
        		var y:=variable.getValue[];	        	        		
        		y.a:=i;
	        	y.b:=i;
	        	//print currentparallelprocess - 1;
	        	variable.setValue[y];	        	
            	body.optimise[];               	     	
            );
            insideparblock:=false;
            variabletypes:=null;
            variable.setValue[oldy];
            currentparallelprocess:=oldp;
          	currentprocesses:=currentprocesses + (tonum.a - fromnum.a);
          	//if (totalprocesses < currentprocesses) (totalprocesses:=currentprocesses);  
		};
        
        var checkType:=method[]
        {        
        	
        	if (( !((variable.getCurrentType[]).check[Int]) && !((variable.getCurrentType[]).check[Null]))   || !((e1.getCurrentType[]).check[Int]) || !((e2.getCurrentType[]).check[Int]))
        	(
        		errors.TypeError[];
        	);
        	e1.checkType[];
        	e2.checkType[];
        	if (holdtotal==false)
          	(
        		startparallel:=blockparreset;
        		fromnum:=e1.getValue[];            
            	tonum:=e2.getValue[];
            	var oldp:=currentparallelprocess;
            );
        	body.checkType[];
        	if ((holdtotal==false) && (!(tonum==null)) && ((tonum :: unknown)==false))
          	(          		
        		currentparallelprocess:=oldp;        		
        		if (currentparallelprocess > 0) currentprocesses:= currentparallelprocess;
          		currentprocesses:=currentprocesses + tonum.a; //(tonum.a - fromnum.a);
          		//print currentprocesses;
          		if (totalprocesses < currentprocesses) totalprocesses:=currentprocesses;            	
          		currentprocesses:=1;
          	);
        };
         var checkExpression:=method[] errors.SExpressionError[];
);
/*
	Parallel Composition method
	First written 10/4/07 by Nick Brown
*/
var inclass SemOpOr:= class (superclass.SemOpOr) (
		var dynamic thisblocknum:=0;
		var dynamic traditional:=false; // signifies traditional use of || for or in assignment
		var dontadd:=0;
        var eval := method [] start[];
        
        
        var checkExpression:=method[]
        (  
        	traditional:=true;
        	e1.checkExpression[];
        	e2.checkExpression[];
        );
        
        var getValue:=method[] 
		{
			if (traditional==true)
			(
			var a:=e1.getValue[];
			var b:=e2.getValue[];
			if ((a :: unknown) || (a==null) || (b :: unknown) || (b==null)) return new unknown;		
			return a==true || b==true;
			);
		};
        
        var checkSequential:=method[]
        (
        	checkParallel[];
        );
        var getCurrentType:=method[] return Bool;
        var checkParallel:= method [] 
         (              	         	
           	e1.checkParallel[];
            e2.checkParallel[];             
        );
        
        var checkType:=method[]
        {
        	//print traditional;
        	if (traditional==true)
        	(
        		if !(e1.getCurrentType[].check[e2.getCurrentType[]])
				(
					errors.TypeError[];
				);
        	) else (
        		//var oldcp:=currentprocesses;
        		if (holdtotal==false)
          		( 
        		var oldp:=currentparallelprocess; 
        		);        	
        		e1.checkType[];
        		if (holdtotal==false)
          		(
        		currentparallelprocess:=currentparallelprocess+1;
        		blockparreset:=blockparreset + 1;
        		thisblocknum:=blockparreset;        		
	    		if (totalprocesses <= currentparallelprocess)  totalprocesses:=currentparallelprocess + 1;	    	
	    		/*
	    			A note: was over estimating the currentprocesses, as currentprocesses is increased regardless
	    			it might be the case that we dont want to increate it, for instance if its another composition block
	    			which is smaller
	    		*/
	    		);
        		e2.checkType[];        		
        		if (holdtotal==false)
          		(    
        		//if (totalprocesses < currentprocesses) 
        		//(
        		//	totalprocesses:=currentprocesses + 1;
        		//	print "NEW TOT=";
        		//	print totalprocesses;
        		//	print "\n";
        		//);
       		 	currentparallelprocess:=oldp;
	   		 	blockparreset:=blockparreset - 1;        	
	   		 	);	   		 	
	   		 	//currentprocesses:=oldcp;
	    	);
        };         
         
         var optimise:=method[]
         {
         	/*
         		Didnt used to have the dont add, also the currentprocess used to be commented out
         	*/
         	if (inafn) fnparallel:=true;
			var oldp:=currentparallelprocess; 			    
			if (dontadd==0) currentparallelprocess:=currentparallelprocess+1;    	
	        e1.optimise[];
	        //currentparallelprocess:=currentparallelprocess+1;
	        /*
	        	Limit - needs a par in second () bit - why? Well, as can be seen above the currentparproess needs to be
	        	increased but if there is a par then its increased also - which leads to a double increase.
	        	Can fix this by simply removing one, chose this one, fix in future
	        */
        	blockparreset:=blockparreset + 1;
        	thisblocknum:=blockparreset;
	    	currentprocesses:=currentprocesses + 1;   		    	// used to be commented out
	    	dontadd:=dontadd + 1;
	    	e2.optimise[];
	    	dontadd:=dontadd - 1;
	    	currentparallelprocess:=oldp;
	    	blockparreset:=blockparreset - 1;
         };
         
         var generateCode:=method[]
         {
         	if (traditional==true)
         	(         		         		
         		output.add["("];         		
				e1.generateCode[];
				output.add["||"];				
				e2.generateCode[];			
				output.add[")"];							
         	) else (
	         	var stc:=parallelgeneratecounter;
         		var startfrom:=output.getSelect[];            		
         		if (startfrom != thisblocknum) output.setOpOrSelect[thisblocknum,thisblocknum - 1];         		         		
         		if (dontadd==0) parallelgeneratecounter:=parallelgeneratecounter+1;
         		output.newline[];
         		e1.generateCode[];  
         		output.setSelect[startfrom];
         		output.setOpOrSelect[thisblocknum + 1,thisblocknum];
         		parallelgeneratecounter:=parallelgeneratecounter+1;
         		output.newline[];
         		dontadd:=dontadd + 1;
         		e2.generateCode[];
         		dontadd:=dontadd - 1;
         		parallelgeneratecounter:=stc;   
         		//if (startfrom==0)
         		//(   
         		//	output.setAllSelect[startfrom];   		
         		//) else (
         		output.setSelect[startfrom];
         		//);
         	);
         };
    );
/*
File created 20/6/2007 by Nick Brown
*/

var inclass SemProc:= class (superclass.SemProc) (

	var dynamic doneflag:=false;
	var checkSequential:=method[]
	(
		checkParallel[];
	);
        
	var checkParallel:= method [] 
	(              	         	
		body.checkParallel[];		
	);
	
	var checkType:=method[]
	(	
		body.checkType[];
		if ((!((variable.getValue[]) == null)) && (((variable.getValue[]) :: unknown)==false))
		(
			doneflag:=true;
			if (totalprocesses < (variable.getValue[]).a + 1) totalprocesses:=(variable.getValue[]).a + 1;
		);
	);
    
	var checkExpression:=method[] errors.SExpressionError[];
	
	var optimise:=method[] 
	{
		if (doneflag==false) checkType[];
		if (inafn) fnparallel:=true;
		var oldp:=currentparallelprocess;
		currentparallelprocess:=(variable.getValue[]).a + 1;
		body.optimise[];
		currentparallelprocess:=oldp;
	};
	
	var generateCode:=method[]
    {   
       		lastproc:=output.getSelect[];
       		output.setProcSelect[((variable.getValue[]).a) + 1, ((variable.getValue[]).a)];  		
       		output.add["{"];
       		output.newline[];
       		var startv:=parallelgeneratecounter;
       		parallelgeneratecounter:=(variable.getValue[]).a + 1;
       		body.generateCode[];
       		output.newline[];
       		output.add["}"];
       		output.setSelect[lastproc];
       		parallelgeneratecounter:=startv;
    };    
);
/* 
Sem Assignment Class first written 10/4/2007 Nick Brown
The class called when we have something like x:=12; 

In scope, i.e. base will only perform checktype and optimise iff it has not been performed on record for that variable
i.e. if the variable is bound to that scope then will perform it per SemExp call as it looses all data in between
however if the variable is bound out of that scope, then these will only be called once per assignment, as the changed are stored
and we do not want to overwrite them

The only issue is if on the right hand side there is a type which is bound in scope and needs updating - it does call get current type so 
hopefully this fixes that problem
*/
var inclass SemAssignment:= class (superclass.SemAssignment) 
(	
	var dynamic thevalue:=unknown;	
	var dynamic needtypeii:=false;
	var eval:=method[] start[];
	var checkParallel:=method[] checkSequential[];
	var checkSequential:=method[] checkAssignment[];
	var mtotal:=0;
	var mdynamic:=-1;
	
	var generateCode:=method[] 
	{	
		var retval1:=false;
		var retval2:=false;
		retval1:=e1.generateAssignment[e2,null];				
		retval2:=e2.generateAccess[e1,null];					
		if (!((retval1==true) || (retval2==true)))
		(						
			var f:=e1.generateCode[];			
			output.add["="];									
			var y:=e2.generateCode[];		
			if (y==33) y:=(e1.getstoredtype[]).generateCode[];	// will look at e1's type and NOT the type of e2, refer to typedexp
			
			if ((y==12) && (f==12))
			(
				// 12 means that they are arrays (or whatever) and not all indexes have been used
				// therefore produce a memcpy;
				output.clearline[];
				output.add["memcpy(&"];
				e1.generateMethodInvoke[new stack[]];
				output.add[",&"];
				e2.generateMethodInvoke[new stack[]];
				output.add[",sizeof("];
				(e1.getstoredtype[]).t.generateDeclaration[];	// array specific?
				output.add[")*"];
				(e2.getstoredtype[]).size.generateCode[];	// only work for 1d
				output.add[")"];
			);	
			
			if (!(y==true))
			(
				output.add[";"];
				output.newline[];
			);
		);	
	};
	
	var checkAssignment:=method[]
	{							
		var y:=e1.checkVariable[];
		if (y==223) needtypeii:=true;				
		e2.checkExpression[];	
		var fun:=e1.getCurrentType[];		
		if ((fun.check[Null]==true) && (e1.getUsesTypeInference[]==false))
		(			
			if (e1.isEmpty[])
			(
				// variable uses type inference to set it
				e1.setUsesTypeInference[true];
			);
		);
	};
	
	var checkExpression:=method[] errors.SExpressionError[];
	
	var optimise:=method[]
	{				
		var thevalue:=e2.getValue[];				
		if (e1.checkAlreadyOptimised[]==true && optimiseblockenabled==true) return null;
		e1.addOptimised[];	
		e1.optimiseAssignment[e2,null];								
		e2.optimiseAccess[e1,null];				
		e1.setValue[thevalue];		
		if (conditionalisunknown==true) unknownconditionalrevert.aadd[e1];
	};

	var checkType:=method[]
	{			
		/*
			At this point the variable will have a certain value associated with it
			This value is of a certain type, as types have to match then simply
			check against this and dont bother updating this variable's value
			
			This will probably work, but if it does not then we will have to update
			the value, atm dont bother tho
		*/		
		if (needtypeii==true) e1.dotypeseqcheck[];
		if (e1.checkAlreadyTypeChecked[]==true && typeblockenabled==true) 
		(
			// does these two lines to update any variables which are updated in e2 class by those methods - incase e2 bound in this scope
			e2.getCurrentType[];
			e2.ismethod[];
			return null;
		);
		e1.addTypeCheck[];
		var userdef:=false;
		if (e2.ismethod[]==true) userdef:=e2.userdefined[];	
			
		// above is so that if its a method call then dont type check - we dont know return type and also can overwrite
		if (!userdef)
		(		
		// if set a type e.g. a:=(a :: Int) then dont type check - as defined the type, else do!		
			//if (e1.isEmpty[])
			//(		
			
			
			/*
				Has been reorganised - Dec 2007. Reason is that the behaviour is very different if a variable has a value
				in it (i.e. not empty)... why?? When was setting the value to be unknown on return from a user defn fn
				was causing a type error. This should not be the case and really there is very little difference between
				if its empty of not - we still care about the type. Therefore moved the empty check and will not override
				the type if the variable is not empty.
			*/
			
				// the variable has no type and therefore needs to be declared				
				var fun:=e1.getCurrentType[];													
				if ((fun.check[Null]==false))
				(											
					if (((e2.getCurrentType[]) :: unknown)==false)
					(
					//print fun.getSize[];
					// this has been declared as a type but no value associated with it, have got type info though					
					if (!(fun.check[e2.getCurrentType[]] == true)) 
					(											
						/*
							FIX - 25/7/2007 The problem was that if the variable has no value, but already is declared
							like a channel, then will come here - it did not take into account if was checking a core type
							or not. Therefore needed to add the following conditional in to check - may need to change the other branch
							in the future
						*/
						if ((e2.getCurrentType[]) :: coretype) 
						(			
							/*
								Addition - 16/5/2008 - if e2 is a core type, check it against e1's coretype - e.g. disallow
								a char being assigned to an integer
							*/
							if (e1.getCurrentType[].getCoreType[].check[e2.getCurrentType[]]==false) errors.TypeError[];
						) else (						
							if (!((e2.getCurrentType[]) :: unknown)) 
							(
								/*
									Here will check for the nativetype - assume that its an array, if not then error and 
									Changed a bit - it used to do the try and then the check just bellow - instead if it is about to give an error will allow for the nativecheck 
								*/								
								if (!(e1.getCurrentType[].check[(e2.getCurrentType[]).getCoreType[]]))
								(
									//try
									//(										
									//	if (((((e2.getCurrentType[]).getCoreType[]).getstoredtype[]) :: nativetype)==true) return null;
									//) catch "" (
									//	skip;
									//);					
									if (!((e1.getCurrentType[]) :: coretype))
									(
										/*
											Addition 17/3/2008 - if a:=b, is assignment, so that neither are coretype (such as two ints allocated to different machines)
											then will get the coretype of both and check them to test for equality
										*/
										if (e1.getCurrentType[].getCoreType[].check[(e2.getCurrentType[]).getCoreType[]] == true) return null;
									);
								 	errors.TypeError[];						
								 );
							);
						);
					);
					);
				) else (	
					if (e1.isEmpty[])
					(					
						if ((e2.getCurrentType[]) :: coretype)
						(	// otherwise set the type info now 					
							// 2 options here - firstly (normally) the coretype is the origional, if this is the case, then just set is as 2nd option
							// otherwise, Int::global[] etc... then the Int is a clone of the orig - need to reger to mastertype and get this rather than use the clone
							// I have not bothered with adding a service as it is very specific - do I need to? Probably not, just refer to variable names
							if (e2.getCurrentType[].master==false)
							(
								var toset:=(e2.getCurrentType[].mastertype).clone[];
								var alloc:=new allocated[];
								alloc.allocationtype:=new multiple[];
								alloc + toset;
								e1.setstoredtype[alloc];	
							) else (				
								toset:=e2.getCurrentType[].clone[];
								alloc:=new allocated[];
								if (e2.isavariable[]==true)
								(
									if ((e2.getstoredtype[].getheldon[])==false)
									(
										alloc.allocationtype:=new multiple[];
									) else (
										var s1:=new single[];
										var h1:=new on[];
										h1.heldon:=e2.getstoredtype[].getheldon[];
										s1.singleheld:=h1;
										alloc.allocationtype:=s1;
									);
								) else (
									alloc.allocationtype:=new multiple[];
								);
								alloc + toset;											
								e1.setstoredtype[alloc];	
							);
						) else (	
							toset:=(e2.getCurrentType[]).getCoreType[].clone[];
							alloc:=new allocated[];
							if (e2.isavariable[]==true)
							(
								if ((e2.getstoredtype[].getheldon[])==false)
								(
									alloc.allocationtype:=new multiple[];
								) else (
									var ho:=new on[];
									ho.heldon:=e2.getstoredtype[].getheldon[];
									var s:=new single[];
									s.singleheld:=ho;
									alloc.allocationtype:=s;
								);
							) else (
								alloc.allocationtype:=new multiple[];
							);
							alloc + toset;
							e1.setstoredtype[alloc];
						);
					) else (
						if (!(e1.getCurrentType[].check[e2.getCurrentType[]]))  errors.TypeError[];	// type not equal = error																
					);
				);
			//) else (				
			//	print (e1.getCurrentType[]) :: unknown;
			//	
			//);			
		);	
	};

);/*
File created 21/4/2008 by Nick Brown
*/
var inclass SemOptypeassignment:= class (superclass.SemOptypeassignment) 
(		
	var dynamic settype;
	var dynamic singletype:=false;
	var dynamic start:=false;
	var dynamic isavar:=false;
 	var checkParallel:=method[] checkSequential;
	var checkSequential:=method[] checkAssignment[];
	var checkAssignment:=method[]
	{				
		e1.checkVariable[];		
		if (e1.getTypeVar[]==false)
		(
			throw error "For Type Assignment the variable must be a type variable";
		);
		var thee1:=e1;		
		inmodtype:=true;	
		var dummycheck:=new dummyfn[];
		if ((e2.getType[]).check[((dummycheck.adummymethod).body).getType[]]) e2:= (e2.eval[]);
		if (e2.isavariable[])
		(
			if (e2.getTypeVar[]==false)
			(
				throw error "You can only do type assignment with a variable if that var is a type var";
			);
			
			if (e2.getCurrentType[].check[Null])
			(
				throw error "To set the type of a variable to that of a type variable, type var can not be null";
			);
		);
		inmodtype:=false;
		e1.setUsesModType[true];		
		var ty:=computeType[];
		doStore[];
		settype:=ty;					
		if (e1.getstoredtype[]==null) start:=true;			
		e1.setstoredtype[ty.clone[]];							
		vartypes.add[thee1];
	};
	
	var checkType:=method[] 
	(				
		doStore[];
		e1.setstoredtype[settype];		
	);
	
	var optimise:=method[] 
	{		
		doStore[];		
		e1.setstoredtype[settype];	
	};
	
	var computeType:=method[]
	{		
		var singlety:=e2;
		var ty:=e1.checkVariable[];		
		if (e2.istypeexp[]==true)
		(
			ty:=e2.checkExpression[];
		) else (
			if (e2.isavariable[]==true)
			(
				ty:=(e2.getstoredtype[]).clone[];	
				isavar:=true;
			) else (
				singletype:=true;	
				var dummycheck:=new dummyfn[];
				if ((singlety.getType[]).check[((dummycheck.adummymethod).body).getType[]])
	 			(	 	 				
	 				singlety:=singlety.eval[];
	 			);
				ty:=(singlety.getTy[]).clone[];
			);
		);			
		return ty;
	};
	
	var doStore:=method[]
	{
		if (!(variabletypes == null))
    	(    		
    		if (variabletypes.hget[e1] == null) 
    		(
    			if (!(e1.getstoredtype[]==null))
    			(    				
    				variabletypes.hput[e1,e1.getstoredtype[].clone[]];	// this adds the initial type for par block (look @ comment 1)
    			);
    		);
    	);
	};	
	
    var generateCode:=method[]
	{
		doStore[];
		e1.setstoredtype[settype];
	}
);/*
	This is called when a variable is first initiated, e.g. var x:=12; the var bit calls this class
	First written 10/4/07 by Nick Brown
*/
var inclass SemVarInit:= class (superclass.SemVarInit) 
(
	var eval:=method[] start[];
	var checkParallel:=method[] checkSequential[];
	var checkSequential:=method[]  
	(
		e.checkAssignment[];	
	);
	var checkType:=method[]
	(	
		skip;
	);
	
	var generateCode:=method[]
	(					
		if (e.getUsesModType[]==false)
		(
			e.generateCode[];
			if (e.isShortCut[]==false)
			(
				output.add[";"];
				output.newline[];
			);
		);
	);
	var setUsesTypeInference:=method[x] e.setUsesTypeInference[x];
 	var getUsesTypeInference:=method[] e.getUsesTypeInference[];
	var getName:=method[] e.getName[];
	var setName:=method[x] e.setName[x];
	var generateName:=method[] e.generateName[];
	var getstoredtype:=method[] e.getstoredtype[];
	var setstoredtype:=method[x] e.setstoredtype[x];
	var generateMethodParam:=method[] e.generateMethodParam[];
	var generateMethodProtoParam:=method[] e.generateMethodProtoParam[];
	var isCpointer:=method[] e.isCpointer[];
	var checkAlreadyTypeChecked:=method[] e.checkAlreadyTypeChecked[];
	var checkAlreadyOptimised:=method[] e.checkAlreadyOptimised[];
	var addOptimised:=method[] e.addOptimised[];
	var getDeclarationChecker:=method[] e.getDeclarationChecker[];
	var checkAlreadySyntaxChecked:=method[] e.checkAlreadySyntaxChecked[];
	var addSyntaxCheck:=method[] e.addSyntaxCheck[];
	var setInitialType:=method[x] e.setInitialType[x];
 	var getInitialType:=method[] e.getInitialType[];
	var generateMethodInvoke:=method[x] e.generateMethodInvoke[x];
	var setUsesModType:=method[x] e.setUsesModType[x];
 	var getUsesModType:=method[] return e.getUsesModType[];
 );/*
Sem Typed Var This class is used to represent a completely typed variable, e.g. var x:Int;
This just is a class infront of pubstaticvar, e.g. e2 is that class
First written 10/4/07 by Nick Brown
*/
var inclass SemTypedVar:= class (superclass.SemTypedVar)
(
	/*
	var eval:=method[] 
	(
		start[];
	);
	*/
	var optimiseAccess:=method[x,i] e2.optimiseAccess[x,i];
	var optimiseAssignment:=method[x,i] e2.optimiseAssignment[x,i];
	var generateAccess:=method[x,i] e2.generateAccess[x,i];
	var generateAssignment:=method[x,i] e2.generateAssignment[x,i];

	var checkAssignment:=method[]
	{	
		e2.checkVariable[];
		if (!(getDeclaredType[]==null))
		(								
			e2.setstoredtype[getDeclaredType[]];
		) else (			
			e2.setstoredtype[(vartypes.get[e1.name]).getstoredtype[].clone[]];	
			/*
				This uses a work around - var t : y, at the start of analysis, y is wired
				into this class as that type, so up to this point any changes made are not
				reflected in the copy of y.
				
				Use vartypes (in file scopeinfo.flex) to hold the name of variables against their
				actual pubstaticvar - so can just access the current type of e1, via using e1.name to get
				the current e1.
				
				A MAJOR problem is scope - the latest variable of e1.name is used, not that alive in the current scope.
				This could be changed (and might need to be) but that bug can exist atm - prob quite easy to change,
				would just store the current vartypes for that scope.			
			*/		
		);
	};
	
	var getCurrentType:=method[] 
	{
		var ptype:=e2.getCurrentType[];		
		if (ptype==null)
		(					
			return getDeclaredType[];
		) else (
			return ptype;
		);
	};	
	
	var generateCode:=method[]
	(	
		e2.generateCode[];		
	);
	
	//var checkParallel:=method[] checkVariable[];
	
	 var checkVariable:=method[] 
	 (
	 	e2.checkVariable[];	 	
	 );
	 
	 var checkExpression:=method[] 
	 (	 	 	
	 	e2.checkExpression[];
	 );
	 var getDotValue:=method[x,i]
	 (
		if (i==null) 
		(
			e2.getDotValue[x,this];
		) else (
			e2.getDotValue[x,i];
		);
	 );
	 var istypeexp:=method[] false;
	 var generateMethodInvoke:=method[x] e2.generateMethodInvoke[x];
	 var hasBeenDeclared:=method[] e2.hasBeenDeclared[];
	 var setUsesModType:=method[x] e2.setUsesModType[x];
 	var getUsesModType:=method[] return e2.getUsesModType[];
);/*
	This represents the :: operator, and at the moment it is used as a sequential component
	i.e. var x; x::(array[10] + shared[]);
	
	This class also forwards syntactic analysis to the type compositioned
	
	First written 10/4/07 by Nick Brown
*/
var inclass SemTypedExp:= class (superclass.SemTypedExp) 
(			

	var dynamic thistype;
	var dynamic novariable:=null;
	
	var istypeexp:=method[] return true;
	
	var checkType:=method[] skip; // NEED TO DO THIS as :: means coherce type the orig might not be empty type
	var dynamic composed:=true;
	 var checkExpression:=method[] 
	 {	
	 	//e2.checkVariable[];
	 	// for notes refer to checkVariable
	 	var dummycheck:=new dummyfn[];
	 	if (((e2.getType[]).check[((dummycheck.adummymethod).body).getType[]])==false)
	 	(
	 		if (e2.isavariable[])
	 		(
	 			if (e2.getUsesTypeInference[]==true) return 223;
	 		);
	 	);
	 	return dotypeseqcheck[]; 	
	 };	
	 
	 var checkVariable:=method[] 
	 {
	 	/*
	 		Had it checking the variable for whether it had done this before - was ok
	 		but if have c:=s::even ... then would not store s quite correctly but would
	 		not redo this if needed to scopyly - therefore removed it.
	 		To reinstate the code was
	 		if (e2.checkAlreadySyntaxChecked[]==true) 
			(
			// does these two lines to update any variables which are updated in e2 class by those methods - incase e2 bound in this scope
			return null;
			);

			e2.addSyntaxCheck[];
			
			A fix was added into dotypeseqcheck
	 	*/	
	 	// if have (f::type) := value;
	 	//e2.checkVariable[];
	 	var dummycheck:=new dummyfn[];
	 	if (((e2.getType[]).check[((dummycheck.adummymethod).body).getType[]])==false)
	 	(	 		
	 		if (e2.isavariable[]==true)
	 		(	 			 		
	 			if (e2.getUsesTypeInference[]==true) return 223;
	 		);
	 	);
	 	return dotypeseqcheck[];
	 };
	 
	 var getValue:=method[] null;
	 
	 var dotypeseqcheck:=method[]
	 {	 			 		 	
	 	if (!(thistype==null)) return null;
	 	var dummycheck:=new dummyfn[];
	 	if ((e1.getType[]).check[((dummycheck.adummymethod).body).getType[]])
	 	(
	 		e1:=e1.eval[];	 		
	 	);
	 	
	 	if ((e2.getType[]).check[((dummycheck.adummymethod).body).getType[]])
	 	(
	 		e2:=e2.eval[];
	 	);
	 	novariable:=true;
	 	var thetype:= e1.getTy[];	 
	 	var currenttype:=e2.getTy[];
	 	//currenttype.display[];	 	
	 	//print thetype.isallocated[];
	 	if (currenttype :: coretype) currenttype:=currenttype.clone[];	// if Int:: etc... then want to make a copy of the coretype rather than use the master coretype (otherwise will change the properties of the master Int, i.e. all Integers in the program!)
	 	
	 	try
	 	(
	 		/*
	 			This fixes a problem - getTy will return the type regardless, which is all cool. BUT, if its a variable then they
	 			get added in the wrong precedence.
	 			Therefore, need to check if its a variable or not. Why do we have it in a try block? Well, if not then for a type
	 			it is simple an instace of type code rather than anything else - so it causes an error.
	 			This would be interesting to fix and take it out of the try block
	 		*/
	 		if (e2.isavariable[]==true) novariable:=false;
	 	) catch "" (
	 		novariable:=true;
	 	);
	 	if (currenttype ==null)
	 	(	 		
	 		currenttype:=thetype;
	 	) else (	 		
	 		try
	 		{	 			
	 			if (novariable==false)
	 			(	 		
	 				// variable i.e. t :: broadcast[2]	
	 				//currenttype:=currenttype.clone[];		
	 				var thesub:=doTypeSub[thetype,currenttype];
	 				if (thesub==false)
	 				(	 					
	 					thetype + currenttype;	 	 					
	 				) else (	 				
	 					thetype:=currenttype;	 					
	 				);	 					 				
	 			) else (	 				
	 				// no var i.e. Int :: shared[] :: multiple[] :: allocated[] 	 						 					
	 				thetype + currenttype;			
	 			);
	 				 			
	 		} catch "" {
	 			/*
	 				This is the fix mentioned in checkVariable - for some, if it has
	 				already done this and stored the type then it can not clone the
	 				current type. Therefore do this try catch block, if it can not
	 				clone it then thats fine - just dont add it to the type
	 				
	 				Seems to work, but be aware of it.
	 			*/
	 			skip;
	 		};		 				
	 	);	 	
	 //	thetype.display[];
	 //	print "\n";
	 	thistype:=thetype;	 	
	 	thistype.valid0[];	 	
	 
	 	return thistype;
	 	//e2.setstoredtype[currenttype];	// sets the type will need to modify as this will override any existing type AND will cause the variable's value to be inconsistent with the type (value has more importance than type when returning current type.) Also, just works for var x; etc... will need to add the required lines to SemTypedVar etc...	 	
	 	// do not setstoredtype as does not nesc do that!
	 };
	 
	 var checkSequential:=method[]  
	 {
	 	// if have f::type;
	 	e2.checkVariable[];
	 	// would set e2 which is pubstaticvariable to be this returned type :=)
	 	return dotypeseqcheck[];
	 };	 
	 
	var doTypeSub:=method[single,existing]
	{						
		var theid:=existing.getId[];    	
    	if (existing.getSub[]==true) theid:=(existing.getDeclaredType[]).getId[];    		
    	if (single.getId[]==null) return false;
    	if ((single.getId[] == theid) && (!(single.getId[] == null)) && (!(theid == null)) )
    	(
    		single.core:=existing.core;
    		single.alone:=existing.alone;
    		single.setSub[false];
    		existing:=single;
    		return true;
    	);   		
    	if (single.getSuperTypeId[]==null) return existing.substitute[single];
    	var i:=(single.getSuperTypeId[]).agetiterator[];
    	while (i.hasNext[])
    	(    			
    		if ( ((i.next[]).getdata[]) == theid)
    		(
    			single.core:=existing.core;
    			single.alone:=existing.alone;
    			single.setSub[true];
    			if (existing.getSub[]==false)
    			(
    				single.setDeclaredType[existing];    					
    			) else (
    				single.setDeclaredType[existing.getDeclaredType[]];
    			);
    			existing:=single;     				  				
    			return true;
    		);
    	);   	
    	return existing.substitute[single];    
	};
	 
	var getTy:=method[]
	{
		var onev:=true;
		var twov:=true;
		var dummycheck:=new dummyfn[];
		if ((e1.getType[]).check[((dummycheck.adummymethod).body).getType[]])
	 	(	 
	 		onev:=false;	 	
	 		e1:=e1.eval[];
	 	);
	 	if ((e2.getType[]).check[((dummycheck.adummymethod).body).getType[]])
	 	(	 
	 		twov:=false;
	 		e2:=e2.eval[];
	 	);
	 	
		var y:=e1.getTy[];
		var x:=e2.getTy[];	
		
		//if (onev==true) y:=y.clone[];
		//if (twov==true) x:=x.clone[];		
		y + x;
		return y;
	};
	
	var generateMethodInvoke:=method[x]
	(
		// if (a::even[..]#p#i) then will call this method!		
		if (thistype==null)
		(	
			e1.generateMethodInvoke[x];
		) else (
			e2.generateName[];
			thistype.generateMethodInvoke[x];
		);
	);
	
	var optimiseMethodInvoke:=method[x]
	(
		if (thistype==null)
		(	
			e1.optimiseMethodInvoke[x];
		) else (			
			thistype.optimiseMethodInvoke[x];
		);
	);
	
	var generateCode:=method[] 
	(	
		if (novariable==true)
		(
			return 33;
			// this, as if its not got a variable in it, a var has been assigned to it, this might be changed, so therefore want to 
			// generate code on the var's type and not the single one here
			//thistype.generateCode[];			
		) else (				
			if (getstoredtype[]==null)
			(
				thistype.generateCode[];
			) else (		
				//getstoredtype[].display[];
				getstoredtype[].generateCode[];
			);		
		);	
	);
	
	// PubStaticVariable forwarding!
	var isavariable:=method[] 
	(
		if (inmodtype==true) return false;
		e2.isavariable[];	
	);
	var getstoredtype:=method[] return e2.getstoredtype[];
	var isEmpty:=method[] e2.isEmpty[];	
	var setstoredtype:=method[x] e2.setstoredtype[x];
	var getCurrentType:=method[] 
	(		
		if (thistype==null)
		(
			return e2.getCurrentType[];			
		) else (
				//print thistype.getdottype["two"];		
			return thistype;
		);
	);
	var generateMethodProtoParam:=method[] e2.generateMethodProtoParam[];
	var generateMethodParam:=method[] e2.generateMethodParam[];
	
	var setMethodInvokeValue:=method[a,b] e2.setMethodInvokeValue[a,b];
	var getMethodInvokeValue:=method[a] e2.getMethodInvokeValue[a];
	var generatePrint:=method[] e2.generatePrint[];
	var isShortCut:=method[] e2.isShortCut[];
	var generateAssignment:=method[x,i] 
	(
		if (thistype==null)
		(	
			return e2.generateAssignment[x,i];
		) else (
			return thistype.generateAssignment[x,i];						
		);
	);
	
	var generateAccess:=method[x,i] 
	(			
		if (thistype==null)
		(			
			return e2.generateAccess[x,i];
		) else (			
			return thistype.generateAccess[x,i];			
		);
		
	);
	
	var optimiseAccess:=method[x,i] 
	(			
		if (thistype==null) dotypeseqcheck[];
		if (thistype==null)
		(			
			return e2.optimiseAccess[x,i];
		) else (			
			return thistype.optimiseAccess[x,i];			
		);		
	);
	
	var optimiseAssignment:=method[x,i] 
	(		
		if (thistype==null) dotypeseqcheck[];	
		if (thistype==null)
		(						
			return e2.optimiseAssignment[x,i];
		) else (			
			return thistype.optimiseAssignment[x,i];			
		);		
	);
	var setUsesTypeInference:=method[x] e2.setUsesTypeInference[x];
 	var getUsesTypeInference:=method[] e2.getUsesTypeInference[];
	var ismethod:=method[] false;
	var generateName:=method[] e2.generateName[];
	var isCpointer:=method[] e2.isCpointer[];
	var getName:=method[] e2.getName[];	
	var isPointer:=method[] e2.isPointer[];	
	var checkAlreadyTypeChecked:=method[] e2.checkAlreadyTypeChecked[];
	var addTypeCheck:=method[] e2.addTypeCheck[];
	var checkAlreadySyntaxChecked:=method[] e2.checkAlreadySyntaxChecked[];
	var addSyntaxCheck:=method[] e2.addSyntaxCheck[];
	var checkAlreadyOptimised:=method[] e2.checkAlreadyOptimised[];
	var addOptimised:=method[] e2.addOptimised[];
	var getDeclarationChecker:=method[] e2.getDeclarationChecker[];
	var getInitialType:=method[] e2.getInitialType[];
	var retrieveMethodArgs:=method[x] e2.retrieveMethodArgs[x];
	var setPointer:=method[x] e2.setPointer[x];
	var setDirty:=method[x] e2.setDirty[x];
	var getDotValue:=method[x,i] 
	(
		if (thistype==null) 
		(
			e2.getDotValue[x,i];
		) else (
			if (i==null) 
			(
				thistype.getDotValue[x,this];
			) else (
				thistype.getDotValue[x,i];
			);
		);
	);
);/*
File created 15/1/2008 by Nick Brown

Comment 1 - This uses variable list - in a par block, will go through optimising/generating the code n times. However
in the first instance might change the type so t2, and will want to revert to its initial value t1 before the next process
(this is for all processes!)

Actually illustrates a more general issue of needing to reset the state between process runs
*/

var inclass SemOpmodifythetype:= class (superclass.SemOpmodifythetype) 
(		
	var dynamic settype;
	var dynamic isavar:=false;
	var dynamic singletype:=false;
	var dynamic start:=false;
	var eval:=method[] 
	(
		start[];
	);
	
	var checkParallel:=method[] checkSequential[];
	var checkSequential:=method[] checkAssignment[];
	
	var generateCode:=method[]
	{
		doStore[];
		if (start==true)
		(
			var carrydecdone:=null;
			if (!( e1.getstoredtype[]==null))
			(
				carrydecdone:= e1.getstoredtype[].getdeclarationDone[];
			);
			e1.setstoredtype[settype];	
			if (e1.isPointer[]==true) 
			(
				e1.getstoredtype[].XsetUpPtr[];
				e1.getstoredtype[].generateDynamicSizeCheck[];
				return null;
			);
			if (!(carrydecdone==null)) (e1.getstoredtype[]).setdeclarationDone[carrydecdone];	
			var isavar:=e1.generateCode[];
			if (isavar==null) isavar:=false;							
			var y;
			if (isavar==false || isavar==12)
			(
				output.add["="];	
				if (singletype==true)
				(					
					y:=(e1.getstoredtype[]).generateCode[];								
				) else (												
					y:=e2.generateCode[];									
					if (y==33) y:=(e1.getstoredtype[]).generateCode[];					
				);
			);
			if ((!(y==true)) && (isavar!=2))
			(	
				output.add[";"];			
				output.newline[];
			);		
		) else (
			e1.setstoredtype[settype];
			if (e1.isPointer[]==true) e1.getstoredtype[].XsetUpPtr[];
		);
	};
	
	var doStore:=method[]
	{
		if (!(variabletypes == null))
    	(    		
    		if (variabletypes.hget[e1] == null) 
    		(
    			if (!(e1.getstoredtype[]==null))
    			(    				
    				variabletypes.hput[e1,e1.getstoredtype[].clone[]];	// this adds the initial type for par block (look @ comment 1)
    			);
    		);
    	);
	};	
	
	var optimise:=method[] 
	{
		//if (e1.getInitialType[]==null) e1.setInitialType[e1.getstoredtype[].clone[]];
		doStore[];		
		e1.setstoredtype[settype];
		if (e1.isPointer[]==true)
		( 
			e1.getstoredtype[].XsetUpPtr[];
			e1.getstoredtype[].checkSharedSize[];
		);
		//settype.display[];
	};
	
	var computeType:=method[]
	{		
		var dummycheck:=new dummyfn[];
		if ((e2.getType[]).check[((dummycheck.adummymethod).body).getType[]]) e2:= (e2.eval[]);
		var singlety:=e2;
		var ty:=e1.checkVariable[];			
		if (e2.istypeexp[]==true)
		(
			ty:=e2.checkExpression[];		
		) else (
			if (e2.isavariable[]==true)
			(
				ty:=(e2.getstoredtype[]).clone[];				
				if (e2.isTypeVar[]) singletype:=true;
				isavar:=true;
			) else (
				singletype:=true;				
				ty:=(singlety.getTy[]).clone[];
				//ty:=e2;
			);
		);			
		return ty;		
	};
	
	var doTypeRetrieval:=method[]
	{
		var thee1:=e1;				
		e1.setUsesModType[true];
		var ty:=computeType[];		
		doStore[];
		settype:=ty;				
		if (e1.getstoredtype[]==null) 
		(
			start:=true;						
		);
		e1.setstoredtype[ty.clone[]];	
		e1.getstoredtype[].XsetUpPtr[];		
		//if (e1.isPointer[]==true) 
		//(
		//	if (start==true)
		//	(
		//		e1.getstoredtype[].XsetUpPtr[];
		//	);
				
		//);
		vartypes.add[thee1];
	};
	
	var checkAssignment:=method[]
	{		
		if (e1.getUsesTypeInference[]==false) doTypeRetrieval[];		
	};
	
	var checkType:=method[] 
	(			
		if (e1.getUsesTypeInference[]==true) 
		(
			doTypeRetrieval[];		
		) else (
			doStore[];
			e1.setstoredtype[settype];
		);
		if (e1.isPointer[]==true) e1.getstoredtype[].XsetUpPtr[];
	);
);/*
File created 24/4/2008 by Nick Brown
*/
var inclass SemUserExp3:= class (superclass.SemUserExp3) 
(
	 name:= "declaredtype";
	 var eval:=method[] att start[];
     var checkParallel:=method[] skip;
     var checkVariable:=method[] skip;
     var checkSequential:=method[] checkParallel[];
     var checkExpression:=method[] e.getDeclaredType[];
     var istypeexp:=method[] true;
     var getTypeVar:=method[] true;
     var getstoredtype:=method[] e.getDeclaredType[];
     var setstoredtype:=method[x] e.setDeclaredType[x];
     var setUsesModType:=method[] skip;
     var getTy:=method[] e.getDeclaredType[];
);/*
File created 24/4/2008 by Nick Brown
*/
var inclass SemUserExp4:= class (superclass.SemUserExp4) 
(
	 name:= "currenttype";
	 var eval:=method[] att start[];
     var checkParallel:=method[] skip;
     var checkVariable:=method[] skip;
     var checkSequential:=method[] checkParallel[];
     var checkExpression:=method[] e.getstoredtype[];
     var istypeexp:=method[] true;
     var getTypeVar:=method[] true;
     var getstoredtype:=method[] e.getstoredtype[];
     var setstoredtype:=method[x] e.setstoredtype[x];
     var setUsesModType:=method[] skip;
      var getTy:=method[] e.getDeclaredType[];
);var  inclass SemSeqComp:= class (superclass.SemSeqComp) (
	var eval:=method[] 
	(
		start[];
	);
	var checkParallel:=method[] att checkSequential[];
	var checkSequential:=method[] 
	(					
		e1.checkSequential[]; 		
		//print e2.getType[];
		e2.checkSequential[];
	);
	 var checkExpression:=method[] errors.SExpressionError[];
	 
	 var generateCode:=method[]
	 (
	 	e1.generateCode[];	 	
	 	e2.generateCode[];
	 );
	 
	 var checkType:=method[]
	 (
	 	e1.checkType[];	 	
	 	e2.checkType[];
	 );	
	 
	 var optimise:=method[]
	 (
	 	e1.optimise[];
	 	if (blockparreset==0)
		(
			if (totalprocesses < currentprocesses) (totalprocesses:=currentprocesses;);
			currentprocesses:=1;
		);
	 	e2.optimise[];	 	
	 );
);
var inclass SemFor:= class (superclass.SemFor) 
(
	var evalStart := method [] start[];
	var eval:=method[] 
	(
		start[];
	);
	var checkParallel:=method[] checkSequential[];
	var dynamic performs:=method[] unknown;
	var checkSequential:=method[]
	{		
		if ((variable.getCurrentType[]).check[Null])
        (
        	/*
        		If there is no type e.g. var p; before, then set the type to be
        		Int - this is so p can be then refered to and worked with
        	*/
        	var alloc:=new allocated[];
			alloc.allocationtype:=new multiple[];
			alloc + Int.clone[];
        	variable.setstoredtype[alloc];
        );
		variable.checkVariable[];
		e1.checkExpression[];
		e2.checkExpression[];
		body.checkSequential[];	
	};
	
	var optimise:=method[]
	{
		var e1val:=e1.getValue[];
		var e2val:=e2.getValue[];	

		if ((e1val::unknown) || (e2val::unknown) || e1val==null || e2val==null)
		(
			variable.setValue[new unknown];	// do not know the value, so set to unknown :)
			insideloop:=insideloop + 1;
			body.optimise[]; 
			insideloop:=insideloop - 1;
		) else (					
			e1val.b:=e2val.b;
			variable.setValue[e1val];
			if (e1val.a > e2val.a)	// replace with proper ranger larger than call!
			(				
				performs:=false;
			) else (
				performs:=true;	// not take account for unknown!
				insideloop:=insideloop + 1;
				body.optimise[]; 
				insideloop:=insideloop - 1;
			);
		);		
	};
	
	var generateCode:=method[]
	(
		output.add["for ("];
		variable.generateCode[];
		output.add["="];
		e1.generateCode[];
		output.add[";"];
		variable.generateCode[];
		output.add["<="];
		e2.generateCode[];
		output.add[";"];
		variable.generateCode[];
		output.add["++)"];
		output.newline[];
		output.add["{"];
		output.newline[];
		insideloop:=insideloop + 1;
		body.generateCode[];		
		insideloop:=insideloop - 1;
		output.add["}"];
		output.newline[];
		
	);
	
	var checkType:=method[]
        (    
        	// all the three arguments will  simplify to a range object            
        	if (( !((variable.getCurrentType[]).check[Int]) && !((variable.getCurrentType[]).check[Null]))   || !((e1.getCurrentType[]).check[Int]) || !((e2.getCurrentType[]).check[Int]))
        	(
        		errors.TypeError[];
        	);
        	e1.checkType[];
        	e2.checkType[];
        	body.checkType[]; 
        );
	
	 var checkExpression:=method[] errors.SExpressionError[];
);var inclass SemTry:=class (superclass.SemTry)
(	
	var eval:=method[] start[];
	var checkParallel:=method[] att checkSequential[];
	var checkSequential:=method[]
	(
		e1.checkParallel[];
		e2.checkParallel[];
	);
	
	var optimise:=method[]
	(
		e1.optimise[];
		e2.optimise[];		
	);
	
	var checkType:=method[]
	(
		e1.checkType[];
		e2.checkType[];
	);
	
	var checkException:=method[x] 
	(
		if (x=s || x==s) return true;
		if (s="" || s=="") return true;
		return false;
	);
	
	var generateCode:=method[]
	{
		if (intry==true) errors.nestedTry[];
		var oint:=intry;	
		registerCommError[];
		output.registerExceptionHandler[this];			
		e1.generateCode[];
		output.deregisterExceptionHandler[this];		
		intry:=oint;		
		generateCommErrorCode[];
	};
	
	var deregisterCommError:=method[]
	{
		if (s="root")
		(
			output.add["MESHsetErrAction(MPI_ERR_ROOT,0);"];
			output.newline[];
		);
		
		if (s="rank")
		(
			output.add["MESHsetErrAction(MPI_ERR_RANK,0);"];
			output.newline[];
		);
		
		if (s="")
		(
			output.add["MESHsetErrAction(MESH_COMM_ERR_UNKNOWN,0);"];
			output.newline[];
		);
		
		if (s="buffer")
		(			
			output.add["MESHsetErrAction(MPI_ERR_BUFFER,0);"];	
			output.newline[];				
		);
		if (s="count")
		(
			output.add["MESHsetErrAction(MPI_ERR_COUNT,0);"];	
			output.newline[];				
		);
		if (s="type")
		(
			output.add["MESHsetErrAction(MPI_ERR_TYPE,0);"];	
			output.newline[];				
		);
		if (s="tag")
		(
			output.add["MESHsetErrAction(MPI_ERR_TAG,0);"];	
			output.newline[];				
		);
		if (s="comm")
		(
			output.add["MESHsetErrAction(MPI_ERR_COMM,0);"];	
			output.newline[];				
		);
		if (s="truncate")
		(
			output.add["MESHsetErrAction(MPI_ERR_TRUNCATE,0);"];	
			output.newline[];				
		);
		if (s="group")
		(
			output.add["MESHsetErrAction(MPI_ERR_GROUP,0);"];	
			output.newline[];				
		);
		if (s="op")
		(
			output.add["MESHsetErrAction(MPI_ERR_OP,0);"];	
			output.newline[];				
		);
		if (s="arg")
		(
			output.add["MESHsetErrAction(MPI_ERR_ARG,0);"];	
			output.newline[];				
		);
	};
	
	var generateCommErrorCode:=method[]
	{
		if (s="root" || s="" || s="rank" || s="buffer" || s="count" || s="type" || s="tag" || s="comm" || s="truncate" || s="group" || s="op" || s="arg")
		(			
			output.add["commerror"];
			output.add[commerrorcnt];
			output.add[":"];
			output.newline[];
			commerrorcnt:=commerrorcnt + 1;
			deregisterCommError[];
			output.add["if (MESHcommerror==1)\n{\nMESHcommerror=0;"];
			output.newline[];
			e2.generateCode[];
			output.add["}"];
			output.newline[];			
		);
	};
	
	var registerCommError:=method[]
	{	
		if (s="")
		(
			intry:=true;
			output.add["MESHsetErrAction(MESH_COMM_ERR_UNKNOWN,1);"];
			output.newline[];		
		);
		if (s="root")
		(
			intry:=true;
			output.add["MESHsetErrAction(MPI_ERR_ROOT,1);"];	
			output.newline[];				
		);
		if (s="rank")
		(
			intry:=true;
			output.add["MESHsetErrAction(MPI_ERR_RANK,1);"];	
			output.newline[];				
		);
		if (s="buffer")
		(
			intry:=true;
			output.add["MESHsetErrAction(MPI_ERR_BUFFER,1);"];	
			output.newline[];				
		);
		if (s="count")
		(
			intry:=true;
			output.add["MESHsetErrAction(MPI_ERR_COUNT,1);"];	
			output.newline[];				
		);
		if (s="type")
		(
			intry:=true;
			output.add["MESHsetErrAction(MPI_ERR_TYPE,1);"];	
			output.newline[];				
		);
		if (s="tag")
		(
			intry:=true;
			output.add["MESHsetErrAction(MPI_ERR_TAG,1);"];	
			output.newline[];				
		);
		if (s="comm")
		(
			intry:=true;
			output.add["MESHsetErrAction(MPI_ERR_COMM,1);"];	
			output.newline[];				
		);
		if (s="truncate")
		(
			intry:=true;
			output.add["MESHsetErrAction(MPI_ERR_TRUNCATE,1);"];	
			output.newline[];				
		);
		if (s="group")
		(
			intry:=true;
			output.add["MESHsetErrAction(MPI_ERR_GROUP,1);"];	
			output.newline[];				
		);
		if (s="op")
		(
			intry:=true;
			output.add["MESHsetErrAction(MPI_ERR_OP,1);"];	
			output.newline[];				
		);
		if (s="arg")
		(
			intry:=true;
			output.add["MESHsetErrAction(MPI_ERR_ARG,1);"];	
			output.newline[];				
		);
		
	};
	
	var getException:=method[] return s;
	
	var generateCatchCode:=method[]
	(
		e2.generateCode[];
	);
);	/*
	If statement
	First written 10/4/07 by Nick Brown
	NOTE: Got rid of b type checking - need to reenable
*/ 
var inclass SemBinaryCondition:= class (superclass.SemBinaryCondition) 
(
	var dynamic outcome:=new unknown;
	var evalStart := method [] start[];
	var checkParallel:=method[] checkSequential[];
	
	var eval:=method[] 
	(
		start[];
	);
	
	var checkSequential:=method[]
	(
		b.checkExpression[];
		e1.checkSequential[];		
		e2.checkSequential[];
	);
	
	var optimise:=method[]
	{
		var oldconditionalisunknown:=conditionalisunknown;
		outcome:=b.getValue[];	
		/*
			Fixed 22/8/2008
			The problem was that, if the condition was unknown it would optimise both branches, but then keep the 
			values of the variables during the last branch optimisation (and we dont know which branch is executed 
			and so this will quite possibly be incorrect.)
			
			Now modified this and the assignment class so that after optimising unknown branches, it will revert all
			the variables's values to become unknown.
			
			Are there any other class apart from assignment which need to be modified? Quite possibly not
		*/
		if (outcome==true) (conditionalisunknown:=false; e1.optimise[];);
		if (outcome==false)	(conditionalisunknown:=false; e2.optimise[];);
		if (outcome :: unknown)
		(
			var oldunknownconditionalrevert:=unknownconditionalrevert;
			unknownconditionalrevert:=new ArrayList[];
			conditionalisunknown:=true;
			e1.optimise[];
			var i:=unknownconditionalrevert.agetiterator[];
			while (i.hasNext[])
			(
				((i.next[]).getdata[]).setValue[new unknown[]];
			);
			unknownconditionalrevert:=new ArrayList[];
			e2.optimise[];
			i:=unknownconditionalrevert.agetiterator[];
			while (i.hasNext[])
			(
				((i.next[]).getdata[]).setValue[new unknown[]];
			);
			unknownconditionalrevert:=oldunknownconditionalrevert;
		);
		conditionalisunknown:=oldconditionalisunknown;
	};
	
	var generateCode:=method[]
	(
		// generate code for the if - depends on outcome!
		if (outcome==true)
		(
			output.add["{"];
			output.newline[];
			e1.generateCode[];
			output.add["}"];
			output.newline[];
		);
		
		if (outcome==false)
		(
			output.add["{"];
			output.newline[];
			e2.generateCode[];
			output.add["}"];
			output.newline[];
		);
		if (outcome :: unknown)
		(
			output.add["if ("];
			b.generateCode[];
			output.add[")"];
			output.newline[];
			output.add["{"];
			output.newline[];
			e1.generateCode[];
			output.add["} else {"];
			output.newline[];
			e2.generateCode[];
			output.add["}"];
			output.newline[];			
		);
	);
	
	var checkType:=method[]
	(
		if (!((b.getCurrentType[]).check[Bool]))
		(
			errors.TypeError[];
		);
		//b.checkType[];
		e1.checkType[];
		e2.checkType[];
	);
	
	 var checkExpression:=method[] errors.SExpressionError[];
);var inclass SemLet:=class (superclass.SemLet)
(
	var eval:=method[] start[];
	var checkParallel:=method[] att checkSequential[];
	var checkSequential:=method[]
	(
		b.setshortcut[e1];

		b.checkVariable[];
		e1.checkExpression[];
		e2.checkSequential[];
	);
	
	var optimise:=method[]
	(
		e2.optimise[];
	);
	
	var generateCode:=method[]
	(
		output.add["{"];
		output.newline[];
		e2.generateCode[];
		output.newline[];
		output.add["}"];
	);
	
	var checkType:=method[]
	(
		b.checkType[];
		e1.checkType[];
		e2.checkType[];	
	);
);/*
File created 29/5/2007 by Nick Brown
*/

var inclass SemWhile:= class (superclass.SemWhile) 
(
	var evalStart := method [] start[];
	
	var eval:=method[] 
	(
		start[];
	);
	
	var checkParallel:=method[] att checkSequential[];
	
	var checkSequential:=method[]
	(		
		e1.checkExpression[];		
		e2.checkSequential[];
	);
	
	var optimise:=method[]
	(		
		e1.setRange[];	
		insideloop:=insideloop + 1;	
		e2.optimise[];			
		insideloop:=insideloop - 1;					
	);
	
	var generateCode:=method[]
	(		
		output.add["while ("];
		e1.generateCode[];
		output.add[")"];
		output.newline[];
		output.add["{"];
		output.newline[];
		insideloop:=insideloop + 1;	
		e2.generateCode[];			
		insideloop:=insideloop - 1;	
		output.add["}"];
		output.newline[];					
	);
	
	var checkType:=method[]
	(
		if (!((e1.getCurrentType[]).check[Bool]))
		(
			errors.TypeError[];
		);
		e2.checkType[];
	);
	
	 var checkExpression:=method[] errors.SExpressionError[];
);var inclass SemReturn:=class (superclass.SemReturn)
(
	var eval:=method[] 
	(
		start[];
	);
	var evalStart := method [] start[];

	var checkParallel:=method[] att checkSequential[];
	var checkSequential:=method[]
	(
		e.checkExpression[];		
	);
	var checkType:=method[] 
	(
		 returntype.aadd[((e.getCurrentType[]).isElementType[])];
	);
	var optimise:=method[] skip;
	var checkExpression:=method[] errors.SExpressionError[]; 
	var generateCode:=method[]
	{
		//(output.getMethodArgs[]).generateMethodVariableRestore[];
		var ns:=scopeinfo.clone[];
		ns.remove[e];
		ns.destroyAll[];
		output.add["return "];
		e.generateCode[];
		output.add[";"];
		output.newline[];
	};
);/*
	Skip is provided so that the coder does not need the else arm of a binary condition
	First written 10/4/07 by Nick Brown
*/
var inclass Skip:= class (superclass.Skip) (
	var checkParallel:=method[] att checkSequential[];
	var checkSequential:=method[] skip;
	var checkType:=method[] skip;
	var generateCode:=method[] skip;
);/*
File created 18/4/2008 by Nick Brown
*/
var inclass Break:= class (superclass.Break) (
	var checkParallel:=method[] att checkSequential[];
	var checkSequential:=method[] skip;
	var checkType:=method[] skip;
	var generateCode:=method[] 
	(
		output.add["break;"];
		output.newline[];
	);
);var inclass SemMethodExp:=class (superclass.SemMethodExp)
(  
    var checkExpression:=method[]
    {
    	skip;  	
    };
    
   
    var getValue:=method[] null;	//method has null value maybe have something instead
    var ismethod:=method[] false;
    var userdefined:=method[] true;
    var getCurrentType:=method[] return new unknown;
   
);
/*
File created 20/6/2007 by Nick Brown
*/

var inclass SemFunction:= class (superclass.SemFunction) 
(
	var dynamic needsstar:=false;
	var dynamic parallelfn:=false;
	var eval:=method[] start[];
	var checkParallel:=method[] 
	(
		checkSequential[];
	);
	
	var setInfo:=method[]
	{
		var xc:=(variable.eval[]);
		if (checkifVar[]==true) xc:=(variable.getstoredtype[].eval[]).clone[];
		methodinfo.add[(e1.getName[]),xc];		
	};
	
	var checkSequential:=method[] 
	{
		if (e1.getName[]="main")
		(
			output.selectGlobal[];
		);			
		var fndet:=new functiondetails[e1.getName[]];
		e2.setsize[];		
		fndet.setArgsNumber[e2.getSize[]];
		thefunctions.hput[e1.getName[],fndet];
		e2.checkParallel[];
		setInfo[];
		body.checkSequential[];
	};
	
	var checkType:=method[] 
	{
		returntype:=new ArrayList[];
		if (e1.getName[]="main")
		(
			if ((e2.getSize[] != 2) && (e2.getSize[] != 0))
			(
				throw error "Incorrect number of arguments to main function";
			);
			if (e2.getSize[]==2)
			(
				var toset:=Int;
				var alloc:=new allocated[];
				alloc.allocationtype:=new multiple[];
				alloc + toset;
				(e2.v[0]).setstoredtype[alloc];
				e2.v[0].setName["MESHargc"];
				output.addDeclaration[e2.v[0].getDeclarationChecker[]];
				toset:=new array[String,new Range[10,10]];
				toset.setarg[String,0];
				toset.setarg[new Range[10,10],1];
				alloc:=new allocated[];
				alloc.allocationtype:=new multiple[];
				alloc + toset;
				(e2.v[1]).setstoredtype[alloc];
				e2.v[1].setName["MESHargv"];
			);
		);
		body.checkType[];
		if (returntype.getsize[] > 0)
		(
			needsstar:=!(returntype.aget[0]);	// invert this - computes if is :: coretype or not, so false = needs star, true is doesn't
			var i:=returntype.agetiterator[];
			while i.hasNext[]
			(
				if (((i.next[]).getdata[])==needsstar) errors.FunctionReturnMixture[];
			);
		);		
	};
	var optimise:=method[] 
	{
		inafn:=true;
		fnparallel:=false;
		body.optimise[];
		inafn:=false;		
		if (fnparallel==true && e1.getName[]!="main")
		(
			parallelfn:=true;
			fnparallel:=false;
			var fndet:=thefunctions.hget[e1.getName[]];
			fndet.setParallel[true];			
		);		
	};
		
	var generateCode:=method[]
	{
		if (e1.getName[]="main")
		(
			output.forgetGlobal[];			
			body.generateCode[];
		) else (			
			if (parallelfn==true)
			(
				output.addMethodProto["typedef "];
				if (checkifVar[]==true)
				(
					output.addMethodProto[((variable.getstoredtype[]).eval[]).getDeclaration[]];
				) else (
					output.addMethodProto[(variable.eval[]).getDeclaration[]];			
				);
				if (needsstar==true) output.addMethodProto[" *"];
				output.addMethodProto[" (*MESHParallelfn"];
				output.addMethodProto[e1.getName[]];
				output.addMethodProto[")("];
				e2.generateMethodProtoParam[];			
				output.addMethodProto[");"];
				output.newlineMethodProto[];
				output.addMethodProto["MESHParallelfn"];
				output.addMethodProto[e1.getName[]];
				output.addMethodProto[" MESHfnreference"];
				output.addMethodProto[e1.getName[]];
				output.addMethodProto["["];
				output.addMethodProto[totalprocesses];
				output.addMethodProto["];"];
				output.newlineMethodProto[];
				var i;
				for i from 0 to totalprocesses - 1
				(
					initfntext.aadd["MESHfnreference"];										
					initfntext.aadd[e1.getName[]];
					initfntext.aadd["["];
					initfntext.aadd[i];
					initfntext.aadd["]"];
					initfntext.aadd["=&"];
					initfntext.aadd[e1.getName[]];
					initfntext.aadd[i];
					initfntext.aadd[";"];
					initfntext.aadd["\n"];
				);
			) else (		
				if (checkifVar[]==true)
				(
					output.addMethodProto[((variable.getstoredtype[]).eval[]).getDeclaration[]];
				) else (
					output.addMethodProto[(variable.eval[]).getDeclaration[]];			
				);
				if (needsstar==true) output.addMethodProto[" *"];
				output.addMethodProto[" "];
				output.addMethodProto[e1.getName[]];
				output.addMethodProto["("];
				e2.generateMethodProtoParam[];			
				output.addMethodProto[");"];
				output.newlineMethodProto[];
			);
				
			var currentp:=output.getSelect[];
			var mp;			
			if (parallelfn==true)
			(	
				mp:=output.addParallelMethod[e2,variable,needsstar,e1];	// fix me
				output.selectMethod[mp];							
			) else (
				mp:=output.addMethod[e2];	
				output.selectMethod[mp];
				if (checkifVar[]==true)
				(		
					var thesize:=((variable.getstoredtype[]).eval[]).getSize[];												
					((variable.getstoredtype[]).eval[]).generateDeclaration[];
					if (thesize.a > 1) needsstar:=false;
				) else (
					(variable.eval[]).generateDeclaration[];
				);
				if (needsstar==true) output.add[" *"];
				output.add[" "];
				e1.generateName[];
				output.add["("];
				e2.generateMethodParam[];
				output.add[")"];			
			);
			output.newline[];						
			output.add["{"];
			output.newline[];			
			body.generateCode[];		
			scopeinfo.destroyAll[];
			scopeinfo.clear[];	
			output.add["}"];
			output.setHardSelect[currentp];
		);
	};	
	
	var checkifVar:=method[]
	{
		var dummycheck:=new dummyfn[];
	 	if (((variable.getType[]).check[((dummycheck.adummymethod).body).getType[]])) return false;
	 	return variable.isavariable[];
	};
	
);
/*
	This class contains much of the work for SemOpAdd, subtract etc.... so they are minimal
	which is good because they share so much.
	The way Flex works is SemOpAdd -> Flex's SemOpAdd -> SemBinOperator -> Flex's SemBinOperator
*/
var inclass SemBinOperator:=class(superclass.SemBinOperator) 
(		
        var checkExpression:=method[]
        (      	         
        	e1.checkExpression[];
        	e2.checkExpression[];
        );
        var isavariable:=method[] false;
);var inclass SemUnaryOperator:=class(superclass.SemUnaryOperator) 
(
	var checkExpression:=method[] e.checkExpression[]; 	
	var checkType:=method[] e.checkType[];
	var isavariable:=method[] false;
);
var inclass SemOpAnd:=class (superclass.SemOpAnd) 
(
	var getCurrentType:=method[] return Bool;
	var checkType:=method[]
	(
		// e1 and e2 MUST have the same type for this to be meaningful
		if !(e1.getCurrentType[].check[e2.getCurrentType[]])
		(
			errors.TypeError[];
		);
	);
	
	var getValue:=method[] 
	{
		var a:=e1.getValue[];
		var b:=e2.getValue[];
		if ((a :: unknown) || (a==null) || (b :: unknown) || (b==null)) return new unknown;		
		return a==true && b==true;
	};
	
	var generateCode:=method[]
	{
			output.add["("];
			e1.generateCode[];
			output.add["&&"];
			e2.generateCode[];			
			output.add[")"];
	};

);/*
	Holds the general classes used by comparable operators
	File created 10/5/2007 by Nick Brown
*/
var inclass SemComparable:=class(superclass.SemComparable) 
(
	var dynamic theval:= new unknown[];
	
	var getCurrentType:=method[] return Bool;
	var isavariable:=method[] false;
	var ismethod:=method[] false; 
	var checkType:=method[]
	(
		// e1 and e2 MUST have the same type for this to be meaningful
		if !(e1.getCurrentType[].check[e2.getCurrentType[]])
		(
			if ((e2.getCurrentType[])::Range)
				(
					// checks to see if it is a Range variable on both (this will fail a check) If so will check the type of high and low
					if  !(((e2.getCurrentType[]).a.getType[]).check[((e1.getCurrentType[]).a.getType[])] &&
						((e2.getCurrentType[]).b.getType[]).check[((e1.getCurrentType[]).b.getType[])])
					(
						// no, the two ranges are not the same!
						errors.TypeError[];
					);					
				) else (
					errors.TypeError[];
				);
		);
	);
	
	var generatePrint:=method[]
	(
		generateCode[];
		output.add["\""];
	);
	
	var setRange:=method[]
	(
		if ((e1.getValue[]) :: Range)
		(
			if ((e2.getValue[]) :: unknown) 
			(
				//e1.setValue[e2.getValue[]];
				(e1.getValue[]).b:=new unknown[];
			) else (
				(e1.getValue[]).b:=(e2.getValue[]).a;	// might not work for == or joint tests!
			);
		) else (
			return new unknown;
		);
	);
	
	var generateCode:=method[]
	{
		if (theval :: unknown)
		(
			output.add["("];
			if (e1.getCurrentType[].check[String])
			(
				// need to be different for string
				output.add["MESHstrequals("];
				e1.generateCode[];
				output.add[","];
				e2.generateCode[];	
				output.add[")"];
				generateSign[];
				output.add["0"];
			) else (				
				e1.generateCode[];
				generateSign[];
				e2.generateCode[];		
			);
			output.add[")"];
		) else (
			if (theval==true) output.add["0==0"];
			if (theval==false) output.add["1==0"];
			//output.add[theval];	// this correct?
		);	
	};
	
	var optimiseAccess:=method[x,i] skip;
	var generateAccess:=method[x,i] false;
	var checkValue:=method[x]
	{
		var e1val:=e1.getValue[];
		var e2val:=e2.getValue[];
		if ((e1val :: unknown) || (e1val==null) || (e2val :: unknown) || (e2val==null)) return new unknown;	
		if (e1val :: Range)
		(
			if (e1val.a !=e1val.b) return new unknown;
		);	
		if (e2val :: Range)
		(
			if (e2val.a !=e2val.b) return new unknown;
		);	
		theval:=x;
		return x;
	};
	
	var isElementType:=method[] true;
);var inclass SemOpNormalEqualTo:=class (superclass.SemOpNormalEqualTo) 
(	
	var getValue:=method[]
	{		
		var first:=checkValue[(e1.getValue[] == e2.getValue[])];		
		if (first==true || first::unknown) return first;
		
		return checkValue[(e1.getValue[] = e2.getValue[])];		
	};
	
	var generateSign:=method[] output.add["=="];	
);var inclass SemOpNotEqualTo:=class (superclass.SemOpNotEqualTo) 
(
	var getValue:=method[]
	{		
		var first:=checkValue[(e1.getValue[] != e2.getValue[])];		
		if (first==true || first::unknown) return first;
		
		return checkValue[(!(e1.getValue[] = e2.getValue[]))];		
	};
	
	var generateSign:=method[] output.add["!="];
);var inclass SemOpGreaterOrEqual:=class (superclass.SemOpGreaterOrEqual) 
(
	var getValue:=method[]
	(		
		return checkValue[(e1.getValue[] >= e2.getValue[])];
	);
	
	var generateSign:=method[] output.add[">="];
);var inclass SemOpLessOrEqual:=class (superclass.SemOpLessOrEqual) 
(
	var getValue:=method[]
	(		
		return checkValue[(e1.getValue[] <= e2.getValue[])];
	);
	
	var generateSign:=method[] output.add["<="];
);var inclass SemOpLessThan:=class (superclass.SemOpLessThan) 
(
	var getValue:=method[]
	(		
		return checkValue[(e1.getValue[] < e2.getValue[])];
	);
	
	var generateSign:=method[] output.add["<"];
);var inclass SemOpGreaterThan:=class (superclass.SemOpGreaterThan) 
(
	
	var getValue:=method[]
	(		
		return checkValue[((e1.getValue[]) > (e2.getValue[]))];
	);
	
	var generateSign:=method[] output.add[">"];
);/*
File created 29/7/2008 by Nick Brown
*/
var inclass SemOpLessLessThan:=class (superclass.SemOpLessLessThan) 
(
	var getValue:=method[]
	(		
		return new unknown[];
	);	
	
	var getCurrentType:=method[] return Int;
	var isavariable:=method[] false;
	var ismethod:=method[] false; 
	var checkType:=method[]
	(
		// e1 and e2 MUST have the same type for this to be meaningful
		if !(e1.getCurrentType[].check[e2.getCurrentType[]])
		(
			if ((e2.getCurrentType[])::Range)
				(
					// checks to see if it is a Range variable on both (this will fail a check) If so will check the type of high and low
					if  !(((e2.getCurrentType[]).a.getType[]).check[((e1.getCurrentType[]).a.getType[])] &&
						((e2.getCurrentType[]).b.getType[]).check[((e1.getCurrentType[]).b.getType[])])
					(
						// no, the two ranges are not the same!
						errors.TypeError[];
					);					
				) else (
					errors.TypeError[];
				);
		);
	);
	
	var generatePrint:=method[]
	(
		generateCode[];
		output.add["\""];
	);
	
	var setRange:=method[]
	(
		if ((e1.getValue[]) :: Range)
		(
			if ((e2.getValue[]) :: unknown) 
			(
				//e1.setValue[e2.getValue[]];
				(e1.getValue[]).b:=new unknown[];
			) else (
				(e1.getValue[]).b:=(e2.getValue[]).a;	// might not work for == or joint tests!
			);
		) else (
			return new unknown;
		);
	);
	
	var generateCode:=method[]
	{
		e1.generateCode[];
		output.add["<<"];
		e2.generateCode[];
	};
	
	var optimiseAccess:=method[x,i] skip;
	var generateAccess:=method[x,i] false;
	var checkValue:=method[x]
	{
		return new unknown[];
	};
	
	var isElementType:=method[] true;
);/*
File created 29/7/2008 by Nick Brown
*/
var inclass SemOpGreaterGreaterThan:=class (superclass.SemOpGreaterGreaterThan) 
(
	var getValue:=method[]
	(		
		return new unknown[];
	);	
	
	var getCurrentType:=method[] return Int;
	var isavariable:=method[] false;
	var ismethod:=method[] false; 
	var checkType:=method[]
	(
		// e1 and e2 MUST have the same type for this to be meaningful
		if !(e1.getCurrentType[].check[e2.getCurrentType[]])
		(
			if ((e2.getCurrentType[])::Range)
				(
					// checks to see if it is a Range variable on both (this will fail a check) If so will check the type of high and low
					if  !(((e2.getCurrentType[]).a.getType[]).check[((e1.getCurrentType[]).a.getType[])] &&
						((e2.getCurrentType[]).b.getType[]).check[((e1.getCurrentType[]).b.getType[])])
					(
						// no, the two ranges are not the same!
						errors.TypeError[];
					);					
				) else (
					errors.TypeError[];
				);
		);
	);
	
	var generatePrint:=method[]
	(
		generateCode[];
		output.add["\""];
	);
	
	var setRange:=method[]
	(
		if ((e1.getValue[]) :: Range)
		(
			if ((e2.getValue[]) :: unknown) 
			(
				//e1.setValue[e2.getValue[]];
				(e1.getValue[]).b:=new unknown[];
			) else (
				(e1.getValue[]).b:=(e2.getValue[]).a;	// might not work for == or joint tests!
			);
		) else (
			return new unknown;
		);
	);
	
	var generateCode:=method[]
	{
		e1.generateCode[];
		output.add[">>"];
		e2.generateCode[];
	};
	
	var optimiseAccess:=method[x,i] skip;
	var generateAccess:=method[x,i] false;
	var checkValue:=method[x]
	{
		return new unknown[];
	};
	
	var isElementType:=method[] true;
);/*
	Holds the general classes used by arithmetic
	File created 10/5/2007 by Nick Brown
*/
var inclass SemArithmetic:=class(superclass.SemArithmetic) 
(
	var dynamic result:= new unknown[];
	var generateMethodInvoke:=method[x] generateUnknownCode[];	// so that can call print on the results
	var generatePrint:=method[]
	{		
		// hidden in fn call - therefore no optimise called, so call at this point to see if can optimise
		var vals:=getValue[];
		if (vals::unknown || vals.isrange[])
		(	
			if (e1.getCurrentType[].check[String])
			(
				output.add["%s"];
			) else (
				output.add["%d"];
			);
			return true;		
		) else (
			output.add[vals];			
		);
	};
	 var isavariable:=method[] false;
	var optimiseAccess:=method[x,i] skip;
	
	var generateAccess:=method[x,i]
	{
		var temp1:=new tempvar[];
		var onething:=e1.generateAccess[temp1,i];
		var temp2:=new tempvar[];	
		var twothing:=e2.generateAccess[temp2,i];
		if ((onething==true) || (twothing==true))
		(
			x.generateName[];
			output.add["="];
			output.add["("];
			if (onething==true)
			(
				temp1.generateName[];
			) else (
				e1.generateName[];
			);
			
			generateSign[];
			
			if (twothing==true)
			(
				temp2.generateName[];
			) else (
				e2.generateName[];
			);
			output.add[")"];
			output.add[";"];
			output.newline[];
		);
		
		return ((onething==true) || (twothing==true));
	};
	
	var generateCode:=method[]
	(		
		//if (result :: unknown || result.isrange[])
		//(
			//e2.generateAccess[];
			output.add["("];
			generateUnknownCode[];
			output.add[")"];
		//) else (			
		//	output.add[result];
		//);
	);
         
    var checkType:=method[]
	{		
		e1.checkType[];
		e2.checkType[];	
		if !(e1.getCurrentType[].check[e2.getCurrentType[]])
		(		
			var firsthing:=e1.getCurrentType[];
			var secondthing:=e2.getCurrentType[];
			if (firsthing.check[Null]==true) return new unknown;
			if (secondthing.check[Null]==true) return new unknown;
			if !(firsthing :: coretype) firsthing:=firsthing.getCoreType[];			
			if !(secondthing :: coretype) secondthing:=secondthing.getCoreType[];
			if (!(firsthing.check[secondthing]) && !(secondthing.check[firsthing]))
			(
				/*
					Why do we do this both ways? Simple - the type checking in core only allows subtyping in one direction
					i.e. Double -> Float -> Integer . This is good for assignment etc... However in this context, we often want
					to have Float op Int or Int op Float etc... To allow for this do check in both directions and allow if 
					either is allowed
				*/
				// no as does not equal - quite ok as used to return .t for both. However, get coretype seems to give null - why?
				errors.TypeError[];							
			);
		);		
	};	
         
    var getCurrentType:=method[]
	(		
		checkType[];
		// Doublee (3) -> Floatt (2) -> Int (1)
		/*
			Here follows the type hierarchy above - in a operation we wish to return
			the type at the top of the relative hierarchy
			i.e. Int + Int = Int, Double + Float = Double, Int * Float = Float, Int - Double = Double etc...
		*/
		if (((e1.getCurrentType[]).isElementType[])==true)
		(
			if ((e1.getCurrentType[]).getTypeID[] < (e2.getCurrentType[]).getTypeID[])
			(
				return e2.getCurrentType[];
			);
		);
		return e1.getCurrentType[];		
	);
	         
    var ismethod:=method[] false;      
   
    
    var checkValue:=method[x]
	{				
		checkType[];		
		var e1val:=e1.getValue[];
		var e2val:=e2.getValue[];
		if (!((e1val==null) || (e1val :: unknown)) && !((e2val==null) || (e2val :: unknown)))
		(
			//if ((e1val.a == e1val.b) && (e2val.a == e2val.b)) 
			//(
				if ( (e1val :: Range) && (e2val :: Range))
				(
					if (x==1) return new Range[e1val.a * e2val.a,e1val.b * e2val.b];
					if (x==2) return new Range[e1val.a % e2val.a,e1val.b % e2val.b];
					if (x==3) return new Range[e1val.a + e2val.a,e1val.b + e2val.b];
					if (x==4) return new Range[e1val.a - e2val.a,e1val.b - e2val.b];				
				);
			//)
		);
		return new unknown;
	};
	
	var isElementType:=method[] true;
);/*
	Add operator. 
	
	First written 10/4/07 by Nick Brown
*/
var inclass SemOpAdd:=class(superclass.SemOpAdd)
(
	var getValue:=method[]
	(				
		return checkValue[3];
	);
	
	var generateUnknownCode:=method[]
	(
		if (e1.getCurrentType[].check[String])
		(
			output.add["MESHstrcat("];
			e1.generateCode[];
			output.add[","];
			e2.generateCode[];
			output.add[")"];
		) else (
			e1.generateCode[];
			generateSign[];
			e2.generateCode[];
		);
	);
	
	var generateSign:=method[]
	(
		output.add["+"];
	);
);/*
	Divide operator.
	
	First written 1/5/07 by Nick Brown
*/
var inclass SemOpDiv:=class(superclass.SemOpDiv)
(
	var getValue:=method[]
	{
		var e2val:=e2.getValue[];	
		if (e2val :: Range)
		(
			if (e2val.a == 0 || e2val.b == 0)
			(
				throw error "Divide by Zero Error!";
			);
		);	
		return checkValue[2];
	};
	
	var getCurrentType:=method[]
	(		
		checkType[];
		// will return a double regardless as has the x.x
		return Doublee;
	);
	
	var generateUnknownCode:=method[]
	{
		if (e2.getValue[]==null)
		(
			output.insertDynamicCheckDividebyZero[e2];
		) else (
			if ((e2.getValue[]) :: unknown || (e2.getValue[]).isrange[]==true)
			(
				// if don't know value of e2 need dynamic check
				output.insertDynamicCheckDividebyZero[e2];
			);
		);		
		/*
			Here will cast the none double variables or values to be double
			so that division will result in a double value
		*/	
		var addd:=false;
		if (((e1.getCurrentType[]).isElementType[]) == true)
		(
			if ((e1.getCurrentType[]).getTypeID[] != 3)
			(
				output.add["(double) "];
				addd:=true;
			);
		);
		e1.generateCode[];
		generateSign[];
		if (addd==true) output.add["(double) "];
		e2.generateCode[];
	};
	
	var generateSign:=method[]
	(
		output.add["/"];
	);
);var inclass SemOpMultiply:=class(superclass.SemOpMultiply)
(
	var getValue:=method[]
	(						
		return checkValue[1];
	);
	
	var generateUnknownCode:=method[]
	(
		e1.generateCode[];
		generateSign[];
		e2.generateCode[];
	);
	
	var generateSign:=method[]
	(
		output.add["*"];
	);
);var inclass SemOpSubtract:=class(superclass.SemOpSubtract)
(
	var getValue:=method[]
	(								
		return checkValue[4];
	);
	
	var generateUnknownCode:=method[]
	(
		e1.generateCode[];
		generateSign[];
		e2.generateCode[];
	);
	
	var generateSign:=method[]
	(
		output.add["-"];
	);
);/*
File created 25/10/2007 by Nick Brown
*/

var inclass SemOpMinus:=class(superclass.SemOpMinus)
(
	
	var generateUnknownCode:=method[]
	(		
		generateSign[];
		e.generateCode[];
	);
	
	var generateSign:=method[]
	(
		output.add["-"];
	);
	
	
	var generatePrint:=method[]
	{		
		var vals:=e.getValue[];
		if (vals::unknown || vals.isrange[])
		(	
			output.add["%d\","];
			generateUnknownCode[];		
		) else (
			output.add[vals];
			output.add["\""];
		);
	};
	
	var generateAccess:=method[x,i]
	{
		skip;
	};
	
	var generateCode:=method[]
	(		
		//if (result :: unknown || result.isrange[])
		//(
			//e2.generateAccess[];
			output.add["("];
			generateUnknownCode[];
			output.add[")"];
		//) else (			
		//	output.add[result];
		//);
	);
         
    var checkType:=method[]
	{		
		e.checkType[];		
	};	
         
    var getCurrentType:=method[]
	(		
		checkType[];
		return e.getCurrentType[];
	);
	         
    var ismethod:=method[] false;        
    
    var checkValue:=method[x]
	{			
		return new unknown;
		/*	
		checkType[];		
		var eval:=e.getValue[];
		if (!((eval==null) || (eval :: unknown)))
		(
			if (eval.a == eval.b)
			(
				return -eval.a;
			);
		);
		return new unknown;
		*/
	};
);/*
	Represents primitivevalues, Characters, Bools etc..
	Also acts as a parent class to Integer and Float
	First written 10/4/07 by Nick Brown
*/
var inclass PrimitiveValue:= class (superclass.PrimitiveValue) 
(
		var isavariable:=method[] false;
        var checkExpression := method [] att checkConstant[];
        var checkConstant:=method[] skip;        
        var getCurrentType:=method[] getSource[].getType[];
        var getValue:=method[] return getSource[];        
        var ismethod:=method[] false;
        //var isrange:=method[] false;
        var generateCode:=method[] output.add[getValue[]];
        var generatePrint:=method[] 
        (
        	generateCode[];
			return false;
        );
        var generateAccess:=method[x,i] skip;
        var optimiseAccess:=method[x,i] skip;
);
/*
	Is a child class of PrimitiveValue - it implements some of the methods 
*/
var inclass Integer:= class (superclass.Integer) 
(       
        var getCurrentType:=method[] return Int;
        var getValue:=method[] return Range[intval, intval];
        var getTy:=method[] getValue[];
);/*
File created 2/7/2007 by Nick Brown
*/
var inclass Char:= class (superclass.Char) 
(       
        var getCurrentType:=method[] return Charr;
        var getValue:=method[] return ch;
        var getTy:=method[] getValue[];
        var generateCode:=method[]
        (
        	output.add["'"];
        	output.add[getValue[]];
        	output.add["'"];
        );
);/*
File created 22/6/2007 by Nick Brown
*/
var inclass MyString:= class (superclass.MyString) 
(       
        var getCurrentType:=method[] return String;
        var getValue:=method[] return s;
        var getTy:=method[] getValue[];
        var isavariable:=method[] false;
);/*
File created 25/6/2007 by Nick Brown
*/

var inclass MyStringExp:=class(superclass.MyStringExp)
(
	 var getCurrentType:=method[] return String;
        var getValue:=method[] return s;
        var getTy:=method[] getValue[];
         var checkExpression := method [] att checkConstant[];
        var checkConstant:=method[] skip;        
        var ismethod:=method[] false;
        var isavariable:=method[] false;
        //var isrange:=method[] false;
        var generateCode:=method[] 
        (
        	output.add["\""];
        	output.add[getValue[]];
        	output.add["\\0\""];
        );
        var generatePrint:=method[] 
        (
        	output.add[getValue[]];        	
        );
        var generateAccess:=method[] skip;
        var optimiseAccess:=method[] skip;
);/*
	Is a child class of PrimitiveValue - it implements some of the methods 
*/
var inclass Float:= class (superclass.Float) 
(      
        var getCurrentType:=method[] return Floatt;
        var getValue:=method[] return new Range[floatval, floatval];
        var getTy:=method[] getValue[];
);/*
File created 29/10/2007 by Nick Brown
*/
var inclass False:= class (superclass.False) 
(       
        var getCurrentType:=method[] return Bool;
        var getValue:=method[] return 0;
        var getTy:=method[] getValue[];
);/*
File created 29/10/2007 by Nick Brown
*/
var inclass True:= class (superclass.True) 
(       
        var getCurrentType:=method[] return Bool;
        var getValue:=method[] return 1;
        var getTy:=method[] getValue[];
);/*
	This class has three major uses
	a) Array access, a#i  
	b) Call a method
	c) Concatenate types
	
	The method deals with all these three requirements, will keep track of which it is
	First written 10/4/07 by Nick Brown
*/

var inclass SemMethodInvoke:=class(superclass.SemMethodInvoke)
(
	// A little more complex due to this class handling BOTH method invoke and also array access.
	// These two concepts are different yet need to be invoked by similar syntax
	
	var dynamic callsamethod:=null;
	var dynamic instanceofclass;
	var dynamic userdefn:=false;
	var dynamic composedcomponent:=false;
	var dynamic userproc:=false;
	
	var nostart:=false; 	// if allocated[evendist[]] in a block then will give a null error as calls start when evals evendist

	var eval:=method[] 
	{
		var dummycheck:=new dummyfn[];	
		var usep;
		var callm:=((e1.getType[]).check[((dummycheck.adummymethod).body).getType[]]);
		if (!(callm==true)) usep:= ((e1.getCurrentType[]) :: usermethod);
		if ((callsamethod==true || userproc==true || callm==true || usep==true) && (nostart==false)) start[];	 					
	};
	
	var isavariable:=method[]
	(
		setReftoMethod[];
		if ((callsamethod==null || callsamethod==false) && (userproc==false))
		(
	 		e1.isavariable[];
	 	) else (
	 		return false;
	 	);
	);
	
	var getDotValue:=method[x,i]
	{
		if (i==null) 
		(
			e1.getDotValue[x,this];
		) else (
			e1.getDotValue[x,i];
		);
		
	};
	
	var generateCommunicationIndex:=method[]
 	(
 		// only works for ONE array index - BAD!!!
 		//output.add[name];
 		e1.generateCode[];
 		output.add["+"];
 		//output.add[e2.getValue[]];
 		e2.generateCode[];
 	);
	
	var checkParallel:=method[] checkSequential[];
	
	var setReftoMethod:=method[]
	{
		if (callsamethod==null)	// is empty and undetermined
		(
			var dummycheck:=new dummyfn[];	
			callsamethod:=((e1.getType[]).check[((dummycheck.adummymethod).body).getType[]]);
			// callsamethod is now true if refers to a method		
			if (callsamethod==true)	// if is a method
			(		
 				try
 				( 	 		
 					var oldn:=nostart;
 					nostart:=true;	 			
 					var p:= (e1.eval)[]; 			
 					nostart:=oldn;
 					instanceofclass:=p;	// instance of class = this class 				
 					userdefn:=p.isuserdefined[];	// is the class user defined or not? 					
 				) catch "Stack overflow!" (
 					errors.FunctionMissing[];	// if the funtion is not found throw an error 			
 				); 				
			) else (	
				userproc:= ((e1.getCurrentType[]) :: usermethod);
			);
		);
	};
	
	var generateDeclaration:=method[] 
	(
		instanceofclass.setarg[e2.v[0],0];
		instanceofclass.generateDeclaration[];
	);
	
	var generatePrint:=method x
	{
		if (callsamethod==true)
		(
			instanceofclass.generatePrint[];
		) else (
			var args:=0;
			var s;
			try
 			(	
 				s:=x[0];
 				args:=1; 			
 			) catch "Index out of range in array reading!" (
 				s:=new stack[];
 			);
			s.push[e2];
			e1.generatePrint[s];
		);
	};
	
	var optimise:=method[]
	{
		if (callsamethod==true)
 		( 
 			instanceofclass.optimise[];
 		) else (
			if (userproc==true)
			(
				var sizeofargs:=e2.getSize[];					
				var i;
				for i from 0 to (sizeofargs - 1)
				(		
					if ((e2.get[i]).isavariable[]) 
					(		
						if ( (!(((e2.get[i]).getstoredtype[]) :: record)) && (!(((e2.get[i]).getstoredtype[]) :: coretype)))
						(					
							var newstack:=new stack[];		
							(e2.get[i]).optimiseMethodInvoke[newstack];					
						);
					);
				);
				e2.setParamUnknown[];					
			);
		);
	};
	
	var checkSequential:=method[]
	(	
		e2.checkExpression[];			
		setReftoMethod[];
		if (callsamethod==true)
 		( 				
 			instanceofclass.checkConstant[]; 	
 			instanceofclass.passArgs[e2];	
 			instanceofclass.checkFunction[e2.getSize[]];  			
 		) else (
 			if (userproc==false)
 			(
 			//	print "BYE!";
 		 	//	errors.SSequentialError[];
 		 		skip;
 		 		// disabled as if (a == (word#1)) will default to here on syntax check
 		 	);
 		);
	);
	
	var istypeexp:=method[] return false;
	
	var checkExpression:=method[] 
	(	
		e2.checkExpression[];				
		setReftoMethod[];
		composedcomponent:=true;
		if (callsamethod==true)
 		( 				
 			instanceofclass.checkConstant[];
 			instanceofclass.passArgs[e2];
 			instanceofclass.checkFunction[e2.getSize[]];
 		) else (
 			if (userproc==false)
 			(
 		 		e1.checkVariable[];	
 		 	);
 		);
	);
	
	var generateCode:=method[]
	{		
		if (callsamethod==true)
		(
			instanceofclass.generateCode[e2.v];
		) else (
			if (userproc==true)
			(
				var needsb:=false;	
				var sizeofargs:=e2.getSize[];
				var i;
				for i from 0 to (sizeofargs - 1)
				(
					if (((e2.get[i]).isavariable[])==false)
					(
						if (needsb==false)
						(
							needsb:=true;
							if (composedcomponent)
							(
								output.getCurrentText[].pointadd:=output.getCurrentText[].lastnewline;
								if (output.getCurrentText[].pointadd==0) output.getCurrentText[].pointadd:=-1;
							) else (
								output.add["{"];
							);
						);					
						output.add[(e2.get[i]).getCurrentType[].getDeclaration[]];
						output.add[" MESHtempfnvar"];
						output.add[i];
						output.add["="];
						(e2.get[i]).generateCode[];
						output.add[";"];
						output.newline[];
					);
				);				
				if (composedcomponent)
				(
					output.getCurrentText[].pointadd:=false;
				);
				var fndet:=thefunctions.hget[e1.getName[]];
				if (fndet.getParallel[]==true)
				(
					output.add["MESHfnreference"];
					output.add[e1.getName[]];
					output.add["[myrank]"];
				) else (
					output.add[e1.getName[]];
				);
				output.add["("];								
				
				var docomma:=false;
				for i from 0 to (sizeofargs - 1)
				(
					if ((e2.get[i]).isavariable[])
					(											
					if (!(((e2.get[i]).getstoredtype[]) :: record))
					(
						if (docomma==true)
						(
							output.add[","];
						) else (
							docomma:=true;
						);					
						
						/*
							Two things - firstly when call method if its a coretype then will put the name out there
							This name will prefix with & for a coretype if needed.
							For a more complicated type uses method invoke - this needs amp before
						*/						
						if (((e2.get[i]).getstoredtype[]) :: coretype)
						(	
							if ((e2.get[i]).isCpointer[]==false) output.add["&"];												
							output.add[(e2.get[i]).getName[]];
						) else (
							var newstack:=new stack[];
							output.add["&"];							
							(e2.get[i]).generateMethodInvoke[newstack];						
						);
					);
					) else (
						if (docomma==true)
						(
							output.add[","];
						) else (
							docomma:=true;
						);	
						output.add["&MESHtempfnvar"];
						output.add[i];
					);
				);
				
				output.add[")"];
				if (composedcomponent==false)
				(
					output.add[";"];
					if (needsb==true) output.add["}"];
					output.newline[];
				);
				
			) else (
				var st:=new stack[];
				st.push[e2];				
				e1.generateMethodInvoke[st];
			);
		);
	};
	
	var retrieveMethodArgs:=method[x]
	(
		x.push[e2];
		return e1.retrieveMethodArgs[x];
	);
	
	var generateMethodInvoke:=method[x]	// NEED TO SORT!
	(
		if (callsamethod==true)
		(
			instanceofclass.generateMethodInvoke[x];
		) else (
			x.push[e2];
			e1.generateMethodInvoke[x];
		);
	);
	
	var optimiseMethodInvoke:=method[x]
	(
		x.push[e2];
		e1.optimiseMethodInvoke[x];
	);
	
	var checkVariable:=method[]
 	( 	  		 
 		e2.checkExpression[]; 		 			
 		setReftoMethod[];
 		
 		if (callsamethod==true)
 		( 				
 			errors.SVariableError[];			
 		) else (
 			e1.checkVariable[];	
 		);
 	);
	
	var ismethod:=method[] callsamethod;
	
	var userdefined:=method[] userdefn;
	
 	var checkType:=method[]
 	( 	 	
 		if (!(callsamethod==true))
 		( 		 	 			 		
 			if (userproc==false)
 			(	
 				if ((e1.getstoredtype[])==null)
 				(
 					errors.TypeError[];	// there is no type
 				);
 				/*
 					Below disabled for now - did check that index is of type int
 				*/ 			 				
 				//if !(e2.getCurrentType[].check[Int])  errors.TypeError[]; // ensure index is : Int 			
 				e1.checkType[]; 				 			
 			);
 		) else (
 			instanceofclass.checkArgType[e2];	// for a method, check the args is done by the method itself
 		); 
 		if (userproc==true)
 		( 			
 			// check number of args match
 			e2.setsize[];
			if ((thefunctions.hget[e1.getName[]]) == null)
			(
				// function does not exist
				errors.FunctionMissing[];
			);
 			if (!(((thefunctions.hget[e1.getName[]]).getArgsNumber[])== e2.getSize[]))
 			(
 				errors.FunctionArguments[];
 			); 			
 		); 		
 	);
 	
 	var getTy:=method[]
	{	
		// Apart from creating instance of type, also need to pass arguments to it
		// Unfortunately this needs to be done separately to creation	
		setReftoMethod[];
		e2.setsize[];
		var numberargs:=e2.getSize[];
		if (numberargs>-1)
		(
			var i;
			for i from 0 to numberargs - 1
			(
				instanceofclass.setarg[e2.v[i],i];
			);
		);
		return instanceofclass;
	};
 	
 	var getCurrentType:=method[]
 	(
 		checkType[];
 		if (!(callsamethod==true))
 		(	 	
 			if (userproc==true) return (methodinfo.get[(e1.getName[])]); //.clone[];
 			//return (e1.getstoredtype[]).t;	// assumes is an array, maybe not nesc who knows!
 			return e1.getCurrentType[];	// does this now , passes for dot, not array!
 		) else (
 			return instanceofclass.getCurrentType[];
 		);
 	);
 	
 	var getValue:=method[]
	{
		if (userproc==true) return new unknown;
		var argstopass:=new stack[];
		return att getMethodInvokeValue[argstopass];
	};
	
	var setValue:=method[x]
 	{  		
 		var argstopass:=new stack[];
 		// WARNING SHOULD BE ENABLED!!!! BELOW!
		//return att setMethodInvokeValue[argstopass,x];
 	};
	
	var getMethodInvokeValue:=method[argstopass] 
	{
		if (callsamethod==true) return new unknown[];
		
		var e2value:=e2.getValue[];
		if ((e2value)::unknown) return new unknown;	// index is unknown
		
		argstopass.push[e2value];
			
		var resulty:=e1.getMethodInvokeValue[argstopass];
		if (resulty==null) return new unknown;	// result is nothing
		return resulty;		
	};
		
	var setMethodInvokeValue:=method[argstopass,data] 
	{
		if (callsamethod==true) throw error "Can't assign value to method!";
 		var e2value:=e2.getValue[];	
 		if ((e2value)::unknown) return new unknown;	// index is unknown			
 		if (e2value :: Range)	// this checks if its a number - if so is it just one or a range? If a range then cant assign
 		(
 			if (!(e2value.a == e2value.b)) return new unknown;
 		);
		argstopass.push[e2value];	
		e1.setMethodInvokeValue[argstopass,data];
	};
	
	var optimiseAssignment:=method[x,i]
	{
		if (callsamethod==false && (userproc==false))
		(
			var m;
			if (i==null)
			(
				m:=new stack[];
			) else (
				m:=i;
			);
			m.push[e2];
			e1.optimiseAssignment[x,m];
		);
	};
	
	var optimiseAccess:=method[x,i]
	{
		if (callsamethod==false && (userproc==false))
		(
			var m;
			if (i==null)
			(
				m:=new stack[];
			) else (
				m:=i;
			);
			m.push[e2];
			e1.optimiseAccess[x,m];
		) else (
			if (userproc==false)
			(
				instanceofclass.optimiseAccess[x,i];
			);
		);	
	};
	
	var generateAssignment:=method[x,i]
	{
		var m;
		if (i==null)
		(
			m:=new stack[];
		) else (
			m:=i;
		);
		m.push[e2];		
		e1.generateAssignment[x,m];
	};
	
	var generateAccess:=method[x,i] 
	{		
		if ((callsamethod==null || callsamethod==false) && (userproc==false)) 
		(
			var m;
			if (i==null)
			(
				m:=new stack[];
			) else (
				m:=i;
			);
			m.push[e2];		
			e1.generateAccess[x,m];
		) else (
			if (userproc==false)
			(
				instanceofclass.generateAccess[x,i];
			);
		);	
	};
);/*
	This class is used to represent a simple variable, in the case of var x:=12; or var x; if the variable is explicitly typed such as var c:Int then use SemTypedVar
	First written 10/4/07 by Nick Brown
*/

 var inclass PubStaticVariable:= class (superclass.PubStaticVariable) 
 (
 	var dynamic usesModType:=false;
 	var dynamic dirtyvalue:=false;
 	var dynamic typevariable:=false;
 	var dynamic pointer;
 	var dynamic usesti:=false;
 	var dynamic storedval:=null; 	
 	var dynamic checkedInBaseC;
 	var dynamic syncheckedInBaseC;
 	var dynamic optimisedInBaseC;
 	var dynamic storedtype:=null;
 	var dynamic shortcutvar:=null;	 
 	var dynamic hasbeendeclared:=false;
 	var dynamic extrastar:=false;
 	var dynamic inittype:=null;
 	var dynamic declaredtype;
 	var dynamic myID;
 	var totalid:=0;
 	
 	
 	var setDirty:=method[x] dirtyvalue:=x;
 	var setUsesTypeInference:=method[x] usesti:=x;
 	var getUsesTypeInference:=method[] usesti;
 	var setTypeVar:=method[x] typevariable:=x;
 	var getTypeVar:=method[] typevariable;
 	var isTypeVar:=method[] getTypeVar[];
 	var setName:=method[x]  name:=x;
 	var setUsesModType:=method[x] usesModType:=x;
 	var getUsesModType:=method[] usesModType;
 	var istypeexp:=method[] return false;
 	var setPointer:=method[x] pointer:=x;
 	var getPointer:=method[] pointer;
 	var isPointer:=method[] return (!(pointer==null));
 	/*
 		The next four methods are for scoping - refer to SemAssignment class, but its so that if a typecheck or optimisation is done and stored
 		then it will not be redone.
 	*/
 	
 	var setInitialType:=method[x] inittype:=x;
 	var getInitialType:=method[] inittype;
 	
 	var addSyntaxCheck:=method[] syncheckedInBaseC.aadd[BaseC];
 	
 	var checkAlreadySyntaxChecked:=method[]
 	{
 		if (syncheckedInBaseC==null) syncheckedInBaseC:=new ArrayList[];
 		var itsy:=syncheckedInBaseC.agetiterator[];
 		while (itsy.hasNext[])
 		(
 			if ((itsy.next[]).getdata[]==BaseC) return true;
 		);	
 		return false;
 	};
 	
 	var addTypeCheck:=method[] checkedInBaseC.aadd[BaseC];
 	
 	var checkAlreadyTypeChecked:=method[]
 	{
 		if (checkedInBaseC==null) checkedInBaseC:=new ArrayList[];
 		var itsy:=checkedInBaseC.agetiterator[];
 		while (itsy.hasNext[])
 		(
 			if ((itsy.next[]).getdata[]==BaseC) return true;
 		);	
 		return false;
 	};
 	
 	var checkDirty:=method[] 
 	(
 		if (dirtyvalue==true) misc.dirtyAccessVar[this];
 	);
 	
 	var getDotValue:=method[x,i]
	{
		if (shortcutvar==null)
 		(
			if (i==null) 
			(
				storedtype.getDotValue[x,this];
			) else (
				storedtype.getDotValue[x,i];
			);
		) else (			
			shortcutvar.getDotValue[x,i];
		);
	};
 	
 	var addOptimised:=method[] optimisedInBaseC.aadd[BaseC];
 	
 	var checkAlreadyOptimised:=method[]
 	{
 		
 		if (optimisedInBaseC==null) optimisedInBaseC:=new ArrayList[];
 		var itsy:=optimisedInBaseC.agetiterator[];
 		while (itsy.hasNext[])
 		(
 			if ((itsy.next[]).getdata[]==BaseC) return true;
 		);	
 		return false;
 		
 	};
 	
 	var getDeclaredType:=method[] declaredtype;
 	var setDeclaredType:=method[x] 
 	(
 		if (declaredtype==null)
 		(
 			declaredtype:=x;
 		) else (
 			throw error "The declared type is already set - can not be overwritten";
 		);
 	);
 	var retrieveMethodArgs:=method[x] return x;
 	var checkExpression:=method[] att checkVariable[];
 	var checkVariable:=method[] 
 	(
 		if (shortcutvar==null)
 		(
 		// gives variable a UID 		
 			if (myID==null)
 			(
 				myID:=totalid;
 				totalid:=totalid + 1;
 			);
 		) else (
 			shortcutvar.checkVariable[];
 		);
 	);
 	var checkAssignment:=method[] checkVariable[]; 
 	var getTy:=method[]
 	( 	
 		//storedtype.display[];
 		try
 		(	 	
 			return (getCurrentType[]).clone[];
 		) catch "" (
 			return getstoredtype[];	
 			/*
 				As moment should never reach this with current semantics - but might use it. e.g. var record.....; var s:=s::record; will set type s to be a record etc.. where this is needed
 			*/
 		);
 	);
 	var setshortcut:=method[x] shortcutvar:=x;
 	var getshortcut:=method[] return shortcutvar;
 	var ismethod:=method[] false;
 	
 	var isShortCut:=method[] return (!(shortcutvar==null));

 	var generateCommunicationIndex:=method[]
 	( 		
 		if (isTypeVar[]==true) errors.typevarmisuseError[];
 		if (shortcutvar==null)
 		(
 			output.add["&"];
 			output.add[name];
 		) else (
 			shortcutvar.generateCommunicationIndex[];
 		);
 	);
 	
 	var generateCode:=method[]
 	{
 		if (isTypeVar[]==true) errors.typevarmisuseError[];
 		if (isPointer[]==true) storedtype.checkSharedSize[];
 		if (shortcutvar==null)
 		( 			
 			var deccheck;
 			if (myID==null)
 			(
 				deccheck:=name;
 			) else (
 				deccheck:=myID;
 			);	 	 		
 			var rt; 			
 			if ((!(storedtype==null)) && ((output.isDeclaration[deccheck])==false)  && (isPointer[]==false))
 			( 	 				
 				storedtype.setVariable[this]; 				
 				rt:=storedtype.generateDeclaration[]; 	 							
 				scopeinfo.addVar[this];
 				if ((rt!=true) && (rt!=2)) output.add[" "];
 			); 			
 			if (!(storedtype==null))
 			(
 				output.addDeclaration[deccheck];
 				if ((rt!=true) && (rt!=2)) generateName[]; 				
 				// next two lines check if its an array - if so return the fact that not using all of indexex (important in assignment)
 				if (!(rt==null)) return rt;
 				var test:=storedtype.getSizeIndex[0];
 				if !(test==null) return 12;
				return rt; 				
 			) else (
 				output.ignoretillnewline[];
 				// if stored type is null then dont generate anything!
 			);
 		) else (
 			// no declaration 			
 			if (myID==null)
 			(
 				deccheck:=name;
 			) else (
 				deccheck:=myID;
 			);
 			if ((output.isDeclaration[deccheck])==false)
 			(
 				output.addDeclaration[deccheck];
 			) else (
 				shortcutvar.generateCode[];
 			);
 		);
 	};
 	
 	var hasBeenDeclared:=method[]
 	(
 		if ((!(storedtype==null)) && ((output.isDeclaration[getDeclarationChecker[]])==false)) return false;
 		return true;
 	);
 	
 	var getDeclarationChecker:=method[]
 	(
 		if (shortcutvar==null)
 		(
 			if (myID==null)
 			(
 				return name
 			) else (
 				return myID;
 			);
 		) else (
 			shortcutvar.getDeclarationChecker[];
 		);
 	);
 	
  	var generateDeclaration:=method[] storedtype.generateDeclaration[];
  	
  	var generateMPIDeclaration:=method[] storedtype.generateMPIDeclaration[];
 	
 	var generateMethodProtoParam:=method[]
 	{
 		if (isTypeVar[]==true) errors.typevarmisuseError[];
 		if (shortcutvar==null)
 		(
 			var storedcoretype:=storedtype.getCoreType[]; 		
 			output.addMethodProto[storedcoretype.getDeclaration[]]; 						 						 			
 			var numstars:=storedtype.getMethodStar[];
 			var i:=0;
 			for i from 0 to numstars - 1
 			(
 				output.addMethodProto[" * "];
 			);
 			if (isCpointer[] ==false)  output.addMethodProto[" * "];
 		) else (
 			shortcutvar.generateMethodProtoParam[];
 		);
 	};
 	
 	var getDeclaration:=method[]
 	{
 		// this is called from protoparam and methodparam to get the type to include in C method declarations
 		// will try to get the decl value from coherced type, if nothing will default to name
 		// for record types and native types atm
 		if (shortcutvar==null)
 		(
 			if (!(storedtype==null))
 			(
 				var decl:=storedtype.getDeclaration[];
 				if (!(decl==null)) return decl;
 			);
 			return getName[];
 		) else (
 			shortcutvar.getDeclaration[];
 		);
 	};
 	
 	var generateMethodParam:=method[]
 	{
 		if (isTypeVar[]==true) errors.typevarmisuseError[];
 		if (shortcutvar==null)
 		(
			if (isCpointer[]==false) extrastar:=true;
 			var storedcoretype:=storedtype.getCoreType[];
 			output.add[storedcoretype.getDeclaration[]];	
			var numstars:=(storedtype.getMethodStar[]);
 			var i:=0;
 			output.add[" "];
 			for i from 0 to numstars - 1
 			(
 				output.add[" * "];
 			);
 			
 			if (extrastar==true) output.add[" * "];
 			output.add[name];
 			storedtype.declarationDone[];
 			output.addDeclaration[getDeclarationChecker[]];
 		) else (
 			shortcutvar.generateMethodParam[];
 		);
 	};
 	var isCpointer:=method[]
 	(
 		if (shortcutvar==null)
 		(
 			if (extrastar==true)
 			(
 				return true;
 			) else (
 				return storedtype.isCpointer[];
 			);
 		) else (
 			return shortcutvar.isCpointer[];
 		);
 	);
 	
 	var generateName:=method[] 
 	(
 		checkDirty[];
 		if (isTypeVar[]==true) errors.typevarmisuseError[];
 		if (shortcutvar==null)
 		( 			
 			if (isPointer[]==true)
 			(
 				getPointer[].generateName[];
 			) else (
 				if (extrastar==true)
 				(
 					output.add["(*"];
 					output.add[name];
 					output.add[")"];
 				) else (
 					output.add[name];
 				);
 			);
 		) else (
 			shortcutvar.generateName[];
 		);
 	);
 	
 	var generateAccess:=method[x,i] 
 	( 		
 		if (isTypeVar[]==true) errors.typevarmisuseError[];
 		if (shortcutvar==null)
 		(
 			if (!(storedtype==null)) 
 			(
 				 //if (isPointer[]==true) storedtype.generateDynamicSizeCheck[];
 				storedtype.setVariable[this];
 				return storedtype.generateAccess[x,i];
 			);
 		) else (
 			shortcutvar.generateAccess[x,i];
 		);
 	);
 	
 	var generateMethodInvoke:=method[x] 
 	{ 		
 		if (isTypeVar[]==true) errors.typevarmisuseError[];
 		if (shortcutvar==null)
 		(
 			generateName[];
 			if (x==null)
 			( 				
 				storedtype.generateMethodInvoke[new stack[]];
 			) else (
 				storedtype.generateMethodInvoke[x];
 			);
 		) else (
 			shortcutvar.generateMethodInvoke[x];
 		);
 	}; 	
 	
 	var optimiseMethodInvoke:=method[x] 
 	{ 		
 		if (shortcutvar==null)
 		( 			
 			//if (isPointer[]==true) storedtype.checkSharedSize[];
 			if (x==null)
 			( 				
 				storedtype.optimiseMethodInvoke[new stack[]];
 			) else (
 				storedtype.optimiseMethodInvoke[x];
 			);
 		) else (
 			shortcutvar.optimiseMethodInvoke[x];
 		);
 	};
 	
 	var generatePrint:=method x
 	{ 		
 		if (isTypeVar[]==true) errors.typevarmisuseError[];
 		if (shortcutvar==null)
 		(
 			if (!(storedtype==null))
 			(
 				storedtype.generatePrint[];
 			); 			
 			var args:=0;
 			try
 			(	
 				x[0];
 				args:=1;
 			) catch "Index out of range in array reading!" (
 				skip;
 			);
 			return true;
 		) else (
 			shortcutvar.generatePrint[];
 		);
 	};
 	
 	var generateAssignment:=method[x,i] 
 	( 		
 		if (isTypeVar[]==true) errors.typevarmisuseError[];
 		if (shortcutvar==null)
 		(
 			if (!(storedtype==null)) 
 			( 				
 				//if (isPointer[]==true) storedtype.generateDynamicSizeCheck[];
 				storedtype.setVariable[this];
 				storedtype.generateAssignment[x,i];
 			);
 		) else (
 			shortcutvar.generateAssignment[x,i];
 		);
 	);
 	
 	var optimiseAssignment:=method[x,i] 
 	(
 		if (shortcutvar==null)
 		(
 			if (!(storedtype==null)) 
 			( 				
 				//if (isPointer[]==true) storedtype.checkSharedSize[];
 				storedtype.setVariable[this];
 				storedtype.optimiseAssignment[x,i];
 			);
 		) else (
 			shortcutvar.optimiseAssignment[x,i];
 		);
 	);
 	
 	var optimiseAccess:=method[x,i] 
 	( 		
 		if (shortcutvar==null)
 		(
 			if (!(storedtype==null)) 
 			(
 				//if (isPointer[]==true) storedtype.checkSharedSize[];
 				storedtype.setVariable[this]; 	
 				storedtype.optimiseAccess[x,i];
 			);
 		) else (
 			shortcutvar.optimiseAccess[x,i];
 		);
 	);
 	
 	var setMethodInvokeValue:=method[argstopass,x]
 	{ 		
 		if (shortcutvar==null)
 		(
 			if (!(storedtype==null))
 			(
				storedtype.methodinvokestore[argstopass,x];
			);
		) else (
			shortcutvar.setMethodInvokeValue[argstopass,x];
		);
 	};
 	
 	var getMethodInvokeValue:=method[argstopass]
 	(
 		if (shortcutvar==null)
 		(
 			if (!(storedtype==null))
 			( 	
 				return storedtype.methodinvokeget[argstopass];	//what ever it is		
			);
		) else (
			shortcutvar.getMethodInvokeValue[argstopass];
		);
 	);
 	
 	var eval:=method[]
 	{
 		/*
 			This is for when a variable has been defined as a method and then called
 			var f:=method[] etc.....
 			f[]; MethodInvoke will call eval on it, which is this in this case
 			also ref to type and fn library
 		*/
 		return new dummyfn[];
 	};
 	
 	var setstoredtype:=method[x]
	(
		if (shortcutvar==null)
 		(
 			storedtype:=x; 			
 			storedtype.setVariable[this];
 			if (declaredtype==null) declaredtype:=x;
 		) else (
 			shortcutvar.setstoredtype[x];
		);
	);
	
	var getName:=method[]
	(
		if (shortcutvar==null)
 		(
 			return name; 			
 		) else (
	 		return shortcutvar.getName[];
	 	);
	);	
	
	var getstoredtype:=method[]
	(
		if (shortcutvar==null)
 		(
	 		return storedtype;
 		) else (
	 		return shortcutvar.getstoredtype[];
	 	);
	);
 	
 	var isEmpty:=method[] 
 	( 
 		if (shortcutvar==null)
 		(
	 		return storedval==null;
 		) else (
 			return shortcutvar.isEmpty[]; 			
 		);
 	);
 	
 	var setValue:=method[toset]
 	(
		if (shortcutvar==null)
 		(
 			/*
 			print "store ";
 			print name;
 			print toset;
 			print "\n";
 			*/
	 		storedval:=toset; 	
 		) else (
 			shortcutvar.setValue[toset];
 		);
 	);
 	
 	var isavariable:=method[]
 	(
 		if (shortcutvar==null)
 		(
 			return true;
 		) else ( 			
 			return shortcutvar.isavariable[];
 		);
 	);
 	

 	var getCurrentType:=method[] 
 	( 		 		
		/*
			Have modified this. Previously, if storedval had a value then returned the
			type of that, which was fine and good.
			BUT when used type cohercsion, it modified the type but not the value and
			the other way round - when had a specific complex type and then assigned value
			it overwrote the type. Therefore settled for this
		*/
		if (shortcutvar==null)
 		( 		
	 		if (storedtype==null)
			(		
 				if (storedval :: Range)
 				(
 					return storedval;
 				) else ( 	
 					return storedval.getType[];
 				);
 			) else ( 				 				
 				if (storedtype.getReturnType[]==null)
 				( 	
 					return storedtype;
 				) else ( 		 					
 					return storedtype;//.getReturnType[];
 				);
 			);	
 		) else (
 			return shortcutvar.getCurrentType[];
 		);
 	);
 	
 	var check:=method[x] 
 	{
 		/*
 			At the moment only used with record types, as a variable is an instance
 			of type record, therefore, getCurrentType actually gets this! and ref
 			to this check method.
 			
 			NOTE 23/8/2007 - this is called if have a variable to a record type, then the type system will call check on this
 			ONLY works if x is pubstaticvariable or is null
 		*/
 		var xx:=x;
 		//print x.check[Null];
 		//print name;
 		if (!(x.check[Null]))	// if x is pubstaticvar (as can be) then will call this method again, then return to here
 		(
 			//print x.getType[];
 			//print x.getName[];
 			xx:= (x.getstoredtype[]);
 		);
 		return (getstoredtype[]).check[xx];
 	};
 		
 	var getValue:=method[]
 	( 		
 		/*
 			Here did test for range, if so return storedval else return new range
 			but this is not needed I dont think - if its a range then it will already
 			be in that form. If not then we just want to return it
 		*/
 		if (shortcutvar==null)
 		(
 			return storedval; 			
 		) else (
 			return shortcutvar.getValue[];
 		);
 	); 	
 );/*
File created 21/4/2008 by Nick Brown
*/

var inclass SemUserExp2:= class (superclass.SemUserExp2) 
(
	 name:= "typevar";
	 var eval:=method[] att start[];
     var checkParallel:=method[] e.setTypeVar[true];
     var checkSequential:=method[] checkParallel[];
     var checkExpression:=method[] errors.SExpressionError[];
     var generateCode:=method[] skip;
);/*
File created 20/6/2007 by Nick Brown
*/
var inclass AttributeVariable:= class (superclass.AttributeVariable) 
(
	var dynamic thistype;
	var getCurrentType:=method[] return new usermethod;
	var getName:=method[] name;
	var generateName:=method[] output.add[name];
	var setMethodType:=method[x] thistype:=x;
	var getMethodType:=method[] thistype;
);/*
	This class is used to represent the atoms of a method invoke, the atoms being in an array. The class performs a number of actions such as calculate size etc...
	First written 10/4/07 by Nick Brown
*/
var inclass SemCompositeExp:=class (superclass.SemCompositeExp)
(
	var dynamic vsize:=null;
	
	var getSize:=method[]
	(
		if (vsize==null)
		(
			return -1;
		) else (
			return (vsize + 1);
		);
	);
	
	var checkParallel:=method[]
	{
		setsize[];
		if (!(vsize==null))
		(
			functioncallnest:=functioncallnest + 1;
			var i;			
			for i from 0 to vsize
			(
				v[i].checkParallel[];	
			);
			functioncallnest:= functioncallnest - 1;
		);
	};	
	
	var checkSequential:=method[]
	(
		checkParallel[];
	);
	
	var setParamUnknown:=method[]
	{
		setsize[];
		var i;
		for i from 0 to vsize
		(
			if (v[i].isavariable[]) v[i].setValue[new unknown[]];
		);
	};
	
	var generateMethodProtoParam:=method[]
	{
		setsize[];
		if (!(vsize==null))
		(
			var i;
			var needsdot:=false;
			for i from 0 to vsize
			(
				if (!((v[i].getstoredtype[]) :: record))
				(
					if (needsdot==true)
					(
						output.addMethodProto[","];
					) else (
						needsdot:=true;
					);
					v[i].generateMethodProtoParam[];
				);
			);
		);
	};
	
	var generateMethodParam:=method[]
	{
		setsize[];
		if (!(vsize==null))
		(
			var i;
			var needsdot:=false;
			for i from 0 to vsize
			(
				if (!((v[i].getstoredtype[]) :: record))
				(
					if (needsdot==true)
					(
						output.add[","];
					) else (
						needsdot:=true;
					);
					v[i].generateMethodParam[];
				);
			);
		);
	};
		
	var checkExpression:=method[]
	{
		setsize[];
		var i:=0;	
		functioncallnest:=functioncallnest + 1;		
		for i from 0 to vsize
		(						
			v[i].checkExpression[];						
		);
		functioncallnest:=functioncallnest - 1;
	};
	
	var setsize:=method[]
	{
		if (vsize==null)
		(
		vsize:=0;
		var contine:=true;		
		while (contine)
		(			
			try
			(
				var x:=v[vsize];
				vsize:=vsize + 1;
			) catch "" (			
				contine:=false;
			);
		);
		vsize:=vsize - 1;
		);
	};
	
	var getCurrentType:=method[] 
	(
		return (v[0]).getCurrentType[];
	);
	
	var getValue:=method[]
	{
		setsize[];
		var toret:=new stack[];
		var i:=0;
		for i from 0 to vsize
		(			
			toret.push[(v[i]).getValue[]];			
		);
		return toret;
	};
	
	var generateCode:=method[]
	{
		/*
			This method is called from the type when performing generateCode on a [] index rather than # index			
		*/	
		setsize[];
		var i;
		for i from 0 to getSize[] - 1
		(
			v[i].generateCode[];
		);
	};
	
	var get:=method[x] return v[x];
);/*
	File created 10/5/2007 by Nick Brown
	This is used by OpDot and SemMethodInvoke which use it to forward variable
	methods :)
	SemVariableForward
*/
var inclass SemExecutable:=class (superclass.SemExecutable)
(	
	var setUsesTypeInference:=method[x] e1.setUsesTypeInference[x];
 	var getUsesTypeInference:=method[] e1.getUsesTypeInference[];
	var setUsesModType:=method[x] e1.setUsesModType[x];
	var setPointer:=method[x] e1.setPointer[x];
	var isPointer:=method[] e1.isPointer[];
	var getPointer:=method[] e1.getPointer[];
	var setDirty:=method[x] e1.setDirty[x];
 	var getUsesModType:=method[] return e1.getUsesModType[];
	var getstoredtype:=method[] return e1.getstoredtype[];
	var setInitialType:=method[x] e1.setInitialType[x];
 	var getInitialType:=method[] e1.getInitialType[];
	var isEmpty:=method[] return e1.isEmpty[];	
	var isCpointer:=method[] e1.isCpointer[];
	var ismethod:=method[] return e1.ismethod[];
	var getName:=method[] return e1.getName[];
	var isavariable:=method[] return e1.isavariable[];
	var setstoredtype:=method[x] e1.setstoredtype[x];
	var generateAssignment:=method[x,m] e1.generateAssignment[x,m];
	var generateAccess:=method[x,i] e1.generateAccess[x,i];
	var optimiseAssignment:=method[x,m] e1.optimiseAssignment[x,m];
	var optimiseAccess:=method[x,i] e1.optimiseAccess[x,i];
	var isShortCut:=method[] e1.isShortCut[];
	var generateCommunicationIndex:=method[] e1.generateCommunicationIndex[];
	var generateMethodProtoParam:=method[] e1.generateMethodProtoParam[];
	var generateMethodParam:=method[] e1.generateMethodParam[];
	var generateName:=method[] e1.generateName[];
	var checkAlreadyTypeChecked:=method[] e1.checkAlreadyTypeChecked[];
	var addTypeCheck:=method[] e1.addTypeCheck[];
	var hasBeenDeclared:=method[] e1.hasBeenDeclared[];
	var checkAlreadyOptimised:=method[] e1.checkAlreadyOptimised[];
	var addOptimised:=method[] e1.addOptimised[];
	var getDeclarationChecker:=method[] e1.getDeclarationChecker[];
	var checkAlreadySyntaxChecked:=method[] e1.checkAlreadySyntaxChecked[];
	var addSyntaxCheck:=method[] e1.addSyntaxCheck[];
	var generateMethodInvoke:=method[x] e1.generateMethodInvoke[x];
	var getDotValue:=method[x,i] e1.getDotValue[x,i];
	//var getDotValue:=method[x] e1.getDotValue[x];
);/*
	This class inherits VariableForward, which provides pubstaticvariable fwd methods
*/
	
var inclass SemOpDot:=class (superclass.SemOpDot)
(
	var dynamic thevalue;
	var checkParallel:=method[] checkVariable[];
	var checkSequential:=method[] checkVariable[];
	var checkVariable:=method[] att checkExpression[];
	var checkExpression:=method[]
	(		
		e1.checkVariable[];		
	);

	var setValue:=method[x] 
	{
		var actualrecord:=getActualRecord[];		
		//print actualrecord.getType[];
		//actualrecord:=actualrecord.clone[];
		actualrecord.setDotValue[e2.name,x];
		e1.setValue[actualrecord];				
	};
	
	var optimiseMethodInvoke:=method[x] e1.optimiseMethodInvoke[x];
	
	var getValue:=method[] 
	{
		//var actualrecord:=getActualRecord[];
		var val:= e1.getDotValue[e2.name,null];
		if (val==null)
		(
			throw error "Dot product does not exist!";
		) else (
			thevalue:=val;
			/*
			print "Wants dot val";
			print e2.name;
			print " ";
			print val;
			print "\n";
			*/
			return val
		);
		
	};
	
	/*
		WARNING - there is an issue here. in getValue it gets the value of the dot thing - what ever it is.
		In generate code it also gets the value and outputs it. Prob is, in processgroup at optimise stage (getvalue)
		there is no value yet, but at generatecode stage there is a value - therefore the caller to this (a loop or whatever)
		thinks during optimisation that the value is unknown - whereas during generateCode the value is known
		
		Is there a problem with this (other than no optimisation of course)?? I do not think so, but not sure
		also this might have other effects yet to be determined;
	*/
	
	var generateCode:=method[]
	{		
		
		thevalue:=e1.getDotValue[e2.name,null];
		
		if (!(thevalue::unknown))
		(
			output.add[thevalue];
		) else (
			e1.generateCode[];
			output.add["."];
			output.add[e2.name];
		);		
	};
	
	var getActualRecord:=method[]
	{
		// gets the currenttype - assume this is a complex type so get the variable
		var thevarinquestion:=e1.getCurrentType[];	// get variable rep			
		var actualrecord:=thevarinquestion;
		/*
			In this case, depends - if have array[complex,etc... then need to get storedtype
			else, if have complex :: etc... then we dont as this is already instatiated for syntax check
		*/			
		if (thevarinquestion.isavariable[])
		(
			actualrecord:=thevarinquestion.getstoredtype[];	// get record representation
		);
		return actualrecord;
	};
	 						
	var getCurrentType:=method[] 
	{
		var actualrecord:=getActualRecord[];
		//print actualrecord.getType[];
		var theval:=actualrecord.getdottype[e2.name];
		if (theval==null)
		(	
			throw error "Dot product does not exist!";
		) else (
			return theval;
		);
	};
	
	//var isCpointer:=method[] true;
	
	var generateAccess:=method[x,i] if !(e2.name="low" || e2.name="high" || e2.name="x" || e2.name="y" || e2.name="blocks") e1.generateAccess[x,i];
	var optimiseAccess:=method[x,i] if !(e2.name="low" || e2.name="high" || e2.name="x" || e2.name="y" || e2.name="blocks") e1.optimiseAccess[x,i];
);/*
File created 18/9/2007 by Nick Brown
*/

var inclass SemEnvExp:=class (superclass.SemEnvExp)
(
	var dynamic oldphase;
	//var eval := method [] start[];
	var dynamic oldbasec;
	var basecnts:=1;
	var dynamic myid;
	var checkParallel:=method[]
	(
		checkSequential[];		
	);
	
	var checkSequential:=method[]
	{		
		myid:=basecnts;
		basecnts:=basecnts + 1;
		oldbasec:=BaseC;
		BaseC:=myid;
		oldphase:=SemExpPhase;
		SemExpPhase:=1;
		att eval[];
		BaseC:=oldbasec;
		SemExpPhase:=oldphase;	
	};
	
	var checkType:=method[]
	(
		oldbasec:=BaseC;
		BaseC:=myid;
		oldphase:=SemExpPhase;
		SemExpPhase:=2;		
		att eval[];
		SemExpPhase:=oldphase;
		BaseC:=oldbasec;
	);
	
	var optimise:=method[]
	(
		oldbasec:=BaseC;
		BaseC:=myid;
		oldphase:=SemExpPhase;
		SemExpPhase:=3;
		att eval[];
		SemExpPhase:=oldphase;
		BaseC:=oldbasec;
	);
	
	var generateCode:=method[] 
	(
		oldbasec:=BaseC;
		BaseC:=myid;
		oldphase:=SemExpPhase;
		SemExpPhase:=4;
		att eval[];		
		SemExpPhase:=oldphase;
		BaseC:=oldbasec;
	);
);/*
	Starts off the whole process
	First written 10/4/07 by Nick Brown
*/
var inclass SemExp:=class(superclass.SemExp) 
(
	var isroot:=true;
	var oldvars:=new stack[];
	var eval:=method[]
	(						
		(superclass.eval)[];
	);
	
	
	var generateTimeStamp:=method[]
	{
		/*
			Java specific class to generate the time and date of compilation
		*/
		var javadateclass:=new Jclass("java.util.GregorianCalendar");		
		print "//Compiled on "; 
		print javadateclass.get[5];	// need to use the number as flex doesnt allow for underscore
		print "/";
		print javadateclass.get[javadateclass.MONTH] + 1;
		print "/";
		print javadateclass.get[javadateclass.YEAR];
		print " at ";
		print javadateclass.get[11];
		print ":";
		if (javadateclass.get[javadateclass.MINUTE] < 10) print "0";
		print javadateclass.get[javadateclass.MINUTE];
		print ":";
		if (javadateclass.get[javadateclass.SECOND] < 10) print "0";
		print javadateclass.get[javadateclass.SECOND];
		print " with Mesham V0.41 beta\n";
	};
	
	var rootStart:=method[]
	{
		generateTimeStamp[];
		dependency.addinclude["\"mpi.h\""];
		dependency.addinclude["<mesham.h>"];
		dependency.addCompileString["-lmesham"];	
		print "//Syntactic Check";		
		att checkParallel[];		
		print " - OK\n";
		print "//Type Check";
		att checkType[];
		print " - OK\n";
		print "//Static Optimise and Check";
		att optimise[];
		print " - OK\n";
		print "//Number of Processes - ";
		print totalprocesses;
		print " with ";
		print syncs.getNumberOfSyncs[];
		print " Synchronisation Points";
		print "\n\n";
		dependency.generateIncludes[];
		print "\n";
		print "#define null NULL\n#define false 0\n#define true 1\n\n";
		print "int myrank, numberofprocesses, MESHargc;\n";	
		print "char ** MESHargv;\n";
		var i;
		for i from 0 to (totalprocesses)
		(
			output.addText[new text[]];
		);
		att generateCode[];
		(output.globaldeclars).display[];
		displayCode[];
		generateParallelCaller[];
		generateMainMethod[];
		warnings.display[];
		dependency.generateCompileString[];
		print "//mpirun -np ";
		print totalprocesses;
		print " ./output\n";
	};
	
	var setUpVars:=method[]
	{
		oldvars.push[variabletypes];
		variabletypes:=new HashMap[];	
	};
	
	var revertVars:=method[]
	{
		if (!(variabletypes == null))
        (            		
            var it:=variabletypes.hgetiterator[];            		
            while (it.hasNext[])
            (            			            		
            	var no:=it.next[];            	
            	var stid:=((no.gethash[]).getstoredtype[]).getSharedPoolID[false];
            	(no.gethash[]).setstoredtype[(no.getdata[]).clone[]];         
            	((no.gethash[]).getstoredtype[]).setSharedPoolID[stid];
            );            	
        );
		variabletypes:=oldvars.pop[];
	};
	
	// should start be dynamic? possibly due to the holding in temp var of the old scope info
	var start:=method [] 
	{				
		if (isroot==true)
		(
			scopeinfo:=new scopeinfoholder[];
			isroot:=false;
			rootStart[];
		) else (		
			if (SemExpPhase==1 || SemExpPhase==2 || SemExpPhase==3 || SemExpPhase==4)
			(			
				setUpVars[];				
				att checkParallel[];												
				revertVars[];
			);	
			if (SemExpPhase==2 || SemExpPhase==3 || SemExpPhase==4)
			{
				var oldtypeblockenabled:=typeblockenabled;
				var oldtotal:=holdtotal;
				if (SemExpPhase==3 || SemExpPhase==4) 
				(
					holdtotal:=true;
					typeblockenabled:=true;
				);
				setUpVars[];
				att checkType[];
				revertVars[];
				holdtotal:=oldtotal;
				typeblockenabled:=oldtypeblockenabled;
			};	
			if (SemExpPhase==3 || SemExpPhase==4)
			{				
				var oldoptimiseblockenabled:=optimiseblockenabled;
				var oldignoreinterference:=ignoreinterference;
				if (SemExpPhase==4) 
				(
					optimiseblockenabled:=true;
					syncs.hold[];
					ignoreinterference:=true;
				);
				setUpVars[];				
				att optimise[];	// used to be att optimise - but caused problems
				revertVars[];		
				if (SemExpPhase==4) syncs.unhold[];
				ignoreinterference:=oldignoreinterference;
				optimiseblockenabled:=oldoptimiseblockenabled;
			};
			
			/*
        	In both these branches, it checks a list of variables and initial types - and resets the variables to the initial types.
        	This is so that, if the variable changes in the par bit, it will be reset before the next process's run through.
        	
        	Has to be here - as when calls generate code in the block, will delve into here and do the generation rather than recall the par block
        	*/
				
			if (SemExpPhase==4)
			(
				var oldscopeinfo:=scopeinfo;
				scopeinfo:=new scopeinfoholder[];	
				setUpVars[];
				att generateCode[];
				revertVars[];			
			//	output.add["MESHgarbagecollect();"];
				output.newline[];	
				scopeinfo.destroyAll[];				
				scopeinfo:=oldscopeinfo;
			);	
		);
	};
	
	var displayCode:=method[]
	{
		output.displayMethodProto[];
		var counter:=0;
		//var i:=processesText.agetiterator[];
		for counter from 0 to totalprocesses - 1
		(
			print "void processor";
			print counter;
			print "()\n{\n";
			counter:=counter + 1;
			output.display[counter];
			print "}\n";
		);
		output.displayMethods[];
	};
	
	var generateMainMethod:=method[]
	(
		print "int main(int argc, char * argv[])\n{\n";
		print "MPI_Init(&argc,&argv);\n";
		print "MESH_Init(410,110);\n";
		print "MESHargc=argc;\n";
		print "MESHargv=argv;\n";
		print "MPI_Comm_rank(MPI_COMM_WORLD, &myrank);\n";
		print "MPI_Comm_size(MPI_COMM_WORLD,&numberofprocesses);\n";
		print "if (MESHcheckstartup(";
		print totalprocesses;
		print ",numberofprocesses,argc,argv)==1)\n{\n";
		print "init();\n";
		if (sharedpoolsizeneeded > 0) 
		(
			print "MESHcreatePool(";
			print sharedpoolsizeneeded;
			print ");\n";
		);
		print "MESHsetUpCommErrHandler(MPI_COMM_WORLD);\n";
		print "processes[myrank]();\n";
		print "}\nMPI_Finalize();\n";
		print "return 0;\n";
		print "}\n\n";
	);
	
	var generateParallelCaller:=method[]
	{
		print "\ntypedef void (*Process)();\n";
		print "Process processes[";
		print totalprocesses;
		print "];\n";
		print "\nvoid init()\n{\n";
		var i;
		for i from 0 to (totalprocesses - 1)
		(
			print "processes[";
			print i;
			print "] = &processor";
			print i;
			print ";\n";
		);	
		
		for i from 0 to initfntext.getsize[] - 1
		(
			print initfntext.aget[i];
		);
		print "}\n\n";
	};

 	// Syntactic Check
 	var checkParallel:=method[] errors.SParallelError[];
 	var checkSequential:=method[] errors.SSequentialError[]; 
 	var checkAssignment:=method[] errors.SAssignmentError[];
 	var checkExpression:=method[] errors.SExpressionError[];
 	var checkVariable:=method[] errors.SVariableError[];
 	var checkConstant:=method[] errors.SConstantError[]; 	
 	
 	// Type Check
 	var checkType:=method[] skip;

	// Optimise and check
 	var optimise:=method[] skip;
););
