"leave" different in interpreter and compiler

1 view
Skip to first unread message

Martin Rubey

unread,
Jan 9, 2010, 9:54:09 AM1/9/10
to fricas-devel
I just noticed a *very* annoying difference between interpreter and
compiler:

rabinProvesCompositeSmall(p,n,nm1,q,k) ==
-- probability n prime is > 3/4 for each iteration
-- for most n this probability is much greater than 3/4
t := powmod(p, q, n)
-- neither of these cases tells us anything
-- if not (one? t or t = nm1) then
if not ((t = 1) or t = nm1) then
for j in 1..k-1 repeat
print(concat("check j ", string(j)$String)::OutputForm)
oldt := t
t := mulmod(t, t, n)
-- one? t => return true
(t = 1) => return true
-- we have squared someting not -1 and got 1
t = nm1 =>
print "leaving"
leave
print "check t = -1 after loop"
not (t = nm1) =>
print "t = -1 after loop"
return true
print "after t = 1 or t = -1"
false

(80) -> rabinProvesCompositeSmall(2,41,40,5,3)$PRIMES INT
1<enter IntegerPrimesPackage.rabinProvesCompositeSmall,51
:
arg1= 2
arg2= 41
arg3= 40
arg4= 5
arg5= 3
"check j 1"
leaving
check t = -1 after loop
after t = 1 or t = -1
1>exit IntegerPrimesPackage.rabinProvesCompositeSmall,51
:
false

(80) false
Type: Boolean
(79) -> rabinProvesCompositeSmall(2,41,40,5,3)
"check j 1"
"leaving"
"check j 2"

(79) true
Type: Boolean

is this known? difficult to fix?

Martin

Ralf Hemmecke

unread,
Jan 9, 2010, 10:52:34 AM1/9/10
to fricas...@googlegroups.com
Hi Martin,

The keyword "leave" is the problem. In Aldor this is "break". And if I
remember correctly, there was a time when someone renamed it in earlier
versions of FriCAS or Axiom.

Just replace "leave" by "break" and commit. Otherwise this code is a bug
in FriCAS (methinks).

At least that works for me in .spad and .input files.

Maybe we should grep the SPAD code and replace any occurrence of leave
by break. And then change the compiler to complain when "leave" occurs
as being an undefined variable.

Ooops. In the interpreter, that is since the interpreter doesn't care
too much about the given signatures. So if you return the unevaluated
*symbol* leave that might have been what you intended. How would the
interpreter know?

Ralf

Waldek Hebisch

unread,
Jan 9, 2010, 2:34:22 PM1/9/10
to fricas...@googlegroups.com
> I just noticed a *very* annoying difference between interpreter and
> compiler:
...

> is this known? difficult to fix?

Compiler and "interpreter" are in fact two different compilers. IMHO
the correct way to avoid differences is to use single compiler. This
will take time.

Currently I am working on replacing various parsers that we have
by a single one. During that I looked at keywords -- set of
keyword recognized by parsers differ a lot. There is a group
of common keyword but, but beyond that:

Shoe recoginizes 'cross', 'of', 'structure' as keywords, but other
parsers do not. Compiler parser recognizes 'otherwise', 'when',
'exquo', 'div', 'suchthat', 'yield', 'leave', 'not', 'unless',
'until' as keywords, but the "interpreter" parser do not.

"Interpreter" parser treats 'break', 'default', 'define', 'do', 'export',
'free', 'inline', 'local', 'macro', 'rule' as keywords, but
the compiler parser do not.

Some changes are kind of obvious: compiler probably should treat
all words that are keywords for "interpreter" as keywords. We
should probably migrate from 'leave' to 'break'. But other
are less clear: I personally would add 'exquo' as keyword
(operator) also to "interpreter", but Martin seems to be
against this (my rationalle is that 'exquo' and 'quo' are
used in similar context, it is silly to have change betwieen
infix and prefix version when changing one to the other).
'div' is used very little, so we could probably drop it.
'otherwise', 'when', 'suchthat', 'yield', 'unless' are
unused so in principle we could drop them. But it makes
sense to reserve 'yield' for possible future use in
Aldor-like generators.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Ralf Hemmecke

unread,
Jan 9, 2010, 3:47:03 PM1/9/10
to fricas...@googlegroups.com
Waldek,

I was a bit confused by this...

> "Interpreter" parser treats 'break', 'default', 'define', 'do', 'export',
> 'free', 'inline', 'local', 'macro', 'rule' as keywords, but
> the compiler parser do not.

Here is the session with the attached programs where I replaced "leave"
in Martin's program by "break".

Don't these programs now behave like Martin expected? In particular, the
SPAD compiler seems to understand "break".

Ralf

---------------------------------------------------------------------
>fricas
Checking for foreign routines

AXIOM="/home/hemmecke/software/lib/fricas/target/i686-pc-linux"

spad-lib="/home/hemmecke/software/lib/fricas/target/i686-pc-linux/lib/libspad.so"
foreign routines found

openServer result 0

FriCAS (AXIOM fork) Computer Algebra System

Version: FriCAS 2009-10-15

Timestamp: Wednesday October 21, 2009 at 19:42:13

-----------------------------------------------------------------------------

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) -> )co rabin.spad

Compiling FriCAS source code from file

