implemented undocumented '.liftLocals' feature

This commit is contained in:
Andreas Rumpf 2017-11-02 10:42:11 +01:00
commit bd19b5f4d3
5 changed files with 35 additions and 7 deletions

View file

@ -182,8 +182,9 @@ proc addField*(obj: PType; s: PSym) =
field.position = sonsLen(obj.n) field.position = sonsLen(obj.n)
addSon(obj.n, newSymNode(field)) addSon(obj.n, newSymNode(field))
proc addUniqueField*(obj: PType; s: PSym) = proc addUniqueField*(obj: PType; s: PSym): PSym {.discardable.} =
if lookupInRecord(obj.n, s.id) == nil: result = lookupInRecord(obj.n, s.id)
if result == nil:
var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info) var field = newSym(skField, getIdent(s.name.s & $obj.n.len), s.owner, s.info)
field.id = -s.id field.id = -s.id
let t = skipIntLit(s.typ) let t = skipIntLit(s.typ)
@ -191,6 +192,7 @@ proc addUniqueField*(obj: PType; s: PSym) =
assert t.kind != tyStmt assert t.kind != tyStmt
field.position = sonsLen(obj.n) field.position = sonsLen(obj.n)
addSon(obj.n, newSymNode(field)) addSon(obj.n, newSymNode(field))
result = field
proc newDotExpr(obj, b: PSym): PNode = proc newDotExpr(obj, b: PSym): PNode =
result = newNodeI(nkDotExpr, obj.info) result = newNodeI(nkDotExpr, obj.info)

View file

@ -25,7 +25,7 @@ const
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC, wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl, wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe, wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
wOverride, wConstructor, wExportNims, wUsed} wOverride, wConstructor, wExportNims, wUsed, wLiftLocals}
converterPragmas* = procPragmas converterPragmas* = procPragmas
methodPragmas* = procPragmas+{wBase}-{wImportCpp} methodPragmas* = procPragmas+{wBase}-{wImportCpp}
templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty, templatePragmas* = {wImmediate, wDeprecated, wError, wGensym, wInject, wDirty,
@ -70,6 +70,14 @@ const
wThread, wRaises, wLocks, wTags, wGcSafe} wThread, wRaises, wLocks, wTags, wGcSafe}
allRoutinePragmas* = methodPragmas + iteratorPragmas + lambdaPragmas 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) proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
# implementation # implementation
@ -978,6 +986,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
noVal(it) noVal(it)
if sym == nil: invalidPragma(it) if sym == nil: invalidPragma(it)
else: sym.flags.incl sfUsed else: sym.flags.incl sfUsed
of wLiftLocals: discard
else: invalidPragma(it) else: invalidPragma(it)
else: invalidPragma(it) else: invalidPragma(it)

View file

@ -21,7 +21,7 @@
import import
intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os, intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os,
idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread, idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread,
lambdalifting, sempass2, lowerings, lookups, destroyer lambdalifting, sempass2, lowerings, lookups, destroyer, liftlocals
type type
PTransNode* = distinct PNode PTransNode* = distinct PNode
@ -978,6 +978,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
liftDefer(c, result) liftDefer(c, result)
#result = liftLambdas(prc, result) #result = liftLambdas(prc, result)
when useEffectSystem: trackProc(prc, result) when useEffectSystem: trackProc(prc, result)
liftLocalsIfRequested(prc)
if c.needsDestroyPass and newDestructors: if c.needsDestroyPass and newDestructors:
result = injectDestructorCalls(prc, result) result = injectDestructorCalls(prc, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)

View file

@ -66,7 +66,7 @@ type
wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit, wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
wAsmNoStackFrame, wAsmNoStackFrame,
wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks, wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks,
wPartial, wExplain, wPartial, wExplain, wLiftLocals,
wAuto, wBool, wCatch, wChar, wClass, wAuto, wBool, wCatch, wChar, wClass,
wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast, wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
@ -152,7 +152,7 @@ const
"computedgoto", "injectstmt", "experimental", "computedgoto", "injectstmt", "experimental",
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit", "write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
"asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked", "asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked",
"guard", "locks", "partial", "explain", "guard", "locks", "partial", "explain", "liftlocals",
"auto", "bool", "catch", "char", "class", "auto", "bool", "catch", "char", "class",
"const_cast", "default", "delete", "double", "const_cast", "default", "delete", "double",

View file

@ -1,6 +1,8 @@
discard """ discard """
output: '''(foo: 38, other: string here) output: '''(foo: 38, other: string here)
43''' 43
100
90'''
""" """
type type
@ -17,3 +19,17 @@ proc my(f: Foo) =
var g: Foo var g: Foo
new(g) new(g)
my(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())