Difference between revisions of "Functions within structures"
Thalhammer (talk | contribs) |
|||
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: | ||
− | < | + | <pre>variable acar = struct { |
plate = "GX 304-1", | plate = "GX 304-1", | ||
place = "Bamberg" | place = "Bamberg" | ||
− | };</ | + | };</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: | ||
− | < | + | <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; | ||
− | }</ | + | }</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 | ||
− | </ | + | </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: | ||
− | < | + | <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 | ||
− | };</ | + | };</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 | ||
− | < | + | <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: | ||
− | < | + | <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" | ||
− | </ | + | </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!): | ||
− | < | + | <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"); | ||
− | </ | + | </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");