+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.
}
;
-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
}
;
+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 {
* 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
{
;
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);
}
;
{
// 7.5.1: Literals
}
-
- | member_name
+ | member_name
{
$$ = ((MemberName) $1).GetTypeExpression (lexer.Location);
}
}
;
+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
{
}
;
+opt_error
+ : /* empty */
+ | error
+ {
+ lexer.PutbackNullable ();
+ }
+ ;
+
+nullable_type_or_conditional
+ : type opt_error
+ {
+ $$ = $1;
+ }
+ ;
+
relational_expression
: shift_expression
| relational_expression OP_LT shift_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);
}
;
{
$$ = 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
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
* > 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.
$$ = new ComposedCast ((Expression) $1, (string) $2, lexer.Location);
}
}
- | builtin_types opt_rank_specifier
+ | builtin_types opt_rank_specifier_or_nullable
{
if ((string) $2 == "")
$$ = $1;
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;
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;
}
}
+ 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
{
//
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)
+ {
+ }
+ }
}