AST.Sub.GetExpr C# (CSharp) Метод

GetExpr() публичный Метод

public GetExpr ( ABT env ) : ABT.Expr
env ABT
Результат ABT.Expr
        public override ABT.Expr GetExpr(ABT.Env env) {

            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((left.Type as ABT.ArrayType).ElemType, left.Type.IsConst, left.Type.IsVolatile));
            }

            if (right.Type is ABT.ArrayType) {
                right = ABT.TypeCast.MakeCast(right, new ABT.PointerType((right.Type as ABT.ArrayType).ElemType, right.Type.IsConst, right.Type.IsVolatile));
            }

            var isConst = left.Type.IsConst || right.Type.IsConst;
            var isVolatile = left.Type.IsVolatile || right.Type.IsVolatile;

            if (left.Type.Kind == ABT.ExprTypeKind.POINTER) {

                // 1. ptr - ptr
                if (right.Type.Kind == ABT.ExprTypeKind.POINTER) {
                    ABT.PointerType leftType = (ABT.PointerType)(left.Type);
                    ABT.PointerType rightType = (ABT.PointerType)(right.Type);
                    if (!leftType.RefType.EqualType(rightType.RefType)) {
                        throw new InvalidOperationException("The 2 pointers don't match.");
                    }

                    Int32 scale = leftType.RefType.SizeOf;

                    if (left.IsConstExpr && right.IsConstExpr) {
                        return new ABT.ConstLong((Int32)(((ABT.ConstPtr)left).Value - ((ABT.ConstPtr)right).Value) / scale, env);
                    }

                    return new ABT.Divide(
                        new ABT.Sub(
                            ABT.TypeCast.MakeCast(left, new ABT.LongType(isConst, isVolatile)),
                            ABT.TypeCast.MakeCast(right, new ABT.LongType(isConst, isVolatile))
                        ),
                        new ABT.ConstLong(scale, env)
                    );
                }

                // 2. ptr - integral
                if (!right.Type.IsIntegral) {
                    throw new InvalidOperationException("Expected an integral.");
                }
                right = ABT.TypeCast.MakeCast(right, new ABT.LongType(right.Type.IsConst, right.Type.IsVolatile));
                return GetPointerSubtraction(left, right);

            }

            // 3. arith - arith
            return base.GetExpr(env);
        }
    }