KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > expr > LetExp


1 package gnu.expr;
2 import gnu.bytecode.*;
3 import gnu.mapping.*;
4
5 /**
6  * Class used to implement "let" syntax (and variants) for Scheme.
7  * @author Per Bothner
8  */

9
10 public class LetExp extends ScopeExp
11 {
12   public Expression[] inits;
13   public Expression body;
14
15   public LetExp (Expression[] i) { inits = i; }
16
17   public Expression getBody() { return body; }
18   public void setBody(Expression body) { this.body = body; }
19
20   protected boolean mustCompile () { return false; }
21
22   public void apply (CallContext ctx) throws Throwable JavaDoc
23   {
24     setIndexes();
25     int level = ScopeExp.nesting(this);
26     int i = frameSize;
27     
28     Object JavaDoc[] evalFrame = new Object JavaDoc[i];
29     Object JavaDoc[][] evalFrames = ctx.evalFrames;
30     if (evalFrames == null)
31       {
32         evalFrames = new Object JavaDoc[level+10][];
33         ctx.evalFrames = evalFrames;
34       }
35     else if (level >= evalFrames.length)
36       {
37         Object JavaDoc[][] newFrames = new Object JavaDoc[level+10][];
38         System.arraycopy(evalFrames, 0, newFrames, 0, evalFrames.length);
39         ctx.evalFrames = evalFrames = newFrames;
40       }
41     evalFrames[level] = evalFrame;
42
43     try
44       {
45         i = 0;
46         for (Declaration decl = firstDecl(); decl != null;
47              decl = decl.nextDecl(), i++)
48           {
49             Expression init = inits[i];
50             if (init == QuoteExp.undefined_exp)
51               continue;
52             Object JavaDoc value = init.eval(ctx);
53             Type type = decl.type;
54             if (type != null && type != Type.pointer_type)
55               value = type.coerceFromObject(value);
56             if (decl.isIndirectBinding())
57               {
58                 gnu.mapping.Location loc = decl.makeIndirectLocationFor();
59                 loc.set(value);
60                 value = loc;
61               }
62             evalFrame[i] = value;
63           }
64         body.apply(ctx);
65       }
66     finally
67       {
68         evalFrames[level] = null;
69       }
70   }
71
72   /* CPS:
73    * Need to ensure that ctx.pc is 0 before the this is called
74    * the first time. This is currently done by match0.
75    * Need to define concention so ReferenceExp can find appropriate binding.
76    * Need to define convention for what gets copied, if anything,
77    * when a continuation is created. (Note problem below if a half-initialized
78    * frame gets captuerd. Then multiple cals to the same continuation
79    * could clobber the frame, unless it has been copied. But copying the
80    * frame is tricky if we want to avoid copying the whole stack, plus we
81    * have to correctly handle set! to a local/
82   public void apply (CallContext ctx) throws Throwable
83   {
84     CallFrame fr;
85     if (ctx.pc == 0)
86       {
87     fr = new gnu.mapping.CallFrame();
88     fr.previous = ctx.frame;
89     fr.saveVstackLen = ctx.startFromContext();
90     ctx.frame = fr;
91       }
92     else
93       fr = ctx.frame;
94     int i = ctx.pc;
95     if (i == inits.length + 1)
96       {
97     // pop
98     ctx.frame = fr.previous;
99     return;
100       }
101     if (i > 0)
102       fr.values[i-1] = ctx.getFromContext(fr.saveVstackLen);
103     ctx.pc++;
104     if (i == inits.length)
105       {
106         body.match0(ctx);
107     return;
108       }
109     fr.saveVstackLen = ctx.startFromContext();
110     inits[i].match0(ctx);
111   }
112   */

113
114   /* Recursive helper routine, to store the values on the stack
115    * into the variables in vars, in reverse order. */

116   void store_rest (Compilation comp, int i, Declaration decl)
117   {
118     if (decl != null)
119       {
120     store_rest (comp, i+1, decl.nextDecl());
121     if (decl.needsInit())
122       {
123         if (decl.isIndirectBinding())
124           {
125         CodeAttr code = comp.getCode();
126         if (inits[i] == QuoteExp.undefined_exp)
127           {
128             Object JavaDoc name = decl.getSymbol();
129             comp.compileConstant(name, Target.pushObject);
130             code.emitInvokeStatic(BindingInitializer.makeLocationMethod(name));
131           }
132         else
133           {
134             decl.pushIndirectBinding(comp);
135           }
136           }
137             decl.compileStore(comp);
138       }
139       }
140   }
141
142   public void compile (Compilation comp, Target target)
143   {
144     gnu.bytecode.CodeAttr code = comp.getCode();
145
146     /*
147     if (comp.usingCPStyle())
148       {
149     for (Declartion decl = firstDecl(); decl != null; decl = decl.nextDecl())
150       {
151         decl.assignField(comp);
152       }
153      }
154     */

155
156     /* Compile all the initializations, leaving the results
157        on the stack (in reverse order). */

158     Declaration decl = firstDecl();
159     for (int i = 0; i < inits.length; i++, decl = decl.nextDecl())
160       {
161     Target varTarget;
162     Expression init = inits[i];
163         boolean needsInit = decl.needsInit();
164     if (needsInit)
165           decl.allocateVariable(code);
166     if (! needsInit
167         || (decl.isIndirectBinding() && init == QuoteExp.undefined_exp))
168       varTarget = Target.Ignore;
169     else
170       {
171         Type varType = decl.getType();
172         varTarget = CheckedTarget.getInstance(varType);
173         if (init == QuoteExp.undefined_exp)
174           {
175         // Typically created by letrec.
176
if (varType instanceof PrimType)
177           init = new QuoteExp(new Byte JavaDoc((byte) 0));
178         else if (varType != null && varType != Type.pointer_type)
179           init = QuoteExp.nullExp;
180           }
181       }
182     init.compile (comp, varTarget);
183       }
184
185     code.enterScope(getVarScope());
186
187     /* Assign the initial values to the proper variables, in reverse order. */
188     store_rest (comp, 0, firstDecl());
189
190     body.compileWithPosition(comp, target);
191     popScope(code);
192   }
193
194   public final gnu.bytecode.Type getType()
195   {
196     return body.getType();
197   }
198
199   protected Expression walk (ExpWalker walker)
200   {
201     return walker.walkLetExp(this);
202   }
203
204   public void walkInitializers (ExpWalker walker)
205   {
206     Declaration decl = firstDecl();
207     for (int i = 0; i < inits.length; i++, decl = decl.nextDecl())
208       {
209         Expression init0 = inits[i];
210         Expression init = walker.walk(init0);
211         inits[i] = init;
212         if (decl.value == init0)
213           decl.value = init;
214       }
215   }
216
217   protected void walkChildren(ExpWalker walker)
218   {
219     walkInitializers(walker);
220     if (walker.exitValue == null)
221       body = (Expression) walker.walk(body);
222   }
223
224   public void print (OutPort out)
225   {
226     print(out, "(Let", ")");
227   }
228
229   public void print (OutPort out, String JavaDoc startTag, String JavaDoc endTag)
230   {
231     out.startLogicalBlock(startTag+"#"+id, endTag, 2);
232     out.writeSpaceFill();
233     printLineColumn(out);
234     out.startLogicalBlock("(", false, ")");
235     Declaration decl = firstDecl();
236     int i = 0;
237     
238     for (; decl != null; decl = decl.nextDecl())
239       {
240     if (i > 0)
241       out.writeSpaceFill();
242     out.startLogicalBlock("(", false, ")");
243     decl.printInfo(out);
244     if (inits != null)
245       {
246         out.writeSpaceFill();
247         out.print('=');
248         out.writeSpaceFill();
249         //if (decl.isArtificial ())
250
//out.print ("<artificial>");
251
//else
252
{
253           if (i >= inits.length)
254         out.print("<missing init>");
255           else if (inits[i] == null)
256         out.print("<null>");
257           else
258         inits[i].print(out);
259           i++;
260         }
261       }
262     out.endLogicalBlock(")");
263       }
264     out.endLogicalBlock(")");
265     out.writeSpaceLinear();
266     if (body == null)
267       out.print("<null body>");
268     else
269       body.print (out);
270     out.endLogicalBlock(endTag);
271   }
272 }
273
Popular Tags