wisp
 
(Arne Babenhauserheide)
2016-10-09: Add working try to implement allowing a space in the name, but not three-witches-space-in-name

Add working try to implement allowing a space in the name, but not yet with compile-time check.

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
@@ -1,4 +1,5 @@
 #!/usr/bin/env sh
+# -*- wisp -*-
 exec guile -L $(dirname $(dirname $(realpath "$0"))) --language=wisp -e '(@@ (examples enter-three-witches) main)' -s "$0" "$@"
 ; !#
 
@@ -6,6 +7,7 @@ define-module : examples enter-three-wit
 
 use-modules : ice-9 optargs
               srfi srfi-1
+              system syntax
 
 ;; FIXME: This version currently does not allow using the same first
 ;; name several times. It will need a more refined macro generator
@@ -33,61 +35,82 @@ 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-syntax Enter
- syntax-rules ()
-  : _ (name more ...) b ...
-    begin
-      ;; process the name: define special syntax for this name (only
-      ;; for the first word of the name, the correctness of the rest
-      ;; of the words is checked at runtime in the say procedure)
-      define-syntax name
-        syntax-rules ::: (more ...)
-          ;; Support form for modifiers: enclose by double parens (used later)
-          ;; when using this name, print all lines indented, with the name in front.
-          : _ more ... ((mod :::)) (word :::) line :::
-            say
-              ` name more ... mod :::
-              quote : (word :::) line :::
-          ;; extend mod keywords
-          : _ more ... ((mod :::)) modifier line :::
-            begin
-              ;; extend the modifier keyword list
-              name ((mod ::: modifier)) line :::
-          ;; say form without modifier
-          : _ more ... (word :::) line :::
-            say
-              ' name more ...
-              quote : (word :::) line :::
-          ;; first modifier keyword after the name
-          : _ more ... modifier line :::
-            begin
-              ;; append to mod helper form
-              name ((modifier)) line :::
-          ;; Strip the name from lines with empty arguments
-          : _ more ... symbol :::
-            begin #t symbol :::
-          ; : _ more ... symbol :::
-          ;   syntax-error
-          ;     . "Name not introduced:" name more ...
-      ;; process the rest of the names
-      Enter b ...
-      ;; record that the name was introduced. I do not see a way to do
-      ;; this directly in the compiler, therefore it is checked later
-      ;; during runtime.
-      set! introduced-names : cons '(name more ...) introduced-names
-      ;; add debug output, must be added it here, not in front
-      ; write 
-      ;   quote : list Enter (name more ...) b ...
-      ; newline
-  : _ b ...
-    begin 
+ lambda (x)
+  syntax-case x ()
+   : _ (name more ...) b ...
+     ; new binding: only create it if the binding is not already a macro
+     not : eq? 'macro (syntax-local-binding (syntax name))
+     #' begin
+       ;; process the name: define special syntax for this name (only
+       ;; for the first word of the name, the correctness of the rest
+       ;; of the words is checked at runtime in the say procedure)
+       define-syntax name
+        lambda (y)
+         with-ellipsis :::
+          syntax-case y (more ...)
+           ; 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 :(
+             with-syntax ((oldname (datum->syntax y 'name)))
+               ; FIXME: this does not correctly make the second name
+               ; part of the name, preventing differentiation between
+               ; name and modifier
+               #` Speak (((oldname))) symbol :::
+       ;; process the rest of the names
+       Enter b ...
+       ;; record that the name was introduced. I do not see a way to do
+       ;; this directly in the compiler, therefore it is checked later
+       ;; during runtime.
+       set! introduced-names : cons '(name more ...) introduced-names
+       ;; add debug output, must be added it here, not in front
+       ; write 
+       ;   quote : list Enter (name more ...) b ...
+       ; newline
+   : _ (name more ...) b ...
+     ; existing binding: Just allow using this. TODO: Make the checking happen at compile time.
+     with-syntax ((oldname (datum->syntax x 'name)))
+       #' begin 
+          set! introduced-names : cons '(name more ...) introduced-names
+   : _ b ...
+     #' begin 
 
 
 define : main args
   Enter : First Witch
           Second Witch
           Third Witch
-  
+          First Eldritch
+
   First Witch
       When shall we three meet again
       In thunder, lightning, or in rain?
@@ -99,3 +122,20 @@ define : main args
   Third Witch
       That will be ere the set of sun.
 
+  First Eldritch
+      gnignigni!
+
+  Enter : Second Eldritch
+  
+  Second Eldritch
+      Guh!
+
+;; Adding one who did not enter throws an Error, but only at runtime:
+;  Third Eldritch
+;      Guh!
+;; ⇒ ERROR: Tried to use (Third Eldritch) who did not Enter. Introduced names: ((Second Eldritch) (First Witch) (Second Witch) (Third Witch) (First Eldritch))
+
+
+
+
+