-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathHuman-Friendly Function Names.i7x
More file actions
883 lines (668 loc) · 49 KB
/
Copy pathHuman-Friendly Function Names.i7x
File metadata and controls
883 lines (668 loc) · 49 KB
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
Version 2 of Human-Friendly Function Names (for Glulx only) by Brady Garvin begins here.
"Facilities for printing and parsing human-friendly names for Glulx functions."
Include Compiler Version Checks by Brady Garvin.
Include Runtime Checks by Brady Garvin.
Include Low-Level Operations by Brady Garvin.
Include Low-Level Text by Brady Garvin.
Include Low-Level Linked Lists by Brady Garvin.
Include Low-Level Hash Tables by Brady Garvin.
Use authorial modesty.
Book "Copyright and License"
[Copyright 2013 Brady J. Garvin]
[This extension is released under the Creative Commons Attribution 3.0 Unported License (CC BY 3.0) so that it can qualify as a public Inform extension. See the LICENSE file included in the release for further details.]
Book "Extension Information"
Chapter "Use Options" - unindexed
Use a function name hash table size of at least 2311 translates as (- Constant HFFN_FUNCTION_NAME_HASH_SIZE = {N}; -).
To decide what number is the function name hash table size: (- HFFN_FUNCTION_NAME_HASH_SIZE -).
Chapter "Rulebooks"
The function name setup rulebook is a rulebook.
The function-naming rulebook is a rulebook.
Book "Phrase Stubs"
[@]
Chapter "Routine Kernel Guessing might be Unavailable without GRIF" (for use without Glulx Runtime Instrumentation Framework by Brady Garvin)
Section "Routine Kernel Guessing is Unavailable without GRIF or Debug File Parsing" (for use without Debug File Parsing by Brady Garvin)
To guess the routine kernel for (A - a sayable value) (this is guessing a routine kernel):
do nothing.
Book "Lazy Initialization" - unindexed
[@]
Chapter "Lazily Initializing Shell-and-Kernel Storage" - unindexed
Shell-and-kernel storage initialized is a truth state that varies. Shell-and-kernel storage initialized is false.
To ensure that the shell-and-kernel storage is initialized (this is initializing the shell-and-kernel storage as necessary):
if shell-and-kernel storage initialized is false:
now shell-and-kernel storage initialized is true;
allocate permanent hash tables for routine shells and kernels.
Chapter "Lazily Initializing Human-Friendly Function Names" - unindexed
Human-friendly function names initialized is a truth state that varies. Human-friendly function names initialized is false.
To ensure that the human-friendly function names are initialized (this is initializing the human-friendly function names as necessary):
ensure that the shell-and-kernel storage is initialized;
if human-friendly function names initialized is false:
now human-friendly function names initialized is true;
traverse the function name setup rulebook;
traverse the function-naming rulebook.
Book "Permanent Hash Tables"
Chapter "Rule Hash Tables" - unindexed
[Map a function address to a text extracted from the I6 routine RulePrintingRule.]
The rule name hash table is a permanent hash table that varies.
[Map a canonical rule name to a function address.]
The rule lookup hash table is a permanent hash table that varies.
A function name setup rule (this is the allocate permanent hash tables for rule names rule):
now the rule name hash table is a new permanent hash table with the function name hash table size buckets;
now the rule lookup hash table is a new permanent hash table with the function name hash table size buckets.
Section "Rule Hash Table Accessors" - unindexed
To decide what text is the name for the rule at address (A - a number) (this is determining the name of a rule):
ensure that the human-friendly function names are initialized;
decide on the first text value matching the key A in the rule name hash table or "" if there are no matches.
To decide what linked list is the list of function addresses for the rules with the canonical name (T - some text) (this is determining the rules matching a name):
ensure that the human-friendly function names are initialized;
let the result be an empty linked list;
repeat with the address running through the number values matching the textual key T in the rule lookup hash table:
push the key address onto the result;
decide on the result.
Section "Rule Hash Table Mutators"
To give the rule at address (A - a number) the rule name (T - some text) (this is giving a function a rule name):
insert the key A and the value T into the rule name hash table;
let the canonical input form be the canonical input form of the function name T;
insert the textual key the canonical input form and the value A into the rule lookup hash table.
Chapter "Phrase Hash Tables" - unindexed
[Map a function address to a text extracted from the I6 Closure_* arrays or else a phrase preamble.]
The phrase name hash table is a permanent hash table that varies.
[Map a canonical phrase name to a function address.]
The phrase lookup hash table is a permanent hash table that varies.
A function name setup rule (this is the allocate permanent hash tables for phrase names rule):
now the phrase name hash table is a new permanent hash table with the function name hash table size buckets;
now the phrase lookup hash table is a new permanent hash table with the function name hash table size buckets.
Section "Phrase Hash Table Accessors" - unindexed
To decide what text is the name for the phrase function at address (A - a number) (this is determining the name of a phrase):
ensure that the human-friendly function names are initialized;
decide on the first text value matching the key A in the phrase name hash table or "" if there are no matches.
To decide what linked list is the list of function addresses for the phrases with the canonical name (T - some text) (this is determining the phrases matching a name):
ensure that the human-friendly function names are initialized;
let the result be an empty linked list;
repeat with the address running through the number values matching the textual key T in the phrase lookup hash table:
push the key address onto the result;
decide on the result.
Section "Phrase Hash Table Mutators"
To give the phrase function at address (A - a number) the phrase name (T - some text) (this is giving a function a phrase name):
insert the key A and the value T into the phrase name hash table;
let the canonical input form be the canonical input form of the function name T;
insert the textual key the canonical input form and the value A into the phrase lookup hash table.
Chapter "Routine Hash Tables" - unindexed
[Map a function address to a text provided by something like the extension I6 Routine Names.]
The routine name hash table is a permanent hash table that varies.
[Map a I6 routine name to a function address.]
The routine lookup hash table is a permanent hash table that varies.
[Map a veneer routine's function address to a truth state, true if the routine is known to be overridden, false if it is known not to be. Non-veneer routines should not be keys.]
The veneer routine override hash table is a permanent hash table that varies.
[Map a function address to a text that describes the routine's purpose, e.g. "displaying a box quote" for the I6 routine Box__Routine.]
The function annotation hash table is a permanent hash table that varies.
A function name setup rule (this is the allocate permanent hash tables for routine names rule):
now the routine name hash table is a new permanent hash table with the function name hash table size buckets;
now the routine lookup hash table is a new permanent hash table with the function name hash table size buckets;
now the veneer routine override hash table is a new permanent hash table with the function name hash table size buckets;
now the function annotation hash table is a new permanent hash table with the function name hash table size buckets.
Section "Private Routine Hash Table Accessors" - unindexed
To decide what text is the name for the routine at address (A - a number) (this is determining the name of a routine):
ensure that the human-friendly function names are initialized;
decide on the first text value matching the key A in the routine name hash table or "" if there are no matches.
To decide what linked list is the list of function addresses for the routines with the canonical name (T - some text) (this is determining the routines matching a name):
ensure that the human-friendly function names are initialized;
let the result be an empty linked list;
repeat with the address running through the number values matching the textual key T in the routine lookup hash table:
push the key address onto the result;
decide on the result.
Section "Public Routine Hash Table Accessors"
To decide whether the function at address (A - a number) is a veneer routine (this is determining whether a routine is a veneer routine):
ensure that the human-friendly function names are initialized;
decide on whether or not the veneer routine override hash table contains the key A.
To decide whether the function at address (A - a number) is a default veneer routine (this is determining whether a routine is a default veneer routine):
ensure that the human-friendly function names are initialized;
decide on whether or not (the first truth state value matching the key A in the veneer routine override hash table or true if there are no matches) is false.
To decide whether the function at address (A - a number) is an overridden veneer routine (this is determining whether a routine is an overridden veneer routine):
ensure that the human-friendly function names are initialized;
decide on the first truth state value matching the key A in the veneer routine override hash table or false if there are no matches.
To decide what text is the annotation for the function at address (A - a number) (this is determining a veneer routine annotation):
ensure that the human-friendly function names are initialized;
decide on the first text value matching the key A in the function annotation hash table or "" if there are no matches.
Section "Routine Hash Table Mutators"
To give the veneer routine at address (A - a number) the override flag (F - a truth state) and the routine name (T - some text) and the annotation (Z - some text) (this is naming each veneer routine):
insert the key A and the value F into the veneer routine override hash table;
insert the key A and the value T into the routine name hash table;
let the canonical input form be the canonical input form of the function name T;
insert the textual key the canonical input form and the value A into the routine lookup hash table;
insert the key A and the value Z into the function annotation hash table.
To give the routine at address (A - a number) the routine name (T - some text) (this is naming each standard template routine):
insert the key A and the value T into the routine name hash table;
let the canonical input form be the canonical input form of the function name T;
insert the textual key the canonical input form and the value A into the routine lookup hash table.
[@]
Chapter "Routine Shell Hash Tables" - unindexed
[Map a function address to the address of the routine shell that encloses it. Non-kernels should not be keys.]
The routine shell hash table is a permanent hash table that varies.
[Map a function address to the address of the routine kernel that it encloses. Non-shells should not be keys.]
The routine kernel hash table is a permanent hash table that varies.
To allocate permanent hash tables for routine shells and kernels (this is allocating permanent hash tables for routine shells and kernels):
now the routine shell hash table is a new permanent hash table with the function name hash table size buckets;
now the routine kernel hash table is a new permanent hash table with the function name hash table size buckets.
Section "Routine Shell Hash Table Accessors"
To decide what number is the routine shell address of the function at address (A - a number) (this is determining a routine shell):
ensure that the shell-and-kernel storage is initialized;
decide on the first number value matching the key A in the routine shell hash table or zero if there are no matches.
To decide what number is the routine kernel address of the function at address (A - a number) (this is determining a routine kernel):
ensure that the shell-and-kernel storage is initialized;
decide on the first number value matching the key A in the routine kernel hash table or zero if there are no matches.
Section "Routine Shell Hash Table Mutators"
To associate the routine shell at address (A - a number) with the routine kernel at address (B - a number) (this is associating a routine shell with a routine kernel):
ensure that the shell-and-kernel storage is initialized;
insert the key A and the value B into the routine kernel hash table;
insert the key B and the value A into the routine shell hash table.
Chapter "Core Hash Tables" - unindexed
[Map a function address to a text that describes it in a standard, maximally unambiguous, human-friendly way.]
The human-friendly function name hash table is a permanent hash table that varies.
A function name setup rule (this is the allocate permanent hash tables for human-friendly function names rule):
now the human-friendly function name hash table is a new permanent hash table with the function name hash table size buckets.
Book "Setup"
[@]
Chapter "Rules" - unindexed
[These magic numbers are fairly sensitive to the workings of both ni and the I6N compiler.]
To repeat with (I - a nonexisting number variable) running through the rule-printing branch addresses begin -- end: (-
for({I} = RulePrintingRule + 79: (llo_getInt({I}) == 624492800) && (llo_getShort({I} + 9) == 29187): {I} = {I} + 18)
-).
To decide what number is the function address of the rule-printing branch at address (A - a number): (- llo_getField({A}, 1) -).
To decide what text is the name of the rule-printing branch at address (A - a number): (- llo_getInt({A} + 11) -).
A function-naming rule (this is the name rules rule):
repeat with the rule-printing branch address running through the rule-printing branch addresses:
let the function address be the function address of the rule-printing branch at address rule-printing branch address;
if the name for the rule at address function address is empty:
let the name be the name of the rule-printing branch at address rule-printing branch address;
give the rule at address function address the rule name name.
[@]
Chapter "Phrases" - unindexed
[These magic numbers are fairly sensitive to the workings of both ni and the I6N compiler.]
To repeat with (I - a nonexisting number variable) running through the phrase addresses begin -- end: (-
for({I} = Closure_0: (llo_getField((+ the phrase that guarantees that we have at least one named phrase +), 1))({I}): {I} = {I} + 12)
-).
To decide what number is the function address of the phrase at address (A - a number): (- llo_getField({A}, 1) -).
To decide what number is the name address of the phrase at address (A - a number): (- llo_getField({A}, 2) -).
To decide what text is the name of the phrase at address (A - a number): (- llo_getField({A}, 2) -).
To decide whether address (A - a number) could contain a phrase (this is the phrase that guarantees that we have at least one named phrase):
let the function address be the function address of the phrase at address A;
unless address function address could contain a function:
decide no;
let the name address be the name address of the phrase at address A;
unless address name address could contain a string:
decide no;
decide yes.
A function-naming rule (this is the name phrases rule):
repeat with the phrase address running through the phrase addresses:
let the function address be the function address of the phrase at address phrase address;
let the name be the name of the phrase at address phrase address;
give the phrase function at address function address the phrase name name.
Chapter "Main" - unindexed
To decide what number is the address of I6_Main: (- Main -).
A function-naming rule (this is the name main rule):
if the address of I6_Main is not zero:
insert the key the address of I6_Main and the value "the main story routine" into the human-friendly function name hash table;
insert the textual key "main" and the value the address of I6_Main into the routine lookup hash table;
insert the textual key "main routine" and the value the address of I6_Main into the routine lookup hash table;
insert the textual key "main story routine" and the value the address of I6_Main into the routine lookup hash table.
Book "Common Substrings" - unindexed
The source text rule keyword is some text that varies.
The source text definite article is some text that varies.
The source text indefinite article for vowel sounds is some text that varies.
The source text indefinite article for consonant sounds is some text that varies.
The zeroth canonically removed function name prefix is some text that varies.
The first canonically removed function name prefix is some text that varies.
The second canonically removed function name prefix is some text that varies.
The third canonically removed function name prefix is some text that varies.
The fourth canonically removed function name prefix is some text that varies.
The fifth canonically removed function name prefix is some text that varies.
The sixth canonically removed function name prefix is some text that varies.
[@] The kernel prefix is some text that varies.
[@] The kernel suffix is some text that varies.
A function name setup rule (this is the allocate the synthetic text for the routine shell prefix and suffix rule):
now the source text rule keyword is a new permanent synthetic text copied from "rule";
now the source text definite article is a new permanent synthetic text copied from "the ";
now the source text indefinite article for vowel sounds is a new permanent synthetic text copied from "an ";
now the source text indefinite article for consonant sounds is a new permanent synthetic text copied from "a ";
now the zeroth canonically removed function name prefix is a new permanent synthetic text copied from "overridden i6 veneer routine ";
now the first canonically removed function name prefix is a new permanent synthetic text copied from "overridden veneer routine ";
now the second canonically removed function name prefix is a new permanent synthetic text copied from "overridden i6 routine ";
now the third canonically removed function name prefix is a new permanent synthetic text copied from "i6 veneer routine ";
now the fourth canonically removed function name prefix is a new permanent synthetic text copied from "veneer routine ";
now the fifth canonically removed function name prefix is a new permanent synthetic text copied from "i6 routine ";
now the sixth canonically removed function name prefix is a new permanent synthetic text copied from "routine ";
[@] now the kernel prefix is a new permanent synthetic text copied from "kernel of '";
[@] now the kernel suffix is a new permanent synthetic text copied from "'".
Book "Rewriting States" - unindexed
A function name rewrite state is a kind of value.
The function name rewrite states are transitioning to gobble whitespace, transitioning after function name whitespace, and transitioning after a function name symbol.
The specification of a function name rewrite state is "Function name rewrite states are used inside Human-Friendly Function Names to represent the various states that its function name canonicalizer, specifically the part dealing with punctuation and whitespace, can be in. Transitioning to gobble whitespace means that whitespace is being removed completely, transitioning after function name whitespace means that one or more whitespace characters in the middle of a function name are being collapsed into a single space, and transitioning after a function name symbol means that no whitespace transformations are ongoing."
Book "Output"
Chapter "Canonical Output Forms of Rule and Phrase Names" - unindexed
To destructively say the canonical output form of the synthetic rule or phrase name (T - some text) with the article flag set to (F - a truth state) (this is destructively saying the canonical output form of a synthetic rule or phrase name):
let the length be the length of the synthetic text T;
if the length is at least two:
let the second character code be the character code at index two of the synthetic text T;
if the second character code is the Latin-1 character code second character code downcased:
let the first character code be the character code at index one of the synthetic text T;
now the first character code is the Latin-1 character code first character code downcased;
write the character code first character code to index one of the synthetic text T;
if F is true and the synthetic text T ends with the synthetic text the source text rule keyword:
unless the synthetic text T begins with the synthetic text the source text definite article or the synthetic text T begins with the synthetic text the source text indefinite article for vowel sounds or the synthetic text T begins with the synthetic text the source text indefinite article for consonant sounds:
say "[the source text definite article]";
let the current state be transitioning to gobble whitespace;
repeat with the character code running through the character codes in the synthetic text T:
if the character code is:
-- 32: [space]
if the current state is transitioning after a function name symbol:
now the current state is transitioning after function name whitespace;
-- 40: [open parenthesis]
say "[if the current state is transitioning after function name whitespace] [end if][the character code converted to a unicode character]";
now the current state is transitioning to gobble whitespace;
-- 41: [close parenthesis]
say "[the character code converted to a unicode character]";
now the current state is transitioning after a function name symbol;
-- otherwise:
say "[if the current state is transitioning after function name whitespace] [end if][the character code converted to a unicode character]";
now the current state is transitioning after a function name symbol.
To decide what text is the canonical output form of the rule or phrase name (T - some text), adding an article if necessary (this is determining the canonical output form of a rule or phrase name):
let the source be a new synthetic text copied from T;
let the maximum length be the length of the synthetic text source plus the length of the synthetic text source text definite article;
let the destination be a new uninitialized permanent synthetic text with length maximum length characters;
overwrite the synthetic text destination with the text printed when we destructively say the canonical output form of the synthetic rule or phrase name source with the article flag set to whether or not adding an article if necessary;
delete the synthetic text source;
decide on the destination.
Chapter "Canonical Output Forms of Routine Names" - unindexed
To decide what text is the canonical output form of the routine name (T - some text) for the routine at address (A - a number) (this is determining the canonical output form of a routine name):
let the permanent linked list vertex be the first match for the key A in the veneer routine override hash table;
let the annotation be the annotation for the function at address A;
let the length be the length of T plus the length of the annotation plus 36;
let the result be a new uninitialized permanent synthetic text with length length characters;
overwrite the synthetic text result with the text printed when we say "the [if the permanent linked list vertex is null]I6[otherwise if the truth state value of the permanent linked list vertex is true]overridden I6 veneer[otherwise]I6 veneer[end if] routine [T converted to some text][if the annotation is not empty] ([the annotation])[end if]";
decide on the result.
Chapter "Human-Friendly Output Names"
To decide whether the function at address (A - a number) already has a human-friendly name (this is determining whether a function already has a human-friendly name):
decide on whether or not the rule name hash table contains the key A or the phrase name hash table contains the key A or the routine shell hash table contains the key A or the routine name hash table contains the key A.
To decide what text is the human-friendly name for the function at address (A - a number) (this is determining the human-friendly name of a function):
ensure that the human-friendly function names are initialized;
let the result be the first text value matching the key A in the human-friendly function name hash table or "" if there are no matches;
if the result is not empty:
decide on the result;
now the result is the name for the rule at address A;
if the result is not empty:
now the result is the canonical output form of the rule or phrase name result, adding an article if necessary;
otherwise:
now the result is the name for the phrase function at address A;
if the result is not empty:
now the result is the canonical output form of the rule or phrase name result;
otherwise:
[@]
let the routine shell address be the routine shell address of the function at address A;
if the routine shell address is not zero:
let the shell name be the human-friendly name for the function at address routine shell address;
let the length be 16 plus the length of the synthetic text shell name;
now the result is a new uninitialized permanent synthetic text with length length characters;
overwrite the synthetic text result with the text printed when we say "the kernel of '[the shell name]'";
otherwise:
now the result is the name for the routine at address A;
if the result is not empty:
now the result is the canonical output form of the routine name result for the routine at address A;
otherwise:
decide on "an unnamed rule or phrase";
insert the key A and the value result into the human-friendly function name hash table;
decide on the result.
Book "Input"
Chapter "Removing Parentheticals and Normalizing Spacing" - unindexed
To decide whether (C - a number) is a character code for punctuation: (- (({C} >= 33) && ({C} <= 47) || ({C} >= 58) && ({C} <= 64) || ({C} >= 91) && ({C} <= 96) || ({C} >= 123) && ({C} <= 126)) -).
To say (T - some text) after removing parentheticals and normalizing spacing (this is saying some text after removing parentheticals and normalizing spacing):
let the current state be transitioning to gobble whitespace;
let the nesting level be zero;
repeat with the character code running through the character codes in the synthetic text T:
if the character code is:
-- 32: [space]
if the nesting level is zero and the current state is transitioning after a function name symbol:
now the current state is transitioning after function name whitespace;
-- 40: [open parenthesis]
increment the nesting level;
-- 41: [close parenthesis]
decrement the nesting level;
-- otherwise:
if the nesting level is zero:
let the punctuation flag be whether or not the character code is a character code for punctuation;
say "[if the punctuation flag is true or the current state is transitioning after function name whitespace] [end if][the character code converted to a unicode character]";
if the punctuation flag is true:
now the current state is transitioning after function name whitespace;
otherwise:
now the current state is transitioning after a function name symbol.
To decide what text is the synthetic text (T - some text) after removing parentheticals and normalizing spacing (this is removing parentheticals and normalizing spacing):
let the length be the length of the synthetic text T;
let the destination be a new uninitialized permanent synthetic text with length two times length characters;
overwrite the synthetic text destination with the text printed when we say T after removing parentheticals and normalizing spacing;
decide on the destination.
Chapter "The Canonical Input Form" - unindexed
To decide what text is the canonical input form of the function name (T - some text) (this is determining the canonical input form of a function name):
ensure that the human-friendly function names are initialized;
let the downcased original be a new synthetic text copied from T;
downcase the synthetic text downcased original;
let the result be the synthetic text downcased original after removing parentheticals and normalizing spacing;
delete the synthetic text downcased original;
[Performance: These substring operations could be faster, if profiling shows a bottleneck here.]
possibly remove the synthetic text prefix source text definite article from the beginning of the synthetic text result;
possibly remove the synthetic text prefix source text indefinite article for vowel sounds from the beginning of the synthetic text result;
possibly remove the synthetic text prefix source text indefinite article for consonant sounds from the beginning of the synthetic text result;
possibly remove the synthetic text prefix the zeroth canonically removed function name prefix from the beginning of the synthetic text result;
possibly remove the synthetic text prefix the first canonically removed function name prefix from the beginning of the synthetic text result;
possibly remove the synthetic text prefix the second canonically removed function name prefix from the beginning of the synthetic text result;
possibly remove the synthetic text prefix the third canonically removed function name prefix from the beginning of the synthetic text result;
possibly remove the synthetic text prefix the fourth canonically removed function name prefix from the beginning of the synthetic text result;
possibly remove the synthetic text prefix the fifth canonically removed function name prefix from the beginning of the synthetic text result;
possibly remove the synthetic text prefix the sixth canonically removed function name prefix from the beginning of the synthetic text result;
decide on the result.
Chapter "General Lookup"
To decide what linked list is the list of addresses matching the function name (T - some text) (this is determining the functions matching a name):
ensure that the human-friendly function names are initialized;
let the downcased original be a new synthetic text copied from T;
downcase the synthetic text downcased original;
let the name be the synthetic text downcased original after removing parentheticals and normalizing spacing;
delete the synthetic text downcased original;
[These substring operations could be faster, if profiling shows a bottleneck here.]
possibly remove the synthetic text prefix source text definite article from the beginning of the synthetic text name;
possibly remove the synthetic text prefix source text indefinite article for vowel sounds from the beginning of the synthetic text name;
possibly remove the synthetic text prefix source text indefinite article for consonant sounds from the beginning of the synthetic text name;
let the result be an empty linked list;
[@]
if the synthetic text name begins with the synthetic text kernel prefix and the synthetic text name ends with the synthetic text kernel suffix:
let the prefix length be the length of the synthetic text kernel prefix;
let the suffix length be the length of the synthetic text kernel suffix;
remove prefix length characters from the beginning of the synthetic text name;
remove suffix length characters from the end of the synthetic text name;
let the shell list be the list of addresses matching the function name name;
repeat with the routine shell address running through the number keys of the shell list:
guess the routine kernel for the routine shell address;
let the routine kernel address be the routine kernel address of the function at address routine shell address;
if the routine kernel address is not zero:
push the key routine kernel address onto the result;
decide on the result;
let the rules-and-phrases flag be true;
let the non-veneer routines flag be true;
let the default veneer routines flag be true;
if we successfully remove the synthetic text prefix the zeroth canonically removed function name prefix from the beginning of the synthetic text name or we successfully remove the synthetic text prefix the first canonically removed function name prefix from the beginning of the synthetic text name or we successfully remove the synthetic text prefix the second canonically removed function name prefix from the beginning of the synthetic text name:
now the rules-and-phrases flag is false;
now the non-veneer routines flag is false;
now the default veneer routines flag is false;
if we successfully remove the synthetic text prefix the third canonically removed function name prefix from the beginning of the synthetic text name or we successfully remove the synthetic text prefix the fourth canonically removed function name prefix from the beginning of the synthetic text name:
now the rules-and-phrases flag is false;
now the non-veneer routines flag is false;
if we successfully remove the synthetic text prefix the fifth canonically removed function name prefix from the beginning of the synthetic text name or we successfully remove the synthetic text prefix the sixth canonically removed function name prefix from the beginning of the synthetic text name:
now the rules-and-phrases flag is false;
if the rules-and-phrases flag is true:
let the address list be the list of function addresses for the rules with the canonical name name;
repeat with the address running through the number keys of the address list:
push the key address onto the result;
delete the address list;
now the address list is the list of function addresses for the phrases with the canonical name name;
repeat with the address running through the number keys of the address list:
push the key address onto the result;
delete the address list;
let the address list be the list of function addresses for the routines with the canonical name name;
repeat with the address running through the number keys of the address list:
if the non-veneer routines flag is true or the function at address address is a veneer routine:
if the default veneer routines flag is true or the function at address address is an overridden veneer routine:
push the key address onto the result;
delete the address list;
decide on the result.
Book "Shielding" (for use with Glulx Runtime Instrumentation Framework by Brady Garvin)
A GRIF shielding rule (this is the shield human-friendly function name rules and phrases rule):
shield determining the name of a rule against instrumentation;
shield determining the rules matching a name against instrumentation;
shield determining the name of a phrase against instrumentation;
shield determining the phrases matching a name against instrumentation;
shield determining the name of a routine against instrumentation;
shield determining the routines matching a name against instrumentation;
shield determining whether a routine is a veneer routine against instrumentation;
shield determining whether a routine is an overridden veneer routine against instrumentation;
shield determining a veneer routine annotation against instrumentation;
shield determining a routine shell against instrumentation;
shield determining a routine kernel against instrumentation;
shield associating a routine shell with a routine kernel against instrumentation;
shield determining the human-friendly name of a function against instrumentation;
shield determining the canonical input form of a function name against instrumentation;
shield determining the functions matching a name against instrumentation.
Human-Friendly Function Names ends here.
---- DOCUMENTATION ----
Chapter: Synopsis
Human-Friendly Function Names allows debugging extensions to print rules,
phrases, and other functions in a form that the author is likely to understand,
such as "instead of jumping", "the start in the correct scenes rule",
"doubling", or the "the I6 routine ScopeCeiling", even when the debugging tool
doesn't know the kind of the function. The extension also makes it possible to
parse these names.
Details are in the following chapters.
Chapter: Usage
Section: Introduction
By the time a story has been compiled for the Glulx virtual machine, every bit
of source text capable of changing the world at runtime has been stashed away in
one or more Glulx functions. These functions correspond almost exactly to
Inform 6 routines, some of which come from I7 rules or I7 phrases. For each
function and each way of thinking about a function, Human-Friendly Function
Names tracks a set of names. For instance, the function that implements this
rule:
Instead of waving hands: say "You wave hello."
would be called by one name,
"instead of waving hands"
when we think about it as a rule, but perhaps
"the I6 routine R_2748"
when we regard it as an I6 routine. It would have no known names if we treated
it as a phrase, since it isn't one.
[@]
There are some complications, first of all because rules and phrases might
compile to two I6 routines instead of one. For example, the rule
Instead of singing: let a temporary value be some indexed text.
will normally be converted to an outer routine---"R_2750" perhaps---that
reserves memory for the indexed text, invokes an inner routine with a name like
"R_SHELL_0", and then frees the memory up again. Here we call the outer routine
a "routine shell" and the inner one a "routine kernel" (though this is a little
confusing because the kernel has the word "SHELL" in its name). The shell is
named normally, that is
"instead of singing"
as a rule and
"the I6 routine R_2750"
as an I6 routine, while the kernel is named based on the shell:
"the kernel of 'instead of singing'"
and
"the I6 routine R_SHELL_0"
Another complication is that certain I6 routines can be overridden, so that,
despite having the same name, they no may longer do what an I6 programmer would
expect. These are the veneer routines documented in the Inform technical
manual:
"The 'veneer' is a thin section of code generated by Inform as an
intermediate layer between the code compiled from the source, and the
[virtual machine] itself: like the veneer on a table, it gilds the
surface of the [virtual machine], or so the term is supposed to mean."
Human-Friendly Function Names treats veneer routines specially, calling them out
as such and indicating whether or not they are overridden. To illustrate,
CA__Pr might be named
"the overridden I6 veneer routine CA__Pr (calling a property value)"
Note also the parenthetical annotation, which is included because the internal
names for veneer routines can be fairly cryptic to the uninitiated.
Section: The contents of the database
We should mention up front that Human-Friendly Function Names only goes so far
in populating its database. Rule names, for instance, are entered
automatically, as are phrase names given by "this is". But the presence of
other function information depends on whether we include code capable of finding
it and storing it in the database. There are currently three examples of such
code:
The extension I6 Routine Names is little more than a table of commonly appearing
I6 routines, including all of the veneer routines. When it detects the presence
of Human-Friendly Function Names, it stores its information in the database.
The Glulx Runtime Instrumentation Framework includes I6 Routine Names and also
notes any routine shell/kernel pairs that it comes across during
instrumentation.
Debug File Parsing requires a bit of setup and slows down the story when it
loads its data, but it can name every statically compiled function in a story,
which for most stories is all of them. It can also detect routine shell/kernel
pairs on its own, or, when the Glulx Runtime Instrumentation Framework is also
included, using a more robust hybrid algorithm.
Section: Looking up a name (and related information) by function address
To obtain a function name, we request
the human-friendly name for the function at address (A - a number)
where A is the memory address of the function. This phrase will decide on the
name most likely to make sense to an I7 programmer: a rule name if one is
available, a phrase name if not, a routine kernel name if neither exists, an I6
routine name after that, and, if all else fails, the text "an unnamed rule or
phrase". Ties between names in the same category are broken by choosing the
name that was given last.
We can also ask whether a function is a veneer routine:
if the function at address (A - a number) is a veneer routine:
....
or specifically an overridden veneer routine:
if the function at address (A - a number) is an overridden veneer routine:
....
on non-overridden veneer routine:
if the function at address (A - a number) is a default veneer routine:
....
If the function is a veneer routine, the phrase
the annotation for the function at address (A - a number)
will decide on some text that describes the routine's purpose in English.
Section: Looking up a function address by name
Similarly, given a name, we can request a set of function addresses:
the list of addresses matching the function name (T - some text)
[@]
(Note that the phrase takes text, not indexed text. If we need to compute the
name at runtime, we must use synthetic text from the extension Low-Level Text.)
The result is a new linked list (which we are responsible for deleting) (see the
extension Low-Level Linked Lists) where each linked list vertex's key is the
address of a function having that name. It is not necessary for the name to be
formatted exactly, nor for it to be the preferred name for a function. For
instance, the rule
Before going through a closed door (called the blocking door):
....
could be identified with
"Before going through a closed door (called the blocking door)"
or
"before going through a closed door"
or even
" beFoRe gOInG tHRoUGH a cLoSEd dOoR( BlOCkInG dOOr ) "
(In the HTML format that Inform generates, the whitespace issues in the last
example might not be visible.)
[@]
Section: Routine shells and kernels
Having the address of a function that might be a kernel, we can ask for
the routine shell address of the function at address (A - a number)
If the function is in fact a kernel and the database knows its shell, this
phrase will return the shell's function address. Otherwise it will return zero.
Likewise, with the address of a possible shell
the routine kernel address of the function at address (A - a number)
is the function address of its kernel, if a kernel is known to exist, and zero
otherwise. Authors using either the Glulx Runtime Instrumentation Framework
(GRIF) or Debug File Parsing (or both) can write the phrase
guess the routine kernel for (A - a sayable value)
with A being a function address to guarantee that, if a kernel of A exists, it
will be known. The similar phrase
guess the routine shell for (A - a sayable value)
should guarantee that a request for a routine shell will return one if one
exists. It is only provided by Debug File Parsing, but becomes more robust when
GRIF is available.
Section: Updating human-friendly function names
If we would like to add function names of our own to the database, we must write
a function-naming rule. For example:
A function-naming rule (this is the name quux rule):
....
The function-naming rulebook is traversed exactly once, whenever the first
database query is made. (If the Glulx Runtime Instrumentation Framework is
included, the first query might be made in a instrumentation context, where
certain normal Inform operations are unsafe. See that extension's
documentation.)
Within a function-naming rule we have four phrases available that should not
otherwise be used. The first,
give the rule at address (A - a number) the rule name (T - some text)
treats A as the address of a rule and assigns a new name. Such names should
usually end with the word "rule", as in "the block thinking rule".
The second is similar:
give the phrase function at address (A - a number) the phrase name (T - some text)
The only thing to note here is that A is the address of the function
implementing the phrase, which is different from the address of the phrase data
structure. The extra word "function" is included as a reminder.
Third,
give the veneer routine at address (A - a number) the override flag (F - a truth state) and the routine name (T - some text) and the annotation (Z - some text)
In addition to the function address and a name, veneer routines are expected to
be marked as overridden or not, hence F, and to have an explanation of what they
do, Z. Normally all of this data is taken from I6 Routine Names, and we do not
have to worry about it.
The final one,
give the routine at address (A - a number) the routine name (T - some text)
acts much like the other three, but applies to routines that don't fit in any of
the above categories.
[@]
Section: Updating routine shells and kernels
Just as we can associate names with functions, we can also manually associate
routine shells and routine kernels. The relevant phrase is
associate the routine shell at address (A - a number) with the routine kernel at address (B - a number)
It can be invoked at any time, not just when the function-naming rules are
running.
Section: Some words of caution
[@]
Most text stored by Human-Friendly Function Names is synthetic (see the
extension Low-Level Text). As a consequence, a test like
if the human-friendly name for the function at address 72 is "the I6 routine ShowExtensionVersions":
....
might always be false, even if the I6 routine ShowExtensionVersions is located
at address 72: the two texts will hold the same sequence of characters, but be
located separately in memory, and Inform's "is" will therefore consider them to
be different. Instead of comparing function names with "is", we should write
the condition with "is identical to":
if the human-friendly name for the function at address 72 is identical to "the I6 routine ShowExtensionVersions":
....
Chapter: Requirements, Limitations, and Bugs
This version was tested with Inform 6G60. It may not function under other
versions.
Section: Regarding bugs
If you encounter a bug, check first on the project website
(https://github.com/i7/i7grip) to see whether a newer version of this extension
is available. If, even using the latest version, the fault remains, please file
a bug report: On the website, choose "Issues" from the toolbar and click on "New
Issue".
I will try to respond quickly, at least with an estimate of when the bug might
be fixed, though sometimes I am away from the internet for a week or two at a
time.
Chapter: Acknowledgements
Human-Friendly Function Names was prepared as part of the Glulx Runtime
Instrumentation Project (https://github.com/i7/i7grip).
GRIP owes a great deal to everyone who made Inform possible and everyone who
continues to contribute. I'd like to give especial thanks to Graham Nelson and
Emily Short, not only for their design and coding work, but also for all of the
documentation, both of the language and its internals---it proved indispensable.
I am likewise indebted to everybody who worked to make Glulx and Glk a reality.
Without them, there simply wouldn't have been any hope for this kind of project.
My special thanks to Andrew Plotkin, with further kudos for his work maintaining
the specifications. They proved as essential as Inform's documentation.
The project itself was inspired by suggestions from Ron Newcomb and Esteban
Montecristo on Inform's feature request page. It's only because of their posts
that I ever started. (And here's hoping that late is better than never.)
Esteban Montecristo also made invaluable contributions as an alpha tester. I
cannot thank him enough: he signed on as a beta tester but then quickly
uncovered a slew of problems that forced me to reconsider both the term ``beta''
and my timeline. The impetus for the new, cleaner design and several clues that
led to huge performance improvements are all due to him. Moreover, he
contributed code, since modified to fit the revised framework, for the extension
Verbose Diagnostics.
As for Ron Newcomb, I can credit him for nearly half of the bugs unearthed in
the beta proper, not to mention sound advice on the organization of the
documentation and the extensions. GRIP is much sturdier as a result.
Roger Carbol, Jesse McGrew, Michael Martin, Dan Shiovitz, Johnny Rivera, and
probably several others deserve similar thanks for answering questions on
ifMUD's I6 and I7 channels. I am grateful to Andrew Plotkin, David Kinder, and
others for the same sort of help on intfiction.org.
On top of that, David Kinder was kind enough to accommodate Debug File Parsing
in the Windows IDE; consequently, authors who have a sufficiently recent version
of Windows no longer need to write batch scripts. His help is much appreciated,
particularly because the majority of downloaders are running Windows.
Even with the IDEs creating debug files, setting up symbolic links to those
files can be a chore. Jim Aiken suggested an automated solution, which now
ships with the project.
And preliminary support for authors who want to debug inside a browser stems
from discussion with Erik Temple and Andrew Plotkin; my thanks for their ideas.
Finally, I should take this opportunity to express my gratitude to everyone who
helped me get involved in the IF community. Notable among these people are
Jesse McGrew and Emily Short, not to mention Jacqueline Lott, David Welbourn,
and all of the other Club Floyd attendees.