mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-01-14 01:07:55 -05:00
made In node invertible
This commit is contained in:
@@ -547,46 +547,46 @@
|
||||
})
|
||||
],
|
||||
Operation: [
|
||||
o("UNARY Expression", function() {
|
||||
o('UNARY Expression', function() {
|
||||
return new Op($1, $2);
|
||||
}), o("- Expression", function() {
|
||||
}), o('- Expression', function() {
|
||||
return new Op('-', $2);
|
||||
}, {
|
||||
prec: 'UNARY'
|
||||
}), o("+ Expression", function() {
|
||||
}), o('+ Expression', function() {
|
||||
return new Op('+', $2);
|
||||
}, {
|
||||
prec: 'UNARY'
|
||||
}), o("-- SimpleAssignable", function() {
|
||||
}), o('-- SimpleAssignable', function() {
|
||||
return new Op('--', $2);
|
||||
}), o("++ SimpleAssignable", function() {
|
||||
}), o('++ SimpleAssignable', function() {
|
||||
return new Op('++', $2);
|
||||
}), o("SimpleAssignable --", function() {
|
||||
}), o('SimpleAssignable --', function() {
|
||||
return new Op('--', $1, null, true);
|
||||
}), o("SimpleAssignable ++", function() {
|
||||
}), o('SimpleAssignable ++', function() {
|
||||
return new Op('++', $1, null, true);
|
||||
}), o("Expression + Expression", function() {
|
||||
}), o('Expression + Expression', function() {
|
||||
return new Op('+', $1, $3);
|
||||
}), o("Expression - Expression", function() {
|
||||
}), o('Expression - Expression', function() {
|
||||
return new Op('-', $1, $3);
|
||||
}), o("Expression == Expression", function() {
|
||||
}), o('Expression == Expression', function() {
|
||||
return new Op('==', $1, $3);
|
||||
}), o("Expression != Expression", function() {
|
||||
}), o('Expression != Expression', function() {
|
||||
return new Op('!=', $1, $3);
|
||||
}), o("Expression MATH Expression", function() {
|
||||
}), o('Expression MATH Expression', function() {
|
||||
return new Op($2, $1, $3);
|
||||
}), o("Expression SHIFT Expression", function() {
|
||||
}), o('Expression SHIFT Expression', function() {
|
||||
return new Op($2, $1, $3);
|
||||
}), o("Expression COMPARE Expression", function() {
|
||||
}), o('Expression COMPARE Expression', function() {
|
||||
return new Op($2, $1, $3);
|
||||
}), o("Expression LOGIC Expression", function() {
|
||||
}), o('Expression LOGIC Expression', function() {
|
||||
return new Op($2, $1, $3);
|
||||
}), o("SimpleAssignable COMPOUND_ASSIGN Expression", function() {
|
||||
}), o('Expression RELATION Expression', function() {
|
||||
return $2.charAt(0) === '!' ? new Op($2.slice(1), $1, $3).invert() : new Op($2, $1, $3);
|
||||
}), o('SimpleAssignable COMPOUND_ASSIGN Expression', function() {
|
||||
return new Assign($1, $3, $2);
|
||||
}), o("SimpleAssignable COMPOUND_ASSIGN INDENT Expression OUTDENT", function() {
|
||||
}), o('SimpleAssignable COMPOUND_ASSIGN INDENT Expression OUTDENT', function() {
|
||||
return new Assign($1, $4, $2);
|
||||
}), o("Expression RELATION Expression", function() {
|
||||
return $2.charAt(0) === '!' ? $2 === '!in' ? new Op('!', new In($1, $3)) : new Op('!', new Parens(new Op($2.slice(1), $1, $3))) : $2 === 'in' ? new In($1, $3) : new Op($2, $1, $3);
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
}
|
||||
forcedIdentifier = colon || this.tagAccessor();
|
||||
tag = 'IDENTIFIER';
|
||||
if ((__indexOf.call(JS_KEYWORDS, id) >= 0) || !forcedIdentifier && (__indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
|
||||
if (__indexOf.call(JS_KEYWORDS, id) >= 0 || !forcedIdentifier && __indexOf.call(COFFEE_KEYWORDS, id) >= 0) {
|
||||
tag = id.toUpperCase();
|
||||
if (tag === 'WHEN' && (_ref2 = this.tag(), __indexOf.call(LINE_BREAK, _ref2) >= 0)) {
|
||||
tag = 'LEADING_WHEN';
|
||||
|
||||
47
lib/nodes.js
47
lib/nodes.js
@@ -1019,6 +1019,10 @@
|
||||
};
|
||||
Assign.prototype.compilePatternMatch = function(o) {
|
||||
var _len, _ref2, _ref3, accessClass, assigns, code, i, idx, isObject, obj, objects, olength, otop, ref, splat, top, val, valVar, value;
|
||||
top = del(o, 'top');
|
||||
otop = merge(o, {
|
||||
top: true
|
||||
});
|
||||
if ((value = this.value).isStatement(o)) {
|
||||
value = Closure.wrap(value);
|
||||
}
|
||||
@@ -1027,7 +1031,7 @@
|
||||
return value.compile(o);
|
||||
}
|
||||
isObject = this.variable.isObject();
|
||||
if (o.top && olength === 1 && !((obj = objects[0]) instanceof Splat)) {
|
||||
if (top && olength === 1 && !((obj = objects[0]) instanceof Splat)) {
|
||||
if (obj instanceof Assign) {
|
||||
_ref2 = obj, idx = _ref2.variable.base, obj = _ref2.value;
|
||||
} else {
|
||||
@@ -1035,12 +1039,8 @@
|
||||
}
|
||||
accessClass = IDENTIFIER.test(idx.value) ? Accessor : Index;
|
||||
(value = Value.wrap(value)).properties.push(new accessClass(idx));
|
||||
return new Assign(obj, value).compile(o);
|
||||
return new Assign(obj, value).compile(otop);
|
||||
}
|
||||
top = del(o, 'top');
|
||||
otop = merge(o, {
|
||||
top: true
|
||||
});
|
||||
valVar = value.compile(o);
|
||||
assigns = [];
|
||||
splat = false;
|
||||
@@ -1345,6 +1345,9 @@
|
||||
exports.Op = (function() {
|
||||
Op = (function() {
|
||||
function Op(op, first, second, flip) {
|
||||
if (op === 'in') {
|
||||
return new In(first, second);
|
||||
}
|
||||
if (op === 'new') {
|
||||
if (first instanceof Call) {
|
||||
return first.newInstance();
|
||||
@@ -1452,25 +1455,29 @@
|
||||
})();
|
||||
__extends(In, Base);
|
||||
In.prototype.children = ['object', 'array'];
|
||||
In.prototype.invert = function() {
|
||||
this.negated = !this.negated;
|
||||
return this;
|
||||
};
|
||||
In.prototype.compileNode = function(o) {
|
||||
var code;
|
||||
code = this.array instanceof Value && this.array.isArray() ? this.compileOrTest(o) : this.compileLoopTest(o);
|
||||
return this.parenthetical ? code : "(" + code + ")";
|
||||
return this.array instanceof Value && this.array.isArray() ? this.compileOrTest(o) : this.compileLoopTest(o);
|
||||
};
|
||||
In.prototype.compileOrTest = function(o) {
|
||||
var _len, _ref2, _ref3, _result, i, item, ref, sub, tests;
|
||||
var _len, _ref2, _ref3, _ref4, _result, cmp, cnj, i, item, ref, sub, tests;
|
||||
_ref2 = this.object.compileReference(o, {
|
||||
precompile: true
|
||||
}), sub = _ref2[0], ref = _ref2[1];
|
||||
_ref3 = this.negated ? [' !== ', ' && '] : [' === ', ' || '], cmp = _ref3[0], cnj = _ref3[1];
|
||||
tests = (function() {
|
||||
_result = [];
|
||||
for (i = 0, _len = (_ref3 = this.array.base.objects).length; i < _len; i++) {
|
||||
item = _ref3[i];
|
||||
_result.push("" + (i ? ref : sub) + " === " + (item.compile(o)));
|
||||
for (i = 0, _len = (_ref4 = this.array.base.objects).length; i < _len; i++) {
|
||||
item = _ref4[i];
|
||||
_result.push((i ? ref : sub) + cmp + item.compile(o));
|
||||
}
|
||||
return _result;
|
||||
}).call(this);
|
||||
return tests.join(' || ');
|
||||
tests = tests.join(cnj);
|
||||
return this.parenthetical ? tests : "(" + tests + ")";
|
||||
};
|
||||
In.prototype.compileLoopTest = function(o) {
|
||||
var _ref2, code, ref, sub;
|
||||
@@ -1479,8 +1486,16 @@
|
||||
}), {
|
||||
precompile: true
|
||||
}), sub = _ref2[0], ref = _ref2[1];
|
||||
code = utility('indexOf') + (".call(" + (this.array.compile(o)) + ", " + ref + ") >= 0");
|
||||
return sub === ref ? code : sub + ', ' + code;
|
||||
code = utility('indexOf') + (".call(" + (this.array.compile(o)) + ", " + ref + ") ");
|
||||
code += this.negated ? '< 0' : '>= 0';
|
||||
if (sub === ref) {
|
||||
return code;
|
||||
}
|
||||
code = sub + ', ' + code;
|
||||
return this.parenthetical ? code : "(" + code + ")";
|
||||
};
|
||||
In.prototype.toString = function(idt) {
|
||||
return In.__super__.toString.call(this, idt, this.constructor.name + (this.negated ? '!' : ''));
|
||||
};
|
||||
return In;
|
||||
})();
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -71,7 +71,7 @@
|
||||
} else {
|
||||
tokens.splice(i, 0, after);
|
||||
}
|
||||
} else if (prev && !((_ref = prev[0]) === 'TERMINATOR' || _ref === 'INDENT' || _ref === 'OUTDENT')) {
|
||||
} else if (prev && ((_ref = prev[0]) !== 'TERMINATOR' && _ref !== 'INDENT' && _ref !== 'OUTDENT')) {
|
||||
if (((post != null) ? post[0] : undefined) === 'TERMINATOR' && ((after != null) ? after[0] : undefined) === 'OUTDENT') {
|
||||
tokens.splice.apply(tokens, [i + 2, 0].concat(tokens.splice(i, 2)));
|
||||
if (tokens[i + 2][0] !== 'TERMINATOR') {
|
||||
@@ -147,7 +147,7 @@
|
||||
}
|
||||
_ref = this.tokens.slice(i + 1, i + 4), one = _ref[0], two = _ref[1], three = _ref[2];
|
||||
tag = token[0];
|
||||
return (tag === 'TERMINATOR' || tag === 'OUTDENT') && !(((two != null) ? two[0] : undefined) === ':' || ((one != null) ? one[0] : undefined) === '@' && ((three != null) ? three[0] : undefined) === ':') || tag === ',' && !((_ref2 = (one != null) ? one[0] : undefined) === 'IDENTIFIER' || _ref2 === 'NUMBER' || _ref2 === 'STRING' || _ref2 === '@' || _ref2 === 'TERMINATOR' || _ref2 === 'OUTDENT');
|
||||
return (tag === 'TERMINATOR' || tag === 'OUTDENT') && !(((two != null) ? two[0] : undefined) === ':' || ((one != null) ? one[0] : undefined) === '@' && ((three != null) ? three[0] : undefined) === ':') || tag === ',' && ((_ref2 = (one != null) ? one[0] : undefined) !== 'IDENTIFIER' && _ref2 !== 'NUMBER' && _ref2 !== 'STRING' && _ref2 !== '@' && _ref2 !== 'TERMINATOR' && _ref2 !== 'OUTDENT');
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice(i, 0, ['}', '}', token[2]]);
|
||||
@@ -201,7 +201,7 @@
|
||||
if (prev && !prev.spaced && tag === '?') {
|
||||
token.call = true;
|
||||
}
|
||||
if (!(callObject || ((prev != null) ? prev.spaced : undefined) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && ((__indexOf.call(IMPLICIT_CALL, tag) >= 0) || !token.spaced && (__indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0)))) {
|
||||
if (!(callObject || ((prev != null) ? prev.spaced : undefined) && (prev.call || (_ref2 = prev[0], __indexOf.call(IMPLICIT_FUNC, _ref2) >= 0)) && (__indexOf.call(IMPLICIT_CALL, tag) >= 0 || !token.spaced && __indexOf.call(IMPLICIT_UNSPACED_CALL, tag) >= 0))) {
|
||||
return 1;
|
||||
}
|
||||
tokens.splice(i, 0, ['CALL_START', '(', token[2]]);
|
||||
@@ -217,7 +217,7 @@
|
||||
if (tag === 'PROPERTY_ACCESS' && this.tag(i - 1) === 'OUTDENT') {
|
||||
return true;
|
||||
}
|
||||
return !token.generated && this.tag(i - 1) !== ',' && (__indexOf.call(IMPLICIT_END, tag) >= 0) && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && !(_ref3 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref3) >= 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
return !token.generated && this.tag(i - 1) !== ',' && __indexOf.call(IMPLICIT_END, tag) >= 0 && (tag !== 'INDENT' || (this.tag(i - 2) !== 'CLASS' && (_ref3 = this.tag(i - 1), __indexOf.call(IMPLICIT_BLOCK, _ref3) < 0) && !((post = this.tokens[i + 1]) && post.generated && post[0] === '{')));
|
||||
}, action);
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
@@ -237,7 +237,7 @@
|
||||
tokens.splice.apply(tokens, [i + 2, 0].concat(this.indentation(token)));
|
||||
return 4;
|
||||
}
|
||||
if ((__indexOf.call(SINGLE_LINERS, tag) >= 0) && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
if (__indexOf.call(SINGLE_LINERS, tag) >= 0 && this.tag(i + 1) !== 'INDENT' && !(tag === 'ELSE' && this.tag(i + 1) === 'IF')) {
|
||||
starter = tag;
|
||||
_ref2 = this.indentation(token), indent = _ref2[0], outdent = _ref2[1];
|
||||
if (starter === 'THEN') {
|
||||
@@ -247,7 +247,7 @@
|
||||
tokens.splice(i + 1, 0, indent);
|
||||
condition = function(token, i) {
|
||||
var _ref3;
|
||||
return token[1] !== ';' && (_ref3 = token[0], __indexOf.call(SINGLE_CLOSERS, _ref3) >= 0) && !(token[0] === 'ELSE' && !(starter === 'IF' || starter === 'THEN'));
|
||||
return token[1] !== ';' && (_ref3 = token[0], __indexOf.call(SINGLE_CLOSERS, _ref3) >= 0) && !(token[0] === 'ELSE' && (starter !== 'IF' && starter !== 'THEN'));
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice(this.tag(i - 1) === ',' ? i - 1 : i, 0, outdent);
|
||||
@@ -269,7 +269,7 @@
|
||||
};
|
||||
return this.scanTokens(function(token, i) {
|
||||
var _ref, original;
|
||||
if (!((_ref = token[0]) === 'IF' || _ref === 'UNLESS')) {
|
||||
if ((_ref = token[0]) !== 'IF' && _ref !== 'UNLESS') {
|
||||
return 1;
|
||||
}
|
||||
original = token;
|
||||
@@ -330,7 +330,7 @@
|
||||
stack.push(token);
|
||||
return 1;
|
||||
}
|
||||
if (!(__indexOf.call(EXPRESSION_END, tag) >= 0)) {
|
||||
if (__indexOf.call(EXPRESSION_END, tag) < 0) {
|
||||
return 1;
|
||||
}
|
||||
if (debt[inv = INVERSES[tag]] > 0) {
|
||||
|
||||
@@ -525,37 +525,34 @@ grammar =
|
||||
# -type rule, but in order to make the precedence binding possible, separate
|
||||
# rules are necessary.
|
||||
Operation: [
|
||||
o "UNARY Expression", -> new Op $1, $2
|
||||
o "- Expression", (-> new Op '-', $2), prec: 'UNARY'
|
||||
o "+ Expression", (-> new Op '+', $2), prec: 'UNARY'
|
||||
o 'UNARY Expression', -> new Op $1 , $2
|
||||
o '- Expression', (-> new Op '-', $2), prec: 'UNARY'
|
||||
o '+ Expression', (-> new Op '+', $2), prec: 'UNARY'
|
||||
|
||||
o "-- SimpleAssignable", -> new Op '--', $2
|
||||
o "++ SimpleAssignable", -> new Op '++', $2
|
||||
o "SimpleAssignable --", -> new Op '--', $1, null, true
|
||||
o "SimpleAssignable ++", -> new Op '++', $1, null, true
|
||||
o '-- SimpleAssignable', -> new Op '--', $2
|
||||
o '++ SimpleAssignable', -> new Op '++', $2
|
||||
o 'SimpleAssignable --', -> new Op '--', $1, null, true
|
||||
o 'SimpleAssignable ++', -> new Op '++', $1, null, true
|
||||
|
||||
o "Expression + Expression", -> new Op '+', $1, $3
|
||||
o "Expression - Expression", -> new Op '-', $1, $3
|
||||
o "Expression == Expression", -> new Op '==', $1, $3
|
||||
o "Expression != Expression", -> new Op '!=', $1, $3
|
||||
o 'Expression + Expression', -> new Op '+' , $1, $3
|
||||
o 'Expression - Expression', -> new Op '-' , $1, $3
|
||||
o 'Expression == Expression', -> new Op '==', $1, $3
|
||||
o 'Expression != Expression', -> new Op '!=', $1, $3
|
||||
|
||||
o "Expression MATH Expression", -> new Op $2, $1, $3
|
||||
o "Expression SHIFT Expression", -> new Op $2, $1, $3
|
||||
o "Expression COMPARE Expression", -> new Op $2, $1, $3
|
||||
o "Expression LOGIC Expression", -> new Op $2, $1, $3
|
||||
o "SimpleAssignable COMPOUND_ASSIGN Expression",
|
||||
-> new Assign $1, $3, $2
|
||||
o "SimpleAssignable COMPOUND_ASSIGN INDENT Expression OUTDENT",
|
||||
-> new Assign $1, $4, $2
|
||||
|
||||
o "Expression RELATION Expression", ->
|
||||
o 'Expression MATH Expression', -> new Op $2, $1, $3
|
||||
o 'Expression SHIFT Expression', -> new Op $2, $1, $3
|
||||
o 'Expression COMPARE Expression', -> new Op $2, $1, $3
|
||||
o 'Expression LOGIC Expression', -> new Op $2, $1, $3
|
||||
o 'Expression RELATION Expression', ->
|
||||
if $2.charAt(0) is '!'
|
||||
if $2 is '!in'
|
||||
new Op '!', new In $1, $3
|
||||
else
|
||||
new Op '!', new Parens new Op $2.slice(1), $1, $3
|
||||
new Op($2.slice(1), $1, $3).invert()
|
||||
else
|
||||
if $2 is 'in' then new In $1, $3 else new Op $2, $1, $3
|
||||
new Op $2, $1, $3
|
||||
|
||||
o 'SimpleAssignable COMPOUND_ASSIGN Expression',
|
||||
-> new Assign $1, $3, $2
|
||||
o 'SimpleAssignable COMPOUND_ASSIGN INDENT Expression OUTDENT',
|
||||
-> new Assign $1, $4, $2
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -881,11 +881,13 @@ exports.Assign = class Assign extends Base
|
||||
# See the [ECMAScript Harmony Wiki](http://wiki.ecmascript.org/doku.php?id=harmony:destructuring)
|
||||
# for details.
|
||||
compilePatternMatch: (o) ->
|
||||
top = del o, 'top'
|
||||
otop = merge o, top: yes
|
||||
if (value = @value).isStatement o then value = Closure.wrap value
|
||||
{objects} = @variable.base
|
||||
return value.compile o unless olength = objects.length
|
||||
isObject = @variable.isObject()
|
||||
if o.top and olength is 1 and (obj = objects[0]) not instanceof Splat
|
||||
if top and olength is 1 and (obj = objects[0]) not instanceof Splat
|
||||
# Unroll simplest cases: `{v} = x` -> `v = x.v`
|
||||
if obj instanceof Assign
|
||||
{variable: {base: idx}, value: obj} = obj
|
||||
@@ -895,9 +897,7 @@ exports.Assign = class Assign extends Base
|
||||
else new Literal 0
|
||||
accessClass = if IDENTIFIER.test idx.value then Accessor else Index
|
||||
(value = Value.wrap value).properties.push new accessClass idx
|
||||
return new Assign(obj, value).compile o
|
||||
top = del o, 'top'
|
||||
otop = merge o, top: yes
|
||||
return new Assign(obj, value).compile otop
|
||||
valVar = value.compile o
|
||||
assigns = []
|
||||
splat = false
|
||||
@@ -1180,6 +1180,7 @@ exports.Op = class Op extends Base
|
||||
children: ['first', 'second']
|
||||
|
||||
constructor: (op, first, second, flip) ->
|
||||
return new In first, second if op is 'in'
|
||||
if op is 'new'
|
||||
return first.newInstance() if first instanceof Call
|
||||
first = new Parens first if first instanceof Code and first.bound
|
||||
@@ -1252,23 +1253,34 @@ exports.In = class In extends Base
|
||||
constructor: (@object, @array) ->
|
||||
super()
|
||||
|
||||
invert: ->
|
||||
@negated = not @negated
|
||||
this
|
||||
|
||||
compileNode: (o) ->
|
||||
code = if @array instanceof Value and @array.isArray()
|
||||
if @array instanceof Value and @array.isArray()
|
||||
@compileOrTest o
|
||||
else
|
||||
@compileLoopTest o
|
||||
if @parenthetical then code else "(#{code})"
|
||||
|
||||
compileOrTest: (o) ->
|
||||
[sub, ref] = @object.compileReference o, precompile: yes
|
||||
[cmp, cnj] = if @negated then [' !== ', ' && '] else [' === ', ' || ']
|
||||
tests = for item, i in @array.base.objects
|
||||
"#{ if i then ref else sub } === #{ item.compile o }"
|
||||
tests.join ' || '
|
||||
(if i then ref else sub) + cmp + item.compile o
|
||||
tests = tests.join cnj
|
||||
if @parenthetical then tests else "(#{tests})"
|
||||
|
||||
compileLoopTest: (o) ->
|
||||
[sub, ref] = @object.compileReference merge(o, top: yes), precompile: yes
|
||||
code = utility('indexOf') + ".call(#{ @array.compile o }, #{ref}) >= 0"
|
||||
if sub is ref then code else sub + ', ' + code
|
||||
code = utility('indexOf') + ".call(#{ @array.compile o }, #{ref}) "
|
||||
code += (if @negated then '< 0' else '>= 0')
|
||||
return code if sub is ref
|
||||
code = sub + ', ' + code
|
||||
if @parenthetical then code else "(#{code})"
|
||||
|
||||
toString: (idt) ->
|
||||
super idt, @constructor.name + if @negated then '!' else ''
|
||||
|
||||
#### Try
|
||||
|
||||
|
||||
Reference in New Issue
Block a user