| Index: frog/type.dart
|
| diff --git a/frog/type.dart b/frog/type.dart
|
| index 70795fbf45d259dce0e20804384ef299a92a1097..82448e7005ceda5e43d873f0df78b8fcc25f2327 100644
|
| --- a/frog/type.dart
|
| +++ b/frog/type.dart
|
| @@ -2,8 +2,7 @@
|
| // 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 implements Named, Hashable {
|
| - final String name;
|
| +class Type extends Element {
|
| bool isTested;
|
|
|
| /**
|
| @@ -12,8 +11,6 @@ class Type implements Named, Hashable {
|
| */
|
| String typeCheckCode;
|
|
|
| - String _jsname;
|
| -
|
| Member _typeMember;
|
|
|
| /** Stubs used to call into this method dynamically. Lazy initialized. */
|
| @@ -22,7 +19,7 @@ class Type implements Named, Hashable {
|
| /** Cache of [MemberSet]s that have been resolved. */
|
| Map<String, MemberSet> _resolvedMembers;
|
|
|
| - Type(this.name): isTested = false, _resolvedMembers = {};
|
| + Type(String name): isTested = false, _resolvedMembers = {}, super(name, null);
|
|
|
| void markUsed() {}
|
| abstract void genMethod(Member method);
|
| @@ -34,10 +31,6 @@ class Type implements Named, Hashable {
|
| return _typeMember;
|
| }
|
|
|
| - abstract SourceSpan get span();
|
| -
|
| - abstract Type resolveType(TypeReference node, bool isRequired);
|
| -
|
| abstract Type resolveTypeParams(ConcreteType inType);
|
|
|
| Member getMember(String name) => null;
|
| @@ -47,7 +40,6 @@ class Type implements Named, Hashable {
|
| 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?
|
| @@ -82,9 +74,6 @@ class Type implements Named, Hashable {
|
| bool get isUsed() => false;
|
|
|
| bool get isGeneric() => false;
|
| - bool get isNativeType() => false;
|
| -
|
| - bool get isNative() => isNativeType; // TODO(jimhug): remove isNativeType.
|
|
|
| bool get isHiddenNativeType() => false;
|
|
|
| @@ -92,10 +81,6 @@ class Type implements Named, Hashable {
|
|
|
| String get typeofName() => null;
|
|
|
| - String get jsname() => _jsname == null ? name : _jsname;
|
| -
|
| - set jsname(String name) => _jsname = name;
|
| -
|
| Map<String, Member> get members() => null;
|
| Definition get definition() => null;
|
| FactoryMap get factories() => null;
|
| @@ -111,12 +96,10 @@ class Type implements Named, Hashable {
|
|
|
| Map<String, Member> getAllMembers() => {};
|
|
|
| - int hashCode() => name.hashCode();
|
| -
|
| bool _hasNativeSubtypes;
|
| bool get hasNativeSubtypes() {
|
| if (_hasNativeSubtypes == null) {
|
| - _hasNativeSubtypes = subtypes.some((t) => t.isNativeType);
|
| + _hasNativeSubtypes = subtypes.some((t) => t.isNative);
|
| }
|
| return _hasNativeSubtypes;
|
| }
|
| @@ -457,9 +440,9 @@ class ParameterType extends Type {
|
| world.internalError('no subtypes of type parameters yet', span);
|
| }
|
|
|
| - resolve(Type inType) {
|
| + resolve() {
|
| if (typeParameter.extendsType != null) {
|
| - extendsType = inType.resolveType(typeParameter.extendsType, true);
|
| + extendsType = enclosingElement.resolveType(typeParameter.extendsType, true);
|
| } else {
|
| extendsType = world.objectType;
|
| }
|
| @@ -515,7 +498,6 @@ class NonNullableType extends Type {
|
| bool get hasTypeParams() => type.hasTypeParams;
|
| String get typeofName() => type.typeofName;
|
| String get jsname() => type.jsname;
|
| - set jsname(String name) => type.jsname = name;
|
| Map<String, Member> get members() => type.members;
|
| Definition get definition() => type.definition;
|
| FactoryMap get factories() => type.factories;
|
| @@ -524,7 +506,7 @@ class NonNullableType extends Type {
|
| List<Type> get interfaces() => type.interfaces;
|
| Type get parent() => type.parent;
|
| Map<String, Member> getAllMembers() => type.getAllMembers();
|
| - bool get isNativeType() => type.isNativeType;
|
| + bool get isNative() => type.isNative;
|
| }
|
|
|
| /** A concrete version of a generic type. */
|
| @@ -731,7 +713,7 @@ class DefinedType extends Type {
|
| Map<String, Member> _lazyGenMethods;
|
|
|
| bool isUsed = false;
|
| - bool isNativeType = false;
|
| + bool isNative = false;
|
|
|
| DefinedType(String name, this.library, Definition definition, this.isClass)
|
| : super(name), directSubtypes = new Set<Type>(), constructors = {},
|
| @@ -743,16 +725,11 @@ class DefinedType extends Type {
|
| assert(definition == null);
|
| definition = def;
|
| if (definition is TypeDefinition && definition.nativeType != null) {
|
| - isNativeType = true;
|
| + isNative = true;
|
| }
|
| if (definition != null && definition.typeParameters != null) {
|
| _concreteTypes = {};
|
| - typeParameters = [];
|
| - // TODO(jimhug): Check for duplicate names.
|
| - for (var tp in definition.typeParameters) {
|
| - var paramName = tp.name.name;
|
| - typeParameters.add(new ParameterType(paramName, tp));
|
| - }
|
| + typeParameters = definition.typeParameters;
|
| }
|
| }
|
|
|
| @@ -996,15 +973,16 @@ class DefinedType extends Type {
|
|
|
| if (typeParameters != null) {
|
| for (var tp in typeParameters) {
|
| - tp.resolve(this);
|
| + tp.enclosingElement = this;
|
| + tp.resolve();
|
| }
|
| }
|
|
|
| world._addType(this);
|
|
|
| - for (var c in constructors.getValues()) c.resolve(this);
|
| - for (var m in members.getValues()) m.resolve(this);
|
| - factories.forEach((f) => f.resolve(this));
|
| + for (var c in constructors.getValues()) c.resolve();
|
| + for (var m in members.getValues()) m.resolve();
|
| + factories.forEach((f) => f.resolve());
|
| }
|
|
|
| addMethod(String methodName, FunctionDefinition definition) {
|
| @@ -1087,7 +1065,7 @@ class DefinedType extends Type {
|
| }
|
| var field = new FieldMember(name, this, definition, value);
|
| members[name] = field;
|
| - if (isNativeType) {
|
| + if (isNative) {
|
| field.isNative = true;
|
| }
|
| }
|
| @@ -1134,7 +1112,7 @@ class DefinedType extends Type {
|
| var span = definition.span;
|
|
|
| var inits = null, body = null;
|
| - if (isNativeType) {
|
| + if (isNative) {
|
| body = new NativeStatement(null, span);
|
| inits = null;
|
| } else {
|
| @@ -1145,9 +1123,9 @@ class DefinedType extends Type {
|
|
|
| TypeDefinition typeDef = definition;
|
| var c = new FunctionDefinition(null, null, typeDef.name, [],
|
| - inits, body, span);
|
| + null, inits, body, span);
|
| addMethod(null, c);
|
| - constructors[''].resolve(this);
|
| + constructors[''].resolve();
|
| return constructors[''];
|
| }
|
| return null;
|
| @@ -1174,105 +1152,31 @@ class DefinedType extends Type {
|
| return _getMemberInParents(memberName);
|
| }
|
|
|
| - static String _getDottedName(NameTypeReference type) {
|
| - if (type.names != null) {
|
| - var names = map(type.names, (n) => n.name);
|
| - return type.name.name + '.' + Strings.join(names, '.');
|
| - } else {
|
| - return type.name.name;
|
| - }
|
| - }
|
| -
|
| - Type resolveType(TypeReference node, bool typeErrors) {
|
| - if (node == null) return world.varType;
|
| -
|
| - if (node.type != null) return node.type;
|
| -
|
| - // TODO(jmesserly): if we failed to resolve a type, we need a way to save
|
| - // that it was an error, so we don't try to resolve it again and show the
|
| - // same message twice.
|
| -
|
| - if (node is NameTypeReference) {
|
| - NameTypeReference typeRef = node;
|
| - String name;
|
| - if (typeRef.names != null) {
|
| - name = typeRef.names.last().name;
|
| - } else {
|
| - name = typeRef.name.name;
|
| - }
|
| - if (typeParameters != null) {
|
| - for (var tp in typeParameters) {
|
| - if (tp.name == name) {
|
| - typeRef.type = tp;
|
| - }
|
| - }
|
| - }
|
| - if (typeRef.type == null) {
|
| - typeRef.type = library.findType(typeRef);
|
| - }
|
| - if (typeRef.type == null) {
|
| - var message = 'cannot find type ${_getDottedName(typeRef)}';
|
| - if (typeErrors) {
|
| - world.error(message, typeRef.span);
|
| - typeRef.type = world.objectType;
|
| - } else {
|
| - world.warning(message, typeRef.span);
|
| - typeRef.type = world.varType;
|
| - }
|
| - }
|
| - } else if (node is GenericTypeReference) {
|
| - GenericTypeReference typeRef = node;
|
| - // TODO(jimhug): Expand the handling of typeErrors to generics and funcs
|
| - var baseType = resolveType(typeRef.baseType, typeErrors);
|
| - if (!baseType.isGeneric) {
|
| - world.error('${baseType.name} is not generic', typeRef.span);
|
| - return null;
|
| - }
|
| - if (typeRef.typeArguments.length != baseType.typeParameters.length) {
|
| - world.error('wrong number of type arguments', typeRef.span);
|
| - return null;
|
| - }
|
| - var typeArgs = [];
|
| - for (int i=0; i < typeRef.typeArguments.length; i++) {
|
| - var extendsType = baseType.typeParameters[i].extendsType;
|
| - var typeArg = resolveType(typeRef.typeArguments[i], typeErrors);
|
| - typeArgs.add(typeArg);
|
| -
|
| - if (extendsType != null && typeArg is! ParameterType) {
|
| - typeArg.ensureSubtypeOf(extendsType,
|
| - typeRef.typeArguments[i].span, typeErrors);
|
| - }
|
| - }
|
| - typeRef.type = baseType.getOrMakeConcreteType(typeArgs);
|
| - } else if (node is FunctionTypeReference) {
|
| - FunctionTypeReference typeRef = node;
|
| - var name = '';
|
| - if (typeRef.func.name != null) name = typeRef.func.name.name;
|
| - typeRef.type = library.getOrAddFunctionType(name, typeRef.func, this);
|
| - } else {
|
| - world.internalError('unknown type reference', node.span);
|
| - }
|
| - return node.type;
|
| - }
|
| -
|
| Type resolveTypeParams(ConcreteType inType) => this;
|
|
|
| Type getOrMakeConcreteType(List<Type> typeArgs) {
|
| assert(isGeneric);
|
| - var names = [name];
|
| + var jsnames = [];
|
| + var names = [];
|
| var typeMap = {};
|
| for (int i=0; i < typeArgs.length; i++) {
|
| var paramName = typeParameters[i].name;
|
| typeMap[paramName] = typeArgs[i];
|
| names.add(typeArgs[i].name);
|
| + jsnames.add(typeArgs[i].jsname);
|
| }
|
|
|
| - var concreteName = Strings.join(names, '\$');
|
| + var jsname = '${jsname}_${Strings.join(jsnames, '\$')}';
|
| + var simpleName = '${name}<${Strings.join(names, ', ')}>';
|
|
|
| - var ret = _concreteTypes[concreteName];
|
| + // TODO(jimhug): Should use jsnames or better type keys.
|
| + var key = Strings.join(names, '\$');
|
| + var ret = _concreteTypes[key];
|
| if (ret == null) {
|
| - ret = new ConcreteType(concreteName, this, typeMap, typeArgs);
|
| - _concreteTypes[concreteName] = ret;
|
| + ret = new ConcreteType(simpleName, this, typeMap, typeArgs);
|
| + ret._jsname = jsname;
|
| +
|
| + _concreteTypes[key] = ret;
|
| }
|
| return ret;
|
| }
|
|
|