Wiki

Clone wiki

MindStream / Articles in English / Script engine organisation / How the “word” is organised

Caching. How the “word” is organised.

The previous series was here.

The terms of the “word”, “variable” and “constant” were introduced there and we learned to use them.

Now, we will talk about “what actually the word is”.

The “word” or the “element of the dictionary” is a “record in the dictionary” which is given as the “key/value”.

I.e. the word:

#!delphi
: A
 ACode
; // A

will be represented in the dictionary as a pair:

( A ACode )

where: A is the name of the word. ACode is the code of the word.

Put it more exactly, it will be represented as a set of three:

( : A ACode )

where: : is the stereotype of the word. A is the name of the word. ACode is the code of the word.

What is the stereotype of the word?

This is kind of a “category” the “word” belongs to.

The stereotype can determine different limitations for work with the word.

These can be, for example: - "constants" can calculate values only, or - "variables" can both return values and store them, or - "words" can calculate values as well as store nested elements.

Stereotypes also specify the sets of operations applicable for the element of the dictionary (it will be discussed further).

Let’s demonstrate the use of stereotypes with the example:

#!delphi
: A
 ACode
; // A

VAR B

CONST C 1

This example will look in the dictionary as follows:

#!delphi
 ( : A ACode )
 ( VAR B {BValue} )
 ( CONST C 1 )
and this example:
#!delphi
: A
 ACode
; // A

VAR B

CONST C 1
CONST D C
will look in the dictionary as follows:

( : A ACode ) ( VAR B {BValue} ) ( CONST C 1 ) ( CONST D ref C )

Note that the element D is not represented with the value "1" but refers to the element C - "ref C".

This is to be discussed further.

So, how the nested words are represented in the dictionary?

At this point, it appears that the words are represented not even in a set of three, but of four: ( Stereotype Word_Name Word_Code Nested_Dictionary ).

Let us demonstrate it with an example.

The following code:

#!delphi
: A
 VAR X
 ACode
; // A
is represented as:

( : A ACode Dict( VAR X {XValue} ) )

where Dict( ... ) is the internal dictionary of the word A.

And the following example:

#!delphi
: A
 VAR X
 ACode
; // A

VAR B

CONST C 1
CONST D C
is represented in the dictionary as follows:

( : A ACode Dict( VAR X {XValue} ) ) ( VAR B {BValue} Dict( ) ) ( CONST C 1 Dict( ) ) ( CONST D ref C Dict( ) )

Thus, the obvious question that arises is: "as the dictionary is the key/value, then can we get access to the nested elements of the word?"

The answer is: yes, since we have the overall code reflection.

How can we do it?

Three wonderful words of axiomatics can be used:

  • @ gets the address of the word.
  • DO executes the words by the address (reversed @).
  • %% gets by the word address the nested word by the name .

Look how the word %% is defined:

#!delphi
OBJECT operator %%
 OBJECT IN aWord
 ^ IN aName

 OBJECT VAR l_Member
 aName DO aWord pop:Word:FindMember >>> l_Member

 if ( l_Member pop:object:IsNil ) then
  ( Result := nil )
 else
  ( Result := ( l_Member pop:KeyWord:Word ) )
; // %%
As we can see, it takes two parameters - aWord and aName.

  • aWord is the word for which the nested element is sought.
  • aName is the name of the nested element.

It also returns the value like OBJECT which is the address of the nested element or nil if such element is not found.

Let us give the example of use:

#!delphi
: A
 : X
  2
 ; // X
 1
; // A

@ A // takes the address of the word A
%% // is the operation %%
'X' // is the name of the sought word X
DO // executes the found word
Print // prints the value
What do we get?

The integer value “2” is printed in the console and it returns the word X.

What do we do if there is no nested word?

In this case, we need to check the returned value for nil.

The example:

#!delphi
: A
 : X
  2
 ; // X
 1
; // A

VAR l_ElementAddr // the variable to store the address of the element 

@ A %% 'X' >>> l_ElementAddr // returns the address of the word X
if NOT ( l_ElementAddr IsNil ) then
// we check it 
begin
 l_ElementAddr DO // prints 2
end

@ A %% 'Y' >>> l_ElementAddr // returns the address of the word Y
if NOT ( l_ElementAddr IsNil ) then
// checks the address
begin
 l_ElementAddr DO // prints nothing 
                  //  for we do not get there
                  //  since the element A has no element Y
end
Can we do without @ and DO?

Yes, we can.

We have the word :: for it.

It is defined in this way:

#!delphi
^@ operator ::
 ^@ IN aSelf
 ^L IN aName

 OBJECT VAR l_Self
 aSelf |^@ >>> l_Self

 STRING VAR l_Name
 aName |N >>> l_Name

 OBJECT VAR l_Res
 l_Self %% l_Name >>> l_Res

 ASSURE
  NOT ( l_Res pop:object:IsNil )
  [ Field not found: ' l_Self LIST %P Reverted ==> ( |N '::' ) l_Self |N '::' l_Name ]
 l_Res >>> Result
; // ::
The example of use:
#!delphi
: A
 : X
  2
 ; // X
 1
; // A

A :: X Print // prints the value "2" that returns X
A :: Y Print // throws the Run-Time error "field Y not found"
Moreover, :: can be used to both read and write the values of the nested elements (if they support it).

The modifier ^@ specifies it before the operation :: is declared.

It means the reference is returned but not the value.

The example:

#!delphi
: A
 VAR X
; // A
A :: X := 2 // assigns the value “2” to the field X
A :: X Print // prints the value
Thus, the obvious question that arises is: as we can get internal elements of the words, can we add new elements?

Yes, we can.

How?

This is what my next article is about.

Updated