; edit - made scanner and make-scanner different
(def make-scanner args
(dsb (&k car cdr) args
(annotate 'scanner (cons car cdr))))
(defm car ((t c scanner))
((car (rep c))))
(defm cdr ((t c scanner))
((cdr (rep c))))
;(defm isa ((t c scanner) typ)
; (if (is typ 'cons) t
; (is typ 'scanner) t))
(redef isa (c typ)
(if (is (type c) 'scanner)
(in typ 'scanner 'cons)
(old c typ)))
(def scanner (s . args)
(err:tostring:write "Unknown scanner type" (type s)))
(defm scanner ((t s string) (o start 0) (o end (len s)))
(let (a d d-valid) nil
(make-scanner
'car (fn () (or a (= a (s start))))
'cdr (fn ()
(if d-valid
d
(= d-valid t
d (if (is (+ 1 start) end)
nil
(scanner s (+ 1 start) end))))))))
; input port
(defm scanner ((t s input))
(let a (readc s)
(if (no a)
nil
(let (d d-valid) nil
(make-scanner
'car (fn () a)
'cdr (fn ()
(if d-valid
d
(= d-valid t
d (scanner s)))))))))
^^ strings as lists, indeed ^^
Hmm. Another idea: make redef bind 'old to (fn args nil) if the functions hasn't been defined yet. Possibly just replace the (let old ,name ...) with (let old (or (errsafe ,name) (fn args nil)) ...)
edit: Hmm, probably should make redef define the function using (fn args (let ,parms args ...)) instead, so that various functions can pass arbitrarily. Or add a 'pass function which just passes the old call completely.
Yeah, that's exactly the sort of thing I was thinking.
As for old functions, I'd really like to have a better way than "errsafe" for determining whether or not a variable is bound. But yeah, I agree this should work for not-yet-defined functions.