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 +4 -3
- data/bin/red +1 -0
- data/lib/red/executable.rb +4 -1
- data/lib/red/nodes/assignment_nodes.rb +6 -5
- data/lib/red/nodes/call_nodes.rb +23 -8
- data/lib/red/nodes/control_nodes.rb +4 -9
- data/lib/red/nodes/data_nodes.rb +8 -6
- data/lib/red/nodes/definition_nodes.rb +14 -6
- data/lib/red/nodes/literal_nodes.rb +1 -1
- data/lib/red/nodes/logic_nodes.rb +14 -8
- data/lib/red/version.rb +2 -2
- data/lib/red.rb +10 -2
- data/lib/source/ruby.rb +387 -334
- data/spec/array.red +389 -0
- data/spec/hash.red +137 -0
- data/spec/object.red +22 -0
- data/spec/string.red +74 -0
- metadata +7 -6
- data/spec/red_spec.rb +0 -10
- data/spec/spec.opts +0 -1
- data/spec/spec_helper.rb +0 -10
data/Manifest.txt
CHANGED
@@ -27,9 +27,10 @@ script/destroy
|
|
27
27
|
script/generate
|
28
28
|
script/txt2html
|
29
29
|
setup.rb
|
30
|
-
spec/
|
31
|
-
spec/
|
32
|
-
spec/
|
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) }
|
data/lib/red/executable.rb
CHANGED
@@ -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
|
-
|
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(
|
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
|
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
|
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
|
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
|
128
|
+
conjunction = LogicNode::Conjunction::And.string % [variable_name, expression]
|
128
129
|
self << "%s=%s" % [variable_name, conjunction]
|
129
130
|
end
|
130
131
|
end
|
data/lib/red/nodes/call_nodes.rb
CHANGED
@@ -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$
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
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$
|
99
|
+
self << "m$block_given_bool(%s.__block__)" % (@@red_block_arg || 'nil')
|
90
100
|
else
|
91
|
-
|
92
|
-
|
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
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
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
|
|
data/lib/red/nodes/data_nodes.rb
CHANGED
@@ -44,7 +44,8 @@ module Red
|
|
44
44
|
class String < DataNode # :nodoc:
|
45
45
|
# 'foo'
|
46
46
|
def initialize(value_data, options)
|
47
|
-
|
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(
|
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
|
63
|
-
|
64
|
-
|
65
|
-
|
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
|
-
|
99
|
-
|
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
|
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
|
-
|
134
|
-
|
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
|
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
|
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
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
63
|
-
|
64
|
-
|
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
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 = '
|
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
|