From 1d18259d031a2bbbb6e99f883f26de1919bda511 Mon Sep 17 00:00:00 2001 From: bnewbold Date: Thu, 22 Jan 2009 02:17:29 -0500 Subject: journal entry, scm interface for sage math --- journal/19jan2009.html | 2 +- journal/21jan2009.html | 56 ++++++++ other/scm.py | 357 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 414 insertions(+), 1 deletion(-) create mode 100644 journal/21jan2009.html create mode 100644 other/scm.py diff --git a/journal/19jan2009.html b/journal/19jan2009.html index 270f527..01d6b98 100644 --- a/journal/19jan2009.html +++ b/journal/19jan2009.html @@ -42,7 +42,7 @@ For now, i'm actually going to switch over to the "scm" scheme distribution which is much simpler and get that going well with sage, then try MIT/GNU scheme again.

-(previous entry +(previous entry) diff --git a/journal/21jan2009.html b/journal/21jan2009.html new file mode 100644 index 0000000..d451c90 --- /dev/null +++ b/journal/21jan2009.html @@ -0,0 +1,56 @@ + + +bnewbold thesis + +

+Journal: Jan 21, 2009

+Bryan Newbold, bnewbold@mit.edu
+ +http://web.mit.edu/bnewbold/thesis/ +

+ + +Aha! Found the hook needed to disable error interrupt REPLs in mit-scheme: +

+(set! standard-error-hook (lambda (x) (begin (warn x) (cmdl-interrupt/abort-top-level))))
+
+For example: +
+1 ]=> (set! standard-error-hook (lambda (x) (begin (warn x) (cmdl-interrupt/abort-top-level))))
+
+;Value: #f
+
+1 ]=> (car 3)
+
+;Warning: The object 3, passed as the first argument to car, is not the correct type.
+;Quit!
+
+1 ]=> 
+
+This makes it much easier for sage to do subprocess interactions. I have a +half-working scm scheme interface and now a half-working mit-scheme interface; +files for both are in the other folder. I should have +a demo server running on SIPB's XVM service +tomorrow, maybe if I polish these interfaces I can package them up as optional +sage .spkgs. Most importantly, for now only put one S-expression in a scheme +notebook cell at a time. +

+ +Of course removing the error REPL loop of course takes away excellent +functionality from the interactive session... to me a vertically split edwin +session with a file *scheme* buffer on the top and REPL output on the bottom is +the best way to "do" scheme. +

+ +In other news I just learned the vim command I was missing: gq} +will rewrap the current paragraph to ~70 columns width; gq will do +the same to the current selection in visual mode. FINALLY. + +

