taipo 1.3.0 → 1.4.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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/taipo.rb +0 -86
- data/lib/taipo/cache.rb +2 -1
- data/lib/taipo/check.rb +9 -7
- data/lib/taipo/parser.rb +292 -153
- data/lib/taipo/parser/stack.rb +143 -0
- data/lib/taipo/parser/syntax_state.rb +12 -11
- data/lib/taipo/parser/validater.rb +126 -58
- data/lib/taipo/refinements.rb +30 -0
- data/lib/taipo/type_element.rb +50 -68
- data/lib/taipo/type_element/children.rb +47 -0
- data/lib/taipo/type_element/constraint.rb +11 -15
- data/lib/taipo/type_element/constraints.rb +36 -0
- data/lib/taipo/type_elements.rb +33 -0
- data/lib/taipo/utilities.rb +81 -0
- data/lib/taipo/version.rb +1 -1
- metadata +8 -3
- data/lib/taipo/type_element/child_type.rb +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb7fcacea028acafa7344ccfc04fbc3c66e50c13
|
4
|
+
data.tar.gz: 052b196e3ed53b4ade6d95abee2b57a266c12a9f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6cced24c850830e10102f010b0b098ff5ed7ebab426f10cee4b51dcdf1ff29622721e75228b9fc4be9f6fa35b8e4917e14961254a4dbfddb0b8110969aad3b0a
|
7
|
+
data.tar.gz: 4e9bd2e042ef2f87808bbdab7c10657d96f75bb969aa725e0b02666e4160a433eb3279b601c232c87f4fce37163b23204d504a31a8307ee0649b7846ff510de4
|
data/README.md
CHANGED
@@ -91,7 +91,7 @@ The information in this README is only meant as an introduction. [More informati
|
|
91
91
|
The simplest case is to write the name of a class. For example, `'String'`. Inherited class names can also be used.
|
92
92
|
|
93
93
|
```ruby
|
94
|
-
check types, a: 'String', b: 'Numeric'
|
94
|
+
check types, a: 'String', b: 'Numeric', c: 'Foo::Bar'
|
95
95
|
```
|
96
96
|
|
97
97
|
#### Duck Types
|
data/lib/taipo.rb
CHANGED
@@ -64,90 +64,4 @@ module Taipo
|
|
64
64
|
def self.alias?
|
65
65
|
@@alias
|
66
66
|
end
|
67
|
-
|
68
|
-
# Check if a string is the name of an instance method
|
69
|
-
#
|
70
|
-
# @note All this does is check whether the given string begins with a hash
|
71
|
-
# symbol.
|
72
|
-
#
|
73
|
-
# @param str [String] the string to check
|
74
|
-
#
|
75
|
-
# @return [Boolean] the result
|
76
|
-
#
|
77
|
-
# @since 1.0.0
|
78
|
-
# @api private
|
79
|
-
def self.instance_method?(str)
|
80
|
-
str[0] == '#'
|
81
|
-
end
|
82
|
-
|
83
|
-
# Return the type definition for an object
|
84
|
-
#
|
85
|
-
# @note This assume that each element returned by Enumerator#each has the same
|
86
|
-
# number of components.
|
87
|
-
#
|
88
|
-
# @param obj [Object] the object
|
89
|
-
#
|
90
|
-
# @return [String] a type definition of the object
|
91
|
-
#
|
92
|
-
# @since 1.1.0
|
93
|
-
# @api private
|
94
|
-
def self.object_to_type_def(obj)
|
95
|
-
return obj.class.name unless obj.is_a? Enumerable
|
96
|
-
|
97
|
-
if obj.is_a? Array
|
98
|
-
element_types = Hash.new
|
99
|
-
obj.each { |o| element_types[self.object_to_type_def(o)] = true }
|
100
|
-
if element_types.empty?
|
101
|
-
obj.class.name
|
102
|
-
else
|
103
|
-
obj.class.name + '<' + element_types.keys.join('|') + '>'
|
104
|
-
end
|
105
|
-
else
|
106
|
-
element_types = Array.new
|
107
|
-
obj.each.with_index do |element,index_e|
|
108
|
-
element.each.with_index do |component,index_c|
|
109
|
-
element_types[index_c] = Hash.new if index_e == 0
|
110
|
-
c_type = self.object_to_type_def(component)
|
111
|
-
element_types[index_c][c_type] = true
|
112
|
-
end
|
113
|
-
end
|
114
|
-
inner = element_types.reduce('') do |memo,e|
|
115
|
-
e_type = e.keys.join('|')
|
116
|
-
(memo == '') ? e_type : memo + ',' + e_type
|
117
|
-
end
|
118
|
-
if element_types.empty?
|
119
|
-
obj.class.name
|
120
|
-
else
|
121
|
-
obj.class.name + '<' + inner + '>'
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# Check if a string is the name of a symbol
|
127
|
-
#
|
128
|
-
# @note All this does is check whether the given string begins with a colon.
|
129
|
-
#
|
130
|
-
# @param str [String] the string to check
|
131
|
-
#
|
132
|
-
# @return [Boolean] the result
|
133
|
-
#
|
134
|
-
# @since 1.2.0
|
135
|
-
# @api private
|
136
|
-
def self.symbol?(str)
|
137
|
-
str[0] == ':'
|
138
|
-
end
|
139
|
-
|
140
|
-
# Return a String representation of an array of {Taipo::TypeElement}
|
141
|
-
#
|
142
|
-
# @param types [Array<Taipo::TypeElement>] the array of {Taipo::TypeElement}
|
143
|
-
#
|
144
|
-
# @return [String] the String representation
|
145
|
-
#
|
146
|
-
# @since 1.1.0
|
147
|
-
# @api private
|
148
|
-
def self.types_to_s(types)
|
149
|
-
types.reduce('') do |memo,t|
|
150
|
-
(memo == '') ? t.to_s : memo + '|' + t.to_s
|
151
|
-
end
|
152
|
-
end
|
153
67
|
end
|
data/lib/taipo/cache.rb
CHANGED
data/lib/taipo/check.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'taipo/cache'
|
2
2
|
require 'taipo/exceptions'
|
3
3
|
require 'taipo/parser'
|
4
|
+
require 'taipo/type_elements'
|
4
5
|
require 'taipo/type_element'
|
6
|
+
require 'taipo/utilities'
|
5
7
|
|
6
8
|
module Taipo
|
7
9
|
|
@@ -86,12 +88,12 @@ module Taipo
|
|
86
88
|
is_match = types.any? { |t| t.match? arg }
|
87
89
|
|
88
90
|
unless collect_invalids || is_match
|
89
|
-
if Taipo::instance_method? v
|
91
|
+
if Taipo::Utilities.instance_method? v
|
90
92
|
msg = "Object '#{k}' does not respond to #{v}."
|
91
|
-
elsif Taipo::symbol? v
|
93
|
+
elsif Taipo::Utilities.symbol? v
|
92
94
|
msg = "Object '#{k}' is not equal to #{v}."
|
93
95
|
elsif arg.is_a? Enumerable
|
94
|
-
type_def = Taipo.object_to_type_def arg
|
96
|
+
type_def = Taipo::Utilities.object_to_type_def arg
|
95
97
|
msg = "Object '#{k}' is #{type_def} but expected #{v}."
|
96
98
|
else
|
97
99
|
msg = "Object '#{k}' is #{arg.class.name} but expected #{v}."
|
@@ -125,8 +127,8 @@ module Taipo
|
|
125
127
|
#
|
126
128
|
# This is the callback called by Ruby when a module is included. In this
|
127
129
|
# case, the callback will alias the method +__types__+ as +types+ if
|
128
|
-
# {Taipo.alias?} returns true. {Taipo
|
129
|
-
# this method.
|
130
|
+
# {Taipo.alias?} returns true. {Taipo::@@alias} is reset to true at the end
|
131
|
+
# of this method.
|
130
132
|
#
|
131
133
|
# @param extender [Class|Module] the class or module extending this module
|
132
134
|
#
|
@@ -142,8 +144,8 @@ module Taipo
|
|
142
144
|
#
|
143
145
|
# This is the callback called by Ruby when a module is included. In this
|
144
146
|
# case, the callback will alias the method +__types__+ as +types+ if
|
145
|
-
# {Taipo.alias?} returns true. {Taipo
|
146
|
-
# this method.
|
147
|
+
# {Taipo.alias?} returns true. {Taipo::@@alias} is reset to true at the end
|
148
|
+
# of this method.
|
147
149
|
#
|
148
150
|
# @param includer [Class|Module] the class or module including this module
|
149
151
|
#
|
data/lib/taipo/parser.rb
CHANGED
@@ -1,18 +1,27 @@
|
|
1
1
|
require 'taipo/exceptions'
|
2
|
+
require 'taipo/parser/stack'
|
2
3
|
require 'taipo/parser/validater'
|
4
|
+
require 'taipo/refinements'
|
5
|
+
require 'taipo/type_elements'
|
3
6
|
require 'taipo/type_element'
|
7
|
+
require 'taipo/type_element/children'
|
8
|
+
require 'taipo/type_element/constraints'
|
9
|
+
require 'taipo/type_element/constraint'
|
4
10
|
|
5
11
|
module Taipo
|
6
12
|
|
7
13
|
# A parser of Taipo type definitions
|
14
|
+
#
|
8
15
|
# @since 1.0.0
|
9
16
|
module Parser
|
10
17
|
|
11
|
-
|
18
|
+
using Taipo::Refinements
|
19
|
+
|
20
|
+
# Return a Taipo::TypeElements object based on +str+
|
12
21
|
#
|
13
22
|
# @param str [String] a type definition
|
14
23
|
#
|
15
|
-
# @return [
|
24
|
+
# @return [Taipo:TypeElements] the result
|
16
25
|
#
|
17
26
|
# @raise [::TypeError] if +str+ is not a String
|
18
27
|
# @raise [Taipo::SyntaxError] if +str+ is not a valid type definition
|
@@ -21,198 +30,328 @@ module Taipo
|
|
21
30
|
def self.parse(str)
|
22
31
|
Taipo::Parser::Validater.validate str
|
23
32
|
|
33
|
+
stack = Taipo::Parser::Stack.new
|
34
|
+
i = 0
|
35
|
+
subject = :implied
|
36
|
+
chars = str.chars
|
24
37
|
content = ''
|
25
|
-
previous = ''
|
26
|
-
is_fallthrough = false
|
27
|
-
fallthroughs = [ '/', '"' ]
|
28
|
-
closing_symbol = ''
|
29
|
-
stack = Array.new
|
30
|
-
elements = Array.new
|
31
|
-
stack.push elements
|
32
38
|
|
33
|
-
|
34
|
-
|
39
|
+
while (i < chars.size)
|
40
|
+
reset = true
|
35
41
|
|
36
|
-
case
|
42
|
+
case chars[i]
|
43
|
+
when ' '
|
44
|
+
i += 1
|
45
|
+
next
|
37
46
|
when '|'
|
38
|
-
|
39
|
-
|
40
|
-
content = ''
|
41
|
-
elements = stack.pop
|
42
|
-
elements.push el
|
43
|
-
stack.push elements
|
44
|
-
end
|
47
|
+
stack = process_sum stack, name: content
|
48
|
+
subject = :implied
|
45
49
|
when '<'
|
46
|
-
|
47
|
-
|
48
|
-
stack.push el
|
49
|
-
child_type = Taipo::TypeElement::ChildType.new
|
50
|
-
stack.push child_type
|
51
|
-
first_component = Array.new
|
52
|
-
stack.push first_component
|
50
|
+
stack = process_collection :open, stack, name: content
|
51
|
+
subject = :implied
|
53
52
|
when '>'
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
last_component = stack.pop
|
60
|
-
last_component.push el
|
61
|
-
end
|
62
|
-
child_type = stack.pop
|
63
|
-
child_type.push last_component
|
64
|
-
parent_el = stack.pop
|
65
|
-
parent_el.child_type = child_type
|
66
|
-
elements = stack.pop
|
67
|
-
elements.push parent_el
|
68
|
-
stack.push elements
|
53
|
+
stack = process_collection :close, stack, name: content
|
54
|
+
subject = :made
|
55
|
+
when ','
|
56
|
+
stack = process_component stack, name: content
|
57
|
+
subject = :implied
|
69
58
|
when '('
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
59
|
+
stack = process_subject stack, name: content, subject: subject
|
60
|
+
stack, i = process_constraints stack, chars: chars, index: i+1
|
61
|
+
else
|
62
|
+
reset = false
|
63
|
+
subject = :unmade
|
64
|
+
end
|
65
|
+
|
66
|
+
content = (reset) ? '' : content + chars[i]
|
67
|
+
i += 1
|
68
|
+
end
|
69
|
+
|
70
|
+
stack = process_end stack, name: content
|
71
|
+
|
72
|
+
stack.result
|
73
|
+
end
|
74
|
+
|
75
|
+
# Check whether the character should be skipped
|
76
|
+
#
|
77
|
+
# This method determines whether a particular character +c+ should be
|
78
|
+
# skipped based on +states+. It also updates +states+.
|
79
|
+
#
|
80
|
+
# @param c [String] the character to check
|
81
|
+
# @param states [Hash<Symbol,Boolean>] a state machine
|
82
|
+
#
|
83
|
+
# @return [Boolean,Hash<Symbol,Boolean>] the result and the updated state
|
84
|
+
# machine
|
85
|
+
#
|
86
|
+
# @since 1.4.0
|
87
|
+
# @api private
|
88
|
+
def self.escape?(c, states)
|
89
|
+
if states[:esc]
|
90
|
+
states[:esc] = false
|
91
|
+
return skip, states
|
92
|
+
end
|
93
|
+
|
94
|
+
skip = true
|
95
|
+
|
96
|
+
case c
|
97
|
+
when "'"
|
98
|
+
states[:ss] = !states[:ss] unless states[:re] || states[:ds]
|
99
|
+
when '"'
|
100
|
+
states[:ds] = !states[:ds] unless states[:re] || states[:ss]
|
101
|
+
when '/'
|
102
|
+
states[:re] = !states[:re] unless states[:ss] || states[:ds]
|
103
|
+
when '\\'
|
104
|
+
states[:esc] = true
|
105
|
+
else
|
106
|
+
skip = false
|
107
|
+
end
|
108
|
+
|
109
|
+
return skip, states
|
110
|
+
end
|
111
|
+
|
112
|
+
# Parse the constraint expressed as a string
|
113
|
+
#
|
114
|
+
# @note If the constraint is in the form of an instance method (eg. #foo)
|
115
|
+
# this method uses {Taipo::TypeElement::Constraint::METHOD} as the name
|
116
|
+
# returned.
|
117
|
+
#
|
118
|
+
# @param str [String] the constraint expressed as a string
|
119
|
+
#
|
120
|
+
# @return [String,String] the name and the value
|
121
|
+
#
|
122
|
+
# @since 1.4.0
|
123
|
+
# @api private
|
124
|
+
def self.parse_constraint(str)
|
125
|
+
str.strip!
|
126
|
+
in_name = nil
|
127
|
+
name = ''
|
128
|
+
content = ''
|
129
|
+
str.each_char do |c|
|
130
|
+
if c == '#' && in_name.nil?
|
131
|
+
name = Taipo::TypeElement::Constraint::METHOD
|
132
|
+
in_name = false
|
133
|
+
elsif c == ':' && in_name.nil?
|
134
|
+
name = 'val'
|
135
|
+
content = content + c
|
136
|
+
in_name = false
|
137
|
+
elsif c == ':' && in_name
|
138
|
+
name = content
|
130
139
|
content = ''
|
131
|
-
|
132
|
-
el = stack.pop
|
133
|
-
el.constraints = cst_collection
|
134
|
-
elements = stack.pop
|
135
|
-
elements.push el
|
136
|
-
stack.push elements
|
140
|
+
in_name = false
|
137
141
|
else
|
138
|
-
if is_fallthrough
|
139
|
-
c = c[1]
|
140
|
-
is_fallthrough = false if c == closing_symbol
|
141
|
-
elsif fallthroughs.any? { |f| f == c }
|
142
|
-
is_fallthrough = true
|
143
|
-
closing_symbol = c
|
144
|
-
end
|
145
142
|
content = content + c
|
143
|
+
in_name = true if in_name.nil?
|
146
144
|
end
|
147
|
-
previous = c
|
148
145
|
end
|
146
|
+
value = content.strip
|
147
|
+
return name, value
|
148
|
+
end
|
149
149
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
150
|
+
# Process a collection
|
151
|
+
#
|
152
|
+
# This method either adds or updates a collection on +stack+ depending on
|
153
|
+
# +direction+. If +direction+ is +:open+, this adds a
|
154
|
+
# {Taipo::TypeElement} to +stack+ representing the class of the collection.
|
155
|
+
# If +direction+ is +:close+, this adds a {Taipo::TypeElement} to +stack+
|
156
|
+
# representing the class of the final component of the collection.
|
157
|
+
#
|
158
|
+
# @param direction [Symbol] Either +:open+ or +:close+ depending on whether
|
159
|
+
# this has been called because the parser reached a +<+ character or a
|
160
|
+
# +>+ character
|
161
|
+
# @param stack [Taipo::Parser::Stack] the stack
|
162
|
+
# @param name [String] the name of the class of the {Taipo::TypeElement} to
|
163
|
+
# add to +stack+
|
164
|
+
#
|
165
|
+
# @return [Taipo::Parser::Stack] the updated stack
|
166
|
+
#
|
167
|
+
# @since 1.4.0
|
168
|
+
# @api private
|
169
|
+
def self.process_collection(direction, stack, name:)
|
170
|
+
case direction
|
171
|
+
when :open
|
172
|
+
stack = process_name stack, name: name
|
173
|
+
stack.add_children
|
174
|
+
when :close
|
175
|
+
stack = process_name stack, name: name unless name.empty?
|
176
|
+
children = stack.remove_children
|
177
|
+
stack.update_element :children=, children
|
155
178
|
end
|
179
|
+
end
|
156
180
|
|
157
|
-
|
181
|
+
# Process a component
|
182
|
+
#
|
183
|
+
# This method adds a {Taipo::TypeElement} to +stack+ representing a
|
184
|
+
# component of a collection.
|
185
|
+
#
|
186
|
+
# @param stack [Taipo::Parser::Stack] the stack
|
187
|
+
# @param name [String] the name of the class of the {Taipo::TypeElement} to
|
188
|
+
# add to +stack+
|
189
|
+
#
|
190
|
+
# @return [Taipo::Parser::Stack] the updated stack
|
191
|
+
#
|
192
|
+
# @since 1.4.0
|
193
|
+
# @api private
|
194
|
+
def self.process_component(stack, name:)
|
195
|
+
stack = process_name stack, name: name
|
196
|
+
stack.add_child
|
158
197
|
end
|
159
|
-
|
160
|
-
#
|
198
|
+
|
199
|
+
# Process a constraint
|
161
200
|
#
|
162
|
-
# This
|
163
|
-
#
|
201
|
+
# This method adds a {Taipo::TypeElement::Constraint} to the last element in
|
202
|
+
# +stack+.
|
164
203
|
#
|
165
|
-
# @param
|
204
|
+
# @param stack [Taipo::Parser::Stack] the stack
|
205
|
+
# @param raw [String] the constraint expressed as a string
|
166
206
|
#
|
167
|
-
# @return [
|
207
|
+
# @return [Taipo::Parser::Stack] the updated stack
|
168
208
|
#
|
169
|
-
# @since 1.
|
209
|
+
# @since 1.4.0
|
170
210
|
# @api private
|
171
|
-
def self.
|
172
|
-
|
211
|
+
def self.process_constraint(stack, raw:)
|
212
|
+
n, v = parse_constraint raw
|
213
|
+
stack.add_constraint Taipo::TypeElement::Constraint.new(name: n, value: v)
|
173
214
|
end
|
174
215
|
|
175
|
-
#
|
216
|
+
# Process a series of constraints
|
176
217
|
#
|
177
|
-
#
|
178
|
-
#
|
179
|
-
# collection.
|
218
|
+
# This method adds a {Taipo::TypeElement::Constraints} to the last element
|
219
|
+
# in +stack+. Because it parses +chars+, it also returns an updated +index+.
|
180
220
|
#
|
181
|
-
# @param
|
221
|
+
# @param stack [Taipo::Parser::Stack] the stack
|
222
|
+
# @param chars [Array<String>] a character array
|
223
|
+
# @param index [Integer] the index of +chars+ at which to begin parsing
|
182
224
|
#
|
183
|
-
# @return [
|
225
|
+
# @return [Taipo::Parser::Stack,Integer] the updated stack and the updated
|
226
|
+
# index
|
184
227
|
#
|
185
|
-
# @since 1.
|
228
|
+
# @since 1.4.0
|
186
229
|
# @api private
|
187
|
-
def self.
|
188
|
-
|
230
|
+
def self.process_constraints(stack, chars:, index:)
|
231
|
+
stack.add_constraints
|
232
|
+
|
233
|
+
inside = { ss: false, ds: false, re: false, esc: false }
|
234
|
+
content = ''
|
235
|
+
|
236
|
+
while (index < chars.size)
|
237
|
+
skip, inside = escape?(chars[index], inside)
|
238
|
+
if skip
|
239
|
+
content = content + chars[index]
|
240
|
+
index += 1
|
241
|
+
next
|
242
|
+
end
|
243
|
+
|
244
|
+
case chars[index]
|
245
|
+
when ')'
|
246
|
+
stack = process_constraint stack, raw: content
|
247
|
+
break
|
248
|
+
when ','
|
249
|
+
stack = process_constraint stack, raw: content
|
250
|
+
content = ''
|
251
|
+
else
|
252
|
+
content = content + chars[index]
|
253
|
+
end
|
254
|
+
|
255
|
+
index += 1
|
256
|
+
end
|
257
|
+
|
258
|
+
constraints = stack.remove_constraints
|
259
|
+
stack.update_element :constraints=, constraints
|
260
|
+
|
261
|
+
return stack, index
|
189
262
|
end
|
190
263
|
|
191
|
-
#
|
264
|
+
# Process the end of the type definition
|
192
265
|
#
|
193
|
-
#
|
266
|
+
# The design of {Taipo::Parser.parse} means that at the end of the loop, an
|
267
|
+
# element may remain to be added. This method add any remaining element to
|
268
|
+
# +stack+.
|
194
269
|
#
|
195
|
-
# @
|
270
|
+
# @param stack [Taipo::Parser::Stack] the stack
|
271
|
+
# @param name [String] the name of the class of the {Taipo::TypeElement} to
|
272
|
+
# add to +stack+
|
196
273
|
#
|
197
|
-
# @
|
274
|
+
# @return [Taipo::Parser::Stack] the updated stack
|
275
|
+
#
|
276
|
+
# @since 1.4.0
|
198
277
|
# @api private
|
199
|
-
def self.
|
200
|
-
stack
|
278
|
+
def self.process_end(stack, name:)
|
279
|
+
return stack if name.empty?
|
280
|
+
|
281
|
+
process_name stack, name: name
|
282
|
+
end
|
283
|
+
|
284
|
+
# Process the name of a {Taipo::TypeElement}
|
285
|
+
#
|
286
|
+
# This method adds a {Taipo::TypeElement} to +stack+ with the name +name+.
|
287
|
+
#
|
288
|
+
# @note Taipo allows certain bare constraints to be written in type
|
289
|
+
# definitions. If +name+ is a bare constraint (either an instance method
|
290
|
+
# or a symbol), this method adds a {Taipo::TypeElement} representing the
|
291
|
+
# Object class with the relevant constraint.
|
292
|
+
#
|
293
|
+
# @param stack [Taipo::Parser::Stack] the stack
|
294
|
+
# @param name [String] the name of the class of the {Taipo::TypeElement} to
|
295
|
+
# add to +stack+
|
296
|
+
#
|
297
|
+
# @return [Taipo::Parser::Stack] the updated stack
|
298
|
+
#
|
299
|
+
# @since 1.4.0
|
300
|
+
# @api private
|
301
|
+
def self.process_name(stack, name:)
|
302
|
+
if name.bare_constraint?
|
303
|
+
chars = "(#{name})".chars
|
304
|
+
stack = process_subject stack, name: '', subject: :implied
|
305
|
+
stack, i = process_constraints stack, chars: chars, index: 1
|
306
|
+
stack
|
307
|
+
else
|
308
|
+
stack.add_element name: name
|
309
|
+
end
|
201
310
|
end
|
202
311
|
|
203
|
-
#
|
312
|
+
# Process the subject of a series of constraints
|
204
313
|
#
|
205
|
-
#
|
206
|
-
# type
|
314
|
+
# Taipo allows for a type definition to specify a series of constraints
|
315
|
+
# that constrain the particular type (the subject). This method adds a
|
316
|
+
# {Taipo::TypeElement} to +stack+ depending on the value of +subject+.
|
207
317
|
#
|
208
|
-
# @param
|
318
|
+
# @param stack [Taipo::Parser::Stack] the stack
|
319
|
+
# @param name [String] the name of the class of the {Taipo::TypeElement} to
|
320
|
+
# add to +stack+
|
321
|
+
# @param subject [Symbol] whether the subject is :made, :unmade or :implied
|
209
322
|
#
|
210
|
-
# @return [
|
323
|
+
# @return [Taipo::Parser::Stack] the updated stack
|
211
324
|
#
|
212
|
-
# @since 1.
|
325
|
+
# @since 1.4.0
|
213
326
|
# @api private
|
214
|
-
def self.
|
215
|
-
|
327
|
+
def self.process_subject(stack, name:, subject:)
|
328
|
+
case subject
|
329
|
+
when :made
|
330
|
+
stack
|
331
|
+
when :unmade
|
332
|
+
process_name stack, name: name
|
333
|
+
when :implied
|
334
|
+
process_name stack, name: 'Object'
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
# Process a sum of types
|
339
|
+
#
|
340
|
+
# This method adds a {Taipo::TypeElement} to +stack+ representing the former
|
341
|
+
# of the types in the sum.
|
342
|
+
#
|
343
|
+
# @param stack [Taipo::Parser::Stack] the stack
|
344
|
+
# @param name [String] the name of the class of the {Taipo::TypeElement} to
|
345
|
+
# add to +stack+
|
346
|
+
#
|
347
|
+
# @return [Taipo::Parser::Stack] the updated stack
|
348
|
+
#
|
349
|
+
# @since 1.4.0
|
350
|
+
# @api private
|
351
|
+
def self.process_sum(stack, name:)
|
352
|
+
return stack if name.empty?
|
353
|
+
|
354
|
+
process_name stack, name: name
|
216
355
|
end
|
217
356
|
end
|
218
357
|
end
|