Skip to content

Commit

Permalink
Duplicate function definiton workaround
Browse files Browse the repository at this point in the history
  • Loading branch information
jjv360 committed Jan 29, 2023
1 parent 1dae01b commit 6009352
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 12 deletions.
2 changes: 1 addition & 1 deletion classes.nimble
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Package
version = "0.2.14"
version = "0.2.15"
author = "jjv360"
description = "Adds class support to Nim."
license = "MIT"
Expand Down
47 changes: 36 additions & 11 deletions src/classes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -403,11 +403,10 @@ proc createClassStructure(head: NimNode, bodyNode: NimNode, result: NimNode, isS
if isStatic:

# Inject unused typedesc placeholder as the first param
let underscore = ident"_"
let vv = quote do:
proc a(`underscore`: typedesc[`className`])

methodNode.params.insert(1, vv.params[1])
let classTypedesc = newNimNode(nnkBracketExpr)
classTypedesc.add(ident"typedesc")
classTypedesc.add(className)
methodNode.params.insert(1, newIdentDefs(ident"_", classTypedesc))

else:

Expand Down Expand Up @@ -622,11 +621,10 @@ proc createClassStructure(head: NimNode, bodyNode: NimNode, result: NimNode, isS
if isStatic:

# Inject unused typedesc placeholder as the first param
let underscore = ident"_"
let vv = quote do:
proc a(`underscore`: typedesc[`className`])

methodNode.params.insert(1, vv.params[1])
let classTypedesc = newNimNode(nnkBracketExpr)
classTypedesc.add(ident"typedesc")
classTypedesc.add(className)
methodNode.params.insert(1, newIdentDefs(ident"_", classTypedesc))

else:

Expand Down Expand Up @@ -769,7 +767,34 @@ proc createClassStructure(head: NimNode, bodyNode: NimNode, result: NimNode, isS
return `sharedVarName`
)

# if $className == "ClassConstr1":
# Workaround: Replace all static methods with procs instead, since there's an odd bug where Nim
# will duplicate the function definition in this exact condition:
# - Compiling to native (not JS)
# - Function is a `method`
# - There's a typedesc[] param type
#
# It's mostly safe to use procs I think for static methods, can't think of a reason not to... They don't have a `this` anyway.
for idx, child in result:

# Check type (remember first param is the return type)
if child.kind == nnkMethodDef and $child.params[1][0] == "_" and child.params[1][1].kind == nnkBracketExpr and $child.params[1][1][0] == "typedesc" and child.params[1][1][1] == className:

# This is a static method, replace with proc
let original = child
let copy = newNimNode(nnkProcDef)
copyChildrenTo(original, copy)
result[idx] = copy

# Remove base pragma, which doesn't apply to procs
var idx2 = 0
while idx2 < copy.pragma.len:
let pragmaItem = copy.pragma[idx2]
if pragmaItem.kind == nnkIdent and $pragmaItem == "base":
copy.pragma.del(idx2)
idx2 -= 1
idx2 += 1

# if $className == "WithStatic":
# echo result.repr

# Export new keyword which was imported from our lib
Expand Down
1 change: 1 addition & 0 deletions test.nim
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ class WithStatic:
method staticFunc2() {.used, static.} = discard

WithStatic.staticFunc()
WithStatic.staticFunc() # <-- Calling it twice



Expand Down

0 comments on commit 6009352

Please sign in to comment.