[nem-en] Operator ??
Ivan A Eryshov
ivan.eryshov at gmail.com
Fri Sep 29 12:03:44 CEST 2006
Hi Michal,
On 26/09/06, Michal Moskal <michal.moskal at gmail.com> wrote:
> As a general remark, it might not be the best idea to follow each and
> every rule. Especially that they are not designed with type inference
> in mind.
Ok. I skip rare cases and add option support. Here is the macro and testes:
// MACRO
namespace Nemerle.Core
{
macro @?? (exprA, exprB)
{
def refEq = System.Type.ReferenceEquals;
def ref3Eq = (t1,t2,t3) => refEq(t1, t2) || refEq(t1, t3);
def tnullable = typeof (System.Nullable[_]);
def toptNone = typeof (Nemerle.Core.option[_].None);
def toptSome = typeof (Nemerle.Core.option[_].Some);
def typer = Macros.ImplicitCTX ();
def hA = typer.TypeExpr (exprA).Type.Hint;
def hB = typer.TypeExpr (exprB).Type.Hint;
def tx = (hA, hB);
match (tx) {
| (Some (Class (tiA, _)), Some (Class (tiB, _)))
when tiA.IsValueType && refEq (tiA.SystemType, tnullable)
&& !refEq (tiB.SystemType, tnullable)
|| ref3Eq (tiA.SystemType, toptNone, toptSome)
&& !ref3Eq (tiB.SystemType, toptNone, toptSome) =>
<[ if ($exprA.HasValue) $exprA.Value else $exprB ]>;
| (Some (Class (tiA, _)), Some (Class (tiB, _)))
when tiA.IsValueType && refEq (tiA.SystemType, tnullable)
&& refEq (tiB.SystemType, tnullable) =>
<[ if ($exprA != null) $exprA else $exprB ]>;
| (Some (Class (tiA, _)), Some (Class (tiB, _)))
when ref3Eq (tiA.SystemType, toptNone, toptSome)
&& ref3Eq (tiB.SystemType, toptNone, toptSome) =>
<[ if ($exprA.IsSome) $exprA else $exprB ]>;
| (Some (Class (tiA, _)), Some (Class (_, _)))
when tiA.IsValueType =>
Message.FatalError (exprA.Location,
$"`$tiA' is not a reference or nullable type "
"as required by the `??' operator");
| _ =>
<[ if ($exprA != null) $exprA else $exprB ]>;
}
}
}
// TESTES
using System.Console;
def GetExprType['t] (_ : 't)
{
typeof ('t)
}
def rn = null;
def r1 = "str1";
def r2 = "str2";
assert (rn ?? r2 == "str2");
assert (GetExprType(rn ?? r2).Equals (typeof (string)));
WriteLine($"$(rn ?? r2)");
assert (r1 ?? r2 == "str1");
assert (GetExprType(r1 ?? r2).Equals (typeof (string)));
WriteLine($"$(r1 ?? r2)");
def dn : double? = null;
def d1 : double? = 0.1;
def d2 : double? = 0.2;
assert ((dn ?? d2).Value == 0.2);
assert (GetExprType(dn ?? d2).Equals (typeof (double?)));
WriteLine($"$(dn ?? d2)");
assert ((d1 ?? d2).Value == 0.1);
assert (GetExprType(d1 ?? d2).Equals (typeof (double?)));
WriteLine($"$(d1 ?? d2)");
assert (dn ?? 0.3 == 0.3);
assert (GetExprType(dn ?? 0.3).Equals (typeof (double)));
WriteLine($"$(dn ?? 0.3)");
assert (d1 ?? 0.3 == 0.1);
assert (GetExprType(d1 ?? 0.3).Equals (typeof (double)));
WriteLine($"$(d1 ?? 0.3)");
def on = None();
def on2 = None();
def o1 = Some(1);
def o2 = Some(2);
assert ((on ?? o2).IsSome);
assert ((on ?? o2).Value == 2);
assert (GetExprType(on ?? o2).Equals (typeof (option[int])));
WriteLine($"$(on ?? o2)");
assert ((o1 ?? o2).Value == 1);
assert (GetExprType(o1 ?? o2).Equals (typeof (option[int].Some)));
WriteLine($"$(o1 ?? o2)");
assert (on ?? 3 == 3);
assert (GetExprType(on ?? 3).Equals (typeof (int)));
WriteLine($"$(on ?? 3)");
assert (o1 ?? 3 == 1);
assert (GetExprType(o1 ?? 3).Equals (typeof (int)));
WriteLine($"$(o1 ?? 3)");
assert ((on ?? on2).IsNone);
assert (GetExprType(on ?? on2).Equals (typeof (option[int].None)));
WriteLine($"$(on ?? on2)");
--
Best Regards,
Ivan A Eryshov.
-= RSDN forever! =-
More information about the devel-en
mailing list