public override ABT.Expr GetExpr(ABT.Env env) {
// 1. semant the operands
var left = SemantExpr(this.Left, ref env);
var right = SemantExpr(this.Right, ref env);
if (left.Type is ABT.ArrayType) {
left = ABT.TypeCast.MakeCast(left, new ABT.PointerType(((ABT.ArrayType)left.Type).ElemType, left.Type.IsConst, left.Type.IsVolatile));
}
if (right.Type is ABT.ArrayType) {
right = ABT.TypeCast.MakeCast(right, new ABT.PointerType(((ABT.ArrayType)right.Type).ElemType, right.Type.IsConst, right.Type.IsVolatile));
}
// 2. ptr + int
if (left.Type.Kind == ABT.ExprTypeKind.POINTER) {
if (!right.Type.IsIntegral) {
throw new InvalidOperationException("Expected integral to be added to a pointer.");
}
right = ABT.TypeCast.MakeCast(right, new ABT.LongType(right.Type.IsConst, right.Type.IsVolatile));
return GetPointerAddition(left, right);
}
// 3. int + ptr
if (right.Type.Kind == ABT.ExprTypeKind.POINTER) {
if (!left.Type.IsIntegral) {
throw new InvalidOperationException("Expected integral to be added to a pointer.");
}
left = ABT.TypeCast.MakeCast(left, new ABT.LongType(left.Type.IsConst, left.Type.IsVolatile));
return GetPointerAddition(right, left, false);
}
// 4. usual arithmetic conversion
return base.GetExpr(env);
}
}