use :node;
var Node = module.require('../Node').Node;
fn UnaryExpression(operator, argument)
extends Node { this.type = 'UnaryExpression'; this.operator = operator; this.argument = argument; this.argument.parent = this; this.prefix = true;
}
UnaryExpression.prototype.codegen = () -> {
if !super.codegen() { return; } this.argument = this.argument.codegen(); // typeof operator should compile to: // ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase() if (this.operator == 'typeof') { var typeofExpression = { "type": "CallExpression", "callee": { "type": "MemberExpression", "computed": false, "object": { "type": "MemberExpression", "computed": true, "object": { "type": "CallExpression", "callee": { "type": "MemberExpression", "computed": false, "object": { "type": "CallExpression", "callee": { "type": "MemberExpression", "computed": false, "object": { "type": "MemberExpression", "computed": false, "object": { "type": "ObjectExpression", "properties": [] }, "property": { "type": "Identifier", "name": "toString" } }, "property": { "type": "Identifier", "name": "call" } }, "arguments": [this.argument] }, "property": { "type": "Identifier", "name": "match" } }, "arguments": [{ "type": "Literal", "value": new ::RegExp("\\s([a-zA-Z]+)") }] }, "property": { "type": "Literal", "value": 1, "raw": "1" } }, "property": { "type": "Identifier", "name": "toLowerCase" } }, "arguments": [] }; if !this.argument.hasCallExpression() { this.type = "ConditionalExpression"; this.test = { "type": "BinaryExpression", "operator": "===", "left": { "type": "UnaryExpression", "operator": "typeof", "argument": this.argument, "prefix": true }, "right": { "type": "Literal", "value": "undefined", "raw": "'undefined'" } }; this.consequent = { "type": "Literal", "value": "undefined" }; this.alternate = typeofExpression; } else { this.type = typeofExpression.type; this.callee = typeofExpression.callee; ::Object.defineProperty(this, 'arguments', { value: typeofExpression.arguments, enumerable: true }); } } else if this.operator == "<-" { var parent = this.parent; while parent? and parent.type != "FunctionExpression" and parent.type != "GoStatement" { parent = parent.parent; } if not parent? or (parent.type != "GoStatement" and (parent.parent.type != "UnaryExpression" or parent.parent.operator != "async")) { Node.getErrorManager().error({ type: "GetExpressionRequiresAsync", message: "unary <- must be in a go statement or an async function", loc: this.loc }); } this.operator = "await"; this.argument = { "type": "CallExpression", "callee": { "type": "MemberExpression", "object": this.argument, "property": { "type": "Identifier", "name": "get" }, "computed": false }, "arguments": [] }; } return this;
};
UnaryExpression.prototype.hasCallExpression = () -> {
return this.argument?.hasCallExpression();
};
exports.UnaryExpression = UnaryExpression;