Index: frog/element.dart |
diff --git a/frog/element.dart b/frog/element.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e3ec26d68f844bc46eab7ac859e058d935c1f83f |
--- /dev/null |
+++ b/frog/element.dart |
@@ -0,0 +1,129 @@ |
+// 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. |
+ |
+/** |
+ * Any abstract representation of a dart element. This includes |
+ * [Library], [Type] and [Member]. |
+ */ |
+class Element implements Hashable { |
+ // TODO(jimhug): Make name final when we can do it for Library. |
+ /** The user-visible name of this [Element]. */ |
+ String name; |
+ |
+ /** A safe name to use for this [Element] in generated JS code. */ |
+ String _jsname; |
+ |
+ /** The lexically/logically enclosing [Element] for lookups. */ |
+ Element _enclosingElement; |
+ |
+ Element(this.name, this._enclosingElement) { |
+ _jsname = name; |
+ } |
+ |
+ // TODO - walk tree |
+ Library get library() => null; |
+ |
+ /** A source location for messages to the user about this [Element]. */ |
+ SourceSpan get span() => null; |
+ |
+ /** Should this element be treated as native JS? */ |
+ bool get isNative() => false; |
+ |
+ int hashCode() => name.hashCode(); |
+ |
+ /** Will return a safe name to refer to this element with in JS code. */ |
+ String get jsname() => _jsname; |
+ |
+ /** Resolve types and other references in the [Element]. */ |
+ void resolve() {} |
+ |
+ /** |
+ * Any type parameters that this element defines to setup a generic |
+ * type resolution context. This is currently used for both generic |
+ * types and the semi-magical generic factory methods - but it will |
+ * not be used for any other members in the current dart language. |
+ */ |
+ List<ParameterType> get typeParameters() => null; |
+ |
+ // TODO(jimhug): Probably kill this. |
+ Element get enclosingElement() => |
+ _enclosingElement === null ? library : _enclosingElement; |
+ |
+ // TODO(jimhug): Absolutely kill this one. |
+ set enclosingElement(Element e) => _enclosingElement = e; |
+ |
+ |
+ /** |
+ * Resolves [node] in the context of this element. Will |
+ * search up the tree of [enclosingElement] to look for matches. |
+ * If [typeErrors] then types that are not found will create errors, |
+ * otherwise they will only signal warnings. |
+ */ |
+ 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) { |
+ return typeRef.type; |
+ } |
+ |
+ return enclosingElement.resolveType(node, typeErrors); |
+ } 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; |
+ } |
+ // Totally bogus! |
+ typeRef.type = library.getOrAddFunctionType(this, name, typeRef.func); |
+ } else { |
+ world.internalError('unknown type reference', node.span); |
+ } |
+ return node.type; |
+ } |
+} |