def test_slots_rt(): ns = Namespace("root", None) rs = Resolver(ns) e = Entity("xx", ns) qs = QueueScheduler(None, [], [], None, set()) r = RelationAttribute(e, None, "xx", Location("", 1)) i = Instance(e, rs, qs) assert_slotted(ResultVariable()) assert_slotted(AttributeVariable(None, None)) assert_slotted(Promise(None, None)) assert_slotted(ListVariable(r, i, qs)) assert_slotted(OptionVariable(r, i, qs)) assert_slotted(qs) assert_slotted(DelegateQueueScheduler(qs, None)) assert_slotted(Waiter(qs)) assert_slotted( ExecutionUnit(qs, r, ResultVariable(), {}, Literal(""), None)) assert_slotted(HangUnit(qs, r, {}, None, Resumer())) assert_slotted(RawUnit(qs, r, {}, Resumer())) assert_slotted(FunctionUnit(qs, rs, ResultVariable(), {}, None)) assert_slotted(i)
def convert_relation(value: ResultVariable): if value.is_ready() and value.value is not None: rawvalue = value.get_value() else: # no value present return {"values": []} if not isinstance(rawvalue, list): rawvalue = [rawvalue] return {"values": [convert(v) for v in rawvalue]}
def resume(self, requires: Dict[object, object], resolver: Resolver, queue: QueueScheduler, target: ResultVariable) -> None: result = self.children[0].execute(requires, resolver, queue) self._validate_value(result, 0) assert isinstance(result, bool) if self._is_final(result): target.set_value(result, self.location) else: ExecutionUnit( queue, resolver, target, self.children[1].requires_emit(resolver, queue), self.children[1], owner=self )
def requires_emit(self, resolver: Resolver, queue: QueueScheduler) -> Dict[object, ResultVariable]: # introduce temp variable to contain the eventual result of this stmt temp = ResultVariable() temp.set_provider(self) # construct waiter resumer = IsDefinedReferenceHelper(temp, self.attr, self.name) self.copy_location(resumer) # wait for the instance RawUnit(queue, resolver, self.attr.requires_emit(resolver, queue), resumer) return {self: temp}
def __init__(self, queue_scheduler, resolver, result: ResultVariable, requires, function: FunctionCall): Waiter.__init__(self, queue_scheduler) self.result = result result.set_provider(self) self.requires = requires self.function = function self.resolver = resolver self.queue_scheduler = queue_scheduler for r in requires.values(): self.await(r) self.ready(self)
def requires_emit(self, resolver: Resolver, queue: QueueScheduler) -> Dict[object, ResultVariable]: # pass context! helper = GradualFor(self, resolver, queue) helperwrapped = ResultVariable() helperwrapped.set_value(helper, self.location) basereq = self.base.requires_emit_gradual(resolver, queue, helper) basereq[self] = helperwrapped return basereq
def requires_emit_gradual(self, resolver: Resolver, queue: QueueScheduler, resultcollector) -> Dict[object, ResultVariable]: # The tricky one! # introduce temp variable to contain the eventual result of this stmt temp = ResultVariable() temp.set_provider(self) # construct waiter resumer = AttributeReferenceHelper(temp, self.instance, self.attribute, resultcollector) self.copy_location(resumer) # wait for the instance RawUnit(queue, resolver, self.instance.requires_emit(resolver, queue), resumer) return {self: temp}
def requires_emit(self, resolver: Resolver, queue: QueueScheduler) -> Dict[object, ResultVariable]: """Not an actual expression, but following the pattern""" # pass context via requires! helper = GradualFor(self, resolver, queue) helperwrapped = ResultVariable() helperwrapped.set_value(helper, self.location) basereq = self.base.requires_emit_gradual(resolver, queue, helper) basereq[self] = helperwrapped return basereq
def __init__(self, queue_scheduler, resolver, result: ResultVariable, requires, function: FunctionCall) -> None: Waiter.__init__(self, queue_scheduler) self.result = result result.set_provider(self) # requires is used to track all required RV's # It can grow larger as new requires are discovered self.requires = requires # base_requires are the original requires for this function call self.base_requires = dict(requires) self.function = function self.resolver = resolver for r in requires.values(): self.waitfor(r) self.ready(self)
def assert_rv(result_variable: ResultVariable) -> None: node_ref: Optional[ AssignableNodeReference] = result_variable.get_dataflow_node() assert node_ref is not None nodes: List[AssignableNode] = list(node_ref.nodes()) assert len(nodes) == 1 assert nodes[0].result_variable is result_variable
def convert_attribute(value: ResultVariable): try: rawvalue = value.get_value() except OptionalValueException: return {"nones": [0]} if isinstance(rawvalue, Unknown): return {"unknowns": [0]} if isinstance(rawvalue, NoneValue): return {"nones": [0]} if not isinstance(rawvalue, list): rawvalue = [rawvalue] return {"values": rawvalue} else: unknowns = [] offset = 0 for i in range(0, len(rawvalue)): value = rawvalue[i - offset] if isinstance(value, Unknown): unknowns.append(i) del rawvalue[i - offset] offset += 1 if len(unknowns) > 0: return {"values": rawvalue, "unknowns": unknowns} else: return {"values": rawvalue}
def requires_emit(self, resolver: Resolver, queue: QueueScheduler) -> Dict[object, ResultVariable]: # introduce temp variable to contain the eventual result of this stmt temp: ResultVariable = ResultVariable() temp.set_type(Bool()) temp.set_provider(self) # wait for the lhs HangUnit(queue, resolver, self.children[0].requires_emit(resolver, queue), temp, self) return {self: temp}
def __init__(self, left, right, annotations=[]): DefinitionStatement.__init__(self) # for later evaluation self.annotation_expression = [(ResultVariable(), exp) for exp in annotations] # for access to results self.annotations = [exp[0] for exp in self.annotation_expression] self.left = left self.right = right self.requires = None self.comment = None
def requires_emit(self, resolver: Resolver, queue: QueueScheduler) -> typing.Dict[object, ResultVariable]: sub = ReferenceStatement.requires_emit(self, resolver, queue) temp = ResultVariable() temp.set_type(self.type) temp.set_provider(self) HangUnit(queue, resolver, sub, temp, self) return {self: temp}
def requires_emit(self, resolver: Resolver, queue: QueueScheduler) -> Dict[object, ResultVariable]: # This ResultVariable will receive the result of this expression result: ResultVariable = ResultVariable() result.set_provider(self) # Schedule execution to resume when the condition can be executed resumer: RawResumer = ConditionalExpressionResumer(self, result) self.copy_location(resumer) RawUnit(queue, resolver, self.condition.requires_emit(resolver, queue), resumer) # Wait for the result variable to be populated return {self: result}
def get_new_result_variable(self, instance: "Instance", queue: QueueScheduler) -> ResultVariable: out: ResultVariable["Instance"] if self.is_optional(): # be a 0-1 relation self.end = None self.low = 0 self.high = 1 out = DeprecatedOptionVariable(self, instance, queue) else: out = ResultVariable() out.set_type(self.type) return out
def __init__(self, left: Relationside, right: Relationside, annotations: List[ExpressionStatement] = []) -> None: DefinitionStatement.__init__(self) # for later evaluation self.annotation_expression = [(ResultVariable(), exp) for exp in annotations] # for access to results self.annotations = [exp[0] for exp in self.annotation_expression] self.anchors.extend((y for x in annotations for y in x.get_anchors())) self.anchors.append(TypeReferenceAnchor(left[0].namespace, left[0])) self.anchors.append(TypeReferenceAnchor(right[0].namespace, right[0])) self.left: Relationside = left self.right: Relationside = right self.comment = None
def get_new_result_variable(self, instance: "Instance", queue: QueueScheduler) -> ResultVariable: if self.__multi: mytype = (TypedList(self.__type)) else: mytype = (self.__type) if (self.__nullallble): # be a 0-1 relation self.end = None self.low = 0 self.high = 1 out = OptionVariable(self, instance, queue) mytype = NullableType(mytype) else: out = ResultVariable() out.set_type(mytype) out.set_provider(instance) return out
def call_in_context( self, args: List[object], kwargs: Dict[str, object], resolver: Resolver, queue: QueueScheduler, result: ResultVariable ) -> None: no_unknows = self.plugin.check_args(args, kwargs) if not no_unknows and not self.plugin.opts["allow_unknown"]: result.set_value(Unknown(self), self.ast_node.location) return if self.plugin._context != -1: args.insert(self.plugin._context, plugins.Context(resolver, queue, self.ast_node, self.plugin, result)) if self.plugin.opts["emits_statements"]: self.plugin(*args, **kwargs) else: try: value = self.plugin(*args, **kwargs) result.set_value(value if value is not None else NoneValue(), self.ast_node.location) except UnknownException as e: result.set_value(e.unknown, self.ast_node.location) except UnsetException as e: call: str = str(self.plugin) location: str = str(self.ast_node.location) LOGGER.debug( "Unset value in python code in plugin at call: %s (%s) (Will be rescheduled by compiler)", call, location ) # Don't handle it here! # This exception is used by the scheduler to re-queue the unit # If it is handled here, the re-queueing can not be done, # leading to very subtle errors such as #2787 raise e except RuntimeException as e: raise WrappingRuntimeException(self.ast_node, "Exception in plugin %s" % self.ast_node.name, e) except plugins.PluginException as e: raise ExplicitPluginException(self.ast_node, "PluginException in plugin %s" % self.ast_node.name, e) except Exception as e: raise ExternalException(self.ast_node, "Exception in plugin %s" % self.ast_node.name, e)
def requires_emit(self, resolver, queue): sub = ReferenceStatement.requires_emit(self, resolver, queue) # add lazy vars temp = ResultVariable() FunctionUnit(queue, resolver, temp, sub, self) return {self: temp}
def call_in_context( self, args: List[object], kwargs: Dict[str, object], resolver: Resolver, queue: QueueScheduler, result: ResultVariable ) -> None: result.set_value(self.call_direct(args, kwargs), self.ast_node.location)
def emit(self, resolver: Resolver, queue: QueueScheduler) -> None: self._add_to_dataflow_graph(resolver.dataflow_graph) reqs = self.instance.requires_emit(resolver, queue) HangUnit(queue, resolver, reqs, ResultVariable(), self)
def emit(self, resolver: Resolver, queue: QueueScheduler) -> None: target = ResultVariable() reqs = self.requires_emit(resolver, queue) ExecutionUnit(queue, resolver, target, reqs, self)