summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/lowerings.nim6
-rw-r--r--compiler/pragmas.nim11
-rw-r--r--compiler/transf.nim3
-rw-r--r--compiler/wordrecg.nim4
-rw-r--r--tests/fields/timplicitfieldswithpartial.nim18
5 files changed, 35 insertions, 7 deletions
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index 787216bb3..9612ff0ab 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -182,8 +182,9 @@ proc addField*(obj: PType; s: PSym) =
   field.position = sonsLen(obj.n)
   addSon(obj.n, newSymNode(field))
 
-proc addUniqueField*(obj: PType; s: PSym) =
-  if lookupInRecord(obj.n, s.id) == nil:
+proc addUniqueField*(obj: PType; s: PSym): PSym {.discardable.} =
+  result = lookupInRecord(obj.n, s.id)
+  if result == nil:
     var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info)
     field.id = -s.id
     let t = skipIntLit(s.typ)
@@ -191,6 +192,7 @@ proc addUniqueField*(obj: PType; s: PSym) =
     assert t.kind != tyStmt
     field.position = sonsLen(obj.n)
     addSon(obj.n, newSymNode(field))
+    result = field
 
 proc newDotExpr(obj, b: PSym): PNode =
   result = newNodeI(nkDotExpr, obj.info)
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index c279e088c..5acfbc919 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -25,7 +25,7 @@ const
     wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
     wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
     wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
-    wOverride, wConstructor, wExportNims, wUsed}
+    wOverride, wConstructor, wExportNims, wUsed, wLiftLocals}
   converterPragmas* = procPragmas
   methodPragmas* = procPragmas+{wBase}-{wImportCpp}
   templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
@@ -70,6 +70,14 @@ const
                       wThread, wRaises, wLocks, wTags, wGcSafe}
   allRoutinePragmas* = methodPragmas + iteratorPragmas + lambdaPragmas
 
+proc getPragmaVal*(procAst: PNode; name: TSpecialWord): PNode =
+  let p = procAst[pragmasPos]
+  if p.kind == nkEmpty: return nil
+  for it in p:
+    if it.kind == nkExprColonExpr and it[0].kind == nkIdent and
+        it[0].ident.id == ord(name):
+      return it[1]
+
 proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
 # implementation
 
@@ -978,6 +986,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
         noVal(it)
         if sym == nil: invalidPragma(it)
         else: sym.flags.incl sfUsed
+      of wLiftLocals: discard
       else: invalidPragma(it)
     else: invalidPragma(it)
 
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 9c947fc1e..c3bdd4ddc 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -21,7 +21,7 @@
 import
   intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os,
   idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread,
-  lambdalifting, sempass2, lowerings, lookups, destroyer
+  lambdalifting, sempass2, lowerings, lookups, destroyer, liftlocals
 
 type
   PTransNode* = distinct PNode
@@ -978,6 +978,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
     liftDefer(c, result)
     #result = liftLambdas(prc, result)
     when useEffectSystem: trackProc(prc, result)
+    liftLocalsIfRequested(prc)
     if c.needsDestroyPass and newDestructors:
       result = injectDestructorCalls(prc, result)
     incl(result.flags, nfTransf)
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index 19e182942..f5ba35dfb 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -66,7 +66,7 @@ type
     wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
     wAsmNoStackFrame,
     wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks,
-    wPartial, wExplain,
+    wPartial, wExplain, wLiftLocals,
 
     wAuto, wBool, wCatch, wChar, wClass,
     wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
@@ -152,7 +152,7 @@ const
     "computedgoto", "injectstmt", "experimental",
     "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
     "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked",
-    "guard", "locks", "partial", "explain",
+    "guard", "locks", "partial", "explain", "liftlocals",
 
     "auto", "bool", "catch", "char", "class",
     "const_cast", "default", "delete", "double",
diff --git a/tests/fields/timplicitfieldswithpartial.nim b/tests/fields/timplicitfieldswithpartial.nim
index 996912a1a..a315cc5d0 100644
--- a/tests/fields/timplicitfieldswithpartial.nim
+++ b/tests/fields/timplicitfieldswithpartial.nim
@@ -1,6 +1,8 @@
 discard """
   output: '''(foo: 38, other: string here)
-43'''
+43
+100
+90'''
 """
 
 type
@@ -17,3 +19,17 @@ proc my(f: Foo) =
 var g: Foo
 new(g)
 my(g)
+
+type
+  FooTask {.partial.} = ref object of RootObj
+
+proc foo(t: FooTask) {.liftLocals: t.} =
+  var x = 90
+  if true:
+    var x = 10
+    while x < 100:
+      inc x
+    echo x
+  echo x
+
+foo(FooTask())