5 コミット 8905dad978 ... 5a548d5c3e

作者 SHA1 メッセージ 日付
  Andrei Bondarenko 5a548d5c3e Added type value constants 5 年 前
  Andrei Bondarenko f6747c6929 initial bottom implementation 5 年 前
  Andrei Bondarenko 6d652c213d Added Element dataclass 5 年 前
  Andrei Bondarenko 34881ad4f4 Fixed string dumping 5 年 前
  Andrei Bondarenko 6961ba97cc Removed relative imports 5 年 前
6 ファイル変更、138 行追加、5 行削除
  1. 0 0
      core/__init__.py
  2. 93 0
      core/bottom.py
  3. 31 0
      core/element.py
  4. 9 2
      state/base.py
  5. 4 2
      state/devstate.py
  6. 1 1
      state/pystate.py

+ 0 - 0
core/__init__.py


+ 93 - 0
core/bottom.py

@@ -0,0 +1,93 @@
+from state.base import State, INTEGER, FLOAT, STRING, BOOLEAN, TYPE, NODE, EDGE
+from core.element import Element, String
+
+
+class Bottom:
+    def __init__(self, state: State) -> None:
+        self.state = state
+
+    def create_model(self, name: String) -> Element:
+        bottom = self.state.create_nodevalue(name.value)
+        self.state.create_dict(bottom, "Model", self.state.create_node())
+        return Element(id=bottom)
+
+    def add_node(self, model: Element, name: String):
+        model_root = self.state.read_dict(model.id, "Model")
+        # create model element
+        element = self.state.create_node()
+        # connect to model root
+        element_edge = self.state.create_edge(model_root, element)
+        # label edge with provided name
+        element_label = self.state.create_nodevalue(name.value)
+        if element_label is None:
+            print(f"Warning: Invalid name {name.value}, element not created.")
+            return
+        self.state.create_edge(element_edge, element_label)
+        # add ltm-bottom typing
+        element_type = self.state.create_nodevalue(NODE)
+        self.state.create_dict(element_label, TYPE, element_type)
+
+    def add_value(self, model: Element, name: String, value: Element):
+        type_map = {
+            int: INTEGER,
+            float: FLOAT,
+            bool: BOOLEAN,
+            str: STRING
+        }
+        model_root = self.state.read_dict(model.id, "Model")
+        # create model element
+        element = self.state.create_nodevalue(value.value)
+        if element is None:
+            print("Warning: Invalid value, value node not created.")
+            return
+        # connect to model root
+        element_edge = self.state.create_edge(model_root, element)
+        # label edge with provided name
+        element_label = self.state.create_nodevalue(name.value)
+        if element_label is None:
+            print(f"Warning: Invalid name {name.value}, element not created.")
+            return
+        self.state.create_edge(element_edge, element_label)
+        # add ltm-bottom typing
+        element_type = self.state.create_nodevalue(type_map[type(value.value)])
+        self.state.create_dict(element_label, TYPE, element_type)
+
+    def add_edge(self, model: Element, name: String, source: String, target: String):
+        model_root = self.state.read_dict(model.id, "Model")
+        source_element = self.state.read_dict(model_root, source.value)
+        if source_element is None:
+            print(f"Warning: Unknown source element {source.value}, edge not created.")
+            return
+        target_element = self.state.read_dict(model_root, target.value)
+        if target_element is None:
+            print(f"Warning: Unknown target element {target.value}, edge not created.")
+            return
+        # create model element
+        element = self.state.create_edge(source_element, target_element)
+        # connect to model root
+        element_edge = self.state.create_edge(model_root, element)
+        # label edge with provided name
+        element_label = self.state.create_nodevalue(name.value)
+        if element_label is None:
+            print(f"Warning: Invalid name {name.value}, element not created.")
+            return
+        self.state.create_edge(element_edge, element_label)
+        # add ltm-bottom typing
+        element_type = self.state.create_nodevalue(EDGE)
+        self.state.create_dict(element_label, TYPE, element_type)
+
+    def get_element(self, model: Element, name: String) -> Element:
+        model_root = self.state.read_dict(model.id, "Model")
+        element = self.state.read_dict(model_root, name.value)
+        if element is None:
+            print(f"Warning: Unknown element {name.value}.")
+            return Element()
+        else:
+            return Element(id=element, value=self.state.read_value(element))
+
+    def delete_element(self, model: Element, name: String):
+        model_root = self.state.read_dict(model.id, "Model")
+        element = self.state.read_dict(model_root, name.value)
+        # could be both a node or an edge
+        self.state.delete_node(element)
+        self.state.delete_edge(element)

+ 31 - 0
core/element.py

@@ -0,0 +1,31 @@
+from dataclasses import dataclass, asdict, astuple
+from typing import TypeVar, Generic, Optional
+
+# Some typing information for Python static type checkers
+Literal = TypeVar('Literal', int, float, bool, str)  # Must be int, float, bool or str
+
+
+@dataclass
+class Element(Generic[Literal]):
+    """
+    An Element can represent one of following two things, based on the value of its attributes:
+
+    *   An element (node or edge) in the State (id is not None). In this case the value can be None because it hasn't
+        yet been read OR because the element doesn't have a value.
+    *   A value for which a node has not yet been materialized in the State (id is None, value is not None).
+
+
+    If you are familiar with the Modelverse Kernel, this class serves a function similar to the {id: ..., value: ...}
+    dict that is used there.
+    """
+    id: Optional[str] = None
+    value: Optional[Literal] = None
+
+    def is_none(self) -> bool:
+        return self.id is None and self.value is None
+
+
+String = Element[str]
+Integer = Element[int]
+Float = Element[float]
+Boolean = Element[bool]

+ 9 - 2
state/base.py

@@ -3,7 +3,14 @@ from typing import Any, List, Tuple, Optional, Union
 import uuid
 
 primitive_types = (int, float, str, bool)
-type_values = ("Integer", "Float", "String", "Boolean", "Type")
+INTEGER = {"type": "Integer"}
+FLOAT = {"type": "Float"}
+STRING = {"type": "String"}
+BOOLEAN = {"type": "Boolean"}
+TYPE = {"type": "Type"}
+NODE = {"type": "Node"}
+EDGE = {"type": "Edge"}
+type_values = (INTEGER, FLOAT, STRING, BOOLEAN, TYPE, NODE, EDGE)
 
 
 Node = str
@@ -37,7 +44,7 @@ class State(ABC):
         Returns:
             True if value type is supported, False otherwise.
         """
-        if isinstance(value, dict) and value.get("type", None) in type_values:
+        if isinstance(value, dict) and value in type_values:
             return True
         if not isinstance(value, primitive_types):
             return False

+ 4 - 2
state/devstate.py

@@ -1,4 +1,4 @@
-from .pystate import PyState
+from state.pystate import PyState
 
 
 class DevState(PyState):
@@ -31,8 +31,10 @@ class DevState(PyState):
                     x = self.values[n]
                     if isinstance(x, dict):
                         x = f"{x.get('type')}"
+                    else:
+                        x = repr(x)
                     f.write("\"a_%s\" [label=\"%s\"];\n" % (
-                        n, str(x).replace('"', '\\"')))
+                        n, x.replace('"', '\\"')))
                 else:
                     f.write("\"a_%s\" [label=\"\"];\n" % n)
             for i, e in sorted(list(self.edges.items())):

+ 1 - 1
state/pystate.py

@@ -1,6 +1,6 @@
 from typing import Any, List, Tuple, Optional
 
-from .base import State, Node, Edge, Element
+from state.base import State, Node, Edge, Element
 
 
 class PyState(State):