opal 0.3.10 → 0.3.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -17,16 +17,10 @@ Opal does not aim to be 100% comaptible with other ruby implementations,
17
17
  but does so where the generated code can be efficient on all modern web
18
18
  browsers - including older versions of IE and mobile devices.
19
19
 
20
- Using opal
20
+ Installing opal
21
21
  ----------
22
22
 
23
- Opal can currently be used in three ways: through a distributed ruby gem,
24
- directly in the web browser or with rbp - a new package manager designed
25
- for opal but usable for any ruby project.
26
-
27
- ### Using the gem
28
-
29
- Install via ruby gems:
23
+ Install the gem:
30
24
 
31
25
  ```
32
26
  $ gem install opal
@@ -38,66 +32,73 @@ The `opal` command should then be available. To run the simple repl use:
38
32
  opal irb
39
33
  ```
40
34
 
41
- The `opal` command can also be used directly from this source repo, so
42
- to download and run opal:
35
+ Usage
36
+ -----
37
+
38
+ The quickest way to get opal running is to use the project generator.
39
+ Simply run the command:
43
40
 
44
41
  ```
45
- $ git clone https://github.com/adambeynon/opal.git
46
- $ cd opal
47
- $ bin/opal
42
+ opal init my_project
48
43
  ```
49
44
 
50
- ### Using rbp
45
+ replacing "my_project" with any name. This will make a "my_project"
46
+ directory with a Rakefile, html document and libs needed for running
47
+ opal in the browser.
51
48
 
52
- rbp installs dependencies locally to your project, so edit your
53
- package.yml file to add the following dependency:
49
+ ### Using opal in the browser
54
50
 
55
- ```yaml
56
- dev_dependencies:
57
- opal: "0.3.9"
58
- therubyracer: "0.9.4"
59
- ```
51
+ Opal runs directly in the browser, and is distributed as two files,
52
+ `opal.js` and `opal-parser.js`. To just run precompiled code, just the
53
+ `opal.js` runtime is required which includes the runtime and opals
54
+ implementation of the ruby core library (pre compiled).
55
+
56
+ To evaluate ruby code directly in the browser, `opal-parser.js` is also
57
+ required which will also load any ruby code found in script tags.
60
58
 
61
- Install them with:
59
+ ### Bundle
60
+
61
+ The Rakefile has a task to build your ruby project, so just run:
62
62
 
63
63
  ```
64
- $ rbp install
64
+ rake bundle
65
65
  ```
66
66
 
67
- This will install them into vendor/ ready to use. therubyracer is only
68
- needed if you want to run your ruby code, compiled into javascript,
69
- directly on the commandline. If you are just compiling ruby then just
70
- the opal package is sufficient.
67
+ Open `index.html` in a browser, and now it should run. Edit, build and
68
+ run to suit.
71
69
 
72
- Running tests
73
- -------------
70
+ Project structure
71
+ -----------------
74
72
 
75
- To run tests, you need opaltest which is the testing framework for opal
76
- based on minitest. To get opaltest, run the following in the opal
77
- directory:
73
+ This repo contains the code for the opal gem as well as the opal core
74
+ library and runtime. Files inside `bin/` and `lib/` are the files that
75
+ are used as part of the gem and run directly on your ruby environment.
78
76
 
79
- ```
80
- $ rbp install
81
- ```
77
+ `corelib/` contains opal's core library implementation and is not used
78
+ directly by the gem. These files are precompiled during development
79
+ ready to be used in the gem or in a browser.
82
80
 
83
- This will put opaltest into `packages/opaltest` so it will be available
84
- for running. To test `array.rb` for example, run:
81
+ `runtime/` contains opal's runtime written in javascript. It is not used
82
+ directly by the gem, but is built ready to use in the js contexts that
83
+ opal runs.
85
84
 
86
- ```
87
- $ rbp exec opal test/array.rb
88
- ```
85
+ `stdlib/` contains the stdlib files that opal comes packaged with. The
86
+ gem does use these, but only as required. Opal does not include the full
87
+ opal stdlib, and some parts are actually written in javascript for
88
+ optimal performance. These can be `require()` at runtime.
89
89
 
90
- The results should be printed to the console.
90
+ `opal.js` and `opal-parser.js` are included in the gem, but not the
91
+ source repo. They are the latest built versions of opal and its parser
92
+ which are built before the gem is published.
91
93
 
