Merged arrays into Charj mainline.
[charm.git] / src / langs / charj / src / charj / translator / ClassSymbol.java
1
2 package charj.translator;
3
4 import java.util.*;
5
6 public class ClassSymbol extends SymbolWithScope implements Scope {
7
8     public ClassSymbol superClass;
9     public List<String> interfaceImpls;
10     public List<String> templateArgs;
11     public List<CharjAST> initializers;
12
13     public CharjAST constructor;
14
15     Map<String, PackageScope> imports =
16         new LinkedHashMap<String, PackageScope>();
17     List<String> includes = new ArrayList<String>();
18     List<String> usings = new ArrayList<String>();
19     List<String> externs = new ArrayList<String>();
20
21     /** Record of all fields and methods */
22     public Map<String, Symbol> members = new LinkedHashMap<String, Symbol>();
23     public Map<String, VariableSymbol> fields = new LinkedHashMap<String, VariableSymbol>();
24     public Map<String, MethodSymbol> methods = new LinkedHashMap<String, MethodSymbol>();
25
26     public boolean hasCopyCtor = false;
27     public boolean isPrimitive = false;
28     public boolean isChare = false;
29     public boolean isMainChare = false;
30
31     public CharjAST migrationCtor = null;
32
33     public ClassSymbol(
34             SymbolTable symtab,
35             String name) {
36         super(symtab, name);
37         type = this;
38         for (String pkg : SymbolTable.AUTO_IMPORTS) {
39             importPackage(pkg);
40         }
41         this.initializers = new ArrayList<CharjAST>();
42         constructor = null;
43     }
44
45     public ClassSymbol(
46             SymbolTable symtab,
47             String name,
48             ClassSymbol superClass,
49             Scope scope) {
50         this(symtab, name);
51         this.superClass = superClass;
52         this.scope = scope;
53         this.initializers = new ArrayList<CharjAST>();
54         constructor = null;
55
56         // manually add automatic class methods and symbols here
57         this.includes.add("charm++.h");
58         this.includes.add("list");
59         this.usings.add("std::list");
60         this.includes.add("string");
61         this.usings.add("std::string");
62         this.includes.add("vector");
63         this.usings.add("std::vector");
64         this.includes.add("map");
65         this.usings.add("std::map");
66         this.includes.add("iostream");
67         this.usings.add("std::cout");
68         this.usings.add("std::endl");
69     }
70
71     public Scope getEnclosingScope() {
72         // at root?  Then use enclosing scope
73         if ( superClass==null ) {
74             return scope;
75         }
76         return superClass;
77     }
78
79     public Map<String, Symbol> getMembers() {
80         return members;
81     }
82
83     /** Importing a package means adding the package to list of "filters"
84      *  used by resolvePackage.  The resolve operation can only see classes
85      *  defined in the imported packages.  This method asks the sym tab if
86      *  it is known before looking at corresponding dir on disk to see if it
87      *  exists.
88      *
89      *  Return null if this class is not in sym tab and was not found in path.
90      */
91     public PackageScope importPackage(String packageName) {
92         if (debug()) System.out.println(
93                 "ClassSymbol.importPackage(" + packageName +
94                 "): add to " + toString());
95
96         PackageScope p = symtab.resolvePackage(packageName);
97         if ( p!=null ) {
98             imports.put(packageName, p);
99             if (debug()) System.out.println(
100                     "ClassSymbol.importPackage(" + packageName + "): known");
101             return p;
102         }
103
104         if ( symtab.translator.findPackage(packageName) != null ) {
105             p = symtab.definePackage(packageName);
106             imports.put(packageName, p);
107         }
108
109         if ( p==null && debug() ) System.out.println(
110                 "ClassSymbol.importPackage(" + packageName +
111                 "): dir not found");
112         return p;
113     }
114
115     /** Using the list of imports, resolve a package name like charj.lang.
116      *  There may be many packages defined and visible to the symbol table
117      *  but this class can only see those packages in the implicit or explicit
118      *  import list.
119      */
120     public PackageScope resolvePackage(String packageName) {
121         return imports.get(packageName);
122     }
123
124     /** To resolve a type in a class, look it up in each imported package
125      *  including the current package. Classes cannot be defined in the
126      *  superclass so don't look upwards for types.
127      *
128      *  First check to see if we are resolving enclosing class then
129      *  look for type in each imported package.  If not found in existing
130      *  packges, walk through imported packages again, trying to load from
131      *  disk.
132      */
133     public ClassSymbol resolveType(String type) {
134         if (debug()) System.out.println(
135                 "ClassSymbol.resolveType(" + type + "): context is " + name +
136                 ":" + members.keySet());
137
138         if (type == null) {
139             return null;
140         }
141
142         if ( name.equals(type) ) {
143             if ( debug() ) System.out.println(
144                     "ClassSymbol.resolveType(" + type +
145                     "): surrounding class " + name + ":" + members.keySet());
146             return this;
147         }
148
149         // look for type in classes already defined in imported packages
150         for (String packageName : imports.keySet()) {
151             if ( debug() ) System.out.println( "Looking for type " +
152                     type + " in package " + packageName);
153             PackageScope pkg = resolvePackage(packageName);
154             ClassSymbol cs = pkg.resolveType(type);
155             if ( cs != null) { // stop looking, found it
156                 if ( debug() ) System.out.println(
157                         "ClassSymbol.resolveType(" + type +
158                         "): found in context " + name + ":" +
159                         members.keySet());
160                 return cs;
161             }
162         }
163
164         // not already seen in one of the imported packages, look on disk
165         //for (String packageName : imports.keySet()) {
166         //    PackageScope pkg = resolvePackage(packageName);
167         //    ClassSymbol cs = symtab.translator.loadType(
168         //            pkg.getFullyQualifiedName(), type);
169         //    if ( cs!=null ) {
170         //        pkg.define(type, cs); // add to symbol table
171         //        if ( debug() ) System.out.println(
172         //                "ClassSymbol.resolveType(" + type +
173         //                "): found after loading in context " + name +
174         //                ":" + members.keySet());
175         //        return cs;
176         //    }
177         //}
178
179         if ( debug() ) System.out.println(
180                 "ClassSymbol.resolveType(" + type +
181                 "): not in context " + name + ":" + members.keySet());
182         return null;
183     }
184
185     public MethodSymbol resolveMethodLocally(
186             String name,
187             int numargs) {
188         if (numargs > 0) {
189             name += numargs;
190         }
191
192         return methods.get(name);
193     }
194
195     public boolean isMethod(String name) {
196         if ( methods.containsKey(name) ) {
197             return true;
198         }
199         if ( getEnclosingScope()!=null ) {
200             return getEnclosingScope().isMethod(name);
201         }
202         return false;
203     }
204
205     public Symbol define(
206             String name,
207             Symbol sym) {
208         if (sym == null) {
209             System.out.println("ClassSymbol.define: Uh oh, defining null symbol");
210         }
211         members.put(name, sym);
212         if (sym instanceof MethodSymbol) {
213             methods.put(name, (MethodSymbol)sym);
214         } else if (sym instanceof VariableSymbol) {
215             fields.put(name, (VariableSymbol)sym);
216         }
217         return super.define(name, sym);
218     }
219
220     public String toString() {
221         return "ClassSymbol[" + name + "]: " + members;
222     }
223
224     public String getFullyQualifiedName() {
225         String parent = null;
226         if ( scope!=null ) { // in a package?
227             parent = scope.getFullyQualifiedName();
228         }
229         if ( parent!=null ) {
230             return parent+"::"+name;
231         }
232         return name;
233     }
234
235     public void addInclude(String includeName) {
236         includes.add(includeName);
237     }
238
239     public void addExtern(String externName) {
240         externs.add(externName);
241     }
242
243     public void getUsings(String usingName) {
244         usings.add(usingName);
245     }
246
247     public List<String> getIncludes()
248     {
249         return includes;
250     }
251
252     public List<String> getUsings()
253     {
254         return usings;
255     }
256
257     public List<String> getExterns()
258     {
259         return externs;
260     }
261
262     public List<String> getPackageNames()
263     {
264         List<String> list = new LinkedList<String>();
265         for(Scope currentScope = scope;
266                 currentScope.getEnclosingScope() != null;
267                 currentScope = currentScope.getEnclosingScope()) {
268             list.add(0, currentScope.getScopeName());
269         }
270         return list;
271     }
272
273     private Set<ClassSymbol> getMemberTypes()
274     {
275         Set<ClassSymbol> types = new HashSet<ClassSymbol>();
276         for (Map.Entry<String, VariableSymbol> entry : fields.entrySet()) {
277             // note: type info may be null for unknown types, but this might
278             // need to be changed at some point.
279             ClassSymbol type = ((VariableSymbol)entry.getValue()).type;
280             if (type != null) types.add(type);
281         }
282         return types;
283     }
284
285     public List<String> getMemberTypeNames()
286     {
287         List<String> names = new ArrayList<String>();
288         for (ClassSymbol c : getMemberTypes()) {
289             if (c.isPrimitive) continue;
290             names.add(c.getName());
291         }
292         return names;
293     }
294
295     public String getName()
296     {
297         return name;
298     }
299 }