Skip to content

Commit

Permalink
chore: Implement an implicit operator for creating JS booleans
Browse files Browse the repository at this point in the history
  • Loading branch information
PrestonLTaylor committed Apr 4, 2024
1 parent ea1573d commit f0e437d
Show file tree
Hide file tree
Showing 16 changed files with 122 additions and 115 deletions.
136 changes: 68 additions & 68 deletions JSS.Lib.UnitTests/ASTTests.cs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions JSS.Lib.UnitTests/AbstractOperationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ internal sealed class AbstractOperationTests
static private readonly List<Value> toPrimitiveIdentityTestCases = new()
{
Null.The,
new Boolean(false),
new Boolean(true),
false,
true,
new Number(0.0),
new Number(1.0),
new Number(123456789.0),
Expand Down
4 changes: 2 additions & 2 deletions JSS.Lib/AST/GreaterThanEqualsExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ override public Completion Evaluate(VM vm)
if (r.IsAbruptCompletion()) return r;

// 6. If r is either true or undefined, return false. Otherwise, return true.
if (r.Value.IsUndefined()) return new Boolean(false);
if (r.Value.IsUndefined()) return false;

var rAsBoolean = r.Value.AsBoolean();
return new Boolean(!rAsBoolean.Value);
return !rAsBoolean.Value;
}

public IExpression Lhs { get; }
Expand Down
4 changes: 2 additions & 2 deletions JSS.Lib/AST/GreaterThanExpreesion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ override public Completion Evaluate(VM vm)
if (r.IsAbruptCompletion()) return r;

// 6. If r is undefined, return false. Otherwise, return r.
if (r.Value.IsUndefined()) return new Boolean(false);
if (r.Value.IsUndefined()) return false;

var rAsBoolean = r.Value.AsBoolean();
return new Boolean(rAsBoolean.Value);
return rAsBoolean.Value;
}

public IExpression Lhs { get; }
Expand Down
4 changes: 2 additions & 2 deletions JSS.Lib/AST/LessThanEqualsExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ override public Completion Evaluate(VM vm)
if (r.IsAbruptCompletion()) return r;

// 6. If r is either true or undefined, return false. Otherwise, return true.
if (r.Value.IsUndefined()) return new Boolean(false);
if (r.Value.IsUndefined()) return false;

var rAsBoolean = r.Value.AsBoolean();
return new Boolean(!rAsBoolean.Value);
return !rAsBoolean.Value;
}

public IExpression Lhs { get; }
Expand Down
4 changes: 2 additions & 2 deletions JSS.Lib/AST/LessThanExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ override public Completion Evaluate(VM vm)
if (r.IsAbruptCompletion()) return r;

// 6. If r is undefined, return false. Otherwise, return r.
if (r.Value.IsUndefined()) return new Boolean(false);
if (r.Value.IsUndefined()) return false;

var rAsBoolean = r.Value.AsBoolean();
return new Boolean(rAsBoolean.Value);
return rAsBoolean.Value;
}

public IExpression Lhs { get; }
Expand Down
2 changes: 1 addition & 1 deletion JSS.Lib/AST/Literal/BooleanLiteral.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ internal sealed class BooleanLiteral : IExpression
{
public BooleanLiteral(bool value)
{
_value = new Boolean(value);
_value = value;
}

// 13.2.3.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-literals-runtime-semantics-evaluation
Expand Down
2 changes: 1 addition & 1 deletion JSS.Lib/AST/LogicalNotExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ override public Completion Evaluate(VM vm)

// 3. If oldValue is true, return false.
// 4. Return true.
return new Boolean(!oldValue.Value);
return !oldValue.Value;
}

public IExpression Expression { get; }
Expand Down
2 changes: 1 addition & 1 deletion JSS.Lib/AST/LooseInequalityExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ override public Completion Evaluate(VM vm)

// 6. If r is true, return false. Otherwise, return true.
var rAsBoolean = r.Value.AsBoolean().Value;
return new Boolean(!rAsBoolean);
return !rAsBoolean;
}

public IExpression Lhs { get; }
Expand Down
2 changes: 1 addition & 1 deletion JSS.Lib/AST/StrictInequalityExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ override public Completion Evaluate(VM vm)
var r = Value.IsStrictlyEqual(rval.Value, lval.Value);

// 6. If r is true, return false. Otherwise, return true.
return new Boolean(!r.Value);
return !r.Value;
}

public IExpression Lhs { get; }
Expand Down
3 changes: 3 additions & 0 deletions JSS.Lib/AST/Values/Boolean.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ public Boolean(bool value)
Value = value;
}

public static implicit operator Boolean(bool value) => new(value);
public static implicit operator bool(Boolean boolean) => boolean.Value;

override public bool IsBoolean() { return true; }
override public ValueType Type() { return ValueType.Boolean; }

Expand Down
10 changes: 5 additions & 5 deletions JSS.Lib/AST/Values/Number.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ static public Value LessThan(Number x, Number y)
// FIXME: 10. Assert: x and y are finite.

// 11. If ℝ(x) < ℝ(y), return true. Otherwise, return false.
return new Boolean(x.Value < y.Value);
return x.Value < y.Value;
}

// 6.1.6.1.13 Number::equal ( x, y )
Expand All @@ -232,26 +232,26 @@ static public Boolean Equal(Number x, Number y)
// 1. If x is NaN, return false.
if (double.IsNaN(x.Value))
{
return new Boolean(false);
return false;
}

// 2. If y is NaN, return false.
if (double.IsNaN(y.Value))
{
return new Boolean(false);
return false;
}

// 3. If x is y, return true.
if (x.Value == y.Value)
{
return new Boolean(true);
return true;
}

// FIXME: 4. If x is +0𝔽 and y is -0𝔽, return true.
// FIXME: 5. If x is -0𝔽 and y is +0𝔽, return true.

// 6. Return false.
return new Boolean(false);
return false;
}

internal enum BitwiseOp
Expand Down
8 changes: 4 additions & 4 deletions JSS.Lib/AST/Values/Object.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ static public Completion HasOwnProperty(Object O, string P)

// 2. If desc is undefined, return false.
// 3. Return true.
return new Boolean(!desc.Value.IsUndefined());
return !desc.Value.IsUndefined();
}

// 7.3.14 Call ( F, V [ , argumentsList ] )
Expand Down Expand Up @@ -152,7 +152,7 @@ static public Completion OrdinaryDefineOwnProperty(Object O, string P, Property
// FIXME: 2. Let extensible be ? IsExtensible(O).
// FIXME: 3. Return ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current).
O.DataProperties.Add(P, desc);
return new Boolean(true);
return true;
}

// 10.1.7 [[HasProperty]] ( P ), https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-hasproperty-p
Expand All @@ -170,7 +170,7 @@ static public Completion OrdinaryHasProperty(Object O, string P)
if (hasOwn.IsAbruptCompletion()) return hasOwn;

// FIXME: 2. If hasOwn is not undefined, return true.
return new Boolean(!hasOwn.Value.IsUndefined());
return !hasOwn.Value.IsUndefined();

// FIXME: 3. Let parent be ? O.[[GetPrototypeOf]]().
// FIXME: 4. If parent is not null, then
Expand Down Expand Up @@ -225,7 +225,7 @@ static public Completion OrdinarySet(Object O, string P, Value V, Object receive
receiver.DataProperties[P] = new Property(V, new Attributes(true, false, false));
}

return new Boolean(true);
return true;
}

