#!/usr/bin/env mzscheme
#lang scheme/base
(require scheme/pretty
scheme/cmdline
(planet zwizwa/staapl/tools))
(define-syntax-rule (flags: name ...)
(begin (define name (make-parameter #f)) ...))
(flags: output-hex
output-dict
console
device
baud
filename
print-asm
output-script
debug-script
dict-suffix
debug-suffix
)
(baud #f)
(print-asm void)
(dict-suffix ".dict")
(debug-suffix ".ss")
(define (get-arguments)
(filename
(command-line
#:program "staaplc"
#:once-each
[("-o" "--output-hex") filename "Output Intel HEX file."
(output-hex filename)]
[("--print-code") "Print assembly and binary code output."
(print-asm (lambda () (eval '(code-print))))]
[("--script") "Don't wrap dictionary as a loadable module."
(dict-suffix ".dict-script")
(output-script #t)]
[("-c" "--comm") filename "Console port. (default: pickit2)" (console (string->symbol filename))]
[("-d" "--device") filename "Console system device. (default: /dev/staapl0)" (device filename)]
[("--baud") number "Console baud rate. (default from source file)" (baud (string->number number))]
[("-d" "--output-dict") filename "Output dictionary file."
(output-dict filename)]
#:args (fname)
fname)))
(define (out param template suffix)
(let ((p (param)))
(unless p
(param
(let-values (((base name _) (split-path template)))
(path-replace-suffix name suffix))))))
(define (absolute param)
(let ((p (param)))
(param
(if (absolute-path? p)
(string->path p)
(path->complete-path p)))))
(define (dir-of path)
(let-values (((base name _) (split-path path)))
base))
(define (requirements path)
`(require
(planet zwizwa/staapl/tools) (planet zwizwa/staapl/live) (planet zwizwa/staapl/code) (planet zwizwa/staapl/port/ihex) (planet zwizwa/staapl/pic18) (file ,(path->string path))))
(define (process-arguments)
(out output-hex (filename) ".hex")
(out output-dict (filename) (dict-suffix)) (out debug-script (filename) (debug-suffix))
(absolute filename)
(absolute output-hex)
(absolute output-dict)
(absolute debug-script)
)
(define (warnf . args)
(display "WARNING: ")
(apply printf args))
(define (console-spec)
(unless (baud)
(let ((b (eval '(macro-constant 'baud))))
(baud b)))
`(console ',(console) ,(device) ,(baud)))
(define (instantiate-and-save)
(unless (file-exists? (filename))
(printf "input file not found: ~a\n" (filename))
(exit 1))
(parameterize
((current-namespace
(make-base-namespace)))
(eval (requirements (filename)))
((print-asm))
(with-output-to-file/safe
(output-hex)
(lambda ()
(eval '(write-ihex (code->binary)))))
(let* ((defs
`(begin
(define labels ',(eval '(code-labels)))
(define pointers ',(eval '(code-pointers)))
(define device ',(device))
(define baud ',(baud))
(define script ',(path->string (debug-script)))))
(reqs (requirements (filename)))
(boot-init `(begin
,(console-spec)
(define (empty)
(code-clear!)
(target-words-check! labels)
(code-pointers-set! pointers)
(clear-flash)
(when-file script load))))
(boot-run
`(begin
(require readline/rep)
(param-to-toplevel 'command repl-command-hook)
(param-to-toplevel 'break repl-break-hook)
(run (lambda () (empty)))))
(save (lambda (text [code #f])
(display text)
(newline)
(when code
(pretty-print code))))
(save-exprs
(lambda ()
(save ";; Target info" defs)
(save ";; Language" reqs)
(save ";; Console setup" boot-init)))
(save-module
(lambda ()
(save "#!/usr/bin/env mzscheme")
(save "#lang scheme/load") (save-exprs)
(save ";; Console run" boot-run))))
(with-output-to-file/safe
(output-dict)
(if (output-script)
save-exprs
save-module)))))
(define (main)
(get-arguments)
(process-arguments)
(instantiate-and-save))
(main)