Charj : the main chare's default constructor is filled with the
[charm.git] / src / langs / charj / src / charj / translator / AstModifier.java
1 package charj.translator;
2
3 import org.antlr.runtime.tree.CommonTree;
4 import org.antlr.runtime.Token;
5 import org.antlr.runtime.CommonToken;
6 import java.util.*;
7
8 class AstModifier
9 {
10     private CharjAST pupNode;
11     private CharjAST initNode;
12     private CharjAST migrationCtor;
13
14     AstModifier()
15     {
16         createPupNode();
17         createInitNode();
18     }
19
20     protected CharjAST getPupRoutineNode()
21     {
22         return pupNode;
23     }
24
25     protected CharjAST getInitRoutineNode()
26     {
27         return initNode;
28     }
29
30     private CharjAST createNode(int type, String text)
31     {
32         return new CharjAST(new CommonToken(type, text));
33     }    
34     
35     private void createInitNode()
36     {
37         initNode = createNode(CharjParser.FUNCTION_METHOD_DECL, "FUNCTION_METHOD_DECL");
38
39         initNode.addChild(createNode(CharjParser.MODIFIER_LIST, "MODIFIER_LIST"));
40         initNode.addChild(createNode(CharjParser.VOID, "void"));
41         initNode.addChild(createNode(CharjParser.IDENT, "initMethod"));
42         initNode.addChild(createNode(CharjParser.FORMAL_PARAM_LIST, "FORMAL_PARAM_LIST"));
43         initNode.addChild(createNode(CharjParser.BLOCK, "BLOCK"));
44
45         initNode.getChild(0).addChild(createNode(CharjParser.ACCESS_MODIFIER_LIST, "ACCESS_MODIFIER_LIST"));
46         initNode.getChild(0).getChild(0).addChild(createNode(CharjParser.PRIVATE, "private"));
47     }
48
49     private void createPupNode()
50     {
51         pupNode = createNode(CharjParser.FUNCTION_METHOD_DECL, "FUNCTION_METHOD_DECL");
52
53         pupNode.addChild(createNode(CharjParser.MODIFIER_LIST, "MODIFIER_LIST"));
54         pupNode.addChild(createNode(CharjParser.VOID, "void"));
55         pupNode.addChild(createNode(CharjParser.IDENT, "pup"));
56         pupNode.addChild(createNode(CharjParser.FORMAL_PARAM_LIST, "FORMAL_PARAM_LIST"));
57         pupNode.addChild(createNode(CharjParser.BLOCK, "BLOCK"));
58
59         pupNode.getChild(0).addChild(createNode(CharjParser.ACCESS_MODIFIER_LIST, "ACCESS_MODIFIER_LIST"));
60         pupNode.getChild(0).getChild(0).addChild(createNode(CharjParser.PUBLIC, "public"));
61
62         pupNode.getChild(3).addChild(createNode(CharjParser.FORMAL_PARAM_STD_DECL, "FORMAL_PARAM_STD_DECL"));
63         pupNode.getChild(3).getChild(0).addChild(createNode(CharjParser.REFERENCE_TYPE, "REFERENCE_TYPE"));
64         pupNode.getChild(3).getChild(0).getChild(0).addChild(createNode(CharjParser.QUALIFIED_TYPE_IDENT, "QUALIFIED_TYPE_IDENT"));
65         pupNode.getChild(3).getChild(0).getChild(0).getChild(0).addChild(createNode(CharjParser.IDENT, "PUP::er"));
66
67         pupNode.getChild(3).getChild(0).addChild(createNode(CharjParser.IDENT, "p"));
68     }
69
70     protected CharjAST getEnclosingType(CharjAST varDeclNode)
71     {
72         for(CharjAST p = varDeclNode.getParent(); p != null; p = p.getParent())
73             if(p.getType() == CharjParser.TYPE)
74                 return p;
75         return null;
76     }         
77
78     protected void varPup(CharjAST idNode)
79     {
80         int type = -1;
81
82         for(CharjAST p = idNode.getParent(); p != null; p = p.getParent())
83         {
84             switch(p.getType())
85             {
86                 case CharjParser.PRIMITIVE_VAR_DECLARATION:
87                     //System.out.println("found primitive var: " + idNode.getText());
88                     type = p.getType();
89                     break;
90                 case CharjParser.OBJECT_VAR_DECLARATION:
91                     //System.out.println("found object var: " + idNode.getText());
92                     type = p.getChildAfterType(CharjParser.MODIFIER_LIST).getType();
93                     break;
94                 case CharjParser.FUNCTION_METHOD_DECL:
95                 case CharjParser.BLOCK:
96                 case CharjParser.FORMAL_PARAM_LIST:
97                     return;
98                 case CharjParser.TYPE:
99                     switch(type)
100                     {
101                         case CharjParser.REFERENCE_TYPE:
102                             //System.out.println("puping a reference type");
103                             break;
104                         case CharjParser.PRIMITIVE_VAR_DECLARATION:
105                             //System.out.println("puping a primitive type");
106                             primitiveVarPup(idNode);
107                             break;
108                         case CharjParser.POINTER_TYPE:
109                             //System.out.println("puping a pointer type");
110                             pointerVarPup(idNode);
111                             break;
112                         case CharjParser.PROXY_TYPE:
113                             //System.out.println("puping a proxy type");
114                             proxyVarPup(idNode);
115                             break;
116                         default:
117                             System.out.println("AstModifier.varPup: unknown type " + idNode);
118                             break;
119                     }
120                     return;
121             }
122         }
123         System.out.println("AstModifier.varPup: could not pup variable " + idNode);
124     }
125
126     protected void primitiveVarPup(CharjAST idNode)
127     {
128         pupNode.getChild(4).addChild(createNode(CharjParser.EXPR, "EXPR"));
129         
130         int index = pupNode.getChild(4).getChildren().size() - 1;
131
132         pupNode.getChild(4).getChild(index).addChild(createNode(CharjParser.BITWISE_OR, "|"));
133         pupNode.getChild(4).getChild(index).getChild(0).addChild(createNode(CharjParser.IDENT, "p"));
134         pupNode.getChild(4).getChild(index).getChild(0).addChild(idNode.dupNode());
135     }
136
137     protected void proxyVarPup(CharjAST idNode)
138     {
139         // For now, just do a basic PUP. More complex handling may be needed later.
140         primitiveVarPup(idNode);
141     }
142     
143     private boolean generatedIf = false;
144
145     protected void pointerVarPup(CharjAST idNode)
146     {
147         if(!generatedIf)
148         {
149             generateIf();
150             generatedIf = true;
151         }
152
153         // add stuff to the initMethod routine
154         initNode.getChild(4).addChild(createNode(CharjParser.EXPR, "EXPR"));
155
156         int index = initNode.getChild(4).getChildren().size() - 1;
157
158         initNode.getChild(4).getChild(index).addChild(createNode(CharjParser.ASSIGNMENT, "="));
159         initNode.getChild(4).getChild(index).getChild(0).addChild(idNode.dupNode());
160         initNode.getChild(4).getChild(index).getChild(0).addChild(createNode(CharjParser.NEW, "new"));
161         initNode.getChild(4).getChild(index).getChild(0).getChild(1).addChild(createNode(CharjParser.OBJECT_TYPE, "OBJECT_TYPE"));
162         initNode.getChild(4).getChild(index).getChild(0).getChild(1).getChild(0).addChild(createNode(CharjParser.QUALIFIED_TYPE_IDENT, "QUALIFIED_TYPE_IDENT"));
163         initNode.getChild(4).getChild(index).getChild(0).getChild(1).getChild(0).getChild(0).addChild(idNode.getParent().getParent().getParent().getChildOfType(CharjParser.POINTER_TYPE).getChild(0).getChild(0).dupTree());
164         initNode.getChild(4).getChild(index).getChild(0).getChild(1).addChild(createNode(CharjParser.ARGUMENT_LIST, "ARGUMENT_LIST"));
165
166         // add stuff to the pup routine
167         pupNode.getChild(4).addChild(createNode(CharjParser.EXPR, "EXPR"));
168
169         index = pupNode.getChild(4).getChildren().size() - 1;
170
171         pupNode.getChild(4).getChild(index).addChild(createNode(CharjParser.METHOD_CALL, "METHOD_CALL"));
172         pupNode.getChild(4).getChild(index).getChild(0).addChild(createNode(CharjParser.ARROW, "ARROW"));
173         pupNode.getChild(4).getChild(index).getChild(0).getChild(0).addChild(idNode.dupNode());
174         pupNode.getChild(4).getChild(index).getChild(0).getChild(0).addChild(createNode(CharjParser.IDENT, "pup"));
175         pupNode.getChild(4).getChild(index).getChild(0).addChild(createNode(CharjParser.ARGUMENT_LIST, "ARGUMENT_LIST"));
176         pupNode.getChild(4).getChild(index).getChild(0).getChild(1).addChild(createNode(CharjParser.EXPR, "EXPR"));
177         pupNode.getChild(4).getChild(index).getChild(0).getChild(1).getChild(0).addChild(createNode(CharjParser.IDENT, "p"));
178     }
179
180     protected void generateIf()
181     {
182         pupNode.getChild(4).addChild(createNode(CharjParser.IF, "if"));
183         
184         int index = pupNode.getChild(4).getChildren().size() - 1;
185        
186         pupNode.getChild(4).getChild(index).addChild(createNode(CharjParser.PAREN_EXPR, "PAREN_EXPR"));
187         pupNode.getChild(4).getChild(index).getChild(0).addChild(createNode(CharjParser.EXPR, "EXPR"));
188         pupNode.getChild(4).getChild(index).getChild(0).getChild(0).addChild(createNode(CharjParser.METHOD_CALL, "METHOD_CALL"));
189         pupNode.getChild(4).getChild(index).getChild(0).getChild(0).getChild(0).addChild(createNode(CharjParser.DOT, "."));
190         pupNode.getChild(4).getChild(index).getChild(0).getChild(0).getChild(0).getChild(0).addChild(createNode(CharjParser.IDENT, "p"));
191         pupNode.getChild(4).getChild(index).getChild(0).getChild(0).getChild(0).getChild(0).addChild(createNode(CharjParser.IDENT, "isUnpacking"));
192         pupNode.getChild(4).getChild(index).getChild(0).getChild(0).getChild(0).addChild(createNode(CharjParser.ARGUMENT_LIST, "ARGUMENT_LIST"));
193         pupNode.getChild(4).getChild(index).addChild(createNode(CharjParser.BLOCK, "BLOCK"));
194         pupNode.getChild(4).getChild(index).getChild(1).addChild(createNode(CharjParser.EXPR, "EXPR"));
195         pupNode.getChild(4).getChild(index).getChild(1).getChild(0).addChild(createNode(CharjParser.METHOD_CALL, "METHOD_CALL"));
196         pupNode.getChild(4).getChild(index).getChild(1).getChild(0).getChild(0).addChild(createNode(CharjParser.IDENT, "initMethod"));
197         pupNode.getChild(4).getChild(index).getChild(1).getChild(0).getChild(0).addChild(createNode(CharjParser.ARGUMENT_LIST, "ARGUMENT_LIST"));
198     }
199
200     protected void arrangeModifiers(CharjAST modlistNode)
201     {
202         CharjAST accessList = createNode(CharjParser.ACCESS_MODIFIER_LIST, "ACCESS_MODIFIER_LIST");
203         CharjAST localList = createNode(CharjParser.LOCAL_MODIFIER_LIST, "LOCAL_MODIFIER_LIST");
204         CharjAST charjList = createNode(CharjParser.CHARJ_MODIFIER_LIST, "CHARJ_MODIFIER_LIST");
205         CharjAST otherList = createNode(CharjParser.CHARJ_MODIFIER_LIST, "OTHER_MODIFIER_LIST");
206
207
208         Iterator<CharjAST> iter = modlistNode.getChildren().iterator();
209         
210         while(iter.hasNext())
211         {
212             CharjAST mod = iter.next();
213             iter.remove();
214
215             switch(mod.getType())
216             {
217                 case CharjParser.PUBLIC:
218                 case CharjParser.PRIVATE:
219                 case CharjParser.PROTECTED:
220                     accessList.addChild(mod.dupNode());
221                     break;
222                 case CharjParser.ENTRY:
223                     charjList.addChild(mod.dupNode());
224                     break;
225                 case CharjParser.FINAL:
226                 case CharjParser.STATIC:
227                 case CharjParser.VOLATILE:
228                     localList.addChild(mod.dupNode());
229                     break;
230                 case CharjParser.ABSTRACT:
231                 case CharjParser.NATIVE:
232                     otherList.addChild(mod.dupNode());
233                     break;
234             }
235         }
236
237        if(accessList.getChildren() == null)
238            try
239            {
240                if(charjList.getChildren().contains(createNode(CharjParser.ENTRY, "entry")))
241                    accessList.addChild(createNode(CharjParser.PUBLIC, "public"));
242                else
243                    accessList.addChild(createNode(CharjParser.PRIVATE, "private"));
244            }
245            catch(NullPointerException npe)
246            {
247                // charjList == null && accessList is empty
248                accessList.addChild(createNode(CharjParser.PRIVATE, "private"));
249            }
250
251        modlistNode.addChild(accessList);
252        if(localList.getChildren() != null) modlistNode.addChild(localList);
253        if(charjList.getChildren() != null) modlistNode.addChild(charjList);
254        if(otherList.getChildren() != null) modlistNode.addChild(otherList);
255     }
256
257     protected void fillPrivateModifier(CharjAST declNode)
258     {
259         CharjAST modlist = createNode(CharjParser.MODIFIER_LIST, "MODIFIER_LIST");
260         modlist.addChild(createNode(CharjParser.ACCESS_MODIFIER_LIST, "ACCESS_MODIFIER_LIST"));
261         modlist.getChild(0).addChild(createNode(CharjParser.PRIVATE, "private"));
262         
263         ArrayList<CharjAST> list = new ArrayList<CharjAST>();
264         list.addAll(declNode.getChildren());
265
266         declNode.getChildren().clear();
267
268         declNode.addChild(modlist);
269
270         for(CharjAST c : list)
271             declNode.addChild(c);
272     }
273
274     private boolean hasMigrationCtor = false;
275     private CharjAST defaultCtor;
276
277     protected void checkForDefaultCtor(CharjAST ctordecl, CharjAST ctordecltree)
278     {
279         if(defaultCtor != null)
280             return;
281
282         CharjAST params = null;
283         for(CharjAST node : ctordecl.getChildren()) {
284             if(node.getType() == CharjParser.FORMAL_PARAM_LIST)
285             {
286                 params = node;
287                 break;
288             }
289         }
290         if(params.getChildren() == null)
291             defaultCtor = ctordecltree;
292     }
293
294     protected boolean isMigrationCtor(CharjAST ctordecl)
295     {
296         CharjAST params = null;
297         for(CharjAST node : ctordecl.getChildren()) {
298             if(node.getType() == CharjParser.FORMAL_PARAM_LIST)
299             {
300                 params = node;
301                 break;
302             }
303         }
304         
305         if (params == null || params.getChildren() == null) return false;
306         if (params.getChildren().size() != 1) return false;
307         params = params.getChild(0);
308         if (params == null || params.getType() != CharjParser.FORMAL_PARAM_STD_DECL) return false;
309         params = params.getChild(0);
310         if (params == null || params.getType() != CharjParser.POINTER_TYPE) return false ;
311         params = params.getChild(0);
312         if (params == null || params.getType() != CharjParser.QUALIFIED_TYPE_IDENT) return false;
313         params = params.getChild(0);
314         if (params.toString().equals("CkMigrateMessage")) return true;
315         return false;
316
317     }
318
319     protected void checkForMigrationCtor(CharjAST ctordecl)
320     {
321         if(hasMigrationCtor) return;
322         if (isMigrationCtor(ctordecl)) {
323             hasMigrationCtor = true;
324             migrationCtor = ctordecl;
325         }
326     }
327
328     protected void ensureDefaultCtor(CharjAST typenode)
329     {
330         if(defaultCtor != null && typenode.getChild(0).getType() == CharjParser.MAINCHARE && defaultCtor.getChild(1).getChildren() == null)
331         {
332             // fill CkMsgArg* argument
333             defaultCtor.getChild(2).addChild(createNode(CharjParser.FORMAL_PARAM_STD_DECL, "FORMAL_PARAM_STD_DECL"));
334             defaultCtor.getChild(2).getChild(0).addChild(createNode(CharjParser.POINTER_TYPE, "POINTER_TYPE"));
335             defaultCtor.getChild(2).getChild(0).getChild(0).addChild(createNode(CharjParser.QUALIFIED_TYPE_IDENT, "QUALIFIED_TYPE_IDENT"));
336             defaultCtor.getChild(2).getChild(0).getChild(0).getChild(0).addChild(createNode(CharjParser.IDENT, "CkArgMsg"));
337             defaultCtor.getChild(2).getChild(0).addChild(createNode(CharjParser.IDENT, "m"));
338         }
339         else if(defaultCtor == null)
340         {
341             CharjAST ctor = createNode(CharjParser.CONSTRUCTOR_DECL, "CONSTRUCTOR_DECL");
342             ctor.addChild(createNode(CharjParser.MODIFIER_LIST, "MODIFIER_LIST"));
343             ctor.getChild(0).addChild(createNode(CharjParser.ACCESS_MODIFIER_LIST, "ACCESS_MODIFIER_LIST"));
344             ctor.getChild(0).getChild(0).addChild(createNode(CharjParser.PUBLIC, "public"));
345             ctor.addChild(typenode.getChild(1).dupNode());
346             ctor.addChild(createNode(CharjParser.FORMAL_PARAM_LIST, "FORMAL_PARAM_LIST"));
347             ctor.addChild(createNode(CharjParser.BLOCK, "BLOCK"));
348
349             typenode.addChild(ctor);
350         }
351     }
352
353     protected CharjAST ensureMigrationCtor(CharjAST typenode)
354     {
355         if(hasMigrationCtor)
356             return migrationCtor;
357         
358         CharjAST ctor = createNode(CharjParser.CONSTRUCTOR_DECL, "CONSTRUCTOR_DECL");
359         ctor.addChild(createNode(CharjParser.MODIFIER_LIST, "MODIFIER_LIST"));
360         ctor.getChild(0).addChild(createNode(CharjParser.ACCESS_MODIFIER_LIST, "ACCESS_MODIFIER_LIST"));
361         ctor.getChild(0).getChild(0).addChild(createNode(CharjParser.PUBLIC, "public"));
362         ctor.getChild(0).addChild(createNode(CharjParser.CHARJ_MODIFIER_LIST, "CHARJ_MODIFIER_LIST"));
363         ctor.getChild(0).getChild(1).addChild(createNode(CharjParser.ENTRY, "entry"));
364         ctor.addChild(typenode.getChild(1).dupNode());
365         CharjAST args = createNode(CharjParser.FORMAL_PARAM_LIST, "FORMAL_PARAM_LIST");
366         args.addChild(createNode(CharjParser.FORMAL_PARAM_STD_DECL, "FORMAL_PARAM_STD_DECL"));
367         args.getChild(0).addChild(createNode(CharjParser.POINTER_TYPE, "POINTER_TYPE"));
368         args.getChild(0).getChild(0).addChild(createNode(CharjParser.QUALIFIED_TYPE_IDENT, "QUALIFIED_TYPE_IDENT"));
369         args.getChild(0).getChild(0).getChild(0).addChild(createNode(CharjParser.IDENT, "CkMigrateMessage"));
370         args.getChild(0).addChild(createNode(CharjParser.IDENT, "m"));
371         ctor.addChild(args);
372         ctor.addChild(createNode(CharjParser.BLOCK, "BLOCK"));
373         typenode.addChild(ctor);
374         migrationCtor = ctor;
375         return migrationCtor;
376     }
377 }