2005-02-25 Martin Baulig <martin@ximian.com>
authorMartin Baulig <martin@novell.com>
Fri, 25 Feb 2005 18:43:07 +0000 (18:43 -0000)
committerMartin Baulig <martin@novell.com>
Fri, 25 Feb 2005 18:43:07 +0000 (18:43 -0000)
The first part of Nullable Types :-)

* generic.cs (NullableType): New public class.
(NullCoalescingOperator): New public class.
(TypeArguments.Resolve): Add a CS0306 check.

* cs-parser.jay (opt_error_modifier): Removed, this was unused.
(opt_nullable): New rule.
(type): Added `opt_nullable' to `namespace_or_type_name',
`builtin_types' and `pointer_type'.
(array_type): Added `opt_nullable'.
(opt_rank_specifier_or_nullable): New rule; this is the
combination of `opt_rank_specifier' and `opt_nullable'.
(opt_error): New rule; catch errors here.
(nullable_type_or_conditional): New rule; we use this to check for
nullable and still detect the conditional operator.
(local_variable_type): Use `opt_rank_specifier_or_nullable'
instead `opt_rank_specifier'.

* expression.cs (ComposedCast.DoResolveAsTypeStep): Added support
for nullables.

svn path=/trunk/mcs/; revision=41210

mcs/gmcs/ChangeLog
mcs/gmcs/cs-parser.jay
mcs/gmcs/cs-tokenizer.cs
mcs/gmcs/expression.cs
mcs/gmcs/generic.cs

index ab5feb7e00404c3ea609ab190aba4f1a283fc891..b4f91f63ade3459014b0ef5a4076aa11261e772c 100644 (file)
@@ -1,3 +1,27 @@
+2005-02-25  Martin Baulig  <martin@ximian.com>
+
+       The first part of Nullable Types :-)
+
+       * generic.cs (NullableType): New public class.
+       (NullCoalescingOperator): New public class.
+       (TypeArguments.Resolve): Add a CS0306 check.
+
+       * cs-parser.jay (opt_error_modifier): Removed, this was unused.
+       (opt_nullable): New rule.
+       (type): Added `opt_nullable' to `namespace_or_type_name',
+       `builtin_types' and `pointer_type'.
+       (array_type): Added `opt_nullable'.
+       (opt_rank_specifier_or_nullable): New rule; this is the
+       combination of `opt_rank_specifier' and `opt_nullable'.
+       (opt_error): New rule; catch errors here.
+       (nullable_type_or_conditional): New rule; we use this to check for
+       nullable and still detect the conditional operator.
+       (local_variable_type): Use `opt_rank_specifier_or_nullable'
+       instead `opt_rank_specifier'.
+
+       * expression.cs (ComposedCast.DoResolveAsTypeStep): Added support
+       for nullables.
+
 2005-02-24  Martin Baulig  <martin@ximian.com>
 
        * README, README.Changes: Removed; they're old and obsolete.
index 285bde8a1bc4249cac4a9f3cbdd12e8b7366fbec..fe3ad7cf385df86608eb8aaca32479e8d788fc64 100644 (file)
@@ -1036,25 +1036,6 @@ method_declaration
          }
        ;
 
-opt_error_modifier
-       : /* empty */
-       | modifiers 
-         {
-               int m = (int) $1;
-               int i = 1;
-
-               while (m != 0){
-                       if ((i & m) != 0){
-                               Report.Error (
-                                       1585, lexer.Location, "Member modifier `" + 
-                                       Modifiers.Name (i) + "' must precede member type and name");
-                       }
-                       m &= ~i;
-                       i = i << 1;
-               }
-         }
-       ;
-
 method_header
        : opt_attributes
          opt_modifiers
@@ -2449,6 +2430,19 @@ delegate_declaration
          }
        ;
 
