class NScript::ForNode

Attributes

index[R]
name[R]
step[R]

Public Class Methods

new(body, source, name, index=nil) click to toggle source
# File lib/nscript/parser/nodes.rb, line 723
def initialize(body, source, name, index=nil)
  @body, @name, @index = body, name, index
  @source = source[:source]
  @filter = source[:filter]
  @step   = source[:step]
  @object = !!source[:object]
  @name, @index = @index, @name if @object
end

Public Instance Methods

compile_node(o) click to toggle source
# File lib/nscript/parser/nodes.rb, line 732
def compile_node(o)
  top_level     = o.delete(:top) && !o[:return]
  range         = @source.is_a?(ValueNode) && @source.base.is_a?(RangeNode) && @source.properties.empty?
  source        = range ? @source.base : @source
  scope         = o[:scope]
  name_found    = @name  && scope.find(@name)
  index_found   = @index && scope.find(@index)
  body_dent     = idt(1)
  rvar          = scope.free_variable unless top_level
  svar          = scope.free_variable
  ivar          = range ? name : @index ? @index : scope.free_variable
  var_part      = ''
  body          = Expressions.wrap(@body)
  if range
    index_var   = scope.free_variable
    source_part = source.compile_variables(o)
    for_part    = "#{index_var}=0, #{source.compile(o.merge(:index => ivar, :step => @step))}, #{index_var}++"
  else
    index_var   = nil
    source_part = "#{svar} = #{@source.compile(o)};\n#{idt}"
    step_part   = @step ? "#{ivar} += #{@step.compile(o)}" : "#{ivar}++"
    for_part    = @object ? "#{ivar} in #{svar}" : "#{ivar} = 0; #{ivar} < #{svar}.length; #{step_part}"
    var_part    = "#{body_dent}#{@name} = #{svar}[#{ivar}];\n" if @name
    # body.unshift(AssignNode.new(@name, ValueNode.new(svar, [IndexNode.new(ivar)]))) if @name
  end
  set_result    = rvar ? "#{idt}#{rvar} = []; " : idt
  return_result = rvar || ''
  body = ClosureNode.wrap(body, true) if top_level && contains? {|n| n.is_a? CodeNode }
  body = PushNode.wrap(rvar, body) unless top_level
  if o[:return]
    return_result = "return #{return_result}" if o[:return]
    o.delete(:return)
    body = IfNode.new(@filter, body, nil, :statement => true) if @filter
  elsif @filter
    body = Expressions.wrap(IfNode.new(@filter, body))
  end
  if @object
    o[:scope].assign("__hasProp", "Object.prototype.hasOwnProperty", true)
    body = Expressions.wrap(IfNode.new(
      CallNode.new(
        ValueNode.new(LiteralNode.wrap("__hasProp"), [AccessorNode.new(Value.new('call'))]),
        [LiteralNode.wrap(svar), LiteralNode.wrap(ivar)]
      ),
      Expressions.wrap(body), nil, {:statement => true}
    ))
  end

  return_result = "\n#{idt}#{return_result};" unless top_level
  body = body.compile(o.merge(:indent => body_dent, :top => true))
  vars = range ? @name : "#{@name}, #{ivar}"
  return write(set_result + source_part + "for (#{for_part}) {\n#{var_part}#{body}\n#{idt}}\n#{idt}#{return_result}")
end