Skip to content

Commit 30b3069

Browse files
committed
Swift: WIP upgrade script for for-each refactor
1 parent eddca7f commit 30b3069

File tree

4 files changed

+5434
-0
lines changed

4 files changed

+5434
-0
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
class Element extends @element {
2+
string toString() { none() }
3+
}
4+
5+
class ForEachStmt extends Element, @for_each_stmt {
6+
Element getSequence() { for_each_stmts(this, _, result, _) }
7+
8+
Pattern getPattern() { for_each_stmts(this, result, _, _) }
9+
}
10+
11+
class Pattern extends Element, @pattern {
12+
string getGeneratorString() { result = "$generator" }
13+
}
14+
15+
class NamedPattern extends Pattern, @named_pattern {
16+
override string getGeneratorString() {
17+
exists(string name |
18+
named_patterns(this, name) and
19+
result = "$" + name + "$generator"
20+
)
21+
}
22+
}
23+
24+
newtype TAddedElement =
25+
TIteratorVar(ForEachStmt stmt) or
26+
TIteratorVarPattern(ForEachStmt stmt) or
27+
TNextCall(ForEachStmt stmt) or
28+
TNextCallMethodLookup(ForEachStmt stmt) or
29+
TNextCallInOutConversion(ForEachStmt stmt) or
30+
TNextCallVarRef(ForEachStmt stmt) or
31+
TNextCallFuncRef(ForEachStmt stmt)
32+
33+
module Fresh = QlBuiltins::NewEntity<TAddedElement>;
34+
35+
class TNewElement = @element or Fresh::EntityId;
36+
37+
class NewElement extends TNewElement {
38+
string toString() { none() }
39+
}
40+
41+
query predicate new_for_each_stmts(ForEachStmt id, NamedPattern pattern, Element body) {
42+
for_each_stmts(id, pattern, _, body)
43+
}
44+
45+
query predicate for_each_stmt_iterator_vars(ForEachStmt id, NewElement iteratorVar) {
46+
Fresh::map(TIteratorVar(id)) = iteratorVar
47+
}
48+
49+
query predicate new_pattern_binding_decls(NewElement id) {
50+
pattern_binding_decls(id)
51+
or
52+
Fresh::map(TIteratorVar(_)) = id
53+
}
54+
55+
query predicate new_pattern_binding_decl_patterns(NewElement id, int index, NewElement pattern) {
56+
pattern_binding_decl_patterns(id, index, pattern)
57+
or
58+
exists(ForEachStmt foreach |
59+
Fresh::map(TIteratorVar(foreach)) = id and
60+
Fresh::map(TIteratorVarPattern(foreach)) = pattern and
61+
index = 0
62+
)
63+
}
64+
65+
query predicate new_named_patterns(NewElement id, string name) {
66+
named_patterns(id, name)
67+
or
68+
exists(ForEachStmt foreach |
69+
Fresh::map(TIteratorVarPattern(foreach)) = id and
70+
name = foreach.getPattern().getGeneratorString()
71+
)
72+
}
73+
74+
query predicate new_pattern_binding_decl_inits(NewElement id, int index, NewElement init) {
75+
pattern_binding_decl_inits(id, index, init)
76+
or
77+
exists(ForEachStmt foreach |
78+
Fresh::map(TIteratorVar(foreach)) = id and
79+
foreach.getSequence() = init and
80+
index = 0
81+
)
82+
}
83+
84+
query predicate for_each_stmt_next_calls(ForEachStmt id, NewElement nextCall) {
85+
Fresh::map(TNextCall(id)) = nextCall
86+
}
87+
88+
query predicate new_dot_syntax_call_exprs(NewElement id) {
89+
dot_syntax_call_exprs(id)
90+
or
91+
Fresh::map(TNextCallMethodLookup(_)) = id
92+
}
93+
94+
query predicate new_self_apply_exprs(NewElement id, NewElement base) {
95+
self_apply_exprs(id, base)
96+
or
97+
exists(ForEachStmt foreach |
98+
Fresh::map(TNextCallMethodLookup(foreach)) = id and
99+
Fresh::map(TNextCallInOutConversion(foreach)) = base
100+
)
101+
}
102+
103+
query predicate new_in_out_exprs(NewElement inOutExpr, NewElement subExpr) {
104+
in_out_exprs(inOutExpr, subExpr)
105+
or
106+
exists(ForEachStmt foreach |
107+
Fresh::map(TNextCallInOutConversion(foreach)) = inOutExpr and
108+
Fresh::map(TNextCallVarRef(foreach)) = subExpr
109+
)
110+
}
111+
112+
query predicate new_apply_exprs(NewElement id, NewElement func) {
113+
apply_exprs(id, func)
114+
or
115+
exists(ForEachStmt foreach |
116+
Fresh::map(TNextCall(foreach)) = id and
117+
Fresh::map(TNextCallMethodLookup(foreach)) = func
118+
)
119+
or
120+
exists(ForEachStmt foreach |
121+
Fresh::map(TNextCallMethodLookup(foreach)) = id and
122+
Fresh::map(TNextCallFuncRef(foreach)) = func
123+
)
124+
}
125+
126+
Element getParent(Element type) {
127+
any_generic_type_parents(type, result)
128+
or
129+
// there may be an extension that implements IteratorProtocol
130+
exists(@extension_decl extDecl, @nominal_type_decl typeDecl, @protocol_decl protocolDecl |
131+
any_generic_types(type, typeDecl) and
132+
extension_decls(extDecl, typeDecl) and
133+
extension_decl_protocols(extDecl, _, protocolDecl) and
134+
any_generic_types(result, protocolDecl)
135+
)
136+
}
137+
138+
// TODO: do we need a new_apply_expr_arguments
139+
query predicate new_decl_ref_exprs(NewElement id, NewElement decl) {
140+
decl_ref_exprs(id, decl)
141+
or
142+
exists(ForEachStmt foreach |
143+
Fresh::map(TNextCallVarRef(foreach)) = id and
144+
Fresh::map(TIteratorVarPattern(foreach)) = decl
145+
)
146+
or
147+
exists(ForEachStmt foreach, @element sequence, @element exprType, @element parentType, @element typeDecl |
148+
Fresh::map(TNextCallFuncRef(foreach)) = id and
149+
// ForEachStmt.getSequence().getType().getMember(next)
150+
sequence = foreach.getSequence() and
151+
expr_types(sequence, exprType) and
152+
parentType = getParent*(exprType) and
153+
any_generic_types(parentType, typeDecl) and
154+
decl_members(typeDecl, _, decl) and
155+
callable_names(decl, "next()")
156+
)
157+
}
158+
159+
query predicate new_lookup_exprs(NewElement id, NewElement base) {
160+
lookup_exprs(id, base)
161+
or
162+
exists(ForEachStmt foreach |
163+
Fresh::map(TNextCallMethodLookup(foreach)) = id and
164+
Fresh::map(TNextCallVarRef(foreach)) = base
165+
)
166+
}
167+
168+
query predicate new_call_exprs(NewElement id) {
169+
call_exprs(id) or
170+
Fresh::map(TNextCall(_)) = id
171+
}

0 commit comments

Comments
 (0)