Class: Mulang::PHP::AstProcessor

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

Instance Method Summary collapse

Methods included from Sexp

#application, #binary_operator, #callable, #ms, #sequence, #simple_function, #simple_method, #simple_send

Constructor Details

#initializeAstProcessor

Returns a new instance of AstProcessor.



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

def initialize
  define_binary_operators!
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(m, *args, &block) ⇒ Object



266
267
268
269
# File 'lib/mulang/php/ast_processor.rb', line 266

def method_missing(m, *args, &block)
  puts m, args
  ms :Other, "#{m}: #{args.to_s}", nil
end

Instance Method Details

#define_binary_operators!Object



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/mulang/php/ast_processor.rb', line 36

def define_binary_operators!
  [
    { token: '===', name: 'Identical', supports_assign?: false },
    { token: '!==', name: 'NotIdentical', supports_assign?: false },
    { token: '.', name: 'Concat', supports_assign?: true },
    { token: '+', name: 'Plus', supports_assign?: true },
    { token: '-', name: 'Minus', supports_assign?: true },
    { token: '*', name: 'Mul', supports_assign?: true },
    { token: '/', name: 'Div', supports_assign?: true },
    { token: '%', name: 'Mod', supports_assign?: true },
    { token: '**', name: 'Pow', supports_assign?: true },
    { token: '>', name: 'Greater', supports_assign?: false },
    { token: '<', name: 'Smaller', supports_assign?: false },
    { token: '>=', name: 'GreaterOrEqual', supports_assign?: false },
    { token: '<=', name: 'SmallerOrEqual', supports_assign?: false },
    { token: '&', name: 'BitwiseAnd', supports_assign?: true },
    { token: '|', name: 'BitwiseOr', supports_assign?: true },
    { token: '&&', name: 'BooleanAnd', supports_assign?: false },
    { token: '||', name: 'BooleanOr', supports_assign?: false },
    { token: 'and', name: 'LogicalAnd', supports_assign?: false },
    { token: 'or', name: 'LogicalOr', supports_assign?: false },
    { token: 'xor', name: 'LogicalXOr', supports_assign?: false }
  ].each { |it|
    self.class.redefine_method(:"on_Expr_BinaryOp_#{it[:name]}") { |node|
      process_binary_operator it[:token], node
    }

    if it[:supports_assign?]
      self.class.redefine_method(:"on_Expr_AssignOp_#{it[:name]}") { |node|
        binary_operator "#{it[:token]}=", process(node[:var]), process(node[:expr])
      }
    end
  }
end

#get_name(node) ⇒ Object



32
33
34
# File 'lib/mulang/php/ast_processor.rb', line 32

def get_name(node)
  node[:parts].first
end

#on_Arg(node) ⇒ Object



160
161
162
# File 'lib/mulang/php/ast_processor.rb', line 160

def on_Arg(node)
  process node[:value]
end

#on_Expr_Array(node) ⇒ Object



111
112
113
114
115
116
117
# File 'lib/mulang/php/ast_processor.rb', line 111

def on_Expr_Array(node)
  items = node[:items]
  is_array = items.all? { |it| it[:key].nil? }

  is_array ? ms(:MuList, process(items))
           : ms(:MuObject, process_block(items))
end

#on_Expr_ArrayItem(node) ⇒ Object



119
120
121
122
123
124
# File 'lib/mulang/php/ast_processor.rb', line 119

def on_Expr_ArrayItem(node)
  value = process(node[:value])

  node[:key] ? ms(:Attribute, node[:key][:value].to_s, value)
             : value
end

#on_Expr_Assign(node) ⇒ Object

STATEMENTS



176
177
178
179
180
181
182
183
184
185
# File 'lib/mulang/php/ast_processor.rb', line 176

def on_Expr_Assign(node)
  left = node[:var]
  exp = process(node[:expr])

  if left[:nodeType] == 'Expr_PropertyFetch'
    simple_send process(left[:var]), "#{left[:name][:name]}=", [exp]
  else
    ms :Assignment, left[:name], exp
  end
end

#on_Expr_BinaryOp_Equal(node) ⇒ Object

OPERATORS



136
137
138
# File 'lib/mulang/php/ast_processor.rb', line 136

