Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions src/api/global_.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@
# This program is Free Software and is released under the terms of
# the GNU General License
# ----------------------------------------------------------------------
from typing import Dict, Final, List, NamedTuple, Optional, Set
from __future__ import annotations

from typing import TYPE_CHECKING, Dict, Final, List, NamedTuple, Optional, Set

from src.api.constants import TYPE, LoopType
from src.api.opcodestemps import OpcodesTemps

if TYPE_CHECKING:
from src.symbols.id_ import SymbolID


# ----------------------------------------------------------------------
# Simple global container for internal constants.
# Internal constants might be architecture dependant. They're set
Expand Down Expand Up @@ -86,7 +92,7 @@ class LoopInfo(NamedTuple):
# Function calls pending to check
# Each scope pushes (prepends) an empty list
# ----------------------------------------------------------------------
FUNCTION_CALLS = []
FUNCTION_CALLS: list[SymbolID] = []

# ----------------------------------------------------------------------
# Function level entry ID in which scope we are in. If the list
Expand All @@ -102,7 +108,7 @@ class LoopInfo(NamedTuple):
# ----------------------------------------------------------------------
# FUNCTIONS pending to translate after parsing stage
# ----------------------------------------------------------------------
FUNCTIONS = []
FUNCTIONS: list[SymbolID] = []

# ----------------------------------------------------------------------
# Parameter alignment. Must be set by arch.<arch>.__init__
Expand All @@ -112,7 +118,7 @@ class LoopInfo(NamedTuple):
# ----------------------------------------------------------------------
# Data type used for array boundaries. Must be an integral
# ----------------------------------------------------------------------
BOUND_TYPE = None # Set to None, so if not set will raise error
BOUND_TYPE: TYPE # Unset, so if not set will raise error

# ----------------------------------------------------------------------
# Data type used for elements size. Must be an integral type
Expand Down Expand Up @@ -155,7 +161,7 @@ class LoopInfo(NamedTuple):
# ----------------------------------------------------------------------
# Type used internally for pointer and memory addresses
# ----------------------------------------------------------------------
PTR_TYPE = None
PTR_TYPE: TYPE # Unset, so if not set will raise error

# ----------------------------------------------------------------------
# Character used for name mangling. Usually '_' or '.'
Expand Down
3 changes: 2 additions & 1 deletion src/api/symboltable/symboltable.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@
warning_implicit_type,
warning_not_used,
)
from src.api.symboltable.scope import Scope
from src.symbols import sym as symbols
from src.symbols.symbol_ import Symbol

from .scope import Scope


class SymbolTable:
"""Implements a symbol table.
Expand Down
12 changes: 9 additions & 3 deletions src/arch/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:ts=4:et:sw=4:

# ----------------------------------------------------------------------
# Copyleft (K), Jose M. Rodriguez-Rosa (a.k.a. Boriel)
#
# This program is Free Software and is released under the terms of
# the GNUv3 General License
# ----------------------------------------------------------------------

import importlib
from types import ModuleType

__all__ = (
"zx48k",
"zxnext",
)

AVAILABLE_ARCHITECTURES = __all__
target = None
target: ModuleType


def set_target_arch(target_arch: str):
Expand Down
3 changes: 0 additions & 3 deletions src/arch/z80/optimizer/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,4 @@
JUMP_LABELS: Final[set[str]] = set()
MEMORY: Final[list[MemCell]] = [] # Instructions emitted by the backend

# PROC labels name space counter
PROC_COUNTER = 0

BLOCKS: Final[list[BasicBlock]] = [] # Memory blocks
40 changes: 21 additions & 19 deletions src/arch/z80/optimizer/main.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from collections import defaultdict

from src.api.config import OPTIONS
from src.api.debug import __DEBUG__
from src.api.utils import flatten_list
Expand All @@ -8,10 +10,14 @@
from .common import JUMP_LABELS, LABELS, MEMORY
from .helpers import ALL_REGS, END_PROGRAM_LABEL
from .labelinfo import LabelInfo
from .memcell import MemCell
from .patterns import RE_LABEL, RE_PRAGMA

__all__ = "init", "optimize"

# PROC labels name space counter
PROC_COUNTER: int = 0


def init():
LABELS.clear()
Expand Down Expand Up @@ -68,19 +74,19 @@ def cleanup_local_labels(block: BasicBlock) -> None:
"""
global PROC_COUNTER

