Skip to content

Commit

Permalink
progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Araq committed Jan 11, 2025
1 parent 02177e7 commit a3bc120
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 107 deletions.
211 changes: 105 additions & 106 deletions src/gear3/destroyer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ interprets this `=` as `=bitcopy`.
]##

import std / assertions
include nifprelude
import nifindexes, symparser, treemangler
import ".." / nimony / [nimony_model, programs, typenav]
import lifter

const
NoLabel = SymId(-2)
AnonBlock = SymId(-3)
NoLabel = SymId(0)

type
ScopeKind = enum
Expand All @@ -61,106 +61,109 @@ type
arg: SymId

Scope = object
p: Program
label: SymId
thisModule: ModuleId
procStart: Cursor
kind: ScopeKind
destroyOps: seq[DestructorOp]
info: PackedLineInfo
parent: ptr Scope
lifter: ref LiftingCtx
isTopLevel: bool

Context = object
currentScope: Scope
#procStart: Cursor
anonBlock: SymId
dest: TokenBuf
lifter: ref LiftingCtx

proc createNestedScope(kind: ScopeKind; parent: var Scope; info: PackedLineInfo; label = NoLabel): Scope =
Scope(p: parent.p, label: label, thisModule: parent.thisModule, procStart: parent.procStart,
kind: kind, destroyOps: @[], info: info, parent: addr(parent), lifter: parent.lifter,
Scope(label: label,
kind: kind, destroyOps: @[], info: info, parent: addr(parent),
isTopLevel: false)

proc createEntryScope(p: Program; thisModule: ModuleId; lifter: ref LiftingCtx;
procStart: Cursor; info: PackedLineInfo): Scope =
Scope(p: p, label: NoLabel, thisModule: thisModule, procStart: procStart,
kind: Other, destroyOps: @[], info: info, parent: nil, lifter: lifter,
proc createEntryScope(info: PackedLineInfo): Scope =
Scope(label: NoLabel,
kind: Other, destroyOps: @[], info: info, parent: nil,
isTopLevel: true)

proc callDestroy(c: var Scope; dest: var TokenBuf; destroyProc: SymId; arg: SymId) =
copyIntoKind dest, Call, c.info:
copyIntoSymUse dest, destroyProc, c.info
copyIntoSymUse dest, arg, c.info
proc callDestroy(c: var Context; destroyProc: SymId; arg: SymId) =
let info = c.currentScope.info
copyIntoKind c.dest, CallS, info:
copyIntoSymUse c.dest, destroyProc, info
copyIntoSymUse c.dest, arg, info

proc leaveScope(c: var Scope; dest: var TokenBuf) =
for i in countdown(c.destroyOps.high, 0):
callDestroy c, dest, c.destroyOps[i].destroyProc, c.destroyOps[i].arg
proc leaveScope(c: var Context; s: var Scope) =
for i in countdown(s.destroyOps.high, 0):
callDestroy c, s.destroyOps[i].destroyProc, s.destroyOps[i].arg

proc leaveNamedBlock(c: var Scope; dest: var TokenBuf; label: SymId) =
proc leaveNamedBlock(c: var Context; label: SymId) =
#[ Consider:
var x = f()
block:
break # do we want to destroy x here? No.
]#
var it = addr(c)
var it = addr(c.currentScope)
while it != nil and it.label != label:
leaveScope(it[], dest)
leaveScope(c, it[])
it = it.parent
if it != nil and it.label == label:
leaveScope(it[], dest)
leaveScope(c, it[])
else:
assert false, "do not know which block to leave"
raiseAssert "do not know which block to leave"

proc leaveAnonBlock(c: var Scope; dest: var TokenBuf) =
var it = addr(c)
proc leaveAnonBlock(c: var Context) =
var it = addr(c.currentScope)
while it != nil and it.kind != WhileOrBlock:
leaveScope(it[], dest)
leaveScope(c, it[])
it = it.parent
if it != nil and it.kind == WhileOrBlock:
leaveScope(it[], dest)
leaveScope(c, it[])
else:
assert false, "do not know which block to leave"
raiseAssert "do not know which block to leave"

proc trBreak(c: var Scope; dest: var TokenBuf; n: Cursor) =
proc trBreak(c: var Context; n: var Cursor) =
let lab = n.firstSon
if lab.kind == SymUse:
leaveNamedBlock(c, dest, lab.symId)
if lab.kind == Symbol:
leaveNamedBlock(c, lab.symId)
else:
leaveAnonBlock(c, dest)
copyTree dest, tree, n
leaveAnonBlock(c)
takeTree c.dest, n

proc trReturn(c: var Scope; dest: var TokenBuf; n: Cursor) =
var it = addr(c)
proc trReturn(c: var Context; n: var Cursor) =
var it = addr(c.currentScope)
while it != nil:
leaveScope(it[], dest)
leaveScope(c, it[])
it = it.parent
copyTree dest, tree, n
takeTree c.dest, n

when not defined(nimony):
proc tr(c: var Scope; dest: var TokenBuf; n: Cursor)
proc tr(c: var Context; n: var Cursor)

proc trLocal(c: var Scope; dest: var TokenBuf; n: Cursor) =
proc trLocal(c: var Context; n: Cursor) =
let r = asLocal(tree, n)

Check failure on line 144 in src/gear3/destroyer.nim

View workflow job for this annotation

GitHub Actions / linux-amd64-nim-devel (master)

undeclared identifier: 'asLocal'

Check failure on line 144 in src/gear3/destroyer.nim

View workflow job for this annotation

GitHub Actions / macos-amd64-nim-devel (master)

undeclared identifier: 'asLocal'

Check failure on line 144 in src/gear3/destroyer.nim

View workflow job for this annotation

GitHub Actions / windows-amd64-nim-devel (master)

undeclared identifier: 'asLocal'
copyIntoKind(dest, n.kind, n.info):
copyTree(dest, tree, r.name)
copyTree(dest, tree, r.ex)
copyTree(dest, tree, r.pragmas)
copyTree(dest, tree, r.typ)
let localType = getType(c.p, tree, r.name)
copyTree(dest, r.name)
copyTree(dest, r.ex)
copyTree(dest, r.pragmas)
copyTree(dest, r.typ)
let localType = getType(c.p, r.name)
let destructor = getDestructor(c.lifter[], localType, n.info)
let s = r.name.symId
let sk = c.p[tree.m].syms[s].kind
if destructor.s != SymId(-1) and sk != CursorDecl:
if not c.isTopLevel and sk != ResultDecl:
# XXX If we don't free global variables let's at least free temporaries!
c.destroyOps.add DestructorOp(destroyProc: destructor, arg: s)
tr c, dest, tree, r.value
tr c, dest, r.value

proc trScope(c: var Scope; dest: var TokenBuf; body: Cursor) =
proc trScope(c: var Context; body: Cursor) =
copyIntoKind dest, StmtList, body.info:
if body.kind == StmtList:
for ch in sonsReadOnly(tree, body):
tr c, dest, tree, ch
tr c, dest, ch
else:
tr c, dest, tree, body
tr c, dest, body
leaveScope(c, dest)

proc registerSinkParameters(c: var Scope; params: Cursor) =
Expand All @@ -171,30 +174,30 @@ proc registerSinkParameters(c: var Scope; params: Cursor) =
if destructor.s != SymId(-1):
c.destroyOps.add DestructorOp(destroyProc: destructor, arg: r.name.symId)

proc trProcDecl(c: var Scope; dest: var TokenBuf; n: Cursor) =
proc trProcDecl(c: var Context; n: Cursor) =
let r = asRoutine(tree, n)
var c2 = createEntryScope(c.p, c.thisModule, c.lifter, r.body, r.body.info)
c2.isTopLevel = false
copyInto(dest, n):
copyTree dest, tree, r.name
copyTree dest, tree, r.ex
copyTree dest, tree, r.pat
copyTree dest, tree, r.generics
copyTree dest, tree, r.params
copyTree dest, tree, r.pragmas
copyTree dest, tree, r.exc
copyTree dest, r.name
copyTree dest, r.ex
copyTree dest, r.pat
copyTree dest, r.generics
copyTree dest, r.params
copyTree dest, r.pragmas
copyTree dest, r.exc
if r.body.kind == StmtList and r.generics.kind != GenericParams and
not hasBuiltinPragma(c.p, tree, r.pragmas, "nodestroy"):
registerSinkParameters(c2, tree, r.params)
trScope c2, dest, tree, r.body
not hasBuiltinPragma(c.p, r.pragmas, "nodestroy"):
registerSinkParameters(c2, r.params)
trScope c2, dest, r.body
else:
copyTree dest, tree, r.body
copyTree dest, r.body

proc trNestedScope(c: var Scope; dest: var TokenBuf; body: Cursor; kind = Other) =
proc trNestedScope(c: var Context; body: Cursor; kind = Other) =
var bodyScope = createNestedScope(kind, c, body.info)
trScope bodyScope, dest, tree, body
trScope bodyScope, dest, body

proc trWhile(c: var Scope; dest: var TokenBuf; n: Cursor) =
proc trWhile(c: var Context; n: Cursor) =
#[ while prop(createsObj())
was turned into `while (let tmp = createsObj(); prop(tmp))` by `duplifier.nim`
already and `to_stmts` did turn it into:
Expand All @@ -208,84 +211,80 @@ proc trWhile(c: var Scope; dest: var TokenBuf; n: Cursor) =
]#
let (cond, body) = sons2(tree, n)
copyInto(dest, n):
tr c, dest, tree, cond
trNestedScope c, dest, tree, body, WhileOrBlock
tr c, dest, cond
trNestedScope c, dest, body, WhileOrBlock

