DFA attempt to capture the essence of linear types
This commit is contained in:
parent
c2d91771bc
commit
8e7829ff82
1 changed files with 21 additions and 2 deletions
|
|
@ -337,10 +337,12 @@ proc gen(c: var Con; n: PNode) =
|
||||||
proc dfa(code: seq[Instr]) =
|
proc dfa(code: seq[Instr]) =
|
||||||
var u = newSeq[IntSet](code.len) # usages
|
var u = newSeq[IntSet](code.len) # usages
|
||||||
var d = newSeq[IntSet](code.len) # defs
|
var d = newSeq[IntSet](code.len) # defs
|
||||||
|
var c = newSeq[IntSet](code.len) # consumed
|
||||||
var backrefs = initTable[int, int]()
|
var backrefs = initTable[int, int]()
|
||||||
for i in 0..<code.len:
|
for i in 0..<code.len:
|
||||||
u[i] = initIntSet()
|
u[i] = initIntSet()
|
||||||
d[i] = initIntSet()
|
d[i] = initIntSet()
|
||||||
|
c[i] = initIntSet()
|
||||||
case code[i].kind
|
case code[i].kind
|
||||||
of use, useWithinCall: u[i].incl(code[i].sym.id)
|
of use, useWithinCall: u[i].incl(code[i].sym.id)
|
||||||
of def: d[i].incl(code[i].sym.id)
|
of def: d[i].incl(code[i].sym.id)
|
||||||
|
|
@ -352,6 +354,7 @@ proc dfa(code: seq[Instr]) =
|
||||||
var maxIters = 50
|
var maxIters = 50
|
||||||
var someChange = true
|
var someChange = true
|
||||||
var takenGotos = initIntSet()
|
var takenGotos = initIntSet()
|
||||||
|
var consuming = -1
|
||||||
while w.len > 0 and maxIters > 0: # and someChange:
|
while w.len > 0 and maxIters > 0: # and someChange:
|
||||||
dec maxIters
|
dec maxIters
|
||||||
var pc = w.pop() # w[^1]
|
var pc = w.pop() # w[^1]
|
||||||
|
|
@ -389,6 +392,10 @@ proc dfa(code: seq[Instr]) =
|
||||||
when defined(debugDfa):
|
when defined(debugDfa):
|
||||||
echo "Excluding ", pc, " prev ", prevPc
|
echo "Excluding ", pc, " prev ", prevPc
|
||||||
assign d[pc], intersect
|
assign d[pc], intersect
|
||||||
|
if consuming >= 0:
|
||||||
|
if not c[pc].containsOrIncl(consuming):
|
||||||
|
someChange = true
|
||||||
|
consuming = -1
|
||||||
|
|
||||||
# our interpretation ![I!]:
|
# our interpretation ![I!]:
|
||||||
prevPc = pc
|
prevPc = pc
|
||||||
|
|
@ -406,12 +413,21 @@ proc dfa(code: seq[Instr]) =
|
||||||
#if someChange:
|
#if someChange:
|
||||||
w.add pc + code[pc].dest
|
w.add pc + code[pc].dest
|
||||||
inc pc
|
inc pc
|
||||||
of use, useWithinCall, def:
|
of use, useWithinCall:
|
||||||
|
#if not d[prevPc].missingOrExcl():
|
||||||
|
# someChange = true
|
||||||
|
consuming = code[pc].sym.id
|
||||||
|
when defined(debugDfa):
|
||||||
|
echo "consumed: ", consuming
|
||||||
|
inc pc
|
||||||
|
of def:
|
||||||
|
if not d[pc].containsOrIncl(code[pc].sym.id):
|
||||||
|
someChange = true
|
||||||
inc pc
|
inc pc
|
||||||
|
|
||||||
when defined(useDfa) and defined(debugDfa):
|
when defined(useDfa) and defined(debugDfa):
|
||||||
for i in 0..<code.len:
|
for i in 0..<code.len:
|
||||||
echo "PC ", i, ": defs: ", d[i], "; uses ", u[i]
|
echo "PC ", i, ": defs: ", d[i], "; uses ", u[i], "; consumes ", c[i]
|
||||||
|
|
||||||
# now check the condition we're interested in:
|
# now check the condition we're interested in:
|
||||||
for i in 0..<code.len:
|
for i in 0..<code.len:
|
||||||
|
|
@ -419,6 +435,9 @@ proc dfa(code: seq[Instr]) =
|
||||||
of use, useWithinCall:
|
of use, useWithinCall:
|
||||||
if code[i].sym.id notin d[i]:
|
if code[i].sym.id notin d[i]:
|
||||||
localError(code[i].n.info, "usage of an uninitialized variable")
|
localError(code[i].n.info, "usage of an uninitialized variable")
|
||||||
|
if code[i].sym.id in c[i]:
|
||||||
|
localError(code[i].n.info, "usage of an already consumed variable")
|
||||||
|
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc dfaUnused(code: seq[Instr]) =
|
proc dfaUnused(code: seq[Instr]) =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue