Arc Forumnew | comments | leaders | submitlogin
1 point by rocketnia 5132 days ago | link | parent

I just re-implemented 'self-orderer-reducer so that it doesn't use continuation-based backtracking. :D I wanted to do that sooner or later anyway, just so that I could port Lathe libraries over to continuation-free languages if and when I wanted to.

In order to do this, I ended up porting an iteration library I'd written from Groovy to Arc, and then the problem was still hairy enough that I had to write Groovy pseudocode for what I wanted and port that too. Not counting the libraries each version needs (amb.arc and iter.arc), the new version is more than twice the size of the old one, and I'm sure it has more than twice as many fiddly bugs I haven't found yet. But hey, no continuations.

I'll try it out on Jarc later today. There are other things like reliance on tail-call optimization that might get in the way, but I'm generally hopeful.



3 points by rocketnia 5131 days ago | link

It turns out supporting Jarc is way more challenging than I expected, and I'm going to give up for now. I pushed what I had to a new branch--woo, first time branching!--and it incorporates workarounds for quite a few idiosyncrasies of Jarc:

- Jarc doesn't have re-invokable continuations. As I mentioned earlier, I'm not relying on those for most of Lathe right now.

- Jarc has no 'get, despite having '.a and '!a ssyntax that expand to 'get forms. So I defined 'get myself, complete with an extension of setforms to make (= ((get a) b) c) work the way it works in Arc 3 and 3.1.

- Jarc has no 'a&b ssyntax, and the implementation of 'andf returns t on success rather than passing on the return value of the last function. So I defined 'doandf and used that instead.

- Jarc has no 'assign; it's named 'set instead. So I defined an 'xassign macro that could expand to the correct special form on Jarc or otherwise.

- Jarc has no (let (first . rest) lst ...) destructuring. I stopped using that.

- Nested quasiquotes don't work the same way in Jarc. I stopped using them.

- Jarc's 'compose apparently isn't a metafn. The symptom is that if I'm using 'a:b ssyntax where a or b is the name of a macro or special form, the arguments are still evaluated. I stopped using 'a:b syntax in these cases, and that was painful, since it gave every '(my:foo a b c) form an additional set of parentheses. I should have defined another macro to save me from adding those parentheses, but it didn't cross my mind until now.

Then I came across these two quirks in macro expansion:

  ; In Jarc, macros in subexpressions of function bodies are not
  ; expanded when the functions are compiled; instead, they're expanded
  ; when the functions are called.
  
  (mac foo () 1)
  (def bar () (foo))
  (mac foo () 3)
  (let foo (annotate 'mac (fn () 4))
    (bar))  ; results in 1 everywhere I've tested
  
  (mac foo () 1)
  (def bar () (idfn (foo)))
  (mac foo () 3)
  (let foo (annotate 'mac (fn () 4))
    (bar))  ; results in 3 on Jarc, but results in 1 on Arc 2 and others
  
  ; In Jarc, the macro expansions delayed this way are expanded
  ; according to the macros bound in their lexical environment rather
  ; than those in the global environment. I presume that this is an
  ; intended feature and that the other quirk exists mainly to let this
  ; work.
  (mac foo () 1)
  (let foo (annotate 'mac (fn () 2))
    (def bar () (foo)))
  (mac foo () 3)
  (let foo (annotate 'mac (fn () 4))
    (bar))  ; results in 2 on Jarc, but results in 1 on Arc 2 and others
The first quirk means my namespace macros almost never work from inside functions. Suppose I write something like this:

  (using-rels-as ut "utils.arc"
    
    (def my.fn-something (x)
      (- x 1))
    
    (mac my.something args
      `(,my!fn-something ,(apply ut.arg-counter args)))
    )
This won't macro-expand my!fn-something or ut.arg-counter until the 'something macro is invoked, by which time 'my and 'ut might be bound to completely different values.

I tried following along with these quirks so that when Lathe was running on Jarc, 'my and 'ut would be bound lexically rather than globally... but then I discovered that 'setforms doesn't expand places based on their lexically bound macros. I think 'setforms must call 'macex from within its own lexical environment, thereby neglecting any macros scoped in the expression's lexical context. And since all of my own uses of 'macex suffer from exactly the same problem, I've finally run out of steam.

For now, I'm just going to work on something besides Jarc support unless somebody here has a better idea. ^_^

-----

1 point by jazzdev 5123 days ago | link

Wow. Thanks for the laundry list. Most of the missing things are probably because I haven't moved Jarc from arc2 to arc3 yet. That's why assign is still called set also. I do plan do this. Probably as soon as I get the compiler working.

The macro expansion was just an expedient. Toplevel macros in functions are expanded at closure-time because it was trivial to implement. I wasn't sure how to do general expansion of all macros without a compiler, but I realize now, it's fairly straight-forward (you just have to know the semantics of the special forms). So I can envision a fix for this now. I never realized that delaying macro expansion would change the semantics (due to different lexical environment at expansion time), that seems pretty bad. I should probably look at fixing this before finishing the compiler.

-----

2 points by jazzdev 5120 days ago | link

I've fixed the most egregious problem, that of macro expansion timing in Jarc 10, released today.

I do plan to address the rest of these issues also in the next week or so. I appreciate all the info on Jarc incompatibilities with Arc. I wasn't aware of all of them.

-----