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 MitScheme(Expect): """ [[Some basic help about your system. This is what will be displayed when somebody write mitscheme?.]] """ 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 = 'MIT/GNU 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 = '\d? \]=> ', # This is the command that starts up your program command = "/usr/local/scmutils/mit-scheme/bin/scheme --library /usr/local/scmutils/mit-scheme/lib/ --heap 12000 --band edwin-mechanics.com", #command = "mit-scheme", 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 self.eval('(set! standard-error-hook (lambda (x) (begin (warn x) (cmdl-interrupt/abort-top-level))))') def chdir(self, dir): raise NotImplemented def eval(self, code, strip=True, synchronize=False, **kwds): """ For Scheme, don't listen for prompt except for the last line Also, for MIT/GNU Scheme strip the ;Value: part of results 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._strip_prompt(self._eval_line(code.replace('\n',' ').replace('\r',' '), **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 _strip_prompt(self, code): return code.strip().replace(';Value: ','') def _repr_(self): return 'MIT/GNU Scheme Interpreter' def __reduce__(self): return reduce_load_mitscheme, tuple([]) def __getattr__(self, attrname): if attrname[:1] == "_": raise AttributeError return MitSchemeFunction(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). mitscheme_console() def version(self): # run the version command (defined below) pass def _object_class(self): return MitSchemeElement 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 MitSchemeElement(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(mitscheme('#t')) True sage: bool(mitscheme('#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 MitSchemeFunctionElement(FunctionElement): def _sage_doc_(self): M = self._obj.parent() return M.help(self._name) class MitSchemeFunction(ExpectFunction): def _sage_doc_(self): M = self._parent return M.help(self._name) def is_MitSchemeElement(x): return isinstance(x, MitSchemeElement) # An instance mitscheme = MitScheme() def reduce_load_MitScheme(): return mitscheme import os def mitscheme_console(): # This will only spawn local processes os.system('mitscheme') def mitscheme_version(): """ UGH hard to implement """ raise NotImplemented