Class: Twig::Compiler

Inherits:
Object
  • Object
show all
Defined in:
lib/twig/compiler.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(environment) ⇒ Compiler

Returns a new instance of Compiler.

Parameters:



13
14
15
16
# File 'lib/twig/compiler.rb', line 13

def initialize(environment)
  @environment = environment
  @var_name_salt = 0
end

Instance Attribute Details

#debug_infoHash<Integer, Integer> (readonly)

Returns:

  • (Hash<Integer, Integer>)


10
11
12
# File 'lib/twig/compiler.rb', line 10

def debug_info
  @debug_info
end

#environmentEnvironment (readonly)

Returns:



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/twig/compiler.rb', line 6

class Compiler
  attr_reader :source, :environment

  # @return [Hash<Integer, Integer>]
  attr_reader :debug_info

  # @param [Environment] environment
  def initialize(environment)
    @environment = environment
    @var_name_salt = 0
  end

  # @param [Node::Base] node
  # @param [Integer] indentation
  # @return [Compiler]
  def compile(node, indentation = 0)
    reset(indentation)
    node.compile(self)

    self
  end

  # @param [Node::Base] node
  # @param [Boolean] raw
  # @return [Compiler]
  def subcompile(node, raw: true)
    indent_source unless raw

    node.compile(self)

    self
  end

  # @param [Array<String>] strings
  # @return [Compiler]
  def write(*strings)
    strings.each do |string|
      indent_source
      @source << string
    end

    self
  end

  # @param [String] value
  # @return [Compiler]
  def string(value)
    @source << "%q[#{value.to_s.gsub(/[\[\]\\]/, '[' => '\[', ']' => '\]', '\\' => '\\\\')}]"

    self
  end

  # @param [String, Symbol] value
  # @return [Compiler]
  def symbol(value)
    @source << if value.is_a?(Symbol)
                 value.inspect
               else
                 "%q[#{value}].to_sym"
               end

    self
  end

  # @param [String] string
  # @return [Compiler]
  def raw(string)
    @source << string

    self
  end

  def repr(value)
    case value
    when Integer, Float
      raw(value.to_s)
    when TrueClass, FalseClass
      raw(value ? 'true' : 'false')
    when NilClass
      raw('nil')
    when Array, Hash
      raw('Marshal.load(').
        raw(Marshal.dump(value).inspect).
        raw(')')
    when Symbol
      symbol(value)
    else
      string(value)
    end
  end

  # @param [Node::Base] node
  # @return [Compiler]
  def add_debug_info(node)
    if node.lineno != @last_line
      write("# line #{node.lineno}\n")

      @source_line += @source[@source_offset..].count("\n")
      @source_offset = @source.length
      @debug_info[@source_line] = node.lineno

      @last_line = node.lineno
    end

    self
  end

  # @param [Integer] step
  # @return [Compiler]
  def indent(step = 1)
    @indentation += step

    self
  end

  # @param [Integer] step
  # @return [Compiler]
  def outdent(step = 1)
    @indentation -= step

    self
  end

  # @return [String]
  def var_name
    @var_name_salt += 1
    "_v#{@var_name_salt}"
  end

  private

  def indent_source
    @source << ('  ' * @indentation)
  end

  # @return [Compiler]
  def reset(indentation = 0)
    @last_line = nil
    @source = +''
    @debug_info = {}
    @source_offset = 0
    # source code starts at 1 (as we then increment it when we encounter new lines)
    @source_line = 1
    @indentation = indentation
    @var_name_salt = 0

    self
  end
end

#sourceObject (readonly)

Returns the value of attribute source.



7
8
9
# File 'lib/twig/compiler.rb', line 7

def source
  @source
end

Instance Method Details

#add_debug_info(node) ⇒ Compiler

Parameters:

Returns:



99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/twig/compiler.rb', line 99

def add_debug_info(node)
  if node.lineno != @last_line
    write("# line #{node.lineno}\n")

    @source_line += @source[@source_offset..].count("\n")
    @source_offset = @source.length
    @debug_info[@source_line] = node.lineno

    @last_line = node.lineno
  end

  self
end

#compile(node, indentation = 0) ⇒ Compiler

Parameters:

  • node (Node::Base)
  • indentation (Integer) (defaults to: 0)

Returns:



21
22
23
24
25
26
# File 'lib/twig/compiler.rb', line 21

def compile(node, indentation = 0)
  reset(indentation)
  node.compile(self)

  self
end

#indent(step = 1) ⇒ Compiler

Parameters:

  • step (Integer) (defaults to: 1)

Returns:



115
116
117
118
119
# File 'lib/twig/compiler.rb', line 115

def indent(step = 1)
  @indentation += step

  self
end

#outdent(step = 1) ⇒ Compiler

Parameters:

  • step (Integer) (defaults to: 1)

Returns:



123
124
125
126
127
# File 'lib/twig/compiler.rb', line 123

def outdent(step = 1)
  @indentation -= step

  self
end

#raw(string) ⇒ Compiler

Parameters:

  • string (String)

Returns:



72
73
74
75
76
# File 'lib/twig/compiler.rb', line 72

def raw(string)
  @source << string

  self
end

#repr(value) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/twig/compiler.rb', line 78

def repr(value)
  case value
  when Integer, Float
    raw(value.to_s)
  when TrueClass, FalseClass
    raw(value ? 'true' : 'false')
  when NilClass
    raw('nil')
  when Array, Hash
    raw('Marshal.load(').
      raw(Marshal.dump(value).inspect).
      raw(')')
  when Symbol
    symbol(value)
  else
    string(value)
  end
end

#string(value) ⇒ Compiler

Parameters:

  • value (String)

Returns:



52
53
54
55
56
# File 'lib/twig/compiler.rb', line 52

def string(value)
  @source << "%q[#{value.to_s.gsub(/[\[\]\\]/, '[' => '\[', ']' => '\]', '\\' => '\\\\')}]"

  self
end

#subcompile(node, raw: true) ⇒ Compiler

Parameters:

  • node (Node::Base)
  • raw (Boolean) (defaults to: true)

Returns:



31
32
33
34
35
36
37
# File 'lib/twig/compiler.rb', line 31

def subcompile(node, raw: true)
  indent_source unless raw

  node.compile(self)

  self
end

#symbol(value) ⇒ Compiler

Parameters:

  • value (String, Symbol)

Returns:



60
61
62
63
64
65
66
67
68
# File 'lib/twig/compiler.rb', line 60

def symbol(value)
  @source << if value.is_a?(Symbol)
               value.inspect
             else
               "%q[#{value}].to_sym"
             end

  self
end

#var_nameString

Returns:

  • (String)


130
131
132
133
# File 'lib/twig/compiler.rb', line 130

def var_name
  @var_name_salt += 1
  "_v#{@var_name_salt}"
end

#write(*strings) ⇒ Compiler

Parameters:

  • strings (Array<String>)

Returns:



41
42
43
44
45
46
47
48
# File 'lib/twig/compiler.rb', line 41

def write(*strings)
  strings.each do |string|
    indent_source
    @source << string
  end

  self
end