(Arne Babenhauserheide)
2016-10-07: Add still incorrect try to implement allowing a space in the name. three-witches-space-in-name Add still incorrect try to implement allowing a space in the name.
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
@@ -5,45 +5,97 @@ exec guile -L $(dirname $(dirname $(real
define-module : examples enter-three-witches
use-modules : ice-9 optargs
+ srfi srfi-1
+
+;; FIXME: This version currently does not allow using the same first
+;; name several times. It will need a more refined macro generator
+;; which first gathers all the necessary definitions and then builds
+;; them.
+
+define introduced-names '()
+
+define : say nameparts lines
+ . "Show the lines as said by the name defined by the list
+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
+ if : not : member pure-name introduced-names
+ error
+ format #f "Tried to use ~A who did not Enter. Introduced names: ~A"
+ . pure-name introduced-names
+ format #t "~A\n ~A\n\n"
+ string-join : map symbol->string nameparts
+ string-join
+ map : lambda (x) (string-join (map symbol->string x))
+ . lines
+ . "\n "
define-syntax Enter
syntax-rules ()
- : _ (name) b ...
+ : _ (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 ::: ()
- : _ (c :::) d :::
- format #t "~A\n ~A\n\n"
- string-join
- string-split (symbol->string 'name) #\_
- string-join
- map : lambda (x) (string-join (map symbol->string x))
- quote : (c :::) d :::
- . "\n "
- : _ c d :::
- ;; allow for modifier keywords after the 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
- format #t "~A:\n" : symbol->string 'c
- name d :::
- : _ c :::
- begin #t c :::
+ ;; 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
define : main args
- Enter : First_Witch
- Second_Witch
- Third_Witch
+ Enter : First Witch
+ Second Witch
+ Third Witch
- First_Witch
+ First Witch
When shall we three meet again
In thunder, lightning, or in rain?
- Second_Witch
+ Second Witch
When the hurlyburly's done,
When the battle's lost and won.
- Third_Witch
+ Third Witch
That will be ere the set of sun.
+