Add support for compiler options

This commit is contained in:
Konrad Borowski 2019-08-14 13:01:16 +02:00
parent 9b001050ef
commit 608cf5a1e8
7 changed files with 86 additions and 20 deletions

View File

@ -0,0 +1,11 @@
ALTER TABLE wrappers DROP COLUMN is_asm;
UPDATE wrappers SET code = 'python3 code' WHERE code = 'python3 %s code';
UPDATE wrappers SET code = 'sh code' WHERE code = 'sh %s code';
UPDATE wrappers SET code = 'sqlite3 < code' WHERE code = 'sqlite3 %s < code';
UPDATE wrappers SET code = 'mv code code.rs && rustc code.rs && ./code' WHERE code = 'mv code code.rs && rustc %s code.rs && ./code';
UPDATE wrappers SET code = 'perl6 code' WHERE code = 'perl6 %s code';
DELETE FROM wrappers WHERE language_id = (SELECT language_id FROM languages WHERE name = 'Rust') AND label = 'ASM';
UPDATE wrappers SET ordering = 2 WHERE label = 'Rustfmt';

View File

@ -0,0 +1,13 @@
ALTER TABLE wrappers ADD COLUMN is_asm boolean NOT NULL DEFAULT FALSE;
UPDATE wrappers SET code = 'python3 %s code' WHERE code = 'python3 code';
UPDATE wrappers SET code = 'sh %s code' WHERE code = 'sh code';
UPDATE wrappers SET code = 'sqlite3 %s < code' WHERE code = 'sqlite3 < code';
UPDATE wrappers SET code = 'mv code code.rs && rustc %s code.rs && ./code' WHERE code = 'mv code code.rs && rustc code.rs && ./code';
UPDATE wrappers SET code = 'perl6 %s code' WHERE code = 'perl6 code';
UPDATE wrappers SET ordering = 3 WHERE label = 'Rustfmt';
INSERT INTO wrappers (language_id, label, code, ordering, is_asm)
SELECT language_id, 'ASM', 'rustc --emit asm --crate-type rlib code && cat code.s', 2, TRUE
FROM languages WHERE name = 'Rust';

View File

@ -27,6 +27,7 @@ struct ApiLanguage {
struct Wrapper {
id: i32,
label: String,
is_asm: bool,
is_formatter: bool,
}
@ -49,6 +50,7 @@ pub fn api_language(
.select((
wrappers::wrapper_id,
wrappers::label,
wrappers::is_asm,
wrappers::is_formatter,
))
.order(wrappers::ordering)

View File

@ -16,8 +16,10 @@ lazy_static! {
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Form {
code: String,
compiler_options: String,
}
#[derive(Serialize)]
@ -42,7 +44,10 @@ struct Output {
pub fn run(
id: i32,
Form { code }: Form,
Form {
code,
compiler_options,
}: Form,
pool: &'static PgPool,
) -> impl Future<Item = impl Reply, Error = Rejection> {
wrappers::table
@ -54,7 +59,7 @@ pub fn run(
.map(|wrapper| wrapper.ok_or_else(warp::reject::not_found))
.map_err(warp::reject::custom)
.flatten()
.and_then(|language_code| {
.and_then(move |language_code: String| {
CLIENT
.post(SANDBOX_URL.as_str())
.json(&Request {
@ -63,7 +68,7 @@ pub fn run(
contents: code,
}],
stdin: "",
code: language_code,
code: language_code.replace("%s", &compiler_options),
})
.send()
.and_then(|mut r| r.json())

View File

@ -28,6 +28,7 @@ table! {
code -> Text,
ordering -> Int4,
is_formatter -> Bool,
is_asm -> Bool,
}
}

View File

@ -27,22 +27,35 @@ function fetchLanguage(id) {
return future
}
let abortEval = new AbortController
const wrapperButtons = document.getElementById('wrapper-buttons')
const compilerOptions = document.createElement('input')
compilerOptions.placeholder = 'Compiler options'
const buttons = document.createElement('span')
wrapperButtons.append(compilerOptions, buttons)
const filterAsm = document.createElement('label')
const filterAsmCheckbox = document.createElement('input')
filterAsmCheckbox.type = 'checkbox'
filterAsmCheckbox.checked = true
filterAsm.append(' ', filterAsmCheckbox, ' Filter assembler directives')
const filterRegex = /(?:\t\.(?:text|file|section|globl|p2align|type|cfi_.*|size|section)\b|.Lfunc_end).*\n?/g
let abortEval = new AbortController
async function updateLanguage() {
const initialValue = language.selectedOptions[0].value
const { mime, mode, wrappers } = await fetchLanguage(initialValue)
if (initialValue === language.selectedOptions[0].value) {
editor.setOption('mode', mime)
CodeMirror.autoLoadMode(editor, mode)
const buttons = document.getElementById('wrapper-buttons')
buttons.textContent = ''
for (const { id, label, isFormatter } of wrappers) {
compilerOptions.style.display = wrappers.length ? 'inline' : 'none'
for (const { id, label, isAsm, isFormatter } of wrappers) {
const button = document.createElement('button')
button.textContent = label
button.addEventListener('click', e => {
e.preventDefault()
const body = new URLSearchParams
body.append('compilerOptions', compilerOptions.value)
body.append('code', editor.getValue())
abortEval.abort()
abortEval = new AbortController
@ -58,7 +71,25 @@ async function updateLanguage() {
output.textContent = ''
fetch(`/api/v0/run/${id}`, parameters)
.then(x => x.json())
.catch(e => {
if (e.name != 'AbortError')
output.textContent = 'An error occured while running the code. Try again.'
})
.then(({ status, stdout, stderr }) => {
function updateStdout() {
if (stdout) {
if (isAsm && filterAsmCheckbox.checked) {
stdoutElement.textContent = stdout.replace(filterRegex, "")
} else {
stdoutElement.textContent = stdout
}
} else {
const italic = document.createElement('i')
italic.textContent = '(no output)'
stdoutElement.append(italic)
}
}
let stdoutElement
if (stderr) {
const stderrHeader = document.createElement('h2')
stderrHeader.textContent = 'Standard error'
@ -69,26 +100,23 @@ async function updateLanguage() {
if (isFormatter) {
editor.setValue(stdout)
} else {
const stdoutHeader = document.createElement('h2')
stdoutHeader.textContent = 'Standard output'
const stdoutHeader = document.createElement('div')
stdoutHeader.className = 'stdout-header'
const stdoutHeaderH2 = document.createElement('h2')
stdoutHeaderH2.textContent = 'Standard output'
if (status) {
stdoutHeader.textContent += ` (exit code ${status})`
stdoutHeaderH2.textContent += ` (exit code ${status})`
}
const stdoutElement = document.createElement('pre')
if (stdout) {
stdoutElement.textContent = stdout
} else {
const italic = document.createElement('i')
italic.textContent = '(no output)'
stdoutElement.append(italic)
stdoutHeader.append(stdoutHeaderH2)
if (isAsm) {
stdoutHeader.append(filterAsm)
filterAsmCheckbox.onchange = updateStdout
}
stdoutElement = document.createElement('pre')
updateStdout()
output.append(stdoutHeader, stdoutElement)
}
})
.catch(e => {
if (e.name != 'AbortError')
output.textContent = 'An error occured while running the code. Try again.'
})
})
buttons.appendChild(button)
}

View File

@ -79,3 +79,9 @@ pre, code {
img {
max-width: 100%;
}
.stdout-header h2, .stdout-header label {
display: inline-block;
}
.stdout-header label {
padding-left: 1em;
}