Re: [racket-users] identifier used out of context

2020-06-09 Thread Anthony Carrico
On 6/9/20 12:57 PM, Anthony Carrico wrote:
> (letrec ((super0 (combine initial (overlay0 self initial)))
>  (super1 (combine super0 (overlay1 self super0)))
>  (super2 (combine super1 (overlay2 self super1)))
>  ;; etc...
>  (final superN))
>   ;; "self" is the desired binding context.
>   ;; "superX" are the staged binding contexts along the way.
>   self)

Oops, sorry, I change the identifier from "final" to "self", but forgot
to change the binding:

(letrec ((super0 (combine initial (overlay0 self initial)))
 (super1 (combine super0 (overlay1 self super0)))
 (super2 (combine super1 (overlay2 self super1)))
 ;; etc...
 (self superN))
  ;; "self" is the desired binding context.
  ;; "superX" are the staged binding contexts along the way.
  self)

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/c340c01e-1c6d-70e1-0325-da2a324a70d5%40memebeam.org.


Re: [racket-users] identifier used out of context

2020-06-09 Thread Anthony Carrico
On 6/7/20 9:23 PM, Alexis King wrote:
>     #lang racket
>     (define-syntax-rule (m) (displayln 'old))
>     (let ()
>       (m)
>       (define-syntax-rule (m) 'new)
>       (void))

I think you meant:

(define-syntax-rule (m) (displayln 'old))
(let ()
  (m)
  (define-syntax-rule (m) (displayln 'new))
  (m)
  (void))

which prints:

old
new

And as usual, Alexis points right to the heart of the problem. All the
way back in Dybvig's psyntax expander, definition contexts are partially
expanded to uncover definitions, and then fully expanded in a second
step. Flatt's papers dig deeper (I hope he is reading this thread). I
will quote one thing directly from Alexis, "resolution of macro bindings
also involves a /temporal/ component, since the compile-time binding
table evolves as the program is expanded."

I'd love to hear your idea of a satisfying semantics to aim for, even if
it doesn't match scheme/racket historical semantics. In the meantime,
I'll draw your attention to another community which has evolved a
potential solution to the "hopeless top level":

Nix is a lazy functional language which is primarily used to define
binding contexts--very much like our "hopeless" definition
contexts--primarily for unix package configuration. The concept of an
"overlay" has emerged (this term might be overloaded in Nix).

An overlay represent a step in the fixed point definition of a binding
context.

Recall the Alexis quote, "resolution of ... bindings ... involves a
/temporal/ component," well in Nix an overlay is a step in the fixed
point definition of a binding context.

It probably isn't proper to call this "temporal", but it is a sequence
of definition contexts which lead to the ultimate desired set of
definitions (the "fixed point" of the computation).

As a racket procedure, an overlay would be defined something like this:

(define (overlay self super) ...etc...)

Overlay is a function ("macro"). It takes two sets of bindings, and
produces a third. Self and super are the conventional names (not great
names) for the parameters.

In the overlay system, a binding context is defined by chaining together
a bunch of overlays. Something like this:

(letrec ((super0 (combine initial (overlay0 self initial)))
 (super1 (combine super0 (overlay1 self super0)))
 (super2 (combine super1 (overlay2 self super1)))
 ;; etc...
 (final superN))
  ;; "self" is the desired binding context.
  ;; "superX" are the staged binding contexts along the way.
  self)

Now of course just like with macros, there can be overlay producing
overlays etc. If you look at an overlay as a macro, it has simultaneous
access to the entire structure of the  of the bindings via the two
handles, self and super, together with whatever bindings are stashed
away by other overlays. You could imagine a sequence of bindings
contexts in which one definition of cc, compiles the next, bootstrapping
a compiler from its initial version, for example, or even one version of
an overlay bootstrapping another overlay.

There are conventions making use of self and super when writing an
overlay. You, and your downstream peers in the chain, will be overriding
the ones in super, if you provide something from self, you know it is
the stable final result.

Isn't there some solid semantics for a hopeful top level in this idea?

-- 
Anthony Carrico

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/ba63f17b-366a-d87e-b1f4-9009952bd805%40memebeam.org.


Re: [racket-users] identifier used out of context

2020-06-07 Thread Alexis King
> On Jun 7, 2020, at 17:44, Sorawee Porncharoenwase  
> wrote:
> 
> Wow, so block is currently buggy?!
> 

This issue isn’t with `block`, per se (though `block` could cooperate more 
nicely with definition context expansion to avoid this problem). You can 
reproduce it without any first-class definition contexts at all:

#lang racket
(define-syntax-rule (m) (displayln 'old))
(let ()
  (m)
  (define-syntax-rule (m) 'new)
  (void))

Arguably, the real issue is the mechanism behind Check Syntax. Check Syntax 
collects information about uses and bindings from the fully-expanded program, 
but that is not straightforward for macro uses and local macro bindings, since 
those go away after expansion. So the expander annotates the program with 
information about disappeared identifier uses and disappeared local bindings 
using the 'origin, 'disappeared-use, and 'disappeared-binding syntax properties.

The hope is that the binding structure of the source program can be 
reconstructed from the fully-expanded program by inspecting identifiers’ 
scopes. This seems plausible, since the scopes of a fully-expanded program 
dictate the binding structure of runtime variables by definition. However, this 
example reveals a flaw in that logic: resolution of macro bindings also 
involves a temporal component, since the compile-time binding table evolves as 
the program is expanded.

Frankly, this temporal dependency is unsatisfying. For runtime bindings, we 
enjoy predictable recursive definition contexts and inter-module lexical 
binding, courtesy of the module system. But to paraphrase Matthew, resolution 
of compile-time bindings is “distressingly like the top level,” since it 
requires interleaving of expansion and evaluation in a similar way.

I think this suggests that perhaps there is something fundamentally incomplete 
in our model of macroexpansion. However, it seems impossible to solve this 
problem without somehow restricting the macro language: the status quo allows 
macros to both (a) expand to absolutely anything via arbitrary procedural logic 
and (b) perform arbitrary side-effects, which allows them to observe expansion 
order. A more restrictive model could require macros to declare more 
information up front (which would allow the macroexpander to learn more about 
the binding structure of a program without fully expanding macros) or could 
provide access to state through restricted channels in such a way that the 
expander could “speculatively” expand a macro, then go back later and change 
its mind.

Of course, these would both require radical, deeply incompatible changes to the 
Racket macro system, so I do not expect them to actually be implemented! But 
perhaps they can be food for thought.

Alexis

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/D48BCCBB-AE1F-47CC-93E8-B90D1129E169%40gmail.com.


[racket-users] identifier used out of context

2020-06-05 Thread Sorawee Porncharoenwase
Hi Racketeers,

I’m creating a macro that collects values in the internal-definition
context. E.g.,

($list
 1
 (define x 2)
 x)

should evaluate to '(1 2).

Here’s my implementation, and it kinda works:

#lang racket

(begin-for-syntax
  (define ((do-it gs ctx) e)
(let loop ([e e])
  (define e-expanded (local-expand e (list gs) #f ctx))
  (syntax-case e-expanded (begin define-syntaxes define-values)
[(begin body ...)
 #`(begin #,@(map loop (syntax->list #'(body ...]
[(define-values ids e)
 (begin
   (syntax-local-bind-syntaxes (syntax->list #'ids) #f ctx)
   e-expanded)]
[(define-syntaxes ids e)
 (begin
   (syntax-local-bind-syntaxes (syntax->list #'ids) #'e ctx)
   #'(begin))]
[e #'(set! acc (cons e acc))]

(define-syntax ($list stx)
  (define gs (gensym))
  (define ctx (syntax-local-make-definition-context))
  (syntax-case stx ()
[(_ body ...)
 #`(let ([acc '()])
 #,@(map (do-it gs ctx) (syntax->list #'(body ...)))
 (reverse acc))]))

($list 1
   (define x 2)
   x)

There are problems though. If I change define to define2 as follows:

(define-syntax-rule (define2 x y)
  (define-values (x) y))

($list 1
   (define2 x 2)
   x)

Then I get the “identifier used out of context” error. This doesn’t make
sense to me at all. My define2 should be very similar to define…

There’s also another weird problem:

($list 1
   (define-syntax (x stx) #'2)
   x)

The above works perfectly, but by wrapping x with #%expression, I get the
“identifier used out of context” error again.

($list 1
   (define-syntax (x stx) #'2)
   (#%expression x))

What did I do wrong?

Thanks!

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CADcuegtJKvcG0kMFp1k2yn8HfGTo5s7z2U2uW2fHF2qa1FQ5_g%40mail.gmail.com.