| As I understand it, Anarki at some point allowed Arc programs to add custom ssyntax. Not sure if it's still in the current version of Anarki or not. In any case, since I'm implementing my own Arc interpreter (in Python), and I'm just about to add in ssyntax, I got to thinking about the Arc interface for custom ssyntax. Here's a quick mockup for the core: (= (ssyntax-rules* #\:) (obj infix (fn (l r) `(compose ,l ,r))))
(= (ssyntax-rules* #\~) (obj prefix (fn (r) `(complement ,r))))
(= (ssyntax-rules* #\.) (obj infix (fn (l r) `(,l ,r))))
(= (ssyntax-rules* #\!) (obj infix (fn (l r) `(,l ',r))))
(= (ssyntax-rules* #\&) (obj infix (fn (l r) `(andf ,l ,r))))
And here's the same thing, but with a nice add-ssyntax-rules macro: (add-ssyntax-rules
(#\: (l r) `(compose ,l ,r))
(#\~ (r) `(complement ,r))
(#\. (l r) `(,l ,r))
(#\! (l r) `(,l ',r))
(#\& (l r) `(andf ,l ,r)))
Basically, what's going on here is that ssyntax-rules* is a global alist that contains all the syntax rules. Each rule can contain a prefix, infix, and/or suffix properties, which should be functions. These functions behave like macros, in that they return a representation of what the ssyntax should expand into.With add-ssyntax-rules, you must use l or r for the property names, since that's how it knows whether it's a prefix, infix, or suffix ssyntax. If you assign directly to ssyntax-rules* then you can use any argument names you want. So, if you wanted to swap the semantics of ! and . you could use this: (let x (ssyntax-rules* #\.)
(= (ssyntax-rules* #\.) (ssyntax-rules* #\!))
(= (ssyntax-rules* #\!) x))
And now . means (x 'y) and ! means (x y)If there was a swap function/macro available, you could just do this: (swap ssyntax-rules* #\. #\!)
With this system, ssyntax can be scoped to each module, so ssyntax defined in one module won't mess up other modules. But let's say a module had a cool ssyntax for % and you wanted to import it. You could do this: (import foo "foo.arc")
(= (ssyntax-rules* #\%) (foo!ssyntax-rules* #\%))
A macro could be written to make the above much nicer: (import-ssyntax foo #\%)
Does this interface look good? Do you think it's powerful enough? For instance, do people want right-associative ssyntax? Here are my requirements:1. Needs to be able to define prefix, infix, and suffix versions for the same character. 2. Needs to have separate ssyntax per module, so ssyntax defined in one module doesn't interfere with another module. 3. Needs to be able to import ssyntax from another module, either wholesale or selectively. Ideally this should be super easy, but I'm more concerned about the core. I can write a macro that wraps around the core and makes it easy, so it's okay if the core is somewhat verbose. Also, I had an idea of defining ssyntax so it only affects argument parameters. For instance, I would like this to work: (def (a=1 b=2 c=3)) -> (def ((= a 1) (= b 2) (= c 3))) ; PyArc
(def ((o a 1) (o b 2) (o c 3))) ; MzArc
But I don't want to mess up function names like expand= or expand=list in arc.arc. This could be as simple as having a ssyntax-argument-rules* global, in addition to ssyntax-rules* but I'm not sure if I want to go that route. Ideas? |