sem pass compiles again

This commit is contained in:
Andreas Rumpf 2018-05-12 21:30:42 +02:00
commit 050789a8f4
12 changed files with 269 additions and 263 deletions

View file

@ -39,32 +39,32 @@ proc mergeInitStatus(existing: var InitStatus, newStatus: InitStatus) =
of initUnknown:
discard
proc invalidObjConstr(n: PNode) =
proc invalidObjConstr(c: PContext, n: PNode) =
if n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.s[0] == ':':
localError(c.config, n.info, "incorrect object construction syntax; use a space after the colon")
else:
localError(c.config, n.info, "incorrect object construction syntax")
proc locateFieldInInitExpr(field: PSym, initExpr: PNode): PNode =
proc locateFieldInInitExpr(c: PContext, field: PSym, initExpr: PNode): PNode =
# Returns the assignment nkExprColonExpr node or nil
let fieldId = field.name.id
for i in 1 ..< initExpr.len:
let assignment = initExpr[i]
if assignment.kind != nkExprColonExpr:
invalidObjConstr(assignment)
invalidObjConstr(c, assignment)
continue
if fieldId == considerQuotedIdent(assignment[0]).id:
if fieldId == considerQuotedIdent(c.config, assignment[0]).id:
return assignment
proc semConstrField(c: PContext, flags: TExprFlags,
field: PSym, initExpr: PNode): PNode =
let assignment = locateFieldInInitExpr(field, initExpr)
let assignment = locateFieldInInitExpr(c, field, initExpr)
if assignment != nil:
if nfSem in assignment.flags: return assignment[1]
if not fieldVisible(c, field):
localError(c.config, initExpr.info,
"the field '$1' is not accessible.", [field.name.s])
"the field '$1' is not accessible." % [field.name.s])
return
var initValue = semExprFlagDispatched(c, assignment[1], flags)
@ -101,25 +101,25 @@ iterator directFieldsInRecList(recList: PNode): PNode =
if recList.kind == nkSym:
yield recList
else:
internalAssert recList.kind == nkRecList
doAssert recList.kind == nkRecList
for field in recList:
if field.kind != nkSym: continue
yield field
template quoteStr(s: string): string = "'" & s & "'"
proc fieldsPresentInInitExpr(fieldsRecList, initExpr: PNode): string =
proc fieldsPresentInInitExpr(c: PContext, fieldsRecList, initExpr: PNode): string =
result = ""
for field in directFieldsInRecList(fieldsRecList):
let assignment = locateFieldInInitExpr(field.sym, initExpr)
let assignment = locateFieldInInitExpr(c, field.sym, initExpr)
if assignment != nil:
if result.len != 0: result.add ", "
result.add field.sym.name.s.quoteStr
proc missingMandatoryFields(fieldsRecList, initExpr: PNode): string =
proc missingMandatoryFields(c: PContext, fieldsRecList, initExpr: PNode): string =
for r in directFieldsInRecList(fieldsRecList):
if {tfNotNil, tfNeedsInit} * r.sym.typ.flags != {}:
let assignment = locateFieldInInitExpr(r.sym, initExpr)
let assignment = locateFieldInInitExpr(c, r.sym, initExpr)
if assignment == nil:
if result == nil:
result = r.sym.name.s
@ -127,8 +127,8 @@ proc missingMandatoryFields(fieldsRecList, initExpr: PNode): string =
result.add ", "
result.add r.sym.name.s
proc checkForMissingFields(recList, initExpr: PNode) =
let missing = missingMandatoryFields(recList, initExpr)
proc checkForMissingFields(c: PContext, recList, initExpr: PNode) =
let missing = missingMandatoryFields(c, recList, initExpr)
if missing != nil:
localError(c.config, initExpr.info, "fields not initialized: $1.", [missing])
@ -146,14 +146,14 @@ proc semConstructFields(c: PContext, recNode: PNode,
template fieldsPresentInBranch(branchIdx: int): string =
let branch = recNode[branchIdx]
let fields = branch[branch.len - 1]
fieldsPresentInInitExpr(fields, initExpr)
fieldsPresentInInitExpr(c, fields, initExpr)
template checkMissingFields(branchNode: PNode) =
let fields = branchNode[branchNode.len - 1]
checkForMissingFields(fields, initExpr)
checkForMissingFields(c, fields, initExpr)
let discriminator = recNode.sons[0];
internalAssert discriminator.kind == nkSym
let discriminator = recNode.sons[0]
internalAssert c.config, discriminator.kind == nkSym
var selectedBranch = -1
for i in 1 ..< recNode.len:
@ -165,8 +165,8 @@ proc semConstructFields(c: PContext, recNode: PNode,
let prevFields = fieldsPresentInBranch(selectedBranch)
let currentFields = fieldsPresentInBranch(i)
localError(c.config, initExpr.info,
"The fields ($1) and ($2) cannot be initialized together, " &
"because they are from conflicting branches in the case object.",
("The fields '$1' and '$2' cannot be initialized together, " &
"because they are from conflicting branches in the case object.") %
[prevFields, currentFields])
result = initConflict
else:
@ -180,8 +180,8 @@ proc semConstructFields(c: PContext, recNode: PNode,
if discriminatorVal == nil:
let fields = fieldsPresentInBranch(selectedBranch)
localError(c.config, initExpr.info,
"you must provide a compile-time value for the discriminator '$1' " &
"in order to prove that it's safe to initialize $2.",
("you must provide a compile-time value for the discriminator '$1' " &
"in order to prove that it's safe to initialize $2.") %
[discriminator.sym.name.s, fields])
mergeInitStatus(result, initNone)
else:
@ -219,7 +219,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
# value was given to the discrimator. We can assume that it will be
# initialized to zero and this will select a particular branch as
# a result:
let matchedBranch = recNode.pickCaseBranch newIntLit(0)
let matchedBranch = recNode.pickCaseBranch newIntLit(c.graph, initExpr.info, 0)
checkMissingFields matchedBranch
else:
result = initPartial
@ -239,20 +239,17 @@ proc semConstructFields(c: PContext, recNode: PNode,
result = if e != nil: initFull else: initNone
else:
internalAssert false
internalAssert c.config, false
proc semConstructType(c: PContext, initExpr: PNode,
t: PType, flags: TExprFlags): InitStatus =
var t = t
result = initUnknown
while true:
let status = semConstructFields(c, t.n, initExpr, flags)
mergeInitStatus(result, status)
if status in {initPartial, initNone, initUnknown}:
checkForMissingFields t.n, initExpr
checkForMissingFields c, t.n, initExpr
let base = t.sons[0]
if base == nil: break
t = skipTypes(base, skipPtrs)
@ -296,17 +293,16 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
let field = result[i]
if nfSem notin field.flags:
if field.kind != nkExprColonExpr:
invalidObjConstr(field)
invalidObjConstr(c, field)
continue
let id = considerQuotedIdent(field[0])
let id = considerQuotedIdent(c.config, field[0])
# This node was not processed. There are two possible reasons:
# 1) It was shadowed by a field with the same name on the left
for j in 1 ..< i:
let prevId = considerQuotedIdent(result[j][0])
let prevId = considerQuotedIdent(c.config, result[j][0])
if prevId.id == id.id:
localError(c.config, field.info, errFieldInitTwice, id.s)
localError(c.config, field.info, errFieldInitTwice % id.s)
return
# 2) No such field exists in the constructed type
localError(c.config, field.info, errUndeclaredFieldX, id.s)
localError(c.config, field.info, errUndeclaredFieldX % id.s)
return