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 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