Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support labeled statements #2889

Open
wrnrlr opened this issue Dec 8, 2024 · 5 comments · May be fixed by #2891
Open

Support labeled statements #2889

wrnrlr opened this issue Dec 8, 2024 · 5 comments · May be fixed by #2891
Assignees

Comments

@wrnrlr
Copy link

wrnrlr commented Dec 8, 2024

Feature suggestion

Labeled statements can come in handy when implementing complex control flow with multiple nested loops and if statements.

Currently parser will complain

function test1():void {
  let str = '';
  loop1: for (let i = 0; i < 5; i++) {
    if (i === 1) {
      continue loop1;
    }
    str = str + i;
  }
}
ERROR TS1109: Expression expected.
    :
 11 │ loop1: for (let i = 0; i < 5; i++) {
    │      ~
    └─ in assembly/index.ts(11,8)
@KazChe
Copy link
Contributor

KazChe commented Dec 13, 2024

If it's decided to move ahead with this, I was curious and had some ideas and questions

I've been digging into the codebase around parser, complier and how AST implementation looks like when I came across this issue and wanted to see if the potential implementation approaches make sense:

  1. Quick Fix:

    • Basic label-to-break or continue functionality
    • simple label tracking without full scope validation
    • focus on common loop label use cases first
  2. Full Implementation:

    • Complete label scope management and validation
    • Support for all label contexts (loops, blocks)
    • full integration with existing control flow system

and some followup questions:
What limitations or constraints should we be aware of before proceeding?
- for example should this support just loops or blocks as well
- should we restrict what control flow statements (break/continue) can target labeled statements?

Thanks.

@wrnrlr
Copy link
Author

wrnrlr commented Dec 15, 2024

That's funny, I've also encounter this when implementing a parser.
For my current usecase I would only need to break out of a nested for loops.
This is however not a insurmountable problem as my situation can be circumvented with some extra if statements.

I do know that in some code-bases, like the Linux kernel, they use labeled statements to avoid having to execute certain instructions for performance reasons. For example to jump directly to the error handling logic or return statement.

However you need full goto statements for that and those are not available in the JS/TS syntax.
JavaScript semantics also do not allow for a statement to break or continue to an outer labeled statement.

Maybe AssemblyScript can reinterpret an if statement with the true condition followed by a break statement to an outer label as a goto statement.

function example() {
  if (true) break ending;

  ending: console.log('LOL')
}

But I don't know the further implications of this hack or even claim this is a good idea, just an idea I had when thinking about this issue.

@JairusSW
Copy link
Contributor

JairusSW commented Dec 15, 2024

I would love to see this implemented. Would help solve a lot of my headaches with https://github.com/JairusSW/as-json

The support is there--built into wasm itself, so it shouldn't be that hard to get a POC going

@HerrCai0907 HerrCai0907 pinned this issue Dec 15, 2024
@HerrCai0907
Copy link
Member

In theory, it is not so hard to do it.
From language design perspective, TS also support label based break statement.
For WASM perspective, br to special labeled block is also possible.

@CountBleck
Copy link
Member

Maybe AssemblyScript can reinterpret an if statement with the true condition followed by a break statement to an outer label as a goto statement.

You can probably just do this right now, with the disadvantage of requiring you wrap the code in a block:

export function example(): void {
  do {
    console.log("Hey")
    if (true) break;
    console.log("skipped")
  } while (0)

  console.log('LOL')
}

I don't think adding more syntax differences between AS and JS is a good idea. As an aside: in JS, you can use a labeled block and a labeled break instead of the do { /* ... */ } while (0).

As for labeled statements...there's probably enough infrastructure to support labeled breaks in the Compiler (since unlabeled breaks are working just fine), but it'd definitely require parser and AST changes. I think an additional field to the AST nodes for for, while, do-while, and blocks themselves is enough, since labeling regular statements isn't very useful.

@CountBleck CountBleck self-assigned this Dec 16, 2024
CountBleck added a commit to CountBleck/assemblyscript that referenced this issue Dec 16, 2024
This requires an additional field to Flow that maps user-defined
statement labels to the internal Binaryen labels passed to module.br().
Thanks to the existing logic to handle unlabeled break/continue, adding
support for labeled break/continue is a breeze.

Fixes AssemblyScript#2889.
CountBleck added a commit to CountBleck/assemblyscript that referenced this issue Dec 16, 2024
This requires an additional field to Flow that maps user-defined
statement labels to the internal Binaryen labels passed to module.br().
Thanks to the existing logic to handle unlabeled break/continue, adding
support for labeled break/continue is a breeze.

Fixes AssemblyScript#2889.
CountBleck added a commit to CountBleck/assemblyscript that referenced this issue Dec 16, 2024
This requires an additional field to Flow that maps user-defined
statement labels to the internal Binaryen labels passed to module.br().
Thanks to the existing logic to handle unlabeled break/continue, adding
support for labeled break/continue is a breeze.

Fixes AssemblyScript#2889.
CountBleck added a commit to CountBleck/assemblyscript that referenced this issue Dec 17, 2024
This requires an additional field to Flow that maps user-defined
statement labels to the internal Binaryen labels passed to module.br().
Thanks to the existing logic to handle unlabeled break/continue, adding
support for labeled break/continue is a breeze.

Fixes AssemblyScript#2889.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants