Franck Pommereau

added missing SNAKES' core features, started plugins

from functools import reduce
from operator import and_, or_
from itertools import chain
from zinc import ConstraintError
from zinc.data import record
from . import ConstraintError
from .data import record
from .utils import autorepr
class Arc (object) :
def _nest (self, *arcs, **more) :
......@@ -19,6 +20,11 @@ class Arc (object) :
self._order = max(a._order for a in chain(arcs, more.values())) + 1
self.__dict__.update(more)
return arcs
def __add__ (self, other) :
return MultiArc(self, other)
def __sub__ (self, other) :
return NotImplementedError("%s does not support substraction"
% self.__class__.__name__)
class InputArc (Arc) :
pass
......@@ -66,30 +72,33 @@ class _AstTypeProduce (_Ast) :
nest.append(node)
return node.body
@autorepr
class Value (InputArc, OutputArc, _AstBindTestConsume, _AstTypeProduce) :
_order = 0
def __init__ (self, value) :
self.source = value
def __repr__ (self) :
return "Value(%r)" % self.source
def copy (self) :
return self.__class__(self.source)
def vars (self) :
return set()
@autorepr
class Expression (InputArc, OutputArc, _AstBindTestConsume, _AstTypeProduce) :
_order = 20
def __init__ (self, code) :
self.source = code
def __repr__ (self) :
return "Expression(%r)" % self.source
def copy (self) :
return self.__class__(self.source)
def vars (self) :
return set()
@autorepr
class Variable (InputArc, OutputArc, _AstTypeProduce) :
_order = 10
def __init__ (self, name) :
self.source = name
def __repr__ (self) :
return "Variable(%r)" % self.source
def copy (self) :
return self.__class__(self.source)
def vars (self) :
return {self.source}
def __astin__ (self, nest, place, ctx, **more) :
......@@ -119,22 +128,38 @@ class Variable (InputArc, OutputArc, _AstTypeProduce) :
return node.body
class MultiArc (InputArc, OutputArc) :
_nestable_in = set()
def __init__ (self, first, *others) :
self.components = self._nest(first, *others)
def copy (self) :
return self.__class__(*(c.copy() for c in self.components))
def __repr__ (self) :
return "%s(%s)" % (self.__class__.__name__,
", ".join(repr(c) for c in self.components))
def vars (self) :
return reduce(or_, (c.vars() for c in self.components), set())
def __add__ (self, other) :
if isinstance(other, MultiArc) :
return self.__class__(*self.components, *other.components)
else :
return self.__class__(*self.components, other)
def __sub__ (self, other) :
if isinstance(other, MultiArc) :
todo = other.components
else :
todo = [other]
keep = list(self.components)
for arc in todo :
keep.remove(arc)
return self.__class__(*keep)
@autorepr
class Flush (InputArc, _Ast) :
_order = 15
def __init__ (self, name, notempty=False) :
self.source = name
self.notempty = notempty
def __repr__ (self) :
return "%s(%r, %s)" % (self.__class__.__name__, self.source, self.notempty)
def copy (self) :
return self.__class__(self.source, self.notempty)
def vars (self) :
return {self.source}
def __astin__ (self, nest, place, ctx, **more) :
......@@ -151,12 +176,13 @@ class Flush (InputArc, _Ast) :
nest.append(node)
return ret
@autorepr
class Fill (OutputArc, _Ast) :
_order = 30
def __init__ (self, code) :
self.source = code
def __repr__ (self) :
return "%s(%r)" % (self.__class__.__name__, self.source)
def copy (self) :
return self.__class__(self.source)
def vars (self) :
return set()
def __astout__ (self, nest, place, ctx, **more) :
......@@ -168,12 +194,12 @@ class Fill (OutputArc, _Ast) :
nest.append(node)
return node.body
@autorepr
class Test (InputArc, OutputArc) :
_nestable_in = {MultiArc}
def __init__ (self, label) :
self._nest(label=label)
def __repr__ (self) :
return "%s(%r)" % (self.__class__.__name__, self.label)
def copy (self) :
return self.__class__(self.label)
def vars (self) :
return self.label.vars()
def __astin__ (self, nest, place, ctx, **more) :
......@@ -200,16 +226,16 @@ class Test (InputArc, OutputArc) :
del tokens[pos - new:]
return newnest
@autorepr
class Inhibitor (InputArc) :
_nestable_in = {MultiArc}
def __init__ (self, label, guard=None) :
if isinstance(label, _AstBindTestConsume) and guard :
raise ConstraintError("inhibition guard forbidden together with %s"
% label)
self._nest(label=label)
self.guard = guard
def __repr__ (self) :
return "%s(%r, %r)" % (self.__class__.__name__, self.label, self.guard)
def copy (self) :
return self.__class__(self.label, self.guard)
def vars (self) :
return set()
def __astin__ (self, nest, place, ctx, **more) :
......@@ -218,6 +244,8 @@ class Inhibitor (InputArc) :
class Tuple (InputArc, OutputArc) :
def __init__ (self, first, *others) :
self.components = self._nest(first, *others)
def copy (self) :
return self.__class__(*(c.copy() for c in self.components))
def __repr__ (self) :
return "%s(%s)" % (self.__class__.__name__,
", ".join(repr(c) for c in self.components))
......@@ -307,6 +335,9 @@ class Tuple (InputArc, OutputArc) :
ctx.add[place.name].append(ctx.Pattern(self, self._fold(toadd), placetype))
return nest
MultiArc._nestable_in = set()
Test._nestable_in = {MultiArc}
Inhibitor._nestable_in = {MultiArc}
Value._nestable_in = {Tuple, Test, Inhibitor, MultiArc}
Variable._nestable_in = {Tuple, Test, Inhibitor, MultiArc}
Expression._nestable_in = {Tuple, Test, Inhibitor, MultiArc}
......
......@@ -13,6 +13,22 @@ BOOL = "Boolean"
EXT = ".coffee"
INMEM = False
def and_ (left, *others) :
seen = set([left])
done = [left]
for right in others :
if right not in seen :
done.append(right)
seen.add(right)
return " and ".join("(%s)" % d for d in done)
def union (left, *other) :
types = set((left,) + other)
if len(types) == 1 :
return next(iter(types))
else :
return "object"
class Declare (BaseDeclare) :
pass
......
......@@ -12,6 +12,22 @@ BOOL = "bool"
EXT = ".go"
INMEM = False
def and_ (left, *others) :
seen = set([left])
done = [left]
for right in others :
if right not in seen :
done.append(right)
seen.add(right)
return " && ".join("(%s)" % d for d in done)
def union (left, *other) :
types = set((left,) + other)
if len(types) == 1 :
return next(iter(types))
else :
return "interface{}"
class Declare (BaseDeclare) :
_levels = ["import", "decl"]
_default = "decl"
......
......@@ -12,6 +12,22 @@ BOOL = "bool"
EXT = ".py"
INMEM = True
def and_ (left, *others) :
seen = set([left])
done = [left]
for right in others :
if right not in seen :
done.append(right)
seen.add(right)
return " and ".join("(%s)" % d for d in done)
def union (left, *other) :
types = set((left,) + other)
if len(types) == 1 :
return next(iter(types))
else :
return "object"
class Declare (BaseDeclare) :
pass
......
......@@ -54,7 +54,7 @@ class Compiler (BaseCompiler) :
net &= n
return net
def visit_model (self, node, ctx) :
return self.visit_seq(node.body, ctx)
return self.build_seq(node.body, ctx)
def visit_task (self, node, ctx) :
pass
def visit_def (self, node, ctx) :
......
This diff is collapsed. Click to expand it.
import operator, logging, collections
from functools import reduce
from zinc import TypingError
from zinc.data import mset, WordSet
from zinc.tokens import Token
from zinc.arcs import MultiArc
from . import TypingError
from .data import mset, WordSet, hashable
from .tokens import Token
from .arcs import MultiArc
from .utils import autorepr
class Node (object) :
pass
def __init__ (self, name) :
self._name = name
@property
def name (self) :
return self._name
@hashable
@autorepr(tokens=mset())
class Place (Node) :
def __init__ (self, name, tokens=[], type=None) :
super().__init__(name)
toks = []
for t in tokens :
if not isinstance(t, Token) :
......@@ -17,16 +25,34 @@ class Place (Node) :
% (t, name, repr(t)))
t = Token(repr(t))
toks.append(t)
self.name = name
self.tokens = mset(toks)
self.type = type
def __repr__ (self) :
return "%s(%r, %r, %r)" % (self.__class__.__name__, self.name,
list(self.tokens), self.type)
def _hash_items (self) :
return [self.name]
def __str__ (self) :
return str(self.name)
def __eq__ (self, other) :
try :
return self.name == other.name
except :
return False
def __iter__ (self) :
return iter(self.tokens)
def __contains__ (self, token) :
return token in self.tokens
def is_empty (self) :
return bool(self.tokens)
def copy (self, name=None) :
return self.__class__(name or self.name, self.tokens, self.type)
def add (self, tokens) :
self.tokens.add(tokens)
def clear (self) :
self.tokens.clear()
def remove (self, tokens) :
self.tokens.remove(tokens)
def reset (self, tokens) :
self.clear()
self.add(tokens)
class _Declarations (dict) :
def __init__ (self, names) :
......@@ -42,14 +68,25 @@ class _Declarations (dict) :
self[name] = type
return name
@hashable
@autorepr
class Transition (Node) :
def __init__ (self, name, guard=None) :
self.name = name
super().__init__(name)
self.guard = guard
self._input = {}
self._output = {}
def __repr__ (self) :
return "%s(%r, %r)" % (self.__class__.__name__, self.name, self.guard)
def _hash_items (self) :
return [self.name]
def copy (self, name=None) :
return self.__class__(name or self.name, self.guard)
def __eq__ (self, other) :
try :
return self.name == other.name
except :
return False
def __str__ (self) :
return str(self.name)
def _astkey (self, arc) :
return arc[1]._order
def __ast__ (self, ctx) :
......
......@@ -25,7 +25,8 @@ class Plugin (object) :
raise PluginError("could not load %r from '.' or 'zinc.plugins'" % p)
# create result module
if self.modname not in sys.modules :
self._mod = sys.modules[self.modname] = types.ModuleType(self.modname)
sys.modules[self.modname] = types.ModuleType(self.modname)
self._mod = sys.modules[self.modname]
# load extended modules
for base in extends :
if base not in self.modules :
......@@ -40,6 +41,7 @@ class Plugin (object) :
return getattr(self._mod, name)
def __call__ (self, obj) :
setattr(self._mod, obj.__name__, obj)
setattr(obj, "__plugmod__", self._mod)
return obj
@classmethod
def reset_plugins (cls, name="zn") :
......
from . import Plugin
plug = Plugin("zinc.nets",
depends=["zinc.plugins.status"])
from .. import ConstraintError
@plug
class Place (plug.Place) :
def __init__ (self, name, tokens=[], type=None, **options) :
status = self.options.pop("status", self.__plugmod__.Status(None))
if status.is_flow() :
if type is None :
type = self.__plugmod__.BlackToken
if type is not self.__plugmod__.BlackToken :
raise ConstraintError("invalid type for control-flow place: %r" % type)
super().__init__(name, tokens, type, status=status, **options)
@plug
class PetriNet (plug.PetriNet) :
def __or__ (self, other) :
# parallel
pass
def __and__ (self, other) :
# sequence
pass
def __add__ (self, other) :
# choice
pass
def __mul__ (self, other) :
# iteration
pass
def __div__ (self, other) :
# buffer hiding
pass
from . import Plugin
plug = Plugin("zinc.nets")
import collections
@plug
class Status (object) :
def __init__ (self, kind, name=None) :
self.kind = kind
self.name = name
def __eq__ (self, other) :
try :
return self.kind == other.kind and self.name == other.name
except :
return False
def __hash__ (self) :
return hash((self.__class__.__name__, self.kind, self.name))
def __str__ (self) :
if self.name :
return "%s[%s]" % (self.kind, self.name)
else :
return self.kind
def __repr__ (self) :
if self.name :
return "%s(%r, %r)" % (self.kind, self.name)
else :
return "%s(%r)" % self.kind
def copy (self) :
return self.__class__(self.kind, self.name)
def is_flow (self) :
return self.name in ("entry", "internal", "exit")
for name in ("entry", "internal", "exit") :
setattr(Status, name, Status(name))
@plug
class Place (plug.Place) :
def __init__ (self, name, tokens=[], type=None, **options) :
self.status = self.options.pop("status", Status(None))
super().__init__(name, tokens, type, **options)
def copy (self, name=None, **options) :
result = super().copy(name, **options)
result.status = self.status.copy()
return result
def __repr__ (self) :
if self.status.kind is None :
return super().__repr__()
else :
return "%s, status=%s)" % (super().__repr__()[:-1], repr(self.status))
@plug
class PetriNet (plug.PetriNet) :
def __init__ (self, name, lang="python", **options) :
super().__init__(name, lang, **options)
self.status = collections.defaultdict(set)
def add_place (self, place, **options) :
super().__init__(place, **options)
self.status[place.status].add(place.name)
def remove_place (self, name, **options) :
place = self.place(name)
super().remove_place(name, **options)
self.status[place.status].remove(name)
import enum
from zinc.data import hashable, mset
from .data import hdict, mset
from .utils import autorepr
class Token (object) :
pass
@autorepr
class CodeToken (Token) :
def __init__ (self, code) :
self.code = code
......@@ -12,8 +14,6 @@ class CodeToken (Token) :
BLAME=ctx.TokenBlame(place, self.code))
def __str__ (self) :
return "(%s)" % self.code
def __repr__ (self) :
return "%s(%r)" % (self.__class__.__name__, self.code)
def __hash__ (self) :
return hash(self.code)
def __eq__ (self, other) :
......@@ -21,11 +21,6 @@ class CodeToken (Token) :
return self.code == other.code
except AttributeError :
return False
def __ne__ (self, other) :
try :
return self.code != other.code
except AttributeError :
return True
def __ge__ (self, other) :
try :
return self.code >= other.code
......@@ -53,10 +48,7 @@ class BlackWhiteToken (Token, enum.IntEnum) :
black = BlackWhiteToken.BLACK
white = BlackWhiteToken.WHITE
@hashable
class Marking (dict) :
def _hash_items (self) :
return self.items()
class Marking (hdict) :
def __repr__ (self) :
return "%s(%s)" % (self.__class__.__name__, dict.__repr__(self))
def __call__ (self, place) :
......
import inspect
def autorepr (cls=None, **defaults) :
def wrapper (cls) :
sig = inspect.signature(cls.__init__)
def __repr__ (self) :
parts = []
for i, (arg, info) in enumerate(sig.parameters.items()) :
if i > 0 :
val = getattr(self, arg)
if info.default is inspect._empty :
parts.append(repr(val))
elif val != info.default and val != defaults.get(arg, val) :
parts.append("%s=%r" % (arg, val))
return "%s(%s)" % (self.__class__.__name__, ", ".join(parts))
cls.__repr__ = __repr__
return cls
if cls is not None :
assert not defaults, "invalid use of @autorepr"
return wrapper(cls)
else :
return wrapper