@@ -8,7 +8,7 @@ class CallNode < Base
8
8
children :recvr , :meth , :arglist , :iter
9
9
10
10
def compile
11
- if handled = compiler . handle_call ( @sexp )
11
+ if handled = self . handle_special
12
12
push handled
13
13
return
14
14
end
@@ -28,17 +28,6 @@ def compile
28
28
return
29
29
end
30
30
31
- case meth
32
- when :block_given?
33
- return push @compiler . js_block_given ( @sexp , @level )
34
- when :__method__ , :__callee__
35
- if scope . def?
36
- return push ( scope . mid . to_s . inspect )
37
- else
38
- return push ( "nil" )
39
- end
40
- end
41
-
42
31
splat = arglist [ 1 ..-1 ] . any? { |a | a . first == :splat }
43
32
44
33
if Sexp === arglist . last and arglist . last . type == :block_pass
@@ -90,56 +79,98 @@ def recv_sexp
90
79
def using_irb?
91
80
@compiler . irb? and scope . top? and arglist == s ( :arglist ) and recvr . nil? and iter . nil?
92
81
end
93
- end
94
82
95
- # FIXME: needs rewrite
96
- class ArglistNode < Base
97
- handle :arglist
83
+ # Handle "special" method calls, e.g. require(). Subclasses can override
84
+ # this method. If this method returns nil, then the method will continue
85
+ # to be generated by CallNode.
86
+ def handle_special
87
+ case meth
88
+ when :require then handle_require
89
+ when :autoload then handle_autoload
90
+ when :block_given? then handle_block_given
91
+ when :__method__ , :__callee__ then handle_callee
92
+ end
93
+ end
98
94
99
- def compile
100
- code , work = [ ] , [ ]
101
-
102
- children . each do |current |
103
- splat = current . first == :splat
104
- arg = expr ( current )
105
-
106
- if splat
107
- if work . empty?
108
- if code . empty?
109
- code << fragment ( "[].concat(" )
110
- code << arg
111
- code << fragment ( ")" )
112
- else
113
- code += ".concat(#{ arg } )"
114
- end
115
- else
116
- if code . empty?
117
- code << [ fragment ( "[" ) , work , fragment ( "]" ) ]
118
- else
119
- code << [ fragment ( ".concat([" ) , work , fragment ( "])" ) ]
120
- end
95
+ def handle_require
96
+ str = DependencyResolver . new ( compiler , arglist [ 1 ] ) . resolve
97
+ compiler . requires << str unless str . nil?
98
+ fragment ''
99
+ end
121
100
122
- code << [ fragment ( ".concat(" ) , arg , fragment ( ")" ) ]
123
- end
101
+ def handle_autoload
102
+ if scope . class_scope?
103
+ str = DependencyResolver . new ( compiler , arglist [ 2 ] ) . resolve
104
+ compiler . requires << str unless str . nil?
105
+ fragment ''
106
+ end
107
+ end
124
108
125
- work = [ ]
126
- else
127
- work << fragment ( ", " ) unless work . empty?
128
- work << arg
129
- end
109
+ def handle_block_given
110
+ compiler . handle_block_given_call @sexp
111
+ end
112
+
113
+ def handle_callee
114
+ if scope . def?
115
+ fragment scope . mid . to_s . inspect
116
+ else
117
+ fragment 'nil'
118
+ end
119
+ end
120
+
121
+ class DependencyResolver
122
+ def initialize ( compiler , sexp )
123
+ @compiler = compiler
124
+ @sexp = sexp
130
125
end
131
126
132
- unless work . empty?
133
- join = work
127
+ def resolve
128
+ handle_part @sexp
129
+ end
130
+
131
+ def handle_part ( sexp )
132
+ type = sexp . type
133
+
134
+ if type == :str
135
+ return sexp [ 1 ]
136
+ elsif type == :call
137
+ _ , recv , meth , args = sexp
138
+
139
+ parts = args [ 1 ..-1 ] . map { |s | handle_part s }
134
140
135
- if code . empty?
136
- code = join
137
- else
138
- code << fragment ( ".concat(" ) << join << fragment ( ")" )
141
+ if recv == [ :const , :File ]
142
+ if meth == :expand_path
143
+ return expand_path ( *parts )
144
+ elsif meth == :join
145
+ return expand_path parts . join ( '/' )
146
+ elsif meth == :dirname
147
+ return expand_path parts [ 0 ] . split ( '/' ) [ 0 ...-1 ] . join ( '/' )
148
+ end
149
+ end
150
+ end
151
+
152
+ msg = "Cannot handle dynamic require"
153
+ case @compiler . dynamic_require_severity
154
+ when :error
155
+ @compiler . error msg
156
+ when :warning
157
+ @compiler . warning msg
139
158
end
140
159
end
141
160
142
- push ( *code )
161
+ def expand_path ( path , base = '' )
162
+ "#{ base } /#{ path } " . split ( "/" ) . inject ( [ ] ) do |p , part |
163
+ if part == ''
164
+ # we had '//', so ignore
165
+ elsif part == '..'
166
+ p . pop
167
+ else
168
+ p << part
169
+ end
170
+
171
+ p
172
+ end . join "/"
173
+ end
143
174
end
144
175
end
145
176
end
0 commit comments