Skip to content

Commit

Permalink
temporary
Browse files Browse the repository at this point in the history
  • Loading branch information
amadolid committed Sep 25, 2024
1 parent e70b6f6 commit b1e073b
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 93 deletions.
2 changes: 1 addition & 1 deletion jac/jaclang/cli/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
from jaclang.compiler.passes.tool.schedules import format_pass
from jaclang.plugin.builtin import dotgen
from jaclang.plugin.feature import JacFeature as Jac
from jaclang.runtimelib.constructs import WalkerArchitype
from jaclang.runtimelib.context import ExecutionContext
from jaclang.runtimelib.implementation import WalkerArchitype
from jaclang.runtimelib.machine import JacMachine, JacProgram
from jaclang.utils.helpers import debugger as db
from jaclang.utils.lang_tools import AstTool
Expand Down
15 changes: 5 additions & 10 deletions jac/jaclang/runtimelib/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

import unittest
from contextvars import ContextVar
from typing import Any, Callable, Optional, cast
from typing import Callable, Optional, cast
from uuid import UUID

from .interface import NodeAnchor, Root
from .memory import Memory, ShelfStorage
from .implementation import NodeAnchor, Root
from .interface import ExecutionContext as BaseExecutionContext
from .memory import ShelfStorage


EXECUTION_CONTEXT = ContextVar[Optional["ExecutionContext"]]("ExecutionContext")
Expand All @@ -21,15 +22,9 @@
SUPER_ROOT_ARCHITYPE.__jac__ = SUPER_ROOT_ANCHOR


class ExecutionContext:
class ExecutionContext(BaseExecutionContext):
"""Execution Context."""

mem: Memory
reports: list[Any]
system_root: NodeAnchor
root: NodeAnchor
entry_node: NodeAnchor

def init_anchor(
self,
anchor_id: str | None,
Expand Down
3 changes: 2 additions & 1 deletion jac/jaclang/runtimelib/implementation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
_ANCHOR,
)

ANCHOR_TYPES: TypeAlias = "NodeAnchor" | "EdgeAnchor" | "WalkerAnchor"
Anchor: TypeAlias = "NodeAnchor" | "EdgeAnchor" | "WalkerAnchor"
Architype: TypeAlias = "NodeArchitype" | "EdgeArchitype" | "WalkerArchitype"
logger = getLogger(__name__)


Expand Down
127 changes: 126 additions & 1 deletion jac/jaclang/runtimelib/interface.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
"""Jaclang Runtimelib interfaces."""

from __future__ import annotations

from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from enum import IntEnum
from types import UnionType
from typing import Any, Callable, ClassVar, Generic, Iterable, Type, TypeVar
from typing import Any, Callable, ClassVar, Generator, Generic, Iterable, Type, TypeVar


_ID = TypeVar("_ID")
Expand All @@ -14,6 +16,11 @@
_DESERIALIZE = TypeVar("_DESERIALIZE")


#########################################################################################
# ID / ACCESS #
#########################################################################################


@dataclass(kw_only=True)
class JID(Generic[_ID, _ANCHOR], ABC):
"""Jaclang ID Interface."""
Expand Down Expand Up @@ -62,6 +69,11 @@ class Permission:
roots: Access = field(default_factory=Access)


#########################################################################################
# ANCHORS #
#########################################################################################


@dataclass(kw_only=True)
class Anchor(Generic[_SERIALIZE], ABC):
"""Anchor Interface."""
Expand Down Expand Up @@ -105,6 +117,11 @@ class WalkerAnchor(Anchor[_SERIALIZE]):
architype: "WalkerArchitype"


#########################################################################################
# ARCHITYPES #
#########################################################################################


class Architype(Generic[_SERIALIZE], ABC):
"""Architype Interface."""

Expand Down Expand Up @@ -159,3 +176,111 @@ class DSFunc:
def resolve(self, cls: type) -> None:
"""Resolve the function."""
self.func = getattr(cls, self.name)


#########################################################################################
# MEMORY INTERFACES #
#########################################################################################


@dataclass
class Memory(Generic[_ID, _ANCHOR]):
"""Generic Memory Handler."""

__mem__: dict[_ID, _ANCHOR] = field(default_factory=dict)
__gc__: set[_ID] = field(default_factory=set)

def close(self) -> None:
"""Close memory handler."""
self.__mem__.clear()
self.__gc__.clear()

def find(
self,
ids: _ID | Iterable[_ID],
filter: Callable[[_ANCHOR], _ANCHOR] | None = None,
) -> Generator[_ANCHOR, None, None]:
"""Find anchors from memory by ids with filter."""
if not isinstance(ids, Iterable):
ids = [ids]

return (
anchor
for id in ids
if (anchor := self.__mem__.get(id)) and (not filter or filter(anchor))
)

def find_one(
self,
ids: _ID | Iterable[_ID],
filter: Callable[[_ANCHOR], _ANCHOR] | None = None,
) -> _ANCHOR | None:
"""Find one anchor from memory by ids with filter."""
return next(self.find(ids, filter), None)

def find_by_id(self, id: _ID) -> _ANCHOR | None:
"""Find one by id."""
return self.__mem__.get(id)

def set(self, id: _ID, data: _ANCHOR) -> None:
"""Save anchor to memory."""
self.__mem__[id] = data

def remove(self, ids: _ID | Iterable[_ID]) -> None:
"""Remove anchor/s from memory."""
if not isinstance(ids, Iterable):
ids = [ids]

for id in ids:
if self.__mem__.pop(id, None):
self.__gc__.add(id)


#########################################################################################
# CONTEXT #
#########################################################################################


