-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Add Optional JavaScript 'let' variables #13851
Conversation
Are you sure that this won't break things? |
What's the point? JS JIT engines should have no problem optimizing |
|
@Araq Problem is that is easily reversible:
JavaScript user base is the biggest basically, attract them here may be good for Nim. @timotheecour Maybe when defined(js) and defined(nimJsLet):
{.warning: "JavaScript target uses 'let', injected variables are not global".} Help prove me wrong, break it, I also try to break it, but it seems that Nim codegen is good, |
So simply enable it all the time. |
changelog.md
Outdated
@@ -10,10 +10,11 @@ | |||
|
|||
## Compiler changes | |||
|
|||
- Specific warnings can now be turned into errors via `--warningAsError[X]:on|off`. | |||
- The `define` and `undef` pragmas have been de-deprecated. | |||
- JavaScript backend adds compile-time optional `let` variable declarations, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- weirdly worded, how about:
JavaScript backend now useslet
instead ofvar
declarations; for previous behavior, compile with-d:nimJsVar
; see also https://caniuse.com/let
changelog.md
Outdated
@@ -12,6 +12,9 @@ | |||
|
|||
- Specific warnings can now be turned into errors via `--warningAsError[X]:on|off`. | |||
- The `define` and `undef` pragmas have been de-deprecated. | |||
- JavaScript backend adds compile-time optional `let` variable declarations, | |||
compile Nim with `-d:nimJsVar` for `var` and without for `let`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead how about using the standard flag --legacy
which is exactly for this purpose;
we already have: --legacy:allowSemcheckedAstModification|checkUnsignedConversions
we'd also now have:
--legacy:jsUseVar
or --legacy:jsvar
compiler/jsgen.nim
Outdated
@@ -1655,15 +1655,15 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) = | |||
varCode: string | |||
varName = mangleName(p.module, v) | |||
useReloadingGuard = sfGlobal in v.flags and p.config.hcrOn | |||
|
|||
const jsVarDecl = when defined(nimJsVar): "var" else: "let" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this makes no sense. Why do you need to recompile nim (aka different dialects) just to change nim's behavior?
instead either use isDefined(conf, "nimJsVar")
or, better, use the suggestion i gave above with --legacy:jsUseVar
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it compile time, because either it always works or never works,
and I dont see people switching back to var
if compiler uses let
already.
But ok.
if v.constraint.isNil: | ||
if useReloadingGuard: | ||
lineF(p, "var $1;$n", varName) | ||
if jsVarDecl: lineF(p, "var $1;$n", varName) else: lineF(p, "let $1;$n", varName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here + elsewhere, please make it more DRY:
introduce this once: let jsdecl = if jsVarDecl: "var" else: "let"
then use it everywhere relevant eg:
lineF(p, "$1 $2;$n", [jsdecl, varName])
code repetition = WET (all acronyms of which apply)
lineF(p, "if ($1 === undefined) {$n", varName) | ||
varCode = $varName | ||
inc p.extraIndent | ||
else: | ||
varCode = "var $2" | ||
varCode = if jsVarDecl: "var $2" else: "let $2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
varCode = jsdecl & " $2"
@@ -1673,8 +1673,12 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) = | |||
if n.kind == nkEmpty: | |||
if not isIndirect(v) and | |||
v.typ.kind in {tyVar, tyPtr, tyLent, tyRef, tyOwned} and mapType(p, v.typ) == etyBaseIndex: | |||
lineF(p, "var $1 = null;$n", [varName]) | |||
lineF(p, "var $1_Idx = 0;$n", [varName]) | |||
if jsVarDecl: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto: no branching needed:
lineF(p, "$1 $2 = null;$n", [jsdecl, varName])
lineF(p, "$1 $2_Idx = 0;$n", [jsdecl,varName])
@@ -1702,7 +1706,11 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) = | |||
else: | |||
if targetBaseIndex: | |||
let tmp = p.getTemp | |||
lineF(p, "var $1 = $2, $3 = $1[0], $3_Idx = $1[1];$n", | |||
if jsVarDecl: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto.
proc fun1(): int = result = 11
doAssert fun1() == 11
let a = @[1,2]
echo a
when true:
block: # works without block
var flag = false
proc wrap(): int =
discard flag
result = 12
doAssert wrap() == 12 |
let
variable declarations.-d:jsLet
forlet
variable declarations, otherwisevar
is used.0
lines added, everything is done at compile-time.codegenDecl
everywhere is not better.I try compiling Karax examples and they work just Ok. NodeJs also works Ok.
We can try enabling it on Nightly or Betas, if no bug are reported for a while it can be switched to default, or just leave it as optional, is a nice option to have for Frontend people.