1 Introduction
MPSIDL uses a simple language to define the interface that an MPS server object publishes to its client objects. Interface definitions written in this language are then compiled by the MPS IDL compiler, mpsidl, into C++, Java, or both.
This is a small example of an MPS IDL file (simple.mps):
import "../libmps/namingservice.mps";
namespace Simple {
interface Simple {
bool not(bool arg);
void dump(org::hebe::mps::naming::NamingService ns);
}
}
Namespaces are hierarchic, and map to nested namespaces in C++ and multi-segmented package names in Java.
Interfaces are defined with the "interface" keyword, and appear to the client as the programming interface to the remote object. No state is mentioned explicitly in an interface definition - interfaces are pure behaviour.
Structures are defined with the "struct" keyword, as below, and appear as state with no behaviour. Once created, an instance of a structure is immutable unless the keyword struct is preceded by the keyword
mutable. They exist as pure value types - once transmitted across an MPS interface, the client and the server hold two physically disjoint objects that are structurally equivalent; updates to one do not affect the other.
The following MPS IDL file is the one used to define the naming service used by the MPS runtime itself (namingservice.mps):
namespace org {
namespace hebe {
namespace mps {
namespace naming {
struct Result {
bool bound;
string objectName;
string resolvedName;
}
interface NamingService {
Result resolve(string objectName);
Result bind(string objectName, string resolvedName, bool replace);
bool unbind(string objectName);
Result[] enumerate();
}
}
}
}
}
2 (Pseudo-)Formal Definition
2.1 Overall File structure
MPS IDL files consist of an optional sequence of import statements, followed by a single namespace declaration.
import "mps-idl-filename";
import "../other-mps-idl-filename";
namespace SomeNamespace {
...
}
2.2 Comments
Comments may be single-line, a la C++ or Java:
// single-line comment
or multi-line, like C:
/* this is
a multi-line comment */
Comments may be inserted at any point in the file.
2.3 Imports
import "filename";
Imports are used to allow complex interface and data-structure definitions to be split across multiple MPS IDL files (and therefore across compilation units in languages like C++).
When code is generated from an MPS IDL file, the only code that is generated is for the namespace specified in the file named on the command-line. Namespaces declared in imported files do not have code generated for them. You will have to specify the imported MPS IDL files on the command-line of a separate invocation of the mpsidl compiler.
2.4 Namespaces
namespace NamespaceName {
// Namespace contents go here
...
}
Namespaces help avoid problems where two separate meanings are attached to the same name. Namespaces are hierarchic - you can nest a namespace within a namespace. All identifiers in an MPS IDL file are bound within a namespace.
2.5 The Scope Override Operator
Take this fragment of MPS IDL:
namespace foo {
namespace bar {
namespace baz {
struct quux {
int blort;
}
}
interface zot {
quux myfunction();
int myotherfunction(quux q);
}
}
}
Note that there is a reference to type "quux" as the result-type of function zot::myfunction(). This code, as it stands, will not compile, because "quux" is not defined at the same scoping level as zot::myfunction(). What you need to do is use the scope override operator:
...
interface zot {
baz::quux myfunction();
int myotherfunction(foo::bar::baz::quux q);
}
...
which lets the compiler figure out which instance of "quux" you are talking about. The scope override operator, "::", works much the same way as in C++, and is similar to fully specifying the name of a class in Java. Note that the two ways of referring to "quux" - absolute (starting with "foo") and relative (starting with "baz") - are interchangeable in this context.
2.6 Structures
struct StructName {
// Member variable definitions go here; for example...
int member1;
string member2;
OtherStruct [] member3;
Interface member4;
}
mutable struct MutableStructName {
// Member variable definitions go here
int member1;
}
Structures are used in MPS IDL to transfer a collection of information of various types using a single object. They default to being immutable objects: once created, there is no way to alter the values of any of the member variables. The exception to this is when the mutable keyword is present at the point where the structure is defined, in which case "setter" functions are emitted which parallel the "getter" functions emitted for immutable structures. Structures are also behaviour-free: they are pure data. Contrast this with interfaces, which have behaviour but no state/data.
2.7 Exceptions
exception ExceptionName {
// Member variable definitions as per structs.
}
Exceptions behave identically to structs, except that they may be listed in the optional "throws" clause of a method on an interface, and translate into the exception mechanism native to the underlying language. The programming interface to an exception object is the same as for MPSIDL structs.
2.8 Enumerations
enum EnumName {
// Names go here
NAME1,
A_SECOND_NAME,
SomeOtherNameInAnEnum
}
Enumerations are useful for declaring symbolic names which have the same meaning to both the client and the server of an MPS interface. Enums map to classes containing static-final-ints in Java, and to classes containing an anonymous enum in C++. The first name in the enum name-list has the numeric value 0, the second has value 1, and so on. Note that MPSIDL enums are not proper types: an enum declaration in MPSIDL only defines a few symbols against constant numeric values; it doesn't generate a proper typename that is usable wherever, say, int or string is usable. The following, for instance, is an error:
interface ThisContainsAnError {
// oops. Can't mention enums here.
void myMethod(EnumName myTypeIsInvalid);
}
2.9 Interfaces
exception CouldNotCreate {
string reason;
}
exception NoResults {
int searchTerm;
string explanation;
}
interface InterfaceName {
// Member function definitions go here; for example
int myFunction(string foo) throws CouldNotCreate, NoResults;
OtherInterface myFactoryMethod() throws CouldNotCreate;
StructureType myResultGatheringMethod(int searchTerm);
}
interface Extension extends InterfaceName {
string anotherFunction(StructureType [] someValues);
}
Interfaces are used to define the functions that remote objects can perform. They are extensible - MPS IDL provides type inheritance (but not code inheritance - that is up to the implementation language). All data types are legal as parameters and return types. Note the optional "throws" clause, which determines which MPS User Exceptions are throwable by servers implementing this interface.
2.10 Data Types
MPS IDL supports a few basic primitive types, plus arrays of other types (including arrays, structures, and interfaces), user-defined structures, and user-defined interfaces.
2.10.1 Supported Primitives
The primitive types MPS IDL supports are:
- int - 32-bit signed
- long - 64-bit signed
- float - 32-bit IEEE floating-point
- char - 8-bit signed
- bool - 1-bit boolean
- string - variable-length character string
See also MpsLanguageMappings.
2.10.2 Variable declarations
Variable declarations are used to define the body of structures. They are very similar to C or Java-style variable declarations, with the base type written first, followed by optional pairs of brackets ('[]') to denote (nested) arrays, and the variable name written last.
2.10.3 Method declarations
Method declarations follow the C and Java pattern as well, with the return-type listed first, followed by the method name, followed by a parameter list enclosed in parentheses and separated by commas, followed by an (optional) "throws" clause consisting of the keyword "throws" followed by a comma-separated list of exception names.
2.10.4 Examples
int x;
float y;
string z;
float [] vec;
float [][] matrix;
string [] names;
float pow10(float x);
string concat(string a, string b);
string repeat(string x, int numberOfRepeats);
int[] addScalar(int[] a, int b);
Handle lookupItem(string key) throws ItemNotFound;
Go to Table of Contents
(last modified 15 August 2001 by surazal)
|