Actually, it would have been nice to have something like (prepend-toplevel-form syntax) Because then you could have done somthing like (define-syntax rx (lambda (x) (syntax-case x () ((_ pat) (with-syntax (((nm) (generate-temporaries (list #'pat)))) (prepend-toplevel-form #'(define nm (make-regexp pat))) #'(let ((val (hash-ref defined 'nm err))) (if (eq? val err) (let ((val (make-regexp pat))) (hash-set! defined 'nm val) val) val)))))))) On Thu, Feb 11, 2016 at 10:37 AM, Stefan Israelsson Tampe < stefan.itampe@gmail.com> wrote: > the result of eval-when will be available only att specified phases. So > your eval-when code will not be available > except at expansion. Also it looks like you want to precompile the > regexes. This is not a stupid idea and should > be done at load time because regexp literals is not supported by guile > scheme. > > I'm not sure what the best way to implement this is but why not memoize > the value of the regexp like in > > (define err (cons 'not 'defined) > (define defined (make-hash-table)) > (define-syntax rx > (lambda (x) > (syntax-case x () > ((_ pat) > (with-syntax (((nm) (generate-temporaries (list #'pat)))) > #'(let ((val (hash-ref defined 'nm err))) > (if (eq? val err) > (let ((val (make-regexp pat))) > (hash-set! defined 'nm val) > val) > val)))))))) > > use it as > > #'(let ((id (rx pat)) ...) > (cond > ((regexp-exec id str) => > (lambda (m) (rx-let m (v ...) exp ...))) > ... > (else else-exp ...))))) > > Ideally you should be able to generate the regexp at loading as you want > to do but I don't think it is supported. > > Regards > Stefan > > > On Thu, Feb 11, 2016 at 5:28 AM, Matt Wette > wrote: > >> I am trying to get a macro to expand at compile time using eval-when, but >> it’s not giving me what I expect: >> >> (eval-when (expand) (make-regexp pat)) … >> >> gets expanded to: >> >> (if #f #f) >> >> I would like to see something like >> >> # >> >> Any help would be appreciated. — Matt >> >> I get the same (if #f #f) result whether I use (expand) or (compile). >> >> Below is >> 1) my macro (missing the helpers all-const-string? and rx-let) >> 2) the macro I use to compile to il-tree and then back to scheme >> 3) the demo code >> 4) the output from expand >> >> === my macro ========================== >> (define-syntax regexp-case >> (lambda (x) >> (syntax-case x (else) >> ((_ str ((pat v ...) exp ...) ... (else else-exp ...)) >> (with-syntax (((id ...) (generate-temporaries #'(pat ...)))) >> (all-const-string? #'(pat ...)) >> #'(let ((id (eval-when (expand) (make-regexp pat))) ...) >> (cond >> ((regexp-exec id str) => >> (lambda (m) (rx-let m (v ...) exp ...))) >> ... >> (else else-exp ...))))) >> ((_ str ((pat v ...) exp ...) ...) >> (with-syntax (((id ...) (generate-temporaries #'(pat ...)))) >> (all-const-string? #'(pat ...)) >> #'(let ((id (eval-when (expand) (make-regexp pat))) ...) >> (cond >> ((regexp-exec id str) => >> (lambda (m) (rx-let m (v ...) exp ...))) >> ... >> (else >> (scm-error #f "regexp-case" >> "no match found: ~S" (list str) >> #f))))))))) >> >> === the expand macro ======================= >> >> #:use-module (srfi srfi-11) >> >> #:use-module (system base compile) >> >> >> (define* (expand-form e #:key (opts '())) >> >> (let-values (((exp env) (decompile >> >> (compile e #:from 'scheme >> >> #:to 'tree-il >> >> #:env (current-module)) >> >> #:from 'tree-il >> >> #:to 'scheme >> >> #:opts opts))) >> >> exp)) >> >> >> (define-syntax-rule (expand _expression_) >> >> (expand-form '_expression_)) >> >> === orig test case ================ >> (regexp-case str >> (("^([a-z]+)\\(([0-9]+)\\)$" v i) >> (list v i)) >> (("^([a-z]+)$" v) >> (list v "1"))) >> >> === output from expand ============= >> >> (let ((t-768 (if #f #f)) >> >> (t-769 (if #f #f))) >> >> (let ((t (regexp-exec t-768 str))) >> >> (if t >> >> (let ((m t)) >> >> (let ((v (match:substring m 1)) >> >> (i (match:substring m 2))) >> >> (list v i))) >> >> (let ((t (regexp-exec t-769 str))) >> >> (if t >> >> (let* ((m t) (v (match:substring m 1))) >> >> (list v "1")) >> >> (scm-error >> >> #f >> >> "regexp-case" >> >> "no match found: ~S" >> >> (list str) >> >> #f)))))) >> >> >