enhance conditionals (#5542)
This commit is contained in:
209
lib/ast.js
209
lib/ast.js
@@ -109,6 +109,9 @@ var AST_Node = DEFNODE("Node", "start end", {
|
||||
start: "[AST_Token] The first token of this node",
|
||||
end: "[AST_Token] The last token of this node"
|
||||
},
|
||||
equals: function(node) {
|
||||
return this.TYPE == node.TYPE && this._equals(node);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
visitor.visit(this);
|
||||
},
|
||||
@@ -231,6 +234,24 @@ AST_Node.disable_validation = function() {
|
||||
while (restore = restore_transforms.pop()) restore();
|
||||
};
|
||||
|
||||
function all_equals(k, l) {
|
||||
return k.length == l.length && all(k, function(m, i) {
|
||||
return m.equals(l[i]);
|
||||
});
|
||||
}
|
||||
|
||||
function list_equals(s, t) {
|
||||
return s.length == t.length && all(s, function(u, i) {
|
||||
return u == t[i];
|
||||
});
|
||||
}
|
||||
|
||||
function prop_equals(u, v) {
|
||||
if (u === v) return true;
|
||||
if (u == null) return v == null;
|
||||
return u instanceof AST_Node && v instanceof AST_Node && u.equals(v);
|
||||
}
|
||||
|
||||
/* -----[ statements ]----- */
|
||||
|
||||
var AST_Statement = DEFNODE("Statement", null, {
|
||||
@@ -242,6 +263,7 @@ var AST_Statement = DEFNODE("Statement", null, {
|
||||
|
||||
var AST_Debugger = DEFNODE("Debugger", null, {
|
||||
$documentation: "Represents a debugger statement",
|
||||
_equals: return_true,
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_Directive = DEFNODE("Directive", "quote value", {
|
||||
@@ -250,6 +272,9 @@ var AST_Directive = DEFNODE("Directive", "quote value", {
|
||||
quote: "[string?] the original quote character",
|
||||
value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.value == node.value;
|
||||
},
|
||||
_validate: function() {
|
||||
if (this.quote != null) {
|
||||
if (typeof this.quote != "string") throw new Error("quote must be string");
|
||||
@@ -260,7 +285,8 @@ var AST_Directive = DEFNODE("Directive", "quote value", {
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
|
||||
$documentation: "The empty statement (empty block or simply a semicolon)"
|
||||
$documentation: "The empty statement (empty block or simply a semicolon)",
|
||||
_equals: return_true,
|
||||
}, AST_Statement);
|
||||
|
||||
function is_statement(node) {
|
||||
@@ -291,6 +317,9 @@ var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
|
||||
$propdoc: {
|
||||
body: "[AST_Node] an expression node (should not be instanceof AST_Statement)",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.body.equals(node.body);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -342,6 +371,9 @@ var AST_Block = DEFNODE("Block", "body", {
|
||||
$propdoc: {
|
||||
body: "[AST_Statement*] an array of statements"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return all_equals(this.body, node.body);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -376,6 +408,10 @@ var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
|
||||
$propdoc: {
|
||||
label: "[AST_Label] a label definition"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.label.equals(node.label)
|
||||
&& this.body.equals(node.body);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -417,6 +453,10 @@ var AST_DWLoop = DEFNODE("DWLoop", "condition", {
|
||||
$propdoc: {
|
||||
condition: "[AST_Node] the loop condition. Should not be instanceof AST_Statement"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.body.equals(node.body)
|
||||
&& this.condition.equals(node.condition);
|
||||
},
|
||||
_validate: function() {
|
||||
if (this.TYPE == "DWLoop") throw new Error("should not instantiate AST_DWLoop");
|
||||
must_be_expression(this, "condition");
|
||||
@@ -431,7 +471,7 @@ var AST_Do = DEFNODE("Do", null, {
|
||||
node.body.walk(visitor);
|
||||
node.condition.walk(visitor);
|
||||
});
|
||||
}
|
||||
},
|
||||
}, AST_DWLoop);
|
||||
|
||||
var AST_While = DEFNODE("While", null, {
|
||||
@@ -442,7 +482,7 @@ var AST_While = DEFNODE("While", null, {
|
||||
node.condition.walk(visitor);
|
||||
node.body.walk(visitor);
|
||||
});
|
||||
}
|
||||
},
|
||||
}, AST_DWLoop);
|
||||
|
||||
var AST_For = DEFNODE("For", "init condition step", {
|
||||
@@ -452,6 +492,12 @@ var AST_For = DEFNODE("For", "init condition step", {
|
||||
condition: "[AST_Node?] the `for` termination clause, or null if empty",
|
||||
step: "[AST_Node?] the `for` update clause, or null if empty"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return prop_equals(this.init, node.init)
|
||||
&& prop_equals(this.condition, node.condition)
|
||||
&& prop_equals(this.step, node.step)
|
||||
&& this.body.equals(node.body);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -479,6 +525,11 @@ var AST_ForEnumeration = DEFNODE("ForEnumeration", "init object", {
|
||||
init: "[AST_Node] the assignment target during iteration",
|
||||
object: "[AST_Node] the object to iterate over"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.init.equals(node.init)
|
||||
&& this.object.equals(node.object)
|
||||
&& this.body.equals(node.body);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -519,6 +570,10 @@ var AST_With = DEFNODE("With", "expression", {
|
||||
$propdoc: {
|
||||
expression: "[AST_Node] the `with` expression"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.expression.equals(node.expression)
|
||||
&& this.body.equals(node.body);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -621,6 +676,13 @@ var AST_Lambda = DEFNODE("Lambda", "argnames length_read rest safe_ids uses_argu
|
||||
});
|
||||
if (this.rest) this.rest.walk(tw);
|
||||
},
|
||||
_equals: function(node) {
|
||||
return prop_equals(this.rest, node.rest)
|
||||
&& prop_equals(this.name, node.name)
|
||||
&& prop_equals(this.value, node.value)
|
||||
&& all_equals(this.argnames, node.argnames)
|
||||
&& all_equals(this.body, node.body);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -831,6 +893,11 @@ var AST_Class = DEFNODE("Class", "extends name properties", {
|
||||
extends: "[AST_Node?] the super class, or null if not specified",
|
||||
properties: "[AST_ClassProperty*] array of class properties",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return prop_equals(this.name, node.name)
|
||||
&& prop_equals(this.extends, node.extends)
|
||||
&& all_equals(this.properties, node.properties);
|
||||
},
|
||||
resolve: function(def_class) {
|
||||
return def_class ? this : this.parent_scope.resolve();
|
||||
},
|
||||
@@ -883,6 +950,12 @@ var AST_ClassProperty = DEFNODE("ClassProperty", "key private static value", {
|
||||
static: "[boolean] whether this is a static property",
|
||||
value: "[AST_Node?] property value (AST_Accessor for getters/setters, AST_LambdaExpression for methods, null if not specified for fields)",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return !this.private == !node.private
|
||||
&& !this.static == !node.static
|
||||
&& prop_equals(this.key, node.key)
|
||||
&& prop_equals(this.value, node.value);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -959,6 +1032,9 @@ var AST_Exit = DEFNODE("Exit", "value", {
|
||||
$propdoc: {
|
||||
value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return prop_equals(this.value, node.value);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -989,6 +1065,9 @@ var AST_LoopControl = DEFNODE("LoopControl", "label", {
|
||||
$propdoc: {
|
||||
label: "[AST_LabelRef?] the label, or null if none",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return prop_equals(this.label, node.label);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1019,6 +1098,11 @@ var AST_If = DEFNODE("If", "condition alternative", {
|
||||
condition: "[AST_Node] the `if` condition",
|
||||
alternative: "[AST_Statement?] the `else` part, or null if not present"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.body.equals(node.body)
|
||||
&& this.condition.equals(node.condition)
|
||||
&& prop_equals(this.alternative, node.alternative);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1116,6 +1200,10 @@ var AST_Catch = DEFNODE("Catch", "argname", {
|
||||
$propdoc: {
|
||||
argname: "[(AST_Destructured|AST_SymbolCatch)?] symbol for the exception, or null if not present",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return prop_equals(this.argname, node.argname)
|
||||
&& all_equals(this.body, node.body);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1141,6 +1229,9 @@ var AST_Definitions = DEFNODE("Definitions", "definitions", {
|
||||
$propdoc: {
|
||||
definitions: "[AST_VarDef*] array of variable definitions"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return all_equals(this.definitions, node.definitions);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1197,6 +1288,10 @@ var AST_VarDef = DEFNODE("VarDef", "name value", {
|
||||
name: "[AST_Destructured|AST_SymbolVar] name of the variable",
|
||||
value: "[AST_Node?] initializer, or null of there's no initializer",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.name.equals(node.name)
|
||||
&& prop_equals(this.value, node.value);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1216,6 +1311,9 @@ var AST_ExportDeclaration = DEFNODE("ExportDeclaration", "body", {
|
||||
$propdoc: {
|
||||
body: "[AST_DefClass|AST_Definitions|AST_LambdaDefinition] the statement to export",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.body.equals(node.body);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1236,6 +1334,9 @@ var AST_ExportDefault = DEFNODE("ExportDefault", "body", {
|
||||
$propdoc: {
|
||||
body: "[AST_Node] the default export",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.body.equals(node.body);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1257,6 +1358,11 @@ var AST_ExportForeign = DEFNODE("ExportForeign", "aliases keys path quote", {
|
||||
path: "[string] the path to import module",
|
||||
quote: "[string?] the original quote character",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.path == node.path
|
||||
&& list_equals(this.aliases, node.aliases)
|
||||
&& list_equals(this.keys, node.keys);
|
||||
},
|
||||
_validate: function() {
|
||||
if (this.aliases.length != this.keys.length) {
|
||||
throw new Error("aliases:key length mismatch: " + this.aliases.length + " != " + this.keys.length);
|
||||
@@ -1280,6 +1386,9 @@ var AST_ExportReferences = DEFNODE("ExportReferences", "properties", {
|
||||
$propdoc: {
|
||||
properties: "[AST_SymbolExport*] array of aliases to export",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return all_equals(this.properties, node.properties);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1304,6 +1413,11 @@ var AST_Import = DEFNODE("Import", "all default path properties quote", {
|
||||
properties: "[(AST_SymbolImport*)?] array of aliases, or null if not specified",
|
||||
quote: "[string?] the original quote character",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.path == node.path
|
||||
&& prop_equals(this.default, node.default)
|
||||
&& (this.all ? prop_equals(this.all, node.all) : all_equals(this.properties, node.properties));
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1340,6 +1454,10 @@ var AST_DefaultValue = DEFNODE("DefaultValue", "name value", {
|
||||
name: "[AST_Destructured|AST_SymbolDeclaration] name of the variable",
|
||||
value: "[AST_Node] value to assign if variable is `undefined`",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.name.equals(node.name)
|
||||
&& this.value.equals(node.value);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1367,6 +1485,11 @@ var AST_Call = DEFNODE("Call", "args expression optional pure terminal", {
|
||||
pure: "[boolean/S] marker for side-effect-free call expression",
|
||||
terminal: "[boolean] whether the chain has ended",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return !this.optional == !node.optional
|
||||
&& this.expression.equals(node.expression)
|
||||
&& all_equals(this.args, node.args);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1395,6 +1518,9 @@ var AST_Sequence = DEFNODE("Sequence", "expressions", {
|
||||
$propdoc: {
|
||||
expressions: "[AST_Node*] array of expressions (at least two)"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return all_equals(this.expressions, node.expressions);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1422,6 +1548,11 @@ var AST_PropAccess = DEFNODE("PropAccess", "expression optional property termina
|
||||
property: "[AST_Node|string] the property to access. For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node",
|
||||
terminal: "[boolean] whether the chain has ended",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return !this.optional == !node.optional
|
||||
&& prop_equals(this.property, node.property)
|
||||
&& this.expression.equals(node.expression);
|
||||
},
|
||||
get_property: function() {
|
||||
var p = this.property;
|
||||
if (p instanceof AST_Constant) return p.value;
|
||||
@@ -1466,6 +1597,9 @@ var AST_Spread = DEFNODE("Spread", "expression", {
|
||||
$propdoc: {
|
||||
expression: "[AST_Node] expression to be expanded",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.expression.equals(node.expression);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1483,6 +1617,10 @@ var AST_Unary = DEFNODE("Unary", "operator expression", {
|
||||
operator: "[string] the operator",
|
||||
expression: "[AST_Node] expression that this unary operator applies to"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.operator == node.operator
|
||||
&& this.expression.equals(node.expression);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1511,6 +1649,11 @@ var AST_Binary = DEFNODE("Binary", "operator left right", {
|
||||
operator: "[string] the operator",
|
||||
right: "[AST_Node] right-hand side expression"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.operator == node.operator
|
||||
&& this.left.equals(node.left)
|
||||
&& this.right.equals(node.right);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1532,6 +1675,11 @@ var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative",
|
||||
consequent: "[AST_Node]",
|
||||
alternative: "[AST_Node]"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.condition.equals(node.condition)
|
||||
&& this.consequent.equals(node.consequent)
|
||||
&& this.alternative.equals(node.alternative);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1573,6 +1721,9 @@ var AST_Await = DEFNODE("Await", "expression", {
|
||||
$propdoc: {
|
||||
expression: "[AST_Node] expression with Promise to resolve on",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.expression.equals(node.expression);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1590,6 +1741,10 @@ var AST_Yield = DEFNODE("Yield", "expression nested", {
|
||||
expression: "[AST_Node?] return value for iterator, or null if undefined",
|
||||
nested: "[boolean] whether to iterate over expression as generator",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return !this.nested == !node.nested
|
||||
&& prop_equals(this.expression, node.expression);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1612,6 +1767,9 @@ var AST_Array = DEFNODE("Array", "elements", {
|
||||
$propdoc: {
|
||||
elements: "[AST_Node*] array of elements"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return all_equals(this.elements, node.elements);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1654,6 +1812,10 @@ var AST_DestructuredArray = DEFNODE("DestructuredArray", "elements", {
|
||||
$propdoc: {
|
||||
elements: "[(AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef)*] array of elements",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return prop_equals(this.rest, node.rest)
|
||||
&& all_equals(this.elements, node.elements);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1671,6 +1833,10 @@ var AST_DestructuredKeyVal = DEFNODE("DestructuredKeyVal", "key value", {
|
||||
key: "[string|AST_Node] property name. For computed property this is an AST_Node.",
|
||||
value: "[AST_DefaultValue|AST_Destructured|AST_SymbolDeclaration|AST_SymbolRef] property value",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return prop_equals(this.key, node.key)
|
||||
&& this.value.equals(node.value);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1692,6 +1858,10 @@ var AST_DestructuredObject = DEFNODE("DestructuredObject", "properties", {
|
||||
$propdoc: {
|
||||
properties: "[AST_DestructuredKeyVal*] array of properties",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return prop_equals(this.rest, node.rest)
|
||||
&& all_equals(this.properties, node.properties);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1713,6 +1883,9 @@ var AST_Object = DEFNODE("Object", "properties", {
|
||||
$propdoc: {
|
||||
properties: "[(AST_ObjectProperty|AST_Spread)*] array of properties"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return all_equals(this.properties, node.properties);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1736,6 +1909,10 @@ var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
|
||||
key: "[string|AST_Node] property name. For computed property this is an AST_Node.",
|
||||
value: "[AST_Node] property value. For getters and setters this is an AST_Accessor.",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return prop_equals(this.key, node.key)
|
||||
&& this.value.equals(node.value);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
visitor.visit(node, function() {
|
||||
@@ -1790,6 +1967,9 @@ var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
|
||||
scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
|
||||
thedef: "[SymbolDef/S] the definition of this symbol"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.thedef ? this.thedef === node.thedef : this.name == node.name;
|
||||
},
|
||||
_validate: function() {
|
||||
if (this.TYPE == "Symbol") throw new Error("should not instantiate AST_Symbol");
|
||||
if (typeof this.name != "string") throw new Error("name must be string");
|
||||
@@ -1809,6 +1989,10 @@ var AST_SymbolImport = DEFNODE("SymbolImport", "key", {
|
||||
$propdoc: {
|
||||
key: "[string] the original `export` name",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.name == node.name
|
||||
&& this.key == node.key;
|
||||
},
|
||||
_validate: function() {
|
||||
if (typeof this.key != "string") throw new Error("key must be string");
|
||||
},
|
||||
@@ -1866,6 +2050,10 @@ var AST_SymbolExport = DEFNODE("SymbolExport", "alias", {
|
||||
$propdoc: {
|
||||
alias: "[string] the `export` alias",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return this.name == node.name
|
||||
&& this.alias == node.alias;
|
||||
},
|
||||
_validate: function() {
|
||||
if (typeof this.alias != "string") throw new Error("alias must be string");
|
||||
},
|
||||
@@ -1877,6 +2065,7 @@ var AST_LabelRef = DEFNODE("LabelRef", null, {
|
||||
|
||||
var AST_ObjectIdentity = DEFNODE("ObjectIdentity", null, {
|
||||
$documentation: "Base class for `super` & `this`",
|
||||
_equals: return_true,
|
||||
_validate: function() {
|
||||
if (this.TYPE == "ObjectIdentity") throw new Error("should not instantiate AST_ObjectIdentity");
|
||||
},
|
||||
@@ -1911,7 +2100,12 @@ var AST_Template = DEFNODE("Template", "expressions strings tag", {
|
||||
$propdoc: {
|
||||
expressions: "[AST_Node*] the placeholder expressions",
|
||||
strings: "[string*] the raw text segments",
|
||||
tag: "[AST_Node] tag function, or null if absent",
|
||||
tag: "[AST_Node?] tag function, or null if absent",
|
||||
},
|
||||
_equals: function(node) {
|
||||
return prop_equals(this.tag, node.tag)
|
||||
&& list_equals(this.strings, node.strings)
|
||||
&& all_equals(this.expressions, node.expressions);
|
||||
},
|
||||
walk: function(visitor) {
|
||||
var node = this;
|
||||
@@ -1936,6 +2130,9 @@ var AST_Template = DEFNODE("Template", "expressions strings tag", {
|
||||
|
||||
var AST_Constant = DEFNODE("Constant", null, {
|
||||
$documentation: "Base class for all constants",
|
||||
_equals: function(node) {
|
||||
return this.value === node.value;
|
||||
},
|
||||
_validate: function() {
|
||||
if (this.TYPE == "Constant") throw new Error("should not instantiate AST_Constant");
|
||||
},
|
||||
@@ -1984,6 +2181,9 @@ var AST_RegExp = DEFNODE("RegExp", "value", {
|
||||
$propdoc: {
|
||||
value: "[RegExp] the actual regexp"
|
||||
},
|
||||
_equals: function(node) {
|
||||
return "" + this.value == "" + node.value;
|
||||
},
|
||||
_validate: function() {
|
||||
if (!(this.value instanceof RegExp)) throw new Error("value must be RegExp");
|
||||
},
|
||||
@@ -1991,6 +2191,7 @@ var AST_RegExp = DEFNODE("RegExp", "value", {
|
||||
|
||||
var AST_Atom = DEFNODE("Atom", null, {
|
||||
$documentation: "Base class for atoms",
|
||||
_equals: return_true,
|
||||
_validate: function() {
|
||||
if (this.TYPE == "Atom") throw new Error("should not instantiate AST_Atom");
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user