diff options
| author | Bruce Hill <bruce@bruce-hill.com> | 2018-12-30 23:56:28 -0800 |
|---|---|---|
| committer | Bruce Hill <bruce@bruce-hill.com> | 2018-12-30 23:58:43 -0800 |
| commit | ec69ee6f62016a2edcc13e3183cbe4cadd75717f (patch) | |
| tree | 24e04f77c7390d379f2fb372611ac468a67aed03 /nomsu_decompiler.moon | |
| parent | 435eae7c0ab10577431bb943a6f48873e5ecdf7c (diff) | |
Fixes for: indented strings ending in ", peeking at code object text
before modifying them, and major upgrades to the nomsu codegen,
including support for indented inline arguments (instead of using
"\n..") and just generally better line wrapping, including finally good
rules for when to use indented text (for almost all cases).
Diffstat (limited to 'nomsu_decompiler.moon')
| -rw-r--r-- | nomsu_decompiler.moon | 93 |
1 files changed, 64 insertions, 29 deletions
diff --git a/nomsu_decompiler.moon b/nomsu_decompiler.moon index 181d73f..3c20f76 100644 --- a/nomsu_decompiler.moon +++ b/nomsu_decompiler.moon @@ -133,24 +133,26 @@ tree_to_inline_nomsu = (tree)-> key[1] else tree_to_inline_nomsu(key) - key_nomsu\parenthesize! if key.type == "Block" or key.type == "Action" or key.type == "MethodCall" + switch key.type + when "Block", "Action", "MethodCall", "IndexChain" + key_nomsu\parenthesize! return NomsuCode\from(key.source, ".", key_nomsu) when "IndexChain" nomsu = NomsuCode\from(tree.source) - for i, bit in ipairs tree - nomsu\add "." if i > 1 and bit.type != "Index" - local bit_nomsu - bit_nomsu = if i > 1 and bit.type == "Text" and #bit == 1 and type(bit[1]) == 'string' and is_identifier(bit[1]) - bit[1] - else tree_to_inline_nomsu(bit) - assert bit.type != "Block" - switch bit.type - when "Action", "MethodCall", "IndexChain" - bit_nomsu\parenthesize! - when "Number" - bit_nomsu\parenthesize! if bit_nomsu\text!\match("%.") - nomsu\add bit_nomsu + target = tree[1] + target_nomsu = tree_to_inline_nomsu(target) + switch target.type + when "Action", "MethodCall" + target_nomsu\parenthesize! + when "Number" + target_nomsu\parenthesize! if target_nomsu\text!\match("%.") + nomsu\add target_nomsu + for i=2,#tree + -- TODO: remove shim? + if tree[i].type != "Index" + tree[i] = {type:"Index", source:tree[i].source, tree[i]} + nomsu\add tree_to_inline_nomsu(tree[i]) return nomsu when "Number" @@ -189,18 +191,27 @@ tree_to_nomsu = (tree)-> space = MAX_LINE - nomsu\trailing_line_len! try_inline = true for subtree in coroutine.wrap(-> (t\map(coroutine.yield) and nil)) - if subtree.type == "Comment" - try_inline = false - if subtree.type == "Block" - if #subtree > 1 + switch subtree.type + when "Comment" try_inline = false + when "Block" + if #subtree > 1 + try_inline = false + when "Text" + indented = tree_to_nomsu(subtree) + indented_lines = [line for line in *indented\text!\lines! when line\match("^ +([^ ].*)")] + for i=#indented_lines,1,-1 + if indented_lines[i]\match("^ *\\;$") + table.remove(indented_lines, i) + if #indented_lines > 1 or (#indented_lines == 1 and #indented_lines[1] > MAX_LINE + 8) + try_inline = false local inline_nomsu if try_inline inline_nomsu = tree_to_inline_nomsu(t) + if (t.type == "Action" or t.type == "MethodCall") + inline_nomsu\parenthesize! if #inline_nomsu\text! <= space or #inline_nomsu\text! <= 8 - if (t.type == "Action" or t.type == "MethodCall") - inline_nomsu\parenthesize! if t.type != "Text" return inline_nomsu indented = tree_to_nomsu(t) @@ -214,11 +225,13 @@ tree_to_nomsu = (tree)-> return NomsuCode\from(t.source, "\n ", indented) else indented\parenthesize! - indented_lines = [line for line in *indented\text!\lines! when line\match("%S")] - if inline_nomsu and #indented_lines == ((t.type == 'Block' or t.type == 'Action' or t.type == 'MethodCall') and 2 or 3) and nomsu\trailing_line_len! <= 8 - return inline_nomsu - elseif inline_nomsu and t.type == "Text" and #indented_lines <= 3 and - (#inline_nomsu\text! - 2 < MAX_LINE + 4 or #inline_nomsu\text! <= space or #inline_nomsu\text! <= 8) + indented_lines = [line for line in *indented\text!\lines! when line\match("^ +([^ ].*)")] + if t.type == "Text" + for i=#indented_lines,1,-1 + if indented_lines[i]\match("^ *\\;$") + table.remove(indented_lines, i) + if inline_nomsu and (#inline_nomsu\text! < MAX_LINE or #inline_nomsu\text! <= space) and + #indented_lines <= 1 return inline_nomsu return indented @@ -265,13 +278,21 @@ tree_to_nomsu = (tree)-> if bit.type == "Block" -- Rule of thumb: nontrivial one-liner block arguments should be no more -- than golden ratio * the length of the proceeding part of the line - if not bit_nomsu\is_multiline! and #bit_nomsu\text! > nomsu\trailing_line_len! * GOLDEN_RATIO and #bit_nomsu\text! > 8 + if not bit_nomsu\is_multiline! and + (#bit_nomsu\text! > nomsu\trailing_line_len! * GOLDEN_RATIO and #bit_nomsu\text! > 8) or + #bit_nomsu\text! + nomsu\trailing_line_len! > MAX_LINE bit_nomsu = tree_to_nomsu(bit) elseif (not bit_nomsu\is_multiline! and nomsu\trailing_line_len! + #bit_nomsu\text! > MAX_LINE and nomsu\trailing_line_len! > 8) if next_space == " " and #bit_nomsu\text! < MAX_LINE - next_space = "\n.." + if i == #tree + bit_nomsu = tree_to_inline_nomsu(bit) + next_space = "\n " + elseif bit.type == "List" or bit.type == "Dict" + bit_nomsu = tree_to_nomsu(bit) + else + next_space = "\n.." elseif bit.type == 'Action' or bit.type == "MethodCall" bit_nomsu = NomsuCode\from bit.source, "\n ", tree_to_nomsu(bit) else @@ -281,7 +302,7 @@ tree_to_nomsu = (tree)-> nomsu\add next_space nomsu\add bit_nomsu - next_space = (bit.type == 'Block' or (i > 1 and (bit.type == 'Action' or bit.type == 'MethodCall')) and bit_nomsu\is_multiline!) and "\n.." or " " + next_space = (bit.type == "Block" or bit_nomsu\text!\matches("\n [^\n]*$")) and "\n.." or " " if #word_buffer > 0 words = table.concat(word_buffer) @@ -365,12 +386,25 @@ tree_to_nomsu = (tree)-> nomsu\add "\\" interp_nomsu = recurse(bit) unless interp_nomsu\is_multiline! + space = max_line - nomsu\trailing_line_len! if bit.type == "Var" next_str = tree[i+1] while type(next_str) == 'table' and next_str.type == 'Text' next_str = next_str[1] if type(next_str) == 'string' and not match(next_str, "^[ \n\t,.:;#(){}[%]]") interp_nomsu\parenthesize! + elseif #interp_nomsu\text! > space + interp_nomsu2 = if bit.type == "Action" or bit.type == "MethodCall" + NomsuCode\from(bit.source, "(\n ", tree_to_nomsu(bit), "\n)") + else + tree_to_nomsu(bit) + + if #interp_nomsu2\text!\lines! > 3 or #interp_nomsu2\text! >= MAX_LINE*GOLDEN_RATIO + interp_nomsu = interp_nomsu2 + else + nomsu\add "\n..\\" + if bit.type == "EscapedNomsu" or bit.type == "Block" or bit.type == "IndexChain" + interp_nomsu\parenthesize! elseif bit.type == "EscapedNomsu" or bit.type == "Block" or bit.type == "IndexChain" interp_nomsu\parenthesize! nomsu\add interp_nomsu @@ -396,7 +430,8 @@ tree_to_nomsu = (tree)-> else item_nomsu = tree_to_inline_nomsu(item) if #item_nomsu\text! > MAX_LINE - item_nomsu = recurse(item) + sep = '\n' if i > 1 + item_nomsu = tree_to_nomsu(item) nomsu\add sep nomsu\add item_nomsu if item_nomsu\is_multiline! or item.type == 'Comment' or nomsu\trailing_line_len! + #tostring(item_nomsu) >= MAX_LINE |
