Переглянути джерело

combine code hinzugefügt (Juhuu genau 100 zeilen insgesammt)

Kolja Strohm 6 роки тому
батько
коміт
0b66d32752

+ 22 - 2
src/bk/BKNodePlacement.java

@@ -185,8 +185,28 @@ public class BKNodePlacement extends AnimatedAlgorithm {
         extremalLayoutStage.add( new PseudoCodeNode( "-- horizontal compaction --", vars, tree, new Comment() ) );
         extremalLayoutStage.add( horizontalCompaction );
         extremalLayoutStage.add( placeBlock );
-        root.add( new PseudoCodeNode( "-- balancing --", vars, tree, new Comment() ) );
-        root.add( combine );
+        PseudoCodeNode balancingStage = new PseudoCodeNode( "-- balancing --", vars, tree, new Comment() ) {
+            @Override
+            public String getDebugOutput( Memory m ) {
+                if( !m.isSomewhereDefined( "graph", MemoryType.COMPLETE_STACK ) )
+                    return "";
+                String info = "| Node | x BR | x BL | x UR | x UL | x CO |\n";
+                info +=       "|------|------|------|------|------|------|\n";
+                LayeredGraphNode graph = m.read( "graph", MemoryType.COMPLETE_STACK );
+                for( LayeredGraphNode n : graph.getContainedNodes() )
+                {
+                    info += "|" + TextLayoutHelper.strToLen( n.getName(), 6 ) + 
+                            "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.TOP_BOTTOM_LEFT ) + "", 6 ) + 
+                            "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.TOP_BOTTOM_RIGHT ) + "", 6 ) + 
+                            "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.BOTTOM_TOP_LEFT ) + "", 6 ) + 
+                            "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.BOTTOM_TOP_LEFT ) + "", 6 ) + 
+                            "|" + TextLayoutHelper.strToLen( n.getX( LayoutType.COMBINED ) + "", 6 ) + "|\n";
+                }
+                return info;
+            }
+        };
+        root.add( balancingStage );
+        balancingStage.add( combine );
         processor = new PseudoCodeProcessor( root );
         return root;
     }

+ 207 - 2
src/bk/Combine.java

@@ -1,9 +1,23 @@
 package bk;
 
+import java.awt.Color;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 import javax.swing.JTree;
 
+import animation.CodeLine;
+import animation.ControlFlow;
+import animation.Memory;
+import animation.Memory.MemoryType;
+import animation.Memory.ReadOnlyMemory;
 import animation.PseudoCodeNode;
+import codelines.DeclareVariable;
+import codelines.ForEachLoop;
 import codelines.FunctionDefinition;
