I6 feature proposal: inline functions in arrays

@joelburton put in a proposal (with implementation – thanks!) for a new I6 language feature: inline functions in array definitions.

Array MyArray --> [
    [; print "I am inline!^"; return 42; ]
    [; print "Second!^"; ]
];

This is exactly analogous to the way you can define inline functions in object properties:

Object obj
  with prop [; print "I am inline!^"; return 42; ];

It makes sense to me, but it’s been a long time since we had a completely new language feature, so I wanted to open a discussion first.

Some details:

As with property inline functions, the default return value will be 0.

The array syntax is somewhat messy. You can write arrays in several ways:

Array arrname --> 1 2 3 4; 
Array arrname --> [ 1 2 3 4 ]; 
Array arrname --> [ 1; 2; 3; 4 ]; 

We can’t drop any of those, but obviously the bracket form is somewhat ambiguous with the idea of throwing [; function code... ] in there. Joel’s proposal handles this by requiring the bracket form of arrays, as in the example above. But this is potentially confusing. Also I haven’t tested how the optional semicolons work.

Maybe we can disambiguate by looking for a semicolon after the first bracket? I’m not sure what’s possible here.

5 Likes

As you write, it makes sense. It is already a known syntax for writing inline routines in properties and me (with quite limited knowledge…) can’t see that the addition could break some old code.

2 Likes

For some context for some readers: you can already have references to functions in arrays and call them, you have to create them and name them yourself:

[ myFunc1; blah blah; rfalse; ];
[ myFunc2; "Hello there"; ];

Array arrname --> [ myFunc1 myFunc2 ];

If you have a few of these, this gets a bit noisy to read, hence the proposal.

Thanks for raising the question here, @zarf . I look forward to people’s thoughts :slight_smile:

2 Likes

As someone who’s dabbled in I6, I like this idea. It would also make it easier to implement advanced menus or conversation menus using ext_menu.h or ext_talk_menu.h, since they use arrays in place of objects.

2 Likes

That’s what I hit, @blindHunter — trying to make a conversation system built with arrays.

Unfortunately, these can’t be a drop-in replacement for existing object-prop-arrays (you do have to access items differently (arr-->I vs obj.&prop-->I) and you’ll probably want to make it a ‘table’, so you have the length.

1 Like

Sounds like a great addition.

I believe we talked about it a few years ago, as it would be beneficial to the talk menu extension (part of the PunyInform library, but can also be used with the standard library if you’re targeting Z-code).

Unrelatedly, Graham asked for support for putting arbitrary statements in braces:

[ func;
  print 1;
  {
    print 2;
  }
];

This is legal in basically all C-like languages, but I6 doesn’t support it. But it looks like an easy feature to add.

2 Likes

I would think the trickiest bit might be getting scope correct. Assuming we want scope to be correct? That’s the main reason to enclose arbitrary things in brackets, I think?

Never a problem in I6, funnily enough! The only sort of identifier that doesn’t have global scope is the function argument. If you want local variables for loops and such, you just declare that the function/routine takes more arguments than it actually does, and the extra ones are yours to use as you like.

Since arguments have to be declared at the top of a routine, their scope is always exactly that routine. Nice and simple! Just don’t ask how the compiler figures out whether something is an identifier instead of a keyword in the first place…

(As an experienced I6 author, you’re probably used to it by now, but it’s a neat quirk of the language that very few others have.)

Man, I had forgotten that. But, right! So, would support for brackets mean… just deleting them?

I think so, yeah; making sure they’re balanced (so it doesn’t cause problems with if-statements and the like) but then ignoring them entirely. Presumably some part of I7 makes it easier to generate useless braces than to just…not.

This sounds right to me, @Draconis . There’s no advantage to the nested block, given the lack of scope stuff. Other than someone who just really, really wants to indicate the next 10 lines are related and group them up, they’d have no use. I also suspect, like you, the real reason would be to simplify i7-code-generation.

Unless: @zarf , would a block let you break out of the block (as do/while/for do). That would be sort-of-useful. But probably not what Graham meant.

Only slightly related: I’ve been building a language server for Inform6 to do stuff like IDE-like hover/structure/refactoring/identifier-matching and, as part of that, updated the Technical Manual’s BNF to modern Inform6. I’ve made an ANTLR4 grammar for it. Oh my is it a hairy language to build a grammar for simply, especially given the conditional-compilation stuff.

But I hope that once it’s complete and accurate (*), it might help anyone else that wants to make i6-parse-aware tools.

(*) currently, it parses all of the stdlib/puny/a few other large-ish inf files, so it’s probably at least somewhat close to right,

4 Likes

No, that’s not the C semantics so we shouldn’t do it.

1 Like