#7377: Symbolic Ring to Maxima via EclObject
-----------------------------------------------------------------------+----
   Reporter:  nbruin                                                   |       
Owner:  nbruin      
       Type:  enhancement                                              |      
Status:  needs_work  
   Priority:  major                                                    |   
Milestone:  sage-feature
  Component:  symbolics                                                |    
Keywords:              
     Author:  Nils Bruin, Jean-Pierre Flori                            |    
Upstream:  N/A         
   Reviewer:  Jean-Pierre Flori, François Bissey, Karl-Dieter Crisman  |      
Merged:              
Work_issues:                                                           |  
-----------------------------------------------------------------------+----

Comment(by nbruin):

 Something blows up rather badly here. The {{{MAXIMA>>}}} prompt indicates
 that you're dropped into to ECL debugger [the default behaviour of LISPs
 is to drop you into a debugger when an uncaught condition arises]. Ecllib
 tries to avoid this by executing any LISP code inside the LISP equivalent
 of try/except (being HANDLER-CASE). You can get tracebacks and code to see
 what is happening from the debugger (try ":h" to get help about the ECL
 debugger)

 {{{
 ----------------------------------------------------------------------
 | Sage Version 4.6.1, Release Date: 2011-01-11                       |
 | Type notebook() for the GUI, and license() for information.        |
 ----------------------------------------------------------------------
 Loading Sage library. Current Mercurial branch is: dev
 sage: elliptic_e(arccoth(1), x^2*e)
 The number 1 isn't in the domain of acoth
  -- an error. To debug this try: debugmode(true);
 }}}
 This is Maxima printing something on the STDOUT. We should be catching
 this before it gets printed! In other words, find which routine in maxima
 prints this and monkey-patch it to raise an error *before* printing this.
 Apparently, maxima does raise an error after printing this, which normally
 gets caught on maxima's top level. But since we decapitated maxima, we're
 getting that now, and that is where the next thing goes wrong:
 {{{
 Error in format: Unknown format directive.
   The number ~:M isn't in the domain of ~A
                ^
 while processing indirect format string:
   ~?
    ^
 No restarts available.

 Broken at LAMBDA.
 MAXIMA>> :b

 Backtrace:
   > LAMBDA
   > print-object
   > common-lisp-user::sage-safe-apply

 MAXIMA>> :le

 (LAMBDA (CONDITION STREAM)
   (FORMAT STREAM
           "~?"
           (SIMPLE-CONDITION-FORMAT-CONTROL CONDITION)
           (SIMPLE-CONDITION-FORMAT-ARGUMENTS CONDITION)))
 }}}
 so a FORMAT statement is failing here. Apparently "Condition" objects
 (roughly "exception" objects in python) can have a format string and items
 hanging off them. FORMAT is LISPs "printf", but with a much more baroque
 set of options. FORMAT format specifiers have been rumoured to be Turing
 complete. Let's look at the parameters:
 {{{
 MAXIMA>> (SIMPLE-CONDITION-FORMAT-CONTROL CONDITION)

 "The number ~:M isn't in the domain of ~A"
 MAXIMA>> (SIMPLE-CONDITION-FORMAT-ARGUMENTS CONDITION)

 NIL
 }}}
 So the "~:M" is probably a Maxima extension to format which is not
 accessible at the point where we are trying it. The fact that there are no
 arguments also indicates that Maxima might be forming a condition object
 that is not fit for general consumption.

 Let's see where this error really arose by stepping further up in the
 backtrace:
 {{{
 MAXIMA>> :p

 Broken at PRINT-OBJECT.
 MAXIMA>> :le

 (SI:LAMBDA-BLOCK PRINT-OBJECT
                  (SI::X STREAM)
                  (DECLARE (TYPE SIMPLE-CONDITION SI::X)
                   (SI::NO-CHECK-TYPE SI::X))
                  (IF *PRINT-ESCAPE*
                      (CALL-NEXT-METHOD)
                      ((LAMBDA (CONDITION STREAM)
                         (FORMAT STREAM
                                 "~?"
                                 (SIMPLE-CONDITION-FORMAT-CONTROL
 CONDITION)
                                 (SIMPLE-CONDITION-FORMAT-ARGUMENTS
 CONDITION)))
                       SI::X STREAM)))
 {{{
 So this is LISP trying to print a CONDITION object. Apparently, Maxima has
 created a CONDITION object that doesn't allow this method to work. This
 could be a bug in ECL or it could be Maxima being non-compliant.
 }}}
 MAXIMA>> :p

 Broken at COMMON-LISP-USER::SAGE-SAFE-APPLY.
 MAXIMA>> :le

 (SI:LAMBDA-BLOCK COMMON-LISP-USER::SAGE-SAFE-APPLY
                  (COMMON-LISP-USER::FUNC COMMON-LISP-USER::ARGS)
                  (DECLARE (SI::C-GLOBAL))
                  (HANDLER-CASE
                   (VALUES
                    (APPLY COMMON-LISP-USER::FUNC COMMON-LISP-USER::ARGS))
                   (SERIOUS-CONDITION (COMMON-LISP-USER::CND)
                    (VALUES NIL (PRINC-TO-STRING COMMON-LISP-USER::CND)))))
 MAXIMA>> COMMON-LISP-USER::FUNC

 MAXIMA-EVAL
 MAXIMA>> COMMON-LISP-USER::ARGS

 ((MEVAL* '((MSETQ) $SAGE1 (($ELLIPTIC_E) ((%ACOTH) 1) ((MTIMES) ((MEXPT)
 $X 2) ((%EXP) 1))))))
 }}}
 Finally we're at the ecllib level. SAGE-SAFE-APPLY is the way ecllib tries
 to execute LISP code
 As you can see, the arguments here indicate that this is the original call
 we started with, translated to maxima (well, the underlying LISP
 representation of maxima).
 We know this raised an error, which gets processed by the HANDLER-CASE
 /SERIOUS-CONDITION. The PRINC-TO-STRING tries to make a string rendition
 of the CONDITION object, which fails for the reasons we have seen above.

 So, the most direct way to solve the problem is to monkey-patch Maxima to
 raise an acceptable error *instead* of printing a message and sending a
 CONDITION object that crashes PRINC (which should be a near-universal
 printing routine). This should be relatively straightforward, because that
 Maxima routine already produces an acceptable string. Simply produce that
 string but instead of printing it, do an (ERROR string) or whatever is
 acceptable (the way "retrieve" gets monkey-patched in maximalib is already
 an example of that).

 It does make me a bit pessimistic, though: Maxima improves some of its
 error reporting and in the process immediately blows up our error
 catching! This looks like something that is going to happen every time
 Maxima changes something. It's bad enough when dealing with the pexpect
 interface, but in this case we're basically using an unsupported and
 undocumented API! I know Robert Dodier is definitely sympathetic to making
 Maxima usable as a library, so perhaps if we can get reasonable
 functionality, he might be willing to take into account the required hooks
 when changing Maxima.

-- 
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/7377#comment:36>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica, 
and MATLAB

-- 
You received this message because you are subscribed to the Google Groups 
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/sage-trac?hl=en.

Reply via email to