import glob import os import sys class Rule: def __init__(self, target: str, prerequisites: list[str], recipe: list[str]) -> None: self.target = target self.prerequisites = prerequisites self.recipe = recipe def make_lines(self): return [ self.target + ': ' + ' '.join(self.prerequisites), ] + [ '\t' + line for line in self.recipe ] + [''] def get_file_list(): return glob.glob('test_*/*.lang0') def make_rules(file_path, lang0it): result: list[Rule] = [] act_result = file_path.replace('.lang0', f'.act.{lang0it}.result') act_stdout = file_path.replace('.lang0', f'.act.{lang0it}.stdout') act_stderr = file_path.replace('.lang0', f'.act.{lang0it}.stderr') stdin = file_path.replace('.lang0', '.stdin') exp_stdout = file_path.replace('.lang0', '.exp.stdout') exp_stderr = file_path.replace('.lang0', '.exp.stderr') program = file_path.replace('.lang0', f'.{lang0it}') if os.path.isfile(exp_stdout) or os.path.isfile(exp_stderr): result.append(Rule( act_stdout, ['build/' + program], [ (f'cat {stdin} | ' if os.path.isfile(stdin) else 'echo x | ') + f'build/{program} 1> {act_stdout} 2> {act_stderr}', ] )) exp_list = [exp_stdout, exp_stderr] act_list = [act_stdout, act_stderr] result.append(Rule( act_result, [ fil for exp_file, act_file in zip(exp_list, act_list, strict=True) if os.path.isfile(exp_file) for fil in [exp_file, act_file] ], [ 'rm -f $@', ] + [ f'-diff {exp_file} {act_file} >> $@' for exp_file, act_file in zip(exp_list, act_list, strict=True) if os.path.isfile(exp_file) ] )) assert result[-1].prerequisites, f'Missing expectations for {file_path}' return result def main(program, write_to, *lang0it): rule_list_list = [ make_rules(file_path, it) for file_path in get_file_list() for it in lang0it ] result_targets = [ rule.target for rule_list in rule_list_list for rule in rule_list if rule.target.endswith('.result') ] rule_list_list.append([Rule( 'verify-results', result_targets, [ '@echo Finding failed test results...', '@find $^ -not -empty -print -exec false {} +', '@echo All tests passed.' ] )]) data = '\n'.join( line for rule_list in rule_list_list for rule in rule_list for line in rule.make_lines() ) with open(write_to, 'wt', encoding='ASCII') as fil: fil.write(data) if __name__ == '__main__': main(*sys.argv)