sem pass compiles again
This commit is contained in:
parent
dd35111ff2
commit
050789a8f4
12 changed files with 269 additions and 263 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue