Skip to content

Conversation

@cxzhong
Copy link
Contributor

@cxzhong cxzhong commented Nov 25, 2025

Most people use the Ubuntu or Debian system. But they do not provide a compatible fricas compiled by sbcl. So I fix it with gcl's fricas compatibility.
Fix #40569

📝 Checklist

  • The title is concise and informative.
  • The description explains in detail what this PR is about.
  • I have linked a relevant issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation and checked the documentation preview.

⌛ Dependencies

@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 25, 2025

@whoami730 I fixed it now. Can you help me test with sbcl fricas or sage's fricas?

@cxzhong cxzhong requested a review from dimpase November 25, 2025 06:33
@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 25, 2025

@cxzhong cxzhong changed the title Help the interface to be compatible with Ubuntu's fricas Make the interface to be compatible with Ubuntu's fricas package Nov 25, 2025
@dimpase
Copy link
Member

dimpase commented Nov 25, 2025

The PR title is misleading. It's clearly about GCL-compiled FriCAS, nothing to do with Ubuntu.
By the way, as usual, Ubuntu just uses the Debian package.

@cxzhong cxzhong changed the title Make the interface to be compatible with Ubuntu's fricas package Make the interface to be compatible with GCL-compiled fricas package Nov 25, 2025
@dimpase
Copy link
Member

dimpase commented Nov 25, 2025

There are much better ways to detect the underlying lisp, e.g. by looking at the output of fricas --version:

$ fricas --version
FriCAS 1.3.12
based on sbcl 2.5.8

I asked on https://groups.google.com/g/fricas-devel/c/a2aqmO58pA4/m/hDgfRlqVBgAJ whether there are better ways.

@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 25, 2025

The PR title is misleading. It's clearly about GCL-compiled FriCAS, nothing to do with Ubuntu. By the way, as usual, Ubuntu just uses the Debian package.

I just ask them. They said I should raise an issue in Debian community

@dimpase
Copy link
Member

dimpase commented Nov 25, 2025

To get the Lisp type, use Lisp!

sage: fricas.eval(")lisp (lisp-implementation-type)")
'\nValue = "SBCL"'

Copy link
Member

@dimpase dimpase left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

simplify Lisp detection

@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 25, 2025

To get the Lisp type, use Lisp!

sage: fricas.eval(")lisp (lisp-implementation-type)")
'\nValue = "SBCL"'

This is my implementation. and for gcl compiled fricas, it also should let the buffer clear before we get this

E.expect(self._prompt, timeout=0.1)
except pexpect.TIMEOUT:
break
E.sendline(')lisp (lisp-implementation-type)')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dimpase in this line I ask that lisp-implementation-type

Copy link
Contributor Author

@cxzhong cxzhong Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And there are other message like

this Function declaration sageprint : InputForm -> String has been added to workspace.

When the fricas running.
So we need to clean this.

Copy link
Member

@dimpase dimpase Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

# GCL-based FriCAS may output function declaration messages
# asynchronously after the prompt appears.

Maybe there is a FriCAS way to suppress these?
Please ask on the FriCAS forum, before starting to mess around with all these timeouts, which are really a weapon of last resort.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we need to ask this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is added when init fricas. But sbcl version of fricas does not output that.

E = self._expect
# First, consume any buffered output from previous commands
# to ensure we get a clean response to the lisp command
while True:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's going on in this loop then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do that for all other messages is clean. So we can run this list-umplementation-type safely

Updated command execution for FriCAS to use stdin for quitting instead of -eval to avoid misinterpretation by GCL-compiled FriCAS.
@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 25, 2025

@dimpase Can you help me test the new change can work on sbcl fricas?

Reduce timeout for subprocess call to fricas from 30 to 1 second.
Refactor subprocess call to avoid timeout handling.
@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 25, 2025

I have completed test, it is OK for sbcl version

@dimpase
Copy link
Member

dimpase commented Nov 25, 2025

I don't understand where the types messages are coming from. FRICAS_INIT_CODE is a variable which contains the init code for the Sage FriCAS session, which has )set messages type off.

If you see types printed it is a bug

@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 26, 2025

I think it is a problem caused in GCL's fricas

(sage-dev) zhongcx@LAPTOP-A6042VHQ:~/sage$ cat << 'EOF' | fricas -nosman 2>&1
> )set functions compile on
> )set message any          on
> )set message autoload     off
> )set message bottomup     off
> )set message dropmap      off
> )set message expose       off
> )set message file         off
> )set message frame        off
> )set message highlighting off
> )set message instant      off
> )set message insteach     off
> )set message interponly   off
> )set message prompt       step
> )set message selection    off
> )set message set          off
> )set message startup      on
> )set message storage      off
> )set message testing      off
> )set message time         off
> )set message type         off
> )set message void         off
> )set output length 80
> )lisp (setf |$ioHook| (lambda (x &optional args) (when (member x '(|startAlgebraOutput| |endOfAlgebraOutput| |startKeyedMsg| |endOfKeyedMsg|)) (prin1 x) (princ #\Newline))))
> )lisp (setf |$IOindex| NIL)
> sageprint(x:InputForm):String == (atom? x => (float? x => return float(x)::String; integer? x => return integer(x)::String; string? x => return concat(["_"", string(x)::String, "_""])$String; symbol? x => return string(symbol(x))); S: List String := [sageprint y for y in destruct x]; R: String := new(1 + reduce(_+, [1 + #(s)$String for s in S], 0), space()$Character); copyInto!(R, "(", 1); i := 2; for s in S repeat(copyInto!(R, s, i); i := i + 1 + #(s)$String); copyInto!(R, ")", i-1); return R)
> x^2+1
> EOF
openServer result -2
                       FriCAS Computer Algebra System 
                 Version: FriCAS 1.3.11 built with gcl 2.7.1
                   Timestamp: Wed May 14 17:20:17 UTC 2025
-----------------------------------------------------------------------------
   Issue )copyright to view copyright notices.
   Issue )summary for a summary of useful system commands.
   Issue )quit to leave FriCAS and return to shell.
-----------------------------------------------------------------------------
 
(1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> 
Value = #<function 0000000001d06990>
(1) -> 
Value = NIL
(NIL) -> |startKeyedMsg|
   Function declaration sageprint : InputForm -> String has been added to 
      workspace.
|endOfKeyedMsg|
(NIL) -> 
|startAlgebraOutput|
    2
   x  + 1
|endOfAlgebraOutput|

As you see, I turn off this. But it still raise a NIL block output and value = NIL block. And for gcl compiled FriCAS messages can not close. I think it is a bug for upstream fix. we can use this fix it. And it will cause 0.2 s slow down when init the FriCAS

@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 26, 2025

I also test the set can proper deal with fricas

(sage-dev) zhongcx@LAPTOP-A6042VHQ:~/sage$ cat << 'EOF' | fricas -nosman 2>&1
> )set message startup off
> )set message prompt silent
> )lisp (setf |$ioHook| (lambda (x &optional args) (when (member x '(|startAlgebraOutput| |endOfAlgebraOutput| |startKeyedMsg| |endOfKeyedMsg|)) (prin1 x) (princ #\Newline))))
> )lisp (setf |$IOindex| NIL)
> sageprint(x:InputForm):String == (atom? x => (float? x => return float(x)::String; integer? x => return integer(x)::String; string? x => return concat(["_"", string(x)::String, "_""])$String; symbol? x => return string(symbol(x))); S: List String := [sageprint y for y in destruct x]; R: String := new(1 + reduce(_+, [1 + #(s)$String for s in S], 0), space()$Character); copyInto!(R, "(", 1); i := 2; for s in S repeat(copyInto!(R, s, i); i := i + 1 + #(s)$String); copyInto!(R, ")", i-1); return R)
> x^2+1
> EOF
openServer result -2
                       FriCAS Computer Algebra System 
                 Version: FriCAS 1.3.11 built with gcl 2.7.1
                   Timestamp: Wed May 14 17:20:17 UTC 2025
-----------------------------------------------------------------------------
   Issue )copyright to view copyright notices.
   Issue )summary for a summary of useful system commands.
   Issue )quit to leave FriCAS and return to shell.
-----------------------------------------------------------------------------
 
(1) -> (1) -> ---------------------------- The prompt Option ----------------------------

 Description: set type of input prompt to display

 The prompt option may be followed by any one of the following:

    none
    frame
    plain
 -> step 
    verbose

 The current setting is indicated within the list.


 Your value silent is not among the valid choices.

(1) -> 
Value = #<function 0000000001d06960>
(1) -> 
Value = NIL
(NIL) -> |startKeyedMsg|
   Function declaration sageprint : InputForm -> String has been added 
      to workspace.
|endOfKeyedMsg|
|startKeyedMsg|
                                                                   Type: Void
|endOfKeyedMsg|
(NIL) -> 
|startAlgebraOutput|
    2
   x  + 1
|endOfAlgebraOutput|
|startKeyedMsg|
                                                    Type: Polynomial(Integer)
|endOfKeyedMsg|

@mantepse
Copy link
Contributor

In my opinion it is an absolute no-go to special case gcl.

The interface to fricas is fragile, mostly because we use communication via strings. Apparently this is hard to change, nobody has done it in many years. Passing very long input and receiving long output may lead to failure, which can be a real pain, because you would usually use FriCAS for computationally expensive stuff.

It is an upstream bug that gcl prints messages after )set message off, and should be fixed there. I suspect that this should actually be easy to do.

@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 26, 2025

In my opinion it is an absolute no-go to special case gcl.

The interface to fricas is fragile, mostly because we use communication via strings. Apparently this is hard to change, nobody has done it in many years. Passing very long input and receiving long output may lead to failure, which can be a real pain, because you would usually use FriCAS for computationally expensive stuff.

It is an upstream bug that gcl prints messages after )set message off, and should be fixed there. I suspect that this should actually be easy to do.

I think it is no side effects. And it is used in Ubuntu and Debian as system's packages. I think many users may meet this problem

@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 26, 2025

It seems fricas in sbcl can also have the same input but it works well with sage, so what exactly the root cause?

zhongcx@LAPTOP-A6042VHQ:~/sage$ cat << 'EOF' | fricas -nosman 2>&1
> )set functions compile on
> )set message any          on
> )set message autoload     off
> )set message bottomup     off
> )set message dropmap      off
> )set message expose       off
> )set message file         off
> )set message frame        off
> )set message highlighting off
> )set message instant      off
> )set message insteach     off
> )set message interponly   off
> )set message prompt       step
> )set message selection    off
> )set message set          off
> )set message startup      on
> )set message storage      off
> )set message testing      off
> )set message time         off
> )set message type         off
> )set message void         off
> )set output length 80
> )lisp (setf |$ioHook| (lambda (x &optional args) (when (member x '(|startAlgebraOutput| |endOfAlgebraOutput| |startKeyedMsg| |endOfKeyedMsg|)) (prin1 x) (princ #\Newline))))
> )lisp (setf |$IOindex| NIL)
> sageprint(x:InputForm):String == (atom? x => (float? x => return float(x)::String; integer? x => return integer(x)::String; string? x => return concat(["_"", string(x)::String, "_""])$String; symbol? x => return string(symbol(x))); S: List String := [sageprint y for y in destruct x]; R: String := new(1 + reduce(_+, [1 + #(s)$String for s in S], 0), space()$Character); copyInto!(R, "(", 1); i := 2; for s in S repeat(copyInto!(R, s, i); i := i + 1 + #(s)$String); copyInto!(R, ")", i-1); return R)
> x^2+1
> EOF
Checking for foreign routines
FRICAS="/usr/local/lib/fricas/target/x86_64-conda-linux-gnu"
spad-lib="/usr/local/lib/fricas/target/x86_64-conda-linux-gnu/lib/libspad.so"
foreign routines found
openServer result -2
                       FriCAS Computer Algebra System 
           Version: FriCAS 2025-04-14 built with sbcl 2.5.2.debian
                   Timestamp: Wed Nov 26 02:01:29 CST 2025
-----------------------------------------------------------------------------
   Issue )copyright to view copyright notices.
   Issue )summary for a summary of useful system commands.
   Issue )quit to leave FriCAS and return to shell.
-----------------------------------------------------------------------------
 
(1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> (1) -> 
Value = #<INTERPRETED-FUNCTION NIL {100110023B}>
(1) -> 
Value = NIL
(NIL) -> |startKeyedMsg|
   Function declaration sageprint : InputForm -> String has been added to 
      workspace.
|endOfKeyedMsg|
(NIL) -> 
|startAlgebraOutput|
    2
   x  + 1
|endOfAlgebraOutput|

@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 26, 2025

If you add -eval it like

zhongcx@LAPTOP-A6042VHQ:~/sage$ fricas -nosman -eval ')set functions compile on' -eval ')set message any on' -eval ')set message autoload off' -eval ')set message bottomup off' -eval ')set message dropmap off' -eval ')set message expose off' -eval ')set message file off' -eval ')set message frame off' -eval ')set message highlighting off' -eval ')set message instant off' -eval ')set message insteach off' -eval ')set message interponly off' -eval ')set message prompt step' -eval ')set message selection off' -eval ')set message set off' -eval ')set message startup on' -eval ')set message storage off' -eval ')set message testing off' -eval ')set message time off' -eval ')set message type off' -eval ')set message void off' -eval ')set output length 80' -eval ')lisp (setf |$ioHook| (lambda (x &optional args) (when (member x (quote (|startAlgebraOutput| |endOfAlgebraOutput| |startKeyedMsg| |endOfKeyedMsg|))) (prin1 x) (princ #\Newline))))' -eval ')lisp (setf |$IOindex| NIL)' -eval 'sageprint(x:InputForm):String == (atom? x => (float? x => return float(x)::String; integer? x => return integer(x)::String; string? x => return concat(["_"", string(x)::String, "_""])$String; symbol? x => return string(symbol(x))); S: List String := [sageprint y for y in destruct x]; R: String := new(1 + reduce(_+, [1 + #(s)$String for s in S], 0), space()$Character); copyInto!(R, "(", 1); i := 2; for s in S repeat(copyInto!(R, s, i); i := i + 1 + #(s)$String); copyInto!(R, ")", i-1); return R)' -eval 'x^2+1' -eval ')quit'
Checking for foreign routines
FRICAS="/usr/local/lib/fricas/target/x86_64-conda-linux-gnu"
spad-lib="/usr/local/lib/fricas/target/x86_64-conda-linux-gnu/lib/libspad.so"
foreign routines found
openServer result -2
                       FriCAS Computer Algebra System 
           Version: FriCAS 2025-04-14 built with sbcl 2.5.2.debian
                   Timestamp: Wed Nov 26 02:01:29 CST 2025
-----------------------------------------------------------------------------
   Issue )copyright to view copyright notices.
   Issue )summary for a summary of useful system commands.
   Issue )quit to leave FriCAS and return to shell.
-----------------------------------------------------------------------------
 
Value = #<INTERPRETED-FUNCTION NIL {100110023B}>
Value = NIL
|startKeyedMsg|
   Function declaration sageprint : InputForm -> String has been added to 
      workspace.
|endOfKeyedMsg|

|startAlgebraOutput|
    2
   x  + 1
|endOfAlgebraOutput|

@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 26, 2025

In my opinion it is an absolute no-go to special case gcl.

The interface to fricas is fragile, mostly because we use communication via strings. Apparently this is hard to change, nobody has done it in many years. Passing very long input and receiving long output may lead to failure, which can be a real pain, because you would usually use FriCAS for computationally expensive stuff.

It is an upstream bug that gcl prints messages after )set message off, and should be fixed there. I suspect that this should actually be easy to do.

The problem looks like in gcl different behavior. not fricas.

@dimpase
Copy link
Member

dimpase commented Nov 26, 2025

It is an upstream bug that gcl prints messages after )set message off, and should be fixed there. I suspect that this should actually be easy to do.

Can one monkey-patch FriCAS in a way one can do with Python?

We can disable the use of system - wide GCL Fricas until we have a fix.

@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 26, 2025

It is an upstream bug that gcl prints messages after )set message off, and should be fixed there. I suspect that this should actually be easy to do.

Can one monkey-patch FriCAS in a way one can do with Python?

We can disable the use of system - wide GCL Fricas until we have a fix.

But fricas developer also do not know what is the exact issue.

@dimpase
Copy link
Member

dimpase commented Nov 26, 2025

They haven't really looked yet, and it's not something that looks hard to debug.

@cxzhong
Copy link
Contributor Author

cxzhong commented Nov 26, 2025

It is an upstream bug that gcl prints messages after )set message off, and should be fixed there. I suspect that this should actually be easy to do.

Can one monkey-patch FriCAS in a way one can do with Python?

We can disable the use of system - wide GCL Fricas until we have a fix.

May be I change it to directly throw an error if gcl is detected, then modify the is_present method. Can you describe it to fricas developer? I think they do not understand. In fact, it do not affect the computing part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

An incompatible bug in the interface.fricas and the system's FriCAS in Ubuntu 25.04

3 participants