// Copyright Epic Games, Inc. All Rights Reserved. using System; namespace EpicGames.BuildGraph.Expressions { /// /// Abstract base class for expressions returning a 32-bit integer value /// [BgType(typeof(BgIntType))] public abstract class BgInt : BgExpr { /// /// Implicit conversion from an integer value /// public static implicit operator BgInt(int value) { return new BgIntConstantExpr(value); } /// /// Constructor /// /// Flags for this expression protected BgInt(BgExprFlags flags) : base(flags) { } /// public static BgInt operator -(BgInt value) => new BgIntUnaryExpr(BgOpcode.IntNegate, value); /// public static BgInt operator +(BgInt lhs, BgInt rhs) => new BgIntBinaryExpr(BgOpcode.IntAdd, lhs, rhs); /// public static BgInt operator -(BgInt lhs, BgInt rhs) => new BgIntBinaryExpr(BgOpcode.IntAdd, lhs, -rhs); /// public static BgInt operator *(BgInt lhs, BgInt rhs) => new BgIntBinaryExpr(BgOpcode.IntMultiply, lhs, rhs); /// public static BgInt operator /(BgInt lhs, BgInt rhs) => new BgIntBinaryExpr(BgOpcode.IntDivide, lhs, rhs); /// public static BgInt operator %(BgInt lhs, BgInt rhs) => new BgIntBinaryExpr(BgOpcode.IntModulo, lhs, rhs); /// public static BgBool operator <(BgInt lhs, BgInt rhs) => new BgIntTestExpr(BgOpcode.IntLt, lhs, rhs); /// public static BgBool operator >(BgInt lhs, BgInt rhs) => new BgIntTestExpr(BgOpcode.IntGt, lhs, rhs); /// public static BgBool operator ==(BgInt lhs, BgInt rhs) => new BgIntTestExpr(BgOpcode.IntEq, lhs, rhs); /// public static BgBool operator !=(BgInt lhs, BgInt rhs) => !(lhs == rhs); /// public static BgBool operator <=(BgInt lhs, BgInt rhs) => !(lhs > rhs); /// public static BgBool operator >=(BgInt lhs, BgInt rhs) => !(lhs < rhs); /// public override bool Equals(object? obj) => throw new InvalidOperationException(); /// public override int GetHashCode() => throw new InvalidOperationException(); /// public override BgString ToBgString() { throw new NotImplementedException(); } } /// /// Traits for a /// class BgIntType : BgType { /// public override BgInt Constant(object value) => new BgIntConstantExpr((int)value); /// public override BgInt Wrap(BgExpr expr) => new BgIntWrappedExpr(expr); } #region Expression classes class BgIntUnaryExpr : BgInt { public BgOpcode Opcode { get; } public BgInt Value { get; } public BgIntUnaryExpr(BgOpcode opcode, BgInt value) : base(value.Flags & BgExprFlags.Eager) { Opcode = opcode; Value = value; } public override void Write(BgBytecodeWriter writer) { writer.WriteOpcode(Opcode); writer.WriteExpr(Value); } } class BgIntBinaryExpr : BgInt { public BgOpcode Opcode { get; } public BgInt Lhs { get; } public BgInt Rhs { get; } public BgIntBinaryExpr(BgOpcode opcode, BgInt lhs, BgInt 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 BgIntTestExpr : BgBool { public BgOpcode Opcode { get; } public BgInt Lhs { get; } public BgInt Rhs { get; } public BgIntTestExpr(BgOpcode opcode, BgInt lhs, BgInt 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 BgIntChooseExpr : BgInt { public BgBool Condition { get; } public BgInt ValueIfTrue { get; } public BgInt ValueIfFalse { get; } public BgIntChooseExpr(BgBool condition, BgInt valueIfTrue, BgInt valueIfFalse) : base(BgExprFlags.None) { Condition = condition; ValueIfTrue = valueIfTrue; ValueIfFalse = valueIfFalse; } public override void Write(BgBytecodeWriter writer) { writer.WriteOpcode(BgOpcode.Choose); writer.WriteExpr(Condition); writer.WriteExpr(ValueIfTrue); writer.WriteExpr(ValueIfFalse); } } class BgIntConstantExpr : BgInt { public int Value { get; } public BgIntConstantExpr(int value) : base(BgExprFlags.NotInterned | BgExprFlags.Eager) { Value = value; } public override void Write(BgBytecodeWriter writer) { writer.WriteOpcode(BgOpcode.IntLiteral); writer.WriteSignedInteger(Value); } } class BgIntWrappedExpr : BgInt { BgExpr Expr { get; } public BgIntWrappedExpr(BgExpr expr) : base(expr.Flags) { Expr = expr; } public override void Write(BgBytecodeWriter writer) => Expr.Write(writer); } class BgIntToBgStringExpr : BgString { BgInt Expr { get; } public BgIntToBgStringExpr(BgInt expr) : base(expr.Flags & BgExprFlags.Eager) { Expr = expr; } public override void Write(BgBytecodeWriter writer) { writer.WriteOpcode(BgOpcode.IntToString); writer.WriteExpr(Expr); } } #endregion /// /// An integer option expression /// public class BgIntOption : BgInt { /// /// 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 BgInt? DefaultValue { get; } /// /// Minimum allowed value /// public BgInt? MinValue { get; } /// /// Maximum allowed value /// public BgInt? MaxValue { get; } /// /// Constructor /// public BgIntOption(string name, BgString? description = null, BgInt? defaultValue = null, BgInt? minValue = null, BgInt? maxValue = null, BgString? label = null) : base(BgExprFlags.None) { Name = name; Label = label; Description = description; DefaultValue = defaultValue; MinValue = minValue; MaxValue = maxValue; } /// public override void Write(BgBytecodeWriter writer) { writer.WriteOpcode(BgOpcode.IntOption); 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); } if (MinValue is not null) { option = option.Set(x => x.MinValue, MinValue); } if (MaxValue is not null) { option = option.Set(x => x.MaxValue, MaxValue); } return option; } } }