Difference between revisions of "Functions within structures"

From Remeis-Wiki
Jump to navigation Jump to search
 
Line 4: Line 4:
  
 
Fields within a structure can hold any type of a variable. In particular, if a field is a reference to a function, this function can be used to operate on the host structure. Imagine a structure defining a car with its plate and a current place:
 
Fields within a structure can hold any type of a variable. In particular, if a field is a reference to a function, this function can be used to operate on the host structure. Imagine a structure defining a car with its plate and a current place:
<code>variable acar = struct {
+
<pre>variable acar = struct {
 
   plate = "GX 304-1",
 
   plate = "GX 304-1",
 
   place = "Bamberg"
 
   place = "Bamberg"
};</code>
+
};</pre>
 
The following function takes a given car structure and sets the place to a new one:
 
The following function takes a given car structure and sets the place to a new one:
<code>define drive_car(car, dest) {
+
<pre>define drive_car(car, dest) {
 
   vmessage("%s drives from %s to %s", car.plate, car.place, dest);
 
   vmessage("%s drives from %s to %s", car.plate, car.place, dest);
 
   car.place = dest;
 
   car.place = dest;
}</code><code>
+
}</pre><pre>
 
slsh> drive_car(acar, "Erlangen");
 
slsh> drive_car(acar, "Erlangen");
 
GX 304-1 drives from Bamberg to Erlangen
 
GX 304-1 drives from Bamberg to Erlangen
</code>
+
</pre>
\\
+
 
 +
 
 
It would be much easier, if the car-structure contains a drive-function itself. This is done by a field pointing to the previously defined function:
 
It would be much easier, if the car-structure contains a drive-function itself. This is done by a field pointing to the previously defined function:
<code>variable acar = struct {
+
<pre>variable acar = struct {
 
   plate = "GX 304-1",
 
   plate = "GX 304-1",
 
   place = "Bamberg",
 
   place = "Bamberg",
 
   drive = &drive_car  % <-- this value is a reference (Ref_Type) to the function drive_car
 
   drive = &drive_car  % <-- this value is a reference (Ref_Type) to the function drive_car
};</code>
+
};</pre>
 
If the function is now called directly via the structure's field
 
If the function is now called directly via the structure's field
<code>acar.drive("Erlangen");</code>
+
<pre>acar.drive("Erlangen");</pre>
 
the structure is automatically passed as first argument to the defined function.
 
the structure is automatically passed as first argument to the defined function.
  
\\
+
 
 
'''Technical details about how this works'''
 
'''Technical details about how this works'''
  
Line 35: Line 36:
  
 
Summarized:
 
Summarized:
<code>car.drive("Erlangen");
+
<pre>car.drive("Erlangen");
 
   --> S-Lang pushes the structure "car" onto the stack
 
   --> S-Lang pushes the structure "car" onto the stack
 
   --> S-Lang pushes the string "Erlangen" onto the stack
 
   --> S-Lang pushes the string "Erlangen" onto the stack
Line 41: Line 42:
 
   --> drive_car pulls the string "Erlangen" from the stack and assignes it to "dest"
 
   --> drive_car pulls the string "Erlangen" from the stack and assignes it to "dest"
 
   --> drive_car pulls the structure "car" from the stack and assignes it to "car"
 
   --> drive_car pulls the structure "car" from the stack and assignes it to "car"
</code>
+
</pre>
  
 
<del>But '''be aware''', that the _NARGS variable holding the passed number of arguments does not count the structure on the stack! In the above example, _NARGS = 1</del>
 
<del>But '''be aware''', that the _NARGS variable holding the passed number of arguments does not count the structure on the stack! In the above example, _NARGS = 1</del>
  
 
This statement is not true any more, see example below (We do not now what has changed!):
 
This statement is not true any more, see example below (We do not now what has changed!):
<code>
+
<pre>
 
private define vsm_fkt(){
 
private define vsm_fkt(){
  
Line 74: Line 75:
 
v.fkt("A");
 
v.fkt("A");
 
v.fkt("B","C");
 
v.fkt("B","C");
</code>
+
</pre>
  
 
[[Category:Isis / Slang]]
 
[[Category:Isis / Slang]]

Latest revision as of 14:15, 24 May 2018

functions within structures

Please note: this tutorial is a modified copy of the object-oriented programming part of the slxfig tutorial.

Fields within a structure can hold any type of a variable. In particular, if a field is a reference to a function, this function can be used to operate on the host structure. Imagine a structure defining a car with its plate and a current place:

variable acar = struct {
  plate = "GX 304-1",
  place = "Bamberg"
};

The following function takes a given car structure and sets the place to a new one:

define drive_car(car, dest) {
  vmessage("%s drives from %s to %s", car.plate, car.place, dest);
  car.place = dest;
}

slsh> drive_car(acar, "Erlangen"); GX 304-1 drives from Bamberg to Erlangen


It would be much easier, if the car-structure contains a drive-function itself. This is done by a field pointing to the previously defined function:

variable acar = struct {
  plate = "GX 304-1",
  place = "Bamberg",
  drive = &drive_car  % <-- this value is a reference (Ref_Type) to the function drive_car
};

If the function is now called directly via the structure's field

acar.drive("Erlangen");

the structure is automatically passed as first argument to the defined function.


Technical details about how this works

If a field of a structure, which is a reference to a function, is accessed, the structure itself is pushed onto the stack first. Right after that, the parameters given to the function are pushed onto the stack also. To get the passed parameters and the structure within the function, the objects have to be pulled from the stack. This can be done, e.g., by simply defining the functions parameter accordingly as done above: define drive_car(car, dest) This pulls the given parameter "dest" from the stack first (because it is pushed onto it last) and at least pulls the structure from the stack into the variable "car".

Summarized:

car.drive("Erlangen");
  --> S-Lang pushes the structure "car" onto the stack
  --> S-Lang pushes the string "Erlangen" onto the stack
  --> S-Lang calls drive_car
  --> drive_car pulls the string "Erlangen" from the stack and assignes it to "dest"
  --> drive_car pulls the structure "car" from the stack and assignes it to "car"

But be aware, that the _NARGS variable holding the passed number of arguments does not count the structure on the stack! In the above example, _NARGS = 1

This statement is not true any more, see example below (We do not now what has changed!):

private define vsm_fkt(){

  vmessage("_NARGS = %d",_NARGS);
  _print_stack();
  variable vsm, arg1, arg2;

  switch(_NARGS)
  { case 2: (vsm,arg1) = ();
    set_struct_field( vsm, "field1", arg1 );
  }
  { case 3: (vsm,arg1,arg2)=();
    set_struct_field( vsm, "field1", arg1 );
    set_struct_field( vsm, "field2", arg2 );
  }
}

define vsm_init(){
  return struct{
    field1 = 1,
    field2 = 2,
    fkt    = &vsm_fkt
  };
}

variable v = vsm_init();
v.fkt("A");
v.fkt("B","C");