Class: StarlarkCompiler::Writer

Inherits:
Object
  • Object
show all
Defined in:
lib/starlark_compiler/writer.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ast:, io:) ⇒ Writer

Returns a new instance of Writer.



17
18
19
20
21
# File 'lib/starlark_compiler/writer.rb', line 17

def initialize(ast:, io:)
  @ast = ast
  @io = io
  @indent = 0
end

Instance Attribute Details

#astObject

Returns the value of attribute ast.



15
16
17
# File 'lib/starlark_compiler/writer.rb', line 15

def ast
  @ast
end

#indentObject

Returns the value of attribute indent.



15
16
17
# File 'lib/starlark_compiler/writer.rb', line 15

def indent
  @indent
end

#ioObject

Returns the value of attribute io.



15
16
17
# File 'lib/starlark_compiler/writer.rb', line 15

def io
  @io
end

Class Method Details

.write(ast:, io: nil) ⇒ Object



5
6
7
8
9
10
11
# File 'lib/starlark_compiler/writer.rb', line 5

def self.write(ast:, io: nil)
  if io.nil?

  end

  new(ast: ast, io: io).write
end

Instance Method Details

#delegate(template, obj) ⇒ Object



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/starlark_compiler/writer.rb', line 58

def delegate(template, obj)
  snake_case = lambda do |str|
    return str.downcase if str =~ /^[A-Z_]+$/

    str.gsub(/\B[A-Z]/, '_\&').squeeze('_') =~ /_*(.*)/
    $+.downcase
  end
  cls = obj.class
  while cls && (cls != AST::Node)
    name = cls.name.split('::').last
    method = template % snake_case[name]
    return send(method, obj) if respond_to?(method)

    cls = cls.superclass
  end
  raise "No #{template} for #{obj.class}"
end

#indented(single_line:) ⇒ Object



191
192
193
194
195
196
197
# File 'lib/starlark_compiler/writer.rb', line 191

def indented(single_line:)
  should_indent = !single_line
  @indent += 1 if should_indent
  yield Indenter.new(self, should_indent)
ensure
  @indent -= 1 if should_indent
end

#single_line?(node) ⇒ Boolean

Returns:

  • (Boolean)


199
200
201
202
203
# File 'lib/starlark_compiler/writer.rb', line 199

def single_line?(node)
  return true unless node

  delegate('single_line_%s?', node)
end

#single_line_array?(array) ⇒ Boolean

Returns:

  • (Boolean)


227
228
229
230
# File 'lib/starlark_compiler/writer.rb', line 227

def single_line_array?(array)
  array.elements.size <= 1 &&
    array.elements.all?(&method(:single_line?))
end

#single_line_binary_operator?(operator) ⇒ Boolean

Returns:

  • (Boolean)


213
214
215
# File 'lib/starlark_compiler/writer.rb', line 213

def single_line_binary_operator?(operator)
  single_line?(operator.lhs) && single_line?(operator.rhs)
end

#single_line_dictionary?(dictionary) ⇒ Boolean

Returns:

  • (Boolean)


232
233
234
235
# File 'lib/starlark_compiler/writer.rb', line 232

def single_line_dictionary?(dictionary)
  dictionary.elements.size <= 1 &&
    dictionary.elements.each_key.all?(&method(:single_line?))
end

#single_line_function_call?(call) ⇒ Boolean

Returns:

  • (Boolean)


217
218
219
220
221
222
223
224
225
# File 'lib/starlark_compiler/writer.rb', line 217

def single_line_function_call?(call)
  if call.args.empty?
    call.kwargs.size <= 1 &&
      call.kwargs.each_value.all? { |v| single_line?(v) }
  elsif call.kwargs.empty?
    call.args.size <= 2 && call.args.all? { |v| single_line?(v) } ||
      (call.args.size == 1 && call.args.first.respond_to?(:elements))
  end
end

#single_line_number?(_) ⇒ Boolean

Returns:

  • (Boolean)


209
210
211
# File 'lib/starlark_compiler/writer.rb', line 209

def single_line_number?(_)
  true
end

#single_line_string?(str) ⇒ Boolean

Returns:

  • (Boolean)


205
206
207
# File 'lib/starlark_compiler/writer.rb', line 205

def single_line_string?(str)
  str.str.size <= 50
end

#single_line_variable_reference?(_) ⇒ Boolean

Returns:

  • (Boolean)


237
238
239
# File 'lib/starlark_compiler/writer.rb', line 237

def single_line_variable_reference?(_)
  true
end

#writeObject



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/starlark_compiler/writer.rb', line 23

