One of the main goals of the refactoring project was to increase the clarity and extensibility of the LiveCode engine, by cleaning up and modularising the script execution code. The project has made it easier than ever to contribute to the development of LiveCode.
One of the areas of syntax in which this is particularly visible is that of properties. The setting and getting of properties is now largely table-driven. Say you want to add ‘myProperty’ as a global boolean property. Here is how it would be done
1) Add your property to the property enum type
The file ‘parsedef.h’ contains all the enum types associated with livecode syntax. For internal reference, ‘myProperty’ needs a numerical value, so you would just add P_MY_PROPERTY to the Properies enum.
2) Add ‘myProperty’ to the table of syntax tokens.
The file ‘lextable.cpp’ contains all the strings of LiveCode’s reserved words in various contexts. The factor table is where all the tokens for properties are defined. In this case, we would add the line
{"myProperty", TT_PROPERTY, P_MY_PROPERTY},
This associates the token with its type (property) and the enum value added in step 1. Make sure it is in alphabetical order! Script parsing uses the alphabetical ordering to speed lookup, so any mistakes will cause unexpected errors.
3) Add to the property info table
The property info table, kMCPropertyInfoTable, is located at the top of the file ‘property.cpp’. We would add
DEFINE_RW_PROPERTY(P_MY_PROPERTY, Bool, <Module>, MyProperty)
where <Module> is the name of the module in which the property should reside. This adds all the relevant information for the engine to be able to execute the relevant property setters and getters.
4) Implement the functions
The final piece of the puzzle is to implement the following two functions:
MC<Module>GetMyProperty(MCExecContext& ctxt, bool& r_value) MC<Module>SetMyProperty(MCExecContext& ctxt, bool p_value)
All being well, this is enough to get the line ‘set the myProperty to true’ in LiveCode to execute the C++ code in the body of MC<Module>SetMyProperty(MCExecContext& ctxt, bool p_value), with p_value equal to true.
In the enhancement requests section of the LiveCode forums, Dar Scott recently suggested having properties of “opened things” (i.e. sockets, processes and files). This proved to be relatively simple to add to the engine, and can be seen on GitHub at https://github.com/runrevali/livecode/tree/feature_pseudo-object_props.
I have implemented the following examples:
the rect of screen the openmode of file|process the name of socket
Notice that the last example is merely an example and not actually useful at all (it just returns the name you put in, or throws an error if the socket is not found). The first example, although equivalent to ‘line of the screenrects’, is an example of the kind of syntax that will be available with Open Language. However it is not a waste of time to implement pseudo-object properties now – it will save some effort later on when Open Language is implemented. Getting the openmode (read/write/update/append etc) of a process or file is, I believe, not currently possible, at least not directly.
The idea is just to have as a separate type of chunk expression, the pseudo-object, which behaves similarly to object chunks. There are no compound pseudo-objects (yet); the only way they parse correctly is in the form ‘the
of [screen|socket|file|process] ‘.
The framework has been set up so that more pseudo-objects can be added if necessary. Every pseudo-object needs:
– A property table, and function MC<Module>GetPropertyTable() that returns it,
– A ‘get object’ function, MC<Module>GetObject, that returns the relevant pseudo-object from the expression (eg the socket from the socket name, the screen from the screen index)
– A template function which calls the appropriate getters and setters
The implementations of these should be fairly easy to copy, see for example the file exec-network-socket.cpp for the implementations of the first two, and for the third exec.h, (search for MCSocketPropertyThunk) which contains the macros and templates – the complex systems of levers and pulleys that makes it work.
If the infrastructure of your pseudo-object is already there, you can add properties to it in much the same way as for the global properties described above, but adding the appropriate incantation to the pseudo-object’s property table. See MCScreenGetRect for a simple example, or MCProcessGetOpenMode for an example using an enumerated string type.
If you’re thinking of contributing to the engine, go to the Engine Contributors LiveCode forum at forums.runrev.com to discuss your ideas with us and other contributors.
7 comments
Join the conversationStephan Uijthoven - May 28, 2014
Stephan Uijthoven liked this on Facebook.
Faber Muñoz Perez - May 28, 2014
(y)
Faber Muñoz Perez - May 28, 2014
Faber Muñoz Perez liked this on Facebook.
Simon Smith - May 28, 2014
Simon Smith liked this on Facebook.
Andy Parng - May 29, 2014
Andy Parng liked this on Facebook.
Dar - May 30, 2014
This is very informative, and, for me, timely.
When will some of refactoring get into a release?
Ali Lloyd - June 9, 2014
Hi Dar,
Sorry for the delay in replying – I have been on holiday. All the refactoring is already present in the 7.0 series of releases, although it will be a while before that becomes the ‘master’ branch. The pseudo-object property branch is based on the refactored branch so could in theory be merged in to it at any time – as soon as something useful comes out of it!