;;; Stub that takes lisp source file as an argument and generates an executable
;;; for it. Assumes entry point is main.

(ql:quickload "unix-opts")

(defun file-test (filename)
(if (probe-file filename) filename (print "Couldn't find filename")))

(defun get-fn-str (filename)
(if (stringp filename) filename))

(opts:define-opts
(:name :help
:description "Print this text"
:short #\h
:long "help")
(:name :output-file
:description "File to write executable to"
:short #\f
:long "output-file"
:arg-parser #'get-fn-str)
(:name :entry-point
:description "Entry point for saved binary"
:short #\e
:long "entry-point"
:arg-parser #'read-from-string)
(:name :input-file
:description "File to load and save"
:short #\l
:long "load"
:arg-parser #'file-test))

;; See: https://github.com/libre-man/unix-opts/blob/master/example/example.lisp
(defmacro when-option ((options opt) &body body)
`(let ((it (getf ,options ,opt)))
(when it
,@body)))

;;(defun saver (filename entry-point)
;; (sb-ext:save-lisp-and-die filename :toplevel (function entry-point) :executable t :compression t))
(defmacro saver (filename entry-point)
`(sb-ext:save-lisp-and-die ,filename :toplevel ,entry-point :executable t :compression t))

(defun display-help ()
(progn
(opts:describe
:prefix "save.bin - Load and then save lisp files. Script over sb-ext:save-lisp-and-die"
:usage-of "save.bin"
:args "[FREE-ARGS]")
(quit)))

(defun builder ()
(if (> 2 (length sb-ext:*posix-argv*)) (display-help))
;;; Get and process args
(let ((matches (opts:get-opts)))
(progn
(format t "~a ~%" matches)
(when-option (matches :help)
(display-help))
;; Load program
(load (getf matches :input-file))
(print "Loaded file")
;; Save program
(saver (getf matches :output-file) (getf matches :entry-point)))))