diff --git a/graph/graph/graph2.lp2.rkt b/graph/graph/graph2.lp2.rkt index fe9679e..986f5cb 100644 --- a/graph/graph/graph2.lp2.rkt +++ b/graph/graph/graph2.lp2.rkt @@ -18,10 +18,10 @@ name. For example, a graph representing a city and its inhabitants could use these variants: @chunk[ - [City (Listof Street) (Listof Person)] - [Street (Listof House)] - [House Person Street] - [Person String]] + [City [streets : (Listof Street)] [inhabitants : (Listof Person)]] + [Street [houses : (Listof House)]] + [House [owner : Person] [location : Street]] + [Person [name : String]]] Notice the cycle in the type: a street contains houses, which are located on the same street. @@ -192,10 +192,11 @@ flexible through wrapper macros. @chunk[ (make-graph-constructor - ([node field-type ...] ...) + ([node [field-name:id (~literal :) field-type:expr] ...] ...) (root-expr:expr ...) - [(mapping [param (~literal :) param-type] ...) (~literal :) result-type - body] + [(mapping:id [param:id (~literal :) param-type:expr] ...) + (~literal :) result-type:expr + . body] ...)] The macro relies heavily on two sidekick modules: @tc[rewrite-type], and @@ -323,15 +324,25 @@ which return type is the desired node type. @; TODO: use a type-expander here, instead of a template metafunction. -@CHUNK[ - (define-type node/incomplete-type - (tmpl-replace-in-type (List 'node field-type ...) +@CHUNK[ + (define-type field/incomplete-type + (tmpl-replace-in-type field-type ([node (U node/incomplete-type - mapping/placeholder-type ...)] ...)))] + mapping/placeholder-type ...)] ...))) + ... + + (define-type node/incomplete-type (List 'node field/incomplete-type …)) + + (: node/make-incomplete (→ field/incomplete-type … node/incomplete-type)) + (define (node/make-incomplete field-name …) + (list 'node field-name …))] @chunk[ - (define-temp-ids "~a/make-incomplete" (node ...)) - (define-temp-ids "~a/incomplete-type" (node ...))] + (define-temp-ids "~a/make-incomplete" (node …)) + (define-temp-ids "~a/incomplete-type" (node …)) + ;; TODO: format-ids doesn't accept arbitrary values. Should we change it? + (define/with-syntax ((field/incomplete-type …) …) + (stx-map generate-temporaries #'((field-type …) …)))] @subsection{Processing the placeholders} @@ -354,6 +365,7 @@ which return type is the desired node type. (let () (begin ) ... (begin ) ... + (begin ) ... )))] @section{Conclusion} @@ -362,6 +374,7 @@ which return type is the desired node type. (module main typed/racket (require (for-syntax syntax/parse racket/syntax + syntax/stx syntax/parse/experimental/template "rewrite-type.lp2.rkt" "../lib/low-untyped.rkt") diff --git a/graph/lib/low.rkt b/graph/lib/low.rkt index e0323f9..37f5924 100644 --- a/graph/lib/low.rkt +++ b/graph/lib/low.rkt @@ -170,7 +170,8 @@ nameof first-value second-value third-value fourth-value fifth-value sixth-value seventh-value eighth-value ninth-value tenth-value - (rename-out [compose ∘]) + ∘ + … stx-list stx-e stx-pair @@ -189,6 +190,10 @@ check-duplicate-identifiers generate-temporary) +(require (only-in racket + [compose ∘] + [... …])) + (require (for-syntax syntax/parse syntax/parse/experimental/template)) (: hash-set** (∀ (K V) @@ -474,6 +479,7 @@ [format-id (→ Syntax String (U String Identifier) * Identifier)]) (require (only-in racket/syntax define/with-syntax) + (only-in syntax/stx stx-map) (for-syntax racket/base racket/syntax syntax/parse)) @@ -535,6 +541,13 @@ (define-syntax (define-temp-ids stx) (syntax-parse stx + ;; TODO : factor this with the next case. + [(_ format ((base:id (~literal ...)) (~literal ...))) + #:when (string? (syntax-e #'format)) + (with-syntax ([pat (format-id #'base (syntax-e #'format) #'base)]) + #'(define/with-syntax ((pat (... ...)) (... ...)) + (stx-map (curry format-temp-ids format) + #'((base (... ...)) (... ...)))))] [(_ format (base:id (~literal ...))) #:when (string? (syntax-e #'format)) (with-syntax ([pat (format-id #'base (syntax-e #'format) #'base)])