wisp
 
(Arne Babenhauserheide)
2016-10-09: Working version, including mood markers, but only with runtime three-witches-space-in-name

Working version, including mood markers, but only with runtime checking of second (and further) names.

diff --git a/examples/enter-three-witches.w b/examples/enter-three-witches.w
--- a/examples/enter-three-witches.w
+++ b/examples/enter-three-witches.w
@@ -23,7 +23,7 @@ of name parts.
        let 
          ;; symbols starting with : are not treated as part of the
          ;; name. They can be used as actor instructions
-         : pure-name : remove (lambda (x) (string-prefix? ":" (symbol->string x))) nameparts
+         : pure-name : remove (lambda (x) (string-prefix? ":" (symbol->string x))) : remove pair? nameparts
          if : not : member pure-name introduced-names
               error 
                 format #f "Tried to use ~A who did not Enter. Introduced names: ~A" 
@@ -35,43 +35,18 @@ of name parts.
                . lines
            . "\n  "
 
-define-syntax Speak
- syntax-rules ::: ()
-  ;; Support form for modifiers: enclose by double parens (used later)
-  ;; when using this name, print all lines indented, with the name in front.
-  : _ (((name :::))) ((mod :::)) (word :::) line :::
-    say
-      quote : name ::: mod :::
-      quote : (word :::) line :::
-  ;; extend mod keywords
-  : _ (((name :::))) ((mod :::)) modifier line :::
-    begin
-      ;; extend the modifier keyword list
-      Speak (((name :::))) ((mod ::: modifier)) line :::
-  ;; say form without modifier
-  : _ (((name :::))) (word :::) line :::
-    Speak (((name :::))) (()) (word :::) line :::
-  ;; first modifier keyword after the name
-  : _ (((name :::))) modifier line :::
-    begin
-      ;; append to mod helper form
-      Speak (((name :::))) ((modifier)) line :::
-  ;; Strip the name from lines with empty arguments
-  : _ (((name :::))) symbol :::
-    begin #t symbol :::
 
-
-define : longest-common-prefix-in introduced-names li
+define : longest-common-prefix li introduced-names
        . "Get the name with the longest common prefix with list li"
        let loop
          : names introduced-names
            longest '()
          if : null? names
-            . longest
+            reverse longest
             let lp
               : prefix '()
                 name : car names
-                l : li
+                l li
               if
                 or 
                   null? name
@@ -88,6 +63,38 @@ define : longest-common-prefix-in introd
                   cdr l
 
 
+define : Squeak . li
+       . "somehow say the given list"
+       let : : name : longest-common-prefix li introduced-names
+         say name : drop li (length name)
+       
+
+define-syntax Speak
+ lambda (x)
+  with-ellipsis :::
+   syntax-case x ()
+     ;; Support form for modifiers: enclose by double parens (used later)
+     ;; when using this name, print all lines indented, with the name in front.
+     : _ (((name :::))) ((mod :::)) (word :::) line :::
+         #` say
+             quote : name ::: mod :::
+             quote : (word :::) line :::
+     ;; extend mod keywords
+     : _ (((name :::))) ((mod :::)) modifier line :::
+         ;; extend the modifier keyword list
+         #` Speak (((name :::))) ((mod ::: modifier)) line :::
+     ;; say form without modifier
+     : _ (((name :::))) (word :::) line :::
+         #` Speak (((name :::))) (()) (word :::) line :::
+     ;; first modifier keyword after the name
+     : _ (((name :::))) modifier line :::
+         ;; append to mod helper form
+         #` Speak (((name :::))) ((modifier)) line :::
+     ;; Strip the name from lines with empty arguments
+     : _ (((name :::))) symbol :::
+         #` begin #t symbol :::
+
+
 define-syntax Enter
  lambda (x)
   syntax-case x ()
@@ -105,14 +112,20 @@ define-syntax Enter
            ; just forward matching rules to Speak
            : _ more ... symbol :::
              #' Speak (((name more ...))) symbol :::
-           ; : _ more ... symbol :::
-           ;   syntax-error
-           ;     . "Name not introduced:" name more ...
            : _ symbol ::: ; FIXME: This prevents checking at compiletime :(
-               ; FIXME: this does not correctly make the second name
-               ; part of the name, preventing differentiation between
-               ; name and modifier
-               #` Speak (((name))) symbol :::
+               ; this does not correctly make the second name part of
+               ; the name, preventing differentiation between name and
+               ; modifier, therefore we have to do that in the Speak
+               ; macro
+               #` let* 
+                    : n : longest-common-prefix '(name symbol :::) introduced-names
+                      lines : drop '(symbol :::) : 1- : length n
+                      line-start-index : list-index pair? lines
+                      line-head : drop-right lines : - (length lines) line-start-index
+                      line-tail : drop lines line-start-index
+                    say
+                      append n line-head ; add mood markers
+                      . line-tail
        ;; process the rest of the names
        Enter b ...
        ;; record that the name was introduced. I do not see a way to do
@@ -142,20 +155,28 @@ define : main args
       When shall we three meet again
       In thunder, lightning, or in rain?
   
-  Second Witch
+  Second Witch :resolute
       When the hurlyburly's done,
       When the battle's lost and won.
 
   Third Witch
       That will be ere the set of sun.
 
-  First Eldritch
+  First Eldritch :crazy
       gnignigni!
 
   Enter : Second Eldritch
   
-  Second Eldritch
+  Second Eldritch :quick
       Guh!
+      ; . :goo ; invalid ⇒ would be an error
+      ; . foo ; invalid ⇒ would be an error
+      Moo
+
+;; Making the name longer throws an Error, but only at runtime:
+;  Second Eldritch shoo
+;      Guh!
+;; ⇒ ERROR: Tried to use (Second Eldritch shoo) who did not Enter. Introduced names: ((Second Eldritch) (First Witch) (Second Witch) (Third Witch) (First Eldritch))
 
 ;; Adding one who did not enter throws an Error, but only at runtime:
 ;  Third Eldritch