ralphm@elaine19.stanford.edu (Ralph Melton) (11/23/90)
I am using Think Pascal 3.01, and I really want to be able to declare procedural variables. I am writing a code resource for that calls one procedure from another procedure many, many times. However, the behavior of this procedure depends on whether Color Quickdraw is available. Currently, this looks like this: {A1 is the procedure executed with ColorQD; A2 is the one executed without ColorQD} Procedure A; begin if Color_QuickDraw_Is_Available then do A1 else do A2 end; Procedure B; begin {lots of calls to procedure A} end; I would like to avoid repeating the check for Color Quickdraw by writing something like this: Procedure B; var A : procedure; begin if Color_QuickDraw_is_available then A := A1 else A := A2; {lots of calls to procedure A, which is the correct one of the subprocedures} end I believe that it is possible to do such things in C, and I know about procedural parameters in Pascal. I also know that I can pass some Toolbox routines the address of a procedure. Is there any way to do what I want within THINK Pascal? Ralph -- Ralph Melton The White Rabbit ralphm@portia.stanford.edu "When you hear of a storybook romance, you don't think of the storybook as being _Alice in Wonderland_ . . ."
aries@rhi.hi.is (Reynir Hugason) (11/26/90)
As far as I can remember MPW (and Think) only have procedural parameters, i.e. you can only pass a procedure (or a function) to another procedure. No tricky procedural variables. The way it works: PROCEDURE MainWork(PROCEDURE WhoYouGonnaCall(param1: INTEGER; ...)); BEGIN { Do some stuff here } WhoYouGonnaCall(passParam1, ...); { Do more stuff here } END; PROCEDURE DrawingWithColorQD(param1: INTEGER; ...); BEGIN { what-ever } END; PROCEDURE DrawingWithVanillaQD(param1: INTEGER; ...); BEGIN { do something else } END; BEGIN IF (hasCQD) THEN MainWork(DrawingWithColorQD) ELSE MainWork(DrawingWithVanillaQD); END. --- Well that's it basically ... don't see why you don't write a couple classes and make you're life a lot easier ;-) --- Mimir Reynisson Software Island
lins@Apple.COM (Chuck Lins) (11/27/90)
In article <2434@krafla.rhi.hi.is> aries@rhi.hi.is (Reynir Hugason) writes: >As far as I can remember MPW (and Think) only have procedural parameters, >i.e. you can only pass a procedure (or a function) to another procedure. >No tricky procedural variables. If you want something whose syntax is similar to Pascal, you can use Modula-2 which has direct support for procedure variables (with static typing). Pascal does not support procedure variables. -- Chuck Lins | "Is this the kind of work you'd like to do?" Apple Computer, Inc. | -- Front 242 20525 Mariani Avenue | Internet: lins@apple.com Mail Stop 37-BD | AppleLink: LINS@applelink.apple.com Cupertino, CA 95014 | "Self-proclaimed Object Oberon Evangelist" The intersection of Apple's ideas and my ideas yields the empty set.
nebel@wam.umd.edu (Chris D. Nebel) (12/01/90)
In article <46833@apple.Apple.COM> lins@Apple.COM (Chuck Lins) writes: >In article <2434@krafla.rhi.hi.is> aries@rhi.hi.is (Reynir Hugason) writes: >>As far as I can remember MPW (and Think) only have procedural parameters, >>i.e. you can only pass a procedure (or a function) to another procedure. >>No tricky procedural variables. Actually, it can be done by exploiting MPW Pascal's INLINE construct. What you do is something like this: procedure OneWay(stuff: StuffType); ... procedure AnotherWay(stuff: StuffType); ... procedure DoStuff(stuff: StuffType; useProc: ProcPtr); INLINE {whatever the opcodes are for move.l (sp)+, A0; jmp (A0) } var theProc: ProcPtr; begin theProc := @OneWay; DoStuff(stuff, theProc); { does it OneWay } theProc := @AnotherWay; DoStuff(stuff, theProc); { does it AnotherWay } end. A couple of caveats here: one, OneWay, AnotherWay, &c must have the same parameters. (If you're into playing really funny games with your compiler's brain, the only real requirement is that the parameters for each procedure occupy the same amount of space on the stack.) Also, they must be globally scoped, same as procedures used for filterProcs. How it works: what the DoStuff stub is doing is to take the last parameter it was passed (the ProcPtr) and then jump to that address. Note that this won't necessarily work on any compiler other than MPW Pascal. Different compilers handle parameters in different ways. If this doesn't make any sense to you, write me and I'll try to explain further. Chris Nebel nebel@wam.umd.edu
tim@hoptoad.uucp (Tim Maroney) (12/01/90)
In article <1990Nov23.082345.12074@portia.Stanford.EDU> ralphm@elaine19.stanford.edu (Ralph Melton) writes: >I am using Think Pascal 3.01, and I really want to be able to declare >procedural variables. > >I believe that it is possible to do such things in C, and I know about >procedural parameters in Pascal. I also know that I can pass some Toolbox >routines the address of a procedure. Is there any way to do what I want >within THINK Pascal? Sure, but you need a little inline assembler. Declare the procedure variables as type ProcPtr (for internal documentation purposes). Then declare an inline routine that takes the parameters of the routine you are calling, plus an extra routine that's the ProcPtr. The inline assembler pops the routine address off the stack and jsr's to it. For example: function CallWombatNipple (operator: longint; params: Handle; routine: ProcPtr): Handle; inline $205F, $4E90; { MOVE.L (A7)+,A0; JSR (A0) } This is a way to call a routine that is declared as: function WombatNipple (operator: longint; params: Handle): Handle; -- Tim Maroney, Mac Software Consultant, sun!hoptoad!tim, tim@toad.com The fact is self-evident from the text and requires no supporting argument.