mirror of
https://github.com/ldmud/ldmud
synced 2026-08-12 14:26:05 -04:00
With the new pragma save_local_names the names of local variables are stored in the program so they can be inspected (with Python) later on.
344 lines
13 KiB
Text
344 lines
13 KiB
Text
PRELIMINARY
|
|
CONCEPT
|
|
python
|
|
|
|
DESCRIPTION
|
|
Python can be used to extend the LDMud driver. At the startup
|
|
of LDMud a python script will be called that can register
|
|
additional efuns. The python script can either be given
|
|
on the command line using the --python-script option,
|
|
or at compile time with the --with-python-script configuration
|
|
option.
|
|
|
|
The python script can import the builtin ldmud module.
|
|
This module provides the following functions:
|
|
|
|
- register_efun(name, function) -> None
|
|
Registers a new efun name. This is not allowed during
|
|
compilation of an LPC object.
|
|
|
|
If the Python function has type annotations for its
|
|
arguments and return value, the type is checked
|
|
at compile and runtime. Union types can be specified
|
|
as tuples of types.
|
|
|
|
- unregister_efun(name) -> None
|
|
Removes a python efun from registration. This is not
|
|
allowed during compilation of an LPC object. The
|
|
removal will only affect newly compiled code,
|
|
already compiled code will produce errors when
|
|
calling this efun.
|
|
|
|
- register_socket(fd, function [,eventmask]) -> None
|
|
Registers a socket <fd> to watch for events (like
|
|
poll/select). The socket must be either given as
|
|
an integer or an object with a fileno() method
|
|
returning an integer. The function must be a callable
|
|
accepting one argument, the actual event mask.
|
|
<eventmask> may be an combination of select.POLLIN,
|
|
select.POLLOUT and select.POLLPRI or a callable
|
|
returning such a combination.
|
|
|
|
- unregister_socket(fd) -> None
|
|
Removes a previously registered socket from the
|
|
watch list.
|
|
|
|
- register_hook(hook, function) -> None
|
|
Register a hook. The python function will be called
|
|
whenever <hook> happens. <hook> can be one of the
|
|
following:
|
|
|
|
ON_HEARTBEAT
|
|
Called without arguments for every backend loop
|
|
|
|
ON_OBJECT_CREATED
|
|
Called whenever an object was created, with the
|
|
object as its first and only argument. This call
|
|
happens before any LPC code of the object ran.
|
|
|
|
ON_OBJECT_DESTRUCTED
|
|
Called just before an object will be destructed,
|
|
with the object as its first and only argument.
|
|
|
|
ON_CHILD_PROCESS_TERMINATED
|
|
Called without any arguments whenever a SIGCHLD signal
|
|
was received. This could also happen for processes
|
|
spawned by the driver itself (eg. erq).
|
|
|
|
- unregister_hook(hook, function) -> None
|
|
Removes a hook function.
|
|
|
|
- get_master() - > Object
|
|
Returns the current master object.
|
|
Returns None, if there is no master object (yet).
|
|
|
|
- get_simul_efun() - > Object
|
|
Returns the current simul-efun object
|
|
(or None if there is none).
|
|
|
|
|
|
This module provides the following types:
|
|
|
|
- Object(filename)
|
|
Corresponds to the LPC object type.
|
|
On instantiation a filename for an object
|
|
to search or load is required.
|
|
|
|
Has the following members:
|
|
|
|
name
|
|
The object name
|
|
|
|
functions
|
|
Contains all the visible functions (private functions
|
|
are excluded) as attributes. They support the call
|
|
operator and contain the following attributes:
|
|
|
|
name
|
|
The name of the function
|
|
|
|
file_name
|
|
The file that contains the function's definition
|
|
|
|
line_number
|
|
The starting line number of the function's definition
|
|
|
|
arguments
|
|
A list of all arguments with their type, flags
|
|
(combination of LA_* constants) and position.
|
|
|
|
return_type
|
|
The return type as Python object (maybe missing if
|
|
unknown or mixed).
|
|
|
|
flags
|
|
A combination of the following flags:
|
|
LF_STATIC, LF_NOMASK, LF_VARARGS, LF_VIRTUAL and
|
|
LF_DEPRECATED
|
|
|
|
visibility:
|
|
One of the following:
|
|
VIS_PRIVATE, VIS_PROTECTED, VIS_VISIBLE, VIS_PUBLIC
|
|
|
|
variables
|
|
Contains all variables as attributes. They contain the
|
|
following attributes:
|
|
|
|
name
|
|
The name of the variable
|
|
|
|
value
|
|
The value of the variable. This attribute is writable
|
|
to assign a new value.
|
|
|
|
type
|
|
The type as a Python object (maybe missing if
|
|
unknown or mixed).
|
|
|
|
flags
|
|
A combination of the following flags:
|
|
VF_NOSAVE, VF_NOMASK, VF_VIRTUAL and VF_DEPRECATED
|
|
|
|
visibility:
|
|
One of the following:
|
|
VIS_PRIVATE, VIS_PROTECTED, VIS_VISIBLE, VIS_PUBLIC
|
|
|
|
- LWObject(filename)
|
|
Corresponds to the LPC lwobject type.
|
|
On instantiation a filename of a blueprint to create
|
|
a lightweight object from is required.
|
|
|
|
Has the following members:
|
|
|
|
program_name
|
|
The program name (file name it was created from)
|
|
|
|
functions
|
|
Contains all the visible functions (private functions
|
|
are excluded) as attributes. They are similar to the
|
|
same member of the Object type.
|
|
|
|
variables
|
|
Contains all variables as attributes. They are similar
|
|
to the same member of the Object type.
|
|
|
|
- Array([values | size])
|
|
Corresponds to an LPC array.
|
|
Can either be initialized with a list of values
|
|
or to a given size.
|
|
|
|
Supports element access with [], len() and __contains__.
|
|
|
|
- Mapping([values | width])
|
|
Corresponds to an LPC mapping.
|
|
Can either be initialized with a dict, a list of tuples
|
|
or as an empty mapping with a given width.
|
|
|
|
Supports element access with [], len(), __contains__
|
|
and has a width member.
|
|
|
|
- Struct(object, name [, values])
|
|
Corresponds to an LPC struct.
|
|
On initialization the name of the struct definition and
|
|
the correspopnding object is required. It can be initialized
|
|
with a list of values or dict.
|
|
|
|
Has the following members:
|
|
|
|
name
|
|
The name of the struct
|
|
|
|
program_name
|
|
The name of the program that defined the struct.
|
|
|
|
members
|
|
Contains all members as attributes. They contain the
|
|
following attributes:
|
|
|
|
name
|
|
The name of the member
|
|
|
|
value
|
|
The value of the member. This attribute is writable
|
|
to assign a new value.
|
|
|
|
type
|
|
The type as a Python object (maybe missing if
|
|
unknown or mixed).
|
|
|
|
- Closure(object [,name [, lfun_object]])
|
|
Corresponds to an LPC closure.
|
|
On initialization a closure bound to <object> will be created,
|
|
like a call to symbol_function(<name> [, <lfun_object>]).
|
|
|
|
Supports function calls.
|
|
|
|
- Coroutine()
|
|
Corresponds to an LPC coroutine.
|
|
They can only be created by LPC code and are not compatible
|
|
with Python coroutines.
|
|
|
|
Supports function calls and has the following members:
|
|
|
|
object
|
|
The object the coroutine belongs to.
|
|
|
|
program_name
|
|
The name of the program that defined the coroutine.
|
|
|
|
function_name
|
|
The name of the function that defined the coroutine.
|
|
|
|
file_name
|
|
The name of the file that contains the definition.
|
|
|
|
line_number
|
|
The current line where the coroutine is suspended.
|
|
|
|
variables
|
|
Contains all local variables as attributes with
|
|
their current value.
|
|
|
|
- Symbol(name [, quotes])
|
|
Corresponds to an LPC symbol.
|
|
On initialization the name of the symbol is required.
|
|
Optionally the number of quotes (at least 1) can be specified.
|
|
|
|
Has two members: name and quotes.
|
|
|
|
- QuotedArray(array [, quotes])
|
|
Corresponds to an LPC quoted array.
|
|
On initialization an array is required.
|
|
Optionally the number of quotes (at least 1) can be specified.
|
|
|
|
Has two members: array and quotes.
|
|
|
|
- Lvalue(value)
|
|
Creates an lvalue reference for the given value.
|
|
|
|
Has two member: value and members.
|
|
|
|
If the value is an array, mapping or string, then lvalues
|
|
to its elements can be created with [].
|
|
|
|
If the value is a struct, then lvalues to its members can
|
|
be created with the members attribute. It contains all
|
|
the struct members as attributes and will return an Lvalue
|
|
object to the struct member.
|
|
|
|
This module contains the following sub-namespaces:
|
|
|
|
- efuns
|
|
This namespace contains all original efuns (without any
|
|
registered python efuns or simul-efuns). These can be called
|
|
as a regular function.
|
|
|
|
|
|
There is mapping of LPC values to Python values for the following types:
|
|
int <-> int(, bool)
|
|
float <-> float
|
|
string <-> str
|
|
bytes <-> bytes
|
|
|
|
Type definitions are translated in a similar fashion, additionally the
|
|
following mappings are done:
|
|
void <-> None
|
|
union <-> tuple of types
|
|
|
|
EXAMPLE
|
|
import ldmud
|
|
|
|
def hello_world(name: str) -> int:
|
|
print("Hello, world, %s!\n" % (name,))
|
|
return 1
|
|
|
|
ldmud.register_efun("hello", hello_world)
|
|
|
|
NOTES
|
|
Just like simul-efuns python efuns can shadow real efuns. The
|
|
original efun is then inaccessible for LPC code (except for code
|
|
that was compiled before the efun was registered). Python efuns are
|
|
nearly indistinguishable from real efuns, they also use the efun::
|
|
prefix. However they can be detected with
|
|
CLOSURE_IS_PYTHON_EFUN(get_type_info(#'efun,1))
|
|
|
|
Without the prefix the order of name resolution for function calls is:
|
|
1. lfuns
|
|
2. simul-efuns
|
|
3. python efuns
|
|
4. real efuns
|
|
|
|
Also just like simul-efuns python-registered efuns are called
|
|
from LPC code that was compiled after the registration. LPC code
|
|
that was compiled before the registration will still call the
|
|
original efuns (or throw a compile error if that efun doesn't exist).
|
|
Therefore such efuns should be registered in the python startup
|
|
script.
|
|
|
|
When a python efun is unregistered, code that was compiled while the
|
|
registration was in effect will throw a runtime error. (Regardless
|
|
of whether a driver efun with the same name exists or not.)
|
|
|
|
There is a limit of 2048 python efuns. Not only registered, but also
|
|
formerly registered - but now unregistered - efuns count toward that
|
|
limit. Re-registering the same efun name again won't count a second
|
|
time. (LPC code that was compiled during the previous registration
|
|
will also call the new efun after the re-registration.)
|
|
|
|
As LDMud is single-threaded, the python code will run in the same
|
|
thread as the LPC machine. So any long-running python function will
|
|
halt the MUD for all players. Hence python functions should return
|
|
promptly and source out any lengthy tasks to another process. If
|
|
other threads are spawned from python, then these threads are not
|
|
allowed to access any LDMud functions or objects.
|
|
|
|
Finally a note of caution: Don't change the meaning of base efuns
|
|
fundamentally as it furthers confusion and hinders exchange of LPC
|
|
code and knowledge between mudlibs.
|
|
|
|
HISTORY
|
|
LDMud 3.5 implemented the python functionality.
|
|
LDMud 3.6 added type checks.
|
|
|
|
SEE ALSO
|
|
simul_efun(C)
|