Class: Mulang::Ruby::AstProcessor

Inherits:
AST::Processor
  • Object
show all
Includes:
AST::Sexp, Sexp
Defined in:
lib/mulang/ruby/ast_processor.rb

Instance Method Summary collapse

Methods included from Sexp

#mnil

Constructor Details

#initializeAstProcessor

Returns a new instance of AstProcessor.



6
7
8
# File 'lib/mulang/ruby/ast_processor.rb', line 6

def initialize
  @contexts = []
end

Instance Method Details

#_Object



68
69
70
# File 'lib/mulang/ruby/ast_processor.rb', line 68

def _
  Object.new.tap { |it| it.define_singleton_method(:==) { |_| true } }
end

#handle_send_with_args(node, extra_args = []) ⇒ Object



311
312
313
314
315
316
# File 'lib/mulang/ruby/ast_processor.rb', line 311

def handle_send_with_args(node, extra_args=[])
  receptor, message, *args = *node
  receptor ||= s(:self)

  ms :Send, process(receptor), message_reference(message), (process_all(args) + extra_args)
end

#handler_missing(*args) ⇒ Object



307
308
309
# File 'lib/mulang/ruby/ast_processor.rb', line 307

def handler_missing(*args)
  ms :Other, args.to_s, nil
end

#message_reference(message) ⇒ Object



318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/mulang/ruby/ast_processor.rb', line 318

def message_reference(message)
  case message
    when :==     then primitive :Equal
    when :!=     then primitive :NotEqual
    when :!      then primitive :Negation
    when :'&&'   then primitive :And
    when :'||'   then primitive :Or
    when :hash   then primitive :Hash
    when :>=     then primitive :GreaterOrEqualThan
    when :>      then primitive :GreaterThan
    when :<=     then primitive :LessOrEqualThan
    when :<      then primitive :LessThan
    when :+      then primitive :Plus
    when :-      then primitive :Minus
    when :*      then primitive :Multiply
    when :/      then primitive :Divide
    when :length then primitive :Size
    when :size   then primitive :Size
    else ms :Reference, message
  end
end

#on_and(node) ⇒ Object



126
127
128
129
130
# File 'lib/mulang/ruby/ast_processor.rb', line 126

def on_and(node)
  value, other = *node

  simple_send process(value), '&&', [process(other)]
end

#on_and_asgn(node) ⇒ Object



281
282
283
284
# File 'lib/mulang/ruby/ast_processor.rb', line 281

def on_and_asgn(node)
  assignee, value = *node
  on_op_asgn s :op_asgn, assignee, '&&', value
end

#on_arg(node) ⇒ Object Also known as: on_restarg, on_procarg0



185
186
187
188
189
190
191
192
# File 'lib/mulang/ruby/ast_processor.rb', line 185

def on_arg(node)
  name, _ = *node
  if name.is_a? Parser::AST::Node
    process name
  else
    ms :VariablePattern, name
  end
end

#on_array(node) ⇒ Object



302
303
304
305
# File 'lib/mulang/ruby/ast_processor.rb', line 302

def on_array(node)
  elements = *node
  {tag: :MuList, contents: process_all(elements)}
end

#on_begin(node) ⇒ Object



49
50
51
52
53
54
55
# File 'lib/mulang/ruby/ast_processor.rb', line 49

def on_begin(node)
  if node.children.size == 1 && node.children[0].nil?
    none # ruby < 2.6 only
  else
    sequence(*process_all(node))
  end
end

#on_block(node) ⇒ Object



167
168
169
170
171
# File 'lib/mulang/ruby/ast_processor.rb', line 167

def on_block(node)
  send, parameters, body = *node
  lambda = ms(:Lambda, process_all(parameters), process(body) || none)
  handle_send_with_args send, [lambda]
end

#on_casgn(node) ⇒ Object



241
242
243
244
# File 'lib/mulang/ruby/ast_processor.rb', line 241

def on_casgn(node)
  _ns, id, value = *node
  ms :Assignment, id, process(value)
end

#on_class(node) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/mulang/ruby/ast_processor.rb', line 14

def on_class(node)
  @contexts.push :class

  name, superclass, body = *node

  _, class_name = *name
  _, superclass_name = *superclass

  ms :Class, class_name, superclass_name, process(body)
ensure
  @contexts.pop
end

#on_const(node) ⇒ Object



289
290
291
292
# File 'lib/mulang/ruby/ast_processor.rb', line 289

def on_const(node)
  _ns, value = *node
  ms :Reference, value
end

#on_def(node) ⇒ Object



