Beispiel #1
0
 static JsExpression getRTTClassId(
     TranslationContext translationContext, ClassElement classElement) {
   JsName classJsName = translationContext.getNames().getName(classElement);
   JsProgram program = translationContext.getProgram();
   JsStringLiteral clsid = program.getStringLiteral(classJsName.getShortIdent());
   return call(null, nameref(null, "$cls"), clsid);
 }
Beispiel #2
0
  private JsExpression generateRawInterfaceTypeComparison(
      JsExpression lhs, DartTypeNode typeNode, SourceInfo src) {
    ClassElement element = (ClassElement) typeNode.getType().getElement();
    if (element.equals(typeProvider.getObjectType().getElement())) {
      // Everything is an object, including null
      return this.translationContext.getProgram().getTrueLiteral();
    }
    String builtin = builtInTypeChecks.get(element);
    if (builtin != null) {
      return call(src, nameref(src, builtin), lhs);
    }

    // Due to implementing implied interfaces of classes, we always have to
    // use $implements$ rather than using JS instanceof for classes.

    // Inject: !!(tmp = target, tmp && tmp.$implements$type)
    JsProgram program = translationContext.getProgram();
    JsName tmp = context.createTemporary();
    String mangledClass = translationContext.getMangler().mangleClassName(element);
    return not(
        src,
        not(
            src,
            comma(
                src,
                assign(src, tmp.makeRef(), lhs),
                and(
                    src,
                    neq(src, tmp.makeRef().setSourceRef(src), program.getNullLiteral()),
                    nameref(src, tmp, "$implements$" + mangledClass)))));
  }
Beispiel #3
0
 private void injectInterfaceMarkers(ClassElement classElement, SourceInfo srcRef) {
   JsProgram program = translationContext.getProgram();
   JsName classJsName = translationContext.getNames().getName(classElement);
   for (InterfaceType iface : getAllInterfaces(classElement)) {
     JsStatement assignment =
         (JsStatement)
             newAssignment(
                     newNameRef(
                         newNameRef(new JsNameRef(classJsName), "prototype"),
                         "$implements$"
                             + translationContext
                                 .getMangler()
                                 .mangleClassName(iface.getElement())),
                     program.getNumberLiteral(1))
                 .makeStmt()
                 .setSourceRef(srcRef);
     globalBlock.getStatements().add(assignment);
   }
 }
Beispiel #4
0
 RuntimeTypeInjector(
     TraversalContextProvider context,
     CoreTypeProvider typeProvider,
     TranslationContext translationContext,
     boolean emitTypeChecks) {
   this.context = context;
   this.translationContext = translationContext;
   JsProgram program = translationContext.getProgram();
   this.globalBlock = program.getGlobalBlock();
   this.globalScope = program.getScope();
   this.builtInTypeChecks = makeBuiltinTypes(typeProvider);
   this.typeProvider = typeProvider;
   this.emitTypeChecks = emitTypeChecks;
 }
Beispiel #5
0
  /** @return a JsArrayLiteral listing the type arguments for the interface instance. */
  private JsExpression buildTypeArgsForFactory(
      FunctionType functionType,
      InterfaceType instanceType,
      List<? extends Type> listTypeVars,
      JsExpression contextTypeArgs) {
    if (functionType.getTypeVariables().size() == 0) {
      return null;
    }

    if (instanceType.hasDynamicTypeArgs()) {
      return translationContext.getProgram().getNullLiteral();
    }

    JsArrayLiteral arr = new JsArrayLiteral();
    for (Type type : instanceType.getArguments()) {
      JsExpression typeExpr = buildTypeLookupExpression(type, listTypeVars, contextTypeArgs);
      arr.getExpressions().add(typeExpr);
    }

    return arr;
  }
Beispiel #6
0
  /** @return a JsArrayLiteral listing the type arguments for the interface instance. */
  private JsExpression buildTypeArgs(
      InterfaceType instanceType, List<? extends Type> listTypeVars, JsExpression contextTypeArgs) {
    ClassElement classElement = instanceType.getElement();
    if (!hasTypeParameters(classElement)) {
      return null;
    }

    if (instanceType.hasDynamicTypeArgs()) {
      JsProgram program = translationContext.getProgram();
      return program.getNullLiteral();
    }

    JsArrayLiteral arr = new JsArrayLiteral();
    assert instanceType.getArguments().size() > 0;
    for (Type type : instanceType.getArguments()) {
      JsExpression typeExpr = buildTypeLookupExpression(type, listTypeVars, contextTypeArgs);
      arr.getExpressions().add(typeExpr);
    }

    return arr;
  }
