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
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. 
- 
  
    
      #ivars  ⇒ Object 
    
    
  
  
  
  
    
      readonly
    
    
  
  
  
  
  
  
    Returns the value of attribute ivars. 
- 
  
    
      #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. 
- 
  
    
      #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(*tmps) ⇒ 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_temp?(tmp) ⇒ Boolean
- #identify! ⇒ Object
- #identity ⇒ Object
- #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?, #unshift, #while_loop, #with_temp, #wrap
Methods included from Helpers
#current_indent, #empty_line, #indent, #js_falsy, #js_truthy, #js_truthy_optimize, #line, #lvar_to_js, #mid_to_jsid, #property, #valid_name?, #variable
Constructor Details
#initialize ⇒ ScopeNode
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 | # 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 # 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
| 32 33 34 | # File 'opal/lib/opal/nodes/scope.rb', line 32 def catch_return @catch_return end | 
#defs ⇒ Object
true if singleton def, false otherwise
| 23 24 25 | # File 'opal/lib/opal/nodes/scope.rb', line 23 def defs @defs end | 
#gvars ⇒ Object (readonly)
Returns the value of attribute gvars
| 18 19 20 | # File 'opal/lib/opal/nodes/scope.rb', line 18 def gvars @gvars end | 
#ivars ⇒ Object (readonly)
Returns the value of attribute ivars
| 17 18 19 | # File 'opal/lib/opal/nodes/scope.rb', line 17 def ivars @ivars end | 
#methods ⇒ Object (readonly)
used by modules to know what methods to donate to includees
| 26 27 28 | # File 'opal/lib/opal/nodes/scope.rb', line 26 def methods @methods end | 
#mid ⇒ Object
Returns the value of attribute mid
| 20 21 22 | # File 'opal/lib/opal/nodes/scope.rb', line 20 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 | 
#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
| 29 30 31 | # File 'opal/lib/opal/nodes/scope.rb', line 29 def uses_super @uses_super end | 
#uses_zuper ⇒ Object
Returns the value of attribute uses_zuper
| 30 31 32 | # File 'opal/lib/opal/nodes/scope.rb', line 30 def uses_zuper @uses_zuper end | 
Instance Method Details
#add_arg(arg) ⇒ Object
| 159 160 161 162 | # File 'opal/lib/opal/nodes/scope.rb', line 159 def add_arg(arg) @args << arg unless @args.include? arg arg end | 
#add_proto_ivar(ivar) ⇒ Object
| 155 156 157 | # File 'opal/lib/opal/nodes/scope.rb', line 155 def add_proto_ivar(ivar) @proto_ivars << ivar unless @proto_ivars.include? ivar end | 
#add_scope_gvar(gvar) ⇒ Object
| 151 152 153 | # File 'opal/lib/opal/nodes/scope.rb', line 151 def add_scope_gvar(gvar) @gvars << gvar unless @gvars.include? gvar end | 
#add_scope_ivar(ivar) ⇒ Object
| 143 144 145 146 147 148 149 | # File 'opal/lib/opal/nodes/scope.rb', line 143 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
| 164 165 166 167 168 | # File 'opal/lib/opal/nodes/scope.rb', line 164 def add_scope_local(local) return if has_local? local @locals << local end | 
#add_scope_temp(*tmps) ⇒ Object
| 177 178 179 | # File 'opal/lib/opal/nodes/scope.rb', line 177 def add_scope_temp(*tmps) @temps.push(*tmps) end | 
#class? ⇒ Boolean
Returns true if this is strictly a class scope
| 72 73 74 | # File 'opal/lib/opal/nodes/scope.rb', line 72 def class? @type == :class end | 
#class_scope? ⇒ Boolean
Returns true if this scope is a class/module body scope
| 67 68 69 | # File 'opal/lib/opal/nodes/scope.rb', line 67 def class_scope? @type == :class or @type == :module end | 
#def? ⇒ Boolean
| 95 96 97 | # File 'opal/lib/opal/nodes/scope.rb', line 95 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
| 102 103 104 | # File 'opal/lib/opal/nodes/scope.rb', line 102 def def_in_class? !@defs && @type == :def && @parent && @parent.class? end | 
#find_parent_def ⇒ Object
| 239 240 241 242 243 244 245 246 247 248 | # File 'opal/lib/opal/nodes/scope.rb', line 239 def find_parent_def scope = self while scope = scope.parent if scope.def? return scope end end nil end | 
#get_super_chain ⇒ Object
| 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | # File 'opal/lib/opal/nodes/scope.rb', line 250 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
| 170 171 172 173 174 175 | # File 'opal/lib/opal/nodes/scope.rb', line 170 def has_local?(local) return true if @locals.include? local or @args.include? local return @parent.has_local?(local) if @parent and @type == :iter false end | 
#has_temp?(tmp) ⇒ Boolean
| 181 182 183 | # File 'opal/lib/opal/nodes/scope.rb', line 181 def has_temp?(tmp) @temps.include? tmp end | 
#identify! ⇒ Object
| 226 227 228 229 230 231 232 233 | # File 'opal/lib/opal/nodes/scope.rb', line 226 def identify! return @identity if @identity @identity = @compiler.unique_temp @parent.add_scope_temp @identity if @parent @identity end | 
#identity ⇒ Object
| 235 236 237 | # File 'opal/lib/opal/nodes/scope.rb', line 235 def identity @identity end | 
#in_scope(&block) ⇒ Object
| 57 58 59 60 61 62 63 64 | # File 'opal/lib/opal/nodes/scope.rb', line 57 def in_scope(&block) indent do @parent = compiler.scope compiler.scope = self block.call self compiler.scope = @parent end end | 
#in_while? ⇒ Boolean
| 213 214 215 | # File 'opal/lib/opal/nodes/scope.rb', line 213 def in_while? !@while_stack.empty? end | 
#iter? ⇒ Boolean
True if a block/iter scope
| 91 92 93 | # File 'opal/lib/opal/nodes/scope.rb', line 91 def iter? @type == :iter end | 
#module? ⇒ Boolean
True if this is a module scope
| 77 78 79 | # File 'opal/lib/opal/nodes/scope.rb', line 77 def module? @type == :module end | 
#new_temp ⇒ Object
| 185 186 187 188 189 190 191 | # File 'opal/lib/opal/nodes/scope.rb', line 185 def new_temp return @queue.pop unless @queue.empty? tmp = next_temp @temps << tmp tmp end | 
#next_temp ⇒ Object
| 193 194 195 196 197 | # File 'opal/lib/opal/nodes/scope.rb', line 193 def next_temp tmp = "$#{@unique}" @unique = @unique.succ tmp end | 
#pop_while ⇒ Object
| 209 210 211 | # File 'opal/lib/opal/nodes/scope.rb', line 209 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.
| 109 110 111 | # File 'opal/lib/opal/nodes/scope.rb', line 109 def proto "def" end | 
#push_while ⇒ Object
| 203 204 205 206 207 | # File 'opal/lib/opal/nodes/scope.rb', line 203 def push_while info = {} @while_stack.push info info end | 
#queue_temp(name) ⇒ Object
| 199 200 201 | # File 'opal/lib/opal/nodes/scope.rb', line 199 def queue_temp(name) @queue << name end | 
#sclass? ⇒ Boolean
| 81 82 83 | # File 'opal/lib/opal/nodes/scope.rb', line 81 def sclass? @type == :sclass end | 
#to_vars ⇒ Object
Vars to use inside each scope
| 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | # File 'opal/lib/opal/nodes/scope.rb', line 115 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)
| 86 87 88 | # File 'opal/lib/opal/nodes/scope.rb', line 86 def top? @type == :top end | 
#uses_block! ⇒ Object
| 217 218 219 220 221 222 223 224 | # File 'opal/lib/opal/nodes/scope.rb', line 217 def uses_block! if @type == :iter && @parent @parent.uses_block! else @uses_block = true identify! end end | 
#uses_block? ⇒ Boolean
| 271 272 273 | # File 'opal/lib/opal/nodes/scope.rb', line 271 def uses_block? @uses_block end |