KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > kawa > standard > syntax_case


1 package kawa.standard;
2 import kawa.lang.*;
3 import gnu.lists.*;
4 import gnu.expr.*;
5 import gnu.math.IntNum;
6 import gnu.bytecode.*;
7
8 public class syntax_case extends Syntax
9 {
10   public static final syntax_case syntax_case = new syntax_case();
11   static { syntax_case.setName("syntax-case"); }
12
13   PrimProcedure call_error;
14
15   Expression rewriteClauses (Object JavaDoc clauses, syntax_case_work work,
16                              Translator tr)
17   {
18     Language language = tr.getLanguage();
19     if (clauses == LList.Empty)
20       {
21         /*
22         // FIXME - throw exception instead?? perhaps SyntaxException?
23         return new QuoteExp(new Pair("quote",
24                                      new Pair("((no match in syntax-case))",
25                                      LList.Empty)));
26         */

27         Expression[] args = new Expression[2];
28         args[0] = new QuoteExp("syntax-case");
29         args[1] = new ReferenceExp(work.inputExpression);
30         if (call_error == null)
31           {
32             ClassType clas = ClassType.make("kawa.standard.syntax_case");
33             Type[] argtypes = new Type[2];
34             argtypes[0] = Compilation.javaStringType;
35             argtypes[1] = Type.pointer_type;
36             Method method = clas.addMethod("error", argtypes,
37                                            Type.pointer_type,
38                                            Access.PUBLIC|Access.STATIC);
39             call_error = new PrimProcedure(method, language);
40           }
41         return new ApplyExp(call_error, args);
42       }
43     Object JavaDoc savePos = tr.pushPositionOf(clauses);
44     Object JavaDoc clause;
45     try
46       {
47     if (! (clauses instanceof Pair)
48         || ! ((clause = ((Pair) clauses).car) instanceof Pair))
49       return tr.syntaxError("syntax-case: bad clause list");
50     Pair pair = (Pair) clause;
51     PatternScope clauseScope = PatternScope.push(tr);
52     clauseScope.matchArray = tr.matchArray;
53     tr.push(clauseScope);
54     int outerVarCount = clauseScope.pattern_names.size();
55     SyntaxPattern pattern
56       = new SyntaxPattern(pair.car, work.literal_identifiers, tr);
57     int varCount = pattern.varCount();
58     if (varCount > work.maxVars)
59       work.maxVars = varCount;
60
61     BlockExp block = new BlockExp();
62     Expression[] args = new Expression[4];
63     args[0] = new QuoteExp(pattern);
64     args[1] = new ReferenceExp(work.inputExpression);
65     args[2] = new ReferenceExp(tr.matchArray);
66     args[3] = new QuoteExp(IntNum.zero());
67     Expression tryMatch
68       = new ApplyExp(new PrimProcedure(Pattern.matchPatternMethod, language), args);
69
70     int newVarCount = varCount - outerVarCount;
71     Expression[] inits = new Expression[newVarCount];
72     for (int i = newVarCount; --i >= 0; )
73       inits[i] = QuoteExp.undefined_exp;
74     clauseScope.inits = inits;
75
76     Expression output;
77         SyntaxForm syntax = null;
78         Object JavaDoc tail = pair.cdr;
79         while (tail instanceof SyntaxForm)
80           {
81             syntax = (SyntaxForm) tail;
82             tail = syntax.form;
83           }
84     pair = (Pair) tail;
85     if (pair.cdr == LList.Empty)
86       output = tr.rewrite_car(pair, syntax);
87     else
88       {
89         Expression fender = tr.rewrite_car(pair, syntax);
90         if (! (pair.cdr instanceof Pair
91            && (pair = (Pair) pair.cdr).cdr == LList.Empty))
92           return tr.syntaxError("syntax-case: bad clause");
93         output = new IfExp(fender, tr.rewrite_car(pair, syntax),
94                                new ExitExp(block));
95       }
96     clauseScope.setBody(output);
97
98     tr.pop(clauseScope);
99     PatternScope.pop(tr);
100     block.setBody(new IfExp(tryMatch, clauseScope, new ExitExp(block)),
101               rewriteClauses(((Pair) clauses).cdr, work, tr));
102     return block;
103       }
104     finally
105       {
106     tr.popPositionOf(savePos);
107       }
108   }
109
110   public Expression rewriteForm (Pair form, Translator tr)
111   {
112     syntax_case_work work = new syntax_case_work();
113
114     Object JavaDoc obj = form.cdr;
115     if (obj instanceof Pair)
116       {
117         form = (Pair) obj;
118         Expression input = tr.rewrite(form.car);
119         obj = form.cdr;
120         if (obj instanceof Pair)
121           {
122             form = (Pair) obj;
123         work.literal_identifiers
124           = SyntaxPattern.getLiteralsList(form.car, null, tr);
125             obj = form.cdr;
126
127             Expression[] linits = new Expression[2];
128             linits[0] = input;
129             LetExp let = new LetExp(linits);
130             work.inputExpression = let.addDeclaration((String JavaDoc) null);
131             work.inputExpression.noteValue(linits[0]);
132         Declaration matchArrayOuter = tr.matchArray;
133         Declaration matchArray = let.addDeclaration((String JavaDoc) null);
134             matchArray.setType(Compilation.objArrayType);
135             matchArray.setCanRead(true);
136         tr.matchArray = matchArray;
137             work.inputExpression.setCanRead(true);
138             tr.push(let);
139             let.body = rewriteClauses(obj, work, tr);
140             tr.pop(let);
141
142         Method allocVars = ClassType.make("kawa.lang.SyntaxPattern")
143           .getDeclaredMethod("allocVars", 2);
144             Expression[] args = new Expression[2];
145             args[0] = new QuoteExp(IntNum.make(work.maxVars));
146         if (matchArrayOuter == null)
147           args[1] = QuoteExp.nullExp;
148         else
149           args[1] = new ReferenceExp(matchArrayOuter);
150             linits[1] = new ApplyExp(allocVars, args);
151             matchArray.noteValue(linits[1]);
152         tr.matchArray = matchArrayOuter;
153             return let;
154           }
155       }
156     return tr.syntaxError("insufficiant arguments to syntax-case");
157   }
158
159   /** Called (at run-time) if syntax-case has no match. */
160   public static Object JavaDoc error(String JavaDoc kind, Object JavaDoc arg)
161   {
162     Translator tr = (Translator) Compilation.getCurrent();
163     if (tr == null)
164       throw new RuntimeException JavaDoc("no match in syntax-case");
165     Syntax syntax = tr.getCurrentSyntax();
166     String JavaDoc name = syntax == null ? "some syntax" : syntax.getName();
167     String JavaDoc msg = "no matching case while expanding " + name;
168     return tr.syntaxError(msg);
169   }
170 }
171
172 class syntax_case_work
173 {
174   LetExp let;
175   Object JavaDoc[] literal_identifiers;
176
177   /** A temporary to hold the value of the input expression. */
178   Declaration inputExpression;
179
180   /** The maximum of the varCount() for the patterns seen so far. */
181   int maxVars;
182 }
183
Popular Tags