KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > kawa > standard > object


1 package kawa.standard;
2 import gnu.expr.*;
3 import kawa.lang.*;
4 import gnu.lists.*;
5 import java.util.Vector JavaDoc;
6 import gnu.mapping.Symbol;
7 import gnu.bytecode.Type;
8 import gnu.kawa.functions.Convert;
9
10 public class object extends Syntax
11 {
12   public static final object objectSyntax
13     = new kawa.standard.object(Scheme.lambda);
14   static { objectSyntax.setName("object"); }
15
16   Lambda lambda;
17   public static final Keyword accessKeyword = Keyword.make("access");
18   public static final Keyword throwsKeyword = Keyword.make("throws");
19   static final Keyword typeKeyword = Keyword.make("type");
20   public static final Keyword allocationKeyword = Keyword.make("allocation");
21   static final Keyword initKeyword = Keyword.make("init");
22   static final Keyword initformKeyword = Keyword.make("initform");
23   static final Keyword init_formKeyword = Keyword.make("init-form");
24   static final Keyword init_valueKeyword = Keyword.make("init-value");
25   static final Keyword init_keywordKeyword = Keyword.make("init-keyword");
26
27   public object(Lambda lambda)
28   {
29     this.lambda = lambda;
30   }
31
32   public Expression rewriteForm (Pair form, Translator tr)
33   {
34     if (! (form.cdr instanceof Pair))
35       return tr.syntaxError("missing superclass specification in object");
36     Pair pair = (Pair) form.cdr;
37     ObjectExp oexp = new ObjectExp();
38     if (pair.car instanceof FString)
39       {
40         // oexp.setName(pair.car.toString());
41
if (! (pair.cdr instanceof Pair))
42       return tr.syntaxError("missing superclass specification after object class name");
43     pair = (Pair) pair.cdr;
44       }
45     Object JavaDoc[] saved = scanClassDef(pair, oexp, tr);
46     if (saved != null)
47       rewriteClassDef(saved, tr);
48     return oexp;
49   }
50
51   /** Does the first "scan-time" processing of the class/object definition.
52    * Returns an array of values to be used at "rewrite-time".
53    */

54   public Object JavaDoc[] scanClassDef (Pair pair, ClassExp oexp, Translator tr)
55   {
56     tr.mustCompileHere();
57     Object JavaDoc superlist = pair.car;
58     Object JavaDoc components = pair.cdr;
59     LambdaExp method_list = null;
60     LambdaExp last_method = null;
61     // First pass (get Declarations).
62
Vector JavaDoc inits = new Vector JavaDoc(20);
63     for (Object JavaDoc obj = components; obj != LList.Empty; )
64       {
65     // The SyntaxForm scopes aren't used in scanClassDef, but they are
66
// used in rewriteClassDef, and might as well make the code the same.
67
while (obj instanceof SyntaxForm)
68       obj = ((SyntaxForm) obj).form;
69     if (! (obj instanceof Pair))
70       {
71         tr.error('e', "object member not a list");
72         return null;
73       }
74     pair = (Pair) obj;
75     Object JavaDoc pair_car = pair.car;
76     while (pair_car instanceof SyntaxForm)
77       pair_car = ((SyntaxForm) pair_car).form;
78     if (! (pair_car instanceof Pair))
79       {
80         tr.error('e', "object member not a list");
81         return null;
82       }
83     obj = pair.cdr; // Next member.
84
Object JavaDoc savedPos1 = tr.pushPositionOf(pair);
85     pair = (Pair) pair_car;
86     pair_car = pair.car;
87     while (pair_car instanceof SyntaxForm)
88       pair_car = ((SyntaxForm) pair_car).form;
89     if (pair_car instanceof String JavaDoc || pair_car instanceof Symbol
90         || pair_car instanceof Keyword)
91       { // Field declaration.
92
Pair typePair = null;
93         Object JavaDoc sname = pair_car;
94         Object JavaDoc args;
95         Declaration decl;
96         int allocationFlag = 0;
97         String JavaDoc accessFlagName = null;
98         int accessFlag = 0;
99         if (sname instanceof Keyword)
100           {
101         decl = null;
102         args = pair;
103           }
104         else
105           {
106         decl = oexp.addDeclaration(sname);
107         decl.setSimple(false);
108         decl.setFlag(Declaration.FIELD_OR_METHOD);
109         Translator.setLine(decl, pair);
110         args = pair.cdr;
111           }
112         int nKeywords = 0;
113         boolean seenInit = false;
114         Pair initPair = null;
115         while (args instanceof Pair)
116           {
117         pair = (Pair) args;
118         Pair keyPair = pair;
119         Object JavaDoc key = pair.car;
120         Object JavaDoc savedPos2 = tr.pushPositionOf(pair);
121         args = pair.cdr;
122         if ((key == "::" || key instanceof Keyword)
123             && args instanceof Pair)
124           {
125             nKeywords++;
126             pair = (Pair) args;
127             Object JavaDoc value = pair.car;
128             args = pair.cdr;
129             if (key == "::" || key == typeKeyword)
130               typePair = pair;
131             else if (key == allocationKeyword)
132               {
133             if (allocationFlag != 0)
134               tr.error('e', "duplicate allocation: specification");
135             if (matches(value, "class", tr)
136                 || matches(value, "static", tr))
137               allocationFlag = Declaration.STATIC_SPECIFIED;
138             else if (matches(value, "instance", tr))
139               allocationFlag = Declaration.NONSTATIC_SPECIFIED;
140             else
141               tr.error('e', "unknown allocation kind '"+value+"'");
142               }
143             else if (key == initKeyword
144                  || key == initformKeyword
145                  || key == init_formKeyword
146                  || key == init_valueKeyword)
147               {
148             if (seenInit)
149               tr.error('e', "duplicate initialization");
150             seenInit = true;
151             // In the case of 'init-form: EXPR' the scope of EXPR
152
// doesn't include this class;
153
// in the case of 'init: EXPR' it does.
154
if (key != initKeyword)
155               initPair = pair;
156               }
157             else if (key == init_keywordKeyword)
158               {
159             if (! (value instanceof Keyword))
160               tr.error('e', "invalid 'init-keyword' - not a keyword");
161             else if (((Keyword) value).getName()
162                  != sname.toString())
163               tr.error('w', "init-keyword option ignored");
164               }
165             else if (key == accessKeyword)
166               {
167             String JavaDoc newAccessFlag = null;
168             if (matches(value, "private", tr))
169               {
170                 newAccessFlag = "private";
171                 accessFlag = Declaration.PRIVATE_ACCESS;
172               }
173             else if (matches(value, "protected", tr))
174               {
175                 newAccessFlag = "protected";
176                 accessFlag = Declaration.PROTECTED_ACCESS;
177               }
178             else if (matches(value, "public", tr))
179               {
180                 newAccessFlag = "public";
181                 accessFlag = Declaration.PUBLIC_ACCESS;
182               }
183             else if (matches(value, "package", tr))
184               {
185                 newAccessFlag = "package";
186                 accessFlag = Declaration.PACKAGE_ACCESS;
187               }
188             else
189               {
190                 tr.error('e', "unknown access specifier");
191               }
192             if (accessFlagName != null && newAccessFlag != null)
193               {
194                 tr.error('e', "duplicate access specifiers - "
195                      + accessFlagName + " and "
196                      + newAccessFlag);
197               }
198             accessFlagName = newAccessFlag;
199               }
200             else
201               {
202             tr.error('w', "unknown slot keyword '"+key+"'");
203               }
204           }
205         else if (args == LList.Empty && ! seenInit)
206           {
207             // CLtL:2 explicitly prohibits this as an extension.
208
initPair = keyPair;
209             seenInit = true;
210           }
211         else if (args instanceof Pair
212              && nKeywords == 0 && ! seenInit && typePair == null
213              && (pair = (Pair) args).cdr == LList.Empty)
214           {
215             // Backward compatibility.
216
typePair = keyPair;
217             initPair = pair;
218             args = pair.cdr;
219             seenInit = true;
220           }
221         else
222           {
223             args = null; // Trigger error message
224
break;
225           }
226         tr.popPositionOf(savedPos2);
227           }
228         if (args != LList.Empty)
229           {
230         tr.error('e', "invalid argument list for slot '"
231              + sname + '\''+" args:"+(args==null?"null":args.getClass().getName()));
232         return null;
233           }
234         if (seenInit)
235           {
236         boolean isStatic
237           = allocationFlag == Declaration.STATIC_SPECIFIED;
238         inits.addElement(decl != null ? (Object JavaDoc) decl
239                  : isStatic ? Boolean.TRUE : Boolean.FALSE);
240         inits.addElement(initPair);
241           }
242         if (decl == null)
243           {
244         if (! seenInit)
245           {
246             tr.error('e', "missing field name");
247             return null;
248           }
249           }
250         else
251           {
252         if (typePair != null)
253           decl.setType(tr.exp2Type(typePair));
254         if (allocationFlag != 0)
255           decl.setFlag(allocationFlag);
256         if (accessFlag != 0)
257           decl.setFlag(accessFlag);
258         decl.setCanRead(true);
259         decl.setCanWrite(true);
260           }
261       }
262     else if (pair_car instanceof Pair)
263       { // Method declaration.
264
Pair mpair = (Pair) pair_car;
265         Object JavaDoc mname = mpair.car;
266         if (! (mname instanceof String JavaDoc)
267         && ! (mname instanceof Symbol))
268           {
269         tr.error('e', "missing method name");
270         return null;
271           }
272         Declaration decl
273               = oexp.addDeclaration(mname, Compilation.typeProcedure);
274         Translator.setLine(decl, mpair);
275         LambdaExp lexp = new LambdaExp();
276         lexp.outer = oexp;
277         lexp.setClassMethod(true);
278         decl.noteValue(lexp);
279         decl.setFlag(Declaration.FIELD_OR_METHOD);
280         decl.setProcedureDecl(true);
281         lexp.setSymbol(mname);
282         if (last_method == null)
283           method_list = lexp;
284         else
285           last_method.nextSibling = lexp;
286         last_method = lexp;
287       }
288     else
289       tr.error ('e', "invalid field/method definition");
290     tr.popPositionOf(savedPos1);
291       }
292     Object JavaDoc[] result = {
293       oexp,
294       components,
295       inits,
296       method_list,
297       superlist
298     };
299     return result;
300   }
301
302   public void rewriteClassDef (Object JavaDoc[] saved, Translator tr)
303   {
304     ClassExp oexp = (ClassExp) saved[0];
305     Object JavaDoc components = saved[1];
306     Vector JavaDoc inits = (Vector JavaDoc) saved[2];
307     LambdaExp method_list = (LambdaExp) saved[3];
308     Object JavaDoc superlist = saved[4];
309     oexp.firstChild = method_list;
310
311     int num_supers = Translator.listLength(superlist);
312     if (num_supers < 0)
313       {
314         tr.error('e', "object superclass specification not a list");
315         num_supers = 0;
316       }
317     Expression[] supers = new Expression[num_supers];
318     for (int i = 0; i < num_supers; i++)
319       {
320     while (superlist instanceof SyntaxForm)
321       {
322         // FIXME - need to pass syntax.
323
superlist = ((SyntaxForm) superlist).form;
324       }
325     Pair superpair = (Pair) superlist;
326     supers[i] = tr.rewrite_car(superpair, false);
327     superlist = superpair.cdr;
328       }
329     oexp.supers = supers;
330
331     oexp.setClassName(tr);
332     oexp.setTypes(tr);
333
334     // First a pass over init-form: specifiers, since these are evaluated
335
// in a scope outside the current class.
336
int len = inits.size();
337     for (int i = 0; i < len; i += 2)
338       {
339     Object JavaDoc init = inits.elementAt(i+1);
340     if (init != null)
341           rewriteInit(inits.elementAt(i), oexp, (Pair) init, tr, null);
342       }
343
344     tr.push(oexp);
345
346     // Pass to rewrite method/initializer bodies.
347
LambdaExp meth = method_list;
348     int init_index = 0; // Input index in inits Vector.
349
SyntaxForm componentsSyntax = null;
350     for (Object JavaDoc obj = components; obj != LList.Empty; )
351       {
352     while (obj instanceof SyntaxForm)
353       {
354         componentsSyntax = (SyntaxForm) obj;
355         obj = componentsSyntax.form;
356       }
357     Pair pair = (Pair) obj;
358     Object JavaDoc savedPos1 = tr.pushPositionOf(pair);
359     Object JavaDoc pair_car = pair.car;
360     SyntaxForm memberSyntax = componentsSyntax;
361     while (pair_car instanceof SyntaxForm)
362       {
363         memberSyntax = (SyntaxForm) pair_car;
364         pair_car = memberSyntax.form;
365       }
366     try
367       {
368         obj = pair.cdr; // Next member.
369
pair = (Pair) pair_car;
370         pair_car = pair.car;
371         SyntaxForm memberCarSyntax = memberSyntax;
372         while (pair_car instanceof SyntaxForm)
373           {
374         memberCarSyntax = (SyntaxForm) pair_car;
375         pair_car = memberCarSyntax.form;
376           }
377         if (pair_car instanceof String JavaDoc || pair_car instanceof Symbol
378         || pair_car instanceof Keyword)
379           { // Field declaration.
380
Object JavaDoc type = null;
381         int nKeywords = 0;
382         Object JavaDoc args = pair_car instanceof Keyword ? pair : pair.cdr;
383         Pair initPair = null;
384         while (args instanceof Pair)
385           {
386             pair = (Pair) args;
387             Object JavaDoc key = pair.car;
388             Object JavaDoc savedPos2 = tr.pushPositionOf(pair);
389             args = pair.cdr;
390             if ((key == "::" || key instanceof Keyword)
391             && args instanceof Pair)
392               {
393             nKeywords++;
394             pair = (Pair) args;
395             Object JavaDoc value = pair.car;
396             args = pair.cdr;
397             if (key == "::" || key == typeKeyword)
398               type = value;
399             else if (key == initKeyword
400                  || key == initformKeyword
401                  || key == init_formKeyword
402                  || key == init_valueKeyword)
403               {
404                 initPair = pair;
405               }
406             else
407               {
408                 // handled in first pass.
409
}
410               }
411             else if (args == LList.Empty && initPair == null)
412               {
413             // CLtL:2 explicitly prohibits this as an extension.
414
initPair = pair;
415               }
416             else if (args instanceof Pair && nKeywords == 0
417                  && initPair == null && type == null
418                  && (pair = (Pair) args).cdr == LList.Empty)
419               {
420             // Backward compatibility.
421
type = key;
422             initPair = pair;
423             args = pair.cdr;
424               }
425             else
426               {
427             args = null; // Trigger error message
428
break;
429               }
430             tr.popPositionOf(savedPos2);
431           }
432         if (initPair != null)
433           {
434             Object JavaDoc d = inits.elementAt(init_index++);
435             boolean isStatic = d instanceof Declaration
436                       ? ((Declaration) d).getFlag(Declaration.STATIC_SPECIFIED)
437                       : d == Boolean.TRUE;
438             if (inits.elementAt(init_index++) == null)
439                       rewriteInit(d, oexp, initPair, tr, memberSyntax);
440           }
441           }
442         else if (pair_car instanceof Pair)
443           { // Method declaration.
444
ScopeExp save_scope = tr.currentScope();
445         // If we saw a TemplateScope (in a SyntaxForm) specific to the
446
// formal parameters, pass it to rewrite so it can create a
447
// renamed alias. A TemplateScope that covers the formals
448
// *and* the body we handle using setCurrentScope.
449
if (memberSyntax != null)
450           tr.setCurrentScope(memberSyntax.scope);
451                 if ("*init*".equals(meth.getName()))
452                   {
453                     meth.setReturnType(Type.void_type);
454                     if (! oexp.isSimple())
455                       tr.error('e', "'*init*' methods only supported for simple classes");
456                   }
457                 Translator.setLine(meth, pair);
458                 LambdaExp saveLambda = tr.curMethodLambda;
459                 tr.curMethodLambda = meth;
460         lambda.rewrite(meth, ((Pair) pair_car).cdr, pair.cdr, tr,
461                    memberCarSyntax != null
462                    && (memberSyntax == null
463                    || memberCarSyntax.scope != memberSyntax.scope)
464                    ? memberCarSyntax.scope
465                    : null);
466                 tr.curMethodLambda = saveLambda;
467         if (memberSyntax != null)
468           tr.setCurrentScope(save_scope);
469         meth = meth.nextSibling;
470           }
471         else
472           tr.syntaxError("invalid field/method definition");
473       }
474     finally
475       {
476         tr.popPositionOf(savedPos1);
477       }
478     
479       }
480     // If initMethod/clinitMethod were created by the "outer" (first) call
481
// to rewriteInit, then we may need to fix up their outer chain.
482
if (oexp.initMethod != null)
483       oexp.initMethod.outer = oexp;
484     if (oexp.clinitMethod != null)
485       oexp.clinitMethod.outer = oexp;
486     tr.pop(oexp);
487     oexp.declareParts(tr);
488   }
489
490   private static void rewriteInit (Object JavaDoc d, ClassExp oexp, Pair initPair,
491                                    Translator tr, SyntaxForm memberSyntax)
492   {
493     boolean isStatic = d instanceof Declaration
494       ? ((Declaration) d).getFlag(Declaration.STATIC_SPECIFIED)
495       : d == Boolean.TRUE;
496     LambdaExp initMethod = isStatic ? oexp.clinitMethod : oexp.initMethod;
497     if (initMethod == null)
498       {
499         initMethod = new LambdaExp(new BeginExp());
500         initMethod.setClassMethod(true);
501         if (isStatic)
502           {
503             initMethod.setName("$clinit$");
504             oexp.clinitMethod = initMethod;
505           }
506         else
507           {
508             initMethod.setName("$finit$");
509             oexp.initMethod = initMethod;
510             // pseudo-this?? $finit$ is a static method - but (this) is valid.
511
// Is type getting set? FIXME
512
initMethod.add(null, new Declaration(ThisExp.THIS_NAME));
513           }
514         initMethod.nextSibling = oexp.firstChild;
515         oexp.firstChild = initMethod;
516       }
517     tr.push(initMethod);
518     LambdaExp saveLambda = tr.curMethodLambda;
519     tr.curMethodLambda = initMethod;
520     Expression initValue = tr.rewrite_car(initPair, memberSyntax);
521     if (d instanceof Declaration)
522       {
523         Declaration decl = (Declaration) d;
524         SetExp sexp = new SetExp(decl, initValue);
525         sexp.setLocation(decl);
526         decl.noteValue(null);
527         initValue = sexp;
528       }
529     else
530       initValue = Convert.makeCoercion(initValue, new QuoteExp(Type.void_type));
531     ((BeginExp) initMethod.body).add(initValue);
532     tr.curMethodLambda = saveLambda;
533     tr.pop(initMethod);
534 }
535
536   /** True if <code>exp</code> matches <code>tag:</code>, <code>"tag"</code>,
537    * or <code>'tag</code>. The latter is recommended as a matter of style.
538    */

539   static boolean matches (Object JavaDoc exp, String JavaDoc tag, Translator tr)
540   {
541     String JavaDoc value;
542     Pair pair;
543     if (exp instanceof Keyword)
544       value = ((Keyword) exp).getName();
545     else if (exp instanceof FString)
546       value = ((FString) exp).toString();
547     else if (exp instanceof Pair
548          && tr.matches((pair = (Pair) exp).car, Scheme.quote_sym)
549          && pair.cdr instanceof Pair
550          && (pair = (Pair) pair.cdr).cdr == LList.Empty
551          && pair.car instanceof String JavaDoc)
552       value = (String JavaDoc) pair.car;
553     else
554       return false;
555     return tag == null || tag.equals(value);
556   }
557 }
558
Popular Tags