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

Revision 4275, 37.2 KB (checked in by sukyoungryu, 5 weeks ago)

[self type idiom] Implemented the new self-type idiom proposal.

Line 
1/*******************************************************************************
2 Copyright 2009 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
18package com.sun.fortress.interpreter.evaluator;
19
20import com.sun.fortress.compiler.WellKnownNames;
21import com.sun.fortress.exceptions.FortressException;
22import static com.sun.fortress.exceptions.InterpreterBug.bug;
23import static com.sun.fortress.exceptions.ProgramError.error;
24import static com.sun.fortress.exceptions.ProgramError.errorMsg;
25import com.sun.fortress.interpreter.env.LazilyEvaluatedCell;
26import com.sun.fortress.interpreter.evaluator.types.*;
27import com.sun.fortress.interpreter.evaluator.values.*;
28import com.sun.fortress.nodes.*;
29import com.sun.fortress.nodes_util.ExprFactory;
30import com.sun.fortress.nodes_util.NodeUtil;
31import com.sun.fortress.useful.HasAt;
32import com.sun.fortress.useful.Useful;
33import edu.rice.cs.plt.tuple.Option;
34
35import java.util.List;
36
37/**
38 * This comment is not yet true; it is a goal.
39 * <p/>
40 * BuildEnvironments is a multiple-pass visitor pattern.
41 * <p/>
42 * The first pass, applied to a node that contains things (for example, a
43 * component contains top-level declarations, a trait contains method
44 * declarations) it creates entries for those things in the bindInto
45 * environment.  In the top-level environment, traits and objects export
46 * the names and definitions for the functional methods that they contain.
47 * <p/>
48 * The bindings created are not complete after the first pass.
49 * <p/>
50 * The second pass completes the type initialization. For contained things that
51 * have internal structure (e.g., a trait within a top level list) this may
52 * require a recursive visit, but with a newly allocated environment running its
53 * first and second passes. This includes singleton object types.
54 * <p/>
55 * The third pass initializes functions and methods; these may depend on types.
56 * The third pass must extract functional methods from traits and objects.
57 * <p/>
58 * The fourth pass performs value initialization. These may depend on functions.
59 * This includes singleton object values.
60 * <p/>
61 * The evaluation order is slightly relaxed to make the interpreter tractable;
62 * value cells (and variable cells?) are initialized with thunks. (How do we
63 * thunk a singleton object?)
64 * <p/>
65 * It may be necessary to thunk the types as well; this is not yet entirely
66 * clear because the type system is so complex. Because types already contain
67 * references to their defining environment, this may proceed in an ad-hoc
68 * fashion with lazy memoization.
69 * <p/>
70 * Note that not all passes are required in all contexts; only the top level has
71 * the combination of types, functions, variables, and unordered access.
72 * Different initializations are assigned to different (numbered) passes so that
73 * environment building in some contexts can skip passes (for example, skip the
74 * type pass in any non-top-level environment).
75 */
76public class BuildEnvironments extends NodeAbstractVisitor<Boolean> {
77
78
79    private int pass = 1;
80
81    public void resetPass() {
82        setPass(1);
83    }
84
85    public void assertPass(int p) {
86        if (getPass() != p) bug("Expected pass " + p + " got pass " + getPass());
87    }
88
89    public void secondPass() {
90        assertPass(1);
91        setPass(2);
92        // An environment must be blessed before it can be cloned.
93        bindInto.bless();
94    }
95
96    public void thirdPass() {
97        assertPass(2);
98        setPass(3);
99    }
100
101    public void fourthPass() {
102        assertPass(3);
103        setPass(4);
104    }
105
106    public void visit(CompilationUnit n) {
107        n.accept(this);
108    }
109
110    Environment containing;
111
112    Environment bindInto;
113
114    /**
115     * Creates an environment builder that will inject bindings into 'within'.
116     * The visit is suspended at generics (com.sun.fortress.interpreter.nodes
117     * with type parameters) until they can be instantiated.
118     */
119    public BuildEnvironments(Environment within) {
120        this.containing = within;
121        this.bindInto = within;
122    }
123
124    protected BuildEnvironments(Environment within, Environment bind_into) {
125        this.containing = within;
126        this.bindInto = bind_into;
127    }
128
129    private BuildEnvironments(Environment within, int pass) {
130        this.containing = within;
131        this.bindInto = within;
132        this.setPass(pass);
133    }
134
135    public Environment getEnvironment() {
136        return containing;
137    }
138
139    static FunctionClosure instantiate(FGenericFunction x) {
140        return null;
141    }
142
143    static Constructor instantiate(GenericConstructor x) {
144        return null;
145    }
146
147    static FTypeTrait instantiate(TypeGeneric x) {
148        return null;
149    }
150
151    protected static void doDefs(BuildEnvironments inner, List<Decl> defs) {
152        for (Decl def : defs) {
153            try {
154                def.accept(inner);
155            }
156            catch (FortressException x) {
157                throw x.setWhere(def);
158            }
159        }
160    }
161
162    protected void doDefs(List<Decl> defs) {
163        doDefs(this, defs);
164    }
165
166    //    /**
167    //     * Put the mappings into "into", but create closures against forTraitMethods.
168    //     *
169    //     * @param into
170    //     * @param forTraitMethods
171    //     * @param defs
172    //     * @param fields
173    //     */
174    //    private void doTraitMethodDefs(FTypeTrait ftt, Set<String> fields) {
175    //        BetterEnv into = ftt.getMembers();
176    //        BetterEnv forTraitMethods = ftt.getMethodExecutionEnv();
177    //        List<Decl> defs = ftt.getASTmembers();
178    //
179    //        BuildTraitEnvironment inner = new BuildTraitEnvironment(into,
180    //                forTraitMethods, ftt, fields);
181    //
182    //        inner.doDefs1234(defs);
183    //
184    //    }
185
186    //
187    public void doDefs1234(List<Decl> defs) {
188        doDefs(defs);
189        doDefs234(defs);
190    }
191
192    public void doDefs234(List<Decl> defs) {
193        secondPass();
194        doDefs(defs);
195        thirdPass();
196        doDefs(defs);
197        fourthPass();
198        doDefs(defs);
199    }
200
201    protected void guardedPutValue(Environment e, String name, FValue value, HasAt where) {
202        guardedPutValue(e, name, value, null, where);
203
204    }
205
206    /**
207     * Put a value, perhaps unconditionally depending on subtype's choice
208     *
209     * @param e
210     * @param name
211     * @param value
212     * @param ft
213     */
214    protected void putValue(Environment e, String name, FValue value, FType ft) {
215        e.putVariable(name, value, ft);
216    }
217
218    /**
219     * Put a value, perhaps unconditionally depending on subtype's choice
220     */
221    protected void putValue(Environment e, String name, FValue value) {
222        e.putValue(name, value);
223    }
224
225    protected void guardedPutValue(Environment e, String name, FValue value, FType ft, HasAt where) {
226        try {
227            if (ft != null) {
228                if (!ft.typeMatch(value)) {
229                    error(where, e, errorMsg("Type mismatch binding ",
230                                             value,
231                                             " (type ",
232                                             value.type(),
233                                             ") to ",
234                                             name,
235                                             " (type ",
236                                             ft,
237                                             ")"));
238                }
239                putValue(e, name, value, ft);
240            } else {
241                putValue(e, name, value);
242            }
243        }
244        catch (FortressException pe) {
245            throw pe.setContext(where, e);
246        }
247    }
248
249    protected void guardedPutType(String name, FType type, HasAt where) {
250        EvalType.guardedPutType(name, type, where, containing);
251    }
252
253    protected FValue newGenericClosure(Environment e, FnDecl x) {
254        return new FGenericFunction(e, x);
255    }
256
257
258    private void forFnDecl1(FnDecl x) {
259        List<StaticParam> optStaticParams = NodeUtil.getStaticParams(x);
260        String fname = NodeUtil.nameAsMethod(x);
261        FValue cl;
262
263        if (!optStaticParams.isEmpty()) {
264            cl = newGenericClosure(containing, x);
265        } else {
266            // NOT GENERIC
267            cl = newClosure(containing, x);
268        }
269        // TODO this isn't right if it was a test function.
270        // it belongs in a different namespace if it is.
271        bindInto.putValue(fname, cl); // was "shadow"
272        //LINKER putOrOverloadOrShadowGeneric(x, containing, name, cl);
273    }
274
275    private void forFnDecl2(FnDecl x) {
276    }
277
278    // Overridden in BuildTraitEnvironment
279    protected void forFnDecl3(FnDecl x) {
280        List<StaticParam> optStaticParams = NodeUtil.getStaticParams(x);
281        String fname = NodeUtil.nameAsMethod(x);
282        Fcn fcn = (Fcn) containing.getLeafValue(fname);
283        fcn.finishInitializing();
284    }
285
286    private void forFnDecl4(FnDecl x) {
287    }
288
289    /*
290    * (non-Javadoc)
291    *
292    * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forFnDecl(com.sun.fortress.interpreter.nodes.FnDecl)
293    */
294    @Override
295    public Boolean forFnDecl(FnDecl x) {
296        if (NodeUtil.getBody(x).isNone()) bug("Function definition should have a body expression.");
297
298        switch (getPass()) {
299            case 1:
300                forFnDecl1(x);
301                break;
302            case 2:
303                forFnDecl2(x);
304                break;
305            case 3:
306                forFnDecl3(x);
307                break;
308            case 4:
309                forFnDecl4(x);
310                break;
311        }
312        return null;
313    }
314
315    //    public void putOrOverloadOrShadow(HasAt x, BetterEnv e, IdOrOpOrAnonymousName name,
316    //            Simple_fcn cl) {
317    //        Fcn g = (Fcn) e.getValueNull(name.name());
318    //        if (g == null) {
319    //            putFunction(e, name, cl, x);
320    //
321    //            // This is delicate temporary code (below), and breaks the
322    //            // property that adding another layer of environment is an OK
323    //            // thing to do.
324    //        } else if (g.getWithin().equals(e)) {
325    //            // OVERLOADING
326    //            OverloadedFunction og;
327    //            if (g instanceof OverloadedFunction) {
328    //                og = (OverloadedFunction) g;
329    //                og.addOverload(cl);
330    //            } else if (g instanceof GenericMethodSet
331    //                    || g instanceof GenericMethod) {
332    //                error(x, e,
333    //                        "Cannot combine generic method and nongeneric method "
334    //                                + name.name() + " in an overloading");
335    //            } else if (g instanceof GenericFunctionSet
336    //                    || g instanceof FGenericFunction) {
337    //                error(x, e,
338    //                        "Cannot combine generic function and nongeneric function "
339    //                                + name.name() + " in an overloading");
340    //            } else {
341    //                og = new OverloadedFunction(name, e);
342    //                og.addOverload(cl);
343    //                og.addOverload((Simple_fcn) g);
344    //
345    //                assignFunction(e, name, og);
346    //            }
347    //        } else {
348    //            // SHADOWING
349    //            putFunction(e, name, cl, x);
350    //        }
351    //    }
352
353    //    /**
354    //     * @param x
355    //     * @param e
356    //     * @param name
357    //     * @param cl
358    //     */
359    //    private void putOrOverloadOrShadowGeneric(HasAt x, BetterEnv e,
360    //            IdOrOpOrAnonymousName name, FValue cl) {
361    //        FValue fv = e.getValueNull(name.name());
362    //        if (fv != null && !(fv instanceof Fcn)) {
363    //            error(x, e, "Generic not generic? " + name.name());
364    //        }
365    //        Fcn g = (Fcn) fv;
366    //        // Actually need to test for diff types of g.
367    //        if (g == null) {
368    //            putFunction(e, name, cl, x);
369    //        } else if (g.getWithin().equals(e)) {
370    //            // OVERLOADING
371    //            if (cl instanceof GenericMethod) {
372    //                GenericMethod clg = (GenericMethod) cl;
373    //                GenericMethodSet og;
374    //                if (g instanceof GenericMethodSet) {
375    //                    og = (GenericMethodSet) g;
376    //                    og.addOverload(clg);
377    //                } else if (g instanceof GenericMethod) {
378    //                    og = new GenericMethodSet(name, e);
379    //                    og.addOverload(clg);
380    //                    og.addOverload((GenericMethod) g);
381    //
382    //                    assignFunction(e, name, og);
383    //                } else {
384    //                    error(x, e, "Overload of generic method "
385    //                            + cl + " with non-generic/method " + g);
386    //                }
387    //            } else if (cl instanceof FGenericFunction) {
388    //                FGenericFunction clg = (FGenericFunction) cl;
389    //                GenericFunctionSet og;
390    //                if (g instanceof GenericFunctionSet) {
391    //                    og = (GenericFunctionSet) g;
392    //                    og.addOverload(clg);
393    //                } else if (g instanceof FGenericFunction) {
394    //                    og = new GenericFunctionSet(name, e);
395    //                    og.addOverload(clg);
396    //                    og.addOverload((FGenericFunction) g);
397    //
398    //                    assignFunction(e, name, og);
399    //                } else {
400    //                    error(x, e, "Overload of function method "
401    //                            + cl + " with non-generic/method " + g);
402    //                }
403    //            } else {
404    //                error(x, e,
405    //                        "Overload of generic, but not a method/function" + cl
406    //                                + " with generic/method " + g);
407    //
408    //            }
409    //        } else {
410    //            // SHADOWING
411    //            putFunction(e, name, cl, x);
412    //        }
413    //    }
414
415    protected Simple_fcn newClosure(Environment e, Applicable x) {
416        return new FunctionClosure(e, x);
417    }
418
419    private void putFunction(Environment e, IdOrOpOrAnonymousName name, FValue f, HasAt x) {
420        String s = NodeUtil.nameString(name);
421        guardedPutValue(e, s, f, x);
422        e.noteName(s);
423    }
424
425    private static void assignFunction(Environment e, IdOrOpOrAnonymousName name, FValue f) {
426        e.putValueRaw(NodeUtil.nameString(name), f);
427    }
428
429    /*
430     * (non-Javadoc)
431     *
432     * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forObjectDef(com.sun.fortress.interpreter.nodes.ObjectDecl)
433     */
434    @Override
435    public Boolean forObjectDecl(ObjectDecl x) {
436        switch (getPass()) {
437            case 1:
438                forObjectDecl1(x);
439                break;
440            case 2:
441                forObjectDecl2(x);
442                break;
443            case 3:
444                forObjectDecl3(x);
445                break;
446            case 4:
447                forObjectDecl4(x);
448                break;
449        }
450        return null;
451    }
452
453    protected void forObjectDecl1(ObjectDecl x) {
454        // List<Modifier> mods;
455
456        Environment e = containing;
457        Id name = NodeUtil.getName(x);
458
459        List<StaticParam> staticParams = NodeUtil.getStaticParams(x);
460        Option<List<Param>> params = NodeUtil.getParams(x);
461
462        // List<Type> throws_;
463        // Contract contract;
464        // List<Decl> defs = NodeUtil.getDecls(x);
465        String fname = NodeUtil.nameString(name);
466        FTraitOrObjectOrGeneric ft;
467        ft = staticParams.isEmpty() ?
468             new FTypeObject(fname, e, x, params, NodeUtil.getDecls(x), x) :
469             new FTypeGeneric(e, x, NodeUtil.getDecls(x), x);
470
471        // Need to check for overloaded constructor.
472
473        guardedPutType(fname, ft, x);
474
475        if (params.isSome()) {
476            if (!staticParams.isEmpty()) {
477                // A generic, not yet a constructor
478                GenericConstructor gen = new GenericConstructor(e, x, name);
479                guardedPutValue(containing, fname, gen, x);
480            } else {
481                // TODO need to deal with constructor overloading.
482
483                // If parameters are present, it is really a constructor
484                // BetterEnv interior = new SpineEnv(e, x);
485                Constructor cl = new Constructor(containing, (FTypeObject) ft, x);
486                guardedPutValue(containing, fname, cl, x);
487                // doDefs(interior, defs);
488            }
489
490        } else {
491            if (!staticParams.isEmpty()) {
492                // A parameterized singleton is a sort of generic value.
493                // bug(x,"Generic singleton objects not yet implemented");
494                makeGenericSingleton(x, e, name, fname, ft);
495
496            } else {
497                // It is a singleton; do not expose the constructor, do
498                // visit the interior environment.
499                // BetterEnv interior = new SpineEnv(e, x);
500
501                // TODO - binding into "containing", or "bindInto"?
502
503                Constructor cl = new Constructor(containing, (FTypeObject) ft, x);
504                guardedPutValue(containing, WellKnownNames.obfuscatedSingletonConstructorName(fname, x), cl, x);
505
506                // Create a little expression to run the constructor.
507                Expr init = ExprFactory.makeTightJuxt(NodeUtil.getSpan(x),
508                                                      ExprFactory.makeVarRef(NodeUtil.getSpan(x),
509                                                                             WellKnownNames.obfuscatedSingletonConstructorName(
510                                                                                     fname,
511                                                                                     x),
512                                                                             0),
513                                                      ExprFactory.makeVoidLiteralExpr(NodeUtil.getSpan(x)));
514                FValue init_value = new LazilyEvaluatedCell(init, containing);
515                putValue(bindInto, fname, init_value);
516
517                // doDefs(interior, defs);
518            }
519        }
520
521        scanForFunctionalMethodNames(ft, NodeUtil.getDecls(x));
522
523    }
524
525    private void makeGenericSingleton(ObjectDecl x, Environment e, Id name, String fname, FTraitOrObjectOrGeneric ft) {
526        GenericConstructor gen = new GenericConstructor(e, x, name);
527        guardedPutValue(containing, WellKnownNames.obfuscatedSingletonConstructorName(fname, x), gen, x);
528        guardedPutValue(containing, fname, new GenericSingleton(x, ft, gen), x);
529    }
530
531    public void scanForFunctionalMethodNames(FTraitOrObjectOrGeneric x, List<Decl> defs) {
532        scanForFunctionalMethodNames(x, defs, false);
533    }
534
535    public void scanForFunctionalMethodNames(FTraitOrObjectOrGeneric x, List<Decl> defs, boolean bogus) {
536        // This is probably going away.
537        Environment topLevel = containing;
538        if (getPass() == 1) {
539            x.initializeFunctionalMethods();
540        } else if (getPass() == 3) {
541            x.finishFunctionalMethods();
542        }
543
544    }
545
546
547    private void forObjectDecl2(ObjectDecl x) {
548
549        Environment e = containing;
550        Id name = NodeUtil.getName(x);
551
552        List<StaticParam> staticParams = NodeUtil.getStaticParams(x);
553        Option<List<Param>> params = NodeUtil.getParams(x);
554
555        String fname = NodeUtil.nameString(name);
556        FType ft;
557
558        if (params.isSome()) {
559            if (!staticParams.isEmpty()) {
560                // Do nothing.
561            } else {
562                FTypeObject fto = (FTypeObject) containing.getRootType(fname); // top level
563                FValue xxx = containing.getLeafValue(fname);
564                //Constructor cl = (Constructor) containing.getValue(fname);
565                finishObjectTrait(x, fto);
566            }
567        } else {
568            // If there are no parameters, it is a singleton.
569            // Not clear we can evaluate it yet.
570            if (!staticParams.isEmpty()) {
571                // Do nothing.
572            } else {
573                FTypeObject fto = (FTypeObject) containing.getRootType(fname); // top level
574
575                finishObjectTrait(x, fto);
576            }
577
578        }
579
580    }
581
582    private void forObjectDecl3(ObjectDecl x) {
583        Environment e = containing;
584        Id name = NodeUtil.getName(x);
585
586        List<StaticParam> staticParams = NodeUtil.getStaticParams(x);
587        Option<List<Param>> params = NodeUtil.getParams(x);
588
589        String fname = NodeUtil.nameString(name);
590        FTraitOrObjectOrGeneric ft = (FTraitOrObjectOrGeneric) containing.getRootType(fname); // toplevel
591        if (!staticParams.isEmpty()) {
592            // Do nothing
593        } else if (params.isSome()) {
594            FTypeObject fto = (FTypeObject) ft;
595            Fcn cl = (Fcn) containing.getLeafValue(fname);
596            //                List<Parameter> fparams = EvalType.paramsToParameters(
597            //                        containing, params.unwrap());
598            //                cl.setParams(fparams);
599            cl.finishInitializing();
600        } else {
601            Constructor cl = (Constructor) containing.getLeafValue(WellKnownNames.obfuscatedSingletonConstructorName(
602                    fname,
603                    x));
604            //  cl.setParams(Collections.<Parameter> emptyList());
605            cl.finishInitializing();
606        }
607        scanForFunctionalMethodNames(ft, NodeUtil.getDecls(x));
608    }
609
610    private void forObjectDecl4(ObjectDecl x) {
611
612        Environment e = containing;
613        Id name = NodeUtil.getName(x);
614
615        Option<List<Param>> params = NodeUtil.getParams(x);
616
617        String fname = NodeUtil.nameString(name);
618
619        if (params.isSome()) {
620
621        } else {
622            // TODO - Blindly assuming a non-generic singleton.
623            // TODO - Need to insert the name much, much, earlier; this is too late.
624
625            FValue value = bindInto.getLeafValue(fname);
626
627            //            Constructor cl = (Constructor) containing
628            //                    .getValue(obfuscated(fname));
629            //
630            //            guardedPutValue(containing, fname, cl.apply(java.util.Collections
631            //                    .<FValue> emptyList(), x, e), x);
632
633        }
634    }
635
636
637    private String obfuscatedConstructorName(String fname) {
638        // TODO Auto-generated method stub
639        return "*1_" + fname;
640    }
641
642    /*
643     * (non-Javadoc)
644     *
645     * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forVarDef(com.sun.fortress.interpreter.nodes.VarDecl)
646     */
647    @Override
648    public Boolean forVarDecl(VarDecl x) {
649        switch (getPass()) {
650            case 1:
651                forVarDecl1(x);
652                break;
653            case 2:
654                forVarDecl2(x);
655                break;
656            case 3:
657                forVarDecl3(x);
658                break;
659            case 4:
660                forVarDecl4(x);
661                break;
662        }
663        return null;
664    }
665
666    private void forVarDecl1(VarDecl x) {
667        List<LValue> lhs = x.getLhs();
668
669        // List<Modifier> mods;
670        // Id name = x.getName();
671        // Option<Type> type = x.getType();
672
673        if (x.getInit().isNone()) bug("Variable definition should have an expression.");
674
675        Expr init = x.getInit().unwrap();
676        LValue lvb = lhs.get(0);
677
678        Option<Type> type = lvb.getIdType();
679        Id name = lvb.getName();
680        String sname = NodeUtil.nameString(name);
681
682        try {
683            /* Ignore the type, until later */
684
685            if (lvb.isMutable()) {
686                bindInto.putVariablePlaceholder(sname);
687            } else {
688                FValue init_val = new LazilyEvaluatedCell(init, containing);
689                putValue(bindInto, sname, init_val);
690            }
691        }
692        catch (FortressException pe) {
693            throw pe.setContext(x, bindInto);
694        }
695    }
696
697    private void forVarDecl2(VarDecl x) {
698
699    }
700
701    private void forVarDecl3(VarDecl x) {
702        List<LValue> lhs = x.getLhs();
703
704        Expr init = x.getInit().unwrap();
705        LValue lvb = lhs.get(0);
706
707        Option<Type> type = lvb.getIdType();
708        Id name = lvb.getName();
709        String sname = NodeUtil.nameString(name);
710
711        try {
712            if (lvb.isMutable()) {
713                /*
714                * re-initialize the reference cell of a mutable
715                * late in the game (with the now-available type);
716                * cannot reallocate, because it may have been exported.
717                */
718                FType ft = (new EvalType(containing)).evalType(type.unwrap());
719                FValue value = new LazilyEvaluatedCell(init, containing);
720                bindInto.assignValue(x, sname, value);
721                bindInto.storeType(x, sname, ft);
722            }
723        }
724        catch (FortressException pe) {
725            throw pe.setContext(x, bindInto);
726        }
727
728
729    }
730
731    private void forVarDecl4(VarDecl x) {
732
733        List<LValue> lhs = x.getLhs();
734
735        // List<Modifier> mods;
736        // Id name = x.getName();
737        // Option<Type> type = x.getType();
738        if (x.getInit().isNone()) bug("Variable definition should have an expression.");
739
740        Expr init = x.getInit().unwrap();
741        // int index = 0;
742        LValue lvb = lhs.get(0);
743
744
745        {
746            Option<Type> type = lvb.getIdType();
747            Id name = lvb.getName();
748            String sname = NodeUtil.nameString(name);
749
750            FType ft = type.isSome() ? (new EvalType(containing)).evalType(type.unwrap()) : null;
751
752            if (lvb.isMutable()) {
753                Expr rhs = init;
754
755                FValue value = (new Evaluator(containing)).eval(rhs);
756
757                // TODO When new environment are created, need to insert
758                // into containing AND bindInto
759
760                if (ft != null) {
761                    if (!ft.typeMatch(value)) {
762                        ft = error(x, bindInto, errorMsg("Type mismatch binding ",
763                                                         value,
764                                                         " (type ",
765                                                         value.type(),
766                                                         ") to ",
767                                                         name,
768                                                         " (type ",
769                                                         ft,
770                                                         ")"));
771                    }
772                } else {
773                    ft = FTypeTop.ONLY;
774                }
775                /* Finally, can finish this initialiation. */
776                // bindInto.storeType(x, sname, ft);
777                bindInto.assignValue(x, sname, value);
778            } else {
779                // Force evaluation, snap the link, check the type!
780                FValue value = bindInto.getLeafValue(sname);
781                if (ft != null) {
782                    if (!ft.typeMatch(value)) {
783                        error(x, bindInto, errorMsg("Type mismatch binding ",
784                                                    value,
785                                                    " (type ",
786                                                    value.type(),
787                                                    ") to ",
788                                                    name,
789                                                    " (type ",
790                                                    ft,
791                                                    ")"));
792                    }
793                }
794            }
795        }
796
797    }
798
799    /*
800     * (non-Javadoc)
801     *
802     * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forTraitDef(com.sun.fortress.interpreter.nodes.TraitDecl)
803     */
804    @Override
805    public Boolean forTraitDecl(TraitDecl x) {
806        switch (getPass()) {
807            case 1:
808                forTraitDecl1(x);
809                break;
810            case 2:
811                forTraitDecl2(x);
812                break;
813            case 3:
814                forTraitDecl3(x);
815                break;
816            case 4:
817                forTraitDecl4(x);
818                break;
819        }
820        return null;
821    }
822
823    private void forTraitDecl1(TraitDecl x) {
824        // TODO Auto-generated method stub
825        List<StaticParam> staticParams = NodeUtil.getStaticParams(x);
826        // List<Modifier> mods;
827        Id name = NodeUtil.getName(x);
828        // List<Type> excludes;
829        // Option<List<Type>> bounds;
830        FTraitOrObjectOrGeneric ft;
831
832        String fname = NodeUtil.nameString(name);
833
834        if (!staticParams.isEmpty()) {
835
836            FTypeGeneric ftg = new FTypeGeneric(containing, x, NodeUtil.getDecls(x), x);
837            guardedPutType(fname, ftg, x);
838            //scanForFunctionalMethodNames(ftg, NodeUtil.getDecls(x), ftg);
839            ft = ftg;
840        } else {
841
842            Environment interior = containing; // new BetterEnv(containing, x);
843            FTypeTrait ftt = new FTypeTrait(fname, interior, x, NodeUtil.getDecls(x), x);
844            guardedPutType(fname, ftt, x);
845            //scanForFunctionalMethodNames(ftt, NodeUtil.getDecls(x), ftt);
846            ft = ftt;
847        }
848
849        scanForFunctionalMethodNames(ft, NodeUtil.getDecls(x));
850    }
851
852    private void forTraitDecl2(TraitDecl x) {
853        // TODO Auto-generated method stub
854        List<StaticParam> staticParams = NodeUtil.getStaticParams(x);
855        // List<Modifier> mods;
856        // List<Type> excludes;
857        // Option<List<Type>> bounds;
858
859        if (staticParams.isEmpty()) {
860            Id name = NodeUtil.getName(x);
861            FTypeTrait ftt = (FTypeTrait) containing.getRootType(NodeUtil.nameString(name)); // toplevel
862            Environment interior = ftt.getWithin();
863            finishTrait(x, ftt, interior);
864        }
865    }
866
867    private void forTraitDecl3(TraitDecl x) {
868        Id name = NodeUtil.getName(x);
869        String fname = NodeUtil.nameString(name);
870        FTraitOrObjectOrGeneric ft = (FTraitOrObjectOrGeneric) containing.getRootType(fname); // toplevel
871        scanForFunctionalMethodNames(ft, NodeUtil.getDecls(x));
872    }
873
874    private void forTraitDecl4(TraitDecl x) {
875    }
876
877    /**
878     * @param x
879     * @param ftt
880     * @param interior
881     */
882    public void finishTrait(TraitDecl x, FTypeTrait ftt, Environment interior) {
883        List<BaseType> extends_ = NodeUtil.getTypes(NodeUtil.getExtendsClause(x));
884        // TODO What if I don't
885        // interior = interior.extendAt(x);
886
887        EvalType et;
888        if (NodeUtil.getWhereClause(x).isSome()) et = processWhereClauses(NodeUtil.getWhereClause(x).unwrap(),
889                                                                          interior);
890        else et = new EvalType(interior);
891
892        List<FType> extl = et.getFTypeListFromList(extends_);
893        List<FType> excl = et.getFTypeListFromList(NodeUtil.getExcludesClause(x));
894        ftt.setExtendsAndExcludes(extl, excl, interior);
895        Option<List<NamedType>> comprs = NodeUtil.getComprisesClause(x);
896        if (!comprs.isNone()) {
897            List<FType> c = et.getFTypeListFromList(comprs.unwrap());
898            ftt.setComprises(Useful.<FType>set(c));
899        }
900        List<Decl> fns = NodeUtil.getDecls(x);
901
902        // doTraitMethodDefs(ftt, null); /* NOTICE THE DIFFERENT ENVIRONMENT! */
903
904    }
905
906
907    /**
908     * Processes a where clause,
909     * both using and augmenting the environment
910     * "interior" passed in as a parameter.
911     *
912     * @param wheres
913     * @param interior
914     * @return
915     */
916    private static EvalType processWhereClauses(WhereClause wheres, Environment interior) {
917
918        if (wheres != null) {
919            for (WhereConstraint w : wheres.getConstraints()) {
920                if (w instanceof WhereExtends) {
921                    WhereExtends we = (WhereExtends) w;
922                    Id name = we.getName();
923                    String string_name = NodeUtil.nameString(name);
924                    // List<Type> types = we.getSupers();
925                    FType ft = interior.getLeafTypeNull(string_name); // leaf
926                    if (ft == null) {
927                        ft = new SymbolicWhereType(string_name, interior, we);
928                        interior.putType(string_name, ft);
929                    }
930                } else {
931                    bug(w, errorMsg("Where clause ", w));
932                }
933            }
934        }
935
936        EvalType et = new EvalType(interior);
937
938        if (wheres != null) {
939            for (WhereConstraint w : wheres.getConstraints()) {
940                if (w instanceof WhereExtends) {
941                    WhereExtends we = (WhereExtends) w;
942                    Id name = we.getName();
943                    String string_name = NodeUtil.nameString(name);
944                    List<BaseType> types = we.getSupers();
945                    FType ft = interior.getLeafTypeNull(string_name); // leaf
946                    for (Type t : types) {
947                        FType st = et.evalType(t); // t.visit(et);
948                        if (ft instanceof SymbolicType) {
949                            // Treat as "extends".
950                            ((SymbolicType) ft).addExtend(st);
951                        } else if (st instanceof SymbolicWhereType) {
952                            // Record subtype ft of st.
953                            SymbolicWhereType swt = (SymbolicWhereType) st;
954                            swt.addSubtype(ft);
955                        } else {
956                            ft.mustExtend(st, w);
957                            // Check that constraint holds.
958                            // NI.nyi("need to verify constraint stated in where clause");
959                        }
960                    }
961                } else {
962                    bug(w, errorMsg("Where clause ", w));
963                }
964            }
965        }
966        return et;
967    }
968
969    public void finishObjectTrait(ObjectDecl x, FTypeObject ftt) {
970        List<BaseType> extends_ = NodeUtil.getTypes(NodeUtil.getExtendsClause(x));
971        finishObjectTrait(extends_, null, NodeUtil.getWhereClause(x), ftt, containing, x);
972    }
973
974    public void finishObjectTrait(_RewriteObjectExpr x, FTypeObject ftt) {
975        List<BaseType> extends_ = NodeUtil.getTypes(NodeUtil.getExtendsClause(x));
976        // _RewriteObjectExpr has no excludes clause.
977        finishObjectTrait(extends_, null, null, ftt, containing, x);
978    }
979
980    static public void finishObjectTrait(List<BaseType> extends_,
981                                         List<? extends Type> excludes,
982                                         Option<WhereClause> wheres,
983                                         FTypeObject ftt,
984                                         Environment interior,
985                                         HasAt x) {
986        interior = interior.extendAt(x);
987        EvalType et;
988        if (wheres != null && wheres.isSome()) et = processWhereClauses(wheres.unwrap(), interior);
989        else et = new EvalType(interior);
990        ftt.setExtendsAndExcludes(et.getFTypeListFromList(extends_), et.getFTypeListFromList(excludes), interior);
991
992    }
993
994    /*
995     * (non-Javadoc)
996     *
997     * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forTypeAlias(com.sun.fortress.interpreter.nodes.TypeAlias)
998     */
999    @Override
1000    public Boolean forTypeAlias(TypeAlias x) {
1001        // Id name;
1002        // List<Id> params;
1003        // Type type;
1004        // TODO Auto-generated method stub
1005        return null;
1006    }
1007
1008    /*
1009     * (non-Javadoc)
1010     *
1011     * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forDimUnitDecl(com.sun.fortress.interpreter.nodes.DimUnitDecl)
1012     */
1013    @Override
1014    public Boolean forDimUnitDecl(DimUnitDecl x) {
1015        // TODO Auto-generated method stub
1016
1017        return null;
1018    }
1019
1020    /*
1021     * (non-Javadoc)
1022     *
1023     * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forDimArg(com.sun.fortress.interpreter.nodes.DimArg)
1024     */
1025    @Override
1026    public Boolean forDimArg(DimArg x) {
1027        // TODO Auto-generated method stub
1028        return null;
1029    }
1030
1031    /*
1032     * (non-Javadoc)
1033     *
1034     * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forImportApi(com.sun.fortress.interpreter.nodes.ImportApi)
1035     */
1036    @Override
1037    public Boolean forImportApi(ImportApi x) {
1038        // TODO Auto-generated method stub
1039        return null;
1040    }
1041
1042
1043    /*
1044    * (non-Javadoc)
1045    *
1046    * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forImportNames(com.sun.fortress.interpreter.nodes.ImportNames)
1047    */
1048    @Override
1049    public Boolean forImportNames(ImportNames x) {
1050        // TODO Auto-generated method stub
1051        return null;
1052    }
1053
1054    /*
1055     * (non-Javadoc)
1056     *
1057     * @see com.sun.fortress.interpreter.nodes.NodeVisitor#forImportStar(com.sun.fortress.interpreter.nodes.ImportStar)
1058     */
1059    @Override
1060    public Boolean forImportStar(ImportStar x) {
1061        // TODO Auto-generated method stub
1062        return null;
1063    }
1064
1065    public Environment getBindingEnv() {
1066        return bindInto;
1067    }
1068
1069    @Override
1070    public Boolean forGrammarDecl(GrammarDecl that) {
1071        return null; // Do nothing
1072    }
1073
1074    public void setPass(int pass) {
1075        this.pass = pass;
1076    }
1077
1078    public int getPass() {
1079        return pass;
1080    }
1081
1082
1083}
Note: See TracBrowser for help on using the browser.