minid.types
The main header file of the MiniD interpreter. This file defines all the basic
types
of MiniD, as well as the MDState type, which is the interpreter (and doubles as the
'thread' type for coroutines).
It makes me sad to have to have so much stuff in one file, but D just can't handle
circular imports (which would be necessary for splitting this up) without throwing
up all over itself in a flurry of forward declaration/reference errors. Sigh, if
only it followed the spec where it says "things to drop: forward declarations."
License:
Copyright (c) 2007 Jarrett Billingsley
This software is provided 'as-is', without any express or implied warranty.
In no event will the authors be held liable for any damages arising from the
use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it freely,
subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software in a
product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not
be misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
- class
MDException
: object.Exception;
- The root of the MiniD exception hierarchy.
All exceptions in MiniD derive from this class. In order to be compatible with the scripting language,
where values of any type can be thrown as exceptions, it has a public member which exposes this value.
- MDValue
value
;
- The MiniD
value
which is used if the exception is caught by a catch statement in MiniD code.
- this(char[] fmt,...);
- Construct an MDException using a format string and a list of arguments, using Tango-style formatting.
The string will be formatted, and assigned into the value member as well.
- this(char[] fmt, TypeInfo[] arguments, void* argptr);
- Like above, but for when you already have the two variadic parameters from another variadic function.
- this(MDValue val);
- Construct an MDException from an MDValue. It will be assigned to the value member, and the string
representation of it (not calling toString metamethods) will be used as the exception message.
- this(MDValue * val);
- Like above, but for MDValue pointers instead.
- class
MDCompileException
: minid.types.MDException;
- Thrown by the compiler whenever there's a compilation error.
The message will be in the form "filename(line:colunm): error message".
- bool
atEOF
;
- Indicates whether the compiler threw this at the end of the file or not. If this is
true, this might be because the compiler ran out of input, in which case the code could
be made to compile by adding more code.
- this(Location loc, char[] fmt,...);
- Takes the location of the error, and a variadic list of Tango-style formatted arguments.
- class
MDRuntimeException
: minid.types.MDException;
- Thrown to indicate an error at run-time, often by the interpreter but not always.
This class includes a location of where the exception was thrown.
- Location
location
;
- The
location
of where the exception was thrown. This may not be entirely accurate,
depending on whether or not debug information was compiled into the bytecode, who
threw the exception etc.
- this(Location loc, MDValue * val);
- Constructs the exception from a location and an MDValue pointer to the value to be thrown.
- this(Location loc, char[] fmt,...);
- Constructs the exception from a location and Tango-style formatted arguments.
- this(Location loc, char[] fmt, TypeInfo[] arguments, void* argptr);
- Like above, but takes the variadic function parameters instead.
- char[]
toUtf8
();
- Overridden to include the location in the error message. Note that the result of this
is in the format "filename(line:instruction): error message". The 'instruction' in this
message is the index of the instruction in the bytecode that caused the exception, and
is mostly meant for low-level debugging.
- struct
MDValue
;
- The basic variant data type which represents a MiniD value.
This structure is the underlying representation of every variable, array slot, table key/value
etc. that appears in the language. It is a variant type which can hold any of the language types.
It's a simple tagged union, with a 4-byte type and an 8-byte data segment (large enough to hold
a double-precision floating-point value, the largest type that it can hold).
- enum
Type
;
- Enumerates the basic datatypes of MiniD. See the 'Types' section of the spec for more info.
- static MDValue
nullValue
;
- A static MDValue instance which should always, always hold 'null'. There is an invariant
which ensures this. This is mostly used by functions which need to return a pointer to a
null MDValue, rather than returning an actual null pointer. You can also use this any time
you need a null MDValue in your D code.
- MDValue
opCall
(T)(T value);
- The "constructor" for the struct. It's templated based on the parameter, and all it does is
call opAssign, so see opAssign for more info.
- int
opEquals
(MDValue * other);
- Returns true if this and the other value are exactly the same type and the same value. The semantics
of this are exactly the same as the 'is' expression in MiniD.
- int
opCmp
(MDValue * other);
- This is mostly overridden for using MDValues as AA keys. You probably shouldn't use this for
comparing MDValues in general, because (1) it will return 'less' or 'greater' for values which are
different types, which doesn't really make sense, and (2) will not call
opCmp
metamethods.
- int
compare
(MDValue * other);
- Compares this to another MDValue in a more sensible way. If the two objects are different types, and are not
both numeric types (int or float), an exception will be thrown. Integers will automatically be cast to floats
when comparing an int and a float. This function still does not call opCmp metamethods, however; you should use
the APIs in the MDState class for the best comparison.
- uint
toHash
();
- Overridden to allow the use of MDValues as AA keys.
- uint
length
();
- Gets the
length
of the MDValue, which will fail (throw an exception) if getting the
length
makes no sense for the MDValue's type. Does not call opLength metamethods.
- Type
type
();
- Returns the current
type
of this value, as a value from the MDValue.Type enumeration.
- static dchar[]
typeString
(Type type);
- A static method which, given a value from the MDValue.Type enumeration, will give the
string representation of that type.
- dchar[]
typeString
();
- Gets a string representation of the type of this value. Differs from passing the type
into the static
typeString
() function in that it will include the name of the class if
this is a class or instance value.
- bool
isNull
();
bool
isBool
();
bool
isNum
();
bool
isInt
();
bool
isFloat
();
bool
isChar
();
bool
isObj
();
bool
isString
();
bool
isTable
();
bool
isArray
();
bool
isFunction
();
bool
isClass
();
bool
isInstance
();
bool
isNamespace
();
bool
isThread
();
- These return true if this is the given type, and false otherwise.
- bool
isFalse
();
- Returns true if this value is false (null, 'false', an integer with the value 0, a float
with the value 0.0, or a NUL ('\0') character).
- bool
isTrue
();
- Returns the opposite of isFalse().
- bool
canCastTo
(T)();
- A templated method which checks if this value can be converted to the given D type. Array
and AA types will check the entire contents of the Array or Table (if the value is one) to make
sure all the elements can be cast as well, so this can be a non-trivial operation for the container
types. .
canCastTo
!(floating point type)() will return true if the value is either a float or an int.
If the value is an instance, it will check that it can be downcast to the given class instance type.
- T
as
(T)();
- A templated method which converts this value to the given D type. This is kind of a power-user
method, used for converting a MiniD value to a D value
as
long
as
you know in advance that this
conversion can be done. If the conversion can't be done, an assertion will be thrown in debug
builds, but the behavior is undefined in release builds.
- T
to
(T)();
- A 'safer' version of .as(), this will do basically the same thing, but will throw an exception on
a failed conversion.
- void
setNull
();
- Sets this value to null. You can also set a value to null by assigning it the D 'null' value.
- void
opAssign
(T)(T src);
- A templated
opAssign
which allows the assignment of many D types into an MDValue. All reasonable
assignments are valid. Assignment of an array or AA to an MDValue will convert it into a MiniD
array or table. You can assign 'null' into an MDValue as well. An invalid type will trigger
a compile-time error.
- char[]
toUtf8
();
- Returns the string representation of the value. Does not call toString metamethods.
- class
MDObject
;
- The base class for all the object (reference) types in MiniD.
- static int
compare
(MDObject o1, MDObject o2);
- Given two MDObject references, compares them. Doesn't call opCmp metamethods, and
throws an exception if the two objects are of different types.
- class
MDString
: minid.types.MDObject;
- The class that represents the MiniD 'string' type.
This holds an immutable string. The hash for this string is calculated once upon creation,
improving speed when used as the key to an AA (which, in MiniD, is very often -- all namespaces
use MDStrings as keys). Immutability also avoids the problem of using a string as an AA key
and then changing it, which would result in undefined behavior.
- this(dchar[] data);
this(wchar[] data);
this(char[] data);
- These construct an MDString from the given D string. The data is duplicated, so you don't
have to worry about changing the source data after the MDString has been created.
- uint
length
();
- Gets the
length
of the string in characters (codepoints? code units? it's all so confusing).
- int
opIn_r
(dchar c);
- If the given character is in the string, returns the index of its first occurrence; otherwise
returns -1.
- MDString
opCat
(MDString other);
- Concatenates two MDStrings, resulting in a new MDString.
- MDString
opCat
(dchar c);
MDString
opCat_r
(dchar c);
- Concatenates an MDString with a single character, resulting in a new MDString.
- uint
toHash
();
- Returns the hash of the string (which was computed at construction).
- int
opEquals
(Object o);
- Returns true if this and another string are identical; false otherwise.
Checks to see if the hashes diff first, which can save a lot of time.
- int
opEquals
(char[] v);
int
opEquals
(wchar[] v);
int
opEquals
(dchar[] v);
- Returns true if this MDString's data is identical to the given D string; false otherwise.
- int
opCmp
(Object o);
- Compares this string to another MDString by character values (i.e. it doesn't do a full lexicographical
language-correct comparison).
- int
opCmp
(char[] v);
int
opCmp
(wchar[] v);
int
opCmp
(dchar[] v);
- Same as above, but for D string arguments.
- dchar
opIndex
(uint index);
- Gets the character at the given index.
- MDString
opSlice
(uint lo, uint hi);
- Slices this string, returning a new MDString. Thanks to immutability, the
new string's data will simply point into the old string's, meaning the only memory
allocation is for the new string's instance.
- char[]
asUTF8
();
wchar[]
asUTF16
();
dchar[]
asUTF32
();
- These convert this string into the given UTF encoding. The returned value will never
reference the data inside the instance, to preserve immutability.
- char[]
toUtf8
();
- Returns the UTF-8 string representation of the string; basically just returns .asUTF8().
- class
MDClosure
: minid.types.MDObject;
- The class which represents the MiniD 'function' type.
This is a closure, that is a function and all the environment it needs to execute correctly.
It can hold either a MiniD closure (a "script closure"), or a reference to a native D function
(a "native closure"). In virtually all cases this distinction is transparent, except when it
comes to coroutines. You cannot yield out of a coroutine across the boundary of a native function
call.
In addition to their executable function, closures also have what's called the "environment."
In the global lookup process (in script functions, that is), the first step is to check if the
global exists in the 'this' parameter. If it doesn't, the next step goes to the closure's
environment. This is a namespace which usually is the module in which the function was defined.
Global lookup begins at the environment, and travels up the chain of namespaces (since each
namespace can have a parent namespace) until the chain is exhausted. The environment is important
for global lookup in script closures, but it's usually not that important in native closures.
Furthermore, if a function is called as a non-method (a plain function call), and is not given
an explicit context with the 'with' keyword, its environment will be passed as the 'this' parameter.
- this(MDNamespace environment, MDFuncDef def);
- Constructs a script closure.
Params:
MDNamespace environment |
The environment of the closure. See the description of this class for info. |
MDFuncDef def |
The MDFuncDef, which was either loaded from a file or just compiled, which holds the
bytecode representation of the closure. |
- this(MDNamespace environment, int delegate(MDState, uint) dg, dchar[] name, MDValue [] upvals = null);
this(MDNamespace environment, int(* func)(MDState, uint), dchar[] name, MDValue [] upvals = null);
- Constructs a native closure. Both function pointers and delegates are allowed; using delegates will be
slightly faster when the closure is called.
All native functions which interact with the API follow the same signature. They take two Params:
an MDValue which represents the thread from which this closure was called, and the number of parameters
(not including the context 'this' parameter, which is always present) with which the function was called.
The MDState parameter contains all the parameters which were passed to the function, as well as being a
very important interface through which much of the native API is used. Native functions return an integer,
which is how many values they are returning (which were pushed onto the MDState's stack prior to returning).
Params:
MDNamespace environment |
The environment of the closure. See the description of this class for info. |
int delegate(MDState, uint) dg |
(or func) The delegate or function pointer of the native function. |
dchar[] name |
The name of the function, which will be used in error messages and when its toString is called. |
MDValue [] upvals |
An optional array of MDValues which serve as the upvalues to the closure. In MiniD, upvalues
are automatic, and are simply local variables declared in enclosing functions. In native code,
you can achieve similar results by either creating an instance of a struct on the heap and using
one of its methods as the delegate for the closure, and keep the closure's upvalues in there; or
by passing an array of MDValues to this constructor. The array of upvalues will be available
through the MDState parameter to the native function. |
- uint
length
();
- Getting the
length
of a closure makes no sense; this just throws an exception.
- char[]
toUtf8
();
- Gets a string representation of the closure. For native closures, it looks something like "native function name";
for script closures, "script function name(location defined)".
- bool
isNative
();
- Returns whether or not this is a native closure.
- MDNamespace
environment
();
void
environment
(MDNamespace env);
- Gets or sets the
environment
of the closure. See the class description for info.
- class
MDTable
: minid.types.MDObject;
- The class which represents the MiniD 'table' type.
This is basically an AA which is indexed by and holds MDValues. Null MDValues cannot be
used as indices. Assigning a null value to a key-value pair removes that pair from the
table, and accessing a key which doesn't exist will return a null value.
- this();
- Creates a new table.
- MDTable
create
(T...)(T args);
- Create a table from a templated list of variadic arguments. There must be an even
number of arguments. Each pair of arguments is interpreted as a key-value pair, and
the types of these must be convertible to MiniD types.
- MDTable
fromAA
(K,V)(V[K] aa);
- Create a table from an associative array. The key and value types must be convertible
to MiniD types.
- uint
length
();
- Gets the number of key-value pairs in the table.
- MDTable
dup
();
- Creates a shallow copy of the table. The keys and values in the new table will be the same;
they are not recursively duplicated.
- MDArray
keys
();
- Gets an MDArray of all the
keys
of the table.
- MDArray
values
();
- Gets an MDArray of all the
values
of the table.
- void
remove
(ref MDValue index);
- Removes a key-value pair from the table with the given key. If the key doesn't exist, this
simply returns. You can also
remove
a pair by assigning a null value to it.
- MDValue *
opIn_r
(ref MDValue index);
- Returns a pointer to the value given the key. Returns a null pointer if the key doesn't exist.
- MDValue *
opIndex
(ref MDValue index);
- Returns a pointer to the value given the key. Throws an exception if the key is a null MDValue.
Never returns a null MDValue*; if the key doesn't exist, returns a pointer to a null MDValue instead.
- void
opIndexAssign
(ref MDValue value, ref MDValue index);
- Assigns a value to a key-value pair. Throws an exception if the key is a null MDValue. Removes
the pair, if it exists, if the value is a null MDValue.
- int
opApply
(int delegate(ref MDValue key, ref MDValue value) dg);
- Overloaded
opApply
so you can use a foreach loop on an MDTable. They key and value are both
MDValues.
- char[]
toUtf8
();
- Returns a string representation of the table, in the format "table 0x00000000", where the number
is the hexidecimal representation of the 'this' pointer.
- class
MDArray
: minid.types.MDObject;
- The class which represents the MiniD 'array' type.
This is a very simple and straightforward class. It's basically a mutable, resizable array of MDValues.
- this(uint size);
- Construct this array with a given size. All the elements will be the null MDValue.
- MDArray
create
(T...)(T args);
- Create an MDArray from a templated list of variadic arguments. All the arguments must have types
which are convertible to MiniD types.
- MDArray
fromArray
(T)(T[] array);
- Create an MDArray from a D array. The element type must be convertible to a MiniD type. Multi-dimensional
arrays work as well.
- uint
length
();
- Gets the number of elements in the array.
- uint
length
(int newLength);
- Sets the
length
of the array. If the new
length
is longer than the old, the new elements will
be filled in with the null MDValue.
- void
sort
();
- Sorts the array. All the elements must be the same type for this to succeed; throws an exception on failure.
- void
sort
(bool delegate(MDValue , MDValue ) predicate);
- Sorts the array, using a custom predicate. This predicate takes two values and should return 'true'
if the first is less than the second, and 'false' otherwise.
- void
reverse
();
- Reverses the order of the array.
- MDArray
dup
();
- Performs a shallow copy of the array.
- int
opCmp
(Object o);
- Compares this array to another array. Comparison works just like on D arrays. As long as the
length and data are identical, the arrays will compare equal. If all the elements of both arrays
are the same type, you can even compare for ordering; smaller arrays and arrays with smaller elements
will compare less than larger arrays. If the elements are different types, comparing for ordering
doesn't make much sense, but equality still works.
- int
opEquals
(Object o);
- Sees if this array is identical to another array.
- int
opIn_r
(ref MDValue v);
- If the given value is in the array, returns the index of the first instance; otherwise, returns -1.
- int
opApply
(int delegate(ref MDValue value) dg);
int
opApply
(int delegate(ref uint index, ref MDValue value) dg);
-
opApply
overloads to allow using foreach on an MDArray. Both index-value and value-only forms are
available. The value type is an MDValue.
- MDArray
opCat
(MDArray other);
- Concatenates two arrays into a new array. The data is always copied from
the source arrays.
- MDArray
opCat
(ref MDValue elem);
MDArray
opCat_r
(ref MDValue elem);
- Concatenates an array with a single element. Always copies from the source array.
- MDArray
opCatAssign
(MDArray other);
- Appends another array onto the end of this one. No new array is created; this array is
just resized.
- MDArray
opCatAssign
(ref MDValue elem);
- Appends a single element to the end of this array.
- MDValue *
opIndex
(int index);
- Gets a pointer to the value stored at the given index. Returns a pointer instead of a plain
MDValue so that the array data can be updated after the fact.
- void
opIndexAssign
(ref MDValue value, uint index);
- Assigns a value into the given index.
- MDArray
opSlice
(uint lo, uint hi);
- Creates a new array which is a slice into this array's data. Modifying the contents of the
sliced array will modify the contents of this array (unless this array is resized, in which
case it may not).
- void
opSliceAssign
(ref MDValue value, uint lo, uint hi);
- Assigns a single value to a range of indices.
- void
opSliceAssign
(MDArray arr, uint lo, uint hi);
- Copies the data from another MDArray into this one. The length of the other array must be the
same as the length of the slice indicated by the indices.
- void
opSliceAssign
(ref MDValue value);
- Assigns a single value to every element of this array.
- void
opSliceAssign
(MDArray arr);
- Copies the data from another array into this one. Both arrays must have the same length.
- char[]
toUtf8
();
- Returns a string representation of the array, in the format "array 0x00000000", where the number
is the hexidecimal representation of the 'this' pointer.
- class
MDClass
: minid.types.MDObject;
- The class which represents the MiniD 'class' type.
Classes hold two namespaces: one for fields and one for methods. The method namespace is shared among
all instances of the class, while the field namespace is duplicated for each instance. Classes can
inherit from other classes.
When assigning members to the class, they will automatically be put into the proper namespace based on their
type -- closures go into the method namespace, all others into the fields namespace. You can also get
references to each of these namespaces.
- this(dchar[] guessedName, MDClass baseClass = cast(MDClass)null);
- Creates a new class.
Params:
dchar[] guessedName |
The name of the class. This is called "guessed" mostly because in MiniD code, classes
do not have any intrinsic name associated with them, and sometimes the compiler will generate a
name for an anonymous class. For any classes that you create from native code, though, you'll
probably given them a real name. |
MDClass baseClass |
An optional base class from which this one should derive. If you skip this parameter or
pass null, the class will have no base class. Otherwise, it will copy the fields and methods
from the base class into its own namespaces, which you can then overwrite (override) with your
own versions. |
- uint
length
();
- Throws an exception since classes do not have a
length
.
- MDValue
superClass
();
- Returns an MDValue containing the base class. Returns a null MDValue if it has no base class.
- MDInstance
newInstance
();
- Creates a new instance of this class; this doesn't, however, run the constructor, so the instance
may be incompletely initialized. The fields are copied from the class into the new instance; the
instance's method namespace simply points to this class's method namespace.
- MDValue *
opIndex
(MDString index);
MDValue *
opIndex
(dchar[] index);
- Look up a member of the class. This will look in the methods, the fields, and then continue the
search in the base class if there is any. Returns a null pointer (not a pointer to a null MDValue)
if the member wasn't found.
- void
opIndexAssign
(ref MDValue value, MDString index);
void
opIndexAssign
(ref MDValue value, dchar[] index);
- Sets a member of a class. If the value is a function, it'll be put into the methods namespace;
otherwise, it'll be put into the fields namespace.
- dchar[]
getName
();
- Returns the guessed name (a duplicate of the internal name, so it can't be corrupted).
- MDNamespace
fields
();
- Returns the namespace that contains the
fields
for this class. Manually adding members to the returned
namespace is not recommended, as this bypasses some caching logic that MDClass performs with a normal
member add.
- MDNamespace
methods
();
- Returns the namespace that contains the
methods
for this class. Manually adding members to the returned
namespace is not recommended, as this bypasses some caching logic that MDClass performs with a normal
member add.
- char[]
toUtf8
();
- Returns a string representation of the class in the form "class name".
- class
MDInstance
: minid.types.MDObject;
- The class which represents the MiniD 'instance' type.
Instances are a bit different from other types in that they also have a class type from which they were
instantiated. This class defines the methods which can be called on its instances, as well as the
fields which they given when they are created. You can query the runtime type of an instance, as well
as see if a given class is anywhere in its inheritance hierarchy (or if it is an instance of that class
itself).
Instances must be created through a class; you cannot instantiate an instance on its own.
- uint
length
();
- Getting the
length
of an instance could make sense, if the instance had an opLength method.
However, none of these class methods call (or can call) metamethods, so this just throws an
exception.
- MDValue *
opIndex
(MDString index);
MDValue *
opIndex
(dchar[] index);
- Looks up a member in the instance. If the member doesn't exist, returns a null pointer.
- void
opIndexAssign
(ref MDValue value, MDString index);
void
opIndexAssign
(ref MDValue value, dchar[] index);
- Sets a member in an instance. You cannot reassign instance methods; attempting to do so will
result in an exception being thrown. You also can't add fields to the class instance which
it didn't have to begin with (also throws an error).
- char[]
toUtf8
();
- Gets a string representation of the instance, in the form "instance of class classname". Does
not call toString metamethods.
- bool
castToClass
(MDClass cls);
- Given a reference to a class, sees if this instance can be cast to the given class.
Returns:
'this' if it can be cast; null otherwise.
- MDNamespace
fields
();
- Get a reference to the field namespace of this instance. Every instance has its own field namespace.
- MDNamespace
methods
();
- Get a reference to the method namespace of this instance. All instances of a class and the class itself
share the method namespace.
- MDClass
getClass
();
- Gets a reference to the owning class.
- class
MDNamespace
: minid.types.MDObject;
- The class which represents the MiniD 'namespace' type.
Namespaces are kind of like tables, but have somewhat different semantics. They are a mapping from strings to
values; only string keys are allowed. Namespaces may hold null values, so assigning a null value to a key-value
pair does not remove that pair from the namespace. Accessing a key-value pair which has not yet been inserted
will throw an exception instead of returning null as tables do. Namespaces can have a name. Lastly namespaces
can also have a parent namespace, which is used in global lookup.
Namespaces are used as symbol tables throughout MiniD. Modules, packages, class fields, and class methods are all
held in namespaces. They are also used as function closure environments. When global lookup reaches the closure's
environment, it looks up the global in that namespace; if it's not found, it goes to that namespace's parent
namespace, all the way up the chain of namespaces until either the global is found or the namespace chain ends.
- this(dchar[] name = null, MDNamespace parent = cast(MDNamespace)null);
- Construct a new namespace.
Params:
dchar[] name |
The optional name of the namespace. It can be null, in which case the namespace will be anonymous.
class method and field namespaces are anonymous, for example. |
MDNamespace parent |
The optional parent of the namespace. The parent is used for global lookup (see the description
of this class). If the namespace won't be being used as the environment for a function, the parent
is mostly purposeless, except for debugging, when the parent's name will be included in the namespace's
name. The parent can be null, which means global lookup will terminate after searching this namespace. |
- MDNamespace
create
(T...)(dchar[] name, MDNamespace parent, T args);
- Create a namespace from a variadic list of arguments. This is similar to the MDTable.
create
() function,
in that there must be an even number of arguments, and each pair is interpreted as a key-value pair.
This has the additional requirement that the keys must all be strings. The name and parent parameters
are the same as in the constructor.
- void
addList
(T...)(T args);
- Similar to create(), but just adds a list of key-value pairs to an already-created namespace.
- uint
length
();
- Gets the number of key-value pairs in the namespace.
- dchar[]
name
();
- Gets the
name
of the namespace (not including the parent's
name
).
- MDNamespace
parent
();
- Gets the
parent
of this namespace.
- MDValue *
opIn_r
(MDString key);
MDValue *
opIn_r
(dchar[] key);
- Looks up a value in the namespace from a string key. As usual for D's 'in', returns null if
the value isn't found, and a pointer to the value if it is.
- MDNamespace
dup
();
- Duplicate this namespace, performing a shallow copy of all the key-value pairs.
- MDArray
keys
();
- Gets an MDArray of all the
keys
in the namespace.
- MDArray
values
();
- Gets an MDArray of all the
values
in the namespace.
- MDValue *
opIndex
(MDString key);
MDValue *
opIndex
(dchar[] key);
- Looks up a value from the namespace. Returns a null pointer if the key doesn't exist.
- void
opIndexAssign
(ref MDValue value, MDString key);
void
opIndexAssign
(ref MDValue value, dchar[] key);
- Assigns a value to a key n the namespace. Will insert the pair if the key doesn't exist
already. Assigning a null value to a key-value pair will not remove the pair from
the namespace as it does with tables.
- void
remove
(MDString key);
void
remove
(dchar[] key);
- Remove the given key from the namespace. Throws an exception if they key does not exist.
- int
opApply
(int delegate(ref MDString, ref MDValue ) dg);
- Overload of
opApply
to allow using foreach over a namespace. The keys are MDStrings, and
the values are MDValues.
- dchar[]
nameString
();
- Gets a more complete name of the namespace, including the name of all parent namespaces.
So if namespace 'b's parent is namespace 'a', this will return a string like "a.b".
- char[]
toUtf8
();
- Gets a string representation of the namespace in the form "namespace full.name".
- struct
Location
;
- A struct that holds a location (a filename, a line number, and a column number) of
a piece of code. Used by the compiler and in runtime debug locations.
- static Location
opCall
(dchar[] fileName, int line = 1, int column = 1);
- Create a location with the given filename, line, and column. Lines and columns start
at 1. A line, column pair of -1, -1 has the special meaning of "in a native function."
- char[]
toUtf8
();
- Gets a string representation of the location. If the line and column are both -1, the
string is formatted like "fileName(native)", meaning that the location came from a native
function (i.e. a native function may have thrown an exception). Otherwise, it's in
the form "fileName(line:column)". For runtime debug locations, 'column' is actually
replaced by the index of the bytecode instruction.
- class
MDModuleDef
;
- A definition of a MiniD module.
This is really just a name and the code for the top-level function of the module. This can
be serialized and deserialized using the minid.utils serialization protocol. This can also
be loaded by the MDContext class, but that's a very low-level API.
- dchar[]
name
();
- Gets the
name
of the module. This is the
name
given in the module declaration.
- void
serialize
(IWriter s);
- Serialize this module to some kind of output. To be used with the minid.utils serialization
protocol.
- static MDModuleDef
deserialize
(IReader s);
- Deserialize this module from some kind of input. To be used with the minid.utils serialization
protocol.
- static MDModuleDef
loadFromFile
(char[] filename);
- Load a module definition from a filename. This is a low-level API that you probably won't have
to deal with.
- void
writeToFile
(char[] filename);
- Save this module to a filename.
- class
MDFuncDef
;
- A class which holds a script function's byte code, as well as all (most) of the information needed to
instantiate a closure of it, and some debug info as well.
You probably won't need to worry about using this class that much.
- class
MDContext
;
- A class which represents an execution context for MiniD code. It holds a global namespace hierarchy into
which modules can be imported, as well as a set of type metatables. Also provides a state which can be
used to run code.
You can create multiple, independent MiniD execution contexts. These are not the same as states. A state
is simply a thread of execution, and there can be multiple states associated with a single context.
When you create a context, a default state (its "main thread") is created for you. This thread can spawn
other threads with the creation of coroutines.
A context is useful for creating a "sandbox." What you can do is create a context, and only load into it
libraries which you know are safe. Then you can execute untrusted code in this sandbox, and it won't have
access to potentially dangerous functionality. Then you can have a separate context for executing trusted
code.
You can instantiate this class directly, and then load the standard libraries into it manually, but there
is minid.minid.NewContext, a helper function which will load standard libraries into the context based on
a flags parameter, which is a bit more compact.
- struct
_Globals
;
- This struct isn't meant to be used as a type in its own right; it's just a helper for accessing globals.
- T
opIndex
(T = MDValue*)(dchar[] name);
alias
get
;
- Attempts to get a global of the given name from the global namespace. Throws an exception if the
global does not exist. This is a templated function and returns an MDValue* by default. If you
want to get another type, you can use the 'get' alias to this function and call it as a templated
method.
- void
opIndexAssign
(T)(T value, dchar[] name);
- Set a global in the global namespace.
- MDNamespace
ns
();
- Get the underlying MDNamespace which actually holds the globals.
- _Globals
globals
;
- An instance of the above struct. You can access globals by writing things like "context.globals["x"d] = 5".
- final MDNamespace
getMetatable
(Type type);
final void
setMetatable
(Type type, MDNamespace table);
- Gets or sets the metatable for the given type. Every type has a metatable associated with it where metamethods
are looked up after any normal method indexing mechanisms fail. For example, the 'string' standard library sets
itself as the metatable for the 'string' type, making it possible to call the library functions as if they were
methods of the string objects themselves.
- final MDState
mainThread
();
- Gets the main thread of execution. This thread is created when the context is created,
and is the default thread of execution.
- final MDClosure
newClosure
(MDFuncDef def);
- Create a new closure in the global namespace from the given script function definition.
- final MDClosure
newClosure
(int delegate(MDState, uint) dg, dchar[] name, MDValue [] upvals = null);
final MDClosure
newClosure
(int(* func)(MDState, uint), dchar[] name, MDValue [] upvals = null);
- Create a new closure in the global namespace from the given native closure information. See
MDClosure.this() for info on these parameters.
- final void
addImportPath
(char[] path);
- Add a path to be searched when performing an import. See importModule() for information on the
import mechanism.
- final void
setModuleLoader
(dchar[] name, MDClosure loader);
- Sets a module loader for a given module name. The name should be in the format of a module declaration
name, such as "fork.knife.spoon".
The closure takes two Params: the name of the module to load (so that multiple modules can be loaded
by the same function), and a namespace in which to place the loaded module symbols. It is not expected to
return anything.
- final MDNamespace
importModule
(dchar[] name, MDState s = cast(MDState)null);
- Import a given module. The process goes something like this.
1. See if the module has been loaded. Module names are case sensitive. If the module name is found
in the internal list of loaded modules, the process stops here.
2. If the module hasn't been loaded, see if a loader was registered for it with setModuleLoader(). If one
has been, the loader is called with the module name and the namespace in which to place the module's
symbols. The process ends here if this succeeds.
3. If there's no registered loader, it attempts to load the module from disk, from either a source file or
a compiled binary module file. This is where the search paths come in. The first path it attempts is
the current working directory. If the module's name is multipartite, the parts before the final part
become directory names. So for example, the name is "fork.knife.spoon", it will look in "fork/knife/"
for both "spoon.md" and "spoon.mdm". If both a source and a binary file are found, it will load the
one with the more recent modification time. After the current directory is tried, it will go through
the list of custom directories (in no particular order) attempting the same process.
4. Not implemented in this release. If no source or binary module could be found, the last attempt is
to try to load a dynamic library with the same name as the module (with a similar pattern as with the
source/binary search; "fork.knife.spoon" will look in fork/knife for the module named "spoon").
If all these steps fail, the import process fails.
Params:
dchar[] name |
The name of the module to load, in the format "fork.knife.spoon". |
MDState s |
The state to use to load the module. This is used when calling any custom module loader functions,
or if the module being loaded is a script module, in which case the top-level function will be called.
Defaults to null, in which case the main thread will be used. |
Returns:
The namespace which holds the module's symbols.
- final MDNamespace
initializeModule
(MDState s, MDModuleDef def, MDValue [] params);
- Initialize a module given the module's definition and a list of parameters which will be
passed as vararg parameters to the top-level function. This is a very low-level API.
Params:
MDState s |
The state to use to call the top-level module function. |
MDModuleDef def |
The module definition, which was compiled from source or loaded from a file. |
MDValue [] params |
An array of parameters which will be passed as varargs to the top-level function. |
Returns:
The namespace of the module.
- final char[]
getTracebackString
();
- Gets traceback info of the most recently-thrown exception, and clears the traceback
info. This method is here because exceptions can propagate through multiple states
and through coroutine calls.
- class
MDState
: minid.types.MDObject;
- The class which represents the MiniD 'thread' type. Also probably the singularly most important class
in the native API, this is passed as a "context" to all native functions and contains the script interpreter.
Also keeps track of the script call call stack and locals stack.
- enum
State
;
- An enumeration of all the valid states a thread can be in, for coroutine support.
-
Initial
- Means the coroutine has been instantiated, but not yet called with the initial parameters.
When called, the context parameter that is passed will be saved, and the coroutine's function
will begin execution.
-
Waiting
- Means that the coroutine resumed another coroutine and is waiting for it to yield or return.
-
Running
- Means that the coroutine is currently executing. You can only get this state if a coroutine
queries its own state.
-
Suspended
- Means that the coroutine executed a yield expression, and is waiting to be resumed.
-
Dead
- Means that the coroutine was exited, either by returning or by having an exception propagate
out of the coroutine. The coroutine can be reset to the initial state and restarted.
- this(MDContext context);
this(MDContext context, MDClosure coroFunc);
- Construct a new thread. A default thread of execution, the 'main thread', is created for
you by MDContext, so you'll really only need this for creating coroutines.
If you pass a script function closure to this constructor, this thread will be a coroutine. It
can then be subsequently resumed by calling it with another MDState (just like how you call
threads to resume them in MiniD).
Attempting to pass a native function closure will throw an exception.
Passing null as the closure (the default) will simply create a new state with no special
properties. Not all that useful.
- uint
length
();
- You can't get the
length
of a state. Throws an exception.
- char[]
toUtf8
();
- Returns a string representation of the thread, in the form "thread 0x00000000", where the number
is the hexadecimal representation of the 'this' pointer.
- final State
state
();
- Gets the current coroutine
state
of the
state
as a member of the State enumeration.
- final MDString
stateString
();
- Gets a string representation of the current state of the coroutine.
- final uint
pushNull
();
- Push a null value onto the value stack.
Returns:
The stack index of the just-pushed value.
- uint
push
(T)(T value);
- Push a value onto the value stack. This is a templated method which can accept any type which can be
converted to a MiniD type.
Params:
value |
The value to
push
. |
Returns:
The stack index of the just-pushed value.
- T
pop
(T = MDValue)();
- Pop a value off the value stack. This is templated so that you can
pop
any type that can be converted from
a MiniD type, but it defaults to MDValue.
- uint
easyCall
(F,T...)(F func, int numReturns, MDValue context, T params);
- Call any callable MiniD type with a simple interface. There are multiple callable types in MiniD. Functions are the
most obvious. You can also call threads, which will resume them. You can call classes to create instances of them.
And you can call any object which has an opCall metamethod.
Once the call completes, you must pop any return values off the stack.
Params:
func |
Any callable type. This is templated to allow any type. |
numReturns |
How many return values you want from this function call. If >= 0, will leave exactly that many values
on the value stack which you can then pop. If this is -1, indicates that you want as many return values that
the call gives back, in which case you can get how many it returned by getting the return value of this method. |
context |
All calls require a context which will be passed as the 'this' parameter to the function. Only significant
for functions. Classes, threads, and objects with opCall will overwrite the context with their own value, so
it's alright to pass null as the context for those. |
params |
A variadic list of parameters to be passed to the function. All values must be convertible to MiniD types. |
Returns:
The number of return values from this call. If the numReturns parameter was >= 0, this is the same as that parameter,
and isn't particularly useful. But if the numReturns parameter was -1, this is very useful, as it indicates how many
values the call gave back.
- uint
callMethod
(T...)(ref MDValue val, dchar[] methodName, int numReturns, T params);
uint
callMethod
');
(T...)(ref MDValue val, MDString methodName, int numReturns, T params);
- Very similar to the easyCall method, this will call a method of any object.
Params:
val |
The object whose method you would like to call. |
methodName |
The name of the method to call. |
numReturns |
See easyCall for a description of this parameter. |
params |
See easyCall for a description of this parameter. |
Returns:
See easyCall for a description of the return value.
- final uint
call
(uint slot, int numParams, int numReturns);
- Perform a slightly lower-level
call
to any callable type.
This interface makes slightly less code bloat than the easyCall, as it doesn't require the use of a
variadic templated function. The protocol for calling something is as follows:
// 1. Push the object you're calling onto the stack, and save its stack index.
auto funcIdx = s.push(something);
// 2. Push the context. You must always have a context.
s.push(someContext);
// 3. Push any parameters.
s.push(param1);
s.push(param2);
// 4. Make the call.
s.call(funcIdx, 3, 1);
// 5. Pop any return values.
auto ret = s.pop!(int);
Params:
uint slot |
The stack slot of the object to
call
. Usually you get this from a push. |
int numParams |
How many parameters, including the context, you are passing to the function.
Since you always need context, this must always be at least 1. |
int numReturns |
See easyCall for an explanation of this parameter. |
Returns:
See easyCall for an explanation of this return value.
- void
setUpvalue
(T)(uint index, T value);
- This is to be used from native closures which were created with a list of upvalues. Sets the
value of the upvalue at the given integer index (upvalues are like an array).
Params:
index |
The index of the upvalue to set. |
value |
The value, which must have a type convertible to a MiniD type, to be set to the upvalue. |
- T
getUpvalue
(T = MDValue*)(uint index);
- The opposite of setUpvalue. This is templated to return any type, and by default will return an
MDValue*. You can then modify the contents of this return value and the changes will be reflected
in the internal upvalue array.
Params:
index |
The index of the upvalue to get. |
Returns:
The value of the upvalue, templated to return whatever you'd like it to. Defaults to MDValue*.
- bool
isParam
(char[] type)(uint index);
- A quirky function which lets you check if the parameter at the given index is of a certain type.
This is a templated method which takes a string that indicates the type you'd like to check for.
Possible values are "null", "bool", "int", "float", "char", "string", "table", "array", "function",
"class", "instance", "namespace", and "thread". Any other value will give a compile-time error.
Params:
index |
The 0-based index of the parameter whose type you'd like to check. Throws an error
if this index is invalid. |
Returns:
True if the parameter is of the given type; false otherwise.
- T
getParam
(T = MDValue)(uint index);
- Gets the value of a parameter off the stack.
Params:
index |
The index of the parameter to get. Throws an error if this index is invalid. |
Returns:
The value of the parameter, templated to whatever type you'd like. Throws an error if it
can't be converted to your desired type. Defaults to MDValue.
- T
getContext
(T = MDValue)();
- Gets the context (what would be the 'this' pointer in MiniD code) with which the function was called.
The context, being special, is not included with the rest of the parameters.
Returns:
The context, whose type is templated to whatever you'd like.
- final MDValue []
getParams
(int lo, int hi);
- Gets a slice of the parameters as an array. Throws an error if the slice boundaries are invalid.
Params:
int lo |
The low index of the slice. Can be negative, which means "from the end," i.e. -1 would mean
"begin at the very last parameter." Inclusive. |
int hi |
The high index of the slice. Can be negative, which means "from the end," i.e. -1 would mean
"end after the very last parameter". Noninclusive. |
Returns:
An array containing the parameter values. Because of the way the stack works, this is not (and cannot
be) a slice into the internal stack, but is instead a copy.
- final MDValue []
getAllParams
();
- Gets all the parameters passed to the function as an array. Equivalent to calling getParams(0, -1).
Returns:
An array of all the parameters. It's a copy of the internal stack.
- T
safeCode
(T)(lazy T code);
- An odd sort of protective function. You can use this function to wrap a call to a library function etc. which
could throw an exception, but when you don't want to have to bother with catching the exception yourself. Useful
for writing native MiniD libraries.
Say you had a function which opened a file:
File f = OpenFile("filename");
Say this function could throw an exception if it failed. Since the interpreter can only catch (and make meaningful
stack traces about) exceptions which derive from MDException, any exceptions that this throws would just percolate
up out of the interpreter stack. You could catch the exception yourself, but that's kind of tedious, especially when
you call a lot of native functions.
Instead, you can wrap the call to this unsafe function with a call to
safeCode
().
File f = s.safeCode(OpenFile("filename"));
What
safeCode
() does is it tries to execute the code it is passed. If it succeeds, it simply returns any value that
the code returns. If it throws an exception derived from MDException, it rethrows the exception. And if it throws
an exception that derives from Exception, it throws a new MDException with the original exception's message as the
message.
safeCode
() is templated to allow any return value.
Params:
code |
The code to be executed. This is a lazy parameter, so it's not actually executed until inside the call to
safeCode
. |
Returns:
Whatever the code parameter returns.
- final void
throwRuntimeException
(MDValue * val);
final void
throwRuntimeException
(char[] fmt,...);
- Throws a new runtime exception, starting the debug traceback with the current debug location.
- final MDNamespace
environment
(int depth = 0);
- Gets the
environment
of a closure on the call stack.
Params:
int depth |
The depth into the call stack of the closure whose
environment
to get. Defaults to 0, which
means the currently-executing closure. A depth of 1 would mean the closure which called this
closure, 2 the closure that called that one etc. |
Returns:
The closure's
environment
.
- final uint
callDepth
();
- Gets the current call depth, that is, how many functions are currently on the call stack which
have yet to return.
- final MDString
valueToString
(ref MDValue value);
- Get a string representation of any MiniD value. This is different from MDValue.toUtf8() in that it will call
any toString metamethods defined for the object.
Params:
Returns:
The string representation of the value.
- final bool
opin
(ref MDValue a, ref MDValue b);
- Determines if the value a is in the container b. Returns true if so, false if not.
- final int
cmp
(ref MDValue a, ref MDValue b);
- Compares the two values, calling any opCmp metamethods, and returns the result.
- final MDValue
idx
(ref MDValue src, ref MDValue index);
- Indexes src with index, and gives the result. Like writing src[index] in MiniD. Calls metamethods.
- final void
idxa
(ref MDValue dest, ref MDValue index, ref MDValue src);
- Index-assigns src into the index slot of dest. Like writing dest[index] = src in MiniD. Calls metamethods.
- final MDValue
len
(ref MDValue val);
- Gets the length of val. Like #val in MiniD. Calls metamethods.
- final MDValue
slice
(ref MDValue src, ref MDValue lo, ref MDValue hi);
- Slice src from lo to hi. Like src[lo .. hi] in MiniD. Calls metamethods.
- final void
slicea
(ref MDValue dest, ref MDValue lo, ref MDValue hi, ref MDValue src);
- Assign a slice src to dest from lo to hi. Like dest[lo .. hi] = src in MiniD. Calls metamethods.
- final MDValue
add
(ref MDValue a, ref MDValue b);
final MDValue
sub
(ref MDValue a, ref MDValue b);
final MDValue
mul
(ref MDValue a, ref MDValue b);
final MDValue
div
(ref MDValue a, ref MDValue b);
final MDValue
mod
(ref MDValue a, ref MDValue b);
- Performs an arithmetic operation on the two values and returns the result. Calls metamethods.
- final MDValue
neg
(ref MDValue a);
- Negates the argument. Calls metamethods.
- final void
addeq
(ref MDValue a, ref MDValue b);
final void
subeq
(ref MDValue a, ref MDValue b);
final void
muleq
(ref MDValue a, ref MDValue b);
final void
diveq
(ref MDValue a, ref MDValue b);
final void
modeq
(ref MDValue a, ref MDValue b);
- Performs a reflexive arithmetic operation on a, with b as the right hand side. Calls metamethods.
- final MDValue
and
(ref MDValue a, ref MDValue b);
final MDValue
or
(ref MDValue a, ref MDValue b);
final MDValue
xor
(ref MDValue a, ref MDValue b);
final MDValue
shl
(ref MDValue a, ref MDValue b);
final MDValue
shr
(ref MDValue a, ref MDValue b);
final MDValue
ushr
(ref MDValue a, ref MDValue b);
- Performs a binary operation on the two values
and
returns the result. Calls metamethods.
- final MDValue
com
(ref MDValue a);
- Performs a bitwise complement of the argument. Calls metamethods.
- final void
andeq
(ref MDValue a, ref MDValue b);
final void
oreq
(ref MDValue a, ref MDValue b);
final void
xoreq
(ref MDValue a, ref MDValue b);
final void
shleq
(ref MDValue a, ref MDValue b);
final void
shreq
(ref MDValue a, ref MDValue b);
final void
ushreq
(ref MDValue a, ref MDValue b);
- Performs a reflexive bitwise operation on a, with b as the right hand side. Calls metamethods.
- final MDValue
cat
(MDValue [] vals);
- Concatenates the list of values (which must be at least two items long) into a single value and
returns it. Calls metamethods.
- final void
cateq
(ref MDValue dest, MDValue [] vals);
- Appends the list of values (which must have at least one item) to the end of the value held in dest.
Calls metamethods.
- final uint
yield
(uint numReturns, MDValue [] values...);
- Yields from a native function acting as a coroutine, just like using the
yield
() expression
in MiniD.
Params:
uint numReturns |
How many returns you'd like to get from the
yield
operation. -1 means as many
values as are passed to this coroutine when it's resumed, in which case the return value
of this method becomes significant. |
MDValue [] values |
A list of values to
yield
. |
Returns:
The number of return values to be popped off the stack. If numReturns was -1, this is how many
values you must pop. If numReturns was >= 0, it's the same as numReturns.
- final void
reset
();
- Resets this coroutine. Only works if this coroutine is in the Dead state.
- final MDContext
context
();
- Gets the
context
which owns this thread.
|