1
+ 'use strict' ;
2
+
3
+ var _classCallCheck = require ( 'babel-runtime/helpers/class-call-check' ) [ 'default' ] ;
4
+
5
+ var _getIterator = require ( 'babel-runtime/core-js/get-iterator' ) [ 'default' ] ;
6
+
7
+ Object . defineProperty ( exports , '__esModule' , {
8
+ value :true
9
+ } ) ;
10
+ exports [ 'default' ] = visit ;
11
+
12
+ var _util = require ( './util' ) ;
13
+
14
+ var _types = require ( './types' ) ;
15
+
16
+ var _tables = require ( './tables' ) ;
17
+
18
+ var LIMIT_FIXNUM = 1 << 31 >>> 0 ;
19
+ var LIMIT_UNSIGNED = Math . pow ( 2 , 32 ) ;
20
+
21
+ var funcVisitor = {
22
+ SequenceExpression :{
23
+ exit :function SequenceExpression ( node , parent , scope , state ) {
24
+ var expressions = this . get ( 'expressions' ) ;
25
+ this . setData ( 'asmType' , ( 0 , _util . validateType ) ( expressions [ expressions . length - 1 ] , state . type ) ) ;
26
+ }
27
+ } ,
28
+
29
+ UnaryExpression :{
30
+ exit :function UnaryExpression ( node , parent , scope , state ) {
31
+ var opTypes = _tables . UNOPS . get ( node . operator ) . alts ;
32
+ var argType = this . get ( 'argument' ) . getData ( 'asmType' ) ;
33
+ for ( var _iterator = opTypes , _isArray = Array . isArray ( _iterator ) , _i = 0 , _iterator = _isArray ?_iterator :_getIterator ( _iterator ) ; ; ) {
34
+ var _ref ;
35
+
36
+ if ( _isArray ) {
37
+ if ( _i >= _iterator . length ) break ;
38
+ _ref = _iterator [ _i ++ ] ;
39
+ } else {
40
+ _i = _iterator . next ( ) ;
41
+ if ( _i . done ) break ;
42
+ _ref = _i . value ;
43
+ }
44
+
45
+ var type = _ref ;
46
+
47
+ if ( argType . subtype ( type . params [ 0 ] ) ) {
48
+ this . setData ( 'asmType' , type . result ) ;
49
+ return ;
50
+ }
51
+ }
52
+ _util . typeError . call ( this , 'Unsupported operation: ' + node . operator + ' ' + argType ) ;
53
+ }
54
+ } ,
55
+
56
+ BinaryExpression :{
57
+ exit :function BinaryExpression ( node , parent , scope , state ) {
58
+ var opTypes = _tables . BINOPS . get ( node . operator ) . alts ;
59
+ var leftType = this . get ( 'left' ) . getData ( 'asmType' ) ;
60
+ var rightType = this . get ( 'right' ) . getData ( 'asmType' ) ;
61
+ for ( var _iterator2 = opTypes , _isArray2 = Array . isArray ( _iterator2 ) , _i2 = 0 , _iterator2 = _isArray2 ?_iterator2 :_getIterator ( _iterator2 ) ; ; ) {
62
+ var _ref2 ;
63
+
64
+ if ( _isArray2 ) {
65
+ if ( _i2 >= _iterator2 . length ) break ;
66
+ _ref2 = _iterator2 [ _i2 ++ ] ;
67
+ } else {
68
+ _i2 = _iterator2 . next ( ) ;
69
+ if ( _i2 . done ) break ;
70
+ _ref2 = _i2 . value ;
71
+ }
72
+
73
+ var type = _ref2 ;
74
+
75
+ if ( leftType . subtype ( type . params [ 0 ] ) && rightType . subtype ( type . params [ 1 ] ) ) {
76
+ this . setData ( 'asmType' , type . result ) ;
77
+ return ;
78
+ }
79
+ }
80
+ _util . typeError . call ( this , 'Unsupported operation: ' + leftType + ' ' + node . operator + ' ' + rightType ) ;
81
+ }
82
+ } ,
83
+
84
+ Literal :function Literal ( node ) {
85
+ var value = node . value ;
86
+
87
+ _util . assert . call ( this , typeof value === 'number' , 'only numeric literals are supported' ) ;
88
+ if ( node . raw . indexOf ( '.' ) < 0 ) {
89
+ if ( value < LIMIT_FIXNUM ) {
90
+ this . setData ( 'asmType' , _types . Fixnum ) ;
91
+ return ;
92
+ }
93
+ if ( value < LIMIT_UNSIGNED ) {
94
+ this . setData ( 'asmType' , _types . Unsigned ) ;
95
+ return ;
96
+ }
97
+ node . raw += '.0' ;
98
+ }
99
+ this . setData ( 'asmType' , _types . Double ) ;
100
+ } ,
101
+
102
+ ReferencedIdentifier :function ReferencedIdentifier ( node , parent , scope , state ) {
103
+ var binding = scope . getBinding ( node . name ) ;
104
+ if ( binding ) {
105
+ this . setData ( 'asmType' , binding . path . getData ( 'asmType' ) ) ;
106
+ } else {
107
+ state . program [ 'import' ] ( this ) ;
108
+ }
109
+ } ,
110
+
111
+ MemberExpression :function MemberExpression ( node , parent , scope , state ) {
112
+ if ( state . program [ 'import' ] ( this ) ) {
113
+ this . skip ( ) ;
114
+ }
115
+ } ,
116
+
117
+ ReturnStatement :{
118
+ exit :function ReturnStatement ( node , parent , scope , state ) {
119
+ var _context ;
120
+
121
+ if ( state . returnType === 'void' ) {
122
+ var arg = node . argument ;
123
+ if ( arg === null ) {
124
+ return ;
125
+ }
126
+ return [ { type :'ExpressionStatement' , expression :arg } , node ] ;
127
+ }
128
+ node . argument = ( _context = this . get ( 'argument' ) , _util . wrap ) . call ( _context , state . returnType , true ) ;
129
+ }
130
+ } ,
131
+
132
+ VariableDeclarator :{
133
+ exit :function VariableDeclarator ( node , parent , scope , state ) {
134
+ var init = this . get ( 'init' ) ;
135
+ var asmType = init . getData ( 'asmType' ) ;
136
+ this . setData ( 'asmType' , asmType ) ;
137
+ state . vars . push ( node ) ;
138
+ if ( node . init . type === 'Literal' && node . init . value === 0 ) {
139
+ return this . dangerouslyRemove ( ) ;
140
+ }
141
+ node . init = { type :'Literal' , value :0 , raw :asmType . subtype ( _types . Intish ) ?'0' :'0.0' } ;
142
+ return {
143
+ type :'AssignmentExpression' ,
144
+ left :node . id ,
145
+ operator :'=' ,
146
+ right :init . node
147
+ } ;
148
+ }
149
+ } ,
150
+
151
+ VariableDeclaration :{
152
+ exit :function VariableDeclaration ( node , parent , scope , state ) {
153
+ var expr = {
154
+ type :'SequenceExpression' ,
155
+ expressions :node . declarations
156
+ } ;
157
+ if ( parent . type === 'ForStatement' ) {
158
+ return expr ;
159
+ }
160
+ return {
161
+ type :'ExpressionStatement' ,
162
+ expression :expr
163
+ } ;
164
+ }
165
+ } ,
166
+
167
+ AssignmentExpression :{
168
+ exit :function AssignmentExpression ( node , parent , scope , state ) {
169
+ var asmType = scope . getBinding ( node . left . name ) . path . getData ( 'asmType' ) ;
170
+ var right = this . get ( 'right' ) ;
171
+ right . replaceWith ( _util . wrap . call ( right , asmType ) ) ;
172
+ }
173
+ } ,
174
+
175
+ CallExpression :{
176
+ exit :function CallExpression ( node , parent , scope , state ) {
177
+ var callee = this . get ( 'callee' ) ;
178
+ _util . assert . call ( callee , callee . node . type === 'Identifier' , 'only calls to direct identifiers are possible' ) ;
179
+ var resultType = callee . getData ( 'asmType' ) . result ;
180
+ this . setData ( 'asmType' , resultType ) ;
181
+ this . replaceWith ( _util . wrap . call ( this , resultType , true ) ) ;
182
+ }
183
+ }
184
+ } ;
185
+
186
+ var FuncState = function FuncState ( programState , returnType ) {
187
+ _classCallCheck ( this , FuncState ) ;
188
+
189
+ this . program = programState ;
190
+ this . returnType = returnType ;
191
+ this . vars = [ ] ;
192
+ } ;
193
+
194
+ function visit ( programState ) {
195
+ var _context3 ;
196
+
197
+ var paramTypes = [ ] ;
198
+ var wrappedParams = this . get ( 'params' ) . map ( function ( param ) {
199
+ var _context2 ;
200
+
201
+ var asmType = ( _context2 = param . get ( 'typeAnnotation' ) , _util . flowToAsm ) . call ( _context2 ) ;
202
+ param . setData ( 'asmType' , asmType ) ;
203
+ paramTypes . push ( asmType ) ;
204
+ var node = param . node ;
205
+
206
+ return {
207
+ type :'ExpressionStatement' ,
208
+ expression :{
209
+ type :'AssignmentExpression' ,
210
+ left :node ,
211
+ operator :'=' ,
212
+ right :_util . wrap . call ( param , asmType , true )
213
+ }
214
+ } ;
215
+ } ) ;
216
+ var returnType = ( _context3 = this . get ( 'returnType' ) , _util . flowToAsm ) . call ( _context3 ) ;
217
+ this . setData ( 'asmType' , new _types . Arrow ( paramTypes , returnType ) ) ;
218
+ var funcState = new FuncState ( programState , returnType ) ;
219
+ this . get ( 'body' ) . traverse ( funcVisitor , funcState ) ;
220
+ this . get ( 'body.body.0' ) . insertBefore ( {
221
+ type :'VariableDeclaration' ,
222
+ kind :'var' ,
223
+ declarations :funcState . vars
224
+ } ) ;
225
+ this . get ( 'body.body.0' ) . insertBefore ( wrappedParams ) ;
226
+ programState . funcs . push ( this . node ) ;
227
+ }
228
+
229
+ module . exports = exports [ 'default' ] ;