Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/memoire/silk/SilkSchemeUtils.java


1   
2   
3   package com.memoire.silk;
4   import com.memoire.silk.*;
5   
6   
7   
8   /**  @author Peter Norvig, peter@norvig.com http://www.norvig.com 
9    * Copyright 1998 Peter Norvig, see http://www.norvig.com/license.html **/
10  
11  import java.io.*;
12  
13  public abstract class SilkSchemeUtils {
14  
15    /** Same as Boolean.TRUE. **/
16    public static final Boolean TRUE = Boolean.TRUE;
17    /** Same as Boolean.FALSE. **/
18    public static final Boolean FALSE = Boolean.FALSE;
19  
20    public static Double ZERO = new Double(0.0);
21    public static Double ONE = new Double(1.0);
22    //////////////// Conversion Routines ////////////////
23  
24    // The following convert or coerce objects to the right type.
25  
26    /** Convert boolean to Boolean. **/
27    public static Boolean truth(boolean x) { return x ? TRUE : FALSE; }
28  
29    /** Convert SilkScheme object to boolean.  Only #f is false, others are true. **/
30    public static boolean truth(Object x) { return x != FALSE; }
31  
32    /** Convert double to Double. Caches 0 and 1; makes new for others. **/
33    public static Double num(double x) { 
34      return (x == 0.0) ? ZERO : (x == 1.0) ? ONE : new Double(x); }
35  
36    /** Converts a SilkScheme object to a double, or calls error. **/
37    public static double num(Object x) { 
38      if (x instanceof Number) return ((Number)x).doubleValue();
39      else return num(error("expected a number, got: " + x));
40    }
41  
42    /** Converts a SilkScheme object to a char, or calls error. **/
43    public static char chr(Object x) {
44      if (x instanceof Character) return ((Character)x).charValue();
45      else return chr(error("expected a char, got: " + x));
46    }
47  
48    /** Converts a char to a Character. **/
49    public static Character chr(char ch) {
50      return new Character(ch);
51    }
52  
53    /** Coerces a SilkScheme object to a SilkScheme string, which is a char[]. **/
54    public static char[] str(Object x) {
55      if (x instanceof char[]) return (char[])x;
56      else return str(error("expected a string, got: " + x)); 
57    }
58  
59    /** Coerces a SilkScheme object to a SilkScheme symbol, which is a string. **/
60    public static String sym(Object x) {
61      if (x instanceof String) return (String)x;
62      else return sym(error("expected a symbol, got: " + x)); 
63    }
64  
65    /** Coerces a SilkScheme object to a SilkScheme vector, which is a Object[]. **/
66    public static Object[] vec(Object x) {
67      if (x instanceof Object[]) return (Object[])x;
68      else return vec(error("expected a vector, got: " + x)); 
69    }
70  
71    /** Coerces a SilkScheme object to a SilkScheme input port, which is an SilkInputPort.
72     * If the argument is null, returns interpreter.input. **/
73    public static SilkInputPort inPort(Object x, SilkScheme interp) {
74      if (x == null) return interp.input;
75      else if (x instanceof SilkInputPort) return (SilkInputPort)x;
76      else return inPort(error("expected an input port, got: " + x), interp); 
77    }
78  
79    /** Coerces a SilkScheme object to a SilkScheme input port, which is a PrintWriter.
80     * If the argument is null, returns System.out. **/
81    public static PrintWriter outPort(Object x, SilkScheme interp) {
82      if (x == null) return interp.output;
83      else if (x instanceof PrintWriter) return (PrintWriter)x;
84      else return outPort(error("expected an output port, got: " + x), interp); 
85    }
86  
87    //////////////// Error Routines ////////////////
88  
89    /** A continuable error. Prints an error message and then prompts for
90     * a value to eval and return. **/
91    public static Object error(String message) {
92      System.err.println("**** ERROR: " + message);
93      throw new RuntimeException(message);  
94    }
95  
96    public static Object warn(String message) {
97      System.err.println("**** WARNING: " + message);
98      return "<warn>";
99    }
100 
101   //////////////// Basic manipulation Routines ////////////////
102 
103   // The following are used throughout the code.
104 
105   /** Like Common Lisp first; car of a SilkPair, or null for anything else. **/
106   public static Object first(Object x) {
107     return (x instanceof SilkPair) ? ((SilkPair)x).first : null; 
108   }
109 
110   /** Like Common Lisp rest; car of a SilkPair, or null for anything else. **/
111   public static Object rest(Object x) {
112     return (x instanceof SilkPair) ? ((SilkPair)x).rest : null; 
113   }
114 
115   /** Like Common Lisp (setf (first ... **/
116   public static Object setFirst(Object x, Object y) {
117     return (x instanceof SilkPair) ? ((SilkPair)x).first = y 
118       : error("Attempt to set-car of a non-SilkPair:" + stringify(x));
119   }
120 
121   /** Like Common Lisp (setf (rest ... **/
122   public static Object setRest(Object x, Object y) {
123     return (x instanceof SilkPair) ? ((SilkPair)x).rest = y 
124       : error("Attempt to set-cdr of a non-SilkPair:" + stringify(x));
125   }
126 
127   /** Like Common Lisp second. **/
128   public static Object second(Object x) {
129     return first(rest(x));
130   }
131 
132   /** Like Common Lisp third. **/
133   public static Object third(Object x) {
134     return first(rest(rest(x)));
135   }
136 
137   /** Creates a two element list. **/
138   public static SilkPair list(Object a, Object b) {
139     return new SilkPair(a, new SilkPair(b, null));
140   }
141 
142   /** Creates a one element list. **/
143   public static SilkPair list(Object a) {
144     return new SilkPair(a, null);
145   }
146 
147   /** listStar(args) is like Common Lisp (apply #'list* args) **/
148   public static Object listStar(Object args) {
149     if (rest(args) == null) return first(args);
150     else return cons(first(args), listStar(rest(args)));
151   }
152 
153   /** cons(x, y) is the same as new SilkPair(x, y). **/
154   public static SilkPair cons(Object a, Object b) {
155     return new SilkPair(a, b);
156   }
157 
158   /** Reverse the elements of a list. **/
159   public static Object reverse(Object x) {
160     Object result = null;
161     while (x instanceof SilkPair) {
162       result = cons(first(x), result);
163       x = rest(x);
164     }
165     return result;
166   }
167 
168   /** Check if two objects are equal. **/
169   public static boolean equal(Object x, Object y) {
170     if (x == null || y == null) {
171       return x == y;
172     } else if (x instanceof char[]) {
173       if (!(y instanceof char[])) return false;
174       char[] xc = (char[])x, yc = (char[])y;
175       if (xc.length != yc.length) return false;
176       for (int i = xc.length - 1; i >= 0; i--) {
177   if (xc[i] != yc[i]) return false;
178       }
179       return true;
180     } else if (x instanceof Object[]) {
181       if (!(y instanceof Object[])) return false;
182       Object[] xo = (Object[])x, yo = (Object[])y;
183       if (xo.length != yo.length) return false;
184       for (int i = xo.length - 1; i >= 0; i--) {
185   if (!equal(xo[i],yo[i])) return false;
186       }
187       return true;
188     } else {
189       return x.equals(y);
190     }
191   }
192 
193   /** Check if two objects are == or are equal numbers or characters. **/
194   public static boolean eqv(Object x, Object y) {
195     return x == y 
196       || (x instanceof Double && x.equals(y))
197       || (x instanceof Character && x.equals(y));
198   }
199 
200   /** The length of a list, or zero for a non-list. **/
201   public static int length(Object x) {
202     int len = 0;
203     while (x instanceof SilkPair) {
204       len++;
205       x = ((SilkPair)x).rest;
206     }
207     return len;
208   }
209 
210   /** Convert a list of characters to a SilkScheme string, which is a char[]. **/
211   public static char[] listToString(Object chars) {
212     char[] str = new char[length(chars)];
213     for (int i = 0; chars instanceof SilkPair; i++) {
214       str[i] = chr(first(chars));
215       chars = rest(chars);
216     }
217     return str;
218   }
219  
220   /** Convert a list of Objects to a SilkScheme vector, which is a Object[]. **/
221   public static Object[] listToVector(Object objs) {
222     Object[] vec = new Object[length(objs)];
223     for (int i = 0; objs instanceof SilkPair; i++) {
224       vec[i] = first(objs);
225       objs = rest(objs);
226     }
227     return vec;
228   }
229  
230   /** Write the object to a port.  If quoted is true, use "str" and #\c,
231    * otherwise use str and c. **/
232   public static Object write(Object x, PrintWriter port, boolean quoted) {
233     port.print(stringify(x, quoted)); 
234     port.flush();
235     return x;
236   }
237 
238   /** Convert a vector to a List. **/
239   public static SilkPair vectorToList(Object x) {
240     if (x instanceof Object[]) {
241       Object[] vec = (Object[])x;
242       SilkPair result = null;
243       for (int i = vec.length - 1; i >= 0; i--) 
244   result = cons(vec[i], result);
245       return result;
246     } else {
247       error("expected a vector, got: " + x);
248       return null;
249     }
250   }
251 
252   /** Convert a SilkScheme object to its printed representation, as
253    * a java String (not a SilkScheme string). If quoted is true, use "str" and #\c,
254    * otherwise use str and c. You need to pass in a StringBuffer that is used 
255    * to accumulate the results. (If the interface didn't work that way, the
256    * system would use lots of little internal StringBuffers.  But note that
257    * you can still call <tt>stringify(x)</tt> and a new StringBuffer will
258    * be created for you. **/
259 
260   static void stringify(Object x, boolean quoted, StringBuffer buf) { 
261     if (x == null) 
262       buf.append("()");
263     else if (x instanceof Double) {
264       double d = ((Double)x).doubleValue();
265       if (Math.round(d) == d) buf.append((long)d); else buf.append(d);
266     } else if (x instanceof Character) {
267       if (quoted) buf.append("#\\");
268       buf.append(x);
269     } else if (x instanceof SilkPair) {
270       ((SilkPair)x).stringifySilkPair(quoted, buf);
271     } else if (x instanceof char[]) {
272       char[] chars = (char[])x;
273       if (quoted) buf.append('"');
274       for (int i = 0; i < chars.length; i++) {
275   if (quoted && chars[i] == '"') buf.append('\\');
276   buf.append(chars[i]);
277       }
278       if (quoted) buf.append('"');
279     } else if (x instanceof Object[]) {
280   Object[] v = (Object[])x;
281   buf.append("#(");
282   for (int i=0; i<v.length; i++) {
283       stringify(v[i], quoted, buf);
284       if (i != v.length-1) buf.append(' ');
285   }
286   buf.append(')');
287     } else if (x == TRUE) {
288       buf.append("#t");
289     } else if (x == FALSE) {
290       buf.append("#f");
291     } else {
292       buf.append(x);
293     }
294   }
295 
296   /** Convert x to a Java String giving its external representation. 
297    * Strings and characters are quoted. **/
298   static String stringify(Object x) { return stringify(x, true); }
299 
300   /** Convert x to a Java String giving its external representation. 
301    * Strings and characters are quoted iff <tt>quoted</tt> is true.. **/
302   static String stringify(Object x, boolean quoted) { 
303     StringBuffer buf = new StringBuffer();
304     stringify(x, quoted, buf);
305     return buf.toString();
306   }
307 
308   /** For debugging purposes, prints output. **/
309   static Object p(Object x) {
310     System.out.println(stringify(x));
311     return x;
312   }
313 
314   /** For debugging purposes, prints output. **/
315   static Object p(String msg, Object x) {
316     System.out.println(msg + ": " + stringify(x));
317     return x;
318   }
319 }