+(previous entry) + + + + + diff --git a/other/scm.py b/other/scm.py new file mode 100644 index 0000000..0152f9f --- /dev/null +++ b/other/scm.py @@ -0,0 +1,357 @@ +r"""nodoctest [[remove the nodoctest, so doctests will run]] +Interface Template + +[[Describe the math software you are interfacing with here.]] + +[[Replace this by something relevant to your system.]] + Type \code{gp.[tab]} for a list of all the functions available + from your Gp install. Type \code{gp.[tab]?} for Gp's + help about a given function. Type \code{gp(...)} to create + a new Gp object, and \code{gp.eval(...)} to run a string + using Gp (and get the result back as a string). + + +EXAMPLES: + +[[Go through a standard tutorial for your software package +and do it via your SAGE interface.]] + +AUTHORS: + -- William Stein (template) +""" + +########################################################################## +# +# Copyright (C) 2006 William Stein +# +# Distributed under the terms of the GNU General Public License (GPL) +# +# http://www.gnu.org/licenses/ +# +########################################################################## + +from __future__ import with_statement +from expect import Expect, ExpectElement, ExpectFunction, FunctionElement, gc_disabled +from sage.misc.misc import verbose + +class SCM(Expect): + """ + [[Some basic help about your system. This is what + will be displayed when somebody write scm?.]] + """ + def __init__(self, + maxread=100000, script_subdirectory=None, + logfile=None, + server=None, + server_tmpdir=None): + Expect.__init__(self, + + # The capitalized version of this is used for printing. + name = 'SCM Scheme', + + # This is regexp of the input prompt. If you can change + # it to be very obfuscated that would be better. Even + # better is to use sequence numbers. + prompt = '> ', + + # This is the command that starts up your program + command = "scm -i", + + maxread = maxread, + + server=server, + server_tmpdir=server_tmpdir, + + script_subdirectory = script_subdirectory, + + # If this is true, then whenever the user presses Control-C to + # interrupt a calculation, the whole interface is restarted. + restart_on_ctrlc = True, + + # If true, print out a message when starting + # up the command when you first send a command + # to this interface. + verbose_start = True, + + logfile=logfile, + + # If an input is longer than this number of characters, then + # try to switch to outputing to a file. + eval_using_file_cutoff=1024) + + self.__seq = 0 + + def chdir(self, dir): + raise NotImplemented + + def eval(self, code, strip=True, synchronize=False, **kwds): + """ + For SCM, don't listen for prompt except for the last line + INPUT: + code -- text to evaluate + strip -- bool; whether to strip output prompts, etc. + (ignored in the base class). + **kwds -- All other arguments are passed onto the _eval_line method. + An often useful example is reformat=False. + """ + if synchronize: + try: + self._synchronize() + except AttributeError: + pass + + if strip: + try: + code = self._strip_prompt(code) + except AttributeError: + pass + + if not isinstance(code, basestring): + raise TypeError, 'input code must be a string.' + + #Remove extra whitespace + code = code.strip() + + try: + with gc_disabled(): + return self._eval_line(code, **kwds) + except KeyboardInterrupt: + # DO NOT CATCH KeyboardInterrupt, as it is being caught + # by _eval_line + # In particular, do NOT call self._keyboard_interrupt() + raise + except TypeError, s: + raise TypeError, 'error evaluating "%s":\n%s'%(code,s) + + def _repr_(self): + return 'scm Scheme Interpreter' + + def __reduce__(self): + return reduce_load_scm, tuple([]) + + def __getattr__(self, attrname): + if attrname[:1] == "_": + raise AttributeError + return SCMFunction(self, attrname) + + def _quit_string(self): + return '(quite)' + + def _read_in_file_command(self, filename): + raise NotImplementedError + + def trait_names(self): + ## [[implement giving a list of all functions and identifiers in the system]] + raise NotImplementedError + + def read(self, filename): + # [[implement loading of the contents of filename into the system]] + raise NotImplementedError + + + def kill(self, var): + # [[send code that kills the variable with given name in the system.]] + pass + + def console(self): + # run the console command (defined below). + scm_console() + + def version(self): + # run the version command (defined below) + pass + + def _object_class(self): + return SCMElement + + def _left_list_delim(self): + raise NotImplementedError + + def _right_list_delim(self): + raise NotImplementedError + + def _assign_symbol(self): + raise NotImplementedError + + def _true_symbol(self): + # return the string rep of truth, i.e., what the system outputs + # when you type 1==1. + return '#t' + + def _false_symbol(self): + # return the string rep of truth, i.e., what the system outputs + # when you type 1==2. + return '#f' + + def _equality_symbol(self): + # return the symbol for checking equality, e.g., == or eq. + raise NotImplementedError + + def help(self, command): + # return help on a given command. + raise NotImplementedError + + def set(self, var, value): + """ + Set the variable var to the given value. + """ + cmd = '(define %s %s)'%(var, value) + self.eval(cmd) + + def get(self, var): + """ + Get the value of the variable var. + """ + cmd = '%s'%var + return self.eval(var) + + def function_call(self, function, args=[], kwds={}): + """ + EXAMPLES: + sage: maxima.quad_qags(x, x, 0, 1, epsrel=1e-4) + [0.5,5.5511151231257...E-15,21,0] + sage: maxima.function_call('quad_qags', [x, x, 0, 1], {'epsrel':'1e-4'}) + [0.5,5.5511151231257...E-15,21,0] + """ + if function == '': + raise ValueError, "function name must be nonempty" + if function[:2] == "__": + raise AttributeError + if not isinstance(args, list): + args = [args] + for i in range(len(args)): + if not isinstance(args[i], ExpectElement): + args[i] = self.new(args[i]) + for key, value in kwds.iteritems(): + kwds[key] = self.new(value) + + return self.new("(%s %s)"%(function, " ".join([s.name() for s in args]+ + ['%s'%(key,value.name()) for key, value in kwds.items()]))) + + +class SCMElement(ExpectElement): + """ + Describe elements of your system here. + """ + def trait_names(self): + # This is if your system doesn't really have types. If you have types + # this function should only return the relevant methods that take self + # as their first argument. + return self.parent().trait_names() + + def __cmp__(self, other): + P = self.parent() + if P.eval("(eq? %s %s)"%(self.name(), other.name())) == P._true_symbol(): + return 0 + elif P.eval("(< %s %s)"%(self.name(), other.name())) == P._true_symbol(): + return -1 + elif P.eval("(> %s %s)"%(self.name(), other.name())) == P._true_symbol(): + return 1 + + # everything is supposed to be comparable in Python, so we define + # the comparison thus when no comparable in interfaced system. + if (hash(self) < hash(other)): + return -1 + else: + return 1 + + def hasattr(self, attrname): + """ + Scheme things don't have attributes (unless SOS...) + """ + raise NotImplementedError + + def attribute(self, attrname): + """ + Scheme things don't have attributes (unless SOS...) + """ + raise NotImplementedError + + def __getitem__(self, n): + """ + Scheme things don't have attributes (unless SOS...) + """ + raise NotImplementedError + + def bool(self): + P = self.parent() + t = P._true_symbol() + cmd = '%s'%self._name + return P.eval(cmd) == t + + def __nonzero__(self): + """ + EXAMPLES: + sage: bool(scm('#t')) + True + sage: bool(scm('#f')) + False + """ + P = self.parent() + t = P._true_symbol() + cmd = '(zero? %s)'%self._name + return P.eval(cmd) == t + + def _operation(self, operation, right): + P = self._check_valid() + try: + return P.new('(%s %s %s)'%(operation, self._name, right._name)) + except Exception, msg: + raise TypeError, msg + + def __pow__(self, n): + """ + EXAMPLES: + sage: a = maxima('2') + sage: a^(3/4) + 2^(3/4) + """ + P = self._check_valid() + if not hasattr(n, 'parent') or P is not n.parent(): + n = P(n) + return self._operation("expt", n) + + +class SCMFunctionElement(FunctionElement): + def _sage_doc_(self): + M = self._obj.parent() + return M.help(self._name) + + +class SCMFunction(ExpectFunction): + def _sage_doc_(self): + M = self._parent + return M.help(self._name) + + +def is_SCMElement(x): + return isinstance(x, SCMElement) + +# An instance +scm = SCM() + +def reduce_load_SCM(): + return scm + +import os +def scm_console(): + # This will only spawn local processes + os.system('scm') + + +def scm_version(): + """ + EXAMPLES: + sage: scm.version() + scm 5e5 + Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + SCM may be distributed under the terms of the GNU General Public Licence; + certain other uses are permitted as well. For details, see the file `COPYING', + which is included in the SCM distribution. + There is no warranty, to the extent permitted by law. + This executable was loaded from "/usr/local/bin/scm" + """ + import subprocess + p = subprocess.Popen('scm --version', shell=True, stdin=subprocess.PIPE, + stdout = subprocess.PIPE, stderr=subprocess.PIPE) + return AsciiArtString(p.stdout.read()) -- cgit v1.2.3