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 CHANGED
@@ -1,3 +1,7 @@
1
+ == 4.0.0 2008-10-12
2
+
3
+ * New version released.
4
+
1
5
  == 3.5.0 2008-08-13
2
6
 
3
7
  * 2 major enhancements:
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/wrap_nodes.rb
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
- = Turn your JavaScript <span style="color:rgb(195,0,0)">Red</span>.
1
+ = Write Ruby. Run JavaScript. The new Red is here.
2
2
 
3
- <span style="color:rgb(195,0,0)">Red</span> is a Ruby-to-JavaScript transliterator built on <a href=http://rubyforge.org/projects/parsetree/>ParseTree</a>.
3
+ Red takes the Ruby you write and turns it into JavaScript for your browser.
4
4
 
5
- === Installation
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
- === Previewing your JavaScript output
7
+ What does this mean for today’s Ruby developer? Simple. You don’t need to learn JavaScript.
32
8
 
33
- If you want to see what JavaScript a snippet of Ruby code will produce without creating a <tt>.js</tt> file, use the special filename <tt>test.red</tt>.
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
- === Documentation
11
+ To get Red working, install the rubygem.
55
12
 
56
- The <a href=http://red-js.rubyforge.org/red/rdoc/>documentation</a> is currently rather nonexistent.
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 transliterator executable.
2
+ # Red's command line Ruby-to-JS conversion executable.
3
3
  #
4
4
  # Copyright (c) 2008 Jesse Sielaff.
5
5
 
6
- begin
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("-h", "--help", "Show this help message.") { puts opts; exit }
24
- opts.on("-r", "--rails", "Add Red plugin to ./vendor/plugins.") { build_red_plugin_for_rails }
25
- opts.on("-s", "--string=RUBY_STRING", "Translate a single string to JavaScript.") { |string| direct_translate(string) }
26
- opts.on("-u", "--unobtrusive [LIBRARY]", "Add support for unobtrusive JavaScript to your Rails project.") { |library| add_unobtrusive(library) }
27
- opts.on("-v", "--version", "Print version number.") { puts Red::VERSION::STRING; exit }
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
- if ARGV.empty?
38
- puts RED_MESSAGES[:usage]; exit
39
- else
40
- class << Red
41
- self.compile_red_to_js(ARGV[0])
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 is a Ruby-to-JavaScript transliterator using ParseTree."
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 = ['--quiet', '--title', 'red documentation',
40
- "--opname", "index.html",
41
- "--line-numbers",
42
- "--main", "README",
43
- "--inline-source"]
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 block is declared as a method argument.
22
- class NoBlockArguments < BuildError # :nodoc:
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
@@ -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
- @files ||= ''
15
- self.build_red_plugin_for_rails(false)
16
- self.create_plugin_file(:copy, 'public/javascripts/dom_ready.js', File.join(File.dirname(__FILE__), "../javascripts/#{(library || '').downcase}_dom_ready.js"))
17
- self.create_plugin_file(:copy, 'public/javascripts/red/unobtrusive.red', File.join(File.dirname(__FILE__), "../javascripts/red/unobtrusive.red"))
18
-
19
- rescue Errno::ENOENT
20
- puts "There is no Unobtrusive Red support for #{library}"
21
- ensure
22
- puts @files
23
- exit
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
- js_output = hush_warnings { string.string_to_node }.compile_node
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 print_js(js_output, filename) # :nodoc:
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
- source = File.read(file)
81
- js_output = hush_warnings { source.string_to_node }.compile_node
82
-
83
- File.open("%s%s.js" % [dir, filename], 'w') {|f| f.write(js_output)} unless filename == 'test'
84
-
85
- print_js(js_output, filename)
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 is a Ruby-to-JavaScript transliterator.
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