Coding_Tools/ucompile

223 lines
6.2 KiB
Plaintext
Raw Normal View History

2023-09-25 16:15:02 +02:00
#!/bin/python3
import argparse
import os
2023-09-25 16:15:02 +02:00
from glob import glob
import subprocess
from colorama import Fore, Style
2024-11-25 18:22:30 +01:00
import time
def check_dependencies() -> None:
# Necessary commands list
commands = ["astyle", "gcc", "ghc", "java", "javac", "mvn", "python3"]
for command in commands:
if os.system(f"which {command} > /dev/null") != 0:
print(f"{Fore.RED}Error: {command} not found{Style.RESET_ALL}")
return
2023-09-25 16:15:02 +02:00
2024-11-25 18:22:30 +01:00
def run_input_cases(program, args):
verbose = args.verbose
output = args.output
tests_dir = args.tests_dir if args.tests_dir else "."
time_flag = args.time
input_files = glob(os.path.join(tests_dir, "*.in"))
2023-09-25 16:15:02 +02:00
if len(input_files) < 1:
2024-11-25 18:22:30 +01:00
if time_flag:
start_time = time.perf_counter()
result = subprocess.run(
program,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
)
2024-11-25 18:22:30 +01:00
end_time = time.perf_counter()
elapsed_time = end_time - start_time
print(result.stdout.strip())
print(f"Time taken: {elapsed_time:.4f} seconds")
return
else:
return os.system(program)
2023-09-25 16:15:02 +02:00
for input_file in input_files:
print(f"Running {input_file}")
2023-09-28 22:14:28 +02:00
end_command = f"{program} < {input_file}"
with open(input_file, "r") as f:
input_data = f.read()
out_file = input_file.replace(".in", ".out")
expected_output = None
if os.path.exists(out_file):
with open(out_file, "r") as f:
expected_output = f.read()
2024-11-25 18:22:30 +01:00
if time_flag:
start_time = time.perf_counter()
result = subprocess.run(
end_command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
)
2024-11-25 18:22:30 +01:00
end_time = time.perf_counter()
elapsed_time = end_time - start_time
else:
result = subprocess.run(
end_command,
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
)
program_output = result.stdout
2024-11-20 19:39:16 +01:00
if verbose and not output:
2023-09-25 16:15:02 +02:00
print("Input:")
print(input_data)
2023-09-28 22:14:28 +02:00
print("")
if expected_output is not None:
print("Expected output:")
print(expected_output)
print("")
print("Program output:")
print(program_output.strip())
print("")
if output:
if expected_output is not None:
# Compare the outputs
if program_output == expected_output:
print("✅")
else:
print("❌")
# green expected output and red program output
print(f"{Fore.GREEN}Expected output:{Style.RESET_ALL}")
print(expected_output)
print(f"{Fore.RED}Program output:{Style.RESET_ALL}")
print(program_output.strip())
else:
print(
f"{Fore.YELLOW}Expected output file not found; cannot compare outputs.{Style.RESET_ALL}"
)
if not verbose:
print("Program output:")
print(program_output.strip())
else:
if not verbose:
print(program_output.strip())
2024-11-25 18:22:30 +01:00
if time_flag:
2024-11-25 18:39:42 +01:00
print("=====")
print(f"⏳: {elapsed_time:.4f} s")
2023-09-28 22:14:28 +02:00
print("-----------")
2023-09-25 16:15:02 +02:00
return
2024-11-25 18:22:30 +01:00
def python_compile(file_name, args):
2024-12-04 02:39:12 +01:00
try:
if subprocess.run(["which", "pypy3"]).returncode == 0:
run_input_cases("pypy3 " + file_name, args)
return
except Exception:
pass
finally:
run_input_cases("python3 " + file_name, args)
2023-09-25 16:15:02 +02:00
return
2024-11-25 18:22:30 +01:00
def java_compile(file_name, args):
if args.alternative:
os.system("mvn clean verify")
run_input_cases("java -jar target/*.jar", args)
2023-09-25 16:15:02 +02:00
return
os.system("javac " + file_name)
class_name = os.path.splitext(file_name)[0]
run_input_cases("java " + class_name, args)
2023-09-25 16:15:02 +02:00
return
2024-11-25 18:22:30 +01:00
def haskell_compile(file_name, args):
os.system("ghc -O2 " + file_name + " -o program")
run_input_cases("./program", args)
return
2024-11-25 18:22:30 +01:00
def c_compile(file_name, args):
2023-10-05 11:06:11 +02:00
# Style the code in Meijster's way
os.system("astyle -A2s2cxgk3W3xbj " + file_name)
os.system(
"gcc -Wall -pedantic --std=c99 -g -o program -lm -Wno-unused-result " + file_name
)
run_input_cases("./program", args)
2023-09-25 16:15:02 +02:00
return
2024-11-25 18:22:30 +01:00
2023-09-25 16:15:02 +02:00
def main():
SUPPORTED_LANGS = {
".c": c_compile,
".py": python_compile,
".java": java_compile,
".hs": haskell_compile,
}
2023-09-25 16:15:02 +02:00
parser = argparse.ArgumentParser(
prog="UCompiler", description="Compiles based on language", epilog="LOL"
)
parser.add_argument("filename", metavar="<file>", type=str, help="File to compile")
parser.add_argument(
"-v",
"--verbose",
action="store_true",
default=False,
help="Prints input and output",
)
parser.add_argument(
"-a",
"--alternative",
action="store_true",
default=False,
help="Uses alternative compiler to compile",
)
parser.add_argument(
"-o",
"--output",
action="store_true",
default=False,
help="Checks diff for each .in file with .out file",
)
parser.add_argument(
"-t", "--tests", metavar="<path>", type=str, help="Directory to run tests"
)
parser.add_argument(
"-T",
"--time",
action="store_true",
default=False,
help="Prints time taken to run each test case",
)
2023-09-28 22:14:28 +02:00
2023-09-25 16:15:02 +02:00
args = parser.parse_args()
file_name = args.filename
file_ext = os.path.splitext(file_name)[1]
2023-09-25 16:15:02 +02:00
if file_ext not in SUPPORTED_LANGS:
print("Unsupported language")
return
args.tests_dir = args.tests if args.tests else "."
SUPPORTED_LANGS[file_ext](file_name, args)
return
2023-09-25 16:15:02 +02:00
2024-11-25 18:22:30 +01:00
2023-09-25 16:15:02 +02:00
if __name__ == "__main__":
check_dependencies()
2023-09-25 16:15:02 +02:00
main()