KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > kawa > xml > NodeConstructor


1 // Copyright (c) 2001, 2003 Per M.A. Bothner and Brainfood Inc.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

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 JavaDoc) KNode.make((NodeTree) ((XMLFilter) current).out)
30                         : (Object JavaDoc) 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 JavaDoc 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 JavaDoc 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   /** Compile an expression using a fresh NodeTree.
79    * Compare with ConsumerTarget.compileUsingConsumer, but creates a NodeTree.
80    */

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             // For slightly improved code generation. We can potentially use
137
// the faster invokevirtual rather than invokeinterface.
138
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