Charj: add automatic forward declarations for class variables
[charm.git] / src / langs / charj / src / charj / translator / SymbolWithScope.java
1
2 package charj.translator;
3
4 import java.util.Map;
5
6 public abstract class SymbolWithScope 
7     extends Symbol 
8     implements Scope {
9
10     public SymbolWithScope(SymbolTable symtab) {
11         super(symtab);
12     }
13
14     public SymbolWithScope(
15             SymbolTable symtab, 
16             String name) {
17         super(symtab, name, null);
18     }
19
20     /** Find any symbol matching name; won't look on disk for classes though */
21     public Symbol resolve(String name) {
22         Symbol s = null;
23         
24         // in this scope?
25         if ( getMembers()!=null ) {
26             s = (Symbol)getMembers().get(name);
27         }
28
29         // if not, check any enclosing scope
30         if ( s==null && getEnclosingScope() != null ) {
31             return getEnclosingScope().resolve(name);
32         }
33
34         return s;
35     }
36
37     /** Scopes other other package and class don't know how to resolve types
38      *  (e.g., MethodSymbol).  Look to enclosing scope.
39      */
40     public ClassSymbol resolveType(String type) {
41         if ( getEnclosingScope()!=null ) {
42             return getEnclosingScope().resolveType(type);
43         }
44         return null;
45     }
46
47     public VariableSymbol resolveVariable(String name) {
48         Symbol s = getMembers().get(name);
49         if (debug()) System.out.println(
50                 "SymbolWithScope.resolveVariable(" + name + 
51                 "): examine " + this.getClass().getName() + "=" + toString());
52         
53         // found it
54         if (s != null && s.getClass() == VariableSymbol.class) {
55             if (debug()) System.out.println(
56                     "SymbolWithScope.resolveVariable(" + name + ") found in " +
57                     this.getClass().getName() + "=" + toString());
58             return (VariableSymbol)s;
59         }
60
61         // not here, check enclosing scope
62         if ( s==null && getEnclosingScope() != null ) {
63             return getEnclosingScope().resolveVariable(name);
64         }
65
66         // not a variable
67         if (debug()) System.out.println(
68                 "SymbolWithScope.resolveVariable(" + name + 
69                 "): not a variable in " + this.getClass().getName() + 
70                 "=" + toString());
71         return null;
72     }
73
74     public MethodSymbol resolveMethod(
75             String name, 
76             int numargs) {
77         if (debug()) System.out.println(
78                 "SymbolWithScope.resolveMethod(" + name + "," + numargs +
79                 "): examine " + this.getClass().getName() + "=" + toString());
80         
81         Symbol s = null;
82         if ( numargs == 0 ) {
83             s = resolve(name);
84         } else {
85             s = resolve(name+numargs);
86         }
87
88         if ( s!=null && debug() ) System.out.println(
89                 "SymbolWithScope.resolveMethod(" + name + "," + numargs +
90                 "): found in context " + this.getClass().getName() +
91                 "=" + toString());
92         else if ( s==null && debug() ) System.out.println(
93                 "SymbolWithScope.resolveMethod(" + name + "," + numargs +
94                 "): not found in context " + this.getClass().getName() + 
95                 "="+toString());
96         
97         if ( s==null || (s!=null && s.getClass() != MethodSymbol.class) ) {
98             // not a method
99             if ( s!=null && debug() ) System.out.println(
100                     "SymbolWithScope.resolveMethod(" + name + "," + numargs +
101                     "): not a method");
102             return null;         
103         }
104         return (MethodSymbol)s;
105     }
106
107     /** By default, pass up responsibility in scope hierarchy until we
108      *  find a class.
109      */
110     public boolean isMethod(String name) {
111         if ( getEnclosingScope()!=null ) {
112             return getEnclosingScope().isMethod(name);
113         }
114         return false;
115     }
116
117     public Symbol remove(String name) {
118         Symbol s = (Symbol)getMembers().get(name);
119         if ( s==null && getEnclosingScope() != null) {
120             return getEnclosingScope().remove(name);
121         }
122         if ( s != null) {
123             getMembers().remove(name);
124         }
125         return s;
126     }
127
128     public Symbol define(
129             String name, 
130             Symbol sym) {
131         // check for error
132         Map members = getMembers();
133         if ( members == null ) {
134             members = createMembers();
135         }
136         members.put(name, sym);
137         sym.scope = this; // track the scope in each symbol
138         
139         if (debug()) System.out.println(" \tdefine " + name + " as " + sym);
140         return sym;
141     }
142
143     /** create the member list; we're about to add stuff */
144     protected Map<String, Symbol> createMembers() {
145         return getMembers();
146     }
147
148     /** Scope defaults to just the symbol name; method f's scope is f by 
149      *  default. 
150      */
151     public String getScopeName() {
152         return name;
153     }
154
155     public String getFullyQualifiedName() {
156         String parent = null;
157         if ( getEnclosingScope()!=null ) {
158             parent = getEnclosingScope().getFullyQualifiedName();
159         }
160         if ( parent!=null ) {
161             return parent + "::" + name;
162         }
163         return name;
164     }
165
166 }