mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 10:33:59 -05:00
New Language: V (#5297)
V (`vlang`) is a simple, fast and safe general purpose programming language compiling to human-readable C. #### Key features of V: - simplicity, "only one way to do things" - performance as fast as C - safety: no null, no globals, no undefined behavior, immutability - automatic C to V translation, good C interoperability - hot code reloading - flexible memory management (GC by default, manual, arena allocation, autofree) - other compilation backends like JavaScript, `native` (wip), `wasm` (wip) or interpreted #### Links: Source code: https://github.com/vlang/v Official website: https://vlang.io Web playground: https://play.vlang.io/ infra PR: https://github.com/compiler-explorer/infra/pull/1058 #### Things this PR adds: - General support for V - Code inspection for the C, Go and JavaScript backends - Support for the v formatter `v fmt` - Some V example code #### Things not implemented: - Support for binary-output backends like `native` and `wasm` - Support for running programs <!-- THIS COMMENT IS INVISIBLE IN THE FINAL PR, BUT FEEL FREE TO REMOVE IT Thanks for taking the time to improve CE. We really appreciate it. Before opening the PR, please make sure that the tests & linter pass their checks, by running `make check`. In the best case scenario, you are also adding tests to back up your changes, but don't sweat it if you don't. We can discuss them at a later date. Feel free to append your name to the CONTRIBUTORS.md file Thanks again, we really appreciate this! --> --------- Co-authored-by: Matt Godbolt <matt@godbolt.org>
This commit is contained in:
4
.github/labeler.yml
vendored
4
.github/labeler.yml
vendored
@@ -181,6 +181,10 @@ lang-toit:
|
||||
lang-typescript:
|
||||
- lib/compilers/typescript.js
|
||||
- etc/config/typescript.*.properties
|
||||
lang-v:
|
||||
- lib/compilers/v.ts
|
||||
- etc/config/v.*.properties
|
||||
- static/modes/v-mode.ts
|
||||
lang-vala:
|
||||
- lib/compilers/vala.ts
|
||||
- etc/config/vala.*.properties
|
||||
|
||||
@@ -133,4 +133,5 @@ From oldest to newest contributor, we would like to thank:
|
||||
- [Vlad Serebrennikov](https://github.com/endilll)
|
||||
- [Mauro Baladés](https://github.com/mauro-balades)
|
||||
- [Jorge López](https://github.com/jolopezl)
|
||||
- [Spydr06](https://github.com/spydr06)
|
||||
- [Simon Sobisch](https://github.com/GitMensch)
|
||||
|
||||
@@ -41,7 +41,7 @@ useninja=false
|
||||
ld=/usr/bin/ld
|
||||
readelf=/usr/bin/readelf
|
||||
|
||||
formatters=clangformat:rustfmt:gofmt:dartformat
|
||||
formatters=clangformat:rustfmt:gofmt:dartformat:vfmt
|
||||
formatter.clangformat.name=clang-format
|
||||
formatter.clangformat.exe=/opt/compiler-explorer/clang-trunk/bin/clang-format
|
||||
formatter.clangformat.styles=Google:LLVM:Mozilla:Chromium:WebKit:Microsoft:GNU
|
||||
@@ -59,6 +59,10 @@ formatter.dartformat.name=dartformat
|
||||
formatter.dartformat.exe=/opt/compiler-explorer/dart-2.16.1/bin/dart
|
||||
formatter.dartformat.styles=
|
||||
formatter.dartformat.type=dartformat
|
||||
formatter.vfmt.name=vfmt
|
||||
formatter.vfmt.exe=/opt/compiler-explorer/v-2023.30/v
|
||||
formatter.vfmt.styles=
|
||||
formatter.vfmt.type=vfmt
|
||||
|
||||
thirdPartyIntegrationEnabled=true
|
||||
statusTrackingEnabled=true
|
||||
|
||||
17
etc/config/v.amazon.properties
Normal file
17
etc/config/v.amazon.properties
Normal file
@@ -0,0 +1,17 @@
|
||||
compilers=&v
|
||||
compilerType=v
|
||||
versionFlag=--version
|
||||
objdumper=/opt/compiler-explorer/gcc-12.1.0/bin/objdump
|
||||
defaultCompiler=v04
|
||||
externalparser=CEAsmParser
|
||||
externalparser.exe=/usr/local/bin/asm-parser
|
||||
supportsBinary=false
|
||||
supportsExecute=false
|
||||
|
||||
group.v.compilers=v04
|
||||
group.v.groupName=V
|
||||
group.v.licenseName=MIT License
|
||||
group.v.licenseLink=https://raw.githubusercontent.com/vlang/v/master/LICENSE
|
||||
|
||||
compiler.v04.exe=/opt/compiler-explorer/v-2023.30/v
|
||||
compiler.v04.name=V 0.4
|
||||
15
etc/config/v.defaults.properties
Normal file
15
etc/config/v.defaults.properties
Normal file
@@ -0,0 +1,15 @@
|
||||
# Default settings for V
|
||||
|
||||
objdumper=objdump
|
||||
supportsBinary=false
|
||||
supportsExecute=false
|
||||
versionFlag=--version
|
||||
compilerType=v
|
||||
|
||||
compilers=v
|
||||
defaultCompiler=v
|
||||
|
||||
compiler.v.exe=/usr/local/bin/v
|
||||
compiler.v.name=V
|
||||
|
||||
libs=
|
||||
12
examples/v/Sum_over_array.v
Normal file
12
examples/v/Sum_over_array.v
Normal file
@@ -0,0 +1,12 @@
|
||||
import arrays
|
||||
|
||||
fn sum_array(array []int) !int {
|
||||
return arrays.reduce(array, fn (acc int, i int) int {
|
||||
return acc + i
|
||||
})
|
||||
}
|
||||
|
||||
fn main() {
|
||||
a := [1, 2, 3, 4, 5]
|
||||
println(sum_array(a) or { 0 })
|
||||
}
|
||||
7
examples/v/default.v
Normal file
7
examples/v/default.v
Normal file
@@ -0,0 +1,7 @@
|
||||
fn square(num int) int {
|
||||
return num * num
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println(square(3))
|
||||
}
|
||||
3
examples/v/helloworld.v
Normal file
3
examples/v/helloworld.v
Normal file
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println('Hello, World!')
|
||||
}
|
||||
@@ -109,6 +109,7 @@ export {TinyCCompiler} from './tinyc.js';
|
||||
export {ToitCompiler} from './toit.js';
|
||||
export {TurboCCompiler} from './turboc.js';
|
||||
export {TypeScriptNativeCompiler} from './typescript-native.js';
|
||||
export {VCompiler} from './v.js';
|
||||
export {ValaCompiler} from './vala.js';
|
||||
export {VBCompiler} from './dotnet.js';
|
||||
export {V8Compiler} from './v8.js';
|
||||
|
||||
211
lib/compilers/v.ts
Normal file
211
lib/compilers/v.ts
Normal file
@@ -0,0 +1,211 @@
|
||||
// Copyright (c) 2023, 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 {unwrap} from '../assert.js';
|
||||
import {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
|
||||
import {BaseCompiler} from '../base-compiler.js';
|
||||
import { ExecutionOptions } from '../../types/compilation/compilation.interfaces.js';
|
||||
|
||||
const V_DEFAULT_BACKEND = 'c';
|
||||
|
||||
export class VCompiler extends BaseCompiler {
|
||||
outputFileExt = `.${V_DEFAULT_BACKEND}`;
|
||||
|
||||
static get key() {
|
||||
return 'v';
|
||||
}
|
||||
|
||||
override optionsForFilter(filters: ParseFiltersAndOutputOptions, outputFilename: string, userOptions?: string[]) {
|
||||
const options = unwrap(userOptions);
|
||||
if (options) {
|
||||
if (options.includes('-h') || options.includes('--help')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const backend = this.getBackendFromOptions(options);
|
||||
const outputFileExt = this.getFileExtForBackend(backend);
|
||||
if (outputFileExt !== undefined) {
|
||||
this.outputFileExt = outputFileExt;
|
||||
}
|
||||
}
|
||||
|
||||
const compilerOptions: string[] = [];
|
||||
if (!filters.binary) {
|
||||
compilerOptions.push('-o');
|
||||
compilerOptions.push(this.filename(this.patchOutputFilename(outputFilename)));
|
||||
}
|
||||
|
||||
if (!filters.labels) {
|
||||
compilerOptions.push('-skip-unused');
|
||||
}
|
||||
|
||||
return compilerOptions;
|
||||
}
|
||||
|
||||
override async processAsm(result: any, filters, options: string[]): Promise<any> {
|
||||
const backend = this.getBackendFromOptions(options);
|
||||
switch (backend) {
|
||||
case 'c':
|
||||
case 'js':
|
||||
case 'js_node':
|
||||
case 'js_browser':
|
||||
case 'js_freestanding':
|
||||
case 'go':
|
||||
return this.processCLike(result, filters);
|
||||
default:
|
||||
return this.asm.process(result.asm, filters);
|
||||
}
|
||||
}
|
||||
|
||||
override getSharedLibraryPathsAsArguments(libraries, libDownloadPath) {
|
||||
return [];
|
||||
}
|
||||
|
||||
override getSharedLibraryLinks(libraries: any[]): string[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
override getOutputFilename(dirPath: string, outputFilebase: string, key?: any): string {
|
||||
return path.join(dirPath, 'output' + this.outputFileExt);
|
||||
}
|
||||
|
||||
override getDefaultExecOptions(): ExecutionOptions & { env: Record<string, string>; } {
|
||||
const options = super.getDefaultExecOptions();
|
||||
options.env['VMODULES'] = path.join(path.dirname(this.compiler.exe), '.vmodules');
|
||||
return options;
|
||||
}
|
||||
|
||||
getBackendFromOptions(options: string[]): string {
|
||||
const backendOpt = options.indexOf('-b');
|
||||
if (backendOpt >= 0 && options[backendOpt + 1]) return options[backendOpt + 1].toLowerCase();
|
||||
if (options.includes('-native')) return 'native';
|
||||
if (options.includes('-interpret')) return 'interpret';
|
||||
|
||||
return V_DEFAULT_BACKEND; // default V backend
|
||||
}
|
||||
|
||||
getFileExtForBackend(backend: string): string | undefined {
|
||||
switch (backend) {
|
||||
case 'c':
|
||||
case 'go':
|
||||
case 'wasm':
|
||||
return '.' + backend;
|
||||
case 'js':
|
||||
case 'js_node':
|
||||
case 'js_browser':
|
||||
case 'js_freestanding':
|
||||
return '.js';
|
||||
case 'native':
|
||||
return '';
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
patchOutputFilename(outputFilename: string): string {
|
||||
const parts = outputFilename.split('.');
|
||||
|
||||
if (this.outputFileExt === '') {
|
||||
parts.pop();
|
||||
return parts.join('.');
|
||||
}
|
||||
|
||||
parts[parts.length - 1] = this.outputFileExt.split('.')[1];
|
||||
return parts.join('.');
|
||||
}
|
||||
|
||||
removeUnusedLabels(input: string[]): string[] {
|
||||
const output: string[] = [];
|
||||
|
||||
const lineRe = /^.*main__.*$/;
|
||||
const mainFunctionCall = '\tmain__main();';
|
||||
|
||||
let scopeDepth = 0;
|
||||
let insertNewLine = false;
|
||||
|
||||
for (const lineNo in input) {
|
||||
const line = input[lineNo];
|
||||
if (!line) continue;
|
||||
|
||||
if (insertNewLine) {
|
||||
output.push('');
|
||||
insertNewLine = false;
|
||||
}
|
||||
|
||||
if ((scopeDepth === 0 && line.match(lineRe) && line !== mainFunctionCall) || scopeDepth > 0) {
|
||||
const opening = (line.match(/{/g) || []).length - 1;
|
||||
const closing = (line.match(/}/g) || []).length - 1;
|
||||
scopeDepth += opening - closing;
|
||||
|
||||
output.push(line);
|
||||
|
||||
insertNewLine = scopeDepth === 0;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
removeWhitespaceLines = (input: string[]) => input.map(line => line.trimStart()).filter(line => line !== '');
|
||||
removeComments = (input: string[]) =>
|
||||
input
|
||||
.filter(line => !line.trimStart().startsWith('//'))
|
||||
.map(line => line.split('//')[0].replaceAll(/(\/\*).*?(\*\/)/g, ''));
|
||||
removeDirectives = (input: string[]) => input.filter(line => !line.trimStart().startsWith('#'));
|
||||
|
||||
async processCLike(result, filters): Promise<any> {
|
||||
let lines = result.asm.split('\n');
|
||||
|
||||
// remove non-user defined code
|
||||
if (!filters.labels) lines = this.removeUnusedLabels(lines);
|
||||
|
||||
// remove comments
|
||||
if (!filters.commentOnly) lines = this.removeComments(lines);
|
||||
|
||||
// remove whitespace
|
||||
if (filters.trim) lines = this.removeWhitespaceLines(lines);
|
||||
|
||||
// remove preprocessor directives
|
||||
if (!filters.directives) lines = this.removeDirectives(lines);
|
||||
|
||||
// finally, remove unnecessary newlines to make the output nicer
|
||||
const finalLines: string[] = [];
|
||||
let emptyLineEncountered = false;
|
||||
|
||||
for (const lineNo in lines) {
|
||||
const line = lines[lineNo];
|
||||
|
||||
if (line.trimStart() === '') {
|
||||
if (emptyLineEncountered) continue;
|
||||
emptyLineEncountered = true;
|
||||
} else emptyLineEncountered = false;
|
||||
|
||||
finalLines.push(line);
|
||||
}
|
||||
|
||||
return {asm: finalLines.map(line => ({text: line}))};
|
||||
}
|
||||
}
|
||||
@@ -26,3 +26,4 @@ export {ClangFormatFormatter} from './clang-format.js';
|
||||
export {DartFormatFormatter} from './dartformat.js';
|
||||
export {GoFmtFormatter} from './gofmt.js';
|
||||
export {RustFmtFormatter} from './rustfmt.js';
|
||||
export {VFmtFormatter} from './vfmt.js';
|
||||
|
||||
52
lib/formatters/vfmt.ts
Normal file
52
lib/formatters/vfmt.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2023, 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 {UnprocessedExecResult} from '../../types/execution/execution.interfaces.js';
|
||||
import {FormatOptions} from './base.interfaces.js';
|
||||
import {BaseFormatter} from './base.js';
|
||||
|
||||
import * as exec from '../exec.js';
|
||||
|
||||
export class VFmtFormatter extends BaseFormatter {
|
||||
static get key() {
|
||||
return 'vfmt';
|
||||
}
|
||||
|
||||
/**
|
||||
* Format the provided source code
|
||||
*
|
||||
* This function does not use any options, because v fmt does not have any
|
||||
* options except the default provided ones (v fmt -w <file.v>).
|
||||
*/
|
||||
override async format(source: string, options: FormatOptions): Promise<UnprocessedExecResult> {
|
||||
return await exec.execute(this.formatterInfo.exe, ['fmt', '-w'], {input: source});
|
||||
}
|
||||
|
||||
/**
|
||||
* v fmt has no styling options
|
||||
*/
|
||||
override isValidStyle(style: string): boolean {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -648,6 +648,17 @@ const definitions: Record<LanguageKey, LanguageDefinition> = {
|
||||
previewFilter: null,
|
||||
monacoDisassembly: null,
|
||||
},
|
||||
v: {
|
||||
name: 'V',
|
||||
monaco: 'v',
|
||||
extensions: ['.v', '.vsh'],
|
||||
alias: [],
|
||||
logoUrl: 'v.svg',
|
||||
logoUrlDark: null,
|
||||
formatter: 'vfmt',
|
||||
previewFilter: null,
|
||||
monacoDisassembly: 'nc',
|
||||
},
|
||||
vala: {
|
||||
name: 'Vala',
|
||||
monaco: 'vala',
|
||||
|
||||
@@ -104,3 +104,4 @@ register('nc', 'clangformat', false);
|
||||
register('go', 'gofmt', true);
|
||||
register('rust', 'rustfmt', true);
|
||||
register('dart', 'dartformat', true);
|
||||
register('v', 'vfmt', true);
|
||||
|
||||
@@ -57,5 +57,6 @@ import './ocaml-mode';
|
||||
import './openclc-mode';
|
||||
import './ptx-mode';
|
||||
import './spirv-mode';
|
||||
import './v-mode';
|
||||
import './vala-mode';
|
||||
import './zig-mode';
|
||||
|
||||
252
static/modes/v-mode.ts
Normal file
252
static/modes/v-mode.ts
Normal file
@@ -0,0 +1,252 @@
|
||||
// Copyright (c) 2023, 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 * as monaco from 'monaco-editor';
|
||||
|
||||
function definition(): monaco.languages.IMonarchLanguage {
|
||||
return {
|
||||
defaultToken: 'invalid',
|
||||
|
||||
keywords: [
|
||||
'__global',
|
||||
'_likely_',
|
||||
'_unlikely_',
|
||||
'as',
|
||||
'asm',
|
||||
'assert',
|
||||
'atomic',
|
||||
'break',
|
||||
'const',
|
||||
'continue',
|
||||
'defer',
|
||||
'dump',
|
||||
'else',
|
||||
'enum',
|
||||
'false',
|
||||
'fn',
|
||||
'for',
|
||||
'go',
|
||||
'goto',
|
||||
'if',
|
||||
'import',
|
||||
'in',
|
||||
'interface',
|
||||
'is',
|
||||
'isreftype',
|
||||
'it',
|
||||
'like',
|
||||
'lock',
|
||||
'match',
|
||||
'module',
|
||||
'mut',
|
||||
'nil',
|
||||
'none',
|
||||
'offsetof',
|
||||
'or',
|
||||
'pub',
|
||||
'return',
|
||||
'rlock',
|
||||
'select',
|
||||
'shared',
|
||||
'sizeof',
|
||||
'spawn',
|
||||
'static',
|
||||
'struct',
|
||||
'true',
|
||||
'type',
|
||||
'typeof',
|
||||
'union',
|
||||
'unsafe',
|
||||
'volatile',
|
||||
],
|
||||
|
||||
typeKeywords: [
|
||||
'i8',
|
||||
'u8',
|
||||
'i16',
|
||||
'u16',
|
||||
'int',
|
||||
'u32',
|
||||
'i64',
|
||||
'u64',
|
||||
'f32',
|
||||
'f64',
|
||||
'string',
|
||||
'map',
|
||||
'struct',
|
||||
'bool',
|
||||
'voidptr',
|
||||
'charptr',
|
||||
'isize',
|
||||
'usize',
|
||||
],
|
||||
|
||||
operators: [
|
||||
'+',
|
||||
'-',
|
||||
'*',
|
||||
'/',
|
||||
'%',
|
||||
'^',
|
||||
'~',
|
||||
'|',
|
||||
'#',
|
||||
'&',
|
||||
'++',
|
||||
'--',
|
||||
'&&',
|
||||
'||',
|
||||
'!',
|
||||
'.',
|
||||
'!in',
|
||||
'!is',
|
||||
';',
|
||||
':',
|
||||
'<-',
|
||||
'=',
|
||||
':=',
|
||||
'+=',
|
||||
'-=',
|
||||
'*=',
|
||||
'/=',
|
||||
'%=',
|
||||
'|=',
|
||||
'&=',
|
||||
'>>=',
|
||||
'>>>=',
|
||||
'<<=',
|
||||
'==',
|
||||
'!=',
|
||||
'>',
|
||||
'<',
|
||||
'>=',
|
||||
'<=',
|
||||
'?',
|
||||
'<<',
|
||||
'>>',
|
||||
'>>>',
|
||||
'$',
|
||||
],
|
||||
|
||||
symbols: /[=><!~?:&|+\-*/^%]+/,
|
||||
|
||||
escapes: /\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,
|
||||
|
||||
tokenizer: {
|
||||
root: [
|
||||
// identifiers and keywords
|
||||
[
|
||||
/[a-z_$][\w$]*/,
|
||||
{
|
||||
cases: {
|
||||
'@typeKeywords': 'keyword',
|
||||
'@keywords': 'keyword',
|
||||
'@default': 'identifier',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
[/@[a-zA-Z_$]*/, 'builtin.identifier'],
|
||||
|
||||
[/[A-Z][\w$]*/, 'type.identifier'], // to show class names nicely
|
||||
|
||||
// whitespace
|
||||
{include: '@whitespace'},
|
||||
|
||||
// delimiters and operators
|
||||
[/[{}()[\]]/, '@brackets'],
|
||||
[/[<>](?!@symbols)/, '@brackets'],
|
||||
[
|
||||
/@symbols/,
|
||||
{
|
||||
cases: {
|
||||
'@operators': 'operator',
|
||||
'@default': '',
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
// numbers
|
||||
[/[0-9_]*\.[0-9_]+([eE][-+]?[0-9_]+)?/, 'number.float'],
|
||||
[/0[xX][0-9a-fA-F_]*[0-9a-fA-F_]/, 'number.hex'],
|
||||
[/0o[0-7_]*[0-7_]/, 'number.octal'],
|
||||
[/0[bB][0-1_]*[0-1_]/, 'number.binary'],
|
||||
[/[0-9_]+/, 'number'],
|
||||
|
||||
// delimiter: after number because of .\d floats
|
||||
[/[;,.]/, 'delimiter'],
|
||||
|
||||
// single-quoted strings
|
||||
[/'([^'\\]|\\.)*$/, 'string.invalid'],
|
||||
[/c?\\\\.*$/, 'string'],
|
||||
[/c?'/, 'string', '@single_quoted_string'],
|
||||
|
||||
// double-quoted strings
|
||||
[/"([^"\\]|\\.)*$/, 'string.invalid'], // non-teminated string
|
||||
[/c?\\\\.*$/, 'string'],
|
||||
[/c?"/, 'string', '@double_quoted_string'],
|
||||
|
||||
// runes
|
||||
[/`[^\\`]`/, 'string'],
|
||||
[/(`)(@escapes)(`)/, ['string', 'string.escape', 'string']],
|
||||
[/`/, 'string.invalid'],
|
||||
],
|
||||
|
||||
whitespace: [
|
||||
[/[ \r\n]+/, 'white'],
|
||||
[/\/\*/, 'comment', '@comment'],
|
||||
[/\/\+/, 'comment', '@comment'],
|
||||
[/\/\/.*$/, 'comment'],
|
||||
[/\t/, 'comment.invalid'],
|
||||
],
|
||||
|
||||
comment: [
|
||||
[/[^/*]+/, 'comment'],
|
||||
[/\/\*/, 'comment', '@comment'],
|
||||
[/\*\//, 'comment', '@pop'],
|
||||
[/[/*]/, 'comment'],
|
||||
],
|
||||
|
||||
single_quoted_string: [
|
||||
[/[^\\']+/, 'string'],
|
||||
[/@escapes/, 'string.escape'],
|
||||
[/\\./, 'string.escape.invalid'],
|
||||
[/'/, 'string', '@pop'],
|
||||
],
|
||||
|
||||
double_quoted_string: [
|
||||
[/[^\\"]+/, 'string'],
|
||||
[/@escapes/, 'string.escape'],
|
||||
[/\\./, 'string.escape.invalid'],
|
||||
[/"/, 'string', '@pop'],
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const def = definition();
|
||||
monaco.languages.register({id: 'v'});
|
||||
monaco.languages.setMonarchTokensProvider('v', def);
|
||||
|
||||
export = def;
|
||||
@@ -79,6 +79,7 @@ export type LanguageKey =
|
||||
| 'swift'
|
||||
| 'toit'
|
||||
| 'typescript'
|
||||
| 'v'
|
||||
| 'vala'
|
||||
| 'vb'
|
||||
| 'zig';
|
||||
|
||||
1
views/resources/logos/v.svg
Normal file
1
views/resources/logos/v.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!-- Generator: Gravit.io --><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="isolation:isolate" viewBox="0 0 500 500" width="500px" height="500px"><defs><clipPath id="_clipPath_8TWIgR1z3pxinjWBiigzcEIrVJKv9Gq4"><rect width="500" height="500"/></clipPath></defs><g clip-path="url(#_clipPath_8TWIgR1z3pxinjWBiigzcEIrVJKv9Gq4)"><path d=" M 318.422 453.543 L 463.705 49.541 C 466.168 42.689 462.285 37.693 455.037 38.392 L 340.786 49.398 C 333.539 50.097 325.71 56.246 323.316 63.121 L 188.843 449.216 C 186.447 456.091 190.414 461.673 197.695 461.673 L 308.901 461.673 C 312.541 461.673 316.497 458.893 317.729 455.466 L 318.422 453.543 Z " fill="rgb(83,107,138)"/><defs><filter id="Hmac7mZraFWHw0G84Yxj4QuzeTFp0E7Y" x="-200%" y="-200%" width="400%" height="400%" filterUnits="objectBoundingBox" color-interpolation-filters="sRGB"><feGaussianBlur xmlns="http://www.w3.org/2000/svg" in="SourceGraphic" stdDeviation="6.440413594258542"/><feOffset xmlns="http://www.w3.org/2000/svg" dx="0" dy="0" result="pf_100_offsetBlur"/><feFlood xmlns="http://www.w3.org/2000/svg" flood-color="#000000" flood-opacity="0.65"/><feComposite xmlns="http://www.w3.org/2000/svg" in2="pf_100_offsetBlur" operator="in" result="pf_100_dropShadow"/><feBlend xmlns="http://www.w3.org/2000/svg" in="SourceGraphic" in2="pf_100_dropShadow" mode="normal"/></filter></defs><g filter="url(#Hmac7mZraFWHw0G84Yxj4QuzeTFp0E7Y)"><path d=" M 301.848 455.466 L 241.359 280.725 L 250 275.324 L 311.57 453.543 L 301.848 455.466 Z " fill="rgb(235,235,235)"/></g><path d=" M 44.963 38.392 L 159.214 49.398 C 166.461 50.097 174.298 56.243 176.704 63.115 L 314.022 455.448 C 315.224 458.885 313.245 461.673 309.604 461.673 L 197.695 461.673 C 190.414 461.673 182.502 456.111 180.038 449.259 L 36.295 49.541 C 33.832 42.689 37.715 37.693 44.963 38.392 Z " fill="rgb(93,135,191)"/></g></svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
Reference in New Issue
Block a user