This repository was archived by the owner on Dec 7, 2019. It is now read-only.
Repository navigation
Compound Data Types
Jonathan50 edited this page Aug 2, 2017
·
8 revisions
Do-it does not have any compound data types built in. But it isn't very hard to implement some yourself, using the C library procedure malloc, and the do-it primitives peek and poke.
Here is an example program, implementing pairs (aka cons cells):
(defvar word-size 4) ; how many bytes can fit into a register
;;; The pair constructor
(defproc cons (car cdr)
(defvar pair (malloc (* word-size 2)))
(set-car pair car)
(set-cdr pair cdr)
pair)
;;; Pair mutators
(defproc set-car (pair car) (poke pair car))
(defproc set-cdr (pair cdr) (poke (+ pair word-size) cdr))
;;; Pair selectors
(defproc car (pair) (peek pair))
(defproc cdr (pair) (peek (+ pair word-size)))
Pairs have two word-sized fields, so cons allocates 2 words (8 bytes on 32-bit systems). Car returns the first word and cdr returns the second and set-car replaces the first and set-cdr replaces the second.
Then pairs can be used:
(defvar x (cons 1 2))
(car x) ; ===> 1
(cdr x) ; ===> 2
(set-car x 42)
(set-cdr x 1337)
(car x) ; ===> 42
(cdr x) ; ===> 1337
(free x) ; free the memory used by the pair
Here is a Scheme macro for creating data structures:
(defmacro defstruct (const . fields)
(define (enumerate lst)
(define (helper lst idx)
(if (null? lst)
'()
(cons idx (helper (cdr lst) (+ idx 1)))))
(helper lst 0))
(let* ((word-size 4)
(field-names (map car fields))
(field-count (length fields))
(field-indices (enumerate fields))
(getters field-names)
(setters (map cadr fields)))
`(begin
(defproc ,const ,field-names
(defvar obj (malloc (* ,word-size ,field-count)))
,@(map (lambda (setter field-name)
`(,setter obj ,field-name))
setters field-names)
obj)
,@(map
(lambda (getter idx)
`(defproc ,getter (obj)
(peek (+ obj (* ,idx ,word-size)))))
getters field-indices)
,@(map
(lambda (setter idx)
`(defproc ,setter (obj1 obj2)
(poke (+ obj1 (* ,idx ,word-size)) obj2)))
setters field-indices))))
The above pair structure could then be defined like this:
(defstruct cons
(car set-car)
(cdr set-cdr))
and used simply like this:
(defproc write-list (list)
(while (> list 0)
(printf "%d " (car list))
(set list (cdr list)))
(newline))
(write-list
(cons 1 (cons 2 (cons 3 (cons 4 0)))))
These examples can be found in the example folder.