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.
@@ -0,0 +1,76 @@
1
+ module Red
2
+ class VariableNode < String # :nodoc:
3
+ class ClassVariable < VariableNode # :nodoc:
4
+ # [:cvar, :@@foo]
5
+ def initialize(variable_name_sexp, options)
6
+ class_name = @@namespace_stack.join('.')
7
+ variable_name = variable_name_sexp.red!
8
+ self << "%s.cvget('%s')" % [class_name, variable_name]
9
+ end
10
+ end
11
+
12
+ class Constant < VariableNode # :nodoc:
13
+ # ex.1: constant_name = 'Baz'
14
+ # @@namespace_stack = ['Foo', 'Bar']
15
+ # @@red_constants = ['Foo', 'Foo.Bar', 'Foo.Baz']
16
+ # 1st check: 'Foo.Bar.Baz' in @@red_constants
17
+ # 2nd check: 'Foo.Baz' in @@red_constants
18
+ # finds it & returns 'Foo.Baz'
19
+ #
20
+ # ex.2: constant_name = 'Qux'
21
+ # @@namespace_stack = ['Foo', 'Bar']
22
+ # @@red_constants = ['Foo', 'Foo.Bar', 'Foo.Baz']
23
+ # 1st check: 'Foo.Bar.Qux' in @@red_constants
24
+ # 2nd check: 'Foo.Qux' in @@red_constants
25
+ # 3rd check: 'Qux' in @@red_constants
26
+ # finds nothing & returns 'Foo.Bar.Qux'
27
+
28
+ # [:const, :Foo]
29
+ def initialize(constant_name_sexp, options)
30
+ constant_name = "c$%s" % constant_name_sexp.red!
31
+ locally_namespaced_constant = (@@namespace_stack + [constant_name]).join('.')
32
+ i = -1
33
+ begin
34
+ constant = (@@namespace_stack[0..i] + [constant_name]).join('.')
35
+ preexisting_constant_namespace = constant if @@red_constants.include?(constant)
36
+ i -= 1
37
+ end until preexisting_constant_namespace || @@namespace_stack.size + i < -1
38
+ self << "%s" % [(preexisting_constant_namespace || locally_namespaced_constant)]
39
+ end
40
+ end
41
+
42
+ class InstanceVariable < VariableNode # :nodoc:
43
+ # [:ivar, :@foo]
44
+ def initialize(variable_name_sexp, options)
45
+ variable_name = variable_name_sexp.red!
46
+ self << "this.i$%s" % [variable_name]
47
+ end
48
+ end
49
+
50
+ class Keyword < VariableNode # :nodoc:
51
+ # [:nil]
52
+ # [:self]
53
+ def initialize(options)
54
+ string = case self when Nil : "nil" when Self : "this" end
55
+ self << string
56
+ end
57
+
58
+ class Nil < Keyword # :nodoc:
59
+ end
60
+
61
+ class Self < Keyword # :nodoc:
62
+ end
63
+ end
64
+
65
+ class OtherVariable < VariableNode # :nodoc:
66
+ # [:dvar, :foo]
67
+ # [:gvar, :foo]
68
+ # [:lvar, :foo]
69
+ # [:vcall, :foo]
70
+ def initialize(variable_name_sexp, options)
71
+ variable_name = variable_name_sexp.red!
72
+ self << "%s" % [variable_name]
73
+ end
74
+ end
75
+ end
76
+ end
data/lib/red/plugin.rb CHANGED
@@ -6,10 +6,11 @@ module Red
6
6
 
7
7
  def update_javascripts
8
8
  @@red_updated = true
9
+ Red.init
9
10
  red_dir = 'public/javascripts/red/'
10
- Dir.glob("#{red_dir}**/*[.rb|.red]").each do |filepath|
11
- if self.update_javascripts?(filename = filepath.gsub(red_dir,'').gsub(/.[rb|red]+$/,'')) || RAILS_ENV != 'production'
12
- js_output = (File.read(filepath).string_to_node.compile_node || '') << (@@red_errors ||= '')
11
+ Dir.glob("#{red_dir}**/*.red").each do |filepath|
12
+ if self.update?(filename = filepath.gsub(red_dir,'').gsub(/.[rb|red]+$/,'')) || true
13
+ js_output = (File.read(filepath).translate_to_sexp_array.red! || '')
13
14
 
14
15
  filename.split('/')[0...-1].inject('public/javascripts') do |string,dir|
15
16
  new_dir = string << '/' << dir
@@ -18,13 +19,11 @@ module Red
18
19
  end
