imba
Version:
607 lines (501 loc) • 14.9 kB
JavaScript
import { fnv1a } from '../../vendor/fnv1a.mjs';
function iter$(a){ return a ? (a.toArray ? a.toArray() : a) : []; };
var self = {};
// imba$v2=0
var ansiMap = {
reset: [0,0],
bold: [1,22],
dim: [2,22],
italic: [3,23],
underline: [4,24],
inverse: [7,27],
hidden: [8,28],
strikethrough: [9,29],
black: [30,39],
red: [31,39],
green: [32,39],
yellow: [33,39],
blue: [34,39],
magenta: [35,39],
cyan: [36,39],
white: [37,39],
gray: [90,39],
redBright: [91,39],
greenBright: [92,39],
yellowBright: [93,39],
blueBright: [94,39],
magentaBright: [95,39],
cyanBright: [96,39],
whiteBright: [97,39]
};
var ansi = {
bold: function(text) { return '\u001b[1m' + text + '\u001b[22m'; },
red: function(text) { return '\u001b[31m' + text + '\u001b[39m'; },
green: function(text) { return '\u001b[32m' + text + '\u001b[39m'; },
yellow: function(text) { return '\u001b[33m' + text + '\u001b[39m'; },
blue: function(text) { return '\u001b[94m' + text + '\u001b[39m'; },
gray: function(text) { return '\u001b[90m' + text + '\u001b[39m'; },
white: function(text) { return '\u001b[37m' + text + '\u001b[39m'; },
f: function(name,text) {
let pair = ansiMap[name];
return '\u001b[' + pair[0] + 'm' + text + '\u001b[' + pair[1] + 'm';
}
};
ansi.warn = ansi.yellow;
ansi.error = ansi.red;
var InternalPrefixes = {
TAG: 'τ',
FLIP: 'ω',
VALUE: 'υ',
CACHE: 'ϲ',
KEY: 'κ',
ANY: 'φ',
SYM: 'ε',
SEP: 'ι',
PRIVATE: 'Ψ',
B: 'ι',
T: 'τ',
C: 'ρ',
V: 'υ',
K: 'κ',
D: 'Δ',
H: 'θ',
EXTEND: 'Ω'
};
var ReservedPrefixes = new Set(Object.values(InternalPrefixes));
var ReservedIdentifierRegex = new RegExp("^[" + Array.from(ReservedPrefixes).join("") + "]","u");
var ToJSMap = {
'-': 'Ξ',
'?': 'Φ',
'#': 'Ψ',
'@': 'α'
};
var toJSregex = /[-?#@]/gu;
var toJSreplacer = function(m) { return ToJSMap[m]; };
var toJSIdentifier = self.toJSIdentifier = function (raw){
return raw.replace(toJSregex,toJSreplacer);
};
var ToImbaMap = {
'Ξ': '-',
'Φ': '?',
'Ψ': '#',
'α': '@'
};
var toImbaRegex = new RegExp("[ΞΦΨα]","gu");
var toImbaReplacer = function(m) { return ToImbaMap[m]; };
var toImbaIdentifier = self.toImbaIdentifier = function (raw){
return raw.replace(toImbaRegex,toImbaReplacer);
};
var toCustomTagIdentifier = self.toCustomTagIdentifier = function (str){
return 'Γ' + toJSIdentifier(str);
};
var GreekLetters = "αβγδεζηθικλμνξοπρστυφχψω";
var brace = self.brace = function (str){
var lines = str.match(/\n/);
// what about indentation?
if (lines) {
return '{' + str + '\n}';
} else {
return '{\n' + str + '\n}';
};
};
var normalizeIndentation = self.normalizeIndentation = function (str){
var m;
var reg = /\n+([^\n\S]*)/g;
var ind = null;
var length_;while (m = reg.exec(str)){
var attempt = m[1];
if (ind === null || 0 < (length_ = attempt.length) && length_ < ind.length) {
ind = attempt;
};
};
if (ind) { str = str.replace(RegExp(("\\n" + ind),"g"),'\n') };
return str;
};
var flatten = self.flatten = function (arr){
var out = [];
arr.forEach(function(v) { return (v instanceof Array) ? out.push.apply(out,self.flatten(v)) : out.push(v); });
return out;
};
var clearLocationMarkers = self.clearLocationMarkers = function (str){
return str.replace(/\/\*\%([\w\|]*)\$\*\//g,'');
};
var pascalCase = self.pascalCase = function (str){
return str.replace(/(^|[\-\_\s])(\w)/g,function(m,v,l) { return l.toUpperCase(); });
};
var camelCase = self.camelCase = function (str){
str = String(str);
// should add shortcut out
return str.replace(/([\-\_\s])(\w)/g,function(m,v,l) { return l.toUpperCase(); });
};
var dashToCamelCase = self.dashToCamelCase = function (str){
str = String(str);
if (str.indexOf('-') >= 0) {
// should add shortcut out
str = str.replace(/([\-\s])(\w)/g,function(m,v,l) { return l.toUpperCase(); });
};
return str;
};
var snakeCase = self.snakeCase = function (str){
var str = str.replace(/([\-\s])(\w)/g,'_');
return str.replace(/()([A-Z])/g,"_$1",function(m,v,l) { return l.toUpperCase(); });
};
var dasherize = self.dasherize = function (str){
return str.replace(/([a-z\d])([A-Z])/g,"$1-$2").toLowerCase();
};
var setterSym = self.setterSym = function (sym){
return self.dashToCamelCase(("set-" + sym));
};
var quote = self.quote = function (str){
return '"' + str + '"';
};
var singlequote = self.singlequote = function (str){
return "'" + str + "'";
};
var isValidIdentifier = self.isValidIdentifier = function (str){
return !(/[?-\s]/).test(str) && str[0] != '#';
};
var toValidIdentifier = self.toValidIdentifier = function (str){
return toJSIdentifier(str);
return str.replace(/[-\?]/g,'$'); // .replace(/\?/g,'θ')
};
var fromValidIdentifier = self.fromValidIdentifier = function (str){
return toImbaIdentifier(str);
return str[0] + str.slice(1).replace(/\$$/,'?').replace(/\$/g,'-');
};
var isSystemIdentifier = self.isSystemIdentifier = function (str){
return GreekLetters.indexOf(str[0]) >= 0;
};
var symbolize = self.symbolize = function (str,stack){
str = String(str);
return self.toValidIdentifier(str);
if (stack && stack.tsc() || true) {
return str;
};
var end = str.charAt(str.length - 1);
if (end == '?') {
str = 'is' + str[0].toUpperCase() + str.slice(1,-1);
};
if (str.indexOf("-") >= 0) {
str = str.replace(/([\-\s])(\w)/g,function(m,v,l) { return l.toUpperCase(); });
};
return str;
};
var indent = self.indent = function (str){
return String(str).replace(/^/g,"\t").replace(/\n/g,"\n\t").replace(/\n\t$/g,"\n");
};
var bracketize = self.bracketize = function (str,ind){
if(ind === undefined) ind = true;
if (ind) { str = "\n" + self.indent(str) + "\n" };
return '{' + str + '}';
};
var parenthesize = self.parenthesize = function (str){
return '(' + String(str) + ')';
};
var unionOfLocations = self.unionOfLocations = function (){
var $0 = arguments, i = $0.length;
var locs = new Array(i>0 ? i : 0);
while(i>0) locs[i-1] = $0[--i];
var a = Infinity;
var b = -Infinity;
for (let i = 0, items = iter$(locs), len = items.length, loc; i < len; i++) {
loc = items[i];
if (loc && loc._loc != undefined) {
loc = loc._loc;
};
if (loc && (loc.loc instanceof Function)) {
loc = loc.loc();
};
if (loc instanceof Array) {
if (a > loc[0]) { a = loc[0] };
if (b < loc[0]) { b = loc[1] };
} else if ((typeof loc=='number'||loc instanceof Number)) {
if (a > loc) { a = loc };
if (b < loc) { b = loc };
};
};
return [a,b];
};
var locationToLineColMap = self.locationToLineColMap = function (code){
// TODO support windows
var lines = code.split(/\n/g);
var map = [];
var chr;
var loc = 0;
var col = 0;
var line = 0;
while (chr = code[loc]){
map[loc] = [line,col];
if (chr == '\n') {
line++;
col = 0;
} else {
col++;
};
loc++;
};
map[loc] = [line,col];
map[loc + 1] = [line,col];
return map;
};
var markLineColForTokens = self.markLineColForTokens = function (tokens,code){
return self;
};
var parseArgs = self.parseArgs = function (argv,o){
var env_;
if(o === undefined) o = {};
var aliases = o.alias || (o.alias = {});
var groups = o.group || (o.group = []);
var schema = o.schema || {};
schema.main = {};
var options = {};
var explicit = {};
argv = argv || process.argv.slice(2);
var curr = null;
var i = 0;
var m;
while ((i < argv.length)){
var arg = argv[i];
i++;
if (m = arg.match(/^\-([a-zA-Z]+)(\=\S+)?$/)) {
curr = null;
let chars = m[1].split('');
for (let i = 0, items = iter$(chars), len = items.length, item; i < len; i++) {
// console.log "parsing {item} at {i}",aliases
item = items[i];
var key = aliases[item] || item;
chars[i] = key;
options[key] = true;
};
if (chars.length == 1) {
curr = chars;
};
continue;
} else if (m = arg.match(/^\-\-([a-z0-9\-\_A-Z]+)(\=\S+)?$/)) {
var val = true;
key = m[1];
if (key.indexOf('no-') == 0) {
key = key.substr(3);
val = false;
};
key = self.dashToCamelCase(key);
if (m[2]) {
val = m[2].slice(1);
};
options[key] = val;
curr = key;
continue;
} else {
var desc = schema[curr];
if (!(curr && schema[curr])) {
curr = 'main';
};
if (arg.match(/^\d+$/)) {
arg = parseInt(arg);
};
val = options[curr];
if (val == true || val == false) {
options[curr] = arg;
} else if ((typeof val=='string'||val instanceof String) || (typeof val=='number'||val instanceof Number)) {
options[curr] = [val].concat(arg);
} else if (val instanceof Array) {
val.push(arg);
} else {
options[curr] = arg;
};
if (!(desc && desc.multi)) {
curr = 'main';
};
};
};
for (let j = 0, items = iter$(groups), len = items.length; j < len; j++) {
let name = self.dashToCamelCase(items[j]);
for (let v, i_ = 0, keys = Object.keys(options), l = keys.length, k; i_ < l; i_++){
k = keys[i_];v = options[k];if (k.indexOf(name) == 0) {
let key = k.substr(name.length).replace(/^\w/,function(m) { return m.toLowerCase(); });
if (key) {
options[name] || (options[name] = {});
options[name][key] = v;
} else {
options[name] || (options[name] = {});
};
};
};
};
if ((typeof (env_ = options.env)=='string'||env_ instanceof String)) {
options[("ENV_" + (options.env))] = true;
};
return options;
};
var printExcerpt = self.printExcerpt = function (code,loc,pars){
if(!pars||pars.constructor !== Object) pars = {};
var hl = pars.hl !== undefined ? pars.hl : false;
var gutter = pars.gutter !== undefined ? pars.gutter : true;
var type = pars.type !== undefined ? pars.type : 'warn';
var pad = pars.pad !== undefined ? pars.pad : 2;
var lines = code.split(/\n/g);
var locmap = self.locationToLineColMap(code);
var lc = locmap[loc[0]] || [0,0];
var ln = lc[0];
var col = lc[1];
var line = lines[ln];
var ln0 = Math.max(0,ln - pad);
var ln1 = Math.min(ln0 + pad + 1 + pad,lines.length);
let lni = ln - ln0;
var l = ln0;
var res1 = [];while (l < ln1){
res1.push(lines[l++]);
};var out = res1;
if (gutter) {
out = out.map(function(line,i) {
let prefix = ("" + (ln0 + i + 1));
let str;
while (prefix.length < String(ln1).length){
prefix = (" " + prefix);
};
if (i == lni) {
str = (" -> " + prefix + " | " + line);
if (hl) { str = ansi.f(hl,str) };
} else {
str = (" " + prefix + " | " + line);
if (hl) { str = ansi.f('gray',str) };
};
return str;
});
};
// if colors isa String
// out[lni] = ansi.f(colors,out[lni])
// elif colors
// let color = ansi[type] or ansi:red
// out[lni] = color(out[lni])
let res = out.join('\n');
return res;
};
var printWarning = self.printWarning = function (code,warn){
let msg = warn.message; // b("{yellow('warn: ')}") + yellow(warn:message)
let excerpt = self.printExcerpt(code,warn.loc,{hl: 'whiteBright',type: 'warn',pad: 1});
return msg + '\n' + excerpt;
};
var identifierForPath = self.identifierForPath = function (str){
let hash = fnv1a(str).toString(36);
if (hash[0].match(/\d/)) { hash = 'z' + hash };
return hash;
};
var isPlainObject = self.isPlainObject = function (val){
return typeof val == 'object' && Object.getPrototypeOf(val) == Object.prototype;
};
var deepAssign = self.deepAssign = function (base,assignment){
for (let v, i = 0, keys = Object.keys(assignment), l = keys.length, k; i < l; i++){
k = keys[i];v = assignment[k];let orig = base[k];
if (self.isPlainObject(orig) && self.isPlainObject(v)) {
self.deepAssign(orig,v);
} else {
base[k] = v;
};
};
return base;
};
var computeLineOffsets = self.computeLineOffsets = function (text,isAtLineStart,textOffset){
if (textOffset === undefined) {
textOffset = 0;
}
var result = isAtLineStart ? [textOffset] : [];
var i = 0;
while (i < text.length){
var ch = text.charCodeAt(i);
if (ch === 13 || ch === 10) {
if (ch === 13 && (i + 1 < text.length) && text.charCodeAt(i + 1) === 10) {
i++;
}
result.push(textOffset + i + 1);
}
i++;
}
return result;
};
class Position {
constructor(line,character,offset,value = null) {
this.line = line;
this.character = character;
this.offset = offset;
}
toString() {
return this.line + ":" + this.character;
}
valueOf() {
return this.offset;
}
}
class Range {
constructor(start,end) {
this.start = start;
this.end = end;
}
get offset() {
return this.start.offset;
}
get length() {
return this.end.offset - this.start.offset;
}
get 0() {
return this.start.offset;
}
get 1() {
return this.end.offset;
}
getText(str) {
return str.slice(this.start,this.end);
}
equals(other) {
return other.offset == this.offset && other.length == this.length;
}
}
var DiagnosticSeverity = {
Error: 1,
Warning: 2,
Information: 3,
Hint: 4,
error: 1,
warning: 2,
warn: 2,
info: 3,
hint: 4
};
const DOCMAP = new WeakMap();
class Diagnostic {
constructor(data,doc = null) {
this.range = data.range;
this.severity = DiagnosticSeverity[data.severity] || data.severity;
this.code = data.code;
this.source = data.source;
this.message = data.message;
DOCMAP.set(this,doc);
}
get sourceDocument() {
return DOCMAP.get(this);
}
toSnippet() {
let source = this.sourceDocument;
let start = this.range.start;
let end = this.range.end;
let msg = source.sourcePath + ":" + (start.line + 1) + ":" + (start.character + 1) + ": " + this.message;
let line = source.doc.getLineText(start.line);
// for multi-line ranges, underline to the end of the first line
let until = end.line == start.line ? end.character : line.length;
let carets = Math.max(until - start.character, 1);
let stack = [msg,line];
stack.push(line.replace(/[^\t]/g,' ').slice(0,start.character) + "^".repeat(carets));
return stack.join('\n').replace(/\t/g,' ') + "\n";
}
toError() {
let start = this.range.start;
let msg = this.sourceDocument.sourcePath + ":" + (start.line + 1) + ":" + (start.character + 1) + ": " + this.message;
let err = new SyntaxError(msg);
err.stack = "\n" + this.toSnippet();
return err;
}
raise() {
throw this.toError();
}
}
export { Diagnostic, DiagnosticSeverity, InternalPrefixes, Position, Range, ReservedIdentifierRegex, ReservedPrefixes, ToImbaMap, ToJSMap, ansi, brace, bracketize, camelCase, clearLocationMarkers, computeLineOffsets, dashToCamelCase, dasherize, deepAssign, flatten, fromValidIdentifier, identifierForPath, indent, isPlainObject, isSystemIdentifier, isValidIdentifier, locationToLineColMap, markLineColForTokens, normalizeIndentation, parenthesize, parseArgs, pascalCase, printExcerpt, printWarning, quote, setterSym, singlequote, snakeCase, symbolize, toCustomTagIdentifier, toImbaIdentifier, toJSIdentifier, toValidIdentifier, unionOfLocations };