Skip to content

Conversation

@Aseminaunz
Copy link

Rendered

Allow empty statements as introduced in Lua 5.2:

;do ; end;

To solve it, the tool will likely want to insert a semicolon at the beginning, and, to be sure, end of the statement. Doing so would also be dangerous, as a syntax error would occur if the statement already had any surrounding semicolons or no statement was preceding it in the block. Tools need to check the context to skip introducing a semicolon where it'd cause an error, adding unnecessary and probably unexpected complexity. If empty statements were allowed, tools could safely surround statements with semicolons, guarding against ambiguity without having to worry about context.

This is especially useful for simple "insert-replace" tools that don't perform a syntactic analysis of the code, such as search-and-replace operations in code editors, where currently each replacement would need review to avoid syntax errors.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tooling argument is compelling, but this argument is not. Using find-and-replace to make your code a horrible mess sounds like an antipattern, and the fact that you today might get parsing errors to correct intentionally actually sounds much better in comparison.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writing prettier or uglier code with more or fewer semicolons is up to the user. If they insert unnecessary semicolons, they can manually remove them where they see fit or pass the code through a formatter. "Ugly syntax" that is not ambiguous should not be a parsing error, regardless of how ugly it is.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If unnecessary semicolons are too horrendous to pass normally, Luau's linter could add a "DuplicatedSemicolon" lint when two or more semicolons are used in a row without whitespace in between. But this is merely style and imo should be up to an external tool. And hey, maybe someone wants to use double semicolons to be extra explicit about a no-op. They should be able to without errors or lint warnings.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make a clearer and more reasonable example: in my code, I might have a specific comment that I want to replace with a series of debugging statements when built for debug. For this, I use a simple CLI tool that replaces occurrences of that comment with my statements. If I want to avoid ambiguity, I'd need to either add a preceding semicolon where appropriate to the comments, or use a more sophisticated and unnecessary solution that performs a syntactic analysis. Both unideal for something theoretically dead simple.

end
```

This syntax however, unlike with statement blocks, is considerably confusing and unusual, has an unclear purpose, and is very likely a mistake, with little to no practical use cases. In table constructors, a single trailing separator is already allowed. No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are these obviously a mistake, but the proposed syntax isn't obviously a mistake? That feels like it needs to be articulated much more crisply.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

f(1, , 3) isn't clear as to whether the intention was to do f(1, nil, 3) or f(1, 3). In my opinion, the most likely thing is the user inserted a comma as placeholder and forgot to insert an actual value later.

Copy link
Author

@Aseminaunz Aseminaunz Oct 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike with statements, an "empty element" in these other list syntaxes does not make sense and needs to either be nil or skipped entirely. I don't believe I can find any benefits to allow "skipping" in those other contexts, and silently defaulting to either of those two solutions would do more harm than good.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not asking you to convince me here, I'm asking you to revise the RFC to be more convincing.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just stating it here for documentation and amending with any further observations when I can

```
> Error:2: Ambiguous syntax: this looks like an argument list for a function call, but could also be a start of new statement; use ';' to separate statements
To solve it, the tool will likely want to insert a semicolon at the beginning, and, to be sure, end of the statement. Doing so would also be dangerous, as a syntax error would occur if the statement already had any surrounding semicolons or no statement was preceding it in the block. Tools need to check the context to skip introducing a semicolon where it'd cause an error, adding unnecessary and probably unexpected complexity. If empty statements were allowed, tools could safely surround statements with semicolons, guarding against ambiguity without having to worry about context.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the tool will likely want to insert a semicolon at the beginning, and, to be sure, end of the statement

Beginning and end? Why? It's trivial to decide whether a semicolon is necessary by literally just stringifying the next statement, and then see if that string starts with (. If it starts with (, then add a ; to the current line, then \n and then add the indentation and finally, the statement string in question.

Something like this:

function print_block(stmts)
  local result = table.create(#stmts)

  for i, stmt in stmts do
    table.insert(result, print_stmt(stmt))
  end

  for i, stmt_str in result do
    local next_str = result[i + 1]
    if next_str == nil then
      break
    end

    local ends_with_semi_colon = string.byte(stmt_str, -1) == string.byte(";")
    local starts_with_open_paren = string.byte(next_str, 1) == string.byte("(")

    if not ends_with_semi_colon and starts_with_open_paren then
      result[i] ..= ";"
    end
  end

  return table.concat(result, "\n")
end

You can avoid an intermediate table if you wish, but I don't care. This argument is weak. Obviously, the specific code I've given you will still generate ; even when it isn't strictly necessary, but you can just replace ends_with_semi_colon with a function that takes some stmt and returns a boolean indicating whether the given stmt fragment ends with an expression and without a semi-colon. Still trivial.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants