var LATEST_RAW = ""; // Only used for numbers and template strings
var LATEST_TEMPLATE_END = true;
var KEYWORDS = "break case catch class const continue debugger default delete do else export extends finally for function if in instanceof let new return switch throw try typeof var void while with";
var KEYWORDS_ATOM = "false null true";
var RESERVED_WORDS = "enum implements import interface package private protected public static super this " + KEYWORDS_ATOM + " " + KEYWORDS;
var KEYWORDS_BEFORE_EXPRESSION = "return new delete throw else case yield await";
var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
var RE_NUM_LITERAL = /[0-9a-f]/i;
var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
var RE_OCT_NUMBER = /^0[0-7]+$/;
var RE_ES6_OCT_NUMBER = /^0o[0-7]+$/i;
var RE_BIN_NUMBER = /^0b[01]+$/i;
var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
var RE_BIG_INT = /^(0[xob])?[0-9a-f]+n$/i;
var OPERATORS = makePredicate([
"in",
"instanceof",
"typeof",
"new",
"void",
"delete",
"++",
"--",
"+",
"-",
"!",
"~",
"&",
"|",
"^",
"*",
"**",
"/",
"%",
">>",
"<<",
">>>",
"<",
">",
"<=",
">=",
"==",
"===",
"!=",
"!==",
"?",
"=",
"+=",
"-=",
"||=",
"&&=",
"??=",
"/=",
"*=",
"**=",
"%=",
">>=",
"<<=",
">>>=",
"|=",
"^=",
"&=",
"&&",
"??",
"||",
]);
var WHITESPACE_CHARS = makePredicate(characters(" \u00a0\n\r\t\f\u000b\u200b\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\uFEFF"));
var NEWLINE_CHARS = makePredicate(characters("\n\r\u2028\u2029"));
var PUNC_AFTER_EXPRESSION = makePredicate(characters(";]),:"));
var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,;:"));
var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
/* -----[ Tokenizer ]----- */
// surrogate safe regexps adapted from https://github.com/mathiasbynens/unicode-8.0.0/tree/89b412d8a71ecca9ed593d9e9fa073ab64acfebe/Binary_Property
if (node instanceof AST_Directive && node.value == "$ORIG") {
return MAP.splice(body);
}
}));
}
}, AST_Scope);
var AST_Expansion = DEFNODE("Expansion", "expression", {
$documentation: "An expandible argument, such as ...rest, a splat, such as [1,2,...all], or an expansion in a variable declaration, such as var [first, ...rest] = list",
$propdoc: {
expression: "[AST_Node] the thing to be expanded"
},
_walk: function(visitor) {
return visitor._visit(this, function() {
this.expression.walk(visitor);
});
},
_children_backwards(push) {
push(this.expression);
},
});
var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments is_generator async", {
$documentation: "Base class for functions",
$propdoc: {
name: "[AST_SymbolDeclaration?] the name of this function",
argnames: "[AST_SymbolFunarg|AST_Destructuring|AST_Expansion|AST_DefaultAssign*] array of function arguments, destructurings, or expanding arguments",
uses_arguments: "[boolean/S] tells whether this function accesses the arguments array",
is_generator: "[boolean] is this a generator method",
async: "[boolean] is this method async",
},
args_as_names: function () {
var out = [];
for (var i = 0; i < this.argnames.length; i++) {
if (this.argnames[i] instanceof AST_Destructuring) {
out.push(...this.argnames[i].all_symbols());
} else {
out.push(this.argnames[i]);
}
}
return out;
},
_walk: function(visitor) {
return visitor._visit(this, function() {
if (this.name) this.name._walk(visitor);
var argnames = this.argnames;
for (var i = 0, len = argnames.length; i < len; i++) {
argnames[i]._walk(visitor);
}
walk_body(this, visitor);
});
},
_children_backwards(push) {
let i = this.body.length;
while (i--) push(this.body[i]);
i = this.argnames.length;
while (i--) push(this.argnames[i]);
if (this.name) push(this.name);
},
}, AST_Scope);
var AST_Accessor = DEFNODE("Accessor", null, {
$documentation: "A setter/getter function. The `name` property is always null."
}, AST_Lambda);
var AST_Function = DEFNODE("Function", null, {
$documentation: "A function expression"
}, AST_Lambda);
var AST_Arrow = DEFNODE("Arrow", null, {
$documentation: "An ES6 Arrow function ((a) => b)"
}, AST_Lambda);
var AST_Defun = DEFNODE("Defun", null, {
$documentation: "A function definition"
}, AST_Lambda);
/* -----[ DESTRUCTURING ]----- */
var AST_Destructuring = DEFNODE("Destructuring", "names is_array", {
$documentation: "A destructuring of several names. Used in destructuring assignment and with destructuring function argument names",
$propdoc: {
"names": "[AST_Node*] Array of properties or elements",
"is_array": "[Boolean] Whether the destructuring represents an object or array"
},
_walk: function(visitor) {
return visitor._visit(this, function() {
this.names.forEach(function(name) {
name._walk(visitor);
});
});
},
_children_backwards(push) {
let i = this.names.length;
while (i--) push(this.names[i]);
},
all_symbols: function() {
var out = [];
this.walk(new TreeWalker(function (node) {
if (node instanceof AST_Symbol) {
out.push(node);
}
}));
return out;
}
});
var AST_PrefixedTemplateString = DEFNODE("PrefixedTemplateString", "template_string prefix", {
$documentation: "A templatestring with a prefix, such as String.raw`foobarbaz`",
$propdoc: {
template_string: "[AST_TemplateString] The template string",
prefix: "[AST_Node] The prefix, which will get called."
},
_walk: function(visitor) {
return visitor._visit(this, function () {
this.prefix._walk(visitor);
this.template_string._walk(visitor);
});
},
_children_backwards(push) {
push(this.template_string);
push(this.prefix);
},
});
var AST_TemplateString = DEFNODE("TemplateString", "segments", {
$documentation: "A template string literal",
$propdoc: {
segments: "[AST_Node*] One or more segments, starting with AST_TemplateSegment. AST_Node may follow AST_TemplateSegment, but each AST_Node must be followed by AST_TemplateSegment."
},
_walk: function(visitor) {
return visitor._visit(this, function() {
this.segments.forEach(function(seg) {
seg._walk(visitor);
});
});
},
_children_backwards(push) {
let i = this.segments.length;
while (i--) push(this.segments[i]);
}
});
var AST_TemplateSegment = DEFNODE("TemplateSegment", "value raw", {
$documentation: "A segment of a template string literal",
$propdoc: {
value: "Content of the segment",
raw: "Raw source of the segment",
}
});
/* -----[ JUMPS ]----- */
var AST_Jump = DEFNODE("Jump", null, {
$documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
}, AST_Statement);
var AST_Exit = DEFNODE("Exit", "value", {
$documentation: "Base class for “exits” (`return` and `throw`)",
$propdoc: {
value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
expression: "[AST_Node] the mandatory expression being awaited",
},
_walk: function(visitor) {
return visitor._visit(this, function() {
this.expression._walk(visitor);
});
},
_children_backwards(push) {
push(this.expression);
},
});
var AST_Yield = DEFNODE("Yield", "expression is_star", {
$documentation: "A `yield` statement",
$propdoc: {
expression: "[AST_Node?] the value returned or thrown by this statement; could be null (representing undefined) but only when is_star is set to false",
is_star: "[Boolean] Whether this is a yield or yield* statement"