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

Add shadow variable assignment similar to proc backend shadow calls #13400

Open
kristianmandrup opened this issue Feb 12, 2020 · 5 comments
Open

Comments

@kristianmandrup
Copy link

kristianmandrup commented Feb 12, 2020

Summary

Add ability to shadow variable assignment similar to proc shadowing calls to backend functions

Description

For a proc, we can redirect the function to call an underlying backend function with the same arguments

      result.add("function $#() { return $#.apply(this, arguments); }$n" %
                  [thunkName, name])

For jsgen it means it is currently impossible to do ES module imports (as far as I can see)

template assign(varName, importName: string): string = 
  varName & " = " & importName

template declareVar(varName: untyped, value: typed, vName: string, importName: typed, filePath: typed) =
  var varName = value
  {.emit: assign(astToStr(varName), importName) .}  
    
declareVar(foo, 0, "foo", "x", "x")
echo $foo

Emits

var foo_42018 = [0];
foo = x // foo undeclared identifier

Here the most recent jsgen code for proc and var generation respectively:

proc genProc(oldProc: PProc, prc: PSym): Rope =
      # The added indirection ensures that such references will end up calling the reloaded code.
      var thunkName = name
      name = name & "IMLP"
      result.add("function $#() { return $#.apply(this, arguments); }$n" %
                  [thunkName, name])

For variable generation, there is no indirection, mapping to backend variables (that I can see)

Would be great if we could do sth like:

var x: string {.importjs "$# = jsX" }

Where $# is the generated (mangled) var identifier and jsX is the pointer to a Javascript backend variable

This would emit the correct Javascript:

import { x } from 'x'

var foo_42018 = [0]; // could we avoid requiring setting this to initial value at tall times?
foo_42018 = x // indirection similar to that done for function gen

Instead of

var foo_42018 = [0];
foo = x // undefined foo
@kristianmandrup
Copy link
Author

kristianmandrup commented Feb 13, 2020

Alternatively/Additionally, it would be very convenient if there was a way to store the last used identifier and be able to reference it in pragmas that follow, so that the above could be done as:

var varName = value
{.emit: "$ID = " & jsVarName .}

@kristianmandrup
Copy link
Author

kristianmandrup commented Feb 13, 2020

As far as I can see, this could be done pretty easily by storing a the name of the last (mangled) var identifier on p:

proc genVarInit(p: PProc, v: PSym, n: PNode) =
  var
    a: TCompRes
    s: Rope
    varCode: string
    # The mangled varName which will be output
    varName = mangleName(p.module, v) 
    useReloadingGuard = sfGlobal in v.flags and p.config.hcrOn

    # store varName on p so that we can reference it later
    p.lastVarName = varName

In genAsmOrEmitStmt replacing $ID with the stored identifier

# replace $ID special ref placeholder with stored lastVarName
proc replaceSpecial(p: PProc, strVal: string): string = 
    strVal.replace "$ID", p.lastVarName

proc genAsmOrEmitStmt(p: PProc, n: PNode): PProc =
  genLineDir(p, n)
  p.body.add p.indentLine(nil)
  for i in 0..<n.len:
    let it = n[i]
    case it.kind
    of nkStrLit..nkTripleStrLit:
      # replace $ID special ref placeholder with stored lastVarName
      var strVal = replaceSpecial(p, it.strVal)
      p.body.add(strVal)

@Araq
Copy link
Member

Araq commented Feb 13, 2020

It's really unclear to me what you're proposing. Please do not compare the C backend with the JS backend, it's only distracting. These are different things with different purposes. Also don't try to outline how the implementation is gonna look like. Instead focus on the feature description, how it should look like and what problem it solves.

@kristianmandrup
Copy link
Author

Ok, I have reworked the feature proposal to make it more clear and not mention C backend

@kristianmandrup
Copy link
Author

This PR addresses:

They all have the objective of making JS generation more flexible and powerful in general and able to support ES modules and other more advanced JS features. Still a WIP. Hope to get it done by next weekend.

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

No branches or pull requests

2 participants