Class: RedParse::AssignNode

Inherits:
ValueNode show all
Defined in:
lib/redparse/node.rb

Constant Summary

Constants included from FlattenedIvars

FlattenedIvars::EXCLUDED_IVARS

Instance Attribute Summary

Attributes inherited from Node

#endline, #errors, #offset, #parent, #startline

Attributes included from Stackable::Meta

#boolean_identity_params, #identity_params

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ValueNode

#lvalue

Methods inherited from Node

#+, #+@, #==, [], #[]=, #add_parent_links!, #begin_parsetree, #data, #deep_copy, #delete_extraneous_ivars!, #delete_linenums!, #depthwalk, #depthwalk_nodes, #error?, #evalable_inspect, #fixup_multiple_assignments!, #fixup_rescue_assignments!, #initialize_ivars, inline_symbols, #inspect, #lhs_unparse, #linerange, #lvalue, #lvars_defined_in, #merge_replacement_session, namelist, #negate, #original_brackets_assign, param_names, #parsetrees, #pretty_print, #prohibit_fixup, #replace_ivars_and_self, #replace_value, #rescue_parsetree, #to_parsetree, #to_parsetree_and_warnings, #unary, #walk, #xform_tree!

Methods included from Stackable::Meta

#build_exemplars, #enumerate_exemplars, #identity_param

Methods included from FlattenedIvars

#flattened_ivars, #flattened_ivars_equal?

Methods included from Stackable

#identity_name

Constructor Details

#initialize(*args) ⇒ AssignNode

Returns a new instance of AssignNode.



2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
# File 'lib/redparse/node.rb', line 2184

def initialize(*args)

  if args.size==5
    #this branch should be dead now
    if args[3].ident=="rescue3"
      lhs,op,rescuee,op2,rescuer=*args
      if MULTIASSIGN===lhs or rescuee.is_list?
        huh
      else
        rhs=RescueOpNode.new(rescuee.val,op2,rescuer)
      end
    else
      lhs,op,bogus1,rhs,bogus2=*args
    end
  else
    lhs,op,rhs=*args
    rhs=rhs.val if AssignmentRhsNode===rhs
  end
  case lhs
  when UnaryStarNode         #look for star on lhs
    lhs=MultiAssign.new([lhs]) unless lhs.after_comma
  when ParenedNode
    if !lhs.after_comma      #look for () around lhs
      if CommaOpNode===lhs.first
        lhs=MultiAssign.new(Array.new(lhs.first))
        @lhs_parens=true
      elsif UnaryStarNode===lhs.first
        lhs=MultiAssign.new([lhs.first])
        @lhs_parens=true
      elsif ParenedNode===lhs.first
        @lhs_parens=true
        lhs=lhs.first
      else
        lhs=lhs.first
      end
    end
  when CommaOpNode
    lhs=MultiAssign.new lhs
    #rhs=Array.new(rhs) if CommaOpNode===rhs
  end 

  if CommaOpNode===rhs
    rhs=Array.new(rhs)
    lhs=MultiAssign.new([lhs]) unless MultiAssign===lhs
  end

  op=op.ident

  if Array==rhs.class
    rhs.extend ListInNode
  end

  @offset=lhs.offset
  return super(lhs,op,rhs)  
  #punting, i hope the next layer can handle += and the like

=begin
  #in theory, we should do something more sophisticated, like this:
  #(but the presence of side effects in lhs will screw it up)
  if op=='='
    super
  else
    super(lhs,OpNode.new(lhs,OperatorToken.new(op.chomp('=')),rhs))
  end
=end
end

Class Method Details

.create(*args) ⇒ Object



2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
# File 'lib/redparse/node.rb', line 2167

def self.create(*args)
  if args.size==5
    if args[3].ident=="rescue3"
      lhs,op,rescuee,op2,rescuer=*args
      if MULTIASSIGN===lhs or !rescuee.is_list
        return RescueOpNode.new(AssignNode.new(lhs,op,rescuee),nil,rescuer)
      else
        rhs=RescueOpNode.new(rescuee.val,op2,rescuer)
      end
    else
      lhs,op,bogus1,rhs,bogus2=*args
    end
    super(lhs,op,rhs)
  else super
  end
end

Instance Method Details

#all_current_lvarsObject



2280
2281
2282
2283
# File 'lib/redparse/node.rb', line 2280

def all_current_lvars
  left.respond_to?(:all_current_lvars) ?
    left.all_current_lvars : []
end

#imageObject



2255
# File 'lib/redparse/node.rb', line 2255

def image; '(=)' end

#multi?Boolean

Returns:

  • (Boolean)


2251
2252
2253
# File 'lib/redparse/node.rb', line 2251

def multi?
  MultiAssign===left
end

#parsetree(o) ⇒ Object



2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
# File 'lib/redparse/node.rb', line 2285

