root/trunk/ProjectFortress/src/com/sun/fortress/parser_util/FortressUtil.java @ 2405

Revision 2405, 34.7 KB (checked in by sukyoungryu, 16 months ago)

[tool] Fixed arrays and also do.

Line 
1/*******************************************************************************
2    Copyright 2008 Sun Microsystems, Inc.,
3    4150 Network Circle, Santa Clara, California 95054, U.S.A.
4    All rights reserved.
5
6    U.S. Government Rights - Commercial software.
7    Government users are subject to the Sun Microsystems, Inc. standard
8    license agreement and applicable provisions of the FAR and its supplements.
9
10    Use is subject to license terms.
11
12    This distribution may include materials developed by third parties.
13
14    Sun, Sun Microsystems, the Sun logo and Java are trademarks or registered
15    trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
16 ******************************************************************************/
17
18/*
19 * Utility functions for the Fortress com.sun.fortress.interpreter.parser.
20 */
21
22package com.sun.fortress.parser_util;
23
24import java.lang.reflect.Array;
25import java.util.ArrayList;
26import java.util.Collections;
27import java.util.List;
28import edu.rice.cs.plt.iter.IterUtil;
29import edu.rice.cs.plt.tuple.Option;
30import edu.rice.cs.plt.tuple.OptionVisitor;
31
32import com.sun.fortress.nodes.*;
33import com.sun.fortress.nodes_util.Span;
34import com.sun.fortress.nodes_util.SourceLoc;
35import com.sun.fortress.nodes_util.ExprFactory;
36import com.sun.fortress.nodes_util.NodeFactory;
37import com.sun.fortress.useful.Cons;
38import com.sun.fortress.useful.Pair;
39import com.sun.fortress.useful.PureList;
40import com.sun.fortress.exceptions.ProgramError;
41
42import static com.sun.fortress.exceptions.InterpreterBug.bug;
43import static com.sun.fortress.exceptions.ProgramError.error;
44
45public final class FortressUtil {
46    public static <T> T syntaxError(Span span, String msg) {
47        return ProgramError.<T>error(new VoidLiteralExpr(span), msg);
48    }
49
50    public static void println(String arg) {
51        System.out.println(arg);
52    }
53
54    public static Contract emptyContract() {
55        return new Contract(new Span(), Option.<List<Expr>>none(),
56                            Option.<List<EnsuresClause>>none(),
57                            Option.<List<Expr>>none());
58    }
59
60    public static List<Decl> emptyDecls() {
61        return Collections.<Decl>emptyList();
62    }
63
64    public static List<EnsuresClause> emptyEnsuresClauses() {
65        return Collections.<EnsuresClause>emptyList();
66    }
67
68    public static List<Expr> emptyExprs() {
69        return Collections.<Expr>emptyList();
70    }
71
72    public static List<Modifier> emptyModifiers() {
73        return Collections.<Modifier>emptyList();
74    }
75
76    public static List<Param> emptyParams() {
77        return Collections.<Param>emptyList();
78    }
79
80    public static List<StaticParam> emptyStaticParams() {
81        return Collections.<StaticParam>emptyList();
82    }
83
84    public static List<BaseType> emptyTraitTypes() {
85        return Collections.<BaseType>emptyList();
86    }
87
88    public static List<TraitTypeWhere> emptyTraitTypeWheres() {
89        return Collections.<TraitTypeWhere>emptyList();
90    }
91
92    public static List<Type> emptyTypes() {
93        return Collections.<Type>emptyList();
94    }
95
96    public static WhereClause emptyWhereClause() {
97        return new WhereClause(Collections.<WhereBinding>emptyList(),
98                               Collections.<WhereConstraint>emptyList());
99    }
100
101    public static Effect emptyEffect() {
102        return new Effect();
103    }
104
105    public static <T> List<T> getListVal(Option<List<T>> o) {
106        return o.unwrap(Collections.<T>emptyList());
107    }
108
109    public static <U, T extends U> List<U> mkList(T first) {
110        List<U> l = new ArrayList<U>();
111        l.add(first);
112        return l;
113    }
114
115    public static <U, T extends U> List<U> mkList(List<T> all) {
116        List<U> l = new ArrayList<U>();
117        l.addAll(all);
118        return l;
119    }
120
121    public static <U, T extends U> List<U> mkList(T first, T second) {
122        List<U> l = new ArrayList<U>();
123        l.add(first);
124        l.add(second);
125        return l;
126    }
127
128    public static <U, T extends U> List<U> mkList(U first, List<T> rest) {
129        List<U> l = new ArrayList<U>();
130        l.add(first);
131        l.addAll(rest);
132        return l;
133    }
134
135    public static <U, T extends U> List<U> mkList(List<T> rest, U last) {
136        List<U> l = new ArrayList<U>();
137        l.addAll(rest);
138        l.add(last);
139        return l;
140    }
141
142    public static List<LValue> toLValueList(List<LValueBind> lvbs) {
143        List<LValue> result = new ArrayList<LValue>();
144        for (LValueBind lvb : lvbs) {
145            result.add((LValue)lvb);
146        }
147        return result;
148    }
149
150    public static List<Type> toTypeList(List<BaseType> tys) {
151        List<Type> result = new ArrayList<Type>();
152        for (BaseType ty : tys) {
153            result.add((Type)ty);
154        }
155        return result;
156    }
157
158    public static Option<List<Type>> toTypeList(Option<List<BaseType>> tys) {
159        return tys.apply(new OptionVisitor<List<BaseType>, Option<List<Type>>>() {
160            public Option<List<Type>> forSome(List<BaseType> l) {
161                return Option.<List<Type>>some(new ArrayList<Type>(l));
162            }
163            public Option<List<Type>> forNone() { return Option.none(); }
164        });
165    }
166
167    public static Expr makeSubscripting(Span span, Span spanOpen, Span spanClose,
168                                        String left, String right,
169                                        Expr base, List<Expr> args,
170                                        List<StaticArg> sargs) {
171        Op open  = NodeFactory.makeOpEnclosing(spanOpen, left);
172        Op close = NodeFactory.makeOpEnclosing(spanClose, right);
173        return makeSubscripting(span, base, open, close, args, sargs);
174    }
175
176    public static Expr makeSubscripting(Span span, Expr base, Op open,
177                                        Op close, List<Expr> args,
178                                        List<StaticArg> sargs) {
179        Enclosing op = new Enclosing(FortressUtil.spanTwo(open,close),
180                                     open, close);
181        List<Expr> es;
182        if (args == null) es = FortressUtil.emptyExprs();
183        else              es = args;
184        return new SubscriptExpr(span, false, base, es, Option.some(op), sargs);
185    }
186
187    public static Expr makeSubscripting(Span span, Span spanOpen, Span spanClose,
188                                        String left, String right,
189                                        PureList<Expr> base, List<Expr> args,
190                                        List<StaticArg> sargs) {
191        Op open  = NodeFactory.makeOpEnclosing(spanOpen, left);
192        Op close = NodeFactory.makeOpEnclosing(spanClose, right);
193        return makeSubscripting(span, base, open, close, args, sargs);
194    }
195
196    public static Expr makeSubscripting(Span span, PureList<Expr> base, Op open,
197                                        Op close, List<Expr> args,
198                                        List<StaticArg> sargs) {
199        Enclosing op = new Enclosing(FortressUtil.spanTwo(open,close),
200                                     open, close);
201        Expr arr = buildPrimary((PureList<Expr>)base);
202        List<Expr> es;
203        if (args == null) es = FortressUtil.emptyExprs();
204        else              es = args;
205        return new SubscriptExpr(span, false, arr, es, Option.some(op), sargs);
206    }
207
208    private static void multiple(Modifier m) {
209        resetMods();
210        syntaxError(m.getSpan(), "A modifier must not occur multiple times");
211    }
212    static boolean m_atomic   = false;
213    static boolean m_getter   = false;
214    static boolean m_hidden   = false;
215    static boolean m_io       = false;
216    static boolean m_private  = false;
217    static boolean m_settable = false;
218    static boolean m_setter   = false;
219    static boolean m_test     = false;
220    static boolean m_value    = false;
221    static boolean m_var      = false;
222    static boolean m_widens   = false;
223    static boolean m_wrapped  = false;
224    private static void resetMods() {
225        m_atomic   = false;
226        m_getter   = false;
227        m_hidden   = false;
228        m_io       = false;
229        m_private  = false;
230        m_settable = false;
231        m_setter   = false;
232        m_test     = false;
233        m_value    = false;
234        m_var      = false;
235        m_widens   = false;
236        m_wrapped  = false;
237    }
238    public static void noDuplicate(List<Modifier> mods) {
239        for (Modifier mod : mods) {
240            mod.accept(new NodeDepthFirstVisitor_void() {
241                    public void forModifierAtomic(ModifierAtomic m) {
242                        if (m_atomic) multiple(m);
243                        else m_atomic = true;
244                    }
245                    public void forModifierGetter(ModifierGetter m) {
246                        if (m_getter) multiple(m);
247                        else m_getter = true;
248                    }
249                    public void forModifierHidden(ModifierHidden m) {
250                        if (m_hidden) multiple(m);
251                        else m_hidden = true;
252                    }
253                    public void forModifierIO(ModifierIO m) {
254                        if (m_io) multiple(m);
255                        else m_io = true;
256                    }
257                    public void forModifierPrivate(ModifierPrivate m) {
258                        if (m_private) multiple(m);
259                        else m_private = true;
260                    }
261                    public void forModifierSettable(ModifierSettable m) {
262                        if (m_settable) multiple(m);
263                        else m_settable = true;
264                    }
265                    public void forModifierSetter(ModifierSetter m) {
266                        if (m_setter) multiple(m);
267                        else m_setter = true;
268                    }
269                    public void forModifierTest(ModifierTest m) {
270                        if (m_test) multiple(m);
271                        else m_test = true;
272                    }
273                    public void forModifierValue(ModifierValue m) {
274                        if (m_value) multiple(m);
275                        else m_value = true;
276                    }
277                    public void forModifierVar(ModifierVar m) {
278                        if (m_var) multiple(m);
279                        else m_var = true;
280                    }
281                    public void forModifierWidens(ModifierWidens m) {
282                        if (m_widens) multiple(m);
283                        else m_widens = true;
284                    }
285                    public void forModifierWrapped(ModifierWrapped m) {
286                        if (m_wrapped) multiple(m);
287                        else m_wrapped = true;
288                    }
289                });
290        }
291        resetMods();
292    }
293
294    /* true is there exists a self parameter in a given parameter list */
295    public static boolean isFunctionalMethod(List<Param> params) {
296        for (Param p : params) {
297            if (p.getName().getText().equals("self")) return true;
298        }
299        return false;
300    }
301
302    public static boolean validId(String s) {
303        return (!FortressUtil.validOp(s) && !s.equals("_") &&
304                !s.equals("SUM") && !s.equals("PROD"));
305    }
306
307    private static boolean compoundOp(String s) {
308        return (s.length() > 1 && s.endsWith("=")
309                && !s.equals("<=") && !s.equals(">=")
310                && !s.equals("=/=") && !s.equals("==="));
311    }
312    private static boolean validOpChar(char c) {
313        return (c == '_' || java.lang.Character.isUpperCase(c));
314    }
315    public static boolean validOp(String s) {
316        if (s.equals("juxtaposition") || s.equals("in") || s.equals("per") ||
317            s.equals("square") || s.equals("cubic") || s.equals("inverse") ||
318            s.equals("squared") || s.equals("cubed"))
319            return true;
320        if (s.equals("SUM") || s.equals("PROD")) return false;
321        int length = s.length();
322        if (length < 2 || compoundOp(s)) return false;
323        char start = s.charAt(0);
324        if (length == 2 && start == s.charAt(1)) return false;
325        if (length > 2 && start == s.charAt(1) && s.charAt(2) == '_')
326            return false;
327        if (start == '_' || s.endsWith("_")) return false;
328        for (int i = 0; i < length; i++) {
329            if (!validOpChar(s.charAt(i))) return false;
330        }
331        return true;
332    }
333
334    public static boolean getMutable(List<Modifier> mods) {
335        for (Modifier m : mods) {
336            if (m instanceof ModifierVar || m instanceof ModifierSettable)
337                return true;
338        }
339        return false;
340    }
341
342    public static List<LValueBind> setMutable(List<LValueBind> vars) {
343        List<LValueBind> result = new ArrayList<LValueBind>();
344        for (LValueBind l : vars) {
345            result.add(NodeFactory.makeLValue(l, true));
346        }
347        return result;
348    }
349
350    public static List<LValueBind> setMutable(List<LValueBind> vars, Span span) {
351        List<LValueBind> result = new ArrayList<LValueBind>();
352        for (LValueBind l : vars) {
353            List<Modifier> mods = new ArrayList<Modifier>();
354            mods.add(new ModifierVar(span));
355            result.add(NodeFactory.makeLValue(l, mods));
356        }
357        return result;
358    }
359
360    public static List<LValueBind> setMods(List<LValueBind> vars,
361                                           List<Modifier> mods) {
362        List<LValueBind> result = new ArrayList<LValueBind>();
363        for (LValueBind l : vars) {
364            result.add(NodeFactory.makeLValue(l, mods));
365        }
366        return result;
367    }
368
369    public static List<LValueBind> setModsAndMutable(List<LValueBind> vars,
370                                                     List<Modifier> mods) {
371        List<LValueBind> result = new ArrayList<LValueBind>();
372        for (LValueBind l : vars) {
373            result.add(NodeFactory.makeLValue(l, mods, true));
374        }
375        return result;
376    }
377
378    public static List<LValue> setMutableLValue(List<LValue> vars, Span span) {
379        List<LValue> result = new ArrayList<LValue>();
380        for (LValue l : vars) {
381            if (l instanceof LValueBind) {
382                List<Modifier> mods = new ArrayList<Modifier>();
383                mods.add(new ModifierVar(span));
384                result.add(NodeFactory.makeLValue((LValueBind)l, mods));
385            } else syntaxError(l.getSpan(), "Unpasting cannot be mutable.");
386        }
387        return result;
388    }
389
390    public static List<LValue> setType(List<LValue> vars, Type ty) {
391        List<LValue> result = new ArrayList<LValue>();
392        for (LValue l : vars) {
393            if (l instanceof LValueBind)
394                result.add(NodeFactory.makeLValue((LValueBind)l, ty));
395            else syntaxError(l.getSpan(), "Unpasting cannot be set types.");
396        }
397        return result;
398    }
399
400    public static List<LValue> setType(List<LValue> vars, List<Type> tys) {
401        List<LValue> result = new ArrayList<LValue>();
402        int ind = 0;
403        for (LValue l : vars) {
404            if (l instanceof LValueBind) {
405                result.add(NodeFactory.makeLValue((LValueBind)l, tys.get(ind)));
406                ind += 1;
407            } else syntaxError(l.getSpan(), "Unpasting cannot be set types.");
408        }
409        return result;
410    }
411
412    public static List<LValue> setMutableAndType(List<LValue> vars, Type ty) {
413        List<LValue> result = new ArrayList<LValue>();
414        for (LValue l : vars) {
415            if (l instanceof LValueBind) {
416                result.add(NodeFactory.makeLValue((LValueBind)l, ty, true));
417            } else syntaxError(l.getSpan(), "Unpasting cannot be mutable.");
418        }
419        return result;
420    }
421
422    public static List<LValue> setMutableAndType(List<LValue> vars, Span span,
423                                                 Type ty) {
424        List<LValue> result = new ArrayList<LValue>();
425        for (LValue l : vars) {
426           if (l instanceof LValueBind) {
427               List<Modifier> mods = new ArrayList<Modifier>();
428               mods.add(new ModifierVar(span));
429               result.add(NodeFactory.makeLValue((LValueBind)l, ty, mods));
430           } else syntaxError(l.getSpan(), "Unpasting cannot be mutable.");
431        }
432        return result;
433    }
434
435    public static List<LValue> setMutableAndType(List<LValue> vars,
436                                                 List<Type> tys) {
437        List<LValue> result = new ArrayList<LValue>();
438        int ind = 0;
439        for (LValue l : vars) {
440            if (l instanceof LValueBind) {
441                result.add(NodeFactory.makeLValue((LValueBind)l, tys.get(ind),
442                                                  true));
443                ind += 1;
444            } else syntaxError(l.getSpan(), "Unpasting cannot be mutable.");
445        }
446        return result;
447    }
448
449    public static List<LValue> setMutableAndType(List<LValue> vars, Span span,
450                                                 List<Type> tys) {
451        List<LValue> result = new ArrayList<LValue>();
452        int ind = 0;
453        for (LValue l : vars) {
454            if (l instanceof LValueBind) {
455               List<Modifier> mods = new ArrayList<Modifier>();
456               mods.add(new ModifierVar(span));
457               result.add(NodeFactory.makeLValue((LValueBind)l, tys.get(ind),
458                                                 mods));
459               ind += 1;
460            } else syntaxError(l.getSpan(), "Unpasting cannot be mutable.");
461        }
462        return result;
463    }
464
465    public static List<LValueBind> ids2Lvs(List<Id> ids, List<Modifier> mods,
466                                           Option<Type> ty, boolean mutable) {
467        List<LValueBind> lvs = new ArrayList<LValueBind>();
468        for (Id id : ids) {
469            lvs.add(new LValueBind(id.getSpan(), id, ty, mods, mutable));
470        }
471        return lvs;
472    }
473
474    public static List<LValueBind> ids2Lvs(List<Id> ids, List<Modifier> mods,
475                                           Type ty, boolean mutable) {
476        return ids2Lvs(ids, mods, Option.some(ty), mutable);
477    }
478
479    public static List<LValueBind> ids2Lvs(List<Id> ids, Type ty,
480                                           boolean mutable) {
481        return ids2Lvs(ids, emptyModifiers(), Option.some(ty), mutable);
482    }
483
484    public static List<LValueBind> ids2Lvs(List<Id> ids, List<Modifier> mods) {
485        return ids2Lvs(ids, mods, Option.<Type>none(), false);
486    }
487
488    public static List<LValueBind> ids2Lvs(List<Id> ids) {
489        return ids2Lvs(ids, emptyModifiers(), Option.<Type>none(), false);
490    }
491
492    public static List<LValueBind> ids2Lvs(List<Id> ids, List<Modifier> mods,
493                                           List<Type> tys, boolean mutable) {
494        List<LValueBind> lvs = new ArrayList<LValueBind>();
495        int ind = 0;
496        for (Id id : ids) {
497            lvs.add(new LValueBind(id.getSpan(), id, Option.some(tys.get(ind)),
498                                   mods, mutable));
499            ind += 1;
500        }
501        return lvs;
502    }
503
504    public static List<LValueBind> ids2Lvs(List<Id> ids, List<Type> tys,
505                                           boolean mutable) {
506        return ids2Lvs(ids, emptyModifiers(), tys, mutable);
507    }
508
509    public static AbsFnDecl mkAbsFnDecl(Span span, List<Modifier> mods,
510                                        Option<Id> receiver,
511                                        FnHeaderFront fhf, FnHeaderClause fhc) {
512        Option<List<BaseType>> throws_ = fhc.getThrowsClause();
513        WhereClause where_ = fhc.getWhereClause();
514        Contract contract = fhc.getContractClause().unwrap(emptyContract());
515        return NodeFactory.makeAbsFnDecl(span, mods, receiver, fhf.getName(),
516                                         fhf.getStaticParams(), fhf.getParams(),
517                                         fhc.getReturnType(), throws_, where_,
518                                         contract);
519    }
520
521    public static AbsFnDecl mkAbsFnDecl(Span span, List<Modifier> mods,
522                                        FnHeaderFront fhf, FnHeaderClause fhc) {
523        return mkAbsFnDecl(span, mods, Option.<Id>none(), fhf, fhc);
524    }
525
526    public static AbsFnDecl mkAbsFnDecl(Span span, List<Modifier> mods,
527                                        IdOrOpOrAnonymousName name, List<StaticParam> sparams,
528                                        List<Param> params,
529                                        FnHeaderClause fhc) {
530        Option<List<BaseType>> throws_ = fhc.getThrowsClause();
531        WhereClause where_ = fhc.getWhereClause();
532        Contract contract = fhc.getContractClause().unwrap(emptyContract());
533        return NodeFactory.makeAbsFnDecl(span, mods, Option.<Id>none(), name,
534                                         sparams, params,
535                                         Option.<Type>none(), throws_,
536                                         where_, contract);
537    }
538
539    public static AbsFnDecl mkAbsFnDecl(Span span, List<Modifier> mods,
540                                        IdOrOpOrAnonymousName name, List<Param> params,
541                                        Type ty) {
542        return NodeFactory.makeAbsFnDecl(span, mods, Option.<Id>none(), name,
543                                         emptyStaticParams(), params,
544                                         Option.some(ty),
545                                         Option.<List<BaseType>>none(),
546                                         emptyWhereClause(), emptyContract());
547    }
548
549    public static FnDef mkFnDecl(Span span, List<Modifier> mods,
550                                 Option<Id> receiver, FnHeaderFront fhf,
551                                 FnHeaderClause fhc, Expr expr) {
552        Option<List<BaseType>> throws_ = fhc.getThrowsClause();
553        WhereClause where_ = fhc.getWhereClause();
554        Contract contract = fhc.getContractClause().unwrap(emptyContract());
555        return NodeFactory.makeFnDecl(span, mods, receiver, fhf.getName(),
556                                      fhf.getStaticParams(), fhf.getParams(),
557                                      fhc.getReturnType(), throws_, where_,
558                                      contract, expr);
559    }
560
561    public static FnDef mkFnDecl(Span span, List<Modifier> mods, IdOrOpOrAnonymousName name,
562                                 List<StaticParam> sparams, List<Param> params,
563                                 FnHeaderClause fhc, Expr expr) {
564        Option<List<BaseType>> throws_ = fhc.getThrowsClause();
565        WhereClause where_ = fhc.getWhereClause();
566        Contract contract = fhc.getContractClause().unwrap(emptyContract());
567        return NodeFactory.makeFnDecl(span, mods, Option.<Id>none(), name,
568                                      sparams, params, Option.<Type>none(),
569                                      throws_, where_, contract, expr);
570    }
571
572    public static FnDef mkFnDecl(Span span, List<Modifier> mods,
573                                 FnHeaderFront fhf, FnHeaderClause fhc,
574                                 Expr expr) {
575        return mkFnDecl(span, mods, Option.<Id>none(), fhf, fhc, expr);
576    }
577
578    public static LocalVarDecl mkLocalVarDecl(Span span, List<LValue> lvs,
579                                              Option<Expr> expr) {
580        return new LocalVarDecl(span, false, emptyExprs(), lvs, expr);
581    }
582    public static LocalVarDecl mkLocalVarDecl(Span span, List<LValue> lvs,
583                                              Expr expr) {
584        return new LocalVarDecl(span, false, emptyExprs(), lvs,
585                                Option.some(expr));
586    }
587    public static LocalVarDecl mkLocalVarDecl(Span span, List<LValue> lvs) {
588        return new LocalVarDecl(span, false, emptyExprs(), lvs,
589                                Option.<Expr>none());
590    }
591
592    public static LValueBind mkLValueBind(Span span, Id id, Type ty) {
593        return new LValueBind(span, id, Option.some(ty), emptyModifiers(),false);
594    }
595    public static LValueBind mkLValueBind(Span span, Id id) {
596        return new LValueBind(span, id, Option.<Type>none(),
597                              emptyModifiers(), false);
598    }
599    public static LValueBind mkLValueBind(Id id, Type ty,
600                                          List<Modifier> mods) {
601        return new LValueBind(id.getSpan(), id, Option.some(ty), mods,
602                              getMutable(mods));
603    }
604    public static LValueBind mkLValueBind(Id id, Type ty) {
605        return mkLValueBind(id, ty, emptyModifiers());
606    }
607
608// let rec multi_dim_cons (expr : expr)
609//                        (dim : int)
610//                        (multi : multi_dim_expr) : multi_dim_expr =
611//   let elem = multi_dim_elem expr in
612//   let span = span_two expr multi in
613//     match multi.node_data with
614//       | `ArrayElement _ ->
615//           multi_dim_row span dim [ elem; multi ]
616//       | `ArrayElements
617//           { node_span = row_span;
618//             node_data =
619//               { multi_dim_row_dimension = row_dim;
620//                 multi_dim_row_elements = elements; } } ->
621//           if dim = row_dim
622//           then multi_dim_row span dim (elem :: elements)
623//           else if dim > row_dim
624//           then multi_dim_row span dim [ elem; multi ]
625//           else
626//             (match elements with
627//                | [] -> Errors.internal_error row_span
628//                    "empty array/matrix literal"
629//                | first::rest ->
630//                    multi_dim_row span row_dim
631//                      (multi_dim_cons expr dim first :: rest))
632    private static ArrayExpr multiDimElement(Expr expr) {
633        return new ArrayElement(expr.getSpan(), false, expr);
634    }
635    private static ArrayElements addOneMultiDim(ArrayExpr multi, int dim,
636                                              Expr expr){
637        Span span = spanTwo(multi, expr);
638        ArrayExpr elem = multiDimElement(expr);
639        if (multi instanceof ArrayElement) {
640            List<ArrayExpr> elems = new ArrayList<ArrayExpr>();
641            elems.add(multi);
642            elems.add(elem);
643            return new ArrayElements(span, false, dim, elems);
644        } else if (multi instanceof ArrayElements) {
645            ArrayElements m = (ArrayElements)multi;
646            int _dim = m.getDimension();
647            List<ArrayExpr> elements = m.getElements();
648            if (dim == _dim) {
649                elements.add(elem);
650                return new ArrayElements(span, false, dim, elements);
651            } else if (dim > _dim) {
652                List<ArrayExpr> elems = new ArrayList<ArrayExpr>();
653                elems.add(multi);
654                elems.add(elem);
655                return new ArrayElements(span, false, dim, elems);
656            } else if (elements.size() == 0) {
657                return syntaxError(multi.getSpan(),
658                                   "Empty array/matrix literal.");
659            } else { // if (dim < _dim)
660                int index = elements.size()-1;
661                ArrayExpr last = elements.get(index);
662                elements.set(index, addOneMultiDim(last, dim, expr));
663                return new ArrayElements(span, false, _dim, elements);
664            }
665        } else {
666            return syntaxError(multi.getSpan(),
667                               "ArrayElement or ArrayElements is expected.");
668        }
669    }
670    public static ArrayElements multiDimCons(Expr init,
671                                        List<Pair<Integer,Expr>> rest) {
672        ArrayExpr _init = multiDimElement(init);
673        if (rest.isEmpty()) {
674            return bug(init, "multiDimCons: empty rest");
675        } else {
676            Pair<Integer,Expr> pair = rest.get(0);
677            Expr expr = pair.getB();
678            List<ArrayExpr> elems = new ArrayList<ArrayExpr>();
679            elems.add(_init);
680            elems.add(multiDimElement(expr));
681            ArrayElements result = new ArrayElements(spanTwo(_init,expr), false,
682                                                     pair.getA(), elems);
683            for (Pair<Integer,Expr> _pair : rest.subList(1, rest.size())) {
684                int _dim   = _pair.getA();
685                Expr _expr = _pair.getB();
686                Span span = spanTwo(result, _expr);
687                result = addOneMultiDim(result, _dim, _expr);
688            }
689            return result;
690        }
691    }
692
693    public static ArrayElements finalizeArrayExpr(ArrayElements a) {
694        return new ArrayElements(a.getSpan(), a.isParenthesized(),
695                                 a.getStaticArgs(), a.getDimension(),
696                                 a.getElements(), true);
697    }
698
699    public static ArrayElements addStaticArgsToArrayExpr(List<StaticArg> sargs,
700                                                         ArrayElements a) {
701        return new ArrayElements(a.getSpan(), a.isParenthesized(),
702                                 sargs, a.getDimension(),
703                                 a.getElements(), true);
704    }
705
706// let rec unpasting_cons (span : span)
707//                        (one : unpasting)
708//                        (sep : int)
709//                        (two : unpasting) : unpasting =
710//   match two.node_data with
711//     | `UnpastingBind _ | `UnpastingNest _ -> unpasting_split span sep [one;two]
712//     | `UnpastingSplit split ->
713//         (match split.node_data with
714//            | { unpasting_split_elems = (head :: tail) as elems;
715//                unpasting_split_dim = dim; } ->
716//                if sep > dim then unpasting_split span sep [one;two]
717//                else if sep < dim then
718//                  unpasting_split span dim
719//                    (unpasting_cons (span_two one head) one sep head :: tail)
720//                else (* sep = dim *)
721//                  unpasting_split span dim (one :: elems)
722//            | _ -> Errors.internal_error span "Empty unpasting.")
723    public static Unpasting unpastingCons(Span span, Unpasting one, int sep,
724                                          Unpasting two) {
725        List<Unpasting> onetwo = new ArrayList<Unpasting>();
726        onetwo.add(one);
727        onetwo.add(two);
728        if (two instanceof UnpastingBind) {
729            return new UnpastingSplit(span, onetwo, sep);
730        } else if (two instanceof UnpastingSplit) {
731            UnpastingSplit split = (UnpastingSplit)two;
732            List<Unpasting> elems = split.getElems();
733            if (elems.size() != 0) {
734                int dim = split.getDim();
735                if (sep > dim) {
736                    return new UnpastingSplit(span, onetwo, sep);
737                } else if (sep < dim) {
738                    Unpasting head = elems.get(0);
739                    elems.set(0, unpastingCons(spanTwo(one,head),one,sep,head));
740                    return new UnpastingSplit(span, elems, dim);
741                } else { // sep = dim
742                    elems.add(0, one);
743                    return new UnpastingSplit(span, elems, dim);
744                }
745            } else { // elems.size() == 0
746                return syntaxError(two.getSpan(), "Empty unpasting.");
747            }
748        } else { //    !(two instanceof UnpastingBind)
749                 // && !(two instanceof UnpastingSplit)
750            return bug(two, "UnpastingBind or UnpastingSplit expected.");
751        }
752    }
753
754// let join (one : span) (two : span) : span =
755//   match one, two with
756//     | None, span | span, None -> span
757//     | Some (left,_), Some (_,right) -> Some (left,right)
758
759// let span_two (one : 'a node) (two : 'b node) : span =
760//   join one.node_span two.node_span
761
762    public static Span spanTwo(Node s1, Node s2) {
763        return new Span(s1.getSpan().getBegin(), s2.getSpan().getEnd());
764    }
765
766    public static Span spanTwo(Span s1, Span s2) {
767        return new Span(s1.getBegin(), s2.getEnd());
768    }
769
770// let rec span_all (com.sun.fortress.interpreter.nodes : 'a node list) : span =
771//   match com.sun.fortress.interpreter.nodes with
772//     | [] -> None
773//     | node :: rest -> join node.node_span (span_all rest)
774    public static Span spanAll(Object[] nodes, int size) {
775        if (size == 0) return new Span();
776        else { // size != 0
777            return new Span(((Node)Array.get(nodes,0)).getSpan().getBegin(),
778                            ((Node)Array.get(nodes,size-1)).getSpan().getEnd());
779        }
780    }
781
782    public static Span spanAll(Iterable<? extends Node> nodes) {
783        if (IterUtil.isEmpty(nodes)) { return new Span(); }
784        else {
785            return new Span(IterUtil.first(nodes).getSpan().getBegin(),
786                            IterUtil.last(nodes).getSpan().getEnd());
787        }
788    }
789
790    public static Span spanAll(SourceLoc defaultLoc, Iterable<? extends Node> nodes) {
791        if (IterUtil.isEmpty(nodes)) { return new Span(defaultLoc, defaultLoc); }
792        else {
793            return new Span(IterUtil.first(nodes).getSpan().getBegin(),
794                            IterUtil.last(nodes).getSpan().getEnd());
795        }
796    }
797
798// let build_block (exprs : expr list) : expr list =
799//   List_aux.foldr
800//     (fun e es ->
801//        match e.node_data with
802//          | `LetExpr (le,[]) -> [{ e with node_data = `LetExpr (le, es) }]
803//          | `LetExpr _ -> raise (Failure "misparsed variable introduction!")
804//          | _ -> e :: es)
805//     exprs
806//     []
807//
808// let do_block (body : expr list) : expr =
809//   let span = span_all body in
810//     node span (`FlowExpr (node span (`BlockExpr (build_block body))))
811    public static Block doBlock(Span span) {
812        return new Block(span, false, emptyExprs());
813    }
814
815    public static Block doBlock(List<Expr> exprs) {
816        Span span = spanAll(exprs.toArray(new AbstractNode[0]), exprs.size());
817        List<Expr> es = new ArrayList<Expr>();
818        Collections.reverse(exprs);
819        for (Expr e : exprs) {
820            if (e instanceof LetExpr) {
821                LetExpr _e = (LetExpr)e;
822                if (_e.getBody().isEmpty()) {
823                    _e = ExprFactory.makeLetExpr(_e, es);
824                    es = mkList((Expr)_e);
825                } else {
826                    syntaxError(e.getSpan(), "Misparsed variable introduction!");
827                }
828            } else {
829                if (isEquality(e) && !e.isParenthesized())
830                    syntaxError(e.getSpan(),
831                                "Equality testing expressions should be parenthesized.");
832                else es.add(0, e);
833            }
834        }
835        return new Block(span, false, es);
836    }
837
838    private static boolean isEquality(Expr expr) {
839        if (expr instanceof ChainExpr) {
840            ChainExpr e = (ChainExpr)expr;
841            List<Link> links = e.getLinks();
842            if (links.size() == 1) {
843                OpName op = links.get(0).getOp().getOriginalName();
844                return (op instanceof Op && ((Op)op).getText().equals("="));
845            } else return false;
846        } else return false;
847    }
848
849// (* Turn an expr list into a single TightJuxt *)
850// let build_primary (p : expr list) : expr =
851//   match p with
852//     | [e] -> e
853//     | _ ->
854//         let es = List.rev p in
855//           Node.node (span_all es) (`TightJuxt es)
856    public static Expr buildPrimary(PureList<Expr> exprs) {
857        if (exprs.size() == 1) return ((Cons<Expr>)exprs).getFirst();
858        else {
859            exprs = exprs.reverse();
860            List<Expr> javaList = exprs.toJavaList();
861            return new TightJuxt(spanAll(javaList.toArray(new AbstractNode[0]),
862                                         javaList.size()), false, javaList);
863        }
864    }
865}
Note: See TracBrowser for help on using the browser.