optimized splatting assignment
This commit is contained in:
parent
e36746d367
commit
1cb6464948
29
lib/nodes.js
29
lib/nodes.js
|
@ -933,15 +933,15 @@
|
|||
return o.level <= LEVEL_LIST ? val : "(" + val + ")";
|
||||
};
|
||||
Assign.prototype.compilePatternMatch = function(o) {
|
||||
var _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, acc, assigns, code, i, idx, isObject, ivar, obj, objects, olength, ref, rest, splat, top, val, valVar, value;
|
||||
var _len, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, acc, assigns, code, i, idx, isObject, ivar, obj, objects, olen, ref, rest, splat, top, val, value, vvar;
|
||||
top = o.level === LEVEL_TOP;
|
||||
value = this.value;
|
||||
objects = this.variable.base.objects;
|
||||
if (!(olength = objects.length)) {
|
||||
if (!(olen = objects.length)) {
|
||||
return value.compile(o);
|
||||
}
|
||||
isObject = this.variable.isObject();
|
||||
if (top && olength === 1 && !((obj = objects[0]) instanceof Splat)) {
|
||||
if (top && olen === 1 && !((obj = objects[0]) instanceof Splat)) {
|
||||
if (obj instanceof Assign) {
|
||||
_ref2 = obj, (_ref3 = _ref2.variable, idx = _ref3.base, _ref3), obj = _ref2.value;
|
||||
} else {
|
||||
|
@ -956,12 +956,12 @@
|
|||
value.properties.push(new (acc ? Accessor : Index)(idx));
|
||||
return new Assign(obj, value).compile(o);
|
||||
}
|
||||
valVar = value.compile(o, LEVEL_LIST);
|
||||
vvar = value.compile(o, LEVEL_LIST);
|
||||
assigns = [];
|
||||
splat = false;
|
||||
if (!IDENTIFIER.test(valVar) || this.variable.assigns(valVar)) {
|
||||
assigns.push("" + (ref = o.scope.freeVariable('ref')) + " = " + valVar);
|
||||
valVar = ref;
|
||||
if (!IDENTIFIER.test(vvar) || this.variable.assigns(vvar)) {
|
||||
assigns.push("" + (ref = o.scope.freeVariable('ref')) + " = " + vvar);
|
||||
vvar = ref;
|
||||
}
|
||||
for (i = 0, _len = objects.length; i < _len; i++) {
|
||||
obj = objects[i];
|
||||
|
@ -978,12 +978,15 @@
|
|||
}
|
||||
}
|
||||
if (!splat && obj instanceof Splat) {
|
||||
if (rest = olength - i - 1 || '') {
|
||||
val = "" + olen + " <= " + vvar + ".length ? " + (utility('slice')) + ".call(" + vvar + ", " + i;
|
||||
if (rest = olen - i - 1) {
|
||||
ivar = o.scope.freeVariable('i');
|
||||
rest = ", " + ivar + " = " + valVar + ".length - " + rest;
|
||||
val += ", " + ivar + " = " + vvar + ".length - " + rest + ") : (" + ivar + " = " + i + ", [])";
|
||||
} else {
|
||||
val += ") : []";
|
||||
}
|
||||
val = new Literal(utility('slice') + (".call(" + valVar + ", " + i + rest + ")"));
|
||||
splat = "" + ivar + " < " + i + " ? " + ivar + " = " + i + " : " + ivar + "++";
|
||||
val = new Literal(val);
|
||||
splat = "" + ivar + "++";
|
||||
} else {
|
||||
if (obj instanceof Splat) {
|
||||
obj = obj.name.compile(o);
|
||||
|
@ -995,12 +998,12 @@
|
|||
} else {
|
||||
acc = isObject && IDENTIFIER.test(idx.unwrap().value || 0);
|
||||
}
|
||||
val = new Value(new Literal(valVar), [new (acc ? Accessor : Index)(idx)]);
|
||||
val = new Value(new Literal(vvar), [new (acc ? Accessor : Index)(idx)]);
|
||||
}
|
||||
assigns.push(new Assign(obj, val).compile(o, LEVEL_LIST));
|
||||
}
|
||||
if (!top) {
|
||||
assigns.push(valVar);
|
||||
assigns.push(vvar);
|
||||
}
|
||||
code = assigns.join(', ');
|
||||
return o.level < LEVEL_LIST ? code : "(" + code + ")";
|
||||
|
|
|
@ -764,9 +764,9 @@ exports.Assign = class Assign extends Base
|
|||
top = o.level is LEVEL_TOP
|
||||
{value} = this
|
||||
{objects} = @variable.base
|
||||
return value.compile o unless olength = objects.length
|
||||
return value.compile o unless olen = objects.length
|
||||
isObject = @variable.isObject()
|
||||
if top and olength is 1 and (obj = objects[0]) not instanceof Splat
|
||||
if top and olen 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
|
||||
|
@ -781,12 +781,12 @@ exports.Assign = class Assign extends Base
|
|||
value = new Value value
|
||||
value.properties.push new (if acc then Accessor else Index) idx
|
||||
return new Assign(obj, value).compile o
|
||||
valVar = value.compile o, LEVEL_LIST
|
||||
vvar = value.compile o, LEVEL_LIST
|
||||
assigns = []
|
||||
splat = false
|
||||
if not IDENTIFIER.test(valVar) or @variable.assigns(valVar)
|
||||
assigns.push "#{ ref = o.scope.freeVariable 'ref' } = #{valVar}"
|
||||
valVar = ref
|
||||
if not IDENTIFIER.test(vvar) or @variable.assigns(vvar)
|
||||
assigns.push "#{ ref = o.scope.freeVariable 'ref' } = #{vvar}"
|
||||
vvar = ref
|
||||
for obj, i in objects
|
||||
# A regular array pattern-match.
|
||||
idx = i
|
||||
|
@ -800,11 +800,14 @@ exports.Assign = class Assign extends Base
|
|||
then [obj, idx] = new Value(obj.unwrapAll()).cacheReference o
|
||||
else idx = if obj.tags.this then obj.properties[0].name else obj
|
||||
if not splat and obj instanceof Splat
|
||||
if rest = olength - i - 1 or ''
|
||||
val = "#{olen} <= #{vvar}.length ? #{ utility 'slice' }.call(#{vvar}, #{i}"
|
||||
if rest = olen - i - 1
|
||||
ivar = o.scope.freeVariable 'i'
|
||||
rest = ", #{ivar} = #{valVar}.length - #{rest}"
|
||||
val = new Literal utility('slice') + ".call(#{valVar}, #{i}#{rest})"
|
||||
splat = "#{ivar} < #{i} ? #{ivar} = #{i} : #{ivar}++"
|
||||
val += ", #{ivar} = #{vvar}.length - #{rest}) : (#{ivar} = #{i}, [])"
|
||||
else
|
||||
val += ") : []"
|
||||
val = new Literal val
|
||||
splat = "#{ivar}++"
|
||||
else
|
||||
if obj instanceof Splat
|
||||
obj = obj.name.compile o
|
||||
|
@ -815,9 +818,9 @@ exports.Assign = class Assign extends Base
|
|||
acc = no
|
||||
else
|
||||
acc = isObject and IDENTIFIER.test idx.unwrap().value or 0
|
||||
val = new Value new Literal(valVar), [new (if acc then Accessor else Index) idx]
|
||||
val = new Value new Literal(vvar), [new (if acc then Accessor else Index) idx]
|
||||
assigns.push new Assign(obj, val).compile o, LEVEL_LIST
|
||||
assigns.push valVar unless top
|
||||
assigns.push vvar unless top
|
||||
code = assigns.join ', '
|
||||
if o.level < LEVEL_LIST then code else "(#{code})"
|
||||
|
||||
|
|
|
@ -29,21 +29,28 @@ ok sumOfArgs(1, 2, 3, 4, 5) is 15
|
|||
ok context.arg is 1
|
||||
|
||||
((splat..., @arg) ->).call context, 1, 2, 3
|
||||
ok context.arg is 3
|
||||
eq context.arg, 3
|
||||
|
||||
((@arg...) ->).call context, 1, 2, 3
|
||||
ok context.arg.join ' ' is '1 2 3'
|
||||
eq context.arg.join(' '), '1 2 3'
|
||||
|
||||
class Klass
|
||||
constructor: (@one, @two) ->
|
||||
|
||||
obj = new Klass 1, 2
|
||||
|
||||
ok obj.one is 1
|
||||
ok obj.two is 2
|
||||
eq obj.one, 1
|
||||
eq obj.two, 2
|
||||
|
||||
|
||||
# Default arguments.
|
||||
obj = f: (q = 123, @p = 456) -> q
|
||||
eq obj.f(), 123
|
||||
eq obj.p , 456
|
||||
|
||||
withSplats = (a = 2, b..., c = 3, d = 5) -> a * (b.length + 1) * c * d
|
||||
eq 30, withSplats()
|
||||
eq 15, withSplats 1
|
||||
eq 5, withSplats 1, 1
|
||||
eq 1, withSplats 1, 1, 1
|
||||
eq 2, withSplats 1, 1, 1, 1
|
||||
|
|
Loading…
Reference in New Issue