stxparse-info/6-11/racket/collects/syntax/parse/private/runtime-reflect.rkt

98 lines
4.2 KiB
Racket

#lang racket/base
(require stxparse-info/parse/private/residual ;; keep abs. path
(only-in syntax/parse/private/residual-ct ;; keep abs. path
attr-name attr-depth)
syntax/parse/private/kws)
(provide reflect-parser
(struct-out reified)
(struct-out reified-syntax-class)
(struct-out reified-splicing-syntax-class))
#|
A Reified is
(reified symbol ParserFunction nat (listof (list symbol nat)))
|#
(require (only-in syntax/parse/private/runtime-reflect
reified
reified?
reified-parser
reified-arity
reified-signature
make-reified
struct:reified
reified-syntax-class
reified-syntax-class?
make-reified-syntax-class
struct:reified-syntax-class
reified-splicing-syntax-class
reified-splicing-syntax-class?
make-reified-splicing-syntax-class
struct:reified-splicing-syntax-class))
#;(define-struct reified-base (name) #:transparent)
#;(define-struct (reified reified-base) (parser arity signature))
#;(define-struct (reified-syntax-class reified) ())
#;(define-struct (reified-splicing-syntax-class reified) ())
(define (reflect-parser obj e-arity e-attrs splicing?)
;; e-arity represents single call; min and max are same
(define who (if splicing? 'reflect-splicing-syntax-class 'reflect-syntax-class))
(if splicing?
(unless (reified-splicing-syntax-class? obj)
(raise-type-error who "reified splicing-syntax-class" obj))
(unless (reified-syntax-class? obj)
(raise-type-error who "reified syntax-class" obj)))
(check-params who e-arity (reified-arity obj) obj)
(adapt-parser who
(for/list ([a (in-list e-attrs)])
(list (attr-name a) (attr-depth a)))
(reified-signature obj)
(reified-parser obj)
splicing?))
(define (check-params who e-arity r-arity obj)
(let ([e-pos (arity-minpos e-arity)]
[e-kws (arity-minkws e-arity)])
(check-arity r-arity e-pos e-kws (lambda (msg) (error who "~a" msg)))))
(define (adapt-parser who esig0 rsig0 parser splicing?)
(if (equal? esig0 rsig0)
parser
(let ([indexes
(let loop ([esig esig0] [rsig rsig0] [index 0])
(cond [(null? esig)
null]
[(and (pair? rsig) (eq? (caar esig) (caar rsig)))
(unless (= (cadar esig) (cadar rsig))
(wrong-depth who (car esig) (car rsig)))
(cons index (loop (cdr esig) (cdr rsig) (add1 index)))]
[(and (pair? rsig)
(string>? (symbol->string (caar esig))
(symbol->string (caar rsig))))
(loop esig (cdr rsig) (add1 index))]
[else
(error who "reified syntax-class is missing declared attribute `~s'"
(caar esig))]))])
(define (take-indexes result indexes)
(let loop ([result result] [indexes indexes] [i 0])
(cond [(null? indexes) null]
[(= (car indexes) i)
(cons (car result) (loop (cdr result) (cdr indexes) (add1 i)))]
[else
(loop (cdr result) indexes (add1 i))])))
(make-keyword-procedure
(lambda (kws kwargs x cx pr es fh cp rl success . rest)
(keyword-apply parser kws kwargs x cx pr es fh cp rl
(if splicing?
(lambda (fh x cx pr . result)
(apply success fh x cx pr (take-indexes result indexes)))
(lambda (fh . result)
(apply success fh (take-indexes result indexes))))
rest))))))
(define (wrong-depth who a b)
(error who
"reified syntax-class has wrong depth for attribute `~s'; expected ~s, got ~s instead"
(car a) (cadr a) (cadr b)))