home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.pascal
- Path: sparky!uunet!cs.utexas.edu!torn!news.ccs.queensu.ca!slip203.telnet1.QueensU.CA!dmurdoch
- From: dmurdoch@mast.queensu.ca (Duncan Murdoch)
- Subject: Re: Calling Local Procedures - Problems
- Message-ID: <dmurdoch.241.724993410@mast.queensu.ca>
- Lines: 69
- Sender: news@knot.ccs.queensu.ca (Netnews control)
- Organization: Queen's University
- References: <1992Dec21.233611.1711@mp.cs.niu.edu> <1992Dec21.235322.21824@mp.cs.niu.edu>
- Date: Tue, 22 Dec 1992 03:03:31 GMT
-
- In TP, the only difference between a local procedure and a regular
- procedure is that the local procedure has a hidden word-sized parameter
- giving the stack frame base (BP) of the enclosing procedure. It's
- possible to fake this, but a little tricky because typecasting doesn't
- work on procedural types. Here's some sample code:
-
- type
- TVector = array[1..100] of real; { This is a sample declaration }
-
- TLocalProc = procedure(var v:real;frame:word);
- { This is the declaration for a local procedure that has declaration
- procedure(var v:real); far;
- }
-
- function CallerFrame: Word;
- { Returns the BP value of the caller's stack frame; used for passing
- local procedures and functions around. Taken from Borland's Outline
- unit. }
- inline(
- $8B/$46/$00 { MOV AX,[BP] }
- );
-
- Procedure VForEach(proc:pointer;x:TVector);
- { Calls a local far procedure Proc once for each element of x, like
- the TCollection.ForEach procedure. The declaration for proc must
- be
- procedure Proc(var v:real); far;
- if it's a local procedure, or
- procedure Proc(var v:real;dummy:word); far;
- if it's a global procedure. If the value of v is modified, the
- corresponding element of x will be updated.
- }
- var
- doit : TLocalProc absolute proc;
- i : integer;
- begin
- for i:=1 to 100 do
- doit(x[i], CallerFrame);
- end;
-
- { Here's sample code to use VForEach: }
-
- procedure ShiftAllElements(var x:TVector; shift:real);
-
- procedure ShiftOne(var v:real); far;
- begin
- v := v + shift;
- end;
-
- begin
- VForEach(@ShiftOne, x);
- end;
-
- var
- x : TVector;
- i : integer;
- begin
- for i:=1 to 100 do
- x[i] := i; { initialize x to 1..100 }
- ShiftAllElements(x, 4); { Add 4 to all elements }
- end.
-
- I haven't tested this code, so it may contain typos, but it's based on
- tested code from my vectors unit. I've simplified it; in the real
- unit the vectors are objects that can be of any size that'll fit in memory
- or on disk, not just 100 elements.
-
- Duncan Murdoch
- dmurdoch@mast.queensu.ca
-