Arc Forumnew | comments | leaders | submitlogin
Jarc 10 Released
3 points by jazzdev 5315 days ago | 4 comments
Jarc 10 was released today. This releases fixes the bogus macro expansion timing that rocketnia mentioned in http://arclanguage.org/item?id=11621

All macros are now expanded at closure-time, so

  (mac foo () 1)
  (def bar () (idfn (foo)))
  (mac foo () 3)
  (let foo (annotate 'mac (fn () 4))
    (bar)) 
now returns 1 in Jarc 10, like it should.


3 points by rocketnia 5314 days ago | link

I made some headway moving Lathe's buggy-jarc branch forward thanks to Jarc 10, but I think I'm stuck again. Here's the sequel to that laundry list:

~~~

- The change to macros doesn't extend to ssyntax. Forms like some-macro!foo and some-macro.foo still don't use the compile-time global binding of 'some-macro. At first I thought this just affected macro!foo, but I should have known better, and the prospect of changing over a hundred instances of my.var-name into (my var-name) throughout the code, only to change them back as soon as you fixed this, was daunting enough that it's what finally burned me out.

- Saying (fn () in) errors out. The 'in macro can be replaced with the name of any macro in lexical scope (!) that requires at least one argument. As far as I can tell, the Jarc compiler compiles (fn () a b c) by compiling the expression (a b c), discarding the result, and then compiling a, b, and c as it should. Anyway, I got around this using the idiom (fn () idfn.in).

- Saying (fn ()) errors out, rather than being equivalent to (fn () nil). I actually noticed this last time, but I forgot to mention it, and the (fn () in) case reminded me.

- For whatever reason, you're calling 'quasiquote 'backquote. This didn't cause me any trouble on its own, but it did get in my way as I was "fixing" some nested quasiquotes I missed last time.

- I'm sure you know about this, but Jarc is missing a bunch of Arc 3.1 utilities. In particular, I had trouble with each's different treatment of tables and split's non-treatment of strings. I also miss arc.arc's 'down as well as strings.arc's 'tokens and 'subst. For the most part, I just copied those into the REPL as I tested and pretended they weren't a problem, but I thought I'd mention it anyway.

- Jarc doesn't recognize the space literal character when it's written as "#\ " without the quotes. (On the plus side, it does recognize "#\space". Nice!) I don't know if I like seeing "#\ " in code, but this nevertheless prevented me from simply loading Arc 3.1's strings.arc to get the functions I wanted.

~~~

The following don't actually have much to do with Lathe. They're only corner cases that came to mind just now:

~~~

- The expressions (is (obj a 1) (obj a 1)) and (iso (obj a 1) (obj a 1)) return t in Jarc even though they return nil in Arc 3.1. The first is a bug, but the second is arguably a feature, and it's consistent with Anarki.

- The result of (odd:len:copy (table) (annotate t t) t (annotate t t) t) is nil in Jarc even though it's t in Arc 3.1 (since Scheme's vectors have special 'equals? behavior).

~~~

Good luck with whatever you do next. If you fix the some-macro.foo problem, I'll be sure to try porting Lathe once again. ^_^

-----

2 points by jazzdev 5314 days ago | link

Jarc 11 has just been released which addresses:

- ssyntax is now expanded at closure time (I noticed this yesterday too, bad...) - can now parse "#\ " - fixed (fn () in) - fixed (fn ())

quasiquote is called backquote for historical reasons. I'll change this when I update Jarc to Arc 3.1

'(is (obj a 1) (obj a 1)) and (iso (obj a 1) (obj a 1))'

Yeah, the latter is useful. They both return t because they share the same code, I can't see any simple, elegant way to have the former fail and latter work.

And I wish I didn't have to choose between Arc behavior and Anarki behavior. I'll probably go with Arc semantics. Yeah, Anarki arc.arc can always be used to get Anarki semantics.

Thanks for the new test cases!

-----

1 point by rocketnia 5312 days ago | link

If there's one way Lathe's made a difference, it's by helping find test cases for Jarc. :-p That said, that role may tone down a bit because... I'm proud to announce that Lathe's buggy-jarc branch now passes all its tests! It's not so buggy anymore.

In the process of getting to that point, I did find a few more things:

- The some-macro.arg case was only partially fixed. In particular, some-macro.arg.another-arg slipped through the cracks, as well as the case where some-macro.arg is in function parameter position. All these give 2 when they should give 1:

  (mac foo (_) '[do 1])
  (def bar () foo.baz.0)
  (mac foo (_) '[do 2])
  (bar)
  
  (mac foo (_) 1)
  (def bar () (idfn foo.baz))
  (mac foo (_) 2)
  (bar)
  
  (mac foo (_) t)
  (def bar () (if foo.baz 1 2))
  (mac foo (_) nil)
  (bar)
I ended up just working around this by manually expanding the ssyntax, just like I talked about not wanting to do. ^_^ Since the majority of the cases were covered already, it wasn't very painful.

- On the other hand, when I changed some of my some-macro.arg.another-arg forms to (some-macro.arg another-arg), I got errors. That's because they were expressions sent to 'setforms, and I'm not quite sure of the nature of this problem, but apparently 'setforms checks the car of the expression, sees that the 'metafn function returns t for it (since 'some-macro.arg has ssyntax), and then tries to 'expand-metafn-call the form even though it isn't really a metafn call. I wasn't able to reproduce this on other versions of Arc, but I didn't try much. The workaround was just to put my code back the way it was, 'cause in (= some-macro.arg.another-arg foo), the ssyntax will expand all in a single step.

- Setting a table entry to nil doesn't remove it. This didn't actually get in my way, and I'm not a big fan of this part of Arc's behavior, but it makes me wonder whether Jarc has any way at all to remove table entries.

- Jarc gensyms are of the form "g1234" rather than "gs1234." This should almost never come up as a problem, but it is a difference.

- Jarc doesn't define 'sref on lists. This means you can't do (++ (q 2)), where q is a list. Since this is an example taken right out of 'enq, queues don't work either. I worked around this by redefining 'enq using (++ (car:cddr q)).

- The type of 0 is num rather than int. In order to check whether something was really an integer, I ended up doing a Java call.

- More aspects of Arc 2 popped up, like 'trunc being absent and 'accum returning its list in reverse order. I won't bother trying to make a list.

That's it for the moment. The next steps, when I get around to them, will probably be reverting Lathe's workarounds that are no longer necessary.

In the meantime, thanks a lot for responding like you have, and I hope with all this hunting for bugs you must be doing that it's still fun. :-p

-----

1 point by jazzdev 5312 days ago | link

Yeah, definitely still fun. I'll add these to the list. Glad your Lathe is working. This certainly has been useful for me (Jarc). My list for "after the compiler" is getting pretty long, but that's okay. I'm learning a lot and definitely having fun.

-----