1 package kawa.standard;
2 import kawa.lang.*;
3 import gnu.lists.*;
4 import gnu.expr.*;
5 import gnu.mapping.Symbol;
6 import gnu.bytecode.ClassType;
7 
8 public class define_class extends Syntax
9 {
10   public static final define_class define_class
11     = new define_class("define-class", false);
12   public static final define_class define_simple_class
13     = new define_class("define-simple-class", true);
14 
15   boolean isSimple;
16   object objectSyntax;
17 
define_class(object objectSyntax, boolean isSimple)18   define_class (object objectSyntax, boolean isSimple)
19   {
20     this.objectSyntax = objectSyntax;
21     this.isSimple = isSimple;
22   }
23 
define_class(String name, boolean isSimple)24   define_class (String name, boolean isSimple)
25   {
26     super(name);
27     this.objectSyntax = object.objectSyntax;
28     this.isSimple = isSimple;
29   }
30 
31   @Override
scanForDefinitions(Pair st, ScopeExp defs, Translator tr)32   public boolean scanForDefinitions(Pair st, ScopeExp defs, Translator tr)
33   {
34     Object st_cdr = st.getCdr();
35     SyntaxForm nameSyntax = null;
36     while (st_cdr instanceof SyntaxForm)
37       {
38 	nameSyntax = (SyntaxForm) st_cdr;
39 	st_cdr = nameSyntax.getDatum();
40       }
41     Object name;
42     if (st_cdr instanceof Pair)
43       {
44         name = ((Pair) st_cdr).getCar();
45         while (name instanceof SyntaxForm)
46           {
47             nameSyntax = (SyntaxForm) name;
48             name = nameSyntax.getDatum();
49           }
50         name = tr.namespaceResolve(name);
51       }
52     else
53       name = null;
54     if (! (name instanceof String || name instanceof Symbol))
55       {
56 	tr.error('e', "missing class name");
57 	return false;
58       }
59     Pair p = (Pair) st_cdr;
60     Declaration decl = tr.define(name, nameSyntax, defs);
61     if (p instanceof PairWithPosition)
62       decl.setLocation((PairWithPosition) p);
63     ClassExp oexp = new ClassExp(isSimple, null);
64     decl.noteValue(oexp);
65     decl.setFlag(Declaration.IS_CONSTANT|Declaration.EARLY_INIT);
66     decl.setType(isSimple ? Compilation.typeClass : Compilation.typeClassType);
67     tr.mustCompileHere();
68 
69     String cname = name instanceof Symbol ? ((Symbol) name).getName()
70       : name.toString();
71     int nlen = cname.length();
72     if (nlen > 2 && cname.charAt(0) == '<' && cname.charAt(nlen-1) == '>')
73       cname = cname.substring(1, nlen-1);
74     oexp.setName(cname);
75 
76     Object members = p.getCdr();
77     while (members instanceof SyntaxForm)
78       {
79 	nameSyntax = (SyntaxForm) members;
80 	members = nameSyntax.getDatum();
81       }
82     if (! (members instanceof Pair))
83       {
84 	tr.error('e', "missing class members");
85 	return false;
86       }
87     p = (Pair) members;
88     ScopeExp save_scope = tr.currentScope();
89     if (nameSyntax != null)
90       tr.setCurrentScope(nameSyntax.getScope());
91     Object[] saved = objectSyntax.scanClassDef(p, oexp, tr);
92     if (nameSyntax != null)
93       tr.setCurrentScope(save_scope);
94     ClassType mtype = tr.getModule().classFor(tr);
95     String clname = oexp.getClassName(tr);
96     String mname = mtype.getName();
97     ClassType ctype;
98     if (clname.equals(mname))
99       {
100         ctype = mtype;
101         tr.getModule().setFlag(ModuleExp.USE_DEFINED_CLASS);
102       }
103     else
104       ctype = new ClassType(clname);
105     oexp.setClassType(ctype);
106     oexp.createFields(tr);
107     if (saved == null)
108 	return false;
109     st = Translator.makePair(st, this, Translator.makePair(p, decl, saved));
110     tr.pushForm(st);
111     return true;
112   }
113 
rewriteForm(Pair form, Translator tr)114   public Expression rewriteForm (Pair form, Translator tr)
115   {
116     Object form_cdr = form.getCdr();
117     if (form_cdr instanceof Pair)
118       {
119         form = (Pair) form_cdr;
120         Object form_car = form.getCar();
121         if (form_car instanceof Declaration)
122           {
123             Declaration decl = (Declaration) form_car;
124             ClassExp oexp = (ClassExp) decl.getValue();
125             objectSyntax.rewriteClassDef((Object[]) form.getCdr(), tr);
126             SetExp sexp = new SetExp(decl, oexp);
127             sexp.setDefining (true);
128             return sexp;
129           }
130       }
131     return tr.syntaxError(this.getName() + " can only be used in <body>");
132   }
133 }
134