Skip to content

Commit

Permalink
avoid worsening char count under --focus-chars due to const propagation
Browse files Browse the repository at this point in the history
  • Loading branch information
thisismypassport committed Jun 15, 2024
1 parent 4c2fc4a commit 9f08608
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 20 deletions.
34 changes: 22 additions & 12 deletions pico_constfold.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,20 +445,27 @@ def get_const(node):
elif node.type == NodeType.group:
return get_const(node.child)
else:
return None
return getattr(node, "worse_const", None)

def set_const(node, value):
def set_const(node, value, ctxt, focus, force):
if value.is_number:
token = ConstToken(TokenType.number, node, parsed_value=value.value)
token = ConstToken(TokenType.number, value.value, node)
elif value.type == LuaType.string:
token = ConstToken(TokenType.string, node, parsed_value=value.value)
token = ConstToken(TokenType.string, value.value, node)
elif value.type == LuaType.boolean:
token = ConstToken(TokenType.keyword, node, value="true" if value.value else "false")
token = Token.synthetic(TokenType.keyword, "true" if value.value else "false", node)
elif value.type == LuaType.nil:
token = ConstToken(TokenType.keyword, node, value="nil")
token = Token.synthetic(TokenType.keyword, "nil", node)
else:
assert False, "unexpected const value: %s" % value

if focus == Focus.chars and not force:
# the new token may take more chars than before
# though it may still be useful when further folded
if len(token.value) > len(output_min_wspace(node, ctxt)):
node.worse_const = value
return

node.replace_with(create_const_node(token))

def fixup_syntax_between(parent, prev, next):
Expand Down Expand Up @@ -556,7 +563,7 @@ def remove_else_node(node):
end_token = Token.synthetic(TokenType.keyword, "end", node, append=True)
node.append_existing(end_token)

def fold_consts(ctxt, root, errors):
def fold_consts(ctxt, focus, root, errors):
lang = ctxt.lang

def add_error(msg, node):
Expand All @@ -581,7 +588,7 @@ def update_node_constval(node):
if child_const:
constval = func(lang, child_const)
if constval:
set_const(node, constval)
set_const(node, constval, ctxt, focus, in_const_ctxt)

elif node.type == NodeType.binary_op:
func = k_const_binary_ops.get(node.op, None)
Expand All @@ -600,11 +607,11 @@ def update_node_constval(node):
if constval is node.right:
node.replace_with(node.right)
else:
set_const(node, constval)
set_const(node, constval, ctxt, focus, in_const_ctxt)

elif node.type == NodeType.var and node.var and not node.new and not node.assignment:
if node.var.constval:
set_const(node, node.var.constval)
set_const(node, node.var.constval, ctxt, focus, in_const_ctxt or node.var.is_const)
elif node.var.is_const:
add_error(f"'{node.name}' is marked as constant but is used above where it is assigned to", node)
node.var.is_const = False
Expand All @@ -628,7 +635,7 @@ def update_node_constval(node):
else:
constval = func(lang, *arg_consts)
if constval:
set_const(node, constval)
set_const(node, constval, ctxt, focus, in_const_ctxt)

elif node.type == NodeType.if_:
constval = get_const(node.cond)
Expand Down Expand Up @@ -693,7 +700,8 @@ def visit_assign(node):
node.sources[i].traverse_nodes(pre=skip_special, post=update_node_constval)

if constval:
if is_const_ctxt or not isinstance(constval, LuaString): # string const folding may balloon total char count
const_unwanted = isinstance(constval, LuaString) or focus == Focus.chars # cases likely to make char count increase too much
if is_const_ctxt or not const_unwanted:
erasable.append(i)
if not target.var.constval: # may've been set to something else through ctxt.consts
target.var.constval = constval
Expand Down Expand Up @@ -739,3 +747,5 @@ def parse_constant(value, lang, as_str=False):
return constval

