// Copyright Epic Games, Inc. All Rights Reserved.
using System;
namespace EpicGames.BuildGraph.Expressions
{
///
/// Abstract base class for expressions returning a boolean value
///
[BgType(typeof(BgBoolType))]
public abstract class BgBool : BgExpr
{
///
/// Constant value for false
///
public static BgBool False { get; } = false;
///
/// Constant value for true
///
public static BgBool True { get; } = true;
///
/// Constructor
///
/// Flags for this expression
protected BgBool(BgExprFlags flags)
: base(flags)
{
}
///
/// Implict conversion operator from a boolean literal
///
public static implicit operator BgBool(bool value)
{
return new BgBoolConstantExpr(value);
}
///
public static BgBool operator !(BgBool inner) => new BgBoolNotExpr(inner);
///
public static BgBool operator &(BgBool lhs, BgBool rhs) => new BgBoolBinaryExpr(BgOpcode.BoolAnd, lhs, rhs);
///
public static BgBool operator |(BgBool lhs, BgBool rhs) => new BgBoolBinaryExpr(BgOpcode.BoolOr, lhs, rhs);
///
public static BgBool operator ^(BgBool lhs, BgBool rhs) => new BgBoolBinaryExpr(BgOpcode.BoolXor, lhs, rhs);
///
public static BgBool operator ==(BgBool lhs, BgBool rhs) => new BgBoolBinaryExpr(BgOpcode.BoolEq, lhs, rhs);
///
public static BgBool operator !=(BgBool lhs, BgBool rhs) => !(lhs == rhs);
///
public sealed override bool Equals(object? obj) => throw new InvalidOperationException();
///
public sealed override int GetHashCode() => throw new InvalidOperationException();
///
public override BgString ToBgString() => new BgBoolToBgStringExpr(this);
}
///
/// Type traits for a
///
class BgBoolType : BgType
{
///
public override BgBool Constant(object value) => new BgBoolConstantExpr((bool)value);
///
public override BgBool Wrap(BgExpr expr) => new BgBoolWrappedExpr(expr);
}
#region Expression classes
class BgBoolNotExpr : BgBool
{
public BgBool Inner { get; }
public BgBoolNotExpr(BgBool inner)
: base(inner.Flags & BgExprFlags.Eager)
{
Inner = inner;
}
public override void Write(BgBytecodeWriter writer)
{
writer.WriteOpcode(BgOpcode.BoolNot);
writer.WriteExpr(Inner);
}
}
class BgBoolBinaryExpr : BgBool
{
public BgOpcode Opcode { get; }
public BgBool Lhs { get; }
public BgBool Rhs { get; }
public BgBoolBinaryExpr(BgOpcode opcode, BgBool lhs, BgBool rhs)
: base(lhs.Flags & rhs.Flags & BgExprFlags.Eager)
{
Opcode = opcode;
Lhs = lhs;
Rhs = rhs;
}
public override void Write(BgBytecodeWriter writer)
{
writer.WriteOpcode(Opcode);
writer.WriteExpr(Lhs);
writer.WriteExpr(Rhs);
}
}
class BgBoolConstantExpr : BgBool
{
public bool Value { get; }
public BgBoolConstantExpr(bool value)
: base(BgExprFlags.NotInterned | BgExprFlags.Eager)
{
Value = value;
}
public override void Write(BgBytecodeWriter writer) => writer.WriteOpcode(Value ? BgOpcode.BoolTrue : BgOpcode.BoolFalse);
}
class BgBoolWrappedExpr : BgBool
{
public BgExpr Expr { get; }
public BgBoolWrappedExpr(BgExpr expr)
: base(expr.Flags)
{
Expr = expr;
}
public override void Write(BgBytecodeWriter writer) => Expr.Write(writer);
}
class BgBoolToBgStringExpr : BgString
{
public BgExpr Expr { get; }
public BgBoolToBgStringExpr(BgExpr expr)
: base(expr.Flags & BgExprFlags.Eager)
{
Expr = expr;
}
public override void Write(BgBytecodeWriter writer)
{
writer.WriteOpcode(BgOpcode.BoolToString);
writer.WriteExpr(Expr);
}
}
#endregion
///
/// A boolean option expression
///
public class BgBoolOption : BgBool
{
///
/// Name of the option
///
public BgString Name { get; }
///
/// Label to display next to the option
///
public BgString? Label { get; }
///
/// Help text to display for the user
///
public BgString? Description { get; }
///
/// Default value for the option
///
public BgBool? DefaultValue { get; }
///
/// Constructor
///
public BgBoolOption(BgString name, BgString? description = null, BgBool? defaultValue = null)
: this(name, null, description, defaultValue)
{
}
///
/// Constructor
///
public BgBoolOption(BgString name, BgString? label, BgString? description, BgBool? defaultValue)
: base(BgExprFlags.None)
{
Name = name;
Label = label;
Description = description;
DefaultValue = defaultValue;
}
///
public override void Write(BgBytecodeWriter writer)
{
writer.WriteOpcode(BgOpcode.BoolOption);
writer.WriteExpr(CreateOptionsObject());
}
BgObject CreateOptionsObject()
{
BgObject option = BgObject.Empty;
option = option.Set(x => x.Name, Name);
if (Label is not null)
{
option = option.Set(x => x.Label, Label);
}
if (Description is not null)
{
option = option.Set(x => x.Description, Description);
}
if (DefaultValue is not null)
{
option = option.Set(x => x.DefaultValue, DefaultValue);
}
return option;
}
}
}