[svn] r6218: nemerle/trunk/ncc: external/InternalTypes.n generation/ILEmitter.n hierarchy/NamespaceTree.n ...

nazgul svnadmin at nemerle.org
Wed May 3 16:24:03 CEST 2006


Log:
Add basic support for nullable types

Author: nazgul
Date: Wed May  3 16:23:42 2006
New Revision: 6218

Added:
   nemerle/trunk/ncc/testsuite/positive/nullable.n
Modified:
   nemerle/trunk/ncc/external/InternalTypes.n
   nemerle/trunk/ncc/generation/ILEmitter.n
   nemerle/trunk/ncc/hierarchy/NamespaceTree.n
   nemerle/trunk/ncc/typing/MType.n
   nemerle/trunk/ncc/typing/Typer2.n

Modified: nemerle/trunk/ncc/external/InternalTypes.n
==============================================================================
--- nemerle/trunk/ncc/external/InternalTypes.n	(original)
+++ nemerle/trunk/ncc/external/InternalTypes.n	Wed May  3 16:23:42 2006
@@ -397,6 +397,7 @@
   public mutable Generic_IEnumerator_tc : TypeInfo;
   public mutable Generic_IList_tc : TypeInfo;
   public mutable Generic_ICollection_tc : TypeInfo;
+  public mutable Generic_Nullable_tc : TypeInfo;
   public mutable DllImport_tc : TypeInfo;
   public mutable Serializable_tc : TypeInfo;    
 
@@ -513,6 +514,13 @@
     }
   }
 
