#lang scheme/base
(require (for-syntax scheme/base)
scheme/contract
scheme/match)
(define (symbolic-identifier=? id1 id2)
(eq? (syntax->datum id1)
(syntax->datum id2)))
(define (make-id stx . args)
(datum->syntax stx (string->symbol (apply string-append (map atom->string args)))))
(define-syntax (begin-for-syntax/any-order stx)
(define (expand-definition-name stx)
(syntax-case stx (define)
[(define (name arg ...) expr ...) #'name]
[(define name expr) #'name]))
(define (expand-definition stx)
(syntax-case stx (define)
[(define (name arg ...) expr ...) #'(name (lambda (arg ...) expr ...))]
[(define name expr) #'(name expr)]))
(syntax-case stx ()
[(_ definition ...)
(let* ([definitions (syntax->list #'(definition ...))]
[names (map expand-definition-name definitions)]
[letrec-clauses (map expand-definition definitions)])
#`(define-values-for-syntax #,names
(letrec #,letrec-clauses
(values #,@names))))]))
(define (syntax-location-string stx)
(define source
(match (syntax-source stx)
[(? path? src)
(let-values ([(base name must-be-dir?) (split-path src)])
name)]
[(? string? src)
(match (regexp-match #rx"[^\\/\\\\]+$" src)
[(list filename) filename]
[other "unknown.ss"])]
[other "unknown.ss"]))
(define line
(or (syntax-line stx) ""))
(define column
(or (and (syntax-line stx) (syntax-column stx))
(syntax-position stx)
""))
(format "~a:~a:~a" source line column))
(define-values (dotted-identifier? split-dotted-identifier)
(let ([rx #rx"([^.][^.]*)[.](..*)"])
(values (lambda (stx)
(and (identifier? stx)
(let ([str (symbol->string (syntax->datum stx))])
(regexp-match rx str))
#t))
(lambda (stx)
(if (dotted-identifier? stx)
(let* ([str (symbol->string (syntax->datum stx))]
[match (regexp-match rx str)])
(map (lambda (str)
(datum->syntax stx (string->symbol str)))
(cdr match)))
(raise-syntax-error #f "expected dotted identifier" stx))))))
(define (atom->string atom)
(cond [(string? atom) atom]
[(symbol? atom) (symbol->string atom)]
[(number? atom) (number->string atom)]
[(syntax? atom) (atom->string (syntax->datum atom))]
[else (error "Expected (syntax of) (U symbol string number), received: " atom)]))
(provide begin-for-syntax/any-order)
(provide/contract
[symbolic-identifier=? (-> syntax? syntax? boolean?)]
[make-id (->* ((or/c syntax? false/c)) ()
#:rest (listof (or/c string? symbol? number? syntax?))
syntax?)]
[syntax-location-string (-> syntax? string?)]
[dotted-identifier? (-> syntax? boolean?)]
[split-dotted-identifier (-> syntax? (list/c syntax? syntax?))])