This commit is contained in:
Andreas Rumpf 2020-08-01 07:39:00 +02:00 • committed by GitHub
commit 4ab6887a67
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 24 deletions

View file

@ -154,20 +154,20 @@ proc collectMissingFields(c: PContext, fieldsRecList: PNode,
if assignment == nil:
constrCtx.missingFields.add r.sym
proc semConstructFields(c: PContext, recNode: PNode,
proc semConstructFields(c: PContext, n: PNode,
constrCtx: var ObjConstrContext,
flags: TExprFlags): InitStatus =
result = initUnknown
case recNode.kind
case n.kind
of nkRecList:
for field in recNode:
for field in n:
let status = semConstructFields(c, field, constrCtx, flags)
mergeInitStatus(result, status)
of nkRecCase:
template fieldsPresentInBranch(branchIdx: int): string =
let branch = recNode[branchIdx]
let branch = n[branchIdx]
let fields = branch[^1]
fieldsPresentInInitExpr(c, fields, constrCtx.initExpr)
@ -176,12 +176,12 @@ proc semConstructFields(c: PContext, recNode: PNode,
let fields = branchNode[^1]
collectMissingFields(c, fields, constrCtx)
let discriminator = recNode[0]
let discriminator = n[0]
internalAssert c.config, discriminator.kind == nkSym
var selectedBranch = -1
for i in 1..<recNode.len:
let innerRecords = recNode[i][^1]
for i in 1..<n.len:
let innerRecords = n[i][^1]
let status = semConstructFields(c, innerRecords, constrCtx, flags)
if status notin {initNone, initUnknown}:
mergeInitStatus(result, status)
@ -217,9 +217,9 @@ proc semConstructFields(c: PContext, recNode: PNode,
localError(c.config, discriminatorVal.info, ("possible values " &
"$2 are in conflict with discriminator values for " &
"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,
efPreferNilResult}
var discriminatorVal = semConstrField(c, flags,
@ -230,7 +230,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
if discriminatorVal.kind notin nkLiterals and (
not isOrdinalType(discriminatorVal.typ, true) 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,
"branch initialization with a runtime discriminator only " &
"supports ordinal types with 2^16 elements or less.")
@ -242,7 +242,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
if ctorCase == nil:
if discriminatorVal.typ.kind == tyRange:
let rangeVals = c.getIntSetOfType(discriminatorVal.typ)
let recBranchVals = branchVals(c, recNode, selectedBranch, false)
let recBranchVals = branchVals(c, n, selectedBranch, false)
let diff = rangeVals - recBranchVals
if diff.len != 0:
valuesInConflictError(diff)
@ -260,7 +260,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
else:
var
ctorBranchVals = branchVals(c, ctorCase, ctorIdx, true)
recBranchVals = branchVals(c, recNode, selectedBranch, false)
recBranchVals = branchVals(c, n, selectedBranch, false)
branchValsDiff = ctorBranchVals - recBranchVals
if branchValsDiff.len != 0:
valuesInConflictError(branchValsDiff)
@ -271,14 +271,14 @@ proc semConstructFields(c: PContext, recNode: PNode,
failedBranch = selectedBranch
else:
# With an else clause, check that all other branches don't match:
for i in 1..<recNode.len - 1:
if recNode[i].caseBranchMatchesExpr(discriminatorVal):
for i in 1..<n.len - 1:
if n[i].caseBranchMatchesExpr(discriminatorVal):
failedBranch = i
break
if failedBranch != -1:
if discriminatorVal.typ.kind == tyRange:
let rangeVals = c.getIntSetOfType(discriminatorVal.typ)
let recBranchVals = branchVals(c, recNode, selectedBranch, false)
let recBranchVals = branchVals(c, n, selectedBranch, false)
let diff = rangeVals - recBranchVals
if diff.len != 0:
valuesInConflictError(diff)
@ -301,22 +301,22 @@ proc semConstructFields(c: PContext, recNode: PNode,
# initialized to zero and this will select a particular branch as
# a result:
let defaultValue = newIntLit(c.graph, constrCtx.initExpr.info, 0)
let matchedBranch = recNode.pickCaseBranch defaultValue
let matchedBranch = n.pickCaseBranch defaultValue
collectMissingFields matchedBranch
else:
result = initPartial
if discriminatorVal.kind == nkIntLit:
# When the discriminator is a compile-time value, we also know
# which branch will be selected:
let matchedBranch = recNode.pickCaseBranch discriminatorVal
let matchedBranch = n.pickCaseBranch discriminatorVal
if matchedBranch != nil: collectMissingFields matchedBranch
else:
# All bets are off. If any of the branches has a mandatory
# 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:
let field = recNode.sym
let field = n.sym
let e = semConstrField(c, flags, field, constrCtx.initExpr)
result = if e != nil: initFull else: initNone