From e9ccab5308d2b6fec79e36c355c03aad4e1e5dec Mon Sep 17 00:00:00 2001
From: Hans Hagen <pragma@wxs.nl>
Date: Sun, 4 Jun 2023 19:46:50 +0200
Subject: 2023-06-04 16:40:00

---
 .../general/manuals/lowlevel/lowlevel-macros.tex   | 51 ++++++++++++++++++++++
 1 file changed, 51 insertions(+)

(limited to 'doc/context/sources/general/manuals/lowlevel/lowlevel-macros.tex')

diff --git a/doc/context/sources/general/manuals/lowlevel/lowlevel-macros.tex b/doc/context/sources/general/manuals/lowlevel/lowlevel-macros.tex
index 83e43818f..cbb52f25c 100644
--- a/doc/context/sources/general/manuals/lowlevel/lowlevel-macros.tex
+++ b/doc/context/sources/general/manuals/lowlevel/lowlevel-macros.tex
@@ -991,6 +991,57 @@ in turn only needs incrementing a reference counter.
 
 \stopsectionlevel
 
+\startsectionlevel[title=Passing parameters]
+
+When you define a macro, the \type {#1} and more parameters are embedded as a
+reference to a parameter that is passed. When we have four parameters, the
+parameter stack has four entries and when an entry is eventually accessed a new
+input level is pushed and tokens are fetched from that list. This has some side
+effects when we check a parameter. This can happen multiple times, depending on
+how often we access a parameter. Take the following:
+
+\startbuffer
+\def\oof#1{#1}
+
+\tolerant\def\foo[#1]#*[#2]%
+  {1:\ifparameter#1\or Y\else N\fi\quad
+   2:\ifparameter#2\or Y\else N\fi\quad
+   \oof{3:\ifparameter #1\or Y\else N\fi\quad
+        4:\ifparameter #2\or Y\else N\fi\quad}%
+   \par}
+
+\foo \foo[] \foo[][] \foo[A] \foo[A][B]
+\stopbuffer
+
+\typebuffer
+
+This gives:
+
+\startpacked \tttf
+\inlinebuffer
+\stoppacked
+
+as you probably expect. However the first two checks
+are different from the embedded checks because they can check against the
+parameter reference. When we expand \type {\oof} its argument gets passed to the
+macro as a list and when the scanner collects the next token it will then push
+the parameter content on the input stack. So, then, instead of a reference we get
+the referenced parameter list. Internally that means that in 3 and 4 we check for
+a token and not for the length of the list (as in case 1 & 2). This means that
+
+\starttyping
+\iftok{#1}\emptytoks Y\else N\fi
+\ifparameter#1\or    Y\else N\fi
+\stoptyping
+
+are different. In the first case we have a proper token list and nested
+conditionals in that list are okay. In the second case we just look ahead to see
+if there is an \type {\or}, \type {\else} or other condition related command and
+if so we decide that there is no parameter. So, if \type {\ifparameter} is a
+suitable check for empty depends on the need for expansion.
+
+\stopsectionlevel
+
 \stopdocument
 
 % freezing pitfalls:
-- 
cgit v1.2.3

