OLD | NEW |
| (Empty) |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library kernel.transformations.closure.mock; | |
6 | |
7 import '../../ast.dart' | |
8 show | |
9 Arguments, | |
10 Block, | |
11 Class, | |
12 Constructor, | |
13 ConstructorInvocation, | |
14 DartType, | |
15 DynamicType, | |
16 EmptyStatement, | |
17 Expression, | |
18 ExpressionStatement, | |
19 Field, | |
20 FieldInitializer, | |
21 FunctionNode, | |
22 Initializer, | |
23 IntLiteral, | |
24 Library, | |
25 MethodInvocation, | |
26 Name, | |
27 NullLiteral, | |
28 Procedure, | |
29 ProcedureKind, | |
30 Program, | |
31 PropertyGet, | |
32 ReturnStatement, | |
33 Source, | |
34 Statement, | |
35 StaticInvocation, | |
36 Supertype, | |
37 TreeNode, | |
38 VariableDeclaration, | |
39 VariableGet; | |
40 | |
41 import '../../core_types.dart' show CoreTypes; | |
42 | |
43 import '../../frontend/accessors.dart' | |
44 show | |
45 Accessor, | |
46 IndexAccessor, | |
47 PropertyAccessor, | |
48 ThisPropertyAccessor, | |
49 VariableAccessor; | |
50 | |
51 /// TODO(dmitryas): make the "[]=" operator return the value. | |
52 /// Extend the program with this mock: | |
53 /// | |
54 /// class Context { | |
55 /// final List list; | |
56 /// var parent; | |
57 /// Context(int i) : list = new List(i); | |
58 /// operator[] (int i) => list[i]; | |
59 /// operator[]= (int i, value) { | |
60 /// list[i] = value; | |
61 /// } | |
62 /// Context copy() { | |
63 /// Context c = new Context(list.length); | |
64 /// c.parent = parent; | |
65 /// c.list.setRange(0, list.length, list); | |
66 /// return c; | |
67 /// } | |
68 /// } | |
69 /// | |
70 /// Returns the mock. | |
71 Library mockUpContextLibrary(CoreTypes coreTypes) { | |
72 String fileUri = "dart:mock"; | |
73 | |
74 /// final List list; | |
75 Field listField = new Field(new Name("list"), | |
76 type: coreTypes.listClass.rawType, isFinal: true, fileUri: fileUri); | |
77 Accessor listFieldAccessor = new ThisPropertyAccessor( | |
78 listField.name, listField, null, TreeNode.noOffset); | |
79 | |
80 /// var parent; | |
81 Field parentField = new Field(new Name("parent"), fileUri: fileUri); | |
82 Accessor parentFieldAccessor = new ThisPropertyAccessor( | |
83 parentField.name, parentField, parentField, TreeNode.noOffset); | |
84 | |
85 List<Field> fields = <Field>[listField, parentField]; | |
86 | |
87 /// Context(int i) : list = new List(i); | |
88 VariableDeclaration iParameter = new VariableDeclaration("i", | |
89 type: coreTypes.intClass.rawType, isFinal: true); | |
90 | |
91 // TODO(karlklose): use the default factory when it is exposed again. | |
92 Procedure listConstructor = coreTypes.listClass.procedures | |
93 .firstWhere((Procedure p) => p.name.name == 'filled'); | |
94 | |
95 Constructor constructor = new Constructor( | |
96 new FunctionNode(new EmptyStatement(), | |
97 positionalParameters: <VariableDeclaration>[iParameter]), | |
98 name: new Name(""), | |
99 initializers: <Initializer>[ | |
100 new FieldInitializer( | |
101 listField, | |
102 new StaticInvocation( | |
103 listConstructor, | |
104 new Arguments(<Expression>[ | |
105 new VariableAccessor(iParameter, null, TreeNode.noOffset) | |
106 .buildSimpleRead(), | |
107 new NullLiteral(), | |
108 ], types: <DartType>[ | |
109 const DynamicType() | |
110 ]))) | |
111 ]); | |
112 | |
113 /// operator[] (int i) => list[i]; | |
114 iParameter = new VariableDeclaration("i", | |
115 type: coreTypes.intClass.rawType, isFinal: true); | |
116 Accessor accessor = IndexAccessor.make( | |
117 listFieldAccessor.buildSimpleRead(), | |
118 new VariableAccessor(iParameter, null, TreeNode.noOffset) | |
119 .buildSimpleRead(), | |
120 null, | |
121 null); | |
122 Procedure indexGet = new Procedure( | |
123 new Name("[]"), | |
124 ProcedureKind.Operator, | |
125 new FunctionNode(new ReturnStatement(accessor.buildSimpleRead()), | |
126 positionalParameters: <VariableDeclaration>[iParameter]), | |
127 fileUri: fileUri); | |
128 | |
129 /// operator[]= (int i, value) { | |
130 /// list[i] = value; | |
131 /// } | |
132 iParameter = new VariableDeclaration("i", | |
133 type: coreTypes.intClass.rawType, isFinal: true); | |
134 VariableDeclaration valueParameter = | |
135 new VariableDeclaration("value", isFinal: true); | |
136 accessor = IndexAccessor.make( | |
137 listFieldAccessor.buildSimpleRead(), | |
138 new VariableAccessor(iParameter, null, TreeNode.noOffset) | |
139 .buildSimpleRead(), | |
140 null, | |
141 null); | |
142 Expression expression = accessor.buildAssignment( | |
143 new VariableAccessor(valueParameter, null, TreeNode.noOffset) | |
144 .buildSimpleRead(), | |
145 voidContext: true); | |
146 Procedure indexSet = new Procedure( | |
147 new Name("[]="), | |
148 ProcedureKind.Operator, | |
149 new FunctionNode(new ExpressionStatement(expression), | |
150 positionalParameters: <VariableDeclaration>[ | |
151 iParameter, | |
152 valueParameter | |
153 ]), | |
154 fileUri: fileUri); | |
155 | |
156 /// Context copy() { | |
157 /// Context c = new Context(list.length); | |
158 /// c.parent = parent; | |
159 /// c.list.setRange(0, list.length, list); | |
160 /// return c; | |
161 /// } | |
162 VariableDeclaration c = new VariableDeclaration("c", | |
163 initializer: new ConstructorInvocation( | |
164 constructor, | |
165 new Arguments(<Expression>[ | |
166 new PropertyGet( | |
167 listFieldAccessor.buildSimpleRead(), new Name("length")) | |
168 ]))); | |
169 Accessor accessCParent = PropertyAccessor.make( | |
170 new VariableGet(c), parentField.name, parentField, parentField); | |
171 Accessor accessCList = PropertyAccessor.make( | |
172 new VariableGet(c), listField.name, listField, null); | |
173 List<Statement> statements = <Statement>[ | |
174 c, | |
175 new ExpressionStatement(accessCParent.buildAssignment( | |
176 parentFieldAccessor.buildSimpleRead(), | |
177 voidContext: true)), | |
178 new ExpressionStatement(new MethodInvocation( | |
179 accessCList.buildSimpleRead(), | |
180 new Name("setRange"), | |
181 new Arguments(<Expression>[ | |
182 new IntLiteral(0), | |
183 new PropertyGet( | |
184 listFieldAccessor.buildSimpleRead(), new Name("length")), | |
185 listFieldAccessor.buildSimpleRead() | |
186 ]))), | |
187 new ReturnStatement(new VariableGet(c)) | |
188 ]; | |
189 Procedure copy = new Procedure(new Name("copy"), ProcedureKind.Method, | |
190 new FunctionNode(new Block(statements)), | |
191 fileUri: fileUri); | |
192 | |
193 List<Procedure> procedures = <Procedure>[indexGet, indexSet, copy]; | |
194 | |
195 Class contextClass = new Class( | |
196 name: "Context", | |
197 supertype: new Supertype(coreTypes.objectClass, const <DartType>[]), | |
198 constructors: [constructor], | |
199 fields: fields, | |
200 procedures: procedures, | |
201 fileUri: fileUri); | |
202 Library mock = | |
203 new Library(Uri.parse(fileUri), name: "mock", classes: [contextClass]) | |
204 ..fileUri = fileUri; | |
205 | |
206 return mock; | |
207 } | |
208 | |
209 Class mockUpContextForLibraries(CoreTypes coreTypes, List<Library> libraries) { | |
210 Library mock = mockUpContextLibrary(coreTypes); | |
211 Program parent = libraries.length > 0 ? libraries[0]?.parent : null; | |
212 libraries.add(mock); | |
213 mock.parent = parent; | |
214 parent?.uriToSource[mock.fileUri] = new Source(<int>[0], const <int>[]); | |
215 return mock.classes[0]; | |
216 } | |
217 | |
218 Class mockUpContextForProgram(CoreTypes coreTypes, Program program) { | |
219 Library mock = mockUpContextLibrary(coreTypes); | |
220 program.libraries.add(mock); | |
221 mock.parent = program; | |
222 program.uriToSource[mock.fileUri] = new Source(<int>[0], const <int>[]); | |
223 return mock.classes[0]; | |
224 } | |
OLD | NEW |