Class: Opal::Nodes::ScopeNode
Direct Known Subclasses
Constant Summary
Constants included from Helpers
Helpers::BASIC_IDENTIFIER_RULES, Helpers::ES3_RESERVED_WORD_EXCLUSIVE, Helpers::ES51_RESERVED_WORD, Helpers::IMMUTABLE_PROPS, Helpers::PROTO_SPECIAL_METHODS, Helpers::PROTO_SPECIAL_PROPS, Helpers::RESERVED_FUNCTION_NAMES
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.
-
#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
- #get_super_chain ⇒ Object
- #has_local?(local) ⇒ Boolean
- #has_rescue_else? ⇒ Boolean
- #has_temp?(tmp) ⇒ Boolean
- #identify! ⇒ Object
- #identity ⇒ Object
- #in_ensure ⇒ Object
- #in_ensure? ⇒ Boolean
- #in_scope(&block) ⇒ 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
-
#proto ⇒ Object
Inside a class or module scope, the javascript variable name returned by this function points to the classes' prototype.
- #push_while ⇒ Object
- #queue_temp(name) ⇒ Object
- #sclass? ⇒ Boolean
-
#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, #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
#current_indent, #empty_line, #indent, #ivar, #js_falsy, #js_truthy, #js_truthy_optimize, #line, #lvar_to_js, #mid_to_jsid, #property, #valid_ivar_name?, #valid_name?, #variable
Constructor Details
#initialize ⇒ ScopeNode
Returns a new instance of ScopeNode
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'opal/lib/opal/nodes/scope.rb', line 37 def initialize(*) super @locals = [] @temps = [] @args = [] @ivars = [] @gvars = [] @parent = nil @queue = [] @unique = 'a' @while_stack = [] @identity = nil @defs = nil @methods = [] @uses_block = 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
14 15 16 |
# File 'opal/lib/opal/nodes/scope.rb', line 14 def block_name @block_name end |
#catch_return ⇒ Object
Returns the value of attribute catch_return
33 34 35 |
# File 'opal/lib/opal/nodes/scope.rb', line 33 def catch_return @catch_return end |
#defs ⇒ Object
true if singleton def, false otherwise
24 25 26 |
# File 'opal/lib/opal/nodes/scope.rb', line 24 def defs @defs end |
#gvars ⇒ Object (readonly)
Returns the value of attribute gvars
19 20 21 |
# File 'opal/lib/opal/nodes/scope.rb', line 19 def gvars @gvars end |
#has_break ⇒ Object
Returns the value of attribute has_break
33 34 35 |
# File 'opal/lib/opal/nodes/scope.rb', line 33 def has_break @has_break end |
#ivars ⇒ Object (readonly)
Returns the value of attribute ivars
18 19 20 |
# File 'opal/lib/opal/nodes/scope.rb', line 18 def ivars @ivars end |
#locals ⇒ Object (readonly)
Returns the value of attribute locals
17 18 19 |
# File 'opal/lib/opal/nodes/scope.rb', line 17 def locals @locals end |
#methods ⇒ Object (readonly)
used by modules to know what methods to donate to includees
27 28 29 |
# File 'opal/lib/opal/nodes/scope.rb', line 27 def methods @methods end |
#mid ⇒ Object
Returns the value of attribute mid
21 22 23 |
# File 'opal/lib/opal/nodes/scope.rb', line 21 def mid @mid end |
#name ⇒ Object
The class or module name if this scope is a class scope
11 12 13 |
# File 'opal/lib/opal/nodes/scope.rb', line 11 def name @name end |
#parent ⇒ Object
Every scope can have a parent scope
8 9 10 |
# File 'opal/lib/opal/nodes/scope.rb', line 8 def parent @parent end |
#rescue_else_sexp ⇒ Object
Returns the value of attribute rescue_else_sexp
35 36 37 |
# File 'opal/lib/opal/nodes/scope.rb', line 35 def rescue_else_sexp @rescue_else_sexp end |
#scope_name ⇒ Object (readonly)
Returns the value of attribute scope_name
16 17 18 |
# File 'opal/lib/opal/nodes/scope.rb', line 16 def scope_name @scope_name end |
#uses_super ⇒ Object
uses parents super method
30 31 32 |
# File 'opal/lib/opal/nodes/scope.rb', line 30 def uses_super @uses_super end |
#uses_zuper ⇒ Object
Returns the value of attribute uses_zuper
31 32 33 |
# File 'opal/lib/opal/nodes/scope.rb', line 31 def uses_zuper @uses_zuper end |
Instance Method Details
#add_arg(arg) ⇒ Object
162 163 164 165 |
# File 'opal/lib/opal/nodes/scope.rb', line 162 def add_arg(arg) @args << arg unless @args.include? arg arg end |
#add_proto_ivar(ivar) ⇒ Object
158 159 160 |
# File 'opal/lib/opal/nodes/scope.rb', line 158 def add_proto_ivar(ivar) @proto_ivars << ivar unless @proto_ivars.include? ivar end |
#add_scope_gvar(gvar) ⇒ Object
154 155 156 |
# File 'opal/lib/opal/nodes/scope.rb', line 154 def add_scope_gvar(gvar) @gvars << gvar unless @gvars.include? gvar end |
#add_scope_ivar(ivar) ⇒ Object
146 147 148 149 150 151 152 |
# File 'opal/lib/opal/nodes/scope.rb', line 146 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
167 168 169 170 171 |
# File 'opal/lib/opal/nodes/scope.rb', line 167 def add_scope_local(local) return if has_local? local @locals << local end |
#add_scope_temp(tmp) ⇒ Object
179 180 181 182 183 |
# File 'opal/lib/opal/nodes/scope.rb', line 179 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
75 76 77 |
# File 'opal/lib/opal/nodes/scope.rb', line 75 def class? @type == :class end |
#class_scope? ⇒ Boolean
Returns true if this scope is a class/module body scope
70 71 72 |
# File 'opal/lib/opal/nodes/scope.rb', line 70 def class_scope? @type == :class or @type == :module end |
#def? ⇒ Boolean
98 99 100 |
# File 'opal/lib/opal/nodes/scope.rb', line 98 def def? @type == :def 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
105 106 107 |
# File 'opal/lib/opal/nodes/scope.rb', line 105 def def_in_class? !@defs && @type == :def && @parent && @parent.class? end |
#find_parent_def ⇒ Object
248 249 250 251 252 253 254 255 256 257 |
# File 'opal/lib/opal/nodes/scope.rb', line 248 def find_parent_def scope = self while scope = scope.parent if scope.def? return scope end end nil end |
#get_super_chain ⇒ Object
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'opal/lib/opal/nodes/scope.rb', line 259 def get_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 scope.type == :def defn = scope.identify! mid = "'#{scope.mid}'" break else break end end [chain, defn, mid] end |
#has_local?(local) ⇒ Boolean
173 174 175 176 177 |
# File 'opal/lib/opal/nodes/scope.rb', line 173 def has_local?(local) return true if @locals.include? local or @args.include? local or @temps.include? local return @parent.has_local?(local) if @parent and @type == :iter false end |
#has_rescue_else? ⇒ Boolean
284 285 286 |
# File 'opal/lib/opal/nodes/scope.rb', line 284 def has_rescue_else? !!rescue_else_sexp end |
#has_temp?(tmp) ⇒ Boolean
185 186 187 |
# File 'opal/lib/opal/nodes/scope.rb', line 185 def has_temp?(tmp) @temps.include? tmp end |
#identify! ⇒ Object
235 236 237 238 239 240 241 242 |
# File 'opal/lib/opal/nodes/scope.rb', line 235 def identify! return @identity if @identity @identity = @compiler.unique_temp @parent.add_scope_temp @identity if @parent @identity end |
#identity ⇒ Object
244 245 246 |
# File 'opal/lib/opal/nodes/scope.rb', line 244 def identity @identity end |
#in_ensure ⇒ Object
288 289 290 291 292 293 294 |
# File 'opal/lib/opal/nodes/scope.rb', line 288 def in_ensure return unless block_given? @in_ensure = true result = yield @in_ensure = false end |
#in_ensure? ⇒ Boolean
296 297 298 |
# File 'opal/lib/opal/nodes/scope.rb', line 296 def in_ensure? !!@in_ensure end |
#in_scope(&block) ⇒ Object
60 61 62 63 64 65 66 67 |
# File 'opal/lib/opal/nodes/scope.rb', line 60 def in_scope(&block) indent do @parent = compiler.scope compiler.scope = self block.call self compiler.scope = @parent end end |
#in_while? ⇒ Boolean
222 223 224 |
# File 'opal/lib/opal/nodes/scope.rb', line 222 def in_while? !@while_stack.empty? end |
#iter? ⇒ Boolean
True if a block/iter scope
94 95 96 |
# File 'opal/lib/opal/nodes/scope.rb', line 94 def iter? @type == :iter end |
#module? ⇒ Boolean
True if this is a module scope
80 81 82 |
# File 'opal/lib/opal/nodes/scope.rb', line 80 def module? @type == :module end |
#new_temp ⇒ Object
189 190 191 192 193 194 195 |
# File 'opal/lib/opal/nodes/scope.rb', line 189 def new_temp return @queue.pop unless @queue.empty? tmp = next_temp @temps << tmp tmp end |
#next_temp ⇒ Object
197 198 199 200 201 202 203 204 205 206 |
# File 'opal/lib/opal/nodes/scope.rb', line 197 def next_temp while true tmp = "$#{@unique}" @unique = @unique.succ unless has_local?(tmp) break end end tmp end |
#pop_while ⇒ Object
218 219 220 |
# File 'opal/lib/opal/nodes/scope.rb', line 218 def pop_while @while_stack.pop end |
#proto ⇒ Object
Inside a class or module scope, the javascript variable name returned by this function points to the classes' prototype. This is the target to where methods are actually added inside a class body.
112 113 114 |
# File 'opal/lib/opal/nodes/scope.rb', line 112 def proto "def" end |
#push_while ⇒ Object
212 213 214 215 216 |
# File 'opal/lib/opal/nodes/scope.rb', line 212 def push_while info = {} @while_stack.push info info end |
#queue_temp(name) ⇒ Object
208 209 210 |
# File 'opal/lib/opal/nodes/scope.rb', line 208 def queue_temp(name) @queue << name end |
#sclass? ⇒ Boolean
84 85 86 |
# File 'opal/lib/opal/nodes/scope.rb', line 84 def sclass? @type == :sclass end |
#to_vars ⇒ Object
Vars to use inside each scope
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'opal/lib/opal/nodes/scope.rb', line 118 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? and !@proto_ivars.empty? #raise "FIXME to_vars" pvars = @proto_ivars.map { |i| "#{proto}#{i}"}.join(' = ') result = "%s\n%s%s = nil;" % [str, indent, pvars] else result = str end fragment(result) end |
#top? ⇒ Boolean
Returns true if this is a top scope (main file body)
89 90 91 |
# File 'opal/lib/opal/nodes/scope.rb', line 89 def top? @type == :top end |
#uses_block! ⇒ Object
226 227 228 229 230 231 232 233 |
# File 'opal/lib/opal/nodes/scope.rb', line 226 def uses_block! if @type == :iter && @parent @parent.uses_block! else @uses_block = true identify! end end |
#uses_block? ⇒ Boolean
280 281 282 |
# File 'opal/lib/opal/nodes/scope.rb', line 280 def uses_block? @uses_block end |