#lang scheme/base
(require
scheme/control
scheme/serialize
scheme/match
"../op.ss"
"../tools.ss")
(provide
print-target-word
format-target-word
target-print-word-bytes target-print-address-bits
new-target-word
word?->name
instruction->string
(struct-out target-word)
target-word->error-string
target-value-delay target-value->number target-value-eval
target-value-source
target-value-abort
(struct-out target-value)
target-value-catch-undefined
target-chain->list
target-chains->bin
target-value-equal?
)
(define-serializable-struct target-word
(name realm code srcloc address bin next postponed)
#:mutable)
(define (new-target-word #:name [name '<anonymous>]
#:realm [realm 'code]
#:code [code #f]
#:srcloc [srcloc #f]
#:address [address #f]
#:bin [bin #f]
#:next [next #f]
#:postponed [postponed #f]
)
(make-target-word name
realm code
srcloc address
bin next postponed))
(define (target-chain->list word [l '()])
(let ((next (target-word-next word))
(l+ (cons word l)))
(if next
(target-chain->list next l+)
l+)))
(define (target-chains->bin chain-list [realm 'code])
(prompt
(bin-flatten
(map
(lambda (c)
(list
(target-word-address c)
(reverse
(flatten
(map (lambda (word)
(let ((bin (target-word-bin word)))
(or bin (abort #f))))
(target-chain->list c))))))
(reverse
(filter
(lambda (w)
(eq? (target-word-realm w) realm))
chain-list))))))
(define-struct target-value (thunk source))
(define target-value-tag
(make-continuation-prompt-tag 'meta))
(define (target-value-abort)
(abort-current-continuation
target-value-tag (lambda () #f)))
(define (target-value-catch-undefined thunk)
(prompt-at target-value-tag (thunk)))
(define (target-value-equal? a b)
(equal? (target-value-eval a)
(target-value-eval b)))
(define (target-value-eval expr)
(cond
((target-value? expr) ((target-value-thunk expr)))
((target-word? expr) (or (target-word-address expr)
(target-value-abort)))
(else expr)))
(define (target-value->number
expr
[e (lambda (n)
(error 'target-value-type-error
"not a number: ~a" n))])
(let ((n (target-value-eval expr)))
(unless (number? n) (e n))
n))
(define-syntax target-value-delay
(syntax-rules ()
((_ e1 e2) (make-target-value (lambda () e1) e2))
((_ expr) (target-value-delay expr #f))
))
(define (target-word->error-string w)
(let ((s (target-word-srcloc w)))
(and s
(apply
(lambda (file line column position span)
(format "~a:~a:~a: ~a"
file line column
(target-word-name w)))
s))))
(define (word?->name r)
(if (not (target-word? r)) r
(target-word-name r)))
(define target-print-address-bits (make-parameter 16))
(define target-print-word-bytes (make-parameter 2))
(define (instruction->string ins [term ""])
(if (not (list? ins))
(format "~a~a" ins term)
(let ((asm (car ins))
(args (map
(lambda (x)
(cond
((target-value? x) (target-value-source x))
((target-word? x) (target-word-name x))
(else x)))
(cdr ins))))
(format "[~a~a]~a"
(asm-name asm)
(if (null? args)
""
(apply string-append
(map (lambda (x)
(format " ~a" x))
args)))
term))))
(define (format-target-word w)
(define port (open-output-string))
(print-target-word w port)
(get-output-string port))
(define (print-target-word word (port (current-output-port)))
(for-each (lambda (w)
(when (target-word-name w) (print-target-word-head w port)))
(reverse
(target-chain->list word))))
(define (print-target-word-head word
port
[addr-conv
(lambda (x) (* x (target-print-word-bytes)))])
(let* ((name (target-word-name word))
(addr (target-word-address word))
(bin (and addr (reverse (target-word-bin word))))
(code (map instruction->string
(reverse
(or (target-word-code word) '())
))))
(print-target-word-internal name port addr bin code addr-conv)))
(define (print-target-word-internal
name port addr bin code addr-conv)
(define w->s word->string)
(define (a->s x) (hex->string (/ (target-print-address-bits) 4) x))
(define (hex x)
(cond
((number? x) (w->s x))
((list? x) (apply string-append
(map (lambda (y)
(format "~a " (w->s y)))
x)))
(else "")))
(parameterize ((current-output-port port))
(let ((name-sym
(match
name
((list _ v) (a->s (addr-conv (target-value->number v))))
(sym sym))))
(printf
(if (and
((string-length (symbol->string name-sym)) . < . 7)
(not (null? code)))
"~a:"
"~a:\n")
name-sym))
(unless (null? code)
(let next ((a addr)
(b bin)
(c code))
(unless (null? c)
(display "\t")
(when a
(printf "~a " (hex a)) (printf "~a ~a"
(hex (addr-conv a)) (hex (car b))))
(printf "~a\n" (car c))
(next (and a (+ (length (car b)) a))
(and a (cdr b))
(cdr c)))))))