diff --git a/implementation.rkt b/implementation.rkt index 82e643e..67beb3b 100644 --- a/implementation.rkt +++ b/implementation.rkt @@ -1,7 +1,8 @@ #lang racket (provide #%dotted-id #%dot-separator - (rename-out [new-#%module-begin #%module-begin])) + (rename-out [new-#%module-begin #%module-begin] + [new-#%top-interaction #%top-interaction])) (require typed/racket) @@ -43,6 +44,13 @@ . #,(fold-syntax replace-dots #'body))])) +(define-syntax (new-#%top-interaction stx) + (syntax-case stx () + [(_ . body) + #`(#%top-interaction + . #,(fold-syntax replace-dots + #'body))])) + (define-for-syntax (make-λ l args e percent?) (define percent* (if (and percent? (>= (length args) 1)) diff --git a/lang/reader.rkt b/lang/reader.rkt index bf38e24..63ffa36 100644 --- a/lang/reader.rkt +++ b/lang/reader.rkt @@ -1,2 +1,2 @@ (module reader syntax/module-reader - dotlambda/lang) \ No newline at end of file + dotlambda) \ No newline at end of file diff --git a/main.rkt b/main.rkt index 2f20414..50051f4 100644 --- a/main.rkt +++ b/main.rkt @@ -1,6 +1,8 @@ #lang racket -(require dotlambda - (except-in typed/racket #%module-begin)) +(require dotlambda/implementation + (except-in typed/racket + #%module-begin + #%top-interaction)) (provide (except-out (all-from-out typed/racket)) - (all-from-out dotlambda)) \ No newline at end of file + (all-from-out dotlambda/implementation)) \ No newline at end of file diff --git a/scribblings/dotlambda.scrbl b/scribblings/dotlambda.scrbl index 8b512e5..c7dda6f 100644 --- a/scribblings/dotlambda.scrbl +++ b/scribblings/dotlambda.scrbl @@ -1,5 +1,6 @@ #lang scribble/manual -@require[@for-label[dotlambda]] +@require[@for-label[@only-in[dotlambda #%dot-separator #%dotted-id] + racket/stxparam]] @title{Dotted identifiers and @racket[λ.code] syntax} @author[@author+email["Georges Dupéron" "georges.duperon@gmail.com"]] @@ -39,18 +40,46 @@ following: @racket[..+], @racket[...+], @racket[..*], @racket[...*], @racket[…], @racket[…+], @racket[…*] and @racket[::...].}] - Furthermore the syntax @racket[λvar.(expr …)] is recognised as a shorthand for - @racket[(λ (var) (expr …))], so that @racket[λx.(+ x 2)] is translated to - @racket[(λ (x) (+ x 2))]. If the @racket[_var] part is left empty, then it - defaults to @racket[%], so that @racket[λ.(+ % 2)] is translated to - @racket[(λ (%) (+ % 2))].} + Furthermore the syntax @racket[λarg₁.arg₂.….argₙ.(expr …)] is recognised as a + shorthand for @racket[(λ (arg₁ arg₂ … argₙ) (expr …))], so that + @racket[λx.(+ x 2)] is roughly translated to @racket[(λ (x) (+ x 2))]. If the + @racket[_var] part is left empty, then it defaults to @racket[%1], @racket[%2] + and so on. The number of parameters is determined from the syntactical + contents of the function's body, before performing macro-expansion. The term + @racket[λ.(+ %1 %2)] is therefore roughly translated to + @racket[(λ (%1 %2) (+ %1 %2))]. The variable named @racket[%] can be used as a + shorthand for @racket[%1], so that @racket[λ.(+ % 10)] is therefore roughly + translated to @racket[(λ (%) (+ % 10))]. -@section{Module language for @racket[dotlambda]} + Since this substitution is performed on the whole program, before + macro-expansion, these notations are performed regardless of the context in + which an expression occurs. For example, the quoted term @racket['a.b] will + also get translated to @racket['(#%dotted-id a #%dot-separator b)]. In this + way, the @racket[#%module-begin] from @racket[dotlambda] works a bit like if + it were a reader extension. -@defmodulelang[dotlambda/lang]{ - This language is equivalent to - @racket[#,(hash-lang) #,(racketmodname dotlambda)], but can also be used as - a module language. -} + @bold{Warning:} There probably are some issues with hygiene, especially in + mixed contexts (e.g. literate programs, or typed/racket programs with untyped + code at phase 1). I will think about these issues and adjust the behaviour in + future versions. Future versions may therefore not be 100% backward-compatible + with the current version, but the general syntax of dotted identifiers should + hopefully not change much.} +@defform[#:kind "syntax parameter" + (#%dotted-id ids-and-separators …)]{ + The default implementation currently translates @racket[a.b.c.d] to + @racket[(d (c (b a)))], and @racket[.a.b.c] to + @racket[(λ (x) (c (b (a x))))]. + This behaviour can be altered using @racket[syntax-parameterize]. I don't + think syntax parameters can be modified globally for the whole containing file + like parameters can (via @racket[(param new-value)]), so the exact mechanism + used to customise the behaviour of @racket[#%dotted-id] may change in the + future.} + +@defidform[#%dot-separator]{ + Indicates the presence of a (possibly implicit) dot. The original string + (usually @racket["."] or the empty string @racket[""] for an implicit dot + before or after an ellipsis) is normally stored in the + @racket['dotted-original-chars] syntax property of the occurrence of the + @racket[#%dot-separator] identifier.} \ No newline at end of file