root/trunk/ProjectFortress/src/com/sun/fortress/interpreter/evaluator/BuildEnvironments.java

Revision 2755, 46.7 kB (checked in by dr2chase, 2 weeks ago)

Fixes for compiled environments -- mostly they work, but are switched off, under property fortress.test.compiled.environments

Line 
1 /*******************************************************************************
2     Copyright 2008 Sun Microsystems, Inc.,
3     4150 Network Circle, Santa Clara, California 95054, U.S.A.
4     All rights reserved.
5
6     U.S. Government Rights - Commercial software.
7     Government users are subject to the Sun Microsystems, Inc. standard
8     license agreement and applicable provisions of the FAR and its supplements.
9
10     Use is subject to license terms.
11
12     This distribution may include materials developed by third parties.
13
14     Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered
15     trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
16  ******************************************************************************/
17
18 package com.sun.fortress.interpreter.evaluator;
19
20 import java.util.Iterator;
21 import java.util.List;
22 import edu.rice.cs.plt.tuple.Option;
23
24 import com.sun.fortress.useful.Useful;
25 import com.sun.fortress.exceptions.FortressException;
26 import com.sun.fortress.interpreter.env.FortressTests;
27 import com.sun.fortress.interpreter.env.LazilyEvaluatedCell;
28 import com.sun.fortress.interpreter.evaluator.types.FTraitOrObjectOrGeneric;
29 import com.sun.fortress.interpreter.evaluator.types.FType;
30 import com.sun.fortress.interpreter.evaluator.types.FTypeGeneric;
31 import com.sun.fortress.interpreter.evaluator.types.FTypeObject;
32 import com.sun.fortress.interpreter.evaluator.types.FTypeTop;
33 import com.sun.fortress.interpreter.evaluator.types.FTypeTrait;
34 import com.sun.fortress.interpreter.evaluator.types.SymbolicType;
35 import com.sun.fortress.interpreter.evaluator.types.SymbolicWhereType;
36 import com.sun.fortress.interpreter.evaluator.types.TypeGeneric;
37 import com.sun.fortress.interpreter.evaluator.values.Closure;
38 import com.sun.fortress.interpreter.evaluator.values.Constructor;
39 import com.sun.fortress.interpreter.evaluator.values.FGenericFunction;
40 import com.sun.fortress.interpreter.evaluator.values.FValue;
41 import com.sun.fortress.interpreter.evaluator.values.FVoid;
42 import com.sun.fortress.interpreter.evaluator.values.Fcn;
43 import com.sun.fortress.interpreter.evaluator.values.GenericConstructor;
44 import com.sun.fortress.interpreter.evaluator.values.GenericSingleton;
45 import com.sun.fortress.interpreter.evaluator.values.Simple_fcn;
46 import com.sun.fortress.interpreter.glue.WellKnownNames;
47 import com.sun.fortress.nodes.*;
48 import com.sun.fortress.nodes_util.Applicable;
49 import com.sun.fortress.nodes_util.ExprFactory;
50 import com.sun.fortress.nodes_util.NodeUtil;
51 import com.sun.fortress.useful.HasAt;
52
53 import static com.sun.fortress.exceptions.InterpreterBug.bug;
54 import static com.sun.fortress.exceptions.ProgramError.error;
55 import static com.sun.fortress.exceptions.ProgramError.errorMsg;
56
57 /**
58  * This comment is not yet true; it is a goal.
59  *
60  * BuildEnvironments is a multiple-pass visitor pattern.
61  *
62  * The first pass, applied to a node that contains things (for example, a
63  * component contains top-level declarations, a trait contains method
64  * declarations) it creates entries for those things in the bindInto
65  * environment.  In the top-level environment, traits and objects export
66  * the names and definitions for the functional methods that they contain.
67  *
68  * The bindings created are not complete after the first pass.
69  *
70  * The second pass completes the type initialization. For contained things that
71  * have internal structure (e.g., a trait within a top level list) this may
72  * require a recursive visit, but with a newly allocated environment running its
73  * first and second passes. This includes singleton object types.
74  *
75  * The third pass initializes functions and methods; these may depend on types.
76  * The third pass must extract functional methods from traits and objects.
77  *
78  * The fourth pass performs value initialization. These may depend on functions.
79  * This includes singleton object values.
80  *
81  * The evaluation order is slightly relaxed to make the interpreter tractable;
82  * value cells (and variable cells?) are initialized with thunks. (How do we
83  * thunk a singleton object?)
84  *
85  * It may be necessary to thunk the types as well; this is not yet entirely
86  * clear because the type system is so complex. Because types already contain
87  * references to their defining environment, this may proceed in an ad-hoc
88  * fashion with lazy memoization.
89  *
90  * Note that not all passes are required in all contexts; only the top level has
91  * the combination of types, functions, variables, and unordered access.
92  * Different initializations are assigned to different (numbered) passes so that
93  * environment building in some contexts can skip passes (for example, skip the
94  * type pass in any non-top-level environment).
95  *
96  */
97 public class BuildEnvironments extends NodeAbstractVisitor<Boolean> {
98
99
100      private int pass = 1;
101
102     public void resetPass() {
103         setPass(1);
104     }
105
106     public void assertPass(int p) {
107         if (getPass() != p)
108             bug("Expected pass " + p + " got pass " + getPass());
109     }
110
111     public void secondPass() {
112         assertPass(1);
113         setPass(2);
114         // An environment must be blessed before it can be cloned.
115         bindInto.bless();
116     }
117
118     public void thirdPass() {
119         assertPass(2);
120         setPass(3);
121     }
122
123     public void fourthPass() {
124         assertPass(3);
125         setPass(4);
126     }
127
128     public void visit(CompilationUnit n) {
129         n.accept(this);
130     }
131
132     Environment containing;
133
134     Environment bindInto;
135
136     /**
137      * Creates an environment builder that will inject bindings into 'within'.
138      * The visit is suspended at generics (com.sun.fortress.interpreter.nodes
139      * with type parameters) until they can be instantiated.
140      */
141     public BuildEnvironments(Environment within) {
142         this.containing = within;
143         this.bindInto = within;
144     }
145
146     protected BuildEnvironments(Environment within, Environment bind_into) {
147         this.containing = within;
148         this.bindInto = bind_into;
149     }
150
151     private BuildEnvironments(Environment within, int pass) {
152         this.containing = within;
153         this.bindInto = within;
154         this.setPass(pass);
155     }
156
157     public Environment getEnvironment() {
158         return containing;
159     }
160
161     static Closure instantiate(FGenericFunction x) {
162         return null;
163     }
164
165     static Constructor instantiate(GenericConstructor x) {
166         return null;
167     }
168
169     static FTypeTrait instantiate(TypeGeneric x) {
170         return null;
171     }
172
173
174
175
176      protected static void doDefs(BuildEnvironments inner, List<? extends AbsDeclOrDecl> defs) {
177         for (AbsDeclOrDecl def : defs) {
178             def.accept(inner);
179         }
180     }
181
182     protected void doDefs(List<? extends AbsDeclOrDecl> defs) {
183         for (AbsDeclOrDecl def : defs) {
184             def.accept(this);
185         }
186     }
187
188 //    /**
189 //     * Put the mappings into "into", but create closures against forTraitMethods.
190 //     *
191 //     * @param into
192 //     * @param forTraitMethods
193 //     * @param defs
194 //     * @param fields
195 //     */
196 //    private void doTraitMethodDefs(FTypeTrait ftt, Set<String> fields) {
197 //        BetterEnv into = ftt.getMembers();
198 //        BetterEnv forTraitMethods = ftt.getMethodExecutionEnv();
199 //        List<? extends AbsDeclOrDecl> defs = ftt.getASTmembers();
200 //
201 //        BuildTraitEnvironment inner = new BuildTraitEnvironment(into,
202 //                forTraitMethods, ftt, fields);
203 //
204 //        inner.doDefs1234(defs);
205 //
206 //    }
207 //
208     public void doDefs1234(List<? extends AbsDeclOrDecl> defs) {
209         doDefs(defs);
210         doDefs234(defs);
211     }
212
213     public void doDefs234(List<? extends AbsDeclOrDecl> defs) {
214         secondPass();
215         doDefs(defs);
216         thirdPass();
217         doDefs(defs);
218         fourthPass();
219         doDefs(defs);
220     }
221
222     protected void guardedPutValue(Environment e, String name, FValue value,
223             HasAt where) {
224         guardedPutValue(e, name, value, null, where);
225
226     }
227
228     /**
229      * Put a value, perhaps unconditionally depending on subtype's choice
230      * @param e
231      * @param name
232      * @param value
233      * @param ft
234      */
235     protected void putValue(Environment e, String name, FValue value, FType ft) {
236         e.putVariable(name, value, ft);
237     }
238
239     /**
240      * Put a value, perhaps unconditionally depending on subtype's choice
241      */
242     protected void putValue(Environment e, String name, FValue value) {
243         e.putValue(name, value);
244     }
245
246     protected void guardedPutValue(Environment e, String name, FValue value,
247             FType ft, HasAt where) {
248         try {
249             if (ft != null) {
250                 if (!ft.typeMatch(value)) {
251                     error(where, e,
252                             errorMsg("Type mismatch binding ", value, " (type ",
253                                      value.type(), ") to ", name, " (type ",
254                                      ft, ")"));
255                 }
256                 putValue(e, name, value, ft);
257             } else {
258                 putValue(e, name, value);
259             }
260         } catch (FortressException pe) {
261             throw pe.setContext(where,e);
262         }
263     }
264
265     protected void guardedPutType(String name, FType type, HasAt where) {
266         EvalType.guardedPutType(name, type, where, containing);
267     }
268
269     protected FValue newGenericClosure(Environment e, FnAbsDeclOrDecl x) {
270         return new FGenericFunction(e, x);
271     }
272
273
274
275     private void forFnDef1(FnDef x) {
276         List<StaticParam> optStaticParams = x.getStaticParams();
277         String fname = NodeUtil.nameAsMethod(x);
278         FValue cl;
279
280         if (!optStaticParams.isEmpty()) {
281             cl = newGenericClosure(containing, x);
282         } else {
283             // NOT GENERIC
284             cl = newClosure(containing, x);
285
286             // Search for test modifier -- can't we have a generic test modifier?
287             List<Modifier> mods = x.getMods();
288             if (!mods.isEmpty()) {
289                 for (Iterator<Modifier> i = mods.iterator(); i.hasNext();) {
290                     Modifier m = i.next();
291                     if (m instanceof ModifierTest) {
292                         FortressTests.add((Closure) cl);
293                         break;
294                     }
295                 }
296             }
297         }
298         // TODO this isn't right if it was a test function.
299         // it belongs in a different namespace if it is.
300         bindInto.putValue(fname, cl); // was "shadow"
301         //LINKER putOrOverloadOrShadowGeneric(x, containing, name, cl);
302
303     }
304
305    private void forFnDef2(FnDef x) {
306    }
307
308    // Overridden in BuildTraitEnvironment
309    protected void forFnDef3(FnDef x) {
310        List<StaticParam> optStaticParams = x.getStaticParams();
311        String fname = NodeUtil.nameAsMethod(x);
312        Fcn fcn = (Fcn)containing.getValue(fname);
313        fcn.finishInitializing();
314    }
315
316    private void forFnDef4(FnDef x) {
317    }
318
319  /*
320      * (non-Javadoc)
321      *
322      * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forFnDef(com.sun.fortress.interpreter.nodes.FnDef)
323      */
324     @Override
325     public Boolean forFnDef(FnDef x) {
326         switch (getPass()) {
327         case 1: forFnDef1(x); break;
328         case 2: forFnDef2(x); break;
329         case 3: forFnDef3(x); break;
330         case 4: forFnDef4(x); break;
331         }
332        return null;
333     }
334
335 //    public void putOrOverloadOrShadow(HasAt x, BetterEnv e, IdOrOpOrAnonymousName name,
336 //            Simple_fcn cl) {
337 //        Fcn g = (Fcn) e.getValueNull(name.name());
338 //        if (g == null) {
339 //            putFunction(e, name, cl, x);
340 //
341 //            // This is delicate temporary code (below), and breaks the
342 //            // property that adding another layer of environment is an OK
343 //            // thing to do.
344 //        } else if (g.getWithin().equals(e)) {
345 //            // OVERLOADING
346 //            OverloadedFunction og;
347 //            if (g instanceof OverloadedFunction) {
348 //                og = (OverloadedFunction) g;
349 //                og.addOverload(cl);
350 //            } else if (g instanceof GenericMethodSet
351 //                    || g instanceof GenericMethod) {
352 //                error(x, e,
353 //                        "Cannot combine generic method and nongeneric method "
354 //                                + name.name() + " in an overloading");
355 //            } else if (g instanceof GenericFunctionSet
356 //                    || g instanceof FGenericFunction) {
357 //                error(x, e,
358 //                        "Cannot combine generic function and nongeneric function "
359 //                                + name.name() + " in an overloading");
360 //            } else {
361 //                og = new OverloadedFunction(name, e);
362 //                og.addOverload(cl);
363 //                og.addOverload((Simple_fcn) g);
364 //
365 //                assignFunction(e, name, og);
366 //            }
367 //        } else {
368 //            // SHADOWING
369 //            putFunction(e, name, cl, x);
370 //        }
371 //    }
372
373 //    /**
374 //     * @param x
375 //     * @param e
376 //     * @param name
377 //     * @param cl
378 //     */
379 //    private void putOrOverloadOrShadowGeneric(HasAt x, BetterEnv e,
380 //            IdOrOpOrAnonymousName name, FValue cl) {
381 //        FValue fv = e.getValueNull(name.name());
382 //        if (fv != null && !(fv instanceof Fcn)) {
383 //            error(x, e, "Generic not generic? " + name.name());
384 //        }
385 //        Fcn g = (Fcn) fv;
386 //        // Actually need to test for diff types of g.
387 //        if (g == null) {
388 //            putFunction(e, name, cl, x);
389 //        } else if (g.getWithin().equals(e)) {
390 //            // OVERLOADING
391 //            if (cl instanceof GenericMethod) {
392 //                GenericMethod clg = (GenericMethod) cl;
393 //                GenericMethodSet og;
394 //                if (g instanceof GenericMethodSet) {
395 //                    og = (GenericMethodSet) g;
396 //                    og.addOverload(clg);
397 //                } else if (g instanceof GenericMethod) {
398 //                    og = new GenericMethodSet(name, e);
399 //                    og.addOverload(clg);
400 //                    og.addOverload((GenericMethod) g);
401 //
402 //                    assignFunction(e, name, og);
403 //                } else {
404 //                    error(x, e, "Overload of generic method "
405 //                            + cl + " with non-generic/method " + g);
406 //                }
407 //            } else if (cl instanceof FGenericFunction) {
408 //                FGenericFunction clg = (FGenericFunction) cl;
409 //                GenericFunctionSet og;
410 //                if (g instanceof GenericFunctionSet) {
411 //                    og = (GenericFunctionSet) g;
412 //                    og.addOverload(clg);
413 //                } else if (g instanceof FGenericFunction) {
414 //                    og = new GenericFunctionSet(name, e);
415 //                    og.addOverload(clg);
416 //                    og.addOverload((FGenericFunction) g);
417 //
418 //                    assignFunction(e, name, og);
419 //                } else {
420 //                    error(x, e, "Overload of function method "
421 //                            + cl + " with non-generic/method " + g);
422 //                }
423 //            } else {
424 //                error(x, e,
425 //                        "Overload of generic, but not a method/function" + cl
426 //                                + " with generic/method " + g);
427 //
428 //            }
429 //        } else {
430 //            // SHADOWING
431 //            putFunction(e, name, cl, x);
432 //        }
433 //    }
434
435     protected Simple_fcn newClosure(Environment e, Applicable x) {
436         return new Closure(e, x);
437     }
438
439     private void putFunction(Environment e, IdOrOpOrAnonymousName name, FValue f, HasAt x) {
440         String s = NodeUtil.nameString(name);
441         guardedPutValue(e, s, f, x);
442         e.noteName(s);
443     }
444
445     private static void assignFunction(Environment e, IdOrOpOrAnonymousName name, FValue f) {
446         e.putValueRaw(NodeUtil.nameString(name), f);
447     }
448
449     /*
450      * (non-Javadoc)
451      *
452      * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forObjectDef(com.sun.fortress.interpreter.nodes.ObjectDecl)
453      */
454     @Override
455     public Boolean forObjectDecl(ObjectDecl x) {
456         switch (getPass()) {
457         case 1: forObjectDecl1(x); break;
458         case 2: forObjectDecl2(x); break;
459         case 3: forObjectDecl3(x); break;
460         case 4: forObjectDecl4(x); break;
461         }
462        return null;
463     }
464     protected void forObjectDecl1(ObjectDecl x) {
465         // List<Modifier> mods;
466
467         Environment e = containing;
468         Id name = x.getName();
469
470         List<StaticParam> staticParams = x.getStaticParams();
471         Option<List<Param>> params = x.getParams();
472
473         // List<Type> throws_;
474         // List<WhereClause> where;
475         // Contract contract;
476         // List<Decl> defs = x.getDecls();
477         String fname = NodeUtil.nameString(name);
478         FTraitOrObjectOrGeneric ft;
479         ft = staticParams.isEmpty() ?
480                   new FTypeObject(fname, e, x, params, x.getDecls(), x)
481                 : new FTypeGeneric(e, x, x.getDecls(), x);
482
483         // Need to check for overloaded constructor.
484
485         guardedPutType(fname, ft, x);
486
487         if (params.isSome()) {
488             if (!staticParams.isEmpty()) {
489                 // A generic, not yet a constructor
490                 GenericConstructor gen = new GenericConstructor(e, x, name);
491                 guardedPutValue(containing, fname, gen, x);
492             } else {
493                 // TODO need to deal with constructor overloading.
494
495                 // If parameters are present, it is really a constructor
496                 // BetterEnv interior = new SpineEnv(e, x);
497                 Constructor cl = new Constructor(containing, (FTypeObject) ft,
498                         x);
499                 guardedPutValue(containing, fname, cl, x);
500                 // doDefs(interior, defs);
501             }
502
503         } else {
504             if (!staticParams.isEmpty()) {
505                 // A parameterized singleton is a sort of generic value.
506                 // bug(x,"Generic singleton objects not yet implemented");
507                 makeGenericSingleton(x, e, name, fname, ft);
508
509             } else {
510                 // It is a singleton; do not expose the constructor, do
511                 // visit the interior environment.
512                 // BetterEnv interior = new SpineEnv(e, x);
513
514                 // TODO - binding into "containing", or "bindInto"?
515
516                 Constructor cl = new Constructor(containing, (FTypeObject) ft,
517                         x);
518                 guardedPutValue(containing, WellKnownNames.obfuscatedSingletonConstructorName(fname, x), cl, x);
519
520                 // Create a little expression to run the constructor.
521                 Expr init = ExprFactory.makeTightJuxt(x.getSpan(),
522                       ExprFactory.makeVarRef(x.getSpan(), WellKnownNames.obfuscatedSingletonConstructorName(fname, x), 0),
523                       ExprFactory.makeVoidLiteralExpr(x.getSpan()));
524                 FValue init_value = new LazilyEvaluatedCell(init, containing);
525                 putValue(bindInto, fname, init_value);
526
527                 // doDefs(interior, defs);
528             }
529         }
530
531         scanForFunctionalMethodNames(ft, x.getDecls());
532
533     }
534
535     private void makeGenericSingleton(ObjectAbsDeclOrDecl x, Environment e, Id name,
536             String fname, FTraitOrObjectOrGeneric ft) {
537         GenericConstructor gen = new GenericConstructor(e, x, name);
538         guardedPutValue(containing, WellKnownNames.obfuscatedSingletonConstructorName(fname, x), gen, x);
539         guardedPutValue(containing, fname, new GenericSingleton(x,ft, gen), x);
540     }
541
542     public void scanForFunctionalMethodNames(
543             FTraitOrObjectOrGeneric x,
544             List<? extends AbsDeclOrDecl> defs) {
545         scanForFunctionalMethodNames(x, defs, false);
546     }
547
548     public void scanForFunctionalMethodNames(FTraitOrObjectOrGeneric x,
549             List<? extends AbsDeclOrDecl> defs, boolean bogus) {
550         // This is probably going away.
551         Environment topLevel = containing;
552         if (getPass() == 1) {
553             x.initializeFunctionalMethods();
554         } else if (getPass() == 3) {
555             x.finishFunctionalMethods();
556         }
557
558     }
559
560
561      private void forObjectDecl2(ObjectDecl x) {
562
563         Environment e = containing;
564         Id name = x.getName();
565
566         List<StaticParam> staticParams = x.getStaticParams();
567         Option<List<Param>> params = x.getParams();
568
569         String fname = NodeUtil.nameString(name);
570         FType ft;
571
572         if (params.isSome()) {
573             if (!staticParams.isEmpty()) {
574                 // Do nothing.
575             } else {
576                 FTypeObject fto = (FTypeObject) containing.getType(fname);
577                 FValue xxx = containing.getValue(fname);
578                 //Constructor cl = (Constructor) containing.getValue(fname);
579                 finishObjectTrait(x, fto);
580             }
581         } else {
582             // If there are no parameters, it is a singleton.
583             // Not clear we can evaluate it yet.
584             if (!staticParams.isEmpty()) {
585                 // Do nothing.
586             } else {
587                 FTypeObject fto = (FTypeObject) containing.getType(fname);
588
589                 finishObjectTrait(x, fto);
590             }
591
592         }
593
594     }
595     private void forObjectDecl3(ObjectDecl x) {
596         Environment e = containing;
597         Id name = x.getName();
598
599         List<StaticParam> staticParams = x.getStaticParams();
600         Option<List<Param>> params = x.getParams();
601
602         String fname = NodeUtil.nameString(name);
603         FTraitOrObjectOrGeneric ft = (FTraitOrObjectOrGeneric) containing.getType(fname);
604         if (!staticParams.isEmpty()) {
605             // Do nothing
606         } else if (params.isSome()) {
607             FTypeObject fto = (FTypeObject) ft;
608             Fcn cl = (Fcn) containing.getValue(fname);
609 //                List<Parameter> fparams = EvalType.paramsToParameters(
610 //                        containing, params.unwrap());
611 //                cl.setParams(fparams);
612             cl.finishInitializing();
613         } else {
614             Constructor cl = (Constructor) containing
615                 .getValue(WellKnownNames.obfuscatedSingletonConstructorName(fname, x));
616             //  cl.setParams(Collections.<Parameter> emptyList());
617             cl.finishInitializing();
618         }
619         scanForFunctionalMethodNames(ft, x.getDecls());
620     }
621     private void forObjectDecl4(ObjectDecl x) {
622
623         Environment e = containing;
624         Id name = x.getName();
625
626         Option<List<Param>> params = x.getParams();
627
628         String fname = NodeUtil.nameString(name);
629
630         if (params.isSome()) {
631
632         } else {
633             // TODO - Blindly assuming a non-generic singleton.
634             // TODO - Need to insert the name much, much, earlier; this is too late.
635
636             FValue value = bindInto.getValue(fname);
637
638 //            Constructor cl = (Constructor) containing
639 //                    .getValue(obfuscated(fname));
640 //
641 //            guardedPutValue(containing, fname, cl.apply(java.util.Collections
642 //                    .<FValue> emptyList(), x, e), x);
643
644         }
645     }
646
647
648     private String obfuscatedConstructorName(String fname) {
649         // TODO Auto-generated method stub
650         return "*1_" + fname;
651     }
652
653     /*
654      * (non-Javadoc)
655      *
656      * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forVarDef(com.sun.fortress.interpreter.nodes.VarDecl)
657      */
658     @Override
659     public Boolean forVarDecl(VarDecl x) {
660         switch (getPass()) {
661         case 1:
662             forVarDecl1(x);
663             break;
664         case 2:
665             forVarDecl2(x);
666             break;
667         case 3:
668             forVarDecl3(x);
669             break;
670         case 4:
671             forVarDecl4(x);
672             break;
673         }
674         return null;
675     }
676
677     private void forVarDecl1(VarDecl x) {
678         List<LValueBind> lhs = x.getLhs();
679
680         // List<Modifier> mods;
681         // Id name = x.getName();
682         // Option<Type> type = x.getType();
683         Expr init = x.getInit();
684         LValueBind lvb = lhs.get(0);
685
686           Option<Type> type = lvb.getType();
687           Id name = lvb.getName();
688           String sname = NodeUtil.nameString(name);
689
690           try {
691               /* Ignore the type, until later */
692               if (lvb.isMutable()) {
693                   bindInto.putVariablePlaceholder(sname);
694               } else {
695                   FValue init_val = new LazilyEvaluatedCell(init, containing);
696                   putValue(bindInto, sname, init_val);
697               }
698           } catch (FortressException pe) {
699               throw pe.setContext(x,bindInto);
700           }
701
702 //        int index = 0;
703
704 //        for (LValue lv : lhs) {
705 //            if (lv instanceof LValueBind) {
706 //                LValueBind lvb = (LValueBind) lv;
707 //                Option<Type> type = lvb.getType();
708 //                Id name = lvb.getName();
709 //                String sname = name.getName();
710 //
711 //                try {
712 //                    /* Ignore the type, until later */
713 //                    if (lvb.isMutable()) {
714 //                        bindInto.putVariablePlaceholder(sname);
715 //                    } else {
716 //                        FValue init_val;
717 //                        if (init instanceof ArgExpr) {
718 //                            init_val = new LazilyEvaluatedCell(
719 //                                      ((ArgExpr)init).getExprs().get(index++),
720 //                                      containing);
721 //                        } else {
722 //                            init_val = new LazilyEvaluatedCell(init, containing);
723 //                        }
724 //                        putValue(bindInto, sname, init_val);
725 //                    }
726 //                } catch (FortressError pe) {
727 //                    throw pe.setContext(x,bindInto);
728 //                }
729 //
730 //            } else {
731 //                bug(x, "Don't support arbitary LHS in Var decl yet");
732 //            }
733 //        }
734     }
735
736     private void forVarDecl2(VarDecl x) {
737
738     }
739
740     private void forVarDecl3(VarDecl x) {
741
742
743     }
744
745     private void forVarDecl4(VarDecl x) {
746
747         List<LValueBind> lhs = x.getLhs();
748
749         // List<Modifier> mods;
750         // Id name = x.getName();
751         // Option<Type> type = x.getType();
752         Expr init = x.getInit();
753         // int index = 0;
754         LValueBind lvb = lhs.get(0);
755
756
757          {
758                 Option<Type> type = lvb.getType();
759                 Id name = lvb.getName();
760                 String sname = NodeUtil.nameString(name);
761
762                 FType ft = type.isSome() ?
763                         (new EvalType(containing)).evalType(type.unwrap())
764                                 : null;
765
766                 if (lvb.isMutable()) {
767                     Expr rhs = init;
768
769                     FValue value = (new Evaluator(containing)).eval(rhs);
770
771                     // TODO When new environment are created, need to insert
772                     // into containing AND bindInto
773
774                     if (ft != null) {
775                         if (!ft.typeMatch(value)) {
776                             ft = error(x, bindInto,
777                                     errorMsg("Type mismatch binding ", value, " (type ",
778                                              value.type(), ") to ", name, " (type ",
779                                              ft, ")"));
780                         }
781                     } else {
782                         ft = FTypeTop.ONLY;
783                     }
784                     /* Finally, can finish this initialiation. */
785                     bindInto.storeType(x, sname, ft);
786                     bindInto.assignValue(x, sname, value);
787                 } else {
788                     // Force evaluation, snap the link, check the type!
789                     FValue value = bindInto.getValue(sname);
790                     if (ft != null) {
791                         if (!ft.typeMatch(value)) {
792                             error(x, bindInto,
793                                   errorMsg("Type mismatch binding ", value, " (type ",
794                                   value.type(), ") to ", name, " (type ",
795                                   ft, ")"));
796                         }
797         &nb