Fix 'as' with generics to work like cast #557
authorBrian Frank
Thu Apr 30 10:01:48 2009 -0400 (16 months ago)
changeset 12518e26ba775c9c
parent 1250 9cd7887d90b5
child 1252 595ae8c6c2e0
Fix 'as' with generics to work like cast #557
src/doc/docIntro/doc/ChangeLog.fandoc
src/sys/dotnet/fanx/emit/FCodeEmit.cs
src/sys/dotnet/fanx/emit/FTypeEmit.cs
src/sys/dotnet/fanx/util/OpUtil.cs
src/sys/java/fanx/emit/FCodeEmit.java
src/sys/java/fanx/emit/FTypeEmit.java
src/sys/java/fanx/util/OpUtil.java
src/testSys/fan/ListTest.fan
src/testSys/fan/MapTest.fan
     1.1 --- a/src/doc/docIntro/doc/ChangeLog.fandoc	Wed Apr 29 17:40:27 2009 -0400
     1.2 +++ b/src/doc/docIntro/doc/ChangeLog.fandoc	Thu Apr 30 10:01:48 2009 -0400
     1.3 @@ -600,5 +600,6 @@
     1.4  - Loosen restrictions on it/this ambiguity errors
     1.5  - webappClient::Effect
     1.6  - Disallow nullable types in 'as' expression
     1.7 +- Fix 'as' with generics to work like cast
     1.8  
     1.9  TODO: change over buildall to use pathPrefix
    1.10 \ No newline at end of file
     2.1 --- a/src/sys/dotnet/fanx/emit/FCodeEmit.cs	Wed Apr 29 17:40:27 2009 -0400
     2.2 +++ b/src/sys/dotnet/fanx/emit/FCodeEmit.cs	Thu Apr 30 10:01:48 2009 -0400
     2.3 @@ -790,23 +790,7 @@
     2.4      {
     2.5        FTypeRef typeRef = pod.typeRef(u2());
     2.6        PERWAPI.Type type = emitter.findType(typeRef.nnameBoxed());
     2.7 -
     2.8 -      // if a generic instance, we have to use a method call
     2.9 -      // because Fan types don't map to Java classes exactly;
    2.10 -      // otherwise we can use straight bytecode
    2.11 -      if (typeRef.isGenericInstance())
    2.12 -      {
    2.13 -        if (parent.AsViaType == null)
    2.14 -          parent.AsViaType = emitter.findMethod("Fanx.Util.OpUtil", "as",
    2.15 -              new string[] { "System.Object", "Fan.Sys.Type" }, "System.Object");
    2.16 -        loadType(typeRef);
    2.17 -        code.MethInst(MethodOp.call, parent.AsViaType);
    2.18 -        code.TypeInst(TypeOp.isinst, type);
    2.19 -      }
    2.20 -      else
    2.21 -      {
    2.22 -        code.TypeInst(TypeOp.isinst, type);
    2.23 -      }
    2.24 +      code.TypeInst(TypeOp.isinst, type);
    2.25      }
    2.26  
    2.27    //////////////////////////////////////////////////////////////////////////
     3.1 --- a/src/sys/dotnet/fanx/emit/FTypeEmit.cs	Wed Apr 29 17:40:27 2009 -0400
     3.2 +++ b/src/sys/dotnet/fanx/emit/FTypeEmit.cs	Thu Apr 30 10:01:48 2009 -0400
     3.3 @@ -549,7 +549,6 @@
     3.4      internal PERWAPI.Method CompareNull;
     3.5      internal PERWAPI.Method CompareNotNull;
     3.6      internal PERWAPI.Method IsViaType;
     3.7 -    internal PERWAPI.Method AsViaType;
     3.8      internal PERWAPI.Method IntVal;
     3.9      internal PERWAPI.Method ErrMake;
    3.10      internal PERWAPI.Field ErrVal;
     4.1 --- a/src/sys/dotnet/fanx/util/OpUtil.cs	Wed Apr 29 17:40:27 2009 -0400
     4.2 +++ b/src/sys/dotnet/fanx/util/OpUtil.cs	Thu Apr 30 10:01:48 2009 -0400
     4.3 @@ -203,12 +203,6 @@
     4.4        return FanObj.type(instance).fits(type);
     4.5      }
     4.6  
     4.7 -    public static object @as(object instance, Type type)
     4.8 -    {
     4.9 -      if (instance == null) return null;
    4.10 -      return FanObj.type(instance).@is(type) ? instance : null;
    4.11 -    }
    4.12 -
    4.13      public static object toImmutable(object obj)
    4.14      {
    4.15        if (obj == null) return null;
     5.1 --- a/src/sys/java/fanx/emit/FCodeEmit.java	Wed Apr 29 17:40:27 2009 -0400
     5.2 +++ b/src/sys/java/fanx/emit/FCodeEmit.java	Thu Apr 30 10:01:48 2009 -0400
     5.3 @@ -850,29 +850,15 @@
     5.4    {
     5.5      FTypeRef typeRef = pod.typeRef(u2());
     5.6      int cls = emit.cls(typeRef.jnameBoxed());
     5.7 -
     5.8 -    // if a generic instance, we have to use a method call
     5.9 -    // because Fan types don't map to Java classes exactly;
    5.10 -    // otherwise we can use straight bytecode
    5.11 -    if (typeRef.isGenericInstance())
    5.12 -    {
    5.13 -      if (parent.AsViaType == 0) parent.AsViaType = emit.method("fanx/util/OpUtil.as(Ljava/lang/Object;Lfan/sys/Type;)Ljava/lang/Object;");
    5.14 -      loadType(typeRef);
    5.15 -      code.op2(INVOKESTATIC, parent.AsViaType);
    5.16 -      code.op2(CHECKCAST, cls);
    5.17 -    }
    5.18 -    else
    5.19 -    {
    5.20 -      code.op(DUP);
    5.21 -      code.op2(INSTANCEOF, cls);
    5.22 -      int is = code.branch(IFNE);
    5.23 -      code.op(POP);
    5.24 -      code.op(ACONST_NULL);
    5.25 -      int end = code.branch(GOTO);
    5.26 -      code.mark(is);
    5.27 -      code.op2(CHECKCAST, cls);
    5.28 -      code.mark(end);
    5.29 -    }
    5.30 +    code.op(DUP);
    5.31 +    code.op2(INSTANCEOF, cls);
    5.32 +    int is = code.branch(IFNE);
    5.33 +    code.op(POP);
    5.34 +    code.op(ACONST_NULL);
    5.35 +    int end = code.branch(GOTO);
    5.36 +    code.mark(is);
    5.37 +    code.op2(CHECKCAST, cls);
    5.38 +    code.mark(end);
    5.39    }
    5.40  
    5.41  //////////////////////////////////////////////////////////////////////////
     6.1 --- a/src/sys/java/fanx/emit/FTypeEmit.java	Wed Apr 29 17:40:27 2009 -0400
     6.2 +++ b/src/sys/java/fanx/emit/FTypeEmit.java	Thu Apr 30 10:01:48 2009 -0400
     6.3 @@ -393,7 +393,6 @@
     6.4    int IntBox, IntUnbox;
     6.5    int FloatBox, FloatUnbox;
     6.6    int IsViaType;
     6.7 -  int AsViaType;
     6.8    int ErrMake;
     6.9    int ErrVal;
    6.10    int TypeToNullable;
     7.1 --- a/src/sys/java/fanx/util/OpUtil.java	Wed Apr 29 17:40:27 2009 -0400
     7.2 +++ b/src/sys/java/fanx/util/OpUtil.java	Thu Apr 30 10:01:48 2009 -0400
     7.3 @@ -180,12 +180,6 @@
     7.4      return FanObj.type(instance).fits(type);
     7.5    }
     7.6  
     7.7 -  public static Object as(Object instance, Type type)
     7.8 -  {
     7.9 -    if (instance == null) return null;
    7.10 -    return FanObj.type(instance).is(type) ? instance : null;
    7.11 -  }
    7.12 -
    7.13    public static Object toImmutable(Object obj)
    7.14    {
    7.15      if (obj == null) return null;
     8.1 --- a/src/testSys/fan/ListTest.fan	Wed Apr 29 17:40:27 2009 -0400
     8.2 +++ b/src/testSys/fan/ListTest.fan	Thu Apr 30 10:01:48 2009 -0400
     8.3 @@ -137,8 +137,9 @@
     8.4      s  := x as Str;    verifySame(s , null)
     8.5      l  := x as List;   verifySame(l , x)
     8.6      ol := x as Obj[];  verifySame(ol , x)
     8.7 -    il := x as Int[];  verifySame(il , null)
     8.8 -    sl := x as Str[];  verifySame(sl , null)
     8.9 +    il := x as Int[];  verifySame(il , x)  // no runtime check
    8.10 +    sl := x as Str[];  verifySame(sl , x)  // no runtime check
    8.11 +    s2 := x as Str?[];  verifySame(s2 , x) // no runtime check
    8.12  
    8.13      x  = ["a", "b"]
    8.14      o  = x as Obj;    verifySame(o , x)
    8.15 @@ -146,8 +147,37 @@
    8.16      s  = x as Str;    verifySame(s , null)
    8.17      l  = x as List;   verifySame(l , x)
    8.18      ol = x as Obj[];  verifySame(ol , x)
    8.19 -    il = x as Int[];  verifySame(il , null)
    8.20 -    sl = x as Str[];  verifySame(sl , x)
    8.21 +    il = x as Int[];  verifySame(il , x) // no runtime check
    8.22 +    sl = x as Str[];  verifySame(sl , x) // no runtime check
    8.23 +    s2 = x as Str?[]; verifySame(sl , x) // no runtime check
    8.24 +
    8.25 +    x = "s"
    8.26 +    o  = x as Obj;    verifySame(o , x)
    8.27 +    b  = x as Bool;   verifySame(b , null)
    8.28 +    s  = x as Str;    verifySame(s , x)
    8.29 +    l  = x as List;   verifySame(l , null)
    8.30 +    ol = x as Obj[];  verifySame(ol , null)
    8.31 +    il = x as Int[];  verifySame(il , null) // no runtime check
    8.32 +    sl = x as Str[];  verifySame(sl , null) // no runtime check
    8.33 +    s2 = x as Str?[]; verifySame(sl , null) // no runtime check
    8.34 +  }
    8.35 +
    8.36 +//////////////////////////////////////////////////////////////////////////
    8.37 +// Cast
    8.38 +//////////////////////////////////////////////////////////////////////////
    8.39 +
    8.40 +  Void testCast()
    8.41 +  {
    8.42 +    Obj x := [2, 4f, 6d]
    8.43 +    verifyEq(((Num[])x)[1], 4f)
    8.44 +    verifyEq(((Int[])x)[0], 2)
    8.45 +
    8.46 +    strs := (Str[])x  // no runtime check
    8.47 +    verifyErr(CastErr#) { strs[2].size }
    8.48 +
    8.49 +    strs = x as Str[] // no runtime check
    8.50 +    verifyNotNull(strs)
    8.51 +    verifyErr(CastErr#) { strs[2].size }
    8.52    }
    8.53  
    8.54  //////////////////////////////////////////////////////////////////////////
     9.1 --- a/src/testSys/fan/MapTest.fan	Wed Apr 29 17:40:27 2009 -0400
     9.2 +++ b/src/testSys/fan/MapTest.fan	Thu Apr 30 10:01:48 2009 -0400
     9.3 @@ -135,8 +135,9 @@
     9.4      s  := x as Str;       verifySame(s , null)
     9.5      m  := x as Map;       verifySame(m , x)
     9.6      ol := x as Obj:Obj;   verifySame(ol , x)
     9.7 -    il := x as Int:Int;   verifySame(il , null)
     9.8 -    sl := x as Int:Str;   verifySame(sl , null)
     9.9 +    il := x as Int:Int;   verifySame(il , x) // no runtime check
    9.10 +    sl := x as Int:Str;   verifySame(sl , x) // no runtime check
    9.11 +    s2 := x as Int:Str?;  verifySame(s2 , x) // no runtime check
    9.12  
    9.13      x  = [0:"a", 1:"b"]
    9.14      o  = x as Obj;       verifySame(o , x)
    9.15 @@ -144,8 +145,17 @@
    9.16      s  = x as Str;       verifySame(s , null)
    9.17      m  = x as Map;       verifySame(m , x)
    9.18      ol = x as Obj:Obj;   verifySame(ol , x)
    9.19 -    il = x as Int:Int;   verifySame(il , null)
    9.20 -    sl = x as Int:Str;   verifySame(sl , x)
    9.21 +    il = x as Int:Int;   verifySame(il , x) // no runtime check
    9.22 +    sl = x as Int:Str;   verifySame(sl , x) // no runtime check
    9.23 +    s2 = x as Int:Str?;  verifySame(s2 , x) // no runtime check
    9.24 +
    9.25 +    x  = 4f
    9.26 +    o  = x as Obj;       verifySame(o , x)
    9.27 +    n := x as Num;       verifySame(o , n)
    9.28 +    f := x as Float;     verifySame(o , f)
    9.29 +    m  = x as Map;       verifySame(m , null)
    9.30 +    ol = x as Obj:Obj;   verifySame(ol, null)
    9.31 +    il = x as Int:Int;   verifySame(il, null)
    9.32    }
    9.33  
    9.34  //////////////////////////////////////////////////////////////////////////