19
20
 
20
21
  File.open("public/javascripts/#{filename}.js", 'w') { |f| f.write(js_output) }
21
-
22
- @@red_errors = ''
23
22
  end
24
23
  end
25
24
  end
26
25
 
27
- def update_javascripts?(filename)
26
+ def update?(filename)
28
27
  if File.exists?("public/javascripts/#{filename}.js")
29
28
  (File.mtime("public/javascripts/red/#{filename}.red") rescue File.mtime("public/javascripts/red/#{filename}.rb")) > File.mtime("public/javascripts/#{filename}.js")
30
29
  else
@@ -38,7 +37,7 @@ module Red
38
37
  base.send('alias_method', :red_old_process, :process)
39
38
  base.class_eval do
40
39
  def process(*args)
41
- Red.update_javascripts unless Red.already_updated?
40
+ Red.update_javascripts #unless Red.already_updated?
42
41
  red_old_process(*args)
43
42
  end
44
43
  end
data/lib/red/version.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  module Red
2
2
  module VERSION #:nodoc:
3
- MAJOR = 3
4
- MINOR = 5
3
+ MAJOR = 4
4
+ MINOR = 0
5
5
  TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
data/lib/red.rb CHANGED
@@ -2,162 +2,240 @@ $:.unshift(File.dirname(__FILE__)) unless
2
2
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
3
 
4
4
  require 'parse_tree'
5
- require 'red/assignment_nodes'
6
- require 'red/call_nodes'
7
- require 'red/conditional_nodes'
8
- require 'red/conjunction_nodes'
9
- require 'red/constant_nodes'
10
- require 'red/control_nodes'
11
- require 'red/data_nodes'
12
- require 'red/definition_nodes'
13
5
  require 'red/errors'
14
- require 'red/illegal_nodes'
15
- require 'red/literal_nodes'
16
6
  require 'red/plugin'
17
- require 'red/variable_nodes'
18
- require 'red/wrap_nodes'
7
+ require 'red/nodes/assignment_nodes'
8
+ require 'red/nodes/call_nodes'
9
+ require 'red/nodes/control_nodes'
10
+ require 'red/nodes/data_nodes'
11
+ require 'red/nodes/definition_nodes'
12
+ require 'red/nodes/illegal_nodes'
13
+ require 'red/nodes/literal_nodes'
14
+ require 'red/nodes/logic_nodes'
15
+ require 'red/nodes/variable_nodes'
19
16
 
