namespace AST { using static SemanticAnalysis; /// /// Assignment: Left = Right /// /// /// Left must be a lvalue, but this check is left to the cgen phase. /// public sealed class Assignment : Expr { private Assignment(Expr left, Expr right) { this.Left = left; this.Right = right; } public Expr Left { get; } public Expr Right { get; } public static Expr Create(Expr left, Expr right) => new Assignment(left, right); protected override ABT.Expr GetExprImpl(ABT.Env env, ILineInfo info) { var left = SemantExpr(this.Left, ref env); var right = SemantExpr(this.Right, ref env); right = ABT.TypeCast.MakeCast(right, left.Type); return new ABT.Assign(left, right); } } /// /// Assignment operator /// public abstract class AssignOp : Expr { protected AssignOp(Expr left, Expr right) { this.Left = left; this.Right = right; } public Expr Left { get; } public Expr Right { get; } public abstract Expr ConstructBinaryOp(); protected override sealed ABT.Expr GetExprImpl(ABT.Env env, ILineInfo info) => Assignment.Create(this.Left, ConstructBinaryOp()).GetExpr(env, info); } /// /// MultAssign: a *= b /// public sealed class MultAssign : AssignOp { private MultAssign(Expr left, Expr right) : base(left, right) { } public static Expr Create(Expr left, Expr right) => new MultAssign(left, right); public override Expr ConstructBinaryOp() => Multiply.Create(this.Left, this.Right); } /// /// DivAssign: a /= b /// public sealed class DivAssign : AssignOp { private DivAssign(Expr left, Expr right) : base(left, right) { } public static Expr Create(Expr left, Expr right) => new DivAssign(left, right); public override Expr ConstructBinaryOp() => Divide.Create(this.Left, this.Right); } /// /// ModAssign: a %= b /// public sealed class ModAssign : AssignOp { private ModAssign(Expr left, Expr right) : base(left, right) { } public static Expr Create(Expr left, Expr right) => new ModAssign(left, right); public override Expr ConstructBinaryOp() => Modulo.Create(this.Left, this.Right); } /// /// AddAssign: a += b /// public sealed class AddAssign : AssignOp { private AddAssign(Expr left, Expr right) : base(left, right) { } public static Expr Create(Expr left, Expr right) => new AddAssign(left, right); public override Expr ConstructBinaryOp() => Add.Create(this.Left, this.Right); } /// /// SubAssign: a -= b /// public sealed class SubAssign : AssignOp { private SubAssign(Expr left, Expr right) : base(left, right) { } public static Expr Create(Expr left, Expr right) => new SubAssign(left, right); public override Expr ConstructBinaryOp() => Sub.Create(this.Left, this.Right); } /// /// LShiftAssign: a <<= b /// public sealed class LShiftAssign : AssignOp { private LShiftAssign(Expr left, Expr right) : base(left, right) { } public static Expr Create(Expr left, Expr right) => new LShiftAssign(left, right); public override Expr ConstructBinaryOp() => LShift.Create(this.Left, this.Right); } /// /// RShiftAssign: a >>= b /// public sealed class RShiftAssign : AssignOp { private RShiftAssign(Expr left, Expr right) : base(left, right) { } public static Expr Create(Expr left, Expr right) => new RShiftAssign(left, right); public override Expr ConstructBinaryOp() => RShift.Create(this.Left, this.Right); } /// /// BitwiseAndAssign: a &= b /// public sealed class BitwiseAndAssign : AssignOp { private BitwiseAndAssign(Expr left, Expr right) : base(left, right) { } public static Expr Create(Expr left, Expr right) => new BitwiseAndAssign(left, right); public override Expr ConstructBinaryOp() => BitwiseAnd.Create(this.Left, this.Right); } /// /// XorAssign: a ^= b /// public sealed class XorAssign : AssignOp { private XorAssign(Expr left, Expr right) : base(left, right) { } public static Expr Create(Expr left, Expr right) => new XorAssign(left, right); public override Expr ConstructBinaryOp() => Xor.Create(this.Left, this.Right); } /// /// BitwiseOrAssign: a |= b /// public sealed class BitwiseOrAssign : AssignOp { private BitwiseOrAssign(Expr left, Expr right) : base(left, right) { } public static Expr Create(Expr left, Expr right) => new BitwiseOrAssign(left, right); public override Expr ConstructBinaryOp() => BitwiseOr.Create(this.Left, this.Right); } }