Re: back once again...



oh well, some assorted pieces of documentation.

sorry if this is long, but actually I have a good deal more
random/fragmentary documentation...

I have a server here (doesn't have much particularly new stuff):
http://cr88192.dyndns.org:8080/

and for random docs:
http://cr88192.dyndns.org:8080/prj_docs/bgbgc_docs/
http://cr88192.dyndns.org:8080/prj_docs/bscc_docs/
http://cr88192.dyndns.org:8080/prj_docs/


and, below are some of the more major things (although there is a good deal
MORE than just this...), and far much more than I have bothered to write
about in the form of docs...

signature strings (these are used in many subsystems):
<---
This will attempt to specify Signature strings as applied to data types.
These may be used for variables, objects, functions or methods, ...

Each type is intended to be parsable fairly easily, and where multiple types
may be present in the same string (them being placed end to end). However,
only the types in-sequence are specified, and this does not necessarily
specify how these will be placed in memory.


Qualifiers:
P*, pointer to type
R*, reference to type (invisible pointer)
C*, complex type (f,d,e,g,k)
G*, imaginary type (f,d,e,g,k)
U*, extended type qualifier ('<name>;')

X*, compound type (struct or union), followed by '<name>;'.
T*, will specify a tagged type (deprecated).
W*, Wide pointer type
L*, reference to object type ('<classname>;')
Q*, dynamic array of type

A*, B*, used for basic extension types

Basic Types:
a, signed char
b, bool
c, char
d, double
e, long double
f, float
g, 128-bit float
h, unsigned char/byte
i, int
j, unsigned int
k, hfloat (16-bit float)
l, long
m, unsigned long
n, 128-bit int
o, unsigned 128-bit int
p, (reserved)
q, (reserved)
r, variant (dynamicly typed reference)
s, short
t, unsigned short
u, custom type
v, void
w, wchar/short
x, long long
y, unsigned long long
z, ... (varargs, ...)

Extended Types:
m64, 64-bit raw SSE vector
m128, 128-bit raw SSE vector
quat, quaternion
hquat, hyperbolic quaternion
vec2, 2-elem geometric vector
vec3, 3-elem geometric vector
vec4, 4-elem geometric vector
mat2, 2x2 matrix
mat3, 3x3 matrix
mat4, 4x4 matrix
v2f, 2-elem raw vector
v3f, 3-elem raw vector
v4f, 4-elem raw vector
v2d, 2-elem raw vector (double)



If the type is followed by a number, it indicates that this is an array,
with a comma allowing multidimensional arrays.

Example:
bar:PXfoo;4,4
struct foo *bar[4][4];

Example:
Uvec4;16
Array of 16 4-vectors.

These arrays will specify memory with the specified physical layout.


Object References
'L<classname>;'

These will refer to a specific object type, where classname will be the
qualified class-name for the object in question.

This will differ from 'PX<name>;' in that 'X<name>;' will refer to a
specific and known structural type (the physical layout is thus known).
Likewise, I says nothing about the pointer itself, or the nature of the
pointed-to memory.

On the other hand, 'r' specifies that a dynamically-typed reference is
given, and thus the nature of the pointer and the kind of memory it can
point to, however, 'r' does not specify anything about 'what' is referenced.

'L<classname>;' will then specify that this is a dynamically typed reference
(similar to 'r'), but will also specify that it is a reference to a specific
abstract type (for example, the class with the given classname, or a class
derived from this class), but will not specify the physical layout or
concrete type of the referenced memory (unlike 'X' or 'PX'). In many cases,
'L' may be treated as simply a special case of 'r' (differing primarily in
terms of assignment, where the implementation is strongly encouraged to
ensure that the object being referenced is of the appropriate class, as
otherwise things may be allowed to break).

The exact structure and meaning of 'classname' will be internal to the
object system, but the current idea is that it will represent a heirarchy of
the form '[<name>/]*<class>'. For example, "myApp/custom/Foo".


Dynamic Arrays
'Q' will be similar to 'P' in spirit, but differ in practice similarly to
how 'L' differs from 'PX'. 'Q' will specify that a reference is used to a
dynamically-managed array holding members with the given type, but will
specify neither the physical layout of the array nor of the referenced
values.
Presently this will be limited to reference based types, such as 'Q', 'L',
and 'r'.

For example: 'QQr' will be an array of arrays of references, and
"QLmyApp/custom/Foo;" will be an array of objects.


Functions and Methods
Signature strings as applied to functions and methods will have a slightly
modified notation, namely in that a specific designation of args and return
type may be given.

The basic layout will be:
'(<args>)<ret>'.

Examples:
"int foo();" gives "()i";
"double bar(int x, int y);" gives "(ii)d".

This whole unit will be treated as a single type-unit, so, for example, a
function-pointer could be specified like this:
"P(d)i" for the type "int (*)(double)".

The exact meaning or interpretation of this type will depend on the context
of its usage.
--->


<---
General info about the Class/Instance system.

Primary goals for this system:
Effectively implement a class/instance system;
Performance is a goal, and wherever possible the system should try to have
good performance;
It should represent a reasonably general feature and be sufficiently capable
for use in VMs.

Features:
Class/Instance;
Emphasis on Single Inheritence;
Inferfaces;
Opaque API;
Anonymous classes;
....

Incomplete:
Multiple Inheritence;
....


Structure:


Classes:

dycClass, represents classes, contains much of the core machinery of the
object system. Classes may link to and make use of superclasses, and an
internal versioning system is used to try to handle structural alterations
to classes.

Interfaces will also be represented via dycClass, and in many ways an
interface is like a class. However, it is not valid to try to create an
instance of an interface, nor can an interface contain usable slots or
methods.

At present, interface lookups (for both slots and methods) are performed by
the use of specialized hash-tables (in general, the use of hash tables is
straightforwards, flexible, and reasonably efficient). The approach used is
a variation of a lookup hash.


Slots:

dycSlot is internally contained within dycClass, and stores info needed for
identifying and retrieving slots. Slots may be inherited from superclass,
and so a slot which is valid in a superclass is typically the same slot that
would be returned by a subclass (an exception is when the slot is shadowed
by another slot with the same name).

Multiple 'types' are supported reflecting different ways of storing or
accessing the contents.


A few slot types:

Static, the slot's payload is managed by the slot itself, and so the same
value is shared between all instances and with any derived classes.

Direct, this is the default case for slots, where in this case the slot
refers directly to the value in an object instance.

Indirect, this is similar to direct, but is used when multiple versions of a
class may be in use (for example, as in the case of dynamically modified
classes), where the slot is referred to via a table associated with the
appropriate class version.

Interface, in this case, the slot does not directly refer to the data.
Interface Slots are typically defined within interfaces, and provide a means
to more efficiently access the contents of different unrelated class types.
An interface slot is used with an instance of an object, and serves to look
up the appropriate slot for the object and act as if the access had been via
using the found slot. It is in error to access an interface via an
interface.


Methods:

dycMethod is similarly contained within dycClass. It contains info needed
for identifying a particular method and for retrieving and applying the
correct function object (defined externally to the object system).

Unlike slots, most method types do not exist within the object instances.
Instead, methods are generally accessed via VTables located within the
class.

Methods are accessed providing both a name and a signature. At present, a
method can only be accessed with a signature that is an exact match (no
soft-matching or coercion is done). Multiple methods may exist with the same
name but with different signatures.


Static methods, unlike static slots, are unique to each class. A method
being static defines how it is to be called, not how it is stored.

Direct and Indirect behave similarly to the case with slots, only that they
refer to vtables rather than the instance payload.

Interface Methods are similar to Interface Slots, and likewise are used to
call a method with a matching name and signature.

Slot Methods are accessed like methods, but differ primarily in that, rather
than referring to the vtable, the method identifies a hidden slot, and it is
this slot which holds the function to be called.


Objects:

dycObject holds an object that is an instance of a particular class.

Objects hold a reference to the class, info about the class version (needed
since the class made be modified, but objects remain using an older layout),
as well as a buffer for the object's payload. An object may also hold some
info related to Multiple Inheritence, or to the use of per-object slots or
delegation.

It is also possible to clone an object, which will create a new object with
the same state as the original (including any per-object slots).


Per-Object Slots:

It will be possible to add slots that exist per-instance.

The idea is that these slots will be primarily accessed either dynamically
or via interfaces. It is also possible to retrieve the slot and method
handles from objects, however for likely obvious reasons, it will not be
able to retrieve these slot handles from classes.




Prototype OO (older):

In this sense, Prototype-OO will not be in a pure sense, but rather as a few
extended features for the class/instance system:
An ability to dynamically add slots or methods to existing objects;
An ability for one object to delegate to another;
....

The current idea is that prototype features will be primarily accessed via
interfaces (thus keeping static typing in place).

Likewise, prototype objects will still generally have a class from which
they are inherited from.


The idea here will be that a "virtual class" will exist, which will hold all
possible slots and methods that may be found in a prototype object (these
will be structurally equivalent to, but functionally distinct from, their
use in class/instance objects). Or, alternatively, this is the collection of
all slot or method signatures that have been seen in the prototype system.

So, to dynamically lookup a slot or method for a prototype object will
retrieve the slot or method from here. Note that it will not be possible to
directly interact with this class, and infact no class may actually exist in
this case.

Each slot or method will have its own ID number, and it will be this number
that is used for retrieving the slot or method from the object (the
representation of prototype objects will thus be that of an ID/value
list/hash).

A few special hash tables may be used for speeding up all this as well.
--->


object system:
<---
int dycObjectP(dyt obj);
int dycClassP(dyt obj);
int dycSlotP(dyt obj);
int dycMethodP(dyt obj);

Return nonzero value if obj is the correct type of object.


void dycBeginClass(char *name, char *super);
dycClass dycEndClass();

Begin and end a class declaration.
Super identifies the superclass, or may be NULL (indicating no superclass).
If name is NULL, then the class will be anonymous.

The return value from 'dycEndClass()' will be the handle of the created
class.


void dycBeginClassAnon(dycClass super);
dycClass dycEndClassAnon();

Also creates an anonymous class, but gives the superclass as a class handle
(allowing the use of other anonymous classes as superclasses).


void dycSlotBasic(char *name, char *sig);
void dycSlotStatic(char *name, char *sig);

Declare a new slot.
Basic slots reserve space in the class-instance, and have a value which is
independent for each class instance.
Static slots share the value between all instances of the class, and also
with any subclasses.

void dycSlotStatici(char *name, char *sig, int val);
void dycSlotStaticl(char *name, char *sig, s64 val);
void dycSlotStaticf(char *name, char *sig, double val);
void dycSlotStaticd(char *name, char *sig, double val);
void dycSlotStaticU(char *name, char *sig, void *val);

Declare a static slot and set the initial value.


void dycSlotInit(char *name, char *sig);
void dycSlotIniti(char *name, char *sig, int val);
void dycSlotInitl(char *name, char *sig, s64 val);
void dycSlotInitf(char *name, char *sig, double val);
void dycSlotInitd(char *name, char *sig, double val);
void dycSlotInitU(char *name, char *sig, void *val);

Declare an initialized slot.
Initialized slots hold their values in the class, and are unique to each
class. When an object is created from the class, the values stored in the
init slot are copied into the object.


void dycMethodBasic(char *name, char *sig);
void dycMethodStatic(char *name, char *sig);

Declare a method in an abstract sense (creates the method, but does not
provide a body). When called, a basic method recieves


void dycMethodFunc(char *name, char *sig, dyt fcn);
void dycMethodStaticFunc(char *name, char *sig, dyt fcn);

Declare a method and give the method body to use. The fcn argument needs to
be an object of an appropriate type.


void dycMethodCFunc(char *name, char *sig, void *fcn);
void dycMethodCFuncData(char *name, char *sig, void *fcn, void *data);
void dycMethodCSelf(char *name, char *sig, void *fcn);
void dycMethodCSelfData(char *name, char *sig, void *fcn, void *data);
void dycMethodStaticCFunc(char *name, char *sig, void *fcn);
void dycMethodStaticCFuncData(char *name, char *sig, void *fcn, void *data);
void dycMethodStaticCSelf(char *name, char *sig, void *fcn);
void dycMethodStaticCSelfData(char *name, char *sig, void *fcn, void *data);

Declare a method and provide a C function (as a void pointer).

'Func' recieves its arguments as-is.
'FuncData' has data passed as the first argument.
'Self' has the object passed as the first argument.
'SelfData' has the object as the first argument and data as the second.

'StaticCSelf' and 'StaticCSelfData' are as above, except that the class is
passed rather than the object.


void dycSlotMethod(char *name, char *sig);
void dycStaticSlotMethod(char *name, char *sig);

Declare a slot method.
A slot method behaves between that of a method and a slot.

Namely:
It may be called like a method, and may only hold method objects;
It is unique to each instance, and so may be used for modifiable
per-instance methods (the method is stored in a slot, rather than in a
vtable).


void dycSlotDelegate(char *name, char *cname);

Add a delegate to an object. A delegate is a special kind of slot which
holds object references. When some kinds of operations are performed, an
access may be directed through a delegate.


void dycClassInterface(char *name);

Declares that the class being declared implements a given interface.


void dycBeginIface(char *name, char *super);
dycClass dycEndIface();

Begin and end an interface declaration.
Super gives the super-interface, and may give multiple super-interfaces
separated by spaces.


void dycClassSuper(char *name);
void dycIfaceSuper(char *name);

Provides an alternate way to give super-interfaces. If these is used, the
super argument to BeginClass/BeginIface is to be NULL. These will differ
from passing a string in that these will always create a
Multiple-Inheritence case, even if only used once.


void dycIfaceMethod(char *name, char *sig);
void dycIfaceSlot(char *name, char *sig);

Declares an interface method or slot.
A method or slot declared in an interface may be used in place of a
class-specific method or slot when accessing an object which is an instance
of a class implementing the interface.


dycClass dycGetClass(char *name);

Lookup the class for a given classname.

dycObject dycAlloc(dycClass inf);
dycObject dycAllocClass(char *name);

Allocate a new instance of the class.
This sets up initial storage and may initialize slots, but does not call the
constructor.


dycObject dycNewClass(char *name);
dycObject dycNewInitClass(char *name, char *sig, ...);
dycObject dycNewInitClassV(char *name, char *sig, va_list args);
dycObject dycNewInitClassU(char *name, char *sig, void **args);

Creates a new instance of a class and calls the constructor.
Sig is to be an exact match to one of the appropriate constructors for the
class.

All constructors are to have a return type of 'v' (void).
In the case of 'dycNewClass()', the sig is '()v'.


dycObject dycNew(dycClass inf);
dycObject dycNewInit(dycClass inf, char *sig, ...);
dycObject dycNewInitV(dycClass inf, char *sig, va_list args);
dycObject dycNewInitU(dycClass inf, char *sig, void **args);

As above, a new instance of the class is created and the constructor is
called.



int dycSubclassP(dycClass info, dycClass super);
int dycSubclassOfP(char *name, char *super);

Check if info is or is a subclass of super.


int dycInstanceP(dycObject obj, dycClass inf);
int dycInstanceOfP(dycObject obj, char *name);

Check if obj is an instance of inf or an instance of a subclass of inf.


dycClass dycGetObjClass(dycObject obj);
dycClass dycGetClassSuper(dycClass inf);
char *dycGetClassName(dycClass inf);
char *dycGetObjClassName(dycObject obj);
char *dycGetSlotName(dycSlot idx);
char *dycGetSlotSig(dycSlot idx);
char *dycGetMethodName(dycMethod idx);
char *dycGetMethodSig(dycMethod idx);

Not hard to figure out...


dycSlot dycIdxSlot(dycClass info, char *name);
dycSlot dycIdxObjSlot(dycObject obj, char *name);
dycSlot dycIdxClassSlot(char *cname, char *sname);
dycMethod dycIdxMethod(dycClass inf, char *name, char *sig);
dycMethod dycIdxObjMethod(dycObject obj, char *name, char *sig);
dycMethod dycIdxClassMethod(char *cname, char *name, char *sig);

Look up slots or methods.


void *dycGetSlotPtr(dycObject obj, dycSlot idx);
void *dycGetInitPtr(dycClass inf, dycSlot idx);
void *dycGetStaticPtr(dycClass inf, dycSlot idx);
void *dycPtrSlot(dycObject obj, char *name);
void *dycPtrStaticSlot(dycClass info, char *name);
void *dycPtrInitSlot(dycClass info, char *name);
void *dycPtrClassSlot(char *cname, char *sname);

Get pointers to slots. This will be a pointer to the memory holding the
value of the slot in question.

note that GetSlotPtr/PtrSlot will also work with static slots and interface
slots and such.
GetInitPtr/PtrInitSlot will work with both init slots and static slot. Note
that an init slot has the same identity as the normal instance slot with the
same name, and so it is the use of this function that indicates one is
accessing the init slot.

GetStaticPtr/PtrStaticSlot are useful for when one knows the slot is static.



dyt dycLookupMethodSig(dycObject obj, char *name, char *sig);
dyt dycGetMethodFunc(dycClass inf, dycMethod idx);
dyt dycGetObjMethodFunc(dycObject obj, dycMethod idx);

Retrieve the function value from a given class or object method.


void dycSetMethodFunc(dycClass inf, dycMethod idx, dyt fcn);
void dycSetObjMethodFunc(dycObject obj, dycMethod idx, dyt fcn);

Assign the method for a given class or object.
Note that for normal static or virtual methods, these will modify the vtable
of the respective object (and thus apply to all instances of this class, but
does not effect superclasses, and it is undefined if/when this change will
be reflected in sub-classes).

For slot methods, the method is located in the object itself, and so the
change will only apply to the object in question.


dycSlot dycAddObjSlot(dycObject obj, char *name, char *sig);
dycMethod dycAddObjMethod(dycObject obj, char *name, char *sig);

Dynamically add a slot to an object. This slot will be a "prototype"
slot/method, and will be unique to the object in question. Methods will be,
by definition, stored in slots, and as such will be unique to this object.


dycObject dycCloneObject(dycObject obj);

Create a clone of an existing object. A clone is basically a new object
which has the same class, a copy of all of the slots/methods/... from the
old object.


dyt dycGetSlot(dycObject obj, char *name);
dyt dycGetSlotr(dycObject obj, char *name);
void *dycGetSlotp(dycObject obj, char *name);
int dycGetSlotsb(dycObject obj, char *name);
int dycGetSlotub(dycObject obj, char *name);
int dycGetSlotss(dycObject obj, char *name);
int dycGetSlotus(dycObject obj, char *name);
int dycGetSloti(dycObject obj, char *name);
s64 dycGetSlotl(dycObject obj, char *name);
float dycGetSlotf(dycObject obj, char *name);
double dycGetSlotd(dycObject obj, char *name);

Get the value of a slot which is looked up by name.

The suffix gives the type, and is to be compatible with the slot in question
(it is undefined what happens if there is a mismatch).

Suffix:
(none), tries to access the slot using dynamic types;
r, reference (generic);
p, pointer (generic);
sb, signed byte;
ub, unsigned byte;
ss, signed short;
us, unsigned short;
i, integer (32-bit);
l, long (64-bit);
f, float;
d, double.

Note that this is not the convention used in the signature strings.


int dycSetSlot(dycObject obj, char *name, dyt val);
int dycSetSlotr(dycObject obj, char *name, dyt val);
int dycSetSlotp(dycObject obj, char *name, void *val);
int dycSetSlotsb(dycObject obj, char *name, int val);
int dycSetSlotub(dycObject obj, char *name, int val);
int dycSetSlotss(dycObject obj, char *name, int val);
int dycSetSlotus(dycObject obj, char *name, int val);
int dycSetSloti(dycObject obj, char *name, int val);
int dycSetSlotl(dycObject obj, char *name, s64 val);
int dycSetSlotf(dycObject obj, char *name, float val);
int dycSetSlotd(dycObject obj, char *name, double val);

Assign the value in the slot, referencing by name.


int dycGetsb(dycObject obj, dycSlot idx);
int dycGetub(dycObject obj, dycSlot idx);
int dycGetss(dycObject obj, dycSlot idx);
int dycGetus(dycObject obj, dycSlot idx);
int dycGeti(dycObject obj, dycSlot idx);
s64 dycGetl(dycObject obj, dycSlot idx);
float dycGetf(dycObject obj, dycSlot idx);
double dycGetd(dycObject obj, dycSlot idx);
dyt dycGetr(dycObject obj, dycSlot idx);
void *dycGetp(dycObject obj, dycSlot idx);

Get the value in the slot, accessed via the slot index.


void dycSetsb(dycObject obj, dycSlot idx, int val);
void dycSetub(dycObject obj, dycSlot idx, int val);
void dycSetss(dycObject obj, dycSlot idx, int val);
void dycSetus(dycObject obj, dycSlot idx, int val);
void dycSeti(dycObject obj, dycSlot idx, int val);
void dycSetl(dycObject obj, dycSlot idx, s64 val);
void dycSetf(dycObject obj, dycSlot idx, float val);
void dycSetd(dycObject obj, dycSlot idx, double val);
void dycSetr(dycObject obj, dycSlot idx, dyt val);
void dycSetp(dycObject obj, dycSlot idx, void *val);

Set the value in the slot, accessed via the slot index.


int dycGetStaticsb(dycClass inf, dycSlot idx);
int dycGetStaticub(dycClass inf, dycSlot idx);
int dycGetStaticss(dycClass inf, dycSlot idx);
int dycGetStaticus(dycClass inf, dycSlot idx);
int dycGetStatici(dycClass inf, dycSlot idx);
s64 dycGetStaticl(dycClass inf, dycSlot idx);
float dycGetStaticf(dycClass inf, dycSlot idx);
double dycGetStaticd(dycClass inf, dycSlot idx);
dyt dycGetStaticr(dycClass inf, dycSlot idx);
void *dycGetStaticp(dycClass inf, dycSlot idx);

Get the value in the static slot, accessed via the slot index.


void dycSetStaticsb(dycClass inf, dycSlot idx, int val);
void dycSetStaticub(dycClass inf, dycSlot idx, int val);
void dycSetStaticss(dycClass inf, dycSlot idx, int val);
void dycSetStaticus(dycClass inf, dycSlot idx, int val);
void dycSetStatici(dycClass inf, dycSlot idx, int val);
void dycSetStaticl(dycClass inf, dycSlot idx, s64 val);
void dycSetStaticf(dycClass inf, dycSlot idx, float val);
void dycSetStaticd(dycClass inf, dycSlot idx, double val);
void dycSetStaticr(dycClass inf, dycSlot idx, dyt val);
void dycSetStaticp(dycClass inf, dycSlot idx, void *val);

Set the value in the static slot, accessed via the slot index.


int dycGetInitsb(dycClass inf, dycSlot idx);
int dycGetInitub(dycClass inf, dycSlot idx);
int dycGetInitss(dycClass inf, dycSlot idx);
int dycGetInitus(dycClass inf, dycSlot idx);
int dycGetIniti(dycClass inf, dycSlot idx);
s64 dycGetInitl(dycClass inf, dycSlot idx);
float dycGetInitf(dycClass inf, dycSlot idx);
double dycGetInitd(dycClass inf, dycSlot idx);
dyt dycGetInitr(dycClass inf, dycSlot idx);
void *dycGetInitp(dycClass inf, dycSlot idx);

Get the value in the init slot, accessed via the slot index.


void dycSetInitsb(dycClass inf, dycSlot idx, int val);
void dycSetInitub(dycClass inf, dycSlot idx, int val);
void dycSetInitss(dycClass inf, dycSlot idx, int val);
void dycSetInitus(dycClass inf, dycSlot idx, int val);
void dycSetIniti(dycClass inf, dycSlot idx, int val);
void dycSetInitl(dycClass inf, dycSlot idx, s64 val);
void dycSetInitf(dycClass inf, dycSlot idx, float val);
void dycSetInitd(dycClass inf, dycSlot idx, double val);
void dycSetInitr(dycClass inf, dycSlot idx, dyt val);
void dycSetInitp(dycClass inf, dycSlot idx, void *val);

Set the value in the init slot, accessed via the slot index.


void *dycCallSigU(dycObject obj, char *name, char *sig, void **args);
void *dycCallSigV(dycObject obj, char *name, char *sig, va_list args);
void *dycCallSig(dycObject obj, char *name, char *sig, ...);

Calls a method dynamically looking up the method.
The return value is a pointer to a temporary buffer holding the return value
for the method.


dyt dycCallSigVr(dycObject obj, char *name, char *sig, va_list lst);
int dycCallSigVi(dycObject obj, char *name, char *sig, va_list lst);
s64 dycCallSigVl(dycObject obj, char *name, char *sig, va_list lst);
float dycCallSigVf(dycObject obj, char *name, char *sig, va_list lst);
double dycCallSigVd(dycObject obj, char *name, char *sig, va_list lst);

dyt dycCallSigUr(dycObject obj, char *name, char *sig, void **args);
int dycCallSigUi(dycObject obj, char *name, char *sig, void **args);
s64 dycCallSigUl(dycObject obj, char *name, char *sig, void **args);
float dycCallSigUf(dycObject obj, char *name, char *sig, void **args);
double dycCallSigUd(dycObject obj, char *name, char *sig, void **args);

int dycCallSigi(dycObject obj, char *name, char *sig, ...);
s64 dycCallSigl(dycObject obj, char *name, char *sig, ...);
float dycCallSigf(dycObject obj, char *name, char *sig, ...);
double dycCallSigd(dycObject obj, char *name, char *sig, ...);

Calls a method dynamically looking up the method.


void *dycCallU(dycObject obj, dycMethod mth, void **args);
void *dycCallV(dycObject obj, dycMethod mth, va_list args);
void *dycCall(dycObject obj, dycMethod mth, ...);

Calls a method given a method handle.
The return value is a pointer to a temporary buffer holding the return value
for the method.


int dycCallUi(dycObject obj, dycMethod mth, void **args);
s64 dycCallUl(dycObject obj, dycMethod mth, void **args);
float dycCallUf(dycObject obj, dycMethod mth, void **args);
double dycCallUd(dycObject obj, dycMethod mth, void **args);
dyt dycCallUr(dycObject obj, dycMethod mth, void **args);
void *dycCallUp(dycObject obj, dycMethod mth, void **args);
void dycCallUv(dycObject obj, dycMethod mth, void **args);

int dycCallVi(dycObject obj, dycMethod mth, va_list args);
s64 dycCallVl(dycObject obj, dycMethod mth, va_list args);
float dycCallVf(dycObject obj, dycMethod mth, va_list args);
double dycCallVd(dycObject obj, dycMethod mth, va_list args);
dyt dycCallVr(dycObject obj, dycMethod mth, va_list args);
void *dycCallVp(dycObject obj, dycMethod mth, va_list args);
void dycCallVv(dycObject obj, dycMethod mth, va_list args);

int dycCalli(dycObject obj, dycMethod mth, ...);
s64 dycCalll(dycObject obj, dycMethod mth, ...);
float dycCallf(dycObject obj, dycMethod mth, ...);
double dycCalld(dycObject obj, dycMethod mth, ...);
dyt dycCallr(dycObject obj, dycMethod mth, ...);
void *dycCallp(dycObject obj, dycMethod mth, ...);
void dycCallv(dycObject obj, dycMethod mth, ...);

Calls a method given a method handle.


void *dycCallStaticU(dycClass inf, dycMethod mth, void **args);
void *dycCallStaticV(dycClass inf, dycMethod mth, va_list args);
void *dycCallStatic(dycClass inf, dycMethod mth, ...);

Calls a static method given a method handle.
The return value is a pointer to a temporary buffer holding the return value
for the method.


int dycCallStaticUi(dycClass inf, dycMethod mth, void **args);
s64 dycCallStaticUl(dycClass inf, dycMethod mth, void **args);
float dycCallStaticUf(dycClass inf, dycMethod mth, void **args);
double dycCallStaticUd(dycClass inf, dycMethod mth, void **args);
dyt dycCallStaticUr(dycClass inf, dycMethod mth, void **args);
void *dycCallStaticUp(dycClass inf, dycMethod mth, void **args);
void dycCallStaticUv(dycClass inf, dycMethod mth, void **args);

int dycCallStaticVi(dycClass inf, dycMethod mth, va_list args);
s64 dycCallStaticVl(dycClass inf, dycMethod mth, va_list args);
float dycCallStaticVf(dycClass inf, dycMethod mth, va_list args);
double dycCallStaticVd(dycClass inf, dycMethod mth, va_list args);
dyt dycCallStaticVr(dycClass inf, dycMethod mth, va_list args);
void *dycCallStaticVp(dycClass inf, dycMethod mth, va_list args);
void dycCallStaticVv(dycClass inf, dycMethod mth, va_list args);

int dycCallStatici(dycClass inf, dycMethod mth, ...);
s64 dycCallStaticl(dycClass inf, dycMethod mth, ...);
float dycCallStaticf(dycClass inf, dycMethod mth, ...);
double dycCallStaticd(dycClass inf, dycMethod mth, ...);
dyt dycCallStaticr(dycClass inf, dycMethod mth, ...);
void *dycCallStaticp(dycClass inf, dycMethod mth, ...);
void dycCallStaticv(dycClass inf, dycMethod mth, ...);

Calls a static method given a method handle.


void *dycCallAsU(dycObject obj, dycClass inf, dycMethod mth, void **args);
void *dycCallAsV(dycObject obj, dycClass inf, dycMethod mth, va_list args);
void *dycCallAs(dycObject obj, dycClass inf, dycMethod mth, ...);

Calls a method given a method handle as-if obj were an instance of inf.
The return value is a pointer to a temporary buffer holding the return value
for the method.


int dycCallAsUi(dycObject obj, dycClass inf, dycMethod mth, void **args);
s64 dycCallAsUl(dycObject obj, dycClass inf, dycMethod mth, void **args);
float dycCallAsUf(dycObject obj, dycClass inf, dycMethod mth, void **args);
double dycCallAsUd(dycObject obj, dycClass inf, dycMethod mth, void **args);
dyt dycCallAsUr(dycObject obj, dycClass inf, dycMethod mth, void **args);
void *dycCallAsUp(dycObject obj, dycClass inf, dycMethod mth, void **args);
void dycCallAsUv(dycObject obj, dycClass inf, dycMethod mth, void **args);

int dycCallAsVi(dycObject obj, dycClass inf, dycMethod mth, va_list args);
s64 dycCallAsVl(dycObject obj, dycClass inf, dycMethod mth, va_list args);
float dycCallAsVf(dycObject obj, dycClass inf, dycMethod mth, va_list args);
double dycCallAsVd(dycObject obj, dycClass inf, dycMethod mth, va_list
args);
dyt dycCallAsVr(dycObject obj, dycClass inf, dycMethod mth, va_list args);
void *dycCallAsVp(dycObject obj, dycClass inf, dycMethod mth, va_list args);
void dycCallAsVv(dycObject obj, dycClass inf, dycMethod mth, va_list args);

int dycCallAsi(dycObject obj, dycClass inf, dycMethod mth, ...);
s64 dycCallAsl(dycObject obj, dycClass inf, dycMethod mth, ...);
float dycCallAsf(dycObject obj, dycClass inf, dycMethod mth, ...);
double dycCallAsd(dycObject obj, dycClass inf, dycMethod mth, ...);
dyt dycCallAsr(dycObject obj, dycClass inf, dycMethod mth, ...);
void *dycCallAsp(dycObject obj, dycClass inf, dycMethod mth, ...);
void dycCallAsv(dycObject obj, dycClass inf, dycMethod mth, ...);

Calls a method given a method handle as-if obj were an instance of inf.
--->


<---
Purpose: Informative, Describe Thunks


Environments

dyt dyllNewEnv(dyt super);

Create a new empty binding environment.
Note, this only refers to the contents of the environment itself, where as a
general rule it is the case that the global toplevel is visible even if the
current env is empty.

The purpose of binding environments is then to provide local bindings which
are separate from those of the global toplevel, and which can be assigned
programatically.

Super will serve a similar role to a class in class/instance OO, where any
bindings lacking in the current env will be checked for in the super, and so
on until there is nowhere left to check.


void dyllEnvBindAddr(dyt env, char *name, void *addr);
void dyllEnvBindAddrSig(dyt env, char *name, char *sig, void *addr);

Bind an address in an environment. This binding will be local to the
environment in question. If provided, the signature will identify the type
of value contained in the variable.


void dyllEnvSetAddr(dyt env, char *name, void *addr);

Try to assign the address of the variable in question.


void *dyllEnvGetAddr(dyt env, char *name);
char *dyllEnvGetSig(dyt env, char *name);

Retrieve the address and signature of a variable in an env.
If no signature was given for the variable, then the returned sig will be
NULL.


void *dyllEnvAllocVar(dyt env, char *name, char *sig);

Create a new variable and allocate storage for it.



Thunks

Thunks are executable objects, part object and part function. A thunk can
generally be cast to a function pointer and called, or it can be accessed
via special functions.


dyt dyllThunkEnv(dyt fcn);

Get the environment from a thunk.


void dyllThunkBindAddr(dyt fcn, char *name, void *addr);
void dyllThunkBindAddrSig(dyt fcn, char *name, char *sig, void *addr);

Create a new variable within a thunk (or, more correctly, in the env held by
the thunk).


void dyllThunkSetAddr(dyt fcn, char *name, void *addr);

Assign the address of a variable within a thunk.


void *dyllThunkGetAddr(dyt fcn, char *name);
char *dyllThunkGetSig(dyt fcn, char *name);

Get the address and sig of a variable within a thunk.


dyt dyllAsmThunk(char *buf);
dyt dyllAsmThunkEnv(char *buf, dyt env);
dyt dyllAsmThunkSuperEnv(char *buf, dyt senv);

Create a new thunk. The 'buf' argument provides the assembly code to be used
for the thunk body. The assembly code in buf should be appropriate for the
particular arch.

The env argument gives the current environment to use when assembling the
thunk. Bindings in the assembly code may be added to env.

In the case of senv, a new environment is created that has senv as the
super, but any new bindings are added to the new environment.

If no environment is provided, then a new empty environment is created to
hold the bindings for the thunk.


Although the thunk may be called as if it were a function pointer, it is
actually a structured object (the first field will typically contain a jump
to the entry point). Otherwise, the structure of a non-inline thunk is not
described.


dyt dyllAsmThunkInline(char *buf);
dyt dyllAsmThunkInlineEnv(char *buf, dyt env);
dyt dyllAsmThunkInlineSuperEnv(char *buf, dyt senv);

These create a thunk, similar to the above, however the thunk itself is
different. In this case, the thunk is assembled as a raw glob of bytes with
no metadata present (for example: the environment is not maintained, ...),
thus making it take less memory. If a data section is present, it is
assembled directly following the code. Note that the entry point is always
located at the physical start of the thunk.

If no data section is present, the end of the thunk is directly after the
last instruction, and if a data section is present, the end of the thunk
follows the end of the data (in this case, padding may be inserted).


Assembly

The basic ASM structure for a thunk is much like any other piece of ASM.

<--
[section .text]
[bits 32]
thunk_start:
push ebp
mov ebp, esp
....
mov ecx, [G.foo]
mov eax, [ecx]
....
pop ebp
ret

[section .data]
foo dd 0
-->

The label 'thunk_start' is special for thunks, and basically tells where the
entry point is. For inline thunks, 'thunk_start' is optional/ignored, and
the entry point is always at the physical start of the thunk.

Variables may also be referenced indirectly, where a direct reference such
as:
mov eax, [foo]
Can be instead written:
mov ecx, [G.foo]
mov eax, [ecx]

Which in effect binds the thunk to the environment, allowing changes in the
environment to be directly reflected in the code (it is done this way since
my other approach to dynamic relinking does not mix well with garbage
collection). Directly referencing a variable will link it with the address
held in the environment at the time. Indirect references are not to be used
with inline thunks.

A data section may be provided with thunks, and serves to hold variables.


An example of an inline thunk:
<--
push ebp
mov ebp, esp
....
pop ebp
ret
-->

--->



.



Relevant Pages

  • passing object reference to the method
    ... and I want to pass it by reference. ... public interface IFoo{} ... void FromHere() ... and compiler screams that it cannot convert IFoo to char (latter ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: pass by reference
    ... char *something; ... You can, if you really need, do something similar to pass by reference, and that is by explicitly passing the address of a variable. ... void AllocateSomething ...
    (comp.lang.c)
  • Re: Passing structs....
    ... void func{ ... int main{ ... char x; ... But a pass by reference in C++ would include the trailing &. ...
    (microsoft.public.vc.language)
  • Re: type-punning?
    ... The problem is that dat is defined as char *. ... defined as a void *. ... pointer by passing a reference to it to a function? ...
    (comp.lang.c)
  • Re: Ref Propogation in C#
    ... You talk about passing an instance by reference - you ... > void MyFunctionA(ref MyObject obj) ... you don't need to have used "ref" anywhere. ...
    (microsoft.public.dotnet.languages.csharp)