Arc Forumnew | comments | leaders | submitlogin
2 points by Pauan 4382 days ago | link | parent

I just pushed out two major changes to nulan.html:

https://github.com/Pauan/nulan/tree/1566c941d47d5c39609a8097...

The first change is that it now only shows the output for the top-level expressions that are selected. To try this out, first input this:

  var foo = 5

  foo
Now try clicking on the "var foo = 5" expression. Then try clicking on the "foo" expression. Then try using "Ctrl+A" to select both expressions.

---

The second change is that I added in a sandbox where you can do DOM stuff interactively. To test it out, input this:

  w/var x = document.create-element "div"
    | x.style.background-color <= "green"
    | x.style.width <= x.style.height <= "50px"
    | x.add-event-listener "click" ->
        alert "Hi!"
    | document.body.append-child x
You should see a little green box in the upper-right panel. If you click on it, it should pop up a dialog box that says "Hi!"

---

At this point it's already a nicer experience than entering stuff into the REPL. But I can do better. I plan to add in CodeMirror[1] support for the textarea on the left side, and add some more polish and such.

* [1]: http://codemirror.net/



2 points by Pauan 4382 days ago | link

Just added in CodeMirror support:

https://github.com/Pauan/nulan/tree/fc8003fc6c238540839a852b...

Awesome, now there's line numbers! Later on I'll write up a mode that will add syntax highlighting and auto-indent to CodeMirror for Nulan, but for now this will do.

-----

1 point by Pauan 4382 days ago | link

By using this CodeMirror demo:

http://codemirror.net/demo/widget.html

I was able to very easily add in inline error messages to nulan.html:

https://github.com/Pauan/nulan/tree/a24a33a864d9e2800fc3c995...

And here's a screenshot of it in action:

http://img687.imageshack.us/img687/2348/screenshot1223201203...

Very nice, no?

-----

3 points by Pauan 4380 days ago | link

Major changes to nulan.html:

https://github.com/Pauan/nulan/tree/9ffecb5a9aa7a4bd7cbe9680...

Firstly, there's now an interactive tutorial. Just open up "nulan.html", and if you don't see the tutorial, click the "Reset Tutorial" button at the top. Be careful, it'll clobber any changes you've made.

Secondly, you might have noticed that the editor has syntax highlighting now. But it's actually really cool. First, try inputting this:

  $mac foo -> a b c
    a + b + c

  foo 1 2 3


  def foo -> a b c
    a + b + c

  foo 1 2 3
Notice that it colored the first "foo" green because it's a macro, and the second "foo" orange because it's a function. It also colored local variables blue.

Now try inputting this:

  # Array comprehensions
  box in

  $mac for -> x {('in) n y}
    'y.map -> n x

  $syntax-infix for 0 [ order "right" ]
  $syntax-infix in  0 [ order "right" ]

  (x + 2) for x in {1 2 3}
Notice that syntax is colored grey. Not just the built-in syntax, but user-created syntax is colored grey as well! It also understands delimiters:

  $mac ^ -> a b
    a + b

  $syntax-infix ^ 0 [ delimiter %t ]

  prn 1^2
Lastly, you can use "Debug mode" to toggle whether additional information is displayed in the lower-right panel or not.

-----

3 points by Pauan 4378 days ago | link

And now it's on Github Pages (thanks rocketnia!) so you don't even have to download the repository:

http://pauan.github.com/nulan/nulan.html

-----

2 points by Pauan 4376 days ago | link

The URL has changed:

http://pauan.github.com/nulan/doc/tutorial.html

I'm thinking about putting in a redirect for the old URL, but I'm not sure if it's worth it or not.

EDIT: I also just now fixed the problem where the panels weren't showing up in Firefox.

-----

2 points by Pauan 4374 days ago | link

Some more changes:

https://github.com/Pauan/nulan/tree/f88a81563fec518cd740302d...

Or just use the uploaded version:

http://pauan.github.com/nulan/doc/tutorial.html

You'll have to use the "Reset Tutorial" button to see all the changes.

The biggest change is that you can now click on an expression to highlight it. To see what I mean, try clicking on stuff in the tutorial.

But the coolest part is that the highlighting understands boxes. Try inputting this:

  box foo = 5

  foo + 10


  box foo = 20

  foo + 30
Now try clicking on the 1st or 2nd "foo". Then try clicking on the 3rd or 4th "foo". And it's so smart, it can even differentiate local variables (which is non-trivial because Nulan compiles top-level forms, like Arc):

  w/box foo = 5
    | foo + 10
    | box foo = 20
    | foo + 30
Once again, try clicking the 1st or 2nd "foo", then the 3rd or 4th "foo".

It's also smart enough to know that the "." syntax is a string, even though it looks like a symbol:

  box foo = []
  
  foo.bar <= 5
  
  foo.bar
So, obviously this isn't just a simple name search. The nice thing about this is, because Nulan uses boxes, it will only highlight the symbols that evaluate to the same box.

Imagine a search/replace function that operates on boxes rather than symbols: you'll be able to find/rename exactly the right symbols, rather than symbols that happen to have the same name.

-----

1 point by akkartik 4376 days ago | link

Ah, I'd wondered about that on firefox. I didn't see any discussion so thought perhaps one of my extensions was acting up.

-----

1 point by akkartik 4377 days ago | link

Awesome!

a) if-box is a kinda contrived example. Perhaps we can find something better?

b) What's the difference between w/uniq and w/box? Both seem to create boxes. Could I just say this at http://github.com/Pauan/nulan/blob/5dfddacfbb/nulan.html#L44...?

  $mac if-box ->
    w/uniq temp
      'w/box temp = 5
         if temp
           temp + 1
