1
2
3 #include "Config.hh"
4 #include <boost/python.hpp>
5 #include "Functional.hh"
6 #include "MMACdb.hh"
7 #include "PreClean.hh"
8 #include "Cleanup.hh"
9 #include "Parser.hh"
10 #include "Kernel.hh"
11 #include "DisplayMMA.hh"
12 #include "algorithms/substitute.hh"
13
14 using namespace cadabra;
15
16 WSLINK MMA::lp = 0;
17 WSEnvironment MMA::stdenv = 0;
18
19 //#define DEBUG 1
20
apply_mma(const Kernel & kernel,Ex & ex,Ex::iterator & it,const std::vector<std::string> & wrap,std::vector<std::string> args,const std::string & method)21 Ex::iterator MMA::apply_mma(const Kernel& kernel, Ex& ex, Ex::iterator& it, const std::vector<std::string>& wrap,
22 std::vector<std::string> args, const std::string& method)
23 {
24 // We first need to print the sub-expression using DisplaySympy,
25 // optionally with the head wrapped around it and the args added
26 // (if present).
27 std::ostringstream str;
28
29 for(size_t i=0; i<wrap.size(); ++i) {
30 str << wrap[i] << "[";
31 }
32
33 DisplayMMA ds(kernel, ex, true);
34 ds.output(str, it);
35
36 if(wrap.size()>0)
37 if(args.size()>0)
38 for(size_t i=0; i<args.size(); ++i)
39 str << ", " << args[i];
40 for(size_t i=1; i<wrap.size(); ++i)
41 str << "]";
42 str << method;
43
44 if(wrap.size()>0)
45 str << "]";
46
47 // We then execute the expression in Python.
48
49 //ex.print_recursive_treeform(std::cerr, it);
50 #ifdef DEBUG
51 std::cerr << "feeding " << str.str() << std::endl;
52 #endif
53
54 std::string result;
55
56 // ---------------------
57 setup_link();
58
59 WSPutFunction(lp, "EvaluatePacket", 1L);
60 WSPutFunction(lp, "ToString", 1L);
61 WSPutFunction(lp, "FullForm", 1L);
62 WSPutFunction(lp, "ToExpression", 1L);
63 WSPutUTF8String(lp, (const unsigned char *)str.str().c_str(), str.str().size());
64 WSEndPacket(lp);
65 WSFlush(lp);
66
67 // std::cerr << "flushed" << std::endl;
68
69 int pkt=0;
70 while( (pkt = WSNextPacket(lp), pkt) && pkt != RETURNPKT ) {
71 // std::cerr << "received packet " << pkt << std::endl;
72 WSNewPacket(lp);
73 if (WSError(lp)) {
74 std::cerr << "error" << std::endl;
75 }
76 }
77 // std::cerr << "packet now " << pkt << std::endl;
78
79 const char *out;
80 if(! WSGetString(lp, &out)) {
81 throw InternalError("Unable to read from WSTP link");
82 }
83 else {
84 result=out;
85 WSReleaseString(lp, out);
86 if(result=="$Failed") {
87 throw RuntimeException("Mathematica failed to handle expression.");
88 }
89 }
90 // -------------------------------
91
92 // After that, we construct a new sub-expression from this string by using our
93 // own parser, and replace the original.
94
95 #ifdef DEBUG
96 std::cerr << "result: " << result << std::endl;
97 #endif
98
99 result = ds.preparse_import(result);
100
101 #ifdef DEBUG
102 std::cerr << "preparsed: " << result << std::endl;
103 #endif
104
105 auto ptr = std::make_shared<Ex>();
106 cadabra::Parser parser(ptr);
107 std::stringstream istr(result);
108 istr >> parser;
109
110 pre_clean_dispatch_deep(kernel, *parser.tree);
111 cleanup_dispatch_deep(kernel, *parser.tree);
112
113 //parser.tree->print_recursive_treeform(std::cerr, parser.tree->begin());
114
115 #ifdef DEBUG
116 std::cerr << "cleaned up: " << *parser.tree << std::endl;
117 #endif
118
119 ds.import(*parser.tree);
120
121 #ifdef DEBUG
122 std::cerr << "imported: " << *parser.tree << std::endl;
123 #endif
124
125 pre_clean_dispatch_deep(kernel, *parser.tree);
126 cleanup_dispatch_deep(kernel, *parser.tree);
127
128 Ex::iterator first=parser.tree->begin();
129 // std::cerr << "reparsed " << Ex(first) << std::endl;
130 it = ex.move_ontop(it, first);
131
132 return it;
133 }
134
setup_link()135 void MMA::setup_link()
136 {
137 if(lp!=0) return; // already setup
138
139 char argvi[4][512] = { "-linkname", Mathematica_KERNEL_EXECUTABLE " -mathlink", "-linkmode", "launch" };
140 char *argv[4];
141 for (size_t i=0; i<4; ++i)
142 argv[i] = argvi[i];
143 int argc = 4;
144
145 int errno;
146 stdenv = WSInitialize((WSEnvironmentParameter)0);
147 if(stdenv==0)
148 throw InternalError("Failed to initialise WSTP");
149
150 // std::cerr << "initialised" << std::endl;
151
152 try {
153 lp = WSOpenArgcArgv(stdenv, argc, argv, &errno);
154 if(lp==0 || errno!=WSEOK) {
155 // std::cerr << errno << ", " << WSErrorMessage(lp) << ";" << std::endl;
156 lp=0;
157 WSDeinitialize(stdenv);
158 throw InternalError("Failed to open Mathematica link");
159 }
160 }
161 catch(std::exception& ex) {
162 lp=0;
163 WSDeinitialize(stdenv);
164 throw InternalError("Failed to open Mathematica link");
165 }
166
167 // std::cerr << "loopback link open" << std::endl;
168
169 WSActivate(lp);
170 }
171
teardown_link()172 void MMA::teardown_link()
173 {
174 if(lp!=0) {
175 WSClose(lp);
176 WSDeinitialize(stdenv);
177 lp=0;
178 }
179 }
180