// Recursively print all nodes below a current one. static dot_graph& recursive_print_impl(const std::shared_ptr<planner_node>& node, std::map<pnode_ptr, std::string>& node_name_map, dot_graph& graph) { pnode_tagger get_tag = [&](pnode_ptr p) -> std::string { auto it = node_name_map.find(p); if(it == node_name_map.end()) { auto s = to_name(node_name_map.size()); node_name_map[p] = s; return s; } else { return it->second; } }; std::string vid = std::to_string((ptrdiff_t)(node.get())); std::string name = (get_tag(node) + ": " + extract_field<visitor_repr, std::string>(node->operator_type, node, get_tag)); bool added = graph.add_vertex(vid, name); // return if the vertex has already been added if (!added) return graph; for (auto input : node->inputs) { std::string srcvid = std::to_string((ptrdiff_t)(input.get())); graph.add_edge(srcvid, vid); recursive_print_impl(input, node_name_map, graph); } return graph; }
void switching(char *hotel_current, char *hotel_name) { char hotel_filename[NAME_MAXIMUM + 1]; FILE *hotel_file; hotel hotel_new; if(!get_name("Hotel Name", hotel_filename, hotel_name)) return; to_filename(hotel_filename); strcat(hotel_filename, NAME_EXTENSION); hotel_file = fopen(hotel_filename, "rb"); if(!hotel_file){ error_print("File not opened!"); return; } fread(&hotel_new, sizeof(hotel_new), 1, hotel_file); if(feof(hotel_file) || ferror(hotel_file)){ error_print("Data not read!"); goto cleanup; } strcpy(hotel_current, to_name(hotel_new.name)); cleanup: fclose(hotel_file); }
options join(options const & opts1, options const & opts2) { sexpr r = opts2.m_value; for_each(opts1.m_value, [&](sexpr const & p) { if (!opts2.contains(to_name(car(p)))) r = cons(p, r); }); return options(r); }
/** \brief Return a new set of options based on \c opts by adding the prefix \c prefix. The procedure throws an exception if \c opts contains an options (o, v), s.t. prefix + o is an unknown option in Lean. */ options add_prefix(name const & prefix, options const & opts) { option_declarations const & decls = get_option_declarations(); return map(opts.m_value, [&](sexpr const & p) { name n = prefix + to_name(car(p)); if (decls.find(n) == decls.end()) throw exception(sstream() << "unknown option '" << n << "'"); return cons(sexpr(n), cdr(p)); }); }
vm_obj attribute_register(vm_obj const & vm_n, vm_obj const & vm_s) { auto const & s = to_tactic_state(vm_s); auto const & n = to_name(vm_n); LEAN_TACTIC_TRY; auto env = add_user_attr(s.env(), n); env = module::add(env, *g_key, [=](environment const &, serializer & s) { s << n; }); return mk_tactic_success(set_env(s, env)); LEAN_TACTIC_CATCH(s); }
vm_obj attribute_fingerprint(vm_obj const & vm_n, vm_obj const & vm_s) { auto const & s = to_tactic_state(vm_s); auto const & n = to_name(vm_n); unsigned h; LEAN_TACTIC_TRY; h = get_attribute(s.env(), n).get_fingerprint(s.env()); LEAN_TACTIC_CATCH(s); return mk_tactic_success(mk_vm_nat(h), s); }
/* VM builtins */ vm_obj attribute_get_instances(vm_obj const & vm_n, vm_obj const & vm_s) { auto const & s = to_tactic_state(vm_s); auto const & n = to_name(vm_n); buffer<name> b; LEAN_TACTIC_TRY; get_attribute(s.env(), n).get_instances(s.env(), b); LEAN_TACTIC_CATCH(s); return mk_tactic_success(to_obj(b), s); }
options options::update(name const & n, sexpr const & v) const { if (contains(n)) { return map(m_value, [&](sexpr p) { if (to_name(car(p)) == n) return cons(car(p), v); else return p; }); } else { return options(cons(cons(sexpr(n), v), m_value)); } }
// meta_constant level.instantiate : level → list (name × level) → list level vm_obj level_instantiate(vm_obj const & o, vm_obj const & lst) { level const & l = to_level(o); buffer<name> ns; buffer<level> ls; vm_obj it = lst; while (!is_simple(it)) { vm_obj const & h = cfield(it, 0); ns.push_back(to_name(cfield(h, 0))); ls.push_back(to_level(cfield(h, 1))); it = cfield(it, 1); } return to_obj(instantiate(l, to_list(ns), to_list(ls))); }
format pp(options const & o) { bool unicode = get_pp_unicode(o); format r; bool first = true; char const * arrow = unicode ? g_arrow : g_assign; for_each(o.m_value, [&](sexpr const & p) { if (first) { first = false; } else { r += comma(); r += line(); } name const & n = to_name(head(p)); unsigned sz = n.size(); unsigned indent = unicode ? sz+3 : sz+4; r += group(nest(indent, pp(head(p)) + space() + format(arrow) + space() + pp(tail(p)))); }); format open = unicode ? format(g_left_angle_bracket) : lp(); format close = unicode ? format(g_right_angle_bracket) : rp(); return group(nest(1, open + r + close)); }
// A basic function to print a node. std::string planner_node_repr(const std::shared_ptr<planner_node>& node) { std::map<pnode_ptr, std::string> names; pnode_tagger get_tag = [&](pnode_ptr p) -> std::string { auto it = names.find(p); if(it == names.end()) { auto s = to_name(names.size()); names[p] = s; return s; } else { return it->second; } }; return get_tag(node) + ": " + extract_field<visitor_repr, std::string>(node->operator_type, node, get_tag); }
vm_obj caching_user_attribute_get_cache(vm_obj const &, vm_obj const & vm_attr, vm_obj const & vm_s) { tactic_state const & s = to_tactic_state(vm_s); name const & n = to_name(cfield(vm_attr, 0)); vm_obj const & cache_handler = cfield(vm_attr, 2); list<name> const & deps = to_list_name(cfield(vm_attr, 3)); LEAN_TACTIC_TRY; environment const & env = s.env(); attribute const & attr = get_attribute(env, n); user_attr_cache & cache = get_user_attribute_cache(); auto it = cache.m_cache.find(attr.get_name()); if (it != cache.m_cache.end()) { if (it->second.m_fingerprint == attr.get_fingerprint(env) && check_dep_fingerprints(env, deps, it->second.m_dep_fingerprints)) { return mk_tactic_success(it->second.m_val, s); } lean_trace("user_attributes_cache", tout() << "cached result for [" << attr.get_name() << "] " << "has been found, but cache fingerprint does not match\n";); } else {
sexpr options::get_sexpr(name const & n, sexpr const & default_value) const { sexpr const * r = find(m_value, [&](sexpr const & p) { return to_name(head(p)) == n; }); return r == nullptr ? default_value : tail(*r); }
vm_obj level_meta(vm_obj const & n) { return to_obj(mk_meta_univ(to_name(n))); }
vm_obj level_global(vm_obj const & n) { return to_obj(mk_global_univ(to_name(n))); }
vm_obj level_param(vm_obj const & n) { return to_obj(mk_param_univ(to_name(n))); }
vm_obj options_set_string(vm_obj const & o, vm_obj const & n, vm_obj const & v) { return to_obj(to_options(o).update(to_name(n), to_string(v))); }
void bill(char *hotel_current, char *guest) { int i, service_id, bill_amount; char hotel_filename[NAME_MAXIMUM + 1], guest_name[NAME_MAXIMUM + 1]; FILE *hotel_file, *service_file; fpos_t write_position; hotel hotel_new; service service_new; room room_new; if(!*hotel_current){ error_print("No hotel selected! Use\n\tswitch <hotel name>"); return; } to_filename(strcpy(hotel_filename, hotel_current)); strcat(hotel_filename, NAME_EXTENSION); hotel_file = fopen(hotel_filename, "rb+"); if(!hotel_file){ error_print("File not opened!"); return; } service_file = fopen(SERVICE_FILENAME, "rb"); if(!service_file){ error_print("Services file unavailable!"); fclose(hotel_file); return; } if(!get_name("Guest Name", guest_name, guest)) goto cleanup; fread(&hotel_new, sizeof(hotel_new), 1, hotel_file); if(feof(hotel_file) || ferror(hotel_file)){ error_print("Data not read!"); goto cleanup; } for(i = 0; i < hotel_new.rooms; ++i){ fgetpos(hotel_file, &write_position); fread(&room_new, sizeof(room_new), 1, hotel_file); if(ferror(hotel_file)){ error_print("Data not read!"); goto cleanup; } if(feof(hotel_file)) break; if(!strcmp(room_new.guest, guest_name)) break; } if(i == hotel_new.rooms || feof(hotel_file)){ error_print("Guest not found!"); goto cleanup; } if(!room_new.number_of_services) goto cleanup; printf( "Bill for %s\n" "+----+------+------------------------------------------------------+\n" "| ID | Cost | Description |\n" "+----+------+------------------------------------------------------+\n" , to_name(room_new.guest) ); bill_amount = 0; for(i = 0; i < room_new.number_of_services; ++i){ for(service_id = 1; ; ++service_id){ fread(&service_new, sizeof(service_new), 1, service_file); if(feof(service_file) || ferror(service_file)){ error_print("Data not read!"); goto cleanup; } if(service_id != room_new.service_list[i]) continue; printf( "| %2d | %4d | %52.52s |\n", service_id, service_new.cost, to_name(service_new.description) ); bill_amount += service_new.cost; break; } rewind(service_file); } room_new.number_of_services = 0; fsetpos(hotel_file, &write_position); fwrite(&room_new, sizeof(room_new), 1, hotel_file); if(ferror(hotel_file)){ error_print("Data not written!"); goto cleanup; } printf( "+----+------+------------------------------------------------------+\n" "| | %4d | Total |\n" "+----+------+------------------------------------------------------+\n" , bill_amount ); cleanup: fclose(hotel_file); fclose(service_file); }
vm_obj options_get_bool(vm_obj const & o, vm_obj const & n, vm_obj const & v) { return mk_vm_bool(to_options(o).get_bool(to_name(n), to_bool(v))); }
vm_obj options_get_nat(vm_obj const & o, vm_obj const & n, vm_obj const & v) { return mk_vm_nat(to_options(o).get_unsigned(to_name(n), to_unsigned(v))); }
vm_obj options_get_string(vm_obj const & o, vm_obj const & n, vm_obj const & v) { return to_obj(std::string(to_options(o).get_string(to_name(n), to_string(v).c_str()))); }
vm_obj options_set_nat(vm_obj const & o, vm_obj const & n, vm_obj const & v) { return to_obj(to_options(o).update(to_name(n), to_unsigned(v))); }
void options::for_each(std::function<void(name const &)> const & fn) const { ::lean::for_each(m_value, [&](sexpr const & p) { fn(to_name(head(p))); }); }
bool options::contains(char const * n) const { return ::lean::contains(m_value, [&](sexpr const & p) { return to_name(head(p)) == n; }); }
/* * Service request stub emitter. * * Emit a service request stub of type `sr' at `start' in `cb'. */ void emit_svcreq(CodeBlock& cb, TCA start, bool persist, folly::Optional<FPInvOffset> spOff, ServiceRequest sr, const ArgVec& argv) { FTRACE(2, "svcreq @{} {}(", start, to_name(sr)); auto const is_reused = start != cb.frontier(); CodeBlock stub; stub.init(start, stub_size(), "svcreq_stub"); { Vauto vasm{stub}; auto& v = vasm.main(); // If we have an spOff, materialize rvmsp() so that handleSRHelper() can do // a VM reg sync. (When we don't have an spOff, the caller of the service // request was responsible for making sure rvmsp already contained the top // of the stack.) if (spOff) { v << lea{rvmfp()[-cellsToBytes(spOff->offset)], rvmsp()}; } auto live_out = leave_trace_regs(); assert(argv.size() <= kMaxArgs); // Pick up CondCode arguments first---vasm may optimize immediate loads // into operations which clobber status flags. for (auto i = 0; i < argv.size(); ++i) { auto const& arg = argv[i]; if (arg.kind != Arg::Kind::CondCode) continue; FTRACE(2, "c({}), ", cc_names[arg.cc]); v << setcc{arg.cc, r_svcreq_sf(), rbyte(r_svcreq_arg(i))}; } for (auto i = 0; i < argv.size(); ++i) { auto const& arg = argv[i]; auto const r = r_svcreq_arg(i); switch (arg.kind) { case Arg::Kind::Immed: FTRACE(2, "{}, ", arg.imm); v << copy{v.cns(arg.imm), r}; break; case Arg::Kind::Address: FTRACE(2, "{}(%rip), ", arg.imm); v << leap{reg::rip[arg.imm], r}; break; case Arg::Kind::CondCode: break; } live_out |= r; } FTRACE(2, ") : stub@"); if (persist) { FTRACE(2, "<none>"); v << copy{v.cns(0), r_svcreq_stub()}; } else { FTRACE(2, "{}", stub.base()); v << leap{reg::rip[int64_t(stub.base())], r_svcreq_stub()}; } v << copy{v.cns(sr), r_svcreq_req()}; live_out |= r_svcreq_stub(); live_out |= r_svcreq_req(); v << jmpi{TCA(handleSRHelper), live_out}; // We pad ephemeral stubs unconditionally. This is required for // correctness by the x64 code relocator. vasm.unit().padding = !persist; } if (!is_reused) cb.skip(stub.used()); }
vm_obj options_contains(vm_obj const & o, vm_obj const & n) { return mk_vm_bool(to_options(o).contains(to_name(n))); }