use Underscore's flatten -- start to make a nicer tree printer

This commit is contained in:
Jeremy Ashkenas
2010-02-13 09:13:50 -05:00
parent dd6be80fca
commit a62923ff97
2 changed files with 34 additions and 43 deletions

View File

@@ -1,5 +1,5 @@
(function(){ (function(){
var AccessorNode, ArrayNode, AssignNode, CallNode, ClosureNode, CodeNode, CommentNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IfNode, IndexNode, LiteralNode, Node, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThisNode, ThrowNode, TryNode, ValueNode, WhileNode, _, del, flatten, inherit, merge, statement; var AccessorNode, ArrayNode, AssignNode, CallNode, ClosureNode, CodeNode, CommentNode, ExistenceNode, Expressions, ExtendsNode, ForNode, IDENTIFIER, IfNode, IndexNode, LiteralNode, Node, ObjectNode, OpNode, ParentheticalNode, PushNode, RangeNode, ReturnNode, SliceNode, SplatNode, TAB, TRAILING_WHITESPACE, ThisNode, ThrowNode, TryNode, ValueNode, WhileNode, _, del, inherit, merge, statement;
var __hasProp = Object.prototype.hasOwnProperty; var __hasProp = Object.prototype.hasOwnProperty;
process.mixin(require('./scope')); process.mixin(require('./scope'));
_ = require('./underscore')._; _ = require('./underscore')._;
@@ -9,21 +9,6 @@
TRAILING_WHITESPACE = /\s+$/gm; TRAILING_WHITESPACE = /\s+$/gm;
// Keep the identifier regex in sync with the Lexer. // Keep the identifier regex in sync with the Lexer.
IDENTIFIER = /^[a-zA-Z$_](\w|\$)*$/; IDENTIFIER = /^[a-zA-Z$_](\w|\$)*$/;
// Flatten nested arrays recursively.
flatten = function flatten(list) {
var __a, __b, item, memo;
memo = [];
__a = list;
for (__b = 0; __b < __a.length; __b++) {
item = __a[__b];
if (item instanceof Array) {
return memo.concat(flatten(item));
}
memo.push(item);
memo;
}
return memo;
};
// Merge objects. // Merge objects.
merge = function merge(options, overrides) { merge = function merge(options, overrides) {
return _.tap({}, function(fresh) { return _.tap({}, function(fresh) {
@@ -123,16 +108,10 @@
}; };
// toString representation of the node, for inspecting the parse tree. // toString representation of the node, for inspecting the parse tree.
Node.prototype.toString = function toString(idt) { Node.prototype.toString = function toString(idt) {
var __a, __b, __c, child;
idt = (idt || '') + TAB; idt = (idt || '') + TAB;
return this.type + "\n" + ((function() { return this.type + '\n' + _.map(this.children, function(child) {
__a = []; __b = this.children; return idt + child.toString(idt);
for (__c = 0; __c < __b.length; __c++) { }).join('');
child = __b[__c];
__a.push(idt + child.toString(idt));
}
return __a;
}).call(this)).join('');
}; };
// Default implementations of the common node methods. // Default implementations of the common node methods.
Node.prototype.unwrap = function unwrap() { Node.prototype.unwrap = function unwrap() {
@@ -152,7 +131,7 @@
Expressions = (exports.Expressions = inherit(Node, { Expressions = (exports.Expressions = inherit(Node, {
type: 'Expressions', type: 'Expressions',
constructor: function constructor(nodes) { constructor: function constructor(nodes) {
this.children = (this.expressions = _.compact(flatten(nodes || []))); this.children = (this.expressions = _.compact(_.flatten(nodes || [])));
return this; return this;
}, },
// Tack an expression on to the end of this expression list. // Tack an expression on to the end of this expression list.
@@ -274,6 +253,9 @@
idt = this.is_statement() ? this.idt() : ''; idt = this.is_statement() ? this.idt() : '';
end = this.is_statement() ? ';' : ''; end = this.is_statement() ? ';' : '';
return idt + this.value + end; return idt + this.value + end;
},
toString: function toString(idt) {
return '"' + this.value + '"' + '\n';
} }
})); }));
LiteralNode.prototype.is_statement_only = LiteralNode.prototype.is_statement; LiteralNode.prototype.is_statement_only = LiteralNode.prototype.is_statement;
@@ -299,7 +281,7 @@
type: 'Value', type: 'Value',
SOAK: " == undefined ? undefined : ", SOAK: " == undefined ? undefined : ",
constructor: function constructor(base, properties) { constructor: function constructor(base, properties) {
this.children = flatten((this.base = base), (this.properties = (properties || []))); this.children = _.flatten([(this.base = base), (this.properties = (properties || []))]);
return this; return this;
}, },
push: function push(prop) { push: function push(prop) {
@@ -380,7 +362,7 @@
CallNode = (exports.CallNode = inherit(Node, { CallNode = (exports.CallNode = inherit(Node, {
type: 'Call', type: 'Call',
constructor: function constructor(variable, args) { constructor: function constructor(variable, args) {
this.children = flatten([(this.variable = variable), (this.args = (args || []))]); this.children = _.flatten([(this.variable = variable), (this.args = (args || []))]);
this.prefix = ''; this.prefix = '';
return this; return this;
}, },
@@ -821,6 +803,16 @@
}, },
top_sensitive: function top_sensitive() { top_sensitive: function top_sensitive() {
return true; return true;
},
toString: function toString(idt) {
var children;
idt = (idt || '') + TAB;
puts(this.body.expressions.length);
children = _.flatten([this.params, this.body.expressions]);
puts(children.length);
return this.type + '\n' + _.map(children, function(child) {
return idt + child.toString(idt);
}).join('');
} }
})); }));
// A splat, either as a parameter to a function, an argument to a call, // A splat, either as a parameter to a function, an argument to a call,
@@ -1206,7 +1198,7 @@
compile_condition: function compile_condition(o) { compile_condition: function compile_condition(o) {
var __a, __b, __c, cond; var __a, __b, __c, cond;
return ((function() { return ((function() {
__a = []; __b = flatten([this.condition]); __a = []; __b = _.flatten([this.condition]);
for (__c = 0; __c < __b.length; __c++) { for (__c = 0; __c < __b.length; __c++) {
cond = __b[__c]; cond = __b[__c];
__a.push(cond.compile(o)); __a.push(cond.compile(o));

View File

@@ -10,15 +10,6 @@ TRAILING_WHITESPACE: /\s+$/gm
# Keep the identifier regex in sync with the Lexer. # Keep the identifier regex in sync with the Lexer.
IDENTIFIER: /^[a-zA-Z$_](\w|\$)*$/ IDENTIFIER: /^[a-zA-Z$_](\w|\$)*$/
# Flatten nested arrays recursively.
flatten: (list) ->
memo: []
for item in list
return memo.concat(flatten(item)) if item instanceof Array
memo.push(item)
memo
memo
# Merge objects. # Merge objects.
merge: (options, overrides) -> merge: (options, overrides) ->
_.tap {}, (fresh) -> _.tap {}, (fresh) ->
@@ -88,7 +79,7 @@ Node::contains: (block) ->
# toString representation of the node, for inspecting the parse tree. # toString representation of the node, for inspecting the parse tree.
Node::toString: (idt) -> Node::toString: (idt) ->
idt: (idt || '') + TAB idt: (idt || '') + TAB
@type + "\n" + (idt + child.toString(idt) for child in @children).join('') @type + '\n' + _.map(@children, (child) -> idt + child.toString(idt)).join('')
# Default implementations of the common node methods. # Default implementations of the common node methods.
Node::unwrap: -> this Node::unwrap: -> this
@@ -102,7 +93,7 @@ Expressions: exports.Expressions: inherit Node, {
type: 'Expressions' type: 'Expressions'
constructor: (nodes) -> constructor: (nodes) ->
@children: @expressions: _.compact flatten nodes or [] @children: @expressions: _.compact _.flatten nodes or []
this this
# Tack an expression on to the end of this expression list. # Tack an expression on to the end of this expression list.
@@ -197,6 +188,9 @@ LiteralNode: exports.LiteralNode: inherit Node, {
end: if @is_statement() then ';' else '' end: if @is_statement() then ';' else ''
idt + @value + end idt + @value + end
toString: (idt) ->
'"' + @value + '"' + '\n'
} }
LiteralNode::is_statement_only: LiteralNode::is_statement LiteralNode::is_statement_only: LiteralNode::is_statement
@@ -224,7 +218,7 @@ ValueNode: exports.ValueNode: inherit Node, {
SOAK: " == undefined ? undefined : " SOAK: " == undefined ? undefined : "
constructor: (base, properties) -> constructor: (base, properties) ->
@children: flatten(@base: base, @properties: (properties or [])) @children: _.flatten [@base: base, @properties: (properties or [])]
this this
push: (prop) -> push: (prop) ->
@@ -304,7 +298,7 @@ CallNode: exports.CallNode: inherit Node, {
type: 'Call' type: 'Call'
constructor: (variable, args) -> constructor: (variable, args) ->
@children: flatten [@variable: variable, @args: (args or [])] @children: _.flatten [@variable: variable, @args: (args or [])]
@prefix: '' @prefix: ''
this this
@@ -658,6 +652,11 @@ CodeNode: exports.CodeNode: inherit Node, {
top_sensitive: -> top_sensitive: ->
true true
toString: (idt) ->
idt: (idt || '') + TAB
children: _.flatten [@params, @body.expressions]
@type + '\n' + _.map(children, (child) -> idt + child.toString(idt)).join('')
} }
# A splat, either as a parameter to a function, an argument to a call, # A splat, either as a parameter to a function, an argument to a call,
@@ -973,7 +972,7 @@ IfNode: exports.IfNode: inherit Node, {
@statement ||= !!(@comment or @tags.statement or @body.is_statement() or (@else_body and @else_body.is_statement())) @statement ||= !!(@comment or @tags.statement or @body.is_statement() or (@else_body and @else_body.is_statement()))
compile_condition: (o) -> compile_condition: (o) ->
(cond.compile(o) for cond in flatten([@condition])).join(' || ') (cond.compile(o) for cond in _.flatten([@condition])).join(' || ')
compile_node: (o) -> compile_node: (o) ->
if @is_statement() then @compile_statement(o) else @compile_ternary(o) if @is_statement() then @compile_statement(o) else @compile_ternary(o)