using System;
using System.Diagnostics;
using CodeGeneration;
namespace ABT {
// IncDecExpr
// |
// +-- PostIncrement, PostDecrement, PreIncrement, PreDecrement
public abstract partial class IncDecExpr : Expr {
protected IncDecExpr(Expr expr) {
if (!(expr.Type is ScalarType)) {
throw new InvalidOperationException("Only supports scalars.").Attach(expr);
}
this.Expr = expr;
}
public Expr Expr { get; }
public override Env Env => this.Expr.Env;
public override Boolean IsLValue => false;
public override ExprType Type => this.Expr.Type;
}
///
/// Expr++: must be integral, float or pointer.
///
/// If Expr is an array, it is converted to a pointer in semantic analysis.
///
public sealed partial class PostIncrement : IncDecExpr {
public PostIncrement(Expr expr)
: base(expr) { }
}
///
/// Expr--: must be a scalar
///
public sealed partial class PostDecrement : IncDecExpr {
public PostDecrement(Expr expr)
: base(expr) { }
}
///
/// ++Expr: must be a scalar
///
public sealed partial class PreIncrement : IncDecExpr {
public PreIncrement(Expr expr)
: base(expr) { }
}
///
/// --Expr: must be a scalar
///
public sealed partial class PreDecrement : IncDecExpr {
public PreDecrement(Expr expr)
: base(expr) { }
}
public abstract partial class UnaryArithOp : Expr {
protected UnaryArithOp(Expr expr) {
this.Expr = expr;
}
public Expr Expr { get; }
public override Env Env => this.Expr.Env;
public override Boolean IsLValue => false;
public override abstract ExprType Type { get; }
}
///
/// -Expr: only takes arithmetic Type.
///
/// After semantic analysis, only the following 4 types are possible:
/// 1) long
/// 2) ulong
/// 3) float
/// 4) double
///
public sealed partial class Negative : UnaryArithOp {
public Negative(Expr expr)
: base(expr) { }
public override ExprType Type => this.Expr.Type;
}
///
/// ~Expr: only takes integral Type.
///
/// After semantic analysis, only the following 2 types are possible:
/// 1) long
/// 2) ulong
///
public sealed partial class BitwiseNot : UnaryArithOp {
public BitwiseNot(Expr expr)
: base(expr) {
if (!(expr.Type is LongType || expr.Type is ULongType)) {
throw new InvalidOperationException("Invalid operand type.").Attach(expr);
}
}
public override ExprType Type => this.Expr.Type;
}
///
/// !Expr: only takes scalar Type.
///
/// After semantic analysis, only the following 4 types are possible:
/// 1) long
/// 2) ulong
/// 3) float
/// 4) double
///
/// Pointers are converted to ulongs.
///
public sealed partial class LogicalNot : UnaryArithOp {
public LogicalNot(Expr expr)
: base(expr) {
if (!(expr.Type is LongType || expr.Type is ULongType
|| expr.Type is FloatType || expr.Type is DoubleType)) {
throw new InvalidOperationException("Invalid operand type.").Attach(expr);
}
}
private static ExprType _type = new LongType(true);
public override ExprType Type => _type;
}
}