feat: add support for the safe navigation (aka Elvis) operator

fixes #791
This commit is contained in:
Victor Berchet
2015-05-28 23:03:30 +02:00
parent ec2d8cc2c8
commit a9be2ebf1b
11 changed files with 153 additions and 18 deletions
@@ -91,6 +91,20 @@ export class AccessMember extends AST {
visit(visitor) { return visitor.visitAccessMember(this); }
}
export class SafeAccessMember extends AST {
constructor(public receiver: AST, public name: string, public getter: Function,
public setter: Function) {
super();
}
eval(context, locals) {
var evaluatedReceiver = this.receiver.eval(context, locals);
return isBlank(evaluatedReceiver) ? null : this.getter(evaluatedReceiver);
}
visit(visitor) { return visitor.visitSafeAccessMember(this); }
}
export class KeyedAccess extends AST {
constructor(public obj: AST, public key: AST) { super(); }
@@ -251,6 +265,22 @@ export class MethodCall extends AST {
visit(visitor) { return visitor.visitMethodCall(this); }
}
export class SafeMethodCall extends AST {
constructor(public receiver: AST, public name: string, public fn: Function,
public args: List<any>) {
super();
}
eval(context, locals) {
var evaluatedReceiver = this.receiver.eval(context, locals);
if (isBlank(evaluatedReceiver)) return null;
var evaluatedArgs = evalList(context, locals, this.args);
return this.fn(evaluatedReceiver, evaluatedArgs);
}
visit(visitor) { return visitor.visitSafeMethodCall(this); }
}
export class FunctionCall extends AST {
constructor(public target: AST, public args: List<any>) { super(); }
@@ -300,6 +330,8 @@ export class AstVisitor {
visitLiteralPrimitive(ast: LiteralPrimitive) {}
visitMethodCall(ast: MethodCall) {}
visitPrefixNot(ast: PrefixNot) {}
visitSafeAccessMember(ast: SafeAccessMember) {}
visitSafeMethodCall(ast: SafeMethodCall) {}
}
export class AstTransformer {
@@ -315,10 +347,18 @@ export class AstTransformer {
return new AccessMember(ast.receiver.visit(this), ast.name, ast.getter, ast.setter);
}
visitSafeAccessMember(ast: SafeAccessMember) {
return new SafeAccessMember(ast.receiver.visit(this), ast.name, ast.getter, ast.setter);
}
visitMethodCall(ast: MethodCall) {
return new MethodCall(ast.receiver.visit(this), ast.name, ast.fn, this.visitAll(ast.args));
}
visitSafeMethodCall(ast: SafeMethodCall) {
return new SafeMethodCall(ast.receiver.visit(this), ast.name, ast.fn, this.visitAll(ast.args));
}
visitFunctionCall(ast: FunctionCall) {
return new FunctionCall(ast.target.visit(this), this.visitAll(ast.args));
}