(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))
+
+
+
+
+