154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/mulang/ruby/ast_processor.rb', line 154

def on_def(node)
  id, args, body = *node

  case id
  when :equal?, :eql?, :==
    primitive_method :Equal, process_all(args), process(body)
  when :hash
    primitive_method :Hash, process_all(args), process(body)
  else
    simple_method id, process_all(args), process(body)
  end
end

#on_defs(node) ⇒ Object



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/mulang/ruby/ast_processor.rb', line 138

def on_defs(node)
  target, id, args, body = *node

  result = simple_method id, process_all(args), process(body)

  if target.type == :self
    if @contexts.last == :module
      result
    else
      ms(:Decorator, [ms(:Classy)], result)
    end
  else
    ms(:EigenClass, process(target), result)
  end
end

#on_dstr(node) ⇒ Object



115
116
117
118
119
# File 'lib/mulang/ruby/ast_processor.rb', line 115

def on_dstr(node)
  parts = *node

  simple_send ms(:MuList, process_all(parts)), :join, []
end

#on_ensure(node) ⇒ Object



99
100
101
102
103
# File 'lib/mulang/ruby/ast_processor.rb', line 99

def on_ensure(node)
  catch, finally = *node
  try, catches = on_rescue(catch)[:contents]
  ms :Try, try, catches, process(finally)
end

#on_false(_) ⇒ Object



298
299
300
# File 'lib/mulang/ruby/ast_processor.rb', line 298

def on_false(_)
  ms :MuBool, false
end

#on_float(node) ⇒ Object Also known as: on_int



218
219
220
221
# File 'lib/mulang/ruby/ast_processor.rb', line 218

def on_float(node)
  value, _ = *node
  ms :MuNumber, value
end

#on_for(node) ⇒ Object



194
195
196
197
198
199
# File 'lib/mulang/ruby/ast_processor.rb', line 194

def on_for(node)
  variable, list, block = *node

  pattern = ms(:VariablePattern, variable.children.first)
  ms(:For, [ms(:Generator, pattern, process(list))], process(block) || none)
end

#on_if(node) ⇒ Object



225
226
227
228
229
# File 'lib/mulang/ruby/ast_processor.rb', line 225

def on_if(node)
  condition, if_true, if_false = *node

  ms :If, process(condition), process(if_true), process(if_false)
end

#on_irange(node) ⇒ Object



105
106
107
# File 'lib/mulang/ruby/ast_processor.rb', line 105

def on_irange(node)
  ms :Other, node.to_s, nil
end

#on_kwbegin(node) ⇒ Object



95
96
97
# File 'lib/mulang/ruby/ast_processor.rb', line 95

def on_kwbegin(node)
  process node.to_a.first
end

#on_lvar(node) ⇒ Object Also known as: on_ivar



231
232
233
234
# File 'lib/mulang/ruby/ast_processor.rb', line 231

def on_lvar(node)
  value = *node
  ms :Reference, value.first
end

#on_lvasgn(node) ⇒ Object Also known as: on_ivasgn



236
237
238
239
# File 'lib/mulang/ruby/ast_processor.rb', line 236

def on_lvasgn(node)
  id, value = *node
  ms :Assignment, id, process(value)
end

#on_module(node) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/mulang/ruby/ast_processor.rb', line 37

def on_module(node)
  @contexts.push :module

  name, body = *node

  _, module_name = *name

  ms :Object, module_name, process(body)
ensure
  @contexts.pop
end

#on_nil(_) ⇒ Object



177
178
179
# File 'lib/mulang/ruby/ast_processor.rb', line 177

def on_nil(_)
  mnil
end

#on_op_asgn(node) ⇒ Object



246
247
248
249
250
251
252
253
254
# File 'lib/mulang/ruby/ast_processor.rb', line 246

def on_op_asgn(node)
  assignee, message, value = *node

  if assignee.type == :send
    property_assignment assignee, message, value
  else
    var_assignment assignee, message, value
  end
end

#on_optarg(node) ⇒ Object



201
202
203
# File 'lib/mulang/ruby/ast_processor.rb', line 201

def on_optarg(node)
  ms :OtherPattern, node.to_s, nil
end

#on_or(node) ⇒ Object



121
122
123
124
# File 'lib/mulang/ruby/ast_processor.rb', line 121

def on_or(node)
  value, other = *node
  simple_send process(value), '||', [process(other)]
end

#on_or_asgn(node) ⇒ Object



276
277
278
279
# File 'lib/mulang/ruby/ast_processor.rb', line 276

def on_or_asgn(node)
  assignee, value = *node
  on_op_asgn s :op_asgn, assignee, '||', value