def on_Expr_BinaryOp_Equal(node)
  ms :Application, [ms(:Equal), [process(node[:left]), process(node[:right])]]
end

#on_Expr_BinaryOp_NotEqual(node) ⇒ Object



140
141
142
# File 'lib/mulang/php/ast_processor.rb', line 140

def on_Expr_BinaryOp_NotEqual(node)
  ms :Application, [ms(:NotEqual), [process(node[:left]), process(node[:right])]]
end

#on_Expr_Closure(node) ⇒ Object



126
127
128
# File 'lib/mulang/php/ast_processor.rb', line 126

def on_Expr_Closure(node)
  ms :Lambda, process(node[:params]), process_block(node[:stmts])
end

#on_Expr_ConstFetch(node) ⇒ Object



96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/mulang/php/ast_processor.rb', line 96

def on_Expr_ConstFetch(node)
   value = get_name(node[:name]).downcase

  case value
    when 'true'
      ms :MuBool, true
    when 'false'
      ms :MuBool, false
    when 'null'
      ms :MuNil
    else
      ms :Reference, value
  end
end

#on_Expr_FuncCall(node) ⇒ Object

FUNCTION CALLS



156
157
158
# File 'lib/mulang/php/ast_processor.rb', line 156

def on_Expr_FuncCall(node)
  application get_name(node[:name]), process(node[:args])
end

#on_Expr_MethodCall(node) ⇒ Object



222
223
224
# File 'lib/mulang/php/ast_processor.rb', line 222

def on_Expr_MethodCall(node)
  simple_send process(node[:var]), node[:name][:name], process(node[:args])
end

#on_Expr_New(node) ⇒ Object



226
227
228
# File 'lib/mulang/php/ast_processor.rb', line 226

def on_Expr_New(node)
  ms :New, process(node[:class]), process(node[:args])
end

#on_Expr_PostDec(node) ⇒ Object Also known as: on_Expr_PreDec



149
150
151
# File 'lib/mulang/php/ast_processor.rb', line 149

def on_Expr_PostDec(node)
  binary_operator '-', process(node[:var]), ms(:MuNumber, 1)
end

#on_Expr_PostInc(node) ⇒ Object Also known as: on_Expr_PreInc



144
145
146
# File 'lib/mulang/php/ast_processor.rb', line 144

def on_Expr_PostInc(node)
  binary_operator '+', process(node[:var]), ms(:MuNumber, 1)
end

#on_Expr_PropertyFetch(node) ⇒ Object

OOP



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

def on_Expr_PropertyFetch(node)
  simple_send process(node[:var]), node[:name][:name], []
end

#on_Expr_Variable(node) ⇒ Object



83
84
85
# File 'lib/mulang/php/ast_processor.rb', line 83

def on_Expr_Variable(node)
  ms :Reference, node[:name]
end

#on_Name(node) ⇒ Object



230
231
232
# File 'lib/mulang/php/ast_processor.rb', line 230

def on_Name(node)
  ms :Reference, get_name(node)
end

#on_Param(node) ⇒ Object



130
131
132
# File 'lib/mulang/php/ast_processor.rb', line 130

def on_Param(node)
  ms :VariablePattern, node[:var][:name]
end

#on_Scalar_DNumber(node) ⇒ Object Also known as: on_Scalar_LNumber



87
88
89
# File 'lib/mulang/php/ast_processor.rb', line 87

def on_Scalar_DNumber(node)
  ms :MuNumber, node[:value]
end

#on_Scalar_String(node) ⇒ Object



92
93
94
# File 'lib/mulang/php/ast_processor.rb', line 92

def on_Scalar_String(node)
  ms :MuString, node[:value]
end

#on_Stmt_Class(node) ⇒ Object



234
235
236
237
238
239
# File 'lib/mulang/php/ast_processor.rb', line 234

def on_Stmt_Class(node)
  superclass = node.dig(:extends, :parts)&.first
  interfaces = node[:implements].map { |it| { nodeType: 'Stmt_Implement', name: get_name(it) } }

  ms :Class, node[:name][:name], superclass, process_block(interfaces.concat(node[:stmts]))
end

#on_Stmt_ClassMethod(node) ⇒ Object



