Add support for Nim language

- Add language
- Adds Nim compiler
- supports js, c, c++ outputs (objc not tested)
- prevent --run option
- Basic test for nim

Todos:
- monaco profile for Nim
This commit is contained in:
bastien penavayre
2019-12-24 13:33:11 +01:00
parent 5924fd3bc7
commit 3492287638
9 changed files with 230 additions and 1 deletions

View File

@@ -81,3 +81,4 @@ From oldest to newest contributor, we would like to thank:
- [Sebastian Rath](https://github.com/seb-mtl)
- [Haze Booth](https://github.com/haze)
- [Cassie Jones](https://github.com/porglezomp)
- [Bastien Penavayre](https://github.com/DaemonSnake)

View File

@@ -0,0 +1,6 @@
compilers=/usr/bin/nim
supportsBinary=true
demangler=c++filt
objdumper=objdump
compilerType=nim
binaryHideFuncRe=^(__.*|_(init|start|fini)|(de)?register_tm_clones|call_gmon_start|frame_dummy|.plt.*|.*@plt|_dl_relocate_static_pie)$

9
examples/nim/default.nim Normal file
View File

@@ -0,0 +1,9 @@
# Minimal example
# Allowed commands:
# - "compile", "compileToC", "c" to build C assambly
# - "compileToCpp", "cpp", "cc" to build C++ assambly
# - "compileToOC", "objc" to build objective-C assambly
# - "js" to output js code
# - "check" to check code validity
echo "hello world"

View File

@@ -281,6 +281,13 @@ class RustParser extends BaseParser {
}
}
class NimParser extends BaseParser {
static parse(compiler) {
return NimParser.getOptions(compiler, "-help").then(() => compiler);
}
}
module.exports = {
Base: BaseParser,
Clang: ClangParser,
@@ -289,5 +296,6 @@ module.exports = {
VC: VCParser,
Pascal: PascalParser,
ISPC: ISPCParser,
Rust: RustParser
Rust: RustParser,
Nim: NimParser,
};

118
lib/compilers/nim.js Normal file
View File

@@ -0,0 +1,118 @@
// Copyright (c) 2019, Bastien Penavayre
// 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.
const BaseCompiler = require('../base-compiler'),
_ = require('underscore'),
path = require('path'),
argumentParsers = require("./argument-parsers"),
fs = require('fs-extra');
class NimCompiler extends BaseCompiler {
constructor(info, env) {
super(info, env);
this.compiler.supportsIntel = true;
}
cacheDir(outputFilename) {
return outputFilename + '.cache';
}
optionsForFilter(filters, outputFilename) {
return [
"-o:" + outputFilename, //output file, only for js mode
"--nolinking", //disable linking, only compile to nimcache
"--nimcache:" + this.cacheDir(outputFilename) //output folder for the nimcache
];
}
filterUserOptions(userOptions) {
return userOptions.filter(option => !['--run', '-r'].includes(option));
}
runCompiler(compiler, options, inputFilename, execOptions) {
//Allowed commands
const commands = [
"compile", "compileToC", "c",
"compileToCpp", "cpp", "cc",
"compileToOC", "objc",
"js",
"check"
];
//If none of the allowed commands is present in userOptions compile to C++
if (_.intersection(options, commands).length === 0) {
options.unshift("compileToCpp");
}
return super.runCompiler(compiler, options, inputFilename, execOptions);
}
postProcess(result, outputFilename, filters) {
let options = result.compilationOptions;
let setup = Promise.resolve("");
const cacheDir = this.cacheDir(outputFilename);
const cleanup = () => fs.remove(cacheDir);
if (_.intersection(options, ["js", "check"]).length !== 0)
filters.binary = false;
else {
filters.binary = true;
const isC = ["compile", "compileToC", "c"],
isCpp = ["compileToCpp", "cpp", "cc"],
isObjC = ["compileToOC", "objc"];
let extension;
if (_.intersection(options, isC).length !== 0)
extension = '.c.o';
else if (_.intersection(options, isCpp).length !== 0)
extension = '.cpp.o';
else if (_.intersection(options, isObjC).length !== 0)
extension = '.m.o';
const moduleName = path.basename(result.inputFilename);
const resultName = moduleName + extension;
const objFile = path.join(cacheDir, resultName);
setup = fs.move(objFile, outputFilename);
}
const postProcess = () => super.postProcess(result, outputFilename, filters);
return setup.then(postProcess).finally(cleanup);
}
getSharedLibraryPathsAsArguments(/*libraries*/) {
return [];
}
getArgumentParser() {
return argumentParsers.Nim;
}
isCfgCompiler(/*compilerVersion*/) {
return true;
}
}
module.exports = NimCompiler;

View File

@@ -175,6 +175,12 @@ const languages = {
monaco: 'ada',
extensions: ['.adb', '.ads'],
alias: []
},
nim: {
name: 'Nim',
monaco: 'nim',
extensions: ['.nim'],
alias: []
}
};

27
static/modes/nim-mode.js Normal file
View File

@@ -0,0 +1,27 @@
// Copyright (c) 2019, 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.
"use strict";
var monaco = require('monaco-editor');
monaco.languages.register({id: 'nim'});

View File

@@ -47,6 +47,7 @@ require('../modes/fortran-mode');
require('../modes/zig-mode');
require('../modes/nc-mode');
require('../modes/ada-mode');
require('../modes/nim-mode');
require('selectize');
var loadSave = new loadSaveLib.LoadSave();

53
test/nim-tests.js Normal file
View File

@@ -0,0 +1,53 @@
// Copyright (c) 2019, Bastien Penavayre
// 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.
const chai = require('chai');
const chaiAsPromised = require("chai-as-promised");
const NimCompiler = require('../lib/compilers/nim');
const CompilationEnvironment = require('../lib/compilation-env');
const properties = require('../lib/properties');
chai.use(chaiAsPromised);
chai.should();
const languages = {
nim: {id: 'nim'}
};
const compilerProps = new properties.CompilerProps(languages, properties.fakeProps({}));
describe('Nim', () => {
const ce = new CompilationEnvironment(compilerProps);
const info = {
exe: null,
remote: true,
lang: languages.nim.id
};
it('Nim should not allow --run/-r parameter', () => {
const compiler = new NimCompiler(info, ce);
compiler.filterUserOptions(["hello", "--run", "--something"]).should.deep.equal(["hello", "--something"]);
compiler.filterUserOptions(["hello", "-r", "--something"]).should.deep.equal(["hello", "--something"]);
});
});