+opt_nullable
+       : /* empty */
+         {
+               lexer.CheckNullable (false);
+               $$ = false;
+         }
+       | INTERR
+         {
+               lexer.CheckNullable (true);
+               $$ = true;
+         }
+       ;
+
 namespace_or_type_name
        : member_name
        | namespace_or_type_name DOT IDENTIFIER opt_type_argument_list {
@@ -2494,16 +2488,22 @@ type_arguments
  * gets rid of a shift/reduce couple
  */
 type
-       : namespace_or_type_name
+       : namespace_or_type_name opt_nullable
          {
                $$ = ((MemberName) $1).GetTypeExpression (lexer.Location);
+
+               if ((bool) $2)
+                       $$ = new NullableType ((Expression) $$, lexer.Location);
+         }
+       | builtin_types opt_nullable
+         {
+               if ((bool) $2)
+                       $$ = new NullableType ((Expression) $1, lexer.Location);
          }
-       | builtin_types
        | array_type
-       | pointer_type    
+       | pointer_type
        ;
 
-
 pointer_type
        : type STAR
          {
@@ -2594,9 +2594,13 @@ integral_type
        ;
 
 array_type
-       : type rank_specifiers
+       : type rank_specifiers opt_nullable
          {
-               $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
+               string rank_specifiers = (string) $2;
+               if ((bool) $3)
+                       rank_specifiers += "?";
+
+               $$ = new ComposedCast ((Expression) $1, rank_specifiers, lexer.Location);
          }
        ;
 
@@ -2608,8 +2612,7 @@ primary_expression
          {
                // 7.5.1: Literals
          }
-       | member_name
+       | member_name
          {
                $$ = ((MemberName) $1).GetTypeExpression (lexer.Location);
          }
@@ -2938,6 +2941,31 @@ opt_rank_specifier
          }
        ;
 
+opt_rank_specifier_or_nullable
+       : /* empty */
+         {
+               $$ = "";
+         }
+       | INTERR
+         {
+               $$ = "?";
+         }
+       | opt_nullable rank_specifiers
+         {
+               if ((bool) $1)
+                       $$ = "?" + $2;
+               else
+                       $$ = $2;
+         }
+       | opt_nullable rank_specifiers INTERR
+         {
+               if ((bool) $1)
+                       $$ = "?" + $2 + "?";
+               else
+                       $$ = $2 + "?";
+         }
+       ;
+
 rank_specifiers
        : rank_specifier opt_rank_specifier
          {
@@ -3288,6 +3316,21 @@ shift_expression
          }
        ; 
 
+opt_error
+       : /* empty */
+       | error
+         {
+               lexer.PutbackNullable ();
+         }
+       ;
+
+nullable_type_or_conditional
+       : type opt_error
+         {
+               $$ = $1;
+         }
+       ;
+
 relational_expression
        : shift_expression
        | relational_expression OP_LT shift_expression
@@ -3310,13 +3353,19 @@ relational_expression
                $$ = new Binary (Binary.Operator.GreaterThanOrEqual, 
                                 (Expression) $1, (Expression) $3, lexer.Location);
          }
-       | relational_expression IS type
+       | relational_expression IS
+         {
+               yyErrorFlag = 3;
+         } nullable_type_or_conditional
          {
-               $$ = new Is ((Expression) $1, (Expression) $3, lexer.Location);
+               $$ = new Is ((Expression) $1, (Expression) $4, lexer.Location);
          }
-       | relational_expression AS type
+       | relational_expression AS
          {
-               $$ = new As ((Expression) $1, (Expression) $3, lexer.Location);
+               yyErrorFlag = 3;
+         } nullable_type_or_conditional
+         {
+               $$ = new As ((Expression) $1, (Expression) $4, lexer.Location);
          }
        ;
 
@@ -3385,6 +3434,10 @@ conditional_expression
          {
                $$ = new Conditional ((Expression) $1, (Expression) $3, (Expression) $5, lexer.Location);
          }
+       | conditional_or_expression INTERR INTERR expression
+         {
+               $$ = new NullCoalescingOperator ((Expression) $1, (Expression) $4, lexer.Location);
+         }
        ;
 
 assignment_expression
@@ -3677,8 +3730,8 @@ block
                        current_block = new ToplevelBlock ((ToplevelBlock) top_current_block, current_local_parameters, lexer.Location);
                        top_current_block = current_block;
                } else {
-               current_block = new Block (current_block, current_local_parameters,
-                                          lexer.Location, Location.Null);
+                       current_block = new Block (current_block, current_local_parameters,
+                                                  lexer.Location, Location.Null);
                }
          } 
          opt_statement_list CLOSE_BRACE 
@@ -3793,7 +3846,7 @@ declaration_statement
  * > The expressions are converted into types during semantic analysis.
  */
 local_variable_type
-       : primary_expression opt_rank_specifier
+       : primary_expression opt_rank_specifier_or_nullable
          { 
                // FIXME: Do something smart here regarding the composition of the type.
 
@@ -3827,7 +3880,7 @@ local_variable_type
                                $$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
                }
          }
