Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rebinding car leads to unexpected behavior #368

Open
jpellegrini opened this issue May 3, 2022 · 11 comments
Open

Rebinding car leads to unexpected behavior #368

jpellegrini opened this issue May 3, 2022 · 11 comments

Comments

@jpellegrini
Copy link
Contributor

Hi @egallesio !

I was working on SRFI 101, which redefines car, cdr etc, and found this:

stklos> 
(define-module x 
  (export (rename mycar car))
  (define (mycar . args)
    (print 'MYCAR)
    (apply car args))) ;; the binding of car used here should be the 
                       ;; one visible at this point, but it doesn't seem to be...

stklos> (import x)
stklos> car
#[closure mycar]
stklos> 

stklos> (car '(1 2 3))
MYCAR
MYCAR
MYCAR
MYCAR
.
.
.  ;; (infinite loop)

Why?

@jpellegrini
Copy link
Contributor Author

Does the call to apply actually retrieve the binding of the procedure at runtime? That would explain this... And maybe also #367 .

@jpellegrini
Copy link
Contributor Author

Aha! It's apply, indeed:

stklos>
(define-module x 
  (export (rename mycar car))
  (define (mycar x)
  (print 'MYCAR) 
  (car x)))

stklos> (import x)
stklos> car
#[closure mycar]
stklos> (car '(1 2 3))
MYCAR
1

@jpellegrini
Copy link
Contributor Author

By the way... I am embarrassed -- I can't find where apply is defined in the source code! Where is it?

@egallesio
Copy link
Owner

Weird.....

I can't find where apply is defined in the source code! Where is it?

in vm.c

@jpellegrini
Copy link
Contributor Author

in vm.c

Ok, I think I understand now... There's this stub:

DEFINE_PRIMITIVE("apply", scheme_apply, apply, (void))
{
  /* This function is never called. It is just here to declare the primitive
   * apply, as a primitive of type tc_apply
   */
  STk_panic("Inside apply. Should not occur");
  return STk_void;
}

But when apply is used in the source code, the VM doesn't call the primitive. Instead, there is this code, which I believe is where the real apply is performed (is this correct?):

    case tc_apply: {
      SCM l, func, *tmp, *argv;
      int len;

      if (nargs == 0) STk_error("no function given to apply");

      nargs -= 1;
      argv   = vm->sp + nargs;
      func   = *argv;
      .
      .
      .

It does func = *argv, which as I understand should take the procedure (and not its name)... But if this was the case, the behavior I showed above would not be possible, right?

@egallesio
Copy link
Owner

Hi @jpellegrini,

I think there is no problem here, in fact 😉 : module x implicitly import module STklos. That means that using car in module x results in using the car of STklos. A simple way to correct this consists in importing the SCHEME module in x.

stklos> (define-module x
  (import SCHEME)
  (export (rename mycar car))
  (define (mycar . args)
    (print 'MYCAR)
    (apply car args)))
;; x
stklos> (import x)
stklos> car
#[closure mycar]
stklos> (car '(1 2 3))
MYCAR
1
stklos> 

You can even use (import (only SCHEME car)), if you don't want to import all STklos.

@jpellegrini
Copy link
Contributor Author

Hi @egallesio !

A simple way to correct this consists in importing the SCHEME module in x.

Thank you. I suppose it will also work with modules created in C. I'll check that later.

@jpellegrini
Copy link
Contributor Author

Hi @egallesio !

It didn't seem to completely fix the issue -- see my comments on PR #404 . One way to reproduce the problem is this:
Get the SRFI 125 implemention from PR #404, remove the s125: prefix from al functions, and set the deb variable in the beginning of the file to #t. Compile, then load SRFI 125 andtry to create hash tables.
It seems that after make-hash-table finishes, STklos internal code runs, and tries to use its internal hash tables -- but it ends up using the hash tables from SRFI-125, and becomse confused by the different signature.

I also tried defining SRFI 125 as R7RS library (not module); and importing SCHEME, as you recommended, but that didn't help...

@jpellegrini
Copy link
Contributor Author

Maybe the internal STklos code could run in a separate module? stklos-internal?

@jpellegrini
Copy link
Contributor Author

And... Is this related to #367 also?

@jpellegrini
Copy link
Contributor Author

Hm, it looks like the code rewriter changed this behavior. It isn't fixed, but... Different!

stklos> (define-module x 
  (export (rename mycar car))
  (define (mycar . args)
    (print 'MYCAR)
    (apply car args))) 
;; x
stklos> (import x)
stklos> car
#[closure mycar]
stklos> (car '(1 2 3))
1

It didn't print MYCAR because the code rewriter changed the car call into 1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants