From b8ca7c792356fdd59385052f1d8172d461e52d66 Mon Sep 17 00:00:00 2001 From: Nafis Zaman Date: Tue, 20 Sep 2022 23:21:30 -0700 Subject: [PATCH] Add support for C++ programs --- express.js | 20 ++++++++++++++++--- src/ProgrammingLanguage.ts | 4 +++- src/compile.ts | 7 +++++-- src/components/Editor/LanguageSelectCharm.tsx | 3 +++ src/components/Root.tsx | 8 +++++--- src/worker.ts | 3 ++- 6 files changed, 35 insertions(+), 10 deletions(-) diff --git a/express.js b/express.js index 9a20e65e..76b372b6 100644 --- a/express.js +++ b/express.js @@ -46,8 +46,21 @@ if (config.server.dependencies.libkipr_c && config.server.dependencies.emsdk_env }); } + if (!('language' in req.body)) { + return res.status(400).json({ + error: "Expected language key in body" + }); + } + + if (typeof req.body.language !== 'string' || !['c', 'cpp'].includes(req.body.language)) { + return res.status(400).json({ + error: "Expected language key in body to be a supported language string" + }); + } + const id = uuid.v4(); - const path = `/tmp/${id}.c`; + const fileExtension = req.body.language; + const path = `/tmp/${id}.${fileExtension}`; fs.writeFile(path, req.body.code, err => { if (err) { return res.status(500).json({ @@ -60,8 +73,9 @@ if (config.server.dependencies.libkipr_c && config.server.dependencies.emsdk_env env['PATH'] = `${config.server.dependencies.emsdk_env.PATH}:${process.env.PATH}`; env['EMSDK'] = config.server.dependencies.emsdk_env.EMSDK; env['EM_CONFIG'] = config.server.dependencies.emsdk_env.EM_CONFIG; - - exec(`emcc -s WASM=1 -s SINGLE_FILE=1 -s INVOKE_RUN=0 -s EXIT_RUNTIME=1 -s "EXPORTED_FUNCTIONS=['_main']" -I${config.server.dependencies.libkipr_c}/include -L${config.server.dependencies.libkipr_c}/lib -lkipr -o ${path}.js ${path}`, { + + const compiler = req.body.language === 'c' ? 'emcc' : 'em++'; + exec(`${compiler} -s WASM=1 -s SINGLE_FILE=1 -s INVOKE_RUN=0 -s EXIT_RUNTIME=1 -s "EXPORTED_FUNCTIONS=['_main']" -I${config.server.dependencies.libkipr_c}/include -L${config.server.dependencies.libkipr_c}/lib -lkipr -o ${path}.js ${path}`, { env }, (err, stdout, stderr) => { if (err) { diff --git a/src/ProgrammingLanguage.ts b/src/ProgrammingLanguage.ts index 9e9ef73c..78d67fe5 100644 --- a/src/ProgrammingLanguage.ts +++ b/src/ProgrammingLanguage.ts @@ -1,10 +1,12 @@ -type ProgrammingLanguage = 'c' | 'python'; +type ProgrammingLanguage = 'c' | 'cpp' | 'python'; namespace ProgrammingLanguage { export const fileExtension = (language: ProgrammingLanguage) => { switch (language) { case 'c': return 'c'; + case 'cpp': + return 'cpp'; case 'python': return 'py'; } diff --git a/src/compile.ts b/src/compile.ts index b0c909ed..e1c81197 100644 --- a/src/compile.ts +++ b/src/compile.ts @@ -1,4 +1,6 @@ -export default (code: string): Promise => { +import ProgrammingLanguage from "./ProgrammingLanguage"; + +export default (code: string, language: ProgrammingLanguage): Promise => { return new Promise((resolve, reject) => { const req = new XMLHttpRequest(); @@ -19,7 +21,8 @@ export default (code: string): Promise => { req.setRequestHeader('Content-Type', 'application/json'); req.send(JSON.stringify({ - code + code, + language, })); }); diff --git a/src/components/Editor/LanguageSelectCharm.tsx b/src/components/Editor/LanguageSelectCharm.tsx index 9da281ca..b65692e2 100644 --- a/src/components/Editor/LanguageSelectCharm.tsx +++ b/src/components/Editor/LanguageSelectCharm.tsx @@ -23,6 +23,9 @@ const Container = styled('div', { const OPTIONS: ComboBox.Option[] = [{ text: 'C', data: 'c' +}, { + text: 'C++', + data: 'cpp' }, { text: 'Python', data: 'python' diff --git a/src/components/Root.tsx b/src/components/Root.tsx index cd8b36c3..4439b517 100644 --- a/src/components/Root.tsx +++ b/src/components/Root.tsx @@ -163,6 +163,7 @@ export class Root extends React.Component { activeLanguage: 'c', code: { 'c': window.localStorage.getItem('code-c') || '#include \n#include \n\nint main()\n{\n printf("Hello, World!\\n");\n return 0;\n}\n', + 'cpp': window.localStorage.getItem('code-cpp') || '#include \n#include \n\nint main()\n{\n std::cout << "Hello, World!" << std::endl;\n return 0;\n}\n', 'python': window.localStorage.getItem('code-python') || 'from kipr import *\n\nprint(\'Hello, World!\')', }, modal: Modal.NONE, @@ -288,7 +289,8 @@ export class Root extends React.Component { const activeCode = code[activeLanguage]; switch (activeLanguage) { - case 'c': { + case 'c': + case 'cpp': { let nextConsole: StyledText = StyledText.extend(console, StyledText.text({ text: `Compiling...\n`, style: STDOUT_STYLE(this.state.theme) @@ -298,7 +300,7 @@ export class Root extends React.Component { simulatorState: SimulatorState.COMPILING, console: nextConsole }, () => { - compile(activeCode) + compile(activeCode, activeLanguage) .then(compileResult => { nextConsole = this.state.console; const messages = sort(parseMessages(compileResult.stderr)); @@ -322,7 +324,7 @@ export class Root extends React.Component { })); WorkerInstance.start({ - language: 'c', + language: activeLanguage, code: compileResult.result }); } else { diff --git a/src/worker.ts b/src/worker.ts index db86c940..cca8f2e1 100644 --- a/src/worker.ts +++ b/src/worker.ts @@ -96,7 +96,8 @@ const startPython = async (message: Protocol.Worker.StartRequest) => { const start = async (message: Protocol.Worker.StartRequest) => { switch (message.language) { - case 'c': { + case 'c': + case 'cpp': { startC(message); break; }