There is no semicolon at the end of the @set_cursor instruction, but the compiler compiles without complaint. And the program does not run properly.
[ Main key;
@set_cursor 3 3
print "Hello, World!";
@read_char 1 ->key;
];
There is no semicolon at the end of the @set_cursor instruction, but the compiler compiles without complaint. And the program does not run properly.
[ Main key;
@set_cursor 3 3
print "Hello, World!";
@read_char 1 ->key;
];
The compiler is not very strict about Z-machine assembly syntax. For EXT/VAR opcodes, it just accepts “0 to 4” arguments and leaves it up to the author to make sure the result is valid Z-code.
By leaving off the semicolon, you’re writing a four-argument opcode:
@set_cursor 3 3 print "Hello, World!";
I’m not sure how the keyword print
is getting transformed into an argument value. The compiler should catch this as an error, so that’s a bug. But I don’t see it as worth getting into at this point.
Now I know that, I’ll be more careful; it’s a difficult error to detect. I had put a comment at the end of the instruction, so I didn’t see that the semicolon was missing.
I looked a little farther and it turns out it’s not even invalid code!
I6 defines a “print” property, although the manual admits it’s pointless. See §3.12.
…provided because it logically ought to be, rather than because it’s useful.
You can write, for example:
val = "This is a string.";
val.print();
So print
is a valid constant – it’s a property ID. In Z-code it happens to always be 70. Since I6 is not strongly typed, you can use it in any expression, not just val.print
. Opcode arguments can be any constant or variable. So there you are.
Ah, I6, one of the few C-style languages that has no qualms about having a built-in property with the same name as a built-in keyword and no type checking to tell the difference…