mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
more cleanups, added a utility helper function to the codegen
This commit is contained in:
parent
6d7a04228f
commit
998a7c8cb0
4 changed files with 35 additions and 33 deletions
34
lib/nodes.js
34
lib/nodes.js
|
@ -1,5 +1,5 @@
|
||||||
(function(){
|
(function(){
|
||||||
var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, CurryNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IfNode, IndexNode, LiteralNode, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, compact, del, flatten, helpers, literal, merge, statement;
|
var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, CurryNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IfNode, IndexNode, LiteralNode, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, Scope, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, UTILITIES, ValueNode, WhileNode, compact, del, flatten, helpers, literal, merge, statement, utility;
|
||||||
var __extend = function(child, parent) {
|
var __extend = function(child, parent) {
|
||||||
var ctor = function(){ };
|
var ctor = function(){ };
|
||||||
ctor.prototype = parent.prototype;
|
ctor.prototype = parent.prototype;
|
||||||
|
@ -596,14 +596,10 @@
|
||||||
};
|
};
|
||||||
CurryNode.prototype.compile_node = function compile_node(o) {
|
CurryNode.prototype.compile_node = function compile_node(o) {
|
||||||
var ref;
|
var ref;
|
||||||
CurryNode.assign_bind();
|
utility('slice');
|
||||||
ref = new ValueNode(literal('__bind'));
|
ref = new ValueNode(literal(utility('bind')));
|
||||||
return (new CallNode(ref, [this.meth, this.context, literal(this.arguments(o))])).compile(o);
|
return (new CallNode(ref, [this.meth, this.context, literal(this.arguments(o))])).compile(o);
|
||||||
};
|
};
|
||||||
CurryNode.assign_bind = function assign_bind() {
|
|
||||||
Scope.root.assign('__slice', UTILITIES['slice']);
|
|
||||||
return Scope.root.assign('__bind', UTILITIES['bind']);
|
|
||||||
};
|
|
||||||
return CurryNode;
|
return CurryNode;
|
||||||
}).call(this);
|
}).call(this);
|
||||||
//### ExtendsNode
|
//### ExtendsNode
|
||||||
|
@ -620,7 +616,7 @@
|
||||||
// Hooks one constructor into another's prototype chain.
|
// Hooks one constructor into another's prototype chain.
|
||||||
ExtendsNode.prototype.compile_node = function compile_node(o) {
|
ExtendsNode.prototype.compile_node = function compile_node(o) {
|
||||||
var ref;
|
var ref;
|
||||||
ref = new ValueNode(literal(Scope.root.assign('__extend', UTILITIES['extend'])));
|
ref = new ValueNode(literal(utility('extend')));
|
||||||
return (new CallNode(ref, [this.child, this.parent])).compile(o);
|
return (new CallNode(ref, [this.child, this.parent])).compile(o);
|
||||||
};
|
};
|
||||||
return ExtendsNode;
|
return ExtendsNode;
|
||||||
|
@ -745,7 +741,7 @@
|
||||||
to = (typeof (_b = this.range.to) !== "undefined" && _b !== null) ? this.range.to : literal('null');
|
to = (typeof (_b = this.range.to) !== "undefined" && _b !== null) ? this.range.to : literal('null');
|
||||||
exclusive = this.range.exclusive ? 'true' : 'false';
|
exclusive = this.range.exclusive ? 'true' : 'false';
|
||||||
v = o.scope.free_variable();
|
v = o.scope.free_variable();
|
||||||
rng = new CallNode(new ValueNode(literal(Scope.root.assign('__range', UTILITIES['range']))), [literal(array), from, to, literal(exclusive)]);
|
rng = new CallNode(new ValueNode(literal(utility('range'))), [literal(array), from, to, literal(exclusive)]);
|
||||||
args = literal("[(" + v + " = " + (rng.compile(o)) + ")[0], " + v + "[1] - " + v + "[0]].concat(" + (replace.compile(o)) + ")");
|
args = literal("[(" + v + " = " + (rng.compile(o)) + ")[0], " + v + "[1] - " + v + "[0]].concat(" + (replace.compile(o)) + ")");
|
||||||
call = new CallNode(new ValueNode(literal(array), [literal('.splice.apply')]), [literal(array), args]);
|
call = new CallNode(new ValueNode(literal(array), [literal('.splice.apply')]), [literal(array), args]);
|
||||||
return call.compile(o);
|
return call.compile(o);
|
||||||
|
@ -756,7 +752,7 @@
|
||||||
from = (typeof (_a = this.range.from) !== "undefined" && _a !== null) ? this.range.from : literal('null');
|
from = (typeof (_a = this.range.from) !== "undefined" && _a !== null) ? this.range.from : literal('null');
|
||||||
to = (typeof (_b = this.range.to) !== "undefined" && _b !== null) ? this.range.to : literal('null');
|
to = (typeof (_b = this.range.to) !== "undefined" && _b !== null) ? this.range.to : literal('null');
|
||||||
exclusive = this.range.exclusive ? 'true' : 'false';
|
exclusive = this.range.exclusive ? 'true' : 'false';
|
||||||
rng = new CallNode(new ValueNode(literal(Scope.root.assign('__range', UTILITIES['range']))), [literal(array), from, to, literal(exclusive)]);
|
rng = new CallNode(new ValueNode(literal(utility('range'))), [literal(array), from, to, literal(exclusive)]);
|
||||||
call = new CallNode(new ValueNode(literal(array), [literal('.slice.apply')]), [literal(array), rng]);
|
call = new CallNode(new ValueNode(literal(array), [literal('.slice.apply')]), [literal(array), rng]);
|
||||||
return call.compile(o);
|
return call.compile(o);
|
||||||
};
|
};
|
||||||
|
@ -1088,8 +1084,8 @@
|
||||||
if (!(this.bound)) {
|
if (!(this.bound)) {
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
CurryNode.assign_bind();
|
utility('slice');
|
||||||
ref = new ValueNode(literal('__bind'));
|
ref = new ValueNode(literal(utility('bind')));
|
||||||
return (new CallNode(ref, [literal(func), literal('this')])).compile(o);
|
return (new CallNode(ref, [literal(func), literal('this')])).compile(o);
|
||||||
};
|
};
|
||||||
CodeNode.prototype.top_sensitive = function top_sensitive() {
|
CodeNode.prototype.top_sensitive = function top_sensitive() {
|
||||||
|
@ -1160,15 +1156,14 @@
|
||||||
o.scope.assign(trailing.compile(o), "arguments[arguments.length - " + this.trailings.length + " + " + i + "]");
|
o.scope.assign(trailing.compile(o), "arguments[arguments.length - " + this.trailings.length + " + " + i + "]");
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
return "" + name + " = " + (Scope.root.assign('__slice', UTILITIES['slice'])) + ".call(arguments, " + this.index + ", arguments.length - " + (this.trailings.length) + ")";
|
return "" + name + " = " + (utility('slice')) + ".call(arguments, " + this.index + ", arguments.length - " + (this.trailings.length) + ")";
|
||||||
};
|
};
|
||||||
// A compiling a splat as a destructuring assignment means slicing arguments
|
// A compiling a splat as a destructuring assignment means slicing arguments
|
||||||
// from the right-hand-side's corresponding array.
|
// from the right-hand-side's corresponding array.
|
||||||
SplatNode.prototype.compile_value = function compile_value(o, name, index, trailings) {
|
SplatNode.prototype.compile_value = function compile_value(o, name, index, trailings) {
|
||||||
var trail;
|
var trail;
|
||||||
Scope.root.assign('__slice', UTILITIES['slice']);
|
|
||||||
trail = trailings ? ", " + (name) + ".length - " + trailings : '';
|
trail = trailings ? ", " + (name) + ".length - " + trailings : '';
|
||||||
return "__slice.call(" + name + ", " + index + trail + ")";
|
return "" + (utility('slice')) + ".call(" + name + ", " + index + trail + ")";
|
||||||
};
|
};
|
||||||
// Utility function that converts arbitrary number of elements, mixed with
|
// Utility function that converts arbitrary number of elements, mixed with
|
||||||
// splats, to a proper array
|
// splats, to a proper array
|
||||||
|
@ -1579,7 +1574,7 @@
|
||||||
body = PushNode.wrap(rvar, body);
|
body = PushNode.wrap(rvar, body);
|
||||||
}
|
}
|
||||||
this.filter ? (body = Expressions.wrap([new IfNode(this.filter, body)])) : null;
|
this.filter ? (body = Expressions.wrap([new IfNode(this.filter, body)])) : null;
|
||||||
this.object ? (for_part = "" + ivar + " in " + svar + ") { if (" + (Scope.root.assign('__hasProp', UTILITIES['hasProp'])) + ".call(" + svar + ", " + ivar + ")") : null;
|
this.object ? (for_part = "" + ivar + " in " + svar + ") { if (" + (utility('hasProp')) + ".call(" + svar + ", " + ivar + ")") : null;
|
||||||
body = body.compile(merge(o, {
|
body = body.compile(merge(o, {
|
||||||
indent: body_dent,
|
indent: body_dent,
|
||||||
top: true
|
top: true
|
||||||
|
@ -1796,4 +1791,11 @@
|
||||||
literal = function literal(name) {
|
literal = function literal(name) {
|
||||||
return new LiteralNode(name);
|
return new LiteralNode(name);
|
||||||
};
|
};
|
||||||
|
// Helper for ensuring that utility functions are assigned at the top level.
|
||||||
|
utility = function utility(name) {
|
||||||
|
var ref;
|
||||||
|
ref = "__" + name;
|
||||||
|
Scope.root.assign(ref, UTILITIES[name]);
|
||||||
|
return ref;
|
||||||
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -85,7 +85,7 @@
|
||||||
value: value,
|
value: value,
|
||||||
assigned: true
|
assigned: true
|
||||||
};
|
};
|
||||||
return name;
|
return this.variables[name];
|
||||||
};
|
};
|
||||||
// Does this scope reference any variables that need to be declared in the
|
// Does this scope reference any variables that need to be declared in the
|
||||||
// given function body?
|
// given function body?
|
||||||
|
|
|
@ -430,14 +430,10 @@ exports.CurryNode: class CurryNode extends CallNode
|
||||||
(new ArrayNode(@args)).compile o
|
(new ArrayNode(@args)).compile o
|
||||||
|
|
||||||
compile_node: (o) ->
|
compile_node: (o) ->
|
||||||
CurryNode.assign_bind()
|
utility 'slice'
|
||||||
ref: new ValueNode literal '__bind'
|
ref: new ValueNode literal utility 'bind'
|
||||||
(new CallNode(ref, [@meth, @context, literal(@arguments(o))])).compile o
|
(new CallNode(ref, [@meth, @context, literal(@arguments(o))])).compile o
|
||||||
|
|
||||||
@assign_bind: ->
|
|
||||||
Scope.root.assign '__slice', UTILITIES['slice']
|
|
||||||
Scope.root.assign '__bind', UTILITIES['bind']
|
|
||||||
|
|
||||||
|
|
||||||
#### ExtendsNode
|
#### ExtendsNode
|
||||||
|
|
||||||
|
@ -452,7 +448,7 @@ exports.ExtendsNode: class ExtendsNode extends BaseNode
|
||||||
|
|
||||||
# Hooks one constructor into another's prototype chain.
|
# Hooks one constructor into another's prototype chain.
|
||||||
compile_node: (o) ->
|
compile_node: (o) ->
|
||||||
ref: new ValueNode literal(Scope.root.assign('__extend', UTILITIES['extend']))
|
ref: new ValueNode literal utility 'extend'
|
||||||
(new CallNode ref, [@child, @parent]).compile o
|
(new CallNode ref, [@child, @parent]).compile o
|
||||||
|
|
||||||
#### AccessorNode
|
#### AccessorNode
|
||||||
|
@ -553,7 +549,7 @@ exports.SliceNode: class SliceNode extends BaseNode
|
||||||
to: if @range.to? then @range.to else literal('null')
|
to: if @range.to? then @range.to else literal('null')
|
||||||
exclusive: if @range.exclusive then 'true' else 'false'
|
exclusive: if @range.exclusive then 'true' else 'false'
|
||||||
v: o.scope.free_variable()
|
v: o.scope.free_variable()
|
||||||
rng: new CallNode new ValueNode(literal(Scope.root.assign('__range', UTILITIES['range']))), [literal(array), from, to, literal(exclusive)]
|
rng: new CallNode new ValueNode(literal(utility('range'))), [literal(array), from, to, literal(exclusive)]
|
||||||
args: literal "[($v = ${rng.compile(o)})[0], $v[1] - $v[0]].concat(${replace.compile(o)})"
|
args: literal "[($v = ${rng.compile(o)})[0], $v[1] - $v[0]].concat(${replace.compile(o)})"
|
||||||
call: new CallNode new ValueNode(literal(array), [literal('.splice.apply')]), [literal(array), args]
|
call: new CallNode new ValueNode(literal(array), [literal('.splice.apply')]), [literal(array), args]
|
||||||
call.compile(o)
|
call.compile(o)
|
||||||
|
@ -563,7 +559,7 @@ exports.SliceNode: class SliceNode extends BaseNode
|
||||||
from: if @range.from? then @range.from else literal('null')
|
from: if @range.from? then @range.from else literal('null')
|
||||||
to: if @range.to? then @range.to else literal('null')
|
to: if @range.to? then @range.to else literal('null')
|
||||||
exclusive: if @range.exclusive then 'true' else 'false'
|
exclusive: if @range.exclusive then 'true' else 'false'
|
||||||
rng: new CallNode new ValueNode(literal(Scope.root.assign('__range', UTILITIES['range']))), [literal(array), from, to, literal(exclusive)]
|
rng: new CallNode new ValueNode(literal(utility('range'))), [literal(array), from, to, literal(exclusive)]
|
||||||
call: new CallNode new ValueNode(literal(array), [literal('.slice.apply')]), [literal(array), rng]
|
call: new CallNode new ValueNode(literal(array), [literal('.slice.apply')]), [literal(array), rng]
|
||||||
call.compile(o)
|
call.compile(o)
|
||||||
|
|
||||||
|
@ -807,8 +803,8 @@ exports.CodeNode: class CodeNode extends BaseNode
|
||||||
func: "function${ if @bound then '' else name_part }(${ params.join(', ') }) {$code${@idt(if @bound then 1 else 0)}}"
|
func: "function${ if @bound then '' else name_part }(${ params.join(', ') }) {$code${@idt(if @bound then 1 else 0)}}"
|
||||||
func: "($func)" if top and not @bound
|
func: "($func)" if top and not @bound
|
||||||
return func unless @bound
|
return func unless @bound
|
||||||
CurryNode.assign_bind()
|
utility 'slice'
|
||||||
ref: new ValueNode literal('__bind')
|
ref: new ValueNode literal utility 'bind'
|
||||||
(new CallNode ref, [literal(func), literal('this')]).compile o
|
(new CallNode ref, [literal(func), literal('this')]).compile o
|
||||||
|
|
||||||
top_sensitive: ->
|
top_sensitive: ->
|
||||||
|
@ -852,14 +848,13 @@ exports.SplatNode: class SplatNode extends BaseNode
|
||||||
for trailing in @trailings
|
for trailing in @trailings
|
||||||
o.scope.assign(trailing.compile(o), "arguments[arguments.length - $@trailings.length + $i]")
|
o.scope.assign(trailing.compile(o), "arguments[arguments.length - $@trailings.length + $i]")
|
||||||
i: + 1
|
i: + 1
|
||||||
"$name = ${Scope.root.assign('__slice', UTILITIES['slice'])}.call(arguments, $@index, arguments.length - ${@trailings.length})"
|
"$name = ${utility('slice')}.call(arguments, $@index, arguments.length - ${@trailings.length})"
|
||||||
|
|
||||||
# A compiling a splat as a destructuring assignment means slicing arguments
|
# A compiling a splat as a destructuring assignment means slicing arguments
|
||||||
# from the right-hand-side's corresponding array.
|
# from the right-hand-side's corresponding array.
|
||||||
compile_value: (o, name, index, trailings) ->
|
compile_value: (o, name, index, trailings) ->
|
||||||
Scope.root.assign '__slice', UTILITIES['slice']
|
|
||||||
trail: if trailings then ", ${name}.length - $trailings" else ''
|
trail: if trailings then ", ${name}.length - $trailings" else ''
|
||||||
"__slice.call($name, $index$trail)"
|
"${utility 'slice'}.call($name, $index$trail)"
|
||||||
|
|
||||||
# Utility function that converts arbitrary number of elements, mixed with
|
# Utility function that converts arbitrary number of elements, mixed with
|
||||||
# splats, to a proper array
|
# splats, to a proper array
|
||||||
|
@ -1178,7 +1173,7 @@ exports.ForNode: class ForNode extends BaseNode
|
||||||
if @filter
|
if @filter
|
||||||
body: Expressions.wrap([new IfNode(@filter, body)])
|
body: Expressions.wrap([new IfNode(@filter, body)])
|
||||||
if @object
|
if @object
|
||||||
for_part: "$ivar in $svar) { if (${Scope.root.assign('__hasProp', UTILITIES['hasProp'])}.call($svar, $ivar)"
|
for_part: "$ivar in $svar) { if (${utility('hasProp')}.call($svar, $ivar)"
|
||||||
body: body.compile(merge(o, {indent: body_dent, top: true}))
|
body: body.compile(merge(o, {indent: body_dent, top: true}))
|
||||||
vars: if range then name else "$name, $ivar"
|
vars: if range then name else "$name, $ivar"
|
||||||
close: if @object then '}}\n' else '}\n'
|
close: if @object then '}}\n' else '}\n'
|
||||||
|
@ -1385,3 +1380,9 @@ IDENTIFIER: /^[a-zA-Z\$_](\w|\$)*$/
|
||||||
# Handy helper for a generating LiteralNode.
|
# Handy helper for a generating LiteralNode.
|
||||||
literal: (name) ->
|
literal: (name) ->
|
||||||
new LiteralNode(name)
|
new LiteralNode(name)
|
||||||
|
|
||||||
|
# Helper for ensuring that utility functions are assigned at the top level.
|
||||||
|
utility: (name) ->
|
||||||
|
ref: "__$name"
|
||||||
|
Scope.root.assign ref, UTILITIES[name]
|
||||||
|
ref
|
||||||
|
|
|
@ -62,7 +62,6 @@ exports.Scope: class Scope
|
||||||
# (or at the top-level scope, if requested).
|
# (or at the top-level scope, if requested).
|
||||||
assign: (name, value) ->
|
assign: (name, value) ->
|
||||||
@variables[name]: {value: value, assigned: true}
|
@variables[name]: {value: value, assigned: true}
|
||||||
name
|
|
||||||
|
|
||||||
# Does this scope reference any variables that need to be declared in the
|
# Does this scope reference any variables that need to be declared in the
|
||||||
# given function body?
|
# given function body?
|
||||||
|
|
Loading…
Reference in a new issue