Class: Ember::Template::Program

Inherits:
Object
  • Object
show all
Defined in:
lib/ember/template.rb

Overview

:nodoc:

Defined Under Namespace

Classes: Statement

Constant Summary collapse

RESULT_VARIABLE_BACKDOOR =

Name of a variable whose value is the name of the result variable in the Ruby code produced by this program.

'e08afdfb_62c7_485f_87a0_80914e1b4703'

Instance Method Summary collapse

Constructor Details

#initialize(result_variable, continue_result) ⇒ Program

Transforms this program into Ruby code which uses the given variable name as the evaluation buffer.

If continue_result is true, the evaluation buffer is reused if it already exists in the rendering context.


495
496
497
498
499
# File 'lib/ember/template.rb', line 495

def initialize result_variable, continue_result
  @result_variable = result_variable
  @continue_result = continue_result
  @source_lines = [] # each line is composed of multiple statements
end

Instance Method Details

#compileObject

Transforms this program into executable Ruby source code.


589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
# File 'lib/ember/template.rb', line 589

def compile
  '(%s = %s; %s %s []; %s; %s.join)' % [
    RESULT_VARIABLE_BACKDOOR,
    @result_variable.inspect,

    @result_variable,
    @continue_result ? '||=' : '=',

    @source_lines.map do |source_line|
      compiled_line = []
      combine_prev = false

      source_line.each do |stmt|
        is_code = stmt.type == :code
        is_expr = stmt.type == :expr

        if is_code
          compiled_line << stmt.value
          combine_prev = false

        else
          code =
            if is_expr
              " << (#{stmt.value.strip})"
            else
              " << #{stmt.value.inspect}"
            end

          if combine_prev
            compiled_line.last << code
          else
            compiled_line << @result_variable.to_s + code
          end

          combine_prev = true
        end
      end

      compiled_line.join('; ')

    end.join("\n"),

    @result_variable,
  ]
end

#emit_code(value) ⇒ Object

Schedules the given Ruby code to be evaluated when this program is run.


544
545
546
# File 'lib/ember/template.rb', line 544

def emit_code value
  statement :code, value
end

#emit_endObject

Inserts an <% end %> directive before the oldest non-whitespace statement possible.

Preceding lines that only emit whitespace are skipped.


562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
# File 'lib/ember/template.rb', line 562

def emit_end
  ending  = Statement.new(:code, :end)
  current = insertion_point

  can_skip_line = lambda do |line|
    line.empty? ||
    line.all? {|stmt| stmt.type == :text && stmt.value =~ /\A\s*\z/ }
  end

  if can_skip_line[current]
    target = current

    # skip past empty whitespace in previous lines
    @source_lines.reverse_each do |line|
      break unless can_skip_line[line]
      target = line
    end

    target.unshift ending
  else
    current.push ending
  end
end

#emit_expr(value) ⇒ Object

Schedules the given Ruby code to be evaluated and inserted into the evaluation buffer when this program is run.


552
553
554
# File 'lib/ember/template.rb', line 552

def emit_expr value
  statement :expr, value
end

#emit_text(value) ⇒ Object

Schedules the given text to be inserted verbatim into the evaluation buffer when this program is run.


528
529
530
531
532
533
534
535
536
537
538
# File 'lib/ember/template.rb', line 528

def emit_text value
  # don't bother emitting empty strings
  return if value.empty?

  # combine adjacent statements to reduce code size
  if prev = insertion_point.last and prev.type == :text
    prev.value << value
  else
    statement :text, value
  end
end

#empty?Boolean

Returns true if there are no source lines in this program.

Returns:

  • (Boolean)

504
505
506
# File 'lib/ember/template.rb', line 504

def empty?
  @source_lines.empty?
end

#new_lineObject

Begins a new line in the program's source code.


511
512
513
# File 'lib/ember/template.rb', line 511

def new_line
  @source_lines << []
end

#new_line?Boolean

Returns true if a new (blank) line is ready in the program's source code.

Returns:

  • (Boolean)

519
520
521
522
# File 'lib/ember/template.rb', line 519

def new_line?
  ary = insertion_point
  ary.empty? || ary.all? {|stmt| stmt.type == :code }
end