[pypy-svn] r37685 - pypy/dist/pypy/lang/js

fijal at codespeak.net fijal at codespeak.net
Wed Jan 31 20:29:26 CET 2007


Author: fijal
Date: Wed Jan 31 20:29:07 2007
New Revision: 37685

Modified:
   pypy/dist/pypy/lang/js/js_interactive.py
Log:
Make it a bit more robust (but untranslatable). We need to dispatch translation
process and use more decent stuff or not.


Modified: pypy/dist/pypy/lang/js/js_interactive.py
==============================================================================
--- pypy/dist/pypy/lang/js/js_interactive.py	(original)
+++ pypy/dist/pypy/lang/js/js_interactive.py	Wed Jan 31 20:29:07 2007
@@ -8,17 +8,33 @@
 import sys
 import getopt
 from pypy.lang.js.interpreter import *
-from pypy.lang.js.jsobj import W_Builtin, W_String
-
-help_message = '''
-Pypy Javascript Interpreter:
- -f filname Load a file
+from pypy.lang.js.jsobj import W_Builtin, W_String, ThrowException
+from pypy.lang.js import jsparser
+import os
+import cmd
+
+help_message = """
+PyPy's JavaScript Interpreter:
+ -f filename - Loads a file
  -n to not be interactive
  -h show this help message
-'''
+ -d jump to a pdb in case of failure
+"""
 
 interactive = True
 
+def setup_readline():
+    import readline
+    import os
+    histfile = os.path.join(os.environ["HOME"], ".jspypyhist")
+    try:
+        getattr(readline, "clear_history", lambda : None)()
+        readline.read_history_file(histfile)
+    except IOError:
+        pass
+    import atexit
+    atexit.register(readline.write_history_file, histfile)
+
 class Usage(Exception):
     def __init__(self, msg):
         self.msg = msg
@@ -36,12 +52,17 @@
     pdb.set_trace()
 
 def main(argv=None):
+    # XXX: note. This will not work when translated, because
+    # globals cannot be modified (ie. interactive is always True).
+    # so I'm adding support which will not be translated, probably
+    # for further consideration
     global interactive
+    debug = False
     if argv is None:
         argv = sys.argv
     try:
         try:
-            opts, args = getopt.getopt(argv[1:], "hnf:", ["help",])
+            opts, args = getopt.getopt(argv[1:], "hdnf:", ["help",])
         except getopt.error, msg:
             raise Usage(msg)
     
@@ -54,6 +75,8 @@
                 interactive = False
             if option in ("-h", "--help"):
                 raise Usage(help_message)
+            if option == '-d':
+                debug = True
     
     except Usage, err:
         print >> sys.stderr, sys.argv[0].split("/")[-1] + ": " + str(err.msg)
@@ -61,21 +84,75 @@
         return 2
     
     interp = Interpreter()
-    def quiter(ctx, args, this):
-        global interactive
-        interactive = False
+    #def quiter(ctx, args, this):
+    #    global interactive
+    #    interactive = False
         
-    interp.w_Global.Put('quit', W_Builtin(quiter))
+    #interp.w_Global.Put('quit', W_Builtin(quiter))
     interp.w_Global.Put('load', W_Builtin(loadjs))
     interp.w_Global.Put('trace', W_Builtin(tracejs))
     for filename in filenames:
         loadjs(interp.global_context, [W_String(filename)], None)
 
-    while interactive:
-        res = interp.run(load_source(raw_input("js-pypy> ")))
+    #while interactive:
+    #    res = interp.run(load_source(raw_input("js-pypy> ")))
+    #    if res is not None:
+    #        print res
+    if interactive:
+        MyCmd(interp, debug).cmdloop()
+
+class MyCmd(cmd.Cmd):
+    prompt = "js-pypy> "
+    def __init__(self, interp, debug):
+        cmd.Cmd.__init__(self)
+        setup_readline()
+        self.debug = debug
+        self.interp = interp
+        self.reset()
+
+    def reset(self):
+        self.prompt = self.__class__.prompt
+        self.lines = []
+        self.level = 0
+    
+    def default(self, line):
+        # let's count lines and continue till matching proper nr of {
+        # XXX: '{' will count as well
+        # we can avoid this by using our own's tokeniser, when we possess one
+        if line == 'EOF':
+            print "\nQuitting"
+            sys.exit()
+        opens = line.count('{')
+        closes = line.count('}')
+        self.level += opens - closes
+        self.lines.append(line)
+        if self.level > 0:
+            self.prompt = '     ... '
+            return
+        elif self.level < 0:
+            print "\nError!!! Too many closing braces"
+            self.level = 0
+            return
+        try:
+            try:
+                res = self.interp.run(load_source("\n".join(self.lines)))
+                # XXX we should catch more stuff here, like not implemented
+                # and such
+            except (jsparser.JsSyntaxError, ThrowException), e:
+                e_info = sys.exc_info()
+                if self.debug:
+                    import pdb
+                    pdb.post_mortem(e_info[2])
+                else:
+                    if isinstance(e, jsparser.JsSyntaxError):
+                        print "\nSyntax error!"
+                    elif isinstance(e, ThrowException):
+                        print "\nJS Exception thrown!"
+                return
+        finally:
+            self.reset()
         if res is not None:
-            print res
-
+            print res        
 
 if __name__ == "__main__":
     sys.exit(main())



More information about the Pypy-commit mailing list