Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(770)

Side by Side Diff: pkg/front_end/lib/src/libraries_reader.dart

Issue 2578693002: Add front end code for reading the SDK's "libraries.dart" file. (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 import 'package:analyzer/src/summary/idl.dart';
2 import 'package:front_end/src/base/library_info.dart';
3
4 /// Decodes the contents of the SDK's "libraries.dart" file.
5 ///
6 /// Caller should pass in the unlinked summary of the libraries.dart file. This
7 /// function will materialize the "libraries" constant based on information in
8 /// the summary.
9 ///
10 /// Note that this code is not intended to be fully general; it makes some
11 /// assumptions about the structure of the "libraries.dart" file (such as what
12 /// declarations are expected to be present in it, and the types of those
13 /// declarations).
14 Map<String, LibraryInfo> readLibraries(UnlinkedUnit librariesUnit) {
Siggi Cherem (dart-lang) 2016/12/14 20:48:43 cool to see that we can use summaries for this - b
Paul Berry 2016/12/14 23:17:25 That's wonderful to hear (see my other comment)!
15 var constContext = new _ConstContext(librariesUnit.references);
16 for (var variable in librariesUnit.variables) {
17 if (!variable.isConst) continue;
18 constContext.topLevelConstants[variable.name] =
19 new _ConstVariable(variable.initializer.bodyExpr, constContext);
20 }
21 for (var cls in librariesUnit.classes) {
22 if (cls.name == 'Maturity') {
23 for (var field in cls.fields) {
24 if (!field.isConst) continue;
25 constContext.maturityConstants[field.name] =
26 new _ConstVariable(field.initializer.bodyExpr, constContext);
27 }
28 }
29 }
30 return constContext.topLevelConstants['libraries'].value;
31 }
32
33 /// Function type used to invoke a constructor based on dynamic information.
34 ///
35 /// Caller supplies two callbacks ([positional] and [named]) which can be used
36 /// to query the arguments passed to the constructor. These callbacks will
37 /// return the requested argument if it was provided; otherwise they will return
38 /// the supplied default value.
39 typedef dynamic _Constructor(dynamic positional(int i, [dynamic defaultValue]),
40 dynamic named(String name, [dynamic defaultValue]));
41
42 /// Contextual information used to evaluate constants in the "libraries.dart"
43 /// file.
44 class _ConstContext {
45 /// Top level constants in the "libraries.dart" file.
46 final topLevelConstants = <String, _ConstVariable>{};
47
48 /// Static constants in "libraries.dart"'s "Maturity" class.
49 final maturityConstants = <String, _ConstVariable>{};
50
51 /// References from the unlinked summary of the "libraries.dart" file.
52 final List<UnlinkedReference> references;
53
54 _ConstContext(this.references);
55 }
56
57 /// Information necessary to evaluate a single constant from the
58 /// "libraries.dart" file.
59 class _ConstVariable {
60 /// The constant expression from the unlinked summary.
61 final UnlinkedExpr expr;
62
63 /// Contextual information necessary to evaluate the constant.
64 final _ConstContext context;
65
66 /// The evaluated value.
67 dynamic _value;
68
69 /// Indicates whether the value has been evaluated yet.
70 bool isMaterialized = false;
Siggi Cherem (dart-lang) 2016/12/14 20:48:43 minor nit: do we expect to have `null` values? If
Paul Berry 2016/12/14 23:17:25 Fair enough. Following your suggestion below gets
71
72 _ConstVariable(this.expr, this.context);
73
74 /// Evaluate the constant (if necessary) and return it.
75 dynamic get value {
Siggi Cherem (dart-lang) 2016/12/14 20:48:43 similarly, if `null` is not a valid value, then:
Paul Berry 2016/12/14 23:17:25 Done.
76 if (!isMaterialized) _materialize();
77 return _value;
78 }
79
80 /// Find the constructor referred to by [entityRef] and return a function
81 /// which may be used to invoke it.
82 _Constructor _findConstructor(EntityRef entityRef) {
83 // This method is not fully general; we only support the constructor
84 // invocations that we expect to find in LibraryInfo.
85 assert(entityRef.implicitFunctionTypeIndices.isEmpty);
86 assert(entityRef.paramReference == 0);
87 assert(entityRef.syntheticParams.isEmpty);
88 assert(entityRef.syntheticReturnType == null);
89 assert(entityRef.typeArguments.isEmpty);
90 var reference = context.references[entityRef.reference];
91 assert(reference.prefixReference == 0);
92 switch (reference.name) {
93 case 'LibraryInfo':
94 return (dynamic positional(int i, [dynamic defaultValue]),
95 dynamic named(String name, [dynamic defaultValue])) =>
96 new LibraryInfo(positional(0),
97 categories: named('categories', ''),
98 dart2jsPath: named('dart2jsPath'),
99 dart2jsPatchPath: named('dart2jsPatchPath'),
100 implementation: named('implementation', false),
101 documented: named('documented', true),
102 maturity: named('maturity', Maturity.UNSPECIFIED),
103 platforms: named('platforms', DART2JS_PLATFORM | VM_PLATFORM));
104 case 'Maturity':
105 return (dynamic positional(int i, [dynamic defaultValue]),
106 dynamic named(String name, [dynamic defaultValue])) =>
107 new Maturity(positional(0), positional(1), positional(2));
108 default:
109 throw new UnimplementedError(
110 'Unexpected constructor reference: ${reference.name}');
111 }
112 }
113
114 /// Compute the value referred to by [entityRef].
115 dynamic _findReference(EntityRef entityRef) {
116 // This method is not fully general; we only support the references that we
117 // expect to find in LibraryInfo.
118 assert(entityRef.implicitFunctionTypeIndices.isEmpty);
119 assert(entityRef.paramReference == 0);
120 assert(entityRef.syntheticParams.isEmpty);
121 assert(entityRef.syntheticReturnType == null);
122 assert(entityRef.typeArguments.isEmpty);
123 var reference = context.references[entityRef.reference];
124 if (reference.prefixReference == 0) {
125 return context.topLevelConstants[reference.name].value;
126 } else {
127 assert(reference.prefixReference != 0);
128 var prefixReference = context.references[reference.prefixReference];
129 assert(prefixReference.name == 'Maturity');
130 assert(prefixReference.prefixReference == 0);
131 return context.maturityConstants[reference.name].value;
132 }
133 }
134
135 /// Compute the value of the constant and store it in [_value].
136 void _materialize() {
137 var stack = [];
138 var stringIndex = 0;
139 var intIndex = 0;
140 var referenceIndex = 0;
141 List popItems(int count) {
142 var items = stack.sublist(stack.length - count, stack.length);
143 stack.length -= count;
144 return items;
145 }
146
147 for (var operation in expr.operations) {
148 switch (operation) {
149 case UnlinkedExprOperation.pushString:
150 stack.add(expr.strings[stringIndex++]);
151 break;
152 case UnlinkedExprOperation.invokeConstructor:
153 var namedArgumentList = popItems(expr.ints[intIndex++]);
154 var namedArguments = <String, dynamic>{};
155 for (var namedArgument in namedArgumentList) {
156 namedArguments[expr.strings[stringIndex++]] = namedArgument;
157 }
158 var positionalArguments = popItems(expr.ints[intIndex++]);
159 stack.add(_findConstructor(expr.references[referenceIndex++])(
160 (i, [defaultValue]) => i < positionalArguments.length
161 ? positionalArguments[i]
162 : defaultValue,
163 (name, [defaultValue]) => namedArguments.containsKey(name)
164 ? namedArguments[name]
165 : defaultValue));
166 break;
167 case UnlinkedExprOperation.makeUntypedMap:
168 var map = {};
169 var numKeyValuePairs = expr.ints[intIndex++];
170 var keyValueList = popItems(numKeyValuePairs * 2);
171 for (var i = 0; i < numKeyValuePairs; i++) {
172 map[keyValueList[2 * i]] = keyValueList[2 * i + 1];
173 }
174 stack.add(map);
175 break;
176 case UnlinkedExprOperation.pushReference:
177 stack.add(_findReference(expr.references[referenceIndex++]));
178 break;
179 case UnlinkedExprOperation.pushInt:
180 stack.add(expr.ints[intIndex++]);
181 break;
182 case UnlinkedExprOperation.pushFalse:
183 stack.add(false);
184 break;
185 case UnlinkedExprOperation.pushTrue:
186 stack.add(true);
187 break;
188 case UnlinkedExprOperation.bitOr:
189 var y = stack.removeLast();
190 var x = stack.removeLast();
191 stack.add(x | y);
192 break;
193 default:
194 throw new UnimplementedError(
195 'Unexpected expression in libraries.dart: $operation');
196 }
197 }
198 assert(stringIndex == expr.strings.length);
199 assert(intIndex == expr.ints.length);
200 assert(referenceIndex == expr.references.length);
201 assert(stack.length == 1);
202 _value = stack[0];
203 isMaterialized = true;
204 }
205 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698