System/Docu/Meta.odc

Meta

DEFINITION Meta;

	CONST
		undef = 0;
		typObj = 2; varObj = 3; procObj = 4; fieldObj = 5; modObj = 6;
		boolTyp = 1; sCharTyp = 2; charTyp = 3;
		byteTyp = 4; sIntTyp = 5; intTyp = 6; longTyp = 10; sRealTyp = 7; realTyp = 8;
		setTyp = 9; anyRecTyp = 11; anyPtrTyp = 12;
		procTyp = 16; recTyp = 17; arrTyp = 18; ptrTyp = 19;
		final = 0; extensible = 1; limited = 2; abstract = 3;
		hidden = 1; readOnly = 2; exported = 4;

	TYPE
		Name = ARRAY 256 OF CHAR;

		Value = ABSTRACT RECORD END;

		Item = RECORD (Value)
			obj-, typ-, vis-, adr-: INTEGER;
			(VAR i: Item) Valid (): BOOLEAN, NEW;
			(VAR i: Item) GetTypeName (OUT mod, type: Name), NEW;
			(VAR i: Item) BaseTyp (): INTEGER, NEW;
			(VAR i: Item) Level (): INTEGER, NEW;
			(VAR i: Item) Size (): INTEGER, NEW;
			(VAR arr: Item) Len (): INTEGER, NEW;
			(VAR in: Item) Lookup (IN name: ARRAY OF CHAR; VAR i: Item), NEW;
			(VAR i: Item) GetBaseType (VAR base: Item), NEW;
			(VAR rec: Item) GetThisBaseType (level: INTEGER; VAR base: Item), NEW;
			(VAR rec: Item) Is (IN type: Value): BOOLEAN, NEW;
			(VAR ptr: Item) Deref (VAR ref: Item), NEW;
			(VAR arr: Item) Index (index: INTEGER; VAR elem: Item), NEW;
			(VAR proc: Item) Call (OUT ok: BOOLEAN), NEW;
			(VAR var: Item) GetVal (VAR x: Value; OUT ok: BOOLEAN), NEW;
			(VAR var: Item) PutVal (IN x: Value; OUT ok: BOOLEAN), NEW;
			(VAR var: Item) GetStringVal (OUT x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW;
			(VAR var: Item) GetSStringVal (OUT x: ARRAY OF SHORTCHAR; OUT ok: BOOLEAN), NEW;
			(VAR var: Item) PutStringVal (IN x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW;
			(VAR var: Item) PutSStringVal (IN x: ARRAY OF SHORTCHAR; OUT ok: BOOLEAN), NEW;
			(VAR var: Item) PtrVal (): ANYPTR, NEW;
			(VAR var: Item) PutPtrVal (x: ANYPTR), NEW;
			(VAR var: Item) IntVal (): INTEGER, NEW;
			(VAR var: Item) PutIntVal (x: INTEGER), NEW;
			(VAR var: Item) RealVal (): REAL, NEW;
			(VAR var: Item) PutRealVal (x: REAL), NEW;
			(VAR var: Item) LongVal (): LONGINT, NEW;
			(VAR var: Item) PutLongVal (x: LONGINT), NEW;
			(VAR var: Item) CharVal (): CHAR, NEW;
			(VAR var: Item) PutCharVal (x: CHAR), NEW;
			(VAR var: Item) BoolVal (): BOOLEAN, NEW;
			(VAR var: Item) PutBoolVal (x: BOOLEAN), NEW;
			(VAR var: Item) SetVal (): SET, NEW;
			(VAR var: Item) PutSetVal (x: SET), NEW;
			(VAR type: Item) New (): ANYPTR, NEW;
			(VAR val: Item) Copy (): ANYPTR, NEW;
			(VAR rec: Item) CallWith (proc: PROCEDURE (VAR rec, par: ANYREC); VAR par: ANYREC), NEW
		END;

		Scanner = RECORD 
			this-: Item;
			eos-: BOOLEAN;
			(VAR s: Scanner) ConnectToMods, NEW;
			(VAR s: Scanner) ConnectTo (IN obj: Item), NEW;
			(VAR s: Scanner) Scan, NEW;
			(VAR s: Scanner) GetObjName (OUT name: Name), NEW;
			(VAR s: Scanner) Level (): INTEGER, NEW
		END;

	LookupFilter = PROCEDURE (IN path: ARRAY OF CHAR; OUT i: Item; OUT done: BOOLEAN)

	PROCEDURE Lookup (IN name: ARRAY OF CHAR; OUT mod: Item);
	PROCEDURE LookupPath (IN path: ARRAY OF CHAR; OUT i: Item);
	PROCEDURE GetItem (obj: ANYPTR; OUT i: Item);
	PROCEDURE GetThisItem (IN attr: ANYREC; OUT i: Item);
	PROCEDURE InstallFilter (filter: LookupFilter);

END Meta.


Meta provides access to Component Pascal run-time type information. Meta is restricted to public information, i.e., it doesn't allow access to non-exported items of a module. Meta is safe, it doesn't allow to change data which is not exported as modifiable. Generally, Meta only allows to do with a module what could be done by a normal client module also. The difference is that Meta is more dynamic; it allows inspection and modification of data depending on run-time decisions, without static import of the inspected or modified module.

Constants are not accessible via Meta, they are not represented at run-time in order to minimize space overhead.

Examples:
ObxCtrls	slider control, extended from Controls.Control
ObxFldCtrls	special-purpose text field control, extended from Controls.Control

How to call procedures using Meta:
In order to call an arbitrary procedure (methods are not possible) whose signature is statically known, the following must be done: first, an item must be created that describes the function:

	Meta.Lookup(moduleName, item);
	IF item.obj = Meta.modObj THEN
		item.Lookup(procedureName, item);
		IF item.obj = Meta.procObj THEN
			item.GetVal(item0, ok);
			IF ok THEN
				item0.fun(x)
				...

The item item is a normal, non-extended Meta.Item item. In contrast, item0 must be an extension of Meta.Value that contains as one additional field a procedure variable of the correct type:

	item0: RECORD (Meta.Value)
				fun: PROCEDURE (x: REAL): REAL
			END;


CONST undef
Possible result code for object classes, type classes, visibility classes.

CONST typObj, varObj, procObj, fieldObj, modObj
Object classes.

CONST boolTyp, sCharTyp, charTyp, byteTyp, sintTyp, intTyp, longTyp,
			sRealTyp, realTyp, setTyp, anyRecTyp, anyPtrTyp, procTyp, recTyp, arrTyp, ptrTyp
Type classes.

CONST final, extensible, limited, abstract
Record attributes.

CONST hidden, readOnly, exported
Visibility classes.


TYPE Name
String type for meta item names.


TYPE Value
ABSTRACT
A value may be extended exactly once, with a single field.


TYPE Item (Value)

obj-: INTEGER	obj IN {typObj..modObj}
Object class.

typ-: INTEGER	obj IN {boolTyp..procTyp}
Object's type.

vis-: INTEGER	vis IN {hidden..exported}
Visibility.

adr-: INTEGER
Memory address.

PROCEDURE (VAR i: Item) Valid (): BOOLEAN
NEW
Determines whether the item is valid, i.e., initialized, set to a defined type, and its module is still loaded.

PROCEDURE (VAR i: Item) GetTypeName (OUT mod, type: Name)
NEW
Get the item's type name and the name of this type's module.

Pre
i.Valid()	20
i.typ >= recTyp	21
module of type is still loaded	24

PROCEDURE (VAR i: Item) BaseTyp (): INTEGER
NEW
Returns the item's base type.

Pre
i.Valid()	20
i.typ IN {arrTyp, recTyp, ptrTyp}	21

PROCEDURE (VAR i: Item) Level (): INTEGER
NEW
Returns the item's level.

Pre
i.Valid()	20
i.typ IN {recTyp, arrTyp}	21

PROCEDURE (VAR i: Item) Size (): INTEGER
NEW
Returns the item's size in bytes.

Pre
i.Valid()	20
i.typ # undef	21

PROCEDURE (VAR arr: Item) Len (): INTEGER
NEW
Returns the array's length.

Pre
i.Valid()	20
i.typ = arrTyp	21

PROCEDURE (VAR in: Item) Lookup (IN name: ARRAY OF CHAR; VAR i: Item)
NEW
Lookup an item in a module or a field in a record.

Pre
in.Valid()	20
in.obj = modObj  OR  in.typ = recTyp	21

Post
i.obj # undef
	lookup was successful
i.obj = undef
	lookup was not successful

PROCEDURE (VAR i: Item) GetBaseType (VAR base: Item)
NEW
Assign i's base type to base.

Pre
i.Valid()	20
i.typ IN {recTyp, arrTyp}	21

PROCEDURE (VAR rec: Item) GetThisBaseType (level: INTEGER; VAR base: Item)
NEW
Assign i's level-th base type to base. If the level does not exist, i.obj is set to undef.

Pre
i.Valid()	20
i.typ IN {recTyp, arrTyp}	21
level >= 0  &  level < 16	28

PROCEDURE (VAR rec: Item) Is (IN type: Value): BOOLEAN
NEW
Perform a type test rec IS type.

Pre
rec.Valid()	20
rec.typ = recTyp	21
type IS Item
	type.Valid()	20
	type.typ = recTyp	21
~(type IS Item)
	type.Level() = 1	25
	number of fields of type = 1	26

PROCEDURE (VAR ptr: Item) Deref (VAR ref: Item)
NEW
Dereference pointer ptr and assign the result to ref.

Pre
ptr.typ = ptrTyp	21
ref must be a level 1 record	25
ref must have exactly one field	26

PROCEDURE (VAR arr: Item) Index (index: INTEGER; VAR elem: Item)
NEW
Assign the index-th element of array arr to elem.

Pre
arr.Valid()	20
arr.typ = arrTyp	21
arr.obj = varObj	22

PROCEDURE (VAR proc: Item) Call (OUT ok: BOOLEAN)
NEW
Call a parameterless procedure.

Pre
proc.Valid()	20
proc.obj = procObj  OR  proc.obj = varObj & proc.typ = procTyp	21

PROCEDURE (VAR var: Item) GetVal (VAR x: Value; OUT ok: BOOLEAN)
NEW

PROCEDURE (VAR var: Item) PutVal (IN x: Value; OUT ok: BOOLEAN)
NEW

PROCEDURE (VAR var: Item) GetStringVal (OUT x: ARRAY OF CHAR; OUT ok: BOOLEAN)
NEW

PROCEDURE (VAR var: Item) GetSStringVal (OUT x: ARRAY OF SHORTCHAR; OUT ok: BOOLEAN)
NEW

PROCEDURE (VAR var: Item) PtrVal (): ANYPTR
NEW

PROCEDURE (VAR var: Item) PutPtrVal (x: ANYPTR)
NEW

PROCEDURE (VAR var: Item) IntVal (): INTEGER
NEW

PROCEDURE (VAR var: Item) PutIntVal (x: INTEGER)
NEW

PROCEDURE (VAR var: Item) RealVal (): REAL
NEW

PROCEDURE (VAR var: Item) PutRealVal (x: REAL)
NEW

PROCEDURE (VAR var: Item) LongVal (): LONGINT
NEW

PROCEDURE (VAR var: Item) PutLongVal (x: LONGINT)
NEW

PROCEDURE (VAR var: Item) CharVal (): CHAR
NEW

PROCEDURE (VAR var: Item) PutCharVal (x: CHAR)
NEW

PROCEDURE (VAR var: Item) BoolVal (): BOOLEAN
NEW

PROCEDURE (VAR var: Item) PutBoolVal (x: BOOLEAN)
NEW

PROCEDURE (VAR var: Item) SetVal (): SET
NEW

PROCEDURE (VAR var: Item) PutSetVal (x: SET)
NEW

PROCEDURE (VAR type: Item) New (): ANYPTR
NEW
Generates a new empty heap object. The item must be a record or a pointer. The type of the new object is the same as the pointer, or a pointer to the record described by the item.

PROCEDURE (VAR val: Item) Copy (): ANYPTR
NEW
The same as New, but also copies the contents byte by byte.

PROCEDURE (VAR rec: Item) CallWith (proc: PROCEDURE (VAR rec, par: ANYREC); VAR par: ANYREC)
NEW
Call procedure proc with the parameters rec (i.e., the item itself, the "self" parameter) and parameter par.


TYPE Scanner
A scanner allows to iterate over all modules, all items in a module, or all fields in a record.

this-: Item
The result of the most recent Scan operation.

eos-: BOOLEAN
This flag tells whether the most recent Scan operation has attempted to read beyond the last item.

PROCEDURE (VAR s: Scanner) ConnectToMods
NEW
Each invocation of s.Scan will return another module.

Post
s.this.obj = undef
~s.eos

PROCEDURE (VAR s: Scanner) ConnectTo (IN obj: Item)
NEW
Connect the scanner to a particular module or record.

Pre
obj.Valid()	20
obj.obj = modObj  OR  obj.typ = recTyp	21

PROCEDURE (VAR s: Scanner) Scan
Scan a new item. The result is put into s.this. If an attempt was made to scan beyond the last item, s.eos is set, otherwise it is cleared.

Pre
s is connected	20

PROCEDURE (VAR s: Scanner) GetObjName (OUT name: Name)
NEW
Get the name of the most recently scanned item.

Pre
s.this.Valid()	20

PROCEDURE (VAR s: Scanner) Level (): INTEGER
NEW
Returns the scanned record's extension level.

Pre
s.this.Valid()	20
s connecte to record variable	22


TYPE LookupFilter = PROCEDURE (IN path: ARRAY OF CHAR; OUT i: Item; OUT done: BOOLEAN)
Type used for extension hook that allows Meta to operate remotely, for example.


PROCEDURE Lookup (IN name: ARRAY OF CHAR; OUT mod: Item)
Set up an item to a module.

Post
mod.obj = modObject
	lookup was successful
mod.obj = undef
	lookup was not successful

PROCEDURE LookupPath (IN path: ARRAY OF CHAR; OUT i: Item)
Lookup an item via a whole designator, starting with a module name.

PROCEDURE GetItem (obj: ANYPTR; OUT i: Item)
Create an item out of a pointer variable.

PROCEDURE GetThisItem (IN attr: ANYREC; OUT i: Item)
Used internally in extension hooks (creates an item out of a record variable). Use Lookup, LookupPath, or GetItem instead.

PROCEDURE InstallFilter (filter: LookupFilter)
Install an extension hook.