aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbnewbold <bnewbold@eta.mit.edu>2009-01-22 02:17:29 -0500
committerbnewbold <bnewbold@eta.mit.edu>2009-01-22 02:17:29 -0500
commit1d18259d031a2bbbb6e99f883f26de1919bda511 (patch)
tree67ec4f83b0071415e00468835164358b0f46a627
parent694370db05356b12c931a9bb4baa65a1dc0cfa16 (diff)
download8thesis-1d18259d031a2bbbb6e99f883f26de1919bda511.tar.gz
8thesis-1d18259d031a2bbbb6e99f883f26de1919bda511.zip
journal entry, scm interface for sage math
-rw-r--r--journal/19jan2009.html2
-rw-r--r--journal/21jan2009.html56
-rw-r--r--other/scm.py357
3 files changed, 414 insertions, 1 deletions
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.
<br /><br />
-<a href="16jan2009.html"><i>(previous entry</i></a>
+<a href="16jan2009.html"><i>(previous entry)</i></a>
<!-- ================================================================ -->
<!-- ================================================================ -->
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 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head><title>bnewbold thesis</title></head>
+<body style="margin: 25px; font-family: helvetica;">
+<h1 style="border-bottom: 2px solid;">
+Journal: Jan 21, 2009</h1>
+<i>Bryan Newbold, <a href="mailto:bnewbold@mit.edu">bnewbold@mit.edu</a></i><br />
+<i><a href="http://web.mit.edu/bnewbold/thesis/">
+http://web.mit.edu/bnewbold/thesis/</a></i>
+<br /><p />
+<!-- ================================================================ -->
+<!-- ================================================================ -->
+Aha! Found the hook needed to disable error interrupt REPLs in mit-scheme:
+<pre style="margin:20px; border-left: solid grey 3px; background-color:lightgrey;padding:5px;width:750px;">
+(set! standard-error-hook (lambda (x) (begin (warn x) (cmdl-interrupt/abort-top-level))))
+</pre>
+For example:
+<pre style="margin:20px; border-left: solid grey 3px; background-color:lightgrey;padding:5px;width:750px;">
+1 ]=&gt; (set! standard-error-hook (lambda (x) (begin (warn x) (cmdl-interrupt/abort-top-level))))
+
+;Value: #f
+
+1 ]=&gt; (car 3)
+
+;Warning: The object 3, passed as the first argument to car, is not the correct type.
+;Quit!
+
+1 ]=&gt;
+</pre>
+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 <a href="../other/">other</a> folder. I should have
+a demo server running on <a href="http://xvm.mit.edu">SIPB's XVM service</a>
+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.
+<p />
+
+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.
+<p />
+
+In other news I just learned the vim command I was missing: <code>gq}</code>
+will rewrap the current paragraph to ~70 columns width; <code>gq</code> will do
+the same to the current selection in visual mode. FINALLY.
+
+<br /><br />
+<a href="19jan2009.html"><i>(previous entry)</i></a>
+
+<!-- ================================================================ -->
+<!-- ================================================================ -->
+</body>
+</html>
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 <wstein@gmail.com>
+#
+# 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())