Skip to content
Draft
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
1 change: 0 additions & 1 deletion python/src/hhat_lang/core/code/ir.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ def __init__(self):

def push(self, new_item: Any, to_instr_fn: Callable | None = None) -> None:
if not isinstance(new_item, InstrIR | BlockIR):

if to_instr_fn is not None:
new_item = to_instr_fn(new_item)

Expand Down
1 change: 0 additions & 1 deletion python/src/hhat_lang/core/code/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ def check_quantum_type_correctness(names: tuple[str, ...]) -> None:
prev_quantum = False
cur_quantum = False
for n, name in enumerate(names):

if n != 0 and cur_quantum and not prev_quantum:
raise ValueError(
f"{name} is an attribute from a non-quantum symbol. "
Expand Down
6 changes: 1 addition & 5 deletions python/src/hhat_lang/core/data/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@


class InvalidType:
"""It just exists to be used as 'default' instance for the `ACCEPTABLE_VALUES` above."""
"""It just exists to be used as 'default' instance for the ``ACCEPTABLE_VALUES`` above."""

pass

Expand Down Expand Up @@ -185,10 +185,6 @@ def __init__(self, value: str, lit_type: str):
self._suppress_type = False
self._bin_form = bin(int(value.strip("@")))[2:]

@property
def value(self) -> str:
return self._value

@property
def bin(self) -> str:
return self._bin_form
Expand Down
142 changes: 142 additions & 0 deletions python/src/hhat_lang/core/data/fn_def.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Any, Iterable

from hhat_lang.core.data.core import Symbol, CompositeSymbol


class BaseFnKey:
"""
Base class for functions definition on memory's SymbolTable.
Provide functions a signature.

Given a function:

```
fn sum (a:u64 b:u64) u64 { ::add(a b) }
```

The function key object is as follows:

```
BaseFnKey(
name=Symbol("sum"),
type=Symbol("u64"),
args_names=(Symbol("a"), Symbol("b"),),
args_types=(Symbol("u64"), Symbol("u64"),)
)
```

When trying to retrieve the function data, use `BaseFnCheck`
parent instance instead:


"""

_name: Symbol
_type: Symbol | CompositeSymbol
_args_types: tuple | tuple[Symbol | CompositeSymbol, ...]
_args_names: tuple | tuple[Symbol, ...]

# TODO: implement code for comparison of out of order args_names

def __init__(
self,
fn_name: Symbol,
fn_type: Symbol | CompositeSymbol,
args_names: tuple | tuple[Symbol, ...],
args_types: tuple | tuple[Symbol | CompositeSymbol, ...],
):

# check correct types for each argument before proceeding
assert (
isinstance(fn_name, Symbol)
and isinstance(fn_type, Symbol | CompositeSymbol)
and all(isinstance(k, Symbol) for k in args_names)
and all(isinstance(p, Symbol | CompositeSymbol) for p in args_types),
f"Wrong types provided for function definition on SymbolTable:\n"
f" name: {fn_name}\n type: {fn_type}\n args types: {args_types}\n"
f" args names: {args_names}\n",
)

self._name = fn_name
self._type = fn_type
self._args_names = args_names
self._args_types = args_types

@property
def name(self) -> Symbol:
return self._name

@property
def type(self) -> Symbol | CompositeSymbol:
return self._type

@property
def args_types(self) -> tuple | tuple[Symbol | CompositeSymbol, ...]:
return self._args_types

@property
def args_names(self) -> tuple | tuple[Symbol, ...]:
return self._args_names

def __hash__(self) -> int:
return hash((self._name, self._type, self._args_types))

def __eq__(self, other: Any) -> bool:
if isinstance(other, BaseFnKey | BaseFnCheck):
return (
self._name == other._name
and self._type == other._type
and self._args_types == other._args_types
)

return False

def has_args(self, args: tuple[Symbol, ...]) -> bool:
return set(self._args_names) == set(args)


class BaseFnCheck:
"""
Base function class to check and retrieve a given function from the SymbolTable.
"""

_name: Symbol
_type: Symbol | CompositeSymbol
_args_types: tuple | tuple[Symbol | CompositeSymbol, ...]
_args_names: tuple | tuple[Symbol, ...]

def __init__(
self,
fn_name: Symbol,
fn_type: Symbol | CompositeSymbol,
args_types: tuple | tuple[Symbol | CompositeSymbol, ...],
):

# checks types correctness
assert (
isinstance(fn_name, Symbol)
and isinstance(fn_type, Symbol | CompositeSymbol)
and all(isinstance(p, Symbol | CompositeSymbol) for p in args_types),
f"Wrong types provided for function retrieval on SymbolTable:\n"
f" name: {fn_name}\n type: {fn_type}\n args types: {args_types}\n",
)

self._name = fn_name
self._type = fn_type
self._args_types = args_types

def __hash__(self) -> int:
return hash((self._name, self._type, self._args_types))

def __eq__(self, other: Any) -> bool:
if isinstance(other, BaseFnKey | BaseFnCheck):
return (
self._name == other._name
and self._type == other._type
and self._args_types == other._args_types
)

return False
24 changes: 0 additions & 24 deletions python/src/hhat_lang/core/data/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,9 @@ def _check_assign_ds_vals(
"""

if data.type == attr_type:

# is quantum or array data structure
if data.is_quantum or self._check_array_prop(data):

if attr_type in self._ds:

if attr_type in self._data:
self._data[attr_type].append(data)

Expand Down Expand Up @@ -168,10 +165,8 @@ def _check_assign_ds_args_vals(
"""

if key in self._ds:

# is quantum or array data structure
if key.is_quantum or self._check_array_prop(value):

if key in self._data:
self._data[key].append(value)

Expand Down Expand Up @@ -235,15 +230,12 @@ def __new__(
type_ds: SymbolOrdered,
flag: VariableKind = VariableKind.IMMUTABLE,
) -> BaseDataContainer | ErrorHandler:

# quantum variables are, at least for now, always appendable and thus mutable
if isquantum(var_name) and isquantum(type_name):
return AppendableVariable(var_name, type_name, type_ds, True)

if not isquantum(var_name) and not isquantum(type_name):

match flag:

# constant, at least for now, cannot be quantum
case VariableKind.CONSTANT:
return ConstantData(var_name, type_name, type_ds)
Expand Down Expand Up @@ -330,20 +322,14 @@ def assign(
*args: Any,
**kwargs: SymbolOrdered,
) -> None | ErrorHandler:

if not self._assigned:

if len(args) == len(self._ds):

for k, d in zip(args, self._ds):

if not self._check_assign_ds_vals(k, d):
return ContainerVarError(self.name)

elif len(kwargs) == len(self._ds):

for k, v in kwargs.items():

if not self._check_assign_ds_args_vals(Symbol(k), v):
return ContainerVarError(self.name)

Expand Down Expand Up @@ -391,18 +377,13 @@ def __init__(
def assign(
self, *args: Any, **kwargs: dict[WorkingData, WorkingData | BaseDataContainer]
) -> None | ErrorHandler:

if len(args) == len(self._ds):

for k, d in zip(args, self._ds):

if not self._check_assign_ds_vals(k, d):
return ContainerVarError(self.name)

elif len(kwargs) == len(self._ds):

for k, v in kwargs.items():

if not self._check_assign_ds_args_vals(Symbol(k), v):
return ContainerVarError(self.name)

Expand Down Expand Up @@ -451,18 +432,13 @@ def assign(
*args: Any,
**kwargs: SymbolOrdered,
) -> None | ErrorHandler:

if len(args) == len(self._ds):

for k, d in zip(args, self._ds):

if not self._check_assign_ds_vals(k, d):
return ContainerVarError(self.name)

elif len(kwargs) == len(self._ds):

for k, v in kwargs.items():

if not self._check_assign_ds_args_vals(Symbol(k), v):
return ContainerVarError(self.name)

Expand Down
20 changes: 20 additions & 0 deletions python/src/hhat_lang/core/error_handlers/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ class ErrorCodes(Enum):
HEAP_INVALID_KEY_ERROR = auto()
HEAP_EMPTY_ERROR = auto()

SYMBOLTABLE_INVALID_KEY_ERROR = auto()

INVALID_QUANTUM_COMPUTED_RESULT = auto()

INSTR_NOTFOUND_ERROR = auto()
Expand Down Expand Up @@ -304,6 +306,24 @@ def __call__(self) -> str:
return f"[[{self.__class__.__name__}]]: key '{self._key}' is invalid."


class SymbolTableInvalidKeyError(ErrorHandler):
def __init__(self, key: Any, key_type: str):
super().__init__(ErrorCodes.SYMBOLTABLE_INVALID_KEY_ERROR)
self._key = key
self._key_type = key_type

@classmethod
def Type(cls) -> str:
return "type"

@classmethod
def Fn(cls) -> str:
return "fn"

def __call__(self) -> str:
return f"[[{self.__class__.__name__}]]: key '{self._key}' is invalid for {self._key_type}."


class InvalidQuantumComputedResult(ErrorHandler):
def __init__(self, qdata: Any):
super().__init__(ErrorCodes.INVALID_QUANTUM_COMPUTED_RESULT)
Expand Down
3 changes: 2 additions & 1 deletion python/src/hhat_lang/core/execution/abstract_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from hhat_lang.core.error_handlers.errors import ErrorHandler
from hhat_lang.core.execution.abstract_base import BaseEvaluator
from hhat_lang.core.lowlevel.abstract_qlang import BaseLowLevelQLang
from hhat_lang.core.memory.core import BaseStack, IndexManager
from hhat_lang.core.memory.core import BaseStack, IndexManager, SymbolTable


class BaseProgram(ABC):
Expand All @@ -18,6 +18,7 @@ class BaseProgram(ABC):
_executor: BaseEvaluator
_qlang: BaseLowLevelQLang
_qstack: BaseStack
_symbol: SymbolTable

@abstractmethod
def run(self) -> Any | ErrorHandler: ...
16 changes: 13 additions & 3 deletions python/src/hhat_lang/core/lowlevel/abstract_qlang.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
from typing import Any

from hhat_lang.core.data.core import WorkingData
from hhat_lang.core.error_handlers.errors import ErrorHandler
from hhat_lang.core.error_handlers.errors import ErrorHandler, IndexInvalidVarError
from hhat_lang.core.execution.abstract_base import BaseEvaluator
from hhat_lang.core.memory.core import BaseStack, IndexManager
from hhat_lang.core.memory.core import BaseStack, IndexManager, SymbolTable
from hhat_lang.core.utils import Result
from hhat_lang.dialects.heather.code.simple_ir_builder.ir import IRBlock

Expand All @@ -23,6 +23,7 @@ class BaseLowLevelQLang(ABC):
_idx: IndexManager
_executor: BaseEvaluator
_qstack: BaseStack
_symbol: SymbolTable

def __init__(
self,
Expand All @@ -31,6 +32,7 @@ def __init__(
idx: IndexManager,
executor: BaseEvaluator,
qstack: BaseStack,
symboltable: SymbolTable,
*_args: Any,
**_kwargs: Any,
):
Expand All @@ -39,7 +41,15 @@ def __init__(
self._idx = idx
self._executor = executor
self._qstack = qstack
self._num_idxs = len(self._idx.in_use_by.get(self._qdata, []))
self._symbol = symboltable

match res := self._idx.in_use_by[self._qdata]:
case IndexInvalidVarError():
# TODO: handle this error properly
raise res

case _:
self._num_idxs = len(res)

@abstractmethod
def init_qlang(self) -> tuple[str, ...]: ...
Expand Down
Loading