Skip to content

Commit

Permalink
Initial version of strict operators
Browse files Browse the repository at this point in the history
  • Loading branch information
marek-safar committed Aug 29, 2013
1 parent 23daaa8 commit 242738b
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 19 deletions.
Expand Up @@ -52,6 +52,11 @@ public enum BinaryOperator
BitwiseOr = 32,

LogicalAnd = 40,
LogicalOr = 41
LogicalOr = 41,

StrictEquality = 50 | StrictMask,
StrictInequality = 51 | StrictMask,

StrictMask = 1 >> 16
}
}
48 changes: 48 additions & 0 deletions mcs/class/PlayScript.Core/PlayScript.Runtime/Operations.cs
Expand Up @@ -37,6 +37,11 @@ public static bool Comparison (BinaryOperator binaryOperator, object left, objec
if (right is int)
return Comparison (binaryOperator, left, (int) right);

if (right is string)
return Comparison (binaryOperator, left, (string) right);

// TODO: uint, string, double, etc

return false;
}

Expand All @@ -46,6 +51,7 @@ public static bool Comparison (BinaryOperator binaryOperator, object left, int r
var l = (int) left;
switch (binaryOperator) {
case BinaryOperator.Equality:
case BinaryOperator.StrictEquality:
return l == right;
case BinaryOperator.Inequality:
return l != right;
Expand All @@ -62,6 +68,9 @@ public static bool Comparison (BinaryOperator binaryOperator, object left, int r
}
}

if ((binaryOperator & BinaryOperator.StrictMask) != 0)
return binaryOperator == BinaryOperator.StrictInequality;

// TODO: uint, string, double, etc

return false;
Expand All @@ -73,8 +82,10 @@ public static bool Comparison (BinaryOperator binaryOperator, int left, object r
var r = (int) right;
switch (binaryOperator) {
case BinaryOperator.Equality:
case BinaryOperator.StrictEquality:
return left == r;
case BinaryOperator.Inequality:
case BinaryOperator.StrictInequality:
return left != r;
case BinaryOperator.GreaterThan:
return left > r;
Expand All @@ -89,6 +100,43 @@ public static bool Comparison (BinaryOperator binaryOperator, int left, object r
}
}

if ((binaryOperator & BinaryOperator.StrictMask) != 0)
return binaryOperator == BinaryOperator.StrictInequality;

// TODO: uint, string, double, etc

return false;
}

public static bool Comparison (BinaryOperator binaryOperator, object left, string right)
{
if (right is string) {
var l = (string) left;
switch (binaryOperator) {
case BinaryOperator.Equality:
case BinaryOperator.StrictEquality:
return l == right;
case BinaryOperator.Inequality:
case BinaryOperator.StrictInequality:
return l != right;
/* TODO: rules base on char comparison but how does it work with unicode
case BinaryOperator.GreaterThan:
return l > right;
case BinaryOperator.GreaterThanOrEqual:
return l >= right;
case BinaryOperator.LessThan:
return l < right;
case BinaryOperator.LessThanOrEqual:
return l <= right;
default:
throw new NotImplementedException (binaryOperator.ToString ());
*/
}
}

if ((binaryOperator & BinaryOperator.StrictMask) != 0)
return binaryOperator == BinaryOperator.StrictInequality;

// TODO: uint, string, double, etc

return false;
Expand Down
30 changes: 22 additions & 8 deletions mcs/mcs/expression.cs
Expand Up @@ -2289,8 +2289,8 @@ public enum Operator {
GreaterThanOrEqual = 11 | ComparisonMask | RelationalMask,
Equality = 12 | ComparisonMask | EqualityMask,
Inequality = 13 | ComparisonMask | EqualityMask,
ReferenceEquality = 14 | ComparisonMask | EqualityMask, // PlayScript Reference Equality
ReferenceInequality = 15 | ComparisonMask | EqualityMask, // PlayScript Reference Inequality
StrictEquality = 14 | ComparisonMask | EqualityMask | NoUserVersion, // PlayScript Strict Equality
StrictInequality = 15 | ComparisonMask | EqualityMask | NoUserVersion, // PlayScript Strict Inequality


BitwiseAnd = 16 | BitwiseMask,
Expand All @@ -2316,6 +2316,7 @@ public enum Operator {

DecomposedMask = 1 << 19,
NullableMask = 1 << 20,
NoUserVersion = 1 << 21
}

[Flags]
Expand Down Expand Up @@ -2425,13 +2426,13 @@ string OperName (Operator oper)
case Operator.Equality:
s = "==";
break;
case Operator.ReferenceEquality:
case Operator.StrictEquality:
s = "===";
break;
case Operator.Inequality:
s = "!=";
break;
case Operator.ReferenceInequality:
case Operator.StrictInequality:
s = "!==";
break;
case Operator.BitwiseAnd:
Expand Down Expand Up @@ -2655,10 +2656,12 @@ public static void EmitOperatorOpcode (EmitContext ec, Operator oper, TypeSpec l
break;

case Operator.Equality:
case Operator.StrictEquality:
opcode = OpCodes.Ceq;
break;

case Operator.Inequality:
case Operator.StrictInequality:
ec.Emit (OpCodes.Ceq);
ec.EmitInt (0);

Expand Down Expand Up @@ -2769,9 +2772,11 @@ public Expression ResolveOperator (ResolveContext rc)
return ResolveOperatorPointer (rc, l, r);

// User operators
expr = ResolveUserOperator (rc, left, right);
if (expr != null)
return expr;
if ((oper & Operator.NoUserVersion) == 0) {
expr = ResolveUserOperator (rc, left, right);
if (expr != null)
return expr;
}


bool lenum = l.IsEnum;
Expand Down Expand Up @@ -2833,7 +2838,14 @@ public Expression ResolveOperator (ResolveContext rc)
// Equality operators are more complicated
//
if ((oper & Operator.EqualityMask) != 0) {
return ResolveEquality (rc, l, r, primitives_only);
expr = ResolveEquality (rc, l, r, primitives_only);
if (primitives_only)
return expr;

if (oper == Operator.StrictEquality || oper == Operator.StrictInequality)
return PlayScript.BinaryOperators.ResolveOperator (rc, this, left, right);

return expr;
}

expr = ResolveOperatorPredefined (rc, rc.BuiltinTypes.OperatorsBinaryStandard, primitives_only);
Expand Down Expand Up @@ -4452,13 +4464,15 @@ public override void EmitBranchable (EmitContext ec, Label target, bool on_true)

switch (oper){
case Operator.Equality:
case Operator.StrictEquality:
if (on_true)
ec.Emit (OpCodes.Beq, target);
else
ec.Emit (OpCodes.Bne_Un, target);
break;

case Operator.Inequality:
case Operator.StrictInequality:
if (on_true)
ec.Emit (OpCodes.Bne_Un, target);
else
Expand Down
15 changes: 8 additions & 7 deletions mcs/mcs/playscript.cs
Expand Up @@ -193,31 +193,32 @@ class BinaryOperators
{
public static Expression ResolveOperator (ResolveContext rc, Binary op, Expression left, Expression right)
{
string method, oper;
string method = "Comparison";
string oper;
switch (op.Oper) {
case Binary.Operator.Equality:
oper = "Equality";
method = "Comparison";
break;
case Binary.Operator.Inequality:
oper = "Inequality";
method = "Comparison";
break;
case Binary.Operator.GreaterThan:
oper = "GreaterThan";
method = "Comparison";
break;
case Binary.Operator.GreaterThanOrEqual:
oper = "GreaterThanOrEqual";
method = "Comparison";
break;
case Binary.Operator.LessThan:
oper = "LessThan";
method = "Comparison";
break;
case Binary.Operator.LessThanOrEqual:
oper = "LessThanOrEqual";
method = "Comparison";
break;
case Binary.Operator.StrictEquality:
oper = "StrictEquality";
break;
case Binary.Operator.StrictInequality:
oper = "StrictInequality";
break;
default:
throw new NotImplementedException ();
Expand Down
4 changes: 2 additions & 2 deletions mcs/mcs/ps-parser.jay
Expand Up @@ -3690,12 +3690,12 @@ equality_expression
}
| equality_expression OP_REF_EQ relational_expression
{
$$ = new Binary (Binary.Operator.ReferenceEquality, (Expression) $1, (Expression) $3);
$$ = new Binary (Binary.Operator.StrictEquality, (Expression) $1, (Expression) $3);
lbag.AddLocation ($$, GetLocation ($2));
}
| equality_expression OP_REF_NE relational_expression
{
$$ = new Binary (Binary.Operator.ReferenceInequality, (Expression) $1, (Expression) $3);
$$ = new Binary (Binary.Operator.StrictInequality, (Expression) $1, (Expression) $3);
lbag.AddLocation ($$, GetLocation ($2));
}
;
Expand Down
64 changes: 63 additions & 1 deletion mcs/tests/test-ps-014.play
Expand Up @@ -2,14 +2,76 @@ package
{
public class BinaryOperations
{
public static function Main ():int
static function MixedTypes ():int
{
var a:Object = 400;
if (a != 400)
return 1;

if (400 != a)
return 2;

return 0;
}

static function StrictEquality ():int
{
var i:int = 4;
var i2:int = 4;

if (!(i == i2))
return 1;
if (!(i === i2))
return 2;

var s:String = "x";
var s2:String = "x";

if (!(s == s2))
return 3;
if (!(s === s2))
return 4;

var d:Number = 2.0;
var di2:int = 2;

if (!(d == di2))
return 5;

var o:Object = new Object ();
var o2:Object = new Object ();
if (o == o2)
return 6;
if (o === o2)
return 7;

var o3:Object = 6;
var o4:Object = 6;
if (!(o3 == o4))
return 8;
if (!(o3 === o4))
return 9;

var os:Object = "oo";
var os2:Object = "oo";
if (!(os == os2))
return 10;
if (!(os === os2))
return 11;

return 0;
}

public static function Main ():int
{
var r:int;
r = MixedTypes ();
if (r != 0)
return r + 100;

r = StrictEquality ();
if (r != 0)
return r + 200;

trace ("ok");
return 0;
Expand Down

0 comments on commit 242738b

Please sign in to comment.