from pico_process import Error, Source
from pico_minify import Focus
from pico_output import output_min_wspace
5 changes: 3 additions & 2 deletions pico_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,10 @@ def process_code(ctxt, source, input_count=False, count=False, lint=False, minif

def simplify_code(ctxt, root, minify, errors):
fold = minify.get("consts", True)
focus = Focus(minify.get("focus"))

if fold:
fold_consts(ctxt, root, errors)
fold_consts(ctxt, focus, root, errors)

def echo_code(code, ctxt, echo=True):
code = from_langstr(code, ctxt.lang)
Expand All @@ -313,7 +314,7 @@ def echo_code(code, ctxt, echo=True):
from pico_tokenize import tokenize, count_tokens
from pico_parse import parse, create_super_root, get_sub_root
from pico_lint import lint_code
from pico_minify import minify_code, minify_needs_comments
from pico_minify import minify_code, minify_needs_comments, Focus
from pico_unminify import unminify_code
from pico_constfold import fold_consts
from pico_output import output_code
Expand Down
13 changes: 8 additions & 5 deletions pico_tokenize.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,22 +196,25 @@ def synthetic(cls, type, value, other, append=False, prepend=False):
Token.none = Token.dummy(None)

class ConstToken(Token):
def __init__(m, type, other, value=None, parsed_value=None):
super().__init__(type, value, other.source, other.idx, other.endidx, lang=other.lang, modified=True)
def __init__(m, type, parsed_value, other):
super().__init__(type, None, other.source, other.idx, other.endidx, lang=other.lang, modified=True)
m.parsed_value = parsed_value
if value is None:
lazy_property.clear(m, "value")
lazy_property.clear(m, "value")

@lazy_property
def value(m): # used during going over chars for rename (tsk...) and for output when not minify-tokens
# (but not used for output under minify-tokens)
if isinstance(m.parsed_value, (int, float)):
allow_unary = can_replace_with_unary(m.parent)
allow_unary = can_replace_with_unary(m.parent) if m.parent else True
format_num = format_fixnum if m.lang == Language.pico8 else format_luanum
return format_num(m.parsed_value, sign=None if allow_unary else "")
else:
return format_string_literal(m.parsed_value, long=False)

@post_property_change
def parent(m, old, new):
lazy_property.clear(m, "value")

class CommentHint(Enum):
none = preserve = lint = keep = ...

Expand Down
1 change: 1 addition & 0 deletions run_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ def run():
run_test("constcl-1", "constcl.p8", "constcl-1.p8", "--minify", "--const", "DEBUG", "true", "--const", "SPEED", "2.5", "--str-const", "VERSION", "v1.2")
run_test("constcl-2", "constcl.p8", "constcl-2.p8", "--minify", "--const", "DEBUG", "true", "--const", "SPEED", "-2.6", "--const", "hero", "~1")
run_test("constmin", "const.p8", "constmin.p8", "--minify", pico8_output="const.p8.printh")
run_test("constchars", "constchars.p8", "constchars.p8", "--minify", "--focus-chars")

if run_test("test", "test.p8", "test.p8", "--minify", "--no-minify-consts", pico8_output_val="DONE"):
run_test("unmintest", "test.p8", "test-un.p8", "--unminify", from_output=True, pico8_output_val="DONE")
Expand Down
2 changes: 1 addition & 1 deletion site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
<div class="base" style="flex: 1">
<div id="input-code" class="ace-textarea full"
placeholder="You can also paste your code here, or drag & drop a {{targetname}} file here.
It can be a .{{srcext}} file, a .png cart, and more."></div>
It can be a .{{srcext}} file, a .png cart, {{"a whole directory, " if picotron}}and more."></div>
<div id="input-overlay" class="overlay">
<div class="center">Opening...</div>
</div>
Expand Down
7 changes: 7 additions & 0 deletions test_compare/constchars.p8
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pico-8 cartridge // http://www.pico-8.com
version 42
__lua__
l=1/30o=1/30+123c=.25a=.01667local l=1/30?l
local l=.01667?l
?.03333
b=1/30
11 changes: 11 additions & 0 deletions test_input/constchars.p8
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pico-8 cartridge // http://www.pico-8.com
version 36
__lua__
x=1/30
y=1/30+123
z=1/4
w=1/30/2
local a=1/30; ?a
local b=1/30/2; ?b
--[[const]] local c=1/30; ?c
v=1 / 30

0 comments on commit 9f08608

Please sign in to comment.