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