[I6] Table array with one entry illegal?

I ran into something strange while working on one of the exercises in DM4. Here’s a quick demo:

Constant Story "Table of Tables Test";
Constant Headline "^(can't have a one-entry table?)^";

Include "Parser";
Include "VerbLib";
Include "Grammar";

Array x_types table "yyy" "zzz";
Array x_names table yyy_names zzz_names;

Array yyy_names table 'yyy' 'zzz';
Array zzz_names table 'aaa';


Class Room
    has light;

Room Start "Starting Point"
    with    description
                "An uninteresting room.";


[ Initialise i ;

    location = Start;
    for (i=1:i<=(x_names-->0): i++)
        {
            print "<Table ", i, " (", (string) x_types-->i, "): addr = ", x_names-->i,
                    ", entries = ", (x_names-->i)-->0, ">^";
        }

];

When run, the first lines produced are:

<Table 1 (yyy): addr = 7298, entries = 2>
<Table 2 (zzz): addr = 7304, entries = 386>

Note that the number of entries in table zzz_names is 386, not 1, as expected. Furthermore, zz_names–>1 seems to evaluate to zero, not the word address for ‘aaa’, as expected. [edited to reverse erroneous edit]

Is it not considered legal in I6 (v6.31) to declare a table array with just one entry? If so, how is the compiler interpreting this declaration in such a way as to not produce an error?

There are two forms of the Array declaration (see §2.4):

! 52 entries, initialized to zero
Array pack_of_cards --> 52;

! 6 entries, initialized as shown
Array small_primes --> 2 3 5 7 11 13;

If there’s one entry after the --> / table keyword, the compiler assumes you mean the first form, even if the entry is not a literal integer. (All literals in I6 have integer values, obviously.)

1 Like

Really, this should throw an error, since the integer value of 'aaa' is not known until backpatch time. When I test it, I sometimes get an error like:

An array must have between 1 and 32767 entries

But not always. There may be an uninitialized variable lurking in the code.

In any case, you don’t want N entries initialized to zero, so don’t do that.

The upshot is that there’s no way to define a one-entry array whose value is initialized to a specific value. If that was your question, that’s the answer. :)

1 Like

@zarf, [edit] I’ve now thoroughly confused things by editing and reversing edits for my original question and correcting my answer here; my apologies for the confusion.

I was hoping for a single-entry table-style array, such that: zzz_names–>0 == 1 (to indicate the number of entries) and zzz_names–>1 == ‘aaa’ (the value of the single entry).

If I’m understanding you correctly, you’re saying that the compiler treats ‘table’ and ‘–>’ interchangeably, and decides how to structure things based on the number of entries. I don’t think I am understanding correctly, because shouldn’t

Array names1 --> 'aaa' 'bbb';

produce something different from

Array names2 table 'aaa' 'bbb';

? I would think names1–>0 == ‘aaa’ and names2–>0 == 2 in those cases.

No. The difference is explained in the manual. An array defined with table is generated with N+1 entries, with the first one containing N.

@zarf, OK. That’s what I had thought from reading the manual, which was why I was thinking that

Array zzz_names table 'aaa';

would create an array with entries zzz_names–>0 == 1 and zzz_names–>1 == ‘aaa’, but it doesn’t.

Your second response makes it sound like there’s a possible compiler bug. If so, I would like to report it, but is the issue that it’s not creating a table-style array, or that it should properly decide to treat the “table” keyword as being equivalent to “–>” because there is only one entry? (I would hope for the former.)

I see I’m explaining this badly. The compiler first determines how many entries you want (N) by looking at the value or values after the keyword. Then it generates the array, adding one initial entry if the keyword is table.

The compiler bug is that it should detect that line of code as an error, because N should be the integer value of 'aaa', but that value can’t be known until later in compilation. I’m not sure what value it’s using. It might be a temporary marker for an unresolved dictionary word. It might be uninitialized.

