import glob import os import sys STAGE0_MAP = { 'it0': '.py', 'it1': '.py', 'it2': '.c', } 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 sorted(glob.glob('test_*/*.lang0')) def make_rules(file_path, lang0it): result: list[Rule] = [] stdin = file_path.replace('.lang0', '.stdin') exp_cmperr = file_path.replace('.lang0', '.exp.cmperr') exp_stderr = file_path.replace('.lang0', '.exp.stderr') exp_stdout = file_path.replace('.lang0', '.exp.stdout') act_cmperr = 'build/' + file_path.replace('.lang0', f'.{lang0it}.cmperr') act_stderr = 'build/' + file_path.replace('.lang0', f'.{lang0it}.stderr') act_stdout = 'build/' + file_path.replace('.lang0', f'.{lang0it}.stdout') act_result = 'build/' + file_path.replace('.lang0', f'.{lang0it}.result') program = 'build/' + file_path.replace('.lang0', f'.{lang0it}') program_stage0 = program + STAGE0_MAP[lang0it] if os.path.isfile(exp_cmperr): # No need to try to run the program exp_list = [exp_cmperr] act_list = [act_cmperr] elif os.path.isfile(exp_stdout) or os.path.isfile(exp_stderr): result.append(Rule( act_stdout, [program] + ([stdin] if os.path.isfile(stdin) else []), [ '-' + (f'cat {stdin} | ' if os.path.isfile(stdin) else 'echo x | ') + f'{program} 1> {act_stdout} 2> {act_stderr}', ] )) exp_list = [exp_stdout, exp_stderr] act_list = [act_stdout, act_stderr] else: assert False, f'Missing expectations for {file_path}' result.append(Rule( act_result, ([program_stage0] if os.path.isfile(exp_cmperr) else [act_stdout]) + [ x for x in exp_list if os.path.isfile(x) ], [ '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) ] + [ f'-diff /dev/null {act_file} >> $@' for exp_file, act_file in zip(exp_list, act_list, strict=True) if not os.path.isfile(exp_file) ] )) 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)