// 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; } } }