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

Unified Diff: frog/type.dart

Issue 10548047: Remove frog from the repository. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Move test and update apidoc.gyp. Created 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « frog/tree.g.dart ('k') | frog/utils.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: frog/type.dart
diff --git a/frog/type.dart b/frog/type.dart
deleted file mode 100644
index cd2b280e073a1e333d8eddfcf24bdd84a86aa189..0000000000000000000000000000000000000000
--- a/frog/type.dart
+++ /dev/null
@@ -1,1220 +0,0 @@
-// Copyright (c) 2011, 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.
-
-class Type extends Element {
- bool isTested = false;
- bool isChecked = false;
- bool isWritten = false;
-
- /**
- * For core types (int, String, etc) this is the generated type assertion
- * function (uses JS "typeof"). This field is null for all other types.
- */
- String typeCheckCode;
-
- Member _typeMember;
-
- /** Stubs used to call into this method dynamically. */
- Map<String, VarMember> varStubs;
-
- /** Cache of [Member]s that have been found. */
- Map<String, Member> _foundMembers;
-
- Type(String name): _foundMembers = {}, varStubs = {}, super(name, null);
-
- void markUsed() {}
- abstract void genMethod(Member method);
-
- TypeMember get typeMember() {
- if (_typeMember == null) {
- _typeMember = new TypeMember(this);
- }
- return _typeMember;
- }
-
- Member getMember(String name) => null;
- abstract MethodMember getConstructor(String name);
- abstract MethodMember getFactory(Type type, String name);
- abstract Type getOrMakeConcreteType(List<Type> typeArgs);
- abstract Map<String, MethodMember> get constructors();
- abstract addDirectSubtype(Type type);
- abstract bool get isClass();
- abstract Library get library();
- Set<Type> get subtypes() => null;
-
- // TODO(jmesserly): rename to isDynamic?
- bool get isVar() => false;
- bool get isTop() => false;
-
- bool get isObject() => false;
- bool get isString() => false;
- bool get isBool() => false;
- bool get isFunction() => false;
- bool get isNum() => false;
- bool get isInt() => false;
- bool get isDouble() => false;
- bool get isVoid() => false;
-
- // True for all types in the Dart type system. We track non-nullabiltity
- // as an optimization for booleans to generate better code in checked mode.
- bool get isNullable() => true;
-
- // Strangely Dart treats calls on Function much like calls on var.
- bool get isVarOrFunction() => isVar || isFunction;
-
- bool get isVarOrObject() => isVar || isObject;
-
- /** Gets the :call method for a function type. */
- MethodMember getCallMethod() => null;
-
- /** These types may not be implemented or extended by user code. */
- bool get isClosed() => isString || isBool || isNum || isFunction || isVar;
-
- bool get isUsed() => false;
-
- bool get isGeneric() => false;
-
- // Various special bits that we track on native types.
- // Generally controls how prototypes are emitted.
- NativeType get nativeType() => null;
- bool get isHiddenNativeType() =>
- (nativeType != null && nativeType.isConstructorHidden);
- bool get isSingletonNative() =>
- (nativeType != null && nativeType.isSingleton);
- bool get isJsGlobalObject() =>
- (nativeType != null && nativeType.isJsGlobalObject);
-
- bool get hasTypeParams() => false;
-
- String get typeofName() => null;
-
- String get fullname() =>
- library.name !== null ? '${library.name}.$name' : name;
-
- Map<String, Member> get members() => null;
- Definition get definition() => null;
- FactoryMap get factories() => null;
-
- List<Type> get typeArgsInOrder() => const [];
- DefinedType get genericType() => this;
-
- /** Indicates a concrete version of a generic type, such as List<String>. */
- bool get isConcreteGeneric() => genericType != this;
-
- // TODO(jmesserly): what should these do for ParameterType?
- List<Type> get interfaces() => null;
- Type get parent() => null;
-
- Map<String, Member> getAllMembers() => {};
-
- /** The native name of this element if it has one, otherwise the JS name. */
- String get nativeName() => isNative ? definition.nativeType.name : jsname;
-
- /**
- * Avoid the native name if hidden native. It might exist on some browsers
- * and we want to use it if it does.
- */
- bool get avoidNativeName() => isHiddenNativeType;
-
- bool _hasNativeSubtypes;
- bool get hasNativeSubtypes() {
- if (_hasNativeSubtypes == null) {
- _hasNativeSubtypes = subtypes.some((t) => t.isNative);
- }
- return _hasNativeSubtypes;
- }
-
- void _checkExtends() {
- var typeParams = genericType.typeParameters;
- if (typeParams != null) {
- for (int i = 0; i < typeParams.length; i++) {
- if (typeParams[i].extendsType != null) {
- // TODO(jimhug): This dynamic shouldn't be needed...
- typeArgsInOrder[i].dynamic.ensureSubtypeOf(typeParams[i].extendsType,
- typeParams[i].span, false);
- }
- }
- }
-
- // Parent should be handled by the super constructor call, but we still
- // need to check our interfaces.
- if (interfaces != null) {
- for (var i in interfaces) {
- i._checkExtends();
- }
- }
- }
-
- void _checkOverride(Member member) {
- // always look in parents to check that any overloads are legal
- var parentMember = _getMemberInParents(member.name);
- if (parentMember != null) {
- // TODO(jimhug): Ensure that this is only done once.
- if (!member.isPrivate || member.library == parentMember.library) {
- member.override(parentMember);
- }
- }
- }
-
- void _createNotEqualMember() {
- assert(isObject);
- // Add a != method just like the == one.
- MethodMember eq = members[':eq'];
- if (eq == null) {
- // TODO(jmesserly): should this be an error?
- // Frog is being hosted by "utils/css" such that it doesn't have its
- // standard lib initialized properly.
- return;
- }
- final ne = new MethodMember(':ne', this, eq.definition);
- ne.returnType = eq.returnType;
- ne.parameters = eq.parameters;
- ne.isStatic = eq.isStatic;
- ne.isAbstract = eq.isAbstract;
- // TODO - What else to fill in?
- members[':ne'] = ne;
- }
-
- Member _getMemberInParents(String memberName) {
- // print('getting $memberName in parents of $name, $isClass');
- // Now look in my parents.
- if (isClass) {
- if (parent != null) {
- return parent.getMember(memberName);
- } else {
- return null;
- }
- } else {
- // TODO(jimhug): Will probably check types more than once - errors?
- if (interfaces != null && interfaces.length > 0) {
- for (var i in interfaces) {
- var ret = i.getMember(memberName);
- if (ret != null) {
- return ret;
- }
- }
- }
- return world.objectType.getMember(memberName);
- }
- }
-
- void ensureSubtypeOf(Type other, SourceSpan span, [bool typeErrors=false]) {
- if (!isSubtypeOf(other)) {
- var msg = 'type $name is not a subtype of ${other.name}';
- if (typeErrors) {
- world.error(msg, span);
- } else {
- world.warning(msg, span);
- }
- }
- }
-
- /**
- * Returns true if we need to use our .call$N$names calling convention.
- * This is only needed for calls to Functions where we lack enough type info.
- */
- bool needsVarCall(Arguments args) {
- if (isVarOrFunction) {
- return true;
- }
-
- var call = getCallMethod();
- if (call != null) {
- // If the call doesn't fill in all arguments, or it doesn't use the right
- // named parameter order, we need to go through a "var" call because we
- // don't know what arguments the callee wants to fill in.
-
- // TODO(jmesserly): we could be smarter if the optional calls look
- // similar enough, which is probably true quite often in practice.
- if (args.length != call.parameters.length || !call.namesInOrder(args)) {
- return true;
- }
- }
-
- // Use a normal JS call, or not a function type.
- return false;
- }
-
- static Type union(Type x, Type y) {
- if (x == y) return x;
- if (x.isNum && y.isNum) return world.numType;
- if (x.isString && y.isString) return world.stringType;
-
- // TODO(jmesserly): make this more precise when we can. Or add UnionValue
- // and have Value do the heavy lifting of tracking sets of types.
- return world.varType;
- }
-
- // This is from the "Interface Types" section of the language spec:
-
- /**
- * A type T may be assigned to a type S, written T <=> S, i either T <: S
- * or S <: T.
- */
- bool isAssignable(Type other) {
- return isSubtypeOf(other) || other.isSubtypeOf(this);
- }
-
- /**
- * An interface I is a direct supertype of an interface J iff:
- * If I is Object, and J has no extends clause
- * if I is listed in the extends clause of J.
- */
- bool _isDirectSupertypeOf(Type other) {
- if (other.isClass) {
- return other.parent == this || isObject && other.parent == null;
- } else {
- if (other.interfaces == null || other.interfaces.isEmpty()) {
- return isObject;
- } else {
- return other.interfaces.some((i) => i == this);
- }
- }
- }
-
- /**
- * This implements the subtype operator <: defined in "Interface Types"
- * of the language spec. It's implemented in terms of the << "more specific"
- * operator. The spec is below:
- *
- * A type T is more specific than a type S, written T << S, if one of the
- * following conditions is met:
- * - T is S.
- * - T is Bottom.
- * - S is Dynamic.
- * - S is a direct supertype of T.
- * - T is a type variable and S is the upper bound of T.
- * - T is of the form I<T1,...,Tn> and S is of the form I<S1,...,Sn>
- * and: Ti << Si, 1 <= i <= n
- * - T << U and U << S.
- *
- * << is a partial order on types. T is a subtype of S, written T <: S, iff
- * [Bottom/Dynamic]T << S.
- */
- // TODO(jmesserly): this function could be expensive. Memoize results?
- // TODO(jmesserly): should merge this with the subtypes/directSubtypes
- // machinery? Possible issues: needing this during resolve(), integrating
- // the more accurate generics/function subtype handling.
- bool isSubtypeOf(Type other) {
- if (this == other) return true;
-
- // Note: the extra "isVar" check here is the difference between << and <:
- // Since we don't implement the << relation itself, we can just pretend
- // "null" literals are Dynamic and not worry about the Bottom type.
- if (isVar || other.isVar) return true;
- if (other._isDirectSupertypeOf(this)) return true;
-
- var call = getCallMethod();
- var otherCall = other.getCallMethod();
- if (call != null && otherCall != null) {
- return _isFunctionSubtypeOf(call, otherCall);
- }
-
- if (genericType === other.genericType) {
- // These must be true for matching generic types.
- assert(typeArgsInOrder.length == other.typeArgsInOrder.length);
-
- for (int i = 0; i < typeArgsInOrder.length; i++) {
- // Type args don't have subtype relationship
- // TODO(jimhug): This dynamic shouldn't be needed...
- if (!typeArgsInOrder[i].dynamic.isSubtypeOf(other.typeArgsInOrder[i])) {
- return false;
- }
- }
- return true;
- }
-
- // And now for some fun: T << U and U << S -> T << S
- // To implement this, we need to enumerate a set of types C such that
- // U will be an element of C. We can do this by either enumerating less
- // specific types of T, or more specific types of S.
- if (parent != null && parent.isSubtypeOf(other)) {
- return true;
- }
- if (interfaces != null && interfaces.some((i) => i.isSubtypeOf(other))) {
- return true;
- }
-
- // Unrelated types
- return false;
- }
-
- int hashCode() {
- var libraryCode = library == null ? 1 : library.hashCode();
- var nameCode = name == null ? 1 : name.hashCode();
- return (libraryCode << 4) ^ nameCode;
- }
-
- bool operator ==(other) =>
- other is Type && other.name == name && library == other.library;
-
- /**
- * A function type (T1,...,Tn, [Tx1 x1,..., Txk xk]) -> T is a subtype of the
- * function type (S1,...,Sn, [Sy1 y1,..., Sym ym]) -> S, if all of the
- * following conditions are met:
- * 1. Either:
- * - S is void, Or
- * - T <=> S.
- * 2. for all i in 1..n, Ti <=> Si
- * 3. k >= m and xi = yi, i is in 1..m. It is necessary, but not sufficient,
- * that the optional arguments of the subtype be a subset of those of the
- * supertype. We cannot treat them as just sets, because optional
- * arguments can be invoked positionally, so the order matters.
- * 4. For all y in {y1,..., ym}Sy <=> Ty
- * We write (T1,..., Tn) => T as a shorthand for the type (T1,...,Tn,[]) => T.
- * All functions implement the interface Function, so all function types are a
- * subtype of Function.
- */
- static bool _isFunctionSubtypeOf(MethodMember t, MethodMember s) {
- if (!s.returnType.isVoid && !s.returnType.isAssignable(t.returnType)) {
- return false; // incompatible return types
- }
-
- var tp = t.parameters;
- var sp = s.parameters;
-
- // Function subtype must have >= the total number of arguments
- if (tp.length < sp.length) return false;
-
- for (int i = 0; i < sp.length; i++) {
- // Mismatched required parameter count
- if (tp[i].isOptional != sp[i].isOptional) return false;
-
- // Mismatched optional parameter name
- if (tp[i].isOptional && tp[i].name != sp[i].name) return false;
-
- // Parameter types not assignable
- if (!tp[i].type.isAssignable(sp[i].type)) return false;
- }
-
- // Mismatched required parameter count
- if (tp.length > sp.length && !tp[sp.length].isOptional) return false;
-
- return true;
- }
-}
-
-
-/** A type parameter within the body of the type. */
-class ParameterType extends Type {
- TypeParameter typeParameter;
- Type extendsType;
-
- bool get isClass() => false;
- Library get library() => null; // TODO(jimhug): Make right...
- SourceSpan get span() => typeParameter.span;
-
- ParameterType(String name, this.typeParameter): super(name);
-
- Map<String, MethodMember> get constructors() {
- world.internalError('no constructors on type parameters yet');
- }
-
- MethodMember getCallMethod() => extendsType.getCallMethod();
-
- void genMethod(Member method) {
- extendsType.genMethod(method);
- }
-
- // TODO(jmesserly): should be like this:
- //bool isSubtypeOf(Type other) => extendsType.isSubtypeOf(other);
- bool isSubtypeOf(Type other) => true;
-
- MethodMember getConstructor(String constructorName) {
- world.internalError('no constructors on type parameters yet');
- }
-
- Type getOrMakeConcreteType(List<Type> typeArgs) {
- world.internalError('no concrete types of type parameters yet', span);
- }
-
- addDirectSubtype(Type type) {
- world.internalError('no subtypes of type parameters yet', span);
- }
-
- resolve() {
- if (typeParameter.extendsType != null) {
- extendsType =
- enclosingElement.resolveType(typeParameter.extendsType, true, true);
- } else {
- extendsType = world.objectType;
- }
- }
-}
-
-/**
- * Non-nullable type. Currently used for bools, so we can generate better
- * asserts in checked mode. Forwards almost all operations to its real type.
- */
-// NOTE: there's more work to do before this would work for types other than
-// bool.
-class NonNullableType extends Type {
-
- /** The corresponding nullable [Type]. */
- final Type type;
-
- NonNullableType(Type type): super(type.name), type = type;
-
- bool get isNullable() => false;
-
- // TODO(jmesserly): this would need to change if we support other types.
- bool get isBool() => type.isBool;
-
- // Treat it as unused so it doesn't get JS generated
- bool get isUsed() => false;
-
- // Augment our subtype rules with: non-nullable types are subtypes of
- // themselves, their corresponding nullable types, or anything that type is a
- // subtype of.
- bool isSubtypeOf(Type other) =>
- this == other || type == other || type.isSubtypeOf(other);
-
- // Forward everything. This is overkill for now; might be useful later.
- Type resolveType(TypeReference node, bool isRequired, bool allowTypeParams) =>
- type.resolveType(node, isRequired, allowTypeParams);
- void addDirectSubtype(Type subtype) { type.addDirectSubtype(subtype); }
- void markUsed() { type.markUsed(); }
- void genMethod(Member method) { type.genMethod(method); }
- SourceSpan get span() => type.span;
- Member getMember(String name) => type.getMember(name);
- MethodMember getConstructor(String name) => type.getConstructor(name);
- MethodMember getFactory(Type t, String name) => type.getFactory(t, name);
- Type getOrMakeConcreteType(List<Type> typeArgs) =>
- type.getOrMakeConcreteType(typeArgs);
- Map<String, MethodMember> get constructors() => type.constructors;
- bool get isClass() => type.isClass;
- Library get library() => type.library;
- MethodMember getCallMethod() => type.getCallMethod();
- bool get isGeneric() => type.isGeneric;
- bool get hasTypeParams() => type.hasTypeParams;
- String get typeofName() => type.typeofName;
- String get jsname() => type.jsname;
- Map<String, Member> get members() => type.members;
- Definition get definition() => type.definition;
- FactoryMap get factories() => type.factories;
- List<Type> get typeArgsInOrder() => type.typeArgsInOrder;
- DefinedType get genericType() => type.genericType;
- List<Type> get interfaces() => type.interfaces;
- Type get parent() => type.parent;
- Map<String, Member> getAllMembers() => type.getAllMembers();
- bool get isNative() => type.isNative;
-}
-
-
-/** Represents a Dart type defined as source code. */
-class DefinedType extends Type {
- // Not final so that we can fill this in for special types like List or num.
- Definition definition;
- final Library library;
- final bool isClass;
-
- // TODO(vsm): Restore the field once Issue 280 is fixed.
- // Type parent;
- Type _parent;
- Type get parent() => _parent;
- void set parent(Type p) { _parent = p; }
-
- List<Type> interfaces;
- DefinedType defaultType;
-
- Set<Type> directSubtypes;
- Set<Type> _subtypes;
-
- List<ParameterType> typeParameters;
- List<Type> typeArgsInOrder;
-
- Map<String, MethodMember> constructors;
- Map<String, Member> members;
- FactoryMap factories;
-
- Map<String, Type> _concreteTypes;
-
- /** Methods to be generated once we know for sure that the type is used. */
- Map<String, Member> _lazyGenMethods;
-
- bool isUsed = false;
- bool isNative = false;
-
- Type baseGenericType;
-
- DefinedType get genericType() =>
- baseGenericType === null ? this : baseGenericType;
-
-
- DefinedType(String name, this.library, Definition definition, this.isClass)
- : super(name), directSubtypes = new Set<Type>(), constructors = {},
- members = {}, factories = new FactoryMap() {
- setDefinition(definition);
- }
-
- void setDefinition(Definition def) {
- assert(definition == null);
- definition = def;
- if (definition is TypeDefinition && definition.nativeType != null) {
- isNative = true;
- }
- if (definition != null && definition.typeParameters != null) {
- _concreteTypes = {};
- typeParameters = definition.typeParameters;
- // TODO(jimhug): Should share these very generic lists better.
- typeArgsInOrder = new List(typeParameters.length);
- for (int i=0; i < typeArgsInOrder.length; i++) {
- typeArgsInOrder[i] = world.varType;
- }
- } else {
- typeArgsInOrder = const [];
- }
- }
-
- NativeType get nativeType() =>
- (definition != null ? definition.nativeType : null);
-
- bool get isVar() => this == world.varType;
- bool get isVoid() => this == world.voidType;
-
- /** Is this the type that holds onto top-level code for its library? **/
- bool get isTop() => name == null;
-
- // TODO(jimhug) -> this == world.objectType, etc.
- bool get isObject() => this == world.objectType;
-
- // TODO(jimhug): Really hating on the interface + impl pattern by now...
- bool get isString() => this == world.stringType ||
- this == world.stringImplType;
-
- // TODO(jimhug): Where is boolImplType?
- bool get isBool() => this == world.boolType;
- bool get isFunction() => this == world.functionType ||
- this == world.functionImplType;
-
- bool get isGeneric() => typeParameters != null;
-
- SourceSpan get span() => definition == null ? null : definition.span;
-
-
- String get typeofName() {
- if (!library.isCore) return null;
-
- if (isBool) return 'boolean';
- else if (isNum) return 'number';
- else if (isString) return 'string';
- else if (isFunction) return 'function';
- else return null;
- }
-
- // TODO(jimhug): Reconcile different number types on JS.
- bool get isNum() {
- return this == world.numType || this == world.intType ||
- this == world.doubleType || this == world.numImplType;
- }
-
- bool get isInt() => this == world.intType;
- bool get isDouble() => this == world.doubleType;
-
- // TODO(jimhug): Understand complicated generics here...
- MethodMember getCallMethod() => genericType.members[':call'];
-
- Map<String, Member> getAllMembers() => new Map.from(members);
-
- void markUsed() {
- if (isUsed) return;
-
- isUsed = true;
-
- _checkExtends();
-
- if (_lazyGenMethods != null) {
- for (var method in orderValuesByKeys(_lazyGenMethods)) {
- world.gen.genMethod(method);
- }
- _lazyGenMethods = null;
- }
-
- if (parent != null) parent.markUsed();
- }
-
- void genMethod(Member method) {
- // TODO(jimhug): Remove baseGenericType check from here.
- if (isUsed || baseGenericType != null) {
- world.gen.genMethod(method);
- } else if (isClass) {
- if (_lazyGenMethods == null) _lazyGenMethods = {};
- _lazyGenMethods[method.name] = method;
- }
- }
-
- List<Type> _resolveInterfaces(List<TypeReference> types) {
- if (types == null) return [];
- var interfaces = [];
- for (final type in types) {
- var resolvedInterface = resolveType(type, true, true);
- if (resolvedInterface.isClosed &&
- !(library.isCore || library.isCoreImpl)) {
- world.error(
- 'cannot implement "${resolvedInterface.name}": '
- 'only native implementation allowed', type.span);
- }
- resolvedInterface.addDirectSubtype(this);
- // TODO(jimhug): if (resolveInterface.isClass) may need special handling.
- interfaces.add(resolvedInterface);
- }
- return interfaces;
- }
-
- addDirectSubtype(Type type) {
- directSubtypes.add(type);
- // TODO(jimhug): Shouldn't need this in both places.
- if (baseGenericType != null) {
- baseGenericType.addDirectSubtype(type);
- }
- }
-
- Set<Type> get subtypes() {
- if (_subtypes == null) {
- _subtypes = new Set<Type>();
- for (var st in directSubtypes) {
- _subtypes.add(st);
- _subtypes.addAll(st.subtypes);
- }
- }
- return _subtypes;
- }
-
- /** Check whether this class has a cycle in its inheritance chain. */
- bool _cycleInClassExtends() {
- final seen = new Set();
- seen.add(this);
- var ancestor = parent;
- while (ancestor != null) {
- if (ancestor === this) {
- return true;
- }
- if (seen.contains(ancestor)) {
- // there is a cycle above, but [this] is not part of it
- return false;
- }
- seen.add(ancestor);
- ancestor = ancestor.parent;
- }
- return false;
- }
-
- /**
- * Check whether this interface has a cycle in its inheritance chain. If so,
- * returns which of the parent interfaces creates the cycle (for error
- * reporting).
- */
- int _cycleInInterfaceExtends() {
- final seen = new Set();
- seen.add(this);
-
- bool _helper(var ancestor) {
- if (ancestor == null) return false;
- if (ancestor === this) return true;
- if (seen.contains(ancestor)) {
- // this detects both cycles and DAGs with interfaces not involving
- // [this]. In the case of cycles, we won't report an error here (but
- // where the cycle was first detected), with DAGs we just take advantage
- // that we detected it to avoid traversing twice.
- return false;
- }
- seen.add(ancestor);
- if (ancestor.interfaces != null) {
- for (final parent in ancestor.interfaces) {
- if (_helper(parent)) return true;
- }
- }
- return false;
- }
-
- for (int i = 0; i < interfaces.length; i++) {
- if (_helper(interfaces[i])) return i;
- }
- return -1;
- }
-
- resolve() {
- if (definition is TypeDefinition) {
- TypeDefinition typeDef = definition;
- if (isClass) {
- if (typeDef.extendsTypes != null && typeDef.extendsTypes.length > 0) {
- if (typeDef.extendsTypes.length > 1) {
- world.error('more than one base class',
- typeDef.extendsTypes[1].span);
- }
- var extendsTypeRef = typeDef.extendsTypes[0];
- if (extendsTypeRef is GenericTypeReference) {
- // TODO(jimhug): Understand and verify comment below.
- // If we are extending a generic type first resolve against the
- // base type, then the full generic type. This makes circular
- // "extends" checks on generic type args work correctly.
- GenericTypeReference g = extendsTypeRef;
- parent = resolveType(g.baseType, true, true);
- }
- parent = resolveType(extendsTypeRef, true, true);
- if (!parent.isClass) {
- world.error('class may not extend an interface - use implements',
- typeDef.extendsTypes[0].span);
- }
- parent.addDirectSubtype(this);
- if (_cycleInClassExtends()) {
- world.error('class "$name" has a cycle in its inheritance chain',
- extendsTypeRef.span);
- }
- } else {
- if (!isObject) {
- // Object is the default parent for everthing except Object.
- parent = world.objectType;
- parent.addDirectSubtype(this);
- }
- }
- this.interfaces = _resolveInterfaces(typeDef.implementsTypes);
- if (typeDef.defaultType != null) {
- world.error('default not allowed on classes',
- typeDef.defaultType.span);
- }
- } else {
- if (typeDef.implementsTypes != null &&
- typeDef.implementsTypes.length > 0) {
- world.error('implements not allowed on interfaces (use extends)',
- typeDef.implementsTypes[0].span);
- }
- this.interfaces = _resolveInterfaces(typeDef.extendsTypes);
- final res = _cycleInInterfaceExtends();
- if (res >= 0) {
- world.error('interface "$name" has a cycle in its inheritance chain',
- typeDef.extendsTypes[res].span);
- }
-
- if (typeDef.defaultType != null) {
- defaultType = resolveType(typeDef.defaultType.baseType, true, true);
- if (defaultType == null) {
- // TODO(jimhug): Appropriate warning levels;
- world.warning('unresolved default class', typeDef.defaultType.span);
- } else {
- if (baseGenericType != null) {
- if (!defaultType.isGeneric) {
- world.error('default type of generic interface must be generic',
- typeDef.defaultType.span);
- }
- defaultType = defaultType.getOrMakeConcreteType(typeArgsInOrder);
- }
- }
- }
- }
- } else if (definition is FunctionTypeDefinition) {
- // Function types implement the Function interface.
- this.interfaces = [world.functionType];
- }
-
- _resolveTypeParams(typeParameters);
-
- if (isObject) _createNotEqualMember();
-
- // Concrete specializations of ListFactory === Array are never actually
- // created as the performance suffers too badly in most JS engines.
- if (baseGenericType != world.listFactoryType) world._addType(this);
-
- for (var c in constructors.getValues()) c.resolve();
- for (var m in members.getValues()) m.resolve();
- factories.forEach((f) => f.resolve());
-
- // All names from the JS global object need to be treated as top-level
- // native names, so we don't clobber them with other Dart top-level names.
- if (isJsGlobalObject) {
- for (var m in members.getValues()) {
- if (!m.isStatic) world._addTopName(new ExistingJsGlobal(m.name, m));
- }
- }
- }
-
- _resolveTypeParams(List<ParameterType> params) {
- if (params == null) return;
- for (var tp in params) {
- tp.enclosingElement = this;
- tp.resolve();
- }
- }
-
- addMethod(String methodName, FunctionDefinition definition) {
- if (methodName == null) methodName = definition.name.name;
-
- var method = new MethodMember(methodName, this, definition);
-
- if (method.isConstructor) {
- if (constructors.containsKey(method.constructorName)) {
- world.error('duplicate constructor definition of ${method.name}',
- definition.span);
- return;
- }
- constructors[method.constructorName] = method;
- return;
- }
-
- if (definition.modifiers != null
- && definition.modifiers.length == 1
- && definition.modifiers[0].kind == TokenKind.FACTORY) {
- // constructorName for a factory is the type.
- if (factories.getFactory(method.constructorName, method.name) != null) {
- world.error('duplicate factory definition of "${method.name}"',
- definition.span);
- return;
- }
- factories.addFactory(method.constructorName, method.name, method);
- return;
- }
-
- if (methodName.startsWith('get:') || methodName.startsWith('set:')) {
- var propName = methodName.substring(4);
- var prop = members[propName];
- if (prop == null) {
- prop = new PropertyMember(propName, this);
- members[propName] = prop;
- }
- if (prop is! PropertyMember) {
- world.error('property conflicts with field "$propName"',
- definition.span);
- return;
- }
- if (methodName[0] == 'g') {
- if (prop.getter != null) {
- world.error('duplicate getter definition for "$propName"',
- definition.span);
- }
- // TODO(jimhug): Validate zero parameters
- prop.getter = method;
- } else {
- if (prop.setter != null) {
- world.error('duplicate setter definition for "$propName"',
- definition.span);
- }
- // TODO(jimhug): Validate one parameters - match with getter?
- prop.setter = method;
- }
- return;
- }
-
- if (members.containsKey(methodName)) {
- world.error('duplicate method definition of "${method.name}"',
- definition.span);
- return;
- }
- members[methodName] = method;
- }
-
- addField(VariableDefinition definition) {
- for (int i=0; i < definition.names.length; i++) {
- var name = definition.names[i].name;
- if (members.containsKey(name)) {
- world.error('duplicate field definition of "$name"',
- definition.span);
- return;
- }
- var value = null;
- if (definition.values != null) {
- value = definition.values[i];
- }
- var field =
- new FieldMember(name, this, definition, value, isNative: isNative);
- members[name] = field;
- }
- }
-
- getFactory(Type type, String constructorName) {
- if (baseGenericType != null) {
- var rr = baseGenericType.factories.getFactory(type.genericType.name,
- constructorName);
- if (rr != null) {
- // TODO(jimhug): Understand and fix this case.
- world.info(
- 'need to remap factory on ${name} from ${rr.declaringType.name}');
- return rr;
- } else {
- var ret = getConstructor(constructorName);
- return ret;
- }
- }
-
- // Try to find factory method with the given type.
- // TODO(jimhug): Use jsname as key here or something better?
- var ret = factories.getFactory(type.genericType.name, constructorName);
- if (ret != null) return ret;
-
- // TODO(ngeoffray): Here we should actually check if the current
- // type implements the given type.
- // Try to find a factory method of this type.
- ret = factories.getFactory(name, constructorName);
- if (ret != null) return ret;
-
- // Try to find a generative constructor of this type.
- ret = constructors[constructorName];
- if (ret != null) return ret;
-
- return _tryCreateDefaultConstructor(constructorName);
- }
-
-
- getConstructor(String constructorName) {
- // cheat and reuse constructors here to be any resolved cons...
- if (baseGenericType != null) {
- var rr = constructors[constructorName];
- if (rr != null) return rr;
-
- rr = baseGenericType.constructors[constructorName];
- if (rr != null) {
- if (defaultType != null) {
- var ret = defaultType.getFactory(this, constructorName);
- return ret;
- }
- } else {
- rr = baseGenericType.factories.getFactory(baseGenericType.name,
- constructorName);
- }
- if (rr == null) {
- rr = baseGenericType.dynamic._tryCreateDefaultConstructor(
- constructorName);
- }
- if (rr == null) return null;
-
- // re-resolve rr in this
- var rr1 = rr.makeConcrete(this);
- rr1.resolve();
-
- constructors[constructorName] = rr1;
- return rr1;
- }
-
-
- var ret = constructors[constructorName];
- if (ret != null) {
- if (defaultType != null) {
- return defaultType.getFactory(this, constructorName);
- }
- return ret;
- }
- ret = factories.getFactory(name, constructorName);
- if (ret != null) return ret;
-
- return _tryCreateDefaultConstructor(constructorName);
- }
-
- // TODO(jimhug): Can we remove this with version in resolve + new spec?
- /**
- * Checks that default type parameters match between all 3 locations:
- * 1. the interface (this)
- * 2. the "default" type parameters
- * 3. the class's type parameters
- *
- * The only deviation is that 2 and 3 can have a tighter "extends" bound.
- */
- _checkDefaultTypeParams() {
- // Convert null to empty list so it doesn't complicate the logic
- List<ParameterType> toList(list) => (list != null ? list : const []);
-
- TypeDefinition typeDef = definition;
- if (typeDef.defaultType.oldFactory) {
- // TODO(jmesserly): for now skip checking of old factories
- return;
- }
-
- var interfaceParams = toList(typeParameters);
- var defaultParams = toList(typeDef.defaultType.typeParameters);
- var classParams = toList(defaultType.typeParameters);
-
- if (interfaceParams.length != defaultParams.length
- || defaultParams.length != classParams.length) {
- world.error('"default" must have the same number of type parameters as '
- + 'the class and interface do', span, typeDef.defaultType.span,
- defaultType.span);
- return;
- }
-
- for (int i = 0; i < interfaceParams.length; i++) {
- var ip = interfaceParams[i];
- var dp = defaultParams[i];
- var cp = classParams[i];
- dp.resolve();
- if (ip.name != dp.name || dp.name != cp.name) {
- world.error('default class must have the same type parameter names as '
- + 'the class and interface', ip.span, dp.span, cp.span);
- } else if (dp.extendsType != cp.extendsType) {
- world.error('default class type parameters must have the same extends '
- + 'as the class does', dp.span, cp.span);
- } else if (!dp.extendsType.isSubtypeOf(ip.extendsType)) {
- // TODO(jmesserly): left this as a warning; it seems harmless to me
- world.warning('"default" can only have tighter type parameter "extends"'
- + ' than the interface', dp.span, ip.span);
- }
- }
- }
-
- _tryCreateDefaultConstructor(String name) {
- // Check if we can create a default constructor.
- if (name == '' && definition != null && isClass &&
- constructors.length == 0) {
- var span = definition.span;
-
- var inits = null, native = null, body = null;
- if (isNative) {
- native = '';
- inits = null;
- } else {
- body = null;
- inits = [new CallExpression(new SuperExpression(span), [], span)];
- }
-
- TypeDefinition typeDef = definition;
- var c = new FunctionDefinition(null, null, typeDef.name, [],
- inits, native, body, span);
- addMethod(null, c);
- constructors[''].resolve();
- return constructors[''];
- }
- return null;
- }
-
- Member getMember(String memberName) {
- Member member = _foundMembers[memberName];
- if (member != null) return member;
-
- if (baseGenericType != null) {
- member = baseGenericType.getMember(memberName);
- // TODO(jimhug): Need much more elaborate lookup duplication here <frown>
-
- if (member == null) return null;
-
- // TODO(jimhug): There will be a few of these we need to specialize for
- // type params, skipping anything not on my direct super is not accurate
- if (member.isStatic || member.declaringType != baseGenericType) {
- _foundMembers[memberName] = member;
- return member;
- }
-
-
- var rr = member.makeConcrete(this);
- if (member.definition !== null || member is PropertyMember) {
- rr.resolve();
- } else {
- world.info('no definition for ${member.name} on ${name}');
- }
- // TODO(jimhug): Why do I need to put this in both maps?
- members[memberName] = rr;
- _foundMembers[memberName] = rr;
- return rr;
- }
-
- member = members[memberName];
- if (member != null) {
- _checkOverride(member);
- _foundMembers[memberName] = member;
- return member;
- }
-
- if (isTop) {
- // Let's pretend classes are members of the top-level library type
- // TODO(jmesserly): using "this." to workaround a VM bug with abstract
- // getters.
- var libType = this.library.findTypeByName(memberName);
- if (libType != null) {
- member = libType.typeMember;
- _foundMembers[memberName] = member;
- return member;
- }
- }
-
- member = _getMemberInParents(memberName);
- _foundMembers[memberName] = member;
- return member;
- }
-
- Type getOrMakeConcreteType(List<Type> typeArgs) {
- assert(isGeneric);
- var jsnames = [];
- var names = [];
- var typeMap = {};
- bool allVar = true;
- for (int i=0; i < typeArgs.length; i++) {
- var typeArg = typeArgs[i];
- if (typeArg is ParameterType) {
- typeArg = world.varType;
- typeArgs[i] = typeArg;
- }
- if (!typeArg.isVar) allVar = false;
-
- var paramName = typeParameters[i].name;
- typeMap[paramName] = typeArg;
- names.add(typeArg.fullname);
- jsnames.add(typeArg.jsname);
- }
-
- // If all type args are var or effectively var, just return this
- if (allVar) return this;
-
- var jsname = '${jsname}_${Strings.join(jsnames, '\$')}';
- var simpleName = '${name}<${Strings.join(names, ', ')}>';
-
- var ret = _concreteTypes[simpleName];
- if (ret == null) {
- ret = new DefinedType(simpleName, library, definition, isClass);
- ret.baseGenericType = this;
- ret.typeArgsInOrder = typeArgs;
- ret._jsname = jsname;
- _concreteTypes[simpleName] = ret;
- ret.resolve();
- }
- return ret;
- }
-
- VarFunctionStub getCallStub(Arguments args) {
- assert(isFunction);
-
- var name = _getCallStubName('call', args);
- var stub = varStubs[name];
- if (stub == null) {
- stub = new VarFunctionStub(name, args);
- varStubs[name] = stub;
- }
- return stub;
- }
-}
-
-/**
- * Information about a native type from the native string.
- *
- * "Foo" - constructor function is called 'Foo'.
- * "=Foo" - a singleton instance that should be patched directly. For example,
- * "=window.console"
- * "*Foo" - name is 'Foo', constructor function and prototype are not available
- * in global scope during initialization. This is characteristic of many
- * DOM types like CanvasPixelArray. However, the *type name* is presumed to
- * be available at runtime from the prototype.
- * "@Foo" - the type of the global object. Members will be treated as names
- * that can't be shadowed in generated JS.
- */
-// TODO(jmesserly): we really need a richer annotation system than just encoding
-// this data in strings with magic characters.
-class NativeType {
- String name;
- bool isConstructorHidden = false;
- bool isJsGlobalObject = false;
- bool isSingleton = false;
-
- NativeType(this.name) {
- while (true) {
- if (name.startsWith('@')) {
- name = name.substring(1);
- isJsGlobalObject = true;
- } else if (name.startsWith('*')) {
- name = name.substring(1);
- isConstructorHidden = true;
- } else {
- break;
- }
- }
- if (name.startsWith('=')) {
- name = name.substring(1);
- isSingleton = true;
- }
- }
-}
« no previous file with comments | « frog/tree.g.dart ('k') | frog/utils.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698