def write
  case ast
  when AST
    ast.toplevel.each_with_index do |o, i|
      unless i.zero?
        write_newline
        write_newline unless o.is_a?(AST::FunctionCall) && o.name == 'load'
      end
      write_node(o)
    end
  when AST::Node
    write_node(ast)
  else
    raise Error, "Trying to write unknown object #{ast.inspect}"
  end
  write_newline
end

#write_array(array) ⇒ Object



130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/starlark_compiler/writer.rb', line 130

def write_array(array)
  single_line = single_line?(array)
  io << '['
  end_index = array.elements.size.pred
  array.elements.each_with_index do |node, i|
    indented(single_line: single_line) do |indenter|
      indenter.write_newline
      write_node(node)
      indenter.write_comma unless i == end_index && single_line
    end
  end
  write_newline unless single_line
  io << ']'
end

#write_binary_operator(operator) ⇒ Object



162
163
164
165
166
# File 'lib/starlark_compiler/writer.rb', line 162

def write_binary_operator(operator)
  write_node(operator.lhs)
  io << " #{operator.operator} "
  write_node(operator.rhs)
end

#write_dictionary(dictionary) ⇒ Object



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/starlark_compiler/writer.rb', line 145

def write_dictionary(dictionary)
  single_line = single_line?(dictionary)
  io << '{'
  end_index = dictionary.elements.size.pred
  dictionary.elements.each_with_index do |(key, value), i|
    indented(single_line: single_line) do |indenter|
      indenter.write_newline
      write_node(key)
      io << ': '
      write_node(value)
      indenter.write_comma unless i == end_index && single_line
    end
  end
  write_newline unless single_line
  io << '}'
end

#write_false(_none) ⇒ Object



176
177
178
# File 'lib/starlark_compiler/writer.rb', line 176

def write_false(_none)
  io << 'False'
end

#write_function_call(call) ⇒ Object



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/starlark_compiler/writer.rb', line 76

def write_function_call(call)
  single_line = single_line?(call)
  io << call.name << '('
  final_index = single_line && call.kwargs.empty? && call.args.size.pred
  call.args.each_with_index do |arg, idx|
    indented(single_line: single_line) do |indenter|
      indenter.write_newline
      write_node(arg)
      indenter.write_comma unless final_index == idx
    end
  end
  final_index = single_line && call.kwargs.size.pred
  call.kwargs.each_with_index do |(k, v), idx|
    indented(single_line: single_line) do |indenter|
      indenter.write_newline
      io << "#{k} = "
      write_node(v)
      indenter.write_comma unless final_index == idx
    end
  end
  write_newline unless single_line
  io << ')'
end

#write_function_declaration(declaration) ⇒ Object



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/starlark_compiler/writer.rb', line 100

def write_function_declaration(declaration)
  io << 'def ' << declaration.name << '('
  final_index = declaration.args.size.pred
  declaration.args.each_with_index do |arg, idx|
    indented(single_line: false) do |indenter|
      indenter.write_newline
      write_node(arg)
      indenter.write_comma unless final_index == idx
    end
  end
  write_newline
  io << '):'
  final_index = declaration.body.size.pred
  declaration.body.each do |arg|
    indented(single_line: false) do |indenter|
      indenter.write_newline
      write_node(arg)
    end
  end
end

#write_newlineObject



45
46
47
48
# File 'lib/starlark_compiler/writer.rb', line 45

def write_newline
  io << "\n"
  io << '    ' * indent
end

#write_node(node) ⇒ Object



41
42
43
# File 'lib/starlark_compiler/writer.rb', line 41

def write_node(node)
  delegate('write_%s', node)
end

#write_none(_none) ⇒ Object



168
169
170
# File 'lib/starlark_compiler/writer.rb', line 168

def write_none(_none)
  io << 'None'
end

#write_number(number) ⇒ Object



54
55
56
# File 'lib/starlark_compiler/writer.rb', line 54

def write_number(number)
  io << number.number.to_s
end

#write_string(str) ⇒ Object



50
51
52
# File 'lib/starlark_compiler/writer.rb', line 50

def write_string(str)
  io << str.str.inspect
end

#write_true(_none) ⇒ Object



172
173
174
# File 'lib/starlark_compiler/writer.rb', line 172

def write_true(_none)
  io << 'True'
end

#write_variable_assignment(assignment) ⇒ Object



125
126
127
128
# File 'lib/starlark_compiler/writer.rb', line 125

def write_variable_assignment(assignment)
  io << assignment.name << ' = '
  write_node(assignment.var)
end

#write_variable_reference(variable) ⇒ Object



121
122
123
# File 'lib/starlark_compiler/writer.rb', line 121

def write_variable_reference(variable)
  io << variable.var
end