Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/trapezium/chisel/Optimizer.java


1   /*
2    * @(#)Optimizer.java
3    *
4    * Copyright (c) 1998 by Trapezium Development LLC.  All Rights Reserved.
5    *
6    * The information in this file is the property of Trapezium Development LLC
7    * and may be used only in accordance with the terms of the license granted
8    * by Trapezium.
9    *
10   */
11  package com.trapezium.chisel;
12  
13  import com.trapezium.parse.TokenEnumerator;
14  import com.trapezium.vrml.ROUTE;
15  import com.trapezium.vrml.node.Node;
16  import com.trapezium.vrml.fields.Field;
17  import com.trapezium.vrml.node.DEFUSENode;
18  import java.util.Vector;
19  
20  import java.io.PrintStream;
21  
22  /** The Optimizer is the base class for all chisels.  It handles replacing a range
23   *  of tokens through the <B>replaceRange</B> method. 
24   */
25  abstract public class Optimizer implements NodeLocatorListener, OptionHolder {
26    RangeReplacer rangeReplacer;
27    
28    // the type of node to replace
29    String nodeName;
30    Vector additionalNodes;
31    
32      // flags for non-node name specific controls
33      boolean specificNodeType;
34      boolean allNodes;
35      boolean coordinateOwnerNode;
36      boolean interpolatorNode;
37      boolean defOnly;
38    
39    protected String baseFilePath;
40    protected String baseFileName;
41    public TokenEnumerator dataSource;
42  
43    public Optimizer( String nodeName, String actionMessage ) {
44      this.nodeName = nodeName;
45      this.actionMessage = actionMessage;
46      allNodes = false;
47      specificNodeType = true;
48      allNodes = false;
49      coordinateOwnerNode = false;
50      interpolatorNode = false;
51      setFlags();
52    }
53  
54      /** Not available ... */
55    private Optimizer() {
56    }
57    
58    public String getNodeName() {
59      return( nodeName );
60    }
61  
62    public void setNodeName( String nodeName ) {
63      this.nodeName = nodeName;
64      setFlags();
65    }
66    
67    public int getNumberAdditionalNames() {
68        if ( additionalNodes == null ) {
69            return( 0 );
70        } else {
71            return( additionalNodes.size() );
72        }
73    }
74    
75    public String getAdditionalName( int offset ) {
76        return( (String)additionalNodes.elementAt( offset ));
77    }
78    
79    public void addAdditionalNode( String nodeName ) {
80        if ( additionalNodes == null ) {
81            additionalNodes = new Vector();
82        }
83        additionalNodes.addElement( nodeName );
84    }
85  
86    void setFlags() {
87        if ( nodeName != null ) {
88            allNodes = ( nodeName.compareTo( "All" ) == 0 );
89              coordinateOwnerNode = ( nodeName.compareTo( "CoordinateOwner" ) == 0 );
90              interpolatorNode = ( nodeName.compareTo( "Interpolator" ) == 0 );
91              defOnly = ( nodeName.compareTo( "DEF" ) == 0 );
92          }
93        specificNodeType = !(allNodes || coordinateOwnerNode || interpolatorNode || defOnly);
94    }
95  
96      /** reset optimizer, subclasses may need this */
97      public void reset() {
98          rangeReplacer = null;
99          dataSource = null;
100     }
101     
102     /** Get a message used for display on status line */
103     String actionMessage;
104     public String getActionMessage() {
105         return( actionMessage );
106     }
107     
108     /** Get the number of control options available for this chisel. */
109     public int getNumberOptions() {
110         return( 0 );
111     }
112 
113     /** Get the class for an option */
114     public Class getOptionClass( int optionOffset ) {
115         return( null );
116     }
117 
118     /** Get a specific control option label */
119     public String getOptionLabel( int optionOffset ) {
120         return( null );
121     }
122 
123     /** Get current option value */
124     public Object getOptionValue( int optionOffset ) {
125         return( null );
126     }
127 
128     /** Set option value */
129     public void setOptionValue( int optionOffset, Object value ) {
130     }
131 
132     /** Get current option value */
133     public Object getOptionConstraints( int optionOffset ) {
134         return( null );
135     }
136 
137     /** Set option value */
138     public void setOptionConstraints( int optionOffset, Object constraints ) {
139     }
140 
141     /** Convert an option value to a boolean */
142     public boolean optionValueToBoolean( Object value ) {
143         return( "true".equalsIgnoreCase(value.toString()) );
144     }
145     /** Convert an integer to an option value */
146     public Object booleanToOptionValue( boolean value ) {
147         return( value ? "true" : "false" );
148     }
149 
150     /** Convert an option value to an integer */
151     public int optionValueToInt( Object value ) {
152         int n;
153         try {
154             n = Integer.parseInt(value.toString());
155         } catch (NumberFormatException e) {
156             System.out.println("Couldn't convert option " + value + " to integer.");
157             n = 0;
158         }
159         return n;
160     }
161     
162     /** Convert an integer to an option value */
163     public Object intToOptionValue( int value ) {
164         return String.valueOf(value);
165     }
166 
167 
168     /** Set the base file path for the source file being processed */
169     public void setBaseFilePath( String baseFilePath ) {
170         this.baseFilePath = baseFilePath;
171     }
172 
173     /** Set the base file name for the source file being processed */
174     public void setBaseFileName( String baseFileName ) {
175         this.baseFileName = baseFileName;
176     }
177 
178   public void setRangeReplacer( RangeReplacer rr ) {
179     this.rangeReplacer = rr;
180   }
181 
182   public void setDataSource( TokenEnumerator v ) {
183       dataSource = v;
184   }
185 
186   public void replaceRange( int firstTokenOffset, int lastTokenOFfset, Object param ) {
187     rangeReplacer.replaceRange( this, firstTokenOffset, lastTokenOFfset, param );
188   }
189 
190   public void replaceStartEnd( int oldStartOffset, int oldEndOffset, int newStartOffset, int newEndOffset ) {
191       rangeReplacer.replaceStartEnd( oldStartOffset, oldEndOffset, newStartOffset, newEndOffset );
192   }
193 
194   public void eofTokens( int firstTokenOffset, int lastTokenOffset ) {
195     rangeReplacer.eofTokens( firstTokenOffset, lastTokenOffset );
196   }
197 
198     void tryAdditional( NodeFoundEvent nfe ) {
199         if ( additionalNodes != null ) {
200           String nfeName = nfe.getName();
201           int numberAdditional = additionalNodes.size();
202           for ( int i = 0; i < numberAdditional; i++ ) {
203               String s = (String)additionalNodes.elementAt( i );
204               if ( nfeName.compareTo( s ) == 0 ) {
205                   attemptOptimization( nfe.getNode() );
206                   break;
207               }
208           }
209       }
210     }
211 
212   //
213   //  "nodeFound" and "getNodeName" are the NodeLocatorListener interface.
214   //  Optimizers listen for NodeFoundEvents then attempt optimizations on those
215   //  nodes.  The "attemptOptimization" is an abstract method implemented in the
216   //  specific Optimizer subclasses.
217   //
218   public void nodeFound( NodeFoundEvent nfe ) {
219       if ( specificNodeType ) {
220             if ( nodeName.compareTo( nfe.getName() ) == 0 ) {
221           attemptOptimization( nfe.getNode() );
222         } else {
223             tryAdditional( nfe );
224         }
225     } else if ( coordinateOwnerNode ) {
226           String nfeName = nfe.getName();
227           if ( nfeName.compareTo( "IndexedFaceSet" ) == 0 ) {
228               attemptOptimization( nfe.getNode() );
229           } else if ( nfeName.compareTo( "IndexedLineSet" ) == 0 ) {
230               attemptOptimization( nfe.getNode() );
231           }
232       } else if ( interpolatorNode ) {
233           String nfeName = nfe.getName();
234           if ( nfeName.indexOf( "Interpolator" ) > 0 ) {
235               attemptOptimization( nfe.getNode() );
236           } else {
237               tryAdditional(nfe );
238           }
239       } else if ( defOnly ) {
240           Node n = nfe.getNode();
241           if ( n instanceof DEFUSENode ) {
242               DEFUSENode dun = (DEFUSENode)n;
243               if ( dun.isDEF() ) {
244                   attemptOptimization( n );
245               }
246           }
247          } else if ( allNodes ) {
248       attemptOptimization( nfe.getNode() );
249     }
250   }
251 
252   public void routeFound( RouteFoundEvent rfe ) {
253     attemptOptimization( rfe.getRoute() );
254   }
255 
256 
257   // some subclasses may override this, determines whether or not optimize is called
258   public boolean optimizePossible( Object param ) {
259     return( true );
260   }
261 
262     /** NodeLocatorListener interface, subclasses override this to return 
263      *  true to force "attemptOptimization" calls on DEF/USE nodes.
264      */
265   public boolean isDEFUSElistener() {
266     return( false );
267   }
268   
269   /** NodeLocatorListener interface, subclasses override this to return 
270   *   true to force "attemptOptimization" calls on DEF nodes.
271    */
272   public boolean isDEFlistener() {
273       return( false );
274   }
275 
276     /** template, subclasses override this to return true if they want to define
277      *  the "attemptOptimization( ROUTE )" method.
278      */
279   public boolean isROUTElistener() {
280     return( false );
281   }
282 
283     /** template, subclasses override tihs to return true if they want access
284      *  to the interior of PROTOs.
285      */
286   public boolean isPROTOlistener() {
287       return( false );
288   }
289 
290     /** template, subclasses override this if they modify ROUTEs */
291   public void attemptOptimization( ROUTE route ) {
292   }
293 
294     /** template, subclasses override this if they modify Nodes */
295   public void attemptOptimization( Node node ) {
296   }
297 
298 
299     /** Print a sequence of numbers
300      *
301      *  @param tp  where to print
302      *  @param scanner  first token to print
303      *  @param endTokenOffset  last token to print, printing stops early if this found
304      *  @param n  number of tokens to print
305      *
306      *  @return  the token after the last token printed, or endTokenOffset if encountered
307      */
308     protected int printNumbers( TokenPrinter tp, int scanner, int endTokenOffset, int n ) {
309         dataSource.setState( scanner );
310         for ( int i = 0; i < n; i++ ) {
311             tp.print( dataSource, scanner );
312             scanner = dataSource.getNextToken();
313             if ( scanner >= endTokenOffset ) {
314                 break;
315             }
316             if ( i < ( n - 1 )) {
317                 scanner = tp.printNonNumbers( scanner, endTokenOffset );
318                 if ( scanner >= endTokenOffset ) {
319                     break;
320                 }
321             }
322         }
323         return( scanner );
324     }
325 
326     /** Replace an index field when there is one index entry per face,
327      *  and that one face has been converted into several faces.
328      *
329      *  @param tp print destination
330      *  @param indexField the index field to replace
331      *  @param faceMultiple array containing factor multiple for each face
332      *  @param faceCount number of faces
333      */
334   protected void replaceIndexFaceMultiple( TokenPrinter tp, Field indexField, int[] faceMultiple, int faceCount ) {
335       int scanner = indexField.getFirstTokenOffset();
336     int endTokenOffset = indexField.getLastTokenOffset();
337       dataSource.setState( scanner );
338       int faceNo = 0;
339       while ( true ) {
340           scanner = tp.printNonNumbers( scanner, endTokenOffset );
341           if ( scanner >= endTokenOffset ) {
342               break;
343           }
344           if (( faceNo < faceCount ) && ( faceMultiple[ faceNo ] > 0 )) {
345               for ( int i = 0; i < faceMultiple[ faceNo ]; i++ ) {
346                   tp.print( dataSource, scanner );
347               }
348           } else {
349               tp.print( dataSource, scanner );
350           }
351           faceNo++;
352           scanner = dataSource.getNextToken();
353       }
354   }
355 
356   protected void replaceValueNodeFaceMultiple( TokenPrinter tp, Field valueNode, int[] faceMultiple, int faceCount ) {
357       int scanner = valueNode.getFirstTokenOffset();
358       int endTokenOffset = valueNode.getLastTokenOffset();
359       dataSource.setState( scanner );
360       int faceNo = 0;
361       while ( true ) {
362           scanner = tp.printNonNumbers( scanner, endTokenOffset );
363           if ( scanner >= endTokenOffset ) {
364               break;
365           }
366           if (( faceNo < faceCount ) && ( faceMultiple[ faceNo ] > 0 ))  {
367               int tscanner = printNumbers( tp, scanner, endTokenOffset, 3 );
368               for ( int i = 1; i < faceMultiple[ faceNo ]; i++ ) {
369                   tscanner = printNumbers( tp, scanner, endTokenOffset, 3 );
370               }
371               scanner = tscanner;
372           } else {
373               tp.print( dataSource, scanner );
374               scanner = dataSource.getNextToken();
375           }
376           faceNo++;
377       }
378   }
379 
380   // RangeReplacer calls this when it has a range of tokens to replace
381   abstract public void optimize( TokenPrinter tp, Object param, int startTokenOffset, int endTokenOffset );
382   
383   /** default summary (none), used by command line version */
384   public void summarize( PrintStream ps ) {
385   }
386   
387   /** default, chisel has no final code generation */
388   public boolean hasFinalCode() {
389       return( false );
390   }
391   
392   /** method which prints final code, subclasses may override this */
393   public void printFinalCode( TokenPrinter tp ) {
394   }
395 
396 }