-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathpttree.e
1816 lines (1695 loc) · 87 KB
/
pttree.e
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
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
--
-- pttree.e
-- ========
--
without trace
--with type_check
global sequence tt -- The ternary tree
--sequence ttchk -- ttchk[ttidx+CH] is 1 for strings, 2 for atoms, 3 for seq
-- ttchk = {}
--type ttt(sequence x)
-- if length(x)>664 then
-- if ttchk[661]!=2 then return 0 end if
-- end if
-- return 1
--end type
--global ttt tt -- The ternary tree
tt = {}
global integer ttidx -- The main idx/result.
ttidx = 0
-- 0-based: tt[ttidx+CH]..tt[ttidx+GT] obtain node elements:
-- For strings (var_ids and literals), this is:
global constant CH=1 -- char this node represents
constant LT=2 -- idx to "<" chs, or 0
global constant EQ=3 -- if ch<=0 then data else idx to next ch, or 0
constant GT=4 -- idx to ">" chs, or 0
-- a terminator (so that "add" and "additional" can be stored in the same
-- tree) of -2 (for var_ids) or -1 (for string literals) is used, which
-- allows for eg string fred="fred" to use the same slots for the ascii
-- characters but yield different tt[ttidx+EQ] for external use.
--DEV tt_integer??
-- For atoms (added via tt_atom), tt[ttidx+CH] holds an integer
-- (in the range -1073741824..1073741823 aka #C0000000..#3FFFFFFF)
-- or a 64-bit float. atom_base holds the root of this tree, and
-- tt[ttidx+EQ] is not used internally/available for external use.
-- For sequences (added via tt_sequence), tt[ttidx+CH] is either
-- an atom element, {} for end of sequence, {-ttidx} for a
-- substring, or {ttidx} for a subsequence. Strict ordering is
-- not obeyed, only uniqueness is guaranteed. seq_base holds
-- the root of this tree, and tt[ttidx+EQ] is available for
-- external use on the {} record.
global string identset
identset = repeat(' ',256) -- characters valid in an identifier
-- convert to "string of nulls" (repeat(0,256) makes a dword-sequence)
for i=1 to 256 do identset[i] = 0 end for
identset['0'..'9'] = 1
identset['A'..'Z'] = 1
identset['_'] = 1
identset['a'..'z'] = 1
--4/9/19 (nb changes must match charset in ptok.e
-- identset[#80] = 1 -- for rosettacode/unicode
-- identset[#88] = 1 -- for rosettacode/unicode
-- identset[#94] = 1 -- for rosettacode/unicode (as ptok.e is not stored in utf8)
-- identset[#9A] = 1 -- for rosettacode/unicode
-- identset[#A3] = 1 -- for rosettacode/unicode
-- identset[#BB] = 1 -- for rosettacode/unicode
-- identset[#CE] = 1 -- for rosettacode/unicode
-- identset[#CF] = 1 -- for rosettacode/unicode
-- identset[#E2] = 1 -- for rosettacode/unicode
identset[#80..#BF] = 1
identset[#C2..#F4] = 1
global string thisline -- copy of text[line]
thisline = ""
integer ttCh -- current tt[ttidx+CH] being inspected [speedwise]
integer isCh -- identset[Ch]
--with trace
global procedure tt_search()
--
-- Search for/Insert a var_id beginning with Ch at thisline[col].
-- Result is ttidx, and Ch must be left correctly set.
--
integer pcurr -- 1-based ptr idx, for later update of tt[pcurr] if needbe.
pcurr = 0
-- isCh = identset[Ch]
isCh = 1 -- must be, charset[Ch[=text[col]]=LETTER to get here.
if length(tt) then -- (19/10 not actually needed as tt_atom called first (via psym.e's PI) )
ttidx = 0
while 1 do
ttCh = tt[ttidx+CH]
-- if ttchk[ttidx+CH]!=1 then ttCh=9/0 end if
--2/8/15!!
if 01 then
if not isCh then
if ttCh=-2 then return end if
--DEV wtf? a) I doubt this is ever even triggered.
-- b) it should clearly be ttCh vs Ch[?]
-- c) is there a way to make it common code?
-- if ttCh<0 then
if ttCh<-2 then -- (2/8/15, yippee!!)
-- if ttCh>0 then -- (2/8/15, nope...)
-- if ttCh>Ch then -- (2/8/15, nope...)
-- if ttCh<Ch then -- (2/8/15, nope...)
pcurr = ttidx+GT
else
pcurr = ttidx+LT
end if
elsif ttCh=Ch then
col += 1
Ch = text[col]
isCh = identset[Ch]
pcurr = ttidx+EQ
elsif Ch<ttCh then
pcurr = ttidx+LT
else -- Ch>ttCh then
pcurr = ttidx+GT
end if
else
if ttCh=Ch then
if ttCh=-2 then return end if
col += 1
Ch = text[col]
isCh = identset[Ch]
pcurr = ttidx+EQ
elsif Ch<ttCh then
pcurr = ttidx+LT
else -- Ch>ttCh then
pcurr = ttidx+GT
end if
end if
ttidx = tt[pcurr]
if ttidx=0 then exit end if
end while
end if
--?{Ch,isCh}
--
-- Not a duplicate, so insert remainder of string
--
ttidx = length(tt)
while 1 do
if pcurr then -- (19/10 not actually needed as tt_atom called first (via psym.e's PI) )
tt[pcurr] = ttidx
end if
-- tt = append(tt,0) -- CH
-- tt = append(tt,0) -- LT
-- tt = append(tt,0) -- EQ
-- tt = append(tt,0) -- GT
tt &= {-2,0,0,0}
--ttchk = append(ttchk,1) -- string check
--ttchk = append(ttchk,0)
--ttchk = append(ttchk,0)
--ttchk = append(ttchk,0)
if not isCh then return end if
tt[ttidx+CH] = Ch
col += 1
Ch = text[col]
isCh = identset[Ch]
pcurr = ttidx+EQ
ttidx += 4
end while
end procedure
integer rtn_id
--DEV string? (tryme)
sequence key, pkey
-- key = ""
integer kidx,lp,lk,pCh,ch
ch = 0
lk = 0
integer term
function charmatch()
if kidx<=lp then
pCh = pkey[kidx]
if ch!=pCh then return 0 end if
end if
if term=-2 then -- identifier scan (-1 is literal strings scan)
if not identset[ch] then return 0 end if
end if
if kidx>lk then
key &= ch
lk += 1
else
key[kidx] = ch
end if
return 1
end function
-- aside:
-- The use of rand() to traverse the tree improves encryption
-- slightly, without any significant performance overhead.
-- Adding a bit of randomness also probably helps the test set
-- catch a few more (obscure) problems than it otherwise would.
-- Just as "constant a=1, b=2" and "constant b=2, a=1" cause
-- no measurable difference to any subsequent code, it does
-- not matter what order we write such things to the exe file.
-- While removing this might help some hacker reverse engineer
-- their own code, it is unlikely to help on yours or mine.
-- I have only put this in on the basis that it has absolutely
-- no impact on interpretation whatsoever, and less than 0.01%
-- when compiling, tracing, or reporting an error or warning.
-- Lastly, and obviously, replacing "j = rand(n)" with "j = n"
-- (perhaps controlled by a new parameter) will of course get
-- things back into strict alphabetical/numerical order.
-- /aside
--
integer ttscramble
function traverse(integer node)
integer nxt, r, j, k
sequence todo
--integer nodech, nodelt, nodeeq, nodegt
--nodech=tt[node+CH]
--nodelt=tt[node+LT]
--nodeeq=tt[node+EQ]
--nodegt=tt[node+GT]
if ttscramble then
todo = {GT,EQ,LT}
--DEV/SUG instead (if ttscramble is still in use?):
-- if ttscramble then todo = scramble(todo) end if & then common up this code...
for n=3 to 1 by -1 do
j = rand(n)
k = todo[j]
nxt = tt[node+k]
if k=EQ then
ch = tt[node+CH]
if ch>0 then
if nxt then
kidx += 1
if charmatch() then
if not traverse(nxt) then return 0 end if
end if
kidx -= 1
end if
elsif ch=term and kidx>=lp then
-- a leaf node with key not shorter than partial:
if not call_func(rtn_id,{key[1..kidx],node}) then return 0 end if
end if
else
if nxt then
if not traverse(nxt) then return 0 end if
end if
end if
if j<n then
todo[j] = todo[n]
end if
end for
return 1
end if
r = 1
--if ttchk[node+CH]!=1 then ttCh=9/0 end if
nxt = tt[node+LT] if nxt then r = traverse(nxt) end if -- recurse(LT)
if r then
ch = tt[node+CH]
--31/1/15:
-- if ch>0 then kidx += 1
if ch>=0 then kidx += 1
if (term!=-2 or ch>0) and charmatch() then
nxt = tt[node+EQ] if nxt then r = traverse(nxt) end if -- recurse(EQ)
end if kidx -= 1
elsif ch=term and kidx>=lp then
-- a leaf node with key not shorter than partial:
r = call_func(rtn_id,{key[1..kidx],node})
end if
if r then
nxt = tt[node+GT] if nxt then r = traverse(nxt) end if -- recurse(GT)
end if
end if
return r
end function
--global procedure tt_traverse(integer rtnid, sequence partkey, integer terminator)
global procedure tt_traverse(integer rtnid, string partkey, integer terminator, integer carblems=scramble)
--
-- Traverses the var_id (terminator=-2) or string literal(terminator=-1) tree
-- calling the specified function, which should accept two parameters, the
-- string and a nodeidx, and return 1 to continue traversal, 0 to cease.
-- A partkey of "fish" will match "fishcake", but not vice versa.
-- The last parameter defaults to pglobals\scramble for use in pemit.e, but is
-- explictly set to 0 for use in intellisense (so things come out alphabetically).
--
-- NB this is not meant to be particularly fast, use sparingly.
--
if length(tt) then
rtn_id = rtnid
pkey = partkey
lp = length(pkey)
key = ""
lk = 0 --length(key)
kidx = 0
term = terminator
ttscramble = carblems
if traverse(0) then end if
end if
end procedure
integer gnidx
function look_for_gnidx(sequence name, integer node)
if node=gnidx then
pkey = name
return 0
end if
return 1
end function
constant r_look_for_gnidx = routine_id("look_for_gnidx")
global function getname(integer getnameidx, integer terminator)
--
-- Perform a tree traversal to obtain the name.
-- warning: only use following a fatal error;
-- unwise use could be awfully slow.
--
-- DEV probably to be replaced with a full traverse/replace of all identifiers...
-- (see pemit.e)
--
gnidx = getnameidx
tt_traverse(r_look_for_gnidx,"",terminator,0)
return pkey
end function
global procedure relink()
-- Compilation has ceased, this is called either from finalfixups or Abort.
-- Locals may have been delinked from the ternary tree, and marked with -2
-- in symtab[i][S_Nlink]: relink them. Suppose for example there are some
-- 18 or so variables/parameters named "desc" in your application. Clearly
-- some/most of those have dropped out of scope at end routine/file so the
-- lookup will get/only examine the right one. By the time this is called,
-- all such "desc" have been replaced with an appropriate varno, and the
-- "desc" sitting in the ternary tree has a pointer of 0. Throw the whole
-- lot back onto that chain, so the exe only needs the one "desc" string,
-- rather than 18 of them...
object si
integer k
-- for i=1 to T_pathset-1 do
-- si = symtab[i]
-- if sequence(si) and si[S_Nlink]=-2 then
-- k = si[S_Name]+EQ
-- si = tt[k]
-- symtab[i][S_Nlink] = si
-- tt[k] = i
-- end if
-- end for
for i=T_constm1 to length(symtab) do
si = symtab[i]
if sequence(si) and si[S_Nlink]=-2 then
k = si[S_Name]+EQ
si = tt[k]
symtab[i][S_Nlink] = si
tt[k] = i
end if
end for
end procedure
--DEV untried, there may be several places (in pEmit2.e) that have/need this:
--/*
global procedure unlink(integer ttidx, integer symidx)
sequence sv = symtab[symidx]
integer node = sv[S_Name],
slink = tt[node+EQ],
snxt
if sv[S_NTyp]=S_Rsvd then ?9/0 end if -- sanity check
if slink=symidx then
tt[node+EQ] = sv[S_Nlink]
else
while slink do
snext = symtab[slink][S_Nlink]
if snext=symidx then
symtab[slink][S_Nlink] = sv[S_Nlink]
exit
end if
slink = snext
end while
end if
end procedure
--*/
--
-- Routines for constant literal handling:
--
integer atom_base
atom_base = 0
global procedure tt_atom(atom data)
--
-- Lookup an atom value in the ternary tree.
-- Result is ttidx. Info may be stored in tt[ttidx+EQ], usually an
-- index into symtab. The atom value corresponding to a given ttidx
-- can be retrieved from tt[ttidx+CH(=1)].
--
-- Note The "atom subtree" is totally separate from the main "string tree",
-- controlled by atom_base. The main string tree does not have an
-- equivalent "string_base", just assumes it is zero, ie that the
-- tt_string calls (below) occur before any tt_atom calls.
-- If at any point you wanted to introduce "string_base" you would
-- need to change ttidx/pcurr=0 handling to !=-1 or somesuch.
--
atom thisAtom
integer pcurr
ttidx = atom_base
pcurr = 0
if ttidx then
while 1 do
thisAtom = tt[ttidx+CH]
--if ttchk[ttidx+CH]!=2 then ttCh=9/0 end if
if data=thisAtom then return end if
if data>thisAtom then
-- c = compare(data,thisAtom)
-- if c=0 then return end if
-- if c=1 then -- data>thisAtom
pcurr = ttidx+GT
else -- data<thisAtom
pcurr = ttidx+LT
end if
ttidx = tt[pcurr]
if ttidx=0 then exit end if
end while
end if
ttidx = length(tt)
if pcurr then
tt[pcurr] = ttidx
else
atom_base = ttidx
end if
tt = append(tt,data) -- CH
tt = append(tt,0) -- LT
tt = append(tt,0) -- EQ
tt = append(tt,0) -- GT
--ttchk = append(ttchk,2) -- atom
--ttchk = append(ttchk,0)
--ttchk = append(ttchk,0)
--ttchk = append(ttchk,0)
end procedure
integer idxstart
idxstart=1
integer idx, ltxt, ltt
integer tCh
integer pcurr
--global procedure tt_string(sequence text, integer idx, integer terminator)
global procedure tt_string(string text, integer terminator)
--
-- Lookup a string value in the ternary tree.
--
-- Result is ttidx. Info may be stored in tt[ttidx+EQ], usually an
-- index into symtab.
--
-- The terminator should be -2 for var_id use or -1 for string literal use.
-- (A terminator of -3 is also used for ilasm.)
-- This allows eg string fred="fred" to share the same slots for the
-- ascii characters but yield a different ttidx and hence tt[ttidx+EQ]
-- for string literal and var_id use.
-- Eg tt_string("global",-2) means that ttidx matches global rather
-- than "global". While we might validly have tt_string("",-1) and
-- T_nullstr=ttidx, it should be clear that tt_string("",-2) yields a
-- ttidx that the parser never can, and in fact yields a ttidx which
-- is very probably of no use to anybody under any circumstances,
-- except perhaps as a special "won't match with anything" value.
--
-- This differs from tt_search in that it does not demand a non-identset
-- terminator and does not place "The cat sat on the mat" and "The " in
-- the exact same pigeonhole, as the parser-orientated tt_search would.
-- As mentioned, this routine can also handle "", ie the null string,
-- which tt_search cannot (ioob on Ch = thisline[col] for starters).
--
-- tt_string("keyword",-2) is the preferred mechanism during compiler
-- initialisation, equivalent to tt_lookup("keyword ",1) [nb the ' '], --DEV pardon?
-- or thisline="keyword "/Ch='k'/col=1/tt_search().
--
-- Unlike the comments in tt_atom and tt_sequence, there should be no
-- reason why this should not be invoked before tt_search, if desired.
--
pcurr = 0
ltxt = length(text)
idx = idxstart
idxstart = 1
if idx<=ltxt then
ch = text[idx]
else
ch = terminator
end if
ltt = length(tt)
if ltt then
ttidx = 0
while 1 do
tCh = tt[ttidx+CH]
--if ttchk[ttidx+CH]!=1 then ttCh=9/0 end if
if ch=tCh then
if ch=terminator then return end if
idx += 1
if idx>ltxt then
ch = terminator
else
ch = text[idx]
if terminator!=-1 then
if not identset[ch] then
ch = terminator
end if
end if
end if
pcurr = ttidx+EQ
elsif ch>tCh then
pcurr = ttidx+GT
else -- ch<tCh
pcurr = ttidx+LT
end if
ttidx = tt[pcurr]
if ttidx=0 then exit end if
end while
end if
ttidx = ltt
if pcurr then
tt[pcurr] = ttidx
end if
while 1 do
tt = append(tt,ch) -- CH
tt = append(tt,0) -- LT
tt = append(tt,0) -- EQ
tt = append(tt,0) -- GT
--ttchk = append(ttchk,1) -- string
--ttchk = append(ttchk,0)
--ttchk = append(ttchk,0)
--ttchk = append(ttchk,0)
if ch=terminator then return end if
pcurr = ttidx+EQ
ttidx += 4
idx += 1
if idx>ltxt then
ch = terminator
else
ch = text[idx]
if terminator!=-1 then
if not identset[ch] then
ch = terminator
end if
end if
end if
tt[pcurr] = ttidx
end while
end procedure
integer seq_base
seq_base = 0
global procedure tt_sequence(sequence data)
--
-- Lookup a sequence value in the ternary tree.
--
-- Result is ttidx. Info may be stored in tt[ttidx+EQ], usually an
-- index into symtab. Integer and float elements are stored as-is.
-- Subsequences must be stored as {ttidx}, and substrings as {-ttidx},
-- ie/eg when parsing say {"string",{1,2},3}, rather than invoking
-- tt_sequence({"string",{1,2},3}) you might instead expect to
-- tt_string("string")/tt_sequence({1,2})/tt_sequence({-t1},{t2},3).
-- The end of sequence is (internally) indicated by {}.
--
-- Retrieval of values stored in the sequence tree is non-trivial; see
-- pemit.e/tt_traverseQ(). The primary goal is to answer the question
-- "is this unique?" as fast as possible: other mechanisms should be
-- used when speed of retrieval is important.
--
-- Note The "sequence subtree" is separate from the main "string tree",
-- controlled by seq_base. The main string tree does not have an
-- equivalent "string_base", just assumes it is zero, ie that the
-- tt_string calls (below) occur before any tt_sequence calls.
-- If at any point you wanted to introduce "string_base" you would
-- need to change ttidx/pcurr=0 handling to !=-1 or somesuch.
--
object thisElement, thisKey
integer pcurr, thisIdx, c
--, save
pcurr = 0
thisIdx = 1
if length(data)=0 then
thisElement = {}
else
thisElement = data[1]
end if
ttidx = seq_base
while ttidx do
thisKey = tt[ttidx+CH]
--if ttchk[ttidx+CH]!=3 then ttCh=9/0 end if
c = compare(thisElement,thisKey)
if c=0 then -- ie thisElement=thisKey
if thisIdx > length(data) then return end if
thisIdx += 1
if thisIdx>length(data) then
thisElement = {}
else
thisElement = data[thisIdx]
end if
pcurr = ttidx+EQ
elsif c=1 then -- ie thisElement>thisKey
pcurr = ttidx+GT
else -- c=-1 -- ie thisElement<thisKey
pcurr = ttidx+LT
end if
ttidx = tt[pcurr]
end while
ttidx = length(tt)
if pcurr then
tt[pcurr] = ttidx
else
seq_base = ttidx
end if
while 1 do
tt = append(tt,thisElement) -- CH
tt = append(tt,0) -- LT
tt = append(tt,0) -- EQ
tt = append(tt,0) -- GT
--ttchk=append(ttchk,3) --seq
--ttchk=append(ttchk,0)
--ttchk=append(ttchk,0)
--ttchk=append(ttchk,0)
if thisIdx > length(data) then return end if
pcurr = ttidx+EQ
ttidx += 4
thisIdx += 1
if thisIdx>length(data) then
thisElement = {}
else
thisElement = data[thisIdx]
end if
tt[pcurr] = ttidx
end while
end procedure
-- version of traverse for items added via tt_atom.
-- in this case the EQ link is not used internally,
-- rtn_id should retrieve tt[node+EQ] itself.
function traverseA(integer node)
integer nxt, r, j, k
sequence todo
--object dbg
if scramble then
todo = {GT,EQ,LT}
for n=3 to 1 by -1 do
j = rand(n)
k = todo[j]
if k=EQ then
if not call_func(rtn_id,{tt[node+CH],node}) then return 0 end if
else
nxt = tt[node+k]
if nxt then
if not traverseA(nxt) then return 0 end if
end if
end if
if j<n then
todo[j] = todo[n]
end if
end for
return 1
end if
r = 1
--if ttchk[node+CH]!=2 then ttCh=9/0 end if
nxt = tt[node+LT] if nxt then r = traverseA(nxt) end if -- recurse(LT)
if r then
--dbg= tt[node+CH]
r = call_func(rtn_id,{tt[node+CH],node})
if r then
nxt = tt[node+GT] if nxt then r = traverseA(nxt) end if -- recurse(GT)
end if
end if
return r
end function
global procedure tt_traverseA(integer rtnid)
--
-- Traverses the tt_atom tree calling the specified function.
-- rtnid should be the routine_id of a funtion which accepts two parameters,
-- atom value and node idx, and returns 1 to continue traversal, 0 to cease.
--
if atom_base then
rtn_id = rtnid
if traverseA(atom_base) then end if
end if
end procedure
-- version of traverse for items added via tt_sequence.
-- rtn_id should retrieve tt[node+EQ] itself.
function traverseQ(integer node)
object element
integer nxt, r, j, k
sequence todo
if scramble then
todo = {GT,EQ,LT}
for n=3 to 1 by -1 do
j = rand(n)
k = todo[j]
nxt = tt[node+k]
if k=EQ then
element = tt[node+CH]
if equal(element,{}) then
if not call_func(rtn_id,{key[1..kidx],node}) then return 0 end if
else
kidx += 1
if kidx>lk then
key = append(key,element)
lk += 1
else
key[kidx] = element
end if
if nxt then
if not traverseQ(nxt) then return 0 end if
end if
kidx -= 1
end if
else
if nxt then
if not traverseQ(nxt) then return 0 end if
end if
end if
if j<n then
todo[j] = todo[n]
end if
end for
return 1
end if
r = 1
--if ttchk[node+CH]!=3 then ttCh=9/0 end if
nxt = tt[node+LT] if nxt then r = traverseQ(nxt) end if -- recurse(LT)
if r then
element = tt[node+CH]
if equal(element,{}) then
r = call_func(rtn_id,{key[1..kidx],node})
else
kidx += 1
if kidx>lk then
key = append(key,element)
lk += 1
else
key[kidx] = element
end if
nxt = tt[node+EQ] if nxt then r = traverseQ(nxt) end if -- recurse(EQ)
-- if r then
kidx -= 1
-- end if
end if
if r then
nxt = tt[node+GT] if nxt then r = traverseQ(nxt) end if -- recurse(GT)
end if
end if
return r
end function
global procedure tt_traverseQ(integer rtnid)
--
-- Traverses the tt_sequence tree calling the specified function.
-- rtnid should be the routine_id of a funtion which accepts two parameters,
-- the sequence and node idx, and returns 1 to continue traversal, 0 to cease.
--
if seq_base then
rtn_id = rtnid
kidx = 0
key = {}
lk = 0 --length(key)
if traverseQ(seq_base) then end if
end if
end procedure
--function tt_stringf(sequence text)
-- tt_string(text,-2)
-- return ttidx
--end function
--procedure tt_stringF(sequence text, integer chk, integer term=-2)
-- tt_string(text,term)
procedure tt_stringF(sequence text, integer chk)
tt_string(text,-2)
if chk!=ttidx then
printf(1,"%s should be %d(not %d)\n",{text,ttidx,chk})
if getc(0) then end if
end if
end procedure
--procedure tt_stringA(sequence text, integer alias)
-- tt_string(text,-2)
-- tt[pcurr] = alias
--end procedure
--
--procedure tt_glabel(sequence glabel, integer chk)
-- tt_string(glabel,-3)
-- if chk!=ttidx then
-- printf(1,"%s should be %d(not %d)\n",{glabel,ttidx,chk})
-- if getc(0) then end if
-- end if
--end procedure
-- Keywords etc (T_xxx constants)
-- ========
-- These don't really add anything, just define a unique ttidx.
-- As such they are just numbers, and you could order this lot
-- in logical grouping, alphabetically, or completely at random,
-- it would make no difference, except inserting things means
-- (lots of) extra work, compared to adding at the end, that is.
--
-- Tech note: Coded this way so that eg "=T_global" in say
-- pmain.e can inline the constant 24, as opposed to
-- say constant T_global = tt_stringF("global"), which
-- obviously means T_global is not known until runtime
-- and hence pmain.e etc have to load it. Whether that
-- actually makes for any measurable gain is unknown.
-- Reordering or inserting causes tt_stringF() to walk
-- you through any necessary changes one at a time, so
-- you can just add "new_keyword" of 0 and be told the
-- number that you actually need to use, the next time
-- you try to compile it (p.exw/pth.exw/pgui.exw).
--
-- TIP: Add things at the end. If you MUST reorder, allow a
-- good 20 mins (depending where you start from) to go
-- through the renumbering, then another 20 mins or so
-- to ponder why you insist on wasting your time. ;-)
--
global constant T_global = 24 tt_stringF("global",T_global)
global constant T_proc = 64 tt_stringF("procedure",T_proc)
global constant T_func = 100 tt_stringF("function",T_func)
global constant T_type = 120 tt_stringF("type",T_type)
global constant T_not = 136 tt_stringF("not",T_not)
global constant T_then = 152 tt_stringF("then",T_then)
global constant T_do = 164 tt_stringF("do",T_do)
global constant T_and = 180 tt_stringF("and",T_and)
global constant T_or = 192 tt_stringF("or",T_or)
global constant T_xor = 208 tt_stringF("xor",T_xor)
global constant T_end = 224 tt_stringF("end",T_end)
global constant T_exit = 240 tt_stringF("exit",T_exit)
global constant T_elsif = 260 tt_stringF("elsif",T_elsif)
global constant T_else = 268 tt_stringF("else",T_else)
global constant T_to = 276 tt_stringF("to",T_to)
global constant T_by = 288 tt_stringF("by",T_by)
global constant T_if = 300 tt_stringF("if",T_if)
global constant T_for = 312 tt_stringF("for",T_for)
global constant T_while = 336 tt_stringF("while",T_while)
global constant T_return = 364 tt_stringF("return",T_return)
global constant T_profile = 384 tt_stringF("profile",T_profile)
global constant T_profile_time = 408 tt_stringF("profile_time",T_profile_time)
global constant T_trace = 428 tt_stringF("trace",T_trace)
global constant T_warning = 456 tt_stringF("warning",T_warning)
global constant T_type_check = 484 tt_stringF("type_check",T_type_check)
global constant T_debug = 504 tt_stringF("debug",T_debug)
global constant T_console = 536 tt_stringF("console",T_console)
global constant T_gui = 548 tt_stringF("gui",T_gui)
global constant T_constant = 568 tt_stringF("constant",T_constant)
global constant T_include = 596 tt_stringF("include",T_include)
global constant T_with = 612 tt_stringF("with",T_with)
global constant T_without = 628 tt_stringF("without",T_without)
global constant T_forward = 648 tt_stringF("forward",T_forward)
--DEV to go... (or better yet move/rename T_ilASM)
global constant T_ilasmX = 668 tt_stringF("ilasm",T_ilasmX)
global constant T_istype = 692 tt_stringF("istype",T_istype)
global constant T_isinit = 712 tt_stringF("isinit",T_isinit)
global constant T_isginfo = 736 tt_stringF("isginfo",T_isginfo)
global constant T_MIN = 752 tt_stringF("MIN",T_MIN)
global constant T_MAX = 764 tt_stringF("MAX",T_MAX)
global constant T_MAXLEN = 780 tt_stringF("MAXLEN",T_MAXLEN)
global constant T_machine_func = 832 tt_stringF("machine_func",T_machine_func)
global constant T_machine_proc = 852 tt_stringF("machine_proc",T_machine_proc)
global constant T_append = 876 tt_stringF("append",T_append)
global constant T_prepend = 900 tt_stringF("prepend",T_prepend)
global constant T_licence = 932 tt_stringF("licence",T_licence)
global constant T_public = 956 tt_stringF("public",T_public)
global constant T_export = 976 tt_stringF("export",T_export)
global constant T_enum = 988 tt_stringF("enum",T_enum)
global constant T_ifdef = 1004 tt_stringF("ifdef",T_ifdef)
global constant T_elsifdef = 1020 tt_stringF("elsifdef",T_elsifdef)
global constant T_elsedef = 1036 tt_stringF("elsedef",T_elsedef)
global constant T_WIN32 = 1060 tt_stringF("WIN32",T_WIN32)
global constant T_WINDOWS = 1080 tt_stringF("WINDOWS",T_WINDOWS)
global constant T_LINUX = 1104 tt_stringF("LINUX",T_LINUX)
global constant T_FREEBSD = 1136 tt_stringF("FREEBSD",T_FREEBSD)
global constant T_SUNOS = 1160 tt_stringF("SUNOS",T_SUNOS)
global constant T_OPENBSD = 1192 tt_stringF("OPENBSD",T_OPENBSD)
global constant T_OSX = 1204 tt_stringF("OSX",T_OSX)
global constant T_UNIX = 1224 tt_stringF("UNIX",T_UNIX)
global constant T_WIN32_GUI = 1244 tt_stringF("WIN32_GUI",T_WIN32_GUI)
global constant T_WIN32_CONSOLE = 1276 tt_stringF("WIN32_CONSOLE",T_WIN32_CONSOLE)
global constant T_SAFE = 1292 tt_stringF("SAFE",T_SAFE)
global constant T_DATA_EXECUTE = 1344 tt_stringF("DATA_EXECUTE",T_DATA_EXECUTE)
global constant T_UCSTYPE_DEBUG = 1396 tt_stringF("UCSTYPE_DEBUG",T_UCSTYPE_DEBUG)
global constant T_CRASH = 1420 tt_stringF("CRASH",T_CRASH)
global constant T_switch = 1448 tt_stringF("switch",T_switch)
global constant T_fallthru = 1480 tt_stringF("fallthru",T_fallthru)
global constant T_fallthrough = 1500 tt_stringF("fallthrough",T_fallthrough)
global constant T_jump_table = 1544 tt_stringF("jump_table",T_jump_table)
global constant T_case = 1560 tt_stringF("case",T_case)
global constant T_default = 1584 tt_stringF("default",T_default)
global constant T_break = 1604 tt_stringF("break",T_break)
global constant T_continue = 1628 tt_stringF("continue",T_continue)
global constant T_strict = 1652 tt_stringF("strict",T_strict)
global constant T_namespace = 1688 tt_stringF("namespace",T_namespace)
--DEV ilASM additions:
global constant T_e_all = 1708 tt_stringF("e_all",T_e_all)
global constant T_byte = 1720 tt_stringF("byte",T_byte)
global constant T_word = 1736 tt_stringF("word",T_word)
global constant T_dword = 1756 tt_stringF("dword",T_dword) -- see also Z_dword below
global constant T_qword = 1780 tt_stringF("qword",T_qword)
--global constant T_tbyte = 1780 tt_stringF("tbyte",T_tbyte) -- I'm with OllyDbg here [== misnamed "tword" of fasm]
global constant T_eax = 1792 tt_stringF("eax",T_eax)
global constant T_ebx = 1804 tt_stringF("ebx",T_ebx)
global constant T_ecx = 1816 tt_stringF("ecx",T_ecx)
global constant T_edx = 1828 tt_stringF("edx",T_edx)
global constant T_ebp = 1836 tt_stringF("ebp",T_ebp)
global constant T_esp = 1848 tt_stringF("esp",T_esp)
global constant T_esi = 1856 tt_stringF("esi",T_esi)
global constant T_edi = 1864 tt_stringF("edi",T_edi)
global constant T_r8d = 1876 tt_stringF("r8d",T_r8d)
global constant T_r9d = 1888 tt_stringF("r9d",T_r9d)
global constant T_r10d = 1904 tt_stringF("r10d",T_r10d)
global constant T_r11d = 1916 tt_stringF("r11d",T_r11d)
global constant T_r12d = 1928 tt_stringF("r12d",T_r12d)
global constant T_r13d = 1940 tt_stringF("r13d",T_r13d)
global constant T_r14d = 1952 tt_stringF("r14d",T_r14d)
global constant T_r15d = 1964 tt_stringF("r15d",T_r15d)
global constant T_al = 1972 tt_stringF("al",T_al)
global constant T_cl = 1980 tt_stringF("cl",T_cl)
global constant T_dl = 1988 tt_stringF("dl",T_dl)
global constant T_bl = 1996 tt_stringF("bl",T_bl)
global constant T_ah = 2004 tt_stringF("ah",T_ah)
global constant T_ch = 2012 tt_stringF("ch",T_ch)
global constant T_dh = 2020 tt_stringF("dh",T_dh)
global constant T_bh = 2028 tt_stringF("bh",T_bh)
global constant T_spl = 2040 tt_stringF("spl",T_spl)
global constant T_bpl = 2052 tt_stringF("bpl",T_bpl)
global constant T_sil = 2064 tt_stringF("sil",T_sil)
global constant T_dil = 2076 tt_stringF("dil",T_dil)
global constant T_r8l = 2084 tt_stringF("r8l",T_r8l)
global constant T_r9l = 2092 tt_stringF("r9l",T_r9l)
global constant T_r10l = 2100 tt_stringF("r10l",T_r10l)
global constant T_r11l = 2108 tt_stringF("r11l",T_r11l)
global constant T_r12l = 2116 tt_stringF("r12l",T_r12l)
global constant T_r13l = 2124 tt_stringF("r13l",T_r13l)
global constant T_r14l = 2132 tt_stringF("r14l",T_r14l)
global constant T_r15l = 2140 tt_stringF("r15l",T_r15l)
-- (r8b..r15b are exactly the same as r8l..r15l)
global constant T_r8b = 2148 tt_stringF("r8b",T_r8b)
global constant T_r9b = 2156 tt_stringF("r9b",T_r9b)
global constant T_r10b = 2164 tt_stringF("r10b",T_r10b)
global constant T_r11b = 2172 tt_stringF("r11b",T_r11b)
global constant T_r12b = 2180 tt_stringF("r12b",T_r12b)
global constant T_r13b = 2188 tt_stringF("r13b",T_r13b)
global constant T_r14b = 2196 tt_stringF("r14b",T_r14b)
global constant T_r15b = 2204 tt_stringF("r15b",T_r15b)
global constant T_ax = 2212 tt_stringF("ax",T_ax)
global constant T_cx = 2220 tt_stringF("cx",T_cx)
global constant T_dx = 2228 tt_stringF("dx",T_dx)
global constant T_bx = 2236 tt_stringF("bx",T_bx)
global constant T_sp = 2240 tt_stringF("sp",T_sp)
global constant T_bp = 2244 tt_stringF("bp",T_bp)
global constant T_si = 2248 tt_stringF("si",T_si)
global constant T_di = 2252 tt_stringF("di",T_di)
global constant T_r8w = 2260 tt_stringF("r8w",T_r8w)
global constant T_r9w = 2268 tt_stringF("r9w",T_r9w)
global constant T_r10w = 2276 tt_stringF("r10w",T_r10w)
global constant T_r11w = 2284 tt_stringF("r11w",T_r11w)
global constant T_r12w = 2292 tt_stringF("r12w",T_r12w)
global constant T_r13w = 2300 tt_stringF("r13w",T_r13w)
global constant T_r14w = 2308 tt_stringF("r14w",T_r14w)
global constant T_r15w = 2316 tt_stringF("r15w",T_r15w)
global constant T_rax = 2328 tt_stringF("rax",T_rax)
global constant T_rbx = 2340 tt_stringF("rbx",T_rbx)
global constant T_rcx = 2352 tt_stringF("rcx",T_rcx)
global constant T_rdx = 2364 tt_stringF("rdx",T_rdx)
global constant T_rbp = 2372 tt_stringF("rbp",T_rbp)
global constant T_rsp = 2384 tt_stringF("rsp",T_rsp)
global constant T_rsi = 2392 tt_stringF("rsi",T_rsi)
global constant T_rdi = 2400 tt_stringF("rdi",T_rdi)
global constant T_r8 = 2404 tt_stringF("r8",T_r8)
global constant T_r9 = 2408 tt_stringF("r9",T_r9)
global constant T_r10 = 2412 tt_stringF("r10",T_r10)
global constant T_r11 = 2416 tt_stringF("r11",T_r11)
global constant T_r12 = 2420 tt_stringF("r12",T_r12)
global constant T_r13 = 2424 tt_stringF("r13",T_r13)
global constant T_r14 = 2428 tt_stringF("r14",T_r14)
global constant T_r15 = 2432 tt_stringF("r15",T_r15)
global constant T_lea = 2444 tt_stringF("lea",T_lea)
global constant T_mov = 2456 tt_stringF("mov",T_mov)
global constant T_add = 2468 tt_stringF("add",T_add)
global constant T_adc = 2476 tt_stringF("adc",T_adc)
global constant T_sbb = 2488 tt_stringF("sbb",T_sbb)
global constant T_sub = 2500 tt_stringF("sub",T_sub)
-- (T_and, T_or, T_xor already defined, using the same ttidx is fine)
global constant T_cmp = 2512 tt_stringF("cmp",T_cmp)
global constant T_test = 2528 tt_stringF("test",T_test)
global constant T_rol = 2540 tt_stringF("rol",T_rol)
global constant T_ror = 2548 tt_stringF("ror",T_ror)
global constant T_rcl = 2556 tt_stringF("rcl",T_rcl)
global constant T_rcr = 2564 tt_stringF("rcr",T_rcr)
global constant T_shl = 2576 tt_stringF("shl",T_shl)
global constant T_shr = 2584 tt_stringF("shr",T_shr)
global constant T_sar = 2596 tt_stringF("sar",T_sar)
global constant T_inc = 2600 tt_stringF("inc",T_inc)
global constant T_dec = 2608 tt_stringF("dec",T_dec)
global constant T_push = 2620 tt_stringF("push",T_push)
global constant T_pop = 2632 tt_stringF("pop",T_pop)