about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--basic.lsp (renamed from comal.lsp)0
-rwxr-xr-xcbtech.lisp18
-rw-r--r--cbuiltins.lisp18
-rw-r--r--ccmd.lisp28
-rwxr-xr-xchello.lisp3
-rw-r--r--doc/Makefile7
-rw-r--r--doc/bane.20.cdr15.md48
-rw-r--r--doc/breaking_rules.md98
8 files changed, 172 insertions, 48 deletions
diff --git a/comal.lsp b/basic.lsp
index 571d4a6..571d4a6 100644
--- a/comal.lsp
+++ b/basic.lsp
diff --git a/cbtech.lisp b/cbtech.lisp
new file mode 100755
index 0000000..15eda5a
--- /dev/null
+++ b/cbtech.lisp
@@ -0,0 +1,18 @@
+(require "ccmd")
+(require "cbuiltins")
+(defpackage #:cbtech
+  (:use #:common-lisp #:ccmd #:cbuiltins)
+  (:export
+    #:main))
+(in-package #:cbtech)
+;; Favour symbols & objects over C-like numbers
+(defconstant +cmds+ (list
+                      (create-tab #'bt-quit "QUIT" 1)
+                      (create-tab #'help "help" 2)
+                      (create-tab #'look "look" 2)))
+(defun main ()
+  (format *standard-output* "> ")
+  (let* ((tab (lookup (parse (read-line)) +cmds+))
+         (f (fun tab)))
+    (funcall f)))                       ; I *think* this is better than (flet ...
+(provide "cbtech")
diff --git a/cbuiltins.lisp b/cbuiltins.lisp
new file mode 100644
index 0000000..fa78407
--- /dev/null
+++ b/cbuiltins.lisp
@@ -0,0 +1,18 @@
+(defpackage #:cbuiltins
+  (:use #:common-lisp)
+  (:export
+    #:connect
+    #:bt-quit
+    #:help
+    #:look)
+  )
+(in-package #:cbuiltins)
+(defun connect ()
+  (format *standard-output* "TODO: connect~%"))
+(defun bt-quit ()
+  (format *standard-output* "TODO: quit~%"))
+(defun help ()
+  (format *standard-output* "TODO: help~%"))
+(defun look ()
+  (format *standard-output* "TODO: look~%"))
+(provide "cbuiltins")
diff --git a/ccmd.lisp b/ccmd.lisp
new file mode 100644
index 0000000..a3eeabd
--- /dev/null
+++ b/ccmd.lisp
@@ -0,0 +1,28 @@
+(require "split-sequence")
+(defpackage #:ccmd
+  (:use #:common-lisp #:split-sequence)
+  (:export
+    #:parse
+    #:create-tab
+    #:fun
+    #:lookup)
+  )
+(in-package #:ccmd)
+(defclass <buf> () ((buf :initarg b :reader buf) (f :initarg f :reader f)))
+(defun parse (p)
+  (let ((toks (split-sequence-if (lambda (c) (member c '(#\Space #\Tab))) p)))
+    (format *error-output* "parse: p ~A toks ~A~%" p toks)
+    (make-instance (find-class '<buf>) 'b (car toks) 'f toks)))
+(defclass <tab> () ((fun :initarg f :reader fun)
+                    (cmd :initarg c :reader cmd)
+                    (narg :initarg n :reader narg)))
+(defun create-tab (f c n)
+  (make-instance (find-class '<tab>) 'f f 'c c 'n n))
+(defgeneric lookup (buf tab))
+(defmethod lookup ((buf <buf>) tabs)
+  (let ((cmd (buf buf)))
+    (find-if (lambda (tab)
+               (let ((c (cmd tab)))
+                 (string= c cmd)))
+             tabs)))
+(provide "ccmd")
diff --git a/chello.lisp b/chello.lisp
new file mode 100755
index 0000000..55b5999
--- /dev/null
+++ b/chello.lisp
@@ -0,0 +1,3 @@
+#!/usr/local/bin/sbcl --script
+
+(format *standard-output* "~A~%" "Hello world")
diff --git a/doc/Makefile b/doc/Makefile
index 2a8f5cc..adae890 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -2,7 +2,7 @@
 .DELETE_ON_ERROR:
 
 .PHONY: all
-all: breaking_rules.pdf breaking_rules.html
+all: breaking_rules.pdf breaking_rules.html breaking_rules.txt
 
 # Stick with gfm for as long as possible.
 # Use stuff beyond that only where absolutely necessary.
@@ -15,9 +15,12 @@ breaking_rules.pdf: macros.ms breaking_rules.md refs.i
 breaking_rules.html: macros.ms breaking_rules.md refs.i
 	( cat macros.ms; lowdown -sTms breaking_rules.md ) | groff -Txhtml -i -t -R -ms -k -Kutf8 > $@
 
+breaking_rules.txt: macros.ms breaking_rules.md refs.i
+	( cat macros.ms; lowdown -sTms breaking_rules.md ) | env GROFF_NO_SGR=t groff -Tlatin1 -i -t -R -ms -k -Kutf8 -c | ul > $@
+
 refs.i: refs
 	indxbib $^
 
 .PHONY: clean
 clean:
-	$(RM) breaking_rules.pdf breaking_rules.html
+	$(RM) breaking_rules.pdf breaking_rules.html breaking_rules.txt
diff --git a/doc/bane.20.cdr15.md b/doc/bane.20.cdr15.md
new file mode 100644
index 0000000..d999852
--- /dev/null
+++ b/doc/bane.20.cdr15.md
@@ -0,0 +1,48 @@
+title: An ISLisp-like subset of ANSI Common Lisp  
+author: Darren Bane  
+copyright: 2020 Darren Bane, CC BY-SA  
+
+# Abstract
+
+A subset of Common Lisp that has rough feature parity with ISLisp is defined.
+
+# Introduction
+
+There are many Common Lisp coding standards encoding the opinion of various experts.
+This document defines yet another, but relies on the opinions of the ISLisp standard committee instead.
+
+The ANSI Common Lisp standard explicitly allows subsets.
+ISLisp was designed to be "culturally-compatible" with Common Lisp,
+and indeed it is only moderate work to port between them
+(and incidentally, also ELisp).
+
+# Procedure
+
+Write an ISLisp program, making the following adaptations:
+
+* `for` becomes `do`
+* `quotient` becomes `/`
+* `create` becomes `make-instance`
+* `(class x)` becomes `(find-class 'x)`
+* `(standard-output)` becomes `*standard-output*`
+
+ISLisp doesn't have the following features (and probably many more):
+
+* structs. Use classes instead.
+* `print-object`. But you can define it yourself.
+
+## Extensions to ISLisp
+
+It was noted in the ISLisp standard document that the committee would have liked to define packages.
+So I recommend the following pattern, using the subset of CL packages that OpenLisp supports:
+
+```lisp
+(require "dependency")
+(defpackage #:pack
+  (:use #:common-lisp #:dependency)
+  (:export
+    #:fun))
+(in-package #:pack)
+...
+(provide "pack")
+```
diff --git a/doc/breaking_rules.md b/doc/breaking_rules.md
index 5061df7..c0f3272 100644
--- a/doc/breaking_rules.md
+++ b/doc/breaking_rules.md
@@ -39,8 +39,9 @@ pitman 1994
 .
 
 *NB*: I am almost certainly re-inventing a SmallTalk wheel.  However I
-argue that Lisp's combination of imperative & OO has been validated by
-industry whereas pure OO as in SmallTalk (or logic programming as in
+argue that Lisp's combination of imperative & OO
+is an easier sell to industry
+whereas pure OO as in SmallTalk (or logic programming as in
 Prolog) is still niche.
 
 A closely related are is that of "specification animation",
@@ -65,41 +66,42 @@ bane 2008
 \.]
 .
 
-Reasons for choosing ISLisp include:
+Reasons for choosing Common Lisp include:
 
 * Procedural and object-oriented programming is commonly taught.
-  And seems to be easier to learn.
-* A disregard for popularity (which Common Lisp, or Java would win).
-  In fact, the language seems more popular in France and Japan than
-  the USA.
-* The efficiency gain from an integrated environment.
-  With Emacs and JSON-RPC it's not totally integrated, but is close.
-  ELisp and ISLisp are not identical but are very similar.
+* The existence of quicklisp.
+  Popularity is not really a reason for choosing Common Lisp over ISLisp,
+  but slotting into quicklisp *is*.
+* Limit to recommendations from the
+  [awesome list](https://github.com/CodyReichert/awesome-cl),
+  or [portability layers](https://github.com/CodyReichert/awesome-cl#portability-layers).
 * Contrary to a lot of other languages, it is fairly paradigm-agnostic.
 
-Unlike Prolog,
-users may end up writing logic eventually for DbC
-but there is no need to force it at the start.
+At the same time, I want a clean subset of CL,
+so cleave as close to ISLisp as practical.
 
-A JSON-RPC library was not difficult to write.
+*TODO*: write CDR
 
-It was decided to use the imperative/object-oriented paradigm.
+It was decided to use the imperative/object-oriented paradigm,
+partly for familiarity in industry and
+partly for a reduced "impedence mismatch" to current hardware.
 The following technology is recommended:
 
-* The OpenLisp interpreter.
-* Emacs for the view layer
-* JSON-RPC for inter-process communication
+* The SBCL compiler.
+* ltk for the view layer.
 
-## Codinmg standards
+The following is probably the most work that makes sense
+without earning money.
+
+## Coding standards
 
 Even though this is a prototype, attention should be paid to basic craftsmanship.
 
-* Divide the system into packages, using at least the subset of CL that is
+* Divide the system into packages, using the subset of CL that is
   supported by OpenLisp
-* Write one-sentence comments for at least each public fun and class
-* Use `assure`
+* Write one-sentence docstrings for at least each public fun and class
+* Use `declare`
   to check the types of parameters in public interfaces.
-  This should probably be done using `defcontract`.
 * Indent all the source code using Emacs.
 * Some minimal documentation, at least an overview README file
 \.[
@@ -111,14 +113,19 @@ collyer cox
 \.]
 .
 
-## Further Work
+## Rejected alternatives
 
-This is probably the most work that makes sense
-without earning money.
+You could use an integrated environment.
+With Emacs and JSON-RPC
+(ELisp and ISLisp are not identical but are very similar),
+but I reject this because jsonrpc is outside this list and
+I don't want to maintain my own.
 
-* Write better pre- and post-conditions in contracts for public funs & classes
-* Could do simple multi-user,
-  using the IRCv3 bots (nickserv, chanserv) and IRCCloud or similar
+DbC would be another nice-to-have,
+but I settle for `(declare`.
+
+Could do simple multi-user,
+using the IRCv3 bots (nickserv, chanserv) and IRCCloud or similar
 
 # Refinement to Production-Quality
 
@@ -130,17 +137,17 @@ If so, I argue that there is a repeatable procedure to improve the quality of a
 First, ensure that the surrounding infrastructure is in place:
 
 * Configuration management. The prototype should already have been checked into git.
-* Build. TODO: Read the recommendations in the OpenLisp manual?
+* Build. Write an ASDF description, and install as a local quicklisp package.
 * Test.
-  Write olunit
-  test cases for any scenarios that aren't coverered by DbC.
+  Write FiveAM
+  test cases.
 * Track. Start using a defect tracking system.
 
 Then, the following code & documentation improvements should be made:
 
 * Document the system more exhaustively
-* Port some of the trivial-\* CL libraries from quicklisp where justified.
-* Port to core-lisp on platform.sh?
+* Can use more of quicklisp, e.g. the trivial-\* libraries.
+* Port to platform.sh?
 
 ## Documentation Details
 
@@ -152,8 +159,8 @@ PlantUML *should* be used where it can replace ad-hoc text.
 
 Documents should be stored under git in a "doc" subdirectory of the project.
 
-I think it is a good idea to keep the separation between library and UI code.
-And JSON-RPC is perfectly adequate for that.
+I think it is a good idea to keep the separation between library and UI code
+when using ltk.
 
 ### Library
 
@@ -165,12 +172,11 @@ bane 2008
 However, some of this documentation is better in the source code:
 
 * The summary of functions should be taken care of by having the public functions and classes commented.
-* The formal requirement for function behaviour is better done with contracts.
-  Tables with Basic English
+* The formal requirement for function behaviour can be donw with
+  tables with Basic English
 \.[
 basic english
-\.]
-  are still a good idea for initial work.
+\.].
 
 ### UI
 
@@ -182,21 +188,21 @@ The following can be added as sections to the README:
 And a proper software requirements spec should be written filling in any blanks that the man pages leave.  
 The specification of input and output variables is best left at the level of tables and Basic English again.
 
-For the UI *technology*, it's probably best to skip local GUIs altogether and go
-straight to ParenScript, Backbone, etc.
+*TODO*: For the UI *technology*, is it best to skip local GUIs altogether and go
+straight to ParenScript, Backbone, etc.?
 
 ## Testing
 
-Unit (olunit) tests should be derived from the module interface specs.
+Unit (FiveAM) tests should be derived from the module interface specs.
 Property-based testing would be nice here, but there doesn't seem to be a readily-available library.
 System tests should be derived from the requirements spec.
-It's ok for system tests to use the JSON-RPC interface.
+It's ok for system tests to use the same interfaces as the ltk code.
 All tests should be automated,
 except possibly for the UI/view layer.
 Q: These scripts could be generated from a literate test plan?
 
-Where there is scope to push some of the testing work "back" in the V model to contracts for the functions,
-this should be done instead.
+It would be nice to push some of the testing work "back" in the V model to contracts for the functions,
+but quid-pro-quo isn't really blessed.
 
 # Conclusion