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)); }
public static void TestPointer() { var type = new ABT.PointerType( new ABT.LongType(isConst: true), isConst: true, isVolatile: true ); Assert.AreEqual("const long *const volatile a", type.Decl("a")); Assert.AreEqual("const long *const volatile", type.Decl()); }
public static void TestArrayPointer() { var arrPtr = new ABT.PointerType( new ABT.ArrayType( new ABT.LongType(), 3 ) ); Assert.AreEqual("long (*a)[3]", arrPtr.Decl("a")); Assert.AreEqual("long (*)[3]", arrPtr.Decl()); }
public static void TestFunctionPointer() { var funcPtr = new ABT.PointerType( ABT.FunctionType.Create( ABT.StructOrUnionType.CreateIncompleteStruct("my_struct", false, false), ImmutableList.Create( Tuple.Create(Option <String> .None, new ABT.LongType() as ABT.ExprType) ), false ) ); Assert.AreEqual("struct my_struct (*a)(long)", funcPtr.Decl("a")); Assert.AreEqual("struct my_struct (*)(long)", funcPtr.Decl()); }
public static void TestFunctionPointer() { var funcPtr = new ABT.PointerType( ABT.FunctionType.Create( ABT.StructOrUnionType.CreateIncompleteStruct("my_struct", false, false), ImmutableList.Create( Tuple.Create(Option<String>.None, new ABT.LongType() as ABT.ExprType) ), false ) ); Assert.AreEqual("struct my_struct (*a)(long)", funcPtr.Decl("a")); Assert.AreEqual("struct my_struct (*)(long)", funcPtr.Decl()); }