parent
6b88cd0d42
commit
4ab6887a67
5 changed files with 32 additions and 24 deletions
|
|
@ -280,7 +280,7 @@ proc patch(c: var Con, p: TPosition) =
|
||||||
# patch with current index
|
# patch with current index
|
||||||
c.code[p.int].dest = checkedDistance(c.code.len - p.int)
|
c.code[p.int].dest = checkedDistance(c.code.len - p.int)
|
||||||
|
|
||||||
func gen(c: var Con; n: PNode)
|
proc gen(c: var Con; n: PNode)
|
||||||
|
|
||||||
proc popBlock(c: var Con; oldLen: int) =
|
proc popBlock(c: var Con; oldLen: int) =
|
||||||
var exits: seq[TPosition]
|
var exits: seq[TPosition]
|
||||||
|
|
@ -712,7 +712,7 @@ proc genVarSection(c: var Con; n: PNode) =
|
||||||
if a.lastSon.kind != nkEmpty:
|
if a.lastSon.kind != nkEmpty:
|
||||||
genDef(c, a[0])
|
genDef(c, a[0])
|
||||||
|
|
||||||
func gen(c: var Con; n: PNode) =
|
proc gen(c: var Con; n: PNode) =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkSym: genUse(c, n)
|
of nkSym: genUse(c, n)
|
||||||
of nkCallKinds:
|
of nkCallKinds:
|
||||||
|
|
|
||||||
|
|
@ -1953,7 +1953,7 @@ proc parseObjectPart(p: var TParser): PNode =
|
||||||
else:
|
else:
|
||||||
parMessage(p, errIdentifierExpected, p.tok)
|
parMessage(p, errIdentifierExpected, p.tok)
|
||||||
break
|
break
|
||||||
else:
|
elif sameOrNoInd(p):
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkWhen:
|
of tkWhen:
|
||||||
result = parseObjectWhen(p)
|
result = parseObjectWhen(p)
|
||||||
|
|
@ -1968,6 +1968,8 @@ proc parseObjectPart(p: var TParser): PNode =
|
||||||
getTok(p)
|
getTok(p)
|
||||||
else:
|
else:
|
||||||
result = p.emptyNode
|
result = p.emptyNode
|
||||||
|
else:
|
||||||
|
result = p.emptyNode
|
||||||
|
|
||||||
proc parseObject(p: var TParser): PNode =
|
proc parseObject(p: var TParser): PNode =
|
||||||
#| object = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart
|
#| object = 'object' pragma? ('of' typeDesc)? COMMENT? objectPart
|
||||||
|
|
|
||||||
|
|
@ -154,20 +154,20 @@ proc collectMissingFields(c: PContext, fieldsRecList: PNode,
|
||||||
if assignment == nil:
|
if assignment == nil:
|
||||||
constrCtx.missingFields.add r.sym
|
constrCtx.missingFields.add r.sym
|
||||||
|
|
||||||
proc semConstructFields(c: PContext, recNode: PNode,
|
proc semConstructFields(c: PContext, n: PNode,
|
||||||
constrCtx: var ObjConstrContext,
|
constrCtx: var ObjConstrContext,
|
||||||
flags: TExprFlags): InitStatus =
|
flags: TExprFlags): InitStatus =
|
||||||
result = initUnknown
|
result = initUnknown
|
||||||
|
|
||||||
case recNode.kind
|
case n.kind
|
||||||
of nkRecList:
|
of nkRecList:
|
||||||
for field in recNode:
|
for field in n:
|
||||||
let status = semConstructFields(c, field, constrCtx, flags)
|
let status = semConstructFields(c, field, constrCtx, flags)
|
||||||
mergeInitStatus(result, status)
|
mergeInitStatus(result, status)
|
||||||
|
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
template fieldsPresentInBranch(branchIdx: int): string =
|
template fieldsPresentInBranch(branchIdx: int): string =
|
||||||
let branch = recNode[branchIdx]
|
let branch = n[branchIdx]
|
||||||
let fields = branch[^1]
|
let fields = branch[^1]
|
||||||
fieldsPresentInInitExpr(c, fields, constrCtx.initExpr)
|
fieldsPresentInInitExpr(c, fields, constrCtx.initExpr)
|
||||||
|
|
||||||
|
|
@ -176,12 +176,12 @@ proc semConstructFields(c: PContext, recNode: PNode,
|
||||||
let fields = branchNode[^1]
|
let fields = branchNode[^1]
|
||||||
collectMissingFields(c, fields, constrCtx)
|
collectMissingFields(c, fields, constrCtx)
|
||||||
|
|
||||||
let discriminator = recNode[0]
|
let discriminator = n[0]
|
||||||
internalAssert c.config, discriminator.kind == nkSym
|
internalAssert c.config, discriminator.kind == nkSym
|
||||||
var selectedBranch = -1
|
var selectedBranch = -1
|
||||||
|
|
||||||
for i in 1..<recNode.len:
|
for i in 1..<n.len:
|
||||||
let innerRecords = recNode[i][^1]
|
let innerRecords = n[i][^1]
|
||||||
let status = semConstructFields(c, innerRecords, constrCtx, flags)
|
let status = semConstructFields(c, innerRecords, constrCtx, flags)
|
||||||
if status notin {initNone, initUnknown}:
|
if status notin {initNone, initUnknown}:
|
||||||
mergeInitStatus(result, status)
|
mergeInitStatus(result, status)
|
||||||
|
|
@ -217,9 +217,9 @@ proc semConstructFields(c: PContext, recNode: PNode,
|
||||||
localError(c.config, discriminatorVal.info, ("possible values " &
|
localError(c.config, discriminatorVal.info, ("possible values " &
|
||||||
"$2 are in conflict with discriminator values for " &
|
"$2 are in conflict with discriminator values for " &
|
||||||
"selected object branch $1.") % [$selectedBranch,
|
"selected object branch $1.") % [$selectedBranch,
|
||||||
valsDiff.renderAsType(recNode[0].typ)])
|
valsDiff.renderAsType(n[0].typ)])
|
||||||
|
|
||||||
let branchNode = recNode[selectedBranch]
|
let branchNode = n[selectedBranch]
|
||||||
let flags = flags*{efAllowDestructor} + {efPreferStatic,
|
let flags = flags*{efAllowDestructor} + {efPreferStatic,
|
||||||
efPreferNilResult}
|
efPreferNilResult}
|
||||||
var discriminatorVal = semConstrField(c, flags,
|
var discriminatorVal = semConstrField(c, flags,
|
||||||
|
|
@ -230,7 +230,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
|
||||||
if discriminatorVal.kind notin nkLiterals and (
|
if discriminatorVal.kind notin nkLiterals and (
|
||||||
not isOrdinalType(discriminatorVal.typ, true) or
|
not isOrdinalType(discriminatorVal.typ, true) or
|
||||||
lengthOrd(c.config, discriminatorVal.typ) > MaxSetElements or
|
lengthOrd(c.config, discriminatorVal.typ) > MaxSetElements or
|
||||||
lengthOrd(c.config, recNode[0].typ) > MaxSetElements):
|
lengthOrd(c.config, n[0].typ) > MaxSetElements):
|
||||||
localError(c.config, discriminatorVal.info,
|
localError(c.config, discriminatorVal.info,
|
||||||
"branch initialization with a runtime discriminator only " &
|
"branch initialization with a runtime discriminator only " &
|
||||||
"supports ordinal types with 2^16 elements or less.")
|
"supports ordinal types with 2^16 elements or less.")
|
||||||
|
|
@ -242,7 +242,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
|
||||||
if ctorCase == nil:
|
if ctorCase == nil:
|
||||||
if discriminatorVal.typ.kind == tyRange:
|
if discriminatorVal.typ.kind == tyRange:
|
||||||
let rangeVals = c.getIntSetOfType(discriminatorVal.typ)
|
let rangeVals = c.getIntSetOfType(discriminatorVal.typ)
|
||||||
let recBranchVals = branchVals(c, recNode, selectedBranch, false)
|
let recBranchVals = branchVals(c, n, selectedBranch, false)
|
||||||
let diff = rangeVals - recBranchVals
|
let diff = rangeVals - recBranchVals
|
||||||
if diff.len != 0:
|
if diff.len != 0:
|
||||||
valuesInConflictError(diff)
|
valuesInConflictError(diff)
|
||||||
|
|
@ -260,7 +260,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
|
||||||
else:
|
else:
|
||||||
var
|
var
|
||||||
ctorBranchVals = branchVals(c, ctorCase, ctorIdx, true)
|
ctorBranchVals = branchVals(c, ctorCase, ctorIdx, true)
|
||||||
recBranchVals = branchVals(c, recNode, selectedBranch, false)
|
recBranchVals = branchVals(c, n, selectedBranch, false)
|
||||||
branchValsDiff = ctorBranchVals - recBranchVals
|
branchValsDiff = ctorBranchVals - recBranchVals
|
||||||
if branchValsDiff.len != 0:
|
if branchValsDiff.len != 0:
|
||||||
valuesInConflictError(branchValsDiff)
|
valuesInConflictError(branchValsDiff)
|
||||||
|
|
@ -271,14 +271,14 @@ proc semConstructFields(c: PContext, recNode: PNode,
|
||||||
failedBranch = selectedBranch
|
failedBranch = selectedBranch
|
||||||
else:
|
else:
|
||||||
# With an else clause, check that all other branches don't match:
|
# With an else clause, check that all other branches don't match:
|
||||||
for i in 1..<recNode.len - 1:
|
for i in 1..<n.len - 1:
|
||||||
if recNode[i].caseBranchMatchesExpr(discriminatorVal):
|
if n[i].caseBranchMatchesExpr(discriminatorVal):
|
||||||
failedBranch = i
|
failedBranch = i
|
||||||
break
|
break
|
||||||
if failedBranch != -1:
|
if failedBranch != -1:
|
||||||
if discriminatorVal.typ.kind == tyRange:
|
if discriminatorVal.typ.kind == tyRange:
|
||||||
let rangeVals = c.getIntSetOfType(discriminatorVal.typ)
|
let rangeVals = c.getIntSetOfType(discriminatorVal.typ)
|
||||||
let recBranchVals = branchVals(c, recNode, selectedBranch, false)
|
let recBranchVals = branchVals(c, n, selectedBranch, false)
|
||||||
let diff = rangeVals - recBranchVals
|
let diff = rangeVals - recBranchVals
|
||||||
if diff.len != 0:
|
if diff.len != 0:
|
||||||
valuesInConflictError(diff)
|
valuesInConflictError(diff)
|
||||||
|
|
@ -301,22 +301,22 @@ proc semConstructFields(c: PContext, recNode: PNode,
|
||||||
# initialized to zero and this will select a particular branch as
|
# initialized to zero and this will select a particular branch as
|
||||||
# a result:
|
# a result:
|
||||||
let defaultValue = newIntLit(c.graph, constrCtx.initExpr.info, 0)
|
let defaultValue = newIntLit(c.graph, constrCtx.initExpr.info, 0)
|
||||||
let matchedBranch = recNode.pickCaseBranch defaultValue
|
let matchedBranch = n.pickCaseBranch defaultValue
|
||||||
collectMissingFields matchedBranch
|
collectMissingFields matchedBranch
|
||||||
else:
|
else:
|
||||||
result = initPartial
|
result = initPartial
|
||||||
if discriminatorVal.kind == nkIntLit:
|
if discriminatorVal.kind == nkIntLit:
|
||||||
# When the discriminator is a compile-time value, we also know
|
# When the discriminator is a compile-time value, we also know
|
||||||
# which branch will be selected:
|
# which branch will be selected:
|
||||||
let matchedBranch = recNode.pickCaseBranch discriminatorVal
|
let matchedBranch = n.pickCaseBranch discriminatorVal
|
||||||
if matchedBranch != nil: collectMissingFields matchedBranch
|
if matchedBranch != nil: collectMissingFields matchedBranch
|
||||||
else:
|
else:
|
||||||
# All bets are off. If any of the branches has a mandatory
|
# All bets are off. If any of the branches has a mandatory
|
||||||
# fields we must produce an error:
|
# fields we must produce an error:
|
||||||
for i in 1..<recNode.len: collectMissingFields recNode[i]
|
for i in 1..<n.len: collectMissingFields n[i]
|
||||||
|
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let field = recNode.sym
|
let field = n.sym
|
||||||
let e = semConstrField(c, flags, field, constrCtx.initExpr)
|
let e = semConstrField(c, flags, field, constrCtx.initExpr)
|
||||||
result = if e != nil: initFull else: initNone
|
result = if e != nil: initFull else: initNone
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -663,7 +663,7 @@ proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||||
internalError(c.config, "semRecordCase: discriminant is no symbol")
|
internalError(c.config, "semRecordCase: discriminant is no symbol")
|
||||||
return
|
return
|
||||||
incl(a[0].sym.flags, sfDiscriminant)
|
incl(a[0].sym.flags, sfDiscriminant)
|
||||||
var covered: Int128 = toInt128(0)
|
var covered = toInt128(0)
|
||||||
var chckCovered = false
|
var chckCovered = false
|
||||||
var typ = skipTypes(a[0].typ, abstractVar-{tyTypeDesc})
|
var typ = skipTypes(a[0].typ, abstractVar-{tyTypeDesc})
|
||||||
const shouldChckCovered = {tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32, tyBool}
|
const shouldChckCovered = {tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt32, tyBool}
|
||||||
|
|
@ -744,6 +744,8 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||||
father.add n
|
father.add n
|
||||||
elif branch != nil:
|
elif branch != nil:
|
||||||
semRecordNodeAux(c, branch, check, pos, father, rectype, hasCaseFields)
|
semRecordNodeAux(c, branch, check, pos, father, rectype, hasCaseFields)
|
||||||
|
elif father.kind in {nkElse, nkOfBranch}:
|
||||||
|
father.add newNodeI(nkRecList, n.info)
|
||||||
of nkRecCase:
|
of nkRecCase:
|
||||||
semRecordCase(c, n, check, pos, father, rectype)
|
semRecordCase(c, n, check, pos, father, rectype)
|
||||||
of nkNilLit:
|
of nkNilLit:
|
||||||
|
|
@ -800,7 +802,9 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
|
||||||
if containsOrIncl(check, n.sym.name.id):
|
if containsOrIncl(check, n.sym.name.id):
|
||||||
localError(c.config, n.info, "attempt to redefine: '" & n.sym.name.s & "'")
|
localError(c.config, n.info, "attempt to redefine: '" & n.sym.name.s & "'")
|
||||||
father.add n
|
father.add n
|
||||||
of nkEmpty: discard
|
of nkEmpty:
|
||||||
|
if father.kind in {nkElse, nkOfBranch}:
|
||||||
|
father.add n
|
||||||
else: illFormedAst(n, c.config)
|
else: illFormedAst(n, c.config)
|
||||||
|
|
||||||
proc addInheritedFieldsAux(c: PContext, check: var IntSet, pos: var int,
|
proc addInheritedFieldsAux(c: PContext, check: var IntSet, pos: var int,
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
|
|
||||||
## Partition variables into different graphs. Used for
|
## Partition variables into different graphs. Used for
|
||||||
## Nim's write tracking and also for the cursor inference.
|
## Nim's write tracking and also for the cursor inference.
|
||||||
|
## The algorithm is a reinvention / variation of Steensgaard's
|
||||||
|
## algorithm.
|
||||||
## The used algorithm is "union find" with path compression.
|
## The used algorithm is "union find" with path compression.
|
||||||
|
|
||||||
import ast, types, lineinfos, options, msgs, renderer
|
import ast, types, lineinfos, options, msgs, renderer
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue