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

Unified Diff: sdk/lib/_internal/compiler/implementation/native/behavior.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/native/behavior.dart
diff --git a/sdk/lib/_internal/compiler/implementation/native/behavior.dart b/sdk/lib/_internal/compiler/implementation/native/behavior.dart
deleted file mode 100644
index 328f42594b20560f745bf85ad738c345dfaf97b0..0000000000000000000000000000000000000000
--- a/sdk/lib/_internal/compiler/implementation/native/behavior.dart
+++ /dev/null
@@ -1,438 +0,0 @@
-// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-part of native;
-
-/// This class is a temporary work-around until we get a more powerful DartType.
-class SpecialType {
-final String name;
-const SpecialType._(this.name);
-
-/// The type Object, but no subtypes:
-static const JsObject = const SpecialType._('=Object');
-
-int get hashCode => name.hashCode;
-}
-
-/**
- * A summary of the behavior of a native element.
- *
- * Native code can return values of one type and cause native subtypes of
- * another type to be instantiated. By default, we compute both from the
- * declared type.
- *
- * A field might yield any native type that 'is' the field type.
- *
- * A method might create and return instances of native subclasses of its
- * declared return type, and a callback argument may be called with instances of
- * the callback parameter type (e.g. Event).
- *
- * If there is one or more `@Creates` annotations, the union of the named types
- * replaces the inferred instantiated type, and the return type is ignored for
- * the purpose of inferring instantiated types.
- *
- * @Creates('IDBCursor') // Created asynchronously.
- * @Creates('IDBRequest') // Created synchronously (for return value).
- * IDBRequest openCursor();
- *
- * If there is one or more `@Returns` annotations, the union of the named types
- * replaces the declared return type.
- *
- * @Returns('IDBRequest')
- * IDBRequest openCursor();
- *
- * Types in annotations are non-nullable, so include `@Returns('Null')` if
- * `null` may be returned.
- */
-class NativeBehavior {
-
- /// [DartType]s or [SpecialType]s returned or yielded by the native element.
- final List typesReturned = [];
-
- /// [DartType]s or [SpecialType]s instantiated by the native element.
- final List typesInstantiated = [];
-
- // If this behavior is for a JS expression, [codeTemplate] contains the
- // parsed tree.
- js.Template codeTemplate;
-
- final SideEffects sideEffects = new SideEffects.empty();
-
- static NativeBehavior NONE = new NativeBehavior();
-
- /// Processes the type specification string of a call to JS and stores the
- /// result in the [typesReturned] and [typesInstantiated].
- ///
- /// Two forms of the string is supported:
- /// 1) A single type string of the form 'void', '', 'var' or 'T1|...|Tn'
- /// which defines the types returned and for the later form also created by
- /// the call to JS.
- /// 2) A sequence of the form '<tag>:<type-string>;' where <tag> is either
- /// 'returns' or 'creates' and where <type-string> is a type string like in
- /// 1). The type string marked by 'returns' defines the types returned and
- /// 'creates' defines the types created by the call to JS. Each tag kind
- /// can only occur once in the sequence.
- ///
- /// [specString] is the specification string, [resolveType] resolves named
- /// types into type values, [typesReturned] and [typesInstantiated] collects
- /// the types defined by the specification string, and [objectType] and
- /// [nullType] define the types for `Object` and `Null`, respectively. The
- /// latter is used for the type strings of the form '' and 'var'.
- // TODO(johnniwinther): Use ';' as a separator instead of a terminator.
- static void processSpecString(
- DiagnosticListener listener,
- Spannable spannable,
- String specString,
- {dynamic resolveType(String typeString),
- List typesReturned, List typesInstantiated,
- objectType, nullType}) {
-
- /// Resolve a type string of one of the three forms:
- /// * 'void' - in which case [onVoid] is called,
- /// * '' or 'var' - in which case [onVar] is called,
- /// * 'T1|...|Tn' - in which case [onType] is called for each Ti.
- void resolveTypesString(String typesString,
- {onVoid(), onVar(), onType(type)}) {
- // Various things that are not in fact types.
- if (typesString == 'void') {
- if (onVoid != null) {
- onVoid();
- }
- return;
- }
- if (typesString == '' || typesString == 'var') {
- if (onVar != null) {
- onVar();
- }
- return;
- }
- for (final typeString in typesString.split('|')) {
- onType(resolveType(typeString));
- }
- }
-
- if (specString.contains(':')) {
- /// Find and remove a substring of the form 'tag:<type-string>;' from
- /// [specString].
- String getTypesString(String tag) {
- String marker = '$tag:';
- int startPos = specString.indexOf(marker);
- if (startPos == -1) return null;
- int endPos = specString.indexOf(';', startPos);
- if (endPos == -1) return null;
- String typeString =
- specString.substring(startPos + marker.length, endPos);
- specString = '${specString.substring(0, startPos)}'
- '${specString.substring(endPos + 1)}'.trim();
- return typeString;
- }
-
- String returns = getTypesString('returns');
- if (returns != null) {
- resolveTypesString(returns, onVar: () {
- typesReturned.add(objectType);
- typesReturned.add(nullType);
- }, onType: (type) {
- typesReturned.add(type);
- });
- }
-
- String creates = getTypesString('creates');
- if (creates != null) {
- resolveTypesString(creates, onVoid: () {
- listener.internalError(spannable,
- "Invalid type string 'creates:$creates'");
- }, onVar: () {
- listener.internalError(spannable,
- "Invalid type string 'creates:$creates'");
- }, onType: (type) {
- typesInstantiated.add(type);
- });
- }
-
- if (!specString.isEmpty) {
- listener.internalError(spannable, "Invalid JS type string.");
- }
- } else {
- resolveTypesString(specString, onVar: () {
- typesReturned.add(objectType);
- typesReturned.add(nullType);
- }, onType: (type) {
- typesInstantiated.add(type);
- typesReturned.add(type);
- });
- }
- }
-
- static NativeBehavior ofJsCall(Send jsCall, Compiler compiler, resolver) {
- // The first argument of a JS-call is a string encoding various attributes
- // of the code.
- //
- // 'Type1|Type2'. A union type.
- // '=Object'. A JavaScript Object, no subtype.
-
- var argNodes = jsCall.arguments;
- if (argNodes.isEmpty) {
- compiler.internalError(jsCall, "JS expression has no type.");
- }
-
- var code = argNodes.tail.head;
- if (code is !StringNode || code.isInterpolation) {
- compiler.internalError(code, 'JS code must be a string literal.');
- }
-
- LiteralString specLiteral = argNodes.head.asLiteralString();
- if (specLiteral == null) {
- // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It
- // is not very satisfactory because it does not work for void, dynamic.
- compiler.internalError(argNodes.head, "Unexpected JS first argument.");
- }
-
- NativeBehavior behavior = new NativeBehavior();
- behavior.codeTemplate =
- js.js.parseForeignJS(code.dartString.slowToString());
- new SideEffectsVisitor(behavior.sideEffects)
- .visit(behavior.codeTemplate.ast);
-
- String specString = specLiteral.dartString.slowToString();
-
- resolveType(String typeString) {
- return _parseType(
- typeString,
- compiler,
- (name) => resolver.resolveTypeFromString(specLiteral, name),
- jsCall);
- }
-
- processSpecString(compiler, jsCall,
- specString,
- resolveType: resolveType,
- typesReturned: behavior.typesReturned,
- typesInstantiated: behavior.typesInstantiated,
- objectType: compiler.objectClass.computeType(compiler),
- nullType: compiler.nullClass.computeType(compiler));
-
- return behavior;
- }
-
- static NativeBehavior ofJsEmbeddedGlobalCall(Send jsGlobalCall,
- Compiler compiler,
- resolver) {
- // The first argument of a JS-embedded global call is a string encoding
- // the type of the code.
- //
- // 'Type1|Type2'. A union type.
- // '=Object'. A JavaScript Object, no subtype.
-
- Link<Node> argNodes = jsGlobalCall.arguments;
- if (argNodes.isEmpty) {
- compiler.internalError(jsGlobalCall,
- "JS embedded global expression has no type.");
- }
-
- // We don't check the given name. That needs to be done at a later point.
- // This is, because we want to allow non-literals as names.
- if (argNodes.tail.isEmpty) {
- compiler.internalError(jsGlobalCall, 'Embedded Global is missing name');
- }
-
- if (!argNodes.tail.tail.isEmpty) {
- compiler.internalError(argNodes.tail.tail.head,
- 'Embedded Global has more than 2 arguments');
- }
-
- LiteralString specLiteral = argNodes.head.asLiteralString();
- if (specLiteral == null) {
- // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It
- // is not very satisfactory because it does not work for void, dynamic.
- compiler.internalError(argNodes.head, "Unexpected first argument.");
- }
-
- NativeBehavior behavior = new NativeBehavior();
-
- String specString = specLiteral.dartString.slowToString();
-
- resolveType(String typeString) {
- return _parseType(
- typeString,
- compiler,
- (name) => resolver.resolveTypeFromString(specLiteral, name),
- jsGlobalCall);
- }
-
- processSpecString(compiler, jsGlobalCall,
- specString,
- resolveType: resolveType,
- typesReturned: behavior.typesReturned,
- typesInstantiated: behavior.typesInstantiated,
- objectType: compiler.objectClass.computeType(compiler),
- nullType: compiler.nullClass.computeType(compiler));
-
- return behavior;
- }
-
- static NativeBehavior ofMethod(FunctionElement method, Compiler compiler) {
- FunctionType type = method.computeType(compiler);
- var behavior = new NativeBehavior();
- behavior.typesReturned.add(type.returnType);
- if (!type.returnType.isVoid) {
- // Declared types are nullable.
- behavior.typesReturned.add(compiler.nullClass.computeType(compiler));
- }
- behavior._capture(type, compiler);
-
- // TODO(sra): Optional arguments are currently missing from the
- // DartType. This should be fixed so the following work-around can be
- // removed.
- method.functionSignature.forEachOptionalParameter(
- (ParameterElement parameter) {
- behavior._escape(parameter.type, compiler);
- });
-
- behavior._overrideWithAnnotations(method, compiler);
- return behavior;
- }
-
- static NativeBehavior ofFieldLoad(Element field, Compiler compiler) {
- DartType type = field.computeType(compiler);
- var behavior = new NativeBehavior();
- behavior.typesReturned.add(type);
- // Declared types are nullable.
- behavior.typesReturned.add(compiler.nullClass.computeType(compiler));
- behavior._capture(type, compiler);
- behavior._overrideWithAnnotations(field, compiler);
- return behavior;
- }
-
- static NativeBehavior ofFieldStore(Element field, Compiler compiler) {
- DartType type = field.computeType(compiler);
- var behavior = new NativeBehavior();
- behavior._escape(type, compiler);
- // We don't override the default behaviour - the annotations apply to
- // loading the field.
- return behavior;
- }
-
- void _overrideWithAnnotations(Element element, Compiler compiler) {
- if (element.metadata.isEmpty) return;
-
- DartType lookup(String name) {
- Element e = element.buildScope().lookup(name);
- if (e == null) return null;
- if (e is! ClassElement) return null;
- ClassElement cls = e;
- cls.ensureResolved(compiler);
- return cls.thisType;
- }
-
- NativeEnqueuer enqueuer = compiler.enqueuer.resolution.nativeEnqueuer;
- var creates = _collect(element, compiler, enqueuer.annotationCreatesClass,
- lookup);
- var returns = _collect(element, compiler, enqueuer.annotationReturnsClass,
- lookup);
-
- if (creates != null) {
- typesInstantiated..clear()..addAll(creates);
- }
- if (returns != null) {
- typesReturned..clear()..addAll(returns);
- }
- }
-
- /**
- * Returns a list of type constraints from the annotations of
- * [annotationClass].
- * Returns `null` if no constraints.
- */
- static _collect(Element element, Compiler compiler, Element annotationClass,
- lookup(str)) {
- var types = null;
- for (Link<MetadataAnnotation> link = element.metadata;
- !link.isEmpty;
- link = link.tail) {
- MetadataAnnotation annotation = link.head.ensureResolved(compiler);
- ConstantValue value = annotation.constant.value;
- if (!value.isConstructedObject) continue;
- ConstructedConstantValue constructedObject = value;
- if (constructedObject.type.element != annotationClass) continue;
-
- List<ConstantValue> fields = constructedObject.fields;
- // TODO(sra): Better validation of the constant.
- if (fields.length != 1 || !fields[0].isString) {
- PartialMetadataAnnotation partial = annotation;
- compiler.internalError(annotation,
- 'Annotations needs one string: ${partial.parseNode(compiler)}');
- }
- StringConstantValue specStringConstant = fields[0];
- String specString = specStringConstant.toDartString().slowToString();
- for (final typeString in specString.split('|')) {
- var type = _parseType(typeString, compiler, lookup, annotation);
- if (types == null) types = [];
- types.add(type);
- }
- }
- return types;
- }
-
- /// Models the behavior of having intances of [type] escape from Dart code
- /// into native code.
- void _escape(DartType type, Compiler compiler) {
- type = type.unalias(compiler);
- if (type is FunctionType) {
- FunctionType functionType = type;
- // A function might be called from native code, passing us novel
- // parameters.
- _escape(functionType.returnType, compiler);
- for (DartType parameter in functionType.parameterTypes) {
- _capture(parameter, compiler);
- }
- }
- }
-
- /// Models the behavior of Dart code receiving instances and methods of [type]
- /// from native code. We usually start the analysis by capturing a native
- /// method that has been used.
- void _capture(DartType type, Compiler compiler) {
- type = type.unalias(compiler);
- if (type is FunctionType) {
- FunctionType functionType = type;
- _capture(functionType.returnType, compiler);
- for (DartType parameter in functionType.parameterTypes) {
- _escape(parameter, compiler);
- }
- } else {
- typesInstantiated.add(type);
- }
- }
-
- static _parseType(String typeString, Compiler compiler,
- lookup(name), locationNodeOrElement) {
- if (typeString == '=Object') return SpecialType.JsObject;
- if (typeString == 'dynamic') {
- return const DynamicType();
- }
- DartType type = lookup(typeString);
- if (type != null) return type;
-
- int index = typeString.indexOf('<');
- if (index < 1) {
- compiler.internalError(
- _errorNode(locationNodeOrElement, compiler),
- "Type '$typeString' not found.");
- }
- type = lookup(typeString.substring(0, index));
- if (type != null) {
- // TODO(sra): Parse type parameters.
- return type;
- }
- compiler.internalError(
- _errorNode(locationNodeOrElement, compiler),
- "Type '$typeString' not found.");
- }
-
- static _errorNode(locationNodeOrElement, compiler) {
- if (locationNodeOrElement is Node) return locationNodeOrElement;
- return locationNodeOrElement.parseNode(compiler);
- }
-}

Powered by Google App Engine
This is Rietveld 408576698