summaryrefslogtreecommitdiff
path: root/doc/context/sources/general/manuals/about/about-calls.tex
blob: 83bf89aad75b662744652bbdf0a2e0250bf60ca7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
% language=uk

\startcomponent about-calls

\environment about-environment

\startchapter[title={Calling Lua}]

\startsection[title=Introduction]

One evening, on Skype, Luigi and I were pondering about the somewhat
disappointing impact of jit in \LUAJITTEX\ and one of the reasons we could come
up with is that when you invoke \LUA\ from inside \TEX\ each \type {\directlua}
gets an extensive treatment. Take the following:

\starttyping
\def\SomeValue#1%
  {\directlua{tex.print(math.sin(#1)/math.cos(2*#1))}}
\stoptyping

Each time \type {\SomeValue} is expanded, the \TEX\ parser will do the following:

\startitemize[packed]
\startitem
    It sees \type {\directlua} and will jump to the related scanner.
\stopitem
\startitem
    There it will see a \type +{+ and enter a special mode in which it starts
    collecting tokens.
\stopitem
\startitem
    In the process, it will expand control sequences that are expandable.
\stopitem
\startitem
    The scanning ends when a matching \type +}+ is seen.
\stopitem
\startitem
    The collected tokens are converted into a regular (C) string.
\stopitem
\startitem
    This string is passed to the \type {lua_load} function that compiles it into
    bytecode.
\stopitem
\startitem
    The bytecode is executed and characters that are printed to \TEX\ are
    injected into the input buffer.
\stopitem
\stopitemize

In the process, some state information is set and reset and errors are dealt
with. Although it looks like a lot of actions, this all happens very fast, so
fast actually that for regular usage you don't need to bother about it.

There are however applications where you might want to see a performance boost,
for instance when you're crunching numbers that end up in tables or graphics
while processing the document. Again, this is not that typical for jobs, but with
the availability of \LUA\ more of that kind of usage will show up. And, as we now
also have \LUAJITTEX\ its jitting capabilities could be an advantage.

Back to the example: there are two calls to functions there and apart from the
fact that they need to be resolved in the \type {math} table, they also are
executed C functions. As \LUAJIT\ optimizes known functions like this, there can
be a potential speed gain but as \type {\directlua} is parsed and loaded each
time, the jit machinery will not do that, unless the same code gets exercised
lots of time. In fact, the jit related overhead would be a waste in this one time
usage.

In the next sections we will show two variants that follow a different approach
and as a consequence can speed up a bit. But, be warned: the impact is not as
large as you might expect, and as the code might look less intuitive, the good
old \type {\directlua} command is still the advised method.

Before we move on it's important to realize that a \type {\directlua} call is
in fact a function call. Say that we have this:

\starttyping
\def\SomeValue{1.23}
\stoptyping

This becomes:

\starttyping
\directlua{tex.print(math.sin(1.23)/math.cos(2*1.23))}
\stoptyping

Which in \LUA\ is wrapped up as:

\starttyping
function()
    tex.print(math.sin(1.23)/math.cos(2*1.23))
end
\stoptyping

that gets executed. So, the code is always wrapped in a function. Being a
function it is also a closure and therefore local variables are local to this
function and are invisible at the outer level.

\stopsection

\startsection[title=Indirect \LUA]

The first variant is tagged as indirect \LUA. With indirect we mean that instead
of directly parsing, compiling and executing the code, it is done in steps. This
method is not as generic a the one discussed in the next section, but for cases
where relatively constant calls are used it is fine. Consider the next call:

\starttyping
\def\NextValue
  {\indirectlua{myfunctions.nextvalue()}}
\stoptyping

This macro does not pass values and always looks the same. Of course there can be
much more code, for instance the following is equally valid:

\starttyping
\def\MoreValues {\indirectlua{
    for i=1,100 do
        myfunctions.nextvalue(i)
    end
}}
\stoptyping

Again, there is no variable information passed from \TEX. Even the next variant
is relative constant:

\starttyping
\def\SomeValues#1{\indirectlua{
    for i=1,#1 do
        myfunctions.nextvalue(i)
    end
}}
\stoptyping

especially when this macro is called many times with the same value. So how does
\type {\indirectlua} work? Well, it's behaviour is in fact undefined! It does,
like \type {\directlua}, parse the argument and makes the string, but instead of
calling \LUA\ directly, it will pass the string to a \LUA\ function \type
{lua_call}.

\starttyping
lua.call = function(s) load(s)() end
\stoptyping

The previous definition is quite okay and in fact makes \type {\indirectlua}
behave like \type {\directlua}. This definition makes

% \ctxlua{lua.savedcall = lua.call lua.call = function(s) load(s)() end}
% \testfeatureonce{10000}{\directlua  {math.sin(1.23)}}
% \testfeatureonce{10000}{\indirectlua{math.sin(1.23)}}
% \ctxlua{lua.call = lua.savedcall}

\starttyping
\directlua  {tex.print(math.sin(1.23))}
\indirectlua{tex.print(math.sin(1.23))}
\stoptyping

equivalent calls but the second one is slightly slower, which is to be expected
due to the wrapping and indirect loading. But look at this:

\starttyping
local indirectcalls = { }

function lua.call(code)
    local fun = indirectcalls[code]
    if not fun then
        fun = load(code)
        if type(fun) ~= "function" then
            fun = function() end
        end
        indirectcalls[code] = fun
    end
    fun()
end
\stoptyping

This time the code needs about one third of the runtime. How much we gain depends
on the size of the code and its complexity, but on the average its's much faster.
Of course, during a \TEX\ job only a small part of the time is spent on this, so
the overall impact is much smaller, but it makes runtime number crunching more
feasible.

If we bring jit into the picture, the situation becomes somewhat more diffuse.
When we use \LUAJITTEX\ the whole job processed faster, also this part, but
because loading and interpreting is more optimized the impact might be less. If
you enable jit, in most cases a run is slower than normal. But as soon as you
have millions of calls to e.g.\ type {math.sin} it might make a difference.

This variant of calling \LUA\ is quite intuitive and also permits us to implement
specific solutions because the \type {lua.call} function can be defined as you
with. Of course macro package writers can decide to use this feature too, so you
need to beware of unpleasant side effects if you redefine this function.

% \testfeatureonce{100000}{\directlua  {math.sin(1.23)}}
% \testfeatureonce{100000}{\indirectlua{math.sin(1.23)}}

\stopsection

\startsection[title=Calling \LUA]

In the process we did some tests with indirect calls in \CONTEXT\ core code and
indeed some gain in speed could be noticed. However, many calls get variable
input and therefore don't qualify. Also, as a mixture of \type {\directlua} and
\type {\indirectlua} calls in the source can be confusing it only makes sense to
use this feature in real time|-|critical cases, because even in moderately
complex documents there are not that many calls anyway.

The next method uses a slightly different approach. Here we stay at the \TEX\
end, parse some basic type arguments, push them on the \LUA\ stack, and call a
predefined function. The amount of parsing \TEX\ code is not less, but especially
when we pass numbers stored in registers, no tokenization (serialization of a
number value into the input stream) and stringification (converting the tokens
back to a \LUA\ number) takes place.

\starttyping
\indirectluacall 123
    {some string}
    \scratchcounter
    {another string}
    true
    \dimexpr 10pt\relax
\relax
\stoptyping

Actually, an extension like this had been on the agenda for a while, but never
really got much priority. The first number is a reference to a function to be
called.

\starttyping
lua.calls = lua.calls or { }
lua.calls[123] = function(s1,n1,s2,b,n2)
    -- do something with
    --
    -- string  s1
    -- number  n1
    -- string  s2
    -- boolean b
    -- number  n2
end
\stoptyping

The first number to \type {indirectluacall} is mandate. It can best also be a
number that has a function associated in the \type {lua.calls} table. Following
that number and before the also mandate \type {\relax}, there can be any number
of arguments: strings, numbers and booleans.

Anything surrounded by \type {{}} becomes a string. The keywords \type {true} and
\type {false} become boolean values. Spaces are skipped and everything else is
assumed to be a number. This means that if you omit the final \type {\relax}, you
get a error message mentioning a \quote {missing number}. The normal number
parser applies, so when a dimension register is passed, it is turned into a
number. The example shows that wrapping a more verbose dimension into a \type
{\dimexpr} also works.

Performance wise, each string goes from list of tokens to temporary C string to
\LUA\ string, so that adds some overhead. A number is more efficient, especially
when you pass it using a register. The booleans are simple sequences of character
tokens so they are relatively efficient too. Because \LUA\ functions accept an
arbitrary number of arguments, you can provide as many as you like, or even less
than the function expects: it is all driven by the final \type {\relax}.

An important characteristic of this kind of call is that there is no \type {load}
involved, which means that the functions in \type {lua.calls} can be subjected to
jitting.

\stopsection

\startsection[title=Name spaces]

As with \type {\indirectlua} there is a potential clash when users mess with the
\type {lua.calls} table without taking the macro package usage into account. It not
that complex to define a variant that provides namespaces:

\starttyping
\newcount\indirectmain \indirectmain=1
\newcount\indirectuser \indirectuser=2

\indirectluacall \indirectmain
    {function 1}
    {some string}
\relax

\indirectluacall \indirectuser
    {function 1}
    {some string}
\relax
\stoptyping

A matching implementation is this:

\starttyping
lua.calls = lua.calls or { }

local main = { }

lua.calls[1] = function(name,...)
    main[name](...)
end

main["function 1"] = function(a,b,c)
    -- do something with a,b,c
end

local user = { }

lua.calls[2] = function(name,...)
    user[name](...)
end

user["function 1"] = function(a,b,c)
    -- do something with a,b,c
end
\stoptyping

Of course this is also ok:

\starttyping
\indirectluacall \indirectmain 1
    {some string}
\relax

\indirectluacall \indirectuser 1
    {some string}
\relax
\stoptyping

with:

\starttyping
main[1] = function(a,b,c)
    -- do something with a,b,c
end

user[1] = function(a,b,c)
    -- do something with a,b,c
end
\stoptyping

Normally a macro package, if it wants to expose this mechanism, will provide a
more abstract interface that hides the implementation details. In that case the
user is not supposed to touch \type {lua.calls} but this is not much different
from the limitations in redefining primitives, so users can learn to live with
this.

\stopsection

\startsection[title=Practice]

There are some limitations. For instance in \CONTEXT\ we often pass tables and
this is not implemented. Providing a special interface for that is possible but
does not really help. Often the data passed that way is far from constant, so it
can as well be parsed by \LUA\ itself, which is quite efficient. We did some
experiments with the more simple calls and the outcome is somewhat disputable. If
we replace some of the \quote {critital} calls we can gain some 3\% on a run of
for instance the \type {fonts-mkiv.pdf} manual and a bit more on the command
reference \type {cont-en.pdf}. The first manual uses lots of position tracking
(an unfortunate side effect of using a specific feature that triggers continuous
tracking) and low level font switches and many of these can benefit from the
indirect call variant. The command reference manual uses \XML\ processing and
that involves many calls to the \XML\ mapper and also does quite some string
manipulations so again there is something to gain there.

The following numbers are just an indication, as only a subset of \type
{\directlua} calls has been replaced. The 166 page font manual processes in about
9~seconds which is not bad given its complexity. The timings are on a Dell
Precision M6700 with Core i7 3840QM, 16 GB memory, a fast SSD and 64 bit Windows
8. The binaries were cross compiled mingw 32 bit by Luigi. \footnote {While
testing with several function definitions we noticed that \type {math.random} in
our binaries made jit twice as slow as normal, while for instance \type
{math.sin} was 100 times faster. As the font manual uses the random function for
rendering random punk examples it might have some negative impact. Our experience
is that binaries compiled with the ms compiler are somewhat faster but as long as
the engines that we test are compiled similarly the numbers can be compared.}

% old: 8.870 8.907 9.089        / jit: 6.948 6.966 7.009         / jiton: 7.449 7.586 7.609
% new: 8.710 8.764 8.682 | 8.64 / jit: 6.935 6.969 6.967  | 6.82 / jiton: 7.412 7.223 7.481
%
% 3% on total, 6% on lua

\starttabulate[|lT|cT|cT|cT|]
\HL
\NC          \NC \LUATEX \NC \LUAJITTEX \NC \LUAJITTEX\ + jit \NC \NR
\HL
\NC direct   \NC 8.90     \NC 6.95      \NC 7.50              \NC \NR
\NC indirect \NC 8.65     \NC 6.80      \NC 7.30              \NC \NR
\HL
\stoptabulate

So, we can gain some 3\% on such a document and given that we spend probably half
the time in \LUA, this means that these new features can make \LUA\ run more than
5\% faster which is not that bad for a couple of lines of extra code. For regular
documents we can forget about jit which confirms earlier experiments. The
commands reference has these timings:

\starttabulate[|lT|cT|cT|cT|]
\HL
\NC          \NC \LUATEX \NC \LUAJITTEX \NC \NR
\HL
\NC direct   \NC 2.55    \NC 1.90       \NC \NR
\NC indirect \NC 2.40    \NC 1.80       \NC \NR
\HL
\stoptabulate

Here the differences are larger which is due to the fact that we can indirect
most of the calls used in this processing. The document is rather simple but as
mentioned is encoded in \XML\ and the \TEX||\XML\ interface qualifies for this
kind of speedups.

As Luigi is still trying to figure out why jitting doesn't work out so well, we
also did some tests with (in itself useless) calculations. After all we need
proof. The first test was a loop with 100.000 step doing a regular \type
{\directlua}:

\starttyping
\directlua {
    local t = { }
    for i=1,10000
        do t[i] = math.sin(i/10000)
    end
}
\stoptyping

The second test is a bit optimized. When we use jit this kind of optimizations
happens automatically for known (!) functions so there is not much won.

\starttyping
\directlua {
    local sin = math.sin
    local t = { }
    for i=1,10000
        do t[i] = sin(i/10000)
    end
}
\stoptyping

We also tested this with \type {\indirectlua} and therefore defined some
functions to test the call variant:

\starttyping
lua.calls[1] = function()
    -- overhead
end

lua.calls[2] = function()
    local t = { }
    for i=1,10000 do
        t[i] = math.sin(i/10000) -- naive
    end
end

lua.calls[3] = function()
    local sin = math.sin
    local t = { }
    for i=1,10000 do
        t[i] = sin(i/10000) -- normal
    end
end
\stoptyping

These are called with:

\starttyping
\indirectluacall0\relax
\indirectluacall1\relax
\indirectluacall2\relax
\stoptyping

The overhead variant demonstrated that there was hardly any: less than 0.1 second.

\starttabulate[|lT|lT|cT|cT|cT|]
\HL
\NC                 \NC        \NC \LUATEX \NC \LUAJITTEX \NC \LUAJITTEX\ + jit \NC \NR
\HL
\NC directlua       \NC normal \NC 167     \NC 64         \NC 46                \NC \NR
\NC                 \NC local  \NC 122     \NC 57         \NC 46                \NC \NR
\NC indirectlua     \NC normal \NC 166     \NC 63         \NC 45                \NC \NR
\NC                 \NC local  \NC 121     \NC 56         \NC 45                \NC \NR
\NC indirectluacall \NC normal \NC 165     \NC 66         \NC 48                \NC \NR
\NC                 \NC local  \NC 120     \NC 60         \NC 47                \NC \NR
\HL
\stoptabulate

The results are somewhat disappoint but not that unexpected. We do see a speedup
with \LUAJITTEX\ and in this case even jitting makes sense. However in a regular
typesetting run jitting will never catch up with the costs it carries for the
overall process. The indirect call is somewhat faster than the direct call.
Possible reasons are that hashing at the \LUA\ end also costs time and the
100.000 calls from \TEX\ to \LUA\ is not that big a burden. The indirect call is
therefore also not much faster because it has some additional parsing overhead at
the \TEX\ end. That one only speeds up when we pass arguments and even then not
always the same amount. It is therefore mostly a convenience feature.

We left one aspect out and that is garbage collection. It might be that in large
runs less loading has a positive impact on collecting garbage. We also need to
keep in mind that careful application can have some real impact. Take the
following example of \CONTEXT\ code:

\startntyping
\dorecurse {1000} {

    \startsection[title=section #1]

        \startitemize[n,columns]
            \startitem test \stopitem
            \startitem test \stopitem
            \startitem test \stopitem
            \startitem test \stopitem
        \stopitemize

        \starttabulate[|l|p|]
            \NC test \NC test \NC \NR
            \NC test \NC test \NC \NR
            \NC test \NC test \NC \NR
        \stoptabulate

        test {\setfontfeature{smallcaps} abc} test
        test {\setfontfeature{smallcaps} abc} test
        test {\setfontfeature{smallcaps} abc} test
        test {\setfontfeature{smallcaps} abc} test
        test {\setfontfeature{smallcaps} abc} test
        test {\setfontfeature{smallcaps} abc} test

        \framed[align={lohi,middle}]{test}

        \startembeddedxtable
            \startxrow \startxcell x \stopxcell \startxcell x \stopxcell \stopxrow
            \startxrow \startxcell x \stopxcell \startxcell x \stopxcell \stopxrow
            \startxrow \startxcell x \stopxcell \startxcell x \stopxcell \stopxrow
            \startxrow \startxcell x \stopxcell \startxcell x \stopxcell \stopxrow
            \startxrow \startxcell x \stopxcell \startxcell x \stopxcell \stopxrow
        \stopembeddedxtable

    \stopsection

    \page

}
\stopntyping

These macros happen to use mechanism that are candidates for indirectness.
However, it doesn't happen often you you process thousands of pages with mostly
tables and smallcaps (although tabular digits are a rather valid font feature in
tables). For instance, in web services squeezing out a few tens of seconds might
make sense if there is a large queue of documents.

\starttabulate[|lT|cT|cT|cT|]
\HL
\NC          \NC \LUATEX \NC \LUAJITTEX \NC \LUAJITTEX\ + jit \NC \NR
\HL
\NC direct   \NC 19.1    \NC 15.9       \NC 15.8              \NC \NR
\NC indirect \NC 18.0    \NC 15.2       \NC 15.0              \NC \NR
\HL
\stoptabulate

Surprisingly, even jitting helps a bit here. Maybe it relates the the number of
pages and the amount of calls but we didn't investigate this. By default jitting
is off anyway. The impact of indirectness is more than in previous examples.

For this test a file was loaded that redefines some core \CONTEXT\ code. This
also has some overhead which means that numbers for the indirect case will be
somewhat better if we decide to use these mechanisms in the core code. It is
tempting to do that but it involves some work and it's always the question if a
week of experimenting and coding will ever be compensated by less. After all, in
this last test, a speed of 50 pages per second is not that bad a performance.

When looking at these numbers, keep in mind that it is still not clear if we end
up using this functionality, and when \CONTEXT\ will use it, it might be in a way
that gives better or worse timings than mentioned above. For instance, storing \LUA\
code in the format is possible, but these implementations force us to serialize
the \type {lua.calls} mechanism and initialize them after format loading. For that
reason alone, a more native solution is better.

\stopsection

\startsection[title=Exploration]

In the early days of \LUATEX\ Taco and I discussed an approach similar do
registers which means that there is some \type {\...def} command available. The
biggest challenge there is to come up with a decent way to define the arguments.
On the one hand, using a hash syntax is natural to \TEX, but using names is more
natural to \LUA. So, when we picked up that thread, solutions like this came up
in a Skype session with Taco:

\starttyping
\luadef\myfunction#1#2{ tex.print(arg[1]+arg[2]) }
\stoptyping

The \LUA\ snippet becomes a function with this body:

\starttyping
local arg = { #1, #2 } -- can be preallocated and reused
-- the body as defined at the tex end
tex.print(arg[1]+arg[2])
\stoptyping

Where \type {arg} is set each time. As we wrapped it in a function we can
also put the arguments on the stack and use:

\starttyping
\luadef\myfunction#1#2{ tex.print((select(1,...))+(select(2,...)) }
\stoptyping

Given that we can make select work this way (either or not by additional
wrapping). Anyway, both these solutions are ugly and so we need to look further.
Also, the \type {arg} variant mandates building a table. So, a natural next
iteration is:

\starttyping
\luadef\myfunction a b { tex.print(a+b) }
\stoptyping

Here it becomes already more natural:

\starttyping
local a = #1
local b = #2
-- the body as defined at the tex end
tex.print(a+b)
\stoptyping

But, as we don't want to reload the body we need to push \type {#1} into the
closure. This is a more static definition equivalent:

\starttyping
local a = select(1,...)
local b = select(2,...)
tex.print(a+b)
\stoptyping

Keep in mind that we are not talking of some template that gets filled in and
loaded, but about precompiled functions! So, a \type {#1} is not really put there
but somehow pushed into the closure (we know the stack offsets).

Yet another issue is more direct alias. Say that we define a function at the
\LUA\ end and want to access it using this kind of interface.

\starttyping
function foo(a,b)
    tex.print(a+b)
end
\stoptyping

Given that we have something:

\starttyping
\luadef \myfunctiona a b { tex.print(a+b) }
\stoptyping

We can consider:

\starttyping
\luaref \myfunctionb 2 {foo}
\stoptyping

The explicit number is debatable as it can be interesting to permit
an arbitrary number of arguments here.

\starttyping
\myfunctiona{1}{2}
\myfunctionb{1}{2}
\stoptyping

So, if we go for:

\starttyping
\luaref \myfunctionb {foo}
\stoptyping

we can use \type {\relax} as terminator:

\starttyping
\myfunctiona{1}{2}
\myfunctionb{1}{2}\relax
\stoptyping

In fact, the call method discussed in a previous section can be used here as well
as it permits less arguments as well as mixed types. Think of this:

\starttyping
\luadef \myfunctiona a b c { tex.print(a or 0 + b or 0 + c or 0) }
\luaref \myfunctionb {foo}
\stoptyping

with

\starttyping
function foo(a,b,c)
    tex.print(a or 0 + b or 0 + c or 0)
end
\stoptyping

This could be all be valid:

\starttyping
\myfunctiona{1}{2}{3]\relax
\myfunctiona{1}\relax
\myfunctionb{1}{2}\relax
\stoptyping

or (as in practice we want numbers):

\starttyping
\myfunctiona 1 \scratchcounter 3\relax
\myfunctiona 1 \relax
\myfunctionb 1 2 \relax
\stoptyping

We basicaly get optional arguments for free, as long as we deal with it properly
at the \LUA\ end. The only condition with the \type {\luadef} case is that there
can be no more than the given number of arguments, because that's how the function
body gets initialized set up. In practice this is quite okay.

% After this exploration we can move on to the final implementation and see what we
% ended up with.

\stopsection

% \startsection[title=The final implementation]
%     {\em todo}
% \stopsection

\startsection[title=The follow up]

We don't know what eventually will happen with \LUATEX. We might even (at least
in \CONTEXT) stick to the current approach because there not much to gain in
terms of speed, convenience and (most of all) beauty.

{\em Note:} In \LUATEX\ 0.79 onward \type {\indirectlua} has been implemented as
\type {\luafunction} and the \type {lua.calls} table is available as \type
{lua.get_functions_table()}. A decent token parser has been discussed at the
\CONTEXT\ 2013 conference and will show up in due time. In addition, so called
\type {latelua} nodes support function assignments and \type {user} nodes support
a field for \LUA\ values. Additional information can be associated with any nodes
using the properties subsystem.

\stopsection

\stopchapter

\stopcomponent