7178a2f4efdab39cc09736ecb8bf4585d2a0c90c — Brit Butler 1 year, 1 month ago a37617b
Lean more heavily into the subcommand style.
3 files changed, 65 insertions(+), 17 deletions(-)

M TODO.org
M src/shell.lisp
M JOURNAL.md => JOURNAL.md +19 -2
@@ 1,5 1,22 @@
### Dev Log

#### 2023/01/01 - Writing Code
#### 2023/03/12 - Sketching a Structure

I'm on my honeymoon and flying back in four days. I haven't started
hacking on rascal "in earnest" but there has been enough time on the bus
to learn clingon a bit and start on the CLI tool, layout some basics of
a protocol for the various sublanguages to work with, etc.

I'm basing this project on Jeremy Siek's Essentials of Compilation, just
adapting it to Common Lisp and to my own sense of aesthetics.

We're about 30 minutes from lunch and 3 and a half hours from Fes. My hope is
that I can get an interpreter for the Integer language in chapter 1 spun up and
figure out parsing. It would also be nice to be able to dump the AST with 
CL-DOT as a debugging aid via the command line.

There are a fair number of details that the book elides which I will try to
reconstruct by hand. Parsing, for example, is something they handle for you. I
should be able to parse via files, strings, and lists (lisp forms). Probably
best to start with just one though, I lean toward files. As for the runtime
written in C they supply, I'll figure out whether to reuse that later. :)

M TODO.org => TODO.org +1 -1
@@ 1,2 1,2 @@
* rascal Tasks
** TODO - Define some tasks...
** TODO - Figure out how to parse code (from files initially)

M src/shell.lisp => src/shell.lisp +45 -14
@@ 1,10 1,12 @@
(mgl-pax:define-package :rascal.shell
  (:use :cl :alexandria :mgl-pax)
  (:import-from :clingon

(in-package :rascal.shell)

@@ 15,20 17,49 @@ Here we document the usage and options the rascal shell command supports.
Rascal is powered under the hood by [clingon][clingon]."
  (command function))

(defun options ()
  "Generates the list of options for the `rascal` command."
;; KLUDGE: Override the usual command initialization from clingon since I
;; prefer a subcommand heavy style and will provide help and version that way.
(defmethod initialize-instance :after ((command clingon:command) &key)
  ;; Configure the parent for any of the sub-commands.
  (dolist (sub (clingon:command-sub-commands command))
    (setf (clingon:command-parent sub) command)))

(defun handler (command)
  "A handler that ignores the command options and prints usage."
  (print-usage command t))
(defvar *no-options* '())

(defun help/handler (command)
  (print-usage-and-exit (clingon:command-parent command) t))

(defun help/command ()
  (make-command :name "help"
                :description "Print usage information for rascal"
                :options *no-options*
                :handler #'help/handler))

(defun version/handler (command)
  (print-version-and-exit command t))

(defun version/command ()
  (make-command :name "version"
                :description "Display the installed rascal version"
                :options *no-options*
                :handler #'version/handler
                :version (asdf:system-version (asdf:find-system :rascal))))

(defun toplevel/handler (command)
  (let ((args (command-arguments command)))
    (if (zerop (length args))
        (print-usage-and-exit command t)
        (format t "TODO~%"))))

(defun command ()
  "The entry point for the `rascal` command."
  (make-command :name "rascal"
                :description "Radically Simple Compiler for a Lisp"
                :version (asdf:system-version (asdf:find-system :rascal))
                :authors '("Brit Butler")
                :license "MIT"
                :options (options)
                :handler #'handler))
  (let ((subcommands (list (help/command)
    (make-command :name "rascal"
                  :description "Radically Simple Compiler for a Lisp"
                  :version (asdf:system-version (asdf:find-system :rascal))
                  :authors '("Brit Butler")
                  :license "MIT"
                  :options *no-options*
                  :handler #'toplevel/handler
                  :sub-commands subcommands)))