Source code
Revision control
Copy as Markdown
Other Tools
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
// WebAssembly experimental syntax highlight add-on for CodeMirror.
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define(["../../lib/codemirror"], factory);
} else if (typeof exports !== 'undefined') {
} else {
factory(root.CodeMirror);
}
}(this, function (CodeMirror) {
"use strict";
var isWordChar = /[\w\$_\.\\\/@]/;
function createLookupTable(list) {
var obj = Object.create(null);
list.forEach(function (key) {
obj[key] = true;
});
return obj;
}
CodeMirror.defineMode("wasm", function() {
var keywords = createLookupTable([
"function", "import", "export", "table", "memory", "segment", "as", "type",
"of", "from", "typeof", "br", "br_if", "loop", "br_table", "if", "else",
"call", "call_import", "call_indirect", "nop", "unreachable", "var",
"align", "select", "return"]);
var builtins = createLookupTable([
"i32:8", "i32:8u", "i32:8s", "i32:16", "i32:16u", "i32:16s",
"i64:8", "i64:8u", "i64:8s", "i64:16", "i64:16u", "i64:16s",
"i64:32", "i64:32u", "i64:32s",
"i32.add", "i32.sub", "i32.mul", "i32.div_s", "i32.div_u",
"i32.rem_s", "i32.rem_u", "i32.and", "i32.or", "i32.xor",
"i32.shl", "i32.shr_u", "i32.shr_s", "i32.rotr", "i32.rotl",
"i32.eq", "i32.ne", "i32.lt_s", "i32.le_s", "i32.lt_u",
"i32.le_u", "i32.gt_s", "i32.ge_s", "i32.gt_u", "i32.ge_u",
"i32.clz", "i32.ctz", "i32.popcnt", "i32.eqz", "i64.add",
"i64.sub", "i64.mul", "i64.div_s", "i64.div_u", "i64.rem_s",
"i64.rem_u", "i64.and", "i64.or", "i64.xor", "i64.shl",
"i64.shr_u", "i64.shr_s", "i64.rotr", "i64.rotl", "i64.eq",
"i64.ne", "i64.lt_s", "i64.le_s", "i64.lt_u", "i64.le_u",
"i64.gt_s", "i64.ge_s", "i64.gt_u", "i64.ge_u", "i64.clz",
"i64.ctz", "i64.popcnt", "i64.eqz", "f32.add", "f32.sub",
"f32.mul", "f32.div", "f32.min", "f32.max", "f32.abs",
"f32.neg", "f32.copysign", "f32.ceil", "f32.floor", "f32.trunc",
"f32.nearest", "f32.sqrt", "f32.eq", "f32.ne", "f32.lt",
"f32.le", "f32.gt", "f32.ge", "f64.add", "f64.sub", "f64.mul",
"f64.div", "f64.min", "f64.max", "f64.abs", "f64.neg",
"f64.copysign", "f64.ceil", "f64.floor", "f64.trunc", "f64.nearest",
"f64.sqrt", "f64.eq", "f64.ne", "f64.lt", "f64.le", "f64.gt",
"f64.ge", "i32.trunc_s/f32", "i32.trunc_s/f64", "i32.trunc_u/f32",
"i32.trunc_u/f64", "i32.wrap/i64", "i64.trunc_s/f32",
"i64.trunc_s/f64", "i64.trunc_u/f32", "i64.trunc_u/f64",
"i64.extend_s/i32", "i64.extend_u/i32", "f32.convert_s/i32",
"f32.convert_u/i32", "f32.convert_s/i64", "f32.convert_u/i64",
"f32.demote/f64", "f32.reinterpret/i32", "f64.convert_s/i32",
"f64.convert_u/i32", "f64.convert_s/i64", "f64.convert_u/i64",
"f64.promote/f32", "f64.reinterpret/i64", "i32.reinterpret/f32",
"i64.reinterpret/f64"]);
var dataTypes = createLookupTable(["i32", "i64", "f32", "f64"]);
var isUnaryOperator = /[\-!]/;
var operators = createLookupTable([
"+", "-", "*", "/", "/s", "/u", "%", "%s", "%u",
"<<", ">>u", ">>s", ">=", "<=", "==", "!=",
"<s", "<u", "<=s", "<=u", ">=s", ">=u", ">s", ">u",
"<", ">", "=", "&", "|", "^", "!"]);
function tokenBase(stream, state) {
var ch = stream.next();
if (ch === "$") {
stream.eatWhile(isWordChar);
return "variable";
}
if (ch === "@") {
stream.eatWhile(isWordChar);
return "meta";
}
if (ch === '"') {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
}
if (ch == "/") {
if (stream.eat("*")) {
state.tokenize = tokenComment;
return tokenComment(stream, state);
} else if (stream.eat("/")) {
stream.skipToEnd();
return "comment";
}
}
if (/\d/.test(ch) ||
((ch === "-" || ch === "+") && /\d/.test(stream.peek()))) {
stream.eatWhile(/[\w\._\-+]/);
return "number";
}
if (/[\[\]\(\)\{\},:]/.test(ch)) {
return null;
}
if (isUnaryOperator.test(ch)) {
return "operator";
}
stream.eatWhile(isWordChar);
var word = stream.current();
if (word in operators) {
return "operator";
}
if (word in keywords){
return "keyword";
}
if (word in dataTypes) {
if (!stream.eat(":")) {
return "builtin";
}
stream.eatWhile(isWordChar);
word = stream.current();
// fall thru for "builtin" check
}
if (word in builtins) {
return "builtin";
}
if (word === "Temporary") {
// Nightly has header with some text graphics -- skipping it.
state.tokenize = tokenTemporary;
return state.tokenize(stream, state);
}
return null;
}
function tokenComment(stream, state) {
state.commentDepth = 1;
var next;
while ((next = stream.next()) != null) {
if (next === "*" && stream.eat("/")) {
if (--state.commentDepth === 0) {
state.tokenize = null;
return "comment";
}
}
if (next === "/" && stream.eat("*")) {
// Nested comment
state.commentDepth++;
}
}
return "comment";
}
function tokenTemporary(stream, state) {
var next, endState = state.commentState;
// Skipping until "text support (Work In Progress):" is found.
while ((next = stream.next()) != null) {
if (endState === 0 && next === "t") {
endState = 1;
} else if (endState === 1 && next === ":") {
state.tokenize = null;
state.commentState = 0;
endState = 2;
return "comment";
}
}
state.commentState = endState;
return "comment";
}
function tokenString(quote) {
return function(stream, state) {
var escaped = false, next, end = false;
while ((next = stream.next()) != null) {
if (next == quote && !escaped) {
state.tokenize = null;
return "string";
}
escaped = !escaped && next === "\\";
}
return "string";
};
}
return {
startState: function() {
return {tokenize: null, commentState: 0, commentDepth: 0};
},
token: function(stream, state) {
if (stream.eatSpace()) return null;
var style = (state.tokenize || tokenBase)(stream, state);
return style;
}
};
});
CodeMirror.registerHelper("wordChars", "wasm", isWordChar);
CodeMirror.defineMIME("text/wasm", "wasm");
}));