Skip to content

Commit db2715d

Browse files
committed
Improve speed in ecl's fricas
1 parent 659edc9 commit db2715d

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

src/sage/interfaces/fricas.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ def __init__(self, name='fricas', command=None,
316316
assert max(len(c) for c in FRICAS_INIT_CODE) < eval_using_file_cutoff
317317
self.__eval_using_file_cutoff = eval_using_file_cutoff
318318
self._COMMANDS_CACHE = '%s/%s_commandlist_cache.sobj' % (DOT_SAGE, name)
319+
self._uses_gcl = None # will be set in _start()
319320
# we run the init code in _start to avoid spurious output
320321
Expect.__init__(self,
321322
name=name,
@@ -354,16 +355,28 @@ def _start(self):
354355
self.eval(FRICAS_LINENUMBER_OFF_CODE, reformat=False)
355356
for line in FRICAS_HELPER_CODE:
356357
self.eval(line, reformat=False)
357-
# FriCAS compiled with GCL may output function declaration messages
358-
# asynchronously after the prompt appears. We need to consume any
359-
# such buffered output to keep the expect interface synchronized.
360-
# See :issue:`40569`.
358+
# Detect whether FriCAS is compiled with GCL.
359+
# GCL-based FriCAS may output function declaration messages
360+
# asynchronously after the prompt appears. We need to handle this
361+
# to keep the expect interface synchronized. See :issue:`40569`.
361362
E = self._expect
362-
for _ in range(3):
363+
# First, consume any buffered output from previous commands
364+
# to ensure we get a clean response to the lisp command
365+
while True:
363366
try:
364-
E.expect(self._prompt, timeout=0.2)
367+
E.expect(self._prompt, timeout=0.1)
365368
except pexpect.TIMEOUT:
366369
break
370+
E.sendline(')lisp (lisp-implementation-type)')
371+
E.expect(self._prompt)
372+
lisp_output = E.before.decode() if isinstance(E.before, bytes) else E.before
373+
self._uses_gcl = 'GCL' in lisp_output
374+
if self._uses_gcl:
375+
for _ in range(3):
376+
try:
377+
E.expect(self._prompt, timeout=0.1)
378+
except pexpect.TIMEOUT:
379+
break
367380
# register translations between SymbolicRing and FriCAS Expression
368381
self._register_symbols()
369382

@@ -932,7 +945,8 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if
932945
restart_if_needed=restart_if_needed)
933946
# FriCAS compiled with GCL may send an extra prompt after each command.
934947
# We try to consume it to keep the interface synchronized.
935-
if wait_for_prompt and self._expect is not None:
948+
# Only do this for GCL-based FriCAS to avoid slowdowns with SBCL.
949+
if self._uses_gcl and wait_for_prompt and self._expect is not None:
936950
try:
937951
self._expect.expect(self._prompt, timeout=0.1)
938952
except pexpect.TIMEOUT:

0 commit comments

Comments
 (0)