Add introspect capabilities of the Scheme implementation using SRFI 0 COND-EXPAND
Environment/Versions
- GIMP version: 2.10.34, 2.99.15 dev beta, all
- Package:
flatpak install --user https://dl.flathub.org/build-repo/32984/org.gimp.GIMP.flatpakref
- Script-Fu init on Ubuntu 22:
~/.local/share/flatpak/app/org.gimp.GIMP/x86_64/beta/25dd33d02a45117189f7de74cb17ad71e555e1ca25c59ec7f6d4afb1bdc9f309/files/share/gimp/2.99/scripts/script-fu.init
- Script-Fu init on Windows 10:
C:\Program Files\GIMP 2\share\gimp\2.0\scripts\script-fu.init
- Operating System: Windows 10, WSL 2 Ubuntu 22.04.2 LTS, All
Reproduction
Is the bug reproducible? Always
Description of the bug
Positive tests in legacy TS 1.42
Firstly, the conditional-compilation-like SRFI registry *features*
is displayed:
(srfi-0 tinyscheme)
Pay attentation to the order of features.
Figure 1: cond-expand
works in TinyScheme 1.42
Like Script-Fu, TS 1.42 has two features:
- srfi-0;
- tinyscheme.
Symbolically, the order of features could be interpreted:
- TS only supports the zero-based Scheme Requests for Implementation
srfi-0
. - There will be not any other SRFI after the core engine
tinyscheme
.
The expected message "Script-Fu implements both TS and Srfi-0" is well displayed.
Since Srfi-38 is not in the SRFI registry *features*
, the message "Srfi-38 is not supported." works.
Negative tests fail
Figure 2: TinyScheme 1.42 fails
Handling else
in cond-expand
has been discussed in 2014-03-12 and updated in 2020-09-28 for the milestone TS 1.43.
Figure 3: Script-Fu fails in Windows 10 Gimp 2.10.34
Hereafter enclosed are the cases where both TS and Script-Fu return unexpected #t or fail with the wrong message.
Click to expand
(cond-expand (srfi-38 "srfi-38 is supported.") (else "srfi-38 is supported!"))
Expected result: "srfi-38 is not supported!"
Actual result: #t
(cond-expand (srfi-38 "srfi-38 is supported."))
Expected result: #f
Actual result: #t
(cond-expand)
Expected result: Error: 0000. Unfulfilled cond-expand.
Actual result: #t
(cond-expand (else))
Expected result: ()
Actual result: #t
(cond-expand (else "srfi-38 is not supported!") (srfi-38 "unreachable"))
Expected result: Error: 0001. cond-expand else clause is not the final one.
Actual result: #t
(cond-expand ((not) "unreachable"))
Expected result: Error: 0002. cond-expand: 'not' takes 1 argument
Actual result: Error: cdr: argument 1 must be: pair
(cond-expand ((boolFnc prm) "unreachable"))
Expected result: Error: 0003. cond-expand: unknown boolean operator boolFnc
Actual result: Error: cond-expand : unknown operator boolFnc
No space before :
.
Implementation
Legacy
Srfi-0
is at the end of script-fu.init
Click to expand
;; SRFI-0
;; COND-EXPAND
;; Implemented as a macro
(define *features* '(srfi-0 tinyscheme))
(define-macro (cond-expand . cond-action-list)
(cond-expand-runtime cond-action-list))
(define (cond-expand-runtime cond-action-list)
(if (null? cond-action-list)
#t
(if (cond-eval (caar cond-action-list))
`(begin ,@(cdar cond-action-list))
(cond-expand-runtime (cdr cond-action-list)))))
(define (cond-eval-and cond-list)
(foldr (lambda (x y) (and (cond-eval x) (cond-eval y))) #t cond-list))
(define (cond-eval-or cond-list)
(foldr (lambda (x y) (or (cond-eval x) (cond-eval y))) #f cond-list))
(define (cond-eval condition)
(cond
((symbol? condition)
(if (member condition *features*) #t #f))
((eq? condition #t) #t)
((eq? condition #f) #f)
(else (case (car condition)
((and) (cond-eval-and (cdr condition)))
((or) (cond-eval-or (cdr condition)))
((not) (if (not (null? (cddr condition)))
(error "cond-expand : 'not' takes 1 argument")
(not (cond-eval (cadr condition)))))
(else (error "cond-expand : unknown operator" (car condition)))))))
The error
message has two characteristics that will be fixed:
- The separator between
cond-expand
and:
is the French froggy space - The function
error
generates a fatal error that stops regression tests before the end of the campaign.
So the legacy:
(error "cond-expand : 'not' takes 1 argument")
could be improved by:
(throw "0002. cond-expand: 'not' takes 1 argument")
Replacing (error "...")
with (throw "...")
allows the campaign of regression test to continue to the next tests.
An expected error is a positive result by the regression test if the expected message matches the result of the execution.
Fix 1srfi-000-cond-expand.scm 1.0
Note that the source code does not end by EOL
= CR LF
in Windows or LF
in Linux. This will discussed later.
In the Scrip-Fu console, run:
*features*
Will improve the differences between TS and Scrip-Fu:
(tinyscheme unicode gimp-pdb srfi-0)
Contrary to Script-Fu, the legacy TS does not support Unicode and cannot access to the Gimp Procedural DataBase.
Into the bargain, ending by srfi-0
before the closing parenthesis keeps open the hypothesis that more SRFI could be added inside Script-Fu in the future.
Script-Fu coding style
The legacy coding style for the C language is applied in the original script-fu.init
.
At the end of a define
, this could lead to the "Lots of Insipid, Stupid Parentheses" syndrom.
Two spaces for each indendation is not enough.
Figure 4: Sript-Fu legacy vs modern coding style
pp
standing for Pretty Print beautifies the legacy coding style.
Figure 5: Script-Fu cross balanced parenthesis in Win10 Notepad++
The modern coding style has:
- Four spaces by indentation. Split in more smaller
define
if the indendation is too large; - Cross balanced parenthesis if the parenthesed expression cannot be closed on the same line;
- The smiley
;-
separator between twodefine
.
Each define
must have --at least-- one line of comment.
Above this minimal comment are one or more regression tests.
Script-Fu re-test regression test
Figure 6: Sript-Fu re-test regression test on Win10
The international end-user does not wish long waffles in English comments but examples with the calling parameters and the expected result.
The following comment starting with ; (
is a running sample of the function fnc
with two parameters
; (fnc prm1 prm2)
; expected result
After the call of fnc
, the next line is the expected result followed by an empty line.
re-test
runs a campaign of regression test. The call is in the header of the source file .scm:
;; (re-test "1srfi-000-cond-expand.scm") SUCCESSFULLY ran 22 tests in 461 ms 165 µs
The double semi-colon ;;
avoids to call recursively a campaign of test during the same campaign of test since the time of execution could change.
Script-Fu integration
Figure 7: Sript-Fu integration for Windows
Loading the source file1srfi-000-cond-expand.scm
always generates the positive result #t
:
; THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
;-
#t
The missing final EOL CR LF
on Windows or LF
in Linux will be discussed in a future report.
srfi-0 cond-expand in Ubuntu 22
Figure 8: Manual campaign of tests in Ubu22 Gimp dev beta 2.99.15