Skip to content

Commit 8410f8c

Browse files
committed
deoptimized a = delete b.c (gkz/LiveScript#273)
1 parent e181b27 commit 8410f8c

File tree

3 files changed

+26
-35
lines changed

3 files changed

+26
-35
lines changed

lib/ast.js

+12-25
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ exports.Block = Block = (function(superclass){
282282
break;
283283
default:
284284
this.lines.push(it);
285-
if (that = it.back, delete it.back, that) {
285+
if (that = (ref$ = it.back, delete it.back, ref$)) {
286286
this.back = that;
287287
}
288288
}
@@ -377,7 +377,7 @@ exports.Block = Block = (function(superclass){
377377
scope: this.scope = Scope.root = new Scope
378378
}, options));
379379
delete o.filename;
380-
o.indent = (bare = o.bare, delete o.bare, bare) ? '' : TAB;
380+
o.indent = (bare = (ref$ = o.bare, delete o.bare, ref$)) ? '' : TAB;
381381
if (/^\s*(?:[/#]|javascript:)/.test((ref$ = this.lines[0]) != null ? ref$.code : void 8)) {
382382
prefix = this.lines.shift().code + '\n';
383383
}
@@ -659,7 +659,7 @@ exports.Chain = Chain = (function(superclass){
659659
this.head.sproto = true;
660660
}
661661
}
662-
if (that = it.vivify, delete it.vivify, that) {
662+
if (that = (ref$ = it.vivify, delete it.vivify, ref$)) {
663663
this.head = Assign(Chain(this.head, this.tails.splice(0, 9e9)), that(), '=', '||');
664664
}
665665
return this;
@@ -1471,14 +1471,7 @@ exports.Unary = Unary = (function(superclass){
14711471
prototype.compilePluck = function(o){
14721472
var ref$, get, del, code, ref;
14731473
ref$ = Chain(this.it).cacheReference(o), get = ref$[0], del = ref$[1];
1474-
code = this.assigned
1475-
? ''
1476-
: (ref = o.scope.temporary()) + " = ";
1477-
code += get.compile(o, LEVEL_LIST) + ", delete " + del.compile(o, LEVEL_LIST);
1478-
if (this.assigned) {
1479-
return code;
1480-
}
1481-
code += ", " + o.scope.free(ref);
1474+
code = (ref = o.scope.temporary()) + " = " + get.compile(o, LEVEL_LIST) + ", delete " + del.compile(o, LEVEL_LIST) + ", " + o.scope.free(ref);
14821475
if (o.level < LEVEL_LIST) {
14831476
return code;
14841477
} else {
@@ -1764,9 +1757,9 @@ exports.Assign = Assign = (function(superclass){
17641757
}
17651758
};
17661759
prototype.unfoldSoak = function(o){
1767-
var that, ref$, rite, temps;
1760+
var that, ref$, ref1$, rite, temps;
17681761
if (this.left instanceof Existence) {
1769-
if (that = (ref$ = this.left = this.left.it).name, delete ref$.name, that) {
1762+
if (that = (ref1$ = (ref$ = this.left = this.left.it).name, delete ref$.name, ref1$)) {
17701763
rite = this.right;
17711764
rite = Assign(this.right = Var(that), rite);
17721765
} else {
@@ -1780,7 +1773,7 @@ exports.Assign = Assign = (function(superclass){
17801773
return this.access && this;
17811774
};
17821775
prototype.compileNode = function(o){
1783-
var left, ref$, i$, len$, op, right, minmax, lefs, reft, ref, x0$, code, name, lvar, del, that, res;
1776+
var left, ref$, i$, len$, op, right, minmax, lefs, reft, ref, x0$, code, name, lvar, that, res;
17841777
left = this.left.expandSlice(o, true).unwrap();
17851778
if (!this.right) {
17861779
left.isAssignable() || left.carp('invalid unary assign');
@@ -1833,7 +1826,6 @@ exports.Assign = Assign = (function(superclass){
18331826
(right = right.unparen()).ripName(left = left.unwrap());
18341827
code = name = (left.front = true, left).compile(o, LEVEL_LIST);
18351828
if (lvar = left instanceof Var) {
1836-
del = right.op === 'delete';
18371829
if (op === '=') {
18381830
o.scope.declare(name, left, this['const']);
18391831
} else if (that = o.scope.checkReadOnly(name)) {
@@ -1843,14 +1835,9 @@ exports.Assign = Assign = (function(superclass){
18431835
code += " " + (replace$.call(op, ':', '')) + " ";
18441836
code = !o.level && right instanceof While && !right['else'] && (lvar || left instanceof Chain && left.isSimpleAccess())
18451837
? (res = o.scope.temporary('res')) + " = [];\n" + this.tab + right.makeReturn(res).compile(o) + "\n" + this.tab + code + o.scope.free(res)
1846-
: code + (right.assigned = true, right).compile(o, LEVEL_LIST);
1847-
if (that = o.level) {
1848-
if (del) {
1849-
code += ", " + name;
1850-
}
1851-
if (that > (del ? LEVEL_PAREN : LEVEL_LIST)) {
1852-
code = "(" + code + ")";
1853-
}
1838+
: code + right.compile(o, LEVEL_LIST);
1839+
if (o.level > LEVEL_LIST) {
1840+
code = "(" + code + ")";
18541841
}
18551842
return code;
18561843
};
@@ -2212,7 +2199,7 @@ exports.Fun = Fun = (function(superclass){
22122199
this.name || (this.name = it.varName());
22132200
};
22142201
prototype.compileNode = function(o){
2215-
var pscope, sscope, scope, that, loop, body, name, tab, code, ref$;
2202+
var pscope, sscope, scope, that, loop, ref$, body, name, tab, code;
22162203
pscope = o.scope;
22172204
sscope = pscope.shared || pscope;
22182205
scope = o.scope = this.body.scope = new Scope(this.wrapper ? pscope : sscope, this.wrapper && sscope);
@@ -2223,7 +2210,7 @@ exports.Fun = Fun = (function(superclass){
22232210
if (that = this.cname) {
22242211
scope.assign('constructor', that);
22252212
}
2226-
if (loop = o.loop, delete o.loop, loop) {
2213+
if (loop = (ref$ = o.loop, delete o.loop, ref$)) {
22272214
o.indent = this.tab = '';
22282215
}
22292216
o.indent += TAB;

src/ast.co

+6-10
Original file line numberDiff line numberDiff line change
@@ -887,11 +887,10 @@ class exports.Unary extends Node
887887
# `v = delete o.k`
888888
compilePluck: (o) ->
889889
[get, del] = Chain @it .cacheReference o
890-
code = if @assigned then '' else "#{ ref = o.scope.temporary! } = "
891-
code += "#{ get.compile o, LEVEL_LIST }
892-
, delete #{ del.compile o, LEVEL_LIST }"
893-
return code if @assigned
894-
code += ", #{ o.scope.free ref }"
890+
code = "#{ ref = o.scope.temporary! } = \
891+
#{ get.compile o, LEVEL_LIST }, delete \
892+
#{ del.compile o, LEVEL_LIST }, \
893+
#{ o.scope.free ref }"
895894
if o.level < LEVEL_LIST then code else "(#code)"
896895

897896
#### Binary operators
@@ -1106,7 +1105,6 @@ class exports.Assign extends Node
11061105
(right.=unparen!)ripName left.=unwrap!
11071106
code = name = (left <<< {+front})compile o, LEVEL_LIST
11081107
if lvar = left instanceof Var
1109-
del = right.op is \delete
11101108
if op is \=
11111109
o.scope.declare name, left, @const
11121110
else if o.scope.checkReadOnly name
@@ -1119,10 +1117,8 @@ class exports.Assign extends Node
11191117
#{@tab}#{ right.makeReturn(res)compile o }
11201118
#{@tab}#code#{ o.scope.free res }"""
11211119
else
1122-
code + (right <<< {+assigned})compile o, LEVEL_LIST
1123-
if o.level
1124-
code += ", #name" if del
1125-
code = "(#code)" if that > (if del then LEVEL_PAREN else LEVEL_LIST)
1120+
code + right.compile o, LEVEL_LIST
1121+
code = "(#code)" if o.level > LEVEL_LIST
11261122
code
11271123

11281124
!function lefseek node, lefs

test/operator.co

+8
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,8 @@ compileThrows 'invalid decrement' 1 'q.=p--'
357357

358358

359359
### `delete`
360+
# - Disallows variable deletion.
361+
# - Returns the deleted value rather than the useless configurability check.
360362
i = 0
361363
O = ->
362364
switch ++i
@@ -369,6 +371,12 @@ eq o[7], void
369371
compileThrows 'invalid delete' 1 'delete a'
370372
compileThrows 'invalid delete' 1 'delete a.=b'
371373

374+
# [livescript#273](https://github.com/gkz/LiveScript/issues/273)
375+
a = b = ^{0} <<< [1]
376+
a = delete a.0
377+
eq 1 a
378+
eq 0 b.0
379+
372380

373381
### [[Class]] sniffing
374382
eq \RegExp typeof! /^/

0 commit comments

Comments
 (0)