@zarf, Ah. Now I think I understand. The address value of ‘aaa’ should be interpreted such that the line of code means “make a table-style array with entries” along the same pattern as:

Array zzz_names table 5;

And, if I’m understanding correctly, you’re saying that it does do that, only with some random value instead of the (unknown at the time) address value of ‘aaa’. (And the compiler trying to do this before knowing the address of ‘aaa’ would be the bug.)

Thank you for your patience in explaining the details, and, again, my apologies for confusing the issue.

Right! Sorry for being confusing my explanations.

You know, peering through the source, I stumble across this alternate format:

Array foo table [ 5 ];

You can have any number of values between the brackets, including one, or even zero. This isn’t mentioned in the DM4 but it’s described in comments.

So I guess you can use that!

(This syntax existed at least as far back as I6.21, so the DM4 should mention it…)

1 Like

At least according to the manual, this ought to be the result:

Array a1 --> 5;     ! produces array with 5 elements 0..4, init to zero
Array a2 --> 5 6;   ! produces array with 2 elements -->0=5, -->1=6
Array a3 table 5;   ! produces array with 2 elements -->0=1, -->1=5
Array a4 table 5 6; ! produces array with 3 elements -->0=2, -->1=5, -->2=6

If that’s not what it’s actually doing (in particular, if the third form is interpreted as creating 6 elements, as you appear to be suggesting), then that seems like a compiler bug.

Only the first form should be unsafe to use with a dictionary word or other late-patched value.

The table keyword is independent of the values after the keyword.

The manual gives this exact example when explaining the table keyword:

For example, the table

Array continents table 5;

has six entries: continents-->0 , which holds the number 5, and further entries continents-->1 to continents-->5 .

Ah. That’s unfortunate, but does resolve my confusion.

So this means that form 3 will actually produce:

Array a3 table 5;   ! produces array with 6 elements -->0=5, -->1..5=0

In which case yes, it would be nice if this produced a compiler error if the N is not a “real” numeric constant value.

(sigh) I can’t seem to type a proper sentence on this thread! For the benefit of anyone coming along in the future, I meant to type “The address value of ‘aaa’ should be interpreted such that the line of code means ‘make a table-style array with this many blank entries’ along the same pattern as…” (which, based on his answer, zarf correctly inferred, despite the lack of clarity).

Thanks again, zarf.

@mirality, Yes, the behavior you describe for the third form was what I was expecting, because I wasn’t thinking that ‘aaa’ would be interpreted as its literal value. The top of DM4 page 43 is explicit about that particular syntax, though. I agree that it seems more intuitive for it to work as you describe in the third form.

Now, it’s unclear whether an array of zero entries is legal.

Array foo --> 0;  ! generates an error
Array foo --> [];  ! works fine

I should make this consistent. I suppose that since the bracket notation was never documented, its behavior shouldn’t be taken as normative…

It creates a pointer to another random array?

If you do

Array foo1 --> [];
Array foo2 --> 4;

then foo1 and foo2 have the same address. This doesn’t violate any rules of the language and it wouldn’t cause any unexpected problems for “normal” array use. Of course accessing any elements of foo1 will cause a runtime error, if strict mode is on. That’s consistent with normal array rules.

It seems worthwhile to rule it out, anyhow.

1 Like

For future searchers, with respect to my original question: As zarf explained, the compiler understands (or at least should understand) the syntax

Array zzz_names 'aaa';

as a request to create a table-style array with a large number (equal to the literal value of the word ‘aaa’) of blank entries initialized to zero.

However, it looks like the intended structure can be easily set up with the alternate syntax

Array zzz_names --> 1 'aaa';

which creates an array with -->0 == 1 and -->1 == ‘aaa’.

1 Like

Or

Array zzz_names table [ 'aaa' ];
1 Like

Even better! And thank you for adding that, because, since you had chosen table [ 5 ] in your original example of the use of brackets (coincidentally the same number as the table 5 of my previous post), I hadn’t realized that there would be a significant difference in interpretation as a result of adding them.