def __init__(self, compiler, namespace, statement): State.__init__(self, compiler, namespace, statement) self._result = None self._child_statements = {} self.__attributes = {} self._refs = {} self._resolved = False self._result_ref = ResultVariable(self)
class DynamicState(State): """ Represents a dynamic state """ def __init__(self, compiler, namespace, statement): State.__init__(self, compiler, namespace, statement) self._result = None self._child_statements = {} self.__attributes = {} self._refs = {} self._resolved = False self._result_ref = ResultVariable(self) def add_to_graph(self, graph): """ @see State#add_to_graph This method ensures that the statement can be statically executed, which means that all types have been resolved. """ State.add_to_graph(self, graph) # make sure all types are resolved if not State.resolved(self): # provide a meaningful error for req_type in self._required_types: if req_type not in self._resolved_types: type_name = str(self._required_types[req_type]) raise Exception("Unable to resolve %s for statement %s in file %s:%d" % (type_name, self.statement, self.statement.filename, self.statement.line)) raise Exception("Unable to resolve all required types") # get all references this statement needs for ref_def in self.statement.references(): name = ref_def[0] value = ref_def[1] ref_type = "use" if len(ref_def) > 2: ref_type = ref_def[2] if ref_type == "use": value_ref = get_ref(self, value) self._refs[name] = value_ref elif ref_type == "def": scope = self.get_local_scope() scope.add_placeholder(name.name) else: raise Exception("Unknown ref type given by %s" % self) # add any statements under this node to the graph as well self.statement.new_statements(self) def resolved(self): """ Are all dynamic references of this statement resolved? """ if self._resolved: return True scope = self.get_local_scope() for ref in self._refs.values(): if not ref.is_available(scope): return False self._resolved = True self.graph.add_actions(self, self.statement.actions(self)) return True def can_evaluate(self): """ Can this statement be evaluated in the current state it is in? """ if not self.graph.can_evaluate(self): return False return self.statement.can_evaluate(self) def get_ref(self, name): """ Get a reference """ reference = self._refs[name] if reference.__class__ == Reference: return self.get_local_scope().resolve_reference(reference) return reference def get_result(self): """ Get the result of evaluating this statement """ return self._result def get_result_reference(self): """ This method returns a reference to a result """ return self._result_ref def set_evaluated(self): """ Mark this state as evaluated """ State.set_evaluated(self) def evaluate(self): """ Evaluate this statement and if successful mark it as evaluated. @param force: Force the evaluation even if the statement is lazy. """ local_scope = self.get_local_scope() value = self.statement.evaluate(self, local_scope) if hasattr(value, "_get_instance"): value = value._get_instance() if not isinstance(value, Variable): value = Variable(value) self._result = value if self._result is not None: self._result_ref.value_available() self.set_evaluated() def get_state(self, statement): """ Get the state of a statement that has been added to the graph by this state. """ if statement in self._child_statements: return self._child_statements[statement] raise KeyError() def add_statement(self, statement, child_ns = False): """ Add a new statement that is generated or included by the statement linked to this state. The new statement is defined in the same namespace as this statement or in a child namespace. @param statement: The new statement @param child_ns: Optional can be set to true to define it in a child namespace. """ if statement in self._child_statements: raise Exception("Statement %s already added by %s" % (statement, self)) namespace = self.namespace if child_ns: object_id = Scope.object_to_name(self) namespace = Namespace(object_id, self.namespace) child_state = DynamicState(self.compiler, namespace, statement) child_state.add_to_graph(self.graph) self._child_statements[statement] = child_state return child_state def get_attribute(self, name): """ Get an attribute that is stored in this state """ if name in self.__attributes: return self.__attributes[name] raise KeyError(name) def set_attribute(self, name, value): """ Set a value in this state """ self.__attributes[name] = value def has_attribute(self, name): """ Is the attribute with name set? """ return name in self.__attributes