STklos icon indicating copy to clipboard operation
STklos copied to clipboard

Add SRFI 101: Purely Functional Random-Access Pairs and Lists

Open jpellegrini opened this issue 2 years ago • 6 comments

Hi @egallesio !

One more R7RS-Large library... This one is tricky, since it requires the redefinition of very fundamental things like CAR and QUOTE.

Relevant points

  • Everything is defined inside the module with a prefix srfi101:, and exported with renaming
  • The ideal way to use this SRFI is to prefix symbols when importing, otherwise one'd lose the standard car, list, quote etc.
  • Its tests are in a separate file, and loaded as a last thing in do-test.stk:
(define (load-tests)
  ...
  (load "test-r5rs-pitfall.stk")
  (load "test-srfi-101.stk")
)

Issues:

  1. When not renamed, quote enters a loop
  2. Tests run fine and pass when called manually, but when inside the test system, they raise some kind of exception

(1) is probably because quote is not a macro in STklos, but rather a special form, so the SRFI's custom quote macro will confuse the compiler:

(define-macro (srfi101:quote x)
  (define (x->rlist obj)
    (if (scheme:pair? obj)
        (srfi101:cons (x->rlist (scheme:car obj))
                      (x->rlist (scheme:cdr obj)))
        obj))
  `(quote ,(x->rlist x)))         ;;; <== here! I can't reference "the quote symbol from Scheme",
                                  ;;; so the macro expander enters a loop when this macro is renamed to
                                  ;;; "quote"

Maybe quote and quasiquote could be turned into macros? I can take a look into that if you think it's ok.

(2) is a mystery to me.

$ src/stklos --no-init-file --utf8-encoding=yes
stklos> (load-path `("lib"   ,@(load-path)))
stklos> (load "tests/test.stk")
stklos> (load "tests/test-srfi-101.stk")
  testing srfi-101.-1 expects 5 ==> OK.
  testing srfi-101.0 expects x ==> OK.
  testing srfi-101.1 expects #t ==> OK.
  ...

(All tests pass)

But if I run the full test suite, it fails.

==== Testing R5RS pitfall  ...                                   passed
**** Error while executing file "do-test.stk"

EXIT
make[1]: *** [Makefile:483: test] Error 70
make[1]: Leaving directory '/home/jeronimo/pkg/scheme/STklos-jpellegrini/tests'
make: *** [Makefile:881: test] Error 2

jpellegrini avatar Jul 01 '22 15:07 jpellegrini

The quote problem is really tricky. I've tried

  • making quote a macro which uses a %%quote special form;
  • having both quote and %%quote special forms, and making srfi101:quote use the second one
  • using only quasiquote in srfi101:quote (but compile-quasiquote will introduce quotes...)

jpellegrini avatar Jul 27 '22 02:07 jpellegrini

Adapted to the new lib/scheme / lib/srfi organization. but this one needs some careful consideration, I suppose, because of the issues described.

jpellegrini avatar Oct 09 '22 23:10 jpellegrini

Adapted to the new lib/scheme / lib/srfi organization. but this one needs some careful consideration, I suppose, because of the issues described.

I'll have a look at this point. But as you said before, this is a more general problem with the redefinition of basic macros.

egallesio avatar Nov 23 '22 20:11 egallesio

Just registering one idea:

  • Create the macro programmatically in C (the expander is easily written as a primitive, and we can build the structure in C also);
  • Then checking for quote wouldn't be necessary in the compiler! When it checks if the form is a macro usage, that "primitive" macro will be there. And it would be rebindable.
  • (Maybe this also works for other special forms)

jpellegrini avatar Sep 02 '23 14:09 jpellegrini

Create the macro programmatically in C (the expander is easily written as a primitive, and we can build the structure in C also);

I just tried... That, by itself, doesn't help. But perhaps a new structure, [quoted-form] (or [self-eval]) would do?

  • The fundamental quote would return quoted forms;
  • The compiler would recognize that, and not try to eval them.

Maybe

  • a SELF_EVALP macro that tests a bit in the header of Scheme objects
  • %self-evaluating? that quote would set, and the compiler would check
  • %self-evaluate-set!, which quote would use to set, and perhaps other parts of STklos could use to UNset the self-evaluation flag...

jpellegrini avatar Sep 02 '23 15:09 jpellegrini

I have this implemented, partially:

stklos> (define x '(+ 2 3))
;; x
stklos> x
(+ 2 3)
stklos> (eval x)
5
stklos> (%self-evaluating? x)
#f
stklos> (%self-evaluate-set! x #t)
stklos> (%self-evaluating? x)
#t
stklos> (eval x)
(+ 2 3)
stklos> (%self-evaluate-set! x #f)
stklos> (%self-evaluating? x)
#f
stklos>  (eval x)
5

Maybe this will make it easier to implement a redefinable quote. I'll continue in a separate PR when I get it to work.

EDIT: Not good -- quasiquote & recursive evaluation would defeat that. But a new quote structure can help.

jpellegrini avatar Sep 02 '23 17:09 jpellegrini