diff --git a/README.md b/README.md index 927668233..c4265079e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Inform 7 -[Version](notes/versioning.md): 10.2.0-beta+6X36 'Krypton' (26 February 2024) +[Version](notes/versioning.md): 10.2.0-beta+6X37 'Krypton' (12 March 2024) ## About Inform diff --git a/build.txt b/build.txt index 24d2a7afd..c410f9cc6 100644 --- a/build.txt +++ b/build.txt @@ -1,3 +1,3 @@ Prerelease: beta -Build Date: 26 February 2024 -Build Number: 6X36 +Build Date: 12 March 2024 +Build Number: 6X37 diff --git a/docs/Architecture16Kit/S-io.html b/docs/Architecture16Kit/S-io.html index 2222bea09..876bb1bd5 100644 --- a/docs/Architecture16Kit/S-io.html +++ b/docs/Architecture16Kit/S-io.html @@ -64,7 +64,7 @@ MathJax = {
Access to the keyboard and to textual windows.
-§1. Transcript support. This is a mode in which the transcript of text in the main window is being written out to an external file. @@ -92,12 +92,24 @@ only if scripting is on. rtrue; ]; -
+Constant #dict_par1 = 6; Constant #dict_par2 = 7; +Constant DICTPAR1_VERB = 1; +Constant DICTPAR1_META = 2; +Constant DICTPAR1_PLURAL = 4; +Constant DICTPAR1_PREP = 8; +Constant DICTPAR1_SING = 16; +Constant DICTPAR1_BIT6 = 32; +Constant DICTPAR1_TRUNC = 64; +Constant DICTPAR1_NOUN = 128; ++ + +
Global xcommsdir; true if command recording is on Constant INPUT_BUFFER_LEN = 120; Length of buffer array @@ -112,7 +124,7 @@ only if scripting is on. Global dict_entry_size; Global dict_end;-
§3. Dictionary words. This tests whether an address is probably that of a dictionary word. It's used +
§4. Dictionary words. This tests whether an address is probably that of a dictionary word. It's used only for debugging output, so the false positives here (where an address is in the dictionary table, but mid-word) really do not matter.
@@ -124,7 +136,7 @@ the dictionary table, but mid-word) really do not matter. rfalse; ]; -§4. Keyboard Input. The VM must provide three routines for keyboard input: +
§5. Keyboard Input. The VM must provide three routines for keyboard input:
§5. Buffer Functions. A "buffer", in this sense, is an array containing a stream of characters +
§6. Buffer Functions. A "buffer", in this sense, is an array containing a stream of characters typed from the keyboard; a "parse buffer" is an array which resolves this into individual words, pointing to the relevant entries in the dictionary structure. Because each VM has its own format for each of these arrays (not @@ -218,7 +230,7 @@ languages of play. if (b->1 < b->0) (b->1)++; ]; -
§6. Dictionary Functions. Again, the dictionary structure is differently arranged on the different VMs. +
§7. Dictionary Functions. Again, the dictionary structure is differently arranged on the different VMs. This is a data structure containing, in compressed form, the text of all the words to be recognised by tokenisation (above). In I6 for Z, a dictionary word value is represented at run-time by its record number in the dictionary, @@ -244,7 +256,7 @@ convert between record numbers and dictionary addresses. [ VM_DictionaryAddressToNumber w; return (w-(HDR_DICTIONARY-->0 + 7))/DICT_ENTRY_BYTES; ]; [ VM_NumberToDictionaryAddress n; return HDR_DICTIONARY-->0 + 7 + DICT_ENTRY_BYTES*n; ]; -
§7. Command Tables. The VM is also generated containing a data structure for the grammar +
§8. Command Tables. The VM is also generated containing a data structure for the grammar produced by I6's Verb and Extend directives: this is essentially a list of command verbs such as DROP or PUSH, together with a list of synonyms, and then the grammar for the subsequent commands to be @@ -263,7 +275,7 @@ recognised by the parser. print "'", (address) VM_NumberToDictionaryAddress(j), "' "; ]; -
§8. Extracting Verb Numbers. A long tale of woe lies behind the following. Infocom games stored verb numbers +
§9. Extracting Verb Numbers. A long tale of woe lies behind the following. Infocom games stored verb numbers in a single byte in dictionary entries, but they did so counting downwards, so that verb number 0 was stored as 255, 1 as 254, and so on. Inform followed suit so that debugging of Inform 1 could be aided by using the then-available @@ -284,7 +296,7 @@ routine was added to concentrate lookups of this field in one place. return $ff-(dword->#dict_par2); ]; -
§9. Action functions. This looks up the address of a function like TakeSub from the table of +
§10. Action functions. This looks up the address of a function like TakeSub from the table of "action subroutines".
@@ -293,7 +305,7 @@ routine was added to concentrate lookups of this field in one place. return #actions_table-->act; ]; -§10. The Screen. Our generic screen model is that the screen is made up of windows: we tend +
§11. The Screen. Our generic screen model is that the screen is made up of windows: we tend to refer only to two of these, the main window and the status line, but others may also exist from time to time. Windows have unique ID numbers: the special window ID \(-1\) means "all windows" or "the entire screen", @@ -324,7 +336,7 @@ in order to keep it accurate. [ VM_ScreenHeight; return (HDR_SCREENHLINES->0); ]; -
§11. Window Colours. Each window can have its own foreground and background colours. +
§12. Window Colours. Each window can have its own foreground and background colours.
The colour of individual letters or words of type is not controllable in @@ -363,7 +375,7 @@ which is greatly superior in this respect). } ]; -
§12. Main Window. The part of the screen on which commands and responses are printed, which +
§13. Main Window. The part of the screen on which commands and responses are printed, which ordinarily occupies almost all of the screen area.
@@ -382,7 +394,7 @@ emulates the Glulx model of window rather than text colours. statuswin_current = false; ]; -§13. Status Line. Despite the name, the status line need not be a single line at the top of +
§14. Status Line. Despite the name, the status line need not be a single line at the top of the screen: that's only the conventional default arrangement. It can expand to become the equivalent of an old-fashioned VT220 terminal, with menus and grids and mazes displayed lovingly in character graphics, or it can diff --git a/docs/Architecture32Kit/S-io.html b/docs/Architecture32Kit/S-io.html index 712770d66..3922ac935 100644 --- a/docs/Architecture32Kit/S-io.html +++ b/docs/Architecture32Kit/S-io.html @@ -64,7 +64,7 @@ MathJax = {
Access to the keyboard and to textual windows.
-§1. Rocks. These are unique ID codes used to mark resources; think of them as inedible cookies. @@ -126,13 +126,25 @@ only if scripting is on: this always succeeds. rtrue; ]; -
+Constant DICT_ENTRY_BYTES = 12+DICT_WORD_SIZE*WORDSIZE; Constant #dict_par1 = DICT_WORD_SIZE*WORDSIZE+4+1; Constant #dict_par2 = DICT_WORD_SIZE*WORDSIZE+4+3; +Constant DICTPAR1_VERB = 1; +Constant DICTPAR1_META = 2; +Constant DICTPAR1_PLURAL = 4; +Constant DICTPAR1_PREP = 8; +Constant DICTPAR1_SING = 16; +Constant DICTPAR1_BIT6 = 32; +Constant DICTPAR1_TRUNC = 64; +Constant DICTPAR1_NOUN = 128; ++ + +
Array gg_event --> 4; Array gg_arguments buffer 28; Global gg_mainwin = 0; @@ -154,7 +166,7 @@ only if scripting is on: this always succeeds. Array parse --> PARSE_BUFFER_LEN; Array parse2 --> PARSE_BUFFER_LEN;-
§4. Dictionary words. This tests whether an address is probably that of a dictionary word. It's used +
§5. Dictionary words. This tests whether an address is probably that of a dictionary word. It's used only for debugging output, so the false positives here really do not matter.
@@ -164,7 +176,7 @@ only for debugging output, so the false positives here really do not matter. rfalse; ]; -§5. Keyboard Input. The VM must provide three routines for keyboard input: +
§6. Keyboard Input. The VM must provide three routines for keyboard input:
§6. Buffer Functions. A "buffer", in this sense, is an array containing a stream of characters +
§7. Buffer Functions. A "buffer", in this sense, is an array containing a stream of characters typed from the keyboard; a "parse buffer" is an array which resolves this into individual words, pointing to the relevant entries in the dictionary structure. Because each VM has its own format for each of these arrays (not @@ -463,7 +475,7 @@ languages of play, and is not called in the template. if (b-->0 < INPUT_BUFFER_LEN) (b-->0)++; ]; -
§7. Dictionary Functions. Again, the dictionary structure is differently arranged on the different VMs. +
§8. Dictionary Functions. Again, the dictionary structure is differently arranged on the different VMs. This is a data structure containing, in compressed form, the text of all the words to be recognised by tokenisation (above). In I6 for Glulx, a dictionary word is represented at run-time by its record's address in the dictionary. @@ -500,7 +512,7 @@ since, on Glulx, they are the same, these are each the identity function. return 0; ]; -
§8. Command Tables. The VM is also generated containing a data structure for the grammar +
§9. Command Tables. The VM is also generated containing a data structure for the grammar produced by I6's Verb and Extend directives: this is essentially a list of command verbs such as DROP or PUSH, together with a list of synonyms, and then the grammar for the subsequent commands to be @@ -522,7 +534,7 @@ recognised by the parser. } ]; -
§9. Extracting Verb Numbers. A long tale of woe lies behind the following. Infocom games stored verb numbers +
§10. Extracting Verb Numbers. A long tale of woe lies behind the following. Infocom games stored verb numbers in a single byte in dictionary entries, but they did so counting downwards, so that verb number 0 was stored as 255, 1 as 254, and so on. Inform followed suit so that debugging of Inform 1 could be aided by using the then-available @@ -546,7 +558,7 @@ routine was added to concentrate lookups of this field in one place. return verbnum; ]; -
§10. Action functions. This looks up the address of a function like TakeSub from the table of +
§11. Action functions. This looks up the address of a function like TakeSub from the table of "action subroutines".
@@ -559,7 +571,7 @@ compared to the Z-machine's: hence the return #actions_table-->(act+1); ]; -§11. Glulx-Only Printing Routines. Partly because of the smallness of the range of representable values in +
§12. Glulx-Only Printing Routines. Partly because of the smallness of the range of representable values in the Z-machine, there is little run-time type-checking that can be done: for instance a dictionary address cannot be distinguished from a function address because they are encoded differently, so that a function address @@ -712,7 +724,7 @@ set stored here is once again ZSCII, not Unicode. return AnyToStrArr; ]; -
§12. The Screen. Our generic screen model is that the screen is made up of windows: we tend +
§13. The Screen. Our generic screen model is that the screen is made up of windows: we tend to refer only to two of these, the main window and the status line, but others may also exist from time to time. Windows have unique ID numbers: the special window ID \(-1\) means "all windows" or "the entire screen", @@ -749,7 +761,7 @@ make little sense there. return gg_arguments-->0; ]; -
§13. Window Colours. Our generic screen model is that the screen is made up of windows, each of +
§14. Window Colours. Our generic screen model is that the screen is made up of windows, each of which can have its own foreground and background colours.
@@ -817,7 +829,7 @@ which is greatly superior in this respect). return $ff0000*(c&1) + $ff00*(c&2 ~= 0) + $ff*(c&4 ~= 0); ]; -§14. Main Window. The part of the screen on which commands and responses are printed, which +
§15. Main Window. The part of the screen on which commands and responses are printed, which ordinarily occupies almost all of the screen area.
@@ -831,7 +843,7 @@ status line, to the main window. statuswin_current=0; ]; -§15. Status Line. Despite the name, the status line need not be a single line at the top of +
§16. Status Line. Despite the name, the status line need not be a single line at the top of the screen: that's only the conventional default arrangement. It can expand to become the equivalent of an old-fashioned VT220 terminal, with menus and grids and mazes displayed lovingly in character graphics, or it can @@ -867,7 +879,7 @@ line; line 2 is underneath, and so on; columns are similarly numbered from statuswin_current=1; ]; -
§16. Quotation Boxes. On the Z-machine, quotation boxes are produced by stretching the status line, +
§17. Quotation Boxes. On the Z-machine, quotation boxes are produced by stretching the status line, but on Glulx they usually occupy windows of their own. If it isn't possible to create such a window, so that gg_quotewin is zero below, the quotation text just appears in the main window. diff --git a/docs/CommandParserKit/S-prs.html b/docs/CommandParserKit/S-prs.html index c09a01d2b..865ceadc0 100644 --- a/docs/CommandParserKit/S-prs.html +++ b/docs/CommandParserKit/S-prs.html @@ -226,8 +226,7 @@ be read or written by the parser. pragmatically useful results (Not a flag: possible values 0, 1, 2) -Global dict_flags_of_noun; Of the noun currently being parsed - (a bitmap in #dict_par1 format) +Global current_noun_is_plural; True or false Global pronoun__word; Saved value Global pronoun__obj; Saved value @@ -932,7 +931,7 @@ fairly thorough description of its output, which is written into the If the first word is not listed as a verb, it must be a direction or the name of someone to talk to - if (verb_word == 0 || ((verb_word->#dict_par1) & 1) == 0) { + if (verb_word == 0 || ((verb_word->#dict_par1) & DICTPAR1_VERB) == 0) { So is the first word an object contained in the special object "compass" (i.e., a direction)? This needs use of NounDomain, a routine which does the object matching, returning the object number, or 0 if none found, @@ -991,7 +990,7 @@ fairly thorough description of its output, which is written into the scope_reason = PARSING_REASON; if (l == REPARSE_CODE) jump ReParse; if (l == 0) { - if (verb_word && ((verb_word->#dict_par1) & 1)) jump NotConversation; + if (verb_word && ((verb_word->#dict_par1) & DICTPAR1_VERB)) jump NotConversation; best_etype = MISSINGPERSON_PE; jump GiveError; } @@ -1009,7 +1008,7 @@ fairly thorough description of its output, which is written into the name and the comma (eg, throw out "dwarf sdfgsdgs, go north"). if (wn ~= j) { - if (verb_word && ((verb_word->#dict_par1) & 1)) jump NotConversation; + if (verb_word && ((verb_word->#dict_par1) & DICTPAR1_VERB)) jump NotConversation; best_etype = TOTALK_PE; jump GiveError; } @@ -1045,7 +1044,7 @@ fairly thorough description of its output, which is written into the
.NotConversation; - if (verb_word == 0 || ((verb_word->#dict_par1) & 1) == 0) { + if (verb_word == 0 || ((verb_word->#dict_par1) & DICTPAR1_VERB) == 0) { verb_word = UnknownVerb(verb_word); if (verb_word ~= 0) jump VerbAccepted; best_etype = VERB_PE; @@ -1056,7 +1055,7 @@ fairly thorough description of its output, which is written into the We now definitely have a verb, not a direction, whether we got here by the "take ..." or "person, take ..." method. Get the meta flag for this verb: - meta = ((verb_word->#dict_par1) & 2)/2; + meta = ((verb_word->#dict_par1) & DICTPAR1_META)/2; You can't order other people to "full score" for you, and so on... @@ -1178,7 +1177,7 @@ and similarly for multiinside do { l = NextWord(); } until ((wn > num_words) || - (l && (l->#dict_par1) & 8 ~= 0)); + (l && (l->#dict_par1) & DICTPAR1_PREP ~= 0)); if (wn > num_words) { #Ifdef DEBUG; @@ -1204,9 +1203,9 @@ and similarly for multiinside do { l = NextWord(); } until ((wn >= num_words) || - (l && (l->#dict_par1) & 8 ~= 0)); + (l && (l->#dict_par1) & DICTPAR1_PREP ~= 0)); - if (l && (l->#dict_par1) & 8) continue; + if (l && (l->#dict_par1) & DICTPAR1_PREP) continue; lookahead failed #Ifdef DEBUG; @@ -2557,8 +2556,7 @@ because we want to allow duplicates). j = wn; first_word = LanguageIsVerb(buffer2, parse2, 1); wn = j; } if (first_word ~= 0) { - j = first_word->#dict_par1; - if ((0 ~= j&1) && ~~LanguageVerbMayBeName(first_word)) { + if (((first_word->#dict_par1) & DICTPAR1_VERB) && ~~LanguageVerbMayBeName(first_word)) { VM_CopyBuffer(buffer, buffer2); jump RECONSTRUCT_INPUT; } @@ -2642,8 +2640,7 @@ because we want to allow duplicates). parser to get on with and forget about the question... if (first_word ~= 0) { - j = first_word->#dict_par1; - if ((0 ~= j&1) && ~~LanguageVerbMayBeName(first_word)) { + if (((first_word->#dict_par1) & DICTPAR1_VERB) && ~~LanguageVerbMayBeName(first_word)) { VM_CopyBuffer(buffer, buffer2); jump RECONSTRUCT_INPUT; } @@ -3811,15 +3808,14 @@ if it was a match because of inadequate input). if (nomatch && obj == 0) return 0; - dict_flags_of_noun = 0; + current_noun_is_plural = false; If input has run out then always match, with only quality 0 (this saves time). if (wn > num_words) { if (nomatch) return 0; - if (indef_mode ~= 0) - dict_flags_of_noun = $$01110000; Reject "plural" bit + if (indef_mode ~= 0) current_noun_is_plural = false; MakeMatch(obj,0); #Ifdef DEBUG; if (parser_trace >= 5) print " Matched (0)^"; @@ -3838,10 +3834,9 @@ if it was a match because of inadequate input). .MMbyPN; - if (parser_action == ##PluralFound) - dict_flags_of_noun = dict_flags_of_noun | 4; + if (parser_action == ##PluralFound) current_noun_is_plural = true; - if (dict_flags_of_noun & 4) { + if (current_noun_is_plural) { if (~~allow_plurals) k = 0; else { if (indef_mode == 0) { @@ -3879,12 +3874,12 @@ if it was a match because of inadequate input). } threshold = 1; - dict_flags_of_noun = RelevantNounBits(w); + current_noun_is_plural = TreatNounAsPlural(w); w = NextWord(); while (Refers(obj, wn-1)) { threshold++; if (w) - dict_flags_of_noun = dict_flags_of_noun | (RelevantNounBits(w)); + current_noun_is_plural = current_noun_is_plural | (TreatNounAsPlural(w)); w = NextWord(); } @@ -3892,11 +3887,14 @@ if it was a match because of inadequate input). jump MMbyPN; ]; -[ RelevantNounBits w b; - if (w == 0) return 0; - b = w->#dict_par1; - if (b & $$10000) return b & $$01110000; - return b & $$01110100; +[ TreatNounAsPlural w b; + if (w) { + b = w->#dict_par1; + if (b & DICTPAR1_SING) rfalse; + if (b & DICTPAR1_TRUNC) rfalse; + if (b & DICTPAR1_PLURAL) rtrue; + } + rfalse; ];
§56. Refers. Refers works out whether the word at number wnum can refer to the object @@ -3953,7 +3951,7 @@ if it is a pronoun, for (j=1 : j<=s : j=j+3) if (i == LanguagePronouns-->j) return j+2; - if ((i->#dict_par1)&128 == 0) rfalse; + if ((i->#dict_par1) & DICTPAR1_NOUN == 0) rfalse; return i; ]; @@ -4053,7 +4051,7 @@ Manual}, 4th edition. for (i=0:i<n:i++) { w = NextWordStopped(); if (w == 0 or THEN1__WD or COMMA_WORD or -1) break; - if ((RelevantNounBits(w)) & $$00000100) { + if (TreatNounAsPlural(w)) { parser_action = ##PluralFound; outcome = true; } @@ -4243,7 +4241,7 @@ is defined in the Standard Rules, not here. while (wn <= num_words) { l = NextWordStopped(); wn--; if (l == THEN1__WD) break; - if ( (l ~= -1 or 0) && (l->#dict_par1) &8 ) { wn++; continue; } if preposition + if ((l ~= -1 or 0) && (l->#dict_par1) & DICTPAR1_PREP) { wn++; continue; } if preposition if (l == ALL1__WD or ALL2__WD or ALL3__WD or ALL4__WD or ALL5__WD) { wn++; continue; } SafeSkipDescriptors(); save the current match state diff --git a/docs/WorldModelKit/S-tst.html b/docs/WorldModelKit/S-tst.html index ad20e3390..ae0ea6845 100644 --- a/docs/WorldModelKit/S-tst.html +++ b/docs/WorldModelKit/S-tst.html @@ -374,9 +374,9 @@ out the I6 command verb grammar for the supplied command.
[ ShowVerbSub address lines meta i x; wn = 2; x = NextWordStopped(); - if (x == 0 || ((x->#dict_par1) & 1) == 0) + if (x == 0 || ((x->#dict_par1) & DICTPAR1_VERB) == 0) "Try typing ~showverb~ and then the name of a verb."; - meta = ((x->#dict_par1) & 2)/2; + meta = ((x->#dict_par1) & DICTPAR1_META)/2; i = DictionaryWordToVerbNum(x); address = VM_CommandTableAddress(i); lines = address->0; diff --git a/docs/final-module/4-fi6.html b/docs/final-module/4-fi6.html index ec54fcf19..7085c134b 100644 --- a/docs/final-module/4-fi6.html +++ b/docs/final-module/4-fi6.html @@ -218,6 +218,7 @@ we will need for the code we are compiling. But this seems a good time to make i WRITE("!%% $ZCODE_LESS_DICT_DATA=1;\n"); WRITE("!%% $LONG_DICT_FLAG_BUG=0;\n"); WRITE("!%% $DICT_IMPLICIT_SINGULAR=1;\n"); + WRITE("!%% $DICT_TRUNCATE_FLAG=1;\n"); if (omit_ur) WRITE("!%% $OMIT_UNUSED_ROUTINES=1;\n"); CodeGen::deselect(gen, saved);diff --git a/inform6/Inform6/ReleaseNotes.html b/inform6/Inform6/ReleaseNotes.html index 9d929efad..c8183b23c 100644 --- a/inform6/Inform6/ReleaseNotes.html +++ b/inform6/Inform6/ReleaseNotes.html @@ -31,9 +31,15 @@ These are the changes delivered in version 6.42 of the Inform compiler.
A new dictionary flag has been introduced, "singular", which is set for any non that is not a plural. +
A new dictionary word flag has been introduced, "singular", which is set for any noun that is not a plural. This can be explicitly set or not set in a dictionary word with the '//s' syntax, i.e. 'word//s' to set it, or 'word//~s' to not set it. +
A new setting $DICT_TRUNCATE_FLAG has been added. If this is set to 1, then bit 6 of the dictionary +word flag is set for any word whose source code definition is truncated to fit in the dictionary. In --trace dict +listings, this is shown as "tr" when the flag is set. +Without this option, bit 6 of the dictionary word flag is set for all verbs (which is the old behavior, redundant with bit 1). +If the compiler truncates only the //p flag (as in $LONG_DICT_FLAG_BUG), that does not count as truncating +the dictionary word: the only relevant test is whether or not characters were dropped.