red 3.5.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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