-       | builtin_types opt_rank_specifier
+       | builtin_types opt_rank_specifier_or_nullable
          {
                if ((string) $2 == "")
                        $$ = $1;
@@ -3871,7 +3924,7 @@ local_variable_declaration
                else
                        $$ = null;
          }
-        | local_variable_pointer_type opt_rank_specifier variable_declarators
+        | local_variable_pointer_type opt_rank_specifier_or_nullable variable_declarators
        {
                if ($1 != null){
                        Expression t;
index 47b47736373553be4ac26467c7b3cb3f13eabd22..df8e977f87ed88652939c27fda14383e33b87c9c 100644 (file)
@@ -499,6 +499,8 @@ namespace Mono.CSharp
                                return true;
                        else if ((the_token == Token.COMMA) || (the_token == Token.DOT))
                                goto start;
+                       else if (the_token == Token.INTERR)
+                               goto again;
                        else if (the_token == Token.OP_GENERICS_LT) {
                                if (!parse_less_than ())
                                        return false;
@@ -745,11 +747,33 @@ namespace Mono.CSharp
                        deambiguate_close_parens++;
                }
 
+               public void PutbackNullable ()
+               {
+                       if (nullable_pos < 0)
+                               throw new Exception ();
+
+                       current_token = -1;
+                       val = null;
+                       reader.Position = nullable_pos;
+
+                       putback_char = '?';
+               }
+
                void Error_NumericConstantTooLong ()
                {
                        Report.Error (1021, Location, "Numeric constant too long");                     
                }
-               
+
+               int nullable_pos = -1;
+
+               public void CheckNullable (bool is_nullable)
+               {
+                       if (is_nullable)
+                               nullable_pos = reader.Position;
+                       else
+                               nullable_pos = -1;
+               }
+
                bool decimal_digits (int c)
                {
                        int d;
index 2bd435d050d4b1cce2e2279d285a7b75e0448f51..8f3317a8030dffcb1f8a4691340b216745acd6b2 100644 (file)
@@ -8802,6 +8802,11 @@ namespace Mono.CSharp {
                                return null;
                        }
 
+                       if (dim == "?") {
+                               NullableType nullable = new NullableType (left, loc);
+                               return nullable.ResolveAsTypeTerminal (ec);
+                       }
+
                        int pos = 0;
                        while ((pos < dim.Length) && (dim [pos] == '[')) {
                                pos++;
index c60682e3bd3ca3a4c011ade80654f8506cb24ee6..78a37d6be9def87c3c2c28c25cbd4afb90b4dcd7 100644 (file)
@@ -1002,6 +1002,12 @@ namespace Mono.CSharp {
                                if (te is TypeParameterExpr)
                                        has_type_args = true;
 
+                               if (te.Type.IsPointer) {
+                                       Report.Error (306, Location, "The type `{0}' may not be used " +
+                                                     "as a type argument.", TypeManager.CSharpName (te.Type));
+                                       return false;
+                               }
+
                                atypes [i] = te.Type;
                        }
                        return ok;
@@ -1548,6 +1554,36 @@ namespace Mono.CSharp {
                }
        }
 
+       public class NullableType : TypeExpr
+       {
+               Expression underlying;
+
+               public NullableType (Expression underlying, Location l)
+               {
+                       this.underlying = underlying;
+                       loc = l;
+
+                       eclass = ExprClass.Type;
+               }
+
+               public override string Name {
+                       get { return underlying.ToString (); }
+               }
+
+               public override string FullName {
+                       get { return underlying.ToString (); }
+               }
+
+               protected override TypeExpr DoResolveAsTypeStep (EmitContext ec)
+               {
+                       TypeArguments args = new TypeArguments (loc);
+                       args.Add (underlying);
+
+                       ConstructedType ctype = new ConstructedType (TypeManager.generic_nullable_type, args, loc);
+                       return ctype.ResolveAsTypeTerminal (ec);
+               }
+       }
+
        public partial class TypeManager
        {
                //
@@ -2182,4 +2218,27 @@ namespace Mono.CSharp {
                        return true;
                }
        }
+
+       public class NullCoalescingOperator : Expression
+       {
+               Expression left;
+               Expression right;
+
+               public NullCoalescingOperator (Expression left, Expression right, Location loc)
+               {
+                       this.left = left;
+                       this.right = right;
+                       this.loc = loc;
+               }
+
+               public override Expression DoResolve (EmitContext ec)
+               {
+                       Error (-1, "The ?? operator is not yet implemented.");
+                       return null;
+               }
+
+               public override void Emit (EmitContext ec)
+               {
+               }
+       }
 }