20
- module Red
21
- @@red_library = nil
22
- @@red_module = nil
23
- @@red_class = :window
24
- @@rescue_is_safe = false
25
- @@exception_index = 0
26
-
17
+ module Red # :nodoc:
27
18
  ARRAY_NODES = {
28
- :and => ConjunctionNode::AndNode,
29
- :argscat => IllegalNode::MultipleAssignmentNode,
30
- :argspush => IllegalNode::MultipleAssignmentNode,
31
- :array => LiteralNode::ArrayNode,
32
- :attrasgn => AssignmentNode::AttributeNode,
33
- :begin => ControlNode::BeginNode,
34
- :block => LiteralNode::MultilineNode,
35
- :block_arg => IllegalNode::BlockArgument,
36
- :block_pass => IllegalNode::BlockArgument,
37
- :break => ConstantNode::BreakNode,
38
- :call => CallNode::MethodNode::ExplicitNode,
39
- :case => ConditionalNode::CaseNode,
40
- :class => DefinitionNode::ClassNode,
41
- :cdecl => AssignmentNode::GlobalVariableNode,
42
- :colon2 => LiteralNode::NamespaceNode,
43
- :colon3 => ControlNode::LibraryNode,
44
- :const => VariableNode::OtherVariableNode,
45
- :cvar => VariableNode::ClassVariableNode,
46
- :cvasgn => AssignmentNode::ClassVariableNode,
47
- :cvdecl => AssignmentNode::ClassVariableNode,
48
- :dasgn => AssignmentNode::LocalVariableNode,
49
- :dasgn_curr => AssignmentNode::LocalVariableNode,
50
- :defined => WrapNode::DefinedNode,
51
- :defn => DefinitionNode::InstanceMethodNode,
52
- :defs => DefinitionNode::ClassMethodNode,
53
- :dot2 => LiteralNode::RangeNode,
54
- :dot3 => LiteralNode::RangeNode::ExclusiveNode,
55
- :dregx => IllegalNode::RegexEvaluationNode,
19
+ :and => LogicNode::Conjunction::And,
20
+ :alias => DefinitionNode::Alias,
21
+ #:argscat => IllegalNode::MultipleAssignmentNode,
22
+ #:argspush => IllegalNode::MultipleAssignmentNode,
23
+ :array => LiteralNode::Array,
24
+ :attrasgn => AssignmentNode::Attribute,
25
+ :begin => ControlNode::Begin,
26
+ :block => LiteralNode::Multiline,
27
+ :block_arg => CallNode::Block::Ampersand,
28
+ :block_pass => CallNode::Ampersand,
29
+ :break => ControlNode::Keyword::Break,
30
+ :call => CallNode::Method::ExplicitReceiver,
31
+ :case => LogicNode::Case,
32
+ :class => DefinitionNode::Class,
33
+ :cdecl => AssignmentNode::Constant,
34
+ :colon2 => LiteralNode::Namespace,
35
+ :colon3 => LiteralNode::Namespace::TopLevel,
36
+ :const => VariableNode::Constant,
37
+ :cvar => VariableNode::ClassVariable,
38
+ :cvasgn => AssignmentNode::ClassVariable,
39
+ :cvdecl => AssignmentNode::ClassVariable,
40
+ :dasgn => AssignmentNode::LocalVariable,
41
+ :dasgn_curr => AssignmentNode::LocalVariable,
42
+ :defined => CallNode::Defined,
43
+ :defn => DefinitionNode::Method::Instance,
44
+ :defs => DefinitionNode::Method::Singleton,
45
+ :dot2 => LiteralNode::Range,
46
+ :dot3 => LiteralNode::Range::Exclusive,
47
+ :dregx => LiteralNode::Regexp,
56
48
  :dregx_once => IllegalNode::RegexEvaluationNode,
57
- :dstr => LiteralNode::StringNode,
58
- :dsym => IllegalNode::SymbolEvaluationNode,
59
- :dvar => VariableNode::OtherVariableNode,
60
- :dxstr => LiteralNode::StringNode,
61
- :ensure => ControlNode::EnsureNode,
62
- :evstr => LiteralNode::StringNode,
63
- :false => ConstantNode::FalseNode,
64
- :fcall => CallNode::MethodNode::ImplicitNode,
49
+ :dstr => LiteralNode::String,
50
+ :dsym => LiteralNode::Symbol,
51
+ :dvar => VariableNode::OtherVariable,
52
+ :dxstr => LiteralNode::Uninterpreted,
53
+ :ensure => ControlNode::Ensure,
54
+ :evstr => LiteralNode::String,
55
+ :false => LogicNode::Boolean::False,
56
+ :fcall => CallNode::Method::ImplicitReceiver,
65
57
  :flip2 => IllegalNode::FlipflopNode,
66
58
  :flip3 => IllegalNode::FlipflopNode,
67
- :for => ControlNode::ForNode,
68
- :gasgn => AssignmentNode::GlobalVariableNode,
69
- :gvar => VariableNode::GlobalVariableNode,
70
- :hash => LiteralNode::HashNode,
71
- :iasgn => AssignmentNode::InstanceVariableNode,
72
- :if => ConditionalNode::IfNode,
73
- :iter => CallNode::BlockNode,
74
- :ivar => VariableNode::InstanceVariableNode,
75
- :lasgn => AssignmentNode::LocalVariableNode,
76
- :lvar => VariableNode::OtherVariableNode,
77
- :lit => LiteralNode::OtherNode,
59
+ :for => ControlNode::For,
60
+ :gasgn => AssignmentNode::GlobalVariable,
61
+ :gvar => VariableNode::OtherVariable,
62
+ :hash => LiteralNode::Hash,
63
+ :iasgn => AssignmentNode::InstanceVariable,
64
+ :if => LogicNode::If,
65
+ :iter => CallNode::Block,
66
+ :ivar => VariableNode::InstanceVariable,
67
+ :lasgn => AssignmentNode::LocalVariable,
68
+ :lvar => VariableNode::OtherVariable,
69
+ :lit => LiteralNode::Other,
78
70
  :match => IllegalNode::MatchNode,
79
- :match2 => CallNode::MatchNode,
80
- :match3 => CallNode::MatchNode::ReverseNode,
81
- :masgn => IllegalNode::MultipleAssignmentNode,
82
- :module => DefinitionNode::ModuleNode,
83
- :next => ConstantNode::NextNode,
84
- :nil => ConstantNode::NilNode,
85
- :not => WrapNode::NotNode,
86
- :op_asgn1 => AssignmentNode::OperatorNode::BracketNode,
87
- :op_asgn2 => AssignmentNode::OperatorNode::DotNode,
88
- :op_asgn_and => AssignmentNode::OperatorNode::AndNode,
89
- :op_asgn_or => AssignmentNode::OperatorNode::OrNode,
90
- :or => ConjunctionNode::OrNode,
71
+ :match2 => CallNode::Match,
72
+ :match3 => CallNode::Match::Reverse,
73
+ :masgn => AssignmentNode::Multiple,
74
+ :module => DefinitionNode::Module,
75
+ :next => ControlNode::Keyword::Next,
76
+ :nil => VariableNode::Keyword::Nil,
77
+ :not => LogicNode::Not,
78
+ :op_asgn1 => AssignmentNode::Operator::Bracket,
79
+ :op_asgn2 => AssignmentNode::Operator::Dot,
80
+ :op_asgn_and => AssignmentNode::Operator::And,
81
+ :op_asgn_or => AssignmentNode::Operator::Or,
82
+ :or => LogicNode::Conjunction::Or,
91
83
  :postexe => IllegalNode::PostexeNode,
92
- :redo => IllegalNode::RedoNode,
93
- :rescue => ControlNode::RescueNode,
84
+ :redo => ControlNode::Keyword::Redo,
85
+ :regex => LiteralNode::Regexp,
86
+ :resbody => ControlNode::RescueBody,
87
+ :rescue => ControlNode::Rescue,
94
88
  :retry => IllegalNode::RetryNode,
95
- :return => WrapNode::ReturnNode,
96
- :sclass => DefinitionNode::ObjectLiteralNode,
97
- :scope => LiteralNode::OtherNode,
98
- :self => ConstantNode::SelfNode,
99
- :splat => LiteralNode::SplatNode,
100
- :super => WrapNode::SuperNode,
101
- :svalue => LiteralNode::OtherNode,
102
- :str => LiteralNode::StringNode,
103
- :true => ConstantNode::TrueNode,
104
- :undef => IllegalNode::UndefNode,
105
- :until => ControlNode::UntilNode,
106
- :vcall => VariableNode::OtherVariableNode,
107
- :when => ConditionalNode::WhenNode,
108
- :while => ControlNode::WhileNode,
109
- :xstr => LiteralNode::StringNode,
110
- :yield => WrapNode::YieldNode,
111
- :zarray => LiteralNode::ArrayNode,
112
- :zsuper => WrapNode::SuperNode
89
+ :return => ControlNode::Return,
90
+ :sclass => DefinitionNode::SingletonClass,
91
+ :scope => DefinitionNode::Scope,
92
+ :self => VariableNode::Keyword::Self,
93
+ :splat => LiteralNode::Splat,
94
+ :super => CallNode::Super,
95
+ :svalue => LiteralNode::Other,
96
+ :str => LiteralNode::String,
97
+ :sym => LiteralNode::Symbol,
98
+ :to_ary => LiteralNode::Array,
99
+ :true => LogicNode::Boolean::True,
100
+ :undef => DefinitionNode::Undef,
101
+ :until => ControlNode::Loop::Until,
102
+ :vcall => VariableNode::OtherVariable,
103
+ :when => LogicNode::Case::When,
104
+ :while => ControlNode::Loop::While,
105
+ :xstr => LiteralNode::Uninterpreted,
106
+ :yield => CallNode::Yield,
107
+ :zarray => LiteralNode::Array,
108
+ :zsuper => CallNode::Super::Delegate
113
109
  }
