def reply(self, *args, **kwargs): reply = super(ContextUpdater, self).reply(*args, **kwargs) if self.Q is None: return reply responses = [] for internal in self.internal.values(): if self.changed[internal]: update = self.updates[internal] source = self.source[internal] responses.append(context_update( source, update, representations.quote(self.current[internal]) )) return reply.add(properties.combine(responses))
def convert(asker, value, req): starting_cost = asker.cost def check(x): return properties.check_firmly(asker, req, representations.quote(x)) if check(value): return asker.reply(answer=value) #TODO in the long run we might want to leave properties in if they can simplify the conversion old_modifier = value.modifier stripped = value.simple_update(_modifier=properties.trivial()) id = stripped.id result = None if (id, req.id) in conversion_cache: result = conversion_cache[(id, req.id)] if result is None: for form in synonyms[id]: if check(form): result = form if result is None: response = asker.ask(raw_convert(value, req)) if response.has_answer(): result = response.answer else: return asker.reply() synonyms[id].add(result) conversion_cache[(id, req.id)] = result #FIXME what an ugly hack; this sort of thing will hopefully be done automatically if (asker.cost - starting_cost > 30 and booleans.ask_firmly(asker, nicer_representation( representations.quote(value), representations.quote(result), req ))): asker.set_repr(value, representations.quote(result)) return asker.reply(answer=properties.simple_add_modifier(result, old_modifier))
def set_lifted_field(asker, object, new_value, field): raw_result = asker.ask(apply_update( set_field(field, convert.unquote(asker, new_value)), convert.unquote(asker, object) )).firm_answer return asker.reply(answer=representations.quote(raw_result))
def lift_field(asker, object, field): response = asker.ask(fields.get_field(field, convert.unquote(asker, object))) if response.has_answer(): return asker.reply(answer=representations.quote(response.answer)) else: return asker.reply()
def lift(asker, repr, update): return asker.reply(answer=representations.make( held_update.head, update=representations.quote(update), object=repr ))
def generic_stripper(asker, update, property, object): if properties.check_firmly(asker, convert.irreducible(), representations.quote(property)): return asker.reply(value=keep_strip(strip=property))
def quote_quote(d): return quote(representations.quote(d))
def update(self, change, v, repr_change=None): if repr_change is None: repr_change = updates.lift(change) default_repr_change = True else: default_repr_change = False if v.id in self.internal: internal = self.internal[v.id] #if we are updating stale information... #apply the update, but not any representation change #(if info is stale, probably just a representation change...) if v.id != self.current[internal].id: if change.head == updates.trivial.head: return True else: repr_change = updates.lift(change) self.updates[internal] = updates.compose(self.updates[internal], change) self.current[internal] = convert.unquote( self, self.ask_firmly(updates.apply_update( repr_change, representations.quote(self.current[internal]) )) ) self.changed[internal] = True return True else: #FIXME think more about how this propagation ought to work #it seems like something is going oddly w.r.t levels of abstraction #also should I propagate back across field accesses? I don't know... #also this whole thing seems kind of like a mess, I don't expect it to work consistently def propagate_back(s): if s.head == term.because.head: return propagate_back(s['operation']) elif s.head == term.explain.head: return propagate_back(s['operation']) or propagate_back(s['prior']) elif s.head == term.accessing.head: if change.head == updates.trivial.head: parent = s['term'] binding = s['binding'] return self.update( updates.trivial(), parent, repr_change=updates.apply_to_field( representations.referent_of(T.from_str(binding)), repr_change ).explain("tracing backwards from [v]", v=v) ) else: return False elif s.head == askers.answering.head: Q = s['Q'] if Q.head == fields.get_field.head: parent = Q['object'] field = Q['field'] return self.update( updates.apply_to_field(field, change), parent, repr_change=updates.apply_to_field(updates.lift_field(field), repr_change) ) elif Q.head == convert.convert.head: previous = Q['value'] return self.update( change, previous, repr_change=None ) return False return propagate_back(v.source)
def check(x): return properties.check_firmly(asker, req, representations.quote(x))
def expose_modifier(asker, object): rep = representations.quote(object) head = strings.to_str(asker, fields.get(asker, representations.head(), rep)) if head not in hidden_modifier_heads: new_modifier = convert.reduce(asker, object.modifier) return asker.reply(answer=object.simple_update(_modifier=new_modifier))
def interpret_str(asker, view, s): return asker.reply(answer=representations.quote(s))
def interpret_int(asker, view, k): return asker.reply(answer=representations.quote(k))