red 4.0.6 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest.txt CHANGED
@@ -27,9 +27,10 @@ script/destroy
27
27
  script/generate
28
28
  script/txt2html
29
29
  setup.rb
30
- spec/red_spec.rb
31
- spec/spec.opts
32
- spec/spec_helper.rb
30
+ spec/array.red
31
+ spec/hash.red
32
+ spec/object.red
33
+ spec/string.red
33
34
  tasks/deployment.rake
34
35
  tasks/environment.rake
35
36
  tasks/rspec.rake
data/bin/red CHANGED
@@ -15,6 +15,7 @@ include Red
15
15
  parser = OptionParser.new do |opts|
16
16
  opts.banner = RED_MESSAGES[:banner]
17
17
  opts.separator ""
18
+ opts.on('-d',"--debug","Translate Red files to JavaScript in debug mode.") { Red.instance_eval "def debug;true;end" }
18
19
  opts.on('-h',"--help","Show this help message.") { puts opts; exit }
19
20
  opts.on('-r',"--rails","Add Red plugin to ./vendor/plugins.") { build_red_plugin_for_rails }
20
21
  opts.on('-s',"--string=RUBY_STRING","Translate a single string to JavaScript.") { |string| Red.init && direct_translate(string) }
@@ -72,9 +72,12 @@ module Red # :nodoc:
72
72
  puts "File #{filename}.red does not exist."
73
73
  exit
74
74
  end
75
+ @@red_filepath = File.dirname(File.expand_path(filename))
75
76
  js_output = hush_warnings { File.read(file).translate_to_sexp_array }.red!
76
77
  ruby_js = compile_ruby_js_source
77
- File.open("%s%s.js" % [dir, filename], 'w') {|f| f.write(ruby_js + js_output)} unless dry_run
78
+ pre = Red.debug ? "try{" : ""
79
+ post = Red.debug ? "}catch(e){if(e.__class__){m$raise(e);};$ee=e;var m=e.message.match(/([^\\$]+)\\.m\\$(\\w+)\\sis\\snot\\sa\\sfunction/);if(m){m$raise(c$NoMethodError,$q('undefined method \"'+m[2]+'\" for '+m[1]));};var c=e.message.match(/([\\s\\S]+)\\sis\\sundefined/);if(c){c=c[1].replace(/\\./g,'::').replace(/c\\$/g,'');m$raise(c$NameError,$q('uninitialized constant '+c));};}" : ""
80
+ File.open("%s%s.js" % [dir, filename], 'w') {|f| f.write(pre + ruby_js + js_output + post)} unless dry_run
78
81
  print_js(js_output, filename, dry_run)
79
82
  end
80
83
 
@@ -46,8 +46,9 @@ module Red
46
46
  def initialize(variable_name_sexp, expression_sexp, options)
47
47
  variable_name = variable_name_sexp.red!
48
48
  expression = expression_sexp.red!(:as_assignment => true)
49
+ a = @@red_boolean.succ!.dup
49
50
  if options[:as_argument_default]
50
- self << "%s=$T(_a=%s)?_a:%s" % [variable_name, variable_name, expression]
51
+ self << "%s=$T($.%s=%s)?$.%s:%s" % [variable_name, a, variable_name, a, expression]
51
52
  else
52
53
  self << "%s=%s" % [variable_name, expression]
53
54
  end
@@ -82,7 +83,7 @@ module Red
82
83
  method = (METHOD_ESCAPE[method_sexp] || method_sexp).red!
83
84
  expression = expression_sexp.red!(:as_argument => true)
84
85
  object = "%s.m$_brac(%s)" % [receiver, arguments]
85
- unless string = ((method == '||' && LogicNode::Conjunction::Or::STRING) || (method == '&&' && LogicNode::Conjunction::And::STRING))
86
+ unless string = ((method == '||' && LogicNode::Conjunction::Or.string) || (method == '&&' && LogicNode::Conjunction::And.string))
86
87
  operation = "%s.m$%s(%s)" % [object, method, expression]
87
88
  else
88
89
  operation = string % [object, expression]
@@ -100,7 +101,7 @@ module Red
100
101
  method = (METHOD_ESCAPE[method_sexp] || method_sexp).red!
101
102
  expression = expression_sexp.red!(:as_argument => true)
102
103
  object = "%s.m$%s()" % [receiver, reader]
103
- unless string = ((method == '||' && LogicNode::Conjunction::Or::STRING) || (method == '&&' && LogicNode::Conjunction::And::STRING))
104
+ unless string = ((method == '||' && LogicNode::Conjunction::Or.string) || (method == '&&' && LogicNode::Conjunction::And.string))
104
105
  operation = "%s.m$%s(%s)" % [object, method, expression]
