| 756 | } |
| 757 | |
| 758 | void FunctionExporter::export_function(const Args& args, const Kwargs& kwargs) { |
| 759 | if (closed) { |
| 760 | throw std::runtime_error( |
| 761 | "[export_function] Attempting to write after exporting is closed."); |
| 762 | } |
| 763 | auto sorted_kwargs = |
| 764 | std::map<std::string, array>(kwargs.begin(), kwargs.end()); |
| 765 | auto [fentry, inserted] = ftable->emplace(args, sorted_kwargs); |
| 766 | if (!inserted) { |
| 767 | throw std::runtime_error( |
| 768 | "[export_function] Attempting to export a function twice with " |
| 769 | "the same signature is not allowed."); |
| 770 | } |
| 771 | |
| 772 | // Flatten the inputs to the function for tracing |
| 773 | std::vector<std::string> kwarg_keys; |
| 774 | auto inputs = args; |
| 775 | for (auto& [k, v] : sorted_kwargs) { |
| 776 | kwarg_keys.push_back(k); |
| 777 | inputs.push_back(v); |
| 778 | } |
| 779 | |
| 780 | auto flat_fun = [this, &kwarg_keys](const Args& flat_args) { |
| 781 | auto args = Args(flat_args.begin(), flat_args.end() - kwarg_keys.size()); |
| 782 | Kwargs kwargs; |
| 783 | auto it = flat_args.end() - kwarg_keys.size(); |
| 784 | ; |
| 785 | for (auto& k : kwarg_keys) { |
| 786 | kwargs.insert({k, *it++}); |
| 787 | } |
| 788 | return detail::ArraysAndExtra{fun(args, kwargs), nullptr}; |
| 789 | }; |
| 790 | |
| 791 | // Trace to build the graph |
| 792 | auto [trace_inputs, trace_outputs, extra] = |
| 793 | detail::compile_trace(flat_fun, inputs, ftable->shapeless); |
| 794 | |
| 795 | // DFS the graph and get the tape |
| 796 | auto [tape, parents_map] = |
| 797 | detail::compile_dfs(trace_inputs, trace_outputs, inputs); |
| 798 | |
| 799 | detail::compile_simplify(tape, parents_map, trace_outputs, /* passes */ 3); |
| 800 | |
| 801 | // Update the table entry |
| 802 | fentry.kwarg_keys = kwarg_keys; |
| 803 | fentry.inputs = trace_inputs; |
| 804 | |
| 805 | count++; |
| 806 | |
| 807 | if (callback) { |
| 808 | export_with_callback(trace_inputs, trace_outputs, tape, kwarg_keys); |
| 809 | return; |
| 810 | } |
| 811 | |
| 812 | // Update the header |
| 813 | auto pos = os.tell(); |
| 814 | os.seek(0); |
| 815 | write_header(os, count, ftable->shapeless); |