001: package sisc.env;
002:
003: import java.io.*;
004: import sisc.data.*;
005: import sisc.io.*;
006:
007: import java.util.WeakHashMap;
008: import java.net.URLClassLoader;
009: import java.net.URL;
010: import java.security.AccessControlException;
011: import sisc.interpreter.AppContext;
012: import sisc.reader.*;
013: import sisc.util.Util;
014: import sisc.util.Defaults;
015:
016: public class DynamicEnvironment extends Util implements Cloneable {
017: public final AppContext ctx;
018:
019: public Value in, out;
020:
021: public Pair sourceAnnotations = EMPTYLIST;
022:
023: public Charset characterSet = Util.getDefaultCharacterSet();
024: public boolean caseSensitive = Defaults.CASE_SENSITIVE;
025: public boolean printShared = Defaults.PRINT_SHARED;
026: public boolean vectorLengthPrefixing = Defaults.VECTOR_LENGTH_PREFIXING;
027: public boolean emitDebuggingSymbols = Defaults.EMIT_DEBUGGING_SYMBOLS;
028: public boolean permissiveParsing = Defaults.PERMISSIVE_PARSING;
029: public boolean hedgedInlining = Defaults.HEDGED_INLINING;
030: public boolean internalDebugging = Defaults.INTERNAL_DEBUGGING;
031: public int synopsisLength = Defaults.SYNOPSIS_LENGTH;
032: public int maxStackTraceDepth = Defaults.MAX_STACK_TRACE_DEPTH;
033:
034: private static String defaultCharacterSet = Util
035: .getDefaultCharacterSet().displayName();
036: private static String defaultCaseSensitive = new Boolean(
037: Defaults.CASE_SENSITIVE).toString();
038: private static String defaultPrintShared = new Boolean(
039: Defaults.PRINT_SHARED).toString();
040: private static String defaultVectorLengthPrefixing = new Boolean(
041: Defaults.VECTOR_LENGTH_PREFIXING).toString();
042: private static String defaultEmitDebuggingSymbols = new Boolean(
043: Defaults.EMIT_DEBUGGING_SYMBOLS).toString();
044: private static String defaultPermissiveParsing = new Boolean(
045: Defaults.PERMISSIVE_PARSING).toString();
046: private static String defaultHedgedInlining = new Boolean(
047: Defaults.HEDGED_INLINING).toString();
048: private static String defaultInternalDebugging = new Boolean(
049: Defaults.INTERNAL_DEBUGGING).toString();
050: private static String defaultSynopsisLength = new Integer(
051: Defaults.SYNOPSIS_LENGTH).toString();
052: private static String defaultEmitAnnotations = new Boolean(
053: Defaults.EMIT_ANNOTATIONS).toString();
054: private static String defaultStrictR5RS = new Boolean(
055: Defaults.STRICT_R5RS).toString();
056: private static String defaultMaxStackTraceDepth = new Integer(
057: Defaults.MAX_STACK_TRACE_DEPTH).toString();
058:
059: public Value wind = FALSE; //top of wind stack
060:
061: //the lexer is stateful
062: public Parser parser = new Parser(new Lexer());
063:
064: private Thread bindingThread;
065: private ClassLoader classLoader;
066: private ExtensibleURLClassLoader urlClassLoader;
067: private URL[] initialClassPathExtension;
068:
069: private static class ExtensibleURLClassLoader extends
070: URLClassLoader {
071:
072: public ExtensibleURLClassLoader(URL[] urls, ClassLoader parent) {
073: super (urls, parent);
074: }
075:
076: public void addURL(URL url) {
077: super .addURL(url);
078: }
079: }
080:
081: //user-defined thread variables; this map is weak so that we don't
082: //hang on to vars that are no longer in use.
083: public java.util.Map parameters = new WeakHashMap(1);
084:
085: public DynamicEnvironment(AppContext ctx) {
086: this (ctx, System.in, System.out);
087: }
088:
089: public DynamicEnvironment(AppContext ctx, InputStream in,
090: OutputStream out) {
091: this .ctx = ctx;
092: this .characterSet = Util.charsetFromString(ctx.getProperty(
093: "sisc.characterSet", defaultCharacterSet));
094: try {
095: this .in = new SchemeCharacterInputPort(new SourceReader(
096: new InputStreamReader(in, this .characterSet
097: .getName()), liMessage(SISCB, "console")));
098: this .out = new SchemeCharacterOutputPort(
099: new AutoflushWriter(new OutputStreamWriter(out,
100: this .characterSet.getName())));
101: } catch (UnsupportedEncodingException use) {
102: //Hack?
103: throw new RuntimeException(use.getMessage());
104: }
105:
106: this .caseSensitive = ctx.getProperty("sisc.caseSensitive",
107: defaultCaseSensitive).equals("true");
108: this .printShared = ctx.getProperty("sisc.printShared",
109: defaultPrintShared).equals("true");
110: this .vectorLengthPrefixing = ctx.getProperty(
111: "sisc.vectorLengthPrefixing",
112: defaultVectorLengthPrefixing).equals("true");
113: this .emitDebuggingSymbols = ctx.getProperty(
114: "sisc.emitDebuggingSymbols",
115: defaultEmitDebuggingSymbols).equals("true");
116: this .permissiveParsing = ctx.getProperty(
117: "sisc.permissiveParsing", defaultPermissiveParsing)
118: .equals("true");
119: this .hedgedInlining = ctx.getProperty("sisc.hedgedInlining",
120: defaultHedgedInlining).equals("true");
121: this .internalDebugging = ctx.getProperty(
122: "sisc.internalDebugging", defaultInternalDebugging)
123: .equals("true");
124: this .synopsisLength = Integer.parseInt(ctx.getProperty(
125: "sisc.synopsisLength", defaultSynopsisLength));
126: this .parser.annotate = ctx.getProperty("sisc.emitAnnotations",
127: defaultEmitAnnotations).equals("true");
128: this .parser.lexer.strictR5RS = ctx.getProperty(
129: "sisc.strictR5RS", defaultStrictR5RS).equals("true");
130: this .maxStackTraceDepth = Integer.parseInt(ctx.getProperty(
131: "sisc.maxStackTraceDepth", defaultMaxStackTraceDepth));
132:
133: initialClassPathExtension = new URL[] {};
134: }
135:
136: public Value getCurrentInPort() {
137: return in;
138: }
139:
140: public Reader getCurrentInReader() {
141: return charinreader(in);
142: }
143:
144: public Value getCurrentOutPort() {
145: return out;
146: }
147:
148: public Writer getCurrentOutWriter() {
149: return charoutwriter(out);
150: }
151:
152: public Object clone() throws CloneNotSupportedException {
153: DynamicEnvironment res = (DynamicEnvironment) super .clone();
154: res.parser = new Parser(new Lexer());
155: res.parser.annotate = parser.annotate;
156: res.parser.lexer.strictR5RS = parser.lexer.strictR5RS;
157: res.initialClassPathExtension = getClassPath();
158: res.bindingThread = null;
159: res.classLoader = null;
160: res.urlClassLoader = null;
161: WeakHashMap newParams = new WeakHashMap();
162: newParams.putAll(res.parameters);
163: res.parameters = newParams;
164: return res;
165: }
166:
167: public DynamicEnvironment copy() {
168: try {
169: return (DynamicEnvironment) clone();
170: } catch (CloneNotSupportedException e) {
171: return this ;
172: }
173: }
174:
175: /**
176: * Binds this DynamicEnvironment to the current thread.
177: *
178: * DynamicEnvironments must not be used across different
179: * threads. This method enforces this. It also initialises the
180: * DynamicEnvironments's class loader, which, if the security
181: * permissions allow it, will have the current thread's context
182: * class loader as a parent.
183: */
184: public void bind() {
185: Thread currentThread = Thread.currentThread();
186: if (bindingThread == null) {
187: bindingThread = currentThread;
188: classLoader = currentClassLoader();
189: try {
190: urlClassLoader = new ExtensibleURLClassLoader(
191: initialClassPathExtension, classLoader);
192: } catch (AccessControlException e) {
193: }
194: } else if (bindingThread != currentThread) {
195: throw new RuntimeException(liMessage(SISCB, "dynenvrebind"));
196: }
197: }
198:
199: public ClassLoader getClassLoader() {
200: return (urlClassLoader == null) ? classLoader : urlClassLoader;
201: }
202:
203: public URL[] getClassPath() {
204: return (urlClassLoader == null ? new URL[] {} : urlClassLoader
205: .getURLs());
206: }
207:
208: public void extendClassPath(URL url) {
209: if (urlClassLoader == null)
210: return;
211: urlClassLoader.addURL(url);
212: }
213:
214: public Value getInputPort() {
215: return in;
216: }
217:
218: public void setInputPort(Value v) {
219: in = v;
220: }
221:
222: public Value getOutputPort() {
223: return out;
224: }
225:
226: public void setOutputPort(Value v) {
227: out = v;
228: }
229:
230: public Value getSourceAnnotations() {
231: return sourceAnnotations;
232: }
233:
234: public void setSourceAnnotations(Value v) {
235: sourceAnnotations = pair(v);
236: }
237:
238: public Charset getCharacterSet() {
239: return characterSet;
240: }
241:
242: public void setCharacterSet(Value v) {
243: characterSet = Util.charsetFromString(string(v));
244: }
245:
246: public Value getCaseSensitive() {
247: return truth(caseSensitive);
248: }
249:
250: public void setCaseSensitive(Value v) {
251: caseSensitive = truth(v);
252: }
253:
254: public Value getPrintShared() {
255: return truth(printShared);
256: }
257:
258: public void setPrintShared(Value v) {
259: printShared = truth(v);
260: }
261:
262: public Value getVectorLengthPrefixing() {
263: return truth(vectorLengthPrefixing);
264: }
265:
266: public void setVectorLengthPrefixing(Value v) {
267: vectorLengthPrefixing = truth(v);
268: }
269:
270: public Value getEmitDebuggingSymbols() {
271: return truth(emitDebuggingSymbols);
272: }
273:
274: public void setEmitDebuggingSymbols(Value v) {
275: emitDebuggingSymbols = truth(v);
276: }
277:
278: public Value getPermissiveParsing() {
279: return truth(permissiveParsing);
280: }
281:
282: public void setPermissiveParsing(Value v) {
283: permissiveParsing = truth(v);
284: }
285:
286: public Value getHedgedInlining() {
287: return truth(hedgedInlining);
288: }
289:
290: public void setHedgedInlining(Value v) {
291: hedgedInlining = truth(v);
292: }
293:
294: public Value getInternalDebugging() {
295: return truth(internalDebugging);
296: }
297:
298: public void setInternalDebugging(Value v) {
299: internalDebugging = truth(v);
300: }
301:
302: public Value getSynopsisLength() {
303: return Quantity.valueOf(synopsisLength);
304: }
305:
306: public void setSynopsisLength(Value v) {
307: synopsisLength = num(v).intValue();
308: }
309:
310: public Value getEmitAnnotations() {
311: return truth(parser.annotate);
312: }
313:
314: public void setEmitAnnotations(Value v) {
315: parser.annotate = truth(v);
316: }
317:
318: public Value getStrictR5RSCompliance() {
319: return truth(parser.lexer.strictR5RS);
320: }
321:
322: public void setStrictR5RSCompliance(Value v) {
323: parser.lexer.strictR5RS = truth(v);
324: }
325:
326: public int getMaxStackTraceDepthAsInt() {
327: return maxStackTraceDepth;
328: }
329:
330: public Value getMaxStackTraceDepth() {
331: return Quantity.valueOf(maxStackTraceDepth);
332: }
333:
334: public void setMaxStackTraceDepth(Value v) {
335: maxStackTraceDepth = num(v).indexValue();
336: }
337: }
338: /*
339: * The contents of this file are subject to the Mozilla Public
340: * License Version 1.1 (the "License"); you may not use this file
341: * except in compliance with the License. You may obtain a copy of
342: * the License at http://www.mozilla.org/MPL/
343: *
344: * Software distributed under the License is distributed on an "AS
345: * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
346: * implied. See the License for the specific language governing
347: * rights and limitations under the License.
348: *
349: * The Original Code is the Second Interpreter of Scheme Code (SISC).
350: *
351: * The Initial Developer of the Original Code is Scott G. Miller.
352: * Portions created by Scott G. Miller are Copyright (C) 2000-2007
353: * Scott G. Miller. All Rights Reserved.
354: *
355: * Contributor(s):
356: * Matthias Radestock
357: *
358: * Alternatively, the contents of this file may be used under the
359: * terms of the GNU General Public License Version 2 or later (the
360: * "GPL"), in which case the provisions of the GPL are applicable
361: * instead of those above. If you wish to allow use of your
362: * version of this file only under the terms of the GPL and not to
363: * allow others to use your version of this file under the MPL,
364: * indicate your decision by deleting the provisions above and
365: * replace them with the notice and other provisions required by
366: * the GPL. If you do not delete the provisions above, a recipient
367: * may use your version of this file under either the MPL or the
368: * GPL.
369: */
|