Przeglądaj źródła

gehler in conflict detection behoben

Kolja Strohm 6 lat temu
rodzic
commit
bceec03912

+ 3 - 1
src/animation/AnimatedAlgorithm.java

@@ -8,6 +8,7 @@ import javax.swing.JFrame;
 import javax.swing.JTree;
 import javax.swing.SwingUtilities;
 
+import animation.Memory.MemoryType;
 import animation.PseudoCodeNode.CodeStatus;
 import animation.StackFrame.FrameType;
 import graph.LayeredGraphNode;
@@ -28,7 +29,7 @@ public abstract class AnimatedAlgorithm extends Thread implements AlgorithmStage
         this.view = view;
         root = null;
         mem = new Memory();
-        mem.declare( "graph", graph, true );
+        mem.declare( "graph", graph, MemoryType.GLOBAL );
         mem.addFrame( new StackFrame( FrameType.FUNCTION ) );
         activeFunction = new Stack<PseudoCodeNode>();
     }
@@ -84,6 +85,7 @@ public abstract class AnimatedAlgorithm extends Thread implements AlgorithmStage
                     status = current.backwardStepOver( mem );
                     break;
                 }
+                System.out.println( "Stack Frames: " + mem.getSize() );
             } catch (InterruptedException e) {
                 e.printStackTrace();
                 return;

+ 147 - 42
src/animation/Memory.java

@@ -6,6 +6,14 @@ import animation.StackFrame.FrameType;
 
 public class Memory {
 
+    public enum MemoryType
+    {
+        GLOBAL,
+        LOCAL,
+        CURRENT
+    }
+    
+    private StackFrame current;
     private StackFrame global;
     private Stack< StackFrame > stack;
     
@@ -13,6 +21,17 @@ public class Memory {
     {
         stack = new Stack<StackFrame>();
         global = new StackFrame( FrameType.FUNCTION );
+        current = null;
+    }
+    
+    public int getSize()
+    {
+        return stack.size();
+    }
+    
+    public void setCurrent( StackFrame frame )
+    {
+        this.current = frame;
     }
     
     public void addFrame( StackFrame frame )
@@ -25,24 +44,54 @@ public class Memory {
         return stack.pop();
     }
     
-    public <T> void declare( String name, T value, boolean global )
+    public <T> void declare( String name, T value, MemoryType type )
     {
-        if( global )
-            this.global.declare( name, value );
-        else
+        switch( type )
         {
+        case GLOBAL:
+            this.global.declare( name, value );
+            break;
+        case CURRENT:
+            if( current != null )
+                current.declare( name, value );
+            break;
+        case LOCAL:
         	if( stack.size() == 0 )
         		return;
             stack.peek().declare( name, value );
+            break;
         }
     }
     
-    public <T> void write( String name, T value, boolean global )
+    public <T> void write( String name, T value, MemoryType type )
     {
-        if( global )
-            this.global.set( name, value );
-        else
+        switch( type )
         {
+        case GLOBAL:
+            this.global.set( name, value );
+            break;
+        case CURRENT:
+            if( current != null )
+            {
+                int index = stack.size() - 1;
+                while( index >= 0 && stack.get( index ) != current ) {
+                    index--;
+                }
+                if( index < 0 )
+                    break;
+                while( index >= 0 ) {
+                    StackFrame stackF = stack.get( index-- );
+                    if( stackF.isDefined( name ) )
+                    {
+                        stackF.set( name, value );
+                        return;
+                    }
+                    if( stackF.getType() == FrameType.FUNCTION )
+                        break;
+                 }
+            }
+            break;
+        case LOCAL:
         	int index = stack.size() - 1;
         	while( index >= 0 ) {
         	   StackFrame stackF = stack.get( index-- );
@@ -57,54 +106,110 @@ public class Memory {
         }
     }
     
-    public <T> T read( String name, boolean global )
+    public <T> T read( String name, MemoryType type )
     {
-        if( global )
-            return this.global.get( name );
-        else
+        switch( type )
         {
-        	int index = stack.size() - 1;
-        	while( index >= 0 ) {
-        	   StackFrame stackF = stack.get( index-- );
-        	   if( stackF.isDefined( name ) )
-        		   return stackF.get( name );
-        	   if( stackF.getType() == FrameType.FUNCTION )
-        		   break;
-        	}
-            return null;
+        case GLOBAL:
+            return this.global.get( name );
+        case CURRENT:
+            if( current != null )
+            {
+                int index = stack.size() - 1;
+                while( index >= 0 && stack.get( index ) != current ) {
+                    index--;
+                }
+                if( index < 0 )
+                    break;
+                while( index >= 0 ) {
+                    StackFrame stackF = stack.get( index-- );
+                    if( stackF.isDefined( name ) )
+                        return stackF.get( name );
+                    if( stackF.getType() == FrameType.FUNCTION )
+                        break;
+                 }
+            }
+            break;
+        case LOCAL:
+            int index = stack.size() - 1;
+            while( index >= 0 ) {
+                StackFrame stackF = stack.get( index-- );
+                if( stackF.isDefined( name ) )
+                    return stackF.get( name );
+                if( stackF.getType() == FrameType.FUNCTION )
+                    break;
+             }
         }
+        return null;
     }
     
-    public boolean isSomewhereDefined( String name, boolean global )
+    public boolean isSomewhereDefined( String name, MemoryType type )
     {
-    	if( global )
-    		return this.global.isDefined( name );
-    	int index = stack.size() - 1;
-    	while( index >= 0 ) {
-    	   StackFrame stackF = stack.get( index-- );
-    	   if( stackF.isDefined( name ) )
-    		   return true;
-    	   if( stackF.getType() == FrameType.FUNCTION )
-    		   break;
-    	}
+        switch( type )
+        {
+        case GLOBAL:
+            return this.global.isDefined( name );
+        case CURRENT:
+            if( current != null )
+            {
+                int index = stack.size() - 1;
+                while( index >= 0 && stack.get( index ) != current ) {
+                    index--;
+                }
+                if( index < 0 )
+                    break;
+                while( index >= 0 ) {
+                    StackFrame stackF = stack.get( index-- );
+                    if( stackF.isDefined( name ) )
+                        return true;
+                    if( stackF.getType() == FrameType.FUNCTION )
+                        break;
+                 }
+            }
+            break;
+        case LOCAL:
+            int index = stack.size() - 1;
+            while( index >= 0 ) {
+                StackFrame stackF = stack.get( index-- );
+                if( stackF.isDefined( name ) )
+                    return true;
+                if( stackF.getType() == FrameType.FUNCTION )
+                    break;
+             }
+        }
     	return false;
     }
     
-    public boolean isDefined( String name, boolean global )
+    public boolean isDefined( String name, MemoryType type )
     {
-    	if( global )
-    		return this.global.isDefined( name );
-    	if( stack.size() == 0 )
-    		return false;
-    	return stack.peek().isDefined( name );
+        switch( type )
+        {
+        case GLOBAL:
+            return this.global.isDefined( name );
+        case CURRENT:
+            if( current != null)
+                return current.isDefined( name );
+            return false;
+        case LOCAL:
+            if( stack.size() == 0 )
+                return false;
+            return stack.peek().isDefined( name );
+        }
+    	return false;
     }
     
-    public void undeclare( String name, boolean global )
+    public void undeclare( String name, MemoryType type )
     {
-        if( global )
-            this.global.undeclare( name );
-        else
+        switch( type )
         {
+        case GLOBAL:
+            this.global.undeclare( name );
+            break;
+        case CURRENT:
+            if( current != null )
+                current.undeclare( name );
+            break;
+        case LOCAL:
         	if( stack.size() == 0 )
         		return;
             stack.peek().undeclare( name );

+ 28 - 10
src/animation/PseudoCodeNode.java

@@ -5,6 +5,8 @@ import javax.swing.tree.DefaultMutableTreeNode;
 import javax.swing.tree.MutableTreeNode;
 import javax.swing.tree.TreePath;
 
+import animation.Memory.MemoryType;
+
 /**
  * represents a line of pseudocode
  * @author kolja
@@ -38,6 +40,7 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
     private boolean breakPoint;
     private boolean function;
 
+    private StackFrame childFrame; // the stackframe added from this node
     private int currentCodeLine; // next forward code line
     
     public PseudoCodeNode( String description, JTree tree, CodeLine line, AnimatedAlgorithm alg )
@@ -54,6 +57,7 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
         currentCodeLine = -1;
         code = line;
         function = false;
+        childFrame = null;
     }
     
     public void setController( AnimationController c )
@@ -70,10 +74,12 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
     
     public void writeToStack( Memory m )
     {
-    	m.declare( "_pos" + nodeId, currentCodeLine, false );
-    	m.declare( "_func" + nodeId, function, false );
+    	m.declare( "_pos" + nodeId, currentCodeLine, MemoryType.LOCAL );
+    	m.declare( "_func" + nodeId, function, MemoryType.LOCAL );
+    	m.declare( "_stack" + nodeId, childFrame, MemoryType.LOCAL );
     	currentCodeLine = -1;
     	function = false;
+    	childFrame = null;
     	setSelected( false );
     	if( children == null )
     		return;
@@ -83,8 +89,9 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
     
     public void loadFromStack( Memory m )
     {
-    	currentCodeLine = m.read( "_pos" + nodeId, false );
-    	function = m.read( "_func" + nodeId, false );
+    	currentCodeLine = m.read( "_pos" + nodeId, MemoryType.LOCAL );
+    	function = m.read( "_func" + nodeId, MemoryType.LOCAL );
+    	childFrame = m.read( "_stack" + nodeId, MemoryType.LOCAL );
     	if( children == null )
     		return;
     	for( Object c : children )
@@ -226,9 +233,10 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
      */
     public CodeStatus forwardStep( Memory m )
     {
+        m.setCurrent( childFrame );
         if( currentCodeLine == -1 )
         {
-			if( !m.isDefined( "node_" + nodeId + "_call", false ) )
+			if( !m.isDefined( "node_" + nodeId + "_call", MemoryType.LOCAL ) )
 			{
 				StackFrame tmp = null;
 				if( function )
@@ -240,7 +248,13 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
 	            switch( cf.getStatus() )
 	            {
 	            case ControlFlow.STEP_INTO:
-	            	writeToStack( m );
+	                childFrame = m.removeFrame();
+	                m.addFrame( childFrame );
+	                if( children != null )
+	                {
+    	                for( Object c : children )
+    	                    ((PseudoCodeNode)c).writeToStack( m );
+	                }
 	            	function = true;
 	                switch( stepInto( m ) )
 	                {
@@ -268,7 +282,11 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
 	            	if( function )
 	            	{
 	            		m.addFrame( tmp ); // add old stack frame
-		            	loadFromStack( m ); // load stored variables
+	                    if( children != null )
+	                    {
+	                        for( Object c : children )
+	                            ((PseudoCodeNode)c).loadFromStack( m );
+	                    }
 	                	m.removeFrame(); // remove the stack frame
 	                	setSelected( false );
 	            	}
@@ -276,9 +294,9 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
 	                return CodeStatus.FINISHED;
 	            case ControlFlow.CALL:
 	    			alg.addActiveFunction( cf.getFunction() );
-	    			m.declare( "node_" + nodeId + "_call", cf.getFunction(), false );
+	    			m.declare( "node_" + nodeId + "_call", cf.getFunction(), MemoryType.LOCAL );
 	    			setSelected( false );
-	    			m.declare( "callback", this, true );
+	    			m.declare( "callback", this, MemoryType.GLOBAL );
 	    			switch( cf.getFunction().setSelected( true ) )
 	    			{
 					case CONTINUE:
@@ -306,7 +324,7 @@ public class PseudoCodeNode extends DefaultMutableTreeNode {
 			}
 			else
 			{
-				m.undeclare( "node_" + nodeId + "_call", false );
+				m.undeclare( "node_" + nodeId + "_call", MemoryType.LOCAL );
                 hiddenActionWithoutSideEffects( m );
 				return CodeStatus.FINISHED;
 			}

+ 4 - 3
src/bk/BKNodePlacement.java

@@ -9,6 +9,7 @@ import animation.CodeLine;
 import animation.ControlFlow;
 import animation.Memory;
 import animation.PseudoCodeNode;
+import animation.Memory.MemoryType;
 import codelines.FunctionCall;
 import codelines.FunctionDefinition;
 import graph.LayeredGraphNode;
@@ -71,15 +72,15 @@ public class BKNodePlacement extends AnimatedAlgorithm {
 
 			@Override
 			public ControlFlow runForward(Memory m) {
-				m.declare( "param1", graph, true );
-				if( m.isDefined( "Called", false ) )
+				m.declare( "param1", graph, MemoryType.GLOBAL );
+				if( m.isDefined( "Called", MemoryType.LOCAL ) )
 				{
 					actions.push( (Memory mem) -> {
 						return new ControlFlow( mainFunction );
 					} );
 					return new ControlFlow( ControlFlow.STEP_OVER );
 				}
-				m.declare( "Called", true, false );
+				m.declare( "Called", true, MemoryType.LOCAL );
 				actions.push( (Memory mem) -> {
 					return new ControlFlow( ControlFlow.STEP_OVER );
 				} );

+ 0 - 3
src/bk/BlockCalc.java

@@ -34,9 +34,6 @@ public class BlockCalc implements AlgorithmStage {
         	
 			@Override
 			public ControlFlow runForward(Memory m) {
-				param = m.<LayeredGraphNode>read( "param1", true );
-				m.declare( "graph", param, false );
-				m.declare( "Layers", param.getContainedLayers(), false );
 				return new ControlFlow( ControlFlow.STEP_INTO );
 			}
         	

+ 43 - 45
src/bk/ConflictDetection.java

@@ -11,6 +11,7 @@ import animation.CodeLine;
 import animation.ControlFlow;
 import animation.Memory;
 import animation.PseudoCodeNode;
+import animation.Memory.MemoryType;
 import bk.BKNodePlacement.State;
 import bk.ExtremalLayoutCalc.LayoutType;
 import codelines.DeclareVariable;
@@ -20,6 +21,7 @@ import codelines.FunctionCall;
 import codelines.FunctionDefinition;
 import codelines.IfLoop;
 import codelines.Kommentar;
+import codelines.SetVariable;
 import codelines.WhileLoop;
 import graph.LayeredGraphEdge;
 import graph.LayeredGraphNode;
@@ -41,7 +43,7 @@ public class ConflictDetection implements AlgorithmStage {
 
     @Override
     public PseudoCodeNode createPseudocodeTree(JTree tree) {
-        String vars[] = { "i", "L", "k0", "l", "l1", "k1", "k", "v", "graph", "n" };
+        String vars[] = { "i", "L", "k0", "l", "l1", "k1", "v", "graph", "n" };
         String params[] = { "graph" };
         @SuppressWarnings("serial")
         PseudoCodeNode root = new PseudoCodeNode(TextLayoutHelper.setupPseudoCode("function mark_conflicts( graph )", vars), tree, new FunctionDefinition( params ), alg ) {
@@ -50,29 +52,28 @@ public class ConflictDetection implements AlgorithmStage {
             {
                 ((BKNodePlacement)alg).setState( State.CONFLICTS );
                 
-                if( m.isSomewhereDefined( "l", false ) && m.isSomewhereDefined( "i", false ) && 
-                        m.<Integer>read( "l", false ) < m.<LayeredGraphNode>read( "graph", false).getContainedLayers().get( m.<Integer>read( "i", false ) + 1 ).size() )
-                    m.<LayeredGraphNode>read( "graph", false).getContainedLayers().get(m.<Integer>read( "i", false ) + 1).get(m.<Integer>read( "l", false )).setSelected(null);
+                if( m.isSomewhereDefined( "l", MemoryType.LOCAL ) && m.isSomewhereDefined( "i", MemoryType.LOCAL ) && 
+                        m.<Integer>read( "l", MemoryType.LOCAL ) < m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL).getContainedLayers().get( m.<Integer>read( "i", MemoryType.LOCAL ) + 1 ).size() )
+                    m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL).getContainedLayers().get(m.<Integer>read( "i", MemoryType.LOCAL ) + 1).get(m.<Integer>read( "l", MemoryType.LOCAL )).setSelected(null);
                 
-                if( m.isSomewhereDefined( "i", false ) && m.isSomewhereDefined( "l1", false ) ) {
-                    m.<LayeredGraphNode>read( "graph", false).getContainedLayers().get(m.<Integer>read( "i", false ) + 1).get(m.<Integer>read( "l1", false )).setSelected(null);
+                if( m.isSomewhereDefined( "i", MemoryType.LOCAL ) && m.isSomewhereDefined( "l1", MemoryType.LOCAL ) &&
+                        m.<Integer>read( "l1", MemoryType.LOCAL ) < m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL).getContainedLayers().get(m.<Integer>read( "i", MemoryType.LOCAL ) + 1).size() ) {
+                    m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL).getContainedLayers().get(m.<Integer>read( "i", MemoryType.LOCAL ) + 1).get(m.<Integer>read( "l1", MemoryType.LOCAL )).setSelected(null);
                 }
                 
-                if( m.isSomewhereDefined( "i", false ) && m.isSomewhereDefined( "k0", false ) ) {
-                    m.<LayeredGraphNode>read( "graph", false).getContainedLayers().get(m.<Integer>read( "i", false ) + 1).get(m.<Integer>read( "k0", false )).setSelected(null);
+                if( m.isSomewhereDefined( "i", MemoryType.LOCAL ) && m.isSomewhereDefined( "k0", MemoryType.LOCAL ) && 
+                        m.<Integer>read( "k0", MemoryType.LOCAL ) <  m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL).getContainedLayers().get(m.read( "i", MemoryType.LOCAL )).size()) {
+                    m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL).getContainedLayers().get(m.read( "i", MemoryType.LOCAL )).get(m.<Integer>read( "k0", MemoryType.LOCAL )).setSelected(null);
                 }
                 
-                if( m.isSomewhereDefined( "i", false ) && m.isSomewhereDefined( "k1", false ) ) {
-                    m.<LayeredGraphNode>read( "graph", false).getContainedLayers().get(m.<Integer>read( "i", false ) + 1).get(m.<Integer>read( "k1", false )).setSelected(null);
+                if( m.isSomewhereDefined( "i", MemoryType.LOCAL ) && m.isSomewhereDefined( "k1", MemoryType.LOCAL ) && 
+                        m.<Integer>read( "k1", MemoryType.LOCAL ) < m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL).getContainedLayers().get(m.read( "i", MemoryType.LOCAL )).size() ) {
+                    m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL).getContainedLayers().get(m.read( "i", MemoryType.LOCAL )).get(m.<Integer>read( "k1", MemoryType.LOCAL )).setSelected(null);
                 }
                 
-                if( m.isSomewhereDefined( "i", false ) && m.isSomewhereDefined( "k", false ) ) {
-                    m.<LayeredGraphNode>read( "graph", false).getContainedLayers().get(m.<Integer>read( "i", false ) + 1).get(m.<Integer>read( "k", false )).setSelected(null);
-                }
-                
-                if( m.isSomewhereDefined( "n", false ) )
+                if( m.isSomewhereDefined( "n", MemoryType.LOCAL ) )
                 {
-                    m.<LayeredGraphNode>read( "n", false ).setSelected( null );
+                    m.<LayeredGraphNode>read( "n", MemoryType.LOCAL ).setSelected( null );
                 }
             }
         };
@@ -81,14 +82,14 @@ public class ConflictDetection implements AlgorithmStage {
         PseudoCodeNode foreach = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "foreach n in graph.getContainedNodes() do", vars ), tree, new ForEachLoop<LayeredGraphNode>( "n" ) {
 			@Override
 			protected List<LayeredGraphNode> list(Memory m) {
-				return m.<LayeredGraphNode>read( "graph", false ).getContainedNodes();
+				return m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL ).getContainedNodes();
 			}
         }, alg );
         root.add( foreach );
         PseudoCodeNode ifNode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "if n has subgraph then", vars ), tree, new IfLoop() {
 			@Override
 			protected boolean condition(Memory m) {
-				return m.<LayeredGraphNode>read( "n", false ).getContainedLayers().size() > 0;
+				return m.<LayeredGraphNode>read( "n", MemoryType.LOCAL ).getContainedLayers().size() > 0;
 			}
         }, alg );
         foreach.add( ifNode );
@@ -99,9 +100,9 @@ public class ConflictDetection implements AlgorithmStage {
         PseudoCodeNode init = new PseudoCodeNode(TextLayoutHelper.setupPseudoCode( "L = graph.getContainedLayers();", vars), tree, new CodeLine() {
 			@Override
 			public ControlFlow runForward(Memory m) {
-				m.declare( "L", m.<LayeredGraphNode>read( "graph", false ).getContainedLayers(), false );
+				m.declare( "L", m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL ).getContainedLayers(), MemoryType.LOCAL );
 				actions.push( (Memory mem) -> {
-					mem.undeclare( "L", false );
+					mem.undeclare( "L", MemoryType.LOCAL );
 					return new ControlFlow( ControlFlow.STEP_OVER );
 				} );
 				return new ControlFlow( ControlFlow.STEP_OVER );
@@ -115,22 +116,18 @@ public class ConflictDetection implements AlgorithmStage {
 			}
 			@Override
 			protected int maximum( Memory m ) {
-				return m.<ArrayList<ArrayList<LayeredGraphNode>>>read( "L", false ).size() - 2;
+				return m.<ArrayList<ArrayList<LayeredGraphNode>>>read( "L", MemoryType.LOCAL ).size() - 2;
 			}
         }, alg );
         root.add( outerLoop );
         PseudoCodeNode line = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "k0 = 0; l = 0;", vars ), tree, new CodeLine() {
 			@Override
 			public ControlFlow runForward(Memory m) {
-				m.declare( "k0", 0, false );
-				m.declare( "l", 0, false );
-				m.declare( "end_", m.<LayeredGraphNode>read( "graph", false ).getContainedLayers().get( m.<Integer>read( "i", false ) + 1 ).size() - 1, false );
-				m.declare( "0", 0, false );
+				m.declare( "k0", 0, MemoryType.LOCAL );
+				m.declare( "l", 0, MemoryType.LOCAL );
 				actions.push( (Memory mem) -> {
-					mem.undeclare( "k0", false );
-					mem.undeclare( "l", false );
-					mem.undeclare( "end_", false );
-					mem.undeclare( "0", false );
+					mem.undeclare( "k0", MemoryType.LOCAL );
+					mem.undeclare( "l", MemoryType.LOCAL );
 					return new ControlFlow( ControlFlow.STEP_OVER );
 				} );
 				return new ControlFlow( ControlFlow.STEP_OVER );
@@ -144,14 +141,14 @@ public class ConflictDetection implements AlgorithmStage {
 			}
 			@Override
 			protected int maximum(Memory m) {
-				return m.<ArrayList<ArrayList<LayeredGraphNode>>>read( "L", false ).get( m.<Integer>read( "i", false ) + 1 ).size() - 1;
+				return m.<ArrayList<ArrayList<LayeredGraphNode>>>read( "L", MemoryType.LOCAL ).get( m.<Integer>read( "i", MemoryType.LOCAL ) + 1 ).size() - 1;
 			}
         }, alg );
         outerLoop.add( innerLoop );
         ifNode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "if l1==|L[i+1]|-1 or L[i+1][l1] incident to inner segment between L[i+1] and L[i] then", vars ), tree, new IfLoop() {
 			@Override
 			protected boolean condition(Memory m) {
-	            return m.<LayeredGraphNode>read( "graph", false ).getContainedLayers().get( m.<Integer>read( "i", false ) + 1).size() == m.<Integer>read( "l1", false ) || 
+	            return m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL ).getContainedLayers().get( m.<Integer>read( "i", MemoryType.LOCAL ) + 1).size() == m.<Integer>read( "l1", MemoryType.LOCAL ) || 
 	            		incidentToInnerSegmentBetweenLiPlusOneAndLi( m );
 			}
         }, alg );
@@ -159,7 +156,7 @@ public class ConflictDetection implements AlgorithmStage {
         line = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "k1 = |L[i]|-1;", vars ), tree, new DeclareVariable<Integer>( "k1" ) {
 			@Override
 			protected Integer value(Memory m) {
-				return (int)m.<ArrayList<ArrayList<LayeredGraphNode>>>read( "L", false ).get( m.read( "i", false ) ).size() - 1;
+				return (int)m.<ArrayList<ArrayList<LayeredGraphNode>>>read( "L", MemoryType.LOCAL ).get( m.read( "i", MemoryType.LOCAL ) ).size() - 1;
 			}
         }, alg );
         ifNode.add( line );
@@ -171,39 +168,40 @@ public class ConflictDetection implements AlgorithmStage {
 		}, alg );
         ifNode.add( innerIfNode );
         
-        line = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "k1 = pos(pred(L[i+1][l1])[0]);", vars ), tree, new DeclareVariable<Integer>( "k1" ) {
+        line = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "k1 = pos(pred(L[i+1][l1])[0]);", vars ), tree, new SetVariable<Integer>( "k1" ) {
 			@Override
 			protected Integer value(Memory m) {
-				return (int)m.<LayeredGraphNode>read( "graph", false ).getContainedLayers().get( m.read( "i", false ) ).indexOf(
-						m.<LayeredGraphNode>read( "graph", false ).getContainedLayers().get( m.<Integer>read( "i", false ) + 1 ).get( m.read( "l1", false ) ).getSortedIncomingEdges().get( 0 ).getSources().get( 0 ) );
+				return (int)m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL ).getContainedLayers().get( m.read( "i", MemoryType.LOCAL ) ).indexOf(
+						m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL ).getContainedLayers().get( m.<Integer>read( "i", MemoryType.LOCAL ) + 1 ).get( m.read( "l1", MemoryType.LOCAL ) ).getSortedIncomingEdges().get( 0 ).getSources().get( 0 ) );
 			}
         }, alg );
         innerIfNode.add( line );
         PseudoCodeNode whileLoop = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "while l <= l1 do", vars ), tree, new WhileLoop() {
 			@Override
 			protected boolean condition( Memory m ) {
-				return m.<Integer>read( "l", false ) <= m.<Integer>read( "l1", false );
+				return m.<Integer>read( "l", MemoryType.LOCAL ) <= m.<Integer>read( "l1", MemoryType.LOCAL );
 			}
         }, alg );
         ifNode.add( whileLoop );
         foreach = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "foreach v in pred(L[i+1][l]) do", vars ), tree, new ForEachLoop<LayeredGraphEdge>( "v" ) {
 			@Override
 			protected List<LayeredGraphEdge> list(Memory m) {
-				return m.<LayeredGraphNode>read( "graph", false ).getContainedLayers().get( m.<Integer>read( "i", false ) + 1 ).get( m.read( "l", false ) ).getIncomingEdges();
+				return m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL ).getContainedLayers().get( m.<Integer>read( "i", MemoryType.LOCAL ) + 1 ).get( m.read( "l", MemoryType.LOCAL ) ).getIncomingEdges();
 			}
         }, alg );
         whileLoop.add( foreach );
