+ if (cur.from != cur.to && sticky == "before") { found = i }
+ else { bidiOther = i }
+ }
+ if (cur.from == ch) {
+ if (cur.from != cur.to && sticky != "before") { found = i }
+ else { bidiOther = i }
+ }
+ }
+ return found != null ? found : bidiOther
+}
+
+// Bidirectional ordering algorithm
+// See http://unicode.org/reports/tr9/tr9-13.html for the algorithm
+// that this (partially) implements.
+
+// One-char codes used for character types:
+// L (L): Left-to-Right
+// R (R): Right-to-Left
+// r (AL): Right-to-Left Arabic
+// 1 (EN): European Number
+// + (ES): European Number Separator
+// % (ET): European Number Terminator
+// n (AN): Arabic Number
+// , (CS): Common Number Separator
+// m (NSM): Non-Spacing Mark
+// b (BN): Boundary Neutral
+// s (B): Paragraph Separator
+// t (S): Segment Separator
+// w (WS): Whitespace
+// N (ON): Other Neutrals
+
+// Returns null if characters are ordered as they appear
+// (left-to-right), or an array of sections ({from, to, level}
+// objects) in the order in which they occur visually.
+var bidiOrdering = (function() {
+ // Character types for codepoints 0 to 0xff
+ var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"
+ // Character types for codepoints 0x600 to 0x6f9
+ var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111"
+ function charType(code) {
+ if (code <= 0xf7) { return lowTypes.charAt(code) }
+ $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"
+ 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 = out.concat(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);
+ });
+ }
+}, AST_Scope);
+
+var AST_Accessor = DEFNODE("Accessor", null, {
+ $documentation: "A setter/getter function. The `name` property is always null."
+ 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."
+ $documentation: "A symbol imported from a module, but it is defined in the other module, and its real name is irrelevant for this module's purposes",
+}, AST_Symbol);
+
+var AST_Label = DEFNODE("Label", "references", {
+ $documentation: "Symbol naming a label (declaration)",
+ $propdoc: {
+ references: "[AST_LoopControl*] a list of nodes referring to this label"
+ },
+ initialize: function() {
+ this.references = [];
+ this.thedef = this;
+ }
+}, AST_Symbol);
+
+var AST_SymbolRef = DEFNODE("SymbolRef", null, {
+ $documentation: "Reference to some symbol (not definition/declaration)",
+ $documentation: "A symbol exported from this module, but it is used in the other module, and its real name is irrelevant for this module's purposes",
+ 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"