furnace 0.0.4 → 0.0.6
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,50 @@
|
|
1
|
+
module Furnace::AST
|
2
|
+
class MatcherDSL
|
3
|
+
SpecialAny = MatcherSpecial.new(:any)
|
4
|
+
SpecialSkip = MatcherSpecial.new(:skip)
|
5
|
+
SpecialEach = MatcherSpecial.define(:each)
|
6
|
+
SpecialEither = MatcherSpecial.define(:either)
|
7
|
+
SpecialEitherMulti = MatcherSpecial.define(:either_multi)
|
8
|
+
SpecialMaybe = MatcherSpecial.define(:maybe)
|
9
|
+
|
10
|
+
def any
|
11
|
+
SpecialAny
|
12
|
+
end
|
13
|
+
|
14
|
+
def skip
|
15
|
+
SpecialSkip
|
16
|
+
end
|
17
|
+
|
18
|
+
def each
|
19
|
+
SpecialEach
|
20
|
+
end
|
21
|
+
|
22
|
+
def either
|
23
|
+
SpecialEither
|
24
|
+
end
|
25
|
+
|
26
|
+
def either_multi
|
27
|
+
SpecialEitherMulti
|
28
|
+
end
|
29
|
+
|
30
|
+
def maybe
|
31
|
+
SpecialMaybe
|
32
|
+
end
|
33
|
+
|
34
|
+
def map(name)
|
35
|
+
->(hash) { MatcherSpecial.new(:map, [name, hash]) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def capture(name)
|
39
|
+
MatcherSpecial.new(:capture, name)
|
40
|
+
end
|
41
|
+
|
42
|
+
def capture_rest(name)
|
43
|
+
MatcherSpecial.new(:capture_rest, name)
|
44
|
+
end
|
45
|
+
|
46
|
+
def backref(name)
|
47
|
+
MatcherSpecial.new(:backref, name)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/furnace/ast/matcher.rb
CHANGED
@@ -3,7 +3,7 @@ module Furnace::AST
|
|
3
3
|
|
4
4
|
class Matcher
|
5
5
|
def initialize(&block)
|
6
|
-
@pattern =
|
6
|
+
@pattern = MatcherDSL.new.instance_exec(&block)
|
7
7
|
end
|
8
8
|
|
9
9
|
def match(object, captures={})
|
@@ -53,55 +53,42 @@ module Furnace::AST
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
SpecialAny = MatcherSpecial.new(:any)
|
57
|
-
SpecialSkip = MatcherSpecial.new(:skip)
|
58
|
-
SpecialSubset = MatcherSpecial.define(:subset)
|
59
|
-
|
60
|
-
class << self
|
61
|
-
def any
|
62
|
-
SpecialAny
|
63
|
-
end
|
64
|
-
|
65
|
-
def skip
|
66
|
-
SpecialSkip
|
67
|
-
end
|
68
|
-
|
69
|
-
def subset
|
70
|
-
SpecialSubset
|
71
|
-
end
|
72
|
-
|
73
|
-
def capture(name)
|
74
|
-
MatcherSpecial.new(:capture, name)
|
75
|
-
end
|
76
|
-
|
77
|
-
def backref(name)
|
78
|
-
MatcherSpecial.new(:backref, name)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
56
|
protected
|
83
57
|
|
84
58
|
def submatch(array, pattern, captures)
|
85
59
|
matches = true
|
86
60
|
nested_captures = captures.dup
|
61
|
+
index = 0
|
87
62
|
|
88
|
-
pattern.each_with_index do |nested_pattern
|
89
|
-
return
|
63
|
+
pattern.each_with_index do |nested_pattern|
|
64
|
+
return nil if index > array.length
|
90
65
|
|
91
66
|
case nested_pattern
|
92
67
|
when Array
|
93
68
|
matches &&= genmatch(array[index], nested_pattern, nested_captures)
|
94
|
-
|
69
|
+
index += 1
|
70
|
+
when MatcherDSL::SpecialAny
|
95
71
|
# it matches
|
96
|
-
|
72
|
+
index += 1
|
73
|
+
when MatcherDSL::SpecialSkip
|
97
74
|
# it matches all remaining elements
|
98
|
-
|
75
|
+
index = array.length
|
99
76
|
when MatcherSpecial.kind(:capture)
|
100
77
|
# it matches and captures
|
101
78
|
nested_captures[nested_pattern.param] = array[index]
|
79
|
+
index += 1
|
80
|
+
when MatcherSpecial.kind(:capture_rest)
|
81
|
+
# it matches and captures all remaining
|
82
|
+
nested_captures[nested_pattern.param] = array[index..-1]
|
83
|
+
index = array.length
|
102
84
|
when MatcherSpecial.kind(:backref)
|
103
85
|
matches &&= (nested_captures[nested_pattern.param] == array[index])
|
104
|
-
|
86
|
+
index += 1
|
87
|
+
when MatcherSpecial.kind(:maybe)
|
88
|
+
if advance = submatch(array[index..-1], nested_pattern.param, nested_captures)
|
89
|
+
index += advance
|
90
|
+
end
|
91
|
+
when MatcherSpecial.kind(:each)
|
105
92
|
all_submatches = true
|
106
93
|
|
107
94
|
workset = Set.new array[index..-1]
|
@@ -122,9 +109,60 @@ module Furnace::AST
|
|
122
109
|
break unless all_submatches
|
123
110
|
end
|
124
111
|
|
112
|
+
index += 1
|
125
113
|
matches &&= all_submatches
|
114
|
+
when MatcherSpecial.kind(:either)
|
115
|
+
sub_found = false
|
116
|
+
|
117
|
+
nested_pattern.param.each do |subset_pattern|
|
118
|
+
if genmatch(array[index], subset_pattern, nested_captures)
|
119
|
+
sub_found = true
|
120
|
+
index += 1
|
121
|
+
break
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
matches &&= sub_found
|
126
|
+
when MatcherSpecial.kind(:either_multi)
|
127
|
+
sub_found = false
|
128
|
+
|
129
|
+
nested_pattern.param.each do |subset_pattern|
|
130
|
+
if matched = genmatch(array[index..-1], subset_pattern, nested_captures)
|
131
|
+
sub_found = true
|
132
|
+
index += matched
|
133
|
+
break
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
matches &&= sub_found
|
138
|
+
when MatcherSpecial.kind(:map)
|
139
|
+
captures_key, patterns = nested_pattern.param
|
140
|
+
nested_captures[captures_key] = []
|
141
|
+
|
142
|
+
while index < array.length
|
143
|
+
sub_found = false
|
144
|
+
|
145
|
+
patterns.each do |subset_key, subset_pattern|
|
146
|
+
subset_captures = captures.dup
|
147
|
+
|
148
|
+
if matched = submatch(array[index..-1], subset_pattern, subset_captures)
|
149
|
+
if subset_key
|
150
|
+
nested_captures[captures_key].push [subset_key, subset_captures]
|
151
|
+
end
|
152
|
+
|
153
|
+
sub_found = true
|
154
|
+
index += matched
|
155
|
+
|
156
|
+
break
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
matches &&= sub_found
|
161
|
+
break unless matches
|
162
|
+
end
|
126
163
|
else
|
127
|
-
matches &&= (array[index]
|
164
|
+
matches &&= (nested_pattern === array[index])
|
165
|
+
index += 1
|
128
166
|
end
|
129
167
|
|
130
168
|
break unless matches
|
@@ -132,7 +170,7 @@ module Furnace::AST
|
|
132
170
|
|
133
171
|
captures.replace(nested_captures) if matches
|
134
172
|
|
135
|
-
matches
|
173
|
+
index if matches
|
136
174
|
end
|
137
175
|
|
138
176
|
def genmatch(astlet, pattern, captures)
|
@@ -144,26 +182,14 @@ module Furnace::AST
|
|
144
182
|
end
|
145
183
|
end
|
146
184
|
|
147
|
-
if pattern
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
submatch(astlet.children, rest, captures)
|
154
|
-
else
|
155
|
-
false
|
156
|
-
end
|
157
|
-
else
|
158
|
-
false
|
159
|
-
end
|
185
|
+
if pattern === astlet
|
186
|
+
true
|
187
|
+
elsif astlet.is_a? Node
|
188
|
+
submatch([astlet.type].concat(astlet.children), pattern, captures)
|
189
|
+
elsif astlet.is_a? Array
|
190
|
+
submatch(astlet, pattern, captures)
|
160
191
|
else
|
161
|
-
|
162
|
-
if astlet.is_a? Array
|
163
|
-
submatch(astlet, pattern, captures)
|
164
|
-
else
|
165
|
-
false
|
166
|
-
end
|
192
|
+
false
|
167
193
|
end
|
168
194
|
end
|
169
195
|
end
|
data/lib/furnace/ast.rb
CHANGED
data/lib/furnace/version.rb
CHANGED
metadata
CHANGED
@@ -1,33 +1,25 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: furnace
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 4
|
10
|
-
version: 0.0.4
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Peter Zotov
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
date: 2012-01-28 00:00:00 Z
|
12
|
+
date: 2012-02-17 00:00:00.000000000 Z
|
19
13
|
dependencies: []
|
20
|
-
|
21
|
-
|
22
|
-
email:
|
14
|
+
description: Furnace is a static code analysis framework for dynamic languages, aimed
|
15
|
+
at efficient type and behavior inference.
|
16
|
+
email:
|
23
17
|
- whitequark@whitequark.org
|
24
|
-
executables:
|
18
|
+
executables:
|
25
19
|
- furnace
|
26
20
|
extensions: []
|
27
|
-
|
28
21
|
extra_rdoc_files: []
|
29
|
-
|
30
|
-
files:
|
22
|
+
files:
|
31
23
|
- .gitignore
|
32
24
|
- .rvmrc
|
33
25
|
- Gemfile
|
@@ -44,7 +36,8 @@ files:
|
|
44
36
|
- lib/furnace/anf/return_node.rb
|
45
37
|
- lib/furnace/ast.rb
|
46
38
|
- lib/furnace/ast/matcher.rb
|
47
|
-
- lib/furnace/ast/
|
39
|
+
- lib/furnace/ast/matcher/dsl.rb
|
40
|
+
- lib/furnace/ast/matcher/special.rb
|
48
41
|
- lib/furnace/ast/node.rb
|
49
42
|
- lib/furnace/ast/symbolic_node.rb
|
50
43
|
- lib/furnace/ast/visitor.rb
|
@@ -66,36 +59,27 @@ files:
|
|
66
59
|
- lib/furnace/version.rb
|
67
60
|
homepage: http://github.com/whitequark/furnace
|
68
61
|
licenses: []
|
69
|
-
|
70
62
|
post_install_message:
|
71
63
|
rdoc_options: []
|
72
|
-
|
73
|
-
require_paths:
|
64
|
+
require_paths:
|
74
65
|
- lib
|
75
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
67
|
none: false
|
77
|
-
requirements:
|
78
|
-
- -
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
|
81
|
-
|
82
|
-
- 0
|
83
|
-
version: "0"
|
84
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
requirements:
|
69
|
+
- - ! '>='
|
70
|
+
- !ruby/object:Gem::Version
|
71
|
+
version: '0'
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
73
|
none: false
|
86
|
-
requirements:
|
87
|
-
- -
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
|
90
|
-
segments:
|
91
|
-
- 0
|
92
|
-
version: "0"
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
93
78
|
requirements: []
|
94
|
-
|
95
79
|
rubyforge_project:
|
96
|
-
rubygems_version: 1.8.
|
80
|
+
rubygems_version: 1.8.10
|
97
81
|
signing_key:
|
98
82
|
specification_version: 3
|
99
83
|
summary: A static code analysis framework
|
100
84
|
test_files: []
|
101
|
-
|
85
|
+
has_rdoc:
|
File without changes
|