/* // $Id: //guest/julian_hyde/saffron/src/main/saffron/util/Obsolete.java#1 $ // Saffron preprocessor and data engine // Copyright (C) 2002 Julian Hyde <julian.hyde@mail.com> // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this library; if not, write to the // Free Software Foundation, Inc., 59 Temple Place - Suite 330, // Boston, MA 02111-1307, USA. // // See the COPYING file located in the top-level-directory of // the archive of this library for complete text of license. */ package saffron.util; import openjava.mop.Environment; import openjava.mop.OJClass; import openjava.mop.Toolbox; import openjava.ptree.*; import saffron.opt.*; import saffron.rel.ExpressionReader; import saffron.rel.Rel; import saffron.rel.convert.Converter; import saffron.rel.java.SingleTerminator; /** * todo: * * @author jhyde * @since 16 December, 2001 * @version $Id: //guest/julian_hyde/saffron/src/main/saffron/util/Obsolete.java#1 $ **/ public class Obsolete { /** * <code>InlineIteratorReader</code> implements {@link ExpressionReader} in * code, for the case that the expression implements {@link * java.util.Iterator}. **/ static class InlineIteratorReader extends ExpressionReader { InlineIteratorReader(Cluster cluster, Expression exp) { super(cluster, exp, null); } public Object clone() { return new InlineIteratorReader(cluster, Util.clone(exp)); } public int getConvention() { return CallingConvention.JAVA; } public Object implement(Implementor implementor, int ordinal) { switch (ordinal) { case -1: // Generate // for (Iterator iter = <<exp>>; iter.hasNext();) { // Object row = iter.next(); // <<parent>> // } StatementList stmtList = implementor.getStatementList(); Variable variable_iter = implementor.newVariable(), variable_row = implementor.newVariable(); StatementList forBody = new StatementList(); Expression exp2 = implementor.translate(exp, this); stmtList.add( new ForStatement( TypeName.forOJClass(Util.clazzIterator), new VariableDeclarator[] { new VariableDeclarator( variable_iter.toString(), exp2)}, new MethodCall( variable_iter, "hasNext", null), new ExpressionList(), forBody)); forBody.add( new VariableDeclaration( TypeName.forOJClass(Toolbox.clazzObject), new VariableDeclarator( variable_row.toString(), new MethodCall( variable_iter, "next", null)))); implementor.bind(this, variable_row); implementor.generateParentBody(this, forBody); return null; default: throw Util.newInternal( "implement: ordinal=" + ordinal); } } }; /** * <code>InlineArrayReader</code> implements {@link ExpressionReader} in * code, for an expression which returns an array. **/ static class InlineArrayReader extends ExpressionReader { InlineArrayReader(Cluster cluster, Expression exp) { super(cluster, exp, null); } public Object clone() { return new InlineArrayReader(cluster, Util.clone(exp)); } public int getConvention() { return CallingConvention.JAVA; } public Object implement(Implementor implementor, int ordinal) { switch (ordinal) { case -1: // Generate // V[] v = <<exp>>; // for (int i = 0; i < v.length; i++) { // V row = v[i]; // <<parent>> // } StatementList stmtList = implementor.getStatementList(); Variable variableArray = implementor.newVariable(), variableIndex = implementor.newVariable(); StatementList forBody = new StatementList(); Expression exp2 = implementor.translate(exp, this); stmtList.add( new VariableDeclaration( TypeName.forOJClass(getType(exp)), variableArray.toString(), exp2)); stmtList.add( new ForStatement( new TypeName("int"), new VariableDeclarator[] { new VariableDeclarator( variableIndex.toString(), Literal.constantZero())}, new BinaryExpression( variableIndex, BinaryExpression.LESS, new FieldAccess( variableArray, "length")), new ExpressionList( new UnaryExpression( UnaryExpression.POST_INCREMENT, variableIndex)), forBody)); Variable variableRow = implementor.newVariable(); forBody.add( new VariableDeclaration( TypeName.forOJClass(getRowType()), variableRow.toString(), new ArrayAccess( variableArray, variableIndex))); implementor.bind(this, variableRow); implementor.generateParentBody(this, forBody); return null; default: throw Util.newInternal( "implement: ordinal=" + ordinal); } } }; /** * <code>IterExpressionReader</code> implements {@link ExpressionReader} in * the {@link CallingConvention#ITERATOR} convention. It generates a piece * of code which creates an {@link java.util.Iterator}. **/ public static class IterExpressionReader extends ExpressionReader { IterExpressionReader(Cluster cluster, Expression exp) { super(cluster, exp, null); OJClass clazz = getType(exp); if (!Util.clazzIterator.isAssignableFrom(clazz)) { throw Util.newInternal( "IterExpressionReader: expression " + clazz + " is not an iterator"); } } public Object clone() { return new IterExpressionReader(cluster, Util.clone(exp)); } public int getConvention() { return CallingConvention.ITERATOR; } public Object implement(Implementor implementor, int ordinal) { switch (ordinal) { case -1: // Generate // <<exp>>; Expression exp2 = implementor.translate(exp, this); return exp2; default: throw Util.newInternal( "implement: ordinal=" + ordinal); } } }; /** * <code>InlineEnumerationReader</code> implements {@link ExpressionReader} * in code, for the case that the expression is a {@link * java.util.Enumeration}. Useful in JDK 1.1, where {@link java.util.Map} * does not exist. **/ static class InlineEnumerationReader extends ExpressionReader { InlineEnumerationReader(Cluster cluster, Expression exp) { super(cluster, exp, null); } public Object clone() { return new InlineEnumerationReader(cluster, Util.clone(exp)); } public int getConvention() { return CallingConvention.JAVA; } public Object implement(Implementor implementor, int ordinal) { switch (ordinal) { case -1: // Generate // for (Enumeration enum = <<exp>>; enum.hasMoreElements();) // { // Row row = enum.nextElement(); // <<parent>> // } StatementList stmtList = implementor.getStatementList(); Variable variable_enum = implementor.newVariable(), variable_row = implementor.newVariable(); StatementList forBody = new StatementList(); Expression exp2 = implementor.translate(exp, this); stmtList.add( new ForStatement( TypeName.forOJClass(Util.clazzEnumeration), new VariableDeclarator[] { new VariableDeclarator( variable_enum.toString(), exp2)}, new MethodCall( variable_enum, "hasMoreElements", null), new ExpressionList(), forBody)); forBody.add( new VariableDeclaration( TypeName.forOJClass(Toolbox.clazzObject), new VariableDeclarator( variable_row.toString(), new MethodCall( variable_enum, "nextElement", null)))); implementor.bind(this, variable_row); implementor.generateParentBody(this, forBody); return null; default: throw Util.newInternal( "implement: ordinal=" + ordinal); } } }; /** * <code>InlineMapReader</code> implements {@link ExpressionReader} in * code, for an expression which implements {@link java.util.Map}. **/ static class InlineMapReader extends ExpressionReader { InlineMapReader(Cluster cluster, Expression exp) { super(cluster, exp, null); } public Object clone() { return new InlineMapReader(cluster, Util.clone(exp)); } public int getConvention() { return CallingConvention.JAVA; } public Object implement(Implementor implementor, int ordinal) { switch (ordinal) { case -1: // Generate // Map m = <<exp>>; // for (Iterator entries = m.entrySet().iterator(); // entries.hasNext();) { // Map.Entry entry = (Map.Entry) keys.next(); // Row row = new Row(entry.getKey(), entry.getValue()); // <<parent>> // } StatementList stmtList = implementor.getStatementList(); Variable variable_m = implementor.newVariable(), variable_entries = implementor.newVariable(), variable_entry = implementor.newVariable(), variable_row = implementor.newVariable(); StatementList forBody = new StatementList(); Expression exp2 = implementor.translate(exp, this); stmtList.add( new VariableDeclaration( TypeName.forOJClass(Util.clazzMap), variable_m.toString(), exp2)); stmtList.add( new ForStatement( TypeName.forOJClass(Util.clazzIterator), new VariableDeclarator[] { new VariableDeclarator( variable_entries.toString(), new MethodCall( new MethodCall( variable_m, "entrySet", null), "iterator", null))}, new MethodCall( variable_entries, "hasNext", null), new ExpressionList(), forBody)); forBody.add( new VariableDeclaration( TypeName.forOJClass(Toolbox.clazzMapEntry), new VariableDeclarator( variable_entry.toString(), new CastExpression( TypeName.forOJClass(Toolbox.clazzMapEntry), new MethodCall( variable_entries, "next", null))))); forBody.add( new VariableDeclaration( TypeName.forOJClass(getRowType()), variable_row.toString(), new AllocationExpression( TypeName.forOJClass(getRowType()), new ExpressionList( new MethodCall( variable_entry, "getKey", null), new MethodCall( variable_entry, "getValue", null))))); implementor.bind(this, variable_row); implementor.generateParentBody(this, forBody); return null; default: throw Util.newInternal( "implement: ordinal=" + ordinal); } } }; /** * <code>InlineHashtableReader</code> implements {@link ExpressionReader} * in code, for the case that the expression is a {@link * java.util.Hashtable}. Useful in JDK 1.1, where {@link java.util.Map} * does not exist. **/ static class InlineHashtableReader extends ExpressionReader { InlineHashtableReader(Cluster cluster, Expression exp) { super(cluster, exp, null); } public Object clone() { return new InlineHashtableReader(cluster, Util.clone(exp)); } public int getConvention() { return CallingConvention.JAVA; } public Object implement(Implementor implementor, int ordinal) { switch (ordinal) { case -1: // Generate // Hashtable h = <<exp>>; // for (Enumeration keys = h.keys(); keys.hasMoreElements();) { // Object key = keys.nextElement(); // Object value = h.get(key); // Row row = new Row(key, value); // <<parent>> // } StatementList stmtList = implementor.getStatementList(); Variable variable_h = implementor.newVariable(), variable_keys = implementor.newVariable(), variable_key = implementor.newVariable(), variable_value = implementor.newVariable(), variable_row = implementor.newVariable(); StatementList forBody = new StatementList(); Expression exp2 = implementor.translate(exp, this); stmtList.add( new VariableDeclaration( TypeName.forOJClass(Util.clazzHashtable), variable_h.toString(), exp2)); stmtList.add( new ForStatement( TypeName.forOJClass(Util.clazzEnumeration), new VariableDeclarator[] { new VariableDeclarator( variable_keys.toString(), new MethodCall( variable_h, "keys", null))}, new MethodCall( variable_keys, "hasMoreElements", null), new ExpressionList(), forBody)); forBody.add( new VariableDeclaration( TypeName.forOJClass(Toolbox.clazzObject), new VariableDeclarator( variable_key.toString(), new MethodCall( variable_keys, "nextElement", null)))); forBody.add( new VariableDeclaration( TypeName.forOJClass(Toolbox.clazzObject), new VariableDeclarator( variable_value.toString(), new MethodCall( variable_h, "get", new ExpressionList(variable_key))))); forBody.add( new VariableDeclaration( TypeName.forOJClass(getRowType()), variable_row.toString(), new AllocationExpression( TypeName.forOJClass(getRowType()), new ExpressionList( variable_key, variable_value)))); implementor.bind(this, variable_row); implementor.generateParentBody(this, forBody); return null; default: throw Util.newInternal( "implement: ordinal=" + ordinal); } } }; /** * <code>ArrayReader</code> implements {@link ExpressionReader} in code, * for an expression which returns an array. **/ static class ArrayReader extends ExpressionReader { ArrayReader(Cluster cluster, Expression exp) { super(cluster, exp, null); } public Object clone() { return new ArrayReader(cluster, Util.clone(exp)); } public int getConvention() { return CallingConvention.ARRAY; } public Object implement(Implementor implementor, int ordinal) { switch (ordinal) { case -1: // Generate // <<exp>> return implementor.translate(exp, this); default: throw Util.newInternal( "implement: ordinal=" + ordinal); } } }; /** * An <code>ArrayTerminator</code> takes a {@link saffron.rel.Rel} and makes it into an * expression which yields an array. **/ static class obsolete_ArrayTerminator extends SingleTerminator { Variable var_v; obsolete_ArrayTerminator(Cluster cluster, Rel child) { super(cluster, child); } // implement Rel public Object clone() { return new obsolete_ArrayTerminator(cluster, Util.clone(child)); } public Object implement(Implementor implementor, int ordinal) { switch (ordinal) { case -1: // called from parent { // Find all unbound variables in expressions in this tree UnboundVariableCollector unboundVars = Util.getUnboundVariables(this); // Generate // new Object() { // /** Executes <code> ... </code>. **/ // Vector asVector(C0 v0, ...) { // Vector v = new Vector(); // <<child loop // v.addElement(i); // >> // return v; // } // Rowtype[] asArray(C0 v0, ...) { // Vector v = asVector(v0, ...); // Rowtype[] a = new Rowtype[v.size()]; // v.copyInto(a); // return a; // } // }.asArray(v0, ...) OJClass clazz = child.getRowType(); // "Rowtype" Variable var_v = this.var_v = implementor.newVariable(), var_a = implementor.newVariable(); implementor.setExitStatement( new ReturnStatement(var_v)); StatementList stmtList = new StatementList( // "Vector v = new Vector();" new VariableDeclaration( null, // no modifiers new TypeName("java.util.Vector"), new VariableDeclarator( var_v.toString(), new AllocationExpression( new TypeName("java.util.Vector"), null)))); // Give child chance to write its code into "stmtList" (and to // call us back so we can write "v.addElement(i);". implementor.pushStatementList(stmtList); Object o = implementor.implementChild(this, 0, child); Util.assert(o == null); implementor.popStatementList(); // "return v;" stmtList.add( new ReturnStatement( var_v)); // "public void asVector(C0 v0, ...) { ... }" MethodDeclaration asVector = new MethodDeclaration( new ModifierList(), new TypeName("java.util.Vector"), "asVector", unboundVars.getParameterList(), // "(C0 v0, ...)" null, // throws nothing stmtList); asVector.setComment( "/** Evaluates <code>" + cluster.getOriginalExpression().toString() + "</code> and returns the results as a vector. **/"); // "public Rowtype[] asArray(C0 v0, ...) { ... }" MethodDeclaration asArray = new MethodDeclaration( new ModifierList(), new TypeName(clazz.getName(), 1), // "Rowtype[]" "asArray", unboundVars.getParameterList(), // "(C0 v0, ...)" null, // throws nothing new StatementList( // "Vector v = asVector(C0 v0, ...);" new VariableDeclaration( null, // no modifiers new TypeName("java.util.Vector"), new VariableDeclarator( var_v.toString(), new MethodCall( "asVector", unboundVars.getArgumentList()))), // "Emp[] a = new Emp[v.size()];" new VariableDeclaration( null, // no modifiers new TypeName(clazz.getName(), 1), new VariableDeclarator( var_a.toString(), new ArrayAllocationExpression( new TypeName( clazz.getName()), // "Emp" new ExpressionList( new MethodCall( var_v, "size", null))))), new ExpressionStatement( clazz.isPrimitive() ? // "saffron.runtime.SaffronUtil.copyInto(v, a);" new MethodCall( new TypeName("saffron.runtime.SaffronUtil"), "copyInto", new ExpressionList(var_v, var_a)) : // "v.copyInto(a);" new MethodCall( var_v, "copyInto", new ExpressionList(var_a))), // "return a;" new ReturnStatement(var_a))); return new MethodCall( new AllocationExpression( new TypeName("Object"), // "Object" null, // "()" new MemberDeclarationList( asVector, asArray)), "asArray", unboundVars.getArgumentList()); } case 0: // called from child { // Generate // v.addElement(i) // Rowtype[] variable = <<child variable>>; // <<parent body (references variable)>> StatementList stmtList = implementor.getStatementList(); stmtList.add( new ExpressionStatement( new MethodCall( var_v, "addElement", new ExpressionList( Toolbox.box( child.getRowType(), implementor.translate( new Variable(RelEnvironment.makeName(0)), this)))))); return null; } default: throw Util.newInternal( "implement: ordinal=" + ordinal); } } }; /** * <code>SingleQueue</code> contains at most one object. **/ static class SingleQueue { private Object full = new Object(); private Object empty = new Object(); private Object data; public void push(Object o) { synchronized (full) { if (data != null) { try { full.wait(); } catch (InterruptedException e) { } } } data = o; synchronized (empty) { if (data != null) { empty.notify(); } } } public Object pop() { synchronized (empty) { if (data == null) { try { empty.wait(); } catch (InterruptedException e) { } } } Object o = data; data = null; synchronized (full) { if (data == null) { full.notify(); } } return o; } }; /** * <code>QueueIterator</code> takes data from a consumer, and converts it * into an iterator. **/ static class QueueIterator2 { private static Object nullObject = new Object(); private static Object doneObject = new Object(); private SingleQueue queue = new SingleQueue(); private boolean done = false; private Object next; private Throwable throwable; QueueIterator2() { moveToNext(); } private void moveToNext() { next = queue.pop(); if (next == doneObject) { done = true; } else if (next == nullObject) { next = null; } } public boolean hasNext() { return !done; } public Object next() { Object o = next; moveToNext(); return o; } /** * Returns the error (if any) which stopped execution. Consumer should only * call this after {@link #hasNext} has returned <code>false</code>. **/ public Throwable getThrowable() { if (!done) { throw new Error("getThrowable called before end of stream"); } return throwable; } /** * Producer calls <code>put</code> to add another object (which may be * null). **/ public void put(Object o) { if (o == null) { o = nullObject; } queue.push(o); } /** * Producer calls <code>done</code> to say that there are no more objects, * setting <code>throwable</code> if there was an error. **/ public void done(Throwable throwable) { this.throwable = throwable; queue.push(doneObject); } }; private static OJClass[] forClass(Class[] classes) { OJClass[] ojClasses = new OJClass[classes.length]; for (int i = 0; i < classes.length; i++) { ojClasses[i] = OJClass.forClass(classes[i]); } return ojClasses; } /** * <code>ConverterRule</code> is a special rule which converts an * expression from one calling convention to another by applying a * Converter. */ static class Obsolete_ConverterRule extends SingleConventionRule { /** * Create a ConverterRule. * * @param outConvention Convention to convert to. (In order words, the * generated expression will use this convention in order to return * its results.) */ Obsolete_ConverterRule(int outConvention) { super( new Operand(saffron.rel.Rel.class, null), outConvention); } public Rel apply(Environment env, Rel[] rels) { Rel rel = rels[0]; if (rel instanceof Converter) { // Don't apply a converter to a converter -- we tend to get // cycles. return null; } else if (convention == rel.getConvention()) { if (planner.getSubset(rel, convention) == null) { // return the expression, and it will be registered with // this convention return rel; } else { // expression is already in this convention's subset -- it // may in fact BE the subset -- so we have nothing to do return null; } } else { for (int inConvention = 0; inConvention < CallingConvention.MAX; inConvention++) { if (convention == rel.getConvention() && Converter.canConvert( inConvention, this.convention)) { rel = planner.register( rel, null, CHILDREN_MUST_BE_REGISTERED); return Converter.create( rel.getCluster(), rel, inConvention, this.convention); } } } return null; } }; /** * <code>SwitchConventionRule</code> changes the convention of the * underlying relation, and adds a converter to compensate. It is the * converse of {@link saffron.Converter.RemoveConverterRule}. **/ static abstract class obsolete_SwitchConventionRule extends SingleConventionRule { int toConvention; obsolete_SwitchConventionRule(int convention, int toConvention) { super( new Operand(Rel.class, null), convention); this.toConvention = toConvention; } public Rel apply(Environment env, Rel[] rels) { Rel rel = rels[0]; if (rel.getConvention() != convention) { return null; } if (rel instanceof Converter) { return null; } RelSet set = planner.getSet(rel); if (set.getSubset(toConvention) != null) { // there are already equivalent expressions in the required // calling convention -- don't create another return null; } Rel rel2 = planner.register(rel, null, VolcanoPlanner.MAY_BE_REGISTERED); Rel converted = Converter.create( rel.getCluster(), rel2, convention, toConvention); Rel converted2 = planner.register( converted, null, VolcanoPlanner.MAY_BE_REGISTERED); Rel convertedBack = Converter.create( rel.getCluster(), converted2, toConvention, convention); return convertedBack; } }; } // End Obsolete.java
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#2 | 1474 | Julian Hyde |
saffron: Aggregations are working. Renamed 'aggregator' to 'aggregation'. |
||
#1 | 1467 | Julian Hyde |
saffron: First saffron check-in; incorporate my changes to openjava. |