Support writing recursive data structures and quoted symbols.

Eliminate use of #="undefined" as an explicit initializer for boxes.
Do not allow #@ ("freeze") to be applied to references, for sanity's sake.

Inside compiler, builtins are now represented by (#%builtin "name") form.
Plain symbols are promoted to builtins; quoted symbols become structures.
This commit is contained in:
Jesse D. McDonald 2010-10-08 21:39:51 -05:00
parent cc16957256
commit cb0d7b62e5
7 changed files with 196 additions and 133 deletions

View File

@ -12,9 +12,9 @@
[unused-g-vars global-variables] [unused-g-vars global-variables]
[i-vars '()]) [i-vars '()])
(define (add-g-var value) (define (add-g-var value)
(let ([value (if (and (pair? value) (eq? (first value) 'quote)) (let ([value (cond [(and (pair? value) (eq? (first value) 'quote)) (second value)]
(second value) [(symbol? value) `(#%builtin ,(symbol->string value))]
value)]) [else value])])
(let/cc return (let/cc return
(for ([g-var (in-list global-variables)] (for ([g-var (in-list global-variables)]
[val (in-list g-vars)]) [val (in-list g-vars)])

View File

@ -147,7 +147,7 @@
(define value-primitives (define value-primitives
(append unary-value-primitives (append unary-value-primitives
binary-value-primitives binary-value-primitives
(list '(#%if #f #f)))) '((#%if #f #f))))
(define statement-primitives (define statement-primitives
(append unary-statement-primitives (append unary-statement-primitives

View File

@ -294,9 +294,9 @@
(map-form form (map-form form
#:bind (lambda (recurse op vars . subforms) #:bind (lambda (recurse op vars . subforms)
(flatten-binds (flatten-binds
`(#%bind ,(subst variable variable vars) `(#%bind ,vars
,@(if (memq variable vars) ,@(if (memq variable vars)
`((#%set! ,variable (#%make-box #%undef))) `((#%set! ,variable (#%make-box ,variable)))
'()) '())
,@(map recurse subforms)))) ,@(map recurse subforms))))
#:set (lambda (recurse op var value) #:set (lambda (recurse op var value)

View File

@ -100,14 +100,13 @@
(append curried-non-keywords non-keywords)))))))) (append curried-non-keywords non-keywords))))))))
(define (variable-value? form) (define (variable-value? form)
(and (symbol? form) (symbol? form))
(not (eq? form '#%undef))))
(define (literal-value? form) (define (literal-value? form)
(and (not (variable-value? form)) (and (not (variable-value? form))
(or (not (pair? form)) (or (not (pair? form))
(eq? (first form) 'quote) (eq? (first form) 'quote)
(eq? (first form) '#%template)))) (memq (first form) '(#%builtin #%immutable #%struct #%template)))))
(define (simple-value? form) (define (simple-value? form)
(or (variable-value? form) (or (variable-value? form)
@ -292,7 +291,7 @@
(let* ([prefix (string-append (symbol->string var) "->g")] (let* ([prefix (string-append (symbol->string var) "->g")]
[unique-var (gensym prefix)]) [unique-var (gensym prefix)])
`(#%bind ,(subst var unique-var (second bind)) `(#%bind ,(subst var unique-var (second bind))
,@(map (lambda (sf) (subst-var var unique-var sf)))))) ,@(map (lambda (sf) (subst-var var unique-var sf)) (cddr bind)))))
(foldr make-binding-unique bind (filter needs-rename? (second bind)))) (foldr make-binding-unique bind (filter needs-rename? (second bind))))
(map-form form (map-form form

View File

@ -13,173 +13,243 @@
(define current-indent-step (make-parameter 2)) (define current-indent-step (make-parameter 2))
(define verbose-rla? (make-parameter #f)) (define verbose-rla? (make-parameter #f))
(define current-object-map (make-parameter #f))
(define next-object-number (make-parameter #f))
(define symbol-structs (make-parameter #f))
(define symbol-type '(#%immutable (#%struct (#%builtin "structure") () 1 #f)))
(define (write-rla-value value (port (current-output-port)))
(void (parameterize ([current-output-port port]
[current-object-map (make-hasheq)]
[next-object-number 0]
[symbol-structs (make-hasheq)])
(build-object-map value)
(port-count-lines! port)
(write-rla-val value))))
(define (symbol->struct sym)
(if (hash-has-key? (symbol-structs) sym)
(hash-ref (symbol-structs) sym)
(begin
(let ([s `(#%immutable (#%struct ,symbol-type ,(symbol->string sym)))])
(hash-set! (symbol-structs) sym s)
s))))
(define (build-object-map value)
(cond
[(or (boolean? value) (number? value) (char? value) (null? value)) (void)]
[(and (pair? value) (eq? (car value) '#%immutable))
(build-object-map (second value))]
[else (let* ([objmap (current-object-map)]
[in-map (hash-has-key? objmap value)])
(hash-set! objmap value in-map)
(unless in-map
(cond
[(pair? value)
(build-object-map (car value))
(build-object-map (cdr value))]
[(symbol? value)
(build-object-map (symbol->struct value))]
[(vector? value)
(for ([item (in-vector value)])
(build-object-map item))])))]))
(define hex-digits "0123456789abcdef") (define hex-digits "0123456789abcdef")
(define (hard-new-line port) (define (hard-new-line)
(write-char #\Newline port) (write-char #\Newline)
(for ([i (in-range 0 (current-indent))]) (for ([i (in-range 0 (current-indent))])
(write-char #\Space port))) (write-char #\Space)))
(define (req-new-line port) (define (req-new-line)
(if (verbose-rla?) (if (verbose-rla?)
(hard-new-line port) (hard-new-line)
(write-char #\Space port))) (write-char #\Space)))
(define (opt-new-line port) (define (opt-new-line)
(when (verbose-rla?) (when (verbose-rla?)
(hard-new-line port))) (hard-new-line)))
(define (write-hex-char ord port) (define (write-hex-char ord)
(write-string "\\x" port) (write-string "\\x")
(write-char (string-ref hex-digits (quotient ord 16)) port) (write-char (string-ref hex-digits (quotient ord 16)))
(write-char (string-ref hex-digits (remainder ord 16)) port)) (write-char (string-ref hex-digits (remainder ord 16))))
(define (write-hex-byte ord port) (define (write-hex-byte ord)
(write-string "0x" port) (write-string "0x")
(write-char (string-ref hex-digits (quotient ord 16)) port) (write-char (string-ref hex-digits (quotient ord 16)))
(write-char (string-ref hex-digits (remainder ord 16)) port)) (write-char (string-ref hex-digits (remainder ord 16))))
(define (write-rla-string value port) (define (write-rla-string value)
(write-char #\" port) (write-char #\")
(for ([ch (in-string value)]) (for ([ch (in-string value)])
(cond (cond
[(and (eq? ch #\")) [(and (eq? ch #\"))
(write-string "\\\"" port)] (write-string "\\\"")]
[(and (< (char->integer ch) 128) (char-graphic? ch)) [(and (< (char->integer ch) 128) (char-graphic? ch))
(write-char ch port)] (write-char ch)]
[else [else
(write-hex-char (char->integer ch) port)])) (write-hex-char (char->integer ch))]))
(write-char #\" port)) (write-char #\"))
(define (write-instance-string inst-vars port) (define (write-rla-struct value)
(write-string "#@\"" port) (write-string "#S(")
(write-rla-val (second value))
(for ([slotval (in-list (cddr value))])
(write-char #\Space)
(write-rla-val slotval))
(write-char #\)))
(define (write-instance-string inst-vars)
(write-string "#@\"")
(for ([var (in-list inst-vars)]) (for ([var (in-list inst-vars)])
(write-hex-char (variable->code var) port)) (write-hex-char (variable->code var)))
(write-char #\" port)) (write-char #\"))
(define (write-rla-bytecode+tail-call forms port) (define (write-rla-bytecode+tail-call forms)
(define (write-tail-call tc-form) (define (write-tail-call tc-form)
(req-new-line port) (req-new-line)
(write-string "#@\"" port) (write-string "#@\"")
(for ([var (in-list (cdr tc-form))]) (for ([var (in-list (cdr tc-form))])
(write-hex-char (variable->code var) port)) (write-hex-char (variable->code var)))
(write-char #\" port) (write-char #\")
(when (verbose-rla?) (when (verbose-rla?)
(write-char #\; port) (write-char #\;)
(for ([var (in-list (cdr tc-form))]) (for ([var (in-list (cdr tc-form))])
(write-char #\Space port) (write-char #\Space)
(write var port)))) (write var))))
(let-values ([(line col pos) (port-next-location port)]) (let-values ([(line col pos) (port-next-location (current-output-port))])
(parameterize ([current-indent col]) (parameterize ([current-indent col])
(write-string "#@\"" port) (write-string "#@\"")
(if (eq? (first (first forms)) '#%tail-call) (if (eq? (first (first forms)) '#%tail-call)
(begin (begin
(write-char #\" port) (write-char #\")
(write-tail-call (first forms))) (write-tail-call (first forms)))
(let iter ([forms forms]) (let iter ([forms forms])
(map (lambda (x) (write-hex-char x port)) (map (lambda (x) (write-hex-char x))
(statement->code (car forms))) (statement->code (car forms)))
(if (eq? (first (second forms)) '#%tail-call) (if (eq? (first (second forms)) '#%tail-call)
(begin (begin
(if (verbose-rla?) (if (verbose-rla?)
(begin (begin
(write-string "\"; " port) (write-string "\"; ")
(write (car forms) port)) (write (car forms)))
(write-char #\" port)) (write-char #\"))
(write-tail-call (second forms))) (write-tail-call (second forms)))
(begin (begin
(when (verbose-rla?) (when (verbose-rla?)
(write-string "\\; " port) (write-string "\\; ")
(write (car forms) port) (write (car forms))
(hard-new-line port) (hard-new-line)
(write-char #\Space port)) (write-string " "))
(iter (cdr forms))))))))) (iter (cdr forms)))))))))
(define (write-rla-function value port) (define (write-rla-function value)
(define template? (eq? (first value) '#%template)) (define template? (eq? (first value) '#%template))
(let-values ([(line col pos) (port-next-location port)]) (let-values ([(line col pos) (port-next-location (current-output-port))])
(parameterize ([current-indent col]) (parameterize ([current-indent col])
(write-string "#@#S(" port) (write-string "#@#S(")
(if (eq? (first value) '#%template) (if (eq? (first value) '#%template)
(write-string "#=\"template\"" port) (write-string "#=\"template\"")
(write-string "#=\"lambda\"" port)) (write-string "#=\"lambda\""))
(parameterize ([current-indent (+ (current-indent-step) (current-indent))]) (parameterize ([current-indent (+ (current-indent-step) (current-indent))])
(req-new-line port) (req-new-line)
(write-string "#@#(" port) (write-string "#@#(")
(unless (null? (second value)) (unless (null? (second value))
(parameterize ([current-indent (+ (current-indent-step) (current-indent))]) (parameterize ([current-indent (+ (current-indent-step) (current-indent))])
(opt-new-line port) (opt-new-line)
(write-rla-value (first (second value)) port) (write-rla-val (first (second value)))
(for ([global (in-list (cdr (second value)))]) (for ([global (in-list (cdr (second value)))])
(req-new-line port) (req-new-line)
(write-rla-value global port))) (write-rla-val global)))
(opt-new-line port)) (opt-new-line))
(write-string ")" port) (write-string ")")
(req-new-line port) (req-new-line)
(if template? (if template?
(write-instance-string (third value) port) (write-instance-string (third value))
(begin (begin
(write-string "#@#(" port) (write-string "#@#(")
(unless (null? (third value)) (unless (null? (third value))
(parameterize ([current-indent (+ (current-indent-step) (current-indent))]) (parameterize ([current-indent (+ (current-indent-step) (current-indent))])
(opt-new-line port) (opt-new-line)
(write-rla-value (first (third value)) port) (write-rla-val (first (third value)))
(for ([instance (in-list (cdr (third value)))]) (for ([instance (in-list (cdr (third value)))])
(req-new-line port) (req-new-line)
(write-rla-value instance port))) (write-rla-val instance)))
(opt-new-line port)) (opt-new-line))
(write-string ")" port))) (write-string ")")))
(req-new-line port) (req-new-line)
(write-rla-value (length (second (fourth value))) port) (write-rla-val (length (second (fourth value))))
(req-new-line port) (req-new-line)
(write-rla-bytecode+tail-call (cddr (fourth value)) port)) (write-rla-bytecode+tail-call (cddr (fourth value))))
(opt-new-line port)) (opt-new-line))
(write-string ")" port))) (write-string ")")))
(define (write-rla-value value [port (current-output-port)]) (define (write-rla-val value)
(port-count-lines! port) (let ([ref (hash-ref (current-object-map) value #f)])
(void (cond
[(number? ref)
(write-string "#=")
(write ref)]
[ref
(let ([objnum (next-object-number)])
(hash-set! (current-object-map) value objnum)
(next-object-number (+ 1 objnum))
(write-char #\#)
(write objnum)
(write-char #\=))
(write-plain-rla-val value)]
[else
(write-plain-rla-val value)])))
(define (write-plain-rla-val value)
(cond (cond
[(eq? value '#%undef)
(write-string "#=\"undefined\"" port)]
[(symbol? value)
(write-string "#=\"" port)
(write-string (symbol->string value) port)
(write-string "\"" port)]
[(or (boolean? value) (number? value)) [(or (boolean? value) (number? value))
(write value port)] (write value)]
[(char? value) [(char? value)
(write (char->integer value) port)] (write (char->integer value))]
[(symbol? value)
(write-plain-rla-val (symbol->struct value))]
[(string? value) [(string? value)
(write-rla-string value port)] (write-rla-string value)]
[(and (pair? value) (memq (car value) '(#%builtin)))
(write-string "#=")
(write-rla-string (second value))]
[(and (pair? value) (memq (car value) '(#%immutable)))
(unless (number? (hash-ref (current-object-map) (second value) #f))
(write-string "#@"))
(write-rla-val (second value))]
[(and (pair? value) (memq (car value) '(#%struct)))
(write-rla-struct value)]
[(and (pair? value) (memq (car value) '(#%lambda #%template))) [(and (pair? value) (memq (car value) '(#%lambda #%template)))
(write-rla-function value port)] (write-rla-function value)]
[(vector? value) [(vector? value)
(write-string "#(" port) (write-string "#(")
(unless (zero? (vector-length value)) (unless (zero? (vector-length value))
(write-rla-value (vector-ref value 0) port)) (write-rla-val (vector-ref value 0)))
(for ([i (in-range 1 (vector-length value))]) (for ([i (in-range 1 (vector-length value))])
(write-rla-value (vector-ref value i) port) (write-rla-val (vector-ref value i))
(write-char #\Space port)) (write-char #\Space))
(write-string ")" port)] (write-string ")")]
[(null? value) [(null? value)
(write-string "()" port)] (write-string "()")]
[(pair? value) [(pair? value)
(write-string "(" port) (write-string "(")
(let iter ([lst value]) (let iter ([lst value])
(write-rla-value (car lst) port) (write-rla-val (car lst))
(cond (cond
[(null? (cdr lst)) [(null? (cdr lst))
(write-string ")" port)] (write-string ")")]
[(pair? (cdr lst)) [(and (pair? (cdr lst)) (not (hash-ref (current-object-map) (cdr lst) #f)))
(write-char #\Space port) (write-char #\Space)
(iter (cdr lst))] (iter (cdr lst))]
[else [else
(write-string " . " port) (write-string " . ")
(write-rla-value (cdr lst)) (write-rla-val (cdr lst))
(write-string ")" port)]))] (write-string ")")]))]
[else (error "Don't know how to write Rosella syntax for:" value)]))) [else (error "Don't know how to write Rosella syntax for:" value)]))
(define (variable->code var) (define (variable->code var)
(or (and (eq? var '#%nil) #x00) (or (and (eq? var '#%nil) #x00)

View File

@ -678,6 +678,7 @@ static value_t read_immutable(reader_state_t *state)
register_gc_root(&ph_root, make_struct(immutable_ph_root.value)); register_gc_root(&ph_root, make_struct(immutable_ph_root.value));
val = read_one_value(state); val = read_one_value(state);
release_assert(!struct_is_a(val, reference_root.value));
IMMUTABLE_PH_VALUE(ph_root.value) = val; IMMUTABLE_PH_VALUE(ph_root.value) = val;
WRITE_BARRIER(ph_root.value); WRITE_BARRIER(ph_root.value);

View File

@ -1,11 +1,4 @@
(define (make-structure-type supers nslots callable) (define s:symbol (struct-type 'a))
(let ([struct (make-struct structure)])
(struct-set! struct 0 supers)
(struct-set! struct 1 nslots)
(struct-set! struct 2 callable)
struct))
(define s:symbol (make-structure-type '() 1 #f))
(define *symbols* '()) (define *symbols* '())
(define (make-symbol name) (define (make-symbol name)