mirror of
https://github.com/irmen/prog8.git
synced 2024-12-11 04:50:05 +00:00
556 lines
15 KiB
Python
556 lines
15 KiB
Python
# generates various Prog8 files with a large amount of number equality tests,
|
|
# using various forms of the if statement (because these forms have their own code gen paths)
|
|
|
|
import sys
|
|
|
|
fail_index = 0
|
|
|
|
|
|
def header(dt):
|
|
print(f"""
|
|
%import textio
|
|
%import floats
|
|
%import test_stack
|
|
%zeropage dontuse
|
|
%option no_sysinit
|
|
|
|
main {{
|
|
ubyte success = 0
|
|
str datatype = "{dt}"
|
|
uword @shared comparison
|
|
|
|
sub start() {{
|
|
txt.print("\\n(in)equality tests for datatype: ")
|
|
txt.print(datatype)
|
|
txt.nl()
|
|
test_stack.test()
|
|
txt.print("==0: ")
|
|
test_is_zero()
|
|
txt.print("\\n!=0: ")
|
|
test_not_zero()
|
|
txt.print("\\n==number: ")
|
|
test_is_number()
|
|
txt.print("\\n!=number: ")
|
|
test_not_number()
|
|
txt.print("\\n==var: ")
|
|
test_is_var()
|
|
txt.print("\\n!=var: ")
|
|
test_not_var()
|
|
txt.print("\\n==array[]: ")
|
|
test_is_array()
|
|
txt.print("\\n!=array[]: ")
|
|
test_not_array()
|
|
txt.print("\\n==expr: ")
|
|
test_is_expr()
|
|
txt.print("\\n!=expr: ")
|
|
test_not_expr()
|
|
test_stack.test()
|
|
}}
|
|
|
|
sub verify_success(ubyte expected) {{
|
|
if success==expected {{
|
|
txt.print("ok")
|
|
}} else {{
|
|
txt.print(" **failed** ")
|
|
txt.print_ub(success)
|
|
txt.print(" success, expected ")
|
|
txt.print_ub(expected)
|
|
}}
|
|
}}
|
|
|
|
sub fail_byte(uword idx, byte v1) {{
|
|
txt.print(" **fail#")
|
|
txt.print_uw(idx)
|
|
txt.chrout(':')
|
|
txt.print_b(v1)
|
|
txt.print(" **")
|
|
}}
|
|
|
|
sub fail_ubyte(uword idx, ubyte v1) {{
|
|
txt.print(" **fail#")
|
|
txt.print_uw(idx)
|
|
txt.chrout(':')
|
|
txt.print_ub(v1)
|
|
txt.print(" **")
|
|
}}
|
|
|
|
sub fail_word(uword idx, word v1) {{
|
|
txt.print(" **fail#")
|
|
txt.print_uw(idx)
|
|
txt.chrout(':')
|
|
txt.print_w(v1)
|
|
txt.print(" **")
|
|
}}
|
|
|
|
sub fail_uword(uword idx, uword v1) {{
|
|
txt.print(" **fail#")
|
|
txt.print_uw(idx)
|
|
txt.chrout(':')
|
|
txt.print_uw(v1)
|
|
txt.print(" **")
|
|
}}
|
|
|
|
sub fail_float(uword idx, float v1) {{
|
|
txt.print(" **fail#")
|
|
txt.print_uw(idx)
|
|
txt.chrout(':')
|
|
floats.print(v1)
|
|
txt.print(" **")
|
|
}}
|
|
|
|
""")
|
|
|
|
|
|
zero_values = {
|
|
"byte": 0,
|
|
"ubyte": 0,
|
|
"word": 0,
|
|
"uword": 0,
|
|
"float": 0.0
|
|
}
|
|
|
|
nonzero_values = {
|
|
"byte": -100,
|
|
"ubyte": 100,
|
|
"word": -9999,
|
|
"uword": 9999,
|
|
"float": 1234.56
|
|
}
|
|
|
|
|
|
def make_test_is_zero(datatype):
|
|
print(f"""
|
|
sub test_is_zero() {{
|
|
{datatype} @shared x
|
|
success = 0
|
|
|
|
x={zero_values[datatype]}
|
|
; direct jump
|
|
if x==0
|
|
goto lbl1
|
|
goto skip1
|
|
lbl1: success++
|
|
skip1:
|
|
; indirect jump
|
|
cx16.r3 = &lbl2
|
|
if x==0
|
|
goto cx16.r3
|
|
goto skip2
|
|
lbl2: success++
|
|
skip2:
|
|
; no else
|
|
if x==0
|
|
success++
|
|
|
|
; with else
|
|
if x==0
|
|
success++
|
|
else
|
|
cx16.r0L++
|
|
|
|
x = {nonzero_values[datatype]}
|
|
; direct jump
|
|
if x==0
|
|
goto skip3
|
|
success++
|
|
skip3:
|
|
; indirect jump
|
|
cx16.r3 = &skip4
|
|
if x==0
|
|
goto cx16.r3
|
|
success++
|
|
skip4:
|
|
; no else
|
|
success++
|
|
if x==0
|
|
success--
|
|
|
|
; with else
|
|
if x==0
|
|
cx16.r0L++
|
|
else
|
|
success++
|
|
|
|
verify_success(8)
|
|
}}
|
|
""")
|
|
|
|
|
|
def make_test_not_zero(datatype):
|
|
print(f"""
|
|
sub test_not_zero() {{
|
|
{datatype} @shared x
|
|
success = 0
|
|
|
|
x={nonzero_values[datatype]}
|
|
; direct jump
|
|
if x!=0
|
|
goto lbl1
|
|
goto skip1
|
|
lbl1: success++
|
|
skip1:
|
|
; indirect jump
|
|
cx16.r3 = &lbl2
|
|
if x!=0
|
|
goto cx16.r3
|
|
goto skip2
|
|
lbl2: success++
|
|
skip2:
|
|
; no else
|
|
if x!=0
|
|
success++
|
|
|
|
; with else
|
|
if x!=0
|
|
success++
|
|
else
|
|
cx16.r0L++
|
|
|
|
x = {zero_values[datatype]}
|
|
; direct jump
|
|
if x!=0
|
|
goto skip3
|
|
success++
|
|
skip3:
|
|
; indirect jump
|
|
cx16.r3 = &skip4
|
|
if x!=0
|
|
goto cx16.r3
|
|
success++
|
|
skip4:
|
|
; no else
|
|
success++
|
|
if x!=0
|
|
success--
|
|
|
|
; with else
|
|
if x!=0
|
|
cx16.r0L++
|
|
else
|
|
success++
|
|
|
|
verify_success(8)
|
|
}}
|
|
""")
|
|
|
|
|
|
def tc(value):
|
|
if value < 0x8000:
|
|
return value
|
|
else:
|
|
return -(65536 - value)
|
|
|
|
|
|
testnumbers = {
|
|
"byte": [-100, 0, 100],
|
|
"ubyte": [0, 1, 255],
|
|
"word": [tc(0xaabb), 0, 0x00aa, 0x7700, 0x7fff],
|
|
"uword": [0, 1, 0x7700, 0xffff],
|
|
"float": [0.0, 1234.56]
|
|
}
|
|
|
|
|
|
def make_test_is_number(datatype, equals):
|
|
numbers = testnumbers[datatype]
|
|
print(" sub test_is_number() {" if equals else " sub test_not_number() {")
|
|
print(f""" {datatype} @shared x
|
|
success = 0""")
|
|
expected = 0
|
|
test_index = 0
|
|
global fail_index
|
|
for x in numbers:
|
|
print(f" x={x}")
|
|
for value in numbers:
|
|
if value == 0:
|
|
continue # 0 already tested separately
|
|
result = (x == value) if equals else (x != value)
|
|
comp = "==" if equals else "!="
|
|
test_index += 1
|
|
if result:
|
|
expected += 4 # there are 4 test types for every successful combo
|
|
true_action1 = "success++"
|
|
true_action2 = "success++"
|
|
true_action3 = "success++"
|
|
true_action4 = "success++"
|
|
else:
|
|
fail_index += 1
|
|
true_action1 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action2 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action3 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action4 = f"fail_{datatype}({fail_index},{x})"
|
|
print(f""" ; direct jump
|
|
if x{comp}{value}
|
|
goto lbl{test_index}a
|
|
goto skip{test_index}a
|
|
lbl{test_index}a: {true_action1}
|
|
skip{test_index}a:
|
|
; indirect jump
|
|
cx16.r3 = &lbl{test_index}b
|
|
if x{comp}{value}
|
|
goto cx16.r3
|
|
goto skip{test_index}b
|
|
lbl{test_index}b: {true_action2}
|
|
skip{test_index}b:
|
|
; no else
|
|
if x{comp}{value}
|
|
{true_action3}
|
|
|
|
; with else
|
|
if x{comp}{value}
|
|
{true_action4}
|
|
else
|
|
cx16.r0L++
|
|
""")
|
|
print(f" verify_success({expected})\n}}")
|
|
|
|
|
|
def make_test_is_var(datatype, equals):
|
|
numbers = testnumbers[datatype]
|
|
print(" sub test_is_var() {" if equals else " sub test_not_var() {")
|
|
print(f""" {datatype} @shared x, value
|
|
success = 0""")
|
|
expected = 0
|
|
test_index = 0
|
|
global fail_index
|
|
for x in numbers:
|
|
print(f" x={x}")
|
|
for value in numbers:
|
|
if value == 0:
|
|
continue # 0 already tested separately
|
|
print(f" value={value}")
|
|
result = (x == value) if equals else (x != value)
|
|
comp = "==" if equals else "!="
|
|
test_index += 1
|
|
if result:
|
|
expected += 4 # there are 4 test types for every successful combo
|
|
true_action1 = "success++"
|
|
true_action2 = "success++"
|
|
true_action3 = "success++"
|
|
true_action4 = "success++"
|
|
else:
|
|
fail_index += 1
|
|
true_action1 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action2 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action3 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action4 = f"fail_{datatype}({fail_index},{x})"
|
|
print(f""" ; direct jump
|
|
if x{comp}value
|
|
goto lbl{test_index}a
|
|
goto skip{test_index}a
|
|
lbl{test_index}a: {true_action1}
|
|
skip{test_index}a:
|
|
; indirect jump
|
|
cx16.r3 = &lbl{test_index}b
|
|
if x{comp}value
|
|
goto cx16.r3
|
|
goto skip{test_index}b
|
|
lbl{test_index}b: {true_action2}
|
|
skip{test_index}b:
|
|
; no else
|
|
if x{comp}value
|
|
{true_action3}
|
|
|
|
; with else
|
|
if x{comp}value
|
|
{true_action4}
|
|
else
|
|
cx16.r0L++
|
|
""")
|
|
print(f" verify_success({expected})\n}}")
|
|
|
|
|
|
def make_test_is_array(datatype, equals):
|
|
numbers = testnumbers[datatype]
|
|
print(" sub test_is_array() {" if equals else " sub test_not_array() {")
|
|
print(f""" {datatype} @shared x
|
|
{datatype}[] values = [0, 0]
|
|
{datatype}[] sources = [0, 0]
|
|
success = 0""")
|
|
expected = 0
|
|
test_index = 0
|
|
global fail_index
|
|
for x in numbers:
|
|
print(f" x={x}")
|
|
print(f" sources[1]={x}")
|
|
for value in numbers:
|
|
if value == 0:
|
|
continue # 0 already tested separately
|
|
print(f" values[1]={value}")
|
|
result = (x == value) if equals else (x != value)
|
|
comp = "==" if equals else "!="
|
|
test_index += 1
|
|
if result:
|
|
expected += 8 # there are 8 test types for every successful combo
|
|
true_action1 = "success++"
|
|
true_action2 = "success++"
|
|
true_action3 = "success++"
|
|
true_action4 = "success++"
|
|
true_action5 = "success++"
|
|
true_action6 = "success++"
|
|
true_action7 = "success++"
|
|
true_action8 = "success++"
|
|
else:
|
|
fail_index += 1
|
|
true_action1 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action2 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action3 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action4 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action5 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action6 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action7 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action8 = f"fail_{datatype}({fail_index},{x})"
|
|
print(f""" ; direct jump
|
|
if x{comp}values[1]
|
|
goto lbl{test_index}a
|
|
goto skip{test_index}a
|
|
lbl{test_index}a: {true_action1}
|
|
skip{test_index}a:
|
|
; indirect jump
|
|
cx16.r3 = &lbl{test_index}b
|
|
if x{comp}values[1]
|
|
goto cx16.r3
|
|
goto skip{test_index}b
|
|
lbl{test_index}b: {true_action2}
|
|
skip{test_index}b:
|
|
; no else
|
|
if x{comp}values[1]
|
|
{true_action3}
|
|
|
|
; with else
|
|
if x{comp}values[1]
|
|
{true_action4}
|
|
else
|
|
cx16.r0L++
|
|
""")
|
|
print(f""" ; direct jump
|
|
if sources[1]{comp}values[1]
|
|
goto lbl{test_index}c
|
|
goto skip{test_index}c
|
|
lbl{test_index}c: {true_action5}
|
|
skip{test_index}c:
|
|
; indirect jump
|
|
cx16.r3 = &lbl{test_index}d
|
|
if sources[1]{comp}values[1]
|
|
goto cx16.r3
|
|
goto skip{test_index}d
|
|
lbl{test_index}d: {true_action6}
|
|
skip{test_index}d:
|
|
; no else
|
|
if sources[1]{comp}values[1]
|
|
{true_action7}
|
|
|
|
; with else
|
|
if sources[1]{comp}values[1]
|
|
{true_action8}
|
|
else
|
|
cx16.r0L++
|
|
""")
|
|
print(f" verify_success({expected})\n}}")
|
|
|
|
|
|
def make_test_is_expr(datatype, equals):
|
|
numbers = testnumbers[datatype]
|
|
print(" sub test_is_expr() {" if equals else " sub test_not_expr() {")
|
|
print(f""" {datatype} @shared x
|
|
cx16.r4 = 1
|
|
cx16.r5 = 1
|
|
float @shared f4 = 1.0
|
|
float @shared f5 = 1.0
|
|
success = 0""")
|
|
expected = 0
|
|
test_index = 0
|
|
global fail_index
|
|
for x in numbers:
|
|
print(f" x={x}")
|
|
for value in numbers:
|
|
if value == 0:
|
|
continue # 0 already tested separately
|
|
if datatype=="byte":
|
|
expr = f"cx16.r4sL+{value}-cx16.r5sL"
|
|
elif datatype=="ubyte":
|
|
expr = f"cx16.r4L+{value}-cx16.r5L"
|
|
elif datatype=="word":
|
|
expr = f"cx16.r4s+{value}-cx16.r5s"
|
|
elif datatype=="uword":
|
|
expr = f"cx16.r4+{value}-cx16.r5"
|
|
elif datatype=="float":
|
|
expr = f"f4+{value}-f5"
|
|
result = (x == value) if equals else (x != value)
|
|
comp = "==" if equals else "!="
|
|
test_index += 1
|
|
if result:
|
|
expected += 4 # there are 4 test types for every successful combo
|
|
true_action1 = "success++"
|
|
true_action2 = "success++"
|
|
true_action3 = "success++"
|
|
true_action4 = "success++"
|
|
else:
|
|
fail_index += 1
|
|
true_action1 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action2 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action3 = f"fail_{datatype}({fail_index},{x})"
|
|
fail_index += 1
|
|
true_action4 = f"fail_{datatype}({fail_index},{x})"
|
|
print(f""" ; direct jump
|
|
if x{comp}{expr}
|
|
goto lbl{test_index}a
|
|
goto skip{test_index}a
|
|
lbl{test_index}a: {true_action1}
|
|
skip{test_index}a:
|
|
; indirect jump
|
|
cx16.r3 = &lbl{test_index}b
|
|
if x{comp}{expr}
|
|
goto cx16.r3
|
|
goto skip{test_index}b
|
|
lbl{test_index}b: {true_action2}
|
|
skip{test_index}b:
|
|
; no else
|
|
if x{comp}{expr}
|
|
{true_action3}
|
|
|
|
; with else
|
|
if x{comp}{expr}
|
|
{true_action4}
|
|
else
|
|
cx16.r0L++
|
|
""")
|
|
print(f" verify_success({expected})\n}}")
|
|
|
|
|
|
def generate(datatype):
|
|
global fail_index
|
|
fail_index = 0
|
|
header(datatype)
|
|
make_test_is_zero(datatype)
|
|
make_test_not_zero(datatype)
|
|
make_test_is_number(datatype, True)
|
|
make_test_is_number(datatype, False)
|
|
make_test_is_var(datatype, True)
|
|
make_test_is_var(datatype, False)
|
|
make_test_is_expr(datatype, True)
|
|
make_test_is_expr(datatype, False)
|
|
make_test_is_array(datatype, True)
|
|
make_test_is_array(datatype, False)
|
|
print("\n}\n")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
for dt in ["ubyte", "uword", "byte", "word", "float"]:
|
|
sys.stdout = open(f"test_{dt}_equalities.p8", "wt")
|
|
generate(dt)
|