1 ! ==============================================================================
2 ! INFIX: Support for the optional library debugger extension "Infix".
4 ! Supplied for use with Inform 6 -- Release 6.12.5 -- Serial number 210605
6 ! Copyright Graham Nelson 1993-2004 and David Griffith 2012-2021
8 ! This file is free software: you can redistribute it and/or modify
9 ! it under the terms of the GNU Affero General Public License as
10 ! published by the Free Software Foundation, either version 3 of the
11 ! License, or (at your option) any later version.
13 ! This file is distributed in the hope that it will be useful, but
14 ! WITHOUT ANY WARRANTY; without even the implied warranty of
15 ! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ! Affero General Public License for more details.
18 ! You should have received a copy of the GNU Affero General Public
19 ! License along with this program. If not, see
20 ! https://gnu.org/licenses/
22 ! This file is automatically Included in your game file by "grammar" if you
23 ! supply the -X compiler switch.
24 ! ==============================================================================
28 ! ------------------------------------------------------------------------------
32 Constant INFIXTT_NUMBER 0;
33 Constant INFIXTT_ARRAY 1;
34 Constant INFIXTT_ROUTINE 2;
35 Constant INFIXTT_CONSTANT 3;
36 Constant INFIXTT_DWORD 4;
37 Constant INFIXTT_ACTION 5;
38 Constant INFIXTT_ATTRIBUTE 6;
39 Constant INFIXTT_PROPERTY 7;
40 Constant INFIXTT_GLOBAL 8;
41 Constant INFIXTT_NAMEDOBJECT 9;
42 Constant INFIXTT_SYSFUN 10;
43 Constant INFIXTT_STATICSTRING 11;
44 Constant INFIXTT_LOGICAL 12;
46 Global infix_term_type;
50 Global infix_parsed_lvalue;
51 Array infix_tolowercase -> 256;
53 Array infix_text buffer 126;
55 Array infix_text -> 128;
59 [ InfixPrintAttribute x; print (string) #attribute_names_array-->x; ];
61 [ InfixPrintProperty x; print (property) x; ];
64 [ InfixPrintGIProperty x; print (property) x; ];
67 [ InfixPrintGlobal x; print (string) #global_names_array-->x; ];
69 [ InfixPrintAction x; print (string) #action_names_array-->(x-#lowest_action_number); ];
71 [ InfixPrintRoutine x; print (string) #routine_names_array-->(x-#lowest_routine_number); ];
73 [ InfixPrintConstant x; print (string) #constant_names_array-->(x-#lowest_constant_number); ];
75 [ InfixPrintArray x; print (string) #array_names_array-->(x-#lowest_array_number); ];
77 [ InfixPrintFakeAction x;
78 print (string) #fake_action_names_array-->(x-#lowest_fake_action_number); ];
81 for (n=#lowest_routine_number : n<=#highest_routine_number : n++) {
82 if (x == Symb__Tab(INFIXTT_ROUTINE, n)) {
83 print (InfixPrintRoutine) n; return;
86 print "Routine(", x, ")";
89 [ InfixMatchPrule PrintingRule range1 range2 wa wl t i i2 it2 itlc j k plus;
90 itlc = infix_tolowercase;
92 for (j=0 : j<256 : j++) itlc->j = j;
93 itlc->'A' = 'a'; itlc->'B' = 'b';
94 itlc->'C' = 'c'; itlc->'D' = 'd';
95 itlc->'E' = 'e'; itlc->'F' = 'f';
96 itlc->'G' = 'g'; itlc->'H' = 'h';
97 itlc->'I' = 'i'; itlc->'J' = 'j';
98 itlc->'K' = 'k'; itlc->'L' = 'l';
99 itlc->'M' = 'm'; itlc->'N' = 'n';
100 itlc->'O' = 'o'; itlc->'P' = 'p';
101 itlc->'Q' = 'q'; itlc->'R' = 'r';
102 itlc->'S' = 's'; itlc->'T' = 't';
103 itlc->'U' = 'u'; itlc->'V' = 'v';
104 itlc->'W' = 'w'; itlc->'X' = 'x';
105 itlc->'Y' = 'y'; itlc->'Z' = 'z';
107 switch (PrintingRule) {
109 if (wa->0 == '~') { wl--; wa++; plus = 100; } ! A tilde
110 t = #attribute_names_array;
111 InfixPrintProperty: t = #property_names_array;
113 InfixPrintGIProperty: t = #identifiers_table-->2;
115 InfixPrintAction: t = #action_names_array;
116 InfixPrintFakeAction: t = #fake_action_names_array;
117 InfixPrintGlobal: t = #global_names_array;
118 InfixPrintRoutine: t = #routine_names_array;
119 InfixPrintAction: t = #constant_names_array;
120 InfixPrintArray: t = #array_names_array;
123 i2 = range2-range1; it2 = infix_text+WORDSIZE;
124 for (i=0 : i<=i2 : i++) {
126 infix_text-->0 = 62; @output_stream 3 infix_text;
127 if (t) print (string) t-->i; else PrintingRule(i+range1);
129 #Ifnot; ! TARGET_GLULX
130 if (t) PrintToBuffer(infix_text, 62, t-->i);
131 else PrintToBuffer(infix_text, 62, PrintingRule, i+range1);
134 if (k ~= wl) jump XL;
135 if (itlc->(it2->0) ~= itlc->(wa->0)) jump XL;
136 for (j=1 : j<k : j++)
137 if (itlc->(it2->j) ~= itlc->(wa->j)) jump XL;
138 parsed_number = i + range1 + plus;
146 if (InfixMatchPrule(InfixPrintAction, #lowest_action_number,
147 #highest_action_number, WordAddress(wn), WordLength(wn))) {
148 wn++; infix_lvalue = parsed_number; return 0;
150 if (InfixMatchPrule(InfixPrintFakeAction, #lowest_fake_action_number,
151 #highest_fake_action_number, WordAddress(wn), WordLength(wn))) {
152 wn++; infix_lvalue = parsed_number; return 0;
157 [ InfixRvalueTerm n w i initial_wn wa wl sign base digit dcount;
161 infix_parsed_lvalue = -1;
162 infix_term_type = INFIXTT_NUMBER;
164 w = NextWordStopped();
165 if (w == -1) return -1;
167 wa = WordAddress(wn-1);
168 wl = WordLength(wn-1);
169 if (wa->0 == '-' or '$' or '0' or '1' or '2' or '3'
170 or '4' or '5' or '6' or '7' or '8' or '9') {
171 ! Parse decimal, hex or binary number
173 sign = 1; base = 10; dcount = 0;
174 if (wa->0 == '-') { sign = -1; wl--; wa++; }
176 if (wa->0 == '$') { base = 16; wl--; wa++; }
177 if (wa->0 == '$') { base = 2; wl--; wa++; }
179 if (wl == 0) return -1;
182 if (wa->0 >= 'a') digit = wa->0 - 'a' + 10;
183 else digit = wa->0 - '0';
188 if (dcount == 17) return -1;
190 if (dcount == 6) return -1;
192 if (n > 3276) return -1;
194 if (sign == 1 && digit > 7) return -1;
195 if (sign == -1 && digit > 8) return -1;
199 if (dcount == 5) return -1;
201 #Ifnot; ! TARGET_GLULX
204 if (dcount == 33) return -1;
206 if (dcount == 11) return -1;
208 if (n > 214748363) return -1;
211 if (dcount == 9) return -1;
214 if (digit >= 0 && digit < base) n = base*n + digit;
218 parsed_number = n*sign; return 1;
221 ! Parse character constant 'a'
223 if (wl == 3 && wa->0 == ''' && wa->2 == ''') {
224 parsed_number = wa->1; return 1;
231 infix_term_type = INFIXTT_ACTION;
232 w = NextWordStopped(); if (w == -1) return -1;
234 if (InfixActionToken() == 0) return 1;
237 infix_term_type = INFIXTT_DWORD;
238 w = NextWordStopped(); if (w == -1) return -1;
239 parsed_number = w; return 1;
242 ! Test for attribute, property, class name, variable name, array name, routine
243 ! name, constant name
246 if ((wa->0 >= 'a' && wa->0 <= 'z') ||
247 (wa->0 >= 'A' && wa->0 <= 'Z') ||
251 infix_term_type = INFIXTT_ATTRIBUTE;
252 if (InfixMatchPrule(InfixPrintAttribute, #lowest_attribute_number,
253 #highest_attribute_number, wa, wl)) {
256 infix_term_type = INFIXTT_PROPERTY;
258 if (InfixMatchPrule(InfixPrintProperty, #lowest_property_number,
259 #highest_property_number, wa, wl)) {
263 if (InfixMatchPrule(InfixPrintProperty, #lowest_property_number,
264 #identifiers_table-->1 - 1, wa, wl)) {
267 if (InfixMatchPrule(InfixPrintGIProperty, INDIV_PROP_START,
268 #highest_property_number, wa, wl)) {
274 infix_term_type = INFIXTT_GLOBAL;
275 if (InfixMatchPrule(InfixPrintGlobal, #lowest_global_number,
276 #highest_global_number, wa, wl)) {
277 infix_parsed_lvalue = parsed_number-16;
278 parsed_number = #globals_array-->infix_parsed_lvalue;
282 infix_term_type = INFIXTT_ARRAY;
283 if (InfixMatchPrule(InfixPrintArray, #lowest_array_number,
284 #highest_array_number, wa, wl)) {
285 infix_parsed_lvalue = parsed_number;
286 parsed_number = Symb__Tab(INFIXTT_ARRAY,parsed_number);
287 infix_data1 = temp__global3;
288 infix_data2 = temp__global2;
292 infix_term_type = INFIXTT_ROUTINE;
293 if (InfixMatchPrule(InfixPrintRoutine, #lowest_routine_number,
294 #highest_routine_number, wa, wl)) {
295 infix_parsed_lvalue = parsed_number;
296 parsed_number = Symb__Tab(INFIXTT_ROUTINE,parsed_number);
297 infix_data1 = temp__global3;
298 infix_data2 = temp__global2;
302 infix_term_type = INFIXTT_CONSTANT;
303 if (InfixMatchPrule(InfixPrintConstant, #lowest_constant_number,
304 #highest_constant_number, wa, wl)) {
305 infix_parsed_lvalue = parsed_number;
306 parsed_number = Symb__Tab(INFIXTT_CONSTANT,parsed_number);
307 infix_data1 = temp__global3;
308 infix_data2 = temp__global2;
313 'parent', 'child', 'children',
314 'random', 'metaclass', 'sibling':
316 infix_parsed_lvalue = INFIXTT_SYSFUN;
321 infix_term_type = INFIXTT_NAMEDOBJECT;
323 wn = initial_wn; i = ParseToken(SCOPE_TT, InfixBigScope);
325 if (i == GPR_REPARSE) return i;
326 if (i > GPR_MULTIPLE) {
327 print "(", (name) i, " (", i, "))^";
328 parsed_number = i; return 1;
331 ]; ! end of InfixRvalueTerm
334 if (scope_stage == 1) return false; ! No multiples here
335 if (scope_stage == 2) {
336 objectloop (x ofclass Object) PlaceInScope(x);
337 return true; ! That's the whole scope
339 print "; I'm unable to make any sense of that term.^";
342 [ InfixCheckLineSpaced wa wl i force altered;
343 for (i=1 : i<=NumberWords() : i++) {
346 if (wl > 3 && wa->0 == ''' && wa->(wl-1) == ''') {
348 if (wa->(wl-2) == '/' && wa->(wl-3) == '/') {
352 LTI_Insert(wa-buffer, ''');
353 LTI_Insert(wa-buffer + 2, ' ');
354 altered = true; break;
357 for (i=WORDSIZE : i<GetKeyBufLength() + WORDSIZE : i++) {
359 buffer->i = LowerCase(buffer->i);
362 if (buffer->i == '-' && buffer->(i+1) == '-' && buffer->(i+2) == '>')
365 if (i>WORDSIZE && buffer->(i-1) ~= ' ') {
366 LTI_Insert(i++, ' '); altered = true;
368 if (buffer->(i+3) ~= ' ') {
369 LTI_Insert(i+3, ' '); i++; altered = true;
374 if (buffer->i == ':' && buffer->(i+1) == ':') force = true;
375 if (buffer->i == '-' && buffer->(i+1) == '>') force = true;
376 if (buffer->i == '.' && buffer->(i+1) == '&') {
377 buffer->i = ']'; force = true;
379 if (buffer->i == '.' && buffer->(i+1) == '#') {
380 buffer->i = ']'; force = true;
382 if (buffer->i == ']' && buffer->(i+1) == '&') force = true;
383 if (buffer->i == ']' && buffer->(i+1) == '#') force = true;
384 if (buffer->i == '+' && buffer->(i+1) == '+') force = true;
385 if (buffer->i == '-' && buffer->(i+1) == '-') force = true;
386 if (buffer->i == '&' && buffer->(i+1) == '&') force = true;
387 if (buffer->i == '|' && buffer->(i+1) == '|') force = true;
388 if (buffer->i == '~' && buffer->(i+1) == '~') force = true;
390 if (buffer->i == '=' && buffer->(i+1) == '=') force = true;
391 if (buffer->i == '~' && buffer->(i+1) == '=') force = true;
392 if (buffer->i == '>' && buffer->(i+1) == '=') force = true;
393 if (buffer->i == '<' && buffer->(i+1) == '=') force = true;
394 if (buffer->i == '#' && buffer->(i+1) == '#') force = true;
397 if (i > WORDSIZE && buffer->(i-1) ~= ' ') {
398 LTI_Insert(i++, ' '); altered = true;
400 if (buffer->(i+2) ~= ' ') {
401 LTI_Insert(i+2, ' '); i++; altered = true;
406 if (buffer->i == '+') force = true;
407 if (buffer->i == '-') force = true;
408 if (buffer->i == '*') force = true;
409 if (buffer->i == '/') force = true;
410 if (buffer->i == '%') force = true;
411 if (buffer->i == '(') force = true;
412 if (buffer->i == ')') force = true;
413 if (buffer->i == '<' && buffer->(i-1) ~= ';') force = true;
414 if (buffer->i == '>') force = true;
415 if (buffer->i == ',') force = true;
416 if (buffer->i == '.') force = true;
417 if (buffer->i == '&') force = true;
418 if (buffer->i == '|') force = true;
419 if (buffer->i == '~') force = true;
420 if (buffer->i == '=') force = true;
422 if (i > WORDSIZE && buffer->(i-1) ~= ' ') {
423 LTI_Insert(i++, ' '); altered = true;
425 if (buffer->(i+1) ~= ' ') {
426 LTI_Insert(i+1, ' '); i++; altered = true;
430 for (i=WORDSIZE : i<GetKeyBufLength() + WORDSIZE : i++)
431 if (buffer->i == '~') { buffer->i = '['; altered = true; }
433 ]; ! end of InfixCheckLineSpaced
435 Array InfixRV_rvals --> 32;
436 Array InfixRV_lvals --> 32;
437 Array InfixRV_op --> 32;
438 Array InfixRV_lop --> 32;
439 Array InfixRV_rop --> 32;
440 Array InfixRV_types --> 32;
441 Array InfixRV_commas --> 32;
443 [ InfixInBounds addr index n;
444 if (addr < #array__start || addr > #array__end)
446 for (n=#lowest_array_number : n<=#highest_array_number : n++) {
447 if (addr == Symb__Tab(INFIXTT_ARRAY, n)) {
448 if (temp__global3 == 1 or 3)
449 temp__global2=temp__global2*WORDSIZE+WORDSIZE-1;
450 if (index > temp__global2) {
451 print "Array index out of range";
459 [ InfixRvalue acc w i n flag base expecting_term max maxi lop rop lvalside
462 if (InfixCheckLineSpaced()) return GPR_REPARSE;
464 ! w = wn; for (i=0 : i<10 : i++) { wn = w; InfixRvalueTerm(); print i, "^"; }
467 expecting_term = true; base = 0;
469 w = NextWordStopped();
470 if (expecting_term) {
473 InfixRV_rvals-->n = 'unary-'; InfixRV_types-->n = base + 8;
475 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 6;
477 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 2;
479 InfixRV_rvals-->n = 'pre++'; InfixRV_types-->n = base + 9;
481 InfixRV_rvals-->n = 'pre--'; InfixRV_types-->n = base + 9;
483 InfixRV_rvals-->n = w; InfixRV_types-->n = -3; base=base+100;
485 InfixRV_rvals-->n = w; InfixRV_types-->n = -3; base=base-100;
486 if (base < 0) { wn--; flag = true; }
491 if (InfixRValueTerm() == 1) {
492 InfixRV_rvals-->n = parsed_number;
493 InfixRV_lvals-->n = infix_parsed_lvalue;
494 InfixRV_types-->n = -1;
495 expecting_term = false;
501 expecting_term = true;
504 InfixRV_rvals-->n = w; InfixRV_types-->n = base;
506 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 1;
508 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 2;
509 '==', '[=', '>//', '>=', '<//', '<=', 'has', 'hasnt',
510 'in', 'notin', 'ofclass', 'provides':
511 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 3;
513 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 4;
515 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 5;
516 '*//', '@{2f}//', '%//', '&//', '|//':
517 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 6;
519 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 7;
521 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 10;
523 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 12;
525 InfixRV_rvals-->n = w; InfixRV_types-->n = base + 13;
527 InfixRV_rvals-->n = '(rcall';
528 InfixRV_types-->n = base + 11; base = base + 100;
530 InfixRV_rvals-->n = w; InfixRV_types-->n = -3;
532 if (base < 0) { wn--; flag = true; }
533 expecting_term = false;
535 InfixRV_rvals-->n = 'post++'; InfixRV_types-->n = base + 9;
536 expecting_term = false;
538 InfixRV_rvals-->n = 'post--'; InfixRV_types-->n = base + 9;
539 expecting_term = false;
545 } until (flag || n == 32);
546 if (base > 0) return -1;
547 n--; if (n == 0) return -1;
550 for (i=0 : i<n : i++) {
551 acc = 0; if (InfixRV_types-->i ~= -3) acc = InfixRV_rvals-->i;
552 InfixRV_op-->i = acc;
557 ! for (i=0 : i<n : i++) {
558 ! if (InfixRV_types-->i == -1) print InfixRV_rvals-->i, " ";
559 ! else if (InfixRV_types-->i == -3) print " # ";
560 ! else if (InfixRV_types-->i == -2) print " ## ";
561 ! else print (address) InfixRV_rvals-->i, "_", InfixRV_types-->i, " ";
566 for (i=0 : i<n : i++) if (InfixRV_types-->i > max) {
567 max = InfixRV_types-->i; maxi = i; }
568 if (max == -1) { parsed_number = InfixRV_rvals-->maxi; return 1; }
570 lop = maxi-1; rop = maxi+1;
571 while (lop >= 0 && InfixRV_types-->lop < -1) lop--;
572 while (rop < n && InfixRV_types-->rop < -1) rop++;
573 if (lop >= 0) InfixRV_lop-->maxi = InfixRV_rvals-->lop;
574 if (rop < n) InfixRV_rop-->maxi = InfixRV_rvals-->rop;
576 infix_term_type = INFIXTT_NUMBER;
577 switch (InfixRV_rvals-->maxi) {
579 acc = (InfixRV_rvals-->rop);
580 '=//', 'pre++', 'post++', 'pre--', 'post--':
582 switch (InfixRV_rvals-->maxi) {
583 '=//': acc = (InfixRV_rvals-->rop);
584 'pre++': acc = (InfixRV_rvals-->rop) + 1; lvalside = rop;
585 'pre--': acc = (InfixRV_rvals-->rop) - 1; lvalside = rop;
586 'post++': acc = (InfixRV_rvals-->lop) + 1;
587 'post--': acc = (InfixRV_rvals-->lop) - 1;
589 switch (InfixRV_op-->lvalside) {
591 (InfixRV_lop-->lvalside).(InfixRV_rop-->lvalside) = acc;
593 if (InfixInBounds(InfixRV_lop-->lvalside, InfixRV_rop-->lvalside))
594 (InfixRV_lop-->lvalside)->(InfixRV_rop-->lvalside) = acc;
596 if (InfixInBounds(InfixRV_lop-->lvalside, WORDSIZE * InfixRV_rop-->lvalside))
597 (InfixRV_lop-->lvalside)-->(InfixRV_rop-->lvalside) = acc;
599 w = InfixRV_lvals-->lvalside; if (w == -1) return -1;
601 @storew #globals_array w acc;
603 @astore #globals_array w acc;
606 switch(InfixRV_rvals-->maxi) {
612 switch (InfixRV_op-->lop) {
614 a = InfixRV_lop-->lop; b = InfixRV_rop-->lop;
616 a = InfixRV_rvals-->lop; b = call;
617 if (InfixRV_lvals-->lop == INFIXTT_SYSFUN)
621 i = maxi + 1; base = 100;
622 if (InfixRV_types-->i == -1 && InfixRV_rvals-->i == ')//') {
623 if (sysfun_f) return -1;
628 if (InfixRV_types-->i == -3 && InfixRV_rvals-->i == ')//') base = base - 100;
629 if (InfixRV_types-->i == -3 && InfixRV_rvals-->i == '(//') base = base + 100;
630 if (InfixRV_op-->i == '(rcall') base = base + 100;
631 if (base == 100 && InfixRV_op-->i == comma_word) {
632 InfixRV_commas-->(w++) = i;
633 ! print "Comma found at ", i, "^";
637 ! print "Num args = ", w + 1, "^";
638 ! for (i=0 : i<w : i++)
639 ! print "arg: ", InfixRV_lop-->(InfixRV_commas-->i), "^";
640 ! print "arg: ", InfixRV_rvals-->rop, "^";
644 b = InfixRV_rvals-->rop;
645 infix_term_type = INFIXTT_NAMEDOBJECT;
655 infix_term_type = INFIXTT_NUMBER;
658 infix_term_type = INFIXTT_NUMBER;
664 acc = a.b(InfixRV_rvals-->rop);
666 if (sysfun_f) return -1;
667 acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
668 InfixRV_rvals-->rop);
670 if (sysfun_f) return -1;
671 acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
672 InfixRV_lop-->(InfixRV_commas-->1),
673 InfixRV_rvals-->rop);
675 if (sysfun_f) return -1;
676 acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
677 InfixRV_lop-->(InfixRV_commas-->1),
678 InfixRV_lop-->(InfixRV_commas-->2),
679 InfixRV_rvals-->rop);
681 if (sysfun_f) return -1;
682 acc = a.b(InfixRV_lop-->(InfixRV_commas-->0),
683 InfixRV_lop-->(InfixRV_commas-->1),
684 InfixRV_lop-->(InfixRV_commas-->2),
685 InfixRV_lop-->(InfixRV_commas-->3),
686 InfixRV_rvals-->rop);
691 '+//': acc = (InfixRV_rvals-->lop) + (InfixRV_rvals-->rop);
692 '-//': acc = (InfixRV_rvals-->lop) - (InfixRV_rvals-->rop);
693 '*//': acc = (InfixRV_rvals-->lop) * (InfixRV_rvals-->rop);
694 '@{2f}//': acc = (InfixRV_rvals-->lop) / (InfixRV_rvals-->rop);
695 '%//': acc = (InfixRV_rvals-->lop) % (InfixRV_rvals-->rop);
696 THEN1__WD: acc = (InfixRV_rvals-->lop) . (InfixRV_rvals-->rop);
697 '->': acc = (InfixRV_rvals-->lop) -> (InfixRV_rvals-->rop);
698 '-->': acc = (InfixRV_rvals-->lop) --> (InfixRV_rvals-->rop);
699 ']&': acc = (InfixRV_rvals-->lop) .& (InfixRV_rvals-->rop);
700 ']#': acc = (InfixRV_rvals-->lop) .# (InfixRV_rvals-->rop);
701 '::': acc = (InfixRV_rvals-->lop) :: (InfixRV_rvals-->rop);
702 '&//': acc = (InfixRV_rvals-->lop) & (InfixRV_rvals-->rop);
703 '|//': acc = (InfixRV_rvals-->lop) | (InfixRV_rvals-->rop);
704 '&&': acc = (InfixRV_rvals-->lop) && (InfixRV_rvals-->rop);
705 infix_term_type = INFIXTT_LOGICAL;
706 '||': acc = (InfixRV_rvals-->lop) || (InfixRV_rvals-->rop);
707 infix_term_type = INFIXTT_LOGICAL;
708 '<//': acc = (InfixRV_rvals-->lop) < (InfixRV_rvals-->rop);
709 infix_term_type = INFIXTT_LOGICAL;
710 '<=': acc = (InfixRV_rvals-->lop) <= (InfixRV_rvals-->rop);
711 infix_term_type = INFIXTT_LOGICAL;
712 '>//': acc = (InfixRV_rvals-->lop) > (InfixRV_rvals-->rop);
713 infix_term_type = INFIXTT_LOGICAL;
714 '>=': acc = (InfixRV_rvals-->lop) >= (InfixRV_rvals-->rop);
715 infix_term_type = INFIXTT_LOGICAL;
716 '==': acc = (InfixRV_rvals-->lop) == (InfixRV_rvals-->rop);
717 infix_term_type = INFIXTT_LOGICAL;
718 '[=': acc = (InfixRV_rvals-->lop) ~= (InfixRV_rvals-->rop);
719 infix_term_type = INFIXTT_LOGICAL;
720 'has': acc = (InfixRV_rvals-->lop) has (InfixRV_rvals-->rop);
721 infix_term_type = INFIXTT_LOGICAL;
722 'hasnt': acc = (InfixRV_rvals-->lop) hasnt (InfixRV_rvals-->rop);
723 infix_term_type = INFIXTT_LOGICAL;
724 'in': acc = (InfixRV_rvals-->lop) in (InfixRV_rvals-->rop);
725 infix_term_type = INFIXTT_LOGICAL;
726 'notin': acc = (InfixRV_rvals-->lop) notin (InfixRV_rvals-->rop);
727 infix_term_type = INFIXTT_LOGICAL;
728 'provides': acc = (InfixRV_rvals-->lop) provides (InfixRV_rvals-->rop);
729 infix_term_type = INFIXTT_LOGICAL;
730 'ofclass': acc = (InfixRV_rvals-->lop) ofclass (InfixRV_rvals-->rop);
731 infix_term_type = INFIXTT_LOGICAL;
732 '[[': acc = ~~ (InfixRV_rvals-->rop); flag = true;
733 '[//': acc = ~ (InfixRV_rvals-->rop); flag = true;
734 'unary-': acc = - (InfixRV_rvals-->rop); flag = true;
735 } ! end of switch(InfixRV_rvals-->maxi)
736 InfixRV_rvals-->maxi = acc;
737 InfixRV_types-->maxi = -1;
738 if (rop < n) InfixRV_types-->rop = -2;
739 if (flag == false && lop >= 0) InfixRV_types-->lop = -2;
741 ]; ! end of InfixRvalue
743 ! ------------------------------------------------------------------------
746 print "; Welcome to the ~Infix~ debugger (1/040828), which makes the
747 following verbs available:^^
748 ~; <expression>~: evaluates this Inform expression: e.g.
749 ~; location~ will print the value of the variable ~location~,
750 ~; 3*5+1~ will print 16, ~; children(old cloth bag)~ will tell you
751 how many items are in it. (You can name objects either by their
752 names inside the source code, such as ~d_obj~, or by typing the
753 names by which the game's parser would normally know them, such
754 as ~floor~: the effect is the same.)^
755 Any expression is allowed except that you can't use double-quoted
756 strings of text: but you can send messages, call routines or
757 assign values to variables, properties and array entries.
758 ^ ~; score++~ is one way to get on in the world.
759 ^ ~; deadflag = true~ is one way to get out of it.
760 ^ ~; StopDaemon(nasty little dwarf)~ will keep you from being pestered.^
761 Conditions like ~; score>20~ are also allowed and print
762 either 1 (if true) or 0 (if false).^^";
763 print "~;examine <something>~ or ~;x <something>~ gives full details
764 of whatever it is. For instance, ~;x ##Take~ describes the Take
765 action; ~;x Class~ the class Class; ~;x 'drop'~ the dictionary
766 word ~drop~ and so on for numbers, routines, arrays and of course
767 objects. ~;xo~ examines something as an object, so for instance
768 ~;x location~ tells you about the variable ~location~, but ~;xo
769 location~ tells you what object it refers to.^^";
770 print "~;give~, ~;remove~ and ~;move~ work like the corresponding
771 Inform statements.^^";
772 print "~;<~ causes an action: for instance, ~;< Eat cheese~.^^";
773 print "~;watch~ or ~;w~ can set a watch on various activities:
774 type just ~;w~ for details.^^";
775 print "~;inventory~ or ~;i~ describes the contents of this story file.^";
778 [ InfixEvalSub; InfixExamineP(true); ];
781 print "; <", (InfixPrintAction) infix_lvalue;
782 if (noun) print " (", (the) noun, ")";
783 if (second) print " (", (the) second, ")";
785 if (second) <<(infix_lvalue) noun second>>;
786 if (noun) <<(infix_lvalue) noun>>;
791 print "; give (", (the) noun, ") ";
792 if (second < 0) { second = ~second; f=true; }
794 t = NUM_ATTR_BYTES * 8;
798 if (second < 0 || second >= t) "<No such attribute>";
799 if (f) print "@@126";
800 print (DebugAttribute) second;
802 if (f) @clear_attr noun second;
803 else @set_attr noun second;
804 #Ifnot; ! TARGET_GLULX
806 if (f) @astorebit noun t 0; ! give noun ~second;
807 else @astorebit noun t 1; ! give noun second;
809 if (t); ! quell unused n variable warning
814 print "; move (", (the) noun, ") to (", (the) second, ")^";
819 print "; remove (", (the) noun, ")^";
825 y = (x & $7f00) / $100;
826 if (x < 0) y = y + $80;
827 #Ifnot; ! TARGET_GLULX
828 y = (x & $7f000000) / $1000000;
829 if (x < 0) y = y + $80;
830 print (Infixhexdigit) y/$10, (Infixhexdigit) y;
831 y = x & $ff0000 / $10000;
832 print (Infixhexdigit) y/$10, (Infixhexdigit) y;
833 y = (x & $ff00) / $100;
836 print (Infixhexdigit) y/$10, (Infixhexdigit) y, (Infixhexdigit) x/$10, (Infixhexdigit) x;
839 [ Infixhexdigit x; x = x % $10; if (x < 10) print x; else print (char) 'a'+x-10; ];
842 infix_data1 = metaclass(noun);
843 #Ifdef TARGET_GLULX; ! different coding for Glulx
844 if (infix_data1 == Object) infix_data1 = 2;
845 if (infix_data1 == Class) infix_data1 = 1;
847 infix_term_type = INFIXTT_CONSTANT;
848 InfixExamineP(false);
852 infix_term_type = INFIXTT_STATICSTRING;
853 InfixExamineP(false);
856 [ InfixExamineSub; InfixExamineP(false); ];
858 [ InfixExamineP brief x a b w flag lines;
859 switch (infix_term_type) {
861 if (brief) "; == ", noun;
862 print "; The number ", noun, " == $", (InfixHex) noun;
863 if (noun >= 32 && noun < 127) print " == '", (char) noun, "'";
866 print "~", (name) noun, "~ (", noun, ")^"; if (brief) return;
869 if (brief) "; == ", noun;
870 switch (infix_data1 & 15) {
872 print "; Constant ", (InfixPrintConstant) infix_parsed_lvalue,
876 print "Class ", (name) noun, "^";
877 objectloop (a ofclass noun) {
878 if (flag) print ", "; else print "Contains: ";
879 print (name) a, " (", a, ")"; flag=true;
881 if (flag == false) "No object is of this class";
885 if (brief) "; == ", noun;
886 if (noun >= 48 || noun < 0) "; No such attribute";
887 print "; Attribute ", (InfixPrintAttribute) noun,
888 " (numbered ", noun, ")^";
889 objectloop (x has noun) {
890 if (flag) print ", ";
891 else print "Each of these ~has ", (InfixPrintAttribute) noun, "~: ";
892 print (name) x, " (", x, ")"; flag = true;
894 if (flag == false) "No object ~has ", (InfixPrintAttribute) noun, "~";
897 if (brief) "; == ", noun;
898 print "; Property ", (property) noun, " (numbered ", noun, ")^";
899 objectloop (x provides noun) {
900 if (flag) print ", "; else print "Provided by: ";
901 print (name) x, " (", x, ")"; flag = true;
903 if (flag == false) "Which is not provided by any object";
906 if (brief) "; == ", noun;
907 if (noun == 0) "; This word is not in the dictionary";
908 a = noun->#dict_par1;
909 print "; Dictionary word '", (address) noun;
910 if (a & 4) print "//p";
911 print "' (address ", noun, ")";
914 if (a & 2) print "meta ";
915 if (a & 1) print "verb ";
916 if (a & 8) print "preposition ";
917 if (a & 4) print "pluralising ";
918 if (a & 128) print "noun ";
921 if (a & 1) <<ShowVerb noun>>;
923 if (brief) "; == ", noun;
924 print "; Routine ", (InfixPrintRoutine) infix_parsed_lvalue, " (number ",
925 infix_parsed_lvalue, ", packed address ", noun, ")^";
927 if (brief) "; == ", noun;
928 print "; Global ", (InfixPrintGlobal) infix_parsed_lvalue, " == ", noun, "^";
930 if (brief) "; == ", noun;
931 print "; Array ", (InfixPrintArray) infix_parsed_lvalue, " ";
932 infix_data1 = infix_data1 % 16;
933 switch (infix_data1) {
936 2: print "string"; a=1;
937 3: print "table"; a=1;
938 4: print "buffer"; a=WORDSIZE;
940 print " ", infix_data2 + 1 - a, "^; == "; b = infix_data2;
941 for (w=b : w>=a : w--)
942 if (infix_data1 == 0 or 2 or 4) { if (noun->w) break; }
943 else { if (noun-->w) break; }
946 if (infix_data1 == 0 or 2 or 4) print noun->x, " ";
947 else print noun-->x, " ";
948 if (x+1 == a) print ": ";
950 if (w < b) print "(then ", b-w, " zero entries)";
953 if (brief) "; == ", noun;
954 if (noun >= #lowest_fake_action_number && noun <= #highest_fake_action_number)
955 "; Fake action ", (InfixPrintFakeAction) noun,
956 " (numbered ", noun, ")^Is not generated by any grammar";
957 print "; Action ", (InfixPrintAction) noun,
958 " (numbered ", noun, ")^";
960 w = HDR_DICTIONARY-->0;
961 for (b=0 : b<(HDR_DICTIONARY-->0 + 5)-->0 : b++) {
962 w = HDR_DICTIONARY-->0 + 7 + b*9;
963 if ((w->#dict_par1) & 1) {
964 a = (HDR_STATICMEMORY-->0)-->($ff-(w->#dict_par2));
966 for (: lines>0 : lines--) {
967 a = UnpackGrammarLine(a);
968 if (action_to_be == noun) {
969 print "'", (address) w, "' "; DebugGrammarLine();
976 #Ifnot; ! TARGET_GLULX
977 for (b=0 : b < #dictionary_table-->0 : b++) {
978 w = #dictionary_table + WORDSIZE + b*(DICT_WORD_SIZE + 7);
979 if ((w->#dict_par1) & 1) {
980 a = (#grammar_table)-->(DictionaryWordToVerbNum(w) + 1);
982 for (: lines>0 : lines--) {
983 a = UnpackGrammarLine(a);
984 if (action_to_be == noun) {
985 print "'", (address) w, "' "; DebugGrammarLine();
994 if (flag == 0) "Is not generated by any grammar";
996 if (brief) "; == ", noun;
997 "; System function ~", (address) infix_parsed_lvalue, "~ has
998 not been overridden by any routine and so has its standard definition.";
999 INFIXTT_STATICSTRING:
1000 if (brief) "; == ", noun;
1001 if (metaclass(noun) ~= String) "; ", noun, " is not a string.";
1002 print "~", (string) noun, "~^";
1004 if (noun == true) "; true"; if (noun == false) "; false";
1008 ]; ! end of InfixExamineP
1010 [ InfixDescribeWatchSub x y z s flag aflag;
1011 print "; The Infix ~;watch~ verb allows you to set a watch on any named
1012 routine(s) or objects: for instance ~;watch ScoreSub~ or
1013 ~;watch silver bars~. You can also:
1014 ^ ~;watch objects~: changes to attribute or property settings";
1015 if (debug_flag & 8) print " (on)"; else print " (off)";
1017 print ";^ ~;watch timers~: the running of timers and daemons each turn";
1018 if (debug_flag & 4) print " (on)"; else print " (off)";
1020 print ";^ ~;watch messages~: all messages sent";
1021 if (debug_flag & 1) print " (on)"; else print " (off)";
1023 print ";^ ~;watch actions~: all actions generated";
1024 if (debug_flag & 2) print " (on)"; else print " (off)";
1026 print ".^~~;watch~ can be abbreviated to ~;w~ and use ~off~ to stop
1027 watching: for instance ~;w location off~.^";
1029 objectloop (x has infix__watching) flag = true; aflag = aflag || flag;
1030 if (flag) print "The following objects are currently being watched: ";
1032 objectloop (x has infix__watching) {
1033 if (flag) print ", "; flag = true;
1034 print (name) x, " (", x, ")";
1037 s = (#highest_routine_number - #lowest_routine_number);
1038 if (s%8 == 0) s=s/8; else s=s/8+1;
1039 for (flag=false,x=0 : x<s : x++) if (#routine_flags_array->x) flag = true;
1040 aflag = aflag || flag;
1041 if (flag) print "The following routines are currently being watched: ";
1042 for (x=0,flag=false : x<s : x++) {
1043 for (y=1,z=0 : y<256 : z++,y=y*2) {
1044 if ((#routine_flags_array->x) & y) {
1045 if (flag) print ", "; flag = true;
1046 print (InfixPrintRoutine)
1047 #lowest_routine_number + x*8 + z;
1052 if (aflag == false) "At present, nothing is being watched.";
1055 [ InfixWatchOnSub i j k l;
1056 if (noun == 0) return InfixDescribeWatchSub();
1057 if (infix_term_type == INFIXTT_ROUTINE) {
1058 i = infix_parsed_lvalue/8;
1059 for (j=0,k=1 : j<infix_parsed_lvalue%8 : j++) k=k*2;
1060 l = #routine_flags_array->i;
1062 #Ifdef TARGET_ZCODE;
1063 @storeb #routine_flags_array i l;
1064 #Ifnot; ! TARGET_GLULX
1065 @astoreb #routine_flags_array i l;
1067 "; Watching routine ", (InfixPrintRoutine) infix_parsed_lvalue, ".";
1069 if (metaclass(noun) == Object) {
1070 give noun infix__watching;
1071 "; Watching object ~", (name) noun, "~ (", noun, ").";
1073 InfixDescribeWatchSub();
1076 [ InfixWatchOffSub i j k l;
1077 if (noun == 0) return InfixDescribeWatchSub();
1078 if (infix_term_type == INFIXTT_ROUTINE) {
1079 i = infix_parsed_lvalue/8;
1080 for (j=0,k=1 : j<infix_parsed_lvalue%8 : j++) k=k*2;
1081 l = #routine_flags_array->i;
1083 #Ifdef TARGET_ZCODE;
1084 @storeb #routine_flags_array i l;
1085 #Ifnot; ! TARGET_GLULX
1086 @astoreb #routine_flags_array i l;
1088 "; Not watching ", (InfixPrintRoutine) infix_parsed_lvalue, ".";
1090 if (metaclass(noun) == Object) {
1091 #Ifdef TARGET_ZCODE;
1092 @clear_attr noun infix__watching;
1093 #Ifnot; ! TARGET_GLULX
1094 @astorebit noun (infix__watching+8) 0;
1096 "; Not watching object ~", (name) noun, "~ (", noun, ").";
1098 InfixDescribeWatchSub();
1101 [ InfixList from to tab filter i flag;
1103 for (i=from : i<=to : i++)
1104 if (tab-->(i-from)) {
1106 if (tab == #array_names_array) {
1107 Symb__Tab(INFIXTT_ARRAY, i);
1108 flag = ~~(temp__global3 & 16);
1110 if (tab == #routine_names_array) {
1111 Symb__Tab(INFIXTT_ROUTINE,i);
1112 flag = ~~(temp__global3 & 16);
1114 if (tab == #constant_names_array) {
1115 Symb__Tab(INFIXTT_CONSTANT,i);
1116 flag = (~~(temp__global3 & 16)) && (temp__global3 % 16 == filter);
1118 if (flag) print (string) tab-->(i-from), " ";
1125 print (string) Story, (string) Headline;
1126 print " ", (number) #highest_object_number - #lowest_object_number + 1,
1129 print " non-library object-name constants:";
1130 InfixList(#lowest_constant_number, #highest_constant_number, #constant_names_array, 2);
1132 print " ", (number) #highest_class_number - #lowest_class_number + 1, " classes:^ ";
1133 for (i=#lowest_class_number : i<=#highest_class_number : i++)
1134 print (name) #class_objects_array-->i, " ";
1137 print " non-library arrays:";
1138 InfixList(#lowest_array_number, #highest_array_number, #array_names_array);
1140 print " non-library routines:";
1141 InfixList(#lowest_routine_number, #highest_routine_number, #routine_names_array);
1143 print " non-library constants:";
1144 InfixList(#lowest_constant_number, #highest_constant_number, #constant_names_array, 0);
1146 print " (common) properties:";
1147 #Ifdef TARGET_ZCODE;
1148 InfixList(#lowest_property_number, INDIV_PROP_START-1, #property_names_array);
1149 #Ifnot; ! TARGET_GLULX
1150 InfixList(#lowest_property_number, #identifiers_table-->1 - 1, #property_names_array);
1153 print " (individual) properties:";
1154 #Ifdef TARGET_ZCODE;
1155 InfixList(INDIV_PROP_START, #highest_property_number, #property_names_array + 126);
1156 #Ifnot; ! TARGET_GLULX
1157 InfixList(INDIV_PROP_START, #highest_property_number, #identifiers_table-->2);
1160 print " attributes:";
1161 InfixList(#lowest_attribute_number, #highest_attribute_number, #attribute_names_array);
1165 print " variables:";
1166 InfixList(#lowest_global_number, #highest_global_number, #global_names_array);
1169 InfixList(#lowest_action_number, #highest_action_number, #action_names_array);
1171 print " fake actions:";
1172 InfixList(#lowest_fake_action_number, #highest_fake_action_number, #fake_action_names_array);
1175 Verb meta ';i' ';inv' ';inventory'
1177 Verb meta ';x' ';examine'
1178 * InfixRvalue -> InfixExamine;
1179 Verb meta ';xo' ';examineo'
1180 * InfixRvalue -> InfixExamineO;
1181 Verb meta ';xs' ';examines'
1182 * InfixRvalue -> InfixExamineS;
1184 * InfixActionToken -> InfixAction
1185 * InfixActionToken InfixRvalue -> InfixAction
1186 * InfixActionToken InfixRvalue InfixRvalue -> InfixAction;
1189 * InfixRvalue -> InfixEval;
1191 * InfixRvalue InfixRvalue -> InfixGive;
1193 * InfixRvalue "to" InfixRvalue -> InfixMove;
1195 * InfixRvalue -> InfixRemove;
1196 Verb meta ';watch' ';w'
1198 * "timers"/"daemons" -> TimersOn
1199 * "timers"/"daemons" "off" -> TimersOff
1200 * "actions" -> ActionsOn
1201 * "actions" "off" -> ActionsOff
1202 * "messages" -> RoutinesOn
1203 * "messages" "off" -> RoutinesOff
1204 * "objects" -> ChangesOn
1205 * "objects" "off" -> ChangesOff
1206 * InfixRvalueTerm -> InfixWatchOn
1207 * InfixRvalueTerm "off" -> InfixWatchOff;
1211 ! ==============================================================================