105
106
  else
106
107
  operation = string % [object, expression]
@@ -114,7 +115,7 @@ module Red
114
115
  def initialize(variable_name_sexp, assignment_sexp, options)
115
116
  variable_name = variable_name_sexp.red!
116
117
  expression = assignment_sexp.last.red!(:as_argument => true)
117
- conjunction = LogicNode::Conjunction::Or::STRING % [variable_name, expression]
118
+ conjunction = LogicNode::Conjunction::Or.string % [variable_name, expression]
118
119
  self << "%s=%s" % [variable_name, conjunction]
119
120
  end
120
121
  end
@@ -124,7 +125,7 @@ module Red
124
125
  def initialize(variable_name_sexp, assignment_sexp, options)
125
126
  variable_name = variable_name_sexp.red!
126
127
  expression = assignment_sexp.last.red!(:as_argument => true)
127
- conjunction = LogicNode::Conjunction::And::STRING % [variable_name, expression]
128
+ conjunction = LogicNode::Conjunction::And.string % [variable_name, expression]
128
129
  self << "%s=%s" % [variable_name, conjunction]
129
130
  end
130
131
  end
@@ -3,7 +3,7 @@ module Red
3
3
  class Ampersand < CallNode # :nodoc:
4
4
  # [:block_pass, {expression}, {expression}]
5
5
  def initialize(block_pass_sexp, function_call_sexp, options)
6
- block_string = "%s.m$toProc()._block" % block_pass_sexp.red!(:as_receiver => true)
6
+ block_string = "%s.m$to_proc().__block__" % block_pass_sexp.red!(:as_receiver => true)
7
7
  function_call = function_call_sexp.red!(options.merge(:block_string => block_string))
8
8
  self << "%s" % [function_call]
9
9
  end
@@ -79,17 +79,32 @@ module Red
79
79
  arguments = args_array.join(",")
80
80
  case function_sexp
81
81
  when :require
82
- #cached_import_status = @@red_import
83
- #@@red_import = true
84
- self << hush_warnings { File.read((arguments_array_sexp.assoc(:array).assoc(:str).last rescue '')).translate_to_sexp_array }.red!
85
- #@@red_import = cached_import_status
82
+ basename = File.basename((arguments_array_sexp.assoc(:array).assoc(:str).last rescue ''))
83
+ dirname = File.dirname((arguments_array_sexp.assoc(:array).assoc(:str).last rescue ''))
84
+ short_filename = File.join(@@red_filepath, basename)
85
+ long_filename = File.join(@@red_filepath, dirname, basename)
86
+ unless @@red_required.include?(basename)
87
+ @@red_required |= [basename]
88
+ file = Dir.glob(short_filename)[0] || Dir.glob('%s.red' % short_filename)[0] || Dir.glob('%s.rb' % short_filename)[0] || Dir.glob(long_filename)[0] || Dir.glob('%s.red' % long_filename)[0] || Dir.glob('%s.rb' % long_filename)[0] || Dir.glob('%s/../../source/redshift/%s' % [File.dirname(__FILE__),basename])[0] || Dir.glob('%s/../../source/redshift/%s.red' % [File.dirname(__FILE__),basename])[0]
89
+ stored_filepath = @@red_filepath
90
+ @@red_filepath = File.dirname(file)
91
+ self << hush_warnings { File.read(file).translate_to_sexp_array }.red!
92
+ @@red_filepath = stored_filepath
93
+ else
94
+ self << "false";
95
+ end
86
96
  when :[]
87
97
  self << "this.m$%s(%s)" % [function, arguments]
88
98
  when :block_given?
89
- self << "m$blockGivenBool(%s._block)" % @@red_block_arg
99
+ self << "m$block_given_bool(%s.__block__)" % (@@red_block_arg || 'nil')
90
100
  else
91
- arguments = ','+arguments unless arguments.empty?
92
- self << "(this.m$%s||m$%s).call(this%s)" % [function, function, arguments]
101
+ if Red.debug
102
+ error_function = arguments.empty? ? 'n' : 'm'
103
+ self << "((this.m$%s&&this.m$%s(%s))||(window.m$%s&&window.m%s(%s))||$%s(this,'%s'))" % [function,function,arguments,function,function,arguments,error_function,function_sexp]
104
+ else
105
+ arguments = ','+arguments unless arguments.empty?
106
+ self << "(this.m$%s||window.m$%s).call(this%s)" % [function, function, arguments]
107
+ end
93
108
  @@red_methods |= [function_sexp] unless @@red_import
