1 /**************************************************************************
2  * Copyright (C) 2011 Ted Kosan                                           *
3  *                                                                        *
4  * Redistribution and use in source and binary forms, with or without     *
5  * modification, are permitted provided that the following conditions are *
6  * met:                                                                   *
7  *                                                                        *
8  *     * Redistributions of source code must retain the relevant          *
9  *       copyright notice, this list of conditions and the following      *
10  *       disclaimer.                                                      *
11  *     * Redistributions in binary form must reproduce the above          *
12  *       copyright notice, this list of conditions and the following      *
13  *       disclaimer in the documentation and/or other materials provided  *
14  *       with the distribution.                                           *
15  *                                                                        *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS    *
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT      *
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS      *
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE         *
20  * COPYRIGHT OWNERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,   *
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,   *
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS  *
23  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR  *
25  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF     *
26  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH   *
27  * DAMAGE.                                                                *
28  *************************************************************************/
29 package org.mathpiper.mpreduce;
30 
31 import com.google.gwt.core.client.EntryPoint;
32 import com.google.gwt.core.client.GWT;
33 import com.google.gwt.core.client.JavaScriptObject;
34 import com.google.gwt.core.client.Scheduler;
35 import com.google.gwt.core.client.Scheduler.RepeatingCommand;
36 import java.io.IOException;
37 
38 
39 import org.mathpiper.mpreduce.io.streams.InputStream;
40 import java.util.ArrayList;
41 import java.util.HashMap;
42 import java.util.Iterator;
43 import org.mathpiper.mpreduce.datatypes.Cons;
44 import org.mathpiper.mpreduce.datatypes.LispString;
45 import org.mathpiper.mpreduce.functions.functionwithenvironment.Bytecode;
46 import org.mathpiper.mpreduce.functions.lisp.LispFunction;
47 import org.mathpiper.mpreduce.io.streams.LispOutputString;
48 import org.mathpiper.mpreduce.io.streams.LispStream;
49 import org.mathpiper.mpreduce.numbers.LispSmallInteger;
50 import org.mathpiper.mpreduce.packagedatastore.PDS;
51 import org.mathpiper.mpreduce.packagedatastore.PDSInputStream;
52 import org.mathpiper.mpreduce.special.SpecialFunction;
53 import org.mathpiper.mpreduce.symbols.Symbol;
54 import org.mathpiper.mpreduce.zip.GZIPInputStream;
55 
56 public class Interpreter implements EntryPoint {
57 
58     Jlisp jlisp;
59     private static Interpreter InterpreterInstance = null;
60     private String startMessage;
61     private String prompt;
62     private String sendString = null;
63     InputStream in;
64     //Lisp out, my in.
65     LispStream out;
66 
Interpreter()67     public Interpreter() {
68 
69         InterpreterInstance = this;
70 
71     }//end constructor.
72 
initialize()73     public String initialize() {
74 
75         String result = "";
76 
77         jlisp = new Jlisp();
78 
79         try {
80 
81             in = new InterpreterInputStream(this);
82 
83             out = new LispOutputString();
84 
85             final String[] args = new String[0];
86 
87             jlisp.startup(args, in, out);
88 
89             jlisp.initialize();
90 
91             result = evaluate("off int; on errcont;");
92 
93 
94         } catch (Throwable t) {
95             t.printStackTrace();
96 
97             result = t.getMessage();
98 
99         } finally {
100             return result;
101         }
102     }
103 
getStartMessage()104     public String getStartMessage() {
105         return startMessage;
106     }//end method.
107 
evaluate(String send)108     public String evaluate(String send) {
109 
110         send = send.trim();
111 
112         if (send.equals("")) {
113             return ("No Input Sumbitted.");
114         }
115 
116         while (send.endsWith(";;")) {
117             send = send.substring(0, send.length() - 1);
118         }
119 
120         if (!send.endsWith(";") && !send.endsWith("$")) {
121             send = send + ";";
122         }
123 
124         send = send + "end;";
125 
126 
127         try {
128 
129             sendString = send;
130 
131             in.close();
132 
133             jlisp.evaluate();
134 
135         } catch (Throwable t) {
136             out.println();
137             out.println(t.getMessage());
138         } finally {
139             String result;
140 
141             out.flush();
142 
143             result = out.toString();
144 
145             out.close();
146 
147             return result;
148         }
149 
150     }//end evaluate.
151 
interruptEvaluation()152     public void interruptEvaluation() {
153         try {
154 
155             jlisp.interruptEvaluation = true;
156 
157         } catch (Throwable e) {
158             //Each excpetion.
159         }
160     }
161 
162     //Lisp in, my out.
163     class InterpreterInputStream extends InputStream {
164 
165         private ArrayList expressions = new ArrayList();
166         private Iterator expressionsIterator;
167         private Interpreter interpreter;
168         public int pos, len;
169         private String result;
170 
InterpreterInputStream(Interpreter interpreter)171         InterpreterInputStream(Interpreter interpreter) {
172             this.interpreter = interpreter;
173 
174             sendString = null;
175         }
176 
available()177         public int available() {
178             if (sendString != null) {
179                 return 1;
180             } else {
181                 return 0;
182             }
183         }
184 
close()185         public void close() {
186             pos = 0;
187             len = sendString.length();
188         }
189 
markSupported()190         public boolean markSupported() {
191             return false;
192         }
193 
read()194         public int read() {
195 
196             if (pos == len) {
197                 sendString = null;
198                 return (int) -1;
199             } else {
200                 int i = (int) sendString.charAt(pos++);
201                 return i;
202             }
203         }
204     }//end method.
205 
test()206     private String test() {
207         String result = "";
208 
209         try {
210 
211             //result = evaluate("2+2");
212 
213             result = evaluate("(X-Y)^100");
214             System.out.println(result);
215 
216             result = evaluate("load ineq");
217             System.out.println(result);
218 
219             result = evaluate("ineq_solve((x - 1)/(x + 2) > 0,x);");
220             System.out.println(result);
221 
222         } catch (Throwable t) {
223             System.out.println(t.getMessage());
224         }
225 
226         return result;
227 
228 
229 
230     }//end method.
231 
232 //---------
casVersion()233     public static String casVersion() {
234         return "MPReduceJS version " + InterpreterInstance.version();
235     }
236 
exportCasVersionMethod()237     public static native void exportCasVersionMethod() /*-{
238     $wnd.casVersion = function(){
239     return @org.mathpiper.mpreduce.Interpreter::casVersion()();
240     }
241     }-*/;
242 
243 //---------
casEvaluate(String send)244     public static String casEvaluate(String send) {
245         return InterpreterInstance.evaluate(send);
246     }
247 
exportEvaluateMethod()248     public static native void exportEvaluateMethod() /*-{
249     $wnd.casEval = function(send){
250     return @org.mathpiper.mpreduce.Interpreter::casEvaluate(Ljava/lang/String;)(send);
251     }
252     }-*/;
253 
254 //---------
casInitialize()255     public static String casInitialize() {
256         String result = InterpreterInstance.initialize();
257 
258         callCasLoaded();
259 
260         return result;
261     }
262 
263 
264 //---------
callCasLoaded()265     public static native void callCasLoaded() /*-{
266     $wnd.casLoaded();
267     }-*/;
268     //---------
269     static JavaScriptObject callBackFunction = null;
270 
casLoadImage()271     public static void casLoadImage() {
272         try {
273 
274             Scheduler.get().scheduleIncremental(InterpreterInstance.getInitializationExecutor());
275 
276 
277         } catch (Exception e) {
278             e.printStackTrace();
279         }
280     }
281 
282 
callImageLoadedCallback()283     public static native void callImageLoadedCallback() /*-{
284     callBackFunction();
285     }-*/;
286 
287 //---------
288     @Override
onModuleLoad()289     public void onModuleLoad() {
290 
291         exportCasVersionMethod();
292 
293         exportEvaluateMethod();
294 
295         casLoadImage();
296 
297     }
298 
version()299     public static String version() {
300         return Jlisp.version;
301     }
302 
getInitializationExecutor()303     public RepeatingCommand getInitializationExecutor() {
304         RepeatingCommand repeatingCommand = new RepeatingCommand() {
305 
306             int counter = 0;
307             private int loopIndex = 1;
308 
309             public boolean execute() {
310 
311                 boolean returnValue = true;
312                 // For use while I am re-loading image and also to assist the
313                 // custom Lisp bytecoded stuff I build a table of all the functions
314                 // that I have built into this Lisp.
315                 //
316                 try {
317                     switch (loopIndex) {
318                         case 1:
319                             LispSmallInteger.preAllocate();  // some small integers treated specially.
320                             loopIndex++;
321                             break;
322                         case 2:
323                             Jlisp.builtinFunctions = new HashMap();
324                             Jlisp.builtinSpecials = new HashMap();
325                             for (int i = 0; i < Jlisp.fns1.builtins.length; i++) {
326                                 ((LispFunction) Jlisp.fns1.builtins[i][1]).name =
327                                         (String) Jlisp.fns1.builtins[i][0];
328                                 Jlisp.builtinFunctions.put(Jlisp.fns1.builtins[i][0], Jlisp.fns1.builtins[i][1]);
329                             }
330                             loopIndex++;
331                             break;
332 
333                         case 3:
334                             for (int i = 0; i < Jlisp.fns2.builtins.length; i++) {
335                                 ((LispFunction) Jlisp.fns2.builtins[i][1]).name =
336                                         (String) Jlisp.fns2.builtins[i][0];
337                                 Jlisp.builtinFunctions.put(Jlisp.fns2.builtins[i][0], Jlisp.fns2.builtins[i][1]);
338                             }
339                             loopIndex++;
340                             break;
341                         case 4:
342                             for (int i = 0; i < Jlisp.fns3.builtins.length; i++) {
343                                 ((LispFunction) Jlisp.fns3.builtins[i][1]).name =
344                                         (String) Jlisp.fns3.builtins[i][0];
345                                 Jlisp.builtinFunctions.put(Jlisp.fns3.builtins[i][0], Jlisp.fns3.builtins[i][1]);
346                             }
347                             loopIndex++;
348                             break;
349                         case 5:
350                             for (int i = 0; i < Jlisp.mpreduceFunctions.builtins.length; i++) {
351                                 ((LispFunction) Jlisp.mpreduceFunctions.builtins[i][1]).name =
352                                         (String) Jlisp.mpreduceFunctions.builtins[i][0];
353                                 Jlisp.builtinFunctions.put(Jlisp.mpreduceFunctions.builtins[i][0], Jlisp.mpreduceFunctions.builtins[i][1]);
354                             }
355                             loopIndex++;
356                             break;
357 
358                         case 6:
359                             for (int i = 0; i < Jlisp.specfn.specials.length; i++) {
360                                 ((SpecialFunction) Jlisp.specfn.specials[i][1]).name =
361                                         (String) Jlisp.specfn.specials[i][0];
362                                 Jlisp.builtinSpecials.put(Jlisp.specfn.specials[i][0], Jlisp.specfn.specials[i][1]);
363                             }
364                             loopIndex++;
365                             break;
366                         case 7:
367                             Bytecode.setupBuiltins();
368 
369                             loopIndex++;
370                             break;
371                         case 8:
372                             loadImageSetup();
373 
374                             loopIndex++;
375                             break;
376                         case 9:
377                             if (Jlisp.image.execute() == false) {
378                                 loopIndex++;
379                             }
380                             break;
381                         case 10:
382                             // The next stage is either to create an initial Lisp heap or to
383                             // re-load one that had been saved from a previous session. Things are
384                             // made MUCH more complicated here because a running Lisp can (under program
385                             // control) get itself restarted either in cold or warm-start mode.
386 
387                             PDSInputStream ii = null;
388                             // I will re-load from the first checkpoint file in the list that has
389                             // a HeapImage stored in it.
390 
391                             try {
392                                 ii = new PDSInputStream(Jlisp.image, "HeapImage");
393                             } catch (IOException e) {
394                                 e.printStackTrace();
395                             }
396 
397 
398                             try {
399                                 if (ii == null) {
400                                     throw new IOException("No valid checkpoint file found");
401                                 }
402 
403 
404                                 gzip = new GZIPInputStream(ii);
405 
406 
407 
408                                 Symbol.symbolCount = Cons.consCount = LispString.stringCount = 0;
409 
410                                         Jlisp.idump = gzip;
411                                         LispReader.getInstance().preRestore();
412 
413 
414                             } catch (Exception e) {
415                                 throw e;
416                             }
417 
418                             loopIndex++;
419                             break;
420                         case 11:
421                             if(LispReader.getInstance().incrementalRestore() == false)
422                             {
423                                 loopIndex++;
424                             }
425                             break;
426                         case 12:
427                             if (LispReader.getInstance().execute() == false) {
428                                 loopIndex++;
429                             }
430                             break;
431                         default:
432                             if (GWT.isClient()) {
433                                 casInitialize();
434                             } else {
435                                 initialize();
436                             }
437 
438                             returnValue = false;
439 
440                             break;
441 
442                     }//end switch.
443                 } catch (Exception e) {
444                     e.printStackTrace();
445                 }
446 
447                 return returnValue;
448 
449             }//end execute
450         };
451 
452         return repeatingCommand;
453     }//end method.
454 
loadImageSetup()455     private void loadImageSetup() throws Exception {
456 
457 
458 
459 //Initialize builtin functions code was here.
460 
461         // I may need to display diagnostics before I have finshed setting up
462         // streams etc in their proper final form, so I arrange a provisional
463         // setting that directs early messages to the terminal.
464         //lispIO = lispErr = new LispOutputStream();
465 
466         Jlisp.lit[Lit.std_output] = Jlisp.lit[Lit.tr_output] =
467                 Jlisp.lit[Lit.err_output] = Jlisp.lit[Lit.std_input] =
468                 Jlisp.lit[Lit.terminal_io] = Jlisp.lit[Lit.debug_io] =
469                 Jlisp.lit[Lit.query_io] = Symbol.intern("temp-stream");
470 
471         Jlisp.standardStreams();
472 
473         Jlisp.image = null;
474 
475         InputStream is = new ReduceImageInputStream();
476 
477         if (is != null) {
478             Jlisp.image = new PDS(is);
479         } else {
480             throw new Exception("Problem loading image.");
481         }
482 
483 
484 
485 
486     }
487 
getPDSFunctionEnteries()488     private String getPDSFunctionEnteries() {
489         String result;
490         try {
491             Jlisp.image.print();
492         } catch (Exception e) {
493             e.printStackTrace();
494         } finally {
495             out.flush();
496             result = out.toString();
497             out.close();
498             return result;
499         }
500     }//end method.
501     GZIPInputStream gzip = null;
502 
main(String[] args)503     public static void main(String[] args) {
504 
505         Interpreter mpreduce = new Interpreter();
506 
507         try {
508 
509             RepeatingCommand builtinFunctionExecutor = mpreduce.getInitializationExecutor();
510             while (builtinFunctionExecutor.execute() == true) {
511             }
512 
513 
514 
515             mpreduce.test();
516 
517 
518             //Uncomment the following line to list the compiled functions that are in the package data store.
519             //System.out.println(mpreduce.getPDSFunctionEnteries());
520 
521 
522 
523             if (mpreduce.gzip != null) {
524 
525                 mpreduce.gzip.close();
526 
527             }
528         } catch (Throwable t) {
529             t.printStackTrace();
530         }
531 
532 
533 
534 
535 
536         /*String result = "";
537 
538         try {
539 
540         result = mpreduce.evaluate("off nat;");
541         System.out.println(result + "\n");
542 
543         result = mpreduce.evaluate("x^2;");
544         System.out.println(result + "\n");
545 
546         result = mpreduce.evaluate("(X-Y)^100;");
547         System.out.println(result + "\n");
548 
549 
550         result = mpreduce.evaluate("2 + 2;");
551         System.out.println(result + "\n");
552 
553 
554         result = mpreduce.evaluate("Factorize(100);");
555         System.out.println(result + "\n");
556 
557         } catch (Throwable t) {
558         t.printStackTrace();
559         } finally {
560         }*/
561 
562 
563 
564 
565     }
566 }//end class.
567 
568