/home/hemmecke/scratch/rabin.spad using old system compiler.

RABIN abbreviates package Rabin

processing macro definition Z ==> Integer


------------------------------------------------------------------------
initializing NRLIB RABIN for Rabin
compiling into NRLIB RABIN
compiling exported rabin :
(Integer,Integer,Integer,Integer,NonNegativeInteger) -> Boolean

Time: 0.09 SEC.


(time taken in buildFunctor: 0)

;;; *** |Rabin| REDEFINED

;;; *** |Rabin| REDEFINED
Time: 0.004 SEC.


Cumulative Statistics for Constructor Rabin
Time: 0.10 seconds

finalizing NRLIB RABIN
Processing Rabin for Browser database:
--->-->Rabin((rabin ((Boolean) Z Z Z Z (NonNegativeInteger)))): Not
documented!!!!
--->-->Rabin(constructor): Not documented!!!!

--->-->Rabin(): Missing Description

; compiling file "/home/hemmecke/scratch/RABIN.NRLIB/RABIN.lsp" (written
09 JAN 2010 09:38:10 PM):

; compiling (/VERSIONCHECK 2)

; compiling (DEFUN |RABIN;rabin;4INniB;1| ...)

; compiling (DEFUN |Rabin| ...)

; compiling (DEFUN |Rabin;| ...)

; compiling (MAKEPROP (QUOTE |Rabin|) ...)

; compiling (MAKEPROP (QUOTE |Rabin|) ...)

; file: /home/hemmecke/scratch/RABIN.NRLIB/RABIN.lsp

; in: DEFUN |Rabin;|

; (BOOT::|haddProp| BOOT::|$ConstructorCache| 'BOOT::|Rabin| NIL

; (CONS 1 BOOT::$))

;

; caught WARNING:

; undefined variable: |$ConstructorCache|


; in: DEFUN |Rabin|
; (VMLISP:HGET BOOT::|$ConstructorCache| 'BOOT::|Rabin|)
; --> GETHASH
; ==>
; (SB-IMPL::GETHASH3 'BOOT::|Rabin| BOOT::|$ConstructorCache| NIL)
;
; caught WARNING:
; undefined variable: |$ConstructorCache|

; in: DEFUN |RABIN;rabin;4INniB;1|
; (BOOT::LETT #:G715 BOOT::|$NoValue| BOOT::|RABIN;rabin;4INniB;1|)
; --> SETQ
; ==>
; (THE #<SB-KERNEL:NAMED-TYPE T> BOOT::|$NoValue|)
;
; caught WARNING:
; undefined variable: |$NoValue|

;
; caught WARNING:
; These variables are undefined:
; |$ConstructorCache| |$NoValue|
;
; compilation unit finished
; caught 4 WARNING conditions


; /home/hemmecke/scratch/RABIN.NRLIB/RABIN.fasl written
; compilation finished in 0:00:00
------------------------------------------------------------------------
Rabin is now explicitly exposed in frame frame1
Rabin will be automatically loaded when needed from
/home/hemmecke/scratch/RABIN.NRLIB/RABIN

(1) -> rabin(2,41,40,5,3)


"check j 1"
leaving
check t = -1 after loop
after t = 1 or t = -1

(1) false
Type:
Boolean
(2) -> )r rabin.input
rb(p,n,nm1,q,k) ==


-- probability n prime is > 3/4 for each iteration
-- for most n this probability is much greater than 3/4
t := powmod(p, q, n)
-- neither of these cases tells us anything
-- if not (one? t or t = nm1) then
if not ((t = 1) or t = nm1) then
for j in 1..k-1 repeat
print(concat("check j ", string(j)$String)::OutputForm)
oldt := t
t := mulmod(t, t, n)
-- one? t => return true
(t = 1) => return true
-- we have squared someting not -1 and got 1
t = nm1 =>
print "leaving"

break


print "check t = -1 after loop"
not (t = nm1) =>
print "t = -1 after loop"
return true
print "after t = 1 or t = -1"
false


Type: Void
(3) -> rb(2,41,40,5,3)
Compiling function rb with type (PositiveInteger,PositiveInteger,
PositiveInteger,PositiveInteger,PositiveInteger) -> Boolean


"check j 1"
"leaving"
"check t = -1 after loop"
"after t = 1 or t = -1"

(3) false
Type:
Boolean

rabin.input
rabin.spad

Waldek Hebisch

unread,
Jan 9, 2010, 4:00:35 PM1/9/10
to fricas...@googlegroups.com
Ralf Hemmecke wrote:
> Waldek,
>
> I was a bit confused by this...
>
> > "Interpreter" parser treats 'break', 'default', 'define', 'do', 'export',
> > 'free', 'inline', 'local', 'macro', 'rule' as keywords, but
> > the compiler parser do not.
>
> Here is the session with the attached programs where I replaced "leave"
> in Martin's program by "break".
>
> Don't these programs now behave like Martin expected? In particular, the
> SPAD compiler seems to understand "break".
>

Yes, Spad compiler understands 'break'. But Spad parser does not
treat it as a keyword. I am not sure if difference is visible to
users, but there is good chance that some tricky code can
spot the difference.

--
Waldek Hebisch
heb...@math.uni.wroc.pl

Reply all
Reply to author
Forward
0 new messages