proc trBlock(c: var Scope; dest: var TokenBuf; n: Cursor) =
proc trBlock(c: var Context; n: Cursor) =
let (label, body) = sons2(tree, n)
let labelId = if label.kind == SymDef: label.symId else: AnonBlock
var bodyScope = createNestedScope(WhileOrBlock, c, body.info, labelId)
copyInto(dest, n):
copyTree dest, tree, label
trScope bodyScope, dest, tree, body
copyTree dest, label
trScope bodyScope, dest, body

proc trIf(c: var Scope; dest: var TokenBuf; n: Cursor) =
for ch in sons(dest, tree, n):
proc trIf(c: var Context; n: Cursor) =
for ch in sons(dest, n):
case ch.kind
of ElifBranch:
let (cond, action) = sons2(tree, ch)
copyInto(dest, ch):
tr c, dest, tree, cond
trNestedScope c, dest, tree, action
tr c, dest, cond
trNestedScope c, dest, action
of ElseBranch:
copyInto(dest, ch):
trNestedScope c, dest, tree, ch.firstSon
trNestedScope c, dest, ch.firstSon
else:
copyTree dest, tree, ch
copyTree dest, ch

proc trCase(c: var Scope; dest: var TokenBuf; n: Cursor) =
proc trCase(c: var Context; n: Cursor) =
copyInto(dest, n):
tr c, dest, tree, n.firstSon
tr c, dest, n.firstSon
for ch in sonsFrom1(tree, n):
case ch.kind
of OfBranch:
copyInto(dest, ch):
let (first, action) = sons2(tree, ch)
copyTree dest, tree, first
trNestedScope c, dest, tree, action
copyTree dest, first
trNestedScope c, dest, action
of ElseBranch:
copyInto(dest, ch):
trNestedScope c, dest, tree, ch.firstSon
trNestedScope c, dest, ch.firstSon
else:
copyTree dest, tree, ch
copyTree dest, ch

