kaiser-ruby 0.5.1 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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