kaiser-ruby 0.5.1 → 0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,200 @@
1
+ module KaiserRuby
2
+ module Refinements
3
+ refine NilClass do
4
+ def to_bool
5
+ false
6
+ end
7
+
8
+ def +(other)
9
+ 'mysterious' + other if other.is_a?(String)
10
+ end
11
+
12
+ def -(other)
13
+ 'mysterious' + other if other.is_a?(String)
14
+ end
15
+
16
+ def to_s
17
+ 'mysterious'
18
+ end
19
+ end
20
+
21
+ refine Float do
22
+ alias_method :old_add, :+
23
+ alias_method :old_mul, :*
24
+ alias_method :old_div, :/
25
+ alias_method :old_gt, :<
26
+ alias_method :old_gte, :<=
27
+ alias_method :old_lt, :>
28
+ alias_method :old_lte, :>=
29
+ alias_method :old_eq, :==
30
+
31
+ def to_bool
32
+ self.zero? ? false : true
33
+ end
34
+
35
+ def +(other)
36
+ other.is_a?(String) ? self.to_s + other : self.old_add(other)
37
+ end
38
+
39
+ def *(other)
40
+ other.is_a?(String) ? other * self : self.old_mul(other)
41
+ end
42
+
43
+ def /(other)
44
+ raise ZeroDivisionError if other.zero?
45
+ self.old_div(other)
46
+ end
47
+
48
+ def <(other)
49
+ other.is_a?(String) ? self < Float(other) : self.old_gt(other)
50
+ end
51
+
52
+ def <=(other)
53
+ other.is_a?(String) ? self <= Float(other) : self.old_gte(other)
54
+ end
55
+
56
+ def >(other)
57
+ other.is_a?(String) ? self > Float(other) : self.old_lt(other)
58
+ end
59
+
60
+ def >=(other)
61
+ other.is_a?(String) ? self >= Float(other) : self.old_lte(other)
62
+ end
63
+
64
+ def ==(other)
65
+ if other.is_a?(TrueClass) || other.is_a?(FalseClass)
66
+ self.to_bool == other
67
+ elsif other.is_a?(String)
68
+ t = Float(other) rescue other
69
+ self.old_eq(t)
70
+ else
71
+ self.old_eq(other)
72
+ end
73
+ end
74
+ end
75
+
76
+ refine String do
77
+ alias_method :old_add, :+
78
+ alias_method :old_gt, :<
79
+ alias_method :old_gte, :<=
80
+ alias_method :old_lt, :>
81
+ alias_method :old_lte, :>=
82
+ alias_method :old_eq, :==
83
+
84
+ def to_bool
85
+ self.size == 0 ? false : true
86
+ end
87
+
88
+ def __booleanize
89
+ if self =~ /\A\bfalse\b|\bno\b|\blies\b|\bwrong\b\Z/i
90
+ return false
91
+ elsif self =~ /\A\btrue\b|\byes\b|\bok\b|\bright\b\Z/i
92
+ return true
93
+ end
94
+
95
+ return self
96
+ end
97
+
98
+ def +(other)
99
+ other.is_a?(String) ? self.old_add(other) : self + other.to_s
100
+ end
101
+
102
+ def <(other)
103
+ other.is_a?(Float) ? Float(self) < other : self.old_gt(other)
104
+ end
105
+
106
+ def <=(other)
107
+ other.is_a?(Float) ? Float(self) <= other : self.old_gte(other)
108
+ end
109
+
110
+ def >(other)
111
+ other.is_a?(Float) ? Float(self) > other : self.old_lt(other)
112
+ end
113
+
114
+ def >=(other)
115
+ other.is_a?(Float) ? Float(self) >= other : self.old_lte(other)
116
+ end
117
+
118
+ def ==(other)
119
+ if other.is_a?(TrueClass) || other.is_a?(FalseClass)
120
+ self.__booleanize == other
121
+ elsif other.is_a?(Float)
122
+ t = Float(self) rescue self
123
+ t == other
124
+ else
125
+ self.old_eq(other)
126
+ end
127
+ end
128
+ end
129
+
130
+ refine TrueClass do
131
+ alias_method :old_eq, :==
132
+
133
+ def to_bool
134
+ true
135
+ end
136
+
137
+ def +(other)
138
+ return 'true' + other if other.is_a?(String)
139
+ other.even? ? self : !self
140
+ end
141
+
142
+ def -(other)
143
+ other.even? ? self : !self
144
+ end
145
+
146
+ def ==(other)
147
+ if other.is_a?(Float)
148
+ self == other.to_bool
149
+ elsif other.is_a?(String)
150
+ self.old_eq(other.__booleanize)
151
+ else
152
+ self.old_eq(other)
153
+ end
154
+ end
155
+ end
156
+
157
+ refine FalseClass do
158
+ alias_method :old_eq, :==
159
+
160
+ def to_bool
161
+ false
162
+ end
163
+
164
+ def +(other)
165
+ return 'false' + other if other.is_a?(String)
166
+ other.even? ? self : !self
167
+ end
168
+
169
+ def -(other)
170
+ other.even? ? self : !self
171
+ end
172
+
173
+ def ==(other)
174
+ if other.is_a?(Float)
175
+ self == other.to_bool
176
+ elsif other.is_a?(String)
177
+ self.old_eq(other.__booleanize)
178
+ else
179
+ self.old_eq(other)
180
+ end
181
+ end
182
+ end
183
+
184
+ refine BasicObject do
185
+ alias_method :old_not, :!
186
+
187
+ def !
188
+ if self.is_a?(String)
189
+ return self.size == 0 ? true : false
190
+ elsif self.is_a?(Float)
191
+ return self.zero? ? true : false
192
+ elsif self.is_a?(NilClass)
193
+ return true
194
+ else
195
+ self.old_not
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,358 @@
1
+ module KaiserRuby
2
+ class Transformer
3
+ attr_reader :parsed_tree, :output
4
+
5
+ def initialize(tree)
6
+ @parsed_tree = tree
7
+ @output = []
8
+ @method_names = []
9
+ @nesting = 0
10
+ @indentation = ''
11
+ @lnum = 0
12
+ end
13
+
14
+ def transform
15
+ @last_variable = nil # name of last used variable for pronouns
16
+ @else_already = nil # line number of a current if block, so we can avoid double else
17
+ @local_variables = [] # locally defined variable names in current function block
18
+
19
+ @parsed_tree.each_with_index do |line_object, lnum|
20
+ @lnum = lnum
21
+ transformed_line = select_transformer(line_object)
22
+ if line_object[:nesting]
23
+ @nesting = line_object[:nesting]
24
+ else
25
+ @nesting = 0
26
+ end
27
+
28
+ @indentation = ' ' * @nesting
29
+ @output << @indentation + transformed_line
30
+ end
31
+
32
+ # at end of file, close all the blocks that are still started
33
+ while @nesting > 0
34
+ @nesting -= 1
35
+ @indentation = ' ' * @nesting
36
+ @output << @indentation + "end"
37
+ end
38
+
39
+ @output << '' if @output.size > 1
40
+ @output.join("\n")
41
+ end
42
+
43
+ def select_transformer(object)
44
+ key = object.keys.first
45
+ send("transform_#{key}", object)
46
+ end
47
+
48
+ def method_missing(m, *args, &block)
49
+ raise ArgumentError, "missing Transform rule: #{m}, #{args}"
50
+ end
51
+
52
+ # transform language tree into Ruby
53
+
54
+ def transform_print(object)
55
+ var = select_transformer(object[:print])
56
+ "puts #{var}"
57
+ end
58
+
59
+ def transform_listen_to(object)
60
+ var = select_transformer(object[:listen_to])
61
+ "print '> '\n__input = $stdin.gets.chomp\n#{var} = Float(__input) rescue __input"
62
+ end
63
+
64
+ def transform_listen(_object)
65
+ "print '> '\n$stdin.gets.chomp"
66
+ end
67
+
68
+ def transform_return(object)
69
+ raise KaiserRuby::RockstarSyntaxError, "Return used outside of a function" if object[:nesting].to_i.zero?
70
+ var = select_transformer(object[:return])
71
+ "return #{var}"
72
+ end
73
+
74
+ def transform_continue(object)
75
+ raise KaiserRuby::RockstarSyntaxError, "Continue used outside of a loop" if object[:nesting].to_i.zero?
76
+ "next"
77
+ end
78
+
79
+ def transform_break(object)
80
+ raise KaiserRuby::RockstarSyntaxError, "Break used outside of a loop" if object[:nesting].to_i.zero?
81
+ "break"
82
+ end
83
+
84
+ def transform_variable_name(object)
85
+ varname = object[:variable_name]
86
+ if object[:type] == :assignment
87
+ if @local_variables.empty?
88
+ varname = "@#{varname}"
89
+ else
90
+ @local_variables << varname
91
+ end
92
+ else
93
+ unless @local_variables.include?(varname)
94
+ varname = @method_names.include?(varname) ? varname : "@#{varname}"
95
+ end
96
+ end
97
+
98
+ @last_variable = varname
99
+ varname
100
+ end
101
+
102
+ def transform_local_variable_name(object)
103
+ object[:local_variable_name]
104
+ end
105
+
106
+ def transform_function_name(object)
107
+ object[:function_name]
108
+ end
109
+
110
+ def transform_pronoun(_object)
111
+ @last_variable
112
+ end
113
+
114
+ def transform_string(object)
115
+ object[:string]
116
+ end
117
+
118
+ def transform_number(object)
119
+ object[:number]
120
+ end
121
+
122
+ def transform_argument_list(object)
123
+ list = []
124
+ object[:argument_list].each do |arg|
125
+ list << select_transformer(arg)
126
+ end
127
+
128
+ list.join(', ')
129
+ end
130
+
131
+ def transform_addition(object)
132
+ left = select_transformer(object[:addition][:left])
133
+ right = select_transformer(object[:addition][:right])
134
+ "#{left} + #{right}"
135
+ end
136
+
137
+ def transform_multiplication(object)
138
+ left = select_transformer(object[:multiplication][:left])
139
+ right = select_transformer(object[:multiplication][:right])
140
+ "#{left} * #{right}"
141
+ end
142
+
143
+ def transform_subtraction(object)
144
+ left = select_transformer(object[:subtraction][:left])
145
+ right = select_transformer(object[:subtraction][:right])
146
+ "#{left} - #{right}"
147
+ end
148
+
149
+ def transform_division(object)
150
+ left = select_transformer(object[:division][:left])
151
+ right = select_transformer(object[:division][:right])
152
+ "#{left} / #{right}"
153
+ end
154
+
155
+ def transform_assignment(object)
156
+ left = select_transformer(object[:assignment][:left])
157
+ right = select_transformer(object[:assignment][:right])
158
+ "#{left} = #{right}"
159
+ end
160
+
161
+ def transform_decrement(object)
162
+ argument = select_transformer(object[:decrement])
163
+ amount = object.dig(:decrement, :amount)
164
+ "#{argument} -= #{amount}"
165
+ end
166
+
167
+ def transform_increment(object)
168
+ argument = select_transformer(object[:increment])
169
+ amount = object.dig(:increment, :amount)
170
+ "#{argument} += #{amount}"
171
+ end
172
+
173
+ def transform_function_call(object)
174
+ func_name = select_transformer(object[:function_call][:left])
175
+ argument = select_transformer(object[:function_call][:right])
176
+
177
+ "#{func_name}(#{argument})"
178
+ end
179
+
180
+ def transform_passed_function_call(object)
181
+ return transform_function_call(object[:passed_function_call])
182
+ end
183
+
184
+ def transform_poetic_string(object)
185
+ var = select_transformer(object[:poetic_string][:left])
186
+ value = select_transformer(object[:poetic_string][:right])
187
+
188
+ "#{var} = #{value}"
189
+ end
190
+
191
+ def transform_poetic_type(object)
192
+ var = select_transformer(object[:poetic_type][:left])
193
+ value = select_transformer(object[:poetic_type][:right])
194
+ "#{var} = #{value}"
195
+ end
196
+
197
+ def transform_poetic_number(object)
198
+ var = select_transformer(object[:poetic_number][:left])
199
+ value = select_transformer(object[:poetic_number][:right])
200
+ "#{var} = #{value}"
201
+ end
202
+
203
+ def transform_number_literal(object)
204
+ string = object[:number_literal]
205
+ if string.include?('.')
206
+ string.split('.', 2).map do |sub|
207
+ str_to_num(sub.strip)
208
+ end.join('.').to_f
209
+ else
210
+ str_to_num(string).to_f
211
+ end
212
+ end
213
+
214
+ def transform_type(object)
215
+ case object[:type]
216
+ when "nil"
217
+ 'nil'
218
+ when "null"
219
+ '0.0'
220
+ when "true"
221
+ 'true'
222
+ when "false"
223
+ 'false'
224
+ end
225
+ end
226
+
227
+ def transform_empty_line(_object)
228
+ if @nesting == 0
229
+ return ""
230
+ elsif @nesting == 1
231
+ @local_variables = []
232
+ return "end\n"
233
+ else
234
+ @else_already = nil
235
+ return "end\n"
236
+ end
237
+ end
238
+
239
+ def additional_argument_transformation(argument)
240
+ # testing function existence
241
+ arg = @method_names.include?(argument) ? "defined?(#{argument})" : argument
242
+
243
+ # single variable without any operator needs to return a refined boolean
244
+ arg = "#{arg}.to_bool" if arg !~ /==|>|>=|<|<=|!=/
245
+
246
+ return arg
247
+ end
248
+
249
+ def transform_if(object)
250
+ argument = select_transformer(object[:if][:argument])
251
+ argument = additional_argument_transformation(argument)
252
+ "if #{argument}"
253
+ end
254
+
255
+ def transform_else(object)
256
+ raise KaiserRuby::RockstarSyntaxError, "Else outside an if block" if object[:nesting].to_i.zero?
257
+ raise KaiserRuby::RockstarSyntaxError, "Double else inside if block" if @else_already != nil && object[:nesting_start_line] == @else_already
258
+
259
+ @else_already = object[:nesting_start_line]
260
+ "else"
261
+ end
262
+
263
+ def transform_while(object)
264
+ argument = select_transformer(object[:while][:argument])
265
+ argument = additional_argument_transformation(argument)
266
+ "while #{argument}"
267
+ end
268
+
269
+ def transform_until(object)
270
+ argument = select_transformer(object[:until][:argument])
271
+ argument = additional_argument_transformation(argument)
272
+ "until #{argument}"
273
+ end
274
+
275
+ def transform_equality(object)
276
+ left = select_transformer(object[:equality][:left])
277
+ right = select_transformer(object[:equality][:right])
278
+ "#{left} == #{right}"
279
+ end
280
+
281
+ def transform_inequality(object)
282
+ left = select_transformer(object[:inequality][:left])
283
+ right = select_transformer(object[:inequality][:right])
284
+ "#{left} != #{right}"
285
+ end
286
+
287
+ def transform_gt(object)
288
+ left = select_transformer(object[:gt][:left])
289
+ right = select_transformer(object[:gt][:right])
290
+ "#{left} > #{right}"
291
+ end
292
+
293
+ def transform_gte(object)
294
+ left = select_transformer(object[:gte][:left])
295
+ right = select_transformer(object[:gte][:right])
296
+ "#{left} >= #{right}"
297
+ end
298
+
299
+ def transform_lt(object)
300
+ left = select_transformer(object[:lt][:left])
301
+ right = select_transformer(object[:lt][:right])
302
+ "#{left} < #{right}"
303
+ end
304
+
305
+ def transform_lte(object)
306
+ left = select_transformer(object[:lte][:left])
307
+ right = select_transformer(object[:lte][:right])
308
+ "#{left} <= #{right}"
309
+ end
310
+
311
+ def transform_function(object)
312
+ funcname = transform_function_name(object[:function][:name])
313
+ argument = select_transformer(object[:function][:argument])
314
+
315
+ # save method name and make local variables out of the function arguments
316
+ @method_names << funcname
317
+ @local_variables = argument.split(', ')
318
+
319
+ "def #{funcname}(#{argument})"
320
+ end
321
+
322
+ def transform_and(object)
323
+ left = select_transformer(object[:and][:left])
324
+ right = select_transformer(object[:and][:right])
325
+
326
+ "#{left} && #{right}"
327
+ end
328
+
329
+ def transform_not(object)
330
+ arg = select_transformer(object[:not])
331
+ "!#{arg}"
332
+ end
333
+
334
+ def transform_or(object)
335
+ left = select_transformer(object[:or][:left])
336
+ right = select_transformer(object[:or][:right])
337
+
338
+ "#{left} || #{right}"
339
+ end
340
+
341
+ def transform_nor(object)
342
+ left = select_transformer(object[:nor][:left])
343
+ right = select_transformer(object[:nor][:right])
344
+
345
+ "!(#{left} || #{right})"
346
+ end
347
+
348
+ # private
349
+
350
+ def str_to_num(string)
351
+ filter_string(string).map { |e| e.length % 10 }.join
352
+ end
353
+
354
+ def filter_string(string, rxp: /[[:alpha:]]/)
355
+ string.to_s.split(/\s+/).map { |e| e.chars.select { |c| c =~ rxp }.join }.reject { |a| a.empty? }
356
+ end
357
+ end
358
+ end