red 3.5.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +10 -15
- data/README.txt +7 -50
- data/bin/red +12 -19
- data/config/hoe.rb +7 -6
- data/lib/red/errors.rb +2 -64
- data/lib/red/executable.rb +35 -34
- data/lib/red/nodes/assignment_nodes.rb +133 -0
- data/lib/red/nodes/call_nodes.rb +126 -0
- data/lib/red/nodes/control_nodes.rb +126 -0
- data/lib/red/nodes/data_nodes.rb +75 -0
- data/lib/red/nodes/definition_nodes.rb +191 -0
- data/lib/red/nodes/illegal_nodes.rb +33 -0
- data/lib/red/nodes/literal_nodes.rb +148 -0
- data/lib/red/nodes/logic_nodes.rb +89 -0
- data/lib/red/nodes/variable_nodes.rb +76 -0
- data/lib/red/plugin.rb +6 -7
- data/lib/red/version.rb +2 -2
- data/lib/red.rb +209 -131
- data/lib/source/ruby.rb +6744 -0
- metadata +14 -19
- data/lib/javascripts/_dom_ready.js +0 -249
- data/lib/javascripts/prototype_dom_ready.js +0 -1
- data/lib/javascripts/red/unobtrusive.red +0 -6
- data/lib/red/assignment_nodes.rb +0 -164
- data/lib/red/call_nodes.rb +0 -90
- data/lib/red/conditional_nodes.rb +0 -63
- data/lib/red/conjunction_nodes.rb +0 -23
- data/lib/red/constant_nodes.rb +0 -47
- data/lib/red/control_nodes.rb +0 -129
- data/lib/red/data_nodes.rb +0 -93
- data/lib/red/definition_nodes.rb +0 -177
- data/lib/red/illegal_nodes.rb +0 -63
- data/lib/red/literal_nodes.rb +0 -119
- data/lib/red/variable_nodes.rb +0 -37
- data/lib/red/wrap_nodes.rb +0 -51
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -7,26 +7,21 @@ Rakefile
|
|
7
7
|
bin/red
|
8
8
|
config/hoe.rb
|
9
9
|
config/requirements.rb
|
10
|
-
lib/javascripts/_dom_ready.js
|
11
|
-
lib/javascripts/prototype_dom_ready.js
|
12
|
-
lib/javascripts/red/unobtrusive.red
|
13
10
|
lib/red.rb
|
14
|
-
lib/red/assignment_nodes.rb
|
15
|
-
lib/red/call_nodes.rb
|
16
|
-
lib/red/conditional_nodes.rb
|
17
|
-
lib/red/conjunction_nodes.rb
|
18
|
-
lib/red/constant_nodes.rb
|
19
|
-
lib/red/control_nodes.rb
|
20
|
-
lib/red/data_nodes.rb
|
21
|
-
lib/red/definition_nodes.rb
|
22
11
|
lib/red/errors.rb
|
23
12
|
lib/red/executable.rb
|
24
|
-
lib/red/illegal_nodes.rb
|
25
|
-
lib/red/literal_nodes.rb
|
26
13
|
lib/red/plugin.rb
|
27
|
-
lib/red/variable_nodes.rb
|
28
14
|
lib/red/version.rb
|
29
|
-
lib/red/
|
15
|
+
lib/red/nodes/assignment_nodes.rb
|
16
|
+
lib/red/nodes/call_nodes.rb
|
17
|
+
lib/red/nodes/control_nodes.rb
|
18
|
+
lib/red/nodes/data_nodes.rb
|
19
|
+
lib/red/nodes/definition_nodes.rb
|
20
|
+
lib/red/nodes/illegal_nodes.rb
|
21
|
+
lib/red/nodes/literal_nodes.rb
|
22
|
+
lib/red/nodes/logic_nodes.rb
|
23
|
+
lib/red/nodes/variable_nodes.rb
|
24
|
+
lib/source/ruby.rb
|
30
25
|
script/console
|
31
26
|
script/destroy
|
32
27
|
script/generate
|
data/README.txt
CHANGED
@@ -1,59 +1,16 @@
|
|
1
|
-
=
|
1
|
+
= Write Ruby. Run JavaScript. The new Red is here.
|
2
2
|
|
3
|
-
|
3
|
+
Red takes the Ruby you write and turns it into JavaScript for your browser.
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
To get <span style="color:rgb(195,0,0)">Red</span> working, install the rubygem.
|
8
|
-
<pre>sudo gem install red</pre>
|
9
|
-
|
10
|
-
=== Creating <tt>.js</tt> Files
|
11
|
-
|
12
|
-
Create a new <tt>.red</tt> file and edit it using your text editor.
|
13
|
-
$ mate example.red
|
14
|
-
|
15
|
-
1| class Foo
|
16
|
-
2| def initialize(foo)
|
17
|
-
3| @foo = foo
|
18
|
-
4| end
|
19
|
-
5| end
|
20
|
-
|
21
|
-
Use the command-line executable to convert your Ruby into JavaScript.
|
22
|
-
|
23
|
-
$ red example
|
24
|
-
#=> var Foo = function(foo) { this.foo = foo; }
|
25
|
-
|
26
|
-
<span style="color:rgb(195,0,0)">Red</span> creates a <tt>.js</tt> file containing the output.
|
27
|
-
|
28
|
-
$ ls
|
29
|
-
#=> example.js example.red
|
5
|
+
The all-new Red is a Ruby-to-JavaScript transliterator backed by a custom ruby.js library designed to let your code run in the browser exactly* the way Ruby would run on your machine. The JavaScript output is optimized to contain only the fraction of the ruby.js source library needed to run your code.
|
30
6
|
|
31
|
-
|
7
|
+
What does this mean for today’s Ruby developer? Simple. You don’t need to learn JavaScript.
|
32
8
|
|
33
|
-
|
34
|
-
|
35
|
-
$ mate test.red
|
36
|
-
|
37
|
-
1| return false unless navigator[:user_agent].index_of('AppleWebKit/') > -1
|
38
|
-
|
39
|
-
$ red test
|
40
|
-
#=> if (!(navigator.userAgent.indexOf('AppleWebKit/') > -1)) { return false; }
|
41
|
-
|
42
|
-
$ ls
|
43
|
-
#=> example.js example.red test.red
|
44
|
-
|
45
|
-
You can test short code snippets from the command line without creating a test file by using the <tt>-s</tt> option.
|
46
|
-
|
47
|
-
$ red -s "@foo"
|
48
|
-
#=> this.foo
|
49
|
-
|
50
|
-
=== Tutorial
|
51
|
-
|
52
|
-
Check the <a href=http://github.com/jessesielaff/red/wikis/tutorial>Tutorial page</a> for an in-depth lesson in how to use <span style="color:rgb(195,0,0)">Red</span> to write your JavaScript in Ruby.
|
9
|
+
=== Installation
|
53
10
|
|
54
|
-
|
11
|
+
To get Red working, install the rubygem.
|
55
12
|
|
56
|
-
|
13
|
+
sudo gem install red
|
57
14
|
|
58
15
|
=== Bugs / Issues
|
59
16
|
|
data/bin/red
CHANGED
@@ -1,14 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
# Red's command line
|
2
|
+
# Red's command line Ruby-to-JS conversion executable.
|
3
3
|
#
|
4
4
|
# Copyright (c) 2008 Jesse Sielaff.
|
5
5
|
|
6
|
-
|
7
|
-
require 'rubygems'
|
8
|
-
rescue LoadError
|
9
|
-
# no rubygems to load, so we fail silently
|
10
|
-
end
|
11
|
-
|
6
|
+
require 'rubygems' rescue nil
|
12
7
|
require 'red'
|
13
8
|
require 'red/executable'
|
14
9
|
require 'red/version'
|
@@ -20,11 +15,11 @@ include Red
|
|
20
15
|
parser = OptionParser.new do |opts|
|
21
16
|
opts.banner = RED_MESSAGES[:banner]
|
22
17
|
opts.separator ""
|
23
|
-
opts.on(
|
24
|
-
opts.on(
|
25
|
-
opts.on(
|
26
|
-
opts.on(
|
27
|
-
opts.on(
|
18
|
+
opts.on('-h',"--help","Show this help message.") { puts opts; exit }
|
19
|
+
opts.on('-r',"--rails","Add Red plugin to ./vendor/plugins.") { build_red_plugin_for_rails }
|
20
|
+
opts.on('-s',"--string=RUBY_STRING","Translate a single string to JavaScript.") { |string| Red.init && direct_translate(string) }
|
21
|
+
opts.on('-t',"--test","Translate a file to JavaScript without writing a .js file.") { ARGV.push(:test) }
|
22
|
+
opts.on('-v',"--version","Print version number.") { puts Red::VERSION::STRING; exit }
|
28
23
|
begin
|
29
24
|
opts.parse!(ARGV)
|
30
25
|
rescue OptionParser::InvalidOption => e
|
@@ -34,10 +29,8 @@ parser = OptionParser.new do |opts|
|
|
34
29
|
end
|
35
30
|
end
|
36
31
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
32
|
+
class << Red
|
33
|
+
dry_run = (ARGV[1] ? ARGV.pop : true) if Red.init && ARGV.last == :test
|
34
|
+
ARGV.map {|filename| self.convert_red_file_to_js(filename, dry_run)}
|
35
|
+
end && exit unless ARGV.empty?
|
36
|
+
puts RED_MESSAGES[:usage]
|
data/config/hoe.rb
CHANGED
@@ -2,7 +2,7 @@ require 'red/version'
|
|
2
2
|
|
3
3
|
AUTHOR = 'Jesse Sielaff'
|
4
4
|
EMAIL = "jesse.sielaff@gmail.com"
|
5
|
-
DESCRIPTION = "Red
|
5
|
+
DESCRIPTION = "Red writes like Ruby and runs like JavaScript."
|
6
6
|
GEM_NAME = 'red'
|
7
7
|
RUBYFORGE_PROJECT = 'red-js'
|
8
8
|
HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
|
@@ -36,11 +36,12 @@ REV = nil
|
|
36
36
|
# UNCOMMENT IF REQUIRED:
|
37
37
|
# REV = YAML.load(`svn info`)['Revision']
|
38
38
|
VERS = Red::VERSION::STRING + (REV ? ".#{REV}" : "")
|
39
|
-
RDOC_OPTS = [
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
RDOC_OPTS = [
|
40
|
+
"--quiet",
|
41
|
+
"--title", "red documentation",
|
42
|
+
"--opname", "index.html",
|
43
|
+
"--line-numbers"
|
44
|
+
]
|
44
45
|
|
45
46
|
class Hoe
|
46
47
|
def extra_deps
|
data/lib/red/errors.rb
CHANGED
@@ -1,43 +1,15 @@
|
|
1
1
|
module Red
|
2
2
|
class BuildError < StandardError # :nodoc:
|
3
|
-
# Raised when a hash is given a key other than a +String+ or +Symbol+
|
4
|
-
# object.
|
5
|
-
class NoArbitraryHashKeys < BuildError # :nodoc:
|
6
|
-
end
|
7
|
-
|
8
3
|
# Raised when a lone +Regex+ is used as a condition.
|
9
4
|
class NoArbitraryMatch < BuildError # :nodoc:
|
10
5
|
end
|
11
6
|
|
12
|
-
# Raised when a +rescue+ block is placed in a way that would produce a
|
13
|
-
# JavaScript syntax error.
|
14
|
-
class NoArbitraryRescue < BuildError # :nodoc:
|
15
|
-
end
|
16
|
-
|
17
7
|
# Raised when a +BEGIN+ or +END+ block is used.
|
18
8
|
class NoBEGINorEND < BuildError # :nodoc:
|
19
9
|
end
|
20
10
|
|
21
|
-
# Raised when a
|
22
|
-
class
|
23
|
-
end
|
24
|
-
|
25
|
-
# Raised when a +break+ keyword is followed by an argument.
|
26
|
-
class NoBreakArguments < BuildError # :nodoc:
|
27
|
-
end
|
28
|
-
|
29
|
-
# Raised when the active JavaScript library does not support class
|
30
|
-
# inheritance.
|
31
|
-
class NoClassInheritance < BuildError # :nodoc:
|
32
|
-
end
|
33
|
-
|
34
|
-
# Raised when the active JavaScript library does not support calls to
|
35
|
-
# class variables or declarations of class variables.
|
36
|
-
class NoClassVariables < BuildError # :nodoc:
|
37
|
-
end
|
38
|
-
|
39
|
-
# Raised when a +redo+ or +retry+ keyword is used.
|
40
|
-
class NoDoOvers < BuildError # :nodoc:
|
11
|
+
# Raised when a +retry+ keyword is used.
|
12
|
+
class NoRetry < BuildError # :nodoc:
|
41
13
|
end
|
42
14
|
|
43
15
|
# Raised when a flipflop operator is called using <tt>..</tt> or
|
@@ -45,49 +17,15 @@ module Red
|
|
45
17
|
class NoFlipflops < BuildError # :nodoc:
|
46
18
|
end
|
47
19
|
|
48
|
-
# Raised when a +begin+ block is used for multiline assignment.
|
49
|
-
class NoMultilineAssignment < BuildError # :nodoc:
|
50
|
-
end
|
51
|
-
|
52
|
-
# Raised when a comma-separated multiple assignment expression is used.
|
53
|
-
class NoMultipleAssignment < BuildError # :nodoc:
|
54
|
-
end
|
55
|
-
|
56
|
-
# Raised when a +break+ keyword is followed by an argument.
|
57
|
-
class NoNextArguments < BuildError # :nodoc:
|
58
|
-
end
|
59
|
-
|
60
|
-
# Raised when the active JavaScript library has no native literal range
|
61
|
-
# constructor.
|
62
|
-
class NoRangeConstructor < BuildError # :nodoc:
|
63
|
-
end
|
64
|
-
|
65
20
|
# Raised when a +Regex+ literal declaration contains evaluated content.
|
66
21
|
class NoRegexEvaluation < BuildError # :nodoc:
|
67
22
|
end
|
68
23
|
|
69
|
-
# Raised when an +Error+ class is passed to +rescue+.
|
70
|
-
class NoSpecificRescue < BuildError # :nodoc:
|
71
|
-
end
|
72
|
-
|
73
24
|
# Raised when the active JavaScript library has no special array
|
74
25
|
# constructor.
|
75
26
|
class NoSplatConstructor < BuildError # :nodoc:
|
76
27
|
end
|
77
28
|
|
78
|
-
# Raised when the active JavaScript library does not support calls to
|
79
|
-
# +super+.
|
80
|
-
class NoSuperMethods < BuildError # :nodoc:
|
81
|
-
end
|
82
|
-
|
83
|
-
# Raised when a +Symbol+ literal declaration contains evaluated content.
|
84
|
-
class NoSymbolEvaluation < BuildError # :nodoc:
|
85
|
-
end
|
86
|
-
|
87
|
-
# Raised when an +undef+ keyword is used.
|
88
|
-
class NoUndef < BuildError # :nodoc:
|
89
|
-
end
|
90
|
-
|
91
29
|
# Raised when an unknown ParseTree sexp type is called to initialize.
|
92
30
|
class UnknownNode < BuildError # :nodoc:
|
93
31
|
end
|
data/lib/red/executable.rb
CHANGED
@@ -6,22 +6,20 @@ module Red # :nodoc:
|
|
6
6
|
self.make_plugin_directory('public/javascripts/red')
|
7
7
|
|
8
8
|
return unless display_message
|
9
|
-
puts @files
|
10
|
-
exit
|
9
|
+
puts @files && exit
|
11
10
|
end
|
12
11
|
|
13
|
-
def add_unobtrusive(library)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
rescue Errno::ENOENT
|
20
|
-
|
21
|
-
ensure
|
22
|
-
|
23
|
-
|
24
|
-
end
|
12
|
+
# def add_unobtrusive(library)
|
13
|
+
# @files ||= ''
|
14
|
+
# self.build_red_plugin_for_rails(false)
|
15
|
+
# self.create_plugin_file(:copy, 'public/javascripts/dom_ready.js', File.join(File.dirname(__FILE__), "../javascripts/#{(library || '').downcase}_dom_ready.js"))
|
16
|
+
# self.create_plugin_file(:copy, 'public/javascripts/red/unobtrusive.red', File.join(File.dirname(__FILE__), "../javascripts/red/unobtrusive.red"))
|
17
|
+
#
|
18
|
+
# rescue Errno::ENOENT
|
19
|
+
# puts "There is no Unobtrusive Red support for #{library}"
|
20
|
+
# ensure
|
21
|
+
# puts @files && exit
|
22
|
+
# end
|
25
23
|
|
26
24
|
def make_plugin_directory(dir, only_this_directory = false)
|
27
25
|
parent_dir = File.dirname(dir)
|
@@ -29,8 +27,7 @@ module Red # :nodoc:
|
|
29
27
|
directory_status = File.exists?(dir) ? 'exists' : Dir.mkdir(dir) && 'create'
|
30
28
|
@files << " %s %s\n" % [directory_status, dir]
|
31
29
|
rescue SystemCallError
|
32
|
-
puts "Unable to create directory in #{parent_dir}"
|
33
|
-
exit
|
30
|
+
puts "Unable to create directory in #{parent_dir}" && exit
|
34
31
|
end
|
35
32
|
|
36
33
|
def create_plugin_file(operation, filename, contents)
|
@@ -52,8 +49,7 @@ module Red # :nodoc:
|
|
52
49
|
end
|
53
50
|
|
54
51
|
def direct_translate(string)
|
55
|
-
|
56
|
-
print_js(js_output, 'test')
|
52
|
+
print_js(hush_warnings { string.translate_to_sexp_array }.red!)
|
57
53
|
exit
|
58
54
|
end
|
59
55
|
|
@@ -61,35 +57,41 @@ module Red # :nodoc:
|
|
61
57
|
$stderr = File.open('spew', 'w')
|
62
58
|
output = yield
|
63
59
|
$stderr = $>
|
64
|
-
|
65
60
|
File.delete('spew')
|
66
|
-
|
67
61
|
return output
|
68
62
|
end
|
69
63
|
|
70
|
-
def
|
71
|
-
puts RED_MESSAGES[:output] % [("- #{filename}.js" unless filename == 'test'), js_output, @@red_errors ||= '']
|
72
|
-
end
|
73
|
-
|
74
|
-
def compile_red_to_js(filename)
|
64
|
+
def convert_red_file_to_js(filename, dry_run = false)
|
75
65
|
unless File.exists?(file = "%s.red" % [filename]) || File.exists?(file = "%sred/%s.red" % [(dir = "public/javascripts/"), filename])
|
76
66
|
puts "File #{filename}.red does not exist."
|
77
67
|
exit
|
78
68
|
end
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
69
|
+
js_output = hush_warnings { File.read(file).translate_to_sexp_array }.red!
|
70
|
+
ruby_js = compile_ruby_js_source
|
71
|
+
File.open("%s%s.js" % [dir, filename], 'w') {|f| f.write(ruby_js + js_output)} unless dry_run
|
72
|
+
print_js(js_output, filename, dry_run)
|
73
|
+
end
|
74
|
+
|
75
|
+
def compile_ruby_js_source
|
76
|
+
cache_known_constants = @@red_constants
|
77
|
+
@@red_constants = []
|
78
|
+
@@red_import = true
|
79
|
+
ruby_js = hush_warnings { File.read(File.join(File.dirname(__FILE__), "../source/ruby.rb")).translate_to_sexp_array }.red!
|
80
|
+
@@red_constants = cache_known_constants
|
81
|
+
@@red_methods = INTERNAL_METHODS
|
82
|
+
@@red_import = false
|
83
|
+
return ruby_js
|
84
|
+
end
|
85
|
+
|
86
|
+
def print_js(js_output, filename = nil, dry_run = true) # :nodoc:
|
87
|
+
puts RED_MESSAGES[:output] % [("- #{filename}.js" unless dry_run), js_output]
|
86
88
|
end
|
87
89
|
|
88
90
|
RED_MESSAGES = {}
|
89
91
|
RED_MESSAGES[:banner] = <<-MESSAGE
|
90
92
|
|
91
93
|
Description:
|
92
|
-
Red
|
94
|
+
Red converts Ruby to JavaScript.
|
93
95
|
For more information see http://github.com/jessesielaff/red/wikis
|
94
96
|
|
95
97
|
Usage: red [filename] [options]
|
@@ -129,7 +131,6 @@ Use red -h for help.
|
|
129
131
|
%s
|
130
132
|
|
131
133
|
=================================
|
132
|
-
%s
|
133
134
|
|
134
135
|
MESSAGE
|
135
136
|
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module Red
|
2
|
+
class AssignmentNode < String # :nodoc:
|
3
|
+
class ClassVariable < AssignmentNode # :nodoc:
|
4
|
+
# [:cvdecl, :@@foo, {expression}] => inside eval portion of class declaration
|
5
|
+
# [:cvasgn, :@@foo, {expression}] => inside method definition
|
6
|
+
def initialize(variable_name_sexp, expression_sexp, options)
|
7
|
+
class_name = @@namespace_stack.join(".")
|
8
|
+
variable_name = variable_name_sexp.red!
|
9
|
+
expression = expression_sexp.red!(:as_argument => true)
|
10
|
+
self << "%s.cvset('%s',%s)" % [class_name, variable_name, expression]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Constant < AssignmentNode # :nodoc:
|
15
|
+
# [:cdecl, :Foo, {expression}]
|
16
|
+
def initialize(constant_name_sexp, expression_sexp, options)
|
17
|
+
constant_name = (@@namespace_stack + ["c$%s" % constant_name_sexp.red!]).join(".")
|
18
|
+
@@red_constants |= [constant_name]
|
19
|
+
expression = expression_sexp.red!(:as_assignment => true)
|
20
|
+
self << "%s=%s" % [constant_name, expression]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class GlobalVariable < AssignmentNode # :nodoc:
|
25
|
+
# [:gasgn, :$foo, {expression}]
|
26
|
+
def initialize(variable_name_sexp, expression_sexp, options)
|
27
|
+
variable_name = variable_name_sexp.red!
|
28
|
+
expression = expression_sexp.red!(:as_assignment => true)
|
29
|
+
self << "%s=%s" % [variable_name, expression]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class InstanceVariable < AssignmentNode # :nodoc:
|
34
|
+
# [:iasgn, :@foo, {expression}]
|
35
|
+
def initialize(variable_name_sexp, expression_sexp, options)
|
36
|
+
variable_name = variable_name_sexp.red!
|
37
|
+
expression = expression_sexp.red!(:as_assignment => true)
|
38
|
+
self << "this.i$%s=%s" % [variable_name, expression]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class LocalVariable < AssignmentNode # :nodoc:
|
43
|
+
# [:lasgn, :foo, {expression}]
|
44
|
+
# [:dasgn, :foo, {expression}] => previously defined inside a proc, but not the nearest proc
|
45
|
+
# [:dasgn_curr, :foo, {expression}] => local to the nearest proc
|
46
|
+
def initialize(variable_name_sexp, expression_sexp, options)
|
47
|
+
variable_name = variable_name_sexp.red!
|
48
|
+
expression = expression_sexp.red!(:as_assignment => true)
|
49
|
+
if options[:as_argument_default]
|
50
|
+
self << "%s=$T(_a=%s)?_a:%s" % [variable_name, variable_name, expression]
|
51
|
+
else
|
52
|
+
self << "%s=%s" % [variable_name, expression]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class Attribute < AssignmentNode # :nodoc:
|
58
|
+
# [:attrasgn, {expression}, :foo= | :[]=, [:array, {element}, {element}, ...]]
|
59
|
+
def initialize(receiver_sexp, writer_sexp, arguments_array_sexp, options)
|
60
|
+
receiver = receiver_sexp.red!(:as_receiver => true)
|
61
|
+
writer = (METHOD_ESCAPE[writer_sexp] || writer_sexp).red!
|
62
|
+
arguments = arguments_array_sexp[1..-1].map {|argument_sexp| argument_sexp.red!(:as_argument => true) }.join(",")
|
63
|
+
self << "%s.m$%s(%s)" % [receiver, writer, arguments]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class Multiple < AssignmentNode # :nodoc:
|
68
|
+
# [:masgn, [:array, {expression}, {expression} ...], [:to_ary, {expression}] | [:array, {expression}, {expression}, ...]]
|
69
|
+
def initialize(variables_array_sexp, assignments_array_sexp)
|
70
|
+
variables = variables_array_sexp[1..-1].map {|variable_sexp| variable_sexp.last.red! }
|
71
|
+
self << ""
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Operator < AssignmentNode # :nodoc:
|
76
|
+
class Bracket < Operator # :nodoc:
|
77
|
+
# [:op_asgn_1, {expression}, [:array, {element}, {element} ...], :+ | :* |..., {expression}] => from e.g. "foo[bar] ||= 1"
|
78
|
+
def initialize(receiver_sexp, arguments_array_sexp, method_sexp, expression_sexp, options)
|
79
|
+
receiver = receiver_sexp.red!(:as_receiver => true)
|
80
|
+
arguments = arguments_array_sexp[1..-1].map {|argument_sexp| argument_sexp.red!(:as_argument => true) }.join(",")
|
81
|
+
comma = arguments.empty? ? "" : ","
|
82
|
+
method = (METHOD_ESCAPE[method_sexp] || method_sexp).red!
|
83
|
+
expression = expression_sexp.red!(:as_argument => true)
|
84
|
+
object = "%s.m$_brkt(%s)" % [receiver, arguments]
|
85
|
+
unless string = ((method == '||' && LogicNode::Conjunction::Or::STRING) || (method == '&&' && LogicNode::Conjunction::And::STRING))
|
86
|
+
operation = "%s.m$%s(%s)" % [object, method, expression]
|
87
|
+
else
|
88
|
+
operation = string % [object, expression]
|
89
|
+
end
|
90
|
+
self << "%s.m$_breq(%s%s%s)" % [receiver, arguments, comma, operation]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Dot < Operator # :nodoc:
|
95
|
+
# [:op_asgn_2, {expression}, :foo=, :+ | :* |..., {expression}] => from e.g. "foo.bar ||= 1"
|
96
|
+
def initialize(receiver_sexp, writer_sexp, method_sexp, expression_sexp, options)
|
97
|
+
receiver = receiver_sexp.red!(:as_receiver => true)
|
98
|
+
reader = writer_sexp.to_s.gsub(/=/,'').to_sym.red!
|
99
|
+
writer = writer_sexp.red!
|
100
|
+
method = (METHOD_ESCAPE[method_sexp] || method_sexp).red!
|
101
|
+
expression = expression_sexp.red!(:as_argument => true)
|
102
|
+
object = "%s.m$%s()" % [receiver, reader]
|
103
|
+
unless string = ((method == '||' && LogicNode::Conjunction::Or::STRING) || (method == '&&' && LogicNode::Conjunction::And::STRING))
|
104
|
+
operation = "%s.m$%s(%s)" % [object, method, expression]
|
105
|
+
else
|
106
|
+
operation = string % [object, expression]
|
107
|
+
end
|
108
|
+
self << "%s.m$%s(%s)" % [receiver, writer, operation]
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class Or < Operator # :nodoc:
|
113
|
+
# [:op_asgn_or, {expression}, {expression}] => from e.g. "foo ||= 1"
|
114
|
+
def initialize(variable_name_sexp, assignment_sexp, options)
|
115
|
+
variable_name = variable_name_sexp.red!
|
116
|
+
expression = assignment_sexp.last.red!(:as_argument => true)
|
117
|
+
conjunction = LogicNode::Conjunction::Or::STRING % [variable_name, expression]
|
118
|
+
self << "%s=%s" % [variable_name, conjunction]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class And < Operator # :nodoc:
|
123
|
+
# [:op_asgn_and, {expression}, {expression}] => from e.g. "foo &&= 1"
|
124
|
+
def initialize(variable_name_sexp, assignment_sexp, options)
|
125
|
+
variable_name = variable_name_sexp.red!
|
126
|
+
expression = assignment_sexp.last.red!(:as_argument => true)
|
127
|
+
conjunction = LogicNode::Conjunction::And::STRING % [variable_name, expression]
|
128
|
+
self << "%s=%s" % [variable_name, conjunction]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Red
|
2
|
+
class CallNode < String # :nodoc:
|
3
|
+
class Ampersand < CallNode # :nodoc:
|
4
|
+
# [:block_pass, {expression}, {expression}]
|
5
|
+
def initialize(block_pass_sexp, function_call_sexp, options)
|
6
|
+
block_string = "%s.m$toProc()._block" % block_pass_sexp.red!(:as_receiver => true)
|
7
|
+
function_call = function_call_sexp.red!(options.merge(:block_string => block_string))
|
8
|
+
self << "%s" % [function_call]
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Block < CallNode # :nodoc:
|
13
|
+
# [:iter, {expression}, {0 | :dasgn_curr | :masgn, [:array, {:dasgn_curr, :dasgn_curr, ...}]}, (expression | :block)]
|
14
|
+
def initialize(function_call_sexp, block_arguments_array_sexp, block_body_sexp = nil, options = {})
|
15
|
+
(options = block_body_sexp) && (block_body_sexp = [:block, [:nil]]) if block_body_sexp.is_a?(::Hash)
|
16
|
+
block_arguments = block_arguments_array_sexp.is_sexp?(:masgn) ? block_arguments_array_sexp.assoc(:array)[1..-1].map {|dasgn_curr| dasgn_curr.last.red! }.join(",") : (block_arguments_array_sexp && block_arguments_array_sexp != 0 ? block_arguments_array_sexp.last : nil).red!
|
17
|
+
block_body = (block_body_sexp.is_sexp?(:block) ? block_body_sexp : [:block, block_body_sexp]).red!(:force_return => true)
|
18
|
+
block_string = "function(%s){%s;}" % [block_arguments, block_body]
|
19
|
+
block_string << ".m$(this)" unless [:instance_eval, :class_eval].include?(function_call_sexp.last)
|
20
|
+
function_call = function_call_sexp.red!(options.merge(:block_string => block_string))
|
21
|
+
self << "%s" % [function_call]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Defined < CallNode # :nodoc:
|
26
|
+
# [:defined, {expression}]
|
27
|
+
def initialize(expression_sexp, options)
|
28
|
+
expression = expression_sexp.red!(:as_argument => true)
|
29
|
+
self << "!(typeof(%s)=='undefined')" % [expression]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class Match # :nodoc:
|
34
|
+
# # [:match2, {expression}, {expression}] => when first expression is RegExp e.g. /foo/ =~ foo | /foo/ =~ /foo/
|
35
|
+
# def initialize(regex, expression)
|
36
|
+
# @regex, @expression = [regex, expression].build_nodes
|
37
|
+
# end
|
38
|
+
#
|
39
|
+
# def compile_node(options = {}) # :nodoc:
|
40
|
+
# regex = @regex.compile_node
|
41
|
+
# expression = @expression.compile_node(:as_argument => true)
|
42
|
+
# "%s.match(%s)" % [regex, expression]
|
43
|
+
# end
|
44
|
+
|
45
|
+
class Reverse < Match # :nodoc:
|
46
|
+
# # [:match3, {expression}, {expression}] => when only second expression is RegExp e.g. foo =~ /foo/
|
47
|
+
# def initialize(expression, regex)
|
48
|
+
# @regex, @expression = [regex, expression].build_nodes
|
49
|
+
# end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Method < CallNode # :nodoc:
|
54
|
+
class ExplicitReceiver < Method # :nodoc:
|
55
|
+
# [:call, {expression}, :foo, (:array, {expression}, {expression}, ...)]
|
56
|
+
def initialize(receiver_sexp, function_sexp, *arguments_array_sexp)
|
57
|
+
options = arguments_array_sexp.pop
|
58
|
+
receiver = receiver_sexp.red!(:as_receiver => true)
|
59
|
+
function = (METHOD_ESCAPE[function_sexp] || function_sexp).red!
|
60
|
+
args_array = arguments_array_sexp.last.is_sexp?(:array) ? arguments_array_sexp.last[1..-1].map {|argument_sexp| argument_sexp.red!(:as_argument => true)} : []
|
61
|
+
args_array += [options[:block_string]] if options[:block_string]
|
62
|
+
arguments = args_array.join(",")
|
63
|
+
self << "%s.m$%s(%s)" % [receiver, function, arguments]
|
64
|
+
@@red_methods |= [function_sexp] unless @@red_import
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class ImplicitReceiver < Method # :nodoc:
|
69
|
+
# [:fcall, :foo, (:array, {expression}, {expression}, ...)]
|
70
|
+
def initialize(function_sexp, *arguments_array_sexp)
|
71
|
+
options = arguments_array_sexp.pop
|
72
|
+
function = (METHOD_ESCAPE[function_sexp] || function_sexp).red!
|
73
|
+
args_array = arguments_array_sexp.last.is_sexp?(:array) ? arguments_array_sexp.last[1..-1].map {|argument_sexp| argument_sexp.red!(:as_argument => true)} : []
|
74
|
+
args_array += [options[:block_string]] if options[:block_string]
|
75
|
+
arguments = args_array.join(",")
|
76
|
+
case function_sexp
|
77
|
+
when :require
|
78
|
+
#cached_import_status = @@red_import
|
79
|
+
#@@red_import = true
|
80
|
+
self << hush_warnings { File.read((arguments_array_sexp.assoc(:array).assoc(:str).last rescue '')).translate_to_sexp_array }.red!
|
81
|
+
#@@red_import = cached_import_status
|
82
|
+
when :[]
|
83
|
+
self << "this.m$%s(%s)" % [function, arguments]
|
84
|
+
when :block_given?
|
85
|
+
self << "m$blockGivenBool(%s._block)" % @@red_block_arg
|
86
|
+
else
|
87
|
+
self << "(this.m$%s||m$%s).call(this,%s)" % [function, function, arguments]
|
88
|
+
@@red_methods |= [function_sexp] unless @@red_import
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Super < CallNode # :nodoc:
|
95
|
+
# [:super, (:array, {expression}, {expression}, ...)]
|
96
|
+
def initialize(*arguments_array_sexp)
|
97
|
+
options = arguments_array_sexp.pop
|
98
|
+
args_array = arguments_array_sexp.last.is_sexp?(:array) ? arguments_array_sexp.last[1..-1].map {|argument_sexp| argument_sexp.red!(:as_argument => true)} : []
|
99
|
+
args_array = ["this"] + args_array
|
100
|
+
args_array += [options[:block_string]] if options[:block_string]
|
101
|
+
arguments = args_array.join(",")
|
102
|
+
self << "this.m$class().m$superclass().prototype.m$%s.call(%s)" % [@@red_function, arguments]
|
103
|
+
end
|
104
|
+
|
105
|
+
class Delegate < Super # :nodoc:
|
106
|
+
# [:zsuper]
|
107
|
+
# FIX: Super::Delegate ignores block_string option when called inside an :iter e.g. super { foo }; this is an easy enough fix but annoying in that it needs fixing
|
108
|
+
def initialize(*arguments_array_sexp)
|
109
|
+
options = arguments_array_sexp.pop
|
110
|
+
self << "this.m$class().m$superclass().prototype.m$%s.apply(this,arguments)" % [@@red_function]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class Yield < CallNode # :nodoc:
|
116
|
+
# [:yield, (expression | :array, {expression}, {expression}, ...)]
|
117
|
+
def initialize(arguments_array_sexp = nil, options = {})
|
118
|
+
(options = arguments_array_sexp) && (arguments_array_sexp = [:array]) if arguments_array_sexp.is_a?(Hash)
|
119
|
+
argument_sexps = arguments_array_sexp.is_sexp?(:array) ? arguments_array_sexp[1..-1] || [] : [arguments_array_sexp]
|
120
|
+
args_array = argument_sexps.map {|argument_sexp| argument_sexp.red!(:as_argument => true)}
|
121
|
+
arguments = args_array.join(",")
|
122
|
+
self << "%s.m$call(%s)" % [@@red_block_arg, arguments]
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|