read: change datum label to object, that returns an encapsulated datum label
This commit is contained in:
parent
fee4198f2f
commit
b0ce282a30
80
read.scm
80
read.scm
|
@ -294,9 +294,10 @@
|
||||||
(else (error 'read:ident "invalid operation" op args))))))
|
(else (error 'read:ident "invalid operation" op args))))))
|
||||||
|
|
||||||
(define read:ident-builder
|
(define read:ident-builder
|
||||||
(lambda (start-char location)
|
(lambda (location . start-char)
|
||||||
(let ((char-list (linked-list:new)))
|
(let ((char-list (linked-list:new)))
|
||||||
(char-list 'push start-char)
|
(if (not (null? start-char))
|
||||||
|
(char-list 'push (car start-char)))
|
||||||
(lambda (op . args)
|
(lambda (op . args)
|
||||||
(cond
|
(cond
|
||||||
((eq? op 'finalize->ident)
|
((eq? op 'finalize->ident)
|
||||||
|
@ -347,8 +348,8 @@
|
||||||
(lambda (table char acc port)
|
(lambda (table char acc port)
|
||||||
(readtable:act readtable:identifier
|
(readtable:act readtable:identifier
|
||||||
(port 'read)
|
(port 'read)
|
||||||
(read:ident-builder char
|
(read:ident-builder (port 'location)
|
||||||
(port 'location))
|
char)
|
||||||
port)))
|
port)))
|
||||||
|
|
||||||
;;; ;;;;;;;;;;;;;;;;;;;;
|
;;; ;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -518,6 +519,30 @@
|
||||||
((eq? op 'toplevel) toplevel)
|
((eq? op 'toplevel) toplevel)
|
||||||
(else (apply ll op args)))))))
|
(else (apply ll op args)))))))
|
||||||
|
|
||||||
|
(define read:datum-label
|
||||||
|
(lambda (location toplevel)
|
||||||
|
(let ((finalized? #f)
|
||||||
|
(value '())
|
||||||
|
(name (read:ident-builder location)))
|
||||||
|
(lambda (op . args)
|
||||||
|
(cond
|
||||||
|
((eq? op 'finalize-value)
|
||||||
|
(if finalized?
|
||||||
|
(error 'datum-label "cannot finalize twice"))
|
||||||
|
(set! finalized? #t)
|
||||||
|
(set! value (car args))
|
||||||
|
(set! toplevel #f))
|
||||||
|
((eq? op 'finalize->ident)
|
||||||
|
(set! name (name 'finalize->ident)))
|
||||||
|
((eq? op 'value)
|
||||||
|
(if (not finalized?)
|
||||||
|
(error 'datum-label "value called before finalize"))
|
||||||
|
value)
|
||||||
|
((eq? op 'toplevel) toplevel)
|
||||||
|
((eq? op 'type) 'datum-label)
|
||||||
|
((eq? op 'as-string) (name 'value))
|
||||||
|
(else (apply name op args)))))))
|
||||||
|
|
||||||
;;; Readtable for the number part of a datum label / reference. A label
|
;;; Readtable for the number part of a datum label / reference. A label
|
||||||
;;; looks like "#[NUMBER]=" and a reference looks like "#[NUMBER]#".
|
;;; looks like "#[NUMBER]=" and a reference looks like "#[NUMBER]#".
|
||||||
(define readtable:datum-label-next
|
(define readtable:datum-label-next
|
||||||
|
@ -527,36 +552,24 @@
|
||||||
(list readtable:update-list readtable:digits readtable:push-char)
|
(list readtable:update-list readtable:digits readtable:push-char)
|
||||||
(list readtable:update #\=
|
(list readtable:update #\=
|
||||||
(lambda (_ __ acc port)
|
(lambda (_ __ acc port)
|
||||||
;; All datum labels are saved as strings.
|
(acc 'finalize->ident)
|
||||||
(let ((label (list->string (acc 'to-list))))
|
(port 'set-datum-label! (acc 'as-string) acc)
|
||||||
;; Datum labels are pairs, one with the label and the other
|
(let ((next-value (readtable:next (acc 'toplevel)
|
||||||
;; with the data that is to be used. The label is there to
|
#f
|
||||||
;; detect when a datum label refers to iself: i.e.
|
port)))
|
||||||
;; #0=#0# .
|
(if (eqv? acc next-value)
|
||||||
;;
|
(error 'datum-label-next "datum label cannot be itself"))
|
||||||
;; The CAR is the label and the CDR is the thing it refers
|
(acc 'finalize-value next-value)
|
||||||
;; to.
|
(acc 'value))))
|
||||||
(let ((datum-label (cons label '())))
|
|
||||||
(port 'set-datum-label! label datum-label)
|
|
||||||
(let ((next-value (readtable:next (acc 'toplevel)
|
|
||||||
#f
|
|
||||||
port)))
|
|
||||||
;; After reading the part after the datum label, check
|
|
||||||
;; that the labeled datum is not self a reference to
|
|
||||||
;; the datum label.
|
|
||||||
(if (and (pair? next-value)
|
|
||||||
(equal? (car next-value) label))
|
|
||||||
(error 'datum-label-next "datum label cannot be itself")
|
|
||||||
(set-cdr! datum-label next-value))
|
|
||||||
next-value)))))
|
|
||||||
(list readtable:update #\#
|
(list readtable:update #\#
|
||||||
(lambda (_ __ acc port)
|
(lambda (_ __ acc port)
|
||||||
(let ((label (list->string (acc 'to-list))))
|
(acc 'finalize->ident)
|
||||||
(let ((datum-label (port 'get-datum-label label)))
|
(let ((datum-label-container (port 'get-datum-label
|
||||||
(if (null? datum-label)
|
(acc 'as-string))))
|
||||||
(error 'datum-label-next
|
(if (null? datum-label-container)
|
||||||
"unknown reference to datum label" label)
|
(error 'datum-label-next
|
||||||
(map:val datum-label))))))))
|
"unknown reference to datum label" label)
|
||||||
|
(map:val datum-label-container)))))))
|
||||||
|
|
||||||
;;; Reads the next toplevel datum, discards it, and then continues at the
|
;;; Reads the next toplevel datum, discards it, and then continues at the
|
||||||
;;; toplevel.
|
;;; toplevel.
|
||||||
|
@ -578,7 +591,7 @@
|
||||||
(lambda (_ char toplevel port)
|
(lambda (_ char toplevel port)
|
||||||
(readtable:act readtable:datum-label-next
|
(readtable:act readtable:datum-label-next
|
||||||
char
|
char
|
||||||
(linked-list/toplevel:new toplevel)
|
(read:datum-label (port 'location) toplevel)
|
||||||
port)))
|
port)))
|
||||||
(list readtable:update %bol readtable:vector)))
|
(list readtable:update %bol readtable:vector)))
|
||||||
|
|
||||||
|
@ -634,6 +647,7 @@
|
||||||
(let ((type (value 'type)))
|
(let ((type (value 'type)))
|
||||||
(cond
|
(cond
|
||||||
((eq? type 'ident) (value 'value))
|
((eq? type 'ident) (value 'value))
|
||||||
|
((eq? type 'datum-label) (uncycle (value 'value)))
|
||||||
(else (vector 'unrepresentable type)))))
|
(else (vector 'unrepresentable type)))))
|
||||||
(else value)))))
|
(else value)))))
|
||||||
(uncycle value)))))
|
(uncycle value)))))
|
||||||
|
|
Loading…
Reference in New Issue