-        innerIfNode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "if k < k0 or k > k1 then", vars ), tree, new IfLoop() {
+        innerIfNode = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "if pos(v) < k0 or pos(v) > k1 then", vars ), tree, new IfLoop() {
 			@Override
 			protected boolean condition(Memory m) {
-				return m.<Integer>read( "k", false ) < m.<Integer>read( "k0", false ) || m.<Integer>read( "k", false ) > m.<Integer>read( "k1", false );
+			    int k = m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL ).getContainedLayers().get( m.read( "i", MemoryType.LOCAL ) ).indexOf( m.<LayeredGraphEdge>read( "v", MemoryType.LOCAL ).getSources().get( 0 ) );
+				return k < m.<Integer>read( "k0", MemoryType.LOCAL ) || k > m.<Integer>read( "k1", MemoryType.LOCAL );
 			}
         }, alg );
         foreach.add( innerIfNode );
         line = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "mark segment (v,L[i+1][l]);", vars ), tree, new CodeLine() {
 			@Override
 			public ControlFlow runForward(Memory m) {
-				LayeredGraphEdge e = m.read( "v", false );
+				LayeredGraphEdge e = m.read( "v", MemoryType.LOCAL );
 				boolean old = e.isConflicted( LayoutType.TOP_BOTTOM_LEFT );
 				e.setConflicted( true, null );
 				actions.add( (Memory mem) -> {
@@ -214,17 +212,17 @@ public class ConflictDetection implements AlgorithmStage {
 			}
         }, alg );
         innerIfNode.add( line );
-        line = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "l = l+1;", vars ), tree, new DeclareVariable<Integer>( "l" ) {
+        line = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "l = l+1;", vars ), tree, new SetVariable<Integer>( "l" ) {
 			@Override
 			protected Integer value(Memory m) {
-				return (int)m.<Integer>read( "l", false ) + 1;
+				return (int)m.<Integer>read( "l", MemoryType.LOCAL ) + 1;
 			}
         }, alg );
         whileLoop.add( line );
