@jpetit/toolkit 3.0.22 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/prompts/creators/create-solution.tpl.txt +10 -0
- package/assets/prompts/creators/create-statement.tpl.txt +21 -0
- package/assets/prompts/creators/create-translation.tpl.txt +5 -0
- package/assets/prompts/creators/private-test-cases.txt +6 -0
- package/assets/prompts/creators/sample-test-cases.txt +6 -0
- package/assets/prompts/creators/system-prompt.txt +2 -0
- package/assets/prompts/examples/statement-coda.tex +7 -0
- package/assets/prompts/examples/statement.tex +19 -0
- package/assets/prompts/generators/efficiency.md +41 -0
- package/assets/prompts/generators/hard.md +47 -0
- package/assets/prompts/generators/random.md +39 -0
- package/assets/prompts/proglangs/cc.md +3 -0
- package/assets/prompts/proglangs/py.md +40 -0
- package/package.json +48 -11
- package/toolkit/index.ts +32 -21
- package/lib/ai.ts +0 -144
- package/lib/cleaner.ts +0 -66
- package/lib/compilers/base.ts +0 -103
- package/lib/compilers/clojure.ts +0 -76
- package/lib/compilers/gcc.ts +0 -68
- package/lib/compilers/ghc.ts +0 -75
- package/lib/compilers/gxx.ts +0 -68
- package/lib/compilers/index.ts +0 -72
- package/lib/compilers/python3.ts +0 -105
- package/lib/compilers/run-haskell.ts +0 -113
- package/lib/compilers/run-python.ts +0 -109
- package/lib/data.ts +0 -19
- package/lib/doctor.ts +0 -158
- package/lib/generate.ts +0 -329
- package/lib/maker.ts +0 -700
- package/lib/settings.ts +0 -42
- package/lib/tui.ts +0 -142
- package/lib/types.ts +0 -20
- package/lib/utils.ts +0 -133
- package/toolkit/ai.ts +0 -30
- package/toolkit/clean.ts +0 -37
- package/toolkit/compilers.ts +0 -29
- package/toolkit/create-jutge-ai.ts +0 -101
- package/toolkit/create-template.ts +0 -55
- package/toolkit/create-wizard.ts +0 -6
- package/toolkit/create.ts +0 -65
- package/toolkit/doctor.ts +0 -18
- package/toolkit/generate.ts +0 -116
- package/toolkit/init.ts +0 -56
- package/toolkit/make.ts +0 -118
- package/toolkit/verify.ts +0 -19
package/lib/compilers/base.ts
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import tui from '../tui'
|
|
2
|
-
import { execa } from 'execa'
|
|
3
|
-
import { exists, rm } from 'fs/promises'
|
|
4
|
-
import { join, sep } from 'path'
|
|
5
|
-
import { readText } from '../utils'
|
|
6
|
-
import type { Handler } from '../types'
|
|
7
|
-
|
|
8
|
-
export type CompilerInfo = {
|
|
9
|
-
compiler_id: string
|
|
10
|
-
name: string
|
|
11
|
-
language: string
|
|
12
|
-
version: string
|
|
13
|
-
flags1: string
|
|
14
|
-
flags2: string
|
|
15
|
-
extension: string
|
|
16
|
-
type: string
|
|
17
|
-
warning: string
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export abstract class Compiler {
|
|
21
|
-
abstract id(): string
|
|
22
|
-
|
|
23
|
-
abstract name(): string
|
|
24
|
-
|
|
25
|
-
abstract type(): string
|
|
26
|
-
|
|
27
|
-
abstract language(): string
|
|
28
|
-
|
|
29
|
-
abstract version(): Promise<string>
|
|
30
|
-
|
|
31
|
-
abstract flags1(): string
|
|
32
|
-
|
|
33
|
-
abstract flags2(): string
|
|
34
|
-
|
|
35
|
-
abstract extension(): string
|
|
36
|
-
|
|
37
|
-
warning(): string {
|
|
38
|
-
return ''
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async available(): Promise<boolean> {
|
|
42
|
-
const version = await this.version()
|
|
43
|
-
return version !== 'not found'
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async info(): Promise<CompilerInfo> {
|
|
47
|
-
return {
|
|
48
|
-
compiler_id: this.id(),
|
|
49
|
-
name: this.name(),
|
|
50
|
-
language: this.language(),
|
|
51
|
-
version: await this.version(),
|
|
52
|
-
flags1: this.flags1(),
|
|
53
|
-
flags2: this.flags2(),
|
|
54
|
-
extension: this.extension(),
|
|
55
|
-
type: this.type(),
|
|
56
|
-
warning: this.warning(),
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
abstract compile(handler: Handler, directory: string, sourcePath: string): Promise<void>
|
|
61
|
-
|
|
62
|
-
// Default implementation of execute for compiled languages
|
|
63
|
-
async execute(
|
|
64
|
-
handler: Handler,
|
|
65
|
-
directory: string,
|
|
66
|
-
sourcePath: string,
|
|
67
|
-
inputPath: string,
|
|
68
|
-
outputPath: string,
|
|
69
|
-
): Promise<void> {
|
|
70
|
-
const executablePath = `solution.${this.extension()}.exe`
|
|
71
|
-
if (!(await exists(join(directory, executablePath)))) {
|
|
72
|
-
throw new Error(`Executable file ${executablePath} does not exist in directory ${directory}`)
|
|
73
|
-
}
|
|
74
|
-
// TODO: check in windows
|
|
75
|
-
const relativeExecutablePath = `.${sep}${executablePath}` // force prepending ./ to make it work
|
|
76
|
-
const fullInputPath = join(directory, inputPath)
|
|
77
|
-
const fullOutputPath = join(directory, outputPath)
|
|
78
|
-
await rm(fullOutputPath, { force: true })
|
|
79
|
-
const input = await readText(fullInputPath)
|
|
80
|
-
|
|
81
|
-
tui.command(`${relativeExecutablePath} < ${inputPath} > ${outputPath}`)
|
|
82
|
-
|
|
83
|
-
const { exitCode } = await execa({
|
|
84
|
-
reject: false,
|
|
85
|
-
input,
|
|
86
|
-
stdout: { file: fullOutputPath },
|
|
87
|
-
stderr: 'inherit',
|
|
88
|
-
cwd: directory,
|
|
89
|
-
})`${relativeExecutablePath}`
|
|
90
|
-
|
|
91
|
-
if (exitCode !== 0) throw new Error(`Execution failed for ${executablePath} with exit code ${exitCode}`)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
protected async getVersion(cmd: string, lineIndex: number): Promise<string> {
|
|
95
|
-
try {
|
|
96
|
-
const { stdout } = await execa`${cmd.split(' ')}`
|
|
97
|
-
const lines = stdout.split('\n')
|
|
98
|
-
return lines[lineIndex]?.trim() || 'Unknown version'
|
|
99
|
-
} catch {
|
|
100
|
-
return 'not found'
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
}
|
package/lib/compilers/clojure.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import tui from '../tui'
|
|
2
|
-
import { type Handler } from '../types'
|
|
3
|
-
import { Compiler } from './base'
|
|
4
|
-
import { execa } from 'execa'
|
|
5
|
-
import { join } from 'path'
|
|
6
|
-
import { nothing, readText } from 'lib/utils'
|
|
7
|
-
import { rm } from 'fs/promises'
|
|
8
|
-
|
|
9
|
-
export class Clojure_Compiler extends Compiler {
|
|
10
|
-
id(): string {
|
|
11
|
-
return 'Clojure'
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
name(): string {
|
|
15
|
-
return 'Clojure'
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
type(): string {
|
|
19
|
-
return 'vm'
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
language(): string {
|
|
23
|
-
return 'Clojure'
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async version(): Promise<string> {
|
|
27
|
-
return await this.getVersion('clj --version', 0)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
flags1(): string {
|
|
31
|
-
return ''
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
flags2(): string {
|
|
35
|
-
return ''
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
extension(): string {
|
|
39
|
-
return 'clj'
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async compile(handler: Handler, directory: string, sourcePath: string): Promise<void> {
|
|
43
|
-
await nothing()
|
|
44
|
-
|
|
45
|
-
if (handler.source_modifier !== 'none') {
|
|
46
|
-
throw new Error(`source modifier not implemented`)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
tui.warning(`No compilation available for Clojure`)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
override async execute(
|
|
53
|
-
handler: Handler,
|
|
54
|
-
directory: string,
|
|
55
|
-
sourcePath: string,
|
|
56
|
-
inputPath: string,
|
|
57
|
-
outputPath: string,
|
|
58
|
-
): Promise<void> {
|
|
59
|
-
const fullInputPath = join(directory, inputPath)
|
|
60
|
-
const fullOutputPath = join(directory, outputPath)
|
|
61
|
-
await rm(fullOutputPath, { force: true })
|
|
62
|
-
const input = await readText(fullInputPath)
|
|
63
|
-
|
|
64
|
-
tui.command(`clj -M ${sourcePath} < ${inputPath} > ${outputPath}`)
|
|
65
|
-
|
|
66
|
-
const { exitCode } = await execa({
|
|
67
|
-
reject: false,
|
|
68
|
-
input,
|
|
69
|
-
stdout: { file: fullOutputPath },
|
|
70
|
-
stderr: 'inherit',
|
|
71
|
-
cwd: directory,
|
|
72
|
-
})`clj -M ${sourcePath}`
|
|
73
|
-
|
|
74
|
-
if (exitCode !== 0) throw new Error(`Execution failed for ${sourcePath}`)
|
|
75
|
-
}
|
|
76
|
-
}
|
package/lib/compilers/gcc.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { type Handler } from '../types'
|
|
2
|
-
import tui from '../tui'
|
|
3
|
-
import { Compiler } from './base'
|
|
4
|
-
import { rm, exists } from 'fs/promises'
|
|
5
|
-
import { join } from 'path'
|
|
6
|
-
import { execa } from 'execa'
|
|
7
|
-
|
|
8
|
-
export class GCC_Compiler extends Compiler {
|
|
9
|
-
id(): string {
|
|
10
|
-
return 'GCC'
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
name(): string {
|
|
14
|
-
return 'GNU C Compiler'
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
type(): string {
|
|
18
|
-
return 'compiler'
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
language(): string {
|
|
22
|
-
return 'C'
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async version(): Promise<string> {
|
|
26
|
-
return await this.getVersion('gcc --version', 0)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
flags1(): string {
|
|
30
|
-
return '-D_JUDGE_ -O2 -DNDEBUG -Wall -Wextra -Wno-sign-compare'
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
flags2(): string {
|
|
34
|
-
return ''
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
extension(): string {
|
|
38
|
-
return 'c'
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async compile(handler: Handler, directory: string, sourcePath: string): Promise<void> {
|
|
42
|
-
const exePath = sourcePath + '.exe'
|
|
43
|
-
const fullExePath = join(directory, exePath)
|
|
44
|
-
await rm(fullExePath, { force: true })
|
|
45
|
-
|
|
46
|
-
if (handler.source_modifier === 'none') {
|
|
47
|
-
tui.command(`gcc ${this.flags1()} ${sourcePath} -o ${exePath}`)
|
|
48
|
-
await execa({
|
|
49
|
-
reject: false,
|
|
50
|
-
stderr: 'inherit',
|
|
51
|
-
stdout: 'inherit',
|
|
52
|
-
cwd: directory,
|
|
53
|
-
})`gcc ${this.flags1().split(' ')} ${sourcePath} -o ${exePath}`
|
|
54
|
-
} else if (handler.source_modifier === 'no_main') {
|
|
55
|
-
tui.command(`gcc ${this.flags1()} ${sourcePath} main.c -o ${exePath}`)
|
|
56
|
-
await execa({
|
|
57
|
-
reject: false,
|
|
58
|
-
stderr: 'inherit',
|
|
59
|
-
stdout: 'inherit',
|
|
60
|
-
cwd: directory,
|
|
61
|
-
})`gcc ${this.flags1().split(' ')} ${sourcePath} main.c -o ${exePath}`
|
|
62
|
-
} else {
|
|
63
|
-
throw new Error(`Unknown source modifier: ${handler.source_modifier}`)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (!(await exists(fullExePath))) throw new Error(`Compilation failed for ${sourcePath}`)
|
|
67
|
-
}
|
|
68
|
-
}
|
package/lib/compilers/ghc.ts
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { execa } from 'execa'
|
|
2
|
-
import { exists, rm } from 'fs/promises'
|
|
3
|
-
import { concatText } from '../utils'
|
|
4
|
-
import { join } from 'path'
|
|
5
|
-
import tui from '../tui'
|
|
6
|
-
import { type Handler } from '../types'
|
|
7
|
-
import { Compiler } from './base'
|
|
8
|
-
|
|
9
|
-
export class GHC_Compiler extends Compiler {
|
|
10
|
-
id(): string {
|
|
11
|
-
return 'GHC'
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
name(): string {
|
|
15
|
-
return 'GHC'
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
type(): string {
|
|
19
|
-
return 'compiler'
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
language(): string {
|
|
23
|
-
return 'Haskell'
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async version(): Promise<string> {
|
|
27
|
-
return await this.getVersion('ghc --version', 0)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
flags1(): string {
|
|
31
|
-
return '-O3'
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
flags2(): string {
|
|
35
|
-
return '-O3'
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
extension(): string {
|
|
39
|
-
return 'hs'
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async compile(handler: Handler, directory: string, sourcePath: string): Promise<void> {
|
|
43
|
-
const outputPath = sourcePath + '.exe'
|
|
44
|
-
const fullOutputPath = join(directory, outputPath)
|
|
45
|
-
await rm(fullOutputPath, { force: true })
|
|
46
|
-
|
|
47
|
-
if (handler.source_modifier === 'none') {
|
|
48
|
-
tui.command(`ghc ${this.flags1()} ${sourcePath} -o ${outputPath}`)
|
|
49
|
-
await execa({
|
|
50
|
-
reject: false,
|
|
51
|
-
stderr: 'inherit',
|
|
52
|
-
stdout: 'inherit',
|
|
53
|
-
cwd: directory,
|
|
54
|
-
})`ghc ${this.flags1().split(' ')} ${sourcePath} -o ${outputPath}`
|
|
55
|
-
} else if (handler.source_modifier === 'no_main') {
|
|
56
|
-
const wrapperPath = `wrapper-${sourcePath}`
|
|
57
|
-
|
|
58
|
-
tui.command(`concat ${sourcePath} and main.hs into ${wrapperPath}`, { italic: true })
|
|
59
|
-
await concatText([join(directory, sourcePath), join(directory, 'main.hs')], join(directory, wrapperPath))
|
|
60
|
-
|
|
61
|
-
tui.command(`ghc ${this.flags1()} ${wrapperPath} -o ${outputPath}`)
|
|
62
|
-
|
|
63
|
-
await execa({
|
|
64
|
-
reject: false,
|
|
65
|
-
stderr: 'inherit',
|
|
66
|
-
stdout: 'inherit',
|
|
67
|
-
cwd: directory,
|
|
68
|
-
})`ghc ${this.flags1().split(' ')} ${wrapperPath} -o ${outputPath}`
|
|
69
|
-
} else {
|
|
70
|
-
throw new Error(`Unknown source modifier: ${handler.source_modifier}`)
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (!(await exists(fullOutputPath))) throw new Error(`Compilation failed for ${sourcePath}`)
|
|
74
|
-
}
|
|
75
|
-
}
|
package/lib/compilers/gxx.ts
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { execa } from 'execa'
|
|
2
|
-
import { exists, rm } from 'fs/promises'
|
|
3
|
-
import { join } from 'path'
|
|
4
|
-
import tui from '../tui'
|
|
5
|
-
import { type Handler } from '../types'
|
|
6
|
-
import { Compiler } from './base'
|
|
7
|
-
|
|
8
|
-
export class GXX_Compiler extends Compiler {
|
|
9
|
-
id(): string {
|
|
10
|
-
return 'GXX'
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
name(): string {
|
|
14
|
-
return 'GNU C++ Compiler'
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
type(): string {
|
|
18
|
-
return 'compiler'
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
language(): string {
|
|
22
|
-
return 'C++'
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async version(): Promise<string> {
|
|
26
|
-
return await this.getVersion('g++ --version', 0)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
flags1(): string {
|
|
30
|
-
return '-std=c++17 -D_JUDGE_ -O2 -DNDEBUG -Wall -Wextra -Wno-sign-compare -Wshadow'
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
flags2(): string {
|
|
34
|
-
return '-std=c++17 -D_JUDGE_ -O2 -DNDEBUG -Wall -Wextra -Wno-sign-compare -Wshadow'
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
extension(): string {
|
|
38
|
-
return 'cc'
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async compile(handler: Handler, directory: string, sourcePath: string): Promise<void> {
|
|
42
|
-
const outputPath = sourcePath + '.exe'
|
|
43
|
-
const fullOutputPath = join(directory, outputPath)
|
|
44
|
-
await rm(fullOutputPath, { force: true })
|
|
45
|
-
|
|
46
|
-
if (handler.source_modifier === 'none') {
|
|
47
|
-
tui.command(`g++ ${this.flags1()} ${sourcePath} -o ${outputPath}`)
|
|
48
|
-
await execa({
|
|
49
|
-
reject: false,
|
|
50
|
-
stderr: 'inherit',
|
|
51
|
-
stdout: 'inherit',
|
|
52
|
-
cwd: directory,
|
|
53
|
-
})`g++ ${this.flags1().split(' ')} ${sourcePath} -o ${outputPath}`
|
|
54
|
-
} else if (handler.source_modifier === 'no_main') {
|
|
55
|
-
tui.command(`g++ ${this.flags1()} ${sourcePath} main.cc -o ${outputPath}`)
|
|
56
|
-
await execa({
|
|
57
|
-
reject: false,
|
|
58
|
-
stderr: 'inherit',
|
|
59
|
-
stdout: 'inherit',
|
|
60
|
-
cwd: directory,
|
|
61
|
-
})`g++ ${this.flags1().split(' ')} ${sourcePath} main.cc -o ${outputPath}`
|
|
62
|
-
} else {
|
|
63
|
-
throw new Error(`Unknown source modifier: ${handler.source_modifier}`)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (!(await exists(fullOutputPath))) throw new Error(`Compilation failed for ${sourcePath}`)
|
|
67
|
-
}
|
|
68
|
-
}
|
package/lib/compilers/index.ts
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import { nothing } from '../utils'
|
|
2
|
-
import { Compiler, type CompilerInfo } from './base'
|
|
3
|
-
import { GCC_Compiler } from './gcc'
|
|
4
|
-
import { GXX_Compiler } from './gxx'
|
|
5
|
-
import { Python3_Compiler } from './python3'
|
|
6
|
-
import { GHC_Compiler } from './ghc'
|
|
7
|
-
import { Clojure_Compiler } from './clojure'
|
|
8
|
-
import { RunPython_Compiler } from './run-python'
|
|
9
|
-
import { RunHaskell_Compiler } from './run-haskell'
|
|
10
|
-
|
|
11
|
-
const compilersRegistryById: Record<string, new () => Compiler> = {
|
|
12
|
-
C: GCC_Compiler,
|
|
13
|
-
'C++': GXX_Compiler,
|
|
14
|
-
Python3: Python3_Compiler,
|
|
15
|
-
Haskell: GHC_Compiler,
|
|
16
|
-
Clojure: Clojure_Compiler,
|
|
17
|
-
RunPython: RunPython_Compiler,
|
|
18
|
-
RunHaskell: RunHaskell_Compiler,
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const compilersRegistryByExtension: Record<string, new () => Compiler> = {
|
|
22
|
-
c: GCC_Compiler,
|
|
23
|
-
cc: GXX_Compiler,
|
|
24
|
-
py: Python3_Compiler,
|
|
25
|
-
hs: GHC_Compiler,
|
|
26
|
-
clj: Clojure_Compiler,
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function getCompilerById(id: string): Compiler {
|
|
30
|
-
const CompilerClass = compilersRegistryById[id]
|
|
31
|
-
if (!CompilerClass) throw new Error(`Compiler '${id}' is not defined`)
|
|
32
|
-
const compilerInstance = new CompilerClass()
|
|
33
|
-
return compilerInstance
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function getCompilerByExtension(extension: string): Compiler {
|
|
37
|
-
const CompilerClass = compilersRegistryByExtension[extension]
|
|
38
|
-
if (!CompilerClass) throw new Error(`No compiler defined for extension '.${extension}'`)
|
|
39
|
-
const compilerInstance = new CompilerClass()
|
|
40
|
-
return compilerInstance
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export async function getDefinedCompilerIds(): Promise<string[]> {
|
|
44
|
-
await nothing()
|
|
45
|
-
return Object.keys(compilersRegistryById)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export async function getAvailableCompilers(): Promise<string[]> {
|
|
49
|
-
const available: string[] = []
|
|
50
|
-
for (const id of Object.keys(compilersRegistryById)) {
|
|
51
|
-
const CompilerClass = compilersRegistryById[id]!
|
|
52
|
-
const compilerInstance = new CompilerClass()
|
|
53
|
-
if (await compilerInstance.available()) {
|
|
54
|
-
available.push(id)
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return available
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
export async function getCompilerInfo(id: string): Promise<CompilerInfo> {
|
|
61
|
-
const compilerInstance = getCompilerById(id)
|
|
62
|
-
if (!compilerInstance) throw new Error(`Compiler '${id}' is not defined`)
|
|
63
|
-
return await compilerInstance.info()
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
export async function getCompilersInfo(): Promise<Record<string, CompilerInfo>> {
|
|
67
|
-
const infos: Record<string, CompilerInfo> = {}
|
|
68
|
-
for (const id of Object.keys(compilersRegistryById)) {
|
|
69
|
-
infos[id] = await getCompilerInfo(id)
|
|
70
|
-
}
|
|
71
|
-
return infos
|
|
72
|
-
}
|
package/lib/compilers/python3.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { execa } from 'execa'
|
|
2
|
-
import { exists, rm } from 'fs/promises'
|
|
3
|
-
import { join } from 'path'
|
|
4
|
-
import tui from '../tui'
|
|
5
|
-
import type { Handler } from '../types'
|
|
6
|
-
import { readText, writeText } from '../utils'
|
|
7
|
-
import { Compiler } from './base'
|
|
8
|
-
|
|
9
|
-
export class Python3_Compiler extends Compiler {
|
|
10
|
-
id(): string {
|
|
11
|
-
return 'Python3'
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
name(): string {
|
|
15
|
-
return 'Python3'
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
type(): string {
|
|
19
|
-
return 'interpreter'
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
language(): string {
|
|
23
|
-
return 'Python'
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async version(): Promise<string> {
|
|
27
|
-
return await this.getVersion('python3 --version', 0)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
flags1(): string {
|
|
31
|
-
return ''
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
flags2(): string {
|
|
35
|
-
return ''
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
extension(): string {
|
|
39
|
-
return 'py'
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async compile(handler: Handler, directory: string, sourcePath: string): Promise<void> {
|
|
43
|
-
const wrapperPath = `wrapper-${sourcePath}`
|
|
44
|
-
const fullWrapperPath = join(directory, wrapperPath)
|
|
45
|
-
const fullSourcePath = join(directory, sourcePath)
|
|
46
|
-
const source = await readText(fullSourcePath)
|
|
47
|
-
|
|
48
|
-
tui.command(`wrap ${sourcePath} to ${wrapperPath}`, { italic: true })
|
|
49
|
-
let wrapperSource: string
|
|
50
|
-
if (handler.source_modifier === 'none') {
|
|
51
|
-
wrapperSource = source
|
|
52
|
-
.replace('import turtle', 'import turtle_pil as turtle')
|
|
53
|
-
.replace('from turtle import', 'from turtle_pil import')
|
|
54
|
-
} else if (handler.source_modifier === 'no_main' || handler.source_modifier === 'structs') {
|
|
55
|
-
const main = await readText(join(directory, 'main.py'))
|
|
56
|
-
wrapperSource = source + '\n\n\n' + main
|
|
57
|
-
} else {
|
|
58
|
-
throw new Error(`Unknown source modifier: ${handler.source_modifier as string}`)
|
|
59
|
-
}
|
|
60
|
-
await writeText(fullWrapperPath, wrapperSource)
|
|
61
|
-
|
|
62
|
-
tui.command(`python3 -m py_compile ${wrapperPath}`)
|
|
63
|
-
|
|
64
|
-
const { exitCode } = await execa({
|
|
65
|
-
reject: false,
|
|
66
|
-
stderr: 'inherit',
|
|
67
|
-
stdout: 'inherit',
|
|
68
|
-
cwd: directory,
|
|
69
|
-
})`python3 -m py_compile ${wrapperPath}`
|
|
70
|
-
|
|
71
|
-
if (exitCode !== 0) throw new Error(`Compilation failed for ${sourcePath}`)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
override async execute(
|
|
75
|
-
handler: Handler,
|
|
76
|
-
directory: string,
|
|
77
|
-
sourcePath: string,
|
|
78
|
-
inputPath: string,
|
|
79
|
-
outputPath: string,
|
|
80
|
-
): Promise<void> {
|
|
81
|
-
const wrapperPath = `wrapper-${sourcePath}`
|
|
82
|
-
const fullWrapperPath = join(directory, wrapperPath)
|
|
83
|
-
|
|
84
|
-
if (!(await exists(join(directory, wrapperPath)))) {
|
|
85
|
-
throw new Error(`Executable file ${wrapperPath} does not exist in directory ${directory}`)
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const fullInputPath = join(directory, inputPath)
|
|
89
|
-
const fullOutputPath = join(directory, outputPath)
|
|
90
|
-
await rm(fullOutputPath, { force: true })
|
|
91
|
-
const input = await readText(fullInputPath)
|
|
92
|
-
|
|
93
|
-
tui.command(`python3 ${wrapperPath} < ${inputPath} > ${outputPath}`)
|
|
94
|
-
|
|
95
|
-
const { exitCode } = await execa({
|
|
96
|
-
reject: false,
|
|
97
|
-
input,
|
|
98
|
-
stdout: { file: fullOutputPath },
|
|
99
|
-
stderr: 'inherit',
|
|
100
|
-
cwd: directory,
|
|
101
|
-
})`python3 ${wrapperPath}`
|
|
102
|
-
|
|
103
|
-
if (exitCode !== 0) throw new Error(`Execution failed for ${wrapperPath}`)
|
|
104
|
-
}
|
|
105
|
-
}
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import { execa } from 'execa'
|
|
2
|
-
import { rm } from 'fs/promises'
|
|
3
|
-
import { join } from 'path'
|
|
4
|
-
import tui from '../tui'
|
|
5
|
-
import type { Handler } from '../types'
|
|
6
|
-
import { readText, writeText } from '../utils'
|
|
7
|
-
import { Compiler } from './base'
|
|
8
|
-
|
|
9
|
-
export class RunHaskell_Compiler extends Compiler {
|
|
10
|
-
id(): string {
|
|
11
|
-
return 'RunHaskell'
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
name(): string {
|
|
15
|
-
return 'RunHaskell'
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
type(): string {
|
|
19
|
-
return 'compiler'
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
language(): string {
|
|
23
|
-
return 'Haskell'
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
async version(): Promise<string> {
|
|
27
|
-
return await this.getVersion('ghc --version', 0)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
flags1(): string {
|
|
31
|
-
return ''
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
flags2(): string {
|
|
35
|
-
return ''
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
extension(): string {
|
|
39
|
-
return 'hs'
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async compile(handler: Handler, directory: string, sourcePath: string): Promise<void> {
|
|
43
|
-
if (handler.source_modifier !== 'none') {
|
|
44
|
-
throw new Error(`Unknown source modifier: ${handler.source_modifier as string}`)
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// ghci -e ':q' solution.hs
|
|
48
|
-
// This will load and typecheck the file, then immediately quit.
|
|
49
|
-
// If there are compilation errors, they'll be shown. If it loads successfully and just exits, the code compiles.
|
|
50
|
-
// With execa, it seems we have to remove the quotes around :q
|
|
51
|
-
|
|
52
|
-
tui.command(`ghci -e ':q' ${sourcePath}`)
|
|
53
|
-
|
|
54
|
-
const { exitCode } = await execa({
|
|
55
|
-
reject: false,
|
|
56
|
-
stderr: 'inherit',
|
|
57
|
-
stdout: 'inherit',
|
|
58
|
-
cwd: directory,
|
|
59
|
-
})`ghci -e :q ${sourcePath}`
|
|
60
|
-
|
|
61
|
-
if (exitCode !== 0) throw new Error(`Compilation failed for ${sourcePath}`)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
override async execute(
|
|
65
|
-
handler: Handler,
|
|
66
|
-
directory: string,
|
|
67
|
-
sourcePath: string,
|
|
68
|
-
inputPath: string,
|
|
69
|
-
outputPath: string,
|
|
70
|
-
): Promise<void> {
|
|
71
|
-
const mergedPath = `solution-${inputPath}.hs.exe`
|
|
72
|
-
|
|
73
|
-
tui.command(`Merging solution.hs and ${inputPath} into ${mergedPath}`, { italic: true })
|
|
74
|
-
await this.mergeScripts(directory, 'solution.hs', inputPath, mergedPath)
|
|
75
|
-
|
|
76
|
-
const fullOutputPath = join(directory, outputPath)
|
|
77
|
-
|
|
78
|
-
await rm(fullOutputPath, { force: true })
|
|
79
|
-
|
|
80
|
-
tui.command(`runhaskell ${mergedPath} > ${outputPath}`)
|
|
81
|
-
|
|
82
|
-
const { exitCode } = await execa({
|
|
83
|
-
reject: false,
|
|
84
|
-
stdout: { file: fullOutputPath },
|
|
85
|
-
stderr: 'inherit',
|
|
86
|
-
cwd: directory,
|
|
87
|
-
})`runhaskell ${mergedPath}`
|
|
88
|
-
|
|
89
|
-
if (exitCode !== 0) throw new Error(`Execution failed for ${mergedPath}`)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
async mergeScripts(
|
|
93
|
-
directory: string,
|
|
94
|
-
scriptPath1: string,
|
|
95
|
-
scriptPath2: string,
|
|
96
|
-
outputScriptPath: string,
|
|
97
|
-
): Promise<void> {
|
|
98
|
-
const script1 = await readText(join(directory, scriptPath1))
|
|
99
|
-
const script2 = await readText(join(directory, scriptPath2))
|
|
100
|
-
let mergedScript = script1
|
|
101
|
-
mergedScript += '\n\n\nmain = do\n'
|
|
102
|
-
for (const line of script2.split('\n')) {
|
|
103
|
-
if (line.trim() === '') {
|
|
104
|
-
mergedScript += '\n'
|
|
105
|
-
} else if (line.startsWith('let')) {
|
|
106
|
-
mergedScript += ` ${line}\n`
|
|
107
|
-
} else {
|
|
108
|
-
mergedScript += ` print $ ${line}\n`
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
await writeText(join(directory, outputScriptPath), mergedScript)
|
|
112
|
-
}
|
|
113
|
-
}
|