status
Most things now seem to work; eflisp
is built with r7rs features built in.
using
rlwrap ./eflisp
-- runs the fully built r7rs system (or whatever boot image is integrated with the application)
rlwrap ./eflisp -b
-- runs the base eflisp with flisp.boot
rlwrap ./eflisp -s
-- runs the base eflisp with efscm.boot
yielding r7rs at the prompt
developing
From a fresh start of eflisp base:
rlwrap ./eflisp -b
(load "r7expander.lsp")
to debug inside "r7expander.lsp"
Use
make efscm.boot
rlwrap ./eflisp -s
(load "tests/chibi/r7rs-tests.scm")
to look for breakage
or
make efscm.boot
make flisp.boot.inc
make
to build the fully built r7rs system; again testing for breakage with
rlwrap ./eflisp
(load "tests/chibi/r7rs-tests.scm")
or use make r7rs-coverage-test
for another test of a fully built r7rs eflisp
VS Code detail
Cmd + K M can be used to set a language file extension association. I did this for .sld and .lsp to scheme.
TODO
there is a spooky bug in the OG chibi definition of
quasiquote
in r7expander.lsp; using named let instead ofdefine
fixed the problem, but sheesh! What's up? (This look(s/d) an eflisp base level bug) but now, it's BACK intermittently with the named let version ofquasiquote
. The test case fron r7rs-tests.scm is\
(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f)`The
delete-duplicates
in system.lsp avoids n**2 perfomance by using an eq-hashtable... it would be nice to take advantage of this somehow for the more general version in(scheme list)
Also note the nicelength=
andlength>
Libraries are loaded only once no matter how many
include
s reference them.1 It might be nice to have a means to unload a library for debugging; other library debugging tools would also be welcome.perhaps integrate with base file loader's
resolve-file-path
:include
load
may need to define
exit
in process-context library as(raise 'exit)
remove redundancies
self host? i.e., build compiler + r7expander with r7expander; this will require rethinking how
make-system-image
choses bindings to dump; perhaps a new version of it should be passed a list of library specs to dump instead of dumping all bound symbols
perhaps not TODO
printing synclosed symbols sucks... the whole environment is printed; adding
unwrap-syntax
in places helps; this sometimes blows the stack and dumps core; an option is to add record specific print functions when not printing values than need*print-readably*
write
in r7rs: "Datum labels must not be used if there are no cycles." Oops.maybe
load
should look at 1st and only form to see if it'sdefine-library
(lambda () (begin))
is legal syntax but is rejected in r7expander'sexpand-body
eflisp string escape x was not compatible with r7rs ("e[1He[J" isn't "x1B;[1Hx1B;[J"); r7rs requires a terminating semicolon, which is discarded; eflisp used to terminate on any non-hex character, and
ungetc
it. The reader is now fixed to handle escape x (a new escape X replaces the original, needed for boot image dumps), but the print function still uses e for x1B; (which is normally fine, but might cause some pedantic tests to fail).investigate whether it's necessary to incorporate eflisp compiler's support for keyword args (I don't think they're used)
It (was? I think this is now fixed) particularly annoying that there is no error checking on library import/export; you'll see errors about
car
orcdr
getting a non-pair from theassq
in the library.
R7RS compliance
Most libraries identified in r7rs are implemented. Currently missing:
(scheme r5rs)
(scheme complex)
No reentry of continuations, so
call/cc
is kludgedguard
andwith-exception-handler
pass all the SRFI-34 examples, and all but one of the chibi tests; for some reason re-raising the exeption ifwith-exception-handler
's handlers don't escape breaks thingsdelete-file
is not implementedNo support for rationals, bignums, complex, inexact & exact -- this results in many failures in the reader
integer?
in femtolisp is used for identifying ctypes that are not floating point... I'm wary of changing that; r7rs says it also should return true for(= x (round x))
... hmm; this also affectsrational?
No string modification, no:
string-set!
string-copy!
string-fill!
-- it's possible these could be implemented by checking that the byte size of the "hole" in the destination is the same byte size as the source, and giving an error only when they are different, but there really is no pressing needFoldcase is kludged with lowercase instead; generally poor Unicode support
Unicode support is very basic in general; several special cases fail in the Chibi tests
No error using a closed string port as long as the memory buffer is still ok
apply
ignores dotted list last cdrs rather than giving an errorThe
guard
syntax is incomplete... it doesn't re-raise if the handler passes up the exceptionThe femtolisp reader is not compatible in at least these ways:
- No support for line continuation with
\
in strings - No support for rationals, bignums, complex, inexact & exact
- No support for 'S' 's' 'F' 'f' 'D' 'd' 'L' 'l' exponent markers to indicate size
- Decimal point in a number translates to floating point even if all the following digits are zero
- Floating point reader does not handle bases other then 10
- No character escape inside
||
[
is accepted to introduce a vector (as is#(
)- Symbols are permitted to contain some characters r7rs restricts, e.g.,
+
and-
as initial characters - No support for case-insensitive reader
- Directives
#!fold-case
and#!no-fold-case
break the reader - The number
#d.1
messes up the reader because it doesn't see a digit after thed
- The
#x
reader was made compatible, I think, by adding#X
for the old behavior
- No support for line continuation with
The femtolisp writer is not compatible in at least these ways:
- Datum labels are used even if the structure printed is not circular
- There are extra character escapes, so text written is sometimes different than expected
- Due to reader incompatibilies, especially for extra characters allowed in symbols, symbols are sometimes printed in a way that cannot be read by another r7rs implementation
The femtolisp compiler does some inlining, so sometimes errors that might be expected at runtime occur at compile time, e.g., with
apply
Notes
Grokking r7expander
The (r7expander native) library imports from eflisp base and exports those symbols
The (r7expander builtin) library defines and exports expanders, implemented on eflisp base augmented with the (r7expander library) and (r7expander syntactic-closure) capabilities; it employs the low level macro mechanisms, such as er-macro-transformer, but doesn't export them!?
The (scheme base) library imports from (r7expander builtin) and (r7expander native) and exports the usual suspects. It defines all the required syntax using the syntax-rules imported from r7expander builtin).
The philosophy for loading files seems to be:
- for library loading use
(import <library-specifier>)
- for list of forms to exaluate in the current environment use
load
- for library loading use
r7expander uses
(if #f #f)
to get an unspecified value; this is leading to some incompatibilities with eflisp, which expects some forms, likecond
, to return#f
if no cases match rather than the "unspecified value," which unfortunately is now#t
(the result of(if #f #f)
in efisp).library-export
adds one entry to the object-exports of the current library, either a symbol mapping to itself or a nickname-id pair if called with(rename id nickname)
-- note that it does not check that the id is present in the library's environment.library-import
creates a map of renames and then installs these bindings into the top level environment. When it processes exports from libraries in it's argument list, it assumes the names in the export list of the library are bound in the library's env (this is now checked!).
Porting notes
These eflisp macros are obsolete now r7expander is complete and should not be translated:
define-macro
import
define-record-field
define-record-modifier
define-record-constructor
define-record-accessor
define-record-predicate
These eflisp macros are used locally and would only need to be translated to syntax-rules if/when we try to self-host:
check-arg
is local to srfi-1r-from-q-n1-n2
is local to the lib/scheme veneercase-pattern
is local to r7expander.lsp and already has a built-in replacement
dotimes
is implemented in (eflisp debug) for use in that file and exported
history of porting r7expander to eflisp
Took the original nyuichi files and combined into one .lsp file that can bootstrap eflisp base to have
define-library
andsyntax-rules
. The originaldefine-library
wrappers of(r7expander syntactic-closure)
and(r7expander library)
are commented out since our base environment doesn't havedefine-library
. These two modules are inlined into r7expander.lsp and followed by the relevant pieces of r7expander's init.scm and main.scm.Needed to rename
environment
record type because it conflicts witht the builtin function of the same name used by eflisp base to identify symbols formake-system-image
and also used inprint-stack-trace
in the toplevel exception handler. For consistency I used lozenge like enclosures, e.g.,<environment>
, for all record typesNeeded to rename r7expander's
expand
in order to keep the base level expand in place for debugging alongside the r7expander version, so it's now calledr7expand
.There was one use of
syntax-rules
in (r7expander builtin) that I had to replace with a macro; I used(bound? '*syntax-environment*)
as a way to select between the macro and rules versions ofcase-pattern
.Replaced the one use of
case-lambda
in r7expander with a dotted arg listIntegrate eflisp compiler special forms in place of rexpander define-syntax versions in init/base.sld:
and
andor
Implement (eflisp native) (built into r7expander.scm) to get access to compiler and runtime builtins
Implement eflisp specific
define-record-type
expander in (r7expander builtin)Begin implementation of (eflisp exceptions) library with
unwind-protect
catch
andthrow
after includingtrycatch
andprog1
in(eflisp native)
Implement eflisp specific
parameterize
expander in (r7expander builtin) using (eflisp exceptions)Extend (eflisp exceptions) library with
assert
,receive
, which is really SRFI-8,time
,with-bindings
,with-input-from
, andwith-output-to
Replace
case
macro in(scheme base) with version from r7rs because it failed this test:
(assert (eq? 'c (case (car '(c d)) ((a e i o y) 'vowel) ((w j) 'semivowel) (else => (lambda (x) x)))))Fix
if-expand
by exportinglibrary
from(r7expander builtin)
and importing it into(scheme base)
to pass this test case:(cond-expand ((or (library (scheme base))) (assert #t)) (else (assert #f)))
Implement evaluating repl using:
((compile-thunk (expand-repl v repl-environment)))
Implement
load
using same eval as repl, and implement(interaction-environment)
; export both from(scheme base)
for nowIncorporate eflisp compiler's support for optional lambda args in
(r7expander builtin))
Remove
unwrap-syntax
from(r7expander builtin)
'squote
to avoid crashing on circular structureUse
call-with-current-continuation
instead ofcall/cc
in base.sld forguard
becausecall/cc
isn't defined at this pointDefine the function
features
to export from(r7expander native)
Add support for eflisp compiler special forms:
for
while
Add auto-load of library files in
library-import
Add a command line option to runtime to boot into r7rs mode,
-s
in parallel with-b
for base modeIntegrate with
make-system-image
& jetison*syntax-environment*
and base eval/repl and add a new bootstrapping script for rsr7 level above baseReplaced
quasiquote
with chibi scheme versionAdded
lambda-case
usingsyntax-rules
Replaced
syntax-rules
with chibi scheme's version (was missing(... <template>)
for quoting elipses)Implement
syntax-quote
, which essential to makesyntax-rules
work (it does now!)- Fix for defines nested in
begin
at top level of macro expansion; two pass expansion added
- Fix for defines nested in
Use
fix!
in newer-macro-transformer
basedletrec
andletrec*
for eflisp compiler optimizationNew
(r7expander syntactic-closure)
library now supports low level macros e.g.,er-macro-transformer
in user codeFun fact:
FL_UNSPECIFIED
==FL_T
so the implemented fix forread
from string returning #when reading the last value in a stirng fails for the case "#t"
-- there's gotta be a better way to detect EOF! Update: perhaps this is fixed. Nowfl_read_sexpr
returnsFL_EOF
when it cannot read anything for any reason (in place ofFL_UNSPECIFIED
) andfl_read
checks for EOF before callingfl_read_sexpr
Add an
(eflisp debug)
library for disassembly, trace, and timing executionAdd SRFI-8
receive
Fix bugs in
define-record-type
by replacing version in r7expander wither-macro-transformer
in base.sld
r7rs-coverage results
cd tests/r7rs-coverage && ./coverage eflisp | grep ERROR
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,complex?,complex literal 3+1i
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,denominator,
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,inexact,
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,numerator,
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,rational?,
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,rationalize,
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,string-copy!,
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,string-copy!,start
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,string-copy!,start and end
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,string-fill!,
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,string-fill!,start
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,string-fill!,start and end
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,string-set!,
eflisp,2025-06-23T17:53:13,(scheme base),ERROR,literals,rational
eflisp,2025-06-23T17:53:13,(scheme complex),ERROR,angle,
eflisp,2025-06-23T17:53:13,(scheme complex),ERROR,imag-part,
eflisp,2025-06-23T17:53:13,(scheme complex),ERROR,magnitude,
eflisp,2025-06-23T17:53:13,(scheme complex),ERROR,make-polar,
eflisp,2025-06-23T17:53:13,(scheme complex),ERROR,make-rectangular,
eflisp,2025-06-23T17:53:13,(scheme complex),ERROR,real-part,
r7rs-benchmarks results
Of 57 tests, 50 pass, 2 fail for no (scheme complex)
, 2 fail for no bignums, 3 fail for no string-set!
Benchmarking eflisp on Thu Jun 26 09:49:37 EDT 2025
under Darwin mini-e.local 24.5.0 Darwin Kernel Version 24.5.0:
Tue Apr 22 19:54:43 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T8132 arm64
Running browse:2000
Elapsed time: 2.295 seconds (2.295) for browse:2000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,browse:2000,2.295
Running deriv:10000000
Elapsed time: 6.097 seconds (6.097) for deriv:10000000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,deriv:10000000,6.097
Running destruc:600:50:4000
Elapsed time: 14.777 seconds (14.777) for destruc:600:50:4000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,destruc:600:50:4000,14.777
Running diviter:1000:1000000
Elapsed time: 10.281 seconds (10.282) for diviter:1000:1000000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,diviter:1000:1000000,10.281
Running divrec:1000:1000000
Elapsed time: 11.851 seconds (11.851) for divrec:1000:1000000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,divrec:1000:1000000,11.851
Running puzzle:1000
Elapsed time: 35.243 seconds (35.243) for puzzle:1000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,puzzle:1000,35.243
Running triangl:22:1:50
Elapsed time: 18.451 seconds (18.451) for triangl:22:1:50
+!CSVLINE!+eflisp-2025-06-23T17:53:13,triangl:22:1:50,18.451
Running tak:40:20:11:1
Elapsed time: 14.244 seconds (14.244) for tak:40:20:11:1
+!CSVLINE!+eflisp-2025-06-23T17:53:13,tak:40:20:11:1,14.244
Running takl:40:20:12:1
Elapsed time: 33.368 seconds (33.368) for takl:40:20:12:1
+!CSVLINE!+eflisp-2025-06-23T17:53:13,takl:40:20:12:1,33.368
Running ntakl:40:20:12:1
Elapsed time: 33.476 seconds (33.476) for ntakl:40:20:12:1
+!CSVLINE!+eflisp-2025-06-23T17:53:13,ntakl:40:20:12:1,33.476
Running cpstak:40:20:11:1
Elapsed time: 30.958 seconds (30.957) for cpstak:40:20:11:1
+!CSVLINE!+eflisp-2025-06-23T17:53:13,cpstak:40:20:11:1,30.958
Running ctak:32:16:8:1
Elapsed time: 24.498 seconds (24.498) for ctak:32:16:8:1
+!CSVLINE!+eflisp-2025-06-23T17:53:13,ctak:32:16:8:1,24.498
Running fib:40:5
Elapsed time: 33.129 seconds (33.129) for fib:40:5
+!CSVLINE!+eflisp-2025-06-23T17:53:13,fib:40:5,33.129
Running fibc:30:10
Elapsed time: 19.712 seconds (19.713) for fibc:30:10
+!CSVLINE!+eflisp-2025-06-23T17:53:13,fibc:30:10,19.712
Running fibfp:35:10
Elapsed time: 9.176 seconds (9.176) for fibfp:35:10
+!CSVLINE!+eflisp-2025-06-23T17:53:13,fibfp:35:10,9.176
Running sum:10000:200000
Elapsed time: 20.194 seconds (20.194) for sum:10000:200000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,sum:10000:200000,20.194
Running sumfp:1000000:500
Elapsed time: 14.781 seconds (14.78) for sumfp:1000000:500
+!CSVLINE!+eflisp-2025-06-23T17:53:13,sumfp:1000000:500,14.781
Running fft:65536:100
Elapsed time: 6.353 seconds (6.352) for fft:65536:100
+!CSVLINE!+eflisp-2025-06-23T17:53:13,fft:65536:100,6.353
Running mbrot:75:1000
Elapsed time: 17.421 seconds (17.42) for mbrot:75:1000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,mbrot:75:1000,17.421
Testing mbrotZ under eflisp
error: library not found: (scheme complex)
+!CSVLINE!+eflisp,mbrotZ,CRASHED
Running nucleic:50
Elapsed time: 9.824999999999999 seconds (9.824999999999999) for nucleic:50
+!CSVLINE!+eflisp-2025-06-23T17:53:13,nucleic:50,9.824999999999999
Testing pi under eflisp
parse-error: read: overflow in numeric constant 314159265358979323846264338327950288419716939937507
+!CSVLINE!+eflisp,pi,CRASHED
Running pnpoly:1000000
Elapsed time: 41.274 seconds (41.274) for pnpoly:1000000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,pnpoly:1000000,41.274
Running ray:50
Elapsed time: 11.259 seconds (11.259) for ray:50
+!CSVLINE!+eflisp-2025-06-23T17:53:13,ray:50,11.259
Running simplex:1000000
Elapsed time: 23.016 seconds (23.015) for simplex:1000000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,simplex:1000000,23.016
Running ack:3:12:2
Elapsed time: 26.594 seconds (26.594) for ack:3:12:2
+!CSVLINE!+eflisp-2025-06-23T17:53:13,ack:3:12:2,26.594
Running array1:1000000:500
Elapsed time: 27.641 seconds (27.641) for array1:1000000:500
+!CSVLINE!+eflisp-2025-06-23T17:53:13,array1:1000000:500,27.641
Running string:500000:100
Elapsed time: 1.538 seconds (1.537) for string:500000:100
+!CSVLINE!+eflisp-2025-06-23T17:53:13,string:500000:100,1.538
Running sum1:25
Elapsed time: 0.28 seconds (0.28) for sum1:25
+!CSVLINE!+eflisp-2025-06-23T17:53:13,sum1:25,0.28
Running cat:50
Elapsed time: 11.341 seconds (11.341) for cat:50
+!CSVLINE!+eflisp-2025-06-23T17:53:13,cat:50,11.341
Running tail:50
Elapsed time: 10.249 seconds (10.249) for tail:50
+!CSVLINE!+eflisp-2025-06-23T17:53:13,tail:50,10.249
Running wc:inputs/bib:50
Elapsed time: 13.405 seconds (13.405) for wc:inputs/bib:50
+!CSVLINE!+eflisp-2025-06-23T17:53:13,wc:inputs/bib:50,13.405
Running read1:2500
Elapsed time: 0.585 seconds (0.584) for read1:2500
+!CSVLINE!+eflisp-2025-06-23T17:53:13,read1:2500,0.585
Testing compiler under eflisp
error: library not found: (scheme complex)
+!CSVLINE!+eflisp,compiler,CRASHED
Running conform:500
Elapsed time: 23.779 seconds (23.779) for conform:500
+!CSVLINE!+eflisp-2025-06-23T17:53:13,conform:500,23.779
Running dynamic:500
Elapsed time: 11.552 seconds (11.552) for dynamic:500
+!CSVLINE!+eflisp-2025-06-23T17:53:13,dynamic:500,11.552
Running earley:1
Elapsed time: 12.403 seconds (12.403) for earley:1
+!CSVLINE!+eflisp-2025-06-23T17:53:13,earley:1,12.403
Running graphs:7:3
Elapsed time: 39.105 seconds (39.105) for graphs:7:3
+!CSVLINE!+eflisp-2025-06-23T17:53:13,graphs:7:3,39.105
Running lattice:44:10
Elapsed time: 77.818 seconds (77.818) for lattice:44:10
+!CSVLINE!+eflisp-2025-06-23T17:53:13,lattice:44:10,77.818
Running matrix:5:5:2500
Elapsed time: 17.573 seconds (17.573) for matrix:5:5:2500
+!CSVLINE!+eflisp-2025-06-23T17:53:13,matrix:5:5:2500,17.573
Running maze:20:7:10000
Elapsed time: 14.106 seconds (14.105) for maze:20:7:10000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,maze:20:7:10000,14.106
Running mazefun:11:11:10000
Elapsed time: 15.09 seconds (15.09) for mazefun:11:11:10000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,mazefun:11:11:10000,15.09
Running nqueens:13:10
Elapsed time: 31.633 seconds (31.634) for nqueens:13:10
+!CSVLINE!+eflisp-2025-06-23T17:53:13,nqueens:13:10,31.633
Running paraffins:23:10
Elapsed time: 2.021 seconds (2.022) for paraffins:23:10
+!CSVLINE!+eflisp-2025-06-23T17:53:13,paraffins:23:10,2.021
Testing parsing under eflisp
eval: variable string-set! has no value
+!CSVLINE!+eflisp,parsing,CRASHED
Running peval:2000
Elapsed time: 13.993 seconds (13.993) for peval:2000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,peval:2000,13.993
Running primes:1000:10000
Elapsed time: 6.591 seconds (6.592) for primes:1000:10000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,primes:1000:10000,6.591
Running quicksort:10000:2500
Elapsed time: 28.369 seconds (28.369) for quicksort:10000:2500
+!CSVLINE!+eflisp-2025-06-23T17:53:13,quicksort:10000:2500,28.369
Testing scheme under eflisp
eval: variable string-set! has no value
+!CSVLINE!+eflisp,scheme,CRASHED
Testing slatex under eflisp
eval: variable string-set! has no value
+!CSVLINE!+eflisp,slatex,CRASHED
Testing chudnovsky under eflisp
parse-error: read: overflow in numeric constant 314159265358979323846264338327950288419716939937510
+!CSVLINE!+eflisp,chudnovsky,CRASHED
Running nboyer:5:1
Elapsed time: 6.865 seconds (6.865) for nboyer:5:1
+!CSVLINE!+eflisp-2025-06-23T17:53:13,nboyer:5:1,6.865
Running sboyer:5:1
Elapsed time: 8.895 seconds (8.895) for sboyer:5:1
+!CSVLINE!+eflisp-2025-06-23T17:53:13,sboyer:5:1,8.895
Running gcbench:20:1
Elapsed time: 12.09 seconds (12.09) for gcbench:20:1
+!CSVLINE!+eflisp-2025-06-23T17:53:13,gcbench:20:1,12.09
Running mperm:20:10:2:1
Elapsed time: 25.619 seconds (25.619) for mperm:20:10:2:1
+!CSVLINE!+eflisp-2025-06-23T17:53:13,mperm:20:10:2:1,25.619
Running equal:100:100:8:1000:2000:5000
Elapsed time: 1.279 seconds (1.28) for equal:100:100:8:1000:2000:5000
+!CSVLINE!+eflisp-2025-06-23T17:53:13,equal:100:100:8:1000:2000:5000,1.279
Running bv2string:1000:1000:100
Elapsed time: 10.836 seconds (10.836) for bv2string:1000:1000:100
+!CSVLINE!+eflisp-2025-06-23T17:53:13,bv2string:1000:1000:100,10.836
- ^
Regardless of the number of times that a library is loaded, each program or library that imports bindings from a library must do so from a single loading of that library, regardless of the number of import declarations in which it appears. That is, (import (only (foo) a)) followed by
(import (only (foo) b))
has the same effect as (import(only (foo) a b))
.