from pprint import pformat
from typing import List
from typing import Optional
from typing import Tuple
from pymavryk.michelson.types.base import MichelsonType
[docs]class MichelsonStack:
def __init__(self, items: Optional[List[MichelsonType]] = None) -> None:
self.items = items or []
self.protected = 0
[docs] @classmethod
def from_items(cls, items: List[MichelsonType]) -> 'MichelsonStack':
return cls(items)
[docs] def protect(self, count: int) -> None:
if len(self.items) < count:
raise Exception(f'got {len(self.items)} items on the stack, want to protect {count}')
self.protected += count
[docs] def restore(self, count: int) -> None:
if self.protected < count:
raise Exception(f'want to restore {count} items, but only {self.protected} are protected')
self.protected -= count
[docs] def push(self, item: MichelsonType):
self.items.insert(self.protected, item)
[docs] def peek(self) -> MichelsonType:
if not self.items:
raise Exception('stack is empty')
return self.items[self.protected]
[docs] def pop(self, count: int) -> List[MichelsonType]:
if len(self.items) - self.protected < count:
raise Exception(f'got {len(self.items) - self.protected} items on the stack, want to pop {count}')
return [self.items.pop(self.protected) for _ in range(count)]
[docs] def pop1(self) -> MichelsonType:
(a,) = self.pop(count=1)
return a
[docs] def pop2(self) -> Tuple[MichelsonType, MichelsonType]:
a, b = self.pop(count=2)
return a, b
[docs] def pop3(self) -> Tuple[MichelsonType, MichelsonType, MichelsonType]:
a, b, c = self.pop(count=3)
return a, b, c
[docs] def clear(self) -> None:
self.items.clear()
self.protected = 0
[docs] def dump(self, count: int) -> Optional[List[MichelsonType]]:
if not self.items:
return None
count = min(count, len(self.items))
return self.items[:count]
def __len__(self) -> int:
return len(self.items)
def __repr__(self) -> str:
return pformat(self.items)