aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/base-compiler.js37
-rw-r--r--lib/compilation-env.js18
-rw-r--r--lib/compile-handler.js109
-rw-r--r--lib/compilers/WSL-CL.js6
-rw-r--r--lib/compilers/Wine-CL.js8
-rw-r--r--lib/compilers/default.js4
-rw-r--r--lib/compilers/golang.js6
-rw-r--r--lib/compilers/haskell.js4
-rw-r--r--lib/compilers/ispc.js4
-rw-r--r--lib/compilers/ldc.js4
-rw-r--r--lib/compilers/pascal.js5
-rw-r--r--lib/compilers/rust.js4
-rw-r--r--lib/compilers/swift.js4
-rw-r--r--lib/languages.js116
-rw-r--r--lib/sources/builtin.js42
15 files changed, 259 insertions, 112 deletions
diff --git a/lib/base-compiler.js b/lib/base-compiler.js
index 21c60f28f..3788aea22 100644
--- a/lib/base-compiler.js
+++ b/lib/base-compiler.js
@@ -34,12 +34,20 @@ const child_process = require('child_process'),
logger = require('./logger').logger,
compilerOptInfo = require("compiler-opt-info"),
argumentParsers = require("./compilers/argument-parsers"),
- cfg = require('./cfg');
+ cfg = require('./cfg'),
+ languages = require('./languages').list;
-function Compile(compiler, env) {
+function Compile(compiler, env, langId) {
this.compiler = compiler;
+ this.lang = langId;
+ this.langInfo = languages[langId];
+ if (!this.langInfo) {
+ throw new Error("Missing language info for " + langId);
+ }
+ this.compileFilename = 'example' + this.langInfo.extensions[0];
this.env = env;
- this.asm = new asm.AsmParser(env.compilerProps);
+ this.compilerProps = _.partial(this.env.compilerPropsL, this.lang);
+ this.asm = new asm.AsmParser(this.compilerProps);
this.compiler.supportsIntel = !!this.compiler.intelAsm;
}
@@ -75,10 +83,10 @@ Compile.prototype.exec = function (compiler, args, options) {
Compile.prototype.getDefaultExecOptions = function () {
return {
- timeoutMs: this.env.gccProps("compileTimeoutMs", 100),
- maxErrorOutput: this.env.gccProps("max-error-output", 5000),
+ timeoutMs: this.env.ceProps("compileTimeoutMs", 100),
+ maxErrorOutput: this.env.ceProps("max-error-output", 5000),
env: this.env.getEnv(this.compiler.needsMulti),
- wrapper: this.env.compilerProps("compiler-wrapper")
+ wrapper: this.compilerProps("compiler-wrapper")
};
};
@@ -226,13 +234,13 @@ Compile.prototype.compile = function (source, options, backendOptions, filters)
return Promise.resolve(cached);
}
- if (filters.binary && !source.match(this.env.compilerProps("stubRe"))) {
- source += "\n" + this.env.compilerProps("stubText") + "\n";
+ if (filters.binary && !source.match(this.compilerProps("stubRe"))) {
+ source += "\n" + this.compilerProps("stubText") + "\n";
}
return this.env.enqueue(() => {
const tempFileAndDirPromise = this.newTempDir()
.then(dirPath => {
- const inputFilename = path.join(dirPath, this.env.compilerProps("compileFilename"));
+ const inputFilename = path.join(dirPath, this.compileFilename);
return this.writeFile(inputFilename, source).then(() => ({
inputFilename: inputFilename,
dirPath: dirPath
@@ -357,8 +365,7 @@ Compile.prototype.postProcessAsm = function (result) {
};
Compile.prototype.processOptOutput = function (hasOptOutput, optPath) {
- const output = [];
- const inputFile = this.env.compilerProps("compileFilename", "");
+ let output = [];
return new Promise(
resolve => {
fs.createReadStream(optPath, {encoding: "utf-8"})
@@ -366,7 +373,7 @@ Compile.prototype.processOptOutput = function (hasOptOutput, optPath) {
.on("data", opt => {
if (opt.DebugLoc &&
opt.DebugLoc.File &&
- opt.DebugLoc.File.indexOf(inputFile) > -1) {
+ opt.DebugLoc.File.indexOf(this.compileFilename) > -1) {
output.push(opt);
}
@@ -519,7 +526,7 @@ Compile.prototype.processGccDumpOutput = function (opts, result) {
Compile.prototype.postProcess = function (result, outputFilename, filters) {
const postProcess = _.compact(this.compiler.postProcess);
- const maxSize = this.env.gccProps("max-asm-size", 8 * 1024 * 1024);
+ const maxSize = this.env.ceProps("max-asm-size", 8 * 1024 * 1024);
let optPromise, asmPromise, execPromise;
if (result.hasOptOutput) {
optPromise = this.processOptOutput(result.hasOptOutput, result.optPath);
@@ -555,7 +562,7 @@ Compile.prototype.postProcess = function (result, outputFilename, filters) {
);
}
if (filters.execute) {
- const maxExecOutputSize = this.env.gccProps("max-executable-output-size", 32 * 1024);
+ const maxExecOutputSize = this.env.ceProps("max-executable-output-size", 32 * 1024);
execPromise = this.execBinary(outputFilename, result, maxExecOutputSize);
} else {
execPromise = Promise.resolve("");
@@ -635,7 +642,7 @@ Compile.prototype.initialise = function () {
'with re', versionRe);
return null;
}
- logger.info(compiler + " is version '" + version + "'");
+ logger.debug(compiler + " is version '" + version + "'");
this.compiler.version = version;
return argumentParser(this);
},
diff --git a/lib/compilation-env.js b/lib/compilation-env.js
index 81f21e54a..1d2d7b6cb 100644
--- a/lib/compilation-env.js
+++ b/lib/compilation-env.js
@@ -32,20 +32,18 @@ const LRU = require('lru-cache'),
Queue.configure(Promise);
-function CompilationEnvironment(gccProps, compilerProps) {
- this.gccProps = gccProps;
- this.compilerProps = compilerProps;
- this.okOptions = new RegExp(gccProps('optionsWhitelistRe', '.*'));
- this.badOptions = new RegExp(gccProps('optionsBlacklistRe', '(?!)'));
+function CompilationEnvironment(ceProps, compilerPropsL) {
+ this.ceProps = ceProps;
+ this.compilerPropsL = compilerPropsL;
+ this.okOptions = new RegExp(ceProps('optionsWhitelistRe', '.*'));
+ this.badOptions = new RegExp(ceProps('optionsBlacklistRe', '(?!)'));
this.cache = LRU({
- max: gccProps('cacheMb') * 1024 * 1024,
- length: function (n) {
- return JSON.stringify(n).length;
- }
+ max: ceProps('cacheMb') * 1024 * 1024,
+ length: n => JSON.stringify(n).length
});
this.cacheHits = 0;
this.cacheMisses = 0;
- this.compileQueue = new Queue(gccProps("maxConcurrentCompiles", 1), Infinity);
+ this.compileQueue = new Queue(ceProps("maxConcurrentCompiles", 1), Infinity);
this.multiarch = null;
try {
var multi = child_process.execSync("gcc -print-multiarch").toString().trim();
diff --git a/lib/compile-handler.js b/lib/compile-handler.js
index 1cbde43f4..159c5eeb5 100644
--- a/lib/compile-handler.js
+++ b/lib/compile-handler.js
@@ -22,8 +22,7 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
-var child_process = require('child_process'),
- temp = require('temp'),
+const temp = require('temp'),
fs = require('fs'),
path = require('path'),
httpProxy = require('http-proxy'),
@@ -37,12 +36,12 @@ var child_process = require('child_process'),
temp.track();
-var oneTimeInit = false;
+let oneTimeInit = false;
-function initialise(gccProps, compilerEnv) {
+function initialise(ceProps, compilerEnv) {
if (oneTimeInit) return;
oneTimeInit = true;
- var tempDirCleanupSecs = gccProps("tempDirCleanupSecs", 600);
+ const tempDirCleanupSecs = ceProps("tempDirCleanupSecs", 600);
logger.info("Cleaning temp dirs every " + tempDirCleanupSecs + " secs");
setInterval(function () {
if (compilerEnv.isBusy()) {
@@ -56,71 +55,61 @@ function initialise(gccProps, compilerEnv) {
}, tempDirCleanupSecs * 1000);
}
-function CompileHandler(gccProps, compilerProps) {
+function CompileHandler(ceProps, compilerPropsL) {
+ const self = this;
this.compilersById = {};
- this.compilerEnv = new CompilationEnvironment(gccProps, compilerProps);
- initialise(gccProps, this.compilerEnv);
+ this.compilerEnv = new CompilationEnvironment(ceProps, compilerPropsL);
+ initialise(ceProps, this.compilerEnv);
this.factories = {};
this.stat = Promise.denodeify(fs.stat);
+ this.proxy = httpProxy.createProxyServer({});
+ this.textBanner = ceProps('textBanner');
+
this.create = function (compiler) {
- var type = compiler.compilerType || "default";
- if (this.factories[type] === undefined) {
- var compilerPath = './compilers/' + type;
- logger.info("Loading compiler from", compilerPath);
- this.factories[type] = require(compilerPath);
+ const type = compiler.compilerType || "default";
+ if (self.factories[type] === undefined) {
+ const compilerPath = './compilers/' + type;
+ logger.debug("Loading compiler from", compilerPath);
+ self.factories[type] = require(compilerPath);
}
if (path.isAbsolute(compiler.exe)) {
// Try stat'ing the compiler to cache its mtime and only re-run it if it
// has changed since the last time.
- return this.stat(compiler.exe)
- .then(_.bind(function (res) {
- var cached = this.compilersById[compiler.id];
+ return self.stat(compiler.exe)
+ .then(_.bind(res => {
+ const cached = self.findCompiler(compiler.lang, compiler.id);
if (cached && cached.mtime.getTime() === res.mtime.getTime()) {
logger.debug(compiler.id + " is unchanged");
return cached;
}
- return this.factories[type](compiler, this.compilerEnv).then(function (compiler) {
+ return self.factories[type](compiler, self.compilerEnv, compiler.lang).then(compiler => {
compiler.mtime = res.mtime;
return compiler;
});
- }, this))
- .catch(function (err) {
+ }, self))
+ .catch(err => {
logger.warn("Unable to stat compiler binary", err);
return null;
});
} else {
- return this.factories[type](compiler, this.compilerEnv);
+ return self.factories[type](compiler, self.compilerEnv, compiler.lang);
}
};
-
- this.setCompilers = function (compilers) {
- return Promise.all(_.map(compilers, this.create, this))
- .then(_.compact)
- .then(compilers => {
- _.each(compilers, compiler => this.compilersById[compiler.compiler.id] = compiler);
- return _.map(compilers, compiler => compiler.getInfo());
- })
- .catch(err => logger.error(err));
- };
- var proxy = httpProxy.createProxyServer({});
- var textBanner = compilerProps('textBanner');
-
- this.handler = _.bind(function compile(req, res, next) {
- var source, options, backendOptions, filters, compiler;
+ this.handler = function compile(req, res, next) {
+ let source, options, backendOptions, filters,
+ compiler = self.findCompiler(req.lang || req.body.lang, req.compiler || req.body.compiler);
+ if (!compiler) return next();
if (req.is('json')) {
// JSON-style request
- compiler = this.compilersById[req.compiler || req.body.compiler];
- if (!compiler) return next();
- var requestOptions = req.body.options;
+ const requestOptions = req.body.options;
source = req.body.source;
options = requestOptions.userArguments;
backendOptions = requestOptions.compilerOptions;
filters = requestOptions.filters || compiler.getDefaultFilters();
} else {
// API-style
- compiler = this.compilersById[req.compiler];
- if (!compiler) return next();
+ // Find the compiler the user is interested in...
source = req.body;
options = req.query.options;
// By default we get the default filters.
@@ -140,10 +129,10 @@ function CompileHandler(gccProps, compilerProps) {
delete filters[filter];
});
}
- var remote = compiler.getRemote();
+ const remote = compiler.getRemote();
if (remote) {
req.url = req.originalUrl; // Undo any routing that was done to get here (i.e. /api/* path has been removed)
- proxy.web(req, res, {target: remote}, function (e) {
+ self.proxy.web(req, res, {target: remote}, function (e) {
logger.error("Proxy error: ", e);
next(e);
});
@@ -170,7 +159,7 @@ function CompileHandler(gccProps, compilerProps) {
} else {
res.set('Content-Type', 'text/plain');
try {
- if (!_.isEmpty(textBanner)) res.write('# ' + textBanner + "\n");
+ if (!_.isEmpty(self.textBanner)) res.write('# ' + self.textBanner + "\n");
res.write(textify(result.asm));
if (result.code !== 0) res.write("\n# Compiler exited with result code " + result.code);
if (!_.isEmpty(result.stdout)) res.write("\nStandard out:\n" + textify(result.stdout));
@@ -198,7 +187,39 @@ function CompileHandler(gccProps, compilerProps) {
res.end(JSON.stringify({code: -1, stderr: [{text: error}]}));
}
);
- }, this);
+ };
+ this.setCompilers = function (newCompilers) {
+ // Delete every compiler first...
+ self.compilersById = {};
+ return Promise.all(_.map(newCompilers, self.create))
+ .then(_.compact)
+ .then(compilers => {
+ _.each(compilers, compiler => {
+ const langId = compiler.compiler.lang;
+ if (!self.compilersById[langId]) self.compilersById[langId] = {};
+ self.compilersById[langId][compiler.compiler.id] = compiler;
+ }, self);
+ return _.map(compilers,compiler => compiler.getInfo());
+ })
+ .catch(logger.error);
+ };
+ this.findCompiler = function (langId, compilerId) {
+ if (langId && self.compilersById[langId]) {
+ return self.compilersById[langId][compilerId];
+ }
+ // If the lang is bad, try to find it in every language
+ let response;
+ _.each(self.compilersById, compilerInLang => {
+ if (response === undefined) {
+ _.each(compilerInLang, compiler => {
+ if (response === undefined && compiler.compiler.id === compilerId) {
+ response = compiler;
+ }
+ });
+ }
+ });
+ return response;
+ };
}
module.exports = {
diff --git a/lib/compilers/WSL-CL.js b/lib/compilers/WSL-CL.js
index 4582e546b..be3bc21c4 100644
--- a/lib/compilers/WSL-CL.js
+++ b/lib/compilers/WSL-CL.js
@@ -32,9 +32,9 @@ const Compile = require('../base-compiler'),
asm = require('../asm-cl'),
temp = require('temp');
-function compileCl(info, env) {
- const compile = new Compile(info, env);
- compile.asm = new asm.AsmParser(env.compilerProps);
+function compileCl(info, env, langId) {
+ var compile = new Compile(info, env, langId);
+ compile.asm = new asm.AsmParser(compile.compilerProps);
info.supportsFiltersInBinary = true;
if (process.platform === "linux") {
const origExec = compile.exec;
diff --git a/lib/compilers/Wine-CL.js b/lib/compilers/Wine-CL.js
index 0e92fe4de..d206bb0f2 100644
--- a/lib/compilers/Wine-CL.js
+++ b/lib/compilers/Wine-CL.js
@@ -25,12 +25,12 @@
var Compile = require('../base-compiler');
var asm = require('../asm-cl');
-function compileCl(info, env) {
- var compile = new Compile(info, env);
- compile.asm = new asm.AsmParser(env.compilerProps);
+function compileCl(info, env, langId) {
+ var compile = new Compile(info, env, langId);
+ compile.asm = new asm.AsmParser(compile.compilerProps);
info.supportsFiltersInBinary = true;
if (process.platform == "linux") {
- var wine = env.gccProps("wine");
+ var wine = env.ceProps("wine");
var origExec = compile.exec;
compile.exec = function (command, args, options) {
if (command.toLowerCase().endsWith(".exe")) {
diff --git a/lib/compilers/default.js b/lib/compilers/default.js
index 759d2bbe8..64a542760 100644
--- a/lib/compilers/default.js
+++ b/lib/compilers/default.js
@@ -24,7 +24,7 @@
const Compile = require('../base-compiler');
-module.exports = function (info, env) {
- var comp = new Compile(info, env);
+module.exports = function (info, env, langId) {
+ var comp = new Compile(info, env, langId);
return comp.initialise();
}; \ No newline at end of file
diff --git a/lib/compilers/golang.js b/lib/compilers/golang.js
index 18a299f17..df63bc8bf 100644
--- a/lib/compilers/golang.js
+++ b/lib/compilers/golang.js
@@ -25,8 +25,8 @@
const Compile = require('../base-compiler'),
_ = require('underscore-node');
-function compilenewgol(info, env) {
- const compiler = new Compile(info, env);
+function compilenewgol(info, env, langId) {
+ const compiler = new Compile(info, env, langId);
compiler.originalGetDefaultExecOptions = compiler.getDefaultExecOptions;
function convertNewGoL(code) {
@@ -70,7 +70,7 @@ function compilenewgol(info, env) {
compiler.getDefaultExecOptions = function () {
const execOptions = this.originalGetDefaultExecOptions();
- const goroot = this.env.compilerProps("compiler." + this.compiler.id + ".goroot");
+ const goroot = this.compilerProps("compiler." + this.compiler.id + ".goroot");
if (goroot) {
execOptions.env.GOROOT = goroot;
}
diff --git a/lib/compilers/haskell.js b/lib/compilers/haskell.js
index a4080192f..78963748e 100644
--- a/lib/compilers/haskell.js
+++ b/lib/compilers/haskell.js
@@ -1,7 +1,7 @@
var Compile = require('../base-compiler');
-function compileHaskell(info, env) {
- var compiler = new Compile(info, env);
+function compileHaskell(info, env, langId) {
+ var compiler = new Compile(info, env, langId);
compiler.optionsForFilter = function (filters, outputFilename, userOptions) {
return ['-S', '-g', '-o', this.filename(outputFilename)];
};
diff --git a/lib/compilers/ispc.js b/lib/compilers/ispc.js
index 3bb0f124f..ff2b8054f 100644
--- a/lib/compilers/ispc.js
+++ b/lib/compilers/ispc.js
@@ -1,7 +1,7 @@
var Compile = require('../base-compiler');
-function compileISPC(info, env) {
- var compiler = new Compile(info, env);
+function compileISPC(info, env, langId) {
+ var compiler = new Compile(info, env, langId);
compiler.optionsForFilter = function (filters, outputFilename, userOptions) {
return ['--target=sse2-i32x4', '--emit-asm', '-g', '-o', this.filename(outputFilename)];
};
diff --git a/lib/compilers/ldc.js b/lib/compilers/ldc.js
index 11de1e66c..ffee8bf95 100644
--- a/lib/compilers/ldc.js
+++ b/lib/compilers/ldc.js
@@ -25,8 +25,8 @@
var Compile = require('../base-compiler'),
argumentParsers = require("./argument-parsers");
-function compileLdc(info, env) {
- var compiler = new Compile(info, env);
+function compileLdc(info, env, langId) {
+ var compiler = new Compile(info, env, langId);
compiler.compiler.supportsIntel = true;
compiler.optionsForFilter = function (filters, outputFilename, userOptions) {
var options = ['-g', '-of', this.filename(outputFilename)];
diff --git a/lib/compilers/pascal.js b/lib/compilers/pascal.js
index f5855f6cd..e4f0fcbc0 100644
--- a/lib/compilers/pascal.js
+++ b/lib/compilers/pascal.js
@@ -24,15 +24,14 @@
"use strict";
var Compile = require('../base-compiler'),
- logger = require('../logger').logger,
PascalDemangler = require('../pascal-support').demangler,
utils = require('../utils'),
fs = require("fs"),
path = require("path");
-function compileFPC(info, env) {
+function compileFPC(info, env, langId) {
var demangler = new PascalDemangler();
- var compiler = new Compile(info, env);
+ var compiler = new Compile(info, env, langId);
compiler.supportsOptOutput = false;
var originalExecBinary = compiler.execBinary;
diff --git a/lib/compilers/rust.js b/lib/compilers/rust.js
index 6d2295cbe..2fc60fa2b 100644
--- a/lib/compilers/rust.js
+++ b/lib/compilers/rust.js
@@ -25,8 +25,8 @@
var Compile = require('../base-compiler'),
_ = require('underscore-node');
-function compileRust(info, env) {
- var compiler = new Compile(info, env);
+function compileRust(info, env, langId) {
+ var compiler = new Compile(info, env, langId);
compiler.compiler.supportsIntel = true;
compiler.optionsForFilter = function (filters, outputFilename, userOptions) {
var options = ['-C', 'debuginfo=1', '-o', this.filename(outputFilename)];
diff --git a/lib/compilers/swift.js b/lib/compilers/swift.js
index 884828852..ffd39a295 100644
--- a/lib/compilers/swift.js
+++ b/lib/compilers/swift.js
@@ -1,8 +1,8 @@
const Compile = require('../base-compiler'),
logger = require('../logger').logger;
-function compileSwift(info, env) {
- const compiler = new Compile(info, env);
+function compileSwift(info, env, langId) {
+ const compiler = new Compile(info, env, langId);
compiler.handlePostProcessResult = function (result, postResult) {
result.asm = postResult.stdout;
diff --git a/lib/languages.js b/lib/languages.js
new file mode 100644
index 000000000..258a9b646
--- /dev/null
+++ b/lib/languages.js
@@ -0,0 +1,116 @@
+// Copyright (c) 2012-2017, Matt Godbolt
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+
+/* id is what we internally use to identify the language.
+ *MUST BE* Same as the key so we can always query for it, everywhere.
+ Used in: properties, url redirect, lang dropdown
+ name is what we display to the user
+ Used in: UI
+ monaco is how we tell the monaco editor which language is this
+ Used in: Monaco.editor.language
+ extension is an array for the usual extensions of the language.
+ The first one declared will be used as the default, else txt
+ Leading point is needed
+ Used in: Save to file extension
+*/
+
+const languages = {
+ 'c++': {
+ id: 'c++',
+ name: 'C++',
+ monaco: 'cppp',
+ extensions: ['.cpp', '.cxx', '.h', '.hpp', '.hxx', '.c']
+ },
+ cppx: {
+ id: 'cppx',
+ name: 'Cppx',
+ monaco: 'cppp',
+ extensions: ['.cpp', '.cxx', '.h', '.hpp', '.hxx', '.c']
+ },
+ c: {
+ id: 'c',
+ name: 'C',
+ monaco: 'c',
+ extensions: ['.c', '.h']
+ },
+ rust: {
+ id: 'rust',
+ name: 'Rust',
+ monaco: 'rust',
+ extensions: ['.rs']
+ },
+ d: {
+ id: 'd',
+ name: 'D',
+ monaco: 'd',
+ extensions: ['.d']
+ },
+ go: {
+ id: 'go',
+ name: 'Go',
+ monaco: 'go',
+ extensions: ['.go']
+ },
+ ispc: {
+ id: 'ispc',
+ name: 'ispc',
+ monaco: 'ispc',
+ extensions: ['.ispc']
+ },
+ haskell: {
+ id: 'haskell',
+ name: 'Haskell',
+ monaco: 'haskell',
+ extensions: ['.hs', '.haskell']
+ },
+ swift: {
+ id: 'swift',
+ name: 'Swift',
+ monaco: 'swift',
+ extensions: ['.swift']
+ },
+ pascal: {
+ id: 'pascal',
+ name: 'Pascal',
+ monaco: 'pascal',
+ extensions: ['.pas']
+ }
+};
+
+const fs = require('fs-extra');
+const _ = require('underscore-node');
+const path = require('path');
+_.each(languages, lang => {
+ try {
+ const example = fs.readFileSync(path.join('examples', lang.id, 'default' + lang.extensions[0]), 'utf8');
+ lang.example = example;
+ } catch (error) {
+ lang.example = "Oops, something went wrong and we could not get the default code for this language.";
+ }
+});
+
+module.exports = {
+ list: languages
+};
diff --git a/lib/sources/builtin.js b/lib/sources/builtin.js
index d5252bc05..aaf78b3be 100644
--- a/lib/sources/builtin.js
+++ b/lib/sources/builtin.js
@@ -24,27 +24,31 @@
const props = require('../properties.js'),
path = require('path'),
- fs = require('fs');
+ fs = require('fs'),
+ _ = require('underscore-node');
+const basePath = props.get('builtin', 'sourcePath', './examples/');
+const replacer = new RegExp('_', 'g');
+const examples = _.flatten(
+ fs.readdirSync(basePath)
+ .map(folder => {
+ const folerPath = path.join(basePath, folder);
+ return fs.readdirSync(folerPath)
+ .map(file => {
+ const filePath = path.join(folerPath, file);
+ const fileName = path.parse(file).name;
+ return {lang: folder, name: fileName.replace(replacer, ' '), path: filePath, file: fileName};
+ })
+ .filter(descriptor => descriptor.name !== "default")
+ .sort((x, y) => x.name.localeCompare(y.name));
+ }));
-const sourcePath = props.get('builtin', 'sourcepath', './examples/c++');
-const sourceMatch = new RegExp(props.get('builtin', 'extensionRe', '.*\\.cpp$'));
-const examples = fs.readdirSync(sourcePath)
- .filter(file => file.match(sourceMatch))
- .map(file => {
- const nicename = file.replace(/\.cpp$/, '');
- return {urlpart: nicename, name: nicename.replace(/_/g, ' '), path: path.join(sourcePath, file)};
- }).sort((x, y) => x.name.localeCompare(y.name));
-
-const byUrlpart = {};
-examples.forEach(e => byUrlpart[e.urlpart] = e.path);
-
-function load(filename) {
- const path = byUrlpart[filename];
- if (!path) {
+function load(lang, filename) {
+ const example = _.find(examples, example => example.lang === lang && example.file === filename);
+ if (!example) {
return Promise.reject("No such path");
}
return new Promise((resolve, reject) => {
- fs.readFile(path, 'utf-8', function (err, res) {
+ fs.readFile(example.path, 'utf-8', (err, res) => {
if (err) {
reject(err);
} else {
@@ -55,7 +59,9 @@ function load(filename) {
}
function list() {
- return Promise.resolve(examples.map(example => ({urlpart: example.urlpart, name: example.name})));
+ return Promise.resolve(examples.map(example => {
+ return {file: example.file, name: example.name, lang: example.lang};
+ }));
}
module.exports.load = load;