Class: KaiserRuby::Transformer
- Inherits:
-
Object
- Object
- KaiserRuby::Transformer
show all
- Defined in:
- lib/kaiser_ruby/transformer.rb
Overview
taking the intermediate tree output of parsing, output Ruby code
Instance Attribute Summary collapse
Instance Method Summary
collapse
Constructor Details
Returns a new instance of Transformer.
8
9
10
11
12
13
14
15
16
17
18
|
# File 'lib/kaiser_ruby/transformer.rb', line 8
def initialize(tree)
@parsed_tree = tree
@output = []
@method_names = []
@global_variables = []
@nested_functions = {}
@nesting = 0
@indentation = ''
@lnum = 0
@current_scope = [nil]
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(rule, *args, &_block) ⇒ Object
63
64
65
|
# File 'lib/kaiser_ruby/transformer.rb', line 63
def method_missing(rule, *args, &_block)
raise ArgumentError, "missing Transform rule: #{rule}, #{args}"
end
|
Instance Attribute Details
#output ⇒ Object
Returns the value of attribute output.
6
7
8
|
# File 'lib/kaiser_ruby/transformer.rb', line 6
def output
@output
end
|
#parsed_tree ⇒ Object
Returns the value of attribute parsed_tree.
6
7
8
|
# File 'lib/kaiser_ruby/transformer.rb', line 6
def parsed_tree
@parsed_tree
end
|
Instance Method Details
272
273
274
275
276
277
278
279
280
|
# File 'lib/kaiser_ruby/transformer.rb', line 272
def additional_argument_transformation(argument)
arg = @method_names.include?(argument) ? "defined?(#{argument})" : argument
arg = "#{arg}.to_bool" if arg !~ /==|>|>=|<|<=|!=/
arg
end
|
#filter_string(string, rxp: /[[:alpha:]]/) ⇒ Object
402
403
404
|
# File 'lib/kaiser_ruby/transformer.rb', line 402
def filter_string(string, rxp: /[[:alpha:]]/)
string.to_s.split(/\s+/).map { |e| e.chars.select { |c| c =~ rxp }.join }.reject(&:empty?)
end
|
#normalize_num(num) ⇒ Object
406
407
408
|
# File 'lib/kaiser_ruby/transformer.rb', line 406
def normalize_num(num)
num.modulo(1).zero? ? num.to_i : num
end
|
58
59
60
61
|
# File 'lib/kaiser_ruby/transformer.rb', line 58
def select_transformer(object)
key = object.keys.first
send("transform_#{key}", object)
end
|
#str_to_num(string) ⇒ Object
398
399
400
|
# File 'lib/kaiser_ruby/transformer.rb', line 398
def str_to_num(string)
filter_string(string).map { |e| e.length % 10 }.join
end
|
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
|
# File 'lib/kaiser_ruby/transformer.rb', line 20
def transform
@last_variable = nil @else_already = nil
@parsed_tree.each do |line_object|
next unless line_object[:current_scope].nil?
line_object.extend(Hashie::Extensions::DeepLocate)
line_object.deep_locate(:variable_name).each do |vname_obj|
@global_variables.push vname_obj.dig(:variable_name)
end
end
@global_variables = @global_variables.compact.uniq
@parsed_tree.each_with_index do |line_object, lnum|
@current_scope.push(line_object[:current_scope]) unless @current_scope.last == line_object[:current_scope]
@lnum = lnum
transformed_line = select_transformer(line_object)
@nesting = line_object[:nesting] || 0
actual_nesting = line_object.key?(:else) ? @nesting - 1 : @nesting
@indentation = ' ' * actual_nesting
@output << @indentation + transformed_line
end
while @nesting.positive?
@nesting -= 1
@indentation = ' ' * @nesting
@output << @indentation + 'end'
end
@output << '' if @output.size > 1
@output.join("\n")
end
|
146
147
148
149
150
151
|
# File 'lib/kaiser_ruby/transformer.rb', line 146
def transform_addition(object)
left = select_transformer(object[:addition][:left])
right = select_transformer(object[:addition][:right])
"#{left} + #{right}"
end
|
369
370
371
372
373
374
|
# File 'lib/kaiser_ruby/transformer.rb', line 369
def transform_and(object)
left = select_transformer(object[:and][:left])
right = select_transformer(object[:and][:right])
"#{left} && #{right}"
end
|
137
138
139
140
141
142
143
144
|
# File 'lib/kaiser_ruby/transformer.rb', line 137
def transform_argument_list(object)
list = []
object[:argument_list].each do |arg|
list << select_transformer(arg)
end
list.join(', ')
end
|
174
175
176
177
178
179
180
|
# File 'lib/kaiser_ruby/transformer.rb', line 174
def transform_assignment(object)
left = select_transformer(object[:assignment][:left])
right = select_transformer(object[:assignment][:right])
@last_variable = left
"#{left} = #{right}"
end
|
95
96
97
98
99
|
# File 'lib/kaiser_ruby/transformer.rb', line 95
def transform_break(object)
raise KaiserRuby::RockstarSyntaxError, 'Break used outside of a loop' if object[:nesting].to_i.zero?
'break'
end
|
89
90
91
92
93
|
# File 'lib/kaiser_ruby/transformer.rb', line 89
def transform_continue(object)
raise KaiserRuby::RockstarSyntaxError, 'Continue used outside of a loop' if object[:nesting].to_i.zero?
'next'
end
|
182
183
184
185
186
187
|
# File 'lib/kaiser_ruby/transformer.rb', line 182
def transform_decrement(object)
argument = select_transformer(object[:decrement])
amount = object.dig(:decrement, :amount)
"#{argument} -= #{amount}"
end
|
167
168
169
170
171
172
|
# File 'lib/kaiser_ruby/transformer.rb', line 167
def transform_division(object)
left = select_transformer(object[:division][:left])
right = select_transformer(object[:division][:right])
"#{left} / #{right}"
end
|
289
290
291
292
293
294
295
296
|
# File 'lib/kaiser_ruby/transformer.rb', line 289
def transform_else(object)
raise KaiserRuby::RockstarSyntaxError, 'Else outside an if block' if object[:nesting].to_i.zero?
raise KaiserRuby::RockstarSyntaxError, 'Double else inside if block' if !@else_already.nil? && object[:nesting_start_line] == @else_already
@else_already = object[:nesting_start_line]
'else'
end
|
261
262
263
264
265
266
267
268
269
270
|
# File 'lib/kaiser_ruby/transformer.rb', line 261
def transform_empty_line(_object)
if @nesting.zero?
''
elsif @nesting == 1
"end\n"
else
@else_already = nil
"end\n"
end
end
|
312
313
314
315
316
317
|
# File 'lib/kaiser_ruby/transformer.rb', line 312
def transform_equality(object)
left = select_transformer(object[:equality][:left])
right = select_transformer(object[:equality][:right])
"#{left} == #{right}"
end
|
354
355
356
357
358
359
360
361
362
363
364
365
366
367
|
# File 'lib/kaiser_ruby/transformer.rb', line 354
def transform_function(object)
funcname = transform_function_name(object[:function][:name])
argument = select_transformer(object[:function][:argument])
if @current_scope.last.nil?
@method_names << funcname
"def #{funcname}(#{argument})"
else
@nested_functions[@current_scope.last] ||= []
@nested_functions[@current_scope.last].push funcname
"#{funcname} = ->(#{argument}) do"
end
end
|
196
197
198
199
200
201
202
203
204
205
|
# File 'lib/kaiser_ruby/transformer.rb', line 196
def transform_function_call(object)
func_name = select_transformer(object[:function_call][:left])
argument = select_transformer(object[:function_call][:right])
if @nested_functions[@current_scope.last]&.include?(func_name)
"#{func_name}.call(#{argument})"
else
"#{func_name}(#{argument})"
end
end
|
121
122
123
|
# File 'lib/kaiser_ruby/transformer.rb', line 121
def transform_function_name(object)
object[:function_name]
end
|
326
327
328
329
330
331
|
# File 'lib/kaiser_ruby/transformer.rb', line 326
def transform_gt(object)
left = select_transformer(object[:gt][:left])
right = select_transformer(object[:gt][:right])
"#{left} > #{right}"
end
|
333
334
335
336
337
338
|
# File 'lib/kaiser_ruby/transformer.rb', line 333
def transform_gte(object)
left = select_transformer(object[:gte][:left])
right = select_transformer(object[:gte][:right])
"#{left} >= #{right}"
end
|
282
283
284
285
286
287
|
# File 'lib/kaiser_ruby/transformer.rb', line 282
def transform_if(object)
argument = select_transformer(object[:if][:argument])
argument = additional_argument_transformation(argument)
"if #{argument}"
end
|
189
190
191
192
193
194
|
# File 'lib/kaiser_ruby/transformer.rb', line 189
def transform_increment(object)
argument = select_transformer(object[:increment])
amount = object.dig(:increment, :amount)
"#{argument} += #{amount}"
end
|
319
320
321
322
323
324
|
# File 'lib/kaiser_ruby/transformer.rb', line 319
def transform_inequality(object)
left = select_transformer(object[:inequality][:left])
right = select_transformer(object[:inequality][:right])
"#{left} != #{right}"
end
|
78
79
80
|
# File 'lib/kaiser_ruby/transformer.rb', line 78
def transform_listen(_object)
"print '> '\n$stdin.gets.chomp"
end
|
73
74
75
76
|
# File 'lib/kaiser_ruby/transformer.rb', line 73
def transform_listen_to(object)
var = select_transformer(object[:listen_to])
"print '> '\n__input = $stdin.gets.chomp\n#{var} = Float(__input) rescue __input"
end
|
117
118
119
|
# File 'lib/kaiser_ruby/transformer.rb', line 117
def transform_local_variable_name(object)
object[:local_variable_name]
end
|
340
341
342
343
344
345
|
# File 'lib/kaiser_ruby/transformer.rb', line 340
def transform_lt(object)
left = select_transformer(object[:lt][:left])
right = select_transformer(object[:lt][:right])
"#{left} < #{right}"
end
|
347
348
349
350
351
352
|
# File 'lib/kaiser_ruby/transformer.rb', line 347
def transform_lte(object)
left = select_transformer(object[:lte][:left])
right = select_transformer(object[:lte][:right])
"#{left} <= #{right}"
end
|
153
154
155
156
157
158
|
# File 'lib/kaiser_ruby/transformer.rb', line 153
def transform_multiplication(object)
left = select_transformer(object[:multiplication][:left])
right = select_transformer(object[:multiplication][:right])
"#{left} * #{right}"
end
|
389
390
391
392
393
394
|
# File 'lib/kaiser_ruby/transformer.rb', line 389
def transform_nor(object)
left = select_transformer(object[:nor][:left])
right = select_transformer(object[:nor][:right])
"!(#{left} || #{right})"
end
|
376
377
378
379
380
|
# File 'lib/kaiser_ruby/transformer.rb', line 376
def transform_not(object)
arg = select_transformer(object[:not])
"!#{arg}"
end
|
133
134
135
|
# File 'lib/kaiser_ruby/transformer.rb', line 133
def transform_number(object)
normalize_num(object[:number])
end
|
235
236
237
238
239
240
241
242
243
244
245
246
|
# File 'lib/kaiser_ruby/transformer.rb', line 235
def transform_number_literal(object)
string = object[:number_literal]
out = if string.include?('.')
string.split('.', 2).map do |sub|
str_to_num(sub.strip)
end.join('.').to_f
else
str_to_num(string).to_f
end
normalize_num(out)
end
|
382
383
384
385
386
387
|
# File 'lib/kaiser_ruby/transformer.rb', line 382
def transform_or(object)
left = select_transformer(object[:or][:left])
right = select_transformer(object[:or][:right])
"#{left} || #{right}"
end
|
207
208
209
|
# File 'lib/kaiser_ruby/transformer.rb', line 207
def transform_passed_function_call(object)
transform_function_call(object[:passed_function_call])
end
|
227
228
229
230
231
232
233
|
# File 'lib/kaiser_ruby/transformer.rb', line 227
def transform_poetic_number(object)
var = select_transformer(object[:poetic_number][:left])
value = select_transformer(object[:poetic_number][:right])
@last_variable = var
"#{var} = #{value}"
end
|
211
212
213
214
215
216
217
|
# File 'lib/kaiser_ruby/transformer.rb', line 211
def transform_poetic_string(object)
var = select_transformer(object[:poetic_string][:left])
value = select_transformer(object[:poetic_string][:right])
@last_variable = var
"#{var} = #{value}"
end
|
219
220
221
222
223
224
225
|
# File 'lib/kaiser_ruby/transformer.rb', line 219
def transform_poetic_type(object)
var = select_transformer(object[:poetic_type][:left])
value = select_transformer(object[:poetic_type][:right])
@last_variable = var
"#{var} = #{value}"
end
|
67
68
69
70
71
|
# File 'lib/kaiser_ruby/transformer.rb', line 67
def transform_print(object)
var = select_transformer(object[:print])
"puts (#{var}).to_s"
end
|
125
126
127
|
# File 'lib/kaiser_ruby/transformer.rb', line 125
def transform_pronoun(_object)
@last_variable
end
|
82
83
84
85
86
87
|
# File 'lib/kaiser_ruby/transformer.rb', line 82
def transform_return(object)
raise KaiserRuby::RockstarSyntaxError, 'Return used outside of a function' if object[:nesting].to_i.zero?
var = select_transformer(object[:return])
"return #{var}"
end
|
129
130
131
|
# File 'lib/kaiser_ruby/transformer.rb', line 129
def transform_string(object)
object[:string]
end
|
160
161
162
163
164
165
|
# File 'lib/kaiser_ruby/transformer.rb', line 160
def transform_subtraction(object)
left = select_transformer(object[:subtraction][:left])
right = select_transformer(object[:subtraction][:right])
"#{left} - #{right}"
end
|
248
249
250
251
252
253
254
255
256
257
258
259
|
# File 'lib/kaiser_ruby/transformer.rb', line 248
def transform_type(object)
case object[:type]
when 'mysterious'
'KaiserRuby::Mysterious.new'
when 'null'
'nil'
when 'true'
'true'
when 'false'
'false'
end
end
|
305
306
307
308
309
310
|
# File 'lib/kaiser_ruby/transformer.rb', line 305
def transform_until(object)
argument = select_transformer(object[:until][:argument])
argument = additional_argument_transformation(argument)
"until #{argument}"
end
|
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
# File 'lib/kaiser_ruby/transformer.rb', line 101
def transform_variable_name(object)
varname = object[:variable_name]
if object[:type] == :assignment
varname = "@#{varname}" if @global_variables&.include?(varname)
elsif @global_variables.include?(varname)
varname = @method_names.include?(varname) ? varname : "@#{varname}"
end
varname
end
|
298
299
300
301
302
303
|
# File 'lib/kaiser_ruby/transformer.rb', line 298
def transform_while(object)
argument = select_transformer(object[:while][:argument])
argument = additional_argument_transformation(argument)
"while #{argument}"
end
|