[go: up one dir, main page]

Menu

[80c337]: / lobscript.h  Maximize  Restore  History

Download this file

385 lines (363 with data), 18.8 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
/** \file lobscript.h
*
* \brief This file contains the necessary functions for making Lobs scriptable
*
* The main function it defines is addLobsToScriptEngine(), which uses all the other
* functions and data in this file to enable a given script engine to create and manipulate
* Lobs from in-script.
*
* Note that the best resource we have found about an introduction to ECMAScript is
* <a href='http://en.wikipedia.org/wiki/ECMAScript_syntax'>the Wikipedia article
* "ECMAScript syntax"</a> (also entitled "JavaScript syntax").
*/
#ifndef LOB_SCRIPT
#define LOB_SCRIPT
#include <QtScript>
#include "lob.h"
/** \brief Adds to the given script engine all the functionality it needs to use Lobs
*
* It registers three classes with the Qt Metatype system (if it has not already done so),
* Lob, Lob*, and LobAddress. It also adds the following things to the script environment.
* Each is described below.
* <ul>
* <li>an <code>OmTypes</code> object</li>
* <li>a <code>Lob</code> constructor</li>
* <li>methods in the Lob prototype</li>
* <li>a convenience function <code>exclude()</code></li>
* </ul>
* Note that the Lob and Lob* classes get member functions as they are converted,
* while the LobAddress class, because it is not a QObject, has four useful member functions
* added, toString(), numSteps(), equal(), and less(). The first two of these function just
* like LobAddress::toString() and LobAddress::numSteps(), while the others embody the C++
* LobAddress::operator<() and LobAddress::operator==().
* Note that LobAddress objects in script have the properties
* stepTypes and stepIndices, which are arrays, the latter of which has values you can
* compare to the four extra entries in the OmTypes object (see immediately below).
*
* <h3>The OmTypes Object</h3>
* The OmTypes object in scripts has properties corresponding to the
* actual values of the OmType enum in C++. Having these values accessible in script
* allows script authors to compare results of Lob.type properties to known values,
* as follows.
* \code
* if ( myLob.type == OmTypes.String ) {
* // do something
* }
* \endcode
* Here is the table of OmType properties.
* <table>
* <tr><th>Script property</th><th>C++ value</th></tr>
* <tr><td><code>OmTypes.Integer</code></td>
* <td><code>OmIntegerType</code></td></tr>
* <tr><td><code>OmTypes.BigInteger</code></td>
* <td><code>OmBigIntegerType</code></td></tr>
* <tr><td><code>OmTypes.Float</code></td>
* <td><code>OmFloatType</code></td></tr>
* <tr><td><code>OmTypes.ByteArray</code></td>
* <td><code>OmByteArrayType</code></td></tr>
* <tr><td><code>OmTypes.Variable</code></td>
* <td><code>OmVariableType</code></td></tr>
* <tr><td><code>OmTypes.String</code></td>
* <td><code>OmStringType</code></td></tr>
* <tr><td><code>OmTypes.WideString</code></td>
* <td><code>OmWStringType</code></td></tr>
* <tr><td><code>OmTypes.Symbol</code></td>
* <td><code>OmSymbolType</code></td></tr>
* <tr><td><code>OmTypes.ProcessingInstruction</code></td>
* <td><code>OmPInstructionType</code></td></tr>
* <tr><td><code>OmTypes.Application</code></td>
* <td><code>OmApplicationType</code></td></tr>
* <tr><td><code>OmTypes.Error</code></td>
* <td><code>OmErrorType</code></td></tr>
* <tr><td><code>OmTypes.Object</code></td>
* <td><code>OmObjectType</code></td></tr>
* <tr><td><code>OmTypes.Binding</code></td>
* <td><code>OmBindingType</code></td></tr>
* <tr><td><code>OmTypes.Unknown</code></td>
* <td><code>OmUnknownType</code></td></tr>
* </table>
* It also contains a map from type codes to names, in the following sense.
* <pre>
* OmTypes[OmTypes.Integer] == "Integer"
* OmTypes[OmTypes.BigInteger] == "BigInteger"
* OmTypes[OmTypes.Float] == "Float"
* OmTypes[OmTypes.ByteArray] == "ByteArray"
* // and so on...
* </pre>
* This is useful when you have a type, and want some debugging information about it.
* For instance, in code like this:
* <code>print( "The Lob L is of type " + OmTypes[L.type] );</code>
*
* Four additional properties are added so that ownership types (as used in LobAddresses)
* can be understood in scripts.
* <table>
* <tr><th>Script property</th><th>C++ value</th></tr>
* <tr><td><code>OmTypes.None</code></td>
* <td><code>OmNode::None</code></td></tr>
* <tr><td><code>OmTypes.AsChild</code></td>
* <td><code>OmNode::AsChild</code></td></tr>
* <tr><td><code>OmTypes.AsKey</code></td>
* <td><code>OmNode::AsKey</code></td></tr>
* <tr><td><code>OmTypes.AsValue</code></td>
* <td><code>OmNode::AsValue</code></td></tr>
* </table>
*
* <h3>The Lob Constructor</h3>
* The Lob constructor in scripts works as follows.
* <table>
* <tr><th>Script code</th><th>Result</th></tr>
* <tr>
* <td><code>a = Lob();</code></td>
* <td><code>a</code> contains a new, empty Lob</td>
* </tr>
* <tr>
* <td><code>a = new Lob();</code></td>
* <td>same as previous case</td>
* </tr>
* <tr>
* <td><code>a = Lob( '&lt;OMI>3&lt;/OMI>' );</code></td>
* <td><code>a</code> contains the OpenMath tree described by the XML code given.
* Any XML code describing a single OpenMath tree will result in a Lob
* that is just that tree. Note the difference between this and Lob::fromXML(),
* which wraps any result in a node of type OmUnknownType, even if it is only
* one node.
* So for example, in the case given to the left, we would then have
* <code>a.basicValue == 3</code> and <code>a.numChildren() == 0</code>.</td>
* </tr>
* <tr>
* <td><code>a = new Lob( '&lt;OMI>3&lt;/OMI>' );</code></td>
* <td>same as previous case</td>
* </tr>
* <tr>
* <td><code>a = Lob( '&lt;OMI>3&lt;/OMI>&lt;OMSTR>foo&lt;/OMSTR>' );</code></td>
* <td><code>a</code> contains an OpenMath tree whose root is of type OmUnknownType,
* and whose children are described by the XML code given.
* Any XML code describing more than one OpenMath tree will result in this kind
* of wrapping, which is the behavior Lob::fromXML() gives for any input.
* So for example, in the case given to the left, we would then have
* <code>a.type == OmTypes.Unknown</code>,
* <code>a.numChildren() == 2</code>, and
* <code>a.child(0).basicValue == 3</code>.</td>
* </tr>
* <tr>
* <td><code>a = new Lob( '&lt;OMI>3&lt;/OMI>&lt;OMSTR>foo&lt;/OMSTR>' );</code></td>
* <td>same as previous case</td>
* </tr>
* </table>
* In addition to the above examples, the Lob constructor ensures that the prototype object
* for Lobs has a new method in it just for scripts, the equals() method. The reason for
* this is that QtScript does not automatically translate the C++ Lob::operator==() to
* script land, and so a member function must be used instead.
*
* <h3>Methods in the Lob prototype</h3>
* One method is added to the Lob prototype, so that it is available as a member function
* for all Lobs in script. It is added here because it is not necessary in C++, as
* is clear by its nature.
* <ul>
* <li><code>equals()</code> - You can call <code>anyLob.equals(anotherLob)</code> to
* check to see if they are wrapping the same OpenMath object. This is different
* from checking <code>anyLob == anotherLob</code> because this latter expression
* asks if the two are different script objects, which they may be even if they wrap
* the same OpenMath object. Thus <code>equals()</code> in script is equivalent to
* <code>Lob::operator==()</code> in C++.</li>
* <li><code>call()</code> - This function was once added to the Lob prototype, but has
* been superceded by the FunctionLob script class in the LobUtilitiesPackage.</li>
* </ul>
*
* <h3>The exclude() Function</h3>
* When calling <code>aLob.equivalentTo()</code>, there is an optional third argument for
* symbols to exclude from consideration if comparing attributes. Due to a combination of
* our design, C++ limitations, and the Qt metatype system, it became a headache to add an
* overloaded (or even differently-named) version that would be callable from script and
* take an array of symbol Lobs as the third argument. Yet this is what script writers
* expect and should get, so the <code>exclude()</code> function was created. It converts
* a sequence of symbol Lobs to a string list of names and content dictionaries of the form
* Lob::equivalentTo() expects as its third argument. So you can write code like this
* <pre>
* someLob.equivalentTo( anotherLob, true, exclude( someSymbol, anotherSymbol ) )
* </pre>
* and it translates to a call like the following in C++.
* <pre>
* someLob.equivalentTo( anotherLob, true,
* QStringList() << "name of someSymbol" << "content dictionary of someSymbol"
* << "name of anotherSymbol" << "content dictionary of anotherSymbol" );
* </pre>
* Note that any object passed to exclude that is not a symbol Lob is ignored.
* So <code>exclude( symbolLob, 3, 7 )</code> is the same as
* <code>exclude( symbolLob )</code>.
*
* <h3>The escapeXML() and unescapeXML() Functions</h3>
* For creating strings that can be safely placed inside XML expressions
* (such as &lt;OMSTR&gt; nodes), these two functions are handy to have in script land.
* They call the C++ functions of the same names, documented on the page for the Lob class.
*
* <h3>The escapeChars() and unescapeChars() Functions</h3>
* For creating strings limited to alphanumeric characters plus an underscore (_) out of
* any Unicode string, these two functions are handy to have in script land.
* They call the C++ functions scriptEscapeChars() and scriptUnescapeChars(),
* documented below.
*
* <h3>The codeString() Function</h3>
* For converting a string into JavaScript code that evaluates to that string, useful when
* creating strings of code. See scriptCodeString() for more information.
*
* <h3>The setHelp() and copyHelp() Functions</h3>
* The former is used to install developer help into an object, and the latter to copy help from
* one object to another. For help on how to use these functions, or for how to get developer
* help when in Lurch, type a question mark (?) alone in the developer console, and execute it.
*
* <h3>The makeLurchURN() and splitLurchURN() Functions</h3>
* These are in-script-land embodiments of Lob::makeLurchURN() and Lob::splitLurchURN().
*
* <h3>The globalNamespace Object</h3>
* The identifier <code>globalNamespace</code> is added as an attribute of the JavaScript
* global object, and refers to that object itself. This is useful for getting a list of
* all identifiers defined; one can look at the properties of the object, or ask for help on
* it in the Lurch console.
*/
void addLobsToScriptEngine ( QScriptEngine& engine );
/** \brief Escapes Unicode characters other than ASCII alphanumerics and the underscore
*
* A string containing any unicode characters can be passed as input (as \a context argument
* zero) and this function will replace all characters other than a-z, A-Z, and 0-9 with
* five-character sequences of the form _AABB, where AA is the hexadecimal (0-9, a-f)
* representation of the Unicode row of the encoded character, and BB is the hexadecimal
* representation of its Unicode cell. Thus the output from this function (returned as a
* string inside the script engine) contains only the characters a-z, A-Z, 0-9, and _.
* The inverse operation can be done with scriptUnescapeChars().
*
* For example, the string "Hello there" is encoded as "Hello_0020there" because the ASCII
* space is the Unicode character in row 00 and cell 20 (in hex, or 32 in decimal).
*/
QScriptValue scriptEscapeChars ( QScriptContext* context, QScriptEngine* engine );
/** \brief Inverts the operation of scriptEscapeChars().
*
* See the documentation for scriptEscapeChars() for more information.
*/
QScriptValue scriptUnescapeChars ( QScriptContext* context, QScriptEngine* engine );
/** \brief Used internally by scriptEscapeChars(). See its documentation for details.
*/
QString escapeChars ( QString input );
/** \brief Used internally by scriptUnescapeChars(). See its documentation for details.
*/
QString unescapeChars ( QString input );
/** \brief Convert any text into a JavaScript string literal that evaluates to that text
*
* <table>
* <tr><th>Example input</th><th>Corresponding output</th></tr>
* <tr><td>She said, "I don't think so."</td>
* <td>\code "She said, \"I don't think so.\"" \endcode</td>
* <tr><td>hello 'world'</td>
* <td>\code 'hello \'world\'' \endcode</td></tr>
* <tr><td>there is a newline<br>before these words</td>
* <td>\code 'there is a newline\\nbefore these words' \endcode</td></tr>
* <tr><td>some "quotes" and \"escaped quotes\"</td>
* <td>\code 'some "quotes" and \\\\"escaped quotes\\"' \endcode</td></tr>
* <tr><td>multi-line<br>input</td>
* <td>\code 'multi-line\\ninput' \endcode</td></tr>
* </table>
*
* Given any text as input, this routine escapes offending characters and wraps the result
* in quotes, so that the result can be used in Javascript code as a string literal
* whose value will be the original input.
*
* If you had a very long line of input, you might want the result to be
* several string literals split over several lines of code (with instances of the + operator
* to join them) for readability. To achieve this behavior, use the optional \a withBreaks
* parameter set to true.
*
* This routine is used for implementing the "paste string literal"
* action in source code editors, among many other things.
*/
QString toJavascriptString ( QString text, bool withBreaks = false );
/** \brief Escapes a string to prepare it for insertion in JavaScript code
*
* If in JavaScript, you are building a string that you will later pass to eval() (that is,
* you're building a string of JavaScript code), it can be dangerous to insert arbitrary
* strings into it. Consider this example.
* \code
* var myJSCode = 'var x = 3;\n'
* + 'var y = "' + someString + '";\n'
* + 'y.length + x';
* eval( myJSCode );
* \endcode
* In some situations, the result will be <code>someString.length + 3</code>, but not in all.
* For instance, if someString contained a double-quote character, or a newline, the eval()
* call would result in an error instead. Worse, someString might contain code that does
* something malicious.
*
* So it's helpful to escape someString for use as a JavaScript string. This routine does
* so, and should be used as in the following example.
* \code
* var myJSCode = 'var x = 3;\n'
* + 'var y = ' + codeString( someString ) + ';\n'
* + 'y.length + x';
* eval( myJSCode );
* \endcode
* Notice that the double quotes around someString have gone. This routine puts quotes
* around its result, and escapes the content appropriately for the quotes used.
*
* \see toJavascriptString()
*/
QScriptValue scriptCodeString ( QScriptContext* context, QScriptEngine* engine );
/** \brief Prints HTML-formatted help on the value passed as first parameter.
*
* If the value is an object with the helpHTML property, that value is printed.
*
* If the value is an object without that property, a message that no help is available is
* printed. (This will change to something more robust in future revisions.)
*
* If the value is a non-object, its value and type are printed. In addition, if it is a
* string, a link to search that string in online help is provided.
*
* The return value is always the script value "undefined."
*/
QScriptValue scriptHelp ( QScriptContext* context, QScriptEngine* engine );
/** \brief Utility function to prepare objects for access by scriptHelp()
*
* Looks through all data in the :/doxygen/Lurch-doxygen.*.processed files (see
* doxygenhelp.qrc) to find any information on members of the class with the given
* \a className. Any members whose information appears are decorated with .helpHTML
* attributes, whose values are strings containing HTML help on the given member.
*/
void putHelpDataInto ( QScriptValue object, QString className );
/** \brief Utility function to for reading data of the kind that is useful to scriptHelp()
*
* Looks through all data in the :/doxygen/Lurch-doxygen.*.processed files (see
* doxygenhelp.qrc) to find any information on the member with the given \a memberName
* in the class with the given \a className. If information appears satisfying these two
* criteria, the corresponding string containing HTML help on the given member is returned;
* otherwise, the empty string is.
*/
QString getHelpDataFor ( QString className, QString memberName );
/** Allows Lob to be a scriptable type, by permitting conversion from Lob to script values
*/
QScriptValue LobStarToScriptValue ( QScriptEngine* engine, Lob* const& in );
/** Allows Lob to be a scriptable type, by permitting conversion to Lob from script values
*/
void LobStarFromScriptValue ( const QScriptValue& object, Lob*& out );
/** Allows Lob to be a scriptable type, by converting it to Lob*, which is scriptable
*/
QScriptValue LobToScriptValue ( QScriptEngine* engine, const Lob& in );
/** Allows Lob to be a scriptable type, by converting it to Lob*, which is scriptable
*/
void LobFromScriptValue ( const QScriptValue& object, Lob& out );
/** Obtain a list of properties that are put into any QScriptEnvironment's global object by
* default.
*/
QStringList globalFixtures ();
/** Copies all properties from one QScriptValue to another, except for any in globalFixtures()
*/
void copyProperties ( QScriptValue from, QScriptValue to );
/** Calls qDebug() to print out a hierarchy of existing objects and their properties
*/
void debugDeepProperties ( QScriptValue v );
/** \brief Returns a short context surrounding a given line of code
*
* From the block of \a code in the given string, return just the five lines (or less)
* centered on the given \a lineNumber. This is useful for printing out errors in context.
* Line numbers are included in the output if and only if \a includeNumbers is true (the
* default).
*/
QString getContext ( QString code, int lineNumber, bool includeNumbers = true );
#endif // LOB_SCRIPT