| 1 4 package gnu.xquery.util; 5 import gnu.lists.*; 6 import gnu.mapping.*; 7 import gnu.bytecode.*; 8 import gnu.expr.*; 9 import gnu.kawa.xml.*; 10 import gnu.math.IntNum; 11 import gnu.kawa.functions.AddOp; 12 import gnu.kawa.functions.NumberCompare; 13 import gnu.kawa.functions.ValuesMap; 14 15 public class ValuesFilter extends MethodProc implements CanInline, Inlineable 16 { 17 19 char kind; 20 21 public ValuesFilter (char kind) 22 { 23 this.kind = kind; 24 } 25 26 public static ValuesFilter get (char kind) 27 { 28 if (kind == 'F') return forwardFilter; 29 else if (kind == 'R') return reverseFilter; 30 else return exprFilter; 31 } 32 33 36 int last_or_position_needed = 2; 37 38 public int numArgs() { return 0x2002; } 39 40 static public boolean matches(Object result, long count) 41 { 42 if (result instanceof Values) 43 result = ((Values) result).canonicalize(); 44 if (result instanceof Number ) 45 { 46 if (result instanceof IntNum) 47 return IntNum.compare((IntNum) result, count) == 0; 48 if (result instanceof Double || result instanceof Float  49 || result instanceof gnu.math.DFloNum) 50 return ((Number ) result).doubleValue() == (double) count; 51 if (result instanceof Long || result instanceof Integer  52 || result instanceof Short || result instanceof Byte ) 53 return count == ((Number ) result).longValue(); 54 return NumberCompare.applyWithPromotion(Compare.TRUE_IF_EQU, 56 IntNum.make(count), 57 result); 58 } 59 return BooleanValue.booleanValue(result); 60 } 61 62 public void apply (CallContext ctx) throws Throwable  63 { 64 Object arg = ctx.getNextArg(); 65 Procedure proc = (Procedure) ctx.getNextArg(); 66 Consumer out = ctx.consumer; 67 Values values; 68 if (kind != 'P') 69 { 70 SortedNodes nodes = new SortedNodes(); 71 Values.writeValues(arg, nodes); 72 values = nodes; 73 } 74 else if (arg instanceof Values) 75 values = (Values) arg; 76 else 77 { 78 IntNum one = IntNum.one(); 79 if (matches(proc.apply3(arg, one, one), 1)) 80 out.writeObject(arg); 81 return; 82 } 83 int count = values.size(); 84 int it = 0; 85 IntNum countObj = IntNum.make(count); 86 int pmax = proc.maxArgs(); 89 for (int i = 0; i < count; i++) 90 { 91 it = values.nextPos(it); 92 Object dot = values.getPosPrevious(it); 93 int pos = kind == 'R' ? (count - i) : (i + 1); 94 IntNum posObj = IntNum.make(pos); 95 Object pred_res = pmax == 2 ? proc.apply2(dot, posObj) 96 : proc.apply3(dot, posObj, countObj); 97 if (matches(pred_res, pos)) 98 out.writeObject(dot); 99 } 100 return; 101 } 102 103 public Expression inline (ApplyExp exp, ExpWalker walker) 104 { 105 Expression[] args = exp.getArgs(); 106 Expression exp2 = args[1]; 107 LambdaExp lexp2; 108 if (! (exp2 instanceof LambdaExp) 109 || (lexp2 = (LambdaExp) exp2).min_args != 3 110 || lexp2.max_args != 3) 111 return exp; 112 113 exp.setType(args[0].getType()); 114 115 Compilation parser = walker.getCompilation(); 116 117 Declaration dotArg = lexp2.firstDecl(); 118 Declaration posArg = dotArg.nextDecl(); 119 Declaration lastArg = posArg.nextDecl(); 120 121 lexp2.setInlineOnly(true); 122 lexp2.returnContinuation = exp; 123 124 lexp2.remove(posArg, lastArg); 126 lexp2.min_args = 2; 127 lexp2.max_args = 2; 128 129 if (! lastArg.getCanRead() && kind != 'R') 130 { 131 return exp; 133 } 134 135 parser.letStart(); 136 Expression seq = args[0]; 137 Type seqType; 138 Method sizeMethod; 139 if (kind == 'P') 140 { 141 seqType = seq.getType(); 142 sizeMethod = Compilation.typeValues.getDeclaredMethod("countValues", 1); 143 } 144 else 145 { 146 seqType = SortNodes.typeSortedNodes; 147 seq = new ApplyExp(SortNodes.sortNodes, new Expression [] {seq}); 148 sizeMethod = CoerceNodes.typeNodes.getDeclaredMethod("size", 0); 149 } 150 Declaration sequence = parser.letVariable("sequence", seqType, seq); 151 parser.letEnter(); 152 153 Expression pred = lexp2.body; 154 if (kind == 'R') 155 { 156 Declaration posIncoming = new Declaration(null, Type.int_type); 157 Expression init 158 = new ApplyExp(AddOp.$Mn, 159 new Expression[] { 160 new ReferenceExp(lastArg), 161 new ReferenceExp(posIncoming)}); 162 init 163 = new ApplyExp(AddOp.$Pl, 164 new Expression[] { 165 init, 166 new QuoteExp(IntNum.one())}); 167 LetExp let = new LetExp(new Expression[] { init }); 168 lexp2.replaceFollowing(dotArg, posIncoming); 169 let.add(posArg); 170 let.body = pred; 171 pred = let; 172 } 173 174 Type predType = lexp2.body.getType(); 175 if (predType != XDataType.booleanType) pred = new ApplyExp(matchesMethod, 177 new Expression[] { pred, 178 new ReferenceExp(posArg) }); 179 pred = new IfExp(pred, 180 new ReferenceExp(dotArg), 181 QuoteExp.voidExp); 182 lexp2.body = pred; 183 184 ApplyExp doMap 185 = new ApplyExp(ValuesMap.valuesMapWithPos, 186 new Expression[] { lexp2, 187 new ReferenceExp(sequence) }); 188 doMap.setType(dotArg.getType()); 189 lexp2.returnContinuation = doMap; 190 191 Expression lastInit = new ApplyExp(sizeMethod, 192 new Expression[] { 193 new ReferenceExp(sequence)}); 194 195 LetExp let2 = new LetExp(new Expression[] { lastInit }); 196 let2.add(lastArg); 197 let2.body = ValuesMap.valuesMapWithPos.inline(doMap, walker); 198 199 200 return parser.letDone(let2); 201 } 202 203 public void compile (ApplyExp exp, Compilation comp, Target target) 204 { 205 Expression[] args = exp.getArgs(); 206 Expression exp1 = args[0]; 207 Expression exp2 = args[1]; 208 if (target instanceof IgnoreTarget) 209 { 210 exp1.compile(comp, target); 211 exp2.compile(comp, target); 212 return; 213 } 214 if (! (exp2 instanceof LambdaExp)) 215 { 216 ApplyExp.compile(exp, comp, target); 217 return; 218 } 219 220 if (! (target instanceof ConsumerTarget)) 221 { 222 ConsumerTarget.compileUsingConsumer(exp, comp, target); 223 return; 224 } 225 227 LambdaExp lexp2 = (LambdaExp) exp2; 229 ValuesMap.compileInlined(lexp2, exp1, 1, matchesMethod, comp, target); 230 } 231 232 public Type getReturnType (Expression[] args) 233 { 234 return Type.pointer_type; 237 } 238 239 public static final ValuesFilter forwardFilter = new ValuesFilter('F'); 240 public static final ValuesFilter reverseFilter = new ValuesFilter('R'); 241 public static final ValuesFilter exprFilter = new ValuesFilter('P'); 242 public static final ClassType typeValuesFilter 243 = ClassType.make("gnu.xquery.util.ValuesFilter"); 244 public static final Method matchesMethod 245 = typeValuesFilter.getDeclaredMethod("matches", 2); 246 } 247 | Popular Tags |