1 4 package gnu.kawa.xml; 5 import gnu.bytecode.*; 6 import gnu.mapping.*; 7 import gnu.expr.*; 8 import gnu.xml.*; 9 import gnu.lists.*; 10 11 public abstract class NodeConstructor extends MethodProc 12 implements Inlineable 13 { 14 public abstract void compileToNode (ApplyExp exp, Compilation comp, 15 ConsumerTarget target); 16 17 public static XMLFilter pushNodeConsumer (Consumer out) 18 { 19 if (out instanceof XMLFilter) 20 return (XMLFilter) out; 21 else 22 return new XMLFilter(new NodeTree()); 23 } 24 25 public static void popNodeConsumer (Consumer saved, Consumer current) 26 { 27 if (saved != current) 28 saved.writeObject(current instanceof XMLFilter 29 ? (Object ) KNode.make((NodeTree) ((XMLFilter) current).out) 30 : (Object ) current); 31 } 32 33 public static XMLFilter pushNodeContext (CallContext ctx) 34 { 35 Consumer out = ctx.consumer; 36 if (out instanceof XMLFilter) 37 return (XMLFilter) out; 38 else 39 { 40 XMLFilter filter = new XMLFilter(new NodeTree()); 41 ctx.consumer = filter; 42 return filter; 43 } 44 } 45 46 public static void popNodeContext (Consumer saved, CallContext ctx) 47 { 48 Object current = ctx.consumer; 49 if (saved != current) 50 { 51 if (current instanceof XMLFilter) 52 current = KNode.make((NodeTree) ((XMLFilter) current).out); 53 saved.writeObject(current); 54 ctx.consumer = saved; 55 } 56 } 57 58 public static void compileChild (Expression arg, 59 Compilation comp, ConsumerTarget target) 60 { 61 if (arg instanceof ApplyExp) 62 { 63 ApplyExp app = (ApplyExp) arg; 64 Expression func = app.getFunction(); 65 if (func instanceof QuoteExp) 66 { 67 Object proc = ((QuoteExp) func).getValue(); 68 if (proc instanceof NodeConstructor) 69 { 70 ((NodeConstructor) proc).compileToNode(app, comp, target); 71 return; 72 } 73 } 74 } 75 arg.compileWithPosition(comp, target); 76 } 77 78 81 public static void compileUsingNodeTree(Expression exp, 82 Compilation comp, Target target) 83 { 84 Method makeMethod = typeNodeConstructor.getDeclaredMethod("makeNode", 0); 85 Method makeKNodeMethod = typeNodeConstructor.getDeclaredMethod("finishNode", 1); 86 ConsumerTarget.compileUsingConsumer(exp, comp, target, 87 makeMethod, makeKNodeMethod); 88 } 89 90 public static XMLFilter makeNode () 91 { 92 return new XMLFilter(new NodeTree()); 93 } 94 95 public static KNode finishNode (XMLFilter filter) 96 { 97 return KNode.make((NodeTree) filter.out); 98 } 99 100 public void compile (ApplyExp exp, Compilation comp, Target target) 101 { 102 if (target instanceof IgnoreTarget) 103 ApplyExp.compile(exp, comp, target); 104 else if (! (target instanceof ConsumerTarget)) 105 compileUsingNodeTree(exp, comp, target); 106 else 107 { 108 ConsumerTarget ctarget = (ConsumerTarget) target; 109 Variable cvar = ctarget.getConsumerVariable(); 110 Type ctype = cvar.getType(); 111 if (ctype.isSubtype(typeXMLFilter)) 112 compileToNode(exp, comp, ctarget); 113 else 114 { 115 Expression[] args = exp.getArgs(); 116 int nargs = args.length; 117 CodeAttr code = comp.getCode(); 118 Scope scope = code.pushScope(); 119 Variable saved 120 = scope.addVariable(code, Compilation.typeConsumer, null); 121 code.emitLoad(cvar); 122 code.emitStore(saved); 123 if (ctarget.isContextTarget()) 124 { 125 comp.loadCallContext(); 126 code.emitInvokeStatic(pushNodeContextMethod); 127 } 128 else 129 { 130 code.emitLoad(cvar); 131 code.emitInvokeStatic(pushNodeConsumerMethod); 132 } 133 code.emitStore(cvar); 134 code.emitTryStart(true, Type.void_type); 135 Type saveType = cvar.getType(); 136 cvar.setType(typeXMLFilter); 139 compileToNode(exp, comp, ctarget); 140 cvar.setType(saveType); 141 code.emitTryEnd(); 142 code.emitFinallyStart(); 143 code.emitLoad(saved); 144 if (ctarget.isContextTarget()) 145 { 146 comp.loadCallContext(); 147 code.emitInvokeStatic(popNodeContextMethod); 148 } 149 else 150 { 151 code.emitLoad(cvar); 152 code.emitInvokeStatic(popNodeConsumerMethod); 153 } 154 code.emitLoad(saved); 155 code.emitStore(cvar); 156 code.emitFinallyEnd(); 157 code.emitTryCatchEnd(); 158 code.popScope(); 159 } 160 } 161 } 162 163 public Type getReturnType (Expression[] args) 164 { 165 return Compilation.typeObject; 166 } 167 168 static final ClassType typeXMLFilter 169 = ClassType.make("gnu.xml.XMLFilter"); 170 static final ClassType typeKNode 171 = ClassType.make("gnu.kawa.xml.KNode"); 172 static final ClassType typeNodeConstructor 173 = ClassType.make("gnu.kawa.xml.NodeConstructor"); 174 static final Method pushNodeContextMethod 175 = typeNodeConstructor.getDeclaredMethod("pushNodeContext", 1); 176 static final Method popNodeContextMethod 177 = typeNodeConstructor.getDeclaredMethod("popNodeContext", 2); 178 static final Method pushNodeConsumerMethod 179 = typeNodeConstructor.getDeclaredMethod("pushNodeConsumer", 1); 180 static final Method popNodeConsumerMethod 181 = typeNodeConstructor.getDeclaredMethod("popNodeConsumer", 2); 182 } 183 | Popular Tags |