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 |