home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.lang.pascal
- Path: sparky!uunet!utcsri!torn!news.ccs.queensu.ca!mast.queensu.ca!dmurdoch
- From: dmurdoch@mast.queensu.ca (Duncan Murdoch)
- Subject: Passing local procedures
- Message-ID: <dmurdoch.77.715018832@mast.queensu.ca>
- Lines: 79
- Sender: news@knot.ccs.queensu.ca (Netnews control)
- Organization: Queen's University
- Date: Fri, 28 Aug 1992 16:20:32 GMT
-
- In TP, it's possible to have procedure parameters with declarations like
-
- type
- Tproc = procedure(arg1:integer);
-
- var
- proc : Tproc;
-
- and then any far procedure with a declaration that looks like the one for
- Tproc can be assigned to the proc variable. However, it doesn't work with
- local procedures, or with object methods, because those both have hidden
- parameters being passed.
-
- I've just worked out what's necessary to do this with local procedures, and
- figured I'd post it in case someone else is interested. It would be nice if
- the language supported this more directly; I've sent a note to Borland
- suggesting it.
-
- This is how it works: A local procedure is actually called with one extra
- parameter after all the others, which is the BP value of the caller. To
- call one of these indirectly, just make the procedural type declaration
- include one more parameter than the procedure, and put the correct BP value
- there when you call it. As far as I've seen, you can't typecast a local
- procedure into this procedural type, so it's necessary to pass the address
- of the local procedure as an untyped parameter. This is where language
- support would help a lot: it's easy to get the declaration wrong, and the
- compiler won't tell you.
-
- Here's an example, and a little assembler function to retrieve the
- appropriate BP value.
-
- function context(n:word):word; assembler;
- { Returns the BP value n stack frames back }
- asm
- push bp
- mov cx,n
- inc cx
- @1:
- mov bp,[bp]
- loop @1
- mov ax,bp
- pop bp
- end;
-
- type
- localproc = procedure(j,k:integer;context:word);
- { This is the declaration for a local procedure declared as:
- procedure myproc(j,k:integer); }
-
- { This is a sample caller for that type of localproc }
-
- procedure Callit(p:pointer;j,k:integer);
- var
- proc : LocalProc absolute p;
- begin
- proc(j,k,context(1)); { The "1" here denotes the stack frame of
- whatever procedure called Callit }
- end;
-
- { Here's how to use the above: }
-
- procedure outer;
-
- var
- i : integer;
-
- procedure inner(j,k:integer); far;
- begin
- i := j+k; { note the access to the variable i in the outer frame }
- end;
-
- begin
- callit(@inner,3,4); { This will set i to 7 }
- writeln('i is now ',i);
- end;
-
- begin
- outer;
- end.
-