diff --git a/.docker.test.py b/.docker.test.py index e6dfb5cd2..4c5f93ea6 100644 --- a/.docker.test.py +++ b/.docker.test.py @@ -6,12 +6,12 @@ from dmoj.executors import get_available arch = platform.machine() -ALLOW_FAIL = {'GASARM', 'JAVA9', 'JAVA10', 'OBJC'} +ALLOW_FAIL = {'GASARM', 'OBJC'} EXECUTORS = get_available() if arch == 'aarch64': ALLOW_FAIL -= {'GASARM'} - ALLOW_FAIL |= {'D', 'GAS32', 'GAS64', 'NASM', 'NASM64', 'SWIFT', 'TUR'} + ALLOW_FAIL |= {'D', 'GAS32', 'GAS64', 'LEAN4', 'NASM', 'NASM64', 'SWIFT', 'TUR'} elif arch != 'x86_64': raise AssertionError('invalid architecture') diff --git a/.docker/tier1/Dockerfile b/.docker/tier1/Dockerfile index f1e48322c..aacdad428 100644 --- a/.docker/tier1/Dockerfile +++ b/.docker/tier1/Dockerfile @@ -15,6 +15,7 @@ RUN curl --location -o scratch-run.zip $(curl -s https://api.github.com/repos/VN RUN mkdir /judge /problems && cd /judge && \ curl -L https://github.com/VNOI-Admin/judge-server/archive/"${TAG}".tar.gz | tar -xz --strip-components=1 && \ pip3 install -e . && \ + python3 setup.py develop && \ HOME=~judge . ~judge/.profile && \ runuser -u judge -w PATH -- dmoj-autoconf -V > /judge-runtime-paths.yml && \ echo ' crt_x86_in_lib32: true' >> /judge-runtime-paths.yml && \ diff --git a/.docker/tier2/Dockerfile b/.docker/tier2/Dockerfile index 634e88f02..71bfd87de 100644 --- a/.docker/tier2/Dockerfile +++ b/.docker/tier2/Dockerfile @@ -15,6 +15,7 @@ RUN curl --location -o scratch-run.zip $(curl -s https://api.github.com/repos/VN RUN mkdir /judge /problems && cd /judge && \ curl -L https://github.com/VNOI-Admin/judge-server/archive/"${TAG}".tar.gz | tar -xz --strip-components=1 && \ pip3 install -e . && \ + python3 setup.py develop && \ HOME=~judge . ~judge/.profile && \ runuser -u judge -w PATH -- dmoj-autoconf -V > /judge-runtime-paths.yml && \ echo ' crt_x86_in_lib32: true' >> /judge-runtime-paths.yml && \ diff --git a/.docker/tier3/Dockerfile b/.docker/tier3/Dockerfile index f32b0dc77..3d91ce30a 100644 --- a/.docker/tier3/Dockerfile +++ b/.docker/tier3/Dockerfile @@ -15,6 +15,7 @@ RUN curl --location -o scratch-run.zip $(curl -s https://api.github.com/repos/VN RUN mkdir /judge /problems && cd /judge && \ curl -L https://github.com/VNOI-Admin/judge-server/archive/"${TAG}".tar.gz | tar -xz --strip-components=1 && \ pip3 install -e . && \ + python3 setup.py develop && \ HOME=~judge . ~judge/.profile && \ runuser -u judge -w PATH -- dmoj-autoconf -V > /judge-runtime-paths.yml && \ echo ' crt_x86_in_lib32: true' >> /judge-runtime-paths.yml && \ diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b91a3d99..4aeedf43e 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,10 +5,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v1 with: - python-version: 3.9 + python-version: '3.10' - name: Install Black and Flake8 run: | pip install black==21.8b0 flake8 flake8-future-import flake8-logging-format flake8-import-order flake8-quotes flake8-black @@ -27,10 +27,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v1 with: - python-version: 3.9 + python-version: '3.10' - name: Install dependencies and mypy run: | pip install cython mypy types-termcolor types-requests types-PyYAML @@ -43,10 +43,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - - name: Set up Python 3.9 + - name: Set up Python 3.10 uses: actions/setup-python@v1 with: - python-version: 3.9 + python-version: '3.10' - name: Install build dependencies run: pip install cython - name: Create sdist @@ -61,7 +61,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [ 3.6, 3.7, 3.8, 3.9 ] + python-version: [ 3.6, 3.7, 3.8, 3.9, '3.10' ] steps: - uses: actions/checkout@v2 - name: Download docker image diff --git a/.github/workflows/update-syscalls.yml b/.github/workflows/update-syscalls.yml index 205940ced..fa182b121 100644 --- a/.github/workflows/update-syscalls.yml +++ b/.github/workflows/update-syscalls.yml @@ -12,10 +12,10 @@ jobs: uses: actions/setup-python@v1 with: python-version: 3.7 - - name: Update Linux syscalls + - name: Update syscalls run: | cd dmoj/cptbox/syscalls - python generate_linux.py + python generate.py - name: Create pull request uses: peter-evans/create-pull-request@v3 with: diff --git a/README.md b/README.md index 59c3bca43..680897aad 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ The judge can also grade in the languages listed below. These languages are less * Haskell * INTERCAL * Kotlin +* Lean 4 * Lua * NASM * Objective-C diff --git a/dmoj/commands/submit.py b/dmoj/commands/submit.py index 105abc58e..4eb7844a7 100644 --- a/dmoj/commands/submit.py +++ b/dmoj/commands/submit.py @@ -1,9 +1,8 @@ from typing import Optional -from dmoj import judgeenv +from dmoj import executors, judgeenv from dmoj.commands.base_command import Command from dmoj.error import InvalidCommandException -from dmoj.executors import executors from dmoj.judge import Submission @@ -45,7 +44,7 @@ def execute(self, line: str) -> None: memory_limit: int = args.memory_limit source_file: Optional[str] = args.source_file - if language_id not in executors: + if language_id not in executors.executors: source_file = language_id language_id = None # source file / language id optional @@ -53,16 +52,10 @@ def execute(self, line: str) -> None: raise InvalidCommandException(f"unknown problem '{problem_id}'") elif not language_id: if source_file: - filename, dot, ext = source_file.partition('.') - if not ext: - raise InvalidCommandException('invalid file name') - else: - # TODO: this should be a proper lookup elsewhere - ext = ext.upper() - language_id = {'PY': 'PY2', 'CPP': 'CPP11', 'JAVA': 'JAVA8'}.get(ext, ext) + language_id = executors.from_filename(source_file).Executor.name else: raise InvalidCommandException('no language is selected') - elif language_id not in executors: + elif language_id not in executors.executors: raise InvalidCommandException(f"unknown language '{language_id}'") elif time_limit <= 0: raise InvalidCommandException('--time-limit must be >= 0') diff --git a/dmoj/cptbox/filesystem_policies.py b/dmoj/cptbox/filesystem_policies.py index a8df7038b..24e2677e7 100644 --- a/dmoj/cptbox/filesystem_policies.py +++ b/dmoj/cptbox/filesystem_policies.py @@ -104,9 +104,10 @@ def _finalize_directory_rule(self, node: Dir, rule: Union[ExactDir, RecursiveDir # `path` should be a normalized path def check(self, path: str) -> bool: assert os.path.abspath(path) == path, 'Must pass a normalized, absolute path to check' + components = [] if path == '/' else path.split('/')[1:] node = self.root - for component in path.split('/')[1:]: + for component in components: if isinstance(node, File): return False elif node.access_mode == AccessMode.RECURSIVE: diff --git a/dmoj/cptbox/isolate.py b/dmoj/cptbox/isolate.py index ffcd6a6b5..f7aa179dc 100644 --- a/dmoj/cptbox/isolate.py +++ b/dmoj/cptbox/isolate.py @@ -50,6 +50,7 @@ def __init__(self, read_fs, write_fs=None, writable=(1, 2)): sys_openat: self.check_file_access_at('openat', is_open=True), sys_open: self.check_file_access('open', 0, is_open=True), sys_faccessat: self.check_file_access_at('faccessat'), + sys_faccessat2: self.check_file_access_at('faccessat2'), sys_access: self.check_file_access('access', 0), sys_readlink: self.check_file_access('readlink', 0), sys_readlinkat: self.check_file_access_at('readlinkat'), @@ -58,6 +59,7 @@ def __init__(self, read_fs, write_fs=None, writable=(1, 2)): sys_lstat: self.check_file_access('lstat', 0), sys_lstat64: self.check_file_access('lstat64', 0), sys_fstatat: self.check_file_access_at('fstatat'), + sys_statx: self.check_file_access_at('statx'), sys_tgkill: self.do_kill, sys_kill: self.do_kill, sys_prctl: self.do_prctl, @@ -70,6 +72,8 @@ def __init__(self, read_fs, write_fs=None, writable=(1, 2)): sys_getpgrp: ALLOW, sys_restart_syscall: ALLOW, sys_select: ALLOW, + sys_pselect6: ALLOW, + sys_pselect6_time64: ALLOW, sys_newselect: ALLOW, sys_modify_ldt: ALLOW, sys_poll: ALLOW, @@ -158,13 +162,13 @@ def __init__(self, read_fs, write_fs=None, writable=(1, 2)): self.update( { sys_mkdir: ACCESS_EPERM, - sys_obreak: ALLOW, + sys_break: ALLOW, sys_sysarch: ALLOW, sys_sysctl: ALLOW, # TODO: More strict? + sys_sysctlbyname: ALLOW, # TODO: More strict? sys_issetugid: ALLOW, sys_rtprio_thread: ALLOW, # EPERMs when invalid anyway sys_umtx_op: ALLOW, # http://fxr.watson.org/fxr/source/kern/kern_umtx.c?v=FREEBSD60#L720 - sys_nosys: ALLOW, # what?? TODO: this shouldn't really exist, so why is Python calling it? sys_getcontext: ALLOW, sys_setcontext: ALLOW, sys_pread: ALLOW, @@ -175,8 +179,6 @@ def __init__(self, read_fs, write_fs=None, writable=(1, 2)): sys_thr_exit: ALLOW, sys_thr_kill: ALLOW, sys_thr_self: ALLOW, - sys__mmap: ALLOW, - sys___mmap: ALLOW, sys_sigsuspend: ALLOW, sys_clock_getcpuclockid2: ALLOW, sys_fstatfs: ALLOW, @@ -285,6 +287,10 @@ def _file_access_check( if normalized.startswith('/proc/self'): file = os.path.join(f'/proc/{debugger.tid}', os.path.relpath(file, '/proc/self')) projected = '/' + os.path.normpath(file).lstrip('/') + elif normalized.startswith(f'/proc/{debugger.tid}/'): + # If the child process uses /proc/getpid()/foo, set the normalized path to be /proc/self/foo. + # Access rules can more easily check /proc/self. + normalized = os.path.join('/proc/self', os.path.relpath(file, f'/proc/{debugger.tid}')) real = os.path.realpath(file) try: diff --git a/dmoj/cptbox/ptbox.h b/dmoj/cptbox/ptbox.h index d37bb1140..d253f9642 100644 --- a/dmoj/cptbox/ptbox.h +++ b/dmoj/cptbox/ptbox.h @@ -25,7 +25,7 @@ #include #endif -#define MAX_SYSCALL 568 +#define MAX_SYSCALL 600 #define PTBOX_HANDLER_DENY 0 #define PTBOX_HANDLER_ALLOW 1 #define PTBOX_HANDLER_CALLBACK 2 diff --git a/dmoj/cptbox/syscalls.pyi b/dmoj/cptbox/syscalls.pyi index beff2e8b9..b082f62e3 100644 --- a/dmoj/cptbox/syscalls.pyi +++ b/dmoj/cptbox/syscalls.pyi @@ -5,9 +5,6 @@ by_name: Dict[str, int] by_id: List[str] SYSCALL_COUNT: int -sys___mmap: int -sys__getsockname: int -sys__mmap: int sys__sysctl: int sys_abort2: int sys_accept: int @@ -36,15 +33,16 @@ sys_aio_error: int sys_aio_fsync: int sys_aio_mlock: int sys_aio_read: int +sys_aio_readv: int sys_aio_return: int sys_aio_suspend: int sys_aio_waitcomplete: int sys_aio_write: int +sys_aio_writev: int sys_alarm: int sys_arch_prctl: int sys_arm_fadvise64_64: int sys_arm_sync_file_range: int -sys_asyncdaemon: int sys_audit: int sys_auditctl: int sys_auditon: int @@ -177,6 +175,7 @@ sys_fsconfig: int sys_fsetxattr: int sys_fsmount: int sys_fsopen: int +sys_fspacectl: int sys_fspick: int sys_fstat: int sys_fstat64: int @@ -187,6 +186,7 @@ sys_fsync: int sys_ftime: int sys_ftruncate: int sys_ftruncate64: int +sys_funlinkat: int sys_futex: int sys_futex_time64: int sys_futex_waitv: int @@ -205,10 +205,8 @@ sys_getcpu: int sys_getcwd: int sys_getdents: int sys_getdents64: int -sys_getdescriptor: int sys_getdirentries: int sys_getdomainname: int -sys_getdopt: int sys_getdtablesize: int sys_getegid: int sys_getegid32: int @@ -228,8 +226,6 @@ sys_getkerninfo: int sys_getlogin: int sys_getloginclass: int sys_getpagesize: int -sys_getpath_fromaddr: int -sys_getpath_fromfd: int sys_getpeername: int sys_getpgid: int sys_getpgrp: int @@ -417,7 +413,8 @@ sys_munlockall: int sys_munmap: int sys_name_to_handle_at: int sys_nanosleep: int -sys_newreboot: int +sys_netbsd_lchown: int +sys_netbsd_msync: int sys_newselect: int sys_nfsclnt: int sys_nfsservctl: int @@ -428,13 +425,11 @@ sys_nlm_syscall: int sys_nlstat: int sys_nmount: int sys_nnpfs_syscall: int -sys_nosys: int sys_nstat: int sys_ntp_adjtime: int sys_ntp_gettime: int sys_numa_getaffinity: int sys_numa_setaffinity: int -sys_obreak: int sys_oldfstat: int sys_oldlstat: int sys_oldolduname: int @@ -446,7 +441,6 @@ sys_open_tree: int sys_openat: int sys_openat2: int sys_openbsd_poll: int -sys_ovadvise: int sys_pathconf: int sys_pause: int sys_pciconfig_iobase: int @@ -455,7 +449,6 @@ sys_pciconfig_write: int sys_pdfork: int sys_pdgetpid: int sys_pdkill: int -sys_pdwait4: int sys_perf_event_open: int sys_personality: int sys_pidfd_getfd: int @@ -510,6 +503,7 @@ sys_readdir: int sys_readlink: int sys_readlinkat: int sys_readv: int +sys_realpathat: int sys_reboot: int sys_recv: int sys_recvfrom: int @@ -523,10 +517,10 @@ sys_renameat: int sys_renameat2: int sys_request_key: int sys_restart_syscall: int -sys_resuba: int sys_revoke: int sys_rfork: int sys_rmdir: int +sys_rpctls_syscall: int sys_rseq: int sys_rt_sigaction: int sys_rt_sigpending: int @@ -544,6 +538,7 @@ sys_sched_get_priority_max: int sys_sched_get_priority_min: int sys_sched_getaffinity: int sys_sched_getattr: int +sys_sched_getcpu: int sys_sched_getparam: int sys_sched_getscheduler: int sys_sched_rr_get_interval: int @@ -560,8 +555,6 @@ sys_sctp_peeloff: int sys_seccomp: int sys_security: int sys_select: int -sys_sem_lock: int -sys_sem_wakeup: int sys_semconfig: int sys_semctl: int sys_semget: int @@ -583,9 +576,7 @@ sys_setaudit: int sys_setaudit_addr: int sys_setauid: int sys_setcontext: int -sys_setdescriptor: int sys_setdomainname: int -sys_setdopt: int sys_setegid: int sys_seteuid: int sys_setfib: int @@ -622,9 +613,10 @@ sys_setuid: int sys_setuid32: int sys_setup: int sys_setxattr: int -sys_sfork: int sys_sgetmask: int sys_shm_open: int +sys_shm_open2: int +sys_shm_rename: int sys_shm_unlink: int sys_shmat: int sys_shmctl: int @@ -635,6 +627,7 @@ sys_shutdown: int sys_sigaction: int sys_sigaltstack: int sys_sigblock: int +sys_sigfastblock: int sys_siggetmask: int sys_signal: int sys_signalfd: int @@ -654,6 +647,7 @@ sys_sigwaitinfo: int sys_socket: int sys_socketcall: int sys_socketpair: int +sys_specialfd: int sys_splice: int sys_ssetmask: int sys_sstk: int @@ -675,6 +669,7 @@ sys_syncfs: int sys_sysarch: int sys_syscall: int sys_sysctl: int +sys_sysctlbyname: int sys_sysfs: int sys_sysinfo: int sys_syslog: int @@ -714,7 +709,9 @@ sys_ulimit: int sys_umask: int sys_umount: int sys_umount2: int +sys_umtx_lock: int sys_umtx_op: int +sys_umtx_unlock: int sys_uname: int sys_undelete: int sys_unlink: int @@ -730,6 +727,7 @@ sys_utimensat_time64: int sys_utimes: int sys_utrace: int sys_uuidgen: int +sys_vadvise: int sys_vfork: int sys_vhangup: int sys_vlimit: int @@ -748,7 +746,4 @@ sys_waitid: int sys_waitpid: int sys_write: int sys_writev: int -sys_xfstat: int -sys_xlstat: int -sys_xstat: int sys_yield: int diff --git a/dmoj/cptbox/syscalls/freebsd.tbl b/dmoj/cptbox/syscalls/freebsd.tbl index fe54f6846..066c7d190 100644 --- a/dmoj/cptbox/syscalls/freebsd.tbl +++ b/dmoj/cptbox/syscalls/freebsd.tbl @@ -1,4 +1,4 @@ -0 nosys +0 syscall 1 exit 2 fork 3 read @@ -15,7 +15,7 @@ 14 mknod 15 chmod 16 chown -17 obreak +17 break 18 getfsstat 19 lseek 20 getpid @@ -70,7 +70,7 @@ 69 sbrk 70 sstk 71 mmap -72 ovadvise +72 vadvise 73 munmap 74 mprotect 75 madvise @@ -89,10 +89,8 @@ 88 sethostname 89 getdtablesize 90 dup2 -91 getdopt 92 fcntl 93 select -94 setdopt 95 fsync 96 setpriority 97 socket @@ -117,7 +115,6 @@ 116 gettimeofday 117 getrusage 118 getsockopt -119 resuba 120 readv 121 writev 122 settimeofday @@ -137,7 +134,6 @@ 136 mkdir 137 rmdir 138 utimes -139 sigreturn 140 adjtime 141 getpeername 142 gethostid @@ -148,10 +144,7 @@ 147 setsid 148 quotactl 149 quota -150 _getsockname -151 sem_lock -152 sem_wakeup -153 asyncdaemon +150 getsockname 154 nlm_syscall 155 nfssvc 156 getdirentries @@ -171,9 +164,6 @@ 174 pwrite 175 setfib 176 ntp_adjtime -177 sfork -178 getdescriptor -179 setdescriptor 181 setgid 182 setegid 183 seteuid @@ -189,7 +179,8 @@ 194 getrlimit 195 setrlimit 196 getdirentries -197 _mmap +197 mmap +198 syscall 199 lseek 200 truncate 201 ftruncate @@ -199,7 +190,6 @@ 205 undelete 206 futimes 207 getpgid -208 newreboot 209 poll 220 semctl 221 semget @@ -225,6 +215,7 @@ 241 ffclock_getcounter 242 ffclock_setestimate 243 ffclock_getestimate +244 clock_nanosleep 247 clock_getcpuclockid2 248 ntp_gettime 250 minherit @@ -237,12 +228,14 @@ 257 lio_listio 272 getdents 274 lchmod -275 lchown +275 netbsd_lchown 276 lutimes -277 msync +277 netbsd_msync 278 nstat 279 nfstat 280 nlstat +289 preadv +290 pwritev 297 fhstatfs 298 fhopen 299 fhstat @@ -273,14 +266,14 @@ 324 mlockall 325 munlockall 326 getcwd -327 sched_setparam -328 sched_getparam -329 sched_setscheduler -330 sched_getscheduler -331 sched_yield -332 sched_get_priority_max -333 sched_get_priority_min -334 sched_rr_get_interval +327 sched_setparam +328 sched_getparam +329 sched_setscheduler +330 sched_getscheduler +331 sched_yield +332 sched_get_priority_max +333 sched_get_priority_min +334 sched_rr_get_interval 335 utrace 336 sendfile 337 kldsym @@ -362,9 +355,6 @@ 415 mac_execve 416 sigaction 417 sigreturn -418 xstat -419 xfstat -420 xlstat 421 getcontext 422 setcontext 423 swapcontext @@ -378,6 +368,8 @@ 431 thr_exit 432 thr_self 433 thr_kill +434 umtx_lock +435 umtx_unlock 436 jail_attach 437 extattr_list_fd 438 extattr_list_file @@ -409,15 +401,13 @@ 464 thr_set_name 465 aio_fsync 466 rtprio_thread -469 getpath_fromfd -470 getpath_fromaddr 471 sctp_peeloff 472 sctp_generic_sendmsg 473 sctp_generic_sendmsg_iov 474 sctp_generic_recvmsg 475 pread 476 pwrite -477 __mmap +477 mmap 478 lseek 479 truncate 480 ftruncate @@ -461,7 +451,6 @@ 518 pdfork 519 pdkill 520 pdgetpid -521 pdwait4 522 pselect 523 getloginclass 524 setloginclass @@ -508,3 +497,18 @@ 565 fhlink 566 fhlinkat 567 fhreadlink +568 funlinkat +569 copy_file_range +570 sysctlbyname +571 shm_open2 +572 shm_rename +573 sigfastblock +574 realpathat +575 close_range +576 rpctls_syscall +577 specialfd +578 aio_writev +579 aio_readv +580 fspacectl +581 sched_getcpu +582 swapoff diff --git a/dmoj/cptbox/syscalls/generate_linux.py b/dmoj/cptbox/syscalls/generate.py similarity index 82% rename from dmoj/cptbox/syscalls/generate_linux.py rename to dmoj/cptbox/syscalls/generate.py index 5db9b3eba..e2bf09af1 100644 --- a/dmoj/cptbox/syscalls/generate_linux.py +++ b/dmoj/cptbox/syscalls/generate.py @@ -8,6 +8,7 @@ LINUX_SYSCALLS_64 = 'https://raw.githubusercontent.com/torvalds/linux/master/arch/x86/entry/syscalls/syscall_64.tbl' LINUX_SYSCALLS_ARM = 'https://raw.githubusercontent.com/torvalds/linux/master/arch/arm/tools/syscall.tbl' LINUX_SYSCALLS_GENERIC = 'https://raw.githubusercontent.com/torvalds/linux/master/include/uapi/asm-generic/unistd.h' +FREEBSD_SYSCALLS = 'https://cgit.freebsd.org/src/plain/sys/kern/syscalls.master' func_to_name = {} names = set() @@ -90,6 +91,34 @@ print('%d\t%s' % (id, name), file=generic64) print('%d\t%s' % (id, name), file=generic32) + +renumber = re.compile(r'^(\d+)\s+AUE_\S+\s+\S+(?:\t(\w+)$)?') +rename = re.compile(r'\t\t\w+ \*?(.*)\(') +number = -1 + + +def freebsd_syscall(name): + global number + if number == -1: + raise RuntimeError('FreeBSD line missed?') + name = name.lstrip('_') + names.add(name) + print(f'{number}\t{name}', file=output) + number = -1 + + +with open('freebsd.tbl', 'w') as output, utf8reader(urlopen(FREEBSD_SYSCALLS)) as data: + for line in data: + match = renumber.match(line) + if match: + number = int(match[1]) + if match[2]: + freebsd_syscall(match[2]) + else: + match = rename.match(line) + if match: + freebsd_syscall(match[1]) + with open('aliases.list') as aliases: for line in aliases: names.add(line.split()[1]) diff --git a/dmoj/executors/ADA.py b/dmoj/executors/ADA.py index 3290ca91f..8243a7dfd 100644 --- a/dmoj/executors/ADA.py +++ b/dmoj/executors/ADA.py @@ -2,7 +2,6 @@ class Executor(GCCExecutor): - name = 'ADA' command = 'gnatmake' ext = 'adb' test_program = """\ diff --git a/dmoj/executors/AWK.py b/dmoj/executors/AWK.py index e87574b37..d5e253f34 100644 --- a/dmoj/executors/AWK.py +++ b/dmoj/executors/AWK.py @@ -3,7 +3,6 @@ class Executor(ScriptExecutor): ext = 'awk' - name = 'AWK' command = 'awk' command_paths = ['mawk', 'gawk', 'awk'] syscalls = ['getgroups'] # gawk is annoying. diff --git a/dmoj/executors/BASH.py b/dmoj/executors/BASH.py index 561d3d3a3..207c34909 100644 --- a/dmoj/executors/BASH.py +++ b/dmoj/executors/BASH.py @@ -3,7 +3,6 @@ class Executor(ShellExecutor): ext = 'sh' - name = 'BASH' command = 'bash' test_program = 'exec cat' diff --git a/dmoj/executors/BF.py b/dmoj/executors/BF.py index 95a8909b5..02aed9bbb 100644 --- a/dmoj/executors/BF.py +++ b/dmoj/executors/BF.py @@ -44,7 +44,6 @@ class Executor(CExecutor): - name = 'BF' test_program = ',+[-.,+]' def __init__(self, problem_id, source_code, **kwargs): diff --git a/dmoj/executors/C.py b/dmoj/executors/C.py index 91d53b0d1..1c5f02675 100644 --- a/dmoj/executors/C.py +++ b/dmoj/executors/C.py @@ -5,7 +5,6 @@ class Executor(GCCExecutor): command = 'gcc' flags = ['-std=c99'] ext = 'c' - name = 'C' test_program = """ #include diff --git a/dmoj/executors/C11.py b/dmoj/executors/C11.py index ded596ecb..67dda17da 100644 --- a/dmoj/executors/C11.py +++ b/dmoj/executors/C11.py @@ -6,7 +6,6 @@ class Executor(GCCExecutor): flags = ['-std=c11'] command_paths = ['gcc'] ext = 'c' - name = 'C11' test_program = """ #include diff --git a/dmoj/executors/CBL.py b/dmoj/executors/CBL.py index 33cd52d08..24cc6e2b0 100644 --- a/dmoj/executors/CBL.py +++ b/dmoj/executors/CBL.py @@ -6,7 +6,6 @@ class Executor(CompiledExecutor): ext = 'cbl' - name = 'CBL' command = 'cobc' address_grace = 131072 compile_output_index = 0 diff --git a/dmoj/executors/CLANG.py b/dmoj/executors/CLANG.py index 4cb1d95e0..8cce22429 100644 --- a/dmoj/executors/CLANG.py +++ b/dmoj/executors/CLANG.py @@ -5,4 +5,3 @@ class Executor(ClangExecutor, CExecutor): command = 'clang' command_paths = ['clang-%s' % i for i in ['3.9', '3.8', '3.7', '3.6', '3.5']] + ['clang'] - name = 'CLANG' diff --git a/dmoj/executors/CLANGX.py b/dmoj/executors/CLANGX.py index b862e2113..9a32115b5 100644 --- a/dmoj/executors/CLANGX.py +++ b/dmoj/executors/CLANGX.py @@ -5,4 +5,3 @@ class Executor(ClangExecutor, CPP11Executor): command = 'clang++' command_paths = ['clang++-%s' % i for i in ['3.9', '3.8', '3.7', '3.6', '3.5']] + ['clang++'] - name = 'CLANG++' diff --git a/dmoj/executors/COFFEE.py b/dmoj/executors/COFFEE.py index ab0d15b8a..873c7f840 100644 --- a/dmoj/executors/COFFEE.py +++ b/dmoj/executors/COFFEE.py @@ -6,7 +6,6 @@ class Executor(ScriptExecutor): ext = 'coffee' - name = 'COFFEE' nproc = -1 command = 'node' syscalls = [ diff --git a/dmoj/executors/CPP03.py b/dmoj/executors/CPP03.py index 8121971d1..aeaf480ab 100644 --- a/dmoj/executors/CPP03.py +++ b/dmoj/executors/CPP03.py @@ -7,7 +7,6 @@ class Executor(GCCExecutor): command = 'g++' std: Optional[str] = None ext = 'cpp' - name = 'CPP03' test_program = """ #include diff --git a/dmoj/executors/CPP11.py b/dmoj/executors/CPP11.py index 87db5e3ac..b6321d28f 100644 --- a/dmoj/executors/CPP11.py +++ b/dmoj/executors/CPP11.py @@ -5,7 +5,6 @@ class Executor(CPPExecutor): command = 'g++11' command_paths = ['g++-5', 'g++-4.9', 'g++-4.8', 'g++'] std = 'c++11' - name = 'CPP11' test_program = """ #include diff --git a/dmoj/executors/CPP14.py b/dmoj/executors/CPP14.py index 0df970d41..873e99d39 100644 --- a/dmoj/executors/CPP14.py +++ b/dmoj/executors/CPP14.py @@ -5,7 +5,6 @@ class Executor(CPPExecutor): command = 'g++14' command_paths = ['g++-5', 'g++'] std = 'c++14' - name = 'CPP14' test_program = """ #include diff --git a/dmoj/executors/CPP17.py b/dmoj/executors/CPP17.py index 415aafcb1..9c7c971ee 100644 --- a/dmoj/executors/CPP17.py +++ b/dmoj/executors/CPP17.py @@ -5,7 +5,6 @@ class Executor(CPPExecutor): command = 'g++17' command_paths = ['g++-7', 'g++'] std = 'c++17' - name = 'CPP17' test_program = """ #include diff --git a/dmoj/executors/CPP20.py b/dmoj/executors/CPP20.py index c5ffc0278..af3d307a0 100644 --- a/dmoj/executors/CPP20.py +++ b/dmoj/executors/CPP20.py @@ -5,7 +5,6 @@ class Executor(CPPExecutor): command = 'g++20' command_paths = ['g++-11', 'g++'] std = 'c++20' - name = 'CPP20' test_program = """ #include diff --git a/dmoj/executors/D.py b/dmoj/executors/D.py index 19b656d18..cda51d015 100644 --- a/dmoj/executors/D.py +++ b/dmoj/executors/D.py @@ -4,7 +4,6 @@ class Executor(CompiledExecutor): ext = 'd' - name = 'D' address_grace = 32768 command = 'dmd' compiler_read_fs = [ diff --git a/dmoj/executors/DART.py b/dmoj/executors/DART.py index a3575875f..2f955cea4 100644 --- a/dmoj/executors/DART.py +++ b/dmoj/executors/DART.py @@ -6,7 +6,6 @@ # Thankfully compiling it results in something... far more sane class Executor(CompiledExecutor): ext = 'dart' - name = 'DART' nproc = -1 # Dart uses a really, really large number of threads command = 'dart' compiler_read_fs = [ diff --git a/dmoj/executors/F95.py b/dmoj/executors/F95.py index 71e0d6f7c..4f9a9a769 100644 --- a/dmoj/executors/F95.py +++ b/dmoj/executors/F95.py @@ -2,7 +2,6 @@ class Executor(GCCExecutor): - name = 'F95' command = 'gfortran' ext = 'f95' test_program = """\ diff --git a/dmoj/executors/FORTH.py b/dmoj/executors/FORTH.py index 4ee7d1706..6e076e26d 100644 --- a/dmoj/executors/FORTH.py +++ b/dmoj/executors/FORTH.py @@ -3,7 +3,6 @@ class Executor(ScriptExecutor): - name = 'FORTH' command = 'gforth' ext = 'fs' test_program = """\ diff --git a/dmoj/executors/GAS32.py b/dmoj/executors/GAS32.py index a4de945cb..3db690f8f 100644 --- a/dmoj/executors/GAS32.py +++ b/dmoj/executors/GAS32.py @@ -3,7 +3,6 @@ class Executor(PlatformX86Mixin, GASExecutor): as_name = 'as_x86' - name = 'GAS32' test_program = r""".intel_syntax noprefix diff --git a/dmoj/executors/GAS64.py b/dmoj/executors/GAS64.py index cc96224b4..1e22bf008 100644 --- a/dmoj/executors/GAS64.py +++ b/dmoj/executors/GAS64.py @@ -3,7 +3,6 @@ class Executor(PlatformX64Mixin, GASExecutor): as_name = 'as_x64' - name = 'GAS64' test_program = r""".intel_syntax noprefix diff --git a/dmoj/executors/GASARM.py b/dmoj/executors/GASARM.py index daf61cdbf..1171865b0 100644 --- a/dmoj/executors/GASARM.py +++ b/dmoj/executors/GASARM.py @@ -14,7 +14,6 @@ class Executor(GASExecutor): dynamic_linker = env.runtime['ld.so_arm'] or '/lib/ld-linux-armhf.so.3' crt_pre = env.runtime.crt_pre_arm or ['/usr/lib/arm-linux-gnueabihf/crt1.o', '/usr/lib/arm-linux-gnueabihf/crti.o'] crt_post = env.runtime.crt_post_arm or ['/usr/lib/arm-linux-gnueabihf/crtn.o'] - name = 'GASARM' test_program = r""" .global _start _start: diff --git a/dmoj/executors/GO.py b/dmoj/executors/GO.py index 7c20faa6c..e95d4bf26 100644 --- a/dmoj/executors/GO.py +++ b/dmoj/executors/GO.py @@ -15,7 +15,6 @@ def decomment(x): class Executor(CompiledExecutor): ext = 'go' - name = 'GO' nproc = -1 data_grace = 98304 # Go uses data segment for heap arena map address_grace = 786432 diff --git a/dmoj/executors/GROOVY.py b/dmoj/executors/GROOVY.py index d4ca7f7d6..f75278d42 100644 --- a/dmoj/executors/GROOVY.py +++ b/dmoj/executors/GROOVY.py @@ -7,7 +7,6 @@ class Executor(JavaExecutor): - name = 'GROOVY' ext = 'groovy' compiler = 'groovyc' diff --git a/dmoj/executors/HASK.py b/dmoj/executors/HASK.py index 626175bd2..2cb1434df 100644 --- a/dmoj/executors/HASK.py +++ b/dmoj/executors/HASK.py @@ -5,7 +5,6 @@ class Executor(NullStdoutMixin, CompiledExecutor): ext = 'hs' - name = 'HASK' command = 'ghc' compiler_read_fs = [ RecursiveDir('/proc/self/task'), diff --git a/dmoj/executors/ICK.py b/dmoj/executors/ICK.py index 5315d2c61..0bcc2eca4 100644 --- a/dmoj/executors/ICK.py +++ b/dmoj/executors/ICK.py @@ -3,7 +3,6 @@ class Executor(CompiledExecutor): ext = 'i' - name = 'ICK' command = 'ick' test_program = """\ PLEASE DO ,1 <- #1 diff --git a/dmoj/executors/JAVA10.py b/dmoj/executors/JAVA10.py index 0cec509b2..329367662 100644 --- a/dmoj/executors/JAVA10.py +++ b/dmoj/executors/JAVA10.py @@ -4,7 +4,6 @@ class Executor(JavacExecutor): compiler = 'javac10' vm = 'java10' - name = 'JAVA10' jvm_regex = r'java-10-|openjdk10' test_program = """\ diff --git a/dmoj/executors/JAVA11.py b/dmoj/executors/JAVA11.py index e82a2c5ff..e9cee1ae2 100644 --- a/dmoj/executors/JAVA11.py +++ b/dmoj/executors/JAVA11.py @@ -4,7 +4,6 @@ class Executor(JavacExecutor): compiler = 'javac11' vm = 'java11' - name = 'JAVA11' jvm_regex = r'java-11-|openjdk11' test_program = """\ diff --git a/dmoj/executors/JAVA15.py b/dmoj/executors/JAVA15.py index eca59c11e..229eb8299 100644 --- a/dmoj/executors/JAVA15.py +++ b/dmoj/executors/JAVA15.py @@ -4,7 +4,6 @@ class Executor(JavacExecutor): compiler = 'javac15' vm = 'java15' - name = 'JAVA15' jvm_regex = r'java-15-|openjdk15' test_program = '''\ diff --git a/dmoj/executors/JAVA17.py b/dmoj/executors/JAVA17.py index 1b1674e0c..60256ef3d 100644 --- a/dmoj/executors/JAVA17.py +++ b/dmoj/executors/JAVA17.py @@ -4,7 +4,6 @@ class Executor(JavacExecutor): compiler = 'javac17' vm = 'java17' - name = 'JAVA17' jvm_regex = r'java-17-|openjdk17' test_program = '''\ diff --git a/dmoj/executors/JAVA8.py b/dmoj/executors/JAVA8.py index 93ba1f6a8..5c14f7058 100644 --- a/dmoj/executors/JAVA8.py +++ b/dmoj/executors/JAVA8.py @@ -4,7 +4,6 @@ class Executor(JavacExecutor): compiler = 'javac8' vm = 'java8' - name = 'JAVA8' jvm_regex = r'java-8-|jdk-8-|openjdk8|oracle-java8' test_program = """\ diff --git a/dmoj/executors/JAVA9.py b/dmoj/executors/JAVA9.py index 5c575256a..d19e8f084 100644 --- a/dmoj/executors/JAVA9.py +++ b/dmoj/executors/JAVA9.py @@ -4,7 +4,6 @@ class Executor(JavacExecutor): compiler = 'javac9' vm = 'java9' - name = 'JAVA9' jvm_regex = r'java-9-|openjdk9|oracle-java9' test_program = """\ diff --git a/dmoj/executors/KOTLIN.py b/dmoj/executors/KOTLIN.py index 9e61f7233..f7cb63e58 100644 --- a/dmoj/executors/KOTLIN.py +++ b/dmoj/executors/KOTLIN.py @@ -3,7 +3,6 @@ class Executor(JavaExecutor): - name = 'KOTLIN' ext = 'kt' compiler = 'kotlinc' diff --git a/dmoj/executors/LEAN4.py b/dmoj/executors/LEAN4.py new file mode 100644 index 000000000..d96e7b785 --- /dev/null +++ b/dmoj/executors/LEAN4.py @@ -0,0 +1,28 @@ +from dmoj.executors.compiled_executor import CompiledExecutor + + +class Executor(CompiledExecutor): + ext = 'lean' + command = 'lean' + test_program = """ +def main : IO Unit := do + let cin ← IO.getStdin + let line ← cin.getLine + IO.println line +""" + + def compile(self) -> str: + command = self.get_command() + assert command is not None + assert self._code is not None + c_file = f'{self.problem}.c' + + # lean -c f2.c f1.lean && leanc -o f3 f2.c -O3 -DNDEBUG + proc1 = self.create_compile_process([command, '-c', c_file, self._code]) + out1 = self.get_compile_output(proc1) + proc2 = self.create_compile_process([f'{command}c', '-o', self.problem, c_file, '-O3', '-DNDEBUG']) + out2 = self.get_compile_output(proc2) + + self.warning = b'\n'.join(filter(None, [out1, out2])) + self._executable = self.get_compiled_file() + return self._executable diff --git a/dmoj/executors/LUA.py b/dmoj/executors/LUA.py index 5613fa5ee..b86bd4fd1 100644 --- a/dmoj/executors/LUA.py +++ b/dmoj/executors/LUA.py @@ -3,7 +3,6 @@ class Executor(ScriptExecutor): ext = 'lua' - name = 'LUA' command = 'lua' command_paths = ['lua', 'lua5.3', 'lua5.2', 'lua5.1'] address_grace = 131072 diff --git a/dmoj/executors/MONOCS.py b/dmoj/executors/MONOCS.py index 0198a87ef..2c74dabaa 100644 --- a/dmoj/executors/MONOCS.py +++ b/dmoj/executors/MONOCS.py @@ -3,7 +3,6 @@ class Executor(MonoExecutor): ext = 'cs' - name = 'MONOCS' command = 'mono-csc' command_paths = ['mono-csc', 'mcs', 'dmcs', 'gmcs'] diff --git a/dmoj/executors/MONOFS.py b/dmoj/executors/MONOFS.py index d7cff692c..a225d19d7 100644 --- a/dmoj/executors/MONOFS.py +++ b/dmoj/executors/MONOFS.py @@ -3,7 +3,6 @@ class Executor(MonoExecutor): ext = 'fs' - name = 'MONOFS' command = 'fsharpc' compiler_time_limit = 20 diff --git a/dmoj/executors/MONOVB.py b/dmoj/executors/MONOVB.py index bad1aeb45..91a8183d4 100644 --- a/dmoj/executors/MONOVB.py +++ b/dmoj/executors/MONOVB.py @@ -5,7 +5,6 @@ class Executor(MonoExecutor): ext = 'vb' - name = 'MONOVB' command = 'mono-vbnc' compile_output_index = 0 diff --git a/dmoj/executors/NASM.py b/dmoj/executors/NASM.py index 2a9e7d685..af606deed 100644 --- a/dmoj/executors/NASM.py +++ b/dmoj/executors/NASM.py @@ -4,8 +4,6 @@ class Executor(PlatformX86Mixin, NASMExecutor): nasm_format = 'elf32' - name = 'NASM' - test_program = """\ section .text global _start diff --git a/dmoj/executors/NASM64.py b/dmoj/executors/NASM64.py index 2728ca157..883c8daa7 100644 --- a/dmoj/executors/NASM64.py +++ b/dmoj/executors/NASM64.py @@ -4,8 +4,6 @@ class Executor(PlatformX64Mixin, NASMExecutor): nasm_format = 'elf64' - name = 'NASM64' - test_program = """\ section .text global _start diff --git a/dmoj/executors/OBJC.py b/dmoj/executors/OBJC.py index a4a26d0e6..549f57999 100644 --- a/dmoj/executors/OBJC.py +++ b/dmoj/executors/OBJC.py @@ -11,7 +11,6 @@ class Executor(GCCExecutor): objc_flags: List[str] = [] objc_ldflags: List[str] = [] command = 'gobjc' - name = 'OBJC' address_grace = 131072 test_program = r""" diff --git a/dmoj/executors/OCAML.py b/dmoj/executors/OCAML.py index 26d61cf89..4d85dd005 100644 --- a/dmoj/executors/OCAML.py +++ b/dmoj/executors/OCAML.py @@ -7,7 +7,6 @@ # functioning opam + ocamlfind installation to work. class Executor(CompiledExecutor): ext = 'ml' - name = 'OCAML' command = 'ocamlfind' compiler_read_fs = [ RecursiveDir('~/.opam'), diff --git a/dmoj/executors/PAS.py b/dmoj/executors/PAS.py index 1eacaf596..f1509cb79 100644 --- a/dmoj/executors/PAS.py +++ b/dmoj/executors/PAS.py @@ -4,7 +4,6 @@ class Executor(CompiledExecutor): ext = 'pas' - name = 'PAS' command = 'fpc' compiler_read_fs = [ ExactFile('/etc/fpc.cfg'), diff --git a/dmoj/executors/PERL.py b/dmoj/executors/PERL.py index d5fdab350..ed94e1fcd 100644 --- a/dmoj/executors/PERL.py +++ b/dmoj/executors/PERL.py @@ -4,7 +4,6 @@ class Executor(ScriptExecutor): ext = 'pl' - name = 'PERL' command = 'perl' fs = [RecursiveDir('/etc/perl')] test_program = 'print<>' diff --git a/dmoj/executors/PHP.py b/dmoj/executors/PHP.py index da9e23fc4..4b7181f17 100644 --- a/dmoj/executors/PHP.py +++ b/dmoj/executors/PHP.py @@ -2,7 +2,6 @@ class Executor(ScriptExecutor): - name = 'PHP' ext = 'php' command = 'php' command_paths = ['php7', 'php5', 'php'] diff --git a/dmoj/executors/PIKE.py b/dmoj/executors/PIKE.py index 7cca7c7ed..0af9efe99 100644 --- a/dmoj/executors/PIKE.py +++ b/dmoj/executors/PIKE.py @@ -4,7 +4,6 @@ class Executor(ScriptExecutor): ext = 'pike' - name = 'PIKE' command = 'pike' syscalls = [ # Linux diff --git a/dmoj/executors/PRO.py b/dmoj/executors/PRO.py index 576b8b3a8..2cd17cfb1 100644 --- a/dmoj/executors/PRO.py +++ b/dmoj/executors/PRO.py @@ -3,7 +3,6 @@ class Executor(ScriptExecutor): ext = 'pl' - name = 'PRO' command = 'swipl' test_program = """ :- set_prolog_flag(verbose,silent). diff --git a/dmoj/executors/PY2.py b/dmoj/executors/PY2.py index 159f7cf3a..9d8804341 100644 --- a/dmoj/executors/PY2.py +++ b/dmoj/executors/PY2.py @@ -5,4 +5,3 @@ class Executor(PythonExecutor): command = 'python' command_paths = ['python2.7', 'python2', 'python'] test_program = "print __import__('sys').stdin.read()" - name = 'PY2' diff --git a/dmoj/executors/PY3.py b/dmoj/executors/PY3.py index 0fd243008..000a964b9 100644 --- a/dmoj/executors/PY3.py +++ b/dmoj/executors/PY3.py @@ -5,4 +5,3 @@ class Executor(PythonExecutor): command = 'python3' command_paths = ['python%s' % i for i in ['3.6', '3.5', '3.4', '3.3', '3.2', '3.1', '3']] test_program = "print(__import__('sys').stdin.read(), end='')" - name = 'PY3' diff --git a/dmoj/executors/PYPY.py b/dmoj/executors/PYPY.py index 2bbd63dac..3814d12b3 100644 --- a/dmoj/executors/PYPY.py +++ b/dmoj/executors/PYPY.py @@ -4,7 +4,6 @@ class Executor(PythonExecutor): - name = 'PYPY' command = 'pypy' test_program = "print __import__('sys').stdin.read()" _pypy_versions: List[Tuple[int, ...]] diff --git a/dmoj/executors/PYPY3.py b/dmoj/executors/PYPY3.py index 62938c4cd..91e27ab06 100644 --- a/dmoj/executors/PYPY3.py +++ b/dmoj/executors/PYPY3.py @@ -4,4 +4,3 @@ class Executor(PYPYExecutor): command = 'pypy3' test_program = "print(__import__('sys').stdin.read(), end='')" - name = 'PYPY3' diff --git a/dmoj/executors/RKT.py b/dmoj/executors/RKT.py index ac431be6d..e3c514490 100644 --- a/dmoj/executors/RKT.py +++ b/dmoj/executors/RKT.py @@ -1,11 +1,10 @@ -from dmoj.cptbox.filesystem_policies import ExactFile, RecursiveDir +from dmoj.cptbox.filesystem_policies import ExactDir, ExactFile, RecursiveDir from dmoj.executors.compiled_executor import CompiledExecutor class Executor(CompiledExecutor): ext = 'rkt' - name = 'RKT' - fs = [RecursiveDir('/etc/racket'), ExactFile('/etc/passwd')] + fs = [RecursiveDir('/etc/racket'), ExactFile('/etc/passwd'), ExactDir('/')] compiler_read_fs = [ RecursiveDir('/etc/racket'), RecursiveDir('~/.local/share/racket'), diff --git a/dmoj/executors/RUBY2.py b/dmoj/executors/RUBY2.py index a9a864ff7..454f7e867 100644 --- a/dmoj/executors/RUBY2.py +++ b/dmoj/executors/RUBY2.py @@ -7,7 +7,6 @@ class Executor(ScriptExecutor): ext = 'rb' - name = 'RUBY2' address_grace = 65536 test_program = 'puts gets' nproc = -1 diff --git a/dmoj/executors/RUST.py b/dmoj/executors/RUST.py index 33f1a9de6..fc6e89b2c 100644 --- a/dmoj/executors/RUST.py +++ b/dmoj/executors/RUST.py @@ -74,7 +74,6 @@ class Executor(CompiledExecutor): ext = 'rs' - name = 'RUST' command = 'cargo' test_program = HELLO_WORLD_PROGRAM compiler_time_limit = 20 diff --git a/dmoj/executors/SBCL.py b/dmoj/executors/SBCL.py index 4132c7d04..636640df7 100644 --- a/dmoj/executors/SBCL.py +++ b/dmoj/executors/SBCL.py @@ -11,7 +11,6 @@ # and proceeds to run. class Executor(NullStdoutMixin, CompiledExecutor): ext = 'cl' - name = 'SBCL' command = 'sbcl' syscalls = ['personality'] test_program = '(write-line (read-line))' diff --git a/dmoj/executors/SCALA.py b/dmoj/executors/SCALA.py index 1a5865b8a..54f2142f4 100644 --- a/dmoj/executors/SCALA.py +++ b/dmoj/executors/SCALA.py @@ -8,7 +8,6 @@ # Must emulate terminal, otherwise `scalac` hangs on a call to `stty` class Executor(JavaExecutor): - name = 'SCALA' ext = 'scala' compiler = 'scalac' diff --git a/dmoj/executors/SCM.py b/dmoj/executors/SCM.py index 34f40969f..e09b21431 100644 --- a/dmoj/executors/SCM.py +++ b/dmoj/executors/SCM.py @@ -4,7 +4,6 @@ class Executor(CompiledExecutor): ext = 'scm' - name = 'SCM' command = 'chicken-csc' command_paths = ['chicken-csc', 'csc'] compiler_read_fs = [ diff --git a/dmoj/executors/SCRATCH.py b/dmoj/executors/SCRATCH.py index d72e1d7e9..13636ea47 100644 --- a/dmoj/executors/SCRATCH.py +++ b/dmoj/executors/SCRATCH.py @@ -13,7 +13,6 @@ class Executor(ScriptExecutor): ext = 'sc3' - name = 'SCRATCH' command = 'scratch-run' nproc = -1 address_grace = 1048576 diff --git a/dmoj/executors/SED.py b/dmoj/executors/SED.py index 55b1261c6..65a5e021b 100644 --- a/dmoj/executors/SED.py +++ b/dmoj/executors/SED.py @@ -3,7 +3,6 @@ class Executor(ScriptExecutor): ext = 'sed' - name = 'SED' command = 'sed' test_program = 's/^//' diff --git a/dmoj/executors/SWIFT.py b/dmoj/executors/SWIFT.py index fcfda281f..379cf5b4a 100644 --- a/dmoj/executors/SWIFT.py +++ b/dmoj/executors/SWIFT.py @@ -4,7 +4,6 @@ class Executor(CompiledExecutor): ext = 'swift' - name = 'SWIFT' command = 'swiftc' compiler_read_fs = [ RecursiveDir('~/.cache'), diff --git a/dmoj/executors/TCL.py b/dmoj/executors/TCL.py index 0339f13c6..05021a5b5 100644 --- a/dmoj/executors/TCL.py +++ b/dmoj/executors/TCL.py @@ -5,7 +5,6 @@ class Executor(ScriptExecutor): ext = 'tcl' - name = 'TCL' nproc = -1 # TCL uses a bunch of threads internally address_grace = 131072 command = 'tclsh' diff --git a/dmoj/executors/TEXT.py b/dmoj/executors/TEXT.py index 01d9f747f..72a716406 100644 --- a/dmoj/executors/TEXT.py +++ b/dmoj/executors/TEXT.py @@ -3,7 +3,6 @@ class Executor(ScriptExecutor): ext = 'txt' - name = 'TEXT' command = 'cat' test_program = 'echo: Hello, World!\n' syscalls = ['fadvise64_64', 'fadvise64', 'posix_fadvise', 'arm_fadvise64_64'] diff --git a/dmoj/executors/TUR.py b/dmoj/executors/TUR.py index 0b1e3b912..48ef785a3 100644 --- a/dmoj/executors/TUR.py +++ b/dmoj/executors/TUR.py @@ -7,7 +7,6 @@ class Executor(CompiledExecutor): ext = 't' - name = 'TUR' command = 'tprolog' test_program = """\ var echo : string diff --git a/dmoj/executors/V8JS.py b/dmoj/executors/V8JS.py index 4c7c9dd30..e840dbf77 100644 --- a/dmoj/executors/V8JS.py +++ b/dmoj/executors/V8JS.py @@ -3,7 +3,6 @@ class Executor(ScriptExecutor): ext = 'js' - name = 'V8JS' command = 'v8dmoj' test_program = 'print(gets());' address_grace = 786432 diff --git a/dmoj/executors/ZIG.py b/dmoj/executors/ZIG.py index c2e8b2053..af8a3acfc 100644 --- a/dmoj/executors/ZIG.py +++ b/dmoj/executors/ZIG.py @@ -4,7 +4,6 @@ class Executor(CompiledExecutor): ext = 'zig' - name = 'ZIG' command = 'zig' compiler_time_limit = 30 compiler_read_fs = [ diff --git a/dmoj/executors/__init__.py b/dmoj/executors/__init__.py index e5088185f..868031d3b 100644 --- a/dmoj/executors/__init__.py +++ b/dmoj/executors/__init__.py @@ -15,6 +15,28 @@ executors: Dict[str, Any] = {} +def by_ext(ext: str) -> Any: + ext = ext.lower() + + for name, executor in executors.items(): + if name.lower() == ext: + return executor + + for executor in sorted(executors.values(), key=lambda executor: executor.Executor.name): + if executor.Executor.ext == ext: + return executor + + raise KeyError('no executor for extension "%s"' % ext) + + +def from_filename(filename: str) -> Any: + _, _, ext = filename.partition('.') + if not ext: + raise KeyError('invalid file name') + + return by_ext(ext) + + def get_available(): return get_available_modules( _reexecutor, os.path.dirname(__file__), only_executors, exclude_executors | _unsupported_executors diff --git a/dmoj/executors/asm_executor.py b/dmoj/executors/asm_executor.py index 5d0dcf8cf..b169c3c28 100644 --- a/dmoj/executors/asm_executor.py +++ b/dmoj/executors/asm_executor.py @@ -23,7 +23,6 @@ class ASMExecutor(CompiledExecutor): crt_post: List[str] platform_prefixes: Optional[List[str]] - name = 'ASM' ext = 'asm' def __init__(self, problem_id: str, source_code: bytes, *args, **kwargs) -> None: @@ -128,7 +127,6 @@ def autoconfig(cls) -> Tuple[Optional[Dict[str, Any]], bool, str, str]: class GASExecutor(ASMExecutor): - name = 'GAS' as_platform_flag: str def get_as_args(self, obj_file: str) -> List[str]: @@ -149,7 +147,6 @@ def get_find_first_mapping(cls) -> Optional[Dict[str, List[str]]]: class NASMExecutor(ASMExecutor): - name = 'NASM' as_name = 'nasm' nasm_format: str diff --git a/dmoj/executors/base_executor.py b/dmoj/executors/base_executor.py index 7d492fbfc..f562c0a37 100644 --- a/dmoj/executors/base_executor.py +++ b/dmoj/executors/base_executor.py @@ -89,7 +89,14 @@ UTF8_LOCALE = 'en_US.UTF-8' -class BaseExecutor: +class ExecutorMeta(type): + def __new__(mcs, name, bases, attrs) -> Any: + if '__module__' in attrs: + attrs['name'] = attrs['__module__'].split('.')[-1] + return super().__new__(mcs, name, bases, attrs) + + +class BaseExecutor(metaclass=ExecutorMeta): ext: str nproc = 0 command: Optional[str] = None diff --git a/dmoj/executors/compiled_executor.py b/dmoj/executors/compiled_executor.py index 41295c383..649bac082 100644 --- a/dmoj/executors/compiled_executor.py +++ b/dmoj/executors/compiled_executor.py @@ -1,4 +1,3 @@ -import abc import hashlib import os import pty @@ -14,7 +13,7 @@ from dmoj.cptbox.syscalls import * from dmoj.cptbox.tracer import AdvancedDebugger from dmoj.error import CompileError, OutputLimitExceeded -from dmoj.executors.base_executor import BASE_FILESYSTEM, BASE_WRITE_FILESYSTEM, BaseExecutor +from dmoj.executors.base_executor import BASE_FILESYSTEM, BASE_WRITE_FILESYSTEM, BaseExecutor, ExecutorMeta from dmoj.judgeenv import env from dmoj.utils.communicate import safe_communicate from dmoj.utils.error import print_protection_fault @@ -31,8 +30,8 @@ # Contract: if cached=True is specified and an entry exists in the cache, # `create_files` and `compile` will not be run, and `_executable` will be loaded # from the cache. -class _CompiledExecutorMeta(abc.ABCMeta): - def __call__(self, *args, **kwargs) -> 'CompiledExecutor': +class _CompiledExecutorMeta(ExecutorMeta): + def __call__(cls, *args, **kwargs) -> 'CompiledExecutor': is_cached: bool = kwargs.pop('cached', False) if is_cached: kwargs['dest_dir'] = env.compiled_binary_cache_dir @@ -100,7 +99,6 @@ def __init__(self, tmpdir, read_fs, write_fs, *args, **kwargs): sys_chdir: self.check_file_access('chdir', 0), sys_chmod: self.check_file_access('chmod', 0, is_write=True), sys_utimensat: self.do_utimensat, - sys_statx: self.check_file_access_at('statx'), sys_umask: ALLOW, sys_flock: ALLOW, sys_fsync: ALLOW, diff --git a/dmoj/executors/gcc_executor.py b/dmoj/executors/gcc_executor.py index 97dcb576a..1443fae5c 100644 --- a/dmoj/executors/gcc_executor.py +++ b/dmoj/executors/gcc_executor.py @@ -20,7 +20,6 @@ class GCCExecutor(SingleDigitVersionMixin, CompiledExecutor): defines: List[str] = [] flags: List[str] = [] - name = 'GCC' arch = 'gcc_target_arch' has_color = False diff --git a/dmoj/executors/mono_executor.py b/dmoj/executors/mono_executor.py index d47a8e4be..fbb70e2d4 100644 --- a/dmoj/executors/mono_executor.py +++ b/dmoj/executors/mono_executor.py @@ -19,7 +19,6 @@ def _cpu_time_exceeded(self): class MonoExecutor(CompiledExecutor): - name = 'MONO' nproc = -1 address_grace = 262144 # Give Mono access to 64mb more data segment memory. This is a hack, for diff --git a/dmoj/utils/helper_files.py b/dmoj/utils/helper_files.py index 8e393a3dd..2bd3dd48f 100644 --- a/dmoj/utils/helper_files.py +++ b/dmoj/utils/helper_files.py @@ -33,7 +33,7 @@ def compile_with_auxiliary_files( compiler_time_limit: Optional[int] = None, unbuffered: bool = False, ) -> 'BaseExecutor': - from dmoj.executors import executors + from dmoj import executors from dmoj.executors.compiled_executor import CompiledExecutor sources = {} @@ -42,23 +42,33 @@ def compile_with_auxiliary_files( with open(filename, 'rb') as f: sources[os.path.basename(filename)] = f.read() - def find_runtime(languages): + def find_runtime(*languages): for grader in languages: - if grader in executors: + if grader in executors.executors: return grader return None use_cpp = any(map(lambda name: os.path.splitext(name)[1] in ['.cpp', '.cc'], filenames)) use_c = any(map(lambda name: os.path.splitext(name)[1] in ['.c'], filenames)) - if lang is None: - best_choices = ('CPP20', 'CPP17', 'CPP14', 'CPP11', 'CPP03') if use_cpp else ('C11', 'C') - lang = find_runtime(best_choices) - - executor = executors.get(lang) - if not executor: - raise IOError(f'could not find an appropriate {lang} executor') - - executor = executor.Executor + if not lang: + if use_cpp: + lang = find_runtime('CPP20', 'CPP17', 'CPP14', 'CPP11', 'CPP03') + elif use_c: + lang = find_runtime('C11', 'C') + + # TODO: remove above code once `from_filename` is smart enough to + # prioritize newer versions of runtimes + if not lang: + for filename in filenames: + try: + lang = executors.from_filename(filename).Executor.name + except KeyError: + continue + + if not lang: + raise IOError('could not find an appropriate executor') + + executor = executors.executors[lang].Executor kwargs = {'fs': executor.fs + [RecursiveDir(tempfile.gettempdir())]} diff --git a/testsuite/generator_python/gen.py b/testsuite/generator_python/gen.py2 similarity index 100% rename from testsuite/generator_python/gen.py rename to testsuite/generator_python/gen.py2 diff --git a/testsuite/generator_python/init.yml b/testsuite/generator_python/init.yml index 13096039d..ff5b3e15b 100644 --- a/testsuite/generator_python/init.yml +++ b/testsuite/generator_python/init.yml @@ -1,6 +1,4 @@ -generator: - language: PY3 - source: gen.py +generator: gen.py2 test_cases: - {generator_args: [1, 2], points: 1} - {generator_args: [10, 20], points: 1}