def parsetree(o)
  case left
  when ParenedNode; huh
  when RescueOpNode; huh
  when BeginNode; huh
  when ConstantNode;
    left.lvalue_parsetree(o) << right.parsetree(o)

  when MultiAssign;
  lhs=left.lvalue_parsetree(o)
  rhs= right.class==Array ? right.dup : [right]
  star=rhs.pop if UnaryStarNode===rhs.last
  rhs=rhs.map{|x| x.rescue_parsetree(o)}
  if rhs.size==0
    star or fail
    rhs= star.parsetree(o)
  elsif rhs.size==1 and !star and !(UnaryStarNode===left.first)
    rhs.unshift :to_ary
  else
    rhs.unshift(:array) 
    if star
      splat=star.val.rescue_parsetree(o)
      #if splat.first==:call #I don't see how this can be right....
      #  splat[0]=:attrasgn
      #  splat[2]="#{splat[2]}=".to_sym
      #end
      rhs=[:argscat, rhs, splat] 
    end
    if left.size==1 and !(UnaryStarNode===left.first) and !(NestedAssign===left.first)
      rhs=[:svalue, rhs]
      if CallNode===left.first
        rhs=[:array, rhs]
      end
    end
  end
  if left.size==1 and BracketsGetNode===left.first and right.class==Array #hack
    lhs.last<<rhs
    lhs
  else
    lhs<< rhs
  end

  when CallSiteNode
  op=op().chomp('=')
  rcvr=left.receiver.parsetree(o)
  prop=left.name.+('=').to_sym
  args=right.rescue_parsetree(o)
  UnaryStarNode===right and args=[:svalue, args]
  if op.empty?
    [:attrasgn, rcvr, prop, [:array, args] ]
  else
    [:op_asgn2, rcvr,prop,  op.to_sym, args]
  end

  when BracketsGetNode
  args=left.params
  if op()=='='
    result=left.lvalue_parsetree(o) #[:attrasgn, left[0].parsetree(o), :[]=]
    result.size==3 and result.push [:array]
    rhs=right.rescue_parsetree(o)
    UnaryStarNode===right and rhs=[:svalue, rhs]
    if args 
      result[-1]=[:argspush,result[-1]] if UnaryStarNode===args.last
    #else result[-1]=[:zarray]
    end
    result.last << rhs
    result            
    
  else
=begin
    args&&=args.map{|x| x.parsetree(o)}.unshift(:array)
    splat=args.pop if :splat==args.last.first
    if splat and left.params.size==1
      args=splat
    elsif splat
      args=[:argscat, args, splat.last]
    end
=end
    lhs=left.parsetree(o)
    if lhs.first==:fcall
      rcvr=[:self]
      args=lhs[2]
    else
      rcvr=lhs[1]
      args=lhs[3]
    end
    args||=[:zarray]
    result=[
      :op_asgn1, rcvr, args,
      op().chomp('=').to_sym, 
      right.rescue_parsetree(o)
    ]
  end

  when VarNode
  node_type=left.varname2assigntype
  if /^(&&|\|\|)=$/===op()
    
    return ["op_asgn_#{$1[0]==?& ? "and" : "or"}".to_sym, 
            left.parsetree(o),
            [node_type, left.ident.to_sym, 
             right.rescue_parsetree(o)]
           ]
  end

  if op()=='='
    rhs=right.rescue_parsetree(o)
    UnaryStarNode===right and rhs=[:svalue, rhs]
    
#          case left
#          when VarNode; 
         [node_type, left.ident.to_sym, rhs]
#          else [node_type, left.data[0].parsetree(o), left.data[1].data[0].ident.+('=').to_sym  ,[:array, rhs]]
#          end

=begin these branches shouldn't be necessary now
  elsif node_type==:op_asgn2
    [node_type, @data[0].data[0].parsetree(o), 
      @data[0].data[1].data[0].ident.+('=').to_sym,
      op().ident.chomp('=').to_sym,
       @data[2].parsetree(o)
    ]
  elsif node_type==:attrasgn
    [node_type]
=end
  else
    [node_type, left.ident.to_sym,
      [:call,
       left.parsetree(o), 
         op().chomp('=').to_sym, 
       [:array, right.rescue_parsetree(o)]
      ]
    ]
  end
  else 
    huh
  end
end

#to_lispObject



2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
# File 'lib/redparse/node.rb', line 2257

def to_lisp
  case left
  when ParenedNode; huh
  when BeginNode; huh
  when RescueOpNode; huh
  when ConstantNode; huh
  when BracketsGetNode; huh
  when VarNode
    "(set #{left.to_lisp} (#{op.chomp('=')} #{left.to_lisp} #{right.to_lisp}))"
  when CallSiteNode
  if op=='='
    "(#{left.receiver.to_lisp} #{left.name}= #{right.to_lisp})"
  else
    op_=op.chomp('=')
    varname=nil
    "(let #{varname=huh} #{left.receiver.to_lisp} "+
      "(#{varname} #{left.name}= "+
        "(#{op_} (#{varname} #{op}) #{right.to_lisp})))"
  end
  else  huh
  end
end

#unparse(o = default_unparse_options) ⇒ Object



2424
2425
2426
2427
2428
2429
2430
2431
2432
# File 'lib/redparse/node.rb', line 2424

def unparse(o=default_unparse_options)
  result=lhs.lhs_unparse(o)
  result="(#{result})" if defined? @lhs_parens
  result+op+
    (rhs.class==Array ? 
      rhs.map{|rv| rv.unparse o}.join(',') :
      rhs.unparse(o) 
    )
end