From 87fde14ea7adb24ecf435bc12e999fab7ea07b89 Mon Sep 17 00:00:00 2001 From: Leorize Date: Sun, 25 Jul 2021 10:48:29 -0500 Subject: [PATCH 1/2] use one env for all symbols The approach of creating child environment comes from the time where CPS has to manually track scope. Nowadays we use the information that is in the AST itself, so this is no longer necessary. --- cps/transform.nim | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/cps/transform.nim b/cps/transform.nim index 4d825f4b..757a50b6 100644 --- a/cps/transform.nim +++ b/cps/transform.nim @@ -9,7 +9,7 @@ export Continuation, ContinuationProc, cpsCall, cpsMustJump when CallNodes - {nnkHiddenCallConv} != nnkCallKinds: {.error: "i'm afraid of what you may have become".} -proc annotate(parent: var Env; n: NormNode): NormNode +proc annotate(env: var Env; n: NormNode): NormNode proc makeContProc(name: Name, cont: Name, source: NimNode): ProcDef = ## creates a continuation proc with `name` using continuation @@ -625,21 +625,12 @@ proc shimAssign(env: var Env; store: NormNode, call: Call, tail: NormNode): Norm shim.add env.annotate(body) result = shim -proc annotate(parent: var Env; n: NormNode): NormNode = +proc annotate(env: var Env; n: NormNode): NormNode = ## annotate `input` or otherwise prepare it for conversion into a - ## mutually-recursive cps convertible form; the `parent` environment - ## may be mutated as a side-effect, otherwise a new environment will be - ## created which points to this parent. - - # the accumulated environment - var env = - if n.kind == nnkStmtList: - newEnv(parent) - else: - parent + ## mutually-recursive cps convertible form # first, rewrite any symbols that have been moved to the env - var n = rewriteSymbolsIntoEnvDotField(parent, n) + var n = rewriteSymbolsIntoEnvDotField(env, n) # the result is a copy of the current node result = copyNimNode n From b796bbbf4b731af3a9526290de1be96cb410cebd Mon Sep 17 00:00:00 2001 From: Leorize Date: Sun, 25 Jul 2021 11:11:22 -0500 Subject: [PATCH 2/2] collect all locals in annotate then rewrite them after Since we are now storing all locals in a single `Env`, we can move the locals to env rewrite outside of annotate, which saves us a lot of processing time (due to reduced re-iteration of the same ast). Testing with cpstest shows a compile-time reduction from 74.760s to 50.019s (33% improvement). --- cps/transform.nim | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/cps/transform.nim b/cps/transform.nim index 757a50b6..849b3664 100644 --- a/cps/transform.nim +++ b/cps/transform.nim @@ -629,9 +629,6 @@ proc annotate(env: var Env; n: NormNode): NormNode = ## annotate `input` or otherwise prepare it for conversion into a ## mutually-recursive cps convertible form - # first, rewrite any symbols that have been moved to the env - var n = rewriteSymbolsIntoEnvDotField(env, n) - # the result is a copy of the current node result = copyNimNode n result.doc "start annotate at " & n.lineAndFile @@ -1105,11 +1102,8 @@ proc cpsTransformProc(T: NimNode, n: NimNode): NormNode = Trace.hook env.first, n # hooking against the proc (minus cloned body) body.add n.body # add in the cloned body of the original proc - # perform sym substitutions (or whatever) - n.body = env.rewriteSymbolsIntoEnvDotField body - # transform defers - n.body = rewriteDefer n.body + n.body = rewriteDefer body # rewrite non-yielding cps calls n.body = env.rewriteVoodoo n.body @@ -1117,6 +1111,9 @@ proc cpsTransformProc(T: NimNode, n: NimNode): NormNode = # annotate the proc's body n.body = env.annotate n.body + # perform sym substitutions (or whatever) + n.body = env.rewriteSymbolsIntoEnvDotField n.body + if n.body.firstReturn.isNil: # fixes https://github.com/disruptek/cps/issues/145 # by ensuring that we always rewrite termination