diff --git a/il65/compile.py b/il65/compile.py index 2caac21d8..0b86b820b 100644 --- a/il65/compile.py +++ b/il65/compile.py @@ -137,6 +137,12 @@ class PlyParser: if isinstance(node, Block): if node in encountered_blocks: raise CompileError("parse tree malformed; block duplicated", node, node.name, node.sourceref) + if node.name is None: + # blocks without names are possible, in this case their address is specified + if node.address is not None: + continue + else: + raise ParseError("block without name must have address", node.sourceref) parentname = (node.parent.name + ".") if node.parent else "" blockname = parentname + node.name if blockname in encountered_block_names: diff --git a/il65/emit/__init__.py b/il65/emit/__init__.py index 12124fa0e..0de064138 100644 --- a/il65/emit/__init__.py +++ b/il65/emit/__init__.py @@ -127,3 +127,8 @@ def preserving_registers(registers: Set[str], scope: Scope, out: Callable, loads out("\t\tpla") else: yield + + +def scoped_name(node_with_name: AstNode, current_scope: Scope) -> str: + node_scope = node_with_name.my_scope() + return node_with_name.name if node_scope is current_scope else node_scope.name + "." + node_with_name.name diff --git a/il65/emit/incrdecr.py b/il65/emit/incrdecr.py index 489a9f7b7..8eb6b057b 100644 --- a/il65/emit/incrdecr.py +++ b/il65/emit/incrdecr.py @@ -9,7 +9,7 @@ Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0 from ..plyparse import VarType, VarDef, Register, IncrDecr, SymbolName, Dereference, LiteralValue, datatype_of from ..datatypes import DataType, REGISTER_BYTES -from . import CodeError, preserving_registers, to_hex, Context +from . import CodeError, preserving_registers, to_hex, Context, scoped_name def generate_incrdecr(ctx: Context) -> None: @@ -139,7 +139,7 @@ def generate_incrdecr(ctx: Context) -> None: elif isinstance(target, VarDef): if target.vartype == VarType.CONST: raise CodeError("cannot modify a constant", target) - what_str = target.name + what_str = scoped_name(target, scope) if target.datatype == DataType.BYTE: if stmt.howmuch == 1: out("\v{:s} {:s}".format("inc" if stmt.operator == "++" else "dec", what_str)) diff --git a/il65/optimize.py b/il65/optimize.py index dd6b373db..2f422eedf 100644 --- a/il65/optimize.py +++ b/il65/optimize.py @@ -203,14 +203,14 @@ class Optimizer: new_assignment = self._make_new_assignment(assignment, 1) assignment.my_scope().replace_node(assignment, new_assignment) self.optimizations_performed = True - if assignment.right.value >= 8 and assignment.operator in ("<<=", ">>="): + elif assignment.right.value >= 8 and assignment.operator in ("<<=", ">>="): print("{}: shifting result is always zero".format(assignment.sourceref)) new_stmt = Assignment(sourceref=assignment.sourceref) new_stmt.nodes.append(AssignmentTargets(nodes=[assignment.left], sourceref=assignment.sourceref)) new_stmt.nodes.append(LiteralValue(value=0, sourceref=assignment.sourceref)) assignment.my_scope().replace_node(assignment, new_stmt) self.optimizations_performed = True - if assignment.operator in ("+=", "-=") and 0 < assignment.right.value < 256: + elif assignment.operator in ("+=", "-=") and 0 < assignment.right.value < 256: howmuch = assignment.right if howmuch.value not in (0, 1): _, howmuch = coerce_constant_value(datatype_of(assignment.left, assignment.my_scope()), @@ -221,7 +221,7 @@ class Optimizer: 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 ("/=", "//=", "*="): + elif assignment.right.value == 1 and assignment.operator in ("/=", "//=", "*="): self.num_warnings += 1 print_warning("{}: removed statement that has no effect".format(assignment.sourceref)) assignment.my_scope().remove_node(assignment) diff --git a/il65/plyparse.py b/il65/plyparse.py index aa09fdd24..3786d7c05 100644 --- a/il65/plyparse.py +++ b/il65/plyparse.py @@ -88,6 +88,9 @@ class AstNode: def all_nodes(self, *nodetypes: type) -> Generator['AstNode', None, None]: nodetypes = nodetypes or (AstNode, ) + if self.nodes is None: + # this is the case when a node has been pruned away + return child_nodes = list(self.nodes) for node in child_nodes: if isinstance(node, nodetypes): @@ -1091,6 +1094,14 @@ def p_block_name(p): p[0].scope = p[4] +def p_block_address(p): + """ + block : BITINVERT INTEGER endl_opt scope + """ + p[0] = Block(address=p[2], sourceref=_token_sref(p, 2)) + p[0].scope = p[4] + + def p_block(p): """ block : BITINVERT endl_opt scope