mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 10:33:59 -05:00
Add support for Ruby (#2816)
This commit is contained in:
3
.github/labeler.yml
vendored
3
.github/labeler.yml
vendored
@@ -74,6 +74,9 @@ lang-pascal:
|
||||
lang-python:
|
||||
- lib/compilers/python.js
|
||||
- etc/config/python.*.properties
|
||||
lang-ruby:
|
||||
- lib/compilers/ruby.js
|
||||
- etc/config/ruby.*.properties
|
||||
lang-rust:
|
||||
- lib/compilers/rust.js
|
||||
- etc/config/rust.*.properties
|
||||
|
||||
17
etc/config/ruby.amazon.properties
Normal file
17
etc/config/ruby.amazon.properties
Normal file
@@ -0,0 +1,17 @@
|
||||
compilers=&ruby
|
||||
defaultCompiler=ruby302
|
||||
|
||||
group.ruby.compilers=ruby302:ruby274:ruby268:ruby259
|
||||
group.ruby.isSemVer=true
|
||||
group.ruby.baseName=Ruby
|
||||
group.ruby.groupName=Ruby YARV
|
||||
group.ruby.compilerType=ruby
|
||||
|
||||
compiler.ruby302.semver=3.0.2
|
||||
compiler.ruby302.exe=/opt/compiler-explorer/ruby-3.0.2/bin/ruby
|
||||
compiler.ruby274.semver=2.7.4
|
||||
compiler.ruby274.exe=/opt/compiler-explorer/ruby-2.7.4/bin/ruby
|
||||
compiler.ruby268.semver=2.6.8
|
||||
compiler.ruby268.exe=/opt/compiler-explorer/ruby-2.6.8/bin/ruby
|
||||
compiler.ruby259.semver=2.5.9
|
||||
compiler.ruby259.exe=/opt/compiler-explorer/ruby-2.5.9/bin/ruby
|
||||
6
etc/config/ruby.defaults.properties
Normal file
6
etc/config/ruby.defaults.properties
Normal file
@@ -0,0 +1,6 @@
|
||||
compilers=/usr/bin/ruby
|
||||
supportsBinary=false
|
||||
supportsExecute=true
|
||||
interpreted=true
|
||||
compilerType=ruby
|
||||
disasmScript=
|
||||
38
etc/scripts/ruby/disasm.rb
Normal file
38
etc/scripts/ruby/disasm.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
# Copyright (c) 2021, Compiler Explorer Authors
|
||||
# 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.
|
||||
|
||||
require 'optparse'
|
||||
|
||||
options = {}
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = "Usage: disasm.rb [options]"
|
||||
|
||||
opts.on("-i", "--inputfile FILE", "Use FILE as input") { |v| options[:inputfile] = v }
|
||||
opts.on("-o", "--outputfile FILE", "Use FILE as output") { |v| options[:outputfile] = v }
|
||||
opts.on("-n", "--fname NAME", "Use NAME as input file name") { |v| options[:fname] = v }
|
||||
end.parse!
|
||||
|
||||
src = File.read(options[:inputfile])
|
||||
insns = RubyVM::InstructionSequence.compile(src, options[:fname] || options[:inputfile], options[:inputfile], 1)
|
||||
File.write(options[:outputfile], insns.disassemble)
|
||||
4
examples/ruby/default.rb
Normal file
4
examples/ruby/default.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
# Type your code here, or load an example.
|
||||
def square(num)
|
||||
num * num
|
||||
end
|
||||
@@ -61,6 +61,7 @@ export { PascalWinCompiler } from './pascal-win';
|
||||
export { PPCICompiler } from './ppci';
|
||||
export { PtxAssembler } from './ptxas';
|
||||
export { PythonCompiler } from './python';
|
||||
export { RubyCompiler } from './ruby';
|
||||
export { RustCompiler } from './rust';
|
||||
export { RustcCgGCCCompiler } from './rustc-cg-gcc';
|
||||
export { MrustcCompiler } from './mrustc';
|
||||
|
||||
95
lib/compilers/ruby.js
Normal file
95
lib/compilers/ruby.js
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// 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.
|
||||
|
||||
import path from 'path';
|
||||
|
||||
import { BaseCompiler } from '../base-compiler';
|
||||
import { resolvePathFromAppRoot } from '../utils';
|
||||
|
||||
import { BaseParser } from './argument-parsers';
|
||||
|
||||
export class RubyCompiler extends BaseCompiler {
|
||||
static get key() { return 'ruby'; }
|
||||
|
||||
constructor(compilerInfo, env) {
|
||||
super(compilerInfo, env);
|
||||
this.compiler.demangler = null;
|
||||
this.demanglerClass = null;
|
||||
}
|
||||
|
||||
processAsm(result, filters) {
|
||||
const lineRe = /\(\s*(\d+)\)(?:\[[^\]]+\])?$/;
|
||||
const fileRe = /ISeq:.*?@(.*?):(\d+) /;
|
||||
const baseFile = path.basename(this.compileFilename);
|
||||
|
||||
const bytecodeLines = result.asm.split('\n');
|
||||
|
||||
const bytecodeResult = [];
|
||||
let lastFile = null;
|
||||
let lastLineNo = null;
|
||||
|
||||
for (const line of bytecodeLines) {
|
||||
const match = line.match(lineRe);
|
||||
|
||||
if (match) {
|
||||
lastLineNo = parseInt(match[1]);
|
||||
} else if (!line) {
|
||||
lastFile = null;
|
||||
lastLineNo = null;
|
||||
} else {
|
||||
const fileMatch = line.match(fileRe);
|
||||
if (fileMatch) {
|
||||
lastFile = fileMatch[1];
|
||||
lastLineNo = parseInt(fileMatch[2]);
|
||||
}
|
||||
}
|
||||
|
||||
const file = lastFile == baseFile ? null : lastFile;
|
||||
const result = {text: line, source: {line: lastLineNo, file: file}};
|
||||
bytecodeResult.push(result);
|
||||
}
|
||||
|
||||
return {asm: bytecodeResult};
|
||||
}
|
||||
|
||||
getDisasmScriptPath() {
|
||||
const script = this.compilerProps('disasmScript');
|
||||
|
||||
return script || resolvePathFromAppRoot('etc', 'scripts', 'ruby', 'disasm.rb');
|
||||
}
|
||||
|
||||
optionsForFilter(filters, outputFilename) {
|
||||
return [
|
||||
this.getDisasmScriptPath(),
|
||||
'--outputfile',
|
||||
outputFilename,
|
||||
'--fname',
|
||||
path.basename(this.compileFilename),
|
||||
'--inputfile'];
|
||||
}
|
||||
|
||||
getArgumentParser() {
|
||||
return BaseParser;
|
||||
}
|
||||
}
|
||||
@@ -235,6 +235,13 @@ export const languages = {
|
||||
alias: [],
|
||||
previewFilter: /^\s*#include/,
|
||||
},
|
||||
ruby: {
|
||||
name: 'Ruby',
|
||||
monaco: 'ruby',
|
||||
extensions: ['.rb'],
|
||||
alias: [],
|
||||
monacoDisassembly: 'asmruby',
|
||||
},
|
||||
};
|
||||
|
||||
_.each(languages, (lang, key) => {
|
||||
|
||||
59
static/modes/asmruby-mode.js
Normal file
59
static/modes/asmruby-mode.js
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2021, Compiler Explorer Authors
|
||||
// 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');
|
||||
|
||||
function definition() {
|
||||
return {
|
||||
tokenizer: {
|
||||
root: [
|
||||
[/^(\| )*==.*$/, 'comment'],
|
||||
[/^(\| )*catch type.*$/, 'comment'],
|
||||
[/^(\| )*local table.*$/, 'comment'],
|
||||
[/^(\| )*\[\s*\d+\].*$/, 'comment'],
|
||||
[/^(\| )*\|-+$/, 'comment'],
|
||||
[/^((?:\| )*)(\d+)/, ['comment', { token: 'number', next: '@opcode' }]],
|
||||
[/^((?:\| )*)(\d+)(\s+)/, ['comment', 'number', { token: '', next: '@opcode' }]],
|
||||
],
|
||||
|
||||
opcode: [
|
||||
[/[a-z_]\w*\s*$/, { token: 'keyword', next: '@root' }],
|
||||
[/([a-z_]\w*)(\s+)/, ['keyword', { token: '', next: '@arguments' }]],
|
||||
],
|
||||
|
||||
arguments: [
|
||||
[/(.*?)(\(\s*\d+\)(?:\[[^\]]+\])?)$/, ['', { token: 'comment', next: '@root' }]],
|
||||
[/.*$/, { token: '', next: '@root' }],
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
var def = definition();
|
||||
monaco.languages.register({ id: 'asmruby' });
|
||||
monaco.languages.setMonarchTokensProvider('asmruby', def);
|
||||
|
||||
module.exports = def;
|
||||
@@ -44,6 +44,7 @@ var CompilerPicker = require('../compiler-picker');
|
||||
var Settings = require('../settings');
|
||||
|
||||
require('../modes/asm-mode');
|
||||
require('../modes/asmruby-mode');
|
||||
require('../modes/ptx-mode');
|
||||
|
||||
var OpcodeCache = new LruCache({
|
||||
|
||||
@@ -46,7 +46,7 @@ const staticPath = path.join(distPath, 'static');
|
||||
const webjackJsHack = '.v4.';
|
||||
const plugins = [
|
||||
new MonacoEditorWebpackPlugin({
|
||||
languages: [ 'cpp', 'go', 'pascal', 'python', 'rust', 'swift', 'java', 'kotlin', 'scala' ],
|
||||
languages: [ 'cpp', 'go', 'pascal', 'python', 'rust', 'swift', 'java', 'kotlin', 'scala', 'ruby' ],
|
||||
filename: isDev ? '[name].worker.js' : `[name]${webjackJsHack}worker.[contenthash].js`,
|
||||
}),
|
||||
new CopyWebpackPlugin([
|
||||
|
||||
Reference in New Issue
Block a user