def node_from_term(asker, quoted_term): head = asker.ask(fields.get_field(representations.head(), quoted_term)).firm_answer bindings = asker.ask(fields.get_field(representations.bindings(), quoted_term)).firm_answer return asker.reply(answer=properties.simple_add_modifier( node(head, T.empty_list()), children_on_expanded(bindings) ))
def unquote(asker, value): #FIXME more circular dependencies import dictionaries, strings if isinstance(value, representations.Representation): return value.represents #FIXME all of this should be done with requirements embedded in questions #rather than asking and then converting bindings = asker.ask(fields.get_field(representations.bindings(), value)).firm_answer proto_literal_bindings = dictionaries.to_dict(asker, bindings) literal_bindings = frozendict({strings.to_str(asker, k):unquote(asker, v) for k, v in proto_literal_bindings.iteritems()}) head = asker.ask(fields.get_field(representations.head(), value)).firm_answer literal_head = strings.to_str(asker, head) return T(literal_head, literal_bindings)
def exposed_modifier(asker, rep): head = asker.ask(fields.get_field(representations.head(), rep)).answer if head is None: return asker.reply(answer=T.no()) else: result = strings.to_str(asker, head) not in hidden_modifier_heads return asker.reply(answer=T.from_bool(result))
def add_children_on_expanded(asker, old, new, bindings): children = [] for p in lists.iterator(asker, lists.from_dict(bindings)): k = asker.ask(fields.get_field(first(), p)).firm_answer v = asker.ask(fields.get_field(second(), p)).firm_answer prefix = strings.string_concat(k, T.from_str(": ")) new_node = node_from_term(asker, v) new_node = updates.update( updates.apply_to(headline(), strings.prepend_str(prefix)), new_node ) children.append(new_node) return asker.reply(answer=updates.update( fields.set_field(all_children(), T.from_list(children)), new ))
def cons_image(asker, k, key, value, other): if booleans.ask_firmly(asker, builtins.equal(k, key)): return asker.reply(answer=value) else: return asker.ask_tail( fields.get_field(image(k), other), handler=asker.pass_through(not_found.head) )
def visible_children(asker, object): expanded = convert.check_hard(asker, is_expanded(), object) object = asker.refresh(object) if not expanded: return asker.reply(answer=T.from_list([])) else: children = asker.ask(fields.get_field(all_children(), object)).firm_answer return asker.reply(answer=children)
def outline_to_lines(asker, root): debug() result = asker.ask(fields.get_field(cached_lines(), root)).answer if result is not None: return asker.reply(answer=result) base_headline = asker.ask(fields.get_field(headline(), root)).firm_answer root = asker.refresh(root) prefix = "* " if convert.check_hard(asker, is_pointer(), root) else " " full_headline = strings.string_concat(T.from_str(prefix), base_headline) root = asker.refresh(root) children = asker.ask(fields.get_field(visible_children(), root)).firm_answer body = empty_lines() for child in lists.iterator(asker, children): section = asker.ask(outline_to_lines(child)).firm_answer body = concat_lines(body, section) result = concat_lines(one_line(full_headline), indent_lines(body)) asker.update(updates.set_field(cached_lines(), result), root) return asker.reply(answer=result)
def add_pointer_to_bottom(asker, object): visible_children = asker.ask(fields.get_field(visible_children()), object).firm_answer if convert.check_hard(asker, lists.is_empty(), visible_children): return asker.reply(answer=updates.update(is_pointer_now(), object)) else: result = updates.update(has_pointer_now(), object) result = updates.update( updates.apply_to( fields.compose(visible_children(), lists.last_element()), add_pointer_to_bottom() ), result ) return asker.reply(answer=result)
def predict_input(asker, view): lines = fields.get(asker, lines_field(), view) h = asker.ask(state.get_history()).firm_answer response = asker.ask(fields.get_field(dictionaries.image(lines), h)) if response.has_answer(): return asker.reply(answer=response.answer) else: input = asker.ask_firmly(elicit(view)) asker.ask(state.update_state(updates.apply_to_field( state.history(), updates.set_field( dictionaries.image(lines), input ) ))) return asker.reply(answer=input)
def interpret_raw(asker, view, text, bindings): #FIXME I think that most field lookups should be done implicitly variable_bindings = fields.get(asker, bindings_field(), view) lookup_value = asker.ask(fields.get_field( dictionaries.image(text), variable_bindings )) if lookup_value.has_answer(): return asker.reply(answer=lookup_value.answer) update_bindings = dictionaries.map( computations.apply_to_single( computations.askQ_literal(interpret_expression( computations.quote(view), computations.getvar(computations.quote(computations.x_var)) )), computations.x_var ) ) return asker.reply(answer=representations.quoted_term( text, functions.apply(update_bindings, bindings) )) #FIXME should have other answers soon, not everything should be held... return elicit_meaning(text, view, functions.apply(update_bindings, bindings))
def get_history(asker): state = asker.ask(get_state()).firm_answer return asker.ask_tail(fields.get_field(history(), state))
def get_handler(asker): state = asker.ask(get_state()).firm_answer return asker.ask_tail(fields.get_field(handler(), state))
def get_referent(asker, rep, s): import dictionaries return asker.ask_tail(fields.get_field( fields.compose(bindings(), dictionaries.image(s)), rep ))
def get_last_concat(asker, a, b): #FIXME deal with the case where b is empty return asker.ask_tail(fields.get_field(last_element(), b))
def get(asker, field, object): return asker.ask_tail(fields.get_field(field, object))
def irreducible(asker, rep): head = asker.ask(fields.get_field(representations.head(), rep)).firm_answer result = strings.to_str(asker, head) not in reducible_heads return asker.reply(answer=T.from_bool(result)) #FIXME this is much cleaner, but too slow; at any rate could remove duplicate code return asker.ask_tail(properties.check(opposite(reducible()), rep))
def getvar(asker, bindings, variable): return asker.ask_tail(fields.get_field(dictionaries.image(variable), bindings))
def process_char(asker, root, c, parents): c = convert.to_char(asker, c) if convert.check_hard(asker, is_pointer(), root): if c == 'q': return asker.reply(value=quit) elif c == 'j': children = asker.ask(fields.get_field(visible_children(), root)).firm_answer if convert.check_hard(asker, lists.is_empty(), children): asker.pass_through(moved(down)) else: children = asker.refresh(children) first_child = asker.ask(fields.get_fields(lists.first(), children)).firm_answer asker.update(has_pointer_now(), root) asker.update(is_pointer_now(), first_child) return asker.reply() elif c == 'k': return asker.reply(value=moved(up)) elif c == 'z': asker.update(toggle_expanded(), root) return asker.reply() elif c == 'h': return asker.reply(value=moved(left)) elif c == 'l': #FIXME zoom out one by one instead of all of the way... #this is pretty straightforward if we are willing to go into and out of python #but it would surely be nicer to do it the 'right' way #I'm also pretty happy to wait asker.ask(explore_outline(root, parents)) return asker.reply(value=moved(left)) elif convert.check_hard(asker, has_pointer(), root): children = asker.ask(field.get_field(visible_children(), root)).firm_answer def make_handler(above, below): handler = Dispatcher("exploration child handler", ("question",)) @handler(moved.head) def move(asker, question, direction): if direction.head == down.head: if below is None: asker.pass_through(moved(direction)) else: asker.update(now_is_pointer(), below) asker.update(remove_pointer(), child) if direction.head == up.head: if above is None: asker.update(now_is_pointer(), root) asker.update(remove_pointer(), child) else: asker.update(add_pointer_to_bottom(), above) asker.update(remove_pointer(), child) elif direction.head == left.head: asker.update(remove_pointer(), child) asker.update(now_is_pointer(), root) return properties.trivial() #TODO insert a handler for changing underlying terms *etc* #I think that this is going to require some thought, #but I can wait return handler child_list = list(lists.iterator(asker, children)) new_parents = lists.snoc(parents, root) for i in range(len(child_list)): child = child_list[i] if i > 0: below = child_list[i-1] else: below = None if i < len(child_list) - 1: above = child_list[i+1] else: above = None asker.ask(process_char(child, c, new_parents), handler=make_handler(above, below)) return asker.reply()
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 reducible(asker, rep): head = asker.ask(fields.get_field(representations.head(), rep)).firm_answer result = strings.to_str(asker, head) in reducible_heads return asker.reply(answer=T.from_bool(result))