114
110
 
115
111
  DATA_NODES = {
116
- Bignum => DataNode::OtherNode,
117
- Fixnum => DataNode::OtherNode,
118
- Float => DataNode::OtherNode,
119
- Range => DataNode::RangeNode,
120
- Regexp => DataNode::OtherNode,
121
- Symbol => DataNode::SymbolNode,
122
- String => DataNode::StringNode,
123
- NilClass => DataNode::NilNode
112
+ Bignum => DataNode::Numeric,
113
+ Fixnum => DataNode::Numeric,
114
+ Float => DataNode::Numeric,
115
+ Range => DataNode::Range,
116
+ Regexp => DataNode::Regexp,
117
+ Symbol => DataNode::Symbol,
118
+ String => DataNode::String,
119
+ NilClass => DataNode::Nil
120
+ }
121
+
122
+ METHOD_ESCAPE = {
123
+ :== => :_eql2,
124
+ :=== => :_eql3,
125
+ :=~ => :_etld,
126
+ :[] => :_brac,
127
+ :[]= => :_breq,
128
+ :<= => :_lteq,
129
+ :>= => :_gteq,
130
+ :<< => :_ltlt,
131
+ :>> => :_gtgt,
132
+ :< => :_lthn,
133
+ :> => :_gthn,
134
+ :'<=>' => :_ltgt,
135
+ :| => :_pipe,
136
+ :& => :_ampe,
137
+ :+ => :_plus,
138
+ :+@ => :_posi,
139
+ :- => :_subt,
140
+ :-@ => :_nega,
141
+ :* => :_star,
142
+ :** => :_str2,
143
+ :/ => :_slsh,
144
+ :% => :_perc,
145
+ :'^' => :_care,
146
+ :~ => :_tild
124
147
  }
