john@cs.utexas.edu (John Baima) (07/06/89)
Turbo Pascal does (as of version 5.0) allow Procedures as parameters. They have implemented a Procedure type which I believe goes beyond "stansard" pascal. With the @ operator in version 4.0, it was easy to pass procedures as parameters anyway. One of the advantages of Borland's nonstandard Read/Write vs. Get/Put is the ability to read or write any enumerated type. This is most useful when one or more variables in a record are enumerated types. As I remember "standard" Pascal in my distant past, one had to convert an enumerated type to an ordinal type (often a byte or integer) and then get/put that. That limitation is a real bother when using records. John Baima d024jkb@utarlg bitnet texbell!utarlg!john uucp
dat0@rimfaxe.diku.dk (Dat-0 undervisningsassistent) (07/06/89)
texbell!utafll!john@cs.utexas.edu (John Baima) writes: >Turbo Pascal does (as of version 5.0) allow Procedures as parameters. >They have implemented a Procedure type which I believe goes beyond >"stansard" pascal. With the @ operator in version 4.0, it was easy to >pass procedures as parameters anyway. Right, you can do it, but you still can't do it the standard way. ("Oh there he goes again"). Can anyone tell me, why it wasn't implemented in such a way as to let standard programs compile without any trouble. It can't be that hard to do. >One of the advantages of Borland's nonstandard Read/Write vs. Get/Put >is the ability to read or write any enumerated type. This is most >useful when one or more variables in a record are enumerated types. As >I remember "standard" Pascal in my distant past, one had to convert >an enumerated type to an ordinal type (often a byte or integer) and >then get/put that. That limitation is a real bother when using >records. This on the other hand is not correct unless you are trying to write record on text file. Kristian Damm Jensen (dat0@diku.dk) Institute of datalogi, University of Copenhagen (DIKU) Universitetsparken 1, DK-2100 Copenhagen \, Denmark Kristian Damm Jensen (dat0@diku.dk) Institute of datalogi, University of Copenhagen (DIKU)
woody@aurora.uucp (Wayne Wood) (07/07/89)
In article <4822@freja.diku.dk> dat0@rimfaxe.diku.dk (Dat-0 undervisningsassistent) writes: >texbell!utafll!john@cs.utexas.edu (John Baima) writes: > >>Turbo Pascal does (as of version 5.0) allow Procedures as parameters. >>They have implemented a Procedure type which I believe goes beyond >>"stansard" pascal. With the @ operator in version 4.0, it was easy to >>pass procedures as parameters anyway. > >Right, you can do it, but you still can't do it the standard way. ("Oh there >he goes again"). Can anyone tell me, why it wasn't implemented in such a >way as to let standard programs compile without any trouble. >It can't be that hard to do. > i've been using Turbo since version 3.0 [still not very long] and i have always been able to pass procedures and functions as parameters to other procedures/functions. and i learned to do it in UCSD PASCAL, it worked the same for me in both languages. refer to OH! PASCAL [author name escapes me] for more information. -- woody %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% ...tongue tied and twisted, just an earthbound misfit, I... %% %% -- David Gilmour, Pink Floyd %% %% woody@aurora.arc.nasa.gov %% my opinions,like my mind,are my own %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
abcscnuk@csuna.csun.edu (Naoto Kimura) (07/10/89)
In article <4249@eos.UUCP> woody@aurora.UUCP (Wayne Wood) writes: >In article <4822@freja.diku.dk> dat0@rimfaxe.diku.dk (Dat-0 undervisningsassistent) writes: >>texbell!utafll!john@cs.utexas.edu (John Baima) writes: >> >>>Turbo Pascal does (as of version 5.0) allow Procedures as parameters. >>>They have implemented a Procedure type which I believe goes beyond >>>"stansard" pascal. With the @ operator in version 4.0, it was easy to >>>pass procedures as parameters anyway. >> >>Right, you can do it, but you still can't do it the standard way. ("Oh there >>he goes again"). Can anyone tell me, why it wasn't implemented in such a >>way as to let standard programs compile without any trouble. >>It can't be that hard to do. >> > >i've been using Turbo since version 3.0 [still not very long] and i have always >been able to pass procedures and functions as parameters to other >procedures/functions. and i learned to do it in UCSD PASCAL, it worked the >same for me in both languages. > >refer to OH! PASCAL [author name escapes me] for more information. > >-- woody >%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% >%% ...tongue tied and twisted, just an earthbound misfit, I... %% >%% -- David Gilmour, Pink Floyd %% >%% woody@aurora.arc.nasa.gov %% my opinions,like my mind,are my own %% >%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The question was not whether you can or cannot, it was that you can't do it in the standard method. BTW, for those who might be making the mistake that several people had made a couple of years back (when this same discussion came about in this newsgroup the last time), what is meant by procedural and functional parameters, it does not mean passing the value returned by a function to a procedure or function. In other words, It's not something like: y := sin(deg2rad(x)); which is passing the value returned by deg2rad() to sin(). An assembly language equivalent of the above would go something like this: mov ax,[word x+4] push ax mov ax,[word x+2] push ax mov ax,[word x] push ax call deg2rad ; evaluate deg2rad(x) push dx push bx push ax call sin ; send return value off to sin(x) mov [word y],dx ; store value into 'y' mov [word y+2],bx mov [word y+4],ax Passing a procedure or function to another procedure or function means basically at the low level, the address of the procedure or function being passed is passed to the called procedure or function. The called procedure then uses the address to perform an indirect call to the passed procedure or function: PROC comparison ARG Key1:DWORD,Key2:DWORD ... ... ret ENDP PROC sort ARG list:DWORD,compare:DWORD LOCAL Temp1:DWORD,Temp2:DWORD ... ; see if we need to swap records mov ax,[Temp1] push ax mov ax,[Temp2] push ax call far [compare] jnc NoSwap ; swap records ... NoSwap: ... ... ret ENDP PROC caller ... push ds mov ax,List push ax push cs mov ax,ptr comparison push ax call sort ... ret ENDP To get back to the discussion, Turbo pascal will not compile the following (the standard method of passing procedural and functional parameters): program bleah(output); procedure ugh( argh : integer ); begin writeln('ugh: passed parameter = ',argh) end; procedure plbbt( yuck : integer ); begin writeln('plbbt: passed parameter = ',yuck) end; procedure oof( procedure foo ( bar : integer ); ick : integer ); begin writeln('oof: calling passed procedure'); foo(ick) end; begin oof(ugh,3); oof(plbbt,5) end. To do the above in Turbo pascal, you have to resort to using inline machine code (some of the code may be incorrect -- I haven't used version 3.0 for a while...). You can continue to do the same sort of thing in versions 4.0 and 5.0, except that with those versions you have to worry about far references. Unfortunately, there was no checking to see if the function or procedure that was passed had the correct number and types of parameters. program bleah(output); {for each kind of procedure or function you want to pass as a parameter, you'll need to build a similar procedure or function} procedure indirect ( parm : integer; proc : integer ); { ^^^^^^^^^^^^^^^ parameters to be passed should come before the address of procedure to be called, this makes calling the procedure easier } begin inline( {I don't have it available with me right now, but it went something like the following (in assembly)} {mov sp,bp ; get rid of local variables} {pop bp ; restore bp} {pop ax ; grab return address} {pop bx ; grab address to routine} {push ax ; put return address back on stack} {jmp near [bx] ; jump to routine -- let it handle stack cleanup} ) end; procedure ugh( argh : integer ); begin writeln('ugh: passed parameter = ',argh) end; procedure plbbt( yuck : integer ); begin writeln('plbbt: passed parameter = ',yuck) end; procedure illegal; begin writeln('this should screw up the stack !') end; procedure oof( foo : integer; ick : integer ); begin writeln('oof: calling passed procedure'); indirect(ick,foo) end; begin oof(addr(ugh),3); oof(addr(plbbt),5); (* The following should cause some problems with the stack *) (* since calling the 'indirect' procedure will cause an *) (* integer parameter to be passed on the stack, which is *) (* expected to be cleaned up by the procedure it jumps to. *) (* But 'illegal' will not, so it ends up leaving an extra *) (* word on the stack. This would cause procedure 'oof' to *) (* use that value as the return address when it performs a *) (* 'ret' instruction *) oof(addr(illegal),0) end. Version 5.0 introduced the ability to pass procedures and functions as parameters without having to resort to inline code, though in a non-standard way. program bleah(output); type procparm = procedure ( iarg : integer ); procedure ugh( argh : integer ); begin writeln('ugh: passed parameter = ',argh) end; procedure plbbt( yuck : integer ); begin writeln('plbbt: passed parameter = ',yuck) end; procedure oof( foo : procparm; ick : integer ); begin writeln('oof: calling passed procedure'); foo(ick) end; begin oof(ugh,3); oof(plbbt,5) end. //-n-\\ Naoto Kimura _____---=======---_____ (abcscnuk@csuna.csun.edu) ====____\ /.. ..\ /____==== // ---\__O__/--- \\ Enterprise... Surrender or we'll \_\ /_/ send back your *&^$% tribbles !!
milne@ics.uci.edu (Alastair Milne) (07/12/89)
abcscnuk@csuna.csun.edu (Naoto Kimura) writes: > program bleah(output); .... > procedure oof( procedure foo ( bar : integer ); ick : integer ); > begin > writeln('oof: calling passed procedure'); > foo(ick) > end; ... This is the way UCSD Pascal does it (though not, I believe, in versions previous to IV.0) I was sure there was nothing like this in Turbo Pascal. Thanks for clearing it up. BTW, how is scoping defined for procedures passed by the method you describe for Turbo 5.0? Alastair Milne
jds@mimsy.UUCP (James da Silva) (07/12/89)
In article <19440@paris.ics.uci.edu> milne@ics.uci.edu (Alastair Milne) writes: > BTW, how is scoping defined for procedures passed by the method you > describe for Turbo 5.0? Alastair, The scoping is static as usual. Since procedure values cannot be returned, the implementation is straightforward. The procedure parameter consists of a code pointer AND an `environment pointer'. The environment pointer points to the frame of the static parent of the procedure parameter. If you could return local procedures, things would get much more complicated. Jaime ........................................................................... : domain: jds@mimsy.umd.edu James da Silva : path: uunet!mimsy!jds
schwartz@shire.cs.psu.edu (Scott Schwartz) (07/12/89)
In article <2075@csuna.csun.edu> abcscnuk@csuna.csun.edu (Naoto Kimura) writes: [ Correctly diagnoses TP's problems with procedure parameters ] |Passing a procedure or function to another procedure or function means |basically at the low level, the address of the procedure or function being |passed is passed to the called procedure or function. The called procedure |then uses the address to perform an indirect call to the passed procedure |or function: This is not quite the whole story. In addition to the address of the function to be called, you need to pass the context of that function (the static link). For this reason, if no other, passing just addr(func) won't do the job properly. Even if you didn't screw up the stack, you'd be unable to correctly access func's global variables. On a slightly differen subject, handling procedure parameters correctly is the hardest part of translating Pascal to C mechanically. The most common tactic is to just punt. (Per Bergsten's otherwise excellent translator punts, for example.) -- Scott Schwartz <schwartz@shire.cs.psu.edu>
stephen@ziebmef.uucp (Stephen M. Dunn) (07/18/89)
In article <4822@freja.diku.dk> dat0@rimfaxe.diku.dk (Dat-0 undervisningsassistent) writes: >refer to OH! PASCAL [author name escapes me] for more information. Oh! Pascal is by Doug Cooper and Michael Clancy. -- ------------------------------------------------------------------------------- ! Stephen M. Dunn stephen@ziebmef.UUCP ! DISCLAIMER: Who'd ever ! ! My puppy died late last fall ! claim such dumb ideas? ! ! He's still rotting in the hall (O.E.) ! I sure as heck wouldn't !