// FIXME: Accessor Attributes
Expand Down
30 changes: 16 additions & 14 deletions JSS.Lib/AST/Values/Value.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ internal enum ValueType
// 6.1 ECMAScript Language Types, https://tc39.es/ecma262/#sec-ecmascript-language-types
internal abstract class Value
{
public static implicit operator Value(bool value) => new Boolean(value);

virtual public bool IsEmpty() { return false; }
virtual public bool IsReference() { return false; }
virtual public bool IsEnvironment() { return false; }
Expand Down Expand Up @@ -229,15 +231,15 @@ public Boolean ToBoolean()
// 2. If argument is one of undefined, null, +0𝔽, -0𝔽, NaN, 0ℤ, or the empty String, return false.
if (IsUndefined() || IsNull())
{
return new Boolean(false);
return false;
}

if (IsNumber())
{
var asNumber = AsNumber().Value;
if (asNumber == 0 || double.IsNaN(asNumber))
{
return new Boolean(false);
return false;
}
}

Expand All @@ -246,14 +248,14 @@ public Boolean ToBoolean()
var asString = AsString().Value;
if (asString.Length == 0)
{
return new Boolean(false);
return false;
}
}

// 3. NOTE: This step is replaced in section B.3.6.1.

// 4. Return true.
return new Boolean(true);
return true;
}

// 7.1.3 ToNumeric ( value ), https://tc39.es/ecma262/#sec-tonumeric
Expand Down Expand Up @@ -426,7 +428,7 @@ static public Boolean SameValueNonNumber(Value x, Value y)
// 2. If x is either null or undefined, return true.
if (x.IsNull() || x.IsUndefined())
{
return new Boolean(true);
return true;
}

// FIXME: 3. If x is a BigInt, then
Expand All @@ -438,7 +440,7 @@ static public Boolean SameValueNonNumber(Value x, Value y)
// a. If x and y have the same length and the same code units in the same positions, return true; otherwise, return false.
var xAsString = x.AsString().Value;
var yAsString = y.AsString().Value;
return new Boolean(xAsString == yAsString);
return xAsString == yAsString;
}

// 5. If x is a Boolean, then
Expand All @@ -447,7 +449,7 @@ static public Boolean SameValueNonNumber(Value x, Value y)
// 6. If x and y are both true or both false, return true; otherwise, return false.
var xAsBoolean = x.AsBoolean().Value;
var yAsBoolean = y.AsBoolean().Value;
return new Boolean(xAsBoolean == yAsBoolean);
return xAsBoolean == yAsBoolean;
}

// FIXME: 6. NOTE: All other ECMAScript language values are compared by identity.
Expand Down Expand Up @@ -509,18 +511,18 @@ static public Completion IsLessThan(Value x, Value y, bool leftFirst)
// iii. If cx < cy, return true.
if (cx < cy)
{
return new Boolean(true);
return true;
}

// iv. If cx > cy, return false.
if (cx > cy)
{
return new Boolean(false);
return false;
}
}

// d. If lx < ly, return true. Otherwise, return false.
return new Boolean(lx < ly);
return lx < ly;
}

// 4. Else,
Expand Down Expand Up @@ -573,13 +575,13 @@ static public Completion IsLooselyEqual(Value x, Value y)
// 2. If x is null and y is undefined, return true.
if (x.IsNull() && y.IsUndefined())
{
return new Boolean(true);
return true;
}

// 3. If x is undefined and y is null, return true.
if (x.IsUndefined() && y.IsNull())
{
return new Boolean(true);
return true;
}

// 4. NOTE: This step is replaced in section B.3.6.2.
Expand Down Expand Up @@ -631,7 +633,7 @@ static public Completion IsLooselyEqual(Value x, Value y)
// FIXME: b. If ℝ(x) = ℝ(y), return true; otherwise return false.

// 14. Return false.
return new Boolean(false);
return false;
}

// 7.2.15 IsStrictlyEqual ( x, y ), https://tc39.es/ecma262/#sec-isstrictlyequal
Expand All @@ -640,7 +642,7 @@ static public Boolean IsStrictlyEqual(Value x, Value y)
// 1. If Type(x) is not Type(y), return false.
if (!x.Type().Equals(y.Type()))
{
return new Boolean(false);
return false;
}

// 2. If x is a Number, then
Expand Down
10 changes: 6 additions & 4 deletions JSS.Lib/Execution/Completion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public Completion(CompletionType type, Value value, string target)
Target = target;
}


override public bool Equals(object? obj)
{
if (obj is not Completion completion) { return false; }
Expand All @@ -43,6 +44,7 @@ static public Completion NormalCompletion(Value value)

// NOTE: We use an implicit conversion operator as a syntaxic sugar for NormalCompletion in functions
public static implicit operator Completion(Value value) => NormalCompletion(value);
public static implicit operator Completion(bool value) => NormalCompletion(value);

// 6.2.4.2 ThrowCompletion ( value ), https://tc39.es/ecma262/#sec-throwcompletion
static public Completion ThrowCompletion(Value value)
Expand Down Expand Up @@ -84,25 +86,25 @@ public Boolean LoopContinues()
// 1. If completion.[[Type]] is NORMAL, return true.
if (IsNormalCompletion())
{
return new Boolean(true);
return true;
}

// 2. If completion.[[Type]] is not CONTINUE, return false.
if (!IsContinueCompletion())
{
return new Boolean(false);
return false;
}

// 3. If completion.[[Target]] is EMPTY, return true.
if (Target.Length == 0)
{
return new Boolean(true);
return true;
}

// FIXME: 4. If labelSet contains completion.[[Target]], return true.

// 5. Return false.
return new Boolean(false);
return false;
}

public bool IsNormalCompletion() { return Type == CompletionType.Normal; }
Expand Down
12 changes: 6 additions & 6 deletions JSS.Lib/Execution/GlobalEnvironment.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,11 @@ public Completion HasRestrictedGlobalProperty(string N)
if (existingProp.IsAbruptCompletion()) return existingProp;

// 4. If existingProp is undefined, return false.
if (existingProp.Value.IsUndefined()) return new Boolean(false);
if (existingProp.Value.IsUndefined()) return false;

// FIXME: 5. If existingProp.[[Configurable]] is true, return false.
// 6. Return true.
return new Boolean(true);
return true;
}

// 9.1.1.4.15 CanDeclareGlobalVar ( N ), https://tc39.es/ecma262/#sec-candeclareglobalvar
Expand All @@ -187,10 +187,10 @@ public Completion CanDeclareGlobalVar(string N)

// 4. If hasProperty is true, return true.
var asBoolean = hasProperty.Value.AsBoolean();
if (asBoolean.Value) return new Boolean(true);
if (asBoolean.Value) return true;

// FIXME: 5. Return ? IsExtensible(globalObject).
return new Boolean(true);
return true;
}

// 9.1.1.4.16 CanDeclareGlobalFunction ( N ), https://tc39.es/ecma262/#sec-candeclareglobalfunction
Expand All @@ -205,12 +205,12 @@ public Completion CanDeclareGlobalFunction(string N)
if (existingProp.IsAbruptCompletion()) return existingProp;

// 4. If existingProp is undefined, FIXME: return ? IsExtensible(globalObject).
if (existingProp.Value.IsUndefined()) return new Boolean(true);
if (existingProp.Value.IsUndefined()) return true;

// FIXME: 5. If existingProp.[[Configurable]] is true, return true.
// FIXME: 6. If IsDataDescriptor(existingProp) is true and existingProp has attribute values { [[Writable]]: true, [[Enumerable]]: true }, return true.
// 7. Return false.
return new Boolean(false);
return false;
}

// 9.1.1.4.17 CreateGlobalVarBinding ( N, D ), https://tc39.es/ecma262/#sec-createglobalvarbinding
Expand Down

0 comments on commit f0e437d

Please sign in to comment.