|
3.1 Overview: MPI
MPI is an interpretted language with a
LISP -like syntax available to all players. Because it is
universally available, MPI includes some security features
that restrict its power. In general, MPI can only read
props on the triggering object and on objects controlled by the
controller of the object on which the MPI string is stored,
and can only set props on the latter... on objects controlled by the
owner of the MPI object. Other than setting props as
mentioned, it is difficult (but not impossible) to significantly modify
the database with MPI, but is ideally suited for
message-handling. And because it is interpretted, it is well-suited for
one-off programming tasks: no separate compiling and linking operations
are needed, nor is a separate program object for holding the code.
MPI's syntax consists of nested functions enlcosed in
curly braces that are evaluated left-to-right and `from the inside out',
much like mathematical expressions are evaluated outward from the
innermost set of parentheses. For example...
{if:{eq:{ref:me},#1},Hey it's God!,Hello world!}
The MPI parser will first evaluate the innermost
function, {ref:me}. The {ref} function returns
the dbref of its single argument which in this case is
`me' so, {ref:me} returns the user's
dbref. The returned expression `replaces', as it were, the function. So,
if the user's dbref were #123, the MPI string
would in effect and at this moment be...
{if:{eq:#123,#1},Hey it's God!,Hello world!.}
Then the next-innermost expression, effectively
{eq:#123,#1}, would be evaluated. The {equals}
function returns true if the two arguments supplied are the same;
otherwise it returns false. In this case, the two arguments are not the
same, so {equals} will return false. At this point, the
MPI value for false the string "0" will
replace the function. (A "" null string is also false in
MPI. Any value other than "" or "0" is considered true.)
So, at this point the string would in effect be...
{if:"0",Hey it's God!,Hello world!}
Finally, this, the outermost function will be evaluated. The
{if} function takes three arguments. If the first argument
is true, it returns the second argument. If the first argument is false,
it returns the third argument. In this example, the first argument is
false, so the the third argument will be returned: MPI will
return the string "Hello world!" to player
#123. If God had triggered the string, the
{if} test would have been true, and the string "Hey
it's God!" would have been returned instead.
The {debug} function displays the progress of the
parser. Enclosing the whole of our example in a {debug}
function will show the process described above.
====================================
> @succ testmpi = {debug:{if:{eq:{ref:me},#1},Hey it's God!,Hello world!}}
Message set.
> testmpi
(@Succ) {IF:"{eq:{ref:me},#1}", "Hey it's God!", "Hello world!"}
(@Succ) {EQ:"{ref:me}", "#1"}
(@Succ) {REF:"me"}
(@Succ) "me"
(@Succ) {REF:"me"} = "#123"
(@Succ) "#1"
(@Succ) {EQ:"#123", "#1"} = "0"
(@Succ) "Hello world!"
(@Succ) {IF:"{eq:{ref:me},#1}", "Hey it's God!", "Hello world!"} = "Hello world!"
Hello world!
====================================
In the lines from the first half of the debugging output where
indentation is moving to the right the parser is essentially
finding the innermost, left-most function to be evaluated. The remaining
portion, with lines ending in ` = <value> ' and
indentation moving back to the left, depicts the series of returned
expressions described above.
The keywords `me' and `here' can be used as
normal. In addition, MPI supports the keyword `this', which
will be replaced by the dbref of the object on which the
MPI is stored.
The variable functions {&cmd}, {&arg}, and
{&how} may be used to retrive information about how
MPI was triggered. {&cmd} stores the command
name typed to trigger the MPI. {&arg} stores
any arguments typed along with the command. {&how} stores
the method by which MPI was triggered, and will have values
such as (@desc), (@succ),
(@osucc), (@lock), etc.
Functions can be nested up to 26 levels deep. Loops may iterate a
maximum of 256 times, at which point the automatically exit. Lists may
have a maximum of 256 lines, or 4096 characters, whichever is less.
An MPI string that appears in a _/ prop (a
@succ message, a @desc, and so forth) will be
parsed automatically. For other triggering props, the parser must be
called by an & ambersand at the beginning of the prop string.
====================================
> @set me=_oarrive/aaa:&{null:{otell:pads in quietly.}}
Property set.
====================================
The arguments of functions are separated by commas. Commas appearing
in argument strings will confuse the parser: functions will seem
to it to have too many arguments. So, commas in argument strings
must be `escaped'... i.e., preceded with a \ backslash
escape character, which tells the parser to treat the next character
literally, rather than as an MPI instruction. For example,
if we wanted our first example to say "Hey, it's God!" or
"Hello, world!", the commas would need to be escaped with a
backslash character.
{if:{eq:{ref:me},#1},Hey\, it's God!,Hello\, world!}
Complex or very long MPI instructions are often better
stored in a list, where whitespace can be used to make the code more
readable, rather than in a single prop where all will run together in an
opaque mass of characters. A simple pointing string using the
{lexec} (`execute list') function can then be placed in the
triggering prop.
====================================
> lsedit harley = bikecode
< Welcome to the list editor. You can get help by
entering `.h' >
< `.end' will exit and save the list. `.abort' will abort any changes. >
< To save changes to the list, and continue
editing, use `.save' >
> {null:
> {if:
> {
> (lots of complicated really cool
motorcycle code goes here)
> }
> }
> }
> .end
< Editor exited. >
< list saved. >
> @succ ride harley;ride motorcycle;ride cycle = {lexec:bikecode}
Message set.
> ride harley
(The Harley does something amazing.)
====================================
The {lexec} function executes MPI in a
list. The {exec} function executes MPI in a
property, and thus provides another way to break code up into managable
pieces. MUSH coders especially might find this method more
intuitive.
prev|
toc|
top|
next
|
|