Stefan Israelsson Tampe <stefan.ita...@gmail.com> writes:

> To note is that in order to implement common lisp one need to bypass tree-il
> and generate directly to glil, the reason is that tagbody is poorly
> represented
> by tree-il. If we intend to be multilingual it would be nice to be able to
> effectively
> represent those ideoms. Any thoughts on it?

At one point I implemented tagbody for a laugh using call/cc. I've
attached the code, but it's kinda lame. I was much less experienced with
continuations and macros then, and I could certainly write it better now.

-- 
Ian Price -- shift-reset.com

"Programming is like pinball. The reward for doing it well is
the opportunity to do it again" - from "The Wizardy Compiled"

(library (tagbody)
(export tagbody go)         
(import (rnrs)
        (for (tagbody utils) expand)
        (for (srfi :8 receive) expand))

(define (go tag)
  (tag #f))

(define-syntax tagbody
  (lambda (stx)
    (define (make-group tag statements next)
      #`(call/cc
         (lambda (escape)
           (call/cc
            (lambda (k)
              (set! #,tag k)
              (escape k)))
           #,@statements
           #,(if next
                 #`(go #,next)
                 #'#f))))
    (define (exprs->groups first-tag list)
      (unzip (plist->alist identifier?
                           (cons first-tag list))))
    (syntax-case stx ()
      [(tagbody tags-or-statements ...)
       (let ((init #'init))
         (receive (tags groups) (exprs->groups
                                 init
                                 (syntax->list #'(tags-or-statements ...)))
           (with-syntax (((entry-point ...) (generate-temporaries tags))
                         ((tag ...) tags)
                         ((group ...)
                          (map make-group tags groups (shift-left tags #f))))
             #`(let ((tag #f) ... (done #f))
                 (let ((entry-point group) ...)
                   (unless done
                     (set! done #t)
                     (go #,init)))))))])))

)
(library (tagbody utils)
(export plist->alist
        shift-left
        unzip
        syntax->list
        )
(import (rnrs))

(define (syntax->list stxobj)
  (define (inner stx)
    (syntax-case stx ()
      [() '()]
      [(x . rest)
       (cons #'x (inner #'rest))]))
  (assert (list? (syntax->datum stxobj)))
  (inner stxobj))

(define (plist->alist car? plist)
  ;; assumes head of (car? plist) is true
  (define (rcons a b)
    (cons (reverse a) b))
  (if (null? plist)
      '()
      (let loop ((plist (cdr plist))
                 (current-field (list (car plist)))
                 (return-list '()))
        (cond ((null? plist)
               (reverse
                (if (null? current-field)
                    return-list
                    (rcons current-field return-list))))
              ((car? (car plist))
               (loop (cdr plist)
                     (list (car plist))
                     (rcons current-field return-list)))
              (else
               (loop (cdr plist)
                     (cons (car plist) current-field)
                     return-list))))))

(define (unzip list-of-pairs)
  (let loop ((pairs list-of-pairs) (cars '()) (cdrs '()))
    (if (null? pairs)
        (values (reverse cars) (reverse cdrs))
        (loop (cdr pairs) (cons (caar pairs) cars)
              (cons (cdar pairs) cdrs)))))

(define (shift-left old-list end)
  (append (cdr old-list) (list end)))

)

Reply via email to