Parcourir la source

patched min/max fpr unsigned data types and overflow check of positive HUGEINT values
note:
the compiler currently uses internally HUGEINT values for constants and thus can handle literals up to MAX(HUGEINT). It is not designed to handle the value of -MIN(HUGEINT), a literal with the value of MIN(HUGEINT) will thus lead to a compiler error message.
Test cases in Oberon.Compileation.Text (compile-time checks)

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@7589 8c9fc860-2736-0410-a75d-ab315db34111

felixf il y a 7 ans
Parent
commit
7ed8f166fd
4 fichiers modifiés avec 42 ajouts et 9 suppressions
  1. 12 4
      source/FoxGlobal.Mod
  2. 1 1
      source/FoxScanner.Mod
  3. 6 4
      source/FoxSemanticChecker.Mod
  4. 23 0
      source/Oberon.Compilation.Test

+ 12 - 4
source/FoxGlobal.Mod

@@ -1419,14 +1419,22 @@ TYPE
 		RETURN LSH (LSH (this, bits), -bits);
 	END ConvertUnsigned;
 
-	PROCEDURE MaxInteger*(system: System; type: SyntaxTree.BasicType): HUGEINT;
+	PROCEDURE MaxInteger*(system: System; type: SyntaxTree.BasicType; signed: BOOLEAN): HUGEINT;
 	BEGIN
-		RETURN ASH (HUGEINT(1), system.SizeOf (type) - 1) - 1;
+		IF signed THEN
+			RETURN ASH (HUGEINT(1), system.SizeOf (type) - 1) - 1;
+		ELSE
+			RETURN ASH (HUGEINT(1), system.SizeOf (type)) -1;
+		END;
 	END MaxInteger;
 
-	PROCEDURE MinInteger*(system: System; type: SyntaxTree.BasicType): HUGEINT;
+	PROCEDURE MinInteger*(system: System; type: SyntaxTree.BasicType; signed: BOOLEAN): HUGEINT;
 	BEGIN
-		RETURN -ASH (HUGEINT(1), system.SizeOf (type) - 1);
+		IF signed THEN
+			RETURN -ASH (HUGEINT(1), system.SizeOf (type) - 1);
+		ELSE
+			RETURN 0
+		END;
 	END MinInteger;
 
 	(*! make architecture  independent ! *)

+ 1 - 1
source/FoxScanner.Mod

@@ -752,7 +752,7 @@ TYPE
 							symbol.numberType := Hugeint;
 							WHILE i < n DO
 								d := Decimal( dig[i] );  INC( i );
-								IF hugeint >= MAX(HUGEINT) DIV 10 THEN Error( Basic.NumberTooLarge) END;
+								IF hugeint > MAX(HUGEINT) DIV 10 THEN Error( Basic.NumberTooLarge) END;
 								hugeint := hugeint * tenh + d;
 								IF hugeint < 0 THEN Error( Basic.NumberTooLarge ) END
 							END;

+ 6 - 4
source/FoxSemanticChecker.Mod

@@ -5655,10 +5655,11 @@ TYPE
 							(*!! ELSIF type = Global.Char16 THEN result.SetResolved(SyntaxTree.NewIntegerValue(position,0FFFFH));
 							ELSIF type = Global.Char32 THEN result.SetResolved(SyntaxTree.NewIntegerValue(position,0FFFFFFFFH));
 							*)
-							ELSIF type IS SyntaxTree.IntegerType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position,Global.MaxInteger(system,type(SyntaxTree.IntegerType))));
+							ELSIF type IS SyntaxTree.IntegerType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position,Global.MaxInteger(system,type(SyntaxTree.IntegerType),type(SyntaxTree.IntegerType).signed)));
 							ELSIF type IS SyntaxTree.FloatType THEN result.SetResolved(SyntaxTree.NewRealValue(position,Global.MaxFloat(system,type(SyntaxTree.FloatType))));
 							ELSIF type IS SyntaxTree.SetType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position,system.SizeOf(type)-1)); type := system.shortintType;
