Repository navigation
fix(#170): stop rewriting "-" as "-1*" before compiling - #223
Merged
Merged
Conversation
The preprocessor turned every unary or binary minus into "-1*" (except
after e/E in a number, after "**", and before "="), so that -a**.5
would mean -(a**.5). But "-1*" binds tighter than the operator before
it, so any negative operand after / or // was evaluated wrong:
3/-3 -> 3/-1*3 = -9 (Python: -1)
7 // -2 -> 7//-1*2 = -14 (Python: -4)
v/-2 -> <-2,-4,-6> (Python: <-0.5,-1,-1.5>)
RapydScript already gives unary minus the right precedence relative
to "**" (-10**2 == -100, -x**-2 == -0.04), and the vector operator
overloading handles unary minus itself, so the rewrite is simply
removed.
Checked with a 39-case program through GlowScriptOffline (Python
semantics as the oracle): master fails the 7 division cases, this
passes all 39, including -10**2, -2**0.5, 10**-2, 1e-3, x -= 3,
-v, -v.x**2, -mag(v)**2, 3*-v and v - -v. JavaScript-mode programs
are unaffected (same results before and after), and all 23 bundled
demos run without errors.
Not fixed here: % with a negative operand still follows JavaScript's
remainder (7 % -3 == 1, Python: -2); that is RapydScript's own
behavior, tracked separately.
package/ and GlowScriptOffline RScompiler + compiler rebuilt with
build_original_py3.py (master rebuilds byte-identical).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QNw6KLiif2r9zSoSQug4iL
sspickle
added a commit
to vpython/rsWVPRunner
that referenced
this pull request
Nov 2, 2026
…ipt#223) GScompiler.js rewrote every unary minus as "-1*" before handing the program to RapydScript. Inside a division that changes the meaning: 3/-3 became 3/-1*3 = -9, 7 // -2 became -14, and v/-2 multiplied a vector by -2. RapydScript 0.7.22 already gets -10**2 = -100 right on its own, so the rewrite isn't needed. lib/compiling/GScompiler.js is copied from glowscript c14f759. It was identical to glowscript's copy before that commit. RScompiler.3.2.min.js and compiler.3.2.min.js are rebuilt with build_package.py. Tested with 39 negative-number cases on GlowScriptOffline using these package files: 7 wrong before, 0 after. All 23 bundled demos run with no errors before and after. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QNw6KLiif2r9zSoSQug4iL
This was referenced Nov 2, 2026
sspickle
added a commit
that referenced
this pull request
Nov 3, 2026
RapydScript gave unary operators the highest precedence, so "-x**2"
parsed as "(-x)**2", and the output stage turned that back into
"-Math.pow(x, 2)" only when the unary had no parentheses. Everything
else came out with the wrong sign:
-(x+1)**2 -> 36 (Python: -36)
-(x)**2 -> 25 (Python: -25)
- -x**2 -> -25 (Python: 25)
exp(-(x-3)**2/8) -> 1.65 (Python: 0.61)
The "-" -> "-1*" rewrite removed in #223 hid all of this, so #223
made it visible. maybe_unary now parses Python's "primary ** factor"
itself: after an atom, "**" takes the next unary expression as its
right operand. That binds ** tighter than a unary on its left and makes
it group right to left, which also fixes 2**3**2 (was 64, now 512) and
2**-1**2 (was 0.25, now 0.5) from #224.
tests/test_compiler.py: 21 power/unary expressions against CPython; 9
failed before the fix, all pass after. Through GlowScriptOffline: the
122-row arithmetic table now differs from CPython only in the 13 known
cases (% with negatives, round halves, int(bool), e), the #170 39-case
program has 0 failures, and all 23 demos run. **kwargs in calls and
definitions, comprehensions and conditionals with ** are unaffected.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QNw6KLiif2r9zSoSQug4iL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #170. Before compiling, the preprocessor rewrote every
-as-1*, except aftere/Ein a number, after**, and before=. The goal was for-a**.5to mean-(a**.5). But-1*binds tighter than the operator in front of it, so any negative operand after/or//came out wrong:3/-33/-1*37 // -27//-1*2v/-2RapydScript already gives unary minus the correct precedence relative to
**(-10**2 == -100,-x**-2 == -0.04). The vector operator overloading handles unary minus itself. So this PR just removes the rewrite.Testing
I used a 39-case program run through GlowScriptOffline, with Python's own results as the expected answers.
3/-3,7 // -2,x/-y,1/-x**2,2/-(x),v/-2, …)-10**2,-x**-2,-2**0.5,10**-2,1e-3,2E-2,x -= 3,f(-1),[-1, -2],range(-3, 0), plus vectors-v,-v.x**2,-mag(v)**2,-y*a,3*-v,v - -v,-dot(v, a),a*-x/ypackage/and the GlowScriptOfflineRScompilerandcompilerfiles were rebuilt withbuild_original_py3.py. Rebuilding master with the same toolchain reproduces its committed files byte for byte, so the diff in those files is only this change.Not fixed here
%with a negative operand still follows JavaScript's remainder:7 % -3 == 1, where Python gives −2. That's RapydScript's own behavior, not the preprocessor's.2**-1**2gives 0.25, where Python gives 0.5. This is also inside RapydScript.Both belong with #217, the RapydScript refresh.
🤖 Generated with Claude Code