guile-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: eval-when not giving me what I hoped for


From: Stefan Israelsson Tampe
Subject: Re: eval-when not giving me what I hoped for
Date: Thu, 11 Feb 2016 10:37:38 +0100

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 <address@hidden> 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))))))




reply via email to

[Prev in Thread] Current Thread [Next in Thread]