Beispiel #7
0
  /** @return js The expression used to lookup the RTT for the given type. */
  private JsExpression buildTypeLookupExpression(
      Type type, List<? extends Type> list, JsExpression contextTypeArgs) {
    switch (TypeKind.of(type)) {
      case INTERFACE:
        InterfaceType interfaceType = (InterfaceType) type;
        JsInvocation callLookup = call(null, getRTTLookupMethodName(interfaceType.getElement()));
        if (hasTypeParameters(interfaceType.getElement()) && !interfaceType.hasDynamicTypeArgs()) {
          JsArrayLiteral typeArgs = new JsArrayLiteral();
          for (Type arg : interfaceType.getArguments()) {
            typeArgs.getExpressions().add(buildTypeLookupExpression(arg, list, contextTypeArgs));
          }
          callLookup.getArguments().add(typeArgs);
        }
        return callLookup;

      case FUNCTION_ALIAS:
        // TODO(johnlenz): implement this
        return newQualifiedNameRef("RTT.placeholderType");

      case VARIABLE:
        TypeVariable var = (TypeVariable) type;
        JsProgram program = translationContext.getProgram();
        int varIndex = 0;
        for (Type t : list) {
          if (t.equals(type)) {
            return call(
                null,
                newQualifiedNameRef("RTT.getTypeArg"),
                Cloner.clone(contextTypeArgs),
                program.getNumberLiteral(varIndex));
          }
          varIndex++;
        }
        throw new AssertionError("unresolved type variable:" + var);

      default:
        throw new AssertionError("unexpected type kind:" + type.getKind());
    }
  }
Beispiel #8
0
  private void generateRTTLookupMethod(DartClass x) {
    ClassElement classElement = x.getSymbol();
    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();
    if (hasRTTImplements(classElement)) {
      callArgs.add(getRTTImplementsMethodName(classElement));
    } else if (hasTypeParams) {
      // need a placeholder param if the typeArgs are needed.
      callArgs.add(program.getNullLiteral());
    }

    if (hasTypeParams) {
      JsName typeArgs = scope.declareName("typeArgs");
      lookupFn.getParameters().add(new JsParameter(typeArgs));
      callArgs.add(typeArgs.makeRef());
    }

    body.add(new JsReturn(invokeCreate));

    // Finally, Add the function
    JsExpression fnDecl = assign(null, getRTTLookupMethodName(classElement), lookupFn);
    globalBlock.getStatements().add(fnDecl.makeStmt());
  }
Beispiel #9
0
 /** @return an expression that implements a runtime "is" operation */
 JsExpression generateInstanceOfComparison(
     ClassElement enclosingClass, JsExpression lhs, DartTypeNode typeNode, SourceInfo src) {
   ClassElement currentClass = enclosingClass;
   Type type = typeNode.getType();
   switch (TypeKind.of(type)) {
     case INTERFACE:
       InterfaceType interfaceType = (InterfaceType) type;
       if (hasTypeParameters(interfaceType.getElement()) && !interfaceType.hasDynamicTypeArgs()) {
         return generateRefiedInterfaceTypeComparison(lhs, interfaceType, currentClass, src);
       } else {
         // TODO(johnlenz): special case "is Object"?
         return generateRawInterfaceTypeComparison(lhs, typeNode, src);
       }
     case VARIABLE:
       TypeVariable typeVar = (TypeVariable) type;
       return generateRefiedTypeVariableComparison(lhs, typeVar, currentClass, src);
     case DYNAMIC:
       JsProgram program = translationContext.getProgram();
       return program.getTrueLiteral();
     default:
       throw new IllegalStateException("unexpected");
   }
 }
Beispiel #10
0
 private JsNameRef getRTTAddToMethodName(ClassElement classElement) {
   return nameref(null, translationContext.getNames().getName(classElement), "$addTo");
 }
Beispiel #11
0
 private JsNameRef getRTTImplementsMethodName(ClassElement classElement) {
   return nameref(null, translationContext.getNames().getName(classElement), "$RTTimplements");
 }
Beispiel #12
0
 private JsNameRef getRTTLookupMethodName(ClassElement classElement) {
   return nameref(null, translationContext.getNames().getName(classElement), "$lookupRTT");
 }