001: package gnu.xquery.util;
002:
003: import gnu.lists.*;
004: import gnu.mapping.*;
005: import gnu.expr.*;
006: import gnu.bytecode.*;
007:
008: /** A procedure used to represent a FLWOR expression with
009: * an {@code order by} clause.
010: * ({@link gnu.kawa.functions.ValuesMap} is used for FLWOR expression
011: * that don't have an {@code order by} clause.)
012: *
013: * As returned by the parser:
014: * <pre>
015: * for $x1 in exp1, $x2 in exp2 where cond order by comparator1 ... return body
016: * </pre>
017: * is represented as
018: * <pre>
019: * ordered-map(tuple-sequence, body-function,
020: * comparator-function1, flags1, collation1, ...)
021: * </pre>
022: * Here tuple-sequence is an expression that returns a sequence of tuples,
023: * which are currently implemnted as Java Object[] arrays.
024: * After inlining we get:
025: * <pre>
026: * ordered-map(tuple-sequence.
027: * OrderedTuples.make$V(body-function,
028: * new Object[]{comparator-function1, flags1, collation1, ...}))
029: * </pre>
030: *
031: * A future optimization would be to create an instance of a new sub-class
032: * of OrderedTuples. Then the body-function and comparator-functions
033: * could be compiled as methods to that class. That wins especially
034: * if it saves us having to create extra frame classes.
035: */
036:
037: public class OrderedMap extends MethodProc implements CanInline,
038: Inlineable {
039: public static final OrderedMap orderedMap = new OrderedMap();
040:
041: public static Object[] makeTuple$V(Object[] values) {
042: return values;
043: }
044:
045: static final ClassType typeTuples = ClassType
046: .make("gnu.xquery.util.OrderedTuples");
047:
048: public Expression inline(ApplyExp exp, ExpWalker walker) {
049: Expression[] args = exp.getArgs();
050: if (args.length > 2) {
051: Expression[] rargs = new Expression[args.length - 1];
052: System.arraycopy(args, 1, rargs, 0, rargs.length);
053: Expression[] xargs = new Expression[2];
054: Method makeTupleMethod = typeTuples.getDeclaredMethod(
055: "make$V", 2);
056: xargs[0] = args[0];
057: xargs[1] = new ApplyExp(makeTupleMethod, rargs);
058: return new ApplyExp(this , xargs);
059: }
060: return exp;
061: }
062:
063: public void apply(CallContext ctx) throws Throwable {
064: Consumer out = ctx.consumer;
065: Object[] args = ctx.getArgs();
066: Object values = args[0];
067: OrderedTuples tuples;
068: if (args.length == 2) {
069: tuples = (OrderedTuples) args[1];
070: } else {
071: Object[] comps = new Object[args.length - 2];
072: System.arraycopy(args, 2, comps, 0, comps.length);
073: tuples = OrderedTuples.make$V((Procedure) args[1], comps);
074: }
075: Values.writeValues(values, tuples);
076: tuples.run$X(ctx);
077: }
078:
079: public void compile(ApplyExp exp, Compilation comp, Target target) {
080: Expression[] args = exp.getArgs();
081: if (args.length != 2) {
082: ApplyExp.compile(exp, comp, target);
083: return;
084: }
085: CodeAttr code = comp.getCode();
086: Scope scope = code.pushScope();
087: Variable consumer = scope.addVariable(code, typeTuples, null);
088: args[1].compile(comp, Target.pushValue(typeTuples));
089: code.emitStore(consumer);
090: ConsumerTarget ctarget = new ConsumerTarget(consumer);
091: args[0].compile(comp, ctarget);
092: Method mm = typeTuples.getDeclaredMethod("run$X", 1);
093: code.emitLoad(consumer);
094: PrimProcedure.compileInvoke(comp, mm, target, exp.isTailCall(),
095: 182/*invokevirtual*/, Type.pointer_type);
096: code.popScope();
097: }
098:
099: public gnu.bytecode.Type getReturnType(Expression[] args) {
100: return Type.pointer_type; // FIXME
101: }
102: }
|