red 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,92 @@
1
+ module Red
2
+ class DataNode # :nodoc:
3
+ attr_reader :value
4
+
5
+ def initialize(value = nil)
6
+ @value = value
7
+ end
8
+
9
+ def compile_node(options = {})
10
+ return @value.inspect
11
+ end
12
+
13
+ def wrap_string(string, left_wrapper = "", right_wrapper = nil)
14
+ return "%s%s%s" % [left_wrapper, string, right_wrapper || left_wrapper]
15
+ end
16
+
17
+ class ErrorNode < DataNode # :nodoc:
18
+ def compile_node(options = {})
19
+ "_____ Error %s _____" % [@value]
20
+ end
21
+
22
+ def data_type
23
+ :error
24
+ end
25
+ end
26
+
27
+ class NilNode < DataNode # :nodoc:
28
+ def compile_node(options = {})
29
+ ""
30
+ end
31
+ end
32
+
33
+ class OtherNode < DataNode # :nodoc:
34
+ end
35
+
36
+ class RangeNode < DataNode # :nodoc:
37
+ def initialize(*args)
38
+ case @@red_library
39
+ when :Prototype : super(*args)
40
+ else raise(BuildError::NoRangeConstructor, "#{@@red_library} JavaScript library has no literal range constructor")
41
+ end
42
+ end
43
+
44
+ def compile_node(options = {})
45
+ case @@red_library
46
+ when :Prototype : return "$R(%s, %s%s)" % self.compile_internals
47
+ else return ""
48
+ end
49
+ end
50
+
51
+ def compile_internals(options = {})
52
+ exclusive = @value.exclude_end? ? ", true" : ""
53
+ return [@value.begin, @value.end, exclusive]
54
+ end
55
+ end
56
+
57
+ class StringNode < DataNode # :nodoc:
58
+ def compile_node(options = {})
59
+ options[:quotes] ||= "'"
60
+ return wrap_string(@value, options[:quotes])
61
+ end
62
+
63
+ def data_type
64
+ :string
65
+ end
66
+ end
67
+
68
+ class SymbolNode < DataNode # :nodoc:
69
+ def compile_node(options = {})
70
+ self.camelize!(options[:not_camelized])
71
+ return wrap_string(@value, options[:quotes])
72
+ end
73
+
74
+ def camelize!(disabled = false)
75
+ return @value = @value.to_s unless camelize? && !disabled
76
+ words = @value.to_s.gsub(/@|\$/,'').split(/_| /)
77
+ underscore = words.shift if words.first.empty?
78
+ @value = (underscore ? '_' : '') + words[0] + words[1..-1].map {|word| word.capitalize}.join
79
+ end
80
+
81
+ def camelize?
82
+ is_not_a_constant_name = @value.to_s != @value.to_s.upcase
83
+ is_not_a_js_special_attribute = @value.to_s[0..1] != '__'
84
+ return is_not_a_constant_name && is_not_a_js_special_attribute
85
+ end
86
+
87
+ def data_type
88
+ :symbol
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,142 @@
1
+ module Red
2
+ class DefinitionNode # :nodoc:
3
+ class ClassNode # :nodoc:
4
+ def initialize(class_name, superclass, scope)
5
+ raise(BuildError::NoClassInheritance, "Class inheritance is currently not supported#{"for the #{@@red_library} JavaScript library";''}") if superclass
6
+ old_class = @@red_class
7
+ @@red_class = @class = class_name
8
+ @class_name, @superclass = [class_name, superclass].build_nodes
9
+ block_node = scope.assoc(:block) || scope
10
+ if initializer_node = block_node.rassoc(:initialize)
11
+ args_node = initializer_node.assoc(:scope).assoc(:block).assoc(:args)
12
+ @arguments = (args_node[1..-1] || []).build_nodes
13
+ @initializer = initializer_node.assoc(:scope).assoc(:block).reject {|node| node == args_node}.build_node
14
+ end
15
+ properties = block_node.select {|node| (node.first == :cvdecl) rescue false }
16
+ functions = block_node.select {|node| (node != initializer_node) && ![:block, :scope].include?(node) }
17
+ @slots = (properties | functions).build_nodes
18
+ @@red_class = old_class
19
+ end
20
+
21
+ def compile_node(options = {})
22
+ old_class = @@red_class
23
+ @@red_class = @class
24
+ if @initializer
25
+ output = self.compile_as_standard_class
26
+ else
27
+ output = self.compile_as_virtual_class
28
+ end
29
+ @@red_class = old_class
30
+ return output
31
+ end
32
+
33
+ def compile_as_standard_class(options = {})
34
+ class_name = @class_name.compile_node
35
+ arguments = @arguments.compile_nodes.join(', ')
36
+ slots = @slots.compile_nodes(:as_attribute => true)
37
+ initializer = @initializer.compile_node
38
+ return "%s%s = function(%s) { %s;%s }" % [self.var?, class_name, arguments, initializer, slots]
39
+ end
40
+
41
+ def compile_as_virtual_class(options = {})
42
+ class_name = @class_name.compile_node
43
+ slots = @slots.compile_nodes(:as_prototype => true).compact.join(', ')
44
+ return "%s%s = { %s }" % [self.var?, class_name, slots]
45
+ end
46
+
47
+ def var?
48
+ return "var " unless @class_name.is_a?(LiteralNode::NamespaceNode)
49
+ end
50
+ end
51
+
52
+ class ClassMethodNode # :nodoc:
53
+ def initialize(receiver, function_name, scope)
54
+ @receiver, @function_name = [receiver, function_name].build_nodes
55
+ @arguments = (scope.assoc(:block).assoc(:args)[1..-1] || []).build_nodes
56
+ @lines = (scope.assoc(:block)[2..-1] || []).build_nodes
57
+ end
58
+
59
+ def compile_node(options = {})
60
+ case false
61
+ when options[:as_attribute].nil?
62
+ "this.%s = function(%s) { %s; }"
63
+ when options[:as_prototype].nil?
64
+ "%s: function(%s) { %s; }"
65
+ when !(options[:as_attribute].nil? && options[:as_prototype].nil?)
66
+ "function %s(%s) { %s; }"
67
+ end % self.compile_internals
68
+ end
69
+
70
+ def compile_internals(options = {})
71
+ function_name = @function_name.compile_node
72
+ arguments = @arguments.compile_nodes.join(', ')
73
+ lines = @lines.compile_nodes.compact.join('; ')
74
+ return [function_name, arguments, lines]
75
+ end
76
+ end
77
+
78
+ class InstanceMethodNode # :nodoc:
79
+ def initialize(function_name, scope)
80
+ block = scope.assoc(:block)
81
+ @@rescue_is_safe = (block[2].first == :rescue)
82
+ @function_name = (function_name == :function ? nil : function_name).build_node
83
+ @arguments = (block.assoc(:args)[1..-1] || []).build_nodes
84
+ @lines = (block[2..-1] || []).build_nodes
85
+ end
86
+
87
+ def compile_node(options = {})
88
+ case false
89
+ when options[:as_attribute].nil?
90
+ "this.%s = function(%s) { %s; }"
91
+ when options[:as_prototype].nil?
92
+ "%s: function(%s) { %s; }"
93
+ when !(options[:as_attribute].nil? && options[:as_prototype].nil?)
94
+ "function %s(%s) { %s; }"
95
+ end % self.compile_internals
96
+ end
97
+
98
+ def compile_internals(options = {})
99
+ function_name = @function_name.compile_node
100
+ arguments = @arguments.compile_nodes.join(', ')
101
+ lines = @lines.compile_nodes.compact.join('; ')
102
+ return [function_name, arguments, lines]
103
+ end
104
+ end
105
+
106
+ class ModuleNode # :nodoc:
107
+ def initialize(module_name, scope)
108
+ old_module = @@red_module
109
+ @@red_module = module_name
110
+ @module_name, @scope = [module_name, scope].build_nodes
111
+ @@red_module = old_module
112
+ end
113
+
114
+ def compile_node(options = {})
115
+ return "%s" % self.compile_internals
116
+ end
117
+
118
+ def compile_internals(options = {})
119
+ old_module = @@red_module
120
+ @@red_module = @module_name.compile_node
121
+ scope = @scope.compile_node
122
+ @@red_module = old_module
123
+ return [scope]
124
+ end
125
+ end
126
+
127
+
128
+ class ObjectLiteralNode # :nodoc:
129
+ def initialize(receiver, scope)
130
+ block_node = scope.assoc(:block) || scope
131
+ properties = block_node.select {|node| (node.first == :cvdecl) rescue false }
132
+ functions = block_node.select {|node| ![:block, :scope].include?(node) }
133
+ @slots = (properties | functions).build_nodes
134
+ end
135
+
136
+ def compile_node(options = {})
137
+ slots = @slots.compile_nodes(:as_prototype => true).compact.join(', ')
138
+ return "{ %s }" % [slots]
139
+ end
140
+ end
141
+ end
142
+ end
data/lib/red/errors.rb ADDED
@@ -0,0 +1,95 @@
1
+ module Red
2
+ class BuildError < StandardError # :nodoc:
3
+ # Raised when a hash is given a key other than a +String+ or +Symbol+
4
+ # object.
5
+ class NoArbitraryHashKeys < BuildError # :nodoc:
6
+ end
7
+
8
+ # Raised when a lone +Regex+ is used as a condition.
9
+ class NoArbitraryMatch < BuildError # :nodoc:
10
+ end
11
+
12
+ # Raised when a +rescue+ block is placed in a way that would produce a
13
+ # JavaScript syntax error.
14
+ class NoArbitraryRescue < BuildError # :nodoc:
15
+ end
16
+
17
+ # Raised when a +BEGIN+ or +END+ block is used.
18
+ class NoBEGINorEND < BuildError # :nodoc:
19
+ end
20
+
21
+ # Raised when a block is declared as a method argument.
22
+ class NoBlockArguments < BuildError # :nodoc:
23
+ end
24
+
25
+ # Raised when a +break+ keyword is followed by an argument.
26
+ class NoBreakArguments < BuildError # :nodoc:
27
+ end
28
+
29
+ # Raised when the active JavaScript library does not support class
30
+ # inheritance.
31
+ class NoClassInheritance < BuildError # :nodoc:
32
+ end
33
+
34
+ # Raised when the active JavaScript library does not support calls to
35
+ # class variables or declarations of class variables.
36
+ class NoClassVariables < BuildError # :nodoc:
37
+ end
38
+
39
+ # Raised when a +redo+ or +retry+ keyword is used.
40
+ class NoDoOvers < BuildError # :nodoc:
41
+ end
42
+
43
+ # Raised when a flipflop operator is called using <tt>..</tt> or
44
+ # <tt>...</tt>
45
+ class NoFlipflops < BuildError # :nodoc:
46
+ end
47
+
48
+ # Raised when a +begin+ block is used for multiline assignment.
49
+ class NoMultilineAssignment < BuildError # :nodoc:
50
+ end
51
+
52
+ # Raised when a comma-separated multiple assignment expression is used.
53
+ class NoMultipleAssignment < BuildError # :nodoc:
54
+ end
55
+
56
+ # Raised when a +break+ keyword is followed by an argument.
57
+ class NoNextArguments < BuildError # :nodoc:
58
+ end
59
+
60
+ # Raised when the active JavaScript library has no native literal range
61
+ # constructor.
62
+ class NoRangeConstructor < BuildError # :nodoc:
63
+ end
64
+
65
+ # Raised when a +Regex+ literal declaration contains evaluated content.
66
+ class NoRegexEvaluation < BuildError # :nodoc:
67
+ end
68
+
69
+ # Raised when an +Error+ class is passed to +rescue+.
70
+ class NoSpecificRescue < BuildError # :nodoc:
71
+ end
72
+
73
+ # Raised when the active JavaScript library has no special array
74
+ # constructor.
75
+ class NoSplatConstructor < BuildError # :nodoc:
76
+ end
77
+
78
+ # Raised when the active JavaScript library does not support calls to
79
+ # +super+.
80
+ class NoSuperMethods < BuildError # :nodoc:
81
+ end
82
+
83
+ # Raised when a +Symbol+ literal declaration contains evaluated content.
84
+ class NoSymbolEvaluation < BuildError # :nodoc:
85
+ end
86
+
87
+ # Raised when an +undef+ keyword is used.
88
+ class NoUndef < BuildError # :nodoc:
89
+ end
90
+
91
+ # Raised when an unknown ParseTree sexp type is called to initialize.
92
+ class UnknownNode < BuildError # :nodoc:
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,63 @@
1
+ module Red
2
+ class IllegalNode # :nodoc:
3
+ class BlockArgument < IllegalNode # :nodoc:
4
+ def initialize(*args)
5
+ raise(BuildError::NoBlockArguments, "JavaScript does not support block arguments")
6
+ end
7
+ end
8
+
9
+ class FlipflopNode < IllegalNode # :nodoc:
10
+ def initialize(*args)
11
+ raise(BuildError::NoFlipflops, "JavaScript does not support flip-flop operators")
12
+ end
13
+ end
14
+
15
+ class MatchNode < IllegalNode # :nodoc:
16
+ def initialize(*args)
17
+ raise(BuildError::NoArbitraryMatch, "JavaScript does not support arbitrary boolean matching")
18
+ end
19
+ end
20
+
21
+ class MultipleAssignmentNode < IllegalNode # :nodoc:
22
+ def initialize(*args)
23
+ raise(BuildError::NoMultipleAssignment, "JavaScript does not support catalogued assignment using multiple comma-separated expressions")
24
+ end
25
+ end
26
+
27
+ class PostexeNode < IllegalNode # :nodoc:
28
+ def initialize(*args)
29
+ raise(BuildError::NoBEGINorEND, "BEGIN and END blocks are not supported")
30
+ end
31
+ end
32
+
33
+ class RedoNode < IllegalNode # :nodoc:
34
+ def initialize(*args)
35
+ raise(BuildError::NoDoOvers, "JavaScript has no redo keyword")
36
+ end
37
+ end
38
+
39
+ class RegexEvaluationNode < IllegalNode # :nodoc:
40
+ def initialize(*args)
41
+ raise(BuildError::NoRegexEvaluation, "Construction of JavaScript regular expressions with evaluated content is not supported")
42
+ end
43
+ end
44
+
45
+ class RetryNode < IllegalNode # :nodoc:
46
+ def initialize(*args)
47
+ raise(BuildError::NoDoOvers, "JavaScript has no retry keyword")
48
+ end
49
+ end
50
+
51
+ class SymbolEvaluationNode < IllegalNode # :nodoc:
52
+ def initialize(*args)
53
+ raise(BuildError::NoSymbolEvaluation, "Construction of JavaScript identifiers through evaluated symbols is not supported")
54
+ end
55
+ end
56
+
57
+ class UndefNode < IllegalNode # :nodoc:
58
+ def initialize(*args)
59
+ raise(BuildError::NoUndef, "JavaScript does not support undefinition of methods")
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,119 @@
1
+ module Red
2
+ class LiteralNode # :nodoc:
3
+ def initialize(*elements)
4
+ @initial = elements.shift.build_node
5
+ @subsequent = elements.build_nodes
6
+ end
7
+
8
+ def compile_node(options = {})
9
+ content = @initial.compile_node(options)
10
+ return "%s" % [content]
11
+ end
12
+
13
+ def data_type
14
+ return :node unless @initial.is_a?(DataNode)
15
+ case @initial
16
+ when DataNode::NilNode : :nil
17
+ when DataNode::RangeNode : :range
18
+ when DataNode::StringNode : :string
19
+ when DataNode::SymbolNode : :symbol
20
+ else @initial.value.is_a?(Numeric) ? :numeric : :regexp
21
+ end
22
+ end
23
+
24
+ class ArrayNode < LiteralNode # :nodoc:
25
+ def compile_node(options = {})
26
+ elements = @subsequent.unshift(@initial).compile_nodes.join(', ')
27
+ return "[%s]" % [elements]
28
+ end
29
+ end
30
+
31
+ class HashNode < LiteralNode # :nodoc:
32
+ def initialize(*array)
33
+ @hash = {}
34
+ Hash[*array].each do |k,v|
35
+ key, value = [k,v].build_nodes
36
+ raise(BuildError::NoArbitraryHashKeys, "JavaScript does not support non-string objects as hash keys") unless [:string, :symbol].include?(key.data_type)
37
+ @hash[key] = value
38
+ end
39
+ end
40
+
41
+ def compile_node(options = {})
42
+ pairs = @hash.map { |k,v| "%s: %s" % [k.compile_node(:quotes => "'"), v.compile_node(:as_argument => true)] }.join(', ')
43
+ "{ %s }" % [pairs]
44
+ end
45
+ end
46
+
47
+ class MultilineNode < LiteralNode # :nodoc:
48
+ def compile_node(options = {})
49
+ lines = @subsequent.unshift(@initial).compile_nodes(options).compact.join('; ')
50
+ return "%s" % [lines]
51
+ end
52
+ end
53
+
54
+ class NamespaceNode < LiteralNode # :nodoc:
55
+ def compile_node(options = {})
56
+ namespaces = @initial.compile_node
57
+ class_name = @subsequent.first.compile_node
58
+ return "%s.%s" % [namespaces, class_name]
59
+ end
60
+ end
61
+
62
+ class OtherNode < LiteralNode # :nodoc:
63
+ end
64
+
65
+ class RangeNode < LiteralNode # :nodoc:
66
+ def initialize(*args)
67
+ case @@red_library
68
+ when :Prototype : super(*args)
69
+ else raise(BuildError::NoRangeConstructor, "#{@@red_library} JavaScript library has no literal range constructor")
70
+ end
71
+ end
72
+
73
+ def compile_node(options = {})
74
+ start = @initial.compile_node(:as_argument => true)
75
+ finish = @subsequent.first.compile_node(:as_argument => true)
76
+ case @@red_library
77
+ when :Prototype : return "$R(%s, %s)" % [start, finish]
78
+ else ""
79
+ end
80
+ end
81
+
82
+ class ExclusiveNode < RangeNode # :nodoc:
83
+ def compile_node(options = {})
84
+ start = @initial.compile_node(:as_argument => true)
85
+ finish = @subsequent.first.compile_node(:as_argument => true)
86
+ case @@red_library
87
+ when :Prototype : return "$R(%s, %s, true)" % [start, finish]
88
+ else ""
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ class SplatNode < LiteralNode # :nodoc:
95
+ def initialize(*args)
96
+ case @@red_library
97
+ when :Prototype : super(*args)
98
+ else raise(BuildError::NoSplatConstructor, "Splat array constructor not supported for #{@@red_library} JavaScript library")
99
+ end
100
+ end
101
+
102
+ def compile_node(options = {})
103
+ initial = @initial.compile_node
104
+ case @@red_library
105
+ when :Prototype : return "$A(%s)" % [initial]
106
+ else ""
107
+ end
108
+ end
109
+ end
110
+
111
+ class StringNode < LiteralNode # :nodoc:
112
+ def compile_node(options = {})
113
+ initial = @initial.compile_node(options)
114
+ subsequent = @subsequent.map {|element| " + %s" % [element.compile_node]}.join
115
+ return "%s%s" % [initial, subsequent]
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,37 @@
1
+ module Red
2
+ class VariableNode # :nodoc:
3
+ def initialize(variable_name)
4
+ @variable_name = variable_name.build_node
5
+ end
6
+
7
+ def compile_node(options = {})
8
+ return "%s" % self.compile_internals
9
+ end
10
+
11
+ def compile_internals(options = {})
12
+ return [@variable_name.compile_node]
13
+ end
14
+
15
+ class ClassVariableNode < VariableNode # :nodoc:
16
+ def compile_node(options = {})
17
+ return "%s.%s" % self.compile_internals
18
+ end
19
+
20
+ def compile_internals(options = {})
21
+ return [@@red_class, @variable_name.compile_node]
22
+ end
23
+ end
24
+
25
+ class InstanceVariableNode < VariableNode # :nodoc:
26
+ def compile_node(options = {})
27
+ return "this.%s" % self.compile_internals
28
+ end
29
+ end
30
+
31
+ class GlobalVariableNode < VariableNode # :nodoc:
32
+ end
33
+
34
+ class OtherVariableNode < VariableNode # :nodoc:
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,9 @@
1
+ module Red
2
+ module VERSION #:nodoc:
3
+ MAJOR = 3
4
+ MINOR = 0
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,51 @@
1
+ module Red
2
+ class WrapNode # :nodoc:
3
+ def initialize(expression = nil)
4
+ @expression = expression.build_node
5
+ end
6
+
7
+ def compile_internals(options = {})
8
+ return [@expression].compile_nodes(:as_argument => true)
9
+ end
10
+
11
+ class DefinedNode < WrapNode # :nodoc:
12
+ def compile_node(options = {})
13
+ return "typeof %s" % self.compile_internals
14
+ end
15
+ end
16
+
17
+ class NotNode < WrapNode # :nodoc:
18
+ def compile_node(options = {})
19
+ return "!(%s)" % self.compile_internals
20
+ end
21
+ end
22
+
23
+ class ReturnNode < WrapNode # :nodoc:
24
+ def compile_node(options = {})
25
+ return ("return %s" % self.compile_internals).rstrip
26
+ end
27
+ end
28
+
29
+ class SuperNode < WrapNode # :nodoc:
30
+ def initialize(args = [nil])
31
+ case @@red_library
32
+ when :Prototype : @args = args[1..-1].build_nodes
33
+ else raise(BuildError::NoSuperMethods, "Calls to super are not supported in #{@@red_library} JavaScript library")
34
+ end
35
+ end
36
+
37
+ def compile_node(options = {})
38
+ case @@red_library
39
+ when :Prototype : return "$super(%s)" % @args.compile_nodes(:as_argument => true).join(', ')
40
+ else return ""
41
+ end
42
+ end
43
+ end
44
+
45
+ class YieldNode < WrapNode # :nodoc:
46
+ def compile_node(options = {})
47
+ return ("yield %s" % self.compile_internals).rstrip
48
+ end
49
+ end
50
+ end
51
+ end