mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
fixed some optimization destroying parent
This commit is contained in:
parent
9b23bfb85c
commit
dd96cd506d
@ -242,6 +242,7 @@ class Optimizer:
|
||||
new_stmt = IncrDecr(operator="++" if assignment.operator == "+=" else "--",
|
||||
howmuch=howmuch.value, sourceref=assignment.sourceref)
|
||||
new_stmt.target = assignment.left
|
||||
new_stmt.target.parent = new_stmt
|
||||
assignment.my_scope().replace_node(assignment, new_stmt)
|
||||
self.optimizations_performed = True
|
||||
if assignment.right.value == 1 and assignment.operator in ("/=", "//=", "*="):
|
||||
@ -265,17 +266,23 @@ class Optimizer:
|
||||
@no_type_check
|
||||
def _make_aug_assign(self, old_assign: Assignment, target: Union[TargetRegisters, Register, SymbolName, Dereference],
|
||||
value: Union[int, float], operator: str) -> AugAssignment:
|
||||
assert isinstance(target, (TargetRegisters, Register, SymbolName, Dereference))
|
||||
a = AugAssignment(operator=operator, sourceref=old_assign.sourceref)
|
||||
a.nodes.append(target)
|
||||
a.nodes.append(LiteralValue(value=value, sourceref=old_assign.sourceref))
|
||||
target.parent = a
|
||||
lv = LiteralValue(value=value, sourceref=old_assign.sourceref)
|
||||
a.nodes.append(lv)
|
||||
lv.parent = a
|
||||
a.parent = old_assign.parent
|
||||
return a
|
||||
|
||||
@no_type_check
|
||||
def _make_incrdecr(self, old_stmt: AstNode, target: Union[TargetRegisters, Register, SymbolName, Dereference],
|
||||
howmuch: Union[int, float], operator: str) -> IncrDecr:
|
||||
assert isinstance(target, (TargetRegisters, Register, SymbolName, Dereference))
|
||||
a = IncrDecr(operator=operator, howmuch=howmuch, sourceref=old_stmt.sourceref)
|
||||
a.nodes.append(target)
|
||||
target.parent = a
|
||||
a.parent = old_stmt.parent
|
||||
return a
|
||||
|
||||
@ -341,7 +348,7 @@ class Optimizer:
|
||||
# the comparison operator and rvalue (0) will be removed and the if-status changed accordingly
|
||||
for goto in self.module.all_nodes(Goto):
|
||||
if isinstance(goto.condition, Expression):
|
||||
print("NOT IMPLEMENTED YET: optimize goto conditionals", goto.condition) # @todo
|
||||
pass # @todo optimize goto conditionals
|
||||
# if cond and isinstance(cond.rvalue, (int, float)) and cond.rvalue.value == 0:
|
||||
# simplified = False
|
||||
# if cond.ifstatus in ("true", "ne"):
|
||||
@ -456,7 +463,7 @@ def _process_constant_expression(expr: Expression, sourceref: SourceRef) -> Lite
|
||||
raise ExpressionEvaluationError("can only use math- or builtin function", expr.sourceref)
|
||||
elif isinstance(expr.target, Dereference): # '[...](1,2,3)'
|
||||
raise ExpressionEvaluationError("dereferenced value call is not a constant value", expr.sourceref)
|
||||
elif type(expr.target) is int: # '64738()'
|
||||
elif isinstance(expr.target, LiteralValue) and type(expr.target.value) is int: # '64738()'
|
||||
raise ExpressionEvaluationError("immediate address call is not a constant value", expr.sourceref)
|
||||
else:
|
||||
raise NotImplementedError("weird call target", expr.target)
|
||||
@ -504,15 +511,19 @@ def _process_dynamic_expression(expr: Expression, sourceref: SourceRef) -> Expre
|
||||
if expr.is_compile_constant():
|
||||
return LiteralValue(value=expr.const_value(), sourceref=sourceref) # type: ignore
|
||||
elif isinstance(expr, SymbolName):
|
||||
try:
|
||||
return _process_constant_expression(expr, sourceref)
|
||||
except ExpressionEvaluationError:
|
||||
return expr
|
||||
if expr.is_compile_constant():
|
||||
try:
|
||||
return _process_constant_expression(expr, sourceref)
|
||||
except ExpressionEvaluationError:
|
||||
pass
|
||||
return expr
|
||||
elif isinstance(expr, AddressOf):
|
||||
try:
|
||||
return _process_constant_expression(expr, sourceref)
|
||||
except ExpressionEvaluationError:
|
||||
return expr
|
||||
if expr.is_compile_constant():
|
||||
try:
|
||||
return _process_constant_expression(expr, sourceref)
|
||||
except ExpressionEvaluationError:
|
||||
pass
|
||||
return expr
|
||||
elif isinstance(expr, SubCall):
|
||||
try:
|
||||
return _process_constant_expression(expr, sourceref)
|
||||
@ -520,11 +531,7 @@ def _process_dynamic_expression(expr: Expression, sourceref: SourceRef) -> Expre
|
||||
if isinstance(expr.target, SymbolName):
|
||||
check_symbol_definition(expr.target.name, expr.my_scope(), expr.target.sourceref)
|
||||
return expr
|
||||
elif isinstance(expr, Register):
|
||||
return expr
|
||||
elif isinstance(expr, Dereference):
|
||||
if isinstance(expr.operand, SymbolName):
|
||||
check_symbol_definition(expr.operand.name, expr.my_scope(), expr.operand.sourceref)
|
||||
elif isinstance(expr, (Register, Dereference)):
|
||||
return expr
|
||||
elif isinstance(expr, ExpressionWithOperator):
|
||||
if expr.unary:
|
||||
|
@ -159,7 +159,7 @@ class Scope(AstNode):
|
||||
if node.name in self.symbols:
|
||||
raise ParseError("symbol '{}' already defined at {}".format(node.name, self.symbols[node.name].sourceref), node.sourceref)
|
||||
self.symbols[node.name] = node
|
||||
elif isinstance(node, Block):
|
||||
elif isinstance(node, (Block, Scope)):
|
||||
if node.name:
|
||||
if node.name != "ZP" and node.name in self.symbols:
|
||||
raise ParseError("symbol '{}' already defined at {}"
|
||||
@ -608,11 +608,11 @@ class ExpressionWithOperator(Expression):
|
||||
|
||||
@attr.s(cmp=False, repr=False)
|
||||
class Goto(AstNode):
|
||||
# one or two subnodes: target (SymbolName, int or Dereference) and optionally: condition (Expression)
|
||||
# one or two subnodes: target (SymbolName, integer LiteralValue, or Dereference) and optionally: condition (Expression)
|
||||
if_stmt = attr.ib(default=None)
|
||||
|
||||
@property
|
||||
def target(self) -> Union[SymbolName, int, Dereference]:
|
||||
def target(self) -> Union[SymbolName, LiteralValue, Dereference]:
|
||||
return self.nodes[0] # type: ignore
|
||||
|
||||
@property
|
||||
@ -1335,7 +1335,10 @@ def p_goto(p):
|
||||
goto : GOTO calltarget
|
||||
"""
|
||||
p[0] = Goto(sourceref=_token_sref(p, 1))
|
||||
p[0].nodes.append(p[2])
|
||||
target = p[2]
|
||||
if isinstance(target, int):
|
||||
target = LiteralValue(value=target, sourceref=p[0].sourceref)
|
||||
p[0].nodes.append(target)
|
||||
|
||||
|
||||
def p_conditional_goto_plain(p):
|
||||
|
@ -322,17 +322,22 @@ def test_symbol_lookup():
|
||||
scope_inner
|
||||
], level="block", sourceref=sref)
|
||||
scope_outer.name = "outer"
|
||||
scope_outer.define_builtin_functions()
|
||||
var1.parent = label1.parent = scope_inner.parent = scope_outer
|
||||
scope_topmost = Scope(nodes=[scope_outer], level="module", sourceref=sref)
|
||||
scope_topmost.name = "topmost"
|
||||
scope_outer.parent = scope_topmost
|
||||
scope_topmost.define_builtin_functions()
|
||||
assert scope_inner.parent_scope is scope_outer
|
||||
assert scope_outer.parent_scope is None
|
||||
assert scope_outer.parent_scope is scope_topmost
|
||||
assert scope_topmost.parent_scope is None
|
||||
assert label1.my_scope() is scope_outer
|
||||
assert var1.my_scope() is scope_outer
|
||||
assert scope_inner.my_scope() is scope_outer
|
||||
assert label2.my_scope() is scope_inner
|
||||
assert var2.my_scope() is scope_inner
|
||||
assert scope_outer.my_scope() is scope_topmost
|
||||
with pytest.raises(LookupError):
|
||||
scope_outer.my_scope()
|
||||
scope_topmost.my_scope()
|
||||
with pytest.raises(UndefinedSymbolError):
|
||||
scope_inner.lookup("unexisting")
|
||||
with pytest.raises(UndefinedSymbolError):
|
||||
@ -353,3 +358,12 @@ def test_symbol_lookup():
|
||||
builtin_func = scope_inner.lookup("max")
|
||||
assert isinstance(builtin_func, BuiltinFunction)
|
||||
assert builtin_func.name == "max" and builtin_func.func is max
|
||||
# test dotted names:
|
||||
with pytest.raises(UndefinedSymbolError):
|
||||
scope_inner.lookup("noscope.nosymbol.nothing")
|
||||
assert scope_inner.lookup("outer.inner.var2") is var2
|
||||
with pytest.raises(UndefinedSymbolError):
|
||||
scope_inner.lookup("outer.inner.var1")
|
||||
with pytest.raises(UndefinedSymbolError):
|
||||
scope_inner.lookup("outer.var2")
|
||||
assert scope_inner.lookup("outer.var1") is var1
|
||||
|
Loading…
x
Reference in New Issue
Block a user