92
94
  Differences from ruby
93
95
  ---------------------
94
96
 
95
- ### No method\_missing
97
+ ### Optional method\_missing
96
98
 
97
- To optimize method dispatch, `method_missing` is not supported in opal.
98
- It is supported in debug mode to improve readability of error messages
99
- from calling undefined methods, but should/will not be used in
100
- production code.
99
+ To optimize method dispatch, `method_missing` is, by default, turned off
100
+ in opal. It can easily be enabled by passing `:method_missing => true`
101
+ in the parser options.
101
102
 
102
103
  ### Immutable strings and removed symbols
103
104
 
data/lib/opal.rb CHANGED
@@ -1,12 +1,20 @@
1
- require 'opal/parser'
2
- require 'opal/builder'
3
- require 'opal/context'
1
+ require "opal/parser"
2
+ require "opal/builder"
3
+ require "opal/context"
4
+ require "opal/version"
4
5
 
5
6
  # Opal is a set of build tools and runtime utilies for compiling ruby
6
7
  # source code into javascript. Opal can use therubyracer to provide a
7
8
  # ruby context for evaluating the generated javascript against the
8
9
  # provided runtime.
9
10
  module Opal
11
+ # Root opal directory (root of gem)
10
12
  OPAL_DIR = File.expand_path('../..', __FILE__)
13
+
14
+ # Full path to our opal.js runtime file
15
+ OPAL_JS_PATH = File.join OPAL_DIR, "opal.js"
16
+
17
+ # Full path to our opal-parser.js parser file
18
+ OPAL_PARSER_JS_PATH = File.join OPAL_DIR, "opal-parser.js"
11
19
  end
12
20
 
data/lib/opal/builder.rb CHANGED
@@ -1,21 +1,17 @@
1
1
  require 'fileutils'
2
2
  require 'opal/parser'
3
+ require 'opal/version'
3
4
 
4
5
  module Opal
5
-
6
6
  # The Builder class is used for building single ruby sources, or
7
7
  # building the core library ready for the browser/v8 context. It
8
- # is not used directly for building packages.
8
+ # is not used directly for building gem.
9
9
  class Builder
10
10
 
11
11
  OPAL_PATH = File.expand_path(File.join('..', '..', '..'), __FILE__)
12
12
 
13
13
  STDLIB_PATH = File.join OPAL_PATH, 'stdlib'
14
14
 
15
- RUNTIME_PATH = File.join OPAL_PATH, 'runtime'
16
-
17
- CORE_PATH = File.join OPAL_PATH, 'corelib'
18
-
19
15
  def initialize
20
16
  @parser = Parser.new
21
17
  end
@@ -43,7 +39,7 @@ module Opal
43
39
  # relative_path = relative_path.sub(/\.rb/, '.js') if ext == '.rb'
44
40
  content = compile_source full_path
45
41
 
46
- "opal.lib('#{relative_path}.rb', #{content});\n"
42
+ "opal.lib('#{relative_path}', #{content});\n"
47
43
  end
48
44
 
49
45
  # Simply compile the given source code at the given path. This is
@@ -61,51 +57,13 @@ module Opal
61
57
  "function($rb, self, __FILE__) { #{src} }"
62
58
 
63
59
  when '.rb'
64
- src = Opal::Parser.new(src).parse!.generate_top
65
- "function($rb, self, __FILE__) { #{src} }"
60
+ return parse src
66
61
 
67
62
  else
68
63
  raise "Bad file type for wrapping. Must be ruby or javascript"
69
64
  end
70
65
  end
71
66
 