+  lookup (type_name : string, args_count : int) : TypeInfo
+  {
+    match (NamespaceTree.LookupExactType (type_name, args_count)) {
+      | Some (t) => t
+      | None => Util.ice ("internal type " + type_name + " not found")
+    }
+  }
     
   internal InitSystemTypes () : void
   {
@@ -553,6 +561,7 @@
     Generic_IEnumerator_tc = lookup ("System.Collections.Generic.IEnumerator");
     Generic_IList_tc = lookup ("System.Collections.Generic.IList");
     Generic_ICollection_tc = lookup ("System.Collections.Generic.ICollection");
+    Generic_Nullable_tc = lookup ("System.Nullable", 1);
     DllImport_tc = lookup ("System.Runtime.InteropServices.DllImportAttribute");
     Serializable_tc = lookup ("System.SerializableAttribute");    
     IObjectReference = MType.Class (lookup ("System.Runtime.Serialization.IObjectReference"), []);

Modified: nemerle/trunk/ncc/generation/ILEmitter.n
==============================================================================
--- nemerle/trunk/ncc/generation/ILEmitter.n	(original)
+++ nemerle/trunk/ncc/generation/ILEmitter.n	Wed May  3 16:23:42 2006
@@ -1268,12 +1268,16 @@
         /* loads a literal on the evaluation stack */
         | Literal (l) => 
           Util.cassert (l != null);
-          if (expr.MType is MType.TyVarRef && l is Literal.Null)
+          if (l is Literal.Null)
+            match (expr.MType) {
+              | TyVarRef 
+              | Class (tc,[_]) when tc.Equals (InternalType.Generic_Nullable_tc) =>
             emit (TExpr.DefaultValue (expr.loc, expr.Type))
+              | _ => emit_literal (l);
+            }
           else
             emit_literal (l);
 
-
         /* loads address of given method */
         | MethodAddress (from, meth, is_virt, typarms) =>
           Mark (expr.loc);

Modified: nemerle/trunk/ncc/hierarchy/NamespaceTree.n
==============================================================================
--- nemerle/trunk/ncc/hierarchy/NamespaceTree.n	(original)
+++ nemerle/trunk/ncc/hierarchy/NamespaceTree.n	Wed May  3 16:23:42 2006
@@ -482,7 +482,11 @@
     }
     
     public LookupExactType (name : string) : option [TypeInfo] {
-      namespace_tree.LookupType (NString.Split (name, '.'), -1)
+      LookupExactType (name, -1)
+    }
+
+    public LookupExactType (name : string, args_count : int) : option [TypeInfo] {
+      namespace_tree.LookupType (NString.Split (name, '.'), args_count)
     }
 
     public LookupExactType (name : list [string]) : option [TypeInfo] {

Added: nemerle/trunk/ncc/testsuite/positive/nullable.n
==============================================================================
--- (empty file)
+++ nemerle/trunk/ncc/testsuite/positive/nullable.n	Wed May  3 16:23:42 2006
@@ -0,0 +1,35 @@
+
+module TestsNullable 
+{
+  print (x : int?) : void {
+    def isnull = x == null;  
+    def isnotnull = x != null;
+    assert (isnull == (null == x));
+    assert (isnotnull == (null != x));
+    assert (isnull != isnotnull);
+    Nemerle.IO.print ("isnull=$isnull value=$x\n");
+  }
+  
+  basic () : void {
+    print (1);  
+    print (null); 
+  }
+
+  equals () : void {
+    mutable x = null;
+    assert (x.Equals (null));
+    _ = x : int?;
+  }
+    
+  Main () : void {
+    basic();
+    equals ();
+  }
+}
+
+/*
+BEGIN-OUTPUT
+isnull=False value=1
+isnull=True value=
+END-OUTPUT
+*/
\ No newline at end of file

Modified: nemerle/trunk/ncc/typing/MType.n
==============================================================================
--- nemerle/trunk/ncc/typing/MType.n	(original)
+++ nemerle/trunk/ncc/typing/MType.n	Wed May  3 16:23:42 2006
@@ -444,7 +444,7 @@
     {
       get {
         match (this) {
-          | Class (ti, _) => !ti.IsValueType
+          | Class (ti, _) => !ti.IsValueType || ti.Equals (InternalType.Generic_Nullable_tc)
           
           | Ref
           | Out

Modified: nemerle/trunk/ncc/typing/Typer2.n
==============================================================================
--- nemerle/trunk/ncc/typing/Typer2.n	(original)
+++ nemerle/trunk/ncc/typing/Typer2.n	Wed May  3 16:23:42 2006
@@ -1002,8 +1002,8 @@
                   ValKind = LocalValue.Kind.BlockReturn) as decl) =>
                 BuildBlockReturn (ctx, expr.Type, decl, parms)
 
-              | TExpr.OpCode ("==.ref")
-              | TExpr.OpCode ("!=.ref") =>
+              | TExpr.OpCode ("==.ref") with eq = true
+              | TExpr.OpCode ("!=.ref") with eq = false =>
                 match (parms) {
                   | [p1, p2] =>
                     def e1 = StripImplicitConversion (p1.expr);
@@ -1011,6 +1011,31 @@
 
                     def t1 = e1.Type.Fix ();
                     def t2 = e2.Type.Fix ();
+                    
+                    //Message.Debug ($"$t1 $t2 with $eq");
+                    
+                    match ((t1, t2)) {
+                      // nullable types need special handling in comparisons
+                      | (MType.Class (tc, _), _) when tc.Equals (InternalType.Generic_Nullable_tc) 
+                      | (_, MType.Class (tc, _)) when tc.Equals (InternalType.Generic_Nullable_tc) => 
+                        match ((e1, e2)) {
+                          | (TExpr.Literal (Literal.Null), e) 
+                          | (e, TExpr.Literal (Literal.Null)) =>
+                            def hasval = TExpr.Call (expr.Type, TExpr.MethodRef (e, 
+                              InternalType.Generic_Nullable_tc.LookupMember ("get_HasValue").Head :> IMethod, [], false), [], false);
+                            if (eq)
+                              TExpr.Call (expr.Type, TExpr.OpCode ("bool.!"), [Parm (hasval)], false)
+                            else
+                              hasval
+                          
+                          | _ => 
+                            ReportError (messenger, 
+                                         $ "Comparison of two nullable instances is not yet supported.");
+                            Message.HintOnce ("You can compare only with null or use Equals method.");
+                            TExpr.Call (Unfold (func), parms, false)
+                        }
+                      
+                      | _ =>
                     def prob =
                       if (t1.IsSystemObject && !t2.CanBeNull) t2
                       else if (t2.IsSystemObject && !t1.CanBeNull) t1
@@ -1030,6 +1055,8 @@
                     } else {}
 
                     TExpr.Call (Unfold (func), parms, false)
+                    }
+                    
                   | _ => assert (false)
                 }
 



More information about the svn mailing list