Skip to content

Commit

Permalink
Significant cleanup of type hinting. #242
Browse files Browse the repository at this point in the history
  • Loading branch information
amykyta3 committed Dec 27, 2024
1 parent 2e18075 commit aeeedda
Show file tree
Hide file tree
Showing 41 changed files with 445 additions and 284 deletions.
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ dependencies = [
"antlr4-python3-runtime >= 4.11, < 4.14",
"colorama",
"markdown",
"typing_extensions",
]
authors = [
{name="Alex Mykyta"},
Expand Down
6 changes: 5 additions & 1 deletion src/systemrdl/ast/cast.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
if TYPE_CHECKING:
from ..compiler import RDLEnvironment
from ..source_ref import SourceRefBase
from rdltypes.typing import PreElabRDLType
from ..rdltypes.typing import PreElabRDLType

OptionalSourceRef = Optional[SourceRefBase]

Expand All @@ -22,6 +22,7 @@ class WidthCast(ASTNode):
def __init__(self, env: 'RDLEnvironment', src_ref: 'OptionalSourceRef', v: ASTNode, w_expr: Optional[ASTNode]=None, w_int: int=64):
super().__init__(env, src_ref)

self.w_expr: Optional[ASTNode]
if w_expr is not None:
self.v = v
self.w_expr = w_expr
Expand All @@ -33,6 +34,7 @@ def __init__(self, env: 'RDLEnvironment', src_ref: 'OptionalSourceRef', v: ASTNo

def predict_type(self) -> Type[int]:
if self.cast_width is None:
assert self.w_expr is not None # mutually exclusive
if not is_castable(self.w_expr.predict_type(), int):
self.msg.fatal(
"Width operand of cast expression is not a compatible numeric type",
Expand All @@ -48,13 +50,15 @@ def predict_type(self) -> Type[int]:

def get_min_eval_width(self) -> int:
if self.cast_width is None:
assert self.w_expr is not None # mutually exclusive
self.cast_width = int(self.w_expr.get_value())
return self.cast_width


def get_value(self, eval_width: Optional[int]=None) -> int:
# Truncate to cast width instead of eval width
if self.cast_width is None:
assert self.w_expr is not None # mutually exclusive
self.cast_width = int(self.w_expr.get_value())
if self.cast_width == 0:
self.msg.fatal(
Expand Down
6 changes: 3 additions & 3 deletions src/systemrdl/ast/conditional.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
if TYPE_CHECKING:
from ..compiler import RDLEnvironment
from ..source_ref import SourceRefBase
from rdltypes.typing import PreElabRDLType
from ..rdltypes.typing import PreElabRDLType

OptionalSourceRef = Optional[SourceRefBase]

Expand All @@ -21,7 +21,7 @@ def __init__(self, env: 'RDLEnvironment', src_ref: 'OptionalSourceRef', i: ASTNo
self.i = i
self.j = j
self.k = k
self.is_numeric = None # type: bool
self.is_numeric: bool = False

def predict_type(self) -> 'PreElabRDLType':
t_i = self.i.predict_type()
Expand All @@ -35,7 +35,7 @@ def predict_type(self) -> 'PreElabRDLType':
t_j = self.j.predict_type()
t_k = self.k.predict_type()

typ = None # type: Any
typ: Any = None
if is_castable(t_j, int) and is_castable(t_k, int):
self.is_numeric = True
typ = int
Expand Down
2 changes: 1 addition & 1 deletion src/systemrdl/ast/literals.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
if TYPE_CHECKING:
from ..compiler import RDLEnvironment
from ..source_ref import SourceRefBase
from rdltypes.typing import PreElabRDLType, RDLValue
from ..rdltypes.typing import PreElabRDLType, RDLValue

OptionalSourceRef = Optional[SourceRefBase]

Expand Down
15 changes: 10 additions & 5 deletions src/systemrdl/ast/references.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from ..compiler import RDLEnvironment
from ..core.parameter import Parameter
from ..source_ref import SourceRefBase
from rdltypes.typing import PreElabRDLType, RDLValue
from ..rdltypes.typing import PreElabRDLType

OptionalSourceRef = Optional[SourceRefBase]

Expand Down Expand Up @@ -59,7 +59,12 @@ def predict_type(self) -> 'PreElabRDLType':
"Cannot index non-array type",
self.array.src_ref
)
assert isinstance(array_type, rdltypes.ArrayedType)
if array_type.element_type is None:
# Array type is not known, therefore it must be an emptyy array.
self.msg.fatal(
"Array is empty. Cannot index",
self.array.src_ref
)

return array_type.element_type

Expand Down Expand Up @@ -162,7 +167,8 @@ def predict_type(self) -> Type[comp.Component]:
referenced.
Also do some checks on the array indexes
"""
current_comp = self.ref_root
current_comp: Optional[comp.Component] = self.ref_root
assert current_comp is not None
for name, array_suffixes, name_src_ref in self.ref_elements:

# find instance
Expand All @@ -179,8 +185,7 @@ def predict_type(self) -> Type[comp.Component]:
array_suffix.predict_type()

# Check array suffixes
if (isinstance(current_comp, comp.AddressableComponent)) and current_comp.is_array:
assert isinstance(current_comp.array_dimensions, list)
if (isinstance(current_comp, comp.AddressableComponent)) and current_comp.array_dimensions:
# is an array
if len(array_suffixes) != len(current_comp.array_dimensions):
self.msg.fatal(
Expand Down
2 changes: 1 addition & 1 deletion src/systemrdl/ast/relational.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __init__(self, env: 'RDLEnvironment', src_ref: 'OptionalSourceRef', l: ASTNo
super().__init__(env, src_ref)
self.l = l
self.r = r
self.is_numeric = None # type: bool
self.is_numeric: bool = False

def predict_type(self) -> Type[bool]:
l_type = self.l.predict_type()
Expand Down
9 changes: 4 additions & 5 deletions src/systemrdl/ast/sequence.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Concatenate(ASTNode):
def __init__(self, env: 'RDLEnvironment', src_ref: 'OptionalSourceRef', elements: List[ASTNode]):
super().__init__(env, src_ref)
self.elements = elements
self.type = None # type: Union[Type[int], Type[str]]
self.type: Union[Type[int], Type[str]] = int

def predict_type(self) -> Union[Type[int], Type[str]]:
element_iter = iter(self.elements)
Expand Down Expand Up @@ -73,11 +73,10 @@ def __init__(self, env: 'RDLEnvironment', src_ref: 'OptionalSourceRef', reps: AS
super().__init__(env, src_ref)
self.reps = reps
self.concat = concat
self.type = None # type: Union[Type[int], Type[str]]
self.reps_value = None # type: int
self.type: Union[Type[int], Type[str]] = int
self.reps_value: Optional[int] = None

def predict_type(self):
# type: () -> Union[Type[int], Type[str]]
def predict_type(self) -> Union[Type[int], Type[str]]:

if not is_castable(self.reps.predict_type(), int):
self.msg.fatal(
Expand Down
24 changes: 17 additions & 7 deletions src/systemrdl/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ def included_files(self) -> Iterable[str]:


class RDLCompiler:

def __init__(self, **kwargs: Any):
"""
RDLCompiler constructor.
Expand Down Expand Up @@ -110,14 +109,14 @@ def __init__(self, **kwargs: Any):
#: This will be deprecated in a future release. See this page for more details: https://github.com/SystemRDL/systemrdl-compiler/issues/168
self.msg = self.env.msg

self.namespace = NamespaceRegistry(self.env) # type: NamespaceRegistry
self.visitor = RootVisitor(self)
self.root = self.visitor.component # type: comp.Root # type: ignore
self.namespace: NamespaceRegistry = NamespaceRegistry(self.env)
self.visitor: RootVisitor = RootVisitor(self)
self.root = self.visitor.component


def define_udp(
self, name: str, valid_type: Any,
valid_components: 'Optional[Set[Type[comp.Component]]]'=None,
valid_components: Optional[Set[Type[comp.Component]]]=None,
default: Any=None
) -> None:

Expand All @@ -130,6 +129,15 @@ def define_udp(
raise ValueError(f"UDP definition's name '{name}' conflicts with existing built-in RDL property")
if name in self.env.property_rules.user_properties:
raise ValueError(f"UDP '{name}' has already been defined")
if valid_components is None:
valid_components = {
comp.Field,
comp.Reg,
comp.Regfile,
comp.Addrmap,
comp.Mem,
comp.Signal,
}

udp = LegacyExternalUserProperty(
self.env,
Expand Down Expand Up @@ -386,8 +394,10 @@ def elaborate(self, top_def_name: Optional[str]=None, inst_name: Optional[str]=N

literal_expr = ast.ExternalLiteral(self.env, value)
assign_expr = ast.AssignmentCast(self.env, None, literal_expr, parameter.param_type)
assign_type = assign_expr.predict_type()
if assign_type is None:
try:
# Try to predict type to test if ExternalLiteral maps to a valid RDL type
assign_expr.predict_type()
except ValueError:
self.msg.fatal(f"Incorrect type for top-level parameter override of '{param_name}'")

parameter.expr = assign_expr
Expand Down
Loading

0 comments on commit aeeedda

Please sign in to comment.