| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- program t36;
- { t36 -- every argument of a call keeps its own value.
- All three call parsers used to read the whole argument list first and emit
- the pushes afterwards:
- ParseCallArgs `p (a, b)' as a statement
- ParseCall a function call inside an expression
- IoCall write/read, one call per argument
- A computed argument (kind 2) has already been emitted and lives only in AX,
- so once the parser had moved on to the NEXT argument, AX belonged to
- whatever that argument computed and the earlier value was gone by the time
- the push loop reached it. TPSRC8 cproc/cprlp1 does it the other way round
- -- `CALL exprsave', then `CALL epushax', for each argument as it is parsed,
- and then a CALL, which is why the original cannot lose one.
- So: parse one argument, put it on the stack, parse the next. The callee
- follows the same ground truth from the other end (RESUME-TP3.md 3.11, and
- the Code Generation Internals stack frame): the LAST declared parameter is
- the one at BP+4, because the first declared is pushed first and so ends up
- farthest away.
- Every line below is derived by hand from the Pascal. The parameters are
- u, v, w in declaration order, and a=5, b=3, c=7, x=0 throughout, so each
- expected line can be written down without running anything:
- p3 (a, b, c) 5 3 7 three plain names: pins the three
- slots against either half of the
- convention being flipped alone
- p2 (x, a + b) 0 8 computed argument LAST
- p2 (a + b, x) 8 0 computed argument FIRST: the deferred
- push printed `0 0' here
- p3 (a+b, x, c*2) 8 0 14 two computed, one named
- p2 (add2 (a+b, 4), x) 12 0 a call nested in an argument
- b2 (a > b, x > c) TRUE FALSE boolean parameters, both computed
- write add2 (c*2, a) 19 a function call parsed by ParseCall
- write (b>a, ' ', x+1) FALSE 1 IoCall, two losses at once: deferred
- until the whole list had been read,
- the first argument was pushed as the
- THIRD argument's value (`TRUE') and
- the third was pushed after the earlier
- arguments' runtime calls had already
- had AX (`544' instead of 1)
- READ is not here on purpose: it refuses anything but a plain name, a name
- emits no code while it is parsed, and there is therefore nothing to lose. }
- var
- a : integer ;
- b : integer ;
- c : integer ;
- x : integer ;
- procedure p2 (u : integer, v : integer) ;
- begin
- writeln (u, ' ', v)
- end ;
- procedure p3 (u : integer, v : integer, w : integer) ;
- begin
- writeln (u, ' ', v, ' ', w)
- end ;
- procedure b2 (u : boolean, v : boolean) ;
- begin
- writeln (u, ' ', v)
- end ;
- function add2 (u : integer, v : integer) : integer ;
- begin
- add2 := u + v
- end ;
- begin
- a := 5 ;
- b := 3 ;
- c := 7 ;
- x := 0 ;
- p3 (a, b, c) ;
- p2 (x, a + b) ;
- p2 (a + b, x) ;
- p3 (a + b, x, c * 2) ;
- p2 (add2 (a + b, 4), x) ;
- b2 (a > b, x > c) ;
- writeln (add2 (c * 2, a)) ;
- writeln (b > a, ' ', x + 1)
- end.
|