stack = [[]]
hashes = [{}]
stackprc = [PROC_COUNTER]
used = [{}] # List of hashes of unresolved labels per scope
stack: list[list[str]] = [[]]
hashes: list[dict[str, str]] = [{}]
stackprc: list[int] = [PROC_COUNTER]
used: list[dict[str, list[MemCell]]] = [defaultdict(list)] # List of hashes of unresolved labels per scope

MEMORY[:] = block.mem[:]

for cell in MEMORY:
if cell.inst.upper() == "PROC":
stack += [[]]
hashes += [{}]
stackprc += [PROC_COUNTER]
used += [{}]
stack.append([])
hashes.append({})
stackprc.append(PROC_COUNTER)
used.append(defaultdict(list))
PROC_COUNTER += 1
continue

Expand All @@ -99,26 +105,25 @@ def cleanup_local_labels(block: BasicBlock) -> None:
continue

tmp = cell.asm.asm
if tmp.upper()[:5] == "LOCAL":
if tmp.upper().startswith("LOCAL"):
tmp = tmp[5:].split(",")
for lbl in tmp:
lbl = lbl.strip()
if lbl in stack[-1]:
continue
stack[-1] += [lbl]
hashes[-1][lbl] = "PROC%i." % stackprc[-1] + lbl
if used[-1].get(lbl, None) is None:
used[-1][lbl] = []

cell.asm = ";" + cell.asm # Remove it
stack[-1].append(lbl)
hashes[-1][lbl] = f"PROC{stackprc[-1]}.{lbl}"

cell.asm = f";{str(cell.asm)}" # Remove it
continue

if cell.is_label:
label = cell.inst
for i in range(len(stack) - 1, -1, -1):
if label in stack[i]:
label = hashes[i][label]
cell.asm = label + ":"
cell.asm = f"{label}:"
break
continue

Expand All @@ -132,10 +137,7 @@ def cleanup_local_labels(block: BasicBlock) -> None:
break

if not labelUsed:
if used[-1].get(label, None) is None:
used[-1][label] = []

used[-1][label] += [cell]
used[-1][label].append(cell)

for i in range(len(MEMORY) - 1, -1, -1):
if MEMORY[i].asm.asm[0] == ";":
Expand Down
6 changes: 3 additions & 3 deletions src/ast/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
# -*- coding: utf-8 -*-

import collections.abc
from typing import Iterable, List, Optional, Union
from typing import Iterable, Optional, Union

from src.api.exception import Error

__all__ = ["NotAnAstError", "Tree", "ChildrenList"]
__all__ = "NotAnAstError", "Tree", "ChildrenList"


class NotAnAstError(Error):
Expand Down Expand Up @@ -81,7 +81,7 @@ class ChildrenList:
def __init__(self, node: Tree):
assert isinstance(node, Tree)
self.owner = node # Node having this children
self._children: List[Tree] = []
self._children: list[Tree | None] = []

def __getitem__(self, key: Union[int, slice]):
if isinstance(key, int):
Expand Down
21 changes: 9 additions & 12 deletions src/zxbc/args_config.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
#!/usr/bin/env python3

from __future__ import annotations
import os
from typing import List
from typing import TYPE_CHECKING

import src.api.config
import src.api.global_ as gl
from src import arch
from src.api import debug, errmsg
from src.api.config import OPTIONS
from src.api.utils import open_file
from src.zxbc import args_parser, zxbparser
from src.zxbc import args_parser

if TYPE_CHECKING:
from argparse import Namespace

__all__ = ["FileType", "parse_options", "set_option_defines"]

Expand All @@ -21,7 +24,7 @@ class FileType:
TZX = "tzx"


def parse_options(args: List[str] = None):
def parse_options(args: list[str] | None = None) -> Namespace:
"""Parses command line options and setup global Options container"""
parser = args_parser.parser()
options = parser.parse_args(args=args)
Expand Down Expand Up @@ -56,7 +59,6 @@ def parse_options(args: List[str] = None):

if options.arch not in arch.AVAILABLE_ARCHITECTURES:
parser.error(f"Invalid architecture '{options.arch}'")
return 2

