aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xapp.js120
-rw-r--r--etc/config/builtin.d.properties2
-rw-r--r--etc/config/builtin.default.properties1
-rw-r--r--etc/config/builtin.go.properties2
-rw-r--r--etc/config/builtin.haskell.properties2
-rw-r--r--etc/config/builtin.ispc.properties2
-rw-r--r--etc/config/builtin.pascal.properties2
-rw-r--r--etc/config/builtin.rust.properties2
-rw-r--r--etc/config/builtin.swift.properties2
-rw-r--r--examples/c++/default.cpp4
-rw-r--r--examples/c/default.c4
-rw-r--r--examples/cppx/default.cpp47
-rw-r--r--examples/d/default.d4
-rw-r--r--examples/go/default.go9
-rw-r--r--examples/haskell/default.hs5
-rw-r--r--examples/ispc/default.ispc4
-rw-r--r--examples/pascal/Max_array.pas (renamed from examples/pascal/max_array.pas)0
-rw-r--r--examples/pascal/Sum_over_array.pas (renamed from examples/pascal/sum_over_array.pas)0
-rw-r--r--examples/pascal/default.pas16
-rw-r--r--examples/rust/default.rs4
-rw-r--r--examples/swift/default.swift4
-rw-r--r--lib/base-compiler.js7
-rw-r--r--lib/languages.js245
-rw-r--r--lib/sources/builtin.js49
-rw-r--r--static/compiler.js14
-rw-r--r--static/editor.js25
-rw-r--r--static/loadSave.js50
27 files changed, 311 insertions, 315 deletions
diff --git a/app.js b/app.js
index 1c9b7346c..9285dca7b 100755
--- a/app.js
+++ b/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;
diff --git a/etc/config/builtin.d.properties b/etc/config/builtin.d.properties
deleted file mode 100644
index bfc5e8548..000000000
--- a/etc/config/builtin.d.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-sourcepath=./examples/d/
-extensionRe=.*\.d$
diff --git a/etc/config/builtin.default.properties b/etc/config/builtin.default.properties
new file mode 100644
index 000000000..0ebf27c6a
--- /dev/null
+++ b/etc/config/builtin.default.properties
@@ -0,0 +1 @@
+sourcePath=./examples/ \ No newline at end of file
diff --git a/etc/config/builtin.go.properties b/etc/config/builtin.go.properties
deleted file mode 100644
index 1fd2bfefc..000000000
--- a/etc/config/builtin.go.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-sourcepath=./examples/go/
-extensionRe=.*\.go$
diff --git a/etc/config/builtin.haskell.properties b/etc/config/builtin.haskell.properties
deleted file mode 100644
index c865078c3..000000000
--- a/etc/config/builtin.haskell.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-sourcepath=./examples/haskell/
-extensionRe=.*\.hs$
diff --git a/etc/config/builtin.ispc.properties b/etc/config/builtin.ispc.properties
deleted file mode 100644
index eff778fcc..000000000
--- a/etc/config/builtin.ispc.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-sourcepath=./examples/ispc/
-extensionRe=.*\.ispc$
diff --git a/etc/config/builtin.pascal.properties b/etc/config/builtin.pascal.properties
deleted file mode 100644
index 79dea28bb..000000000
--- a/etc/config/builtin.pascal.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-sourcepath=./examples/pascal/
-extensionRe=.*\.pas$
diff --git a/etc/config/builtin.rust.properties b/etc/config/builtin.rust.properties
deleted file mode 100644
index c61faaa7c..000000000
--- a/etc/config/builtin.rust.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-sourcepath=./examples/rust/
-extensionRe=.*\.rs$
diff --git a/etc/config/builtin.swift.properties b/etc/config/builtin.swift.properties
deleted file mode 100644
index 77f22f08e..000000000
--- a/etc/config/builtin.swift.properties
+++ /dev/null
@@ -1,2 +0,0 @@
-sourcepath=./examples/swift/
-extensionRe=.*\.swift$
diff --git a/examples/c++/default.cpp b/examples/c++/default.cpp
new file mode 100644
index 000000000..e8c4fe4ec
--- /dev/null
+++ b/examples/c++/default.cpp
@@ -0,0 +1,4 @@
+// Type your code here, or load an example.
+int square(int num) {
+ return num * num;
+} \ No newline at end of file
diff --git a/examples/c/default.c b/examples/c/default.c
new file mode 100644
index 000000000..e8c4fe4ec
--- /dev/null
+++ b/examples/c/default.c
@@ -0,0 +1,4 @@
+// Type your code here, or load an example.
+int square(int num) {
+ return num * num;
+} \ No newline at end of file
diff --git a/examples/cppx/default.cpp b/examples/cppx/default.cpp
new file mode 100644
index 000000000..503cffe41
--- /dev/null
+++ b/examples/cppx/default.cpp
@@ -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);
+}
diff --git a/examples/d/default.d b/examples/d/default.d
new file mode 100644
index 000000000..3cb5a30c3
--- /dev/null
+++ b/examples/d/default.d
@@ -0,0 +1,4 @@
+// Type your code here, or load an example.
+int square(int num) {
+ return num * num;
+}
diff --git a/examples/go/default.go b/examples/go/default.go
new file mode 100644
index 000000000..65be52b7a
--- /dev/null
+++ b/examples/go/default.go
@@ -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() {}
diff --git a/examples/haskell/default.hs b/examples/haskell/default.hs
new file mode 100644
index 000000000..97106284d
--- /dev/null
+++ b/examples/haskell/default.hs
@@ -0,0 +1,5 @@
+module Example where
+
+sumOverArray :: [Int] -> Int
+sumOverArray (x:xs) = x + sumOverArray xs
+sumOverArray [] = 0
diff --git a/examples/ispc/default.ispc b/examples/ispc/default.ispc
new file mode 100644
index 000000000..0924dc0b6
--- /dev/null
+++ b/examples/ispc/default.ispc
@@ -0,0 +1,4 @@
+// Type your code here, or load an example.
+uniform int square(uniform int num) {
+ return num * num;
+}
diff --git a/examples/pascal/max_array.pas b/examples/pascal/Max_array.pas
index ebacc2b3b..ebacc2b3b 100644
--- a/examples/pascal/max_array.pas
+++ b/examples/pascal/Max_array.pas
diff --git a/examples/pascal/sum_over_array.pas b/examples/pascal/Sum_over_array.pas
index 714a4f6c9..714a4f6c9 100644
--- a/examples/pascal/sum_over_array.pas
+++ b/examples/pascal/Sum_over_array.pas
diff --git a/examples/pascal/default.pas b/examples/pascal/default.pas
new file mode 100644
index 000000000..eddb3978a
--- /dev/null
+++ b/examples/pascal/default.pas
@@ -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.
diff --git a/examples/rust/default.rs b/examples/rust/default.rs
new file mode 100644
index 000000000..ff272bd4d
--- /dev/null
+++ b/examples/rust/default.rs
@@ -0,0 +1,4 @@
+// Type your code here, or load an example.
+pub fn square(num: i32) -> i32 {
+ num * num
+}
diff --git a/examples/swift/default.swift b/examples/swift/default.swift
new file mode 100644
index 000000000..af4a0979c
--- /dev/null
+++ b/examples/swift/default.swift
@@ -0,0 +1,4 @@
+// Type your code here, or load an example.
+func square(n: Int) -> Int {
+ return n * n
+} \ No newline at end of file
diff --git a/lib/base-compiler.js b/lib/base-compiler.js
index 94e7504ab..76ad5b5fc 100644
--- a/lib/base-compiler.js
+++ b/lib/base-compiler.js
@@ -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);
}
diff --git a/lib/languages.js b/lib/languages.js
index 0f5665de1..55dbc275e 100644
--- a/lib/languages.js
+++ b/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');
+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.";
+ }
+});
-function asArray() {
- return _.map(languages(), _.identity);
-}
module.exports = {
- list: languages,
- toArray: asArray
+ list: languages
};
diff --git a/lib/sources/builtin.js b/lib/sources/builtin.js
index bab8f74f2..4baaa49f5 100644
--- a/lib/sources/builtin.js
+++ b/lib/sources/builtin.js
@@ -24,34 +24,33 @@
(function () {
- var props = require('../properties.js'),
+ const props = require('../properties.js'),
path = require('path'),
- fs = require('fs');
-
- 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;
- });
+ 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))
+ }));
- 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};
}));
}
diff --git a/static/compiler.js b/static/compiler.js
index 4f1b61ebe..cfd0eabb3 100644
--- a/static/compiler.js
+++ b/static/compiler.js
@@ -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());
diff --git a/static/editor.js b/static/editor.js
index e820db208..4dc58a4d7 100644
--- a/static/editor.js
+++ b/static/editor.js
@@ -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);
diff --git a/static/loadSave.js b/static/loadSave.js
index 884e87088..371df3eaa 100644
--- a/static/loadSave.js
+++ b/static/loadSave.js
@@ -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');
};