-							ELSIF type IS SyntaxTree.SizeType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position,Global.MaxInteger(system,type(SyntaxTree.BasicType))));
+							ELSIF type IS SyntaxTree.SizeType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position,Global.MaxInteger(system,type(SyntaxTree.BasicType),TRUE)));
+							ELSIF type IS SyntaxTree.AddressType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position,Global.MaxInteger(system,type(SyntaxTree.BasicType),FALSE)));
 							ELSE Error(parameter0.position, "builtin function not applicable to this type");
 							END;
 						ELSE
@@ -5686,10 +5687,11 @@ TYPE
 						IF parameter0.type = SyntaxTree.typeDeclarationType THEN
 							type := parameter0(SyntaxTree.SymbolDesignator).symbol(SyntaxTree.TypeDeclaration).declaredType.resolved;
 							IF type IS SyntaxTree.CharacterType THEN result.SetResolved(SyntaxTree.NewCharacterValue(position,MIN(CHAR)));
-							ELSIF type IS SyntaxTree.IntegerType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position,Global.MinInteger(system,type(SyntaxTree.IntegerType))));
+							ELSIF type IS SyntaxTree.IntegerType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position,Global.MinInteger(system,type(SyntaxTree.IntegerType),type(SyntaxTree.IntegerType).signed)));
 							ELSIF type IS SyntaxTree.FloatType THEN result.SetResolved(SyntaxTree.NewRealValue(position,Global.MinFloat(system,type(SyntaxTree.FloatType))));
 							ELSIF type IS SyntaxTree.SetType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position,0)); type := system.shortintType;
-							ELSIF type IS SyntaxTree.SizeType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position, Global.MinInteger(system,type(SyntaxTree.BasicType))));
+							ELSIF type IS SyntaxTree.SizeType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position, Global.MinInteger(system,type(SyntaxTree.BasicType),TRUE)));
+							ELSIF type IS SyntaxTree.AddressType THEN result.SetResolved(SyntaxTree.NewIntegerValue(position, Global.MinInteger(system,type(SyntaxTree.BasicType),FALSE)));
 							ELSE Error(parameter0.position,"builtin function not applicable to this type");
 							END;
 						ELSE

+ 23 - 0
source/Oberon.Compilation.Test

@@ -39447,3 +39447,26 @@ negative: invalid arrow designator
 		COPY("WMClock.Open~", s)^;
 	END Test.
 
+positive: tests of MIN and MAX
+	MODULE Test;
+
+	PROCEDURE TestMinMax*();
+	BEGIN
+	    ASSERT(-128 = MIN(SHORTINT)); ASSERT(127 = MAX(SHORTINT));
+	    ASSERT(-32768 = MIN(INTEGER)); ASSERT(32767 = MAX(INTEGER));
+	    ASSERT(-2147483648 = MIN(LONGINT)); ASSERT(2147483647 = MAX(LONGINT));
+	    ASSERT(-9223372036854775807-1 = MIN(HUGEINT)); ASSERT(9223372036854775807 = MAX(HUGEINT));
+
+	    ASSERT(-128 = MIN(SIGNED8)); ASSERT(127 = MAX(SIGNED8));
+	    ASSERT(-32768 = MIN(SIGNED16)); ASSERT(32767 = MAX(SIGNED16));
+	    ASSERT(-2147483648 = MIN(SIGNED32)); ASSERT(2147483647 = MAX(SIGNED32));
+	    ASSERT(-9223372036854775807 -1  = MIN(SIGNED64)); ASSERT(9223372036854775807 = MAX(SIGNED64));
+
+	    ASSERT(0 = MIN(UNSIGNED8)); ASSERT(255 = MAX(UNSIGNED8));
+	    ASSERT(0 = MIN(UNSIGNED16)); ASSERT(65535 = MAX(UNSIGNED16));
+	    ASSERT(0 = MIN(UNSIGNED32)); ASSERT(4294967295 = MAX(UNSIGNED32));
+	    ASSERT(0 = MIN(UNSIGNED64)); ASSERT(LSH(1,64)-1 = MAX(UNSIGNED64));
+	END TestMinMax;
+
+	BEGIN
+	END Test.