Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save tinkerer-red/c7416fc7c2affd875aa313d9d3e71ffc to your computer and use it in GitHub Desktop.
Save tinkerer-red/c7416fc7c2affd875aa313d9d3e71ffc to your computer and use it in GitHub Desktop.
BasicCompileEvalConsistencyTestSuite
import os
from itertools import product
script_dir = os.path.dirname(os.path.abspath(__file__))
# Operand types with example values
operands = {
"0b": "0b1011", # 11
"0x": "0xA7", # 167
"Unsigned-real": "167", # int
"Signed-real": "1.5" # float
}
# Operators to test (excluding =, ++/-- for now)
operators = [
"&", "|", "^", "<<", ">>",
"+", "-", "*", "/", "%", "div", "mod",
"==", "!=", "<", ">", "<=", ">=",
"&&", "||", "^^", "??"
]
# Unary operators
unary_operators = ["!", "-", "~"]
single_arg_funcs = [
"sin", "cos", "tan",
"ceil", "floor",
"abs", "sign",
"frac", "sqr", "exp", "ln", "log2", "log10", "chr",
"int64", "real", "variable_get_hash"
]
multi_arg_funcs = {
"power": 2,
"min": 2,
"max": 2,
"mean": 2,
"median": 2,
"clamp": 3,
"lerp": 3,
"logn": 2,
}
# Output GML header
def write_header():
return (
"function OperatorTypeAndValueTestSuite() : TestSuite() constructor {\n"
)
# GML fact generator for binary operators
def write_binary_fact(op, left_key, right_key, left_val, right_val, index):
name = f"{op} - {left_key} {op} {right_key}"
op_safe = op.replace("=", "eq").replace("<", "lt").replace(">", "gt").replace("&", "and").replace("|", "or").replace("^", "xor").replace("!", "not")
fact_id = f"{op_safe}_{left_key}_{right_key}_{index}"
return f'''
addFact("{name}", function() {{
var result_ct = {left_val} {op} {right_val};
var a = {left_val};
var b = {right_val};
var result_rt = a {op} b;
assert_equals(result_ct == result_rt, true, "{left_key} {op} {right_key} :: value mismatch");
assert_equals(typeof(result_ct) == typeof(result_rt), true, "{left_key} {op} {right_key} :: type mismatch");
}});'''
# GML fact generator for unary operators
def write_unary_fact(op, operand_key, operand_val, index):
name = f"{op} - {op}{operand_key}"
op_safe = op.replace("!", "not").replace("-", "neg").replace("~", "bitneg")
fact_id = f"{op_safe}_{operand_key}_{index}"
return f'''
addFact("{name}", function() {{
var result_ct = {op}{operand_val};
var a = {operand_val};
var result_rt = {op}a;
var name = "{op}{operand_key}";
assert_equals(result_ct == result_rt, true, name + ": value mismatch");
assert_equals(typeof(result_ct) == typeof(result_rt), true, name + ": type mismatch");
}});'''
def write_single_arg_function_fact(func, value, index):
return f'''
addFact("{func} - Single Arg", function() {{
var result_ct = {func}({value});
var a = {value};
var result_rt = {func}(a);
assert_equals(result_ct == result_rt, true, "{func}({value}): value mismatch");
assert_equals(typeof(result_ct), typeof(result_rt), "{func}({value}): type mismatch");
}});'''
def write_multi_arg_function_fact(func, arg_count, values, index):
args = ", ".join(values[:arg_count])
vars_ = ", ".join([f"a{i}" for i in range(arg_count)])
vars_decl = "\n".join([f"\t\tvar a{i} = {values[i]};" for i in range(arg_count)])
return f'''
addFact("{func} - {arg_count} Arg(s)", function() {{
var result_ct = {func}({args});
{vars_decl}
var result_rt = {func}({vars_});
assert_equals(result_ct == result_rt, true, "{func}({args}): value mismatch");
assert_equals(typeof(result_ct), typeof(result_rt), "{func}({args}): type mismatch");
}});'''
# Main output builder
def generate_gml_test_file(path):
result = [write_header()]
idx = 0
# Binary operator tests
result.append("#region === Binary Operators ===")
for op in operators:
for (l_key, r_key) in product(operands, repeat=2):
l_val, r_val = operands[l_key], operands[r_key]
result.append(write_binary_fact(op, l_key, r_key, l_val, r_val, idx))
idx += 1
result.append("#endregion")
# Unary operator tests
result.append("#region === Unary Operators ===")
for op in unary_operators:
for o_key in operands:
o_val = operands[o_key]
result.append(write_unary_fact(op, o_key, o_val, idx))
idx += 1
result.append("#endregion")
# Single-arg function tests
result.append("#region === Single-Arg Functions ===")
for func in single_arg_funcs:
result.append(write_single_arg_function_fact(func, "167.0", idx))
idx += 1
result.append("#endregion")
# Multi-arg function tests
result.append("#region === Multi-Arg Functions ===")
multi_arg_test_values = ["3", "7", "0.5"] # generic test values
for func, arg_count in multi_arg_funcs.items():
result.append(write_multi_arg_function_fact(func, arg_count, multi_arg_test_values, idx))
idx += 1
result.append("#endregion")
result.append("\n}")
gml_code = "\n".join(result)
with open(path, "w", encoding="utf-8") as f:
f.write(gml_code)
print(f"✅ Test suite written to: {path}")
# Run generator
if __name__ == "__main__":
generate_gml_test_file(os.path.join(script_dir, "OperatorTypeAndValueTestSuite.gml"))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment