Arc Forumnew | comments | leaders | submitlogin
1 point by Pauan 4912 days ago | link | parent

I have started work on an Arc to JavaScript compiler. Unlike ArcLite, this does not use an interpreter written in JS. Instead, the Arc code is translated directly into a JavaScript string, which can then be evaluated in your favorite JS interpreter (V8 is quite fast).

I actually just started this today, so naturally it may be buggy and is missing a lot of functionality, but basic functions, function calls, and macros work:

  (with (a 1 b 2 c 3)
    (list a b c))
Becomes:

  (function (a, b, c) {
      return [a, b, c];
  })(1, 2, 3)
Because this is a direct one-to-one compiler, I think it would be more accurate to think of it as a thin Arc-like syntax for JS, rather than as a port of Arc. Basically, this is just like CoffeeScript, but for Arc.

So, if you're used to Arc but have never programmed in JavaScript, certain things will trip you up. For starters, all numbers in JS are 64-bit floating point, there are no ints. Thus, Arc ints become JS floating points.

Also, strings in JS may differ somewhat from Arc strings, but they should be reasonably similar (both support \n and \t syntax, etc.) One difference is that JS supports both ' and " for strings, but Arc only supports "

Also, JS has a lot of things that evaluate to false: "", null, undefined, false, NaN, and 0

Arc only has nil, everything else is true.

---

I still need to get table notation working. Once that's done, you should be able to do stuff like this:

  (= foo (document!createElement "div"))
  (foo!setAttribute "bar" "qux")
Which should compile into the following:

  var foo = document["createElement"]("div");
  foo["setAttribute"]("bar", "qux");
---

Because it's just a thin skin over JS and not a full port, the primary reason you would want to use arc2js is if you want to program in JS, but you like Arc syntax and macros.

Which reminds me. Because the compiler does not have access to the JS environment, there is a clean separation between JS and Arc code: Arc macros can call any Arc function, but JS code can only call JS code.

Unfortunately, that means the following won't work:

  (= browser ...) ; code to detect what the browser is

  (mac something ()
    (case browser
      ie     ...
      gecko  ...
      webkit ...
      opera  ...))
Because the macro "something" doesn't have access to the JS environment, it can't expand into different code depending on what the JS code does. It'll have to do the browser check at runtime.


1 point by Pauan 4912 days ago | link

And now things like `assign`, `if`, and `is` work. Which means that the `in` macro also works:

  (in x "foo" "bar" "qux")
Becomes:

  (function (g1585) {
      return (function (g1586) {
          return (g1586 ? g1586 : (function (g1587) {
              return (g1587 ? g1587 : (function (g1588) {
                  return (g1588 ? g1588 : undefined);
              })((g1585 === "qux")));
          })((g1585 === "bar")));
      })((g1585 === "foo"));
  })(x)
Atrociously inefficient and verbose, obviously, but it does work. And when I add in `or` it should become clearer.

---

EDIT: I just added in `or`. Now the output is a lot more readable:

  (function (g1590) {
      return ((g1590 === "foo") || (g1590 === "bar") || (g1590 === "qux"));
  })(x)
Also, you may have noticed that the output includes the actual gensym name. This is unfortunate, but JS doesn't have gensyms, so it's the best we can do.

-----