94
109
  end
95
110
  end
@@ -62,15 +62,10 @@ module Red
62
62
  class For < ControlNode # :nodoc:
63
63
  # [:for, {expression}, {expression}, {expression | :block}]
64
64
  def initialize(source_sexp, iterator_assignment_sexp, body_sexp, options)
65
- body = body_sexp.red!
66
- unless source_sexp.is_sexp?(:xstr, :dxstr)
67
- source = source_sexp.red!(:as_argument => true)
68
- iterator = iterator_assignment_sexp.last.red!
69
- self << "for(var %s in %s){%s;}" % [iterator, source, body]
70
- else
71
- loop_statement = source_sexp.red!
72
- self << "for(%s){%s;}" % [loop_statement, body]
73
- end
65
+ iterator = iterator_assignment_sexp.last.red!
66
+ source = source_sexp.red!(:as_receiver => true)
67
+ body = body_sexp.red!
68
+ self << "%s.m$each(function(%s){%s;}.m$(this))" % [source, iterator, body]
74
69
  end
75
70
  end
76
71
 
@@ -44,7 +44,8 @@ module Red
44
44
  class String < DataNode # :nodoc:
45
45
  # 'foo'
46
46
  def initialize(value_data, options)
47
- value = options[:no_escape] ? value_data : value_data.gsub(/'/, "\\\\'")
47
+ # value = options[:no_escape] ? value_data : value_data.gsub(/"/, '\\"')
48
+ value = value_data
48
49
  string = options[:unquoted] ? "%s" % [value] : "%s" % [value.inspect]
49
50
  self << string
50
51
  end
@@ -54,15 +55,16 @@ module Red
54
55
  # :foo
55
56
  def initialize(value_data, options)
56
57
  value = self.camelize(value_data.to_s, options[:not_camelized])
57
- string = options[:as_receiver] ? "$q('%s')" : options[:as_argument] ? "'%s'" : "%s"
58
+ string = options[:as_receiver] ? "$q(\"%s\")" : options[:as_argument] ? "\"%s\"" : "%s"
58
59
  self << string % [value]
59
60
  end
60
61
 
61
62
  def camelize(string, disabled = false)
62
- return string unless self.camelize?(string) && !disabled
63
- words = string.gsub(/@/,'').gsub('?','_bool').gsub('!','_bang').gsub('=','_eql').split(/_/)
64
- underscore = words.shift if words.first.empty?
65
- return (underscore ? '_' : '') + words[0] + words[1..-1].map {|word| word == word.upcase ? word : word.capitalize }.join
63
+ return string.gsub(/@/,'').gsub('?','_bool').gsub('!','_bang').gsub('=','_eql')
64
+ # return string unless self.camelize?(string) && !disabled
65
+ # words = string.gsub(/@/,'').gsub('?','_bool').gsub('!','_bang').gsub('=','_eql').split(/_/)
66
+ # underscore = words.shift if words.first.empty?
67
+ # return (underscore ? '_' : '') + words[0] + words[1..-1].map {|word| word == word.upcase ? word : word.capitalize }.join
66
68
  end
67
69
 
68
70
  def camelize?(string)
@@ -95,12 +95,16 @@ module Red
95
95
  splat_arg = argument_sexps.pop.to_s[1..-1] if argument_sexps.last && argument_sexps.last.to_s.include?('*')
96
96
  argument_sexps += [block_arg_sexp.last] if block_arg_sexp
97
97
  args_array = argument_sexps.map {|argument| argument.red! }
98
- splatten_args = "for(var bg=m$blockGivenBool(arguments[arguments.length-1]),l=bg?arguments.length-1:arguments.length,i=#{block_arg_sexp ? argument_sexps.size - 1 : argument_sexps.size},#{splat_arg}=[];i<l;++i){#{splat_arg}.push(arguments[i]);};var #{block_arg_sexp.last rescue :_block}=(bg?c$Proc.m$new(arguments[arguments.length-1]):nil)" if splat_arg
99
- block_arg = "var #{block_arg_sexp.last rescue :_block}=(m$blockGivenBool(arguments[arguments.length-1])?c$Proc.m$new(arguments[arguments.length-1]):nil)" if block_arg_sexp && !splat_arg
98
+ maximum_args = args_array.length - (block_arg_sexp ? 1 : 0)
99
+ minimum_args = maximum_args - (defaults_sexp ? defaults_sexp.flatten.select {|x| x == :lasgn}.length : 0)
100
+ splatten_args = "for(var l=arguments.length,i=#{argument_sexps.size},#{splat_arg}=[];i<l;++i){#{splat_arg}.push(arguments[i]);}" if splat_arg && !block_arg_sexp
101
+ splat_block = "for(var l=arguments.length,bg=m$block_given_bool(arguments[l-1]),l=bg?l-1:l,i=#{argument_sexps.size - 1},#{splat_arg}=[];i<l;++i){#{splat_arg}.push(arguments[i]);};var #{block_arg_sexp.last rescue :_block}=(bg?c$Proc.m$new(arguments[arguments.length-1]):nil)" if splat_arg && block_arg_sexp
102
+ block_arg = "var z=arguments[arguments.length-1],bg=m$block_given_bool(z),#{block_arg_sexp.last rescue :_block}=bg?c$Proc.m$new(z):nil" if block_arg_sexp && !splat_arg
103
+ args_checker = "$a(%s,%s,arguments,%s)" % [minimum_args, (splat_arg ? -1 : maximum_args), (splat_block || block_arg ? "bg?1:0" : "arguments[arguments.length-1]&&arguments[arguments.length-1].__block__?1:0")] if Red.debug && ![:new, :initialize].include?(function_name_sexp)
100
104
  defaults = defaults_sexp.red!(:as_argument_default => true) if defaults_sexp
101
105
  arguments = args_array.join(",")
102
106
  scope = scope_sexp.red!(:force_return => function != 'initialize')
103
- contents = [splatten_args, block_arg, defaults, scope].compact.join(";")
107
+ contents = [(splatten_args || splat_block || block_arg), args_checker, defaults, scope].compact.join(";")
104
108
  if options[:as_class_eval]
105
109
  string = "_.m$%s=function(%s){%s;}"
106
110
  else
@@ -130,12 +134,16 @@ module Red
130
134
  splat_arg = argument_sexps.pop.to_s[1..-1] if argument_sexps.last && argument_sexps.last.to_s.include?('*')
131
135
  argument_sexps += [block_arg_sexp.last] if block_arg_sexp
132
136
  args_array = argument_sexps.map {|argument| argument.red! }
133
- splatten_args = "for(var bg=m$blockGivenBool(arguments[arguments.length-1]),l=bg?arguments.length-1:arguments.length,i=#{block_arg_sexp ? argument_sexps.size - 1 : argument_sexps.size},#{splat_arg}=[];i<l;++i){#{splat_arg}.push(arguments[i]);};var #{block_arg_sexp.last rescue :_block}=(bg?c$Proc.m$new(arguments[arguments.length-1]):nil)" if splat_arg
134
- block_arg = "var #{block_arg_sexp.last rescue :_block}=(m$blockGivenBool(arguments[arguments.length-1])?c$Proc.m$new(arguments[arguments.length-1]):nil)" if block_arg_sexp && !splat_arg
137
+ maximum_args = args_array.length - (block_arg_sexp ? 1 : 0)
138
+ minimum_args = maximum_args - (defaults_sexp ? defaults_sexp.flatten.select {|x| x == :lasgn}.length : 0)
139
+ splatten_args = "for(var l=arguments.length,i=#{argument_sexps.size},#{splat_arg}=[];i<l;++i){#{splat_arg}.push(arguments[i]);}" if splat_arg && !block_arg_sexp
140
+ splat_block = "for(var l=arguments.length,bg=m$block_given_bool(arguments[l-1]),l=bg?l-1:l,i=#{argument_sexps.size - 1},#{splat_arg}=[];i<l;++i){#{splat_arg}.push(arguments[i]);};var #{block_arg_sexp.last rescue :_block}=(bg?c$Proc.m$new(arguments[arguments.length-1]):nil)" if splat_arg && block_arg_sexp
141
+ block_arg = "var z=arguments[arguments.length-1],bg=m$block_given_bool(z),#{block_arg_sexp.last rescue :_block}=bg?c$Proc.m$new(z):nil" if block_arg_sexp && !splat_arg
142
+ args_checker = "$a(%s,%s,arguments,%s)" % [minimum_args, (splat_arg ? -1 : maximum_args), (splat_block || block_arg ? "bg?1:0" : 0)]#{}"arguments[arguments.length-1]&&arguments[arguments.length-1].__block__?1:0")]
135
143
  defaults = defaults_sexp.red!(:as_argument_default => true) if defaults_sexp
136
144
  arguments = args_array.join(",")
137
145
  scope = scope_sexp.red!(:force_return => function != 'initialize')
138
- contents = [splatten_args, block_arg, defaults, scope].compact.join(";")
146
+ contents = [(splatten_args || splat_block || block_arg), args_checker, defaults, scope].compact.join(";")
139
147
  self << "%s=function(%s){%s;}" % [singleton, arguments, contents]
140
148
  @@red_block_arg = nil
141
149
  @@red_function = nil
@@ -28,7 +28,7 @@ module Red
28
28
  # as_argument: duplicates :force_return and adds "function() {
29
29
  # <multiline block>; }()" wrapper to the entire block.
30
30
  options = expression_sexps.pop
31
- if options[:as_argument] || options[:as_assignment] || options[:force_return] && expression_sexps.last.is_a?(::Array) && !expression_sexps.last.is_sexp?(:rescue, :ensure, :begin) && (expression_sexps.last.first == :iter ? true : !expression_sexps.last.flatten.include?(:return))
31
+ if options[:as_argument] || options[:as_assignment] || options.delete(:force_return) && expression_sexps.last.is_a?(::Array) && !expression_sexps.last.is_sexp?(:rescue, :ensure, :begin) && (expression_sexps.last.first == :iter ? true : !expression_sexps.last.flatten.include?(:return))
32
32
  returner = "return %s" % [expression_sexps.pop.red!(:as_argument => true)]
33
33
  end
34
34
  string = options[:as_argument] || options[:as_assignment] ? "function(){%s;}.m$(this)()" : "%s"
@@ -46,11 +46,14 @@ module Red
46
46
  def initialize(expression_a_sexp, expression_b_sexp, options)
47
47
  a = expression_a_sexp.red!(:as_argument => true)
48
48
  b = expression_b_sexp.red!(:as_argument => true)
49
- d = @@red_boolean.succ!.dup
50
- e = @@red_boolean.succ!.dup
51
- f = @@red_boolean.succ!.dup
52
- string = "($.%s=$T(%s)?($.%s=$T($.%s=%s)?$.%s:$.%s):$.%s)" % [d, '%s', f, e, '%s', e, f, d]
53
- self << string % [a,b]
49
+ self << self.class.string % [a, b]
50
+ end
51
+
52
+ def self.string # :nodoc:
53
+ a = @@red_boolean.succ!.dup
54
+ b = @@red_boolean.succ!.dup
55
+ c = @@red_boolean.succ!.dup
56
+ "(($.%s=$T(%s))?(($.%s=$T($.%s=%s))?$.%s:$.%s):$.%s)" % [a, '%s', c, b, '%s', b, c, a]
54
57
  end
55
58
  end
56
59
 
@@ -59,9 +62,12 @@ module Red
59
62
  def initialize(expression_a_sexp, expression_b_sexp, options)
60
63
  a = expression_a_sexp.red!(:as_argument => true)
61
64
  b = expression_b_sexp.red!(:as_argument => true)
62
- c = @@red_boolean.succ!.dup
63
- string = "($T($.%s=%s)?$.%s:%s)" % [c, '%s', c, '%s']
64
- self << string % [a,b]
65
+ self << self.class.string % [a, b]
66
+ end
67
+
68
+ def self.string
69
+ a = @@red_boolean.succ!.dup
70
+ "($T($.%s=%s)?$.%s:%s)" % [a, '%s', a, '%s']
65
71
  end
66
72
  end
67
73
  end
data/lib/red/version.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Red
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 4
4
- MINOR = 0
5
- TINY = 6
4
+ MINOR = 1
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/lib/red.rb CHANGED
@@ -193,6 +193,7 @@ module Red # :nodoc:
193
193
  block_given?
194
194
  call
195
195
  class
196
+ each
196
197
  extend_object
197
198
  extended
198
199
  hash
@@ -206,12 +207,14 @@ module Red # :nodoc:
206
207
  new
207
208
  raise
208
209
  sprintf
210
+ superclass
209
211
  to_proc
210
212
  to_s
211
213
  to_str
212
214
  }.map {|m| m.to_sym }
213
215
 
214
- def self.init
216
+ def self.init(file = '')
217
+ @@red_filepath = File.dirname(File.expand_path(file))
215
218
  @@namespace_stack = []
216
219
  @@red_constants = NATIVE_CONSTANTS
217
220
  @@red_methods = INTERNAL_METHODS
@@ -219,10 +222,15 @@ module Red # :nodoc:
219
222
  @@red_singleton = nil
220
223
  @@red_block_arg = nil
221
224
  @@red_import = false
222
- @@red_boolean = 'a'
225
+ @@red_boolean = '`'
226
+ @@red_required = []
223
227
  return true
224
228
  end
225
229
 
230
+ def self.debug
231
+ false
232
+ end
233
+
226
234
  def red!(options = {}, reset = false)
227
235
  case self
228
236
  when Array