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

Unified Diff: compiler/java/com/google/dart/compiler/backend/js/RuntimeTypeInjector.java

Issue 8479049: Allow for instance checking of methods and function aliases. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 9 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: compiler/java/com/google/dart/compiler/backend/js/RuntimeTypeInjector.java
diff --git a/compiler/java/com/google/dart/compiler/backend/js/RuntimeTypeInjector.java b/compiler/java/com/google/dart/compiler/backend/js/RuntimeTypeInjector.java
index 44ae3c5c99322b3cd85fc5fd95fda8417479ab7c..3e4e80889f0740f8a6ea6fcac4a8682b07a731e2 100644
--- a/compiler/java/com/google/dart/compiler/backend/js/RuntimeTypeInjector.java
+++ b/compiler/java/com/google/dart/compiler/backend/js/RuntimeTypeInjector.java
@@ -46,12 +46,16 @@ import com.google.dart.compiler.InternalCompilerException;
import com.google.dart.compiler.ast.DartArrayLiteral;
import com.google.dart.compiler.ast.DartClass;
import com.google.dart.compiler.ast.DartClassMember;
+import com.google.dart.compiler.ast.DartFunctionTypeAlias;
import com.google.dart.compiler.ast.DartMapLiteral;
import com.google.dart.compiler.ast.DartMethodDefinition;
import com.google.dart.compiler.ast.DartNewExpression;
+import com.google.dart.compiler.ast.DartParameter;
import com.google.dart.compiler.ast.DartTypeNode;
+import com.google.dart.compiler.ast.Modifiers;
import com.google.dart.compiler.backend.js.ast.JsArrayAccess;
import com.google.dart.compiler.backend.js.ast.JsArrayLiteral;
+import com.google.dart.compiler.backend.js.ast.JsBinaryOperation;
import com.google.dart.compiler.backend.js.ast.JsBlock;
import com.google.dart.compiler.backend.js.ast.JsExpression;
import com.google.dart.compiler.backend.js.ast.JsFunction;
@@ -66,16 +70,25 @@ import com.google.dart.compiler.backend.js.ast.JsStatement;
import com.google.dart.compiler.backend.js.ast.JsStringLiteral;
import com.google.dart.compiler.backend.js.ast.JsThisRef;
import com.google.dart.compiler.common.SourceInfo;
+import com.google.dart.compiler.common.Symbol;
import com.google.dart.compiler.resolver.ClassElement;
import com.google.dart.compiler.resolver.ConstructorElement;
import com.google.dart.compiler.resolver.CoreTypeProvider;
+import com.google.dart.compiler.resolver.Element;
import com.google.dart.compiler.resolver.ElementKind;
+import com.google.dart.compiler.resolver.Elements;
+import com.google.dart.compiler.resolver.FunctionAliasElementImplementation;
+import com.google.dart.compiler.resolver.MethodElement;
+import com.google.dart.compiler.resolver.VariableElement;
+import com.google.dart.compiler.resolver.TypeVariableElement;
+import com.google.dart.compiler.type.FunctionAliasType;
import com.google.dart.compiler.type.FunctionType;
import com.google.dart.compiler.type.InterfaceType;
import com.google.dart.compiler.type.Type;
import com.google.dart.compiler.type.TypeKind;
import com.google.dart.compiler.type.TypeVariable;
import com.google.dart.compiler.type.Types;
+import com.google.dart.compiler.util.AstUtil;
import java.util.List;
import java.util.Map;
@@ -133,6 +146,20 @@ public class RuntimeTypeInjector {
}
}
+ /**
+ * Generate the code necessary to allow for runtime type checks
+ */
+ void generateRuntimeTypeInfo(DartFunctionTypeAlias x) {
+ generateRuntimeTypeInfoMethods(x);
+ }
+
+ /**
+ * Generate the code necessary to allow for runtime type checks
+ */
+ void generateRuntimeTypeInfo(DartMethodDefinition x) {
+ generateRuntimeTypeInfoMethods(x);
+ }
+
private void injectInterfaceMarkers(ClassElement classElement, SourceInfo srcRef) {
JsProgram program = translationContext.getProgram();
JsName classJsName = translationContext.getNames().getName(classElement);
@@ -190,6 +217,30 @@ public class RuntimeTypeInjector {
generateRTTAddToMethod(x);
}
+ /**
+ * Insert the function or method necessary to implement runtime type information
+ * for the provided class.
+ */
+ private void generateRuntimeTypeInfoMethods(DartFunctionTypeAlias x) {
+ // 1) create static type information lookup function
+ generateRTTLookupMethod(x);
+
+ // 3) create "addTo" method for use by classes or interfaces that inherit from this class
+// generateRTTAddToMethod(x);
+ }
+
+ /**
+ * Insert the function or method necessary to implement runtime type information
+ * for the provided class.
+ */
+ private void generateRuntimeTypeInfoMethods(DartMethodDefinition x) {
+ // 1) create static type information lookup function
+ generateRTTLookupMethod(x);
+
+ // 3) create "addTo" method for use by classes or interfaces that inherit from this class
+// generateRTTAddToMethod(x);
+ }
+
private void generateRTTLookupMethod(DartClass x) {
ClassElement classElement = x.getSymbol();
boolean hasTypeParams = hasTypeParameters(classElement);
zundel 2011/11/08 15:28:42 looks like you aren't using hasTypeParams() anymor
codefu 2011/11/14 19:33:40 For now, yes. I need to look into a generic rtt c
@@ -217,11 +268,17 @@ public class RuntimeTypeInjector {
callArgs.add(program.getNullLiteral());
}
- if (hasTypeParams) {
- JsName typeArgs = scope.declareName("typeArgs");
- lookupFn.getParameters().add(new JsParameter(typeArgs));
- callArgs.add(typeArgs.makeRef());
- }
+ JsName typeArgs = scope.declareName("typeArgs");
+ lookupFn.getParameters().add(new JsParameter(typeArgs));
+ callArgs.add(typeArgs.makeRef());
+
+ JsName returnType = scope.declareName("returnType");
+ lookupFn.getParameters().add(new JsParameter(returnType));
+ callArgs.add(returnType.makeRef());
+
+ JsName functionType = scope.declareName("functionType");
+ lookupFn.getParameters().add(new JsParameter(functionType));
+ callArgs.add(functionType.makeRef());
body.add(new JsReturn(invokeCreate));
@@ -373,6 +430,217 @@ public class RuntimeTypeInjector {
globalBlock.getStatements().add(fnDecl.makeStmt());
}
+//todo: was generateRTTGetToMethod, dumb
+ private void generateRTTLookupMethod(DartMethodDefinition x) {
+ MethodElement methodElement = x.getSymbol();
+ if (Elements.isTopLevel(methodElement)) {
+ return; /* top level methods can't have type parameters */
+ }
+ ClassElement classElement = (ClassElement)methodElement.getEnclosingElement();
+
+ JsProgram program = translationContext.getProgram();
+
+ // Create function looking up RTT parameters and return type for method x
+ // return jtm86182b$A$Dart.$lookupRTT(null,Collection$Dart.$lookupRTT([RTT.getTypeArg(RTT.getTypeArgsFor(this, $cls('jtm86182b$A$Dart')), 0)]));
+
+ JsExpression typeArgContextExpr = buildTypeArgsReference(classElement);
+
+ // Build the function
+ JsFunction lookupFn = new JsFunction(globalScope);
+ lookupFn.setBody(new JsBlock());
+ JsScope scope = new JsScope(globalScope, "temp");
+
+ List<JsStatement> body = lookupFn.getBody().getStatements();
+ JsInvocation callLookup = newInvocation(
+ getRTTLookupMethodName(classElement));
+
+ JsArrayLiteral arr = new JsArrayLiteral();
+ for (VariableElement element : methodElement.getParameters()) {
+ Type elementType = element.getType();
+ ClassElement cElement = null;
+ switch(TypeKind.of(elementType)) {
+ case VARIABLE:
+ cElement = (ClassElement) ((TypeVariableElement)elementType.getElement()).getDeclaringElement();
+ break;
+ default:
+ cElement = (ClassElement) elementType.getElement();
+ break;
+ }
+ JsExpression elementExpr;
+ switch (TypeKind.of(elementType)) {
+ case INTERFACE:
+ elementExpr = generateRTTLookup((ClassElement) elementType.getElement(), (InterfaceType) elementType, classElement);
zundel 2011/11/08 15:28:42 this and other lines > 100chars
codefu 2011/11/14 19:33:40 Done.
+ break;
+
+ case FUNCTION:
+ case FUNCTION_ALIAS:
+ // TODO(johnlenz): implement this
+ //elementExpr = null; //newQualifiedNameRef("RTT.placeholderType");
+ return; // F'em
+ case VARIABLE:
+ elementExpr = buildTypeLookupExpression(
+ elementType, classElement.getTypeParameters(), typeArgContextExpr );
+ break;
+ default:
+ //throw new AssertionError("unexpected type kind:" + elementType.getKind());
+ return; /* f'em, they don't get a lookup */
+ }
+ arr.getExpressions().add(elementExpr);
+ }
+ Type returnType = methodElement.getReturnType();
+ JsExpression returnExpr;
+ if( returnType.getElement() instanceof ClassElement ) {
+ returnExpr = generateRTTLookup((ClassElement) returnType.getElement(), (InterfaceType) returnType, classElement);
+ } else {
+ switch( TypeKind.of(returnType) ) {
+ case VOID:
+ case NONE:
+ returnExpr = program.getNullLiteral();
+ break;
+ default:
+ returnExpr = buildTypeLookupExpression(
+ returnType, classElement.getTypeParameters(), typeArgContextExpr );
+ break;
+ }
+ }
+
+ callLookup.getArguments().add(0, arr.getExpressions().isEmpty() ? program.getNullLiteral() : arr);
+ callLookup.getArguments().add(1, returnExpr);
+ callLookup.getArguments().add(2, program.getBooleanLiteral(true));
+ body.add(new JsReturn(callLookup));
+
+ // Finally, Add the function
+ JsExpression fnDecl;
+ if (methodElement.getEnclosingElement().getKind().equals(ElementKind.CLASS)) {
+ //JsName name = new JsName();
+ JsNameRef prop = makeMethodJsReference(methodElement);
+ fnDecl = assign(null, prop, lookupFn);
+ } else {
+ fnDecl = assign(null, getRTTLookupMethodName(classElement), lookupFn);
+ }
+ globalBlock.getStatements().add(fnDecl.makeStmt());
+ }
+
+ private JsName getJsName(Symbol symbol) {
+ return translationContext.getNames().getName(symbol);
+ }
+
+ private JsNameRef makeMethodJsReference(Element element) {
+ JsNameRef qualifier;
+ boolean isNonFactoryConstructor = Elements.isNonFactoryConstructor(element);
+ Modifiers modifiers = element.getModifiers();
+
+ JsNameRef classJsName = getJsName(element.getEnclosingElement()).makeRef();
+ if (modifiers.isStatic() || modifiers.isFactory() || isNonFactoryConstructor) {
+ // Static methods hang directly from the constructor.
+ qualifier = classJsName;
+ } else {
+ // Instance methods hang from the prototype.
+ qualifier = AstUtil.newPrototypeNameRef(classJsName);
+ }
+
+ JsNameRef blah = AstUtil.nameref(null, new JsNameRef(element.getName()) + "$lookupRTT"); //nameref(null, element.getName(), "$lookupRTT");
+ JsNameRef asdf = newNameRef(qualifier, blah.toString());
+
+ // TODO(johnlenz): This should be the name node reference
+ asdf.setSourceRef(element.getNode());
+ return asdf;
+ }
+
+ private void generateRTTLookupMethod(DartFunctionTypeAlias x) {
+ FunctionAliasElementImplementation classElement = (FunctionAliasElementImplementation) x.getSymbol();
+ FunctionType funcType = classElement.getFunctionType();
+ boolean hasTypeParams = hasTypeParameters(classElement);
+
+ // 1) create static type information construction function
+ // function Foo$lookupOrCreateRTT(typeargs) {
+ // return $createRTT(name, Foo$RTTimplements, typeargs) ;
+ // }
+
+ // Build the function
+ JsFunction lookupFn = new JsFunction(globalScope);
+ lookupFn.setBody(new JsBlock());
+ List<JsStatement> body = lookupFn.getBody().getStatements();
+ JsScope scope = new JsScope(globalScope, "temp");
+
+ JsProgram program = translationContext.getProgram();
+
+ JsInvocation invokeCreate = call(null,
+ newQualifiedNameRef("RTT.create"), getRTTClassId(classElement));
+ List<JsExpression> callArgs = invokeCreate.getArguments();
+
+ JsName typeArgs = scope.declareName("typeArgs");
+ JsExpression typeArgsExpr = new JsNameRef("typeArgs");
+ lookupFn.getParameters().add(new JsParameter(typeArgs));
+
+ // There is no implementing... just saying.
+ callArgs.add(program.getNullLiteral());
+
+ JsArrayLiteral arr = new JsArrayLiteral();
+ for (DartParameter param : x.getParameters()) {
+ if( param.getTypeNode() == null ) {
+ return; //F'em
+ }
+ Type elementType = param.getTypeNode().getType();
+ ClassElement cElement;
+ switch(TypeKind.of(elementType)) {
+ case VARIABLE:
+ cElement = (ClassElement) ((TypeVariableElement)elementType.getElement()).getDeclaringElement();
+ break;
+ default:
+ cElement = (ClassElement) elementType.getElement();
+ break;
+ }
+ JsExpression elementExpr;
+ switch (TypeKind.of(elementType)) {
+ case INTERFACE:
+ elementExpr = generateRTTLookup((ClassElement) elementType.getElement(), (InterfaceType) elementType, classElement);
+ break;
+
+ case FUNCTION:
+ case FUNCTION_ALIAS:
+ // TODO(johnlenz): implement this
+ //elementExpr = null; //newQualifiedNameRef("RTT.placeholderType");
+ return; // F'em
+ case VARIABLE:
+ elementExpr = buildTypeLookupExpression(
+ elementType, classElement.getTypeParameters(), typeArgsExpr );
+ break;
+ default:
+ //throw new AssertionError("unexpected type kind:" + elementType.getKind());
+ return; /* f'em, they don't get a lookup */
+ }
+ arr.getExpressions().add(elementExpr);
+ }
+ callArgs.add(arr.getExpressions().isEmpty() ? program.getNullLiteral() : arr);
+
+ Type returnType = funcType.getReturnType();
+ JsExpression returnExpr;
+ if( returnType.getElement() instanceof ClassElement ) {
+ returnExpr = generateRTTLookup((ClassElement) returnType.getElement(), (InterfaceType) returnType, classElement);
+ } else {
+ switch( TypeKind.of(returnType) ) {
+ case VOID:
+ case NONE:
+ returnExpr = program.getNullLiteral();
+ break;
+ default:
+ returnExpr = buildTypeLookupExpression(
+ returnType, classElement.getTypeParameters(), typeArgsExpr );
+ break;
+ }
+ }
+ callArgs.add(returnExpr);
+ callArgs.add(program.getBooleanLiteral(true));
+
+ body.add(new JsReturn(invokeCreate));
+
+ // Finally, Add the function
+ JsExpression fnDecl = assign(null,
+ getRTTLookupMethodName(classElement), lookupFn);
+ globalBlock.getStatements().add(fnDecl.makeStmt());
+ }
+
static JsExpression getRTTClassId(TranslationContext translationContext,
ClassElement classElement) {
JsName classJsName = translationContext.getNames().getName(classElement);
@@ -385,7 +653,7 @@ public class RuntimeTypeInjector {
return getRTTClassId(translationContext, classElement);
}
- private JsNameRef getRTTLookupMethodName(ClassElement classElement) {
+ private JsNameRef getRTTLookupMethodName(Symbol classElement) {
return nameref(null, translationContext.getNames().getName(classElement), "$lookupRTT");
}
@@ -495,6 +763,22 @@ public class RuntimeTypeInjector {
return invokeLookup;
}
+// private JsExpression generateRTTLookup(
+// FunctionAliasType aliasType, ClassElement contextClassElement) {
+// return generateRTTLookup(aliasType.getElement(), aliasType, contextClassElement);
+// }
+//
+// private JsExpression generateRTTLookup(
+// ClassElement classElement, FunctionAliasType aliasType, ClassElement contextClassElement) {
+// JsInvocation invokeLookup = call(null, getRTTLookupMethodName(classElement));
+// if (hasTypeParameters(aliasType.getElement()) && !aliasType.hasDynamicTypeArgs()) {
+// JsExpression typeArgs = generateTypeArgsArray(aliasType, contextClassElement);
+// assert typeArgs != null;
+// invokeLookup.getArguments().add(typeArgs);
+// }
+// return invokeLookup;
+// }
+
private JsExpression generateTypeArgsArray(
InterfaceType instanceType, ClassElement contextClassElement) {
JsExpression typeArgs;
@@ -510,7 +794,12 @@ public class RuntimeTypeInjector {
((FunctionType)contextElement.getType()).getTypeVariables(),
buildFactoryTypeInfoReference());
} else {
- typeArgs = buildTypeArgs(instanceType, null, null);
+ if( contextClassElement instanceof FunctionAliasElementImplementation) {
+ JsExpression blah = new JsNameRef("typeArgs");
+ typeArgs = buildTypeArgs(instanceType, contextClassElement.getTypeParameters(), blah);
+ } else {
+ typeArgs = buildTypeArgs(instanceType, null, null);
+ }
}
} else {
// Build type args in a class context:
@@ -748,6 +1037,16 @@ public class RuntimeTypeInjector {
case DYNAMIC:
JsProgram program = translationContext.getProgram();
return program.getTrueLiteral();
+ case FUNCTION_ALIAS:
+ FunctionAliasType aliasType = (FunctionAliasType) type;
+ if (hasTypeParameters(aliasType.getElement())
+ && !aliasType.hasDynamicTypeArgs()) {
+ return generateRefiedInterfaceTypeComparison(lhs, aliasType, currentClass, src);
+ } else {
+ // TODO(johnlenz): special case "is Object"?
+ return generateRefiedInterfaceTypeComparison(lhs, aliasType, currentClass, src);
+ }
+
default:
throw new IllegalStateException("unexpected");
}

Powered by Google App Engine
This is Rietveld 408576698