250
251
252
253
254
255
256
257
258
259
# File 'lib/mulang/php/ast_processor.rb', line 250

def on_Stmt_ClassMethod(node)
  name = node[:name][:name]
  params = process(node[:params])

  if node[:stmts].nil?
    ms :TypeSignature, name, ms(:ParameterizedType, params.map { |it| 'Any' }, 'Any', [])
  else
    simple_method name, params, process_block(node[:stmts])
  end
end

#on_Stmt_Echo(node) ⇒ Object



187
188
189
# File 'lib/mulang/php/ast_processor.rb', line 187

def on_Stmt_Echo(node)
  ms :Print, process_block(node[:exprs])
end

#on_Stmt_Else(node) ⇒ Object



200
201
202
# File 'lib/mulang/php/ast_processor.rb', line 200

def on_Stmt_Else(node)
  process_block node[:stmts]
end

#on_Stmt_Expression(node) ⇒ Object

VALUES



79
80
81
# File 'lib/mulang/php/ast_processor.rb', line 79

def on_Stmt_Expression(node)
  process node[:expr]
end

#on_Stmt_For(node) ⇒ Object



204
205
206
# File 'lib/mulang/php/ast_processor.rb', line 204

def on_Stmt_For(node)
  ms :ForLoop, process_block(node[:init]), process_block(node[:cond]), process_block(node[:loop]), process_block(node[:stmts])
end

#on_Stmt_Foreach(node) ⇒ Object



212
213
214
# File 'lib/mulang/php/ast_processor.rb', line 212

def on_Stmt_Foreach(node)
  ms :For, [ms(:Generator, ms(:VariablePattern, node[:valueVar][:name]), process(node[:expr]))], process_block(node[:stmts])
end

#on_Stmt_Function(node) ⇒ Object

DECLARATIONS



166
167
168
# File 'lib/mulang/php/ast_processor.rb', line 166

def on_Stmt_Function(node)
  simple_function node[:name][:name], process(node[:params]), process_block(node[:stmts])
end

#on_Stmt_If(node) ⇒ Object Also known as: on_Stmt_ElseIf



191
192
193
194
195
196
197
# File 'lib/mulang/php/ast_processor.rb', line 191

def on_Stmt_If(node)
  condition = node[:cond]
  body = node[:stmts]
  else_block = node[:else]

  ms :If, process(condition), process_block(body), process(else_block)
end

#on_Stmt_Implement(node) ⇒ Object



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

def on_Stmt_Implement(node)
  ms :Implement, ms(:Reference, node[:name])
end

#on_Stmt_Interface(node) ⇒ Object



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

def on_Stmt_Interface(node)
  parents = node[:extends].map { |it| get_name(it) }
  ms :Interface, node[:name][:name], parents, process_block(node[:stmts])
end

#on_Stmt_Property(node) ⇒ Object



245
246
247
248
# File 'lib/mulang/php/ast_processor.rb', line 245

def on_Stmt_Property(node)
  prop = node[:props].first
  ms :Attribute, prop[:name][:name], process(prop[:default])
end

#on_Stmt_Return(node) ⇒ Object



170
171
172
# File 'lib/mulang/php/ast_processor.rb', line 170

def on_Stmt_Return(node)
  ms :Return, process(node[:expr])
end

#on_Stmt_While(node) ⇒ Object



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

def on_Stmt_While(node)
  ms :While, process(node[:cond]), process_block(node[:stmts])
end

#process(node) ⇒ Object



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

def process(node)
  return ms(:None) if node.nil?

  if node.is_a?(Array)
    return node.map { |it| process it }
  end

  if node.is_a?(Hash)
    return send "on_#{node[:nodeType]}", node
  end

  ms(:Other)
end

#process_array(array, &f) ⇒ Object



28
29
30
# File 'lib/mulang/php/ast_processor.rb', line 28

def process_array(array, &f)
  array.map f
end

#process_binary_operator(operator, node) ⇒ Object



71
72
73
# File 'lib/mulang/php/ast_processor.rb', line 71

def process_binary_operator(operator, node)
  binary_operator operator, process(node[:left]), process(node[:right])
end

#process_block(stmts) ⇒ Object



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

def process_block(stmts)
  sequence *process(stmts)
end