Skip to content

JS/Java backends: bitwise & vs comparison operator precedence differs from Python #333

@ldayton

Description

@ldayton

Summary

Python's bitwise & has higher precedence than comparison operators (!=, ==), so flags & FLAG != 0 means (flags & FLAG) != 0. In JavaScript and Java, & has lower precedence than !==/!=, so the same expression means flags & (FLAG !== 0) = flags & 1, which is wrong.

Tongues correctly parenthesizes for Perl (($flags & $FLAG) != 0) but not for JS or Java.

Reproduction

Python:

flags & FLAG != 0     # → (flags & FLAG) != 0 → correct

Transpiled JS:

flags & FLAG !== 0    // → flags & (FLAG !== 0) → flags & 1 → WRONG

Expected JS:

(flags & FLAG) !== 0  // → correct

Verification

>>> 6 & 2 != 0     # True  (because (6 & 2) = 2, 2 != 0)
> 6 & 2 !== 0      // 0     (because 2 !== 0 = true, 6 & 1 = 0)

Impact

9 instances in the Parable JS transpilation, all in _parse_matched_pair and _subst_matched_pair. This causes the DOLBRACE, ALLOWESC, EXTGLOB, ARITH, and DQUOTE flag checks to silently return wrong results, leading to incorrect brace/quote matching in parameter expansions.

This is the root cause of ~24 "unexpected EOF" errors in the JS backend (e.g., ${x:-a{b} fails because the DOLBRACE flag isn't detected, so the { inside the default value is incorrectly counted as opening a new brace group).

Ruby and Perl are not affected — Ruby's & has higher precedence than != (like Python), and Perl's transpilation already includes parentheses.

Java has the same precedence rules as JS and will have the same bug.

Discovered via ldayton/Parable#413.

Metadata

Metadata

Assignees

No one assigned

    Labels

    backendbugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions