fixing single evaluation of functions used in chained comparisons wrapped in parentheses.

This commit is contained in:
Jeremy Ashkenas
2010-03-31 22:48:47 -04:00
parent f86fca2739
commit 3605168e85
3 changed files with 22 additions and 2 deletions

View File

@@ -131,6 +131,12 @@
} }
return false; return false;
}; };
// Is this node of a certain type, or does it contain the type?
BaseNode.prototype.contains_type = function contains_type(type) {
return this instanceof type || this.contains(function(n) {
return n instanceof type;
});
};
// Convenience for the most common use of contains. Does the node contain // Convenience for the most common use of contains. Does the node contain
// a pure statement? // a pure statement?
BaseNode.prototype.contains_pure_statement = function contains_pure_statement() { BaseNode.prototype.contains_pure_statement = function contains_pure_statement() {
@@ -1248,7 +1254,7 @@
OpNode.prototype.compile_chain = function compile_chain(o) { OpNode.prototype.compile_chain = function compile_chain(o) {
var _a, _b, first, second, shared; var _a, _b, first, second, shared;
shared = this.first.unwrap().second; shared = this.first.unwrap().second;
if (shared instanceof CallNode) { if (shared.contains_type(CallNode)) {
_a = shared.compile_reference(o); _a = shared.compile_reference(o);
this.first.second = _a[0]; this.first.second = _a[0];
shared = _a[1]; shared = _a[1];

View File

@@ -98,6 +98,10 @@ exports.BaseNode: class BaseNode
return true if node.contains and node.contains block return true if node.contains and node.contains block
false false
# Is this node of a certain type, or does it contain the type?
contains_type: (type) ->
this instanceof type or @contains (n) -> n instanceof type
# Convenience for the most common use of contains. Does the node contain # Convenience for the most common use of contains. Does the node contain
# a pure statement? # a pure statement?
contains_pure_statement: -> contains_pure_statement: ->
@@ -928,7 +932,7 @@ exports.OpNode: class OpNode extends BaseNode
# true # true
compile_chain: (o) -> compile_chain: (o) ->
shared: @first.unwrap().second shared: @first.unwrap().second
[@first.second, shared]: shared.compile_reference(o) if shared instanceof CallNode [@first.second, shared]: shared.compile_reference(o) if shared.contains_type CallNode
[first, second, shared]: [@first.compile(o), @second.compile(o), shared.compile(o)] [first, second, shared]: [@first.compile(o), @second.compile(o), shared.compile(o)]
"($first) && ($shared $@operator $second)" "($first) && ($shared $@operator $second)"

View File

@@ -28,3 +28,13 @@ b: 1
ok a is 1 and b is 1 ok a is 1 and b is 1
ok a == b ok a == b
ok a is b ok a is b
# Ensure that chained operations don't cause functions to be evaluated more
# than once.
val: 0
func: -> val: + 1
ok 2 > (func null) < 2
ok val is 1