commit 4a09246307bdf0a2d745efba75049d3af424c457
Author: Georges Dupéron <georges.duperon@gmail.com>
Date: Tue, 25 Apr 2017 16:39:36 +0200
Initial commit
Diffstat:
7 files changed, 173 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,6 @@
+*~
+\#*
+.\#*
+.DS_Store
+compiled/
+/doc/
diff --git a/.travis.yml b/.travis.yml
@@ -0,0 +1,37 @@
+language: c
+sudo: false
+
+env:
+ global:
+ # RACKET_DIR is an argument to install-racket.sh
+ - RACKET_DIR=~/racket
+ - PATH="$RACKET_DIR/bin:$PATH"
+ matrix:
+ # RACKET_VERSION is an argument to install-racket.sh
+ - RACKET_VERSION=6.0 COV=false
+ - RACKET_VERSION=6.1 COV=false
+ - RACKET_VERSION=6.1.1 COV=false
+ - RACKET_VERSION=6.2 COV=false
+ - RACKET_VERSION=6.3 COV=true
+ - RACKET_VERSION=6.4 COV=true
+ - RACKET_VERSION=6.5 COV=true
+ - RACKET_VERSION=6.6 COV=true
+ - RACKET_VERSION=6.7 COV=true
+ - RACKET_VERSION=6.8 COV=true
+ - RACKET_VERSION=RELEASE COV=true
+ - RACKET_VERSION=HEAD COV=true
+
+before_install:
+- curl -L https://raw.githubusercontent.com/greghendershott/travis-racket/master/install-racket.sh | bash
+- if $COV; then raco pkg install --deps search-auto doc-coverage cover cover-codecov; fi # or cover-coveralls
+
+install:
+- raco pkg install --deps search-auto -j 2
+
+script:
+- raco test -x -p "$(basename "$TRAVIS_BUILD_DIR")"
+- if $COV; then raco setup --check-pkg-deps --no-zo --no-launcher --no-install --no-post-install --no-docs --pkgs "$(basename "$TRAVIS_BUILD_DIR")"; fi
+- if $COV; then raco doc-coverage "$(basename "$TRAVIS_BUILD_DIR")"; fi
+- if $COV; then raco cover -s main -s test -s doc -f codecov -f html -d ~/coverage . || true; fi
+# TODO: add an option to cover to run the "outer" module too, not just the submodules.
+# TODO: deploy the coverage info.
+\ No newline at end of file
diff --git a/LICENSE.txt b/LICENSE.txt
@@ -0,0 +1,11 @@
+chain-module-begin
+Copyright (c) 2017 georges
+
+This package is distributed under the GNU Lesser General Public
+License (LGPL). This means that you can link chain-module-begin into proprietary
+applications, provided you follow the rules stated in the LGPL. You
+can also modify this package; if you distribute a modified version,
+you must distribute it under the terms of the LGPL, which in
+particular means that you must release the source code for the
+modified software. See http://www.gnu.org/copyleft/lesser.html
+for more information.
diff --git a/README.md b/README.md
@@ -0,0 +1,3 @@
+chain-module-begin
+==================
+README text here.
diff --git a/info.rkt b/info.rkt
@@ -0,0 +1,11 @@
+#lang info
+(define collection "chain-module-begin")
+(define deps '("base"
+ "rackunit-lib"
+ "debug-scopes"))
+(define build-deps '("scribble-lib"
+ "racket-doc"))
+(define scribblings '(("scribblings/chain-module-begin.scrbl" ())))
+(define pkg-desc "Use this to build meta-languages, where a #%module-begin expands to the #%module-begin of another user-specified language.")
+(define version "0.1")
+(define pkg-authors '("Georges Dupéron"))
diff --git a/main.rkt b/main.rkt
@@ -0,0 +1,29 @@
+#lang racket/base
+
+(provide chain-module-begin)
+
+(require (for-syntax racket/base
+ syntax/parse
+ debug-scopes/named-scopes/exptime))
+
+(define-syntax continue
+ (syntax-parser
+ [(_ whole-ctx lang lang-modbeg . body)
+ #:with ({~literal #%plain-module-begin} . expanded-body)
+ (local-expand (datum->syntax #'whole-ctx
+ `(,#'lang-modbeg . ,#'body)
+ #'whole-ctx)
+ 'module-begin
+ '())
+ (define new-scope (make-module-like-named-scope
+ (format "nested-lang-~a" (syntax-e #'lang))))
+ (new-scope #`(begin . expanded-body))]))
+
+(define-syntax chain-module-begin
+ (syntax-parser
+ [{~and whole (_ lang . body)}
+ #:with lang-modbeg (datum->syntax #'lang '#%module-begin #'lang)
+ #:with whole-ctx (datum->syntax #'whole 'ctx #'whole)
+ #'(#%plain-module-begin
+ (require lang)
+ (continue whole-ctx lang lang-modbeg . body))]))
+\ No newline at end of file
diff --git a/scribblings/chain-module-begin.scrbl b/scribblings/chain-module-begin.scrbl
@@ -0,0 +1,73 @@
+#lang scribble/manual
+@require[@for-label[chain-module-begin
+ racket/base]]
+
+@title{Chaining module languages}
+@author[@author+email["Georges Dupéron" "georges.duperon@gmail.com"]]
+
+@defmodule[chain-module-begin]
+
+This package is experimental. Later versions may break backward-compatibility.
+
+@defform[(chain-module-begin lang . body)]{
+ This macro is intended to be used as the result of a @racket[#%module-begin]
+ macro. It chain-calls the @racket[#%module-begin] of @racket[lang]. This makes
+ it possible for a @racket[#%module-begin] to perform some changes on its body,
+ and then chain-call the @racket[#%module-begin] of a user-specified language.
+
+ As an example here is the definition for a no-op language, which simply takes a
+ (possibly improper) list of languages to chain, and calls the next one:
+
+ @racketblock[
+ (module the-meta-lang racket/base
+ (provide (rename-out [new-#%module-begin #%module-begin]))
+
+ (require chain-module-begin
+ (for-syntax racket/base
+ syntax/parse))
+
+ (define-syntax (new-#%module-begin stx)
+ (syntax-parse stx
+ [(_ {~or next-lang:id (next-lang:id . chain₊)} . body)
+ (define maybe-chain₊ (if (attribute chain₊)
+ `(,#'chain₊)
+ '()))
+ (define new-form `(,#'chain-module-begin ,#'next-lang ,@maybe-chain₊
+ . ,(transform-body #'body)))
+ (datum->syntax stx new-form stx stx)]))
+
+ (define-for-syntax (transform-body body)
+ (code:comment "identity transformation:")
+ body))]
+
+ This language could then be used as follows:
+
+ @racketblock[
+ (module b the-meta-lang typed/racket
+ (define x : Number 123))]
+
+ Given two other meta-language built in the same way and provided by
+ @racketid[meta-two] and @racketid[meta-three], it would be possible
+ to chain the three languages as follows:
+
+ @racketblock[
+ (module b the-lang (meta-two meta-three . typed/racket)
+ (define x : Number 123))]
+
+ The @racket[chain-module-begin] macro produces the following syntax:
+
+ @racketblock[(#%plain-module-begin
+ (require lang)
+ (continue . internal-args))]
+
+ where @racket[(continue . _internal-args)] fully expands
+ @racket[(#%module-begin . body)], where @racket[#%module-begin] is the one
+ provided by @racket[lang], and produces the following syntax:
+
+ @racketblock[(begin . _expanded-body)]
+
+ An extra scope is added to the whole @racket[(begin . _expanded-body)] form,
+ so that a @racket[#%require] form within the @racket[_expanded-body] may
+ shadow bindings provided by @racket[lang], just as @racket[require] forms
+ normally have the possibility to shadow bindings provided by the @(hash-lang)
+ language.}
+\ No newline at end of file