From f453de631d87e6f9a25eb84e0dff2c6652210fe9 Mon Sep 17 00:00:00 2001 From: prod2 <95874442+prod2@users.noreply.github.com> Date: Sun, 6 Feb 2022 04:21:32 +0100 Subject: [PATCH] wip closures: dedupliacation of upvalue references --- src/ndspkg/compiler.nim | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/ndspkg/compiler.nim b/src/ndspkg/compiler.nim index a11ad8e..9d2910e 100644 --- a/src/ndspkg/compiler.nim +++ b/src/ndspkg/compiler.nim @@ -407,22 +407,30 @@ proc addUpvalue(comp: Compiler, index: int): int = ## and creates an upvalue in every function up until the one ## including this local so that all of the function scopes in between ## have the right upvalue in them (compile time) - + ## + ## does not create duplicates: at each layer it will first find existing ones + ## and create references to that further down the line + template lenCheck(scope: Scope, blk: untyped) = if scope.upvalues.len() >= argMax: comp.error("Too many closure variables in function.") blk - let local = comp.locals[index] - var scopeIndex = local.depth + var scopeIndex = comp.locals[index].depth var isLocal = true - var upvalIndex: int + var upvalIndex: int = index while scopeIndex < comp.scopes.len(): let scope = comp.scopes[scopeIndex] if scope.function: scope.lenCheck(): return 0 - scope.upvalues.add(Upvalue(index: if isLocal: index else: upvalIndex, isLocal: isLocal)) + block ensure: # exiting this block means that the upvalueIndex is updated and points to the upvalue within scope + for i in countup(0, scope.upvalues.high()): + let upval = scope.upvalues[i] + if upval.index == upvalIndex and upval.isLocal == isLocal: + upvalIndex = i + break ensure + scope.upvalues.add(Upvalue(index: upvalIndex, isLocal: isLocal)) isLocal = false upvalIndex = scope.upvalues.high() scopeIndex.inc