125
148
 
126
- def build_node # :nodoc:
149
+ NATIVE_CONSTANTS = %w{
150
+ c$Object
151
+ c$Module
152
+ c$Class
153
+ c$Comparable
154
+ c$Enumerable
155
+ c$Kernel
156
+ c$Math
157
+ c$Math.c$E
158
+ c$Math.c$PI
159
+ c$Array
160
+ c$Exception
161
+ c$StandardError
162
+ c$ArgumentError
163
+ c$IndexError
164
+ c$RangeError
165
+ c$RuntimeError
166
+ c$TypeError
167
+ c$FalseClass
168
+ c$Hash
169
+ c$MatchData
170
+ c$NilClass
171
+ c$Numeric
172
+ c$Proc
173
+ c$Range
174
+ c$Regexp
175
+ c$Regexp.c$IGNORECASE
176
+ c$Regexp.c$EXTENDED
177
+ c$Regexp.c$MULTILINE
178
+ c$String
179
+ c$Symbol
180
+ c$Time
181
+ c$TrueClass
182
+ }
183
+
184
+ INTERNAL_METHODS = %w{
185
+ []
186
+ <=>
187
+ ==
188
+ allocate
189
+ append_features
190
+ backtrace
191
+ block_given?
192
+ call
193
+ class
194
+ extend_object
195
+ extended
196
+ hash
197
+ include
198
+ included
199
+ inherited
200
+ initialize
201
+ inspect
202
+ is_a?
203
+ join
204
+ new
205
+ sprintf
206
+ to_proc
207
+ to_s
208
+ to_str
209
+ }.map {|m| m.to_sym }
210
+
211
+ def self.init
212
+ @@namespace_stack = []
213
+ @@red_constants = NATIVE_CONSTANTS
214
+ @@red_methods = INTERNAL_METHODS
215
+ @@red_function = nil
216
+ @@red_block_arg = nil
217
+ @@red_import = false
218
+ return true
219
+ end
220
+
221
+ def red!(options = {}, reset = false)
222
+ Red.init if reset
127
223
  case self
128
224
  when Array
129
225
  raise(BuildError::UnknownNode, "Don't know how to handle sexp type :#{self.first}") unless ARRAY_NODES[self.first]
130
- return ARRAY_NODES[self.first].new(*self[1..-1])
226
+ return ARRAY_NODES[self.first].new(*(self[1..-1] + [options]))
131
227
  else
132
- return DATA_NODES[self.class].new(self)
228
+ return DATA_NODES[self.class].new(self, options)
133
229
  end
134
- rescue => e
135
- self.handle_red_error(e)
136
- end
137
-
138
- def build_nodes # :nodoc:
139
- self.map {|node| node.build_node}
140
- end
141
-
142
- def compile_nodes(options = {}) # :nodoc:
143
- self.map {|node| node.compile_node(options)}
144
- end
145
-
146
- def string_to_node # :nodoc:
147
- self.translate_to_sexp_array.build_node
148
- rescue SyntaxError => e
149
- self.handle_red_error(e)
150
230
  end
151
231
 
152
- def translate_to_sexp_array # :nodoc:
232
+ def translate_to_sexp_array
153
233
  raise TypeError, "Can only translate Strings" unless self.is_a?(String)
154
- ParseTree.translate("::Standard\n" + self)
234
+ ParseTree.translate(self)
155
235
  end
156
236
 
157
- def handle_red_error(error) # :nodoc:
158
- @@red_errors ||= "\n// Errors"
159
- @@red_errors << "\n// %s: %s" % [@@exception_index += 1, error]
160
- return DataNode::ErrorNode.new(@@exception_index)
237
+ def is_sexp?(*sexp_types)
238
+ self.is_a?(Array) && sexp_types.include?(self.first)
161
239
  end
162
240
 
163
241
  def self.rails