tmedwards / sugarcube-2

SugarCube is a free (gratis and libre) story format for Twine/Twee.
https://www.motoslave.net/sugarcube/2/
BSD 2-Clause "Simplified" License
185 stars 42 forks source link

Child tags don't have to be unique. #77

Closed ChapelR closed 4 years ago

ChapelR commented 4 years ago

For example:

Macro.add("whatever", tags : [ "else" ], handler : function () {});

Doesn't throw.

I'm not sure if this is on purpose. Probably a breaking change either way for version 2, but as I was explaining this to someone on the Discord, it occurred to me that this may be a bug or limitation, so I figured I'd open an issue just in case.

tmedwards commented 4 years ago

Child tags do not have to be unique, unlike macro names. This is definitely intentional and not a bug.

The standard library uses this in, at least, the <<createaudiogroup>> and <<createplaylist>> macros with their <<track>> children.

cyrusfirheir commented 4 years ago

Wouldn't that be problematic if someone tried nesting two macros with the same child macros?

<<ship "The Freedom">>
<<big>> /* this 'big' is a child of the 'ship' */
  <<deck 3>>
  <<big>> /* this 'big' is a child of the 'deck' */
  <</deck>>
<</ship>>

Is this a potential problem, or does it all work out because things unravel inside out? (which I assume from how macros look like they work, don't know for sure)

Of course, it'd be axing your own foot to write such overlapping and ambiguous code, but you never know...

ChapelR commented 4 years ago

@cyrusfirheir since you can't interleave macros, I do believe the innermost <<big>> will always be associated with <<deck>>.

cyrusfirheir commented 4 years ago

Right... That's what I'd thought would be the case. That makes things a bit simpler.

tmedwards commented 4 years ago

@cyrusfirheir Parsing is non-ambiguous in that case. As speculated by @ChapelR , a child tag will always be associated with its directly enclosing macro, so nesting macros with same named child tags is safe.

That said. It is also possible to write macros that are meant to act as children of another macro without actually being child tags—i.e., <<break>> and <<continue>> as children of <<for>>. In such a case, you'd have issues with duplicate children, because they're macros not child tags. The noted macros have to be written that way, since they must be usable within other macros—e.g., within <<if>> for loop control.

cyrusfirheir commented 4 years ago

<MacroContext>.contextHas() is the key here, huh... Understood.

tmedwards commented 4 years ago

I think this has been resolved.