LPC (programming language)
From Wikipedia, the free encyclopedia
Paradigm: | prototype-based |
---|---|
Designed by: | Lars Pensjö |
Developer: | Lars Pensjö and others |
Major implementations: | LPC |
Dialects: | Amylaar, MudOS, LDMud, DGD |
Influenced by: | C, C++, Lisp |
Influenced: | Pike |
The LPC programming language is an object-oriented programming language derived from C and developed by Lars Pensjö to facilitate MUD building on LPMuds. It has been used not only for mud game creation, but also has evolved into the Pike programming language used for various internet servers, multimedia applications and system administration tasks. LPC stands for 'Lars Pensjö C'.
LPC syntax is similar to that of the Java programming language, but people used to programming in Java will notice the following key differences:
- Referencing a method of an object is done via the -> operator instead of the . operator (ob->method() instead of ob.method()); member variables cannot be externally referenced.
- LPC has no general support for threading and execution stacks are limited in duration before they "time out" (reach an evaluation limit).
Contents |
[edit] Basic structure
Almost everything in LPC is an object. However, LPC does not precisely use the concept of a class (MudOS has something called a class, but it is really a struct). Instead, LPC objects are blueprint objects and clones of blueprint objects. You can treat a blueprint object much as you would a class in other object-oriented languages, with exceptions such as not being able to specify attributes that belong only to the blueprint object, i.e. class variables, and the blueprint object being subject to interaction in exactly the same fashion as its clones.
Each object has variables (attributes) and functions (methods). The variables store the object's state; the functions are executable routines that can be called in the object. An object is uniquely defined by the name of the file in which it comes from, plus, if a clone, a numeric identifier. In a typical implementation, a clone of the file /lib/weapon.c which is the third clone created in the current run session will be /lib/weapon#3. The blueprint object corresponding to /lib/weapon.c is simply /lib/weapon. In a MUD game, common objects include rooms, weapons, armor, and NPCs. Most mudlibs define inheritable objects for such common things. In the LPMud 2.4.5 mudlib, for example, the parent object for all rooms is /lib/room.
[edit] A simple room in a Typical Mudlib
Because LPC is generally used to code MUDs, 'rooms' are often created as objects that store information describing a particular scene along with exits that point to other room objects. This is the most common usage of LPC. Other uses that are not game related are possible.
The following example shows a very simple room that leverages methods defined in the mudlib object /lib/room. However, not all mudlibs define or determine rooms in the same way. The following is typical of a traditional room, but is not the only method of defining a room.
inherit "/lib/room"; void create() { ::create(); set_short("a simple room"); set_long("A simple room in a simple building."); set_description("This is a simple room in a simple building. It is very nice."); add_exit("north", "/realms/descartes/north_room"); }
The first line tells the object to inherit functionality from the /lib/room object. This example assumes the /lib/room object defines functions for ::create(), set_short(), set_long(), set_description(), and add_exit().
This example contains a single method, create(). Most drivers call or can be set to call create() to allow an object to initialize itself with startup values. In this case, the example calls functions that set up the basic room attributes in the inherited /lib/room. The functions you call here are highly dependent on the mudlib you are using since the mudlib defines the actual room parent.
[edit] Data types
Most LPC drivers have the following data types:
- object
- int
- string
- (array, declared as <type> *)
- mapping
- float
- status
- mixed
You can count on object, int, string, array, and mixed being available in most drivers.
- An object is any LPC object, including both blueprints and clones.
- An int is a 32-bit integer.
- A string is a variable length string. You do not need to do any form of memory management or bounds management. LPC handles that for you.
- The mixed type is used to designate variables that may hold values of different types. Effectively, this disables compile-time typechecking on the variable. LPC has strong dynamic typing; you would work with mixed type variables by checking type information at runtime.
In most drivers, you define an array by type with the * modifier:
- object *
- int *
- string *
Typically, only one * can be applied to a declaration, so if you wanted an array of arrays, you would declare it as mixed *. LPC arrays are generally "rubberband" arrays that can have their length modified after allocation.
Most drivers support the mapping, float, and status data types.
- A mapping is a hash map (associative array) of keys to values.
- A float is a floating point value.
- A status is a value intended to hold a 1 or a 0 and thus represents true or false. In most drivers it is implemented as an int, and so actually can hold other values. It is deprecated in MudOS, largely because of this inconsistency.
Many drivers support a function-pointer type, most typically 'closure'.
Under MudOS, you can use the following:
- <type> array
- class <name>
- function
- map
The class type is unique to MudOS and behaves like a C struct. It is not a class in any object-oriented sense of the word. function is the MudOS function-pointer type, equivalent to the closure type in other drivers. map is the MudOS version of the mapping type.
Under DGD, you cannot use the following data types:
- array
- status
- class
Drivers which support lambda closures, such as the Amylaar LPMud driver and LDMud, have a 'symbol' type, used in lambda construction, and a quoted array type that has no declaration form, used for designating arrays so that lambda construction will not process them as execution instructions.
[edit] Passing values
Primitive LPC types (int, string, status, float, etc.) are passed by value. Data structure types (object, array, mapping, class) are passed by reference.
This feature can be powerful, but it can also lead to security holes. In most mud systems, the people building the world are generally less trusted than the staff running the game. If an object passes a mapping with sensitive values like access control information, an author of another object can modify that and thus increase their access rights. Mudlib developers and game admins should thus be careful when passing complex types to lower access objects.
[edit] Function types
LPC environments generally categorize functions into several major types according to how they are implemented:
- lfun
An lfun, or "local function", is defined by a blueprint object. (Clones have the same function set as their blueprint.) They are written in LPC. Functions in a given object can call other functions within the same object using the syntax function_name(), while functions in other objects are usually called with the syntax object->function_name(). Lfuns defined in objects one is inheriting can be called with the syntax ::function_name() or module_name::function_name().
- efun
An efun, or "external function", is defined by the driver. Efuns are written in C and compiled statically into the driver, so they generally run much faster than other function types, but lack flexibility. They are available in the namespace of all functions written in LPC, so, for example, the efun this_player() can be called with the syntax this_player(), or efun::this_player() if one needs to bypass an lfun or simul_efun.
DGD uses the term kfuns, "kernel functions", rather than efuns. DGD kfuns are mostly identical with efuns in other implementations.
- simul_efun
A simul_efun, "simulated external function", is written in LPC within the driver environment and placed in a special object whose functions mimic efuns for syntax purposes. So a simul_efun some_function() is available as some_function() in the namespace of all LPC functions.
DGD does not precisely have simul_efuns, but rather has an auto object that acts as if it is automatically inherited by all other objects. This partially mimics the behavior of simul_efuns in other implementations.
[edit] The Master Object
LPC implementations generally have a master object, which is a specific LPC object that is loaded first by the LPC driver and which essentially controls what will happen past that point. The master object will typically tell the driver where the simul_efun object is, preload any objects which need to be present at startup, define what functions will be called when an object is loaded, and otherwise configure the driver's operation. The driver will refer back to the master object when it needs to interact with a central point of reference for the running environment, such as for accepting network connections, handling errors, and validating attempts to perform privileged operations.
[edit] See also
[edit] External links
- LPC Basics by George Reese on Apr 23rd, 1993
- NannyMUD LPC by Mats H. Carlberg in March in 1998
- LPC Tutorial by Ronny Wikh on Jul 8th, 2003
- LPMuds.net - A resource for MUD's that use LPC.