1if not modules then modules = { } end modules [ ' cldf-lmt ' ] = {
2 version = 1 . 001 ,
3 comment = " companion to toks-scn.mkiv " ,
4 author = " Hans Hagen, PRAGMA-ADE, Hasselt NL " ,
5 copyright = " PRAGMA ADE / ConTeXt Development Team " ,
6 license = " see context related readme files "
7}
8
9local next , load = next , load
10
11local setmetatableindex = table . setmetatableindex
12local setmetatablenewindex = table . setmetatablenewindex
13local serialize = table . serialize
14
15local random = math . random
16local randomseed = math . randomseed
17local round = math . round
18local abs = math . abs
19
20local implement = interfaces . implement
21
22local scanners = tokens . scanners
23local scanword = scanners . word
24local scanstring = scanners . string
25local scanboolean = scanners . boolean
26local scandimen = scanners . dimen
27local scanfloat = scanners . float
28local scaninteger = scanners . integer
29local scannumber = scanners . luanumber
30local scanluainteger = scanners . luainteger
31local scanluacardinal = scanners . luacardinal
32local scanluanumber = scanners . luanumber
33local scanargument = scanners . argument
34local scantoken = scanners . token
35local scancsname = scanners . csname
36
37local getindex = token . get_index
38
39local texsetdimen = tex . setdimen
40local texget = tex . get
41
42local values = tokens . values
43local none_code = values . none
44local integer_code = values . integer
45local cardinal_code = values . cardinal
46local dimension_code = values . dimension
47local skip_code = values . skip
48local boolean_code = values . boolean
49local float_code = values . float
50
51local context = context
52
53
54
55local floats = { }
56local integers = { }
57local cardinals = { }
58local numbers = { }
59
60implement {
61 name = " luafloat " ,
62 public = true ,
63 value = true ,
64 actions = function ( b )
65 local n = scanword ( )
66 if b = = " value " then
67 context ( " %.99g " , floats [ n ] or 0 )
68 else
69 floats [ n ] = scanluanumber ( true )
70
71 end
72 end ,
73}
74
75implement {
76 name = " luainteger " ,
77 public = true ,
78 value = true ,
79 actions = function ( b )
80 local n = scanword ( )
81 if b = = " value " then
82 context ( " %i " , integers [ n ] or 0 )
83 else
84 integers [ n ] = scanluainteger ( true )
85 end
86 end ,
87}
88
89implement {
90 name = " luacount " ,
91 public = true ,
92 value = true ,
93 actions = function ( b )
94 local n = scanword ( )
95 if b = = " value " then
96 return integer_code , integers [ n ] or 0
97 else
98 integers [ n ] = scaninteger ( true )
99 end
100 end ,
101}
102
103implement {
104 name = " luadimen " ,
105 public = true ,
106 value = true ,
107 actions = function ( b )
108 local n = scanword ( )
109 if b = = " value " then
110 return dimension_code , integers [ n ] or 0
111 else
112 integers [ n ] = scandimen ( false , false , true )
113 end
114 end ,
115}
116
117implement {
118 name = " luacardinal " ,
119 public = true ,
120 value = true ,
121 actions = function ( b )
122 local n = scanword ( )
123 if b = = " value " then
124 context ( " %1.0f " , cardinals [ n ] or 0 )
125 else
126 cardinals [ n ] = scanluacardinal ( true )
127 end
128 end ,
129}
130
131implement {
132 name = " luanumber " ,
133 public = true ,
134 value = true ,
135 actions = function ( b )
136 local n = scanword ( )
137 if b = = " value " then
138 context ( " %N " , floats [ n ] or integers [ n ] or cardinals [ n ] or 0 )
139 else
140
141 floats [ n ] = scanluanumber ( true )
142 end
143 end ,
144}
145
146implement {
147 name = " luarandom " ,
148 public = true ,
149 value = true ,
150 actions = function ( b )
151 if b = = " value " then
152 return integer_code , random ( scanluainteger ( ) , scanluainteger ( ) )
153 else
154 randomseed ( scanluainteger ( true ) )
155 end
156 end ,
157}
158
159interfaces . floats = floats
160interfaces . integers = integers
161interfaces . cardinals = cardinals
162
163interfaces . numbers = table . setmetatableindex ( function ( t , k )
164 return floats [ k ] or integers [ k ] or cardinals [ k ]
165end )
166
167
168
169local arrays = { }
170
171interfaces . arrays = arrays
172
173local newindex = lua . newindex
174
175implement {
176 name = " newarray " ,
177 public = true ,
178 protected = true ,
179 arguments = { {
180 { " name " , " string " } ,
181 { " nx " , " integer " } ,
182 { " ny " , " integer " } ,
183 { " type " , " string " } ,
184 } } ,
185 actions = function ( t )
186 local name = t . name
187 if t . name then
188 local nx = t . nx
189 local ny = t . ny
190 local ty = t . type or " integer "
191 local df = nil
192 if ty = = " integer " or ty = = " float " or ty = = " dimension " then
193 df = 0
194 elseif ty = = " boolean " then
195 df = false
196 else
197 ty = nil
198 end
199 if nx and ty ~ = nil then
200 local data
201 if ny then
202 data = newindex ( t . ny )
203 for i = 1 , ny do
204 data [ i ] = newindex ( nx , df )
205 end
206 else
207 data = newindex ( nx , df )
208 end
209 arrays [ name ] = data
210 data . nx = nx
211 data . ny = ny
212 data . type = ty
213 if ty = = " integer " then
214 data . scanner = scaninteger
215 elseif ty = = " boolean " then
216 data . scanner = scanboolean
217 elseif ty = = " dimension " then
218 data . scanner = scandimen
219 elseif ty = = " float " then
220 data . scanner = scanfloat
221 end
222 if ty = = " integer " then
223 data . code = integer_code
224 elseif ty = = " boolean " then
225 data . code = boolean_code
226 elseif ty = = " dimension " then
227 data . code = dimension_code
228 elseif ty = = " float " then
229 data . code = float_code
230 end
231 end
232 end
233 end ,
234}
235
236implement {
237 name = " arrayvalue " ,
238 public = true ,
239 value = true ,
240 actions = function ( b )
241 local name = scanstring ( )
242 if name then
243 local a = arrays [ name ]
244 if a then
245 local nx = a . nx
246 local ny = a . ny
247 local d = a
248 if ny then
249 d = d [ scaninteger ( ) ]
250 end
251 local x = scaninteger ( )
252 if b = = " value " then
253 local code = a . code
254 if code = = float_code then
255 context ( " %.99g " , d [ x ] )
256 else
257 return code , d [ x ]
258 end
259 else
260 d [ x ] = a . scanner ( )
261 end
262 end
263 end
264 end ,
265}
266
267implement {
268 name = " arrayequals " ,
269 public = true ,
270 value = true ,
271 actions = function ( b )
272 local name = scanstring ( )
273 if name then
274 local a = arrays [ name ]
275 if a then
276 local nx = a . nx
277 local ny = a . ny
278 local d = a
279 if ny then
280 d = d [ scaninteger ( ) ]
281 end
282 local x = scaninteger ( )
283 if b = = " value " then
284 return boolean_code , a . scanner ( ) = = d [ x ]
285 end
286 end
287 end
288 end ,
289}
290
291implement {
292 name = " arraycompare " ,
293 public = true ,
294 value = true ,
295 actions = function ( b )
296 local name = scanstring ( )
297 if name then
298 local a = arrays [ name ]
299 if a then
300 local nx = a . nx
301 local ny = a . ny
302 local d = a
303 if ny then
304 d = d [ scaninteger ( ) ]
305 end
306 local x = scaninteger ( )
307 if b = = " value " then
308 local v = a . scanner ( )
309 local d = d [ x ]
310 if d < v then
311 return integer_code , 0
312 elseif d = = v then
313 return integer_code , 1
314 else
315 return integer_code , 2
316 end
317 end
318 end
319 end
320 end ,
321}
322
323implement {
324 name = " showarray " ,
325 public = true ,
326 protected = true ,
327 actions = function ( )
328 local name = scanstring ( )
329 if name then
330 inspect ( arrays [ name ] )
331 end
332 end ,
333}
334
335
336
337local cache = table . setmetatableindex ( function ( t , k )
338 local code = " return function() local n = interfaces.numbers local a = interfaces.arrays return " . . k . . " end "
339 code = loadstring ( code )
340 if code then
341 code = code ( )
342 end
343 t [ k ] = code or false
344 return code
345end )
346
347table . makeweak ( cache )
348
349implement {
350 name = " luaexpression " ,
351 public = true ,
352 actions = function ( )
353 local how = scanword ( )
354 local code = cache [ scanargument ( ) ]
355 if code then
356 local result = code ( )
357 if result then
358 if not how then
359 context ( tostring ( code ( ) ) )
360 elseif how = = " float " then
361 context ( " %.99g " , result )
362 elseif how = = " integer " then
363 context ( " %i " , round ( result ) )
364 elseif how = = " cardinal " then
365 context ( " %d " , abs ( round ( result ) ) )
366 elseif how = = " dimen " then
367 context ( " %p " , result )
368 elseif how = = " boolean " then
369 context ( " %d " , result and 1 or 0 )
370 elseif how = = " lua " then
371 context ( " %q " , result )
372 else
373 context ( tostring ( code ( ) ) )
374 end
375 end
376 end
377 end
378}
379
380local dimenfactors = number . dimenfactors
381
382implement {
383 name = " nodimen " ,
384 public = true ,
385 value = true ,
386 actions = function ( b )
387 if b = = " value " then
388 local how = scanword ( )
389 local what = scandimen ( )
390 if how then
391 local factor = dimenfactors [ how ]
392 if factor then
393 context ( " %.6N%s " , factor * what , how )
394 else
395 return dimension_code , what
396 end
397 else
398 return dimension_code , what
399 end
400 else
401 local t = scantoken ( )
402 if t then
403 local i = getindex ( t )
404 if i then
405 local d = scandimen ( false , false , true )
406 texsetdimen ( i , d )
407 end
408 end
409 end
410 end ,
411}
412
413
414
415local grouped = { }
416local slots = { }
417local nofslots = 0
418local nofgrouped = 0
419
420local getdata = tokens . getdata
421local setdata = tokens . setdata
422
423local report = logs . reporter ( " lua table " )
424
425local ctxsprint = context . sprint
426
427
428
429
430local function newluatable ( name , mt , dispose )
431 local g = { }
432 local t = slots [ nofslots ]
433 slots [ nofslots ] = false
434 nofslots = nofslots - 1
435 if not t then
436 nofgrouped = nofgrouped + 1
437 t = nofgrouped
438 end
439 if mt then
440 mt = getdata ( name )
441 if mt then
442 mt = grouped [ mt ]
443 if mt then
444 setmetatableindex ( g , mt )
445 end
446 end
447 end
448 grouped [ t ] = g
449 setdata ( name , t )
450
451
452 if dispose then
453 ctxsprint ( " \\atendofgrouped{\\disposeluatable\\ " . . name . . " } " )
454 end
455end
456
457local function disposeluatable ( name )
458 local t = getdata ( name )
459 local g = grouped [ t ]
460 if g then
461 grouped [ t ] = false
462 nofslots = nofslots + 1
463 slots [ nofslots ] = t
464 end
465end
466
467local function setluatable ( name , kv )
468 local t = getdata ( name )
469 local g = grouped [ t ]
470 if g and kv then
471 for k , v in next , kv do
472 g [ k ] = v
473 end
474 end
475end
476
477local function getfromluatable ( name , k )
478 local t = getdata ( name )
479 local g = grouped [ t ]
480 if g then
481 local v = g [ k ]
482 if v then
483 context ( v )
484 else
485 local n = tonumber ( k )
486 if n then
487 local v = g [ n ]
488 if v then
489 context ( v )
490 end
491 end
492 end
493 end
494end
495
496local function idxfromluatable ( name , k )
497 local t = getdata ( name )
498 local g = grouped [ t ]
499 if g then
500 local v = g [ k ]
501 if v then
502 context ( v )
503 end
504 end
505end
506
507local function getluatable ( name , k )
508 local t = getdata ( name )
509 local g = grouped [ t ]
510 if g then
511 return g
512 end
513end
514
515local function inspectluatable ( name )
516 local t = getdata ( name )
517 local g = grouped [ t ]
518 if g then
519 report ( " %s " , serialize ( g , ' [grouped slot ' . . t . . ' ] ' ) )
520 end
521end
522
523local function showluatables ( )
524 report ( " nofgrouped %i, nofslots %i " , nofgrouped , nofslots )
525 for t = 1 , nofgrouped do
526 local g = grouped [ t ]
527 if g then
528 report ( " %s " , serialize ( g , ' [grouped slot ' . . t . . ' ] ' ) )
529 end
530 end
531end
532
533implement {
534 name = " newluatable " ,
535 protected = true ,
536
537 arguments = " csname " ,
538 actions = newluatable ,
539}
540
541implement {
542 name = " useluatable " ,
543 protected = true ,
544
545 arguments = { " csname " , true } ,
546 actions = newluatable ,
547}
548
549implement {
550 name = " disposeluatable " ,
551 protected = true ,
552 public = true ,
553 arguments = " csname " ,
554 actions = disposeluatable ,
555}
556
557implement {
558 name = " inspectluatable " ,
559 protected = true ,
560 public = true ,
561 arguments = " csname " ,
562 actions = inspectluatable ,
563}
564
565implement {
566 name = " showluatables " ,
567 protected = true ,
568 public = true ,
569 actions = showluatables ,
570}
571
572implement {
573 name = " setluatable " ,
574 protected = true ,
575 public = true ,
576 arguments = { " csname " , " argument " } ,
577 actions = function ( name , data )
578 data = load ( " return { " . . data . . " } " )
579 if data then
580 data = data ( )
581 if data then
582 setluatable ( name , data )
583 end
584 end
585 end
586}
587
588implement {
589 name = " getfromluatable " ,
590 protected = false ,
591 public = true ,
592 arguments = { " csname " , " argument " } ,
593 actions = getfromluatable ,
594}
595
596implement {
597 name = " idxfromluatable " ,
598 protected = false ,
599 public = true ,
600 arguments = { " csname " , " integer " } ,
601 actions = idxfromluatable ,
602}
603
604context . luatables = {
605 new = function ( name ) newluatable ( name , false , true ) end ,
606 use = function ( name ) useluatable ( name , true , true ) end ,
607 dispose = disposeluatable ,
608 set = setluatable ,
609 get = getluatable ,
610 getfrom = getfromluatable ,
611 idxfrom = idxfromluatable ,
612 inspect = inspectluatable ,
613 show = showluatables ,
614}
615
616
617
618local tables = { }
619local stack = setmetatableindex ( " table " )
620
621interfaces . implement {
622 name = " droptablegroup " ,
623 public = true ,
624 actions = function ( )
625 local g = texget ( " currentgrouplevel " )
626 local s = stack [ g ]
627 if s then
628 for t , data in next , s do
629 for k , v in next , data do
630 t [ k ] = v
631 end
632 end
633 stack [ g ] = { }
634 end
635 end ,
636}
637
638local ctx_atendofgroup = context . core . cs . atendofgroup
639local ctx_droptablegroup = context . core . cs . droptablegroup
640
641local function handletable ( t , b , array )
642 if b = = " value " then
643 local k = array and scaninteger ( ) or scanargument ( )
644 local v = t [ k ]
645 if v then
646 context ( v )
647 end
648 else
649 local data = scanargument ( )
650 data = load ( " return { " . . data . . " } " )
651 if data then
652 data = data ( )
653 if data then
654 local l = t . level
655 local g = texget ( " currentgrouplevel " )
656 local s = stack [ g ]
657 local d = s [ t ]
658 if not d then
659 d = { }
660 s [ t ] = d
661 ctx_atendofgroup ( )
662 ctx_droptablegroup ( )
663 end
664 for k , v in next , data do
665 if not d [ k ] then
666 d [ k ] = t [ k ]
667 end
668 t [ k ] = v
669 end
670 if b = = " global " then
671 for k , v in next , stack do
672 local t = s [ t ]
673 if t then
674 for k , v in next , data do
675 if t [ k ] then
676 t [ k ] = nil
677 end
678 end
679 end
680 end
681 end
682 end
683 end
684 end
685end
686
687local function newtable ( array )
688 local name = scancsname ( true )
689 if not tables [ name ] then
690 local t = { }
691 tables [ name ] = t
692 interfaces . implement {
693 name = name ,
694 public = true ,
695 value = true ,
696 actions = function ( b )
697 handletable ( t , b , array )
698 end ,
699 }
700 else
701
702 end
703end
704
705implement {
706 name = " newhashedtable " ,
707 protected = true ,
708 public = true ,
709 actions = newtable ,
710}
711
712implement {
713 name = " newindexedtable " ,
714 protected = true ,
715 public = true ,
716 actions = function ( ) newtable ( true ) end ,
717}
718
719context . hashedtables = setmetatableindex ( function ( t , k ) return tables [ k ] end )
720context . indexedtables = context . hashedtables
721 |