72
- # Builds core opal runtime + core libs, and returns as a string.
73
- # This can then just be used directly by any compiled code. The
74
- # core lib is then auto loaded so it is ready for running.
75
- def build_core
76
- code = ''
77
-
78
- %w[pre runtime init class module fs loader].each do |f|
79
- code += File.read(File.join RUNTIME_PATH, f + '.js')
80
- end
81
-
82
- order = File.read(File.join(CORE_PATH, 'load_order')).strip.split
83
-
84
- core = order.map do |o|
85
- File.read File.join(CORE_PATH, o + '.rb')
86
- end
87
-
88
- code += "var core_lib = #{parse core.join};"
89
-
90
- code + File.read(File.join RUNTIME_PATH, 'post.js')
91
- end
92
-
93
- # Builds the opal parser and dev.rb file, and returns as a string.
94
- def build_parser
95
- code = ''
96
-
97
- %w[opal/nodes opal/lexer opal/parser].each do |src|
98
- full = File.join OPAL_PATH, 'lib', src + '.rb'
99
- compiled = compile_source full
100
- code += "opal.lib('#{src}.rb', #{compiled});"
101
- end
102
-
103
- code += build_stdlib 'racc/parser', 'strscan', 'dev'
104
- code += "opal.require('dev');"
105
-
106
- code
107
- end
108
-
109
67
  # Build the given sources from the standard library. These can be
110
68
  # globs. Returns a string of all content.
111
69
  def build_stdlib(*files)
data/lib/opal/bundle.rb CHANGED
@@ -1,41 +1,27 @@
1
1
  require 'opal/builder'
2
2
 
3
- begin
4
- require 'rbp/package'
5
- rescue LoadError
6
- abort "You need to install rbp. `gem install rbp`."
7
- end
8
-
9
3
  module Opal
10
- # Takes a package and builds it ready for the browser
11
4
  class Bundle
12
- # @return [Rbp::Package] the package this is bundling
13
- attr_reader :package
14
-
5
+ attr_accessor :name
6
+ attr_accessor :version
15
7
  attr_accessor :options
16
8
 
17
- def initialize(package)
18
- @package = package
19
- @builder = Builder.new
9
+ def initialize
10
+ @builder = Builder.new
20
11
  @options = {}
21
12
  end
22
13
 
23
- # Simple build - returns a string which can be written to a file
24
- # FIXME: hardcoded lib directory to './lib'
25
14
  def build
26
- package_dir = @package.package_dir
27
-
28
- lib_files = @package.relative_lib_files.map do |lib|
29
- path = File.join package_dir, lib
30
- code = @builder.parse File.read(path), options
31
-
32
- "\"#{lib}\": #{code}"
15
+ lib_files = Dir["{lib}/**/*.rb"].map do |lib|
16
+ code = @builder.parse File.read(lib), options
17
+ path = lib[4, lib.length - 7]
18
+ "\"#{path}\": #{code}"
33
19
  end
34
20
 
35
21
  bundle = []
