Class: Furnace::AVM2::Transform::ASTNormalize

Inherits:
Object
  • Object
show all
Includes:
Visitor
Defined in:
lib/furnace-avm2/transform/ast_normalize.rb

Constant Summary collapse

IF_MAPPING =

(if-* a b) -> (*‘ a b)

{
  :eq        => [false, :==],
  :ne        => [false, :!=],
  :ge        => [false, :>=],
  :nge       => [true,  :>=],
  :gt        => [false, :>],
  :ngt       => [true,  :>],
  :le        => [false, :<=],
  :nle       => [true,  :<=],
  :lt        => [false, :<],
  :nlt       => [true,  :<],
  :strict_eq => [false, :===],
  :strict_ne => [true,  :===], # Why? Because of (lookup-switch ...).
  :true      => [false, :expand],
  :false     => [true,  :expand]
}

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ ASTNormalize

Returns a new instance of ASTNormalize.



6
7
8
# File 'lib/furnace-avm2/transform/ast_normalize.rb', line 6

def initialize(options={})
  @options = options
end

Instance Method Details

#fix_boolean(node) ⇒ Object Also known as: on_and, on_or, on_jump_if

(&& (coerce-b …) (coerce-b …)) -> (&& … …)



103
104
105
106
107
108
109
110
111
112
# File 'lib/furnace-avm2/transform/ast_normalize.rb', line 103

def fix_boolean(node)
  node.children.map! do |child|
    if child.is_a?(AST::Node) &&
          child.type == :coerce_b
      child.children.first
    else
      child
    end
  end
end

#on_call_property_void(node) ⇒ Object

(call-property-void *) -> (call-property *)



27
28
29
# File 'lib/furnace-avm2/transform/ast_normalize.rb', line 27

def on_call_property_void(node)
  node.update(:call_property)
end

#on_call_super_void(node) ⇒ Object

(call-super-void *) -> (call-super *)



32
33
34
# File 'lib/furnace-avm2/transform/ast_normalize.rb', line 32

def on_call_super_void(node)
  node.update(:call_super)
end

#on_nop(node) ⇒ Object



128
129
130
131
132
# File 'lib/furnace-avm2/transform/ast_normalize.rb', line 128

def on_nop(node)
  if @options[:eliminate_nops]
    node.update(:remove)
  end
end

#on_pop(node) ⇒ Object

(pop x) -> (jump-target) x



17
18
19
20
21
22
23
24
# File 'lib/furnace-avm2/transform/ast_normalize.rb', line 17

def on_pop(node)
  child = node.children.first

  node.update(:expand, [
    child,
    AST::Node.new(:nop, [], node.)
  ], nil)
end

#on_ternary_if(node) ⇒ Object

(ternary-if * (op a b x y)) -> (ternary-if-boolean * (op a b) x y)



84
85
86
87
88
89
# File 'lib/furnace-avm2/transform/ast_normalize.rb', line 84

def on_ternary_if(node)
  comparsion, op = node.children
  node.children.concat op.children.slice!(2..-1)

  on_ternary_if_boolean(node)
end

#on_ternary_if_boolean(node) ⇒ Object

(ternary-if-boolean true (op a b) x y) -> (ternary (op a b) x y) (ternary-if-boolean false (op a b) x y) -> (ternary (op a b) y x)



93
94
95
96
97
98
99
100
# File 'lib/furnace-avm2/transform/ast_normalize.rb', line 93

def on_ternary_if_boolean(node)
  comparsion, condition, if_true, if_false = node.children
  if comparsion
    node.update(:ternary, [ condition, if_true, if_false ])
  else
    node.update(:ternary, [ condition, if_false, if_true ])
  end
end

#replace_with_nop(node) ⇒ Object Also known as: on_debug, on_debug_file, on_debug_line



117
118
119
120
121
122
123
# File 'lib/furnace-avm2/transform/ast_normalize.rb', line 117

def replace_with_nop(node)
  if @options[:eliminate_nops]
    node.update(:remove)
  else
    node.update(:nop)
  end
end

#transform(ast) ⇒ Object



10
11
12
13
14
# File 'lib/furnace-avm2/transform/ast_normalize.rb', line 10

def transform(ast)
  visit ast

  ast
end

#transform_conditional(node, comp, reverse) ⇒ Object



54
55
56
57
# File 'lib/furnace-avm2/transform/ast_normalize.rb', line 54

def transform_conditional(node, comp, reverse)
  node.update(comp)
  node.parent.children[0] = !node.parent.children[0] if reverse
end