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

Side by Side Diff: lib/runtime/dart_runtime.dart

Issue 1148283010: Remove dart backend (Closed) Base URL: https://github.com/dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 6 months 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
« no previous file with comments | « lib/runtime/dart_logging_runtime.dart ('k') | lib/src/codegen/dart_codegen.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, 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 dev_compiler.runtime.dart_runtime;
6
7 import 'dart:mirrors';
8
9 import 'package:dev_compiler/config.dart';
10
11 dynamic dload(dynamic obj, String field) {
12 var symbol = new Symbol(field);
13 var mirror = reflect(obj);
14 // TODO(vsm): Does this create an NSM?
15 var fieldMirror = mirror.getField(symbol);
16 return fieldMirror.reflectee;
17 }
18
19 dynamic dinvokef(dynamic f, List args) {
20 // TODO(vsm): Support named arguments.
21 assert(f is Function);
22 return Function.apply(f, args);
23 }
24
25 // A workaround to manufacture a generic Type object inline.
26 // We use mirrors to extract type T given a TypeFunction<T>.
27 // E.g., Map<String, String> is not a valid literal in Dart.
28 // Instead, use: type((Map<String, String> _) {});
29 // See bug: https://code.google.com/p/dart/issues/detail?id=11923
30 typedef TypeFunction<T>(T x);
31
32 Type type(TypeFunction f) {
33 ClosureMirror cm = reflect(f);
34 MethodMirror mm = cm.function;
35 ParameterMirror pm = mm.parameters[0];
36 TypeMirror tm = pm.type;
37 return tm.reflectedType;
38 }
39
40 dynamic cast(dynamic obj, Type staticType) {
41 // This is our 'as' equivalent.
42 if (obj == null) {
43 // A null can be cast only to non-primitive types.
44 if (!isPrimitiveType(staticType)) return null;
45 } else {
46 // For non-null values, val is T => val as T succeeds.
47 if (instanceOf(obj, staticType)) return obj;
48 }
49 // TODO(vsm): Add message.
50 throw new CastError();
51 }
52
53 bool instanceOf(dynamic obj, Type staticType) {
54 // This is our 'is' equivalent.
55 Type runtimeType = obj.runtimeType;
56 return _isSubType(reflectType(runtimeType), reflectType(staticType));
57 }
58
59 bool isGroundType(Type type) {
60 // These are types allowed in is / as expressions.
61 final mirror = reflectType(type);
62 return _isGroundTypeMirror(mirror);
63 }
64
65 final _primitiveMap = {
66 'int': int,
67 'double': double,
68 'num': num,
69 'bool': bool,
70 'String': String,
71 };
72
73 // TODO(vsm): Make this configurable? Using default settings for now.
74 final _typeOptions = new TypeOptions();
75
76 Set<Type> _primitives = () {
77 var types = _typeOptions.nonnullableTypes;
78 var set = new Set<Type>.from(types.map((t) => _primitiveMap[t]));
79 return set;
80 }();
81
82 bool isPrimitiveType(Type t) {
83 return _primitives.contains(t);
84 }
85
86 class Arity {
87 final int normal;
88 final int optionalPositional;
89
90 Arity._internal(this.normal, this.optionalPositional);
91
92 int get min => normal;
93 int get max => normal + optionalPositional;
94 }
95
96 Arity getArity(Function f) {
97 final FunctionTypeMirror mirror = reflectType(f.runtimeType);
98 final parameters = mirror.parameters;
99 int normal = 0;
100 int optionalPositional = 0;
101 for (var parameter in parameters) {
102 if (parameter.isNamed) {
103 // Ignore named parameters - these cannot be passed positionally.
104 } else if (parameter.isOptional) {
105 optionalPositional++;
106 } else {
107 normal++;
108 }
109 }
110 return new Arity._internal(normal, optionalPositional);
111 }
112
113 bool _isFunctionSubType(TypeMirror ret1, List<ParameterMirror> params1,
114 TypeMirror ret2, List<ParameterMirror> params2) {
115 if (!_isSubType(ret1, ret2)) {
116 // Covariant return types
117 // Note, void (which can only appear as a return type) is effectively
118 // treated as dynamic. If the base return type is void, we allow any
119 // subtype return type.
120 // E.g., we allow:
121 // () -> int <: () -> void
122 if (ret2.simpleName != const Symbol('void')) {
123 return false;
124 }
125 }
126
127 if (params1.length < params2.length) {
128 return false;
129 }
130
131 for (int i = 0; i < params2.length; ++i) {
132 ParameterMirror p1 = params1[i];
133 ParameterMirror p2 = params2[i];
134
135 // Contravariant parameter types.
136 if (!_isSubType(p2.type, p1.type, dynamicIsBottom: true)) {
137 return false;
138 }
139
140 // Optional parameters.
141 if (p2.isOptional) {
142 // If the base param is optional, the sub param must be optional:
143 if (!p1.isOptional) return false;
144 if (!p2.isNamed) {
145 // either neither are named or
146 if (p1.isNamed) return false;
147 } else {
148 // both are named with the same name
149 if (!p1.isNamed || p1.simpleName != p2.simpleName) return false;
150 }
151 } else {
152 // If the base param is required, the sub may be optional, but not named.
153 if (p1.isNamed) return false;
154 }
155 }
156
157 for (int i = params2.length; i < params1.length; ++i) {
158 ParameterMirror p1 = params1[i];
159 // Any additional sub params must be optional.
160 if (!p1.isOptional) return false;
161 }
162
163 return true;
164 }
165
166 bool _isClassSubType(ClassMirror m1, ClassMirror m2) {
167 // TODO(vsm): Consider some caching for efficiency here.
168
169 // We support Dart's covariant generics with the caveat that we do not
170 // substitute bottom for dynamic in subtyping rules.
171 // I.e., given T1, ..., Tn where at least one Ti != dynamic we disallow:
172 // - S !<: S<T1, ..., Tn>
173 // - S<dynamic, ..., dynamic> !<: S<T1, ..., Tn>
174 if (m1 == m2) return true;
175
176 if (_isTop(m1)) return false;
177
178 // Check if m1 and m2 have the same raw type. If so, check covariance on
179 // type parameters.
180 if (m1.originalDeclaration == m2.originalDeclaration) {
181 if (_isRawClass(m2)) return true;
182 if (_isRawClass(m1)) return false;
183
184 final typeArguments1 = m1.typeArguments;
185 final typeArguments2 = m2.typeArguments;
186 final length = typeArguments1.length;
187 assert(typeArguments1.isNotEmpty && typeArguments2.isNotEmpty);
188 assert(typeArguments2.length == length);
189 for (var i = 0; i < length; ++i) {
190 var typeArgument1 = typeArguments1[i];
191 var typeArgument2 = typeArguments2[i];
192 if (!_isSubType(typeArgument1, typeArgument2)) {
193 return false;
194 }
195 }
196 return true;
197 }
198
199 // Check superclass.
200 if (_isClassSubType(m1.superclass, m2)) return true;
201
202 // Check for mixins. The mixin getter returns the original class if there is
203 // no mixin.
204 if (m1 != m1.mixin && _isClassSubType(m1.mixin, m2)) return true;
205
206 // Check interfaces.
207 for (final parent in m1.superinterfaces) {
208 if (_isClassSubType(parent, m2)) return true;
209 }
210
211 return false;
212 }
213
214 final _dynamicMirror = reflectType(dynamic);
215 final _objectMirror = reflectType(Object);
216
217 bool _isBottom(TypeMirror t, {bool dynamicIsBottom: false}) {
218 if (t == _dynamicMirror && dynamicIsBottom) return true;
219 // TODO(vsm): Do we need an explicit representation of Bottom?
220 return false;
221 }
222
223 bool _isTop(TypeMirror t, {bool dynamicIsBottom: false}) {
224 if (t == _dynamicMirror && !dynamicIsBottom) return true;
225 if (t == _objectMirror) return true;
226 return false;
227 }
228
229 bool _isGroundTypeMirror(TypeMirror mirror) {
230 // This is a runtime type - we should not see type parameters here.
231 assert(mirror is! TypeVariableMirror);
232
233 // Allow only 'raw' functions.
234 if (mirror is TypedefMirror) {
235 return _isRawFunction(mirror.referent);
236 }
237 if (mirror is FunctionTypeMirror) {
238 return _isRawFunction(mirror);
239 }
240
241 // Allow only 'raw' classes.
242 if (mirror is ClassMirror) {
243 return _isRawClass(mirror);
244 }
245
246 // Only dynamic should be left. Should this be allowed?
247 // It's not particularly useful.
248 assert(mirror.reflectedType == dynamic);
249 return true;
250 }
251
252 bool _isRawFunction(FunctionTypeMirror mirror) {
253 var returnType = mirror.returnType;
254 if (!_isTop(returnType)) return false;
255 for (var parameter in mirror.parameters) {
256 var paramType = parameter.type;
257 if (!_isBottom(paramType, dynamicIsBottom: true)) return false;
258 }
259 return true;
260 }
261
262 bool _isRawClass(ClassMirror mirror) {
263 // Allow only raw types.
264 if (mirror == mirror.originalDeclaration) return true;
265 for (var typeArgument in mirror.typeArguments) {
266 if (!_isTop(typeArgument)) return false;
267 }
268 return true;
269 }
270
271 TypeMirror _canonicalizeTypeMirror(TypeMirror t) {
272 if (t is TypedefMirror) {
273 // We canonicalize Typedefs to their underlying function types.
274 t = (t as TypedefMirror).referent;
275 }
276 if (t is ClassMirror && _isRawClass(t)) {
277 // We canonicalize T<dynamic> to T.
278 t = t.originalDeclaration;
279 }
280 return t;
281 }
282
283 bool _reflects(TypeMirror mirror, Type t) {
284 return mirror.hasReflectedType && mirror.reflectedType == t;
285 }
286
287 bool _isSubType(TypeMirror t1, TypeMirror t2, {bool dynamicIsBottom: false}) {
288 t1 = _canonicalizeTypeMirror(t1);
289 t2 = _canonicalizeTypeMirror(t2);
290
291 if (t1 is TypeVariableMirror) {
292 t1 = t1.upperBound;
293 }
294
295 if (t1 == t2) return true;
296
297 // Trivially true.
298 if (_isTop(t2, dynamicIsBottom: dynamicIsBottom) ||
299 _isBottom(t1, dynamicIsBottom: dynamicIsBottom)) {
300 return true;
301 }
302
303 // Trivially false.
304 if (_isTop(t1, dynamicIsBottom: dynamicIsBottom) ||
305 _isBottom(t2, dynamicIsBottom: dynamicIsBottom)) {
306 return false;
307 }
308
309 // "Traditional" name-based subtype check.
310 final c1 = t1 as ClassMirror;
311 final c2 = t2 as ClassMirror;
312 if (_isClassSubType(c1, c2)) {
313 return true;
314 }
315
316 // Function subtyping.
317 // Note: it appears under the hood all Dart functions map to a class / hidden type
318 // that:
319 // (a) subtypes Object (an internal _FunctionImpl in the VM)
320 // (b) implements Function
321 // (c) provides standard Object members (hashCode, toString)
322 // (d) contains private members (corresponding to _FunctionImpl?)
323 // (e) provides a call method to handle the actual function invocation
324 //
325 // The standard Dart subtyping rules are structural in nature. I.e.,
326 // bivariant on arguments and return type.
327 //
328 // The below tries for a more traditional subtyping rule:
329 // - covariant on return type
330 // - contravariant on parameters
331 // - 'sensible' (?) rules on optional and/or named params
332 // but doesn't properly mix with class subtyping yet.
333 //
334 // Note, a class type that implements a call method implicitly subtypes
335 // the function type of the call method. However, the converse is not true:
336 // a function type does not subtype a class type with a call method.
337
338 // If c1 is not a proper function or a class type with call method,
339 // return false.
340 TypeMirror ret1;
341 List<ParameterMirror> params1;
342 // Note, a proper function has a call method, but it's not a regular method,
343 // so we break out the two cases.
344 if (c1 is FunctionTypeMirror) {
345 // Regular function
346 ret1 = c1.returnType;
347 params1 = c1.parameters;
348 } else {
349 var call1 = c1.instanceMembers[#call];
350 if (call1 == null || !call1.isRegularMethod) return false;
351 // Class that emulate a function
352 ret1 = call1.returnType;
353 params1 = call1.parameters;
354 }
355
356 // Any type that implements a call method implicitly subtypes Function.
357 if (_reflects(c2, Function)) return true;
358
359 // Check structural function subtyping
360 return _isFunctionSubType(ret1, params1, c2.returnType, c2.parameters);
361 }
OLDNEW
« no previous file with comments | « lib/runtime/dart_logging_runtime.dart ('k') | lib/src/codegen/dart_codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698