mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 07:04:04 -05:00
Fix various points raised after code reviews
Some fixes, a great slam and then some
This commit is contained in:
120
app.js
120
app.js
@@ -117,14 +117,12 @@ var CompileHandler = require('./lib/compile-handler').CompileHandler,
|
||||
// in hidden object props.properties
|
||||
var ceProps = props.propsFor("compiler-explorer");
|
||||
|
||||
var languages = require('./lib/languages');
|
||||
const languages = require('./lib/languages').list;
|
||||
|
||||
// Instantiate a function to access records concerning the chosen language
|
||||
// in hidden object props.properties
|
||||
var compilerPropsFuncsL = {};
|
||||
_.each(languages.list(), function (lang) {
|
||||
compilerPropsFuncsL[lang.id] = props.propsFor(lang.id);
|
||||
});
|
||||
_.each(languages, lang => compilerPropsFuncsL[lang.id] = props.propsFor(lang.id));
|
||||
|
||||
// Get a property from the specified langId, and if not found, use defaults from CE,
|
||||
// and at last return whatever default value was set by the caller
|
||||
@@ -139,16 +137,16 @@ function compilerPropsL(lang, property, defaultValue) {
|
||||
|
||||
// For every lang passed, get its corresponding compiler property
|
||||
function compilerPropsA(langs, property, defaultValue) {
|
||||
const forLanguages = {};
|
||||
let forLanguages = {};
|
||||
_.each(langs, lang => {
|
||||
forLanguages[lang.id] = compilerPropsL(lang.id, property, defaultValue);
|
||||
});
|
||||
return forLanguages;
|
||||
}
|
||||
|
||||
// Same as A version, but transfrom each value by fn(original, lang)
|
||||
// Same as A version, but transfroms each value by fn(original, lang)
|
||||
function compilerPropsAT(langs, transform, property, defaultValue) {
|
||||
var forLanguages = {};
|
||||
let forLanguages = {};
|
||||
_.each(langs, lang => {
|
||||
forLanguages[lang.id] = transform(compilerPropsL(lang.id, property, defaultValue), lang);
|
||||
});
|
||||
@@ -208,18 +206,16 @@ function compareOn(key) {
|
||||
|
||||
// instantiate a function that generate javascript code,
|
||||
function ClientOptionsHandler(fileSources) {
|
||||
var sources = fileSources.map(function (source) {
|
||||
const sources = fileSources.map(function (source) {
|
||||
return {name: source.name, urlpart: source.urlpart};
|
||||
});
|
||||
}).sort(compareOn("name"));
|
||||
// sort source file alphabetically
|
||||
sources = sources.sort(compareOn("name"));
|
||||
|
||||
var langs = languages.toArray();
|
||||
var supportsBinary = compilerPropsAT(langs, res => !!res, "supportsBinary", true);
|
||||
var supportsExecute = supportsBinary && !!compilerPropsAT(langs, (res, lang) => supportsBinary[lang.id] && !!res, "supportsExecute", true);
|
||||
var supportsBinary = compilerPropsAT(languages, res => !!res, "supportsBinary", true);
|
||||
var supportsExecute = supportsBinary && !!compilerPropsAT(languages, (res, lang) => supportsBinary[lang.id] && !!res, "supportsExecute", true);
|
||||
var libs = {};
|
||||
|
||||
var baseLibs = compilerPropsA(langs, "libs");
|
||||
var baseLibs = compilerPropsA(languages, "libs");
|
||||
_.each(baseLibs, function (forLang, lang) {
|
||||
if (lang && forLang) {
|
||||
libs[lang] = {};
|
||||
@@ -257,11 +253,11 @@ function ClientOptionsHandler(fileSources) {
|
||||
defaultSource: ceProps('defaultSource', ''),
|
||||
compilers: [],
|
||||
libs: libs,
|
||||
defaultCompiler: compilerPropsA(langs, 'defaultCompiler', ''),
|
||||
compileOptions: compilerPropsA(langs, 'defaultOptions', ''),
|
||||
defaultCompiler: compilerPropsA(languages, 'defaultCompiler', ''),
|
||||
compileOptions: compilerPropsA(languages, 'defaultOptions', ''),
|
||||
supportsBinary: supportsBinary,
|
||||
supportsExecute: supportsExecute,
|
||||
languages: languages.list(),
|
||||
languages: languages,
|
||||
sources: sources,
|
||||
raven: ceProps('ravenUrl', ''),
|
||||
release: gitReleaseName,
|
||||
@@ -336,23 +332,21 @@ function retryPromise(promiseFunc, name, maxFails, retryMs) {
|
||||
}
|
||||
|
||||
function findCompilers() {
|
||||
var exes = compilerPropsAT(languages.toArray(), exs => {
|
||||
return exs.split(":").filter(x => x);
|
||||
}, "compilers", "/usr/bin/g++");
|
||||
let exes = compilerPropsAT(languages, exs => {
|
||||
return exs.split(":").filter(_.identity);
|
||||
}, "compilers", "");
|
||||
|
||||
var ndk = compilerPropsA(languages.toArray(), 'androidNdk');
|
||||
const ndk = compilerPropsA(languages, 'androidNdk');
|
||||
_.each(ndk, (ndkPath, langId) => {
|
||||
if (ndkPath) {
|
||||
var toolchains = fs.readdirSync(ndkPath + "/toolchains");
|
||||
toolchains.forEach(function (v, i, a) {
|
||||
var path = ndkPath + "/toolchains/" + v + "/prebuilt/linux-x86_64/bin/";
|
||||
let toolchains = fs.readdirSync(ndkPath + "/toolchains");
|
||||
toolchains.forEach((version, index, a) => {
|
||||
const path = ndkPath + "/toolchains/" + version + "/prebuilt/linux-x86_64/bin/";
|
||||
if (fs.existsSync(path)) {
|
||||
var cc = fs.readdirSync(path).filter(function (filename) {
|
||||
return filename.indexOf("g++") !== -1;
|
||||
});
|
||||
a[i] = path + cc[0];
|
||||
const cc = fs.readdirSync(path).filter(filename => filename.indexOf("g++") !== -1);
|
||||
a[index] = path + cc[0];
|
||||
} else {
|
||||
a[i] = null;
|
||||
a[index] = null;
|
||||
}
|
||||
});
|
||||
toolchains = toolchains.filter(x => x !== null);
|
||||
@@ -362,40 +356,38 @@ function findCompilers() {
|
||||
|
||||
function fetchRemote(host, port, props) {
|
||||
logger.info("Fetching compilers from remote source " + host + ":" + port);
|
||||
return retryPromise(function () {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var request = http.get({
|
||||
return retryPromise(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let request = http.get({
|
||||
hostname: host,
|
||||
port: port,
|
||||
path: "/api/compilers",
|
||||
headers: {
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
}, function (res) {
|
||||
var str = '';
|
||||
res.on('data', function (chunk) {
|
||||
}, res => {
|
||||
let str = '';
|
||||
res.on('data', chunk => {
|
||||
str += chunk;
|
||||
});
|
||||
res.on('end', function () {
|
||||
var compilers = JSON.parse(str).map(function (compiler) {
|
||||
res.on('end', () => {
|
||||
let compilers = JSON.parse(str).map(compiler => {
|
||||
compiler.exe = null;
|
||||
compiler.remote = "http://" + host + ":" + port;
|
||||
return compiler;
|
||||
});
|
||||
resolve(compilers);
|
||||
});
|
||||
}).on('error', function (e) {
|
||||
reject(e);
|
||||
}).on('timeout', function () {
|
||||
reject("timeout");
|
||||
});
|
||||
})
|
||||
.on('error', reject)
|
||||
.on('timeout', () => reject("timeout"));
|
||||
request.setTimeout(awsProps('proxyTimeout', 1000));
|
||||
});
|
||||
},
|
||||
host + ":" + port,
|
||||
props('proxyRetries', 5),
|
||||
props('proxyRetryMs', 500))
|
||||
.catch(function () {
|
||||
.catch(() => {
|
||||
logger.warn("Unable to contact " + host + ":" + port + "; skipping");
|
||||
return [];
|
||||
});
|
||||
@@ -403,10 +395,10 @@ function findCompilers() {
|
||||
|
||||
function fetchAws() {
|
||||
logger.info("Fetching instances from AWS");
|
||||
return awsInstances().then(function (instances) {
|
||||
return Promise.all(instances.map(function (instance) {
|
||||
return awsInstances().then(instances => {
|
||||
return Promise.all(instances.map(instance => {
|
||||
logger.info("Checking instance " + instance.InstanceId);
|
||||
var address = instance.PrivateDnsName;
|
||||
let address = instance.PrivateDnsName;
|
||||
if (awsProps("externalTestMode", false)) {
|
||||
address = instance.PublicDnsName;
|
||||
}
|
||||
@@ -419,16 +411,16 @@ function findCompilers() {
|
||||
const base = "compiler." + compilerName + ".";
|
||||
|
||||
function props(propName, def) {
|
||||
var propsForCompiler = parentProps(langId, base + propName, undefined);
|
||||
let propsForCompiler = parentProps(langId, base + propName, undefined);
|
||||
if (propsForCompiler === undefined) {
|
||||
propsForCompiler = parentProps(langId, propName, def);
|
||||
}
|
||||
return propsForCompiler;
|
||||
}
|
||||
|
||||
var supportsBinary = !!props("supportsBinary", true);
|
||||
var supportsExecute = supportsBinary && !!props("supportsExecute", true);
|
||||
var compilerInfo = {
|
||||
const supportsBinary = !!props("supportsBinary", true);
|
||||
const supportsExecute = supportsBinary && !!props("supportsExecute", true);
|
||||
const compilerInfo = {
|
||||
id: compilerName,
|
||||
exe: props("exe", compilerName),
|
||||
name: props("name", compilerName),
|
||||
@@ -469,20 +461,16 @@ function findCompilers() {
|
||||
|
||||
const compilerExes = props(langId, 'compilers', '').split(":").filter(_.identity);
|
||||
logger.debug("Processing compilers from group " + groupName);
|
||||
return Promise.all(compilerExes.map(function (compiler) {
|
||||
return recurseGetCompilers(langId, compiler, props);
|
||||
}));
|
||||
return Promise.all(compilerExes.map(compiler => recurseGetCompilers(langId, compiler, props)));
|
||||
}
|
||||
if (compilerName === "AWS") return fetchAws();
|
||||
return compilerConfigFor(langId, compilerName, parentProps);
|
||||
}
|
||||
|
||||
function getCompilers() {
|
||||
var compilers = [];
|
||||
let compilers = [];
|
||||
_.each(exes, (exs, langId) => {
|
||||
_.each(exs, exe => {
|
||||
compilers.push(recurseGetCompilers(langId, exe, compilerPropsL));
|
||||
});
|
||||
_.each(exs, exe => compilers.push(recurseGetCompilers(langId, exe, compilerPropsL)));
|
||||
});
|
||||
return compilers;
|
||||
}
|
||||
@@ -517,12 +505,12 @@ function ApiHandler(compileHandler) {
|
||||
this.compilers = compilers;
|
||||
};
|
||||
this.handler = express.Router();
|
||||
this.handler.use(function (req, res, next) {
|
||||
this.handler.use((req, res, next) => {
|
||||
res.header("Access-Control-Allow-Origin", "*");
|
||||
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
|
||||
next();
|
||||
});
|
||||
this.handler.get('/compilers', _.bind(function (req, res) {
|
||||
this.handler.get('/compilers', _.bind((req, res) => {
|
||||
if (req.accepts(['text', 'json']) === 'json') {
|
||||
res.set('Content-Type', 'application/json');
|
||||
res.end(JSON.stringify(this.compilers));
|
||||
@@ -531,13 +519,13 @@ function ApiHandler(compileHandler) {
|
||||
var title = 'Compiler Name';
|
||||
var maxLength = _.max(_.pluck(_.pluck(this.compilers, 'id').concat([title]), 'length'));
|
||||
res.write(utils.padRight(title, maxLength) + ' | Description\n');
|
||||
res.end(_.map(this.compilers, function (compiler) {
|
||||
res.end(_.map(this.compilers, compiler => {
|
||||
return utils.padRight(compiler.id, maxLength) + ' | ' + compiler.name;
|
||||
}).join("\n"));
|
||||
}
|
||||
}, this));
|
||||
this.handler.get('/asm/:opcode', asm_doc_api.asmDocsHandler);
|
||||
this.handler.param('compiler', _.bind(function (req, res, next, compilerName) {
|
||||
this.handler.param('compiler', _.bind((req, res, next, compilerName) => {
|
||||
req.compiler = compilerName;
|
||||
next();
|
||||
}, this));
|
||||
@@ -554,12 +542,10 @@ function shortUrlHandler(req, res, next) {
|
||||
var key = aws.getConfig('googleApiKey');
|
||||
var googleApiUrl = 'https://www.googleapis.com/urlshortener/v1/url?shortUrl=http://goo.gl/' +
|
||||
encodeURIComponent(bits[1]) + '&key=' + key;
|
||||
https.get(googleApiUrl, function (response) {
|
||||
https.get(googleApiUrl, response => {
|
||||
var responseText = '';
|
||||
response.on('data', function (d) {
|
||||
responseText += d;
|
||||
});
|
||||
response.on('end', function () {
|
||||
response.on('data', d => responseText += d);
|
||||
response.on('end', () => {
|
||||
if (response.statusCode !== 200) {
|
||||
logger.error("Failed to resolve short URL " + bits[1] + " - got response " +
|
||||
response.statusCode + " : " + responseText);
|
||||
@@ -591,7 +577,7 @@ function shortUrlHandler(req, res, next) {
|
||||
|
||||
|
||||
Promise.all([findCompilers(), aws.initConfig(awsProps)])
|
||||
.then(function (args) {
|
||||
.then(args => {
|
||||
let compilers = args[0];
|
||||
var prevCompilers;
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
sourcepath=./examples/d/
|
||||
extensionRe=.*\.d$
|
||||
1
etc/config/builtin.default.properties
Normal file
1
etc/config/builtin.default.properties
Normal file
@@ -0,0 +1 @@
|
||||
sourcePath=./examples/
|
||||
@@ -1,2 +0,0 @@
|
||||
sourcepath=./examples/go/
|
||||
extensionRe=.*\.go$
|
||||
@@ -1,2 +0,0 @@
|
||||
sourcepath=./examples/haskell/
|
||||
extensionRe=.*\.hs$
|
||||
@@ -1,2 +0,0 @@
|
||||
sourcepath=./examples/ispc/
|
||||
extensionRe=.*\.ispc$
|
||||
@@ -1,2 +0,0 @@
|
||||
sourcepath=./examples/pascal/
|
||||
extensionRe=.*\.pas$
|
||||
@@ -1,2 +0,0 @@
|
||||
sourcepath=./examples/rust/
|
||||
extensionRe=.*\.rs$
|
||||
@@ -1,2 +0,0 @@
|
||||
sourcepath=./examples/swift/
|
||||
extensionRe=.*\.swift$
|
||||
4
examples/c++/default.cpp
Normal file
4
examples/c++/default.cpp
Normal file
@@ -0,0 +1,4 @@
|
||||
// Type your code here, or load an example.
|
||||
int square(int num) {
|
||||
return num * num;
|
||||
}
|
||||
4
examples/c/default.c
Normal file
4
examples/c/default.c
Normal file
@@ -0,0 +1,4 @@
|
||||
// Type your code here, or load an example.
|
||||
int square(int num) {
|
||||
return num * num;
|
||||
}
|
||||
47
examples/cppx/default.cpp
Normal file
47
examples/cppx/default.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
//====================================================================
|
||||
// Library code: implementing the metaclass (once)
|
||||
|
||||
$class basic_value {
|
||||
basic_value() = default;
|
||||
basic_value(const basic_value& that) = default;
|
||||
basic_value(basic_value&& that) = default;
|
||||
basic_value& operator=(const basic_value& that) = default;
|
||||
basic_value& operator=(basic_value&& that) = default;
|
||||
|
||||
constexpr {
|
||||
for... (auto f : $basic_value.variables())
|
||||
if (!f.has_access()) f.make_private();
|
||||
for... (auto f : $basic_value.functions()) {
|
||||
if (!f.has_access()) f.make_public();
|
||||
compiler.require(!f.is_protected(), "a value type may not have a protected function");
|
||||
compiler.require(!f.is_virtual(), "a value type may not have a virtual function");
|
||||
compiler.require(!f.is_destructor() || f.is_public(), "a value destructor must be public");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$class value : basic_value { };
|
||||
|
||||
|
||||
//====================================================================
|
||||
// User code: using the metaclass to write a type (many times)
|
||||
|
||||
value Point {
|
||||
int x = 0, y = 0;
|
||||
Point(int xx, int yy) : x{xx}, y{yy} { }
|
||||
};
|
||||
|
||||
Point get_some_point() { return {1,1}; }
|
||||
|
||||
int main() {
|
||||
|
||||
Point p1(50,100), p2;
|
||||
p2 = get_some_point();
|
||||
p2.x = 42;
|
||||
|
||||
}
|
||||
|
||||
// Compiler Explorer note: Click the "triangle ! icon" to see the output:
|
||||
constexpr {
|
||||
compiler.debug($Point);
|
||||
}
|
||||
4
examples/d/default.d
Normal file
4
examples/d/default.d
Normal file
@@ -0,0 +1,4 @@
|
||||
// Type your code here, or load an example.
|
||||
int square(int num) {
|
||||
return num * num;
|
||||
}
|
||||
9
examples/go/default.go
Normal file
9
examples/go/default.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// Type your code here, or load an example.
|
||||
// Your function name should start with a capital letter.
|
||||
package main
|
||||
|
||||
func Square(x int) int {
|
||||
return x * x
|
||||
}
|
||||
|
||||
func main() {}
|
||||
5
examples/haskell/default.hs
Normal file
5
examples/haskell/default.hs
Normal file
@@ -0,0 +1,5 @@
|
||||
module Example where
|
||||
|
||||
sumOverArray :: [Int] -> Int
|
||||
sumOverArray (x:xs) = x + sumOverArray xs
|
||||
sumOverArray [] = 0
|
||||
4
examples/ispc/default.ispc
Normal file
4
examples/ispc/default.ispc
Normal file
@@ -0,0 +1,4 @@
|
||||
// Type your code here, or load an example.
|
||||
uniform int square(uniform int num) {
|
||||
return num * num;
|
||||
}
|
||||
16
examples/pascal/default.pas
Normal file
16
examples/pascal/default.pas
Normal file
@@ -0,0 +1,16 @@
|
||||
unit output;
|
||||
|
||||
interface
|
||||
|
||||
function Square(const num: Integer): Integer;
|
||||
|
||||
implementation
|
||||
|
||||
// Type your code here, or load an example.
|
||||
|
||||
function Square(const num: Integer): Integer;
|
||||
begin
|
||||
Square := num * num;
|
||||
end;
|
||||
|
||||
end.
|
||||
4
examples/rust/default.rs
Normal file
4
examples/rust/default.rs
Normal file
@@ -0,0 +1,4 @@
|
||||
// Type your code here, or load an example.
|
||||
pub fn square(num: i32) -> i32 {
|
||||
num * num
|
||||
}
|
||||
4
examples/swift/default.swift
Normal file
4
examples/swift/default.swift
Normal file
@@ -0,0 +1,4 @@
|
||||
// Type your code here, or load an example.
|
||||
func square(n: Int) -> Int {
|
||||
return n * n
|
||||
}
|
||||
@@ -25,8 +25,7 @@
|
||||
/*jslint node: true */
|
||||
"use strict";
|
||||
|
||||
var child_process = require('child_process'),
|
||||
temp = require('temp'),
|
||||
var temp = require('temp'),
|
||||
path = require('path'),
|
||||
fs = require('fs-extra'),
|
||||
Promise = require('promise'), // jshint ignore:line
|
||||
@@ -38,12 +37,12 @@ var child_process = require('child_process'),
|
||||
compilerOptInfo = require("compiler-opt-info"),
|
||||
argumentParsers = require("./compilers/argument-parsers"),
|
||||
cfg = require('./cfg'),
|
||||
languages = require('./languages');
|
||||
languages = require('./languages').list;
|
||||
|
||||
function Compile(compiler, env, langId) {
|
||||
this.compiler = compiler;
|
||||
this.lang = langId;
|
||||
this.langInfo = languages.list()[langId];
|
||||
this.langInfo = languages[langId];
|
||||
if (!this.langInfo) {
|
||||
throw new Error("Missing language info for " + langId);
|
||||
}
|
||||
|
||||
249
lib/languages.js
249
lib/languages.js
@@ -35,178 +35,81 @@
|
||||
Leading point is needed
|
||||
Used in: Save to file extension
|
||||
*/
|
||||
function languages() {
|
||||
return {
|
||||
'c++': {
|
||||
id: 'c++',
|
||||
name: 'C++',
|
||||
monaco: 'cppp',
|
||||
extensions: ['.cpp', '.cxx', '.h', '.hpp', '.hxx', '.c'],
|
||||
example: "// Type your code here, or load an example.\n" +
|
||||
"int square(int num) {\n" +
|
||||
" return num * num;\n" +
|
||||
"}\n"
|
||||
},
|
||||
cppx: {
|
||||
id: 'cppx',
|
||||
name: 'Cppx',
|
||||
monaco: 'cppp',
|
||||
extensions: ['.cpp', '.cxx', '.h', '.hpp', '.hxx', '.c'],
|
||||
example: "//====================================================================\n" +
|
||||
"// Library code: implementing the metaclass (once)\n" +
|
||||
"\n" +
|
||||
"$class basic_value {\n" +
|
||||
" basic_value() = default;\n" +
|
||||
" basic_value(const basic_value& that) = default;\n" +
|
||||
" basic_value(basic_value&& that) = default;\n" +
|
||||
" basic_value& operator=(const basic_value& that) = default;\n" +
|
||||
" basic_value& operator=(basic_value&& that) = default;\n" +
|
||||
"\n" +
|
||||
" constexpr {\n" +
|
||||
" for... (auto f : $basic_value.variables())\n" +
|
||||
" if (!f.has_access()) f.make_private();\n" +
|
||||
" for... (auto f : $basic_value.functions()) {\n" +
|
||||
" if (!f.has_access()) f.make_public();\n" +
|
||||
" compiler.require(!f.is_protected(), \"a value type may not have a protected function\");\n" +
|
||||
" compiler.require(!f.is_virtual(), \"a value type may not have a virtual function\");\n" +
|
||||
" compiler.require(!f.is_destructor() || f.is_public(), \"a value destructor must be public\");\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"};\n" +
|
||||
"\n" +
|
||||
"$class value : basic_value { };\n" +
|
||||
"\n" +
|
||||
"\n" +
|
||||
"//====================================================================\n" +
|
||||
"// User code: using the metaclass to write a type (many times)\n" +
|
||||
"\n" +
|
||||
"value Point {\n" +
|
||||
" int x = 0, y = 0;\n" +
|
||||
" Point(int xx, int yy) : x{xx}, y{yy} { }\n" +
|
||||
"};\n" +
|
||||
"\n" +
|
||||
"Point get_some_point() { return {1,1}; }\n" +
|
||||
"\n" +
|
||||
"int main() {\n" +
|
||||
"\n" +
|
||||
" Point p1(50,100), p2;\n" +
|
||||
" p2 = get_some_point();\n" +
|
||||
" p2.x = 42;\n" +
|
||||
"\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"// Compiler Explorer note: Click the \"triangle ! icon\" to see the output:\n" +
|
||||
"constexpr {\n" +
|
||||
" compiler.debug($Point);\n" +
|
||||
"}\n"
|
||||
},
|
||||
c: {
|
||||
id: 'c',
|
||||
name: 'C',
|
||||
monaco: 'c',
|
||||
extensions: ['.c', '.h'],
|
||||
example: "// Type your code here, or load an example.\n" +
|
||||
"int square(int num) {\n" +
|
||||
" return num * num;\n" +
|
||||
"}\n"
|
||||
},
|
||||
rust: {
|
||||
id: 'rust',
|
||||
name: 'Rust',
|
||||
monaco: 'rust',
|
||||
extensions: ['.rs'],
|
||||
example: "// Type your code here, or load an example.\n" +
|
||||
"pub fn square(num: i32) -> i32 {\n" +
|
||||
" num * num\n" +
|
||||
"}\n"
|
||||
},
|
||||
d: {
|
||||
id: 'd',
|
||||
name: 'D',
|
||||
monaco: 'd',
|
||||
extensions: ['.d'],
|
||||
example: "// Type your code here, or load an example.\n" +
|
||||
"int square(int num) {\n" +
|
||||
" return num * num;\n" +
|
||||
"}\n"
|
||||
},
|
||||
go: {
|
||||
id: 'go',
|
||||
name: 'Go',
|
||||
monaco: 'go',
|
||||
extensions: ['.go'],
|
||||
example: "// Type your code here, or load an example.\n" +
|
||||
"// Your function name should start with a capital letter.\n" +
|
||||
"package main\n" +
|
||||
"\n" +
|
||||
"func Square(x int) int {\n" +
|
||||
" return x * x\n" +
|
||||
"}\n" +
|
||||
"\n" +
|
||||
"func main() {}\n"
|
||||
},
|
||||
ispc: {
|
||||
id: 'ispc',
|
||||
name: 'ispc',
|
||||
monaco: 'ispc',
|
||||
extensions: ['.ispc'],
|
||||
example: "// Type your code here, or load an example.\n" +
|
||||
"uniform int square(uniform int num) {\n" +
|
||||
" return num * num;\n" +
|
||||
"}\n"
|
||||
},
|
||||
haskell: {
|
||||
id: 'haskell',
|
||||
name: 'Haskell',
|
||||
monaco: 'haskell',
|
||||
extensions: ['.hs', '.haskell'],
|
||||
example: "module Example where\n" +
|
||||
"\n" +
|
||||
"sumOverArray :: [Int] -> Int\n" +
|
||||
"sumOverArray (x:xs) = x + sumOverArray xs\n" +
|
||||
"sumOverArray [] = 0\n"
|
||||
},
|
||||
swift: {
|
||||
id: 'swift',
|
||||
name: 'Swift',
|
||||
monaco: 'swift',
|
||||
extensions: ['.swift'],
|
||||
example: "// Type your code here, or load an example.\n" +
|
||||
"func square(n: Int) -> Int {\n" +
|
||||
" return n * n\n" +
|
||||
"}"
|
||||
},
|
||||
pascal: {
|
||||
id: 'pascal',
|
||||
name: 'Pascal',
|
||||
monaco: 'pascal',
|
||||
extenions: ['.pas'],
|
||||
example: "unit output;\n" +
|
||||
"\n" +
|
||||
"interface\n" +
|
||||
"\n" +
|
||||
"function Square(const num: Integer): Integer;\n" +
|
||||
"\n" +
|
||||
"implementation\n" +
|
||||
"\n" +
|
||||
"// Type your code here, or load an example.\n" +
|
||||
"\n" +
|
||||
"function Square(const num: Integer): Integer;\n" +
|
||||
"begin\n" +
|
||||
" Square := num * num;\n" +
|
||||
"end;\n" +
|
||||
"\n" +
|
||||
"end.\n"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var _ = require('underscore-node');
|
||||
|
||||
function asArray() {
|
||||
return _.map(languages(), _.identity);
|
||||
}
|
||||
module.exports = {
|
||||
list: languages,
|
||||
toArray: asArray
|
||||
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');
|
||||
_.each(languages, lang => {
|
||||
try {
|
||||
const example = fs.readFileSync('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
|
||||
};
|
||||
|
||||
@@ -24,34 +24,33 @@
|
||||
|
||||
(function () {
|
||||
|
||||
var props = require('../properties.js'),
|
||||
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))
|
||||
}));
|
||||
|
||||
var sourcePath = props.get('builtin', 'sourcepath', './examples/c++');
|
||||
var sourceMatch = new RegExp(props.get('builtin', 'extensionRe', '.*\\.cpp$'));
|
||||
var examples = fs.readdirSync(sourcePath)
|
||||
.filter(function (file) {
|
||||
return file.match(sourceMatch);
|
||||
})
|
||||
.map(function (file) {
|
||||
var nicename = file.replace(/\.cpp$/, '');
|
||||
return {urlpart: nicename, name: nicename.replace(/_/g, ' '), path: path.join(sourcePath, file)};
|
||||
}).sort(function (x, y) {
|
||||
return x.name.localeCompare(y.name);
|
||||
});
|
||||
var byUrlpart = {};
|
||||
examples.forEach(function (e) {
|
||||
byUrlpart[e.urlpart] = e.path;
|
||||
});
|
||||
|
||||
function load(filename, callback) {
|
||||
var path = byUrlpart[filename];
|
||||
if (!path) {
|
||||
function load(lang, filename, callback) {
|
||||
const example = _.find(examples, example => example.lang === lang && example.file === filename);
|
||||
if (!example) {
|
||||
callback("No such path");
|
||||
return;
|
||||
}
|
||||
fs.readFile(path, 'utf-8', function (err, res) {
|
||||
fs.readFile(example.path, 'utf-8', (err, res) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
@@ -61,8 +60,8 @@
|
||||
}
|
||||
|
||||
function list(callback) {
|
||||
callback(null, examples.map(function (example) {
|
||||
return {urlpart: example.urlpart, name: example.name};
|
||||
callback(null, examples.map(example => {
|
||||
return {file: example.file, name: example.name, lang: example.lang};
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -127,12 +127,14 @@ define(function (require) {
|
||||
items: this.compiler ? [this.compiler.id] : []
|
||||
}).on('change', _.bind(function (e) {
|
||||
var val = $(e.target).val();
|
||||
ga('send', {
|
||||
hitType: 'event',
|
||||
eventCategory: 'SelectCompiler',
|
||||
eventAction: val
|
||||
});
|
||||
this.onCompilerChange(val);
|
||||
if (val) {
|
||||
ga('send', {
|
||||
hitType: 'event',
|
||||
eventCategory: 'SelectCompiler',
|
||||
eventAction: val
|
||||
});
|
||||
this.onCompilerChange(val);
|
||||
}
|
||||
}, this));
|
||||
var optionsChange = _.debounce(_.bind(function (e) {
|
||||
this.onOptionsChange($(e.target).val());
|
||||
|
||||
@@ -96,6 +96,8 @@ define(function (require) {
|
||||
this.updateEditorCode();
|
||||
}
|
||||
|
||||
this.initLoadSaver();
|
||||
|
||||
var startFolded = /^[/*#;]+\s*setup.*/;
|
||||
if (state.source && state.source.match(startFolded)) {
|
||||
var foldAction = this.editor.getAction('editor.fold');
|
||||
@@ -291,6 +293,7 @@ define(function (require) {
|
||||
this.container.layoutManager.root.contentItems[0];
|
||||
insertPoint.addChild(conformanceConfig);
|
||||
}, this));
|
||||
this.container.setTitle(this.currentLanguage.name + " source #" + this.id);
|
||||
|
||||
this.updateState();
|
||||
}
|
||||
@@ -485,22 +488,26 @@ define(function (require) {
|
||||
}
|
||||
};
|
||||
|
||||
Editor.prototype.initLoadSaver = function () {
|
||||
this.domRoot.find('.load-save')
|
||||
.off('click')
|
||||
.click(_.bind(function () {
|
||||
loadSave.run(_.bind(function (text) {
|
||||
this.setSource(text);
|
||||
this.updateState();
|
||||
this.maybeEmitChange();
|
||||
}, this), this.getSource(), this.currentLanguage);
|
||||
}, this));
|
||||
};
|
||||
|
||||
Editor.prototype.onLanguageChange = function (newLangId) {
|
||||
if (newLangId !== this.currentLanguage.id && languages[newLangId]) {
|
||||
var oldLangId = this.currentLanguage.id;
|
||||
// Save the current source, so we can come back to it later
|
||||
this.editorSourceByLang[oldLangId] = this.getSource();
|
||||
this.currentLanguage = languages[newLangId];
|
||||
this.initLoadSaver();
|
||||
monaco.editor.setModelLanguage(this.editor.getModel(), this.currentLanguage.monaco);
|
||||
this.domRoot.find('.load-save')
|
||||
.off('click')
|
||||
.click(_.bind(function () {
|
||||
loadSave.run(_.bind(function (text) {
|
||||
this.setSource(text);
|
||||
this.updateState();
|
||||
this.maybeEmitChange();
|
||||
}, this), this.getSource(), this.currentLanguage.extensions);
|
||||
}, this));
|
||||
// And now set the editor value to either the saved one or the default to the new lang
|
||||
this.updateEditorCode();
|
||||
this.container.setTitle(this.currentLanguage.name + " source #" + this.id);
|
||||
|
||||
@@ -52,21 +52,29 @@ define(function (require) {
|
||||
this.modal.find('.save-button').click(_.bind(this.onSaveToBrowserStorage, this));
|
||||
this.modal.find('.save-file').click(_.bind(this.onSaveToFile, this));
|
||||
|
||||
this.populateBuiltins();
|
||||
this.fetchBuiltins();
|
||||
}
|
||||
|
||||
LoadSave.prototype.populateBuiltins = function () {
|
||||
LoadSave.prototype.fetchBuiltins = function () {
|
||||
$.getJSON('source/builtin/list', _.bind(function (list) {
|
||||
this.populate(
|
||||
this.modal.find('.examples'),
|
||||
_.map(list, _.bind(function (elem) {
|
||||
return {
|
||||
name: elem.name, load: _.bind(function () {
|
||||
this.doLoad(elem.urlpart);
|
||||
}, this)
|
||||
};
|
||||
}, this)));
|
||||
}, this));
|
||||
this.savedBuiltins = list;
|
||||
}, this))
|
||||
};
|
||||
|
||||
LoadSave.prototype.populateBuiltins = function () {
|
||||
var isVisible = _.bind(function (entry) {
|
||||
return this.currentLanguage && this.currentLanguage.id === entry.lang;
|
||||
}, this);
|
||||
this.populate(this.modal.find('.examples'),
|
||||
_.map(_.filter(this.savedBuiltins, isVisible), _.bind(function (elem) {
|
||||
return {
|
||||
name: elem.name,
|
||||
load: _.bind(function () {
|
||||
this.doLoad(elem);
|
||||
}, this)
|
||||
};
|
||||
}, this))
|
||||
);
|
||||
};
|
||||
|
||||
LoadSave.prototype.populateLocalStorage = function () {
|
||||
@@ -108,13 +116,15 @@ define(function (require) {
|
||||
this.modal.modal('hide');
|
||||
};
|
||||
|
||||
LoadSave.prototype.run = function (onLoad, editorText, extensions) {
|
||||
LoadSave.prototype.run = function (onLoad, editorText, currentLanguage) {
|
||||
this.populateLocalStorage();
|
||||
this.onLoad = onLoad;
|
||||
this.editorText = editorText;
|
||||
// In case we don't send anything...
|
||||
this.extension = extensions[0] || '.txt';
|
||||
this.modal.find('.local-file').attr('accept', _.map(extensions, function (extension) {
|
||||
this.currentLanguage = currentLanguage;
|
||||
this.populateBuiltins();
|
||||
this.extension = currentLanguage.extensions[0] || '.txt';
|
||||
this.modal.find('.local-file').attr('accept', _.map(currentLanguage.extensions, function (extension) {
|
||||
return extension + ', ';
|
||||
}, this));
|
||||
this.modal.modal();
|
||||
@@ -126,6 +136,7 @@ define(function (require) {
|
||||
this.alert.alert("Save name", "Invalid save name");
|
||||
return;
|
||||
}
|
||||
name += " (" + this.currentLanguage.name + ")";
|
||||
var done = _.bind(function () {
|
||||
setLocalFile(name, this.editorText);
|
||||
}, this);
|
||||
@@ -153,11 +164,12 @@ define(function (require) {
|
||||
}
|
||||
};
|
||||
|
||||
LoadSave.prototype.doLoad = function (urlpart) {
|
||||
LoadSave.prototype.doLoad = function (element) {
|
||||
// TODO: handle errors. consider promises...
|
||||
$.getJSON('source/builtin/load/' + urlpart, _.bind(function (response) {
|
||||
this.onLoad(response.file);
|
||||
}, this));
|
||||
$.getJSON('source/builtin/load/' + element.lang + '/' + element.file,
|
||||
_.bind(function (response) {
|
||||
this.onLoad(response.file);
|
||||
}, this));
|
||||
this.modal.modal('hide');
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user