home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / lang / pascal / 7614 < prev    next >
Encoding:
Text File  |  1992-12-22  |  2.4 KB  |  81 lines

  1. Newsgroups: comp.lang.pascal
  2. Path: sparky!uunet!cs.utexas.edu!torn!news.ccs.queensu.ca!slip203.telnet1.QueensU.CA!dmurdoch
  3. From: dmurdoch@mast.queensu.ca (Duncan Murdoch)
  4. Subject: Re: Calling Local Procedures - Problems
  5. Message-ID: <dmurdoch.241.724993410@mast.queensu.ca>
  6. Lines: 69
  7. Sender: news@knot.ccs.queensu.ca (Netnews control)
  8. Organization: Queen's University
  9. References: <1992Dec21.233611.1711@mp.cs.niu.edu> <1992Dec21.235322.21824@mp.cs.niu.edu>
  10. Date: Tue, 22 Dec 1992 03:03:31 GMT
  11.  
  12. In TP, the only difference between a local procedure and a regular 
  13. procedure is that the local procedure has a hidden word-sized parameter 
  14. giving the stack frame base (BP) of the enclosing procedure.  It's 
  15. possible to fake this, but a little tricky because typecasting doesn't 
  16. work on procedural types.  Here's some sample code:
  17.  
  18. type
  19.   TVector = array[1..100] of real;    { This is a sample declaration }
  20.  
  21.   TLocalProc = procedure(var v:real;frame:word);
  22.   { This is the declaration for a local procedure that has declaration 
  23.     procedure(var v:real); far;
  24.   }
  25.  
  26. function CallerFrame: Word;
  27. { Returns the BP value of the caller's stack frame; used for passing
  28.   local procedures and functions around. Taken from Borland's Outline
  29.   unit. }
  30. inline(
  31.   $8B/$46/$00           { MOV   AX,[BP] }
  32.   );
  33.  
  34. Procedure VForEach(proc:pointer;x:TVector);
  35. { Calls a local far procedure Proc once for each element of x, like
  36.   the TCollection.ForEach procedure.  The declaration for proc must
  37.   be
  38.      procedure Proc(var v:real); far;
  39.   if it's a local procedure, or
  40.      procedure Proc(var v:real;dummy:word); far;
  41.   if it's a global procedure.  If the value of v is modified, the
  42.   corresponding element of x will be updated.
  43. }
  44. var
  45.   doit : TLocalProc absolute proc;
  46.   i : integer;
  47. begin
  48.   for i:=1 to 100 do
  49.     doit(x[i], CallerFrame);
  50. end;
  51.  
  52. { Here's sample code to use VForEach: }
  53.  
  54. procedure ShiftAllElements(var x:TVector; shift:real);
  55.  
  56.   procedure ShiftOne(var v:real); far;
  57.   begin
  58.     v := v + shift;
  59.   end;
  60.  
  61. begin
  62.   VForEach(@ShiftOne, x);
  63. end;
  64.  
  65. var
  66.   x : TVector;
  67.   i : integer;
  68. begin
  69.   for i:=1 to 100 do
  70.     x[i] := i;             { initialize x to 1..100 }
  71.   ShiftAllElements(x, 4);  { Add 4 to all elements }
  72. end.
  73.  
  74. I haven't tested this code, so it may contain typos, but it's based on 
  75. tested code from my vectors unit.  I've simplified it; in the real 
  76. unit the vectors are objects that can be of any size that'll fit in memory 
  77. or on disk, not just 100 elements. 
  78.  
  79. Duncan Murdoch
  80. dmurdoch@mast.queensu.ca
  81.