red 4.0.6 → 4.1.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/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
|