py-scopes/scopes/core/core.py

54 lines
1.5 KiB
Python

# scopes.core.core
"""A concurrent cybernetic communication system"""
from __future__ import annotations # no check of type annotations at runtime
import asyncio
from collections.abc import Awaitable, Callable, Coroutine
from dataclasses import dataclass, field
from typing import Any
from scopes.core import actor
from scopes.core.message import Message
from scopes.util import keywords as k, Symbol
type Mailbox = asyncio.Queue
type Categ = tuple[Symbol, Symbol]
type Proc = Callable[[Scope, Message], Awaitable[Scope]]
type Program = Callable[[Scope], Proc]
type Syn = Callable[[Message], Message]
async def proc_dummy(scope: Scope, msg: Message) -> Scope:
await scope.environ.put(msg)
return scope
global_mailbox: Mailbox = asyncio.Queue()
@dataclass
class Scope:
value: Any = 0
categ: Categ = (k.csys, k.c00)
stage: Symbol = k.initial
proc: Proc = field(init=False)
program: Program = lambda x: proc_dummy
syns: list[Syn] = field(default_factory=list)
environ: Mailbox = global_mailbox
def __post_init__(self):
self.set_proc()
def set_proc(self) -> Scope:
self.proc = self.program(self)
return self
def create_scope(env: Mailbox, cat=(k.csys, k.c00), **kw) -> Scope:
scope = Scope(environ=env, categ=cat, **kw)
return scope.set_proc()
def neuron(scope: Scope) -> Mailbox:
async def process(msg: Message) -> actor.Behavior | None:
nonlocal scope
scope = await scope.proc(scope, msg)
return None if scope is None else process
return actor.create(process)