-        line = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "k0 = k1;", vars ), tree, new DeclareVariable<Integer>( "k0" ) {
+        line = new PseudoCodeNode( TextLayoutHelper.setupPseudoCode( "k0 = k1;", vars ), tree, new SetVariable<Integer>( "k0" ) {
 			@Override
 			protected Integer value(Memory m) {
-				return (int)m.<Integer>read( "l1", false );
+				return (int)m.<Integer>read( "l1", MemoryType.LOCAL );
 			}
         }, alg );
         ifNode.add( line );
@@ -232,7 +230,7 @@ public class ConflictDetection implements AlgorithmStage {
     }
     
     private boolean incidentToInnerSegmentBetweenLiPlusOneAndLi( Memory m ) {
-        LayeredGraphNode curr = m.<LayeredGraphNode>read( "graph", false ).getContainedLayers().get( m.<Integer>read( "i", false ) + 1 ).get( m.read( "l1", false ) );
+        LayeredGraphNode curr = m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL ).getContainedLayers().get( m.<Integer>read( "i", MemoryType.LOCAL ) + 1 ).get( m.read( "l1", MemoryType.LOCAL ) );
         for (LayeredGraphEdge e : curr.getIncomingEdges()) {
             if (e.isDummyEdge()) {
                 return true;

+ 17 - 13
src/codelines/BackwardForEachLoop.java

@@ -6,6 +6,7 @@ import animation.CodeLine;
 import animation.ControlFlow;
 import animation.Memory;
 import animation.StackFrame;
+import animation.Memory.MemoryType;
 import animation.StackFrame.FrameType;
 
 public class BackwardForEachLoop <T> extends CodeLine {
@@ -22,14 +23,14 @@ public class BackwardForEachLoop <T> extends CodeLine {
 	@Override
 	public ControlFlow runForward(Memory m) {
 		boolean declared = false; // prove if it is the first step in the loop
-		if( !m.isSomewhereDefined( "line_" + lineId + "_index", false ) )
+		if( !m.isSomewhereDefined( "line_" + lineId + "_index", MemoryType.LOCAL ) )
 		{ // first loop step
-			m.declare( "line_" + lineId + "_index", m.<List<T>>read( listVar, false ).size() - 1, false );
+			m.declare( "line_" + lineId + "_index", m.<List<T>>read( listVar, MemoryType.LOCAL ).size() - 1, MemoryType.LOCAL );
 			declared = true;
 		}
-		if( m.<Integer>read( "line_" + lineId + "_index", false ) < 0 ) // prove if the loop has finished
+		if( m.<Integer>read( "line_" + lineId + "_index", MemoryType.LOCAL ) < 0 ) // prove if the loop has finished
 		{
-			m.undeclare( "line_" + lineId + "_index", false );
+			m.undeclare( "line_" + lineId + "_index", MemoryType.LOCAL );
 			actions.push( (Memory mem) -> {
 				return new ControlFlow( ControlFlow.STEP_OVER ); // loop was not called so nothing to reverse
 			});
@@ -37,24 +38,27 @@ public class BackwardForEachLoop <T> extends CodeLine {
 		}
 		if( declared )
 		{
-			m.declare( loopVar, m.<List<T>>read( listVar, false ).get( m.read( "line_" + lineId + "_index", false ) ), false ); // set loop variable
+			m.declare( loopVar, m.<List<T>>read( listVar, MemoryType.LOCAL ).get( m.read( "line_" + lineId + "_index", MemoryType.LOCAL ) ), MemoryType.LOCAL ); // set loop variable
 			m.addFrame( new StackFrame( FrameType.LOOP ) );
 			actions.push( (Memory mem) -> {
 				mem.removeFrame();
-				mem.undeclare( "line_" + lineId + "_index", false );
+				mem.undeclare( "line_" + lineId + "_index", MemoryType.LOCAL );
 				return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
 			} );
 		}
 		else
 		{
-			int oldIndex = m.<Integer>read( "line_" + lineId + "_index", false );
-			m.write( "line_" + lineId + "_index", oldIndex - 1, false ); // count index down
-			if( m.<Integer>read( "line_" + lineId + "_index", false ) < 0 ) // prove if loop was finished
+			int oldIndex = m.<Integer>read( "line_" + lineId + "_index", MemoryType.LOCAL );
+			m.write( "line_" + lineId + "_index", oldIndex - 1, MemoryType.LOCAL ); // count index down
+			if( m.<Integer>read( "line_" + lineId + "_index", MemoryType.LOCAL ) < 0 ) // prove if loop was finished
 			{
 				StackFrame sf = m.removeFrame(); // remove loop stack
-				m.undeclare( "line_" + lineId + "_index", false );
+                T old = m.read( loopVar, MemoryType.LOCAL );
+                m.undeclare( loopVar, MemoryType.LOCAL );
+				m.undeclare( "line_" + lineId + "_index", MemoryType.LOCAL );
 				actions.push( (Memory mem) -> {
-					mem.write( "line_" + lineId + "_index", oldIndex, false );
+	                m.declare( loopVar, old, MemoryType.LOCAL );
+					mem.write( "line_" + lineId + "_index", oldIndex, MemoryType.LOCAL );
 					mem.addFrame( sf ); // restore last loop stack
 					return new ControlFlow( ControlFlow.STEP_INTO ); // step into the loop body
 				});
@@ -62,11 +66,11 @@ public class BackwardForEachLoop <T> extends CodeLine {
 			}
 			StackFrame old = m.removeFrame(); // fresh stack frame for loop body
 			m.addFrame( new StackFrame( FrameType.LOOP ) );
-			m.write( loopVar, m.<List<T>>read( listVar, false ).get( m.read( "line_" + lineId + "_index", false ) ), false ); // update loop variable
+			m.write( loopVar, m.<List<T>>read( listVar, MemoryType.LOCAL ).get( m.read( "line_" + lineId + "_index", MemoryType.LOCAL ) ), MemoryType.LOCAL ); // update loop variable
 			actions.push( (Memory mem) -> {
 				mem.removeFrame();
 				mem.addFrame( old );
-				mem.write( "line_" + lineId + "_index", oldIndex, false );
+				mem.write( "line_" + lineId + "_index", oldIndex, MemoryType.LOCAL );
 				return new ControlFlow( ControlFlow.STEP_INTO );
 			});
 		}

+ 6 - 5
src/codelines/DeclareVariable.java

@@ -3,6 +3,7 @@ package codelines;
 import animation.CodeLine;
 import animation.ControlFlow;
 import animation.Memory;
+import animation.Memory.MemoryType;
 
 public abstract class DeclareVariable <T> extends CodeLine {
 
@@ -17,14 +18,14 @@ public abstract class DeclareVariable <T> extends CodeLine {
 	@Override
 	public ControlFlow runForward(Memory m) {
 		
-		oldExists = m.isDefined( name, false );
-		T oldVal = m.read( name, false );
-		m.declare( name, value( m ), false );
+		oldExists = m.isDefined( name, MemoryType.LOCAL );
+		T oldVal = m.read( name, MemoryType.LOCAL );
+		m.declare( name, value( m ), MemoryType.LOCAL );
 		actions.push( (Memory mem) -> {
 			if( !oldExists )
-				mem.undeclare( name, false );
+				mem.undeclare( name, MemoryType.LOCAL );
 			else
-				mem.declare( name, oldVal, false );
+				mem.declare( name, oldVal, MemoryType.LOCAL ); // TODO declare in correct stack frame
 			return new ControlFlow( ControlFlow.STEP_OVER );
 		});
 		return new ControlFlow( ControlFlow.STEP_OVER );

+ 17 - 13
src/codelines/ForEachLoop.java

@@ -6,6 +6,7 @@ import animation.CodeLine;
 import animation.ControlFlow;
 import animation.Memory;
 import animation.StackFrame;
+import animation.Memory.MemoryType;
 import animation.StackFrame.FrameType;
 
 public abstract class ForEachLoop <T> extends CodeLine {
@@ -20,14 +21,14 @@ public abstract class ForEachLoop <T> extends CodeLine {
 	@Override
 	public ControlFlow runForward(Memory m) {
 		boolean declared = false; // prove if it is the first step in the loop
-		if( !m.isSomewhereDefined( "line_" + lineId + "_index", false ) )
+		if( !m.isSomewhereDefined( "line_" + lineId + "_index", MemoryType.LOCAL ) )
 		{ // first loop step
-			m.declare( "line_" + lineId + "_index", 0, false );
+			m.declare( "line_" + lineId + "_index", 0, MemoryType.LOCAL );
 			declared = true;
 		}
-		if( m.<Integer>read( "line_" + lineId + "_index", false ) > list( m ).size() - 1 ) // prove if the loop has finished
+		if( m.<Integer>read( "line_" + lineId + "_index", MemoryType.LOCAL ) > list( m ).size() - 1 ) // prove if the loop has finished
 		{
-			m.undeclare( "line_" + lineId + "_index", false );
+			m.undeclare( "line_" + lineId + "_index", MemoryType.LOCAL );
 			actions.push( (Memory mem) -> {
 				return new ControlFlow( ControlFlow.STEP_OVER ); // loop was not called so nothing to reverse
 			});
@@ -35,24 +36,27 @@ public abstract class ForEachLoop <T> extends CodeLine {
 		}
 		if( declared )
 		{
-			m.declare( loopVar, list( m ).get( m.read( "line_" + lineId + "_index", false ) ), false ); // set loop variable
+			m.declare( loopVar, list( m ).get( m.read( "line_" + lineId + "_index", MemoryType.LOCAL ) ), MemoryType.LOCAL ); // set loop variable
 			m.addFrame( new StackFrame( FrameType.LOOP ) );
 			actions.push( (Memory mem) -> {
 				mem.removeFrame();
-				mem.undeclare( "line_" + lineId + "_index", false );
+				mem.undeclare( "line_" + lineId + "_index", MemoryType.LOCAL );
 				return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
 			} );
 		}
 		else
 		{
-			int oldIndex = m.<Integer>read( "line_" + lineId + "_index", false );
-			m.write( "line_" + lineId + "_index", oldIndex + 1, false ); // count index down
-			if( m.<Integer>read( "line_" + lineId + "_index", false ) > list( m ).size() - 1 ) // prove if loop was finished
+			int oldIndex = m.<Integer>read( "line_" + lineId + "_index", MemoryType.LOCAL );
+			m.write( "line_" + lineId + "_index", oldIndex + 1, MemoryType.LOCAL ); // count index down
+			if( m.<Integer>read( "line_" + lineId + "_index", MemoryType.LOCAL ) > list( m ).size() - 1 ) // prove if loop was finished
 			{
 				StackFrame sf = m.removeFrame(); // remove loop stack
-				m.undeclare( "line_" + lineId + "_index", false );
+				m.undeclare( "line_" + lineId + "_index", MemoryType.LOCAL );
+				T old = m.read( loopVar, MemoryType.LOCAL );
+				m.undeclare( loopVar, MemoryType.LOCAL );
 				actions.push( (Memory mem) -> {
-					mem.write( "line_" + lineId + "_index", oldIndex, false );
+				    mem.declare( loopVar, old, MemoryType.LOCAL );
+					mem.write( "line_" + lineId + "_index", oldIndex, MemoryType.LOCAL );
 					mem.addFrame( sf ); // restore last loop stack
 					return new ControlFlow( ControlFlow.STEP_INTO ); // step into the loop body
 				});
@@ -60,11 +64,11 @@ public abstract class ForEachLoop <T> extends CodeLine {
 			}
 			StackFrame old = m.removeFrame(); // fresh stack frame for loop body
 			m.addFrame( new StackFrame( FrameType.LOOP ) );
-			m.write( loopVar, list( m ).get( m.read( "line_" + lineId + "_index", false ) ), false ); // update loop variable
+			m.write( loopVar, list( m ).get( m.read( "line_" + lineId + "_index", MemoryType.LOCAL ) ), MemoryType.LOCAL ); // update loop variable
 			actions.push( (Memory mem) -> {
 				mem.removeFrame();
 				mem.addFrame( old );
-				mem.write( "line_" + lineId + "_index", oldIndex, false );
+				mem.write( "line_" + lineId + "_index", oldIndex, MemoryType.LOCAL );
 				return new ControlFlow( ControlFlow.STEP_INTO );
 			});
 		}

+ 17 - 13
src/codelines/ForLoop.java

@@ -4,6 +4,7 @@ import animation.CodeLine;
 import animation.ControlFlow;
 import animation.Memory;
 import animation.StackFrame;
+import animation.Memory.MemoryType;
 import animation.StackFrame.FrameType;
 
 public abstract class ForLoop extends CodeLine {
@@ -18,14 +19,14 @@ public abstract class ForLoop extends CodeLine {
 	@Override
 	public ControlFlow runForward(Memory m) {
 		boolean declared = false; // prove if it is the first step in the loop
-		if( !m.isSomewhereDefined( "line_" + lineId + "_index", false ) )
+		if( !m.isSomewhereDefined( "line_" + lineId + "_index", MemoryType.LOCAL ) )
 		{ // first loop step
-			m.declare( "line_" + lineId + "_index", minimum( m ), false );
+			m.declare( "line_" + lineId + "_index", minimum( m ), MemoryType.LOCAL );
 			declared = true;
 		}
-		if( m.<Integer>read( "line_" + lineId + "_index", false ) > maximum( m ) ) // prove if the loop has finished
+		if( m.<Integer>read( "line_" + lineId + "_index", MemoryType.LOCAL ) > maximum( m ) ) // prove if the loop has finished
 		{
-			m.undeclare( "line_" + lineId + "_index", false );
+			m.undeclare( "line_" + lineId + "_index", MemoryType.LOCAL );
 			actions.push( (Memory mem) -> {
 				return new ControlFlow( ControlFlow.STEP_OVER ); // loop was not called so nothing to reverse
 			});
@@ -33,24 +34,27 @@ public abstract class ForLoop extends CodeLine {
 		}
 		if( declared )
 		{
-			m.declare( loopVar, minimum( m ), false ); // set loop variable
 			m.addFrame( new StackFrame( FrameType.LOOP ) );
+            m.declare( loopVar, minimum( m ), MemoryType.LOCAL ); // set loop variable
 			actions.push( (Memory mem) -> {
 				mem.removeFrame();
-				mem.undeclare( "line_" + lineId + "_index", false );
+				mem.undeclare( "line_" + lineId + "_index", MemoryType.LOCAL );
 				return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
 			} );
 		}
 		else
 		{
-			int oldIndex = m.<Integer>read( "line_" + lineId + "_index", false );
-			m.write( "line_" + lineId + "_index", oldIndex + 1, false ); // count index down
-			if( m.<Integer>read( "line_" + lineId + "_index", false ) > maximum( m ) ) // prove if loop was finished
+			int oldIndex = m.<Integer>read( "line_" + lineId + "_index", MemoryType.LOCAL );
+			m.write( "line_" + lineId + "_index", oldIndex + 1, MemoryType.LOCAL ); // count index down
+			if( m.<Integer>read( "line_" + lineId + "_index", MemoryType.LOCAL ) > maximum( m ) ) // prove if loop was finished
 			{
 				StackFrame sf = m.removeFrame(); // remove loop stack
-				m.undeclare( "line_" + lineId + "_index", false );
+				m.undeclare( "line_" + lineId + "_index", MemoryType.LOCAL );
+                //int old = m.read( loopVar, false );
+                //m.undeclare( loopVar, false );
 				actions.add( (Memory mem) -> {
-					mem.write( "line_" + lineId + "_index", oldIndex, false );
+	                //m.declare( loopVar, old, false );
+					mem.write( "line_" + lineId + "_index", oldIndex, MemoryType.LOCAL );
 					mem.addFrame( sf ); // restore last loop stack
 					return new ControlFlow( ControlFlow.STEP_INTO ); // step into the loop body
 				});
@@ -58,11 +62,11 @@ public abstract class ForLoop extends CodeLine {
 			}
 			StackFrame old = m.removeFrame(); // fresh stack frame for loop body
 			m.addFrame( new StackFrame( FrameType.LOOP ) );
-			m.write( loopVar, (int)m.read( "line_" + lineId + "_index", false ), false ); // update loop variable
+			m.declare( loopVar, (int)m.read( "line_" + lineId + "_index", MemoryType.LOCAL ), MemoryType.LOCAL ); // update loop variable
 			actions.push( (Memory mem) -> {
 				mem.removeFrame();
 				mem.addFrame( old );
-				mem.write( "line_" + lineId + "_index", oldIndex, false );
+				mem.write( "line_" + lineId + "_index", oldIndex, MemoryType.LOCAL );
 				return new ControlFlow( ControlFlow.STEP_INTO );
 			});
 		}

+ 3 - 2
src/codelines/FunctionCall.java

@@ -4,6 +4,7 @@ import animation.CodeLine;
 import animation.ControlFlow;
 import animation.Memory;
 import animation.PseudoCodeNode;
+import animation.Memory.MemoryType;
 
 public class FunctionCall extends CodeLine {
 
@@ -21,14 +22,14 @@ public class FunctionCall extends CodeLine {
 		int index = 1;
 		for( String p : params )
 		{
-			m.declare( "param" + index, m.read( p, false ), true );
+			m.declare( "param" + index, m.read( p, MemoryType.LOCAL ), MemoryType.GLOBAL );
 			index++;
 		}
 		actions.push( (Memory mem) -> {
 			int ind = 1;
 			for( @SuppressWarnings("unused") String p : params )
 			{
-				m.undeclare( "param" + ind, true );
+				m.undeclare( "param" + ind, MemoryType.GLOBAL );
 				ind++;
 			}
 			return new ControlFlow( target );

+ 7 - 8
src/codelines/FunctionDefinition.java

@@ -3,6 +3,7 @@ package codelines;
 import animation.CodeLine;
 import animation.ControlFlow;
 import animation.Memory;
+import animation.Memory.MemoryType;
 import animation.StackFrame;
 import animation.StackFrame.FrameType;
 
@@ -17,19 +18,17 @@ public class FunctionDefinition extends CodeLine {
 	
 	@Override
 	public ControlFlow runForward(Memory m) {
-		if( !m.isDefined( "param1", true ) && !m.isDefined( "line_" + lineId + "_inside", false ) )
-			return new ControlFlow( ControlFlow.STEP_OVER );
-		if( !m.isDefined( "line_" + lineId + "_inside", false ) )
+		if( !m.isDefined( "line_" + lineId + "_inside", MemoryType.CURRENT ) )
 		{
 			m.addFrame( new StackFrame( FrameType.FUNCTION ) );
-			m.declare( "line_" + lineId + "_inside", true, false );
+			m.declare( "line_" + lineId + "_inside", true, MemoryType.LOCAL );
 			int index = 1;
 			Object olds[] = new Object[ params.length ];
 			for( String p : params )
 			{
-				olds[ index - 1 ] = m.read( "param" + index, true );
-				m.declare( p, olds[ index - 1 ], false );
-				m.undeclare( "param" + index, true );
+				olds[ index - 1 ] = m.read( "param" + index, MemoryType.GLOBAL );
+				m.declare( p, olds[ index - 1 ], MemoryType.LOCAL );
+				m.undeclare( "param" + index, MemoryType.GLOBAL );
 				index++;
 			}
 			actions.push( (Memory mem) -> {
@@ -37,7 +36,7 @@ public class FunctionDefinition extends CodeLine {
 				int i = 1;
 				for( @SuppressWarnings("unused") String p : params )
 				{
-					mem.declare( "param" + i, olds[ i - 1], true );
+					mem.declare( "param" + i, olds[ i - 1], MemoryType.GLOBAL );
 					i++;
 				}
 				return new ControlFlow( ControlFlow.STEP_OVER );

+ 3 - 4
src/codelines/IfLoop.java

@@ -4,6 +4,7 @@ import animation.CodeLine;
 import animation.ControlFlow;
 import animation.Memory;
 import animation.StackFrame;
+import animation.Memory.MemoryType;
 import animation.StackFrame.FrameType;
 
 /**
@@ -15,7 +16,7 @@ public abstract class IfLoop extends CodeLine {
 
 	@Override
 	public ControlFlow runForward(Memory m) {
-		if( m.isDefined( "line_" + lineId + "_inside", false ) )
+		if( m.isDefined( "line_" + lineId + "_inside", MemoryType.CURRENT ) )
 		{
 			StackFrame old = m.removeFrame();
 			actions.push( (Memory mem) -> {
@@ -28,16 +29,14 @@ public abstract class IfLoop extends CodeLine {
 		{
             if( condition( m ) ) {
             	m.addFrame( new StackFrame( FrameType.LOOP ) );
-            	m.declare( "line_" + lineId + "_inside", true, false );
+            	m.declare( "line_" + lineId + "_inside", true, MemoryType.LOCAL );
             	actions.push( (Memory mem) -> {
             		mem.removeFrame();
             		return new ControlFlow( ControlFlow.STEP_OVER );
             	} );
             	return new ControlFlow( ControlFlow.STEP_INTO );
             } else {
-            	m.declare( "line_" + lineId + "_inside", false, false );
             	actions.push( (Memory mem) -> {
-            		mem.undeclare( "line_" + lineId + "_inside", false );
 	                return new ControlFlow( ControlFlow.STEP_OVER );
             	} );
                 return new ControlFlow( ControlFlow.STEP_OVER );

+ 35 - 0
src/codelines/SetVariable.java

@@ -0,0 +1,35 @@
+package codelines;
+
+import animation.CodeLine;
+import animation.ControlFlow;
+import animation.Memory;
+import animation.Memory.MemoryType;
+
+public abstract class SetVariable <T> extends CodeLine {
+
+    private boolean oldExists;
+    private String name;
+    
+    public SetVariable( String name )
+    {
+        this.name = name;
+    }
+
+    @Override
+    public ControlFlow runForward(Memory m) {
+        
+        oldExists = m.isDefined( name, MemoryType.LOCAL );
+        T oldVal = m.read( name, MemoryType.LOCAL );
+        m.write( name, value( m ), MemoryType.LOCAL );
+        actions.push( (Memory mem) -> {
+            if( !oldExists )
+                mem.undeclare( name, MemoryType.LOCAL );
+            else
+                mem.write( name, oldVal, MemoryType.LOCAL ); // TODO write in correct stack frame
+            return new ControlFlow( ControlFlow.STEP_OVER );
+        });
+        return new ControlFlow( ControlFlow.STEP_OVER );
+    }
+    
+    abstract protected T value( Memory m );
+}

+ 22 - 22
src/codelines/WhileLoop.java

@@ -4,6 +4,7 @@ import animation.CodeLine;
 import animation.ControlFlow;
 import animation.Memory;
 import animation.StackFrame;
+import animation.Memory.MemoryType;
 import animation.StackFrame.FrameType;
 
 public abstract class WhileLoop extends CodeLine {
@@ -11,43 +12,42 @@ public abstract class WhileLoop extends CodeLine {
 	@Override
 	public ControlFlow runForward(Memory m) {
 		boolean declared = false; // prove if it is the first step in the loop
-		if( !m.isSomewhereDefined( "line_" + lineId + "_index", false ) )
+		if( !m.isDefined( "line_" + lineId + "_index", MemoryType.LOCAL ) )
 		{ // first loop step
-			m.declare( "line_" + lineId + "_index", 0, false );
 			declared = true;
 		}
-		if( !condition( m ) ) // prove if the loop has finished
-		{
-			m.undeclare( "line_" + lineId + "_index", false );
-			actions.push( (Memory mem) -> {
-				return new ControlFlow( ControlFlow.STEP_OVER ); // loop was not called so nothing to reverse
-			});
-			return new ControlFlow( ControlFlow.STEP_OVER ); // don't execute the loop body
-		}
+        if( !condition( m ) ) // prove if loop was finished
+        {
+            if( !declared )
+            {
+                StackFrame sf = m.removeFrame(); // remove loop stack
+                actions.push( (Memory mem) -> {
+                    mem.addFrame( sf ); // restore last loop stack
+                    return new ControlFlow( ControlFlow.STEP_INTO ); // step into the loop body
+                });
+            }
+            else
+            {
+                actions.push( (Memory mem) -> {
+                    return new ControlFlow( ControlFlow.STEP_INTO ); // step into the loop body
+                });
+            }
+            return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
+        }
 		if( declared )
 		{
 			m.addFrame( new StackFrame( FrameType.LOOP ) );
+            m.declare( "line_" + lineId + "_index", 0, MemoryType.LOCAL );
 			actions.push( (Memory mem) -> {
 				mem.removeFrame();
-				mem.undeclare( "line_" + lineId + "_index", false );
 				return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
 			} );
 		}
 		else
 		{
-			if( !condition( m ) ) // prove if loop was finished
-			{
-				StackFrame sf = m.removeFrame(); // remove loop stack
-				m.undeclare( "line_" + lineId + "_index", false );
-				actions.push( (Memory mem) -> {
-					mem.declare( "line_" + lineId + "_index", 0, false );
-					mem.addFrame( sf ); // restore last loop stack
-					return new ControlFlow( ControlFlow.STEP_INTO ); // step into the loop body
-				});
-				return new ControlFlow( ControlFlow.STEP_OVER ); // step out of the loop
-			}
 			StackFrame old = m.removeFrame(); // fresh stack frame for loop body
 			m.addFrame( new StackFrame( FrameType.LOOP ) );
+            m.declare( "line_" + lineId + "_index", 0, MemoryType.LOCAL );
 			actions.push( (Memory mem) -> {
 				mem.removeFrame();
 				mem.addFrame( old );