prog8/compiler/test/comparisons/make_tests.py
2024-03-02 23:19:39 +01:00

509 lines
15 KiB
Python

# generates various Prog8 files with a huge amount of number comparion tests,
# for all supported datatypes and all comparison operators.
import sys
index = 0
def minmaxvalues(dt):
if dt == "ubyte":
return 0, 255
elif dt == "uword":
return 0, 65535
elif dt == "byte":
return -128, 127
elif dt == "word":
return -32768, 32767
elif dt == "float":
return -99999999, 99999999
else:
raise ValueError(dt)
def gen_test(dt, comparison, left, right, expected):
global index
etxt = f"{left} {comparison} {right}"
if eval(etxt) != expected:
raise ValueError("invalid comparison: "+etxt+" for "+dt)
if expected:
stmt_ok = lambda ix: "num_successes++"
stmt_else = lambda ix: f"error({ix})"
else:
stmt_ok = lambda ix: f"error({ix})"
stmt_else = lambda ix: "num_successes++"
def c(number):
if dt not in ("byte", "ubyte"):
return f"({number} as {dt})"
return str(number)
print(
f""" left = {c(left)}
right = {c(right)}
"""
)
# const <op> const
index += 1
print(
f""" ; test #{index}
if {c(left)} {comparison} {c(right)} {{
{stmt_ok(index)}
}} else {{
{stmt_else(index)}
}}
""")
# const <op> var
index += 1
print(
f""" ; test #{index}
if {c(left)} {comparison} right {{
{stmt_ok(index)}
}} else {{
{stmt_else(index)}
}}
""")
# const <op> expr
index += 1
print(
f""" ; test #{index}
if {c(left)} {comparison} right+zero {{
{stmt_ok(index)}
}} else {{
{stmt_else(index)}
}}
""")
# var <op> const
index += 1
print(
f""" ; test #{index}
if left {comparison} {c(right)} {{
{stmt_ok(index)}
}} else {{
{stmt_else(index)}
}}
""")
# var <op> var
index += 1
print(
f""" ; test #{index}
if left {comparison} right {{
{stmt_ok(index)}
}} else {{
{stmt_else(index)}
}}
""")
# var <op> expr
index += 1
print(
f""" ; test #{index}
if left {comparison} right+zero {{
{stmt_ok(index)}
}} else {{
{stmt_else(index)}
}}
""")
# expr <op> const
index += 1
print(
f""" ; test #{index}
if left+zero {comparison} {c(right)} {{
{stmt_ok(index)}
}} else {{
{stmt_else(index)}
}}
""")
# expr <op> var
index += 1
print(
f""" ; test #{index}
if left+zero {comparison} right {{
{stmt_ok(index)}
}} else {{
{stmt_else(index)}
}}
""")
# expr <op> expr
index += 1
print(
f""" ; test #{index}
if left+zero {comparison} right+zero {{
{stmt_ok(index)}
}} else {{
{stmt_else(index)}
}}
""")
def gen_comp_header(dt, operator):
print(" ; tests: ", dt, operator)
print(" comparison = \""+operator+"\"")
print(" txt.print(datatype)")
print(" txt.spc()")
print(" txt.print(comparison)")
print(" txt.nl()")
def gen_comp_equal(dt):
minval, maxval = minmaxvalues(dt)
gen_comp_header(dt, "==")
gen_test(dt, "==", 0, 0, True)
gen_test(dt, "==", 0, 1, False)
gen_test(dt, "==", 100, 100, True)
gen_test(dt, "==", 100, 101, False)
if maxval >= 200:
gen_test(dt, "==", 200, 200, True)
gen_test(dt, "==", 200, 201, False)
if maxval >= 9999:
gen_test(dt, "==", 9999, 9999, True)
gen_test(dt, "==", 9999, 10000, False)
gen_test(dt, "==", 0x5000, 0x5000, True)
gen_test(dt, "==", 0x5000, 0x5001, False)
gen_test(dt, "==", 0x5000, 0x4fff, False)
if maxval >= 30000:
gen_test(dt, "==", 30000, 30000, True)
gen_test(dt, "==", 30000, 30001, False)
if maxval >= 40000:
gen_test(dt, "==", 0xf000, 0xf000, True)
gen_test(dt, "==", 0xf000, 0xf001, False)
gen_test(dt, "==", 0xf000, 0xffff, False)
if minval < 0:
gen_test(dt, "==", 0, -1, False)
gen_test(dt, "==", -100, -100, True)
if minval < -200:
gen_test(dt, "==", -200, -200, True)
gen_test(dt, "==", -200, -201, False)
if minval < -9999:
gen_test(dt, "==", -0x5000, -0x5000, True)
gen_test(dt, "==", -0x5000, -0x5001, False)
gen_test(dt, "==", -0x5000, -0x4fff, False)
gen_test(dt, "==", -9999, -9999, True)
gen_test(dt, "==", -9999, -10000, False)
gen_test(dt, "==", minval, minval, True)
gen_test(dt, "==", minval, minval+1, False)
gen_test(dt, "==", maxval, maxval, True)
gen_test(dt, "==", maxval, maxval-1, False)
def gen_comp_notequal(dt):
minval, maxval = minmaxvalues(dt)
gen_comp_header(dt, "!=")
gen_test(dt, "!=", 0, 0, False)
gen_test(dt, "!=", 0, 1, True)
gen_test(dt, "!=", 100, 100, False)
gen_test(dt, "!=", 100, 101, True)
if maxval >= 200:
gen_test(dt, "!=", 200, 200, False)
gen_test(dt, "!=", 200, 201, True)
if maxval >= 9999:
gen_test(dt, "!=", 9999, 9999, False)
gen_test(dt, "!=", 9999, 10000, True)
gen_test(dt, "!=", 0x5000, 0x5000, False)
gen_test(dt, "!=", 0x5000, 0x5001, True)
gen_test(dt, "!=", 0x5000, 0x4fff, True)
if maxval >= 30000:
gen_test(dt, "!=", 30000, 30000, False)
gen_test(dt, "!=", 30000, 30001, True)
if maxval >= 40000:
gen_test(dt, "!=", 0xf000, 0xf000, False)
gen_test(dt, "!=", 0xf000, 0xf001, True)
gen_test(dt, "!=", 0xf000, 0xffff, True)
if minval < 0:
gen_test(dt, "!=", 0, -1, True)
gen_test(dt, "!=", -100, -100, False)
if minval < -200:
gen_test(dt, "!=", -200, -200, False)
gen_test(dt, "!=", -200, -201, True)
if minval < -9999:
gen_test(dt, "!=", -0x5000, -0x5000, False)
gen_test(dt, "!=", -0x5000, -0x5001, True)
gen_test(dt, "!=", -0x5000, -0x4fff, True)
gen_test(dt, "!=", -9999, -9999, False)
gen_test(dt, "!=", -9999, -10000, True)
gen_test(dt, "!=", minval, minval, False)
gen_test(dt, "!=", minval, minval+1, True)
gen_test(dt, "!=", maxval, maxval, False)
gen_test(dt, "!=", maxval, maxval-1, True)
def gen_comp_less(dt):
minval, maxval = minmaxvalues(dt)
gen_comp_header(dt, "<")
gen_test(dt, "<", 0, 0, False)
gen_test(dt, "<", 0, 1, True)
gen_test(dt, "<", 100, 100, False)
gen_test(dt, "<", 100, 101, True)
gen_test(dt, "<", 100, 99, False)
if maxval >= 200:
gen_test(dt, "<", 200, 200, False)
gen_test(dt, "<", 200, 201, True)
gen_test(dt, "<", 200, 199, False)
if maxval >= 9999:
gen_test(dt, "<", 9999, 9999, False)
gen_test(dt, "<", 9999, 10000, True)
gen_test(dt, "<", 9999, 9998, False)
gen_test(dt, "<", 0x5000, 0x5000, False)
gen_test(dt, "<", 0x5000, 0x5001, True)
gen_test(dt, "<", 0x5000, 0x4fff, False)
if maxval >= 30000:
gen_test(dt, "<", 30000, 30000, False)
gen_test(dt, "<", 30000, 30001, True)
gen_test(dt, "<", 30000, 29999, False)
if maxval >= 40000:
gen_test(dt, "<", 0xf000, 0xf000, False)
gen_test(dt, "<", 0xf000, 0xf001, True)
gen_test(dt, "<", 0xf000, 0xefff, False)
if minval < 0:
gen_test(dt, "<", 0, -1, False)
gen_test(dt, "<", -100, -100, False)
gen_test(dt, "<", -100, -101, False)
gen_test(dt, "<", -100, -99, True)
if minval < -200:
gen_test(dt, "<", -200, -200, False)
gen_test(dt, "<", -200, -201, False)
gen_test(dt, "<", -200, -199, True)
if minval < -9999:
gen_test(dt, "<", -0x5000, -0x5000, False)
gen_test(dt, "<", -0x5000, -0x5001, False)
gen_test(dt, "<", -0x5000, -0x4fff, True)
gen_test(dt, "<", -9999, -9999, False)
gen_test(dt, "<", -9999, -10000, False)
gen_test(dt, "<", -9999, -9998, True)
def gen_comp_greater(dt):
minval, maxval = minmaxvalues(dt)
gen_comp_header(dt, ">")
gen_test(dt, ">", 0, 0, False)
gen_test(dt, ">", 0, 1, False)
gen_test(dt, ">", 100, 100, False)
gen_test(dt, ">", 100, 101, False)
gen_test(dt, ">", 100, 99, True)
if maxval >= 200:
gen_test(dt, ">", 200, 200, False)
gen_test(dt, ">", 200, 201, False)
gen_test(dt, ">", 200, 199, True)
if maxval >= 9999:
gen_test(dt, ">", 9999, 9999, False)
gen_test(dt, ">", 9999, 10000, False)
gen_test(dt, ">", 9999, 9998, True)
gen_test(dt, ">", 0x5000, 0x5000, False)
gen_test(dt, ">", 0x5000, 0x5001, False)
gen_test(dt, ">", 0x5000, 0x4fff, True)
if maxval >= 30000:
gen_test(dt, ">", 30000, 30000, False)
gen_test(dt, ">", 30000, 30001, False)
gen_test(dt, ">", 30000, 29999, True)
if maxval >= 40000:
gen_test(dt, ">", 0xf000, 0xf000, False)
gen_test(dt, ">", 0xf000, 0xf001, False)
gen_test(dt, ">", 0xf000, 0xefff, True)
if minval < 0:
gen_test(dt, ">", 0, -1, True)
gen_test(dt, ">", -100, -100, False)
gen_test(dt, ">", -100, -101, True)
gen_test(dt, ">", -100, -99, False)
if minval < -200:
gen_test(dt, ">", -200, -200, False)
gen_test(dt, ">", -200, -201, True)
gen_test(dt, ">", -200, -199, False)
if minval < -9999:
gen_test(dt, ">", -0x5000, -0x5000, False)
gen_test(dt, ">", -0x5000, -0x5001, True)
gen_test(dt, ">", -0x5000, -0x4fff, False)
gen_test(dt, ">", -9999, -9999, False)
gen_test(dt, ">", -9999, -10000, True)
gen_test(dt, ">", -9999, -9998, False)
def gen_comp_lessequal(dt):
minval, maxval = minmaxvalues(dt)
gen_comp_header(dt, "<=")
gen_test(dt, "<=", 0, 0, True)
gen_test(dt, "<=", 0, 1, True)
gen_test(dt, "<=", 100, 100, True)
gen_test(dt, "<=", 100, 101, True)
gen_test(dt, "<=", 100, 99, False)
if maxval >= 200:
gen_test(dt, "<=", 200, 200, True)
gen_test(dt, "<=", 200, 201, True)
gen_test(dt, "<=", 200, 199, False)
if maxval >= 9999:
gen_test(dt, "<=", 9999, 9999, True)
gen_test(dt, "<=", 9999, 10000, True)
gen_test(dt, "<=", 9999, 9998, False)
gen_test(dt, "<=", 0x5000, 0x5000, True)
gen_test(dt, "<=", 0x5000, 0x5001, True)
gen_test(dt, "<=", 0x5000, 0x4fff, False)
if maxval >= 30000:
gen_test(dt, "<=", 30000, 30000, True)
gen_test(dt, "<=", 30000, 30001, True)
gen_test(dt, "<=", 30000, 29999, False)
if maxval >= 40000:
gen_test(dt, "<=", 0xf000, 0xf000, True)
gen_test(dt, "<=", 0xf000, 0xf001, True)
gen_test(dt, "<=", 0xf000, 0xefff, False)
if minval < 0:
gen_test(dt, "<=", 0, -1, False)
gen_test(dt, "<=", -100, -100, True)
gen_test(dt, "<=", -100, -101, False)
gen_test(dt, "<=", -100, -99, True)
if minval < -200:
gen_test(dt, "<=", -200, -200, True)
gen_test(dt, "<=", -200, -201, False)
gen_test(dt, "<=", -200, -199, True)
if minval < -9999:
gen_test(dt, "<=", -0x5000, -0x5000, True)
gen_test(dt, "<=", -0x5000, -0x5001, False)
gen_test(dt, "<=", -0x5000, -0x4fff, True)
gen_test(dt, "<=", -9999, -9999, True)
gen_test(dt, "<=", -9999, -10000, False)
gen_test(dt, "<=", -9999, -9998, True)
def gen_comp_greaterequal(dt):
minval, maxval = minmaxvalues(dt)
gen_comp_header(dt, ">=")
gen_test(dt, ">=", 0, 0, True)
gen_test(dt, ">=", 0, 1, False)
gen_test(dt, ">=", 100, 100, True)
gen_test(dt, ">=", 100, 101, False)
gen_test(dt, ">=", 100, 99, True)
if maxval >= 200:
gen_test(dt, ">=", 200, 200, True)
gen_test(dt, ">=", 200, 201, False)
gen_test(dt, ">=", 200, 199, True)
if maxval >= 9999:
gen_test(dt, ">=", 9999, 9999, True)
gen_test(dt, ">=", 9999, 10000, False)
gen_test(dt, ">=", 9999, 9998, True)
gen_test(dt, ">=", 0x5000, 0x5000, True)
gen_test(dt, ">=", 0x5000, 0x5001, False)
gen_test(dt, ">=", 0x5000, 0x4fff, True)
if maxval >= 30000:
gen_test(dt, ">=", 30000, 30000, True)
gen_test(dt, ">=", 30000, 30001, False)
gen_test(dt, ">=", 30000, 29999, True)
if maxval >= 40000:
gen_test(dt, ">=", 0xf000, 0xf000, True)
gen_test(dt, ">=", 0xf000, 0xf001, False)
gen_test(dt, ">=", 0xf000, 0xefff, True)
if minval < 0:
gen_test(dt, ">=", 0, -1, True)
gen_test(dt, ">=", -100, -100, True)
gen_test(dt, ">=", -100, -101, True)
gen_test(dt, ">=", -100, -99, False)
if minval < -200:
gen_test(dt, ">=", -200, -200, True)
gen_test(dt, ">=", -200, -201, True)
gen_test(dt, ">=", -200, -199, False)
if minval < -9999:
gen_test(dt, ">=", -0x5000, -0x5000, True)
gen_test(dt, ">=", -0x5000, -0x5001, True)
gen_test(dt, ">=", -0x5000, -0x4fff, False)
gen_test(dt, ">=", -9999, -9999, True)
gen_test(dt, ">=", -9999, -10000, True)
gen_test(dt, ">=", -9999, -9998, False)
def generate_test_routine_equalsnotequals(dt):
print(f"""
sub test_comparisons() {{
{dt} @shared left
{dt} @shared right
{dt} @shared zero = 0
""")
gen_comp_equal(dt)
gen_comp_notequal(dt)
print(" }")
def generate_test_routine_lessgreater(dt):
print(f"""
sub test_comparisons() {{
{dt} @shared left
{dt} @shared right
{dt} @shared zero = 0
""")
gen_comp_less(dt)
gen_comp_greater(dt)
print(" }")
def generate_test_routine_lessequalsgreaterequals(dt):
print(f"""
sub test_comparisons() {{
{dt} @shared left
{dt} @shared right
{dt} @shared zero = 0
""")
gen_comp_lessequal(dt)
gen_comp_greaterequal(dt)
print(" }")
def generate(dt, operators):
global index
index = 0
print(f"""
%import textio
%import floats
%import test_stack
%zeropage basicsafe
main {{
uword num_errors = 0
uword num_successes = 0
str datatype = "{dt}"
uword @shared comparison
sub start() {{
test_comparisons()
print_results()
test_stack.test()
}}
sub error(uword index) {{
txt.print(" ! error in test ")
txt.print_uw(index)
txt.chrout(' ')
txt.print(datatype)
txt.chrout(' ')
txt.print(comparison)
txt.nl()
num_errors++
}}
""")
if operators=="eq":
generate_test_routine_equalsnotequals(dt)
elif operators=="lt":
generate_test_routine_lessgreater(dt)
elif operators=="lteq":
generate_test_routine_lessequalsgreaterequals(dt)
else:
raise ValueError(operators)
print(f"""
sub print_results() {{
txt.nl()
txt.print("total {index}: ")
txt.print_uw(num_successes)
txt.print(" good, ")
txt.print_uw(num_errors)
txt.print(" errors!\\n")
}}
}}
""")
if __name__ == '__main__':
for dt in ["ubyte", "uword", "byte", "word", "float"]:
sys.stdout = open(f"test_{dt}_eq.p8", "wt")
generate(dt, "eq")
sys.stdout = open(f"test_{dt}_lt.p8", "wt")
generate(dt, "lt")
sys.stdout = open(f"test_{dt}_lteq.p8", "wt")
generate(dt, "lteq")