You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pollen/main-helper.rkt

71 lines
3.1 KiB
Racket

#lang racket
(require (for-syntax (planet mb/pollen/tools) (planet mb/pollen/world)))
(require (planet mb/pollen/tools) (planet mb/pollen/world))
(require racket/contract/region)
(provide (all-defined-out))
(module+ test (require rackunit))
;; Look for an EXTRAS_DIR directory local to the source file.
;; and require all the .rkt files therein.
;; optionally provide them.
(define-syntax (require-extras stx #:provide [provide #f])
(cond
[(directory-exists? EXTRAS_DIR)
;; This will be resolved in the context of current-directory.
;; So when called from outside the project directory,
;; current-directory must be properly set with 'parameterize'
(define (make-complete-path path)
(define-values (start_dir name _ignore) (split-path (path->complete-path path)))
(build-path start_dir EXTRAS_DIR name))
(define files (map make-complete-path (filter (λ(i) (has-ext? i 'rkt)) (directory-list EXTRAS_DIR))))
(define files-in-require-form
(map (λ(file) `(file ,(as-string file))) files))
(datum->syntax stx
(if provide
`(begin
(require ,@files-in-require-form)
(provide (all-from-out ,@files-in-require-form)))
`(begin
(require ,@files-in-require-form))))]
; if no files to import, do nothing
[else #'(begin)]))
;; here = name of current file without extensions.
;; We want to make this identifier behave as a runtime function
;; This requires two steps.
;; First, define the underlying function as syntax-rule
(define-syntax (get-here stx)
(datum->syntax stx
'(begin
;; Even though begin permits defines,
;; This macro might be used in an expression context,
;; whereupon define would cause an error.
;; Therefore, best to use let.
(let* ([ccr (current-contract-region)] ; trick for getting current module name
[ccr (cond
;; if contract-region is called from within submodule,
;; you get a list
;; in which case, just grab the path from the front
[(list? ccr) (car ccr)]
;; file isn't yet saved in drracket
[(equal? 'pollen-lang-module ccr) 'nowhere]
[else ccr])])
(match-let-values ([(_ here-name _) (split-path ccr)])
(as-string (remove-all-ext here-name)))))))
(module+ test
(check-equal? (get-here) "main-helper"))
; Second step: apply a separate syntax transform to the identifier itself
; We can't do this in one step, because if the macro goes from identifier to function definition,
; The macro processor will evaluate the body at compile-time, not at runtime.
(define-syntax here (λ (stx) (datum->syntax stx '(get-here))))
(module+ test
(check-equal? here "main-helper"))