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