+import codelines.SetVariable;
+import graph.LayeredGraphNode;
 
 /**
  * The stage of the combination of the four extremal layouts.
@@ -13,8 +27,199 @@ import codelines.FunctionDefinition;
 public class Combine {
 
     public static PseudoCodeNode combine( JTree tree ) {
-        String[] vars = { "graph" };
-        PseudoCodeNode root = new PseudoCodeNode( "function combine( graph )", vars, tree, new FunctionDefinition( vars ) );
+        String[] vars = { "graph", "l", "l_min", "v", "positions" };
+        @SuppressWarnings("serial")
+        PseudoCodeNode root = new PseudoCodeNode( "function combine( graph )", vars, tree, new FunctionDefinition( new String[]{ "graph" } ) ){
+            @Override
+            public String getDebugOutput( Memory m )
+            {
+                if( m.isSomewhereDefined( "v", MemoryType.LOCAL ) )
+                    m.<LayeredGraphNode>read( "v", MemoryType.LOCAL).setSelected( null );
+                return super.getDebugOutput( m );
+            }
+        };
+        root.add( new PseudoCodeNode( "-- Align all Layouts to the one with the smallest width --", vars, tree, new CodeLine() {
+            @Override
+            public ControlFlow runForward(Memory m) {
+                LayeredGraphNode graph = m.read( "graph", MemoryType.LOCAL );
+                if( graph.parent() == null )
+                    graph.setColor( Color.BLACK, null );
+                actions.add( (Memory mem) -> {
+                    if( graph.parent() == null )
+                        graph.setColor( null, null );
+                });
+                return null;
+            }
+        }));
+        PseudoCodeNode firstLoop = new PseudoCodeNode( "foreach l in ['DOWN_RIGHT', 'DOWN_LEFT', 'UP_RIGHT', 'UP_LEFT'] do", vars, tree, new ForEachLoop<String>( "l" ) {
+            @Override
+            protected List<String> list(ReadOnlyMemory m) {
+                ArrayList< String > list = new ArrayList<String>();
+                list.add( "DOWN_RIGHT" );
+                list.add( "DOWN_LEFT" );
+                list.add( "UP_RIGHT" );
+                list.add( "UP_LEFT" );
+                return list;
+            }
+        });
+        root.add( firstLoop );
+        firstLoop.add( new PseudoCodeNode( "min[l] = minimum x coordinate in l;", vars, tree, new CodeLine() {
+            @Override
+            public ControlFlow runForward(Memory m) {
+                String layout = m.read( "l", MemoryType.LOCAL );
+                m.declare( "min[" + layout + "]", calcMinX( m.read( "graph", MemoryType.LOCAL ), LayoutType.fromString( layout ) ), MemoryType.GLOBAL );
+                actions.add( (Memory mem) -> {
+                    mem.undeclare( "min[" + layout + "]", MemoryType.GLOBAL );
+                });
+                return new ControlFlow( ControlFlow.STEP_OVER );
+            }
+        }));
+        firstLoop.add( new PseudoCodeNode( "max[l] = maximum x coordinate in l;", vars, tree, new CodeLine() {
+            @Override
+            public ControlFlow runForward(Memory m) {
+                String layout = m.read( "l", MemoryType.LOCAL );
+                m.declare( "max[" + layout + "]", calcMaxX( m.read( "graph", MemoryType.LOCAL ), LayoutType.fromString( layout ) ), MemoryType.GLOBAL );
+                actions.add( (Memory mem) -> {
+                    mem.undeclare( "max[" + layout + "]", MemoryType.GLOBAL );
+                });
+                return new ControlFlow( ControlFlow.STEP_OVER );
+            }
+        }));
+        firstLoop.add( new PseudoCodeNode( "width[l] = max[l] - min[l];", vars, tree, new CodeLine() {
+            @Override
+            public ControlFlow runForward(Memory m) {
+                String layout = m.read( "l", MemoryType.LOCAL );
+                m.declare( "height[" + layout + "]", m.<Integer>read( "max[" + layout + "]", MemoryType.LOCAL ) - m.<Integer>read( "min[" + layout + "]", MemoryType.LOCAL ), MemoryType.GLOBAL );
+                actions.add( (Memory mem) -> {
+                    mem.undeclare( "width[" + layout + "]", MemoryType.GLOBAL );
+                });
+                return new ControlFlow( ControlFlow.STEP_OVER );
+            }
+        }));
+        root.add( new PseudoCodeNode( "l_min = l with width[l] == min(width);", vars, tree, new DeclareVariable<String>( "l_min" ) {
+            @Override
+            protected String value(ReadOnlyMemory m) {
+                String min = "DOWN_RIGHT";
+                int minW = m.read( "width[DOWN_RIGHT]", MemoryType.GLOBAL );
+                for( String l : new String[]{ "DOWN_LEFT", "UP_RIGHT", "UP_LEFT" } )
+                {
+                    if( minW > m.<Integer>read( "width[" + l + "]", MemoryType.GLOBAL ) )
+                    {
+                        minW = m.<Integer>read( "width[" + l + "]", MemoryType.GLOBAL );
+                        min = l;
+                    }
+                }
+                return min;
+            }
+        }));
+        PseudoCodeNode secondLoop = new PseudoCodeNode( "foreach l in ['DOWN_RIGHT', 'DOWN_LEFT', 'UP_RIGHT', 'UP_LEFT'] do", vars, tree, new ForEachLoop<String>( "l" ) {
+            @Override
+            protected List<String> list(ReadOnlyMemory m) {
+                ArrayList< String > list = new ArrayList<String>();
+                list.add( "DOWN_RIGHT" );
+                list.add( "DOWN_LEFT" );
+                list.add( "UP_RIGHT" );
+                list.add( "UP_LEFT" );
+                return list;
+            }
+        });
+        root.add( secondLoop );
+        secondLoop.add( new PseudoCodeNode( "shift[l] = l.contains('RIGHT') ? min[l_min] - min[l] : max[l_min] - max[l];", vars, tree, new CodeLine() {
+            @Override
+            public ControlFlow runForward(Memory m) {
+                String layout = m.read( "l", MemoryType.LOCAL );
+                String lMin = m.read( "l_min", MemoryType.LOCAL );
+                if( layout.contains( "RIGHT" ) )
+                    m.declare( "shift[" + layout + "]", m.<Integer>read( "min[" + lMin + "]", MemoryType.LOCAL ) - m.<Integer>read( "min[" + layout + "]", MemoryType.LOCAL ), MemoryType.GLOBAL );
+                else
+                    m.declare( "shift[" + layout + "]", m.<Integer>read( "max[" + lMin + "]", MemoryType.LOCAL ) - m.<Integer>read( "max[" + layout + "]", MemoryType.LOCAL ), MemoryType.GLOBAL );
+                actions.add( (Memory mem) -> {
+                    mem.undeclare( "shift[" + layout + "]", MemoryType.GLOBAL );
+                });
+                return new ControlFlow( ControlFlow.STEP_OVER );
+            }
+        }));
+        PseudoCodeNode thirdLoop = new PseudoCodeNode( "foreach v in graph do", vars, tree, new ForEachLoop<LayeredGraphNode>( "v" ) {
+            @Override
+            protected List<LayeredGraphNode> list(ReadOnlyMemory m) {
+                return m.<LayeredGraphNode>read( "graph", MemoryType.LOCAL ).getContainedNodes();
+            }
+        });
+        root.add( thirdLoop );
+        thirdLoop.add( new PseudoCodeNode( "positions = [];", vars, tree, new DeclareVariable<ArrayList<Integer>>( "positions") {
+            @Override
+            protected ArrayList<Integer> value(ReadOnlyMemory m) {
+                return new ArrayList<Integer>();
+            }
+        }));
+        PseudoCodeNode innerLoop = new PseudoCodeNode( "foreach l in ['DOWN_RIGHT', 'DOWN_LEFT', 'UP_RIGHT', 'UP_LEFT'] do", vars, tree, new ForEachLoop<String>( "l" ) {
+            @Override
+            protected List<String> list(ReadOnlyMemory m) {
+                ArrayList< String > list = new ArrayList<String>();
+                list.add( "DOWN_RIGHT" );
+                list.add( "DOWN_LEFT" );
+                list.add( "UP_RIGHT" );
+                list.add( "UP_LEFT" );
+                return list;
+            }
+        });
+        innerLoop.add( new PseudoCodeNode( "positions.add(x[v] in l);", vars, tree, new CodeLine() {
+            @Override
+            public ControlFlow runForward(Memory m) {
+                String layout = m.read( "l", MemoryType.LOCAL );
+                ArrayList<Integer> positions = m.read( "positions", MemoryType.LOCAL );
+                positions.add( (int)m.<LayeredGraphNode>read( "v", MemoryType.LOCAL ).getX( LayoutType.fromString( layout ) ) + m.<Integer>read( "shift[" + layout + "]", MemoryType.GLOBAL ) );
+                actions.add( (Memory mem) -> {
+                    positions.remove( positions.size() - 1 );
+                });
+                return new ControlFlow( ControlFlow.STEP_OVER );
+            }
+        }));
+        thirdLoop.add( innerLoop );
+        thirdLoop.add( new PseudoCodeNode( "positions = sort( positions );", vars, tree, new SetVariable<ArrayList<Integer>>( "positions" ) {
+            @Override
+            public ArrayList<Integer> value(ReadOnlyMemory m) {
+                ArrayList<Integer> positions = m.read( "positions", MemoryType.LOCAL );
+                ArrayList<Integer> neu = new ArrayList<Integer>();
+                for( int p : positions )
+                    neu.add( p );
+                Collections.sort( neu );
+                return neu;
+            }
+        }));
+        thirdLoop.add( new PseudoCodeNode( "x[v] = (positions[1]+positions[2]) / 2;", vars, tree, new CodeLine() {
+            @Override
+            public ControlFlow runForward(Memory m) {
+                ArrayList<Integer> positions = m.read( "positions", MemoryType.LOCAL );
+                LayeredGraphNode v = m.read( "v", MemoryType.LOCAL );
+                double old = v.getX( LayoutType.COMBINED );
+                v.setX( (positions.get( 1 ) + positions.get( 2 )) / 2.0, true, LayoutType.COMBINED );
+                actions.add( (Memory mem) -> {
+                    v.setX( old, false, LayoutType.COMBINED );
+                });
+                return new ControlFlow( ControlFlow.STEP_OVER );
+            }
+        }));
         return root;
     }
+
+    private static int calcMinX( LayeredGraphNode graph, LayoutType layout )
+    {
+        int minX = 0;
+        if( graph.getContainedNodes().size() > 0 )
+            minX = (int)graph.getContainedNodes().get( 0 ).getX( layout );
+        for( LayeredGraphNode n : graph.getContainedNodes() )
+            minX = Math.min( minX, (int)n.getX( layout ) );
+        return minX;
+    }
+
+    private static int calcMaxX( LayeredGraphNode graph, LayoutType layout )
+    {
+        int maxX = 0;
+        if( graph.getContainedNodes().size() > 0 )
+            maxX = (int)graph.getContainedNodes().get( 0 ).getX( layout );
+        for( LayeredGraphNode n : graph.getContainedNodes() )
+            maxX = Math.max( maxX, (int)n.getX( layout ) );
+        return maxX;
+    }
 }

+ 15 - 8
src/codelines/DeclareVariable.java

@@ -10,23 +10,30 @@ public abstract class DeclareVariable <T> extends CodeLine {
 
 	private boolean oldExists;
 	private String name;
+	private MemoryType mt;
+    
+    public DeclareVariable( String name )
+    {
+        this.name = name;
+        this.mt = MemoryType.LOCAL;
+    }
 	
-	public DeclareVariable( String name )
+	public DeclareVariable( String name, MemoryType mt )
 	{
 		this.name = name;
+		this.mt = mt;
 	}
 
 	@Override
 	public ControlFlow runForward(Memory m) {
 		
-		oldExists = m.isDefined( name, MemoryType.LOCAL );
-		T oldVal = m.read( name, MemoryType.LOCAL );
-		m.declare( name, value( m.createReadOnlyMemory() ), MemoryType.LOCAL );
+		oldExists = m.isDefined( name, mt );
+		T oldVal = m.read( name, mt );
+		m.declare( name, value( m.createReadOnlyMemory() ), mt );
 		actions.push( (Memory mem) -> {
-			if( !oldExists )
-				mem.undeclare( name, MemoryType.LOCAL );
-			else
-				mem.declare( name, oldVal, MemoryType.LOCAL ); // TODO declare in correct stack frame
+			mem.undeclare( name, mt );
+            if( oldExists )
+				mem.write( name, oldVal, mt );
 		});
 		return new ControlFlow( ControlFlow.STEP_OVER );
 	}

+ 1 - 1
src/lib/TextLayoutHelper.java

@@ -24,7 +24,7 @@ public class TextLayoutHelper {
         return s;
     }
     
-    private static String[] keywords = { "for", "do", "to", "then", "else", "if", "foreach", "while", "or", "and", "call", "function", "false", "true", "undefined" };
+    private static String[] keywords = { "for", "do", "to", "then", "else", "if", "foreach", "while", "or", "and", "call", "function", "false", "true", "undefined", "with" };
     private static String[] delimiter = { "\\+", "\\-", "\\[", "\\]", "\\|", " ", "^", "$", "\\=", "\\,", "\\(", "\\;", "\\.", "\\)" };
     
     private static String getDelimiterRegex()