diff --git a/.pylintrc b/.pylintrc index 8f6ec9e..f8c5e34 100644 --- a/.pylintrc +++ b/.pylintrc @@ -452,8 +452,7 @@ timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests. # List of note tags to take in consideration, separated by a comma. notes=FIXME, - XXX, - TODO + XXX # Regular expression of note tags to take in consideration. notes-rgx= diff --git a/nada_dsl/nada_types/__init__.py b/nada_dsl/nada_types/__init__.py index b313729..9aff870 100644 --- a/nada_dsl/nada_types/__init__.py +++ b/nada_dsl/nada_types/__init__.py @@ -1,10 +1,10 @@ """Nada type definitions.""" +from abc import ABC, abstractmethod from dataclasses import dataclass from enum import Enum -from typing import Any, Dict, TypeAlias, Union, Type +from typing import Dict, TypeAlias, Union, Type from nada_dsl.source_ref import SourceRef -from abc import abstractmethod @dataclass @@ -147,15 +147,6 @@ def __init__(self, child: OperationType): if self.child is not None: self.child.store_in_ast(self.metatype().to_mir()) - # @classmethod - # def class_to_mir(cls) -> str: - # """Converts a class into a MIR Nada type.""" - # name = cls.__name__ - # # Rename public variables so they are considered as the same as literals. - # if name.startswith("Public"): - # name = name[len("Public") :].lstrip() - # return name - def __bool__(self): raise NotImplementedError @@ -168,3 +159,7 @@ def is_scalar(cls) -> bool: def is_literal(cls) -> bool: """Returns True if the type is a literal.""" return False + + @abstractmethod + def metatype(self): + """Returns a meta type for this NadaType.""" diff --git a/nada_dsl/nada_types/collections.py b/nada_dsl/nada_types/collections.py index 7735f5b..0f4c7f4 100644 --- a/nada_dsl/nada_types/collections.py +++ b/nada_dsl/nada_types/collections.py @@ -1,12 +1,8 @@ """Nada Collection type definitions.""" -import copy from dataclasses import dataclass -import inspect -import traceback from typing import Any, Dict, Generic, List import typing -from typing import TypeVar from nada_dsl.ast_util import ( AST_OPERATIONS, @@ -114,14 +110,15 @@ def store_in_ast(self, ty): class TupleMetaType(MetaType): """Marker type for Tuples.""" + is_compound = True def __init__(self, left_type: MetaType, right_type: MetaType): self.left_type = left_type self.right_type = right_type - def instantiate(self, child): - return Tuple(child, self.left_type, self.right_type) + def instantiate(self, child_or_value): + return Tuple(child_or_value, self.left_type, self.right_type) def to_mir(self): """Convert a tuple object into a Nada type.""" @@ -164,6 +161,7 @@ def generic_type(cls, left_type: U, right_type: T) -> TupleMetaType: return TupleMetaType(left_type=left_type, right_type=right_type) def metatype(self): + """Metatype for Tuple""" return TupleMetaType(self.left_type, self.right_type) @@ -175,13 +173,14 @@ def _generate_accessor(ty: Any, accessor: Any) -> NadaType: class NTupleMetaType(MetaType): """Marker type for NTuples.""" + is_compound = True def __init__(self, types: List[MetaType]): self.types = types - def instantiate(self, child): - return NTuple(child, self.types) + def instantiate(self, child_or_value): + return NTuple(child_or_value, self.types) def to_mir(self): """Convert a tuple object into a Nada type.""" @@ -228,6 +227,7 @@ def __getitem__(self, index: int) -> NadaType: return _generate_accessor(self.types[index], accessor) def metatype(self): + """Metatype for NTuple""" return NTupleMetaType(self.types) @@ -263,6 +263,7 @@ def store_in_ast(self, ty: object): class ObjectMetaType(MetaType): """Marker type for Objects.""" + is_compound = True def __init__(self, types: Dict[str, MetaType]): @@ -271,13 +272,11 @@ def __init__(self, types: Dict[str, MetaType]): def to_mir(self): """Convert an object into a Nada type.""" return { - "Object": { - "types": { name: ty.to_mir() for name, ty in self.types.items() } - } + "Object": {"types": {name: ty.to_mir() for name, ty in self.types.items()}} } - def instantiate(self, child): - return Object(child, self.types) + def instantiate(self, child_or_value): + return Object(child_or_value, self.types) @dataclass @@ -318,6 +317,7 @@ def __getattr__(self, attr: str) -> NadaType: return _generate_accessor(self.types[attr], accessor) def metatype(self): + """Metatype for Object""" return ObjectMetaType(types=self.types) @@ -411,10 +411,11 @@ def store_in_ast(self, ty: NadaTypeRepr): ty=ty, ) + class ArrayMetaType(MetaType): """Marker type for arrays.""" - is_compound = True + is_compound = True def __init__(self, contained_type: AllTypesType, size: int): self.contained_type = contained_type @@ -428,13 +429,15 @@ def to_mir(self): # so we now the size of the array if self.size is None: raise NotImplementedError("ArrayMetaType.to_mir") - size = {"size": self.size} if self.size else {} return { - "Array": {"inner_type": self.contained_type.to_mir(), **size} # TODO: why? + "Array": { + "inner_type": self.contained_type.to_mir(), + "size": self.size, + } } - def instantiate(self, child): - return Array(child, self.size, self.contained_type) + def instantiate(self, child_or_value): + return Array(child_or_value, self.size, self.contained_type) @dataclass @@ -473,8 +476,11 @@ def __iter__(self): ) def check_not_constant(self, ty): + """Checks that a type is not a constant""" if ty.is_constant: - raise NotAllowedException("functors (map and reduce) can't be called with constant args") + raise NotAllowedException( + "functors (map and reduce) can't be called with constant args" + ) def map(self: "Array[T]", function) -> "Array": """The map operation for Arrays.""" @@ -490,7 +496,9 @@ def reduce(self: "Array[T]", function, initial: R) -> R: """The Reduce operation for arrays.""" self.check_not_constant(self.contained_type) self.check_not_constant(initial.metatype()) - function = create_nada_fn(function, args_ty=[initial.metatype(), self.contained_type]) + function = create_nada_fn( + function, args_ty=[initial.metatype(), self.contained_type] + ) return function.return_type.instantiate( Reduce( child=self, @@ -525,9 +533,7 @@ def inner_product(self: "Array[T]", other: "Array[T]") -> T: ): return self.contained_type.instantiate( - child=InnerProduct( - left=self, right=other, source_ref=SourceRef.back_frame() - ) + InnerProduct(left=self, right=other, source_ref=SourceRef.back_frame()) ) # type: ignore raise InvalidTypeError( @@ -554,6 +560,7 @@ def new(cls, *args) -> "Array[T]": ) def metatype(self): + """Metatype for Array""" return ArrayMetaType(self.contained_type, self.size) diff --git a/nada_dsl/nada_types/function.py b/nada_dsl/nada_types/function.py index 28d1c3b..8b08f10 100644 --- a/nada_dsl/nada_types/function.py +++ b/nada_dsl/nada_types/function.py @@ -6,7 +6,6 @@ import inspect from dataclasses import dataclass from typing import Generic, List, Callable -from copy import copy from nada_dsl import SourceRef from nada_dsl.ast_util import ( AST_OPERATIONS, @@ -16,9 +15,7 @@ next_operation_id, ) from nada_dsl.nada_types.generics import T, R -from nada_dsl.nada_types import Mode, NadaType -from nada_dsl.nada_types.scalar_types import ScalarType -from nada_dsl.errors import NotAllowedException +from nada_dsl.nada_types import NadaType class NadaFunctionArg(Generic[T]): @@ -121,6 +118,7 @@ def store_in_ast(self, ty): ty=ty, ) + def create_nada_fn(fn, args_ty) -> NadaFunction[T, R]: """ Can be used also for lambdas diff --git a/nada_dsl/nada_types/scalar_types.py b/nada_dsl/nada_types/scalar_types.py index 964ac37..50d513a 100644 --- a/nada_dsl/nada_types/scalar_types.py +++ b/nada_dsl/nada_types/scalar_types.py @@ -350,30 +350,36 @@ def binary_logical_operation( class MetaType(ABC): + """Abstract meta type""" + is_constant = False is_scalar = False is_compound = False @abstractmethod - def to_mir(self): - pass + def instantiate(self, child_or_value): + """Creates a value corresponding to this meta type""" @abstractmethod - def instantiate(self, child_or_value): - pass + def to_mir(self): + """Returns a MIR representation of this meta type""" class MetaTypePassthroughMixin(MetaType): - @classmethod - def instantiate(cls, child_or_value): - return cls.ty(child_or_value) + """Mixin for meta types""" - @classmethod - def to_mir(cls): - name = cls.ty.__name__ + def instantiate(self, child_or_value): + """Creates a value corresponding to this meta type""" + return self.ty(child_or_value) + + def to_mir(self): + name = self.ty.__name__ # Rename public variables so they are considered as the same as literals. if name.startswith("Public"): name = name[len("Public") :].lstrip() + + if name.endswith("MetaType"): + name = name[: -len("MetaType")].rstrip() return name @@ -399,16 +405,18 @@ def __eq__(self, other) -> AnyBoolean: def is_literal(cls) -> bool: return True - @classmethod - def metatype(cls): + def metatype(self): return IntegerMetaType() class IntegerMetaType(MetaTypePassthroughMixin): + """Meta type for integers""" + ty = Integer is_constant = True is_scalar = True + @dataclass @register_scalar_type(Mode.CONSTANT, BaseType.UNSIGNED_INTEGER) class UnsignedInteger(NumericType): @@ -434,12 +442,13 @@ def __eq__(self, other) -> AnyBoolean: def is_literal(cls) -> bool: return True - @classmethod - def metatype(cls): + def metatype(self): return UnsignedIntegerMetaType() class UnsignedIntegerMetaType(MetaTypePassthroughMixin): + """Meta type for unsigned integers""" + ty = UnsignedInteger is_constant = True is_scalar = True @@ -475,12 +484,13 @@ def __invert__(self: "Boolean") -> "Boolean": def is_literal(cls) -> bool: return True - @classmethod - def metatype(cls): + def metatype(self): return BooleanMetaType() class BooleanMetaType(MetaTypePassthroughMixin): + """Meta type for booleans""" + ty = Boolean is_constant = True is_scalar = True @@ -505,12 +515,13 @@ def public_equals( """Implementation of public equality for Public integer types.""" return public_equals_operation(self, other) - @classmethod - def metatype(cls): + def metatype(self): return PublicIntegerMetaType() class PublicIntegerMetaType(MetaTypePassthroughMixin): + """Meta type for public integers""" + ty = PublicInteger is_scalar = True @@ -534,12 +545,13 @@ def public_equals( """Implementation of public equality for Public unsigned integer types.""" return public_equals_operation(self, other) - @classmethod - def metatype(cls): + def metatype(self): return PublicUnsignedIntegerMetaType() class PublicUnsignedIntegerMetaType(MetaTypePassthroughMixin): + """Meta type for public unsigned integers""" + ty = PublicUnsignedInteger is_scalar = True @@ -568,12 +580,13 @@ def public_equals( """Implementation of public equality for Public boolean types.""" return public_equals_operation(self, other) - @classmethod - def metatype(cls): + def metatype(self): return PublicBooleanMetaType() class PublicBooleanMetaType(MetaTypePassthroughMixin): + """Meta type for public booleans""" + ty = PublicBoolean is_scalar = True @@ -622,12 +635,13 @@ def to_public(self: "SecretInteger") -> "PublicInteger": operation = Reveal(this=self, source_ref=SourceRef.back_frame()) return PublicInteger(child=operation) - @classmethod - def metatype(cls): + def metatype(self): return SecretIntegerMetaType() class SecretIntegerMetaType(MetaTypePassthroughMixin): + """Meta type for secret integers""" + ty = SecretInteger is_scalar = True @@ -678,12 +692,13 @@ def to_public( operation = Reveal(this=self, source_ref=SourceRef.back_frame()) return PublicUnsignedInteger(child=operation) - @classmethod - def metatype(cls): + def metatype(self): return SecretUnsignedIntegerMetaType() class SecretUnsignedIntegerMetaType(MetaTypePassthroughMixin): + """Meta type for secret unsigned integers""" + ty = SecretUnsignedInteger is_scalar = True @@ -713,12 +728,13 @@ def random(cls) -> "SecretBoolean": """Generate a random secret boolean.""" return SecretBoolean(child=Random(source_ref=SourceRef.back_frame())) - @classmethod - def metatype(cls): + def metatype(self): return SecretBooleanMetaType() class SecretBooleanMetaType(MetaTypePassthroughMixin): + """Meta type for secret booleans""" + ty = SecretBoolean is_scalar = True @@ -730,12 +746,13 @@ class EcdsaSignature(NadaType): def __init__(self, child: OperationType): super().__init__(child=child) - @classmethod - def metatype(cls): + def metatype(self): return EcdsaSignatureMetaType() class EcdsaSignatureMetaType(MetaTypePassthroughMixin): + """Meta type for EcdsaSignatures""" + ty = EcdsaSignature @@ -746,12 +763,13 @@ class EcdsaDigestMessage(NadaType): def __init__(self, child: OperationType): super().__init__(child=child) - @classmethod - def metatype(cls): + def metatype(self): return EcdsaDigestMessageMetaType() class EcdsaDigestMessageMetaType(MetaTypePassthroughMixin): + """Meta type for EcdsaDigestMessages""" + ty = EcdsaDigestMessage @@ -768,10 +786,11 @@ def ecdsa_sign(self, digest: "EcdsaDigestMessage") -> "EcdsaSignature": child=EcdsaSign(left=self, right=digest, source_ref=SourceRef.back_frame()) ) - @classmethod - def metatype(cls): + def metatype(self): return EcdsaPrivateKeyMetaType() class EcdsaPrivateKeyMetaType(MetaTypePassthroughMixin): + """Meta type for EcdsaPrivateKeys""" + ty = EcdsaPrivateKey diff --git a/nada_dsl/program_io.py b/nada_dsl/program_io.py index 7d23d26..308d2a0 100644 --- a/nada_dsl/program_io.py +++ b/nada_dsl/program_io.py @@ -55,6 +55,7 @@ def store_in_ast(self, ty: object): ) +@dataclass class Literal(NadaType): """ Represents a literal value.