proc tr(c: var Scope; dest: var TokenBuf; n: Cursor) =
proc tr(c: var Context; n: var Cursor) =
case n.kind
of ReturnStmt:
trReturn(c, dest, tree, n)
trReturn(c, dest, n)
of BreakStmt:
trBreak(c, dest, tree, n)
trBreak(c, dest, n)
of IfStmt:
trIf c, dest, tree, n
trIf c, dest, n
of CaseStmt:
trCase c, dest, tree, n
trCase c, dest, n
of BlockStmt:
trBlock c, dest, tree, n
trBlock c, dest, n
#of Asgn, FirstAsgn:
# trAsgn c, dest, tree, n
# trAsgn c, dest, n
of VarDecl, LetDecl, ConstDecl, ResultDecl:
trLocal c, dest, tree, n
trLocal c, dest, n
of WhileStmt:
trWhile c, dest, tree, n
trWhile c, dest, n
of DeclarativeNodes, Atoms, Pragmas, TemplateDecl, IteratorDecl,
UsingStmt, CommentStmt, BindStmt, MixinStmt, ContinueStmt:
copyTree dest, tree, n
copyTree dest, n
of ProcDecl, FuncDecl, MacroDecl, MethodDecl, ConverterDecl:
trProcDecl c, dest, tree, n
trProcDecl c, dest, n
else:
for ch in sons(dest, tree, n):
tr(c, dest, tree, ch)

proc injectDestructors*(p: Program; t: TreeId; lifter: ref LiftingCtx): TreeId =
let thisModule = p[t].m
let info = p[t][StartPos].info

var c = createEntryScope(p, thisModule, lifter, StartPos, info)
result = createTree(p, c.thisModule)
p[result].flags.incl dontTouch

tr(c, p[result], p[t], StartPos)
for ch in sons(dest, n):
tr(c, dest, ch)

proc injectDestructors*(n: Cursor; lifter: ref LiftingCtx): TokenBuf =
var c = Context(currentScope: createEntryScope(p, thisModule, lifter, StartPos, info),
anonBlock: pool.syms.getOrIncl("`anonblock.0"),
dest: createTokenBuf(400))
var n = n
tr(c, n)
leaveScope c, p[result]
genMissingHooks lifter[], p[result]
patch p[result], PatchPos(0)
p[result].flags.excl dontTouch
result = ensureMove c.dest
2 changes: 1 addition & 1 deletion src/gear3/gear3.nim
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Gear 3 accepts Gear 2's grammar.
]##

import std / [parseopt, strutils, os, osproc, tables, assertions, syncio]
import expander, lifter, duplifier #, destroyer
import expander, lifter, duplifier, destroyer

const
Version = "0.2"
Expand Down

0 comments on commit a3bc120

Please sign in to comment.