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