class ExecutionContext(ABC):
"""Execution Context."""

mem: Memory
reports: list[Any]
system_root: NodeAnchor
root: NodeAnchor
entry_node: NodeAnchor

@abstractmethod
def init_anchor(
self,
anchor_id: str | None,
default: NodeAnchor,
) -> NodeAnchor:
"""Load initial anchors."""

def set_entry_node(self, entry_node: str | None) -> None:
"""Override entry."""
self.entry_node = self.init_anchor(entry_node, self.root)

@abstractmethod
def close(self) -> None:
"""Close current ExecutionContext."""

@staticmethod
@abstractmethod
def create(
session: str | None = None,
root: str | None = None,
auto_close: bool = True,
) -> ExecutionContext:
"""Create ExecutionContext."""

@staticmethod
@abstractmethod
def get() -> ExecutionContext:
"""Get current ExecutionContext."""

@staticmethod
@abstractmethod
def get_root() -> Root:
"""Get current root."""
110 changes: 30 additions & 80 deletions jac/jaclang/runtimelib/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,72 +2,20 @@

from __future__ import annotations

from dataclasses import dataclass, field
from dataclasses import dataclass
from pickle import dumps
from shelve import Shelf, open
from typing import Callable, Generator, Generic, Iterable, TypeVar
from typing import Callable, Generator, Iterable, TypeVar
from uuid import UUID

from .architype import Anchor, NodeAnchor, Root, TANCH
from .implementation import Anchor, JID, NodeAnchor, Root
from .interface import Memory

ID = TypeVar("ID")


@dataclass
class Memory(Generic[ID, TANCH]):
"""Generic Memory Handler."""

__mem__: dict[ID, TANCH] = field(default_factory=dict)
__gc__: set[TANCH] = field(default_factory=set)

def close(self) -> None:
"""Close memory handler."""
self.__mem__.clear()
self.__gc__.clear()

def find(
self,
ids: ID | Iterable[ID],
filter: Callable[[TANCH], TANCH] | None = None,
) -> Generator[TANCH, None, None]:
"""Find anchors from memory by ids with filter."""
if not isinstance(ids, Iterable):
ids = [ids]

return (
anchor
for id in ids
if (anchor := self.__mem__.get(id)) and (not filter or filter(anchor))
)

def find_one(
self,
ids: ID | Iterable[ID],
filter: Callable[[TANCH], TANCH] | None = None,
) -> TANCH | None:
"""Find one anchor from memory by ids with filter."""
return next(self.find(ids, filter), None)

def find_by_id(self, id: ID) -> TANCH | None:
"""Find one by id."""
return self.__mem__.get(id)

def set(self, id: ID, data: TANCH) -> None:
"""Save anchor to memory."""
self.__mem__[id] = data

def remove(self, ids: ID | Iterable[ID]) -> None:
"""Remove anchor/s from memory."""
if not isinstance(ids, Iterable):
ids = [ids]

for id in ids:
if anchor := self.__mem__.pop(id, None):
self.__gc__.add(anchor)


@dataclass
class ShelfStorage(Memory[UUID, Anchor]):
class ShelfStorage(Memory[JID[Anchor], Anchor]):
"""Shelf Handler."""

__shelf__: Shelf[Anchor] | None = None
Expand All @@ -82,38 +30,40 @@ def close(self) -> None:
if isinstance(self.__shelf__, Shelf):
from jaclang.plugin.feature import JacFeature as Jac

for anchor in self.__gc__:
self.__shelf__.pop(str(anchor.id), None)
self.__mem__.pop(anchor.id, None)
for jid in self.__gc__:
self.__shelf__.pop(str(jid), None)
self.__mem__.pop(jid, None)

for d in self.__mem__.values():
if d.persistent and d.hash != hash(dumps(d)):
_id = str(d.id)
if p_d := self.__shelf__.get(_id):
for jid, anchor in self.__mem__.items():
if anchor.persistent and anchor.hash != hash(dumps(anchor)):
_jid = str(jid)
if p_d := self.__shelf__.get(_jid):
if (
isinstance(p_d, NodeAnchor)
and isinstance(d, NodeAnchor)
and p_d.edges != d.edges
and Jac.check_connect_access(d)
and isinstance(anchor, NodeAnchor)
and p_d.edge_ids != anchor.edge_ids
and Jac.check_connect_access(anchor)
):
if not d.edges:
self.__shelf__.pop(_id, None)
if not anchor.edge_ids:
self.__shelf__.pop(_jid, None)
continue
p_d.edges = d.edges
p_d.edge_ids = anchor.edge_ids

if Jac.check_write_access(d):
if hash(dumps(p_d.access)) != hash(dumps(d.access)):
p_d.access = d.access
if hash(dumps(d.architype)) != hash(dumps(d.architype)):
p_d.architype = d.architype
if Jac.check_write_access(anchor):
if hash(dumps(p_d.access)) != hash(dumps(anchor.access)):
p_d.access = anchor.access
if hash(dumps(anchor.architype)) != hash(
dumps(anchor.architype)
):
p_d.architype = anchor.architype

self.__shelf__[_id] = p_d
self.__shelf__[_jid] = p_d
elif not (
isinstance(d, NodeAnchor)
and not isinstance(d.architype, Root)
and not d.edges
isinstance(anchor, NodeAnchor)
and not isinstance(anchor.architype, Root)
and not anchor.edge_ids
):
self.__shelf__[_id] = d
self.__shelf__[_jid] = anchor

self.__shelf__.close()
super().close()
Expand Down

0 comments on commit b1e073b

Please sign in to comment.