c5f7726f904f9c47e31426ea6c2eb8835468a6cb
[charm.git] / src / langs / charj / src / charj / translator / SymbolTable.java
1
2 package charj.translator;
3
4 import java.lang.reflect.Field;
5 import java.util.*;
6
7 public class SymbolTable {
8     public static final String DEFAULT_PACKAGE_NAME = "default";
9     public static final List<String> AUTO_IMPORTS = 
10         new ArrayList<String>() {
11             {
12                 add("charj.lang");
13                 add(DEFAULT_PACKAGE_NAME);
14             }
15         };
16
17     public static final Set<String> TYPE_NAMES_TO_MANGLE = 
18         new HashSet<String>() { {} };
19
20     public static final Set<String> METHOD_NAMES_TO_MANGLE = 
21         new HashSet<String>() { {} };
22
23     public static Map<String, ClassSymbol> primitiveTypes =
24         new HashMap<String, ClassSymbol>() { {} };
25
26     /** Provides runtime variables and loads classes */
27     public Translator translator;
28
29     /** The scope for the "default" package */
30     PackageScope defaultPkg;
31
32     public Map<String,PackageScope> topLevelPackageScopes = new HashMap();
33
34     /** This is the list of all scopes created during symbol table building. */
35     public List scopes = new ArrayList();
36
37     /** Root of the object hierarchy, Charj.lang.Object */
38     ClassSymbol objectRoot;
39
40     public SymbolTable(Translator _translator) 
41     {
42         translator = _translator;
43         // define default package
44         defaultPkg = new PackageScope(this, DEFAULT_PACKAGE_NAME, null);
45         topLevelPackageScopes.put(DEFAULT_PACKAGE_NAME, defaultPkg);
46         PackageScope lang = definePackage("charj.lang");
47         addScope(defaultPkg);
48         initObjectHierarchy();
49     }
50
51     public boolean debug() {
52         return translator.debug();
53     }
54
55     protected void initObjectHierarchy() 
56     {
57         PackageScope lang = resolvePackage("charj.lang");
58         objectRoot = new ClassSymbol(this, "Object", null, lang);
59         objectRoot.define("EOF", new VariableSymbol(this,"EOF",null));
60         lang.define("Object", objectRoot);
61
62         primitiveTypes.put("void",   new ClassSymbol(this, "void",   null, lang));
63         primitiveTypes.put("int",    new ClassSymbol(this, "int",    null, lang));
64         primitiveTypes.put("long",   new ClassSymbol(this, "long",   null, lang));
65         primitiveTypes.put("float",  new ClassSymbol(this, "float",  null, lang));
66         primitiveTypes.put("double", new ClassSymbol(this, "double", null, lang));
67         primitiveTypes.put("char",   new ClassSymbol(this, "char",   null, lang)); 
68         primitiveTypes.put("short",  new ClassSymbol(this, "short",  null, lang)); 
69         primitiveTypes.put("bool",   new ClassSymbol(this, "bool",   null, lang)); 
70         lang.define("void", primitiveTypes.get("void"));
71         lang.define("int", primitiveTypes.get("int"));
72         lang.define("long", primitiveTypes.get("long"));
73         lang.define("float", primitiveTypes.get("float"));
74         lang.define("double", primitiveTypes.get("double"));
75         lang.define("char", primitiveTypes.get("char"));
76         lang.define("short", primitiveTypes.get("short"));
77         lang.define("bool", primitiveTypes.get("bool"));
78     }
79
80     public ClassSymbol resolveBuiltinType(String type) {
81         ClassSymbol ptype = primitiveTypes.get(type);
82         if (ptype != null) return ptype;
83         return objectRoot.resolveType(type);
84     }
85
86     /** Given a package like foo or charj.io, define it by breaking it up and
87      *  looking up the packages to left of last id.  Add last id to that 
88      *  package.
89      */
90     public PackageScope definePackage(String packageName) {
91         String[] packageNames = packageName.split("[.]");
92         String outerPackageName = packageNames[0];
93         PackageScope outerPackage = (PackageScope)defaultPkg.resolve(
94                 outerPackageName);
95         if (outerPackage == null) {
96             if (debug()) {
97                 System.out.println(
98                         " SymbolTable.definePackage(" + packageName + 
99                         "): defining outer pkg: " + outerPackageName);
100             }
101             outerPackage = new PackageScope(this,outerPackageName,defaultPkg);
102             defaultPkg.define(outerPackageName, outerPackage);
103             topLevelPackageScopes.put(outerPackageName, outerPackage);
104         }
105
106         PackageScope enclosingPackage = defaultPkg;
107         for (String pname : packageNames) {
108             PackageScope p = (PackageScope)enclosingPackage.resolve(pname);
109             if (p==null) {
110                 if (debug()) System.out.println(
111                         " SymbolTable.definePackage(" + packageName + 
112                         "): defining inner pkg: " + pname +
113                         " in "+enclosingPackage.toString());
114                 
115                 p = new PackageScope(this,pname,enclosingPackage);
116                 enclosingPackage.define(pname, p);
117             }
118             enclosingPackage = p;
119         }
120         return enclosingPackage;
121     }
122
123     public PackageScope getDefaultPkg() {
124         return defaultPkg;
125     }
126
127     /** Find package starting with its outermost package name.  If
128      *  not in sym tab, return null.
129      */
130     public PackageScope resolvePackage(String packageName) {
131         if (debug()) System.out.println(
132                 " SymbolTable.resolvePackage(" + packageName + 
133                 "): examine: " + topLevelPackageScopes.keySet());
134         String[] packageNames = packageName.split("[.]");
135         String outerPackageName = packageNames[0];
136         PackageScope enclosingPackage = topLevelPackageScopes.get(
137                 outerPackageName);
138
139         if (enclosingPackage == null) {
140             if (debug()) System.out.println(
141                     " SymbolTable.resolvePackage(" + packageName + 
142                     "): outer package " +
143                     outerPackageName + " not found in top level " +
144                     topLevelPackageScopes.keySet());
145             return null;
146         }
147
148         if (packageNames.length==1) {
149             return enclosingPackage; // top-level package
150         }
151
152         PackageScope p = null;
153         for (int i=1; i<packageNames.length; i++) {
154             String pname = packageNames[i];
155             p = (PackageScope)enclosingPackage.resolve(pname);
156             if (p == null) {
157                 if (debug()) System.out.println(
158                         " SymbolTable.resolvePackage(" + packageName +
159                         "): not found in " + topLevelPackageScopes.keySet());
160                 return null;
161             }
162             enclosingPackage = p;
163         }
164
165         if (p!=null && debug()) System.out.println(
166                 " SymbolTable.resolvePackage(" + packageName + "): found in " +
167                 topLevelPackageScopes.keySet());
168         return p;
169     }
170
171     public ClassSymbol getObjectRoot() {
172         return objectRoot;
173     }
174
175     public void addScope(Scope s) {
176         scopes.add(s);
177     }
178
179     // TODO:  shouldn't we include the arguments and do all mangling here?
180     public static String mangle(String methodName) {
181         if (METHOD_NAMES_TO_MANGLE.contains(methodName)) {
182             return "cj" + methodName;
183         }
184         return methodName;
185     }
186
187     public static String unmangle(String methodName) {
188         // this is not perfect because perhaps someone makes a method called
189         // mtoString() etc.
190         String unmangled = methodName.substring(2, methodName.length());
191         if (METHOD_NAMES_TO_MANGLE.contains(unmangled)) {
192             return unmangled;
193         }
194         return methodName;
195     }
196
197     public static String getCharjTypeName(String className) {
198         if (SymbolTable.TYPE_NAMES_TO_MANGLE.contains(className)) {
199             return "cj"+className;
200         }
201         return className;
202     }
203
204     public String toString() {
205         return scopes.toString();
206     }
207 }
208