c) I tried running this and got the following:

  TypeError: Cannot call method 'chunkSize' of undefined
I'm gonna play with this more!

-----

2 points by Pauan 4377 days ago | link

"if-box is a kinda contrived example. Perhaps we can find something better?"

If you have a better suggestion, I'm all ears. But I settled on that because A) it's simple, B) it's short, C) it's something that does actually come up in practice, so it's not too contrived.

---

"What's the difference between w/uniq and w/box? Both seem to create boxes."

Well, to explain this... unique variables are actually implemented as anonymous boxes. So implementation-wise, there's not much difference.

The difference is in the actual macros "w/box" and "w/uniq". Here's the definition for them:

  $mac w/box -> @args body
    'w/new-scope
       | var ,@args
       | body

  $mac w/uniq -> @args body
    'w/box ,@(args.map -> x 'x = make-uniq;)
       body
In other words, these are the same:

  w/box foo = 5
    foo

  w/new-scope
    | var foo = 5
    | foo
And these are the same:

  w/uniq foo
    foo

  w/box foo = make-uniq;
    foo

  w/new-scope
    | var foo = make-uniq;
    | foo
In other words, "w/box" puts a value into a box. "w/uniq" puts a box into a box.

They serve exactly the same purpose as "let" and "w/uniq" in Arc.

If you're asking why you can't just do this:

  $mac if-box ->
    w/box temp
      'w/box temp = 5
         if temp
           temp + 1
The answer is that "quote" inserts boxes for global symbols, but values for local symbols. That is, this macro...

  $mac foo ->
    w/box bar = 5
      'bar + 2
...returns "5 + 2", not "#<box bar> + 2". This is an unfortunate inconsistency which happens because I'm using JavaScript variables for the sake of speed.

I thought about having it throw an error for local symbols, which would have required you to write the macro like this:

  $mac foo ->
    w/box bar = 5
      ',bar + 2
But I decided that it wasn't worth it. Now that I think about it, I wonder if it would be possible to hack something up so you no longer need w/uniq...

---

"I tried running this and got the following"

It works fine for me. And in fact, the code snippet you posted seems exactly the same as what is already in the tutorial. Maybe you intended to paste something else?

As for the error... yeah, there are still some cryptic errors. I plan to make them more meaningful later.

-----

1 point by Pauan 4376 days ago | link

"Now that I think about it, I wonder if it would be possible to hack something up so you no longer need w/uniq..."

After thinking about it some more, I realized it won't work very well. It would require me to make all variables global, which would slow things down and be more verbose.

-----

1 point by Pauan 4376 days ago | link

Whoops, those examples should use "box" rather than "var". But otherwise they're correct.

-----

1 point by rocketnia 4382 days ago | link

This is extremely nice. XD

I pasted your DOM demo code twice, and then I was able to access both window.x and window.x2 from within Nulan. Is this intentional?

I also appended some DOM elements to the parent frame using "window.parent.document.append-child x", and they didn't get cleared on each update, but that's my own fault I guess. :-p

How do you call a function with no arguments?

-----

2 points by Pauan 4382 days ago | link

"I pasted your DOM demo code twice, and then I was able to access both window.x and window.x2 from within Nulan. Is this intentional?"

Yes, absolutely. It's how Nulan ensures that every variable is bound to a single "box". This also has the nice property that all the different "versions" of a variable can be accessed from the JavaScript side.

Ordinarily you can't access the different versions from within Nulan, but "window" is one of the ways you can do so. Another way would be the "&" macro which bypasses the Nulan compiler.

---

"I also appended some DOM elements to the parent frame using "window.parent.document.append-child x", and they didn't get cleared on each update, but that's my own fault I guess. :-p"

Yeah, only the <iframe> is sandboxed. Of course you can refresh the page to clear it out. Don't worry, it'll save the text you typed in the textarea.

---

"How do you call a function with no arguments?"

Use ; like so:

  foo;
  foo.bar.qux;

-----

1 point by rocketnia 4382 days ago | link

Thank you. :D

-----