Class: Packcr::Node::AlternateNode
- Inherits:
-
Packcr::Node
- Object
- Packcr::Node
- Packcr::Node::AlternateNode
- Defined in:
- lib/packcr/node/alternate_node.rb,
lib/packcr/generated/node/alternate_node.rb
Instance Attribute Summary collapse
-
#nodes ⇒ Object
Returns the value of attribute nodes.
Instance Method Summary collapse
- #alt(node) ⇒ Object
- #debug_dump(indent = 0) ⇒ Object
- #generate_code(gen, onfail, indent, bare, oncut: nil) ⇒ Object
- #get_code(gen, onfail, indent, bare, oncut) ⇒ Object
-
#initialize(*nodes) ⇒ AlternateNode
constructor
A new instance of AlternateNode.
- #max ⇒ Object
- #reachability ⇒ Object
- #to_h ⇒ Object
- #verify_captures(ctx, capts) ⇒ Object
- #verify_variables(vars) ⇒ Object
Methods inherited from Packcr::Node
#link_references, #reversible?, #seq, #sequence?, #setup, #setup_rule
Constructor Details
#initialize(*nodes) ⇒ AlternateNode
Returns a new instance of AlternateNode.
6 7 8 9 |
# File 'lib/packcr/node/alternate_node.rb', line 6 def initialize(*nodes) super() self.nodes = nodes end |
Instance Attribute Details
#nodes ⇒ Object
Returns the value of attribute nodes.
4 5 6 |
# File 'lib/packcr/node/alternate_node.rb', line 4 def nodes @nodes end |
Instance Method Details
#alt(node) ⇒ Object
11 12 13 14 |
# File 'lib/packcr/node/alternate_node.rb', line 11 def alt(node) @nodes << node if node self end |
#debug_dump(indent = 0) ⇒ Object
16 17 18 19 20 21 22 |
# File 'lib/packcr/node/alternate_node.rb', line 16 def debug_dump(indent = 0) $stdout.print "#{" " * indent}Alternate(max:#{max}, len:#{nodes.length}) {\n" nodes.each do |node| node.debug_dump(indent + 2) end $stdout.print "#{" " * indent}}\n" end |
#generate_code(gen, onfail, indent, bare, oncut: nil) ⇒ Object
30 31 32 |
# File 'lib/packcr/node/alternate_node.rb', line 30 def generate_code(gen, onfail, indent, , oncut: nil) gen.write Packcr.format_code(get_code(gen, onfail, indent, , oncut), indent: indent, unwrap: ) end |
#get_code(gen, onfail, indent, bare, oncut) ⇒ Object
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/packcr/generated/node/alternate_node.rb', line 4 def get_code(gen, onfail, indent, , oncut) case gen.lang when :c erbout = +"" m = gen.next_label erbout << "{\n const size_t p = ctx->position_offset;\n".freeze if gen.location erbout << " const packcr_location_t p_loc = ctx->position_offset_loc;\n".freeze end erbout << " const size_t n = chunk->thunks.len;\n".freeze nodes.each_with_index do |expr, i| c = i + 1 < nodes.length l = gen.next_label r = expr.reachability erbout << "#{gen.generate_code(expr, l, 4, false)}".freeze if r == Packcr::CODE_REACH__ALWAYS_SUCCEED if c erbout << " /* unreachable codes omitted */\n".freeze end break elsif r == Packcr::CODE_REACH__BOTH erbout << " goto L#{format("%04d", m)};\n".freeze end erbout << "L#{format("%04d", l)}:;\n ctx->position_offset = p;\n".freeze if gen.location erbout << " ctx->position_offset_loc = p_loc;\n".freeze end erbout << " packcr_thunk_array__revert(ctx->auxil, &chunk->thunks, n);\n".freeze next if c erbout << " goto L#{format("%04d", onfail)};\n".freeze end erbout << "L#{format("%04d", m)}:;\n}\n".freeze erbout when :rb erbout = +"" m = gen.next_label erbout << "catch(#{m}) do\n pos#{gen.level} = @position_offset\n".freeze if gen.location erbout << " p_loc#{gen.level} = @position_offset_loc\n".freeze end erbout << " n#{gen.level} = answer.thunks.length\n".freeze nodes.each_with_index do |expr, i| c = i + 1 < nodes.length if expr.reversible?(gen) erbout << "#{gen.generate_code(expr, m, 2, false, reverse: true, oncut: onfail)}".freeze else l = gen.next_label erbout << " catch(#{l}) do\n".freeze r = expr.reachability erbout << "#{gen.generate_code(expr, l, 4, false, oncut: onfail)}".freeze if r == Packcr::CODE_REACH__ALWAYS_SUCCEED if c erbout << " # unreachable codes omitted\n".freeze end erbout << " end\n".freeze break elsif r == Packcr::CODE_REACH__BOTH erbout << " throw(#{m})\n".freeze end erbout << " end\n".freeze end erbout << " @position_offset = pos#{gen.level}\n".freeze if gen.location erbout << " @position_offset_loc = p_loc#{gen.level}\n".freeze end erbout << " answer.thunks[n#{gen.level}..-1] = []\n".freeze next if c erbout << " throw(#{onfail})\n".freeze end erbout << "end\n".freeze erbout when :rs erbout = +"" m = gen.next_label erbout << "'L#{format("%04d", m)}: {\n let p = self.input.position_offset;\n".freeze if gen.location erbout << " TODO\n".freeze end nodes.each_with_index do |expr, i| erbout << " {\n".freeze c = i + 1 < nodes.length if expr.reversible?(gen) erbout << "#{gen.generate_code(expr, m, 8, false, reverse: true, oncut: onfail)}".freeze else l = gen.next_label erbout << " 'L#{format("%04d", l)}: {\n".freeze r = expr.reachability erbout << "#{gen.generate_code(expr, l, 12, false, oncut: onfail)}".freeze if r == Packcr::CODE_REACH__ALWAYS_SUCCEED if c erbout << " // unreachable codes omitted\n".freeze end erbout << " }\n".freeze break elsif r == Packcr::CODE_REACH__BOTH erbout << " break 'L#{format("%04d", m)};\n".freeze end erbout << " }\n".freeze end erbout << " }\n self.input.position_offset = p;\n".freeze if gen.location erbout << " TODO\n".freeze end next if c erbout << " break 'L#{format("%04d", onfail)};\n".freeze end erbout << "} // 'L#{format("%04d", m)}\n".freeze erbout else raise "unknown lang #{gen.lang}" end end |
#max ⇒ Object
24 25 26 27 28 |
# File 'lib/packcr/node/alternate_node.rb', line 24 def max m = 1 m <<= 1 while m < @nodes.length m end |
#reachability ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/packcr/node/alternate_node.rb', line 34 def reachability r = Packcr::CODE_REACH__ALWAYS_FAIL nodes.each do |expr| case expr.reachability when Packcr::CODE_REACH__ALWAYS_SUCCEED return Packcr::CODE_REACH__ALWAYS_SUCCEED when Packcr::CODE_REACH__BOTH r = Packcr::CODE_REACH__BOTH end end r end |
#to_h ⇒ Object
76 77 78 79 80 81 |
# File 'lib/packcr/node/alternate_node.rb', line 76 def to_h { type: :alternate, nodes: nodes&.map(&:to_h), } end |
#verify_captures(ctx, capts) ⇒ Object
64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/packcr/node/alternate_node.rb', line 64 def verify_captures(ctx, capts) m = capts.length v = capts.dup nodes.each do |node| v = v[0, m] node.verify_captures(ctx, v) v[m...-1].each do |added_node| capts.push(added_node) end end end |
#verify_variables(vars) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/packcr/node/alternate_node.rb', line 47 def verify_variables(vars) m = vars.length v = vars.dup nodes.each do |node| v = v[0, m] node.verify_variables(v) v[m...-1].each do |added_node| found = vars[m...-1].any? do |added_var| added_node.index == added_var.index end if !found vars.push(added_node) end end end end |