end

#on_regexp(node) ⇒ Object



109
110
111
112
113
# File 'lib/mulang/ruby/ast_processor.rb', line 109

def on_regexp(node)
  value, _ops = *node

  simple_send ms(:Reference, :Regexp), :new, [process(value)]
end

#on_resbody(node) ⇒ Object



62
63
64
65
66
# File 'lib/mulang/ruby/ast_processor.rb', line 62

def on_resbody(node)
  patterns, variable, block = *node

  [to_mulang_pattern(patterns, variable), process(block) || none]
end

#on_rescue(node) ⇒ Object



57
58
59
60
# File 'lib/mulang/ruby/ast_processor.rb', line 57

def on_rescue(node)
  try, *catch, _ = *node
  ms :Try, process(try), process_all(catch), none
end

#on_return(node) ⇒ Object



132
133
134
135
136
# File 'lib/mulang/ruby/ast_processor.rb', line 132

def on_return(node)
  value = *node

  ms(:Return, process(value.first))
end

#on_sclass(node) ⇒ Object



27
28
29
30
31
32
33
34
35
# File 'lib/mulang/ruby/ast_processor.rb', line 27

def on_sclass(node)
  @contexts.push :sclass

  target, body = *node

  ms :EigenClass, process(target), process(body)
ensure
  @contexts.pop
end

#on_self(_) ⇒ Object



181
182
183
# File 'lib/mulang/ruby/ast_processor.rb', line 181

def on_self(_)
  ms :Self
end

#on_send(node) ⇒ Object



173
174
175
# File 'lib/mulang/ruby/ast_processor.rb', line 173

def on_send(node)
  handle_send_with_args(node)
end

#on_str(node) ⇒ Object



208
209
210
211
# File 'lib/mulang/ruby/ast_processor.rb', line 208

def on_str(node)
  value, _ = *node
  ms :MuString, value
end

#on_sym(node) ⇒ Object



213
214
215
216
# File 'lib/mulang/ruby/ast_processor.rb', line 213

def on_sym(node)
  value, _ = *node
  ms :MuSymbol, value.to_s
end

#on_true(_) ⇒ Object



294
295
296
# File 'lib/mulang/ruby/ast_processor.rb', line 294

def on_true(_)
  ms :MuBool, true
end

#process(node) ⇒ Object



10
11
12
# File 'lib/mulang/ruby/ast_processor.rb', line 10

def process(node)
  node.nil? ? none : super
end

#property_assignment(assignee, message, value) ⇒ Object



261
262
263
264
265
# File 'lib/mulang/ruby/ast_processor.rb', line 261

def property_assignment(assignee, message, value)
  receiver, accessor, *accessor_args = *assignee

  reasign accessor, process_all(accessor_args), process(receiver), message, process(value)
end

#reasign(accessor, args, id, message, value) ⇒ Object



267
268
269
270
271
272
273
274
# File 'lib/mulang/ruby/ast_processor.rb', line 267

def reasign(accessor, args, id, message, value)
  simple_send id,
              "#{accessor}=".to_sym,
              args + [ms(:Send,
                        simple_send(id, accessor, args),
                        message_reference(message),
                        [value])]
end

#to_mulang_pattern(patterns, variable) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/mulang/ruby/ast_processor.rb', line 72

def to_mulang_pattern(patterns, variable)
  case [patterns, variable]
    when [nil, nil]
      ms :WildcardPattern
    when [nil, _]
      ms :VariablePattern, variable.to_a.first
    when [_, nil]
      to_single_pattern patterns
    else
      ms(:AsPattern, variable.to_a.first, to_single_pattern(patterns))
  end
end

#to_single_pattern(patterns) ⇒ Object



85
86
87
88
# File 'lib/mulang/ruby/ast_processor.rb', line 85

def to_single_pattern(patterns)
  mu_patterns = patterns.to_a.map { |it| to_type_pattern it }
  mu_patterns.size == 1 ? mu_patterns.first : ms(:UnionPattern, mu_patterns)
end

#to_type_pattern(node) ⇒ Object



90
91
92
93
# File 'lib/mulang/ruby/ast_processor.rb', line 90

def to_type_pattern(node)
  _, type = *node
  ms :TypePattern, type
end

#var_assignment(assignee, message, value) ⇒ Object



256
257
258
259
# File 'lib/mulang/ruby/ast_processor.rb', line 256

def var_assignment(assignee, message, value)
  id = assignee.to_a.first
  ms :Assignment, id, ms(:Send, ms(:Reference, id), message_reference(message), [process(value)])
end