Arc Forumnew | comments | leaders | submitlogin
Extend Arc's ssyntax?
2 points by evanrmurphy 4276 days ago | 4 comments
I'd like to override Arc's dot ssyntax and be able to use the period as a variable, as in

  (= . 5)
or at least

  (= |.| 5)
How would you go about doing this?

I've tried using aw's scheme macro [1] to redefine ac.scm's ssyntax functions, but no dice. I was able to use his extend-readtable to succeed at a similar operation for square brackets and curly braces:

  (mac read-normal (x)
    `(extend-readtable ,x
       (fn (port)
           (let c (peekc port)
             (unless (or (whitec  c) (ssyntax c) (in c #\( #\) ))
               (read port)))))))
  (read-normal #\[)
  (read-normal #\])
  (read-normal #\{)
  (read-normal #\})

  ; now I can do things like make `{` an alias for obj...

  arc> (= { obj)
  #(tagged mac #<procedure: obj>)
  arc> ({ a 1  b 2)
  #hash((a . 1) (b . 2))
But alas, it doesn't work for the dot:

  arc> (read-normal #\.)
  arc> (= . 4)
  Error: "list->string: expects argument of type <list of character>;   given #\\."
  arc> (= |.| 4)
  Error: "list->string: expects argument of type <list of character>; given #\\."
I found mentions in old posts [3] about a "ssyntaxes.arc" in Anarki that lets you do things like this, but it's not in my lib/. Nor do I see it on the github [4].

Please save me, Arc brethren!






2 points by waterhouse 4276 days ago | link

The function in ac.scm (in plain Arc) that expands ssyntax is this:

  (define (expand-ssyntax sym)
    ((cond ((or (insym? #\: sym) (insym? #\~ sym)) expand-compose)
           ((or (insym? #\. sym) (insym? #\! sym)) expand-sexpr)
           ((insym? #\& sym) expand-and)
       ;   ((insym? #\_ sym) expand-curry)
           (#t (error "Unknown ssyntax" sym)))
You could modify that function directly, by sticking (if (eq? sym '.) '. <proceed-as-usual>) in front of it. Or, if the Anarki guys have been through it, I'm guessing they added a hook at the beginning of that function, and wrote another function that would make it easy to add things to the hook. Look for 'expand-ssyntax in ac.scm, and follow where it leads you.


3 points by rocketnia 4276 days ago | link

Changing ac.scm's 'expand-ssyntax will make Arc's 'ssyntax predicate incorrect. The exception should be added in here, where there happen to already be a few exceptions that are currently meaningless:

  (define (ssyntax? x)
    (and (symbol? x)
         (not (or (eqv? x '+) (eqv? x '++) (eqv? x '_)))
         (let ((name (symbol->string x)))
           (has-ssyntax-char? name (- (string-length name) 1)))))
(This is quoted from Anarki 'cause the source is handier for me right now.)

Note, however, that calling Arc's 'ssexpand will expand a symbol regardless of whether it's an exception. I don't know whether this is a bug or not; the workaround is just to check with 'ssyntax first if it matters.


1 point by evanrmurphy 4274 days ago | link

Thanks for the tip, this is working well. The only minor issue I'm still dealing with on this is how to strip the dot of all special meaning except in the context of rest parameters.

By adding the dot ssyntax exception in ac and not applying the read-normal macro from the OP to #\., I've gotten this to work so long as dot is inside the scheme bars:

  ; Dot treated as a symbol when inside the bars

  arc> (= |.| 2)
  arc> (is (+ 1 1) |.|)

  ; It still works in the rest parameter context

  arc> (def foo (x . args)
         `(,x ,@args d))
  #<procedure: foo>
  arc> (foo 'a 'b 'c)
  (a b c d)

  ; But it doesn't work as a symbol without the bars.
  ; Note that (read-normal #\.) can make this work but
  ; it breaks the rest parameter case.

  arc> (= . 2)
  Error: "map: expects type <proper list> as 2nd argument,
  given: 2; other arguments were: #<procedure:ac-niltree>"
So I'm about 3/4 of the way there. :)


2 points by thaddeus 4276 days ago | link

I believe ssyntax.arc was a patch by the users that allowed you to dynamically over-ride the symbols. I remember seeing it in anarki v2.