Skip to content

Commit

Permalink
fix calling function pointers stored in variable (#247)
Browse files Browse the repository at this point in the history
This is done by restricting the concept of "having an implementation" in
normalizedast for Call to having a *routine* implementation. This is not
the best way to solve this, but it is suffice for CPS where we only care
about routine implementations for pragma/parameters inspection.
  • Loading branch information
alaviss authored Oct 18, 2021
1 parent 310bfaf commit 4a75626
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 4 deletions.
11 changes: 7 additions & 4 deletions cps/normalizedast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,7 @@ func pragma*(n: PragmaHaver): PragmaLike =
when n is RoutineDef | ProcDef:
PragmaStmt n.NimNode.pragma
elif n is Call:
if n.canGetImpl:
if n.hasImpl:
n.impl.pragma
else:
PragmaStmt newEmptyNormNode()
Expand Down Expand Up @@ -1030,12 +1030,15 @@ func canGetImpl*(n: Call): bool =
n.name.isSymbol

func hasImpl*(n: Call): bool =
## the callee's name is a symbol and an impl is present
n.name.isSymbol and n.name.NimNode.getImpl.kind != nnkNilLit
## the callee's name is a symbol and a routine impl is present
n.name.isSymbol and n.name.NimNode.getImpl.kind in RoutineNodes

func impl*(n: Call): RoutineDef =
## return the `RoutineDef` associated to this `Call` `n`
RoutineDef n.name.NimNode.getImpl
if n.hasImpl:
result = RoutineDef n.name.NimNode.getImpl
else:
error("call does not have an implementation", n.name.NimNode)

proc resymCall*(n: Call; sym, field: NormNode): Call =
## this is used to rewrite continuation calls into their results
Expand Down
31 changes: 31 additions & 0 deletions tests/taste.nim
Original file line number Diff line number Diff line change
Expand Up @@ -466,3 +466,34 @@ suite "tasteful tests":

foo()
check r == 1

block:
## calling a non-local function pointer
r = 0
proc bar() =
inc r

let fn = bar
proc foo() {.cps: Cont.} =
noop()
inc r
fn()

foo()
check r == 2

block:
## calling a local proc variable
skip "pending #185":
r = 0
proc bar() =
inc r

proc foo() {.cps: Cont.} =
let fn = bar
noop()
inc r
fn()

foo()
check r == 2

0 comments on commit 4a75626

Please sign in to comment.