Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix type checking of binary type #335

Merged
merged 10 commits into from
Aug 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@ default boolean fitsInto(IDataType target)
/**
* Determines if both types have the same family, e.g. N, I, P are all numeric.
*/
default boolean hasSameFamily(IDataType other)
default boolean hasSameFamily(IDataType target)
{
var targetFormat = other.format();
var targetFormat = target.format();
return format() == targetFormat || switch (format())
{
case PACKED, FLOAT, INTEGER, NUMERIC -> targetFormat == PACKED
case PACKED, FLOAT, INTEGER, NUMERIC, TIME -> targetFormat == PACKED
|| targetFormat == FLOAT
|| targetFormat == INTEGER
|| targetFormat == NUMERIC
|| targetFormat == BINARY;
case ALPHANUMERIC, UNICODE, BINARY -> targetFormat == ALPHANUMERIC
|| targetFormat == TIME;
case ALPHANUMERIC, UNICODE -> targetFormat == ALPHANUMERIC
|| targetFormat == UNICODE
|| targetFormat == BINARY;
default -> false;
Expand All @@ -53,20 +53,26 @@ default boolean hasSameFamily(IDataType other)
/**
* Takes implicit conversion into account, e.g. N -> A
*/
default boolean hasCompatibleFormat(IDataType other)
default boolean hasCompatibleFormat(IDataType target)
{
var targetFormat = other.format();
return hasSameFamily(other) || switch (format())
var targetFormat = target.format();
return hasSameFamily(target) || switch (format())
{
case PACKED, FLOAT, INTEGER, NUMERIC -> targetFormat == ALPHANUMERIC
|| targetFormat == UNICODE
|| targetFormat == BINARY
|| targetFormat == TIME;
case TIME, DATE -> targetFormat == ALPHANUMERIC
|| targetFormat == NUMERIC
|| isShortBinary(target);
case TIME, DATE -> targetFormat == NUMERIC
|| targetFormat == PACKED
|| targetFormat == INTEGER; // this one can fail, but not for early times
case LOGIC -> targetFormat == ALPHANUMERIC;
|| targetFormat == ALPHANUMERIC
|| targetFormat == UNICODE
|| isShortBinary(target)
|| targetFormat == INTEGER // this one can fail, but not for early times
|| targetFormat == DATE
|| targetFormat == TIME
|| targetFormat == FLOAT;
case LOGIC -> targetFormat == ALPHANUMERIC
|| targetFormat == UNICODE;
case BINARY -> binaryCompatibility(target);
default -> false; // we don't know whats implicitly compatible yet
};
}
Expand Down Expand Up @@ -139,4 +145,34 @@ private int calculateDigitsAfterDecimalPoint()
{
return Integer.parseInt((Double.toString(length()).split("\\.")[1]));
}

private boolean isShortBinary()
{
return format() == BINARY && length() < 5;
}

private boolean isShortBinary(IDataType target)
{
return target.format() == BINARY && target.length() < 5;
}

private boolean isLongBinary()
{
return format() == BINARY && length() > 4;
}

private boolean binaryCompatibility(IDataType target)
{
var targetFormat = target.format();
return (isLongBinary() && switch (targetFormat)
{
case ALPHANUMERIC, UNICODE -> true;
default -> false;
}) ||
(isShortBinary() && switch (targetFormat)
{
case NUMERIC, PACKED, ALPHANUMERIC, UNICODE, INTEGER, TIME, FLOAT -> true;
default -> false;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ private void checkDecideOnBranches(IDecideOnNode decideOn)
for (var value : branch.values())
{
var inferredType = inferDataType(value);
if (inferredType.format() != DataFormat.NONE && !inferredType.hasSameFamily(typedTarget.type()))
if (inferredType.format() != DataFormat.NONE && !inferredType.hasCompatibleFormat(typedTarget.type()))
{
report(
ParserErrors.typeMismatch(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,11 @@ void seeImplicitlyCompatibleDataTypesAsIncompatibleWithBiggerLength(String numer
@ParameterizedTest
@CsvSource(
{
"N,N", "N,I", "N,F", "N,P", "N,B",
"A,U", "A,B", "A,A"
"N,N", "N,I", "N,F", "N,P", "N,T",
"P,N", "P,I", "P,F", "P,P", "P,T",
"T,N", "T,I", "T,F", "T,P", "T,T",
"A,A", "A,U", "A,B", "B,B",
"U,A", "U,B", "U,U"
}
)
void recognizeDataFormatsAsTheSameFamily(String firstFormat, String secondFormat)
Expand All @@ -130,11 +133,11 @@ void recognizeDataFormatsAsTheSameFamily(String firstFormat, String secondFormat
@ParameterizedTest
@CsvSource(
{
"N,A", "N,U", "N,L", "N,C", "N,D", "N,T",
"N,A", "N,U", "N,L", "N,C", "N,D",
"A,L", "A,C", "A,D", "A,F", "A,I", "A,P", "A,T",
"I,A", "I,U", "I,L", "I,C", "I,D", "I,T",
"P,A", "P,U", "P,L", "P,C", "P,D", "P,T",
"F,A", "F,U", "F,L", "F,C", "F,D", "F,T",
"I,A", "I,U", "I,L", "I,C", "I,D",
"P,A", "P,U", "P,L", "P,C", "P,D",
"F,A", "F,U", "F,L", "F,C", "F,D",
"L,B", "L,D", "L,T", "L,U", "L,A", "L,P"
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void inferTheCorrectTypeBasedOnTargetTypeForIntegers(String source, String targe
"200,B2",
"12345,B2",
"2147483647,B4",
"2147483648,B10",
"2147483648,P10",
}
)
void inferTheCorrectTypeBasedOnTargetTypeForBinary(String source, String targetType)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,65 @@
DEFINE DATA LOCAL
1 #B-01 (B01)
1 #B-10 (B10)
1 #A-10 (A10)
1 #N-10 (N10)
1 #CV (C)
END-DEFINE

DECIDE ON FIRST VALUE OF #A-10

VALUE 5 /* !{D:ERROR:NPP037}
IGNORE

VALUE TRUE /* !{D:ERROR:NPP037}
IGNORE

VALUE FALSE /* !{D:ERROR:NPP037}
IGNORE

VALUE 5
IGNORE
VALUE TRUE
IGNORE
VALUE FALSE
IGNORE
VALUE #B-10
IGNORE
VALUE #CV /* !{D:ERROR:NPP037}
IGNORE
NONE
IGNORE
IGNORE
END-DECIDE

DECIDE ON FIRST VALUE OF #N-10

VALUE 5
IGNORE

IGNORE
VALUE 500
IGNORE

IGNORE
VALUE 'Hi' /* !{D:ERROR:NPP037}
IGNORE

IGNORE
VALUE TRUE /* !{D:ERROR:NPP037}
IGNORE

IGNORE
VALUE FALSE /* !{D:ERROR:NPP037}
IGNORE
IGNORE
NONE
IGNORE
END-DECIDE

DECIDE ON FIRST VALUE OF #B-01
VALUE 5
IGNORE
VALUE 'Hi'
IGNORE
VALUE H'00'
IGNORE
VALUE #B-10
IGNORE
NONE
IGNORE
IGNORE
END-DECIDE

DECIDE ON FIRST VALUE OF #B-10
VALUE 5
IGNORE
VALUE 5 /* !{D:ERROR:NPP037}
IGNORE
VALUE 'Hi'
IGNORE
IGNORE
VALUE H'00'
IGNORE
VALUE #B-01
IGNORE
NONE
IGNORE
IGNORE
END-DECIDE

END
Loading