Skip to content

Commit

Permalink
Update docs on compiler output to reflect current status
Browse files Browse the repository at this point in the history
  • Loading branch information
adambeynon committed Oct 24, 2013
1 parent 145bf2b commit ce96e67
Showing 1 changed file with 15 additions and 47 deletions.
62 changes: 15 additions & 47 deletions doc/generated_javascript.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Generated Javascript

Opal is a source-to-source compiler, so there is no VM as such and the
compiled code aims to be as fast and efficient as possible, mapping
directly to underlying javascript features and objects where possible.
Expand Down Expand Up @@ -35,13 +37,12 @@ to convert values to opal specific values. It does mean that there is
only a `Boolean` ruby class available, not seperate `TrueClass` and
`FalseClass` classes.

*nil* is compiled to `null`, so it can easily be passed between ruby and
javascript code. `undefined` is also a valid value for `nil`, and both
can be passed seamlessly. You can still call methods on `nil` as it is
treated as an instance of `NilClass`.
**nil** is compiled to a `nil` javascript variable. `nil` is a real object
which allows methods to be called on it. Opal cannot send methods to `null`
or `undefined`, and they are considered bad values to be inside ruby code.

```ruby
nil # => null
nil # => nil
true # => true
false # => false
self # => self
Expand Down Expand Up @@ -111,43 +112,14 @@ range instances.
3...7 # => __range(3, 7, false)
```

## Method missing (method_missing)

Opal fully supports `method_missing` and it is turned on by default.
Opal can also send methods to `nil`, and the receiver is checked inline
to be able to dispatch calls to native `null` or `undefined`.

### Optimized Math Operators

In ruby, all math operators are method calls, but compiling this into
javascript would end up being too slow. For this reason, math
operators are optimized to test first if the receiver is a number, and
if so then to just carry out the math call.

```ruby
3 + 4
```

This ruby code will then be compiled into the following javascript:

```javascript
(a = 3, b = 4, typeof(a) === "number" ? a + b : /* method call */)
```

This ternary statement falls back on sending a method to the receiver
so all non-numeric receivers will still have the normal method call
being sent. This optimization makes math operators a **lot faster**.
Currently, the optimized method calls are `+`, `-`, `*` and `/`.

## Logic and conditionals

As per ruby, Opal treats only `false` and `nil` as falsy, everything
else is a truthy value including `""`, `0` and `[]`. This differs from
javascript as these values are also treated as false.

For this reason, most truthy tests must check if values are `false` or
`nil`. Note: as `nil` compiles to `null`, the truthyness tests will
check `null` and `undefined` as both values are valid `nil`.
`nil`.

Taking the following test:

Expand All @@ -164,7 +136,7 @@ This would be compiled into:
```javascript
var val = 42;

if (val !== false && val != null) {
if (val !== false && val !== nil) {
return 3.142;
}
```
Expand Down Expand Up @@ -243,10 +215,10 @@ of javascript code that is wrapped inside an anonymous function. This
looks similar to the following:

```javascript
(function() {
var _klass = Opal.klass, self = Opal.top;
(function($opal) {
var $klass = $opal.klass, self = $opal.top;
// generated code
})();
})(Opal);
```

As a complete example, assuming the following code:
Expand All @@ -258,10 +230,10 @@ puts "foo"
This would compile directly into:

```javascript
(function() {
var _klass = Opal.klass, self = Opal.top;
(function($opal) {
var $klass = $opal.klass, self = $opal.top;
self.$puts("foo");
})();
})(Opal);
```

Most of the helpers are no longer present as they are not used in this
Expand Down Expand Up @@ -294,11 +266,7 @@ debug:
The x-strings just pass the debugger statement straight through to the
javascript output.

Inside methods and blocks, the current `self` value is always the
native `this` value. You will not see `self` inside debuggers as it is
never used to refer to the actual ruby self value.

All local variables and method/block arguments also keep their ruby
names except in the rare cases when the name is reserved in javascript.
In these cases, a `$` suffix is added to the name (e.g. `try` =>
`try$`).
`try$`).

0 comments on commit ce96e67

Please sign in to comment.