root/trunk/ProjectFortress/src/com/sun/fortress/interpreter/rewrite/DesugarerVisitor.java

Revision 4300, 60.1 KB (checked in by jmaessen, 3 weeks ago)

[codegen, typechecking] Single inheritance of methods. Uses java
inheritance from boilerplate classes. Multiple inheritance is coming,
but will require wrappers for methods inherited from traits other than
the leftmost (enumerating exactly these methods could prove a bit
fiddly).

Fixed typechecker so that method applications that use an implicit
receiver (_RewriteFnApp nodes) are transformed into dotted method
applications (MethodInvocation nodes). This is done after type
checking in order to avoid some unusual corner cases in the type of
self in object expressions. As these expressions must be hoisted
before code generation, this is the least of our troubles on that
front.

Did some minor tweaks to conversions between java and Scala types to
use idioms for List conversion recommended by the Scala community;
this seems to speed compilation up noticeably during testing. Some
more care may be warranted here; more careful code generation
for FortressAst.scala in astgen may produce big payoffs in run time.

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.rewrite;
19
20import com.sun.fortress.compiler.WellKnownNames;
21import static com.sun.fortress.exceptions.InterpreterBug.bug;
22import static com.sun.fortress.exceptions.ProgramError.error;
23import static com.sun.fortress.exceptions.ProgramError.errorMsg;
24import com.sun.fortress.interpreter.evaluator.Environment;
25import com.sun.fortress.nodes.*;
26import static com.sun.fortress.nodes_util.DesugarerUtil.*;
27import com.sun.fortress.nodes_util.*;
28import com.sun.fortress.useful.*;
29import edu.rice.cs.plt.iter.IterUtil;
30import edu.rice.cs.plt.tuple.Option;
31import edu.rice.cs.plt.tuple.Wrapper;
32
33import java.io.IOException;
34import java.util.*;
35
36public class DesugarerVisitor extends NodeUpdateVisitor implements HasRewrites {
37
38    private boolean suppressDebugDump;
39    private final static boolean debug = false;
40
41    private class Thing implements InterpreterNameRewriter {
42        int objectNestedness;
43        int lexicalNestedness;
44
45        Thing() {
46            objectNestedness = objectNestingDepth;
47            lexicalNestedness = lexicalNestingDepth;
48        }
49
50        public boolean equals(Object o) {
51            if (o.getClass() == getClass()) {
52                Thing that = (Thing) o;
53                if (that.objectNestedness == this.objectNestedness && that.lexicalNestedness == this.lexicalNestedness)
54                    return true;
55            }
56            return false;
57        }
58
59        /**
60         * May assume {@code original} has a non-zero length.
61         */
62        public Expr replacement(VarRef original) {
63            return ExprFactory.makeVarRef(original, lexicalNestedness);
64        }
65
66        public BoolRef replacement(BoolRef original) {
67            return NodeFactory.makeBoolRef(original, lexicalNestedness);
68        }
69
70        public IntRef replacement(IntRef original) {
71            return NodeFactory.makeIntRef(original, lexicalNestedness);
72        }
73
74        public Expr replacement(FnRef original) {
75            return ExprFactory.makeFnRef(original, lexicalNestedness);
76        }
77
78        public Expr replacement(OpRef original) {
79            return ExprFactory.makeOpRef(original, lexicalNestedness);
80        }
81
82        public VarType replacement(VarType original) {
83            return NodeFactory.makeVarType(original, lexicalNestedness);
84        }
85        //        TraitType replacement(TraitType original) {
86        //            return NodeFactory.makeTraitType(original);
87
88        //        }
89        public String toString() {
90            return "Thing@" + objectNestedness + "/" + lexicalNestedness;
91        }
92    }
93
94    private class Local extends Thing {
95        public String toString() {
96            return "Local@" + objectNestedness + "/" + lexicalNestedness;
97        }
98    }
99
100    public class FunctionalMethod extends Local {
101        FunctionalMethod() {
102            super();
103            objectNestedness = 0;
104            lexicalNestedness = 0;
105        }
106
107        public String toString() {
108            return "FunctionalMethod@" + objectNestedness + "/" + lexicalNestedness;
109        }
110    }
111
112    /**
113     * Traits need to identify their declaration, for purposes of figuring out
114     * what names are in scope, though not necessarily what they mean.
115     */
116    private class Trait extends Local {
117        TraitDecl defOrDecl;
118        Map<String, InterpreterNameRewriter> env;
119
120        Trait(TraitDecl dod, Map<String, InterpreterNameRewriter> env) {
121            defOrDecl = dod;
122            this.env = env;
123        }
124
125        public String toString() {
126            return "Trait=" + defOrDecl;
127        }
128
129        public boolean equals(Object o) {
130            if (super.equals(o)) {
131                Trait that = (Trait) o;
132                // Conservative definition for now.
133                // Full "equals" applied to "env" would probably not terminate
134                // because of cycles.
135                return (that.defOrDecl == this.defOrDecl && that.env == this.env);
136            }
137            return false;
138        }
139    }
140
141
142    static Id filterQID(Id qid) {
143        if (qid.getApiName().isNone()) return qid;
144        return bug("Not yet prepared for QIDs ref'd through self/parent, QID=" + NodeUtil.dump(qid));
145    }
146
147    private class Member extends Thing {
148        Member() {
149            super();
150        }
151
152        @Override
153        public Expr replacement(VarRef original) {
154            return ExprFactory.makeFieldRef(NodeUtil.getSpan(original),
155                                            // Use this constructor
156                                            // here because it is a
157                                            // rewrite.
158                                            dottedReference(NodeUtil.getSpan(original),
159                                                            objectNestingDepth - objectNestedness),
160                                            filterQID(original.getVarId()));
161        }
162
163        public String toString() {
164            return "Member@" + objectNestedness + "/" + lexicalNestedness;
165        }
166    }
167
168    private class SelfRewrite extends Member {
169        SelfRewrite() {
170        }
171
172        public Expr replacement(VarRef original) {
173            Expr expr = dottedReference(NodeUtil.getSpan(original), objectNestingDepth - objectNestedness);
174            return expr;
175        }
176
177        public String toString() {
178            return "Self(self)@" + objectNestedness + "/" + lexicalNestedness;
179        }
180    }
181
182    /**
183     * Rewritings in scope.
184     */
185    private BATree<String, InterpreterNameRewriter> rewrites;
186
187    public Map<String, InterpreterNameRewriter> getRewrites() {
188        return rewrites.copy();
189    }
190
191    /*
192     * The next four methods all do the same thing,
193     * but the intent is indicated in case it becomes
194     * necessary to maintain separate rewritings (this is
195     * an issue if the same name is defined in different
196     * ways at different lexical depths; need to check
197     * whether that is allowed, or might become allowed).
198     */
199    public InterpreterNameRewriter var_rewrites_put(String k, InterpreterNameRewriter d) {
200        return rewrites.put(k, d);
201    }
202
203    public InterpreterNameRewriter obj_rewrites_put(String k, InterpreterNameRewriter d) {
204        return rewrites.put(k, d);
205    }
206
207    public InterpreterNameRewriter rewrites_put(String k, InterpreterNameRewriter d) {
208        return rewrites.put(k, d);
209    }
210
211    public InterpreterNameRewriter type_rewrites_put(String k, InterpreterNameRewriter d) {
212        return rewrites.put(k, d);
213    }
214
215    /**
216     * Things that are arrow-typed (used to avoid method-invoking self fields)
217     */
218    private BASet<String> arrows;
219
220    /**
221     * Generic parameters currently in scope.
222     */
223    private BATree<String, StaticParam> visibleGenericParameters;
224    private BATree<String, StaticParam> usedGenericParameters;
225
226    public BASet<String> functionals;
227
228    /**
229     * Experimental -- when would this ever apply?
230     *
231     * @param s
232     */
233    protected void noteUse(String s, VarRef vre) {
234        if (!functionals.contains(s)) Debug.debug(Debug.Type.INTERPRETER, 2, s, " used at ", vre.at());
235    }
236
237    /**
238     * All the object exprs (this may generalize to nested functions as well)
239     * need to have their gensym'd types and constructors registered at the
240     * top level.  The top level environment is available to the creator/caller
241     * of Disambiguate.
242     */
243    private List<_RewriteObjectExpr> objectExprs = new ArrayList<_RewriteObjectExpr>();
244
245    DesugarerVisitor(BATree<String, InterpreterNameRewriter> initial,
246                     BATree<String, StaticParam> initialGenericScope,
247                     BASet<String> initialArrows,
248                     BASet<String> initialFunctionals) {
249        rewrites = initial;
250        arrows = initialArrows;
251        visibleGenericParameters = initialGenericScope;
252        usedGenericParameters = new BATree<String, StaticParam>(StringHashComparer.V);
253        functionals = initialFunctionals;
254        // packages = new BASet<String>(StringHashComparer.V);
255    }
256
257    /**
258     * Returns a new DesugarerVisitor.
259     *
260     * @param suppressDebugDump normally true for everything but files mentioned on the command line.
261     * @param list
262     */
263    public DesugarerVisitor(boolean suppressDebugDump) {
264        this(new BATree<String, InterpreterNameRewriter>(StringHashComparer.V),
265             new BATree<String, StaticParam>(StringHashComparer.V),
266             new BASet<String>(StringHashComparer.V),
267             new BASet<String>(StringHashComparer.V));
268        this.suppressDebugDump = suppressDebugDump;
269    }
270
271    /**
272     * Zero outside of an object, equal to the number of Object[Exprs] or traits
273     * enclosing the current node.
274     * <p/>
275     * When objects are entered, all the symbols defined there are associated
276     * with a depth; when a var reference is rewritten, the symbol used depends
277     * on the number. If the numbers match, then use the surrounding method's
278     * default name for self. If the name is some outer method's name for self,
279     * it should suffice to use it (it should work). If the numbers do not
280     * match, presumably the symbol's number is smaller than current, and it
281     * will be bound in the surrounding environment.
282     * <p/>
283     * Local variables are normally just captured, because the constructor
284     * carries them around, but those from the top level surrounding methods
285     * defined in traits are captured differently, and must be noted with a
286     * special "*TRAIT" symbol (optimization; if any such methods occur, they
287     * should be noted, and if not noted then a specialization step can be
288     * dodged later).
289     * <p/>
290     * Actually, probably not; the construction of trait environments should get
291     * this right without this additional frob (this is much, much less hacky).
292     */
293    int objectNestingDepth;
294
295    /**
296     * Zero for toplevel, otherwise equal to the number of enclosing scopes,
297     * for some definition of scope.  The definition of scope will be adjusted
298     * as is convenient to the implementation.
299     */
300    int lexicalNestingDepth;
301
302    boolean inTrait;
303
304    boolean atTopLevelInsideTraitOrObject = false; // true immediately within a trait/object
305
306    BATree<String, Boolean> immediateDef = null;
307
308    Expr newName(VarRef vre, String s) {
309        InterpreterNameRewriter t = rewrites.get(s);
310
311        if (NodeUtil.isSingletonObject(vre)) {
312            if (t == null) {
313                noteUse(s, vre);
314                return vre;
315            } else {
316                return t.replacement(vre);
317            }
318        } else {
319            if (t == null) {
320                noteUse(s, vre);
321                return vre;
322            } else {
323                return t.replacement(vre);
324            }
325        }
326    }
327
328    Expr newName(OpRef vre, String s) {
329        InterpreterNameRewriter t = rewrites.get(s);
330        if (t == null) {
331            return vre;
332        } else {
333            return t.replacement(vre);
334        }
335
336    }
337
338    BoolRef newName(BoolRef vre, String s) {
339        InterpreterNameRewriter t = rewrites.get(s);
340        if (t == null) {
341            return vre;
342        } else {
343            return t.replacement(vre);
344        }
345
346    }
347
348    IntRef newName(IntRef vre, String s) {
349        InterpreterNameRewriter t = rewrites.get(s);
350        if (t == null) {
351            return vre;
352        } else {
353            return t.replacement(vre);
354        }
355
356    }
357
358    NamedType newType(VarType nt, String s) {
359
360        InterpreterNameRewriter t = rewrites.get(s);
361        if (t == null) {
362            return nt;
363        } else {
364            return t.replacement(nt);
365        }
366    }
367
368    //   NamedType newType(TraitType nt, String s) {
369    //
370    //       Thing t = rewrites.get(s);
371    //       if (t == null) {
372    //           return nt;
373    //       } else {
374    //           return t.replacement(nt);
375    //       }
376    //   }
377
378    //    Iterable<Id> newName(Iterable<Id> ids, String s) {
379    //        Thing t = e.get(s);
380    //        if (t == null) {
381    //            return ids;
382    //        } else {
383    //            return t.replacement(ids);
384    //        }
385    //    }
386
387    /**
388     * Returns the proper name for the object enclosing a method/field; either
389     * "self/notself", or "*parent."^N "self", where N is nesting depth.
390     *
391     * @param s
392     * @param i
393     * @return
394     */
395    Expr dottedReference(Span s, int i) {
396        if (i == 0) {
397            return ExprFactory.makeVarRef(s, WellKnownNames.secretSelfName, -1);
398        }
399        if (i > 0) {
400            return ExprFactory.makeFieldRef(s, dottedReference(s, i - 1), NodeFactory.makeId(s,
401                                                                                             WellKnownNames.secretParentName));
402        } else {
403            throw new Error("Confusion in member reference numbering.");
404        }
405
406    }
407
408    /**
409     * Inserts visible top-level names into the maps used by the desugarer.
410     *
411     * @param tlnode
412     */
413    public void preloadTopLevel(CompilationUnit tlnode) {
414        if (tlnode instanceof Component) {
415            // Iterate over definitions, collecting mapping from name
416            // to node.
417            // TODO - we may need to separate this out some more because of
418            // circular dependences between type names. See above.
419            Component com = (Component) tlnode;
420            List<Decl> defs = com.getDecls();
421            defsToLocals(defs);
422            functionalMethodsOfDefsToLocals(defs);
423        } else if (tlnode instanceof Api) {
424            // Iterate over definitions, collecting mapping from name
425            // to node.
426            // TODO - we may need to separate this out some more because of
427            // circular dependences between type names. See above.
428            Api com = (Api) tlnode;
429            List<Decl> defs = com.getDecls();
430            defsToLocals(defs);
431            functionalMethodsOfDefsToLocals(defs);
432        }
433
434    }
435
436    public boolean injectAtTopLevel(String putName,
437                                    String getName,
438                                    Map<String, InterpreterNameRewriter> getFrom,
439                                    Set<String> excluded) {
440        InterpreterNameRewriter th = getFrom.get(getName);
441        InterpreterNameRewriter old = rewrites.get(putName);
442        /* Empty means do  add */
443        if (old == null) {
444            rewrites_put(putName, th);
445            return true;
446        }
447        /* Equal means no change */
448        if (old.equals(th)) return false;
449        excluded.add(putName);
450        rewrites.remove(putName);
451
452        return true;
453
454    }
455
456    /**
457     * The helper visitor takes the place of "super.forWhatever".
458     * This simplifies translation of code from the reflective visitor,
459     * and also allows easy spearation (below) of the normal recursion from
460     * the within-trait-or-object recursion (visitNode, visitNodeTO).
461     */
462    final NodeUpdateVisitor helper = new NodeUpdateVisitor() {
463        @Override
464        public Node recur(Node that) {
465            return DesugarerVisitor.this.recur(that);
466        }
467
468        /**
469         * Optionally splices in the contents of a RewriteHackList
470         * returned from a visit; otherwise, it is just like the supertype's
471         * implementation.  Inspection (and testing) of the code reveals
472         * that RewriteHackList are only returned into lists of Decl, so this
473         * is the only override that is necessary.
474         */
475        @Override
476        public List<Decl> recurOnListOfDecl(List<Decl> that) {
477            List<Decl> accum = new java.util.ArrayList<Decl>();
478            boolean unchanged = true;
479            for (Decl elt : that) {
480                Node node = recur(elt);
481
482                if (node instanceof RewriteHackList) {
483                    /*
484                     * Assume change, if someone went to the trouble to return
485                     * one of these.
486                     */
487                    unchanged = false;
488                    for (Node nnode : ((RewriteHackList) node).getNodes()) {
489                        accum.add((Decl) nnode);
490                    }
491                } else {
492                    Decl update_elt = (Decl) node;
493                    unchanged &= (elt == update_elt);
494                    accum.add(update_elt);
495                }
496            }
497            return unchanged ? that : accum;
498        }
499
500    };
501
502    /**
503     * Explicit recursion, from anything that is not a trait or an object.
504     * All things that can appear at the top level of a trait or object use
505     * explicit recursive calls.
506     *
507     * @param that
508     * @return
509     */
510    public AbstractNode visitNode(Node that) {
511        atTopLevelInsideTraitOrObject = false;
512        return (AbstractNode) that.accept(helper);
513    }
514
515    /**
516     * Explicit recursion from a trait or object.
517     * Leaves atTopLevelInsideTraitOrObject unchanged.
518     *
519     * @param that
520     * @return
521     */
522    public AbstractNode visitNodeTO(Node that) {
523        return (AbstractNode) that.accept(helper);
524    }
525
526    /**
527     * Recursion into descendant nodes is wrapped in a save/restore/filter
528     * of the various maps and state variables set in desugarer's walk over
529     * the AST.
530     */
531    @Override
532    public Node recur(Node that) {
533
534        BATree<String, InterpreterNameRewriter> savedE = rewrites;
535        rewrites = rewrites.copy();
536
537        BASet<String> savedA = arrows;
538        arrows = arrows.copy();
539
540        BATree<String, StaticParam> savedVisibleGenerics = visibleGenericParameters;
541        visibleGenericParameters = visibleGenericParameters.copy();
542
543        BATree<String, StaticParam> savedUsedGenerics = usedGenericParameters;
544        usedGenericParameters = usedGenericParameters.copy();
545
546        BATree<String, Boolean> savedImmediateDef = immediateDef;
547        immediateDef = null;
548
549        boolean savedFnDeclIsMethod = atTopLevelInsideTraitOrObject;
550        int savedObjectNestingDepth = objectNestingDepth;
551        int savedLexicalNestingDepth = lexicalNestingDepth;
552
553        /*
554         * TRUE RECURSION HERE
555         */
556        Node returned_node = that.accept(this);
557
558        rewrites = savedE;
559        arrows = savedA;
560        // Copy references from enclosed into enclosing.
561        // Set true for all strings s in savedVisible
562        // such that s is not in the immediately-defined set
563        // (the immediate definition shadows) and where
564        // used(s) is true.
565        for (String s : savedVisibleGenerics.keySet()) {
566            if (immediateDef == null || !immediateDef.containsKey(s)) {
567                StaticParam tp = usedGenericParameters.get(s);
568                if (tp != null) savedUsedGenerics.put(s, tp);
569            }
570        }
571        visibleGenericParameters = savedVisibleGenerics;
572        usedGenericParameters = savedUsedGenerics;
573        atTopLevelInsideTraitOrObject = savedFnDeclIsMethod;
574        objectNestingDepth = savedObjectNestingDepth;
575        lexicalNestingDepth = savedLexicalNestingDepth;
576        immediateDef = savedImmediateDef;
577
578        return returned_node;
579    }
580
581    /**
582     * Redirects the call to the helper to avoid code duplication;
583     * that code pasted here would have exactly the same effect.
584     */
585    @Override
586    public List<Decl> recurOnListOfDecl(List<Decl> that) {
587        return helper.recurOnListOfDecl(that);
588    }
589
590
591    @Override
592    public Node forComponent(Component com) {
593        List<Decl> defs = com.getDecls();
594        defsToLocals(defs);
595
596        if (debug && !suppressDebugDump) System.err.println("BEFORE\n" + NodeUtil.dump(com));
597
598        APIName name_result = (APIName) recur(com.getName());
599        List<Import> imports_result = recurOnListOfImport(com.getImports());
600        List<APIName> exports_result = recurOnListOfAPIName(com.getExports());
601        List<Decl> decls_result = recurOnListOfDecl(com.getDecls());
602
603        /* decls_result could be an immutable list, so we must create
604         * a new one and modify that
605         */
606        List<Decl> new_decls_result = new ArrayList<Decl>(decls_result);
607
608        new_decls_result.add(NodeFactory.make_RewriteObjectExprDecl(NodeUtil.getSpan(com), objectExprs));
609        new_decls_result.add(NodeFactory.make_RewriteFunctionalMethodDecl(NodeUtil.getSpan(com),
610                                                                          Useful.list(functionals)));
611
612        AbstractNode nn = NodeFactory.makeComponent(NodeUtil.getSpan(com),
613                                                    name_result,
614                                                    imports_result,
615                                                    new_decls_result,
616                                                    com.is_native(),
617                                                    exports_result);
618
619        if (debug && !suppressDebugDump) System.err.println("AFTER\n" + NodeUtil.dump(nn));
620
621        return nn;
622    }
623
624    @Override
625    public Node forAmbiguousMultifixOpExpr(AmbiguousMultifixOpExpr op) {
626        // NEB: This code is temporary. Very soon the static end will
627        // remove these nodes and they should never appear at this
628        // phase of execution. However, now we simply create an OpExpr.
629        Node node = ExprFactory.makeOpExpr(NodeUtil.getSpan(op),
630                                           NodeUtil.isParenthesized(op),
631                                           NodeUtil.getExprType(op),
632                                           op.getInfix_op(),
633                                           op.getArgs());
634        return visitNode(node);
635    }
636
637    @Override
638    public Node forApi(Api com) {
639        List<Decl> defs = com.getDecls();
640        defsToLocals(defs);
641        return visitNode(com);
642    }
643
644    @Override
645    public Node forOpRef(OpRef vre) {
646        String s = NodeUtil.stringName(vre.getOriginalName());
647        Expr expr = newName(vre, s);
648        return visitNode(expr);
649    }
650
651    @Override
652    public Node forBoolRef(BoolRef vre) {
653        String s = NodeUtil.nameString(vre);
654        BoolRef expr = newName(vre, s);
655        return visitNode(expr);
656    }
657
658    @Override
659    public Node forIntRef(IntRef vre) {
660        String s = NodeUtil.nameString(vre);
661        IntRef expr = newName(vre, s);
662        return visitNode(expr);
663    }
664
665    @Override
666    public Node forVarRef(VarRef vre) {
667        if (NodeUtil.isSingletonObject(vre)) {
668            String s = NodeUtil.stringName(vre.getVarId());
669            return visitNode(newName(vre, s));
670        }
671
672        String s = vrToString(vre);
673        StaticParam tp = visibleGenericParameters.get(s);
674        if (tp != null) {
675            usedGenericParameters.put(s, tp);
676        }
677        Expr update = newName(vre, s);
678        return update;
679    }
680
681    @Override
682    public Node forVarType(VarType vre) {
683        Id id = vre.getName();
684        Node node = vre;
685        if (id.getApiName().isNone()) {
686            String s = NodeUtil.nameString(id);
687            StaticParam tp = visibleGenericParameters.get(s);
688            if (tp != null) {
689                usedGenericParameters.put(s, tp);
690            }
691            node = newType(vre, s);
692        } else {
693            // Rewrite lexical nesting depth to zero if api-qualified.
694            node = NodeFactory.makeVarType(vre, Environment.TOP_LEVEL);
695        }
696
697        return visitNode(node);
698
699    }
700
701
702    @Override
703    public Node forFieldRef(FieldRef that) {
704        atTopLevelInsideTraitOrObject = false;
705        // Believe that any field selection is already
706        // disambiguated. In an ordinary method, "self"
707        // is already defined, in a notself method, "notself"
708        // is defined, and "self" is defined as a local in
709        // an enclosing scope (as is "notnotself", etc, that
710        // intervening notself methods might define).
711
712        // However, since the LHS of a field selection might
713        // be a method invocation, we DO need to check that.
714        return visitNode(that);
715    }
716
717    @Override
718    public Node forLValue(LValue lvb) {
719        Id id = lvb.getName();
720        if ("_".equals(id.getText())) {
721            Id newId = NodeFactory.makeId(NodeUtil.getSpan(id), WellKnownNames.tempForUnderscore(id));
722            return NodeFactory.makeLValue(lvb, newId);
723        }
724        return visitNode(lvb);
725    }
726
727    @Override
728    public Node forMathPrimary(MathPrimary node) {
729        if (looksLikeMethodInvocation(node)) return translateJuxtOfDotted(node);
730        else return visitNode(node);
731    }
732
733    @Override
734    public Node forJuxt(Juxt node) {
735        if (node.isTight()) {
736            if (looksLikeMethodInvocation(node)) return translateJuxtOfDotted(node);
737            else return visitNode(node);
738        } else return visitNode(node);
739    }
740
741    @Override
742    public Node forTraitType(TraitType vre) {
743        return visitNode(vre);
744    }
745
746    @Override
747    public Node forTraitTypeWhere(TraitTypeWhere vre) {
748        lexicalNestingDepth++;
749        Option<WhereClause> owc = vre.getWhereClause();
750        if (owc.isSome()) {
751            WhereClause wc = owc.unwrap();
752            boolean change = false;
753            List<WhereBinding> lwb = wc.getBindings();
754
755            for (WhereBinding wb : lwb) {
756                type_rewrites_put(wb.getName().getText(), new Local());
757            }
758
759            /* Handcoded visit to avoid a "recur" visit on the WhereClause
760              The binding action of a WhereClause in a TraitTypeWhere seems
761              to be different.
762            */
763
764            WhereClause nwc = (WhereClause) visitNode(wc);
765            BaseType t = vre.getBaseType();
766            BaseType nt = (BaseType) recur(t);
767            if (t == nt && wc == nwc) return vre;
768            else return NodeFactory.makeTraitTypeWhere(nt, Wrapper.<WhereClause>make(nwc));
769        } else {
770            return visitNode(vre);
771        }
772
773
774    }
775
776    @Override
777    public Node forWhereClause(WhereClause wc) {
778        lexicalNestingDepth++;
779
780        List<WhereBinding> lwb = wc.getBindings();
781        for (WhereBinding wb : lwb) {
782            type_rewrites_put(wb.getName().getText(), new Local());
783        }
784
785        return visitNode(wc);
786    }
787
788
789    @Override
790    public Node forFnDecl(FnDecl fndef) {
791        if (atTopLevelInsideTraitOrObject) {
792            var_rewrites_put(WellKnownNames.defaultSelfName, new SelfRewrite());
793        }
794        atTopLevelInsideTraitOrObject = false;
795        lexicalNestingDepth++;
796
797        List<Param> params = NodeUtil.getParams(fndef);
798        // NodeUtil.getFnName(fndef); handled at top level.
799        List<StaticParam> tparams = NodeUtil.getStaticParams(fndef);
800
801        paramsToLocals(params);
802        immediateDef = tparamsToLocals(tparams, immediateDef);
803
804        Option<Contract> _contract = NodeUtil.getContract(fndef);
805        Option<List<Expr>> _requires;
806        Option<List<EnsuresClause>> _ensures;
807        Option<List<Expr>> _invariants;
808        if (_contract.isSome()) {
809            _requires = _contract.unwrap().getRequiresClause();
810            _ensures = _contract.unwrap().getEnsuresClause();
811            _invariants = _contract.unwrap().getInvariantsClause();
812        } else {
813            _requires = Option.<List<Expr>>none();
814            _ensures = Option.<List<EnsuresClause>>none();
815            _invariants = Option.<List<Expr>>none();
816        }
817        List<Expr> _exprs = new ArrayList<Expr>();
818
819        AbstractNode n;
820
821        if (fndef.getBody().isSome() && (_ensures.isSome() || _requires.isSome() || _invariants.isSome())) {
822            List<Expr> exprs = new ArrayList<Expr>();
823            exprs.add(fndef.getBody().unwrap());
824            Block b = ExprFactory.makeBlock(NodeUtil.getSpan(_contract.unwrap()), exprs);
825            if (_invariants.isSome()) b = translateInvariants(_invariants, b);
826            if (_ensures.isSome()) b = translateEnsures(_ensures, b);
827            if (_requires.isSome()) b = translateRequires(_requires, b);
828
829            // Remove the original contract, add the translation
830            FnDecl f = NodeFactory.makeFnDecl(NodeUtil.getSpan(fndef),
831                                              NodeUtil.getMods(fndef),
832                                              NodeUtil.getName(fndef),
833                                              NodeUtil.getStaticParams(fndef),
834                                              NodeUtil.getParams(fndef),
835                                              NodeUtil.getReturnType(fndef),
836                                              NodeUtil.getThrowsClause(fndef),
837                                              NodeUtil.getWhereClause(fndef),
838                                              Option.<Contract>none(),
839                                              Option.<Expr>some(b));
840
841            n = visitNode(f);
842        } else {
843            n = visitNode(fndef);
844        }
845
846        dumpIfChange(fndef, n);
847        return n;
848
849    }
850
851    @Override
852    public Node forVarDecl(VarDecl vd) {
853        atTopLevelInsideTraitOrObject = false;
854        List<LValue> lhs = vd.getLhs();
855
856        if (lhs.size() > 1) {
857            // Introduce a temporary, then initialize elements
858            // piece-by-piece.
859            if (vd.getInit().isNone()) return bug(vd, "Variable definition should have an expression.");
860            Expr init = vd.getInit().unwrap();
861            init = (Expr) recur(init);
862            lhs = (List<LValue>) recurOnListOfLValue(lhs);
863            ArrayList<VarDecl> newdecls = new ArrayList<VarDecl>(1 + lhs.size());
864            String temp = WellKnownNames.tempTupleName(vd);
865            Span at = NodeUtil.getSpan(vd);
866            VarDecl new_vd = NodeFactory.makeVarDecl(at, temp, init);
867            newdecls.add(new_vd);
868            int element_index = 0;
869            for (LValue lv : lhs) {
870                Id newName = NodeFactory.makeId(at, "$" + element_index);
871                Option<Type> type = lv.getIdType();
872                newdecls.add(NodeFactory.makeVarDecl(at, Useful.list(lv), Option.<Expr>some(ExprFactory.makeFieldRef(at,
873                                                                                                                     init,
874                                                                                                                     newName))));
875                element_index++;
876            }
877            return new RewriteHackList(newdecls);
878        }
879        // Leave singleton VarDecl alone, probably, because it gets properly
880        // handled
881        // at the enclosing block.
882        return visitNode(vd);
883
884    }
885
886
887    @Override
888    public Node for_RewriteObjectExpr(_RewriteObjectExpr oe) {
889        List<Decl> defs = NodeUtil.getDecls(oe);
890        List<BaseType> xtends = NodeUtil.getTypes(NodeUtil.getExtendsClause(oe));
891        objectNestingDepth++;
892        lexicalNestingDepth++;
893        atTopLevelInsideTraitOrObject = true;
894        defsToMembers(defs);
895        accumulateMembersFromExtends(xtends, rewrites);
896        AbstractNode n = visitNodeTO(oe);
897        return n;
898    }
899
900    @Override
901    public Node forObjectExpr(ObjectExpr oe) {
902        // TODO wip
903
904        // REMEMBER THAT THIS IS THE NEW _RewriteObjectExpr!
905        // Implicitly parameterized by either visibleGenericParameters,
906        // or by usedGenericParameters.
907        // Note the keys of a BATree are sorted.
908        _RewriteObjectExpr rwoe = (_RewriteObjectExpr) recur(ExprFactory.make_RewriteObjectExpr((ObjectExpr) oe,
909                                                                                                usedGenericParameters));
910        objectExprs.add(rwoe);
911
912        return visitNode(ExprFactory.make_RewriteObjectExprRef(rwoe));
913    }
914
915    @Override
916    public Node forCatch(Catch that) {
917        String s = ((Catch) that).getName().stringName();
918        lexicalNestingDepth++;
919        var_rewrites_put(s, new Local());
920        return visitNode(that);
921    }
922
923    @Override
924    public Node forFnExpr(FnExpr fndef) {
925        atTopLevelInsideTraitOrObject = false;
926        lexicalNestingDepth++;
927        List<Param> params = NodeUtil.getParams(fndef);
928        paramsToLocals(params);
929        return visitNode(fndef);
930    }
931
932    @Override
933    public Node forLetFn(LetFn lf) {
934        atTopLevelInsideTraitOrObject = false;
935        lexicalNestingDepth++;
936        // defined var is no longer eligible for rewrite.
937        List<Decl> defs = new ArrayList<Decl>();
938        for (FnDecl d : lf.getFns()) {
939            defs.add((Decl) d);
940        }
941        defsToLocals(defs);
942        // All the function names are in scope in the function
943        // definitions, and in the body of code that follows them.
944        // TODO wip
945        return visitNode(lf);
946
947    }
948
949    @Override
950    public Node forLocalVarDecl(LocalVarDecl lvd) {
951        atTopLevelInsideTraitOrObject = false;
952        lexicalNestingDepth++;
953        lvaluesToLocal(lvd.getLhs());
954        // not quite right because initializing exprs are evaluated in the wrong context.
955        // TODO wip
956
957        return visitNode(lvd);
958    }
959
960    @Override
961    public Node forObjectDecl(ObjectDecl od) {
962        // All the methods and fields defined in object and the
963        // extended traits
964        // are mapped to "self".
965        List<Decl> defs = NodeUtil.getDecls(od);
966        Option<List<Param>> params = NodeUtil.getParams(od);
967        List<StaticParam> tparams = NodeUtil.getStaticParams(od);
968        List<BaseType> xtends = NodeUtil.getTypes(NodeUtil.getExtendsClause(od));
969
970        // TODO wip
971        lexicalNestingDepth++;
972        objectNestingDepth++;
973        atTopLevelInsideTraitOrObject = true;
974
975        defsToMembers(defs);
976        immediateDef = tparamsToLocals(tparams, immediateDef);
977        paramsToMembers(params);
978
979        accumulateMembersFromExtends(xtends, rewrites);
980
981        AbstractNode n = visitNodeTO(od);
982
983        return n;
984    }
985
986    @Override
987    public Node forTraitDecl(TraitDecl td) {
988        List<Decl> defs = NodeUtil.getDecls(td);
989        List<StaticParam> tparams = NodeUtil.getStaticParams(td);
990        // TODO wip
991        lexicalNestingDepth++;
992        objectNestingDepth++;
993        atTopLevelInsideTraitOrObject = true;
994        defsToMembers(defs);
995        immediateDef = tparamsToLocals(tparams, immediateDef);
996
997        accumulateMembersFromExtends(td);
998
999        inTrait = true;
1000        AbstractNode n = visitNodeTO(td);
1001        inTrait = false;
1002        return n;
1003    }
1004
1005    @Override
1006    public Node forSpawn(Spawn s) {
1007        Expr body = s.getBody();
1008        Span sp = NodeUtil.getSpan(s);
1009        // If the user writes Spawn(foo) instead of Spawn(foo()) we get an inexplicable error
1010        // message.  We might want to put in a check for that someday.
1011
1012        Node rewrittenExpr = visit(body);
1013
1014        Expr in_fn =
1015            ExprFactory.makeVarRef(sp,
1016                NodeFactory.makeId(sp,
1017                                   WellKnownNames.fortressBuiltin(),
1018                                   WellKnownNames.thread));
1019        List<StaticArg> args = new ArrayList<StaticArg>();
1020        args.add(
1021            NodeFactory.makeTypeArg(sp,
1022                NodeFactory.makeVarType(sp,
1023                    NodeFactory.makeId(sp,
1024                                       WellKnownNames.anyTypeLibrary(),
1025                                       WellKnownNames.anyTypeName),
1026                    Environment.TOP_LEVEL)));
1027
1028        _RewriteFnRef fn = ExprFactory.make_RewriteFnRef(NodeUtil.getSpan(s), false, Option.<Type>none(), in_fn, args);
1029
1030        List<Param> params = Collections.emptyList();
1031        FnExpr fnExpr = ExprFactory.makeFnExpr(sp, params, (Expr) rewrittenExpr);
1032
1033        return visitNode(ExprFactory.make_RewriteFnApp(NodeUtil.getSpan(s), fn, fnExpr));
1034    }
1035
1036    @Override
1037    public Node forGrammarDecl(GrammarDecl node) {
1038        return node;
1039    }
1040
1041    @Override
1042    public Node forTypecase(Typecase tc) {
1043        List<Id> lid = tc.getBindIds();
1044        Option<Expr> oe = tc.getBindExpr();
1045        // Not quite right because this will remove them from arrows,
1046        // but perhaps they ARE arrows, depending on the typecase.
1047        IdsToLocals(lid);
1048
1049        if (oe.isNone()) {
1050            tc = ExprFactory.makeTypecase(tc, lid, (Expr) tupleForIdList(lid));
1051        }
1052        return visitNode(tc);
1053    }
1054
1055    /**
1056     * Performs an object-reference-disambiguating com.sun.fortress.interpreter.rewrite of the AST. Any
1057     * effects on the environment from the toplevel remain visible, otherwise
1058     * visit only rewrites.
1059     */
1060    //@Override
1061    public Node visit(AbstractNode node) {
1062        return recur(node);
1063    }
1064
1065    private String vrToString(VarRef vre) {
1066        Iterable<Id> ids = NodeUtil.getIds(vre.getVarId());
1067        // TODO this omits the leading API name
1068        String s = IterUtil.last(ids).getText();
1069        return s;
1070    }
1071
1072    /**
1073     * Given List<Id>, generate tuple of corresponding VarRef
1074     */
1075    Expr tupleForIdList(List<Id> binds) {
1076        if (binds.size() == 1) return ExprFactory.makeVarRef(binds.get(0));
1077
1078        List<Expr> refs = new ArrayList<Expr>(binds.size());
1079
1080        for (Id b : binds) {
1081            refs.add(ExprFactory.makeVarRef(b));
1082        }
1083
1084        return ExprFactory.makeTupleExpr(new Span(NodeUtil.getSpan(binds.get(0)), NodeUtil.getSpan(binds.get(
1085                binds.size() - 1))), refs);
1086    }
1087
1088    /**
1089     * Given expr e, return (fn () => e)
1090     */
1091    Expr thunk(Expr e) {
1092        return ExprFactory.makeFnExpr(NodeUtil.getSpan(e), Collections.<Param>emptyList(), e);
1093    }
1094
1095    /**
1096     * @param td
1097     */
1098    private void accumulateMembersFromExtends(TraitDecl td) {
1099        accumulateMembersFromExtends(NodeUtil.getTypes(NodeUtil.getExtendsClause(td)), rewrites);
1100    }
1101
1102    private void accumulateMembersFromExtends(List<BaseType> xtends, Map<String, InterpreterNameRewriter> disEnv) {
1103        Set<String> members = new HashSet<String>();
1104        Set<String> types = new HashSet<String>();
1105        Set<String> arrow_names = new HashSet<String>();
1106        Set<String> not_arrow_names = new HashSet<String>();
1107        Set<AbstractNode> visited = new HashSet<AbstractNode>();
1108        accumulateTraitsAndMethods(xtends, disEnv, members, types, arrow_names, not_arrow_names, visited);
1109        stringsToLocals(types);
1110        stringsToMembers(members);
1111        arrows.removeAll(not_arrow_names);
1112        arrows.addAll(arrow_names);
1113    }
1114
1115    /**
1116     * @param node
1117     * @param n
1118     */
1119    private void dumpIfChange(AbstractNode old, AbstractNode n) {
1120        if (false && n != old) {
1121            try {
1122                System.err.println("Rewritten method body:");
1123                NodeUtil.dump(System.err, n);
1124                System.err.println();
1125            }
1126            catch (IOException ex) {
1127                ex.printStackTrace();
1128            }
1129
1130        }
1131    }
1132
1133    /**
1134     * @param defs
1135     */
1136    private void defsToLocals(List<Decl> defs) {
1137        for (Decl d : defs) {
1138            if (d instanceof TraitDecl) {
1139                String s = d.stringName();
1140                TraitDecl dod = (TraitDecl) d;
1141                type_rewrites_put(s, new Trait(dod, rewrites));
1142            } else if (d instanceof ObjectDecl) {
1143                ObjectDecl od = (ObjectDecl) d;
1144                Option<List<Param>> params = od.getParams();
1145                /*
1146                 *  Add the object itself (either constructor or singleton,
1147                 *  we don't care much) to the locals.
1148                 *
1149                 *  If it is a constructor, it is also an arrow type.
1150                 *
1151                 */
1152                String s = NodeUtil.getName(od).getText();
1153                obj_rewrites_put(s, new Local());
1154
1155                if (params.isNone()) arrows.remove(s);
1156                else arrows.add(s);
1157            } else {
1158                for (String s : NodeUtil.stringNames(d)) {
1159                    var_rewrites_put(s, new Local());
1160                }
1161            }
1162        }
1163    }
1164
1165    /**
1166     * @param defs
1167     */
1168    private void functionalMethodsOfDefsToLocals(List<Decl> defs) {
1169        for (Decl d : defs) {
1170            if (d instanceof TraitObjectDecl) {
1171                TraitObjectDecl dod = (TraitObjectDecl) d;
1172                List<Decl> tdecls = NodeUtil.getDecls(dod);
1173                handlePossibleFM(tdecls);
1174            } else {
1175                // Thankfully, do nothing.
1176            }
1177        }
1178    }
1179
1180    private void handlePossibleFM(List<Decl> tdecls) {
1181        for (Decl adod : tdecls) {
1182            ArrowOrFunctional aof = adod.accept(IsAnArrowName.isAnArrowName);
1183            if (aof == ArrowOrFunctional.FUNCTIONAL) {
1184                // Only certain things can be a functional method.
1185                FnDecl fadod = (FnDecl) adod;
1186                String s = NodeUtil.getName(fadod).stringName();
1187                arrows.add(s);
1188                functionals.add(s);
1189                var_rewrites_put(s, new FunctionalMethod());
1190            }
1191
1192        }
1193    }
1194
1195
1196    /**
1197     * @param params
1198     */
1199    private void paramsToLocals(List<? extends Param> params) {
1200        for (Param d : params) {
1201            String s = d.getName().getText();
1202            // "self" is not a local.
1203            if (!s.equals(WellKnownNames.defaultSelfName)) {
1204                var_rewrites_put(s, new Local());
1205
1206            }
1207        }
1208    }
1209
1210    private void IdsToLocals(List<Id> lid) {
1211        for (Id d : lid) {
1212            String s = d.getText();
1213            var_rewrites_put(s, new Local());
1214        }
1215    }
1216
1217    private NodeAbstractVisitor_void localVisitor = new NodeAbstractVisitor_void() {
1218
1219        @Override
1220        public void forExtentRange(ExtentRange that) {
1221            super.forExtentRange(that);
1222        }
1223
1224        @Override
1225        public void forLValue(LValue that) {
1226            that.getName().accept(this);
1227        }
1228
1229        @Override
1230        public void forId(Id that) {
1231            String s = that.getText();
1232            var_rewrites_put(s, new Local());
1233        }
1234
1235    };
1236
1237    /**
1238     * @param params
1239     */
1240    private void lvaluesToLocal(List<? extends LValue> params) {
1241        for (LValue param : params) {
1242            param.accept(localVisitor);
1243        }
1244    }
1245
1246    /**
1247     * @param params
1248     */
1249    private BATree<String, Boolean> tparamsToLocals(List<StaticParam> params, BATree<String, Boolean> immediateDef) {
1250        if (!params.isEmpty()) for (StaticParam d : params) {
1251            String s = NodeUtil.getName(d);
1252            // OpParams are not real members
1253            // if (! (d instanceof OpParam))
1254            type_rewrites_put(s, new Local());
1255            visibleGenericParameters.put(s, d);
1256            immediateDef = addToImmediateDef(immediateDef, s);
1257        }
1258        return immediateDef;
1259    }
1260
1261    /**
1262     * @param immediateDef
1263     * @param s
1264     * @return
1265     */
1266    private BATree<String, Boolean> addToImmediateDef(BATree<String, Boolean> immediateDef, String s) {
1267        if (immediateDef == null) immediateDef = new BATree<String, Boolean>(StringHashComparer.V);
1268        immediateDef.put(s, Boolean.FALSE);
1269        return immediateDef;
1270    }
1271
1272    /**
1273     * @param defs
1274     */
1275    private void defsToMembers(List<Decl> defs) {
1276        for (Decl dd : defs) {
1277
1278            if (dd instanceof VarDecl) {
1279                //visited.add(tdod);
1280            } else {
1281                String sdd = dd.stringName();
1282                ArrowOrFunctional aof = dd.accept(IsAnArrowName.isAnArrowName);
1283
1284                if (aof != ArrowOrFunctional.NEITHER) {
1285
1286                    arrows.add(sdd);
1287                    if (aof == ArrowOrFunctional.FUNCTIONAL) {
1288                        functionals.add(sdd);
1289
1290                        continue; // NOT a regular member, do not add.
1291                    }
1292                } else {
1293                    arrows.remove(sdd);
1294                }
1295            }
1296            for (String s : NodeUtil.stringNames(dd)) {
1297                var_rewrites_put(s, new Member());
1298            }
1299        }
1300
1301    }
1302
1303    /**
1304     * @param params
1305     */
1306    private void paramsToMembers(Option<List<Param>> params) {
1307        if (params.isSome()) for (Param d : params.unwrap()) {
1308            String s = d.getName().getText();
1309            var_rewrites_put(s, new Member());
1310            ArrowOrFunctional aof = d.accept(IsAnArrowName.isAnArrowName);
1311            if (aof != ArrowOrFunctional.NEITHER) {
1312                arrows.add(s);
1313                if (aof == ArrowOrFunctional.FUNCTIONAL) {
1314                    functionals.add(s);
1315                    throw new Error("Don't think this can happen");
1316
1317                }
1318            } else arrows.remove(s);
1319        }
1320    }
1321
1322
1323    /**
1324     * @param params
1325     */
1326    private void stringsToMembers(Collection<String> strings) {
1327        for (String s : strings) {
1328            var_rewrites_put(s, new Member());
1329            arrows.remove(s);
1330        }
1331    }
1332
1333    /**
1334     * @param params
1335     */
1336    private void stringsToLocals(Collection<String> strings) {
1337        for (String s : strings) {
1338            type_rewrites_put(s, new Local());
1339            arrows.remove(s);
1340        }
1341    }
1342
1343    /**
1344     * @param xtends  List of types that a trait/object extends
1345     * @param typeEnv The environment in which those names are interpreted
1346     * @param members (output) all the members transitively introduced by all
1347     *                extended traits
1348     * @param types   (output) all the names of all the types transitively extended
1349     * @param visited (bookkeeping) to prevent revisiting, and possible looping on
1350     *                bad inputs
1351     */
1352    private void accumulateTraitsAndMethods(List<BaseType> xtends,
1353                                            Map<String, InterpreterNameRewriter> typeEnv,
1354                                            Set<String> members,
1355                                            Set<String> types,
1356                                            Set<String> arrow_names,
1357                                            Set<String> not_arrow_names,
1358                                            Set<AbstractNode> visited) {
1359
1360        for (Type t : xtends) {
1361            Id name = null;
1362            // First de-parameterize the type
1363            if (t instanceof TraitType) {
1364                name = ((TraitType) t).getName();
1365            } else if (t instanceof VarType) {
1366                name = ((VarType) t).getName();
1367            } else if (t instanceof AnyType) {
1368                name = INTERNAL_ANY_NAME;
1369            } else {
1370                // TODO Way too many types; deal with them as necessary.
1371                bug(t, errorMsg("Object extends something exciting: ", t));
1372            }
1373            boolean hasApi = name.getApiName().isSome();
1374            // The map is not consistent; the stored names lack API qualifiers.
1375            // TODO fix this inconsistency.
1376            if (true || !hasApi) {
1377                // TODO we've got to generalize this to qualified names.
1378                String s = name.getText();
1379                InterpreterNameRewriter th;
1380                try {
1381                    th = typeEnv.get(s);
1382                }
1383                catch (NullPointerException x) {
1384                    String msg = errorMsg("Entity ", s, " not found in typeEnv ", typeEnv);
1385                    th = bug(msg);
1386                }
1387                if (th instanceof Trait) {
1388                    Trait tr = (Trait) th;
1389                    TraitDecl tdod = tr.defOrDecl;
1390                    if (!(visited.contains(tdod))) {
1391                        visited.add(tdod);
1392                        // Process this trait -- add its name, as well
1393                        // as all the members
1394                        // types.add(s); // The trait is known by this
1395                        // name.
1396                        for (Decl dd : NodeUtil.getDecls(tdod)) {
1397                            String sdd = dd.stringName();
1398                            if (dd instanceof VarDecl) {
1399                                //visited.add(tdod);
1400                            } else {
1401                                ArrowOrFunctional aof = dd.accept(IsAnArrowName.isAnArrowName);
1402
1403                                if (aof != ArrowOrFunctional.NEITHER) {
1404                                    arrow_names.add(sdd);
1405                                    if (aof == ArrowOrFunctional.FUNCTIONAL) {
1406                                        functionals.add(sdd);
1407                                        var_rewrites_put(sdd, new FunctionalMethod());
1408                                        continue; // do not add as a member
1409                                    }
1410                                } else {
1411                                    not_arrow_names.add(sdd);
1412                                }
1413                            }
1414                            members.add(sdd);
1415                        }
1416                        accumulateTraitsAndMethods(NodeUtil.getTypes(NodeUtil.getExtendsClause(tdod)),
1417                                                   tr.env,
1418                                                   members,
1419                                                   types,
1420                                                   arrow_names,
1421                                                   not_arrow_names,
1422                                                   visited);
1423                    }
1424                } else if (th instanceof Object) {
1425                    error(t, errorMsg("Attempt to extend object type ", s, ", saw ", th));
1426                } else if (th == null) {
1427                    /* This was missing the "throw" for a long
1428                    * time, and adding it back in actually
1429                    * broke tests/extendAny.fss.  Oddly it
1430                    * only seems to catch this case; if we
1431                    * name an actually bogus type that causes
1432                    * a more meaningful failure elsewhere.
1433                    * Consequently we leave it commented out
1434                    * for the moment.
1435                    */
1436                    // error(t,"Type extends non-visible entity " + s);
1437                } else {
1438                    error(t, errorMsg("Attempt to extend type ", s, " (which maps to the following Thing: ", th, ")"));
1439                }
1440            } else {
1441                NI.nyi("General qualified name");
1442            }
1443        }
1444    }
1445
1446    private AbstractNode translateJuxtOfDotted(Juxt node) {
1447        List<Expr> exprs = node.getExprs();
1448        VarRef first = (VarRef) exprs.get(0);
1449        Id qidn = first.getVarId();
1450
1451        // Optimistic casts here, will need revisiting in the future,
1452        // perhaps FieldRefs are too general
1453        // Recursive visits here
1454        Node expr = visit(first);
1455        List<Expr> visitedArgs = recurOnListOfExpr(exprs.subList(1, exprs.size()));
1456        if (expr instanceof VarRef) {
1457            VarRef vre = (VarRef) expr;
1458            if (vre.getLexicalDepth() == -1) {
1459                return ExprFactory.makeMethodInvocation(NodeUtil.getSpan(node),
1460                                                        false,
1461                                                        NodeUtil.getExprType(node),
1462                                                        ExprFactory.makeVarRef(NodeUtil.getSpan(node),
1463                                                                               WellKnownNames.secretSelfName),
1464                                                        // this will rewrite in the future.
1465                                                        (Id) vre.getVarId(),
1466                                                        visitedArgs.size() == 0 ? ExprFactory.makeVoidLiteralExpr(
1467                                                                NodeUtil.getSpan(node)) : //TODO wrong span
1468                                                        visitedArgs.size() == 1 ?
1469                                                        visitedArgs.get(0) :
1470                                                        ExprFactory.makeTupleExpr(NodeFactory.makeSpan("impossible",
1471                                                                                                       visitedArgs),
1472                                                                                  visitedArgs));
1473            }
1474        } else if (expr instanceof FieldRef) {
1475
1476            FieldRef selfDotSomething = (FieldRef) visit(first);
1477
1478            return ExprFactory.makeMethodInvocation(NodeUtil.getSpan(node),
1479                                                    false,
1480                                                    NodeUtil.getExprType(node),
1481                                                    selfDotSomething.getObj(),
1482                                                    // this will rewrite in the future.
1483                                                    selfDotSomething.getField(),
1484                                                    visitedArgs.size() == 0 ?
1485                                                    ExprFactory.makeVoidLiteralExpr(NodeUtil.getSpan(node)) :
1486                                                    //TODO wrong span
1487                                                    visitedArgs.size() == 1 ?
1488                                                    visitedArgs.get(0) :
1489                                                    ExprFactory.makeTupleExpr(NodeFactory.makeSpan("impossible",
1490                                                                                                   visitedArgs),
1491                                                                              visitedArgs));
1492        }
1493
1494        throw new Error("Not there yet.");
1495
1496
1497    }
1498
1499    private AbstractNode translateJuxtOfDotted(MathPrimary node) {
1500        VarRef first = (VarRef) node.getFront();
1501        Id qidn = first.getVarId();
1502
1503        // Optimistic casts here, will need revisiting in the future,
1504        // perhaps FieldRefs are too general
1505        // Recursive visits here
1506        FieldRef selfDotSomething = (FieldRef) visit(first);
1507        //        List<MathItem> visitedArgs = visitList(exprs);
1508        Node arg = visit(((ExprMI) node.getRest().get(0)).getExpr());
1509
1510        return ExprFactory.makeMethodInvocation(NodeUtil.getSpan(node),
1511                                                false,
1512                                                NodeUtil.getExprType(node),
1513                                                selfDotSomething.getObj(),
1514                                                // this will rewrite in the future.
1515                                                selfDotSomething.getField(),
1516                                                (Expr) arg
1517                                                /*
1518                                            visitedArgs.size() == 0 ? ExprFactory.makeVoidLiteralExpr(NodeUtil.getSpan(node)) : // wrong span
1519                                            visitedArgs.size() == 1 ? visitedArgs.get(0) :
1520                                                new TupleExpr(visitedArgs)
1521                                                */);
1522    }
1523
1524    private Block translateRequires(Option<List<Expr>> _requires, Block b) {
1525        List<Expr> r = _requires.unwrap(Collections.<Expr>emptyList());
1526        for (Expr e : r) {
1527            Span sp = NodeUtil.getSpan(e);
1528            GeneratorClause cond = ExprFactory.makeGeneratorClause(sp, Useful.<Id>list(), e);
1529            If _if = ExprFactory.makeIf(sp, NodeFactory.makeIfClause(sp, cond, b), ExprFactory.makeThrow(sp,
1530                                                                                                         "CallerViolation"));
1531            b = ExprFactory.makeBlock(sp, _if);
1532        }
1533        return b;
1534    }
1535
1536    private Block translateEnsures(Option<List<EnsuresClause>> _ensures, Block b) {
1537        List<EnsuresClause> es = _ensures.unwrap(Collections.<EnsuresClause>emptyList());
1538        for (EnsuresClause e : es) {
1539            Span sp = NodeUtil.getSpan(e);
1540            Id t1 = gensymId("t1");
1541            Block inner_block = ExprFactory.makeBlock(sp, ExprFactory.makeVarRef(sp, WellKnownNames.outcome));
1542            GeneratorClause cond;
1543            cond = ExprFactory.makeGeneratorClause(sp, Useful.<Id>list(), e.getPost());
1544            If _inner_if = ExprFactory.makeIf(sp,
1545                                              NodeFactory.makeIfClause(sp, cond, inner_block),
1546                                              ExprFactory.makeThrow(sp, WellKnownNames.calleeViolationException));
1547
1548            cond = ExprFactory.makeGeneratorClause(sp, Useful.<Id>list(), (Expr) ExprFactory.makeVarRef(sp, t1));
1549            If _if = ExprFactory.makeIf(sp,
1550                                        NodeFactory.makeIfClause(sp, cond, ExprFactory.makeBlock(sp, _inner_if)),
1551                                        ExprFactory.makeBlock(sp, ExprFactory.makeVarRef(sp, WellKnownNames.outcome)));
1552            LocalVarDecl r = ExprFactory.makeLocalVarDecl(sp, NodeFactory.makeId(sp, WellKnownNames.outcome), b, _if);
1553            Option<Expr> _pre = e.getPre();
1554            LocalVarDecl provided_lvd = ExprFactory.makeLocalVarDecl(sp,
1555                                                                     t1,
1556                                                                     _pre.unwrap(ExprFactory.makeVarRef(sp,
1557                                                                                                        WellKnownNames.fortressLibrary(),
1558                                                                                                        "true")),
1559                                                                     ExprFactory.makeBlock(sp, r));
1560            b = ExprFactory.makeBlock(sp, provided_lvd);
1561        }
1562        return b;
1563    }
1564
1565    private Block translateInvariants(Option<List<Expr>> _invariants, Block b) {
1566        for (Expr e : _invariants.unwrap(Collections.<Expr>emptyList())) {
1567            Span sp = NodeUtil.getSpan(e);
1568            Id t1 = gensymId("t1");
1569            Id t_outcome = gensymId(WellKnownNames.outcome);
1570            Id t2 = gensymId("t2");
1571
1572            Expr chain = (Expr) ExprFactory.makeChainExpr(sp,
1573                                                          (Expr) ExprFactory.makeVarRef(sp, t1),
1574                                                          NodeFactory.makeOpInfix(sp,
1575                                                                                  WellKnownNames.fortressLibrary(),
1576                                                                                  "="),
1577                                                          // new Op("="),
1578                                                          (Expr) ExprFactory.makeVarRef(sp, t2));
1579            GeneratorClause gen_chain = ExprFactory.makeGeneratorClause(sp, Useful.<Id>list(), chain);
1580            If _post = ExprFactory.makeIf(sp, NodeFactory.makeIfClause(sp, gen_chain, ExprFactory.makeBlock(sp,
1581                                                                                                            ExprFactory.makeVarRef(
1582                                                                                                                    sp,
1583                                                                                                                    WellKnownNames.outcome))),
1584                                          ExprFactory.makeThrow(sp, WellKnownNames.calleeViolationException));
1585            LocalVarDecl r2 = ExprFactory.makeLocalVarDecl(sp, t2, e, _post);
1586            LocalVarDecl r1 = ExprFactory.makeLocalVarDecl(NodeFactory.makeId(sp, WellKnownNames.outcome), b, r2);
1587
1588            b = ExprFactory.makeBlock(sp, ExprFactory.makeLocalVarDecl(sp, t1, e, r1));
1589        }
1590
1591        return b;
1592    }
1593
1594    private boolean looksLikeMethodInvocation(Juxt node) {
1595        Expr first = node.getExprs().get(0);
1596
1597        if (first instanceof VarRef) {
1598            VarRef vr = (VarRef) first;
1599            String s = vrToString(vr);
1600
1601            /*
1602             * If the var ref will be rewritten to self.var (or self.parent.var,
1603             * etc) and if the var ref IS NOT an arrow type (a function), then
1604             * it looks like a method invocation.
1605             */
1606            if (rewrites.get(s) instanceof Member && !arrows.contains(s)) return true;
1607        }
1608        return false;
1609    }
1610
1611    private boolean looksLikeMethodInvocation(MathPrimary node) {
1612        Expr first = node.getFront();
1613        if (first instanceof VarRef) {
1614            VarRef vr = (VarRef) first;
1615            String s = vrToString(vr);
1616            if (rewrites.get(s) instanceof Member && !arrows.contains(s) && node.getRest().size() == 1 &&
1617                node.getRest().get(0) instanceof ExprMI) return true;
1618        }
1619        return false;
1620    }
1621
1622    public Set<String> getTopLevelRewriteNames() {
1623        return rewrites.keySet();
1624    }
1625
1626}
Note: See TracBrowser for help on using the browser.