summaryrefslogtreecommitdiff
path: root/module/language/sassy/push-stacks.scm
diff options
context:
space:
mode:
Diffstat (limited to 'module/language/sassy/push-stacks.scm')
-rw-r--r--module/language/sassy/push-stacks.scm187
1 files changed, 187 insertions, 0 deletions
diff --git a/module/language/sassy/push-stacks.scm b/module/language/sassy/push-stacks.scm
new file mode 100644
index 000000000..cb9b7511e
--- /dev/null
+++ b/module/language/sassy/push-stacks.scm
@@ -0,0 +1,187 @@
+; push-stacks.scm - A stack-like data-type
+; Copyright (C) 2005 Jonathan Kraut
+
+; This library is free software; you can redistribute it and/or
+; modify it under the terms of the GNU Lesser General Public
+; License as published by the Free Software Foundation; either
+; version 2.1 of the License, or (at your option) any later version.
+
+; This library is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; Lesser General Public License for more details.
+
+; You should have received a copy of the GNU Lesser General Public
+; License along with this library; if not, write to the Free Software
+; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+; Contact:
+; Jonathan Kraut
+; 4130 43 ST #C2
+; Sunnyside, NY 11104
+; jak76@columbia.edu
+
+; see file COPYING in the top of Sassy's distribution directory
+
+
+; module sassy-push-stacks
+; import-syntax meta-lambda
+; export all
+
+(define make-pushdown-stack #f)
+(define make-pushup-stack #f)
+
+(let ((make-push-stack
+ (lambda (direc)
+ (define size 0)
+ (define items '())
+ (define pointer '())
+ (define down-stack-base '())
+
+ (define (cycle lst siz)
+ (do ((ls lst (cdr ls))
+ (c siz (+ c 1)))
+ ((null? (cdr ls)) (set! size c) ls)))
+
+ (define push-gs
+ (if (eqv? 'up direc)
+ (lambda (itm-or-pr)
+ (and (not (pair? itm-or-pr))
+ (set! itm-or-pr (list itm-or-pr)))
+ (if (null? pointer)
+ (begin (set! items itm-or-pr)
+ (set! pointer (cycle itm-or-pr (+ size 1)))
+ items)
+ (begin (set-cdr! pointer itm-or-pr)
+ (let ((old (cdr pointer)))
+ (set! pointer (cycle pointer size))
+ old))))
+ (lambda (itm-or-pr)
+ (let ((push-one (lambda () ; fast path for non-pairs
+ (set! items (cons itm-or-pr items))
+ (set! pointer items)
+ (set! size (+ size 1)))))
+ (if (null? pointer)
+ (if (not (pair? itm-or-pr))
+ (begin (push-one)
+ (set! down-stack-base pointer)
+ pointer)
+ (begin (set! items itm-or-pr)
+ (set! down-stack-base
+ (cycle itm-or-pr (+ size 1)))
+ (set! pointer items)
+ pointer))
+ (if (not (pair? itm-or-pr))
+ (begin (push-one)
+ pointer)
+ (begin (set-cdr! (cycle itm-or-pr (+ size 1)) items)
+ (set! items itm-or-pr)
+ (set! pointer itm-or-pr)
+ pointer)))))))
+; (and (not (pair? lst))
+; (set! lst (list lst)))
+; (if (null? pointer)
+; (begin (set! items lst)
+; (set! down-stack-base (cycle lst (+ size 1)))
+; (set! pointer items)
+; pointer)
+; (begin (set-cdr! (cycle lst (+ size 1)) items)
+; (set! items lst)
+; (set! pointer lst)
+; pointer)))))
+
+ (define (patch-gs pnt lst)
+ (do ((rst lst (cdr rst))
+ (loc pnt (cdr loc)))
+ ((null? rst))
+ (set-car! loc (car rst))))
+
+ (define previous '())
+
+ (define append-gs
+ (if (eqv? 'up direc)
+ (lambda (stk2)
+ (if (memq stk2 previous)
+ (error "tried to append! the same stacks twice" stk2)
+ (begin (set! previous (cons stk2 previous))
+ (set! size (+ size (stk2 'size)))
+ (if (null? pointer)
+ (set! items (stk2 'items))
+ (set-cdr! pointer (stk2 'items)))
+ (let ((p (if (eqv? 'up (stk2 'direc))
+ (stk2 'pointer)
+ (stk2 'down-base))))
+ (if (and (not (eq? pointer p))
+ (not (null? p)))
+ (set! pointer p))))))
+ (lambda (stk2)
+ (if (memq stk2 previous)
+ (error "tried to append! the same stacks twice" stk2)
+ (begin (set! previous (cons stk2 previous))
+ (set! size (+ size (stk2 'size)))
+ (if (null? pointer)
+ (begin (set! items (stk2 'items))
+ (set! pointer items))
+ (set-cdr! down-stack-base (stk2 'items)))
+ (let ((d (if (eqv? 'up (stk2 'direc))
+ (stk2 'pointer)
+ (stk2 'down-base))))
+ (if (and (not (eq? down-stack-base d))
+ (not (null? d)))
+ (set! down-stack-base d))))))))
+
+ (meta-lambda-dot
+ (or (and 'push ? (lambda (x) (push-gs x)))
+ (and 'size (begin size))
+ (and 'patch pair? (or (and pair? (lambda (x y) (patch-gs x y)))
+ (and ? (lambda (x y) (set-car! x y)))))
+ (and 'append procedure? (lambda (x) (append-gs x)))
+ (and 'set-previous procedure? (lambda (x) (set! previous
+ (cons x previous))))
+ (and 'pointer (begin pointer))
+ (and 'down-base (begin down-stack-base))
+ (and 'items (begin items))
+ (and 'save (begin
+ (let ((os size) (op pointer) (oi items))
+ (lambda ()
+ (set! size os)
+ (set! pointer op)
+ (set! items oi)
+ (if (and (not (null? pointer)) (eqv? direc 'up))
+ (set-cdr! pointer '()))))))
+ (and 'push-proc ? (lambda (x) (let ((t (push-gs x)))
+ (lambda (new) (patch-gs t new)))))
+ (and 'direc (begin direc))
+ ; last because it may return #f
+ (and 'empty (begin (null? items))))))))
+
+ (set! make-pushdown-stack (lambda () (make-push-stack 'up)))
+ (set! make-pushup-stack (lambda () (make-push-stack 'down))))
+
+(define (push-stack-push stk itm) (stk 'push itm))
+(define (push-stack-pointer stk) (stk 'pointer))
+(define (push-stack-items stk) (stk 'items))
+(define (push-stack-patch stk pnt itm) (stk 'patch pnt itm))
+(define (push-stack-push->patcher stk itm) (stk 'push-proc itm))
+(define (push-stack-save stk) (stk 'save))
+(define (push-stack-direction stk) (stk 'direc))
+(define (push-stack-size stk) (stk 'size))
+(define (push-stack-append! stk1 stk2)
+ (stk2 'set-previous stk1)
+ (stk1 'append stk2))
+(define (push-stack-empty? stk) (stk 'empty))
+(define push-stack-align
+ (let ((align-to (lambda (count align)
+ (let ((diff (modulo count align)))
+ (if (zero? diff)
+ 0
+ (- align diff))))))
+ (lambda (stk align fill . offset)
+ (let ((amount (align-to (+ (stk 'size)
+ (if (null? offset) 0 (car offset)))
+ align)))
+ (if (pair? fill)
+ (error "can not fill a push-stack with a pair" fill)
+ (when (not (zero? amount))
+ (stk 'push (make-list amount fill))))))))
+