001: /*
002: * @(#)CompileContext.java 1.5 05/06/14
003: *
004: * Copyright (c) 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package pnuts.compiler;
010:
011: import java.io.ByteArrayOutputStream;
012: import java.io.DataOutputStream;
013: import java.io.FileOutputStream;
014: import java.io.IOException;
015: import java.util.Enumeration;
016: import java.util.Map;
017: import java.util.HashMap;
018: import java.util.List;
019: import java.util.ArrayList;
020:
021: import pnuts.lang.Context;
022: import pnuts.lang.PnutsException;
023:
024: /**
025: * This class is used with pnuts.compiler.Compiler class to compile Pnuts
026: * scripts.
027: *
028: * @see pnuts.compiler.Compiler
029: * @see pnuts.lang.Context
030: */
031: class CompileContext extends Context {
032:
033: private final static boolean DEBUG = false;
034:
035: Frame env = new Frame();
036:
037: Symbol sym = new Symbol();
038:
039: Map constants = new HashMap();
040:
041: ClassFile cf;
042:
043: List classFiles = new ArrayList();
044:
045: String constClassName;
046:
047: List classes = new ArrayList();
048:
049: boolean hasAttachMethod;
050:
051: int line = 0xffffffff;
052:
053: int column = 0xffffffff;
054:
055: Label returnLabel;
056:
057: boolean inGeneratorBlock;
058:
059: Object scriptSource;
060:
061: BeanEnv beanEnv;
062:
063: CompileContext() {
064: }
065:
066: CompileContext(Context context) {
067: super (context);
068: }
069:
070: Class loadClasses(CodeLoader loader) throws IOException {
071: ByteArrayOutputStream bout = new ByteArrayOutputStream();
072: Class ret = load(cf, loader, bout);
073:
074: for (int i = 0, n = classFiles.size(); i < n; i++) {
075: load((ClassFile) classFiles.get(i), loader, bout);
076: }
077: /*
078: for (Enumeration e = classFiles.elements(); e.hasMoreElements();) {
079: load((ClassFile) e.nextElement(), loader, bout);
080: }
081: */
082: resolve(loader);
083: return ret;
084: }
085:
086: void resolve(CodeLoader loader) {
087: for (int i = 0, n = classes.size(); i < n; i++) {
088: Class c = (Class) classes.get(i);
089: loader.resolve(c);
090: }
091: /*
092: for (Enumeration e = classes.elements(); e.hasMoreElements();) {
093: Class c = (Class) e.nextElement();
094: loader.resolve(c);
095: }
096: */
097: }
098:
099: Class load(ClassFile file, CodeLoader loader) throws IOException {
100: return load(file, loader, new ByteArrayOutputStream());
101: }
102:
103: Class load(ClassFile file, CodeLoader loader,
104: ByteArrayOutputStream bout) throws IOException {
105: bout.reset();
106: file.write(new DataOutputStream(bout));
107:
108: byte array[] = bout.toByteArray();
109: Class ret = loader.define(file.getClassName(), array, 0,
110: array.length);
111: classes.add(ret);
112: return ret;
113: }
114:
115: /**
116: * Get the primary class file
117: */
118: public ClassFile getClassFile() {
119: return cf;
120: }
121:
122: /**
123: * Enumerate related class files.
124: */
125: public List getClassFiles() {
126: return classFiles;
127: }
128:
129: public void write(DataOutputStream out) throws IOException {
130: cf.write(out);
131: }
132:
133: void debug(ClassFile file) {
134: try {
135: String fileName = "/tmp/" + file.getClassName() + ".class";
136: System.out.println(fileName);
137: FileOutputStream fout = new FileOutputStream(fileName);
138: DataOutputStream dout = new DataOutputStream(fout);
139: file.write(dout);
140: fout.close();
141: } catch (IOException e) {
142: e.printStackTrace();
143: }
144: }
145:
146: void debug() {
147: debug(cf);
148: for (int i = 0, n = classFiles.size(); i < n; i++) {
149: ClassFile file = (ClassFile) classFiles.get(i);
150: debug(file);
151: }
152: /*
153: for (Enumeration e = classFiles.elements(); e.hasMoreElements();) {
154: ClassFile file = (ClassFile) e.nextElement();
155: debug(file);
156: }
157: */
158: }
159:
160: void _openFrame(String func, String locals[], boolean leaf) {
161: env = new Frame(locals, func, env, leaf);
162: }
163:
164: void _closeFrame() {
165: env = env.parent;
166: }
167:
168: void openScope(String locals[]) {
169: env.openLocal();
170: for (int i = 0; i < locals.length; i++) {
171: _declare(locals[i]);
172: }
173: }
174:
175: void closeScope() {
176: env.closeLocal();
177: }
178:
179: void setReference(String symbol) {
180: String sym = symbol.intern();
181: Frame f = env;
182: f.setReference(sym);
183: }
184:
185: Reference findReference(String symbol) {
186: return getReference(symbol, true);
187: }
188:
189: Reference getReference(String symbol) {
190: return getReference(symbol, false);
191: }
192:
193: Reference getReference(String symbol, boolean flag) {
194: String sym = symbol.intern();
195: Frame f = env;
196: Reference ref = f.getReference(sym, flag);
197: if (ref != null) {
198: return ref;
199: }
200: f = f.parent;
201:
202: while (f != null) {
203: Reference r = f.getReference(sym, flag);
204: if (r != null) {
205: Frame f0 = env;
206: Frame f1 = null;
207: while (f0 != f) {
208: f1 = f0;
209: if (!f0.imports.contains(sym)) {
210: if (DEBUG) {
211: System.out.println(f0.fname + " imports "
212: + sym);
213: }
214: f0.imports.add(sym);
215: }
216: f0 = f0.parent;
217: }
218: Reference ret = new Reference(sym, -1,
219: ((r.offset >= 0) ? r.offset : 0));
220: Reference _ref = f.getReference(sym, flag);
221: List vec = (ArrayList) f.exports.get(f1);
222: if (vec == null) {
223: vec = new ArrayList();
224: f.exports.put(f1, vec);
225: }
226: if (!vec.contains(_ref)) {
227: vec.add(_ref);
228: if (DEBUG) {
229: System.out.println(f.fname + "["
230: + Integer.toHexString(f.hashCode())
231: + "] exports " + _ref + " to "
232: + f1.fname + "["
233: + Integer.toHexString(f1.hashCode())
234: + "]");
235: }
236: }
237: f0 = env;
238: while (f0 != f1) {
239: Frame p = f0.parent;
240: vec = (ArrayList) p.exports.get(f0);
241: if (vec == null) {
242: vec = new ArrayList();
243: p.exports.put(f0, vec);
244: }
245: if (!vec.contains(ret)) {
246: vec.add(ret);
247: if (DEBUG) {
248: System.out.println(p.fname
249: + "["
250: + Integer.toHexString(p.hashCode())
251: + "] exports "
252: + ret
253: + " to "
254: + f0.fname
255: + "["
256: + Integer
257: .toHexString(f0.hashCode())
258: + "]");
259: }
260: }
261: f0 = p;
262: }
263: return ret;
264: }
265: f = f.parent;
266: }
267: return null;
268: }
269:
270: int _declare(String symbol) {
271: int local = cf.getLocal();
272: _declare(symbol, local);
273: return local;
274: }
275:
276: void _declare_frame(String symbol, int local) {
277: env._declare_frame(symbol, local);
278: }
279:
280: void redefine(String symbol) {
281: LocalInfo i = env.lookup(symbol);
282: if (i != null) {
283: i.frame = null;
284: }
285: }
286:
287: void _declare(String symbol, int local) {
288: _declare(symbol, local, env.leaf ? -1 : 0);
289: }
290:
291: void _declare(String symbol, int local, int idx) {
292: if (DEBUG) {
293: System.out.println("_declare " + symbol + " " + local + " "
294: + idx);
295: }
296: env._declare(symbol, local, idx);
297: }
298:
299: int declare(String symbol) {
300: int local = cf.declareLocal();
301: declare(symbol, local);
302: return local;
303: }
304:
305: void declare(String symbol, int local) {
306: declare(symbol, local, env.leaf ? -1 : 0);
307: }
308:
309: void declare(String symbol, int local, int idx) {
310: if (DEBUG) {
311: System.out.println("declare " + symbol + " " + local + " "
312: + idx);
313: }
314: env.declare(symbol, local, idx);
315: }
316:
317: int contextIndex = 0;
318:
319: int getContextIndex() {
320: return contextIndex;
321: }
322:
323: void setContextIndex(int index) {
324: contextIndex = index;
325: }
326:
327: /*
328: * loops
329: */
330:
331: ControlEnv ctrl_env;
332:
333: java.util.Stack finallyBlocks = new java.util.Stack(); // for outside loop
334:
335: ControlEnv openControlEnv(int id) {
336: return ctrl_env = new ControlEnv(id, ctrl_env);
337: }
338:
339: void closeControlEnv() {
340: ctrl_env = ctrl_env.parent;
341: }
342:
343: Label getContinueLabel() {
344: if (ctrl_env == null) {
345: return null;
346: }
347: return ctrl_env.continueLabel;
348: }
349:
350: Label getBreakLabel() {
351: if (ctrl_env == null) {
352: return null;
353: }
354: return ctrl_env.breakLabel;
355: }
356:
357: void pushFinallyBlock(Label label) {
358: if (ctrl_env != null) {
359: ctrl_env.pushFinallyBlock(label);
360: } else {
361: this .finallyBlocks.push(label);
362: }
363: }
364:
365: Label popFinallyBlock() {
366: if (ctrl_env != null) {
367: return ctrl_env.popFinallyBlock();
368: } else {
369: return (Label) this .finallyBlocks.pop();
370: }
371: }
372:
373: void leaveControlEnv() {
374: if (ctrl_env != null) {
375: leaveControlEnv(ctrl_env);
376: }
377: }
378:
379: void leaveControlEnv(ControlEnv env) {
380: java.util.Stack finallyBlocks = env.finallyBlocks;
381: for (int i = 0; i < finallyBlocks.size(); i++) {
382: Label finalTag = (Label) finallyBlocks.get(finallyBlocks
383: .size()
384: - 1 - i);
385: cf.add(Opcode.JSR, finalTag);
386: }
387: }
388:
389: void leaveFrame() {
390: ControlEnv env = ctrl_env;
391: while (env != null) {
392: leaveControlEnv(env);
393: env = env.parent;
394: }
395: java.util.Stack blocks = this .finallyBlocks;
396: for (int i = 0; i < blocks.size(); i++) {
397: Label finalTag = (Label) blocks.get(blocks.size() - 1 - i);
398: cf.add(Opcode.JSR, finalTag);
399: }
400: }
401:
402: void openBranchEnv() {
403: env.openBranchEnv();
404: }
405:
406: void addBranch() {
407: env.addBranch();
408: }
409:
410: void closeBranchEnv() {
411: env.closeBranchEnv();
412: }
413:
414: public Object clone() {
415: try {
416: CompileContext cc = (CompileContext) super .clone();
417: cc.ctrl_env = null;
418: cc.finallyBlocks = new java.util.Stack();
419: cc.inGeneratorBlock = false;
420: cc.env = (Frame) cc.env.clone();
421: return cc;
422: } catch (Throwable t) {
423: throw new PnutsException(t, this);
424: }
425: }
426: }
|