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