36
- bundle << %[opal.package({\n]
37
- bundle << %[ name: "#{@package.name}",\n]
38
- bundle << %[ version: "#{@package.version}",\n]
22
+ bundle << %[opal.gem({\n]
23
+ bundle << %[ name: "#{@name}",\n]
24
+ bundle << %[ version: "#{@version}",\n]
39
25
  bundle << %[ libs: {\n]
40
26
  bundle << %[ #{lib_files.join ",\n "}\n]
41
27
  bundle << %[ }\n]
data/lib/opal/command.rb CHANGED
@@ -1,15 +1,20 @@
1
- module Opal
1
+ require 'optparse'
2
+ require 'fileutils'
3
+ require 'opal/builder'
2
4
 
5
+ module Opal
6
+ # Command runner. When using the `opal` bin file, this class is used to
7
+ # delegate commands based on the options passed from the command line.
3
8
  class Command
4
9
 
5
10
  # Valid command line arguments
6
- COMMANDS = [:help, :irb, :compile, :bundle, :exec, :eval, :install]
11
+ COMMANDS = [:help, :irb, :compile, :bundle, :exec, :eval, :install, :init]
7
12
 
8
13
  def initialize(args)
9
14
  command = args.shift
10
15
 
11
16
  if command and COMMANDS.include?(command.to_sym)
12
- __send__ command.to_sym, *args
17
+ __send__ command.to_sym
13
18
  elsif command and File.exists? command
14
19
  eval command
15
20
  else
@@ -17,36 +22,113 @@ module Opal
17
22
  end
18
23
  end
19
24
 
25
+ # Initialize a project either in current directory, or directory
26
+ # specified in ARGV.
27
+ def init
28
+ path = File.expand_path(ARGV.first || Dir.getwd)
29
+ base = File.basename(path)
30
+ template = File.join(OPAL_DIR, "templates", "init")
31
+
32
+ Dir.chdir(template) do
33
+ Dir["**/*"].each do |f|
34
+ next if File.directory? f
35
+
36
+ full = File.expand_path f, template
37
+ dest = File.join path, f.sub(/__NAME__/, base)
38
+
39
+ if File.exists? dest
40
+ puts "Skipping #{f}"
41
+ next
42
+ end
43
+
44
+ FileUtils.mkdir_p File.dirname(dest)
45
+
46
+ File.open(dest, 'w+') do |o|
47
+ o.write File.read(full).gsub(/__NAME__/, base)
48
+ end
49
+ end
50
+ end
51
+
52
+ FileUtils.mkdir_p File.join(path, "js")
53
+
54
+ %w[opal.js opal-parser.js].each do |src|
55
+ File.open(File.join(path, "js", src), "w+") do |o|
56
+ o.write File.read(File.join(OPAL_DIR, src))
57
+ end
58
+ end
59
+ end
60
+
20
61
  def help
21
62
  puts "need to print help"
22
63
  end
23
64
 
24
- # desc "irb", "Opens interactive opal/ruby repl"
25
- def irb
26
- ctx = Opal::Context.new
65
+ # Starts an irb session using an inline v8 context. Commands can be
66
+ # entered just like IRB. Use Ctrl-C or type `exit` to quit.
67
+ def irb(*)
68
+ ctx = Context.new :method_missing => true,
69
+ :overload_arithmetic => true,
70
+ :overload_comparison => true,
71
+ :overload_bitwise => true
27
72
  ctx.start_repl
28
73
  end
29
74
 
30
- def eval(path = nil)
31
- return "no path given for eval" unless path
75
+ # If the given arg exists as a file, then the source code is compiled
76
+ # and then run through a javascript context and the result printed out.
77
+ #
78
+ # If the arg isn't a file, then it is assumed to be raw ruby code and it
79
+ # is compiled and run directly with the result being printed out.
80
+ #
81
+ # Usage:
82
+ #
83
+ # opal eval path/to/some/file.rb
84
+ # # => "some result"
85
+ #
86
+ # opal eval "1.class"
87
+ # # => Numeric
88
+ #
89
+ # @param [String] code path or ruby code to eval
90
+ def eval(code = nil, *)
91
+ abort "Usage: opal eval [Ruby code or file path]" unless code
92
+
93
+ if File.exists? code
94
+ code = Parser.new.parse File.read(code)
95
+ end
32
96
 
33
- abort "path does not exist `#{path}'" unless File.exist? path
97
+ context = Context.new :method_missing => true,
98
+ :overload_arithmetic => true,
99
+ :overload_comparison => true,
100
+ :overload_bitwise => true
34
101
 
35
- ctx = Opal::Context.new
36
- ctx.require_file File.expand_path(path)
102
+ puts context.eval code
37
103
  end
38
104
 
39
- def compile(path)
40
- puts Opal::Parser.new(File.read(path)).parse!.generate_top
41
- end
42
-
43
- def install
44
- install = RBP::Install.new
45
- install.install
105
+ # If the given path exists, then compiles the source code of that
106
+ # file and spits out the generated javascript.
107
+ #
108
+ # If this file does not exist, then assumes the input is ruby code
109
+ # to compile and return.
110
+ #
111
+ # Usage:
112
+ #
113
+ # opal compile path/to/ruby.rb
114
+ # # => "generated code"
115
+ #
116
+ # opal compile "some ruby code"
117
+ # # => generated code
118
+ #
119
+ # @param [String] path file path or ruby code
120
+ def compile(path = nil, *)
121
+ abort "Usage: opal compile [Ruby code or file path]" unless path
122
+
123
+ if File.exists? path
124
+ puts Parser.new.parse File.read(path)
125
+ else
126
+ puts Parser.new.parse path
127
+ end
46
128
  end
47
129
 
48
130
  # Bundle the gem (browserify) ready for the browser
49
- def bundle
131
+ def bundle(*)
50
132
  # lazy load incase user does not have rbp installed
51
133
  require 'opal/bundle'
52
134
 
@@ -54,9 +136,6 @@ module Opal
54
136
  package = Rbp::Package.load_path path
55
137
  bundle = Bundle.new package
56
138
 
57
- puts bundle
58
- puts bundle.package
59
-
60
139
  puts bundle.build
61
140
  end
62
141
  end