@@ -79,7 +79,17 @@ exports.Base = class Base
79
79
if jumpNode = @ jumps ()
80
80
jumpNode .error ' cannot use a pure statement in an expression'
81
81
o .sharedScope = yes
82
- Closure .wrap (this ).compileNode o
82
+ func = new Code [], Block .wrap [this ]
83
+ args = []
84
+ if (argumentsNode = @ contains isLiteralArguments) or @ contains isLiteralThis
85
+ args = [new Literal ' this' ]
86
+ if argumentsNode
87
+ meth = ' apply'
88
+ args .push new Literal ' arguments'
89
+ else
90
+ meth = ' call'
91
+ func = new Value func, [new Access new Literal meth]
92
+ (new Call func, args).compileNode o
83
93
84
94
# If the code generation wishes to use the result of a complex expression
85
95
# in multiple places, ensure that the expression is only ever evaluated once,
@@ -848,7 +858,7 @@ exports.Range = class Range extends Base
848
858
cond = " #{ @fromVar } <= #{ @toVar } "
849
859
body = " var #{ vars} ; #{ cond} ? #{ i} <#{ @equals } #{ @toVar } : #{ i} >#{ @equals } #{ @toVar } ; #{ cond} ? #{ i} ++ : #{ i} --"
850
860
post = " { #{ result} .push(#{ i} ); }\n #{ idt} return #{ result} ;\n #{ o .indent } "
851
- hasArgs = (node ) -> node ? .contains (n) -> n instanceof Literal and n . value is ' arguments ' and not n . asKey
861
+ hasArgs = (node ) -> node ? .contains isLiteralArguments
852
862
args = ' , arguments' if hasArgs (@from ) or hasArgs (@to )
853
863
[@ makeCode " (function() {#{ pre} \n #{ idt} for (#{ body} )#{ post} }).apply(this#{ args ? ' ' } )" ]
854
864
@@ -1078,9 +1088,16 @@ exports.Class = class Class extends Base
1078
1088
# equivalent syntax tree and compile that, in pieces. You can see the
1079
1089
# constructor, property assignments, and inheritance getting built out below.
1080
1090
compileNode : (o ) ->
1091
+ if jumpNode = @body .jumps ()
1092
+ jumpNode .error ' Class bodies cannot contain pure statements'
1093
+ if argumentsNode = @body .contains isLiteralArguments
1094
+ argumentsNode .error " Class bodies shouldn't reference arguments"
1095
+
1081
1096
name = @ determineName () or ' _Class'
1082
- name = " _#{ name} " if name .reserved
1097
+ name = " _#{ name} " if name .reserved
1083
1098
lname = new Literal name
1099
+ func = new Code [], Block .wrap [@body ]
1100
+ args = []
1084
1101
1085
1102
@ hoistDirectivePrologue ()
1086
1103
@ setContext name
@@ -1091,18 +1108,15 @@ exports.Class = class Class extends Base
1091
1108
@body .expressions .unshift @ctor unless @ctor instanceof Code
1092
1109
@body .expressions .push lname
1093
1110
1094
- call = Closure .wrap @body
1095
-
1096
- if @parent and call .args
1097
- @superClass = new Literal o .scope .freeVariable ' super' , no
1098
- @body .expressions .unshift new Extends lname, @superClass
1099
- call .args .push @parent
1100
- params = call .variable .params or call .variable .base .params
1101
- params .push new Param @superClass
1111
+ if @parent
1112
+ superClass = new Literal o .scope .freeVariable ' super' , no
1113
+ @body .expressions .unshift new Extends lname, superClass
1114
+ func .params .push new Param superClass
1115
+ args .push @parent
1102
1116
1103
1117
@body .expressions .unshift @directives ...
1104
1118
1105
- klass = new Parens call, yes
1119
+ klass = new Parens new Call func, args
1106
1120
klass = new Assign @variable , klass if @variable
1107
1121
klass .compileToFragments o
1108
1122
@@ -2080,50 +2094,6 @@ exports.If = class If extends Base
2080
2094
unfoldSoak : ->
2081
2095
@soak and this
2082
2096
2083
- # Faux-Nodes
2084
- # ----------
2085
- # Faux-nodes are never created by the grammar, but are used during code
2086
- # generation to generate other combinations of nodes.
2087
-
2088
- # ### Closure
2089
-
2090
- # A faux-node used to wrap an expressions body in a closure.
2091
- Closure =
2092
-
2093
- # Wrap the expressions body, unless it contains a pure statement,
2094
- # in which case, no dice. If the body mentions `this` or `arguments`,
2095
- # then make sure that the closure wrapper preserves the original values.
2096
- wrap : (expressions , statement , noReturn ) ->
2097
- return expressions if expressions .jumps ()
2098
- func = new Code [], Block .wrap [expressions]
2099
- args = []
2100
- argumentsNode = expressions .contains @isLiteralArguments
2101
- if argumentsNode and expressions .classBody
2102
- argumentsNode .error " Class bodies shouldn't reference arguments"
2103
- if argumentsNode or expressions .contains @isLiteralThis
2104
- meth = new Literal if argumentsNode then ' apply' else ' call'
2105
- args = [new Literal ' this' ]
2106
- args .push new Literal ' arguments' if argumentsNode
2107
- func = new Value func, [new Access meth]
2108
- func .noReturn = noReturn
2109
- call = new Call func, args
2110
- if statement then Block .wrap [call] else call
2111
-
2112
- isLiteralArguments : (node ) ->
2113
- node instanceof Literal and node .value is ' arguments' and not node .asKey
2114
-
2115
- isLiteralThis : (node ) ->
2116
- (node instanceof Literal and node .value is ' this' and not node .asKey ) or
2117
- (node instanceof Code and node .bound ) or
2118
- (node instanceof Call and node .isSuper )
2119
-
2120
- # Unfold a node's child if soak, then tuck the node under created `If`
2121
- unfoldSoak = (o , parent , name ) ->
2122
- return unless ifn = parent[name].unfoldSoak o
2123
- parent[name] = ifn .body
2124
- ifn .body = new Value parent
2125
- ifn
2126
-
2127
2097
# Constants
2128
2098
# ---------
2129
2099
@@ -2190,8 +2160,8 @@ METHOD_DEF = ///
2190
2160
IS_STRING = / ^ ['"] /
2191
2161
IS_REGEX = / ^ \/ /
2192
2162
2193
- # Utility Functions
2194
- # -----------------
2163
+ # Helper Functions
2164
+ # ----------------
2195
2165
2196
2166
# Helper for ensuring that utility functions are assigned at the top level.
2197
2167
utility = (name ) ->
@@ -2212,3 +2182,18 @@ parseNum = (x) ->
2212
2182
parseInt x, 16
2213
2183
else
2214
2184
parseFloat x
2185
+
2186
+ isLiteralArguments = (node ) ->
2187
+ node instanceof Literal and node .value is ' arguments' and not node .asKey
2188
+
2189
+ isLiteralThis = (node ) ->
2190
+ (node instanceof Literal and node .value is ' this' and not node .asKey ) or
2191
+ (node instanceof Code and node .bound ) or
2192
+ (node instanceof Call and node .isSuper )
2193
+
2194
+ # Unfold a node's child if soak, then tuck the node under created `If`
2195
+ unfoldSoak = (o , parent , name ) ->
2196
+ return unless ifn = parent[name].unfoldSoak o
2197
+ parent[name] = ifn .body
2198
+ ifn .body = new Value parent
2199
+ ifn
0 commit comments