001: package gnu.expr;
002:
003: import gnu.text.SourceMessages;
004:
005: /** Class for doing a tree-walk over an Expression tree. */
006:
007: public class ExpWalker implements gnu.text.SourceLocator {
008: protected SourceMessages messages;
009: Compilation comp;
010:
011: /** Get the Compilation associated with this walker. */
012: public Compilation getCompilation() {
013: return comp;
014: }
015:
016: public SourceMessages getMessages() {
017: return messages;
018: }
019:
020: protected Expression walkExpression(Expression exp) {
021: exp.walkChildren(this );
022: return exp;
023: }
024:
025: public void setContext(Compilation comp) {
026: this .comp = comp;
027: messages = comp.getMessages();
028: }
029:
030: /** Call the walk method of argument Expression.
031: * Could call Expression's walk directly, but this allows us to
032: * interpose a method call on each Expression. We use it to note the
033: * Expression's line number. Should not need to be overridden;
034: * if you do, you may also want to override walkExps. */
035: public Expression walk(Expression exp) {
036: int line = exp.getLineNumber();
037: if (messages != null && line > 0) {
038: String saveFile = messages.getFileName();
039: int saveLine = messages.getLineNumber();
040: int saveColumn = messages.getColumnNumber();
041: messages.setLine(exp.getFileName(), line, exp
042: .getColumnNumber());
043: Expression ret = exp.walk(this );
044: messages.setLine(saveFile, saveLine, saveColumn);
045: return ret;
046: }
047: return exp.walk(this );
048: }
049:
050: protected Expression walkApplyExp(ApplyExp exp) {
051: return walkExpression(exp);
052: }
053:
054: protected Expression walkIfExp(IfExp exp) {
055: return walkExpression(exp);
056: }
057:
058: protected final void walkDeclarationType(Declaration decl) {
059: Expression texp1 = decl.getTypeExp();
060: if (texp1 != null) {
061: Expression texp2 = texp1.walk(this );
062: if (texp2 != texp1)
063: decl.setTypeExp(texp2);
064: }
065: }
066:
067: protected final void walkDeclarationTypes(ScopeExp exp) {
068: for (Declaration decl = exp.firstDecl(); decl != null; decl = decl
069: .nextDecl()) {
070: walkDeclarationType(decl);
071: }
072: }
073:
074: protected Expression walkScopeExp(ScopeExp exp) {
075: walkDeclarationTypes(exp);
076: return walkExpression(exp);
077: }
078:
079: protected Expression walkLetExp(LetExp exp) {
080: return walkScopeExp(exp);
081: }
082:
083: protected Expression walkLambdaExp(LambdaExp exp) {
084: return walkScopeExp(exp);
085: }
086:
087: protected Expression walkClassExp(ClassExp exp) {
088: return walkLambdaExp(exp);
089: }
090:
091: protected Expression walkObjectExp(ObjectExp exp) {
092: return walkClassExp(exp);
093: }
094:
095: protected Expression walkModuleExp(ModuleExp exp) {
096: return walkLambdaExp(exp);
097: }
098:
099: protected Expression walkSetExp(SetExp exp) {
100: Declaration decl = exp.binding;
101: boolean updateNeeded = decl != null
102: && decl.value == exp.new_value;
103: Expression ret = walkExpression(exp);
104: // If the Declarations's value was that of our new_value,
105: // and we modified/simplified the latter, update the former as well.
106: if (updateNeeded && exp.isDefining()) {
107: decl.value = exp.new_value;
108: if (exp.new_value instanceof LambdaExp)
109: ((LambdaExp) exp.new_value).nameDecl = decl;
110: }
111: return ret;
112: }
113:
114: //protected Expression walkSwitchExp (SwitchExp exp) { return walkExpression(exp); }
115: protected Expression walkTryExp(TryExp exp) {
116: return walkExpression(exp);
117: }
118:
119: protected Expression walkBeginExp(BeginExp exp) {
120: return walkExpression(exp);
121: }
122:
123: protected Expression walkQuoteExp(QuoteExp exp) {
124: return walkExpression(exp);
125: }
126:
127: protected Expression walkReferenceExp(ReferenceExp exp) {
128: return walkExpression(exp);
129: }
130:
131: protected Expression walkThisExp(ThisExp exp) {
132: return walkReferenceExp(exp);
133: }
134:
135: protected Expression walkSynchronizedExp(SynchronizedExp exp) {
136: return walkExpression(exp);
137: }
138:
139: protected Expression walkBlockExp(BlockExp exp) {
140: return walkExpression(exp);
141: }
142:
143: protected Expression walkExitExp(ExitExp exp) {
144: return walkExpression(exp);
145: }
146:
147: protected Expression walkFluidLetExp(FluidLetExp exp) {
148: return walkLetExp(exp);
149: }
150:
151: protected Expression walkLangExp(LangExp exp) {
152: return walkExpression(exp);
153: }
154:
155: protected LambdaExp currentLambda = null;
156:
157: /** If exitValue is set to non-null, the walk stops. */
158: Object exitValue = null;
159:
160: public final LambdaExp getCurrentLambda() {
161: return currentLambda;
162: }
163:
164: public Expression[] walkExps(Expression[] exps) {
165: return walkExps(exps, exps.length);
166: }
167:
168: /** Call walk on the Expressions in an array.
169: * However, the walk method is inlined for speed.
170: */
171: public Expression[] walkExps(Expression[] exps, int n) {
172: String saveFile;
173: int saveLine;
174: int saveColumn;
175: if (messages != null) {
176: saveFile = messages.getFileName();
177: saveLine = messages.getLineNumber();
178: saveColumn = messages.getColumnNumber();
179: } else {
180: saveFile = null;
181: saveLine = 0;
182: saveColumn = 0;
183: }
184: boolean mustRestore = false;
185: for (int i = 0; i < n && exitValue == null; i++) {
186: Expression exp = exps[i];
187: int line = exp.getLineNumber();
188: if (messages != null && line > 0) {
189: messages.setLine(exp.getFileName(), line, exp
190: .getColumnNumber());
191: mustRestore = true;
192: } else if (mustRestore) {
193: messages.setLine(saveFile, saveLine, saveColumn);
194: mustRestore = false;
195: }
196: exps[i] = walk(exp);
197: }
198: if (mustRestore)
199: messages.setLine(saveFile, saveLine, saveColumn);
200: return exps;
201: }
202:
203: public void walkDefaultArgs(LambdaExp exp) {
204: if (exp.defaultArgs != null)
205: exp.defaultArgs = walkExps(exp.defaultArgs);
206: }
207:
208: public void error(char kind, String message) {
209: if (kind == 'w'
210: && comp.getBooleanOption("warn-as-error", false))
211: kind = 'e';
212: if (messages != null)
213: messages.error(kind, message);
214: else
215: new Error("internal error: " + message);
216: }
217:
218: public Expression noteError(String message) {
219: if (messages != null)
220: messages.error('e', message);
221: return new ErrorExp(message);
222: }
223:
224: public final String getFileName() {
225: return messages.getFileName();
226: }
227:
228: public final int getLineNumber() {
229: return messages.getLineNumber();
230: }
231:
232: public final int getColumnNumber() {
233: return messages.getColumnNumber();
234: }
235:
236: public String getPublicId() {
237: return messages.getPublicId();
238: }
239:
240: public String getSystemId() {
241: return messages.getSystemId();
242: }
243:
244: /** Normally same as getSystemId. */
245:
246: public boolean isStableSourceLocation() {
247: return false;
248: }
249:
250: public void setFile(String filename) {
251: messages.setFile(filename);
252: }
253:
254: public void setLine(int line) {
255: messages.setLine(line);
256: }
257:
258: public void setColumn(int column) {
259: messages.setColumn(column);
260: }
261:
262: public void setLine(String filename, int line, int column) {
263: messages.setLine(filename, line, column);
264: }
265: }
|