1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

nodes: reformatted

This commit is contained in:
satyr 2010-10-25 08:55:42 +09:00
parent 7bfb2e3a78
commit 101a044219
2 changed files with 62 additions and 106 deletions

View file

@ -6,9 +6,6 @@
child.prototype = new ctor; child.prototype = new ctor;
if (typeof parent.extended === "function") parent.extended(child); if (typeof parent.extended === "function") parent.extended(child);
child.__super__ = parent.prototype; child.__super__ = parent.prototype;
}, __indexOf = Array.prototype.indexOf || function(item) {
for (var i = 0, l = this.length; i < l; i++) if (this[i] === item) return i;
return -1;
}; };
Scope = require('./scope').Scope; Scope = require('./scope').Scope;
_ref = require('./helpers'), compact = _ref.compact, flatten = _ref.flatten, extend = _ref.extend, merge = _ref.merge, del = _ref.del, starts = _ref.starts, ends = _ref.ends, last = _ref.last; _ref = require('./helpers'), compact = _ref.compact, flatten = _ref.flatten, extend = _ref.extend, merge = _ref.merge, del = _ref.del, starts = _ref.starts, ends = _ref.ends, last = _ref.last;
@ -347,13 +344,19 @@
return !!this.properties.length; return !!this.properties.length;
}; };
Value.prototype.isArray = function() { Value.prototype.isArray = function() {
return this.base instanceof Arr && !this.properties.length; return !this.properties.length && this.base instanceof Arr;
}; };
Value.prototype.isObject = function() { Value.prototype.isObject = function() {
return this.base instanceof Obj && !this.properties.length; return !this.properties.length && this.base instanceof Obj;
}; };
Value.prototype.isComplex = function() { Value.prototype.isComplex = function() {
return this.base.isComplex() || this.hasProperties(); return this.hasProperties() || this.base.isComplex();
};
Value.prototype.isAssignable = function() {
return this.hasProperties() || this.base.isAssignable();
};
Value.prototype.isSimpleNumber = function() {
return this.base instanceof Literal && SIMPLENUM.test(this.base.value);
}; };
Value.prototype.isAtomic = function() { Value.prototype.isAtomic = function() {
var _i, _len, _ref2, node; var _i, _len, _ref2, node;
@ -366,8 +369,8 @@
} }
return true; return true;
}; };
Value.prototype.isAssignable = function() { Value.prototype.isStatement = function(o) {
return this.hasProperties() || this.base.isAssignable(); return !this.properties.length && this.base.isStatement(o);
}; };
Value.prototype.assigns = function(name) { Value.prototype.assigns = function(name) {
return !this.properties.length && this.base.assigns(name); return !this.properties.length && this.base.assigns(name);
@ -378,12 +381,6 @@
Value.prototype.unwrap = function() { Value.prototype.unwrap = function() {
return this.properties.length ? this : this.base; return this.properties.length ? this : this.base;
}; };
Value.prototype.isStatement = function(o) {
return !this.properties.length && this.base.isStatement(o);
};
Value.prototype.isSimpleNumber = function() {
return this.base instanceof Literal && SIMPLENUM.test(this.base.value);
};
Value.prototype.cacheReference = function(o) { Value.prototype.cacheReference = function(o) {
var base, bref, name, nref; var base, bref, name, nref;
name = last(this.properties); name = last(this.properties);
@ -479,9 +476,6 @@
})(); })();
__extends(Call, Base); __extends(Call, Base);
Call.prototype.children = ['variable', 'args']; Call.prototype.children = ['variable', 'args'];
Call.prototype.compileSplatArguments = function(o) {
return Splat.compileSplattedArray(this.args, o);
};
Call.prototype.newInstance = function() { Call.prototype.newInstance = function() {
this.isNew = true; this.isNew = true;
return this; return this;
@ -575,7 +569,7 @@
}; };
Call.prototype.compileSplat = function(o) { Call.prototype.compileSplat = function(o) {
var base, fun, idt, name, ref, splatargs; var base, fun, idt, name, ref, splatargs;
splatargs = this.compileSplatArguments(o); splatargs = Splat.compileSplattedArray(this.args, o);
if (this.isSuper) { if (this.isSuper) {
return "" + (this.superReference(o)) + ".apply(this, " + splatargs + ")"; return "" + (this.superReference(o)) + ".apply(this, " + splatargs + ")";
} }
@ -753,9 +747,6 @@
})(); })();
__extends(Arr, Base); __extends(Arr, Base);
Arr.prototype.children = ['objects']; Arr.prototype.children = ['objects'];
Arr.prototype.compileSplatLiteral = function(o) {
return Splat.compileSplattedArray(this.objects, o);
};
Arr.prototype.compileNode = function(o) { Arr.prototype.compileNode = function(o) {
var _i, _len, _len2, _ref2, _ref3, code, i, obj, objects; var _i, _len, _len2, _ref2, _ref3, code, i, obj, objects;
o.indent = this.idt(1); o.indent = this.idt(1);
@ -763,7 +754,7 @@
for (_i = 0, _len = _ref2.length; _i < _len; _i++) { for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
obj = _ref2[_i]; obj = _ref2[_i];
if (obj instanceof Splat) { if (obj instanceof Splat) {
return this.compileSplatLiteral(o); return Splat.compileSplattedArray(this.objects, o);
} }
} }
objects = []; objects = [];
@ -901,7 +892,6 @@
})(); })();
__extends(Assign, Base); __extends(Assign, Base);
Assign.prototype.METHOD_DEF = /^(?:(\S+)\.prototype\.)?([$A-Za-z_][$\w]*)$/; Assign.prototype.METHOD_DEF = /^(?:(\S+)\.prototype\.)?([$A-Za-z_][$\w]*)$/;
Assign.prototype.CONDITIONAL = ['||=', '&&=', '?='];
Assign.prototype.children = ['variable', 'value']; Assign.prototype.children = ['variable', 'value'];
Assign.prototype.assigns = function(name) { Assign.prototype.assigns = function(name) {
return this[this.context === 'object' ? 'value' : 'variable'].assigns(name); return this[this.context === 'object' ? 'value' : 'variable'].assigns(name);
@ -915,7 +905,7 @@
if (this.variable.isArray() || this.variable.isObject()) { if (this.variable.isArray() || this.variable.isObject()) {
return this.compilePatternMatch(o); return this.compilePatternMatch(o);
} }
if (_ref2 = this.context, __indexOf.call(this.CONDITIONAL, _ref2) >= 0) { if ((_ref2 = this.context) === '||=' || _ref2 === '&&=' || _ref2 === '?=') {
return this.compileConditional(o); return this.compileConditional(o);
} }
} }
@ -1011,12 +1001,10 @@
})(); })();
exports.Code = (function() { exports.Code = (function() {
Code = (function() { Code = (function() {
function Code(_arg, _arg2, tag) { function Code(params, body, tag) {
this.body = _arg2;
this.params = _arg;
Code.__super__.constructor.call(this); Code.__super__.constructor.call(this);
this.params || (this.params = []); this.params = params || [];
this.body || (this.body = new Expressions); this.body = body || new Expressions;
this.bound = tag === 'boundfunc'; this.bound = tag === 'boundfunc';
if (this.bound) { if (this.bound) {
this.context = 'this'; this.context = 'this';
@ -1111,12 +1099,11 @@
})(); })();
exports.Param = (function() { exports.Param = (function() {
Param = (function() { Param = (function() {
function Param(_arg, _arg2, _arg3) { function Param(name, _arg, _arg2) {
this.splat = _arg3; this.splat = _arg2;
this.attach = _arg2; this.attach = _arg;
this.name = _arg;
Param.__super__.constructor.call(this); Param.__super__.constructor.call(this);
this.value = new Literal(this.name); this.value = new Literal(this.name = name);
return this; return this;
}; };
return Param; return Param;
@ -1796,11 +1783,11 @@
return If; return If;
}).call(this); }).call(this);
Push = { Push = {
wrap: function(name, expressions) { wrap: function(name, exps) {
if (expressions.isEmpty() || last(expressions.expressions).containsPureStatement()) { if (exps.isEmpty() || last(exps.expressions).containsPureStatement()) {
return expressions; return exps;
} }
return expressions.push(new Call(new Value(new Literal(name), [new Accessor(new Literal('push'))]), [expressions.pop()])); return exps.push(new Call(new Value(new Literal(name), [new Accessor(new Literal('push'))]), [exps.pop()]));
} }
}; };
Closure = { Closure = {

View file

@ -28,8 +28,7 @@ THIS = -> this
# scope, and indentation level. # scope, and indentation level.
exports.Base = class Base exports.Base = class Base
constructor: -> constructor: -> @tags = {}
@tags = {}
# Common logic for determining whether to wrap this node in a closure before # Common logic for determining whether to wrap this node in a closure before
# compiling it, or to compile directly. We need to wrap if this node is a # compiling it, or to compile directly. We need to wrap if this node is a
@ -81,8 +80,7 @@ exports.Base = class Base
# Construct a node that returns the current node's result. # Construct a node that returns the current node's result.
# Note that this is overridden for smarter behavior for # Note that this is overridden for smarter behavior for
# many statement nodes (eg If, For)... # many statement nodes (eg If, For)...
makeReturn: -> makeReturn: -> new Return this
new Return this
# Does this node, or any of its children, contain a node of a certain kind? # Does this node, or any of its children, contain a node of a certain kind?
# Recursively traverses down the *children* of the nodes, yielding to a block # Recursively traverses down the *children* of the nodes, yielding to a block
@ -178,8 +176,7 @@ exports.Expressions = class Expressions extends Base
this this
# Remove and return the last expression of this expression list. # Remove and return the last expression of this expression list.
pop: -> pop: -> @expressions.pop()
@expressions.pop()
# Add an expression at the beginning of this expression list. # Add an expression at the beginning of this expression list.
unshift: (node) -> unshift: (node) ->
@ -188,8 +185,7 @@ exports.Expressions = class Expressions extends Base
# If this Expressions consists of just a single node, unwrap it by pulling # If this Expressions consists of just a single node, unwrap it by pulling
# it back out. # it back out.
unwrap: -> unwrap: -> if @expressions.length is 1 then @expressions[0] else this
if @expressions.length is 1 then @expressions[0] else this
# Is this an empty block of code? # Is this an empty block of code?
isEmpty: -> not @expressions.length isEmpty: -> not @expressions.length
@ -319,45 +315,27 @@ exports.Value = class Value extends Base
@properties.push prop @properties.push prop
this this
hasProperties: -> hasProperties: -> !!@properties.length
!!@properties.length
# Some boolean checks for the benefit of other nodes. # Some boolean checks for the benefit of other nodes.
isArray : -> not @properties.length and @base instanceof Arr
isArray: -> isObject : -> not @properties.length and @base instanceof Obj
@base instanceof Arr and not @properties.length isComplex : -> @hasProperties() or @base.isComplex()
isAssignable : -> @hasProperties() or @base.isAssignable()
isObject: -> isSimpleNumber : -> @base instanceof Literal and SIMPLENUM.test @base.value
@base instanceof Obj and not @properties.length isAtomic : ->
isComplex: ->
@base.isComplex() or @hasProperties()
isAtomic: ->
for node in @properties.concat @base for node in @properties.concat @base
return no if node.soakNode or node instanceof Call return no if node.soakNode or node instanceof Call
yes yes
isAssignable: -> isStatement : (o) -> not @properties.length and @base.isStatement o
@hasProperties() or @base.isAssignable() assigns : (name) -> not @properties.length and @base.assigns name
assigns: (name) -> makeReturn: -> if @properties.length then super() else @base.makeReturn()
not @properties.length and @base.assigns name
makeReturn: ->
if @properties.length then super() else @base.makeReturn()
# The value can be unwrapped as its inner node, if there are no attached # The value can be unwrapped as its inner node, if there are no attached
# properties. # properties.
unwrap: -> unwrap: -> if @properties.length then this else @base
if @properties.length then this else @base
# Values are considered to be statements if their base is a statement.
isStatement: (o) ->
not @properties.length and @base.isStatement o
isSimpleNumber: ->
@base instanceof Literal and SIMPLENUM.test @base.value
# A reference has base part (`this` value) and name part. # A reference has base part (`this` value) and name part.
# We cache them separately for compiling complex expressions. # We cache them separately for compiling complex expressions.
@ -434,9 +412,6 @@ exports.Call = class Call extends Base
@variable = if @isSuper then null else variable @variable = if @isSuper then null else variable
@args or= [] @args or= []
compileSplatArguments: (o) ->
Splat.compileSplattedArray @args, o
# Tag this invocation as creating a new instance. # Tag this invocation as creating a new instance.
newInstance: -> newInstance: ->
@isNew = true @isNew = true
@ -506,7 +481,7 @@ exports.Call = class Call extends Base
# If it's a constructor, then things get real tricky. We have to inject an # If it's a constructor, then things get real tricky. We have to inject an
# inner constructor in order to be able to pass the varargs. # inner constructor in order to be able to pass the varargs.
compileSplat: (o) -> compileSplat: (o) ->
splatargs = @compileSplatArguments o splatargs = Splat.compileSplattedArray @args, o
return "#{ @superReference o }.apply(this, #{splatargs})" if @isSuper return "#{ @superReference o }.apply(this, #{splatargs})" if @isSuper
unless @isNew unless @isNew
base = new Value @variable base = new Value @variable
@ -639,13 +614,10 @@ exports.Arr = class Arr extends Base
super() super()
@objects = objs or [] @objects = objs or []
compileSplatLiteral: (o) ->
Splat.compileSplattedArray @objects, o
compileNode: (o) -> compileNode: (o) ->
o.indent = @idt 1 o.indent = @idt 1
for obj in @objects when obj instanceof Splat for obj in @objects when obj instanceof Splat
return @compileSplatLiteral o return Splat.compileSplattedArray @objects, o
objects = [] objects = []
for obj, i in @objects for obj, i in @objects
code = obj.compile o, LEVEL_LIST code = obj.compile o, LEVEL_LIST
@ -756,8 +728,6 @@ exports.Assign = class Assign extends Base
# Matchers for detecting class/method names # Matchers for detecting class/method names
METHOD_DEF: /^(?:(\S+)\.prototype\.)?([$A-Za-z_][$\w]*)$/ METHOD_DEF: /^(?:(\S+)\.prototype\.)?([$A-Za-z_][$\w]*)$/
CONDITIONAL: ['||=', '&&=', '?=']
children: ['variable', 'value'] children: ['variable', 'value']
constructor: (@variable, @value, @context) -> super() constructor: (@variable, @value, @context) -> super()
@ -774,7 +744,7 @@ exports.Assign = class Assign extends Base
compileNode: (o) -> compileNode: (o) ->
if isValue = @variable instanceof Value if isValue = @variable instanceof Value
return @compilePatternMatch o if @variable.isArray() or @variable.isObject() return @compilePatternMatch o if @variable.isArray() or @variable.isObject()
return @compileConditional o if @context in @CONDITIONAL return @compileConditional o if @context in ['||=', '&&=', '?=']
name = @variable.compile o, LEVEL_LIST name = @variable.compile o, LEVEL_LIST
if @value instanceof Code and match = @METHOD_DEF.exec name if @value instanceof Code and match = @METHOD_DEF.exec name
@value.name = match[2] @value.name = match[2]
@ -863,12 +833,12 @@ exports.Code = class Code extends Base
children: ['params', 'body'] children: ['params', 'body']
constructor: (@params, @body, tag) -> constructor: (params, body, tag) ->
super() super()
@params or= [] @params = params or []
@body or= new Expressions @body = body or new Expressions
@bound = tag is 'boundfunc' @bound = tag is 'boundfunc'
@context = 'this' if @bound @context = 'this' if @bound
# Compilation creates a new scope unless explicitly asked to share with the # Compilation creates a new scope unless explicitly asked to share with the
# outer scope. Handles splat parameters in the parameter list by peeking at # outer scope. Handles splat parameters in the parameter list by peeking at
@ -945,9 +915,9 @@ exports.Param = class Param extends Base
children: ['name'] children: ['name']
constructor: (@name, @attach, @splat) -> constructor: (name, @attach, @splat) ->
super() super()
@value = new Literal @name @value = new Literal @name = name
compile: (o) -> @value.compile o, LEVEL_LIST compile: (o) -> @value.compile o, LEVEL_LIST
@ -973,8 +943,7 @@ exports.Splat = class Splat extends Base
assigns: (name) -> @name.assigns name assigns: (name) -> @name.assigns name
compile: (o) -> compile: (o) -> if @index? then @compileParam o else @name.compile o
if @index? then @compileParam o else @name.compile o
# Compiling a parameter splat means recovering the parameters that succeed # Compiling a parameter splat means recovering the parameters that succeed
# the splat in the parameter list, by slicing the arguments object. # the splat in the parameter list, by slicing the arguments object.
@ -1036,8 +1005,8 @@ exports.While = class While extends Base
constructor: (condition, opts) -> constructor: (condition, opts) ->
super() super()
@condition = if opts?.invert then condition.invert() else condition @condition = if opts?.invert then condition.invert() else condition
@guard = opts?.guard @guard = opts?.guard
addBody: (body) -> addBody: (body) ->
@body = body @body = body
@ -1095,9 +1064,9 @@ exports.Op = class Op extends Base
first = new Parens first if first instanceof Code and first.bound first = new Parens first if first instanceof Code and first.bound
super() super()
@operator = @CONVERSIONS[op] or op @operator = @CONVERSIONS[op] or op
@first = first @first = first
@second = second @second = second
@flip = !!flip @flip = !!flip
isUnary: -> not @second isUnary: -> not @second
@ -1447,7 +1416,8 @@ exports.If = class If extends Base
# The **If** only compiles into a statement if either of its bodies needs # The **If** only compiles into a statement if either of its bodies needs
# to be a statement. Otherwise a conditional operator is safe. # to be a statement. Otherwise a conditional operator is safe.
isStatement: (o) -> isStatement: (o) ->
o?.level is LEVEL_TOP or @bodyNode().isStatement(o) or @elseBodyNode()?.isStatement(o) o?.level is LEVEL_TOP or
@bodyNode().isStatement(o) or @elseBodyNode()?.isStatement(o)
compileNode: (o) -> compileNode: (o) ->
if @isStatement o then @compileStatement o else @compileExpression o if @isStatement o then @compileStatement o else @compileExpression o
@ -1504,11 +1474,10 @@ exports.If = class If extends Base
# The **Push** creates the tree for `array.push(value)`, # The **Push** creates the tree for `array.push(value)`,
# which is helpful for recording the result arrays from comprehensions. # which is helpful for recording the result arrays from comprehensions.
Push = Push =
wrap: (name, expressions) -> wrap: (name, exps) ->
return expressions if expressions.isEmpty() or return exps if exps.isEmpty() or last(exps.expressions).containsPureStatement()
last(expressions.expressions).containsPureStatement() exps.push new Call \
expressions.push new Call(new Value new Literal(name), [new Accessor new Literal 'push'] new Value(new Literal(name), [new Accessor new Literal 'push']), [exps.pop()]
[expressions.pop()])
#### Closure #### Closure