OPTIONS.architecture = options.arch

Expand All @@ -67,7 +69,6 @@ def parse_options(args: List[str] = None):

if duplicated_options:
parser.error(f"Warning(s) {', '.join(duplicated_options)} cannot be enabled " f"and disabled simultaneously")
return 2

for warn_code in enabled_warnings:
errmsg.enable_warning(warn_code)
Expand Down Expand Up @@ -103,15 +104,12 @@ def parse_options(args: List[str] = None):

if options.basic and not options.tzx and not options.tap:
parser.error("Option --BASIC and --autorun requires --tzx or tap format")
return 4

if options.append_binary and not options.tzx and not options.tap:
parser.error("Option --append-binary needs either --tap or --tzx")
return 5

if options.asm and options.memory_map:
parser.error("Option --asm and --mmap cannot be used together")
return 6

OPTIONS.use_basic_loader = options.basic
OPTIONS.autorun = options.autorun
Expand All @@ -128,12 +126,11 @@ def parse_options(args: List[str] = None):
args = [options.PROGRAM]
if not os.path.exists(options.PROGRAM):
parser.error("No such file or directory: '%s'" % args[0])
return 2

set_option_defines()

OPTIONS.include_path = options.include_path
OPTIONS.input_filename = zxbparser.FILENAME = os.path.basename(args[0])
OPTIONS.input_filename = os.path.basename(args[0])

if not OPTIONS.output_filename:
OPTIONS.output_filename = (
Expand All @@ -146,7 +143,7 @@ def parse_options(args: List[str] = None):
return options


def set_option_defines():
def set_option_defines() -> None:
"""Sets some macros automatically, according to options"""
if OPTIONS.memory_check:
OPTIONS.__DEFINES["__MEMORY_CHECK__"] = ""
Expand Down
25 changes: 12 additions & 13 deletions src/zxbc/zxbparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,13 @@
from math import pi as PI

# typings
from typing import List, NamedTuple, Optional
from typing import NamedTuple, Optional

import src.api.config
import src.api.dataref
import src.api.options
import src.api.symboltable

# Compiler API
import src.api.symboltable.symboltable
import src.api.utils

# Lexers and parsers, etc
import src.ply.yacc as yacc

# Symbol Classes
from src import arch

Expand All @@ -54,6 +47,12 @@
from src.api.errmsg import error, warning
from src.api.global_ import LoopInfo
from src.api.opcodestemps import OpcodesTemps

# Compiler API
from src.api.symboltable.symboltable import SymbolTable

# Lexers and parsers, etc
from src.ply import yacc
from src.symbols import sym
from src.symbols.id_ import SymbolID
from src.symbols.symbol_ import Symbol
Expand All @@ -65,7 +64,7 @@
# Function level entry ID in which scope we are into. If the list
# is empty, we are at global scope
# ----------------------------------------------------------------------
FUNCTION_LEVEL: List[SymbolID] = gl.FUNCTION_LEVEL
FUNCTION_LEVEL: list[SymbolID] = gl.FUNCTION_LEVEL

# ----------------------------------------------------------------------
# Function calls pending to check
Expand All @@ -81,7 +80,7 @@
# ----------------------------------------------------------------------
# Global Symbol Table
# ----------------------------------------------------------------------
SYMBOL_TABLE = gl.SYMBOL_TABLE = src.api.symboltable.symboltable.SymbolTable()
SYMBOL_TABLE = gl.SYMBOL_TABLE = SymbolTable()

# ----------------------------------------------------------------------
# Defined user labels. They all are prepended _label_. Line numbers 10,
Expand All @@ -92,17 +91,17 @@
# ----------------------------------------------------------------------
# True if we're in the middle of a LET sentence. False otherwise.
# ----------------------------------------------------------------------
LET_ASSIGNMENT = False
LET_ASSIGNMENT: bool = False

# ----------------------------------------------------------------------
# True if PRINT sentence has been used.
# ----------------------------------------------------------------------
PRINT_IS_USED = False
PRINT_IS_USED: bool = False

# ----------------------------------------------------------------------
# Last line number output for checking program key board BREAK
# ----------------------------------------------------------------------
last_brk_linenum = 0
last_brk_linenum: int = 0


# ----------------------------------------------------------------------
Expand Down