[フレーム]

Class: Opal::Nodes::ScopeNode

Inherits:
Base
  • Object
  • Base
  • Opal::Nodes::ScopeNode
show all
Defined in:
opal/lib/opal/nodes/scope.rb

Direct Known Subclasses

BeginNode , ModuleNode , NodeWithArgs , SingletonClassNode , TopNode

Instance Attribute Summary collapse

Attributes inherited from Base

#compiler , #sexp , #type

Attributes included from Closure::NodeSupport

#closure

Instance Method Summary collapse

Methods inherited from Base

#add_gvar , #add_ivar , #add_local , #add_temp , children , #children , #class_variable_owner , #class_variable_owner_nesting_level , #comments , #compile , #compile_to_fragments , #error , #expr , #expr? , #expr_or_empty , #expr_or_nil , #fragment , handle , handlers , #helper , #process , #push , #recv , #recv? , #s , #scope , #source_location , #stmt , #stmt? , #top_scope , truthy_optimize? , #unshift , #while_loop , #with_temp , #wrap

Methods included from Closure::NodeSupport

#closure_is? , #compile_catcher , #generate_thrower , #generate_thrower_without_catcher , #in_closure , #pop_closure , #push_closure , #select_closure , #thrower

Methods included from Helpers

#current_indent , #empty_line , #indent , #js_truthy , #js_truthy_optimize , #line , #mid_to_jsid , #property , #valid_name?

Constructor Details

#initializeScopeNode

Returns a new instance of ScopeNode.

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'opal/lib/opal/nodes/scope.rb', line 34
def initialize(*)
 super
 @locals = []
 @temps = []
 @args = []
 @ivars = []
 @gvars = []
 @parent = nil
 @queue = []
 @unique = 'a'
 @while_stack = []
 @identity = nil
 @defs = nil
 @methods = []
 @uses_block = false
 @in_ensure = false
 # used by classes to store all ivars used in direct def methods
 @proto_ivars = []
end

Instance Attribute Details

#await_encounteredObject

Returns the value of attribute await_encountered.

419
420
421
# File 'opal/lib/opal/nodes/scope.rb', line 419
def await_encountered
 @await_encountered
end

#block_nameObject

The given block name for a def scope

15
16
17
# File 'opal/lib/opal/nodes/scope.rb', line 15
def block_name
 @block_name
end

#catch_returnObject

Returns the value of attribute catch_return.

30
31
32
# File 'opal/lib/opal/nodes/scope.rb', line 30
def catch_return
 @catch_return
end

#defsObject

true if singleton def, false otherwise

25
26
27
# File 'opal/lib/opal/nodes/scope.rb', line 25
def defs
 @defs
end

#gvarsObject (readonly)

Returns the value of attribute gvars.

20
21
22
# File 'opal/lib/opal/nodes/scope.rb', line 20
def gvars
 @gvars
end

#has_breakObject

Returns the value of attribute has_break.

30
31
32
# File 'opal/lib/opal/nodes/scope.rb', line 30
def has_break
 @has_break
end

#has_retryObject

Returns the value of attribute has_retry.

30
31
32
# File 'opal/lib/opal/nodes/scope.rb', line 30
def has_retry
 @has_retry
end

#identityObject (readonly)

Returns the value of attribute identity.

277
278
279
# File 'opal/lib/opal/nodes/scope.rb', line 277
def identity
 @identity
end

#ivarsObject (readonly)

Returns the value of attribute ivars.

19
20
21
# File 'opal/lib/opal/nodes/scope.rb', line 19
def ivars
 @ivars
end

#localsObject (readonly)

Returns the value of attribute locals.

18
19
20
# File 'opal/lib/opal/nodes/scope.rb', line 18
def locals
 @locals
end

#methodsObject (readonly)

used by modules to know what methods to donate to includees

28
29
30
# File 'opal/lib/opal/nodes/scope.rb', line 28
def methods
 @methods
end

#midObject

Returns the value of attribute mid.

22
23
24
# File 'opal/lib/opal/nodes/scope.rb', line 22
def mid
 @mid
end

#nameObject

The class or module name if this scope is a class scope

12
13
14
# File 'opal/lib/opal/nodes/scope.rb', line 12
def name
 @name
end

#parentObject

Every scope can have a parent scope

9
10
11
# File 'opal/lib/opal/nodes/scope.rb', line 9
def parent
 @parent
end

#rescue_else_sexpObject

Returns the value of attribute rescue_else_sexp.

32
33
34
# File 'opal/lib/opal/nodes/scope.rb', line 32
def rescue_else_sexp
 @rescue_else_sexp
end

#scope_nameObject (readonly)

Returns the value of attribute scope_name.

17
18
19
# File 'opal/lib/opal/nodes/scope.rb', line 17
def scope_name
 @scope_name
end

Instance Method Details

#accepts_using?Boolean

Returns:

  • (Boolean)
365
366
367
368
369
# File 'opal/lib/opal/nodes/scope.rb', line 365
def accepts_using?
 # IterNode of a special kind of Module.new {} is accepted...
 # though we don't check for it that thoroughly.
 [TopNode , ModuleNode , ClassNode , IterNode ].include? self.class
end

#add_arg(arg) ⇒ Object

172
173
174
175
# File 'opal/lib/opal/nodes/scope.rb', line 172
def add_arg(arg)
 @args << arg unless @args.include? arg
 arg
end

#add_proto_ivar(ivar) ⇒ Object

168
169
170
# File 'opal/lib/opal/nodes/scope.rb', line 168
def add_proto_ivar(ivar)
 @proto_ivars << ivar unless @proto_ivars.include? ivar
end

#add_scope_gvar(gvar) ⇒ Object

164
165
166
# File 'opal/lib/opal/nodes/scope.rb', line 164
def add_scope_gvar(gvar)
 @gvars << gvar unless @gvars.include? gvar
end

#add_scope_ivar(ivar) ⇒ Object

156
157
158
159
160
161
162
# File 'opal/lib/opal/nodes/scope.rb', line 156
def add_scope_ivar(ivar)
 if def_in_class?
 @parent.add_proto_ivar ivar
 else
 @ivars << ivar unless @ivars.include? ivar
 end
end

#add_scope_local(local) ⇒ Object

177
178
179
180
181
# File 'opal/lib/opal/nodes/scope.rb', line 177
def add_scope_local(local)
 return if has_local? local
 @locals << local
end

#add_scope_temp(tmp) ⇒ Object

194
195
196
197
198
# File 'opal/lib/opal/nodes/scope.rb', line 194
def add_scope_temp(tmp)
 return if has_temp?(tmp)
 @temps.push(tmp)
end

#class?Boolean

Returns true if this is strictly a class scope

Returns:

  • (Boolean)
73
74
75
# File 'opal/lib/opal/nodes/scope.rb', line 73
def class?
 @type == :class
end

#class_scope?Boolean

Returns true if this scope is a class/module body scope

Returns:

  • (Boolean)
68
69
70
# File 'opal/lib/opal/nodes/scope.rb', line 68
def class_scope?
 @type == :class || @type == :module
end

#collect_refinements_temps(temps = []) ⇒ Object

371
372
373
374
375
# File 'opal/lib/opal/nodes/scope.rb', line 371
def collect_refinements_temps(temps = [])
 temps << @refinements_temp if @refinements_temp
 return parent.collect_refinements_temps(temps) if parent
 temps
end

#current_rescueObject

328
329
330
# File 'opal/lib/opal/nodes/scope.rb', line 328
def current_rescue
 @rescues.last
end

#def?Boolean

Returns:

  • (Boolean)
96
97
98
# File 'opal/lib/opal/nodes/scope.rb', line 96
def def?
 @type == :def || @type == :defs
end

#def_in_class?Boolean

Is this a normal def method directly inside a class? This is used for optimizing ivars as we can set them to nil in the class body

Returns:

  • (Boolean)
121
122
123
# File 'opal/lib/opal/nodes/scope.rb', line 121
def def_in_class?
 !@defs && @type == :def && @parent && @parent.class?
end

#defines_lambdaObject

108
109
110
111
112
# File 'opal/lib/opal/nodes/scope.rb', line 108
def defines_lambda
 @lambda_definition = true
 yield
 @lambda_definition = false
end

#find_parent_defObject

279
280
281
282
283
284
285
286
287
288
# File 'opal/lib/opal/nodes/scope.rb', line 279
def find_parent_def
 scope = self
 while scope = scope.parent
 if scope.def? || scope.lambda?
 return scope
 end
 end
 nil
end

#gen_retry_idObject

360
361
362
363
# File 'opal/lib/opal/nodes/scope.rb', line 360
def gen_retry_id
 @next_retry_id ||= 'retry_0'
 @next_retry_id = @next_retry_id.succ
end

#has_local?(local) ⇒ Boolean

Returns:

  • (Boolean)
183
184
185
186
187
# File 'opal/lib/opal/nodes/scope.rb', line 183
def has_local?(local)
 return true if @locals.include?(local) || @args.include?(local) || @temps.include?(local)
 return @parent.has_local?(local) if @parent && @type == :iter
 false
end

#has_rescue_else?Boolean

Returns:

  • (Boolean)
314
315
316
# File 'opal/lib/opal/nodes/scope.rb', line 314
def has_rescue_else?
 !rescue_else_sexp.nil?
end

#has_temp?(tmp) ⇒ Boolean

Returns:

  • (Boolean)
206
207
208
# File 'opal/lib/opal/nodes/scope.rb', line 206
def has_temp?(tmp)
 @temps.include? tmp
end

#identify!(name = nil) ⇒ Object

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'opal/lib/opal/nodes/scope.rb', line 255
def identify!(name = nil)
 return @identity if @identity
 if valid_name? mid
 # There are some special utf8 chars that can be used as valid JS
 # identifiers, some examples:
 #
 # utf8_pond = 'ⵌ'
 # utf8_question = 'ʔ̣'
 # utf8_exclamation 'ǃ'
 #
 # For now we're just using $,ドル to maintain compatibility with older IEs.
 @identity = "$$#{mid}"
 else
 # Parent scope is the defining module/class
 name ||= [(parent && (parent.name || parent.scope_name)), mid].compact.join('_')
 @identity = @compiler.unique_temp(name)
 end
 @identity
end

#in_ensureObject

346
347
348
349
350
351
352
353
354
# File 'opal/lib/opal/nodes/scope.rb', line 346
def in_ensure
 return unless block_given?
 @in_ensure = true
 result = yield
 @in_ensure = false
 result
end

#in_ensure?Boolean

Returns:

  • (Boolean)
356
357
358
# File 'opal/lib/opal/nodes/scope.rb', line 356
def in_ensure?
 @in_ensure
end

#in_resbodyObject

332
333
334
335
336
337
338
339
340
# File 'opal/lib/opal/nodes/scope.rb', line 332
def in_resbody
 return unless block_given?
 @in_resbody = true
 result = yield
 @in_resbody = false
 result
end

#in_resbody?Boolean

Returns:

  • (Boolean)
342
343
344
# File 'opal/lib/opal/nodes/scope.rb', line 342
def in_resbody?
 @in_resbody
end

#in_rescue(node) ⇒ Object

318
319
320
321
322
323
324
325
326
# File 'opal/lib/opal/nodes/scope.rb', line 318
def in_rescue(node)
 @rescues ||= []
 @rescues.push(node)
 result = yield
 @rescues.pop
 result
end

#in_scopeObject

58
59
60
61
62
63
64
65
# File 'opal/lib/opal/nodes/scope.rb', line 58
def in_scope
 indent do
 @parent = compiler.scope
 compiler.scope = self
 yield self
 compiler.scope = @parent
 end
end

#in_while?Boolean

Returns:

  • (Boolean)
242
243
244
# File 'opal/lib/opal/nodes/scope.rb', line 242
def in_while?
 !@while_stack.empty?
end

#is_lambda!Object

rubocop:disable Naming/PredicateName

104
105
106
# File 'opal/lib/opal/nodes/scope.rb', line 104
def is_lambda! # rubocop:disable Naming/PredicateName
 @is_lambda = true
end

#iter?Boolean

True if a block/iter scope

Returns:

  • (Boolean)
92
93
94
# File 'opal/lib/opal/nodes/scope.rb', line 92
def iter?
 @type == :iter
end

#lambda?Boolean

Returns:

  • (Boolean)
100
101
102
# File 'opal/lib/opal/nodes/scope.rb', line 100
def lambda?
 iter? && @is_lambda
end

#lambda_definition?Boolean

Returns:

  • (Boolean)
114
115
116
# File 'opal/lib/opal/nodes/scope.rb', line 114
def lambda_definition?
 @lambda_definition
end

#module?Boolean

True if this is a module scope

Returns:

  • (Boolean)
78
79
80
# File 'opal/lib/opal/nodes/scope.rb', line 78
def module?
 @type == :module
end

#nestingObject

Returns '$nesting', but also ensures we compile the nesting chain

396
397
398
399
# File 'opal/lib/opal/nodes/scope.rb', line 396
def nesting
 @define_nesting = true
 '$nesting'
end

#new_refinements_tempObject

377
378
379
380
381
# File 'opal/lib/opal/nodes/scope.rb', line 377
def new_refinements_temp
 var = compiler.unique_temp("$refn")
 add_scope_local(var)
 var
end

#new_tempObject

210
211
212
213
214
215
216
# File 'opal/lib/opal/nodes/scope.rb', line 210
def new_temp
 return @queue.pop unless @queue.empty?
 tmp = next_temp
 @temps << tmp
 tmp
end

#next_tempObject

218
219
220
221
222
223
224
225
226
# File 'opal/lib/opal/nodes/scope.rb', line 218
def next_temp
 tmp = nil
 loop do
 tmp = "$#{@unique}"
 @unique = @unique.succ
 break unless has_local?(tmp)
 end
 tmp
end

#pop_whileObject

238
239
240
# File 'opal/lib/opal/nodes/scope.rb', line 238
def pop_while
 @while_stack.pop
end

#prepare_block(block_name = nil) ⇒ Object

407
408
409
410
411
412
413
414
415
416
417
# File 'opal/lib/opal/nodes/scope.rb', line 407
def prepare_block(block_name = nil)
 scope_name = scope.identity
 self.block_name = block_name if block_name
 add_temp "#{self.block_name} = #{scope_name}.$$p || nil"
 unless @block_prepared
 line "#{scope_name}.$$p = null;"
 @block_prepared = true
 end
end

#prepend_scope_temp(tmp) ⇒ Object

200
201
202
203
204
# File 'opal/lib/opal/nodes/scope.rb', line 200
def prepend_scope_temp(tmp)
 return if has_temp?(tmp)
 @temps.unshift(tmp)
end

#push_whileObject

232
233
234
235
236
# File 'opal/lib/opal/nodes/scope.rb', line 232
def push_while
 info = {}
 @while_stack.push info
 info
end

#queue_temp(name) ⇒ Object

228
229
230
# File 'opal/lib/opal/nodes/scope.rb', line 228
def queue_temp(name)
 @queue << name
end

#refinements_tempObject

383
384
385
386
387
# File 'opal/lib/opal/nodes/scope.rb', line 383
def refinements_temp
 prev, curr = @refinements_temp, new_refinements_temp
 @refinements_temp = curr
 [prev, curr]
end

#relative_accessObject

Returns '$$', but also ensures we compile it

402
403
404
405
# File 'opal/lib/opal/nodes/scope.rb', line 402
def relative_access
 @define_relative_access = @define_nesting = true
 '$$'
end

#sclass?Boolean

Returns:

  • (Boolean)
82
83
84
# File 'opal/lib/opal/nodes/scope.rb', line 82
def sclass?
 @type == :sclass
end

#scope_localsObject

189
190
191
192
# File 'opal/lib/opal/nodes/scope.rb', line 189
def scope_locals
 locals = @locals | @args | (@parent && @type == :iter ? @parent.scope_locals : [])
 locals.reject { |i| i.to_s.start_with?('$') }
end

#selfObject

Returns 'self', but also ensures that the self variable is set

390
391
392
393
# File 'opal/lib/opal/nodes/scope.rb', line 390
def self
 @define_self = true
 'self'
end

#super_chainObject

290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'opal/lib/opal/nodes/scope.rb', line 290
def super_chain
 chain, scope, defn, mid = [], self, 'null', 'null'
 while scope
 if scope.type == :iter
 chain << scope.identify!
 scope = scope.parent if scope.parent
 elsif %i[defdefs].include?(scope.type)
 defn = scope.identify!
 mid = "'#{scope.mid}'"
 break
 else
 break
 end
 end
 [chain, defn, mid]
end

#to_varsObject

Vars to use inside each scope

127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'opal/lib/opal/nodes/scope.rb', line 127
def to_vars
 vars = @temps.dup
 vars.push(*@locals.map { |l| "#{l} = nil" })
 iv = ivars.map do |ivar|
 "if (self#{ivar} == null) self#{ivar} = nil;\n"
 end
 gv = gvars.map do |gvar|
 "if ($gvars#{gvar} == null) $gvars#{gvar} = nil;\n"
 end
 if class? && !@proto_ivars.empty?
 vars << '$proto = self.$$prototype'
 end
 indent = @compiler.parser_indent
 str = vars.empty? ? '' : "var #{vars.join ', '};\n"
 str += "#{indent}#{iv.join indent}" unless ivars.empty?
 str += "#{indent}#{gv.join indent}" unless gvars.empty?
 if class? && !@proto_ivars.empty?
 pvars = @proto_ivars.map { |i| "$proto#{i}" }.join(' = ')
 str = "#{str}\n#{indent}#{pvars} = nil;"
 end
 fragment(str)
end

#top?Boolean

Returns true if this is a top scope (main file body)

Returns:

  • (Boolean)
87
88
89
# File 'opal/lib/opal/nodes/scope.rb', line 87
def top?
 @type == :top
end

#uses_block!Object

246
247
248
249
250
251
252
253
# File 'opal/lib/opal/nodes/scope.rb', line 246
def uses_block!
 if @type == :iter && @parent
 @parent.uses_block!
 else
 @uses_block = true
 identify!
 end
end

#uses_block?Boolean

Returns:

  • (Boolean)
310
311
312
# File 'opal/lib/opal/nodes/scope.rb', line 310
def uses_block?
 @uses_block
end

AltStyle によって変換されたページ (->オリジナル) /