Source code for uppaal2jetracer.uppaalmodel.frame

"""Frame

This file contains the frame component of the UPPAAL model.

This file can be imported and contains the following classes:

    * Frame: Holds all variable and function bindings and represents a scope.
"""

from __future__ import annotations

import copy
import logging
from typing import Dict, Optional

from uppaal2jetracer.declarations.declarations_ast import FuncDef
from uppaal2jetracer.uppaalmodel.variable import Variable
from uppaal2jetracer.uppaalmodel.elements import Update

logger = logging.getLogger('uppaal_model')


[docs] class Frame: """ Represents a visibility scope for variables and functions in the system. :ivar _parent: The parent Frame. :vartype _parent: Frame """ __slots__ = ('_functions', '_bindings', '_parent') def __init__(self, parent: Frame = None): self._parent = parent self._functions: Dict[str, FuncDef] = {} self._bindings: Dict[str, Variable] = {} @property def parent(self) -> Frame: """ The parent of the frame. :return: The parent of the frame. :rtype: Frame """ return self._parent @parent.setter def parent(self, frame: Frame): self._parent = frame
[docs] def add_function(self, name: str, n: FuncDef): """ Add function root node to the frame. :param name: The reference name of the function. :type name: str :param n: The root node of the function :type n: FuncDef """ logger.debug("Add function '%s' to frame!", name) self._functions[name] = n
[docs] def add_binding(self, name: str, v: Variable): """ Add variable reference to the frame. :param name: The reference name of the variable. :type name: str :param v: The variable reference. :type v: Variable """ logger.debug("Add Variable '%s' to frame!", name) self._bindings[name] = v
[docs] def get_function(self, name: str) -> Optional[FuncDef]: """ Return the function root node if name is found otherwise check parent frame. :param name: Reference name to search for. :type name: str :return: Function root node if found, else return None. :rtype: Optional[Node] """ logger.debug("Fetching function '%s' from frame!", name) if self._functions.keys().__contains__(name): return self._functions[name] if self._parent is None: return None function = self._parent.get_function(name) if function is None: logger.debug("No function '%s' found!", name) return function
[docs] def get_variable(self, name: str) -> Optional[Variable]: """ Return the variable reference if name is found otherwise check parent frame. :param name: Reference name to search for. :type name: str :return: Variable reference if found, else return None. :rtype: Optional[Variable] """ logger.debug("Fetching variable '%s' from frame!", name) if self._bindings.keys().__contains__(name): return self._bindings[name] if self._parent is None: return None variable = self._parent.get_variable(name) if variable is None: logger.debug("No variable '%s' found!", name) return variable
[docs] def create_temporary_frame(self, update: Update) -> Frame: """ Creates a child frame of this frame, having a copy of all the values assigned in the update. :param update: The assignments the frame needs to contain. :return: The new frame. """ new_frame = Frame(self) logger.debug("Created temporary frame!") if update is None: return new_frame for assignment in update.assignments: name = assignment.children()[0][1].name var = self.get_variable(name) new_frame.add_binding(name, copy.deepcopy(var)) logger.debug("Added '%s' to temporary frame!", name) return new_frame
[docs] def reset(self): """ Resets all variables inside the frame to their starting value. """ logger.debug("Start to reset all variables in frame!") for variable in self._bindings.values(): variable.reset()