opal 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,31 @@
1
+ 2011-03-31 Adam Beynon <adam@adambeynon.com>
2
+
3
+ * Changelog, README.md, opal.gemspec: Update to 0.3.2
4
+
5
+ * lib/opal/rake/builder_task.rb: Added task used in Rakefiles for
6
+ building simple opal projects.
7
+
8
+ * lib/opal/builder.rb: Update builder options to correctly glob files
9
+ passed as strings or arrays.
10
+
11
+ * lib/opal.rb: Load builder tasks for rakefiles.
12
+
13
+ * README.md: Update to list packaged gems and links to relevant docs.
14
+ Also added docs on using BuilderTask.
15
+
16
+ * gems/core/Rakefile: Use markdown for markup in documentation.
17
+
18
+ * gems/core/lib/core/object.rb: Add core Object class to aid
19
+ documentation.
20
+
21
+ * gems/core/lib/core.rb, gems/core/lib/core/array.rb,
22
+ gems/core/lib/core/basic_object.rb, gems/core/lib/core/class.rb,
23
+ gems/core/lib/core/error.rb, gems/core/lib/core/false_class.rb,
24
+ gems/core/lib/core/hash.rb, gems/core/lib/core/kernel.rb,
25
+ gems/core/lib/core/module.rb, gems/core/lib/core/nil_class.rb,
26
+ gems/core/lib/core/numeric.rb, gems/core/lib/core/proc.rb,
27
+ gems/core/lib/core/regexp.rb, gems/core/lib/core/string.rb,
28
+ gems/core/lib/core/symbol.rb, gems/core/lib/core/true_class.rb: Update
29
+ core documentation with implementation details for toll free classes
30
+ and special use information.
31
+
data/README.md CHANGED
@@ -3,6 +3,7 @@ Opal: Ruby runtime for javascript
3
3
 
4
4
  **Homepage**: [http://opalscript.org](http://opalscript.org)
5
5
  **Github**: [http://github.com/adambeynon/opal](http://github.com/adambeynon/opal)
6
+ **Documentation**: [http://adambeynon.github.com/opal/index.html](http://adambeynon.github.com/opal/index.html)
6
7
 
7
8
  Description
8
9
  -----------
@@ -46,9 +47,117 @@ The REPL can be used like any other repl, and internally each command is
46
47
  being compiled into javascript, and run in the context which opal is
47
48
  already loaded into.
48
49
 
50
+ **2. Builder Rake Task**
51
+
52
+ To build simple ruby files (without a .gemspec) is to use the
53
+ BuilderTask class in a rake file. This can be done by adding the
54
+ following to a `Rakefile`:
55
+
56
+ require 'opal'
57
+
58
+ Opal::Rake::BuilderTask.new do |t|
59
+ t.files = 'ruby/**/*.rb'
60
+ t.out = 'js/ruby_code.js'
61
+ end
62
+
63
+ When using the rake task, the `files` and `out` optional are usually
64
+ best required. The `files` will take an array, or a single string, and
65
+ can be globs. It is important to use relative paths here not absolute
66
+ paths. This will be default create a rake task called `opal` in your
67
+ rakefile, but you can rename it by passing another name into `new`. To
68
+ compile the javascript run:
69
+
70
+ $ rake opal
71
+
72
+ The out file will now contain the compiled ruby code. Run this in a
73
+ browser by including it into a html document, but make sure to include
74
+ the latest `opal.js` file first.
75
+
76
+ **Main file**
77
+
78
+ By default the builder task will automatically load the first listed
79
+ file in the `files` array when the file is loaded in the browser. The
80
+ `main` option allows you to specify another file:
81
+
82
+ Opal::Rake::BuilderTask.new do |t|
83
+ t.files = ['ruby/file_1.rb', 'ruby/file_2.rb', 'ruby/file_3.rb']
84
+ t.out = 'out.js'
85
+ t.main = 'ruby/file_2.rb'
86
+ end
87
+
88
+ **File watching**
89
+
90
+ To save manually compiling each time you change a file, the `watch`
91
+ option can be set to automatically recompile everytime a listed file is
92
+ modified. Observe the command line after using this task:
93
+
94
+ Opal::Rake::BuilderTask.new do |t|
95
+ t.files = 'ruby/*.rb'
96
+ t.out = 'my_code.js'
97
+ t.watch = true
98
+ end
99
+
100
+ Built-in gems
101
+ ------------
102
+
103
+ Opal uses gems as the main means of distributing and building code ready
104
+ for the browser. Opal uses its own gem system, and cannot access gems
105
+ included in the standard ruby installation. To aid this, the actual opal
106
+ gem includes several gems that offer the basic features. These gems are:
107
+
108
+ **core**
109
+
110
+ The core gem offers the ruby core library. It is mostly written in ruby,
111
+ but has a large proportion of inline javascript to make it as performant
112
+ as possible. Many of the classes are toll-free bridged to native
113
+ javascript objects, including Array, String, Numeric and Proc. Read the
114
+ [core library documentation](http://adambeynon.github.com/opal/gems/core/index.html)
115
+ for more information.
116
+
117
+ **dev**
118
+
119
+ The dev gem contains a ruby parser and compiler written in javascript.
120
+ It is a clone of the default opal parser written in ruby. This gem is in
121
+ the process of being replaced with the pure ruby version, which will be
122
+ compiled into javascript for this gem. This gem can be loaded into
123
+ javascript to allow in browser compilation of ruby sources from external
124
+ files or through html `script` tags.
125
+
126
+ **json**
127
+
128
+ The json gem included methods for parsing json strings and then
129
+ generating json objects from a string of json code. This gem aims to be
130
+ API compatible with the standard json library. Similarly to that
131
+ library, json objects are mapped to Hash, Array, true, false, nil,
132
+ String and Numeric as appropriate. See the
133
+ [JSON documentation](http://adambeynon.github.com/opal/gems/json/index.html)
134
+ for the full api.
135
+
136
+ **rquery**
137
+
138
+ RQuery is a port/abstraction of the jQuery javascript library for DOM
139
+ manipulation. jQuery is actually included as part of the gem, and top
140
+ level classes like Element, Document and Request are used to interact
141
+ with the document and elements. The api tries to stay as close to the
142
+ jquery interface as possible, but adds appropriate ruby syntax features
143
+ on top. See the [rquery documentation](http://adambeynon.github.com/opal/gems/rquery/index.html)
144
+ for the full api.
145
+
146
+ **ospec**
147
+
148
+ OSpec is a minimal clone of the ruby rspec library. It implements the
149
+ core features available in rspec, and works both from the command line
150
+ and in browser. The core, json and rquery gems all have tests/specs
151
+ written ready for ospec. See the [ospec guide](http://adambeynon.github.com/opal/gems/ospec/index.html)
152
+ to get started.
153
+
49
154
  Changelog
50
155
  ---------
51
156
 
157
+ - **31 March 2011**: 0.3.2 Release
158
+ - Added BuilderTask for easy building for simple projects.
159
+ - Amended build options in Builder to support new rake task.
160
+
52
161
  - **30 March 2011**: 0.3.1 Release
53
162
  - Fix to make `opal` an executable
54
163
 
@@ -1,5 +1,14 @@
1
1
  Core Library
2
2
  ============
3
3
 
4
- Core ruby libraries for opal.
4
+ **Homepage**: [http://opalscript.org](http://opalscript.org)
5
+ **GitHub**: [http://github.com/adambeynon/opal](http://github.com/adambeynon/opal)
6
+
7
+ Synopsis
8
+ --------
9
+
10
+ This gem contains the core library implementation for opal. It is kept
11
+ as a seperate gem so that the base opal.js loader simply contains the
12
+ core runtime and object hierarchy setup, and then this gem simply
13
+ implements the methods for the standard library.
5
14
 
@@ -2,6 +2,7 @@ require 'yard'
2
2
 
3
3
  YARD::Rake::YardocTask.new do |t|
4
4
  t.files = ['lib/**/*.rb']
5
- t.options = ['--title', 'Opal Core Library']
5
+ t.options = ['--title', 'Documentation for Opal Core Library',
6
+ '--markup', 'markdown']
6
7
  end
7
8
 
@@ -12,6 +12,7 @@ module Kernel
12
12
  end
13
13
 
14
14
  require 'core/basic_object'
15
+ require 'core/object'
15
16
  require 'core/module'
16
17
  require 'core/class'
17
18
  require 'core/kernel'
@@ -1,19 +1,63 @@
1
- # Arrays are ordered, indexed by integers starting at 0
1
+ # Arrays are ordered collections, indexed by integers starting at `0`.
2
+ # Indexes may be negative, where `-1` represents the last item in the
3
+ # array, `-2` the last but one, etc. Arrays may be constructed by using a
4
+ # method like {Array.[]}, or by using an array literal:
5
+ #
6
+ # Array[1, 2, 3, 4, 5] # => [1, 2, 3, 4, 5]
7
+ # ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
2
8
  #
3
9
  # Implementation details
4
- # ======================
10
+ # ----------------------
11
+ #
12
+ # Ruby arrays are toll-free bridged to native javascript arrays, meaning
13
+ # that anywhere that a ruby array is required, a normal javascript array
14
+ # may be passed instead. The {Array} class infact makes use of a lot of
15
+ # the standard javascript functions on array prototypes to make its
16
+ # functionality as fast as possible.
17
+ #
18
+ # Due to the fact that arrays may be constructed in a javascript
19
+ # environment, and then passed through to a ruby method, Opal cannot
20
+ # guarantee that an array will not have a bad value. Bad values are
21
+ # those which ruby cannot send messages to, and therefore is an object
22
+ # that will raise an error when it is accessed by methods in {Array}, or
23
+ # any other object accessing an arrays elements. Bad values from
24
+ # javascript include the native `true`, `false`, `null` and `undefined`
25
+ # values from javascript, as well as any object literal.
26
+ #
27
+ # Ruby compatibility
28
+ # ------------------
29
+ #
30
+ # As instances of {Array} are actually javascript arrays, they can
31
+ # perform all the same functionality as Rubyspec defines arrays should.
32
+ # While not 100% of methods are currently implemented, the missing
33
+ # methods are being added quickly. All implemented methods are listed in
34
+ # this file. Any method that is only partially implemented also contains
35
+ # a list of restrictions in its description.
5
36
  #
6
- # For efficiency, an array instance is simply a native javascript array. There
7
- # is no wrapping, it is simply a toll-free class
37
+ # The main area of partialy implemented methods are the enumerating
38
+ # methods like {#each}, {#each\_index} and {#reverse\_each}. Rubyspec
39
+ # defines that they should return an Enumerator if no block is passed to
40
+ # that method. Currently this does not happen, and `self` is returned
41
+ # with no side effects.
42
+ #
43
+ # Custom subclasses of {Array} may also be defined, and this is
44
+ # implemented in {.allocate}, when the array is created using {.new}.
45
+ # Internally a native javascript array is still used, but its class and
46
+ # method table are swizzled.
47
+ #
48
+ # Finally the {Array} class does not include the Enumerable module. Its
49
+ # methods are mostly implemented directly on the Array class. The
50
+ # Enumerable module will be added shortly, and the relevant methods
51
+ # moved back into that module.
8
52
  class Array
53
+
9
54
  # Returns a new array populated with the given objects.
10
55
  #
11
56
  # @example
12
57
  #
13
- # Array['a', 'b', 'c']
14
- # # => ['a', 'b', 'c']
58
+ # Array['a', 'b', 'c'] # => ['a', 'b', 'c']
15
59
  #
16
- # FIXME should support custom subclasses
60
+ # **FIXME** should support custom subclasses
17
61
  #
18
62
  # @param [Object] objs
19
63
  # @return [Array]
@@ -21,7 +65,7 @@ class Array
21
65
  objs
22
66
  end
23
67
 
24
- # FIXME should support custom subclasses
68
+ # **FIXME** should support custom subclasses
25
69
  def self.allocate
26
70
  []
27
71
  end
@@ -105,7 +149,7 @@ class Array
105
149
  # # => 'b'
106
150
  # # => 'c'
107
151
  #
108
- # TODO: needs to return enumerator for no block.
152
+ # **TODO** needs to return enumerator for no block.
109
153
  #
110
154
  # @return [Array] returns the receiver
111
155
  def each
@@ -149,7 +193,7 @@ class Array
149
193
  #
150
194
  # If no block given, an enumerator is returned instead.
151
195
  #
152
- # TODO: enumerator functionality not yet implemented.
196
+ # **TODO** enumerator functionality not yet implemented.
153
197
  #
154
198
  # @example
155
199
  #
@@ -250,8 +294,8 @@ class Array
250
294
  end
251
295
 
252
296
  # Equality. Two arrays are equal if they contain the same number of elements
253
- # and if each element is equal to (according to {Object#==} the corresponding
254
- # element in the second array.
297
+ # and if each element is equal to (according to {BasicObject#==} the
298
+ # corresponding element in the second array.
255
299
  #
256
300
  # @example
257
301
  #
@@ -275,9 +319,9 @@ class Array
275
319
  end
276
320
 
277
321
  # Searches through an array whose elements are also arrays, comparing `obj`
278
- # with their first element of each contained array using {Object#==}. Returns
279
- # the first contained array that matches (that is, the first associated array)
280
- # or `nil` if no match is found. See also {#rassoc}.
322
+ # with their first element of each contained array using {BasicObject#==}.
323
+ # Returns the first contained array that matches (that is, the first
324
+ # associated array) or `nil` if no match is found. See also {#rassoc}.
281
325
  #
282
326
  # @example
283
327
  #
@@ -368,7 +412,7 @@ class Array
368
412
  end
369
413
 
370
414
  # Yields the block once for each element of the receiver. Creates a new array
371
- # containing the values returned by the block. See also {Enumerable#collect}.
415
+ # containing the values returned by the block. See also `Enumerable#collect`.
372
416
  #
373
417
  # @example
374
418
  #
@@ -399,7 +443,7 @@ class Array
399
443
  # alias_method 'map', 'collect'
400
444
 
401
445
  # Yields the block once for each element of `self`, replacing the element with
402
- # the value returned by the block. See also {Enumerable#collect}.
446
+ # the value returned by the block. See also `Enumerable#collect`.
403
447
  #
404
448
  # @example
405
449
  #
@@ -978,7 +1022,7 @@ class Array
978
1022
  end
979
1023
 
980
1024
  # Returns a new array containing the items in `self` for which the block is
981
- # not true. See also {#delete_if}.
1025
+ # not true. See also `#delete_if`.
982
1026
  #
983
1027
  # @example
984
1028
  #
@@ -1001,7 +1045,7 @@ class Array
1001
1045
  return result;`
1002
1046
  end
1003
1047
 
1004
- # Equivalent to {#delete_if!}, deleting elements from self for which the block
1048
+ # Equivalent to `#delete_if!`, deleting elements from self for which the block
1005
1049
  # evaluates to true, but returns nil if no changes were made.
1006
1050
  #
1007
1051
  # @example
@@ -1161,7 +1205,7 @@ class Array
1161
1205
  # elements down by one). Returns `nil` if the array is empty.
1162
1206
  #
1163
1207
  # If a number `n` is given, returns an array of the first n elements (or
1164
- # less), just like {#slice} does.
1208
+ # less), just like `#slice` does.
1165
1209
  #
1166
1210
  # @example
1167
1211
  #
@@ -1206,7 +1250,7 @@ class Array
1206
1250
  # a.slice! 100
1207
1251
  # # => nil
1208
1252
  #
1209
- # TODO does not yet work with ranges
1253
+ # **TODO** does not yet work with ranges
1210
1254
  #
1211
1255
  # @param [Range, Number] index to begin with
1212
1256
  # @param [Number] length last index
@@ -1440,7 +1484,7 @@ class Array
1440
1484
  # a[5, 1] # => []
1441
1485
  # a[5..10] # => []
1442
1486
  #
1443
- # @TODO: does not yet work with ranges
1487
+ # **TODO** does not yet work with ranges
1444
1488
  #
1445
1489
  # @param [Range, Numeric] index to begin
1446
1490
  # @param [Numeric] length last index
@@ -1462,7 +1506,7 @@ class Array
1462
1506
 
1463
1507
  # Element reference setting.
1464
1508
  #
1465
- # @TODO: need to expand functionlaity.
1509
+ # **TODO** need to expand functionlaity.
1466
1510
  def []=(index, value)
1467
1511
  `return self[index] = value;`
1468
1512
  end
@@ -1,3 +1,8 @@
1
+ # BasicObject is the root object in opal. Even {Object} inherits from
2
+ # {BasicObject}. Instances of BasicObject (or subclasses of) are useful
3
+ # as they give almost a clean interface in which the absolute minimum of
4
+ # methods are defined on it. It therefore becomes useful for such
5
+ # applications as HashStructs.
1
6
  class BasicObject
2
7
  def initialize
3
8
  # ...
@@ -11,5 +16,19 @@ class BasicObject
11
16
  def equal?(other)
12
17
  self == other
13
18
  end
19
+
20
+ def __send__(method_id, *args)
21
+ `args.unshift(self);
22
+ return self.$m[#{method_id.to_s}].apply(self, args);`
23
+ end
24
+
25
+ def instance_eval(&block)
26
+ `block(self)` if block_given?
27
+ self
28
+ end
29
+
30
+ def method_missing(sym, *args)
31
+ raise NoMethodError, "undefined method `#{sym}` for #{self.inspect}"
32
+ end
14
33
  end
15
34
 
@@ -1,4 +1,4 @@
1
- class Class
1
+ class Class < Module
2
2
 
3
3
  # def new(*args)
4
4
  # `var obj = self.$m.allocate(self);
@@ -1,9 +1,44 @@
1
+ # Instances of {Exception} and its subclasses are used to hold error
2
+ # information between `raise` calls, `begin` blocks and `rescue` statements.
3
+ # `Exceptions` will hold an optional `message`, which is a description
4
+ # of the error that occured. The exception `type` is also useful, and is
5
+ # just the name of the class that is a decendant of `Exception`.
6
+ # Subclasses are generally made of `StandardError`, but a subclass of
7
+ # any core `Exception` class is valid.
8
+ #
9
+ # Implementation details
10
+ # ----------------------
11
+ #
12
+ # Inside opal, exceptions are instances of the native javascript `Error`
13
+ # objects. This allows an efficient means to "piggy-back" the javascript
14
+ # try/catch/finally statements, as well as the `throw` statement for
15
+ # actually raising exceptions.
16
+ #
17
+ # Subclasses of `Exception` can also be used on top of `Error`, and the
18
+ # correct class and method tables for these subclasses are set in
19
+ # {.allocate}.
20
+ #
21
+ # Exceptions cannot be altered once created, so their message is
22
+ # permanently fixed. To improve debugging opal, once an exception it
23
+ # {#initialize}, the native error has its `.message` property set to a
24
+ # descriptive name with the format `ErrorClassName: error_message`. This
25
+ # helps to observe top level error statements appearing in debug tools.
26
+ # The original error message may be received using the standard
27
+ # {#message} or {#to_s} methods.
28
+ #
29
+ # Accessing the `backtrace` of an exception is platform dependant. It is
30
+ # fully supported on the server side v8 context, but differs in the
31
+ # browser context as some browsers have better support than others. The
32
+ # backtrace should not be relied on, and is supported purely on a
33
+ # platform to platform basis.
1
34
  class Exception
2
- # we also need to set err.$m to the right method table incase a subclass adds
35
+
36
+ # We also need to set err.$m to the right method table incase a subclass adds
3
37
  # custom methods.. just get this from the klass: self.
4
38
  def self.allocate
5
39
  `var err = new Error();
6
40
  err.$klass = self;
41
+ err.$m = self.$m_tbl;
7
42
  return err;`
8
43
  end
9
44
 
@@ -1,17 +1,77 @@
1
+ # Instances of `FalseClass` represent logically false values. There may
2
+ # only be one instance of `FalseClass`, which is the global value
3
+ # `false`. Attempts to create a new instance will yield an error.
4
+ # `FalseClass` provides methods to perform logical operations with other
5
+ # ruby objects.
6
+ #
7
+ # Implementation details
8
+ # ----------------------
9
+ #
10
+ # Due to the way messages are passed inside opal, `false` is not
11
+ # actually toll-free bridged onto the native javascript `false` value.
12
+ # In javascript, `false` and `true` are both instances of the Boolean
13
+ # type, which means they would need to share the same method_table in
14
+ # opal, which would remove their ability to be true instances of Rubys'
15
+ # `TrueClass` or `FalseClass`.
16
+ #
17
+ # As javascripts `false` is not actually the value used in opal, passing
18
+ # the native `false` value will cause errors when messages are sent to
19
+ # it. Within a file directly loaded by opal, `Qfalse` is a free variable
20
+ # that points to the actualy ruby instance of this class. This variable
21
+ # may be passed around freely.
1
22
  class FalseClass
2
23
 
24
+ # Returns a string representation of `false`, which is simply
25
+ # `"false"`.
26
+ #
27
+ # @example
28
+ #
29
+ # false.to_s # => "false"
30
+ #
31
+ # @return [String]
3
32
  def to_s
4
33
  "false"
5
34
  end
6
35
 
36
+ # And; This always returns `false`.
37
+ #
38
+ # @example
39
+ #
40
+ # false & true # => false
41
+ # false & nil # => false
42
+ # false & false # => false
43
+ #
44
+ # @return [false]
7
45
  def &(other)
8
46
  false
9
47
  end
10
48
 
49
+ # Or; If `other` is `false` or `nil`, returns `false`, otherwise
50
+ # returns `true`.
51
+ #
52
+ # @example
53
+ #
54
+ # false & false # => false
55
+ # false & nil # => false
56
+ # false & true # => true
57
+ # false & [1, 2, 3] # => true
58
+ #
59
+ # @return [true, false]
11
60
  def |(other)
12
61
  `return other.$r ? Qtrue : Qfalse;`
13
62
  end
14
63
 
64
+ # Exclusive Or; If `other` is `false` or `nil`, then it returns
65
+ # `false`, otherwise returns `true`.
66
+ #
67
+ # @example
68
+ #
69
+ # false & false # => false
70
+ # false & nil # => false
71
+ # false & true # => true
72
+ # false & [1, 2, 3] # => true
73
+ #
74
+ # @return [true, false]
15
75
  def ^(other)
16
76
  `return other.$r ? Qtrue : Qfalse;`
17
77
  end
@@ -1,10 +1,42 @@
1
- # A Hash is a collection of key-value pairs. It is similar to an array except
1
+ # A `Hash` is a collection of key-value pairs. It is similar to an array except
2
2
  # that indexing is done via arbitrary keys of any object type, not an integer
3
3
  # index. Hahses enumerate their values in the order that the corresponding keys
4
4
  # were inserted.
5
5
  #
6
6
  # Hashes have a default value that is returned when accessing keys that do not
7
7
  # exist in the hash. By default, that valus is `nil`.
8
+ #
9
+ # Implementation details
10
+ # ----------------------
11
+ #
12
+ # An Opal hash is actually toll-free bridged to a custom javascript
13
+ # prototype called RHash. This is all handled internally and is actually
14
+ # just an implementation detail, and is only done for the convenience of
15
+ # construction through literals and methods such as {Hash.new}.
16
+ #
17
+ # Although its syntax is similar to that of an object literal in
18
+ # javascript, it is very important to know that they are completely
19
+ # different, and a javascript/json object cannot be used in place of a
20
+ # ruby hash. All ruby objects require, at minimum, a `.$m` property
21
+ # which is their method table. When trying to send a message to a non
22
+ # ruby object, like a javascript object, errors will start occuring when
23
+ # this method table is not found.
24
+ #
25
+ # Hash and the JSON gem contain methods for converting native objects into
26
+ # `Hash` instances, so those should be used if you need to use objects from
27
+ # an external javascript library.
28
+ #
29
+ # Ruby compatibility
30
+ # ------------------
31
+ #
32
+ # `Hash` implements the majority of methods from the ruby standard
33
+ # library, and those that are not implemented are being added
34
+ # constantly.
35
+ #
36
+ # The `Enumerable` module is not yet implemented in opal, so most of the
37
+ # relevant methods used by `Hash` are implemented directly into this class.
38
+ # When `Enumerable` gets implemented, the relevant methods will be moved
39
+ # back into that module.
8
40
  class Hash
9
41
  # Returns a new array populated with the values from `self`.
10
42
  #
@@ -116,7 +148,7 @@ class Hash
116
148
  end
117
149
 
118
150
  # Equality - Two hashes are equal if they each contain the same number of keys
119
- # and if each key-value paid is equal, accordind to {Object#==}, to the
151
+ # and if each key-value paid is equal, accordind to {BasicObject#==}, to the
120
152
  # corresponding elements in the other hash.
121
153
  #
122
154
  # @example
@@ -1,3 +1,6 @@
1
+ # The {Kernel} module is directly included into {Object} and provides a
2
+ # lot of the core object functionality. It is not, however, included in
3
+ # {BasicObject}.
1
4
  module Kernel
2
5
  # Repeatedly executes the given block.
3
6
  #
@@ -107,10 +110,6 @@ module Kernel
107
110
  false
108
111
  end
109
112
 
110
- def method_missing(sym, *args)
111
- raise NoMethodError, "undefined method `#{sym}` for #{self.inspect}"
112
- end
113
-
114
113
  def to_a
115
114
  [self]
116
115
  end
@@ -171,11 +170,6 @@ module Kernel
171
170
  self == other
172
171
  end
173
172
 
174
- def __send__(method_id, *args)
175
- `args.unshift(self);
176
- return self.$m[#{method_id.to_s}].apply(self, args);`
177
- end
178
-
179
173
  def send(method_id, *args)
180
174
  __send__ method_id, *args
181
175
  end
@@ -224,11 +218,6 @@ module Kernel
224
218
  to_s
225
219
  end
226
220
 
227
- def instance_eval(&block)
228
- `block(self)` if block_given?
229
- self
230
- end
231
-
232
221
  def const_set(name, value)
233
222
  `return rb_const_set(VM.class_real(self.$klass), name, value);`
234
223
  end
@@ -1,4 +1,6 @@
1
-
1
+ # Implements the core functionality of modules. This is inherited from
2
+ # by instances of {Class}, so these methods are also available to
3
+ # classes.
2
4
  class Module
3
5
 
4
6
  def name
@@ -1,3 +1,16 @@
1
+ # `NilClass` has a single instance `nil`. No more instances of this
2
+ # class can be created, and attempts to do so will yield an error.
3
+ #
4
+ # Implementation details
5
+ # ----------------------
6
+ #
7
+ # `nil` is an actual ruby object, and is not just a reference to the
8
+ # native `null` or `undefined` values in javascript. Sending messages to
9
+ # `nil` in ruby is a very useful feature of ruby, and this would not be
10
+ # possible in opal if `nil` was just the `null` or `undefined` value.
11
+ #
12
+ # To access `nil` from javascript, `Qnil` points to this instance and is
13
+ # available in both ruby and javascript sources loaded by opal.
1
14
  class NilClass
2
15
 
3
16
  def to_i
@@ -1,3 +1,43 @@
1
+ # Numeric objects represent numbers in opal. Unlike ruby, this class is
2
+ # used to represent both floats and integers, and there is currently no
3
+ # class representing bignums. Numeric values may only be made using
4
+ # their literal representations:
5
+ #
6
+ # 1 # => 1
7
+ # 2.0 # => 2
8
+ # 0.05 # => 0.05
9
+ #
10
+ # Implementation details
11
+ # ----------------------
12
+ #
13
+ # Opal numbers are toll-free bridged to native javascript numbers so
14
+ # that anywhere a ruby number is expected, a native javascript number
15
+ # may be used in its place. Javascript only has a single class/prototype
16
+ # to represent numbers, meaning that all integers and floats contain the
17
+ # same prototype. For this reason, Opal follows suit and implements all
18
+ # numbers as a direct instance of {Numeric}.
19
+ #
20
+ # Floats and Integers could be truley represented using wrappers, but
21
+ # this would **dramatically** increase performance overhead at the very
22
+ # core parts of the opal runtime. This overhead is too great, and the
23
+ # benefits would be too few.
24
+ #
25
+ # Ruby compatibility
26
+ # ------------------
27
+ #
28
+ # As discussed, {Numeric} is the only class used to represent numbers in
29
+ # opal. Most of the useful methods from `Fixnum`, `Integer` and `Float`
30
+ # are implemented on this class.
31
+ #
32
+ # It is also important to note that there is no distinguishment between
33
+ # floats and integers, so that, `1` and `1.0` are exactly equal.
34
+ #
35
+ # Custom subclasses of Numeric may be used so that a numeric literal is
36
+ # passed in. This differs from the ruby approach of number inheritance,
37
+ # but does allow for certain circumstances where a subclass of number
38
+ # might be useful. Opal does not try to implement `Integer` or `Float`
39
+ # for these purposes, but it is easily done. This approach will still
40
+ # not allow for literals to be used to make these subclass instances.
1
41
  class Numeric
2
42
  # Unary Plus - Returns the receivers value
3
43
  #
@@ -23,7 +63,7 @@ class Numeric
23
63
  `return -self;`
24
64
  end
25
65
 
26
- # Returns `self` modulo `other`. See {#divmod} for more information.
66
+ # Returns `self` modulo `other`. See `divmod` for more information.
27
67
  #
28
68
  # @param [Numeric] other number to use for module
29
69
  # @return [Numeric] result
@@ -0,0 +1,6 @@
1
+ # Core object in hierarchy. Most of the implementation of this core
2
+ # object are implemented in {Kernel}.
3
+ class Object < BasicObject
4
+
5
+ end
6
+
@@ -1,5 +1,39 @@
1
+ # `Proc` objects are blocks of code that can also be bound to local
2
+ # variables in their defined scope. When called, a proc will maintain
3
+ # its `self` value, and still have the ability to access variables
4
+ # defined within the same scope. A proc may also be called in another
5
+ # context and have its `self` value tempararily adjusted.
6
+ #
7
+ # Creation of procs may be done by passing a block into the {Proc.new}
8
+ # constructor, or the {Kernel} method {Kernel#proc}:
9
+ #
10
+ # a = Proc.new { 14 } # => #<Proc:0x98aef>
11
+ # b = proc { 42 + a.call } # => #<Proc:0x98ef3>
12
+ #
13
+ # a.call # => 14
14
+ # b.call # => 56
15
+ #
16
+ # Implementation details
17
+ # ----------------------
18
+ #
19
+ # Due to their obvious similarities in functionality, a proc instance is
20
+ # simply a native javascript function allowing it to maintain access to
21
+ # variables in its outer scope, and to have its `self` value changed on
22
+ # demand.
23
+ #
24
+ # When a proc is defined, its `self` value is stored on the function
25
+ # instance itself as a `.$self` property, so when the proc is called in
26
+ # future, this is the default value passed as the self property. This
27
+ # also means that every function used in the same context as opal may be
28
+ # used as a `Proc` meaning the transition back and forth between ruby
29
+ # and javascript contexts is easy.
1
30
  class Proc
2
31
 
32
+ def self.new(&block)
33
+ raise "No block given" unless block_given?
34
+ block
35
+ end
36
+
3
37
  def to_proc
4
38
  self
5
39
  end
@@ -1,3 +1,22 @@
1
+ # A `Regexp` holds a regular expression, that can be used to match
2
+ # against strings. Regexps may be created as literals, or using the
3
+ # {Regexp.new} method:
4
+ #
5
+ # /abc/ # => /abc/
6
+ # Regexp.new '[a-z]' # => /[a-z]/
7
+ #
8
+ # Implementation details
9
+ # ----------------------
10
+ #
11
+ # Instances of {Regexp} are toll-free bridged to native javascript
12
+ # regular expressions. This means that javascript regexp instances may
13
+ # be passed directly into ruby methods that expect a regexp instance.
14
+ #
15
+ # Due to the limitations of some browser engines, regexps from ruby are
16
+ # not always compatible with the target browser javascript engine.
17
+ # Compatibility differences change between engines, so reading up on a
18
+ # particular browsers documentation might point to differences
19
+ # discovered. The majority of regexp syntax is typically the same.
1
20
  class Regexp
2
21
  def inspect
3
22
  `return self.toString();`
@@ -1,18 +1,66 @@
1
- # A {String} object holds a sequence of bytes, typically representing
2
- # characters.
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ # String objects holds a sequence of bytes, typically representing
4
+ # characters. Strings may be constructed by using methods like
5
+ # {String.new} or literals, like the following:
6
+ #
7
+ # String.new("foo") # => "foo"
8
+ # "bar" # => "bar"
9
+ #
10
+ # Strings in Opal are immutable; which means that their contents cannot
11
+ # be changed. This means that a lot of methods like `strip!` are not
12
+ # present, and will yield a `NoMethodError`. Thier immutable
13
+ # counterparts are still available, which typically just return a new
14
+ # string.
15
+ #
16
+ # Implementation details
17
+ # ----------------------
18
+ #
19
+ # Ruby strings are toll-free bridged to native javascript strings,
20
+ # meaning that anywhere that a ruby string is required, a normal
21
+ # javascript string may be passed. This dramatically improves the
22
+ # performance of Opal due to a lower overhead in allocating strings as
23
+ # well as the ability to used functions of the String prototype to
24
+ # perform many of the core ruby methods.
25
+ #
26
+ # It is due to this limitation that strings are immutable. Javascript
27
+ # strings are immutable too, which limits what can be done with them in
28
+ # regards to Ruby methods.
29
+ #
30
+ # Ruby compatibility
31
+ # ------------------
32
+ #
33
+ # As discussed, {String} instances are immutable so they do not
34
+ # implement any of the self mutable methods found in the ruby core
35
+ # library. Most of these methods have their relative immutable
36
+ # implementations, or alternative methods to take their place.
37
+ #
38
+ # Custom subclasses of {String} can be used, and are constructed in the
39
+ # {.new} method. To due opals internals, a regular string is constructed
40
+ # using `new String(string_content)`, and its class and method table
41
+ # simply pointed at the custom subclass. As these custom subclasses are
42
+ # simply javascript strings as well, they are also limited to being
43
+ # immutable. This is because they share the same internal structre as
44
+ # regular {String} instances.
3
45
  #
4
- # Implementation Details
5
- # ======================
46
+ # String instances will never actually have their {.allocate} methods
47
+ # called. Due to the way opal bridges strings to javascript, when a new
48
+ # string is constructed, its value must be know. This is not possible in
49
+ # `allocate` as the value is not passed. Therefore the creation of
50
+ # strings (including subclasses) is done in {.new} where the string
51
+ # value is passed as an argument.
6
52
  #
7
- # For performance, strings in Opal are build directly on top of native
8
- # javascript strings, so that they are infact the same object. This has the side
9
- # effect that all strings are immutable, that is, they cannot be changed. Most
10
- # of the string methods that end in '!' are therefore not implemented, but their
11
- # counterparts are: 'upase' exists, but 'upcase!' does not, for example.
53
+ # Finally, strings do not currently include the `Comparable` module, as
54
+ # it is not yet implemented. The main methods used by {String} from this
55
+ # module are implemented directly as String methods. When `Comparable`
56
+ # is implemented, these methods will be moved back to the module.
12
57
  class String
13
58
 
14
59
  def self.new(str = "")
15
- `return new String(str);`
60
+ `var result = new String(str);
61
+ result.$klass = self;
62
+ result.$m = self.$m_tbl;
63
+ return result;`
16
64
  end
17
65
 
18
66
  # Copy - returns a new string containing `count` copies of the receiver.
@@ -137,11 +185,11 @@ class String
137
185
  #
138
186
  # @return [Symbol]
139
187
  def to_sym
140
- `return $opal.Y(self);`
188
+ `return VM.Y(self);`
141
189
  end
142
190
 
143
191
  def intern
144
- `return $opal.Y(self);`
192
+ `return VM.Y(self);`
145
193
  end
146
194
 
147
195
  # Returns a new string with the characters from `self` in reverse order.
@@ -212,7 +260,7 @@ class String
212
260
  # obj is not a regexp, then it calls =~ on it, using the receiver as an
213
261
  # argument
214
262
  #
215
- # @TODO passing a non regexp is not currently supported
263
+ # **TODO** passing a non regexp is not currently supported
216
264
  #
217
265
  # @param [Regexp, Objec] obj
218
266
  # @return [Numeric, nil]
@@ -295,7 +343,7 @@ class String
295
343
  # self. Returns `nil` if not found. If the second param is present then it
296
344
  # specifies the index of self to begin searching.
297
345
  #
298
- # @TODO: regexp and offsets not yet implemented.
346
+ # **TODO** regexp and offsets not yet implemented.
299
347
  #
300
348
  # @example
301
349
  #
@@ -1,3 +1,30 @@
1
+ # `Symbols` are used to represent names and can often be used in place
2
+ # of enum variables used in other languages. Symbols can be constructed
3
+ # using their literal syntax or one of the various `to_sym` methods
4
+ # found in the standard library:
5
+ #
6
+ # :some_symbol # => :some_symbol
7
+ # "a_string".to_sym # => :a_string
8
+ #
9
+ # It is important to note that regardless of the context that created
10
+ # them, two symbols with the same name will always be the exact same
11
+ # object. The opal runtime guarantees this as it creates them. If one
12
+ # exists already with the required name, it will be returned instead of
13
+ # creating a new one.
14
+ #
15
+ # Implementation details
16
+ # ----------------------
17
+ #
18
+ # Internally, symbols are just javascript strings. They are constructed
19
+ # with the javascript `new String(symbol_name)` syntax. Once created,
20
+ # they have their class and method tables altered to point towards the
21
+ # {Symbol} class. This avoids them conflicting with regular strings.
22
+ #
23
+ # Symbols are implemented as strings for performance. They are only
24
+ # created once per name, so past the initial creation phase, which
25
+ # happends just the once, they perform as quickly as just passig them
26
+ # between method calls, and as strings their native prototype offers all
27
+ # the required functionality needed by the class.
1
28
  class Symbol
2
29
 
3
30
  def inspect
@@ -1,3 +1,24 @@
1
+ # Instances of `TrueClass` represent logically true values. There may
2
+ # only be one instance of `TrueClass`, which is the global value
3
+ # `true`. Attempts to create a new instance will yield an error.
4
+ # `TrueClass` provides methods to perform logical operations with other
5
+ # ruby objects.
6
+ #
7
+ # Implementation details
8
+ # ----------------------
9
+ #
10
+ # Due to the way messages are passed inside opal, `true` is not
11
+ # actually toll-free bridged onto the native javascript `true` value.
12
+ # In javascript, `true` and `true` are both instances of the Boolean
13
+ # type, which means they would need to share the same method_table in
14
+ # opal, which would remove their ability to be true instances of Rubys'
15
+ # `TrueClass` or `FalseClass`.
16
+ #
17
+ # As javascripts `true` is not actually the value used in opal, passing
18
+ # the native `true` value will cause errors when messages are sent to
19
+ # it. Within a file directly loaded by opal, `Qtrue` is a free variable
20
+ # that points to the actualy ruby instance of this class. This variable
21
+ # may be passed around freely.
1
22
  class TrueClass
2
23
  def to_s
3
24
  "true"
@@ -10,3 +10,5 @@ require 'opal/gem'
10
10
  require 'opal/bundle'
11
11
  require 'opal/builder'
12
12
 
13
+ require 'opal/rake/builder_task'
14
+
@@ -29,26 +29,26 @@ module Opal
29
29
  @project_dir = options[:project_dir] || Dir.getwd
30
30
  @project_name = File.basename @project_dir
31
31
 
32
- out = options[:out] || File.join('javascripts', "#@project_name.js")
33
- @out = File.join @project_dir, out
34
- FileUtils.mkdir_p File.dirname(@out)
35
-
36
32
  files = options[:files] || []
37
- @files = []
33
+ files = [files] unless files.is_a? Array
34
+ @files = Dir.[](*files)
38
35
 
39
- if Array === files
40
- files.each do |file|
41
- @files << file
42
- end
36
+ @watch = options[:watch]
37
+
38
+ raise "Opal::Builder - No input files could be found!" if @files.empty?
39
+
40
+ @main = options[:main]
41
+
42
+ if @main
43
+ raise "Opal::Builder - Main file does not exist!" unless File.exists? @main
44
+ @files << @main unless @files.include? @main
43
45
  else
44
- Dir.glob(File.join(@project_dir, files)) do |file|
45
- @files << file
46
- end
46
+ @main = @files.first
47
47
  end
48
48
 
49
- @watch = options[:watch]
50
-
51
- raise "Opal::Builder - No input files!" if @files.empty?
49
+ out = options[:out] || File.basename(@main, '.rb') + '.js'
50
+ @out = File.join @project_dir, out
51
+ FileUtils.mkdir_p File.dirname(@out)
52
52
  end
53
53
 
54
54
  # Actually build the simple builder. This is simply used as a looper to
@@ -79,11 +79,13 @@ module Opal
79
79
 
80
80
  # Does the actual rebuild of a project
81
81
  def rebuild
82
+ puts "rebuilding to #@out"
83
+ puts @files.inspect
82
84
  File.open(@out, 'w') do |out|
83
85
  @files.each do |file|
84
86
  out.write wrap_source file
85
87
  end
86
- main = File.basename(@files.first).sub(/\.rb/, '')
88
+ main = File.basename(@main).sub(/\.rb/, '')
87
89
  out.write "opal.require('#{main}');\n"
88
90
  end
89
91
  end
@@ -0,0 +1,44 @@
1
+ require 'rake'
2
+ require 'rake/tasklib'
3
+
4
+ module Opal
5
+ module Rake
6
+
7
+ class BuilderTask < ::Rake::TaskLib
8
+
9
+ attr_accessor :files
10
+
11
+ attr_accessor :out
12
+
13
+ attr_accessor :main
14
+
15
+ attr_accessor :watch
16
+
17
+ def initialize(name = :opal)
18
+ @name = name
19
+ @files = []
20
+ @out = nil
21
+ @main = nil
22
+ @watch = false
23
+
24
+ yield self if block_given?
25
+ define_rake_task
26
+ end
27
+
28
+ def define_rake_task
29
+ desc "Build opal files"
30
+ task(@name) do
31
+ options = {}
32
+ options[:files] = @files
33
+ options[:out] = @out if @out
34
+ options[:main] = @main if @main
35
+ options[:watch] = @watch
36
+
37
+ builder = Opal::Builder.new options
38
+ builder.build
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+
@@ -1,7 +1,7 @@
1
1
 
2
2
  Gem::Specification.new do |gem|
3
3
  gem.name = "opal"
4
- gem.version = "0.3.1"
4
+ gem.version = "0.3.2"
5
5
  gem.authors = ["Adam Beynon"]
6
6
  gem.email = ["adam@adambeynon.com"]
7
7
  gem.homepage = "http://github.com/adambeynon/opal"
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: opal
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.3.1
5
+ version: 0.3.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Adam Beynon
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-03-30 00:00:00 +01:00
13
+ date: 2011-03-31 00:00:00 +01:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -25,6 +25,7 @@ extra_rdoc_files: []
25
25
 
26
26
  files:
27
27
  - .gitignore
28
+ - Changelog
28
29
  - LICENSE
29
30
  - README.md
30
31
  - Rakefile
@@ -45,6 +46,7 @@ files:
45
46
  - gems/core/lib/core/module.rb
46
47
  - gems/core/lib/core/nil_class.rb
47
48
  - gems/core/lib/core/numeric.rb
49
+ - gems/core/lib/core/object.rb
48
50
  - gems/core/lib/core/proc.rb
49
51
  - gems/core/lib/core/range.rb
50
52
  - gems/core/lib/core/regexp.rb
@@ -186,6 +188,7 @@ files:
186
188
  - lib/opal/context/file_system.rb
187
189
  - lib/opal/context/loader.rb
188
190
  - lib/opal/gem.rb
191
+ - lib/opal/rake/builder_task.rb
189
192
  - lib/opal/ruby/nodes.rb
190
193
  - lib/opal/ruby/parser.rb
191
194
  - lib/opal/ruby/ruby_parser.rb