red 3.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,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