red 3.5.0 → 4.0.0
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/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
|