Stupid email client, ... one more try
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)))
#'nm)))))
and use it as previous mail
On Thu, Feb 11, 2016 at 11:08 AM, Stefan Israelsson Tampe <
[email protected]> wrote:
> 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 <
> [email protected]> 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 <[email protected]>
>> 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
>>>
>>> #<regexp 1098a2d40>
>>>
>>> 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))))))
>>>
>>>
>>
>