removing the (now-unused) inherits helper, and adding a helper for creating LiteralNodes

This commit is contained in:
Jeremy Ashkenas 2010-02-28 00:22:06 -05:00
parent 56eb474bf3
commit fec2eaef7e
2 changed files with 35 additions and 46 deletions

View File

@ -1,5 +1,5 @@
(function(){ (function(){
var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IfNode, IndexNode, LiteralNode, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, ValueNode, WhileNode, compact, del, flatten, inherit, merge, statement; var AccessorNode, ArrayNode, AssignNode, BaseNode, CallNode, ClassNode, ClosureNode, CodeNode, CommentNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IfNode, IndexNode, LiteralNode, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThrowNode, TryNode, ValueNode, WhileNode, compact, del, flatten, literal, merge, statement;
var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
var ctor = function(){ }; var ctor = function(){ };
ctor.prototype = parent.prototype; ctor.prototype = parent.prototype;
@ -62,17 +62,9 @@
delete obj[key]; delete obj[key];
return val; return val;
}; };
// Quickie inheritance convenience wrapper to reduce typing. // Quickie helper for a generated LiteralNode.
inherit = function inherit(parent, props) { literal = function literal(name) {
var _a, klass, name, prop; return new LiteralNode(name);
klass = del(props, 'constructor');
__extends(klass, parent);
_a = props;
for (name in _a) { if (__hasProp.call(_a, name)) {
prop = _a[name];
((klass.prototype[name] = prop));
}}
return klass;
}; };
// Mark a node as a statement, or a statement only. // Mark a node as a statement, or a statement only.
statement = function statement(klass, only) { statement = function statement(klass, only) {
@ -122,7 +114,7 @@
// in multiple places, ensure that the expression is only ever evaluated once. // in multiple places, ensure that the expression is only ever evaluated once.
BaseNode.prototype.compile_reference = function compile_reference(o) { BaseNode.prototype.compile_reference = function compile_reference(o) {
var compiled, reference; var compiled, reference;
reference = new LiteralNode(o.scope.free_variable()); reference = literal(o.scope.free_variable());
compiled = new AssignNode(reference, this); compiled = new AssignNode(reference, this);
return [compiled, reference]; return [compiled, reference];
}; };
@ -527,7 +519,7 @@
ExtendsNode.prototype.compile_node = function compile_node(o) { ExtendsNode.prototype.compile_node = function compile_node(o) {
var call, ref; var call, ref;
o.scope.assign('__extends', this.code, true); o.scope.assign('__extends', this.code, true);
ref = new ValueNode(new LiteralNode('__extends')); ref = new ValueNode(literal('__extends'));
call = new CallNode(ref, [this.child, this.parent]); call = new CallNode(ref, [this.child, this.parent]);
return call.compile(o); return call.compile(o);
}; };
@ -601,10 +593,10 @@
RangeNode.prototype.compile_array = function compile_array(o) { RangeNode.prototype.compile_array = function compile_array(o) {
var arr, body, name; var arr, body, name;
name = o.scope.free_variable(); name = o.scope.free_variable();
body = Expressions.wrap([new LiteralNode(name)]); body = Expressions.wrap([literal(name)]);
arr = Expressions.wrap([new ForNode(body, { arr = Expressions.wrap([new ForNode(body, {
source: (new ValueNode(this)) source: (new ValueNode(this))
}, new LiteralNode(name)) }, literal(name))
]); ]);
return (new ParentheticalNode(new CallNode(new CodeNode([], arr)))).compile(o); return (new ParentheticalNode(new CallNode(new CodeNode([], arr)))).compile(o);
}; };
@ -699,7 +691,7 @@
prop = _a[_b]; prop = _a[_b];
if (prop.variable && prop.variable.base.value === 'constructor') { if (prop.variable && prop.variable.base.value === 'constructor') {
func = prop.value; func = prop.value;
func.body.push(new ReturnNode(new LiteralNode('this'))); func.body.push(new ReturnNode(literal('this')));
constructor = new AssignNode(this.variable, func); constructor = new AssignNode(this.variable, func);
} else { } else {
if (prop.variable) { if (prop.variable) {
@ -711,8 +703,8 @@
} }
if (!constructor) { if (!constructor) {
if (this.parent) { if (this.parent) {
applied = new ValueNode(this.parent, [new AccessorNode(new LiteralNode('apply'))]); applied = new ValueNode(this.parent, [new AccessorNode(literal('apply'))]);
constructor = new AssignNode(this.variable, new CodeNode([], new Expressions([new CallNode(applied, [new LiteralNode('this'), new LiteralNode('arguments')])]))); constructor = new AssignNode(this.variable, new CodeNode([], new Expressions([new CallNode(applied, [literal('this'), literal('arguments')])])));
} else { } else {
constructor = new AssignNode(this.variable, new CodeNode()); constructor = new AssignNode(this.variable, new CodeNode());
} }
@ -771,7 +763,7 @@
})) { })) {
return expressions; return expressions;
} }
return Expressions.wrap([new CallNode(new ValueNode(new LiteralNode(array), [new AccessorNode(new LiteralNode('push'))]), [expr])]); return Expressions.wrap([new CallNode(new ValueNode(literal(array), [new AccessorNode(literal('push'))]), [expr])]);
} }
}); });
// A faux-node used to wrap an expressions body in a closure. // A faux-node used to wrap an expressions body in a closure.
@ -779,7 +771,7 @@
wrap: function wrap(expressions, statement) { wrap: function wrap(expressions, statement) {
var call, func; var call, func;
func = new ParentheticalNode(new CodeNode([], Expressions.wrap([expressions]))); func = new ParentheticalNode(new CodeNode([], Expressions.wrap([expressions])));
call = new CallNode(new ValueNode(func, [new AccessorNode(new LiteralNode('call'))]), [new LiteralNode('this')]); call = new CallNode(new ValueNode(func, [new AccessorNode(literal('call'))]), [literal('this')]);
return statement ? Expressions.wrap([call]) : call; return statement ? Expressions.wrap([call]) : call;
} }
}); });
@ -864,12 +856,12 @@
} }
access_class = this.variable.is_array() ? IndexNode : AccessorNode; access_class = this.variable.is_array() ? IndexNode : AccessorNode;
if (obj instanceof SplatNode) { if (obj instanceof SplatNode) {
val = new LiteralNode(obj.compile_value(o, val_var, this.variable.base.objects.indexOf(obj))); val = literal(obj.compile_value(o, val_var, this.variable.base.objects.indexOf(obj)));
} else { } else {
if (!(typeof idx === 'object')) { if (!(typeof idx === 'object')) {
idx = new LiteralNode(idx); idx = literal(idx);
} }
val = new ValueNode(new LiteralNode(val_var), [new access_class(idx)]); val = new ValueNode(literal(val_var), [new access_class(idx)]);
} }
assigns.push(new AssignNode(obj, val).compile(o)); assigns.push(new AssignNode(obj, val).compile(o));
} }
@ -979,7 +971,7 @@
exports.SplatNode = (function() { exports.SplatNode = (function() {
SplatNode = function SplatNode(name) { SplatNode = function SplatNode(name) {
if (!(name.compile)) { if (!(name.compile)) {
name = new LiteralNode(name); name = literal(name);
} }
this.children = [(this.name = name)]; this.children = [(this.name = name)];
return this; return this;
@ -1367,7 +1359,7 @@
var _a, _b, _c, assigner, cond, i, variable; var _a, _b, _c, assigner, cond, i, variable;
assigner = this.switcher; assigner = this.switcher;
if (!(this.switcher.unwrap() instanceof LiteralNode)) { if (!(this.switcher.unwrap() instanceof LiteralNode)) {
variable = new LiteralNode(o.scope.free_variable()); variable = literal(o.scope.free_variable());
assigner = new AssignNode(variable, this.switcher); assigner = new AssignNode(variable, this.switcher);
this.switcher = variable; this.switcher = variable;
} }

View File

@ -36,12 +36,9 @@ del: (obj, key) ->
delete obj[key] delete obj[key]
val val
# Quickie inheritance convenience wrapper to reduce typing. # Quickie helper for a generated LiteralNode.
inherit: (parent, props) -> literal: (name) ->
klass: del(props, 'constructor') new LiteralNode(name)
klass extends parent
(klass.prototype[name]: prop) for name, prop of props
klass
# Mark a node as a statement, or a statement only. # Mark a node as a statement, or a statement only.
statement: (klass, only) -> statement: (klass, only) ->
@ -82,7 +79,7 @@ exports.BaseNode: class BaseNode
# If the code generation wishes to use the result of a complex expression # If the code generation wishes to use the result of a complex expression
# in multiple places, ensure that the expression is only ever evaluated once. # in multiple places, ensure that the expression is only ever evaluated once.
compile_reference: (o) -> compile_reference: (o) ->
reference: new LiteralNode(o.scope.free_variable()) reference: literal(o.scope.free_variable())
compiled: new AssignNode(reference, this) compiled: new AssignNode(reference, this)
[compiled, reference] [compiled, reference]
@ -387,7 +384,7 @@ exports.ExtendsNode: class ExtendsNode extends BaseNode
# Hooking one constructor into another's prototype chain. # Hooking one constructor into another's prototype chain.
compile_node: (o) -> compile_node: (o) ->
o.scope.assign('__extends', @code, true) o.scope.assign('__extends', @code, true)
ref: new ValueNode new LiteralNode '__extends' ref: new ValueNode literal('__extends')
call: new CallNode ref, [@child, @parent] call: new CallNode ref, [@child, @parent]
call.compile(o) call.compile(o)
@ -451,8 +448,8 @@ exports.RangeNode: class RangeNode extends BaseNode
# TODO: This generates pretty ugly code ... shrink it. # TODO: This generates pretty ugly code ... shrink it.
compile_array: (o) -> compile_array: (o) ->
name: o.scope.free_variable() name: o.scope.free_variable()
body: Expressions.wrap([new LiteralNode(name)]) body: Expressions.wrap([literal(name)])
arr: Expressions.wrap([new ForNode(body, {source: (new ValueNode(this))}, new LiteralNode(name))]) arr: Expressions.wrap([new ForNode(body, {source: (new ValueNode(this))}, literal(name))])
(new ParentheticalNode(new CallNode(new CodeNode([], arr)))).compile(o) (new ParentheticalNode(new CallNode(new CodeNode([], arr)))).compile(o)
@ -515,7 +512,7 @@ exports.ClassNode: class ClassNode extends BaseNode
for prop in @properties for prop in @properties
if prop.variable and prop.variable.base.value is 'constructor' if prop.variable and prop.variable.base.value is 'constructor'
func: prop.value func: prop.value
func.body.push(new ReturnNode(new LiteralNode('this'))) func.body.push(new ReturnNode(literal('this')))
constructor: new AssignNode(@variable, func) constructor: new AssignNode(@variable, func)
else else
if prop.variable if prop.variable
@ -525,9 +522,9 @@ exports.ClassNode: class ClassNode extends BaseNode
if not constructor if not constructor
if @parent if @parent
applied: new ValueNode(@parent, [new AccessorNode(new LiteralNode('apply'))]) applied: new ValueNode(@parent, [new AccessorNode(literal('apply'))])
constructor: new AssignNode(@variable, new CodeNode([], new Expressions([ constructor: new AssignNode(@variable, new CodeNode([], new Expressions([
new CallNode(applied, [new LiteralNode('this'), new LiteralNode('arguments')]) new CallNode(applied, [literal('this'), literal('arguments')])
]))) ])))
else else
constructor: new AssignNode(@variable, new CodeNode()) constructor: new AssignNode(@variable, new CodeNode())
@ -571,7 +568,7 @@ PushNode: exports.PushNode: {
expr: expressions.unwrap() expr: expressions.unwrap()
return expressions if expr.is_statement_only() or expr.contains (n) -> n.is_statement_only() return expressions if expr.is_statement_only() or expr.contains (n) -> n.is_statement_only()
Expressions.wrap([new CallNode( Expressions.wrap([new CallNode(
new ValueNode(new LiteralNode(array), [new AccessorNode(new LiteralNode('push'))]), [expr] new ValueNode(literal(array), [new AccessorNode(literal('push'))]), [expr]
)]) )])
} }
@ -582,7 +579,7 @@ ClosureNode: exports.ClosureNode: {
wrap: (expressions, statement) -> wrap: (expressions, statement) ->
func: new ParentheticalNode(new CodeNode([], Expressions.wrap([expressions]))) func: new ParentheticalNode(new CodeNode([], Expressions.wrap([expressions])))
call: new CallNode(new ValueNode(func, [new AccessorNode(new LiteralNode('call'))]), [new LiteralNode('this')]) call: new CallNode(new ValueNode(func, [new AccessorNode(literal('call'))]), [literal('this')])
if statement then Expressions.wrap([call]) else call if statement then Expressions.wrap([call]) else call
} }
@ -642,10 +639,10 @@ exports.AssignNode: class AssignNode extends BaseNode
[obj, idx]: [obj.value, obj.variable.base] if @variable.is_object() [obj, idx]: [obj.value, obj.variable.base] if @variable.is_object()
access_class: if @variable.is_array() then IndexNode else AccessorNode access_class: if @variable.is_array() then IndexNode else AccessorNode
if obj instanceof SplatNode if obj instanceof SplatNode
val: new LiteralNode(obj.compile_value(o, val_var, @variable.base.objects.indexOf(obj))) val: literal(obj.compile_value(o, val_var, @variable.base.objects.indexOf(obj)))
else else
idx: new LiteralNode(idx) unless typeof idx is 'object' idx: literal(idx) unless typeof idx is 'object'
val: new ValueNode(new LiteralNode(val_var), [new access_class(idx)]) val: new ValueNode(literal(val_var), [new access_class(idx)])
assigns.push(new AssignNode(obj, val).compile(o)) assigns.push(new AssignNode(obj, val).compile(o))
code: assigns.join("\n") code: assigns.join("\n")
code += '\n' + @idt() + 'return ' + @variable.compile(o) + ';' if o.returns code += '\n' + @idt() + 'return ' + @variable.compile(o) + ';' if o.returns
@ -715,7 +712,7 @@ exports.SplatNode: class SplatNode extends BaseNode
type: 'Splat' type: 'Splat'
constructor: (name) -> constructor: (name) ->
name: new LiteralNode(name) unless name.compile name: literal(name) unless name.compile
@children: [@name: name] @children: [@name: name]
compile_node: (o) -> compile_node: (o) ->
@ -1001,7 +998,7 @@ exports.IfNode: class IfNode extends BaseNode
rewrite_switch: (o) -> rewrite_switch: (o) ->
assigner: @switcher assigner: @switcher
if not (@switcher.unwrap() instanceof LiteralNode) if not (@switcher.unwrap() instanceof LiteralNode)
variable: new LiteralNode(o.scope.free_variable()) variable: literal(o.scope.free_variable())
assigner: new AssignNode(variable, @switcher) assigner: new AssignNode(variable, @switcher)
@switcher: variable @switcher: variable
@condition: if @multiple @condition: if @multiple