Class: Opal::Nodes::ScopeNode
Direct Known Subclasses
BeginNode, ModuleNode, NodeWithArgs, SingletonClassNode, TopNode
Instance Attribute Summary collapse
-
#block_name ⇒ Object
The given block name for a def scope.
-
#catch_return ⇒ Object
Returns the value of attribute catch_return.
-
#defs ⇒ Object
true if singleton def, false otherwise.
-
#gvars ⇒ Object
readonly
Returns the value of attribute gvars.
-
#has_break ⇒ Object
Returns the value of attribute has_break.
-
#identity ⇒ Object
readonly
Returns the value of attribute identity.
-
#ivars ⇒ Object
readonly
Returns the value of attribute ivars.
-
#locals ⇒ Object
readonly
Returns the value of attribute locals.
-
#methods ⇒ Object
readonly
used by modules to know what methods to donate to includees.
-
#mid ⇒ Object
Returns the value of attribute mid.
-
#name ⇒ Object
The class or module name if this scope is a class scope.
-
#parent ⇒ Object
Every scope can have a parent scope.
-
#rescue_else_sexp ⇒ Object
Returns the value of attribute rescue_else_sexp.
-
#scope_name ⇒ Object
readonly
Returns the value of attribute scope_name.
-
#uses_super ⇒ Object
uses parents super method.
-
#uses_zuper ⇒ Object
Returns the value of attribute uses_zuper.
Attributes inherited from Base
Instance Method Summary collapse
- #add_arg(arg) ⇒ Object
- #add_proto_ivar(ivar) ⇒ Object
- #add_scope_gvar(gvar) ⇒ Object
- #add_scope_ivar(ivar) ⇒ Object
- #add_scope_local(local) ⇒ Object
- #add_scope_temp(tmp) ⇒ Object
-
#class? ⇒ Boolean
Returns true if this is strictly a class scope.
-
#class_scope? ⇒ Boolean
Returns true if this scope is a class/module body scope.
- #def? ⇒ Boolean
-
#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.
- #find_parent_def ⇒ Object
- #has_local?(local) ⇒ Boolean
- #has_rescue_else? ⇒ Boolean
- #has_temp?(tmp) ⇒ Boolean
- #identify!(name = nil) ⇒ Object
- #in_ensure ⇒ Object
- #in_ensure? ⇒ Boolean
- #in_scope ⇒ Object
- #in_while? ⇒ Boolean
-
#initialize ⇒ ScopeNode
constructor
A new instance of ScopeNode.
-
#iter? ⇒ Boolean
True if a block/iter scope.
-
#module? ⇒ Boolean
True if this is a module scope.
- #new_temp ⇒ Object
- #next_temp ⇒ Object
- #pop_while ⇒ Object
- #push_while ⇒ Object
- #queue_temp(name) ⇒ Object
- #sclass? ⇒ Boolean
- #super_chain ⇒ Object
-
#to_vars ⇒ Object
Vars to use inside each scope.
-
#top? ⇒ Boolean
Returns true if this is a top scope (main file body).
- #uses_block! ⇒ Object
- #uses_block? ⇒ Boolean
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_nil, #fragment, handle, handlers, #helper, #process, #push, #recv, #recv?, #s, #scope, #stmt, #stmt?, truthy_optimize?, #unshift, #while_loop, #with_temp, #wrap
Methods included from Helpers
#conditional_send, #current_indent, #empty_line, #indent, #js_falsy, #js_truthy, #js_truthy_optimize, #line, #mid_to_jsid, #property, #valid_name?
Constructor Details
#initialize ⇒ ScopeNode
Returns a new instance of ScopeNode.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'opal/lib/opal/nodes/scope.rb', line 38 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
#block_name ⇒ Object
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_return ⇒ Object
Returns the value of attribute catch_return.
34 35 36 |
# File 'opal/lib/opal/nodes/scope.rb', line 34 def catch_return @catch_return end |
#defs ⇒ Object
true if singleton def, false otherwise
25 26 27 |
# File 'opal/lib/opal/nodes/scope.rb', line 25 def defs @defs end |
#gvars ⇒ Object (readonly)
Returns the value of attribute gvars.
20 21 22 |
# File 'opal/lib/opal/nodes/scope.rb', line 20 def gvars @gvars end |
#has_break ⇒ Object
Returns the value of attribute has_break.
34 35 36 |
# File 'opal/lib/opal/nodes/scope.rb', line 34 def has_break @has_break end |
#identity ⇒ Object (readonly)
Returns the value of attribute identity.
239 240 241 |
# File 'opal/lib/opal/nodes/scope.rb', line 239 def identity @identity end |
#ivars ⇒ Object (readonly)
Returns the value of attribute ivars.
19 20 21 |
# File 'opal/lib/opal/nodes/scope.rb', line 19 def ivars @ivars end |
#locals ⇒ Object (readonly)
Returns the value of attribute locals.
18 19 20 |
# File 'opal/lib/opal/nodes/scope.rb', line 18 def locals @locals end |
#methods ⇒ Object (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 |
#mid ⇒ Object
Returns the value of attribute mid.
22 23 24 |
# File 'opal/lib/opal/nodes/scope.rb', line 22 def mid @mid end |
#name ⇒ Object
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 |
#parent ⇒ Object
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_sexp ⇒ Object
Returns the value of attribute rescue_else_sexp.
36 37 38 |
# File 'opal/lib/opal/nodes/scope.rb', line 36 def rescue_else_sexp @rescue_else_sexp end |
#scope_name ⇒ Object (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 |
#uses_super ⇒ Object
uses parents super method
31 32 33 |
# File 'opal/lib/opal/nodes/scope.rb', line 31 def uses_super @uses_super end |
#uses_zuper ⇒ Object
Returns the value of attribute uses_zuper.
32 33 34 |
# File 'opal/lib/opal/nodes/scope.rb', line 32 def uses_zuper @uses_zuper end |
Instance Method Details
#add_arg(arg) ⇒ Object
156 157 158 159 |
# File 'opal/lib/opal/nodes/scope.rb', line 156 def add_arg(arg) @args << arg unless @args.include? arg arg end |
#add_proto_ivar(ivar) ⇒ Object
152 153 154 |
# File 'opal/lib/opal/nodes/scope.rb', line 152 def add_proto_ivar(ivar) @proto_ivars << ivar unless @proto_ivars.include? ivar end |
#add_scope_gvar(gvar) ⇒ Object
148 149 150 |
# File 'opal/lib/opal/nodes/scope.rb', line 148 def add_scope_gvar(gvar) @gvars << gvar unless @gvars.include? gvar end |
#add_scope_ivar(ivar) ⇒ Object
140 141 142 143 144 145 146 |
# File 'opal/lib/opal/nodes/scope.rb', line 140 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
161 162 163 164 165 |
# File 'opal/lib/opal/nodes/scope.rb', line 161 def add_scope_local(local) return if has_local? local @locals << local end |
#add_scope_temp(tmp) ⇒ Object
173 174 175 176 177 |
# File 'opal/lib/opal/nodes/scope.rb', line 173 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
77 78 79 |
# File 'opal/lib/opal/nodes/scope.rb', line 77 def class? @type == :class end |
#class_scope? ⇒ Boolean
Returns true if this scope is a class/module body scope
72 73 74 |
# File 'opal/lib/opal/nodes/scope.rb', line 72 def class_scope? @type == :class || @type == :module end |
#def? ⇒ Boolean
100 101 102 |
# File 'opal/lib/opal/nodes/scope.rb', line 100 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
107 108 109 |
# File 'opal/lib/opal/nodes/scope.rb', line 107 def def_in_class? !@defs && @type == :def && @parent && @parent.class? end |
#find_parent_def ⇒ Object
241 242 243 244 245 246 247 248 249 250 |
# File 'opal/lib/opal/nodes/scope.rb', line 241 def find_parent_def scope = self while scope = scope.parent if scope.def? return scope end end nil end |
#has_local?(local) ⇒ Boolean
167 168 169 170 171 |
# File 'opal/lib/opal/nodes/scope.rb', line 167 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
276 277 278 |
# File 'opal/lib/opal/nodes/scope.rb', line 276 def has_rescue_else? !rescue_else_sexp.nil? end |
#has_temp?(tmp) ⇒ Boolean
179 180 181 |
# File 'opal/lib/opal/nodes/scope.rb', line 179 def has_temp?(tmp) @temps.include? tmp end |
#identify!(name = nil) ⇒ Object
228 229 230 231 232 233 234 235 236 237 |
# File 'opal/lib/opal/nodes/scope.rb', line 228 def identify!(name = nil) return @identity if @identity # Parent scope is the defining module/class name ||= [(parent && (parent.name || parent.scope_name)), mid].compact.join('_') @identity = @compiler.unique_temp(name) @parent.add_scope_temp @identity if @parent @identity end |
#in_ensure ⇒ Object
280 281 282 283 284 285 286 287 288 |
# File 'opal/lib/opal/nodes/scope.rb', line 280 def in_ensure return unless block_given? @in_ensure = true result = yield @in_ensure = false result end |
#in_ensure? ⇒ Boolean
290 291 292 |
# File 'opal/lib/opal/nodes/scope.rb', line 290 def in_ensure? @in_ensure end |
#in_scope ⇒ Object
62 63 64 65 66 67 68 69 |
# File 'opal/lib/opal/nodes/scope.rb', line 62 def in_scope indent do @parent = compiler.scope compiler.scope = self yield self compiler.scope = @parent end end |
#in_while? ⇒ Boolean
215 216 217 |
# File 'opal/lib/opal/nodes/scope.rb', line 215 def in_while? !@while_stack.empty? end |
#iter? ⇒ Boolean
True if a block/iter scope
96 97 98 |
# File 'opal/lib/opal/nodes/scope.rb', line 96 def iter? @type == :iter end |
#module? ⇒ Boolean
True if this is a module scope
82 83 84 |
# File 'opal/lib/opal/nodes/scope.rb', line 82 def module? @type == :module end |
#new_temp ⇒ Object
183 184 185 186 187 188 189 |
# File 'opal/lib/opal/nodes/scope.rb', line 183 def new_temp return @queue.pop unless @queue.empty? tmp = next_temp @temps << tmp tmp end |
#next_temp ⇒ Object
191 192 193 194 195 196 197 198 199 |
# File 'opal/lib/opal/nodes/scope.rb', line 191 def next_temp tmp = nil loop do tmp = "$#{@unique}" @unique = @unique.succ break unless has_local?(tmp) end tmp end |
#pop_while ⇒ Object
211 212 213 |
# File 'opal/lib/opal/nodes/scope.rb', line 211 def pop_while @while_stack.pop end |
#push_while ⇒ Object
205 206 207 208 209 |
# File 'opal/lib/opal/nodes/scope.rb', line 205 def push_while info = {} @while_stack.push info info end |
#queue_temp(name) ⇒ Object
201 202 203 |
# File 'opal/lib/opal/nodes/scope.rb', line 201 def queue_temp(name) @queue << name end |
#sclass? ⇒ Boolean
86 87 88 |
# File 'opal/lib/opal/nodes/scope.rb', line 86 def sclass? @type == :sclass end |
#super_chain ⇒ Object
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
# File 'opal/lib/opal/nodes/scope.rb', line 252 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[def defs].include?(scope.type) defn = scope.identify! mid = "'#{scope.mid}'" break else break end end [chain, defn, mid] end |
#to_vars ⇒ Object
Vars to use inside each scope
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'opal/lib/opal/nodes/scope.rb', line 113 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 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| "self.$$prototype#{i}" }.join(' = ') result = "#{str}\n#{indent}#{pvars} = nil;" else result = str end fragment(result) end |
#top? ⇒ Boolean
Returns true if this is a top scope (main file body)
91 92 93 |
# File 'opal/lib/opal/nodes/scope.rb', line 91 def top? @type == :top end |
#uses_block! ⇒ Object
219 220 221 222 223 224 225 226 |
# File 'opal/lib/opal/nodes/scope.rb', line 219 def uses_block! if @type == :iter && @parent @parent.uses_block! else @uses_block = true identify! end end |
#uses_block? ⇒ Boolean
272 273 274 |
# File 'opal/lib/opal/nodes/scope.rb', line 272 def uses_block? @uses_block end |