more modules compile again

This commit is contained in:
Andreas Rumpf 2018-05-12 16:35:59 +02:00
commit ce859d8c16
15 changed files with 544 additions and 518 deletions

View file

@ -229,7 +229,6 @@ errXExpectsArrayType: "'$1' expects an array type",
errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet", errIteratorCannotBeInstantiated: "'$1' cannot be instantiated because its body has not been compiled yet",
errExprXAmbiguous: "expression '$1' ambiguous in this context", errExprXAmbiguous: "expression '$1' ambiguous in this context",
errConstantDivisionByZero: , errConstantDivisionByZero: ,
errOrdinalTypeExpected: "ordinal type expected",
errOrdinalOrFloatTypeExpected: "ordinal or float type expected", errOrdinalOrFloatTypeExpected: "ordinal or float type expected",
errOverOrUnderflow: , errOverOrUnderflow: ,
errCannotEvalXBecauseIncompletelyDefined: , errCannotEvalXBecauseIncompletelyDefined: ,
@ -274,9 +273,6 @@ errConstNeedsConstExpr: "a constant can only be initialized with a constant expr
errConstNeedsValue: "a constant needs a value", errConstNeedsValue: "a constant needs a value",
errResultCannotBeOpenArray: "the result type cannot be on open array", errResultCannotBeOpenArray: "the result type cannot be on open array",
errSizeTooBig: "computing the type's size produced an overflow", errSizeTooBig: "computing the type's size produced an overflow",
errSetTooBig: "set is too large",
errBaseTypeMustBeOrdinal: "base type of a set must be an ordinal",
errInheritanceOnlyWithNonFinalObjects: "inheritance only works with non-final objects",
errInheritanceOnlyWithEnums: "inheritance only works with an enum", errInheritanceOnlyWithEnums: "inheritance only works with an enum",
errIllegalRecursionInTypeX:, errIllegalRecursionInTypeX:,
errCannotInstantiateX: "cannot instantiate: '$1'", errCannotInstantiateX: "cannot instantiate: '$1'",
@ -293,7 +289,6 @@ errWrongNumberOfArgumentsInCall: "wrong number of arguments in call to '$1'",
errMissingGenericParamsForTemplate: "'$1' has unspecified generic parameters", errMissingGenericParamsForTemplate: "'$1' has unspecified generic parameters",
errXCannotBePassedToProcVar: , errXCannotBePassedToProcVar: ,
errPragmaOnlyInHeaderOfProcX: "pragmas are only allowed in the header of a proc; redefinition of $1", errPragmaOnlyInHeaderOfProcX: "pragmas are only allowed in the header of a proc; redefinition of $1",
errImplOfXNotAllowed: "implementation of '$1' is not allowed",
errImplOfXexpected: , errImplOfXexpected: ,
errNoSymbolToBorrowFromFound: "no symbol to borrow from found", errNoSymbolToBorrowFromFound: "no symbol to borrow from found",
errDiscardValueX: "value of type '$1' has to be discarded", errDiscardValueX: "value of type '$1' has to be discarded",
@ -312,7 +307,7 @@ errUnknownSubstitionVar: "unknown substitution variable: '$1'",
errComplexStmtRequiresInd: "complex statement requires indentation", errComplexStmtRequiresInd: "complex statement requires indentation",
errXisNotCallable: "'$1' is not callable", errXisNotCallable: "'$1' is not callable",
errNoPragmasAllowedForX: "no pragmas allowed for $1", errNoPragmasAllowedForX: "no pragmas allowed for $1",
errNoGenericParamsAllowedForX: "no generic parameters allowed for $1", ,
errInvalidParamKindX: "invalid param kind: '$1'", errInvalidParamKindX: "invalid param kind: '$1'",
errDefaultArgumentInvalid: "default argument invalid", errDefaultArgumentInvalid: "default argument invalid",
errNamedParamHasToBeIdent: "named parameter has to be an identifier", errNamedParamHasToBeIdent: "named parameter has to be an identifier",
@ -328,17 +323,8 @@ errInvalidExpressionX: "invalid expression: '$1'",
errEnumHasNoValueX: "enum has no value '$1'", errEnumHasNoValueX: "enum has no value '$1'",
errNamedExprExpected: "named expression expected", errNamedExprExpected: "named expression expected",
errNamedExprNotAllowed: "named expression not allowed here", errNamedExprNotAllowed: "named expression not allowed here",
errXExpectsOneTypeParam: "'$1' expects one type parameter",
errArrayExpectsTwoTypeParams: "array expects two type parameters",
errInvalidVisibilityX: "invalid visibility: '$1'",
errInitHereNotAllowed: "initialization not allowed here",
errXCannotBeAssignedTo: "'$1' cannot be assigned to",
errIteratorNotAllowed: "iterators can only be defined at the module's top level",
errXNeedsReturnType: "$1 needs a return type",
errNoReturnTypeDeclared: "no return type declared",
errNoCommand: "no command given", errNoCommand: "no command given",
errInvalidCommandX: "invalid command: '$1'", errInvalidCommandX: "invalid command: '$1'",
errXOnlyAtModuleScope: "'$1' is only allowed at top level",
errXNeedsParamObjectType: "'$1' needs a parameter that has an object type", errXNeedsParamObjectType: "'$1' needs a parameter that has an object type",
errTemplateInstantiationTooNested: "template instantiation too nested, try --evalTemplateLimit:N", errTemplateInstantiationTooNested: "template instantiation too nested, try --evalTemplateLimit:N",
errMacroInstantiationTooNested: "macro instantiation too nested, try --evalMacroLimit:N", errMacroInstantiationTooNested: "macro instantiation too nested, try --evalMacroLimit:N",
@ -347,7 +333,7 @@ errInvalidIndexValueForTuple: "invalid index value for tuple subscript",
errCommandExpectsFilename: "command expects a filename argument", errCommandExpectsFilename: "command expects a filename argument",
errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file", errMainModuleMustBeSpecified: "please, specify a main module in the project configuration file",
errXExpected: "'$1' expected", errXExpected: "'$1' expected",
errTIsNotAConcreteType: "'$1' is not a concrete type.", ,
errCastToANonConcreteType: "cannot cast to a non concrete type: '$1'", errCastToANonConcreteType: "cannot cast to a non concrete type: '$1'",
errInvalidSectionStart: "invalid section start", errInvalidSectionStart: "invalid section start",
errGridTableNotImplemented: "grid table is not implemented", errGridTableNotImplemented: "grid table is not implemented",
@ -396,5 +382,4 @@ errGenericLambdaNotAllowed: "A nested proc can have generic parameters only when
"it is used as an operand to another routine and the types " & "it is used as an operand to another routine and the types " &
"of the generic paramers can be inferred from the expected signature.", "of the generic paramers can be inferred from the expected signature.",
errProcHasNoConcreteType: "'$1' doesn't have a concrete type, due to unspecified generic parameters.", errProcHasNoConcreteType: "'$1' doesn't have a concrete type, due to unspecified generic parameters.",
errInOutFlagNotExtern: "The `$1` modifier can be used only with imported types",
]# ]#

View file

@ -114,7 +114,7 @@ proc evalTemplateArgs(n: PNode, s: PSym; conf: ConfigRef; fromHlo: bool): PNode
# to prevent endless recursion in template instantiation # to prevent endless recursion in template instantiation
const evalTemplateLimit* = 1000 const evalTemplateLimit* = 1000
var evalTemplateCounter* = 0 var evalTemplateCounter* = 0 # XXX remove this global
proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode = proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
when true: when true:

View file

@ -17,7 +17,7 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
# aweful to semcheck before macro invocation, so we don't and treat # aweful to semcheck before macro invocation, so we don't and treat
# templates and macros as immediate in this context. # templates and macros as immediate in this context.
var rule: string var rule: string
if optHints in gOptions and hintPattern in gNotes: if optHints in gOptions and hintPattern in c.config.notes:
rule = renderTree(n, {renderNoComments}) rule = renderTree(n, {renderNoComments})
let s = n.sons[0].sym let s = n.sons[0].sym
case s.kind case s.kind
@ -27,8 +27,8 @@ proc evalPattern(c: PContext, n, orig: PNode): PNode =
result = semTemplateExpr(c, n, s, {efFromHlo}) result = semTemplateExpr(c, n, s, {efFromHlo})
else: else:
result = semDirectOp(c, n, {}) result = semDirectOp(c, n, {})
if optHints in gOptions and hintPattern in gNotes: if optHints in gOptions and hintPattern in c.config.notes:
message(orig.info, hintPattern, rule & " --> '" & message(c.config, orig.info, hintPattern, rule & " --> '" &
renderTree(result, {renderNoComments}) & "'") renderTree(result, {renderNoComments}) & "'")
proc applyPatterns(c: PContext, n: PNode): PNode = proc applyPatterns(c: PContext, n: PNode): PNode =
@ -45,7 +45,7 @@ proc applyPatterns(c: PContext, n: PNode): PNode =
# better be safe than sorry, so check evalTemplateCounter too: # better be safe than sorry, so check evalTemplateCounter too:
inc(evalTemplateCounter) inc(evalTemplateCounter)
if evalTemplateCounter > evalTemplateLimit: if evalTemplateCounter > evalTemplateLimit:
globalError(n.info, errTemplateInstantiationTooNested) globalError(c.config, n.info, "template instantiation too nested")
# deactivate this pattern: # deactivate this pattern:
c.patterns[i] = nil c.patterns[i] = nil
if x.kind == nkStmtList: if x.kind == nkStmtList:
@ -86,9 +86,9 @@ proc hlo(c: PContext, n: PNode): PNode =
else: else:
result = fitNode(c, n.typ, result, n.info) result = fitNode(c, n.typ, result, n.info)
# optimization has been applied so check again: # optimization has been applied so check again:
result = commonOptimizations(c.module, result) result = commonOptimizations(c.graph, c.module, result)
result = hlo(c, result) result = hlo(c, result)
result = commonOptimizations(c.module, result) result = commonOptimizations(c.graph, c.module, result)
proc hloBody(c: PContext, n: PNode): PNode = proc hloBody(c: PContext, n: PNode): PNode =
# fast exit: # fast exit:

View file

@ -132,9 +132,9 @@ template styleCheckDef*(info: TLineInfo; s: PSym; k: TSymKind) =
if gStyleCheck != StyleCheck.None: styleCheckDefImpl(conf, info, s, k) if gStyleCheck != StyleCheck.None: styleCheckDefImpl(conf, info, s, k)
template styleCheckDef*(info: TLineInfo; s: PSym) = template styleCheckDef*(info: TLineInfo; s: PSym) =
styleCheckDef(conf, info, s, s.kind) styleCheckDef(info, s, s.kind)
template styleCheckDef*(s: PSym) = template styleCheckDef*(s: PSym) =
styleCheckDef(conf, s.info, s, s.kind) styleCheckDef(s.info, s, s.kind)
proc styleCheckUseImpl(info: TLineInfo; s: PSym) = proc styleCheckUseImpl(info: TLineInfo; s: PSym) =
if info.fileIndex.int < 0: return if info.fileIndex.int < 0: return

View file

@ -16,7 +16,7 @@ import
procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch, procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch,
intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting, intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
evaltempl, patterns, parampatterns, sempass2, nimfix.pretty, semmacrosanity, evaltempl, patterns, parampatterns, sempass2, nimfix.pretty, semmacrosanity,
semparallel, lowerings, pluginsupport, plugins.active, rod semparallel, lowerings, pluginsupport, plugins.active, rod, configuration
from modulegraphs import ModuleGraph from modulegraphs import ModuleGraph
@ -382,7 +382,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
## contains. ## contains.
inc(evalTemplateCounter) inc(evalTemplateCounter)
if evalTemplateCounter > evalTemplateLimit: if evalTemplateCounter > evalTemplateLimit:
globalError(s.info, errTemplateInstantiationTooNested) globalError(c.config, s.info, "template instantiation too nested")
c.friendModules.add(s.owner.getModule) c.friendModules.add(s.owner.getModule)
result = macroResult result = macroResult
@ -424,43 +424,46 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
dec(evalTemplateCounter) dec(evalTemplateCounter)
discard c.friendModules.pop() discard c.friendModules.pop()
const
errMissingGenericParamsForTemplate = "'$1' has unspecified generic parameters"
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
flags: TExprFlags = {}): PNode = flags: TExprFlags = {}): PNode =
pushInfoContext(nOrig.info) pushInfoContext(nOrig.info)
markUsed(n.info, sym, c.graph.usageSym) markUsed(c.config, n.info, sym, c.graph.usageSym)
styleCheckUse(n.info, sym) styleCheckUse(n.info, sym)
if sym == c.p.owner: if sym == c.p.owner:
globalError(n.info, errRecursiveDependencyX, sym.name.s) globalError(c.config, n.info, "recursive dependency: '$1'" % sym.name.s)
let genericParams = if sfImmediate in sym.flags: 0 let genericParams = if sfImmediate in sym.flags: 0
else: sym.ast[genericParamsPos].len else: sym.ast[genericParamsPos].len
let suppliedParams = max(n.safeLen - 1, 0) let suppliedParams = max(n.safeLen - 1, 0)
if suppliedParams < genericParams: if suppliedParams < genericParams:
globalError(n.info, errMissingGenericParamsForTemplate, n.renderTree) globalError(c.config, n.info, errMissingGenericParamsForTemplate % n.renderTree)
#if c.evalContext == nil: #if c.evalContext == nil:
# c.evalContext = c.createEvalContext(emStatic) # c.evalContext = c.createEvalContext(emStatic)
result = evalMacroCall(c.module, c.cache, c.graph.config, n, nOrig, sym) result = evalMacroCall(c.module, c.cache, c.graph, n, nOrig, sym)
if efNoSemCheck notin flags: if efNoSemCheck notin flags:
result = semAfterMacroCall(c, n, result, sym, flags) result = semAfterMacroCall(c, n, result, sym, flags)
result = wrapInComesFrom(nOrig.info, sym, result) result = wrapInComesFrom(nOrig.info, sym, result)
popInfoContext() popInfoContext()
proc forceBool(c: PContext, n: PNode): PNode = proc forceBool(c: PContext, n: PNode): PNode =
result = fitNode(c, getSysType(tyBool), n, n.info) result = fitNode(c, getSysType(c.graph, n.info, tyBool), n, n.info)
if result == nil: result = n if result == nil: result = n
proc semConstBoolExpr(c: PContext, n: PNode): PNode = proc semConstBoolExpr(c: PContext, n: PNode): PNode =
let nn = semExprWithType(c, n) let nn = semExprWithType(c, n)
result = fitNode(c, getSysType(tyBool), nn, nn.info) result = fitNode(c, getSysType(c.graph, n.info, tyBool), nn, nn.info)
if result == nil: if result == nil:
localError(n.info, errConstExprExpected) localError(c.config, n.info, errConstExprExpected)
return nn return nn
result = getConstExpr(c.module, result) result = getConstExpr(c.module, result, c.graph)
if result == nil: if result == nil:
localError(n.info, errConstExprExpected) localError(c.config, n.info, errConstExprExpected)
result = nn result = nn
proc semGenericStmt(c: PContext, n: PNode): PNode proc semGenericStmt(c: PContext, n: PNode): PNode
@ -480,7 +483,7 @@ proc addCodeForGenerics(c: PContext, n: PNode) =
proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext = proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
var c = newContext(graph, module, cache) var c = newContext(graph, module, cache)
if c.p != nil: internalError(module.info, "sem.myOpen") if c.p != nil: internalError(graph.config, module.info, "sem.myOpen")
c.semConstExpr = semConstExpr c.semConstExpr = semConstExpr
c.semExpr = semExpr c.semExpr = semExpr
c.semTryExpr = tryExpr c.semTryExpr = tryExpr
@ -532,7 +535,7 @@ proc isImportSystemStmt(n: PNode): bool =
proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
if n.kind == nkDefer: if n.kind == nkDefer:
localError(n.info, "defer statement not supported at top level") localError(c.config, n.info, "defer statement not supported at top level")
if c.topStmts == 0 and not isImportSystemStmt(n): if c.topStmts == 0 and not isImportSystemStmt(n):
if sfSystemModule notin c.module.flags and if sfSystemModule notin c.module.flags and
n.kind notin {nkEmpty, nkCommentStmt}: n.kind notin {nkEmpty, nkCommentStmt}:

View file

@ -202,24 +202,31 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
result = (prefer, candidates) result = (prefer, candidates)
const
errTypeMismatch = "type mismatch: got <"
errButExpected = "but expected one of: "
errUndeclaredField = "undeclared field: '$1'"
errUndeclaredRoutine = "attempting to call undeclared routine: '$1'"
errAmbiguousCallXYZ = "ambiguous call; both $1 and $2 match for: $3"
proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) = proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
# Gives a detailed error message; this is separated from semOverloadedCall, # Gives a detailed error message; this is separated from semOverloadedCall,
# as semOverlodedCall is already pretty slow (and we need this information # as semOverlodedCall is already pretty slow (and we need this information
# only in case of an error). # only in case of an error).
if errorOutputs == {}: if errorOutputs == {}:
# fail fast: # fail fast:
globalError(n.info, errTypeMismatch, "") globalError(c.config, n.info, "type mismatch")
if errors.len == 0: if errors.len == 0:
localError(n.info, errExprXCannotBeCalled, n[0].renderTree) localError(c.config, n.info, "expression '$1' cannot be called" % n[0].renderTree)
return return
let (prefer, candidates) = presentFailedCandidates(c, n, errors) let (prefer, candidates) = presentFailedCandidates(c, n, errors)
var result = msgKindToString(errTypeMismatch) var result = errTypeMismatch
add(result, describeArgs(c, n, 1, prefer)) add(result, describeArgs(c, n, 1, prefer))
add(result, '>') add(result, '>')
if candidates != "": if candidates != "":
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates) add(result, "\n" & errButExpected & "\n" & candidates)
localError(n.info, errGenerated, result & "\nexpression: " & $n) localError(c.config, n.info, result & "\nexpression: " & $n)
proc bracketNotFoundError(c: PContext; n: PNode) = proc bracketNotFoundError(c: PContext; n: PNode) =
var errors: CandidateErrors = @[] var errors: CandidateErrors = @[]
@ -234,7 +241,7 @@ proc bracketNotFoundError(c: PContext; n: PNode) =
enabled: false)) enabled: false))
symx = nextOverloadIter(o, c, headSymbol) symx = nextOverloadIter(o, c, headSymbol)
if errors.len == 0: if errors.len == 0:
localError(n.info, "could not resolve: " & $n) localError(c.config, n.info, "could not resolve: " & $n)
else: else:
notFoundError(c, n, errors) notFoundError(c, n, errors)
@ -277,7 +284,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
else: return else: return
if nfDotField in n.flags: if nfDotField in n.flags:
internalAssert f.kind == nkIdent and n.sonsLen >= 2 internalAssert c.config, f.kind == nkIdent and n.len >= 2
# leave the op head symbol empty, # leave the op head symbol empty,
# we are going to try multiple variants # we are going to try multiple variants
@ -306,13 +313,13 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
if overloadsState == csEmpty and result.state == csEmpty: if overloadsState == csEmpty and result.state == csEmpty:
if nfDotField in n.flags and nfExplicitCall notin n.flags: if nfDotField in n.flags and nfExplicitCall notin n.flags:
localError(n.info, errUndeclaredField, considerQuotedIdent(f, n).s) localError(c.config, n.info, errUndeclaredField % considerQuotedIdent(c.config, f, n).s)
else: else:
localError(n.info, errUndeclaredRoutine, considerQuotedIdent(f, n).s) localError(c.config, n.info, errUndeclaredRoutine % considerQuotedIdent(c.config, f, n).s)
return return
elif result.state != csMatch: elif result.state != csMatch:
if nfExprCall in n.flags: if nfExprCall in n.flags:
localError(n.info, errExprXCannotBeCalled, localError(c.config, n.info, "expression '$1' cannot be called" %
renderTree(n, {renderNoComments})) renderTree(n, {renderNoComments}))
else: else:
if {nfDotField, nfDotSetter} * n.flags != {}: if {nfDotField, nfDotSetter} * n.flags != {}:
@ -322,13 +329,13 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
return return
if alt.state == csMatch and cmpCandidates(result, alt) == 0 and if alt.state == csMatch and cmpCandidates(result, alt) == 0 and
not sameMethodDispatcher(result.calleeSym, alt.calleeSym): not sameMethodDispatcher(result.calleeSym, alt.calleeSym):
internalAssert result.state == csMatch internalAssert c.config, result.state == csMatch
#writeMatches(result) #writeMatches(result)
#writeMatches(alt) #writeMatches(alt)
if errorOutputs == {}: if errorOutputs == {}:
# quick error message for performance of 'compiles' built-in: # quick error message for performance of 'compiles' built-in:
globalError(n.info, errGenerated, "ambiguous call") globalError(c.config, n.info, errGenerated, "ambiguous call")
elif gErrorCounter == 0: elif c.config.errorCounter == 0:
# don't cascade errors # don't cascade errors
var args = "(" var args = "("
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
@ -336,7 +343,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
add(args, typeToString(n.sons[i].typ)) add(args, typeToString(n.sons[i].typ))
add(args, ")") add(args, ")")
localError(n.info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [ localError(c.config, n.info, errAmbiguousCallXYZ % [
getProcHeader(result.calleeSym), getProcHeader(alt.calleeSym), getProcHeader(result.calleeSym), getProcHeader(alt.calleeSym),
args]) args])
@ -377,7 +384,7 @@ proc inferWithMetatype(c: PContext, formal: PType,
result.typ = generateTypeInstance(c, m.bindings, arg.info, result.typ = generateTypeInstance(c, m.bindings, arg.info,
formal.skipTypes({tyCompositeTypeClass})) formal.skipTypes({tyCompositeTypeClass}))
else: else:
typeMismatch(arg.info, formal, arg.typ) typeMismatch(c.config, arg.info, formal, arg.typ)
# error correction: # error correction:
result = copyTree(arg) result = copyTree(arg)
result.typ = formal result.typ = formal
@ -385,7 +392,7 @@ proc inferWithMetatype(c: PContext, formal: PType,
proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode = proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
assert x.state == csMatch assert x.state == csMatch
var finalCallee = x.calleeSym var finalCallee = x.calleeSym
markUsed(n.sons[0].info, finalCallee, c.graph.usageSym) markUsed(c.config, n.sons[0].info, finalCallee, c.graph.usageSym)
styleCheckUse(n.sons[0].info, finalCallee) styleCheckUse(n.sons[0].info, finalCallee)
assert finalCallee.ast != nil assert finalCallee.ast != nil
if x.hasFauxMatch: if x.hasFauxMatch:
@ -411,7 +418,7 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
of skType: of skType:
x.call.add newSymNode(s, n.info) x.call.add newSymNode(s, n.info)
else: else:
internalAssert false internalAssert c.config, false
result = x.call result = x.call
instGenericConvertersSons(c, result, x) instGenericConvertersSons(c, result, x)
@ -435,7 +442,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
# this may be triggered, when the explain pragma is used # this may be triggered, when the explain pragma is used
if errors.len > 0: if errors.len > 0:
let (_, candidates) = presentFailedCandidates(c, n, errors) let (_, candidates) = presentFailedCandidates(c, n, errors)
message(n.info, hintUserRaw, message(c.config, n.info, hintUserRaw,
"Non-matching candidates for " & renderTree(n) & "\n" & "Non-matching candidates for " & renderTree(n) & "\n" &
candidates) candidates)
result = semResolvedCall(c, n, r) result = semResolvedCall(c, n, r)
@ -468,8 +475,8 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
else: else:
notFoundError(c, n, errors) notFoundError(c, n, errors)
proc explicitGenericInstError(n: PNode): PNode = proc explicitGenericInstError(c: PContext; n: PNode): PNode =
localError(n.info, errCannotInstantiateX, renderTree(n)) localError(c.config, n.info, errCannotInstantiateX % renderTree(n))
result = n result = n
proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode = proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
@ -484,7 +491,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
if tm in {isNone, isConvertible}: return nil if tm in {isNone, isConvertible}: return nil
var newInst = generateInstance(c, s, m.bindings, n.info) var newInst = generateInstance(c, s, m.bindings, n.info)
newInst.typ.flags.excl tfUnresolved newInst.typ.flags.excl tfUnresolved
markUsed(n.info, s, c.graph.usageSym) markUsed(c.config, n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
result = newSymNode(newInst, n.info) result = newSymNode(newInst, n.info)
@ -500,11 +507,11 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
# number of generic type parameters: # number of generic type parameters:
if safeLen(s.ast.sons[genericParamsPos]) != n.len-1: if safeLen(s.ast.sons[genericParamsPos]) != n.len-1:
let expected = safeLen(s.ast.sons[genericParamsPos]) let expected = safeLen(s.ast.sons[genericParamsPos])
localError(n.info, errGenerated, "cannot instantiate: " & renderTree(n) & localError(c.config, n.info, errGenerated, "cannot instantiate: " & renderTree(n) &
"; got " & $(n.len-1) & " type(s) but expected " & $expected) "; got " & $(n.len-1) & " type(s) but expected " & $expected)
return n return n
result = explicitGenericSym(c, n, s) result = explicitGenericSym(c, n, s)
if result == nil: result = explicitGenericInstError(n) if result == nil: result = explicitGenericInstError(c, n)
elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}: elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}:
# choose the generic proc with the proper number of type parameters. # choose the generic proc with the proper number of type parameters.
# XXX I think this could be improved by reusing sigmatch.paramTypesMatch. # XXX I think this could be improved by reusing sigmatch.paramTypesMatch.
@ -522,10 +529,10 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
# get rid of nkClosedSymChoice if not ambiguous: # get rid of nkClosedSymChoice if not ambiguous:
if result.len == 1 and a.kind == nkClosedSymChoice: if result.len == 1 and a.kind == nkClosedSymChoice:
result = result[0] result = result[0]
elif result.len == 0: result = explicitGenericInstError(n) elif result.len == 0: result = explicitGenericInstError(c, n)
# candidateCount != 1: return explicitGenericInstError(n) # candidateCount != 1: return explicitGenericInstError(c, n)
else: else:
result = explicitGenericInstError(n) result = explicitGenericInstError(c, n)
proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym = proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
# Searchs for the fn in the symbol table. If the parameter lists are suitable # Searchs for the fn in the symbol table. If the parameter lists are suitable

View file

@ -31,12 +31,12 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
if result.typ != nil: if result.typ != nil:
# XXX tyGenericInst here? # XXX tyGenericInst here?
if result.typ.kind == tyProc and tfUnresolved in result.typ.flags: if result.typ.kind == tyProc and tfUnresolved in result.typ.flags:
localError(n.info, errProcHasNoConcreteType, n.renderTree) localError(c.config, n.info, errProcHasNoConcreteType, n.renderTree)
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result) if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
elif {efWantStmt, efAllowStmt} * flags != {}: elif {efWantStmt, efAllowStmt} * flags != {}:
result.typ = newTypeS(tyVoid, c) result.typ = newTypeS(tyVoid, c)
else: else:
localError(n.info, errExprXHasNoType, localError(c.config, n.info, errExprXHasNoType,
renderTree(result, {renderNoComments})) renderTree(result, {renderNoComments}))
result.typ = errorType(c) result.typ = errorType(c)
@ -47,7 +47,7 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
#raiseRecoverableError("") #raiseRecoverableError("")
result = errorNode(c, n) result = errorNode(c, n)
if result.typ == nil or result.typ == enforceVoidContext: if result.typ == nil or result.typ == enforceVoidContext:
localError(n.info, errExprXHasNoType, localError(c.config, n.info, errExprXHasNoType,
renderTree(result, {renderNoComments})) renderTree(result, {renderNoComments}))
result.typ = errorType(c) result.typ = errorType(c)
else: else:
@ -59,7 +59,7 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# do not produce another redundant error message: # do not produce another redundant error message:
result = errorNode(c, n) result = errorNode(c, n)
if result.typ == nil: if result.typ == nil:
localError(n.info, errExprXHasNoType, localError(c.config, n.info, errExprXHasNoType,
renderTree(result, {renderNoComments})) renderTree(result, {renderNoComments}))
result.typ = errorType(c) result.typ = errorType(c)
@ -69,7 +69,7 @@ proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
proc inlineConst(n: PNode, s: PSym): PNode {.inline.} = proc inlineConst(n: PNode, s: PSym): PNode {.inline.} =
result = copyTree(s.ast) result = copyTree(s.ast)
if result.isNil: if result.isNil:
localError(n.info, "constant of type '" & typeToString(s.typ) & "' has no value") localError(c.config, n.info, "constant of type '" & typeToString(s.typ) & "' has no value")
result = newSymNode(s) result = newSymNode(s)
else: else:
result.typ = s.typ result.typ = s.typ
@ -172,7 +172,7 @@ proc maybeLiftType(t: var PType, c: PContext, info: TLineInfo) =
proc semConv(c: PContext, n: PNode): PNode = proc semConv(c: PContext, n: PNode): PNode =
if sonsLen(n) != 2: if sonsLen(n) != 2:
localError(n.info, errConvNeedsOneArg) localError(c.config, n.info, errConvNeedsOneArg)
return n return n
result = newNodeI(nkConv, n.info) result = newNodeI(nkConv, n.info)
@ -192,7 +192,7 @@ proc semConv(c: PContext, n: PNode): PNode =
# special case to make MyObject(x = 3) produce a nicer error message: # special case to make MyObject(x = 3) produce a nicer error message:
if n[1].kind == nkExprEqExpr and if n[1].kind == nkExprEqExpr and
targetType.skipTypes(abstractPtrs).kind == tyObject: targetType.skipTypes(abstractPtrs).kind == tyObject:
localError(n.info, "object contruction uses ':', not '='") localError(c.config, n.info, "object contruction uses ':', not '='")
var op = semExprWithType(c, n.sons[1]) var op = semExprWithType(c, n.sons[1])
if targetType.isMetaType: if targetType.isMetaType:
let final = inferWithMetatype(c, targetType, op, true) let final = inferWithMetatype(c, targetType, op, true)
@ -219,7 +219,7 @@ proc semConv(c: PContext, n: PNode): PNode =
of convNotLegal: of convNotLegal:
result = fitNode(c, result.typ, result.sons[1], result.info) result = fitNode(c, result.typ, result.sons[1], result.info)
if result == nil: if result == nil:
localError(n.info, errGenerated, msgKindToString(errIllegalConvFromXtoY)% localError(c.config, n.info, errGenerated, msgKindToString(errIllegalConvFromXtoY)%
[op.typ.typeToString, result.typ.typeToString]) [op.typ.typeToString, result.typ.typeToString])
else: else:
for i in countup(0, sonsLen(op) - 1): for i in countup(0, sonsLen(op) - 1):
@ -234,16 +234,16 @@ proc semConv(c: PContext, n: PNode): PNode =
proc semCast(c: PContext, n: PNode): PNode = proc semCast(c: PContext, n: PNode): PNode =
## Semantically analyze a casting ("cast[type](param)") ## Semantically analyze a casting ("cast[type](param)")
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
let targetType = semTypeNode(c, n.sons[0], nil) let targetType = semTypeNode(c, n.sons[0], nil)
let castedExpr = semExprWithType(c, n.sons[1]) let castedExpr = semExprWithType(c, n.sons[1])
if tfHasMeta in targetType.flags: if tfHasMeta in targetType.flags:
localError(n.sons[0].info, errCastToANonConcreteType, $targetType) localError(c.config, n.sons[0].info, errCastToANonConcreteType, $targetType)
if not isCastable(targetType, castedExpr.typ): if not isCastable(targetType, castedExpr.typ):
let tar = $targetType let tar = $targetType
let alt = typeToString(targetType, preferDesc) let alt = typeToString(targetType, preferDesc)
let msg = if tar != alt: tar & "=" & alt else: tar let msg = if tar != alt: tar & "=" & alt else: tar
localError(n.info, errExprCannotBeCastToX, msg) localError(c.config, n.info, errExprCannotBeCastToX, msg)
result = newNodeI(nkCast, n.info) result = newNodeI(nkCast, n.info)
result.typ = targetType result.typ = targetType
addSon(result, copyTree(n.sons[0])) addSon(result, copyTree(n.sons[0]))
@ -253,7 +253,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
const const
opToStr: array[mLow..mHigh, string] = ["low", "high"] opToStr: array[mLow..mHigh, string] = ["low", "high"]
if sonsLen(n) != 2: if sonsLen(n) != 2:
localError(n.info, errXExpectsTypeOrValue, opToStr[m]) localError(c.config, n.info, errXExpectsTypeOrValue, opToStr[m])
else: else:
n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType}) n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType})
var typ = skipTypes(n.sons[1].typ, abstractVarRange + {tyTypeDesc}) var typ = skipTypes(n.sons[1].typ, abstractVarRange + {tyTypeDesc})
@ -271,12 +271,12 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
# that could easily turn into an infinite recursion in semtypinst # that could easily turn into an infinite recursion in semtypinst
n.typ = makeTypeFromExpr(c, n.copyTree) n.typ = makeTypeFromExpr(c, n.copyTree)
else: else:
localError(n.info, errInvalidArgForX, opToStr[m]) localError(c.config, n.info, errInvalidArgForX, opToStr[m])
result = n result = n
proc semSizeof(c: PContext, n: PNode): PNode = proc semSizeof(c: PContext, n: PNode): PNode =
if sonsLen(n) != 2: if sonsLen(n) != 2:
localError(n.info, errXExpectsTypeOrValue, "sizeof") localError(c.config, n.info, errXExpectsTypeOrValue, "sizeof")
else: else:
n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType}) n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType})
#restoreOldStyleType(n.sons[1]) #restoreOldStyleType(n.sons[1])
@ -315,7 +315,7 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode = proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
if sonsLen(n) != 3: if sonsLen(n) != 3:
localError(n.info, errXExpectsTwoArguments, "is") localError(c.config, n.info, errXExpectsTwoArguments, "is")
result = n result = n
n.typ = getSysType(tyBool) n.typ = getSysType(tyBool)
@ -396,7 +396,7 @@ proc changeType(n: PNode, newType: PType, check: bool) =
if check and n.kind != nkUInt64Lit: if check and n.kind != nkUInt64Lit:
let value = n.intVal let value = n.intVal
if value < firstOrd(newType) or value > lastOrd(newType): if value < firstOrd(newType) or value > lastOrd(newType):
localError(n.info, errGenerated, "cannot convert " & $value & localError(c.config, n.info, errGenerated, "cannot convert " & $value &
" to " & typeToString(newType)) " to " & typeToString(newType))
else: discard else: discard
n.typ = newType n.typ = newType
@ -438,7 +438,7 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
var idx = semConstExpr(c, x.sons[0]) var idx = semConstExpr(c, x.sons[0])
idx = fitNode(c, indexType, idx, x.info) idx = fitNode(c, indexType, idx, x.info)
if lastIndex+1 != getOrdValue(idx): if lastIndex+1 != getOrdValue(idx):
localError(x.info, errInvalidOrderInArrayConstructor) localError(c.config, x.info, errInvalidOrderInArrayConstructor)
x = x.sons[1] x = x.sons[1]
let xx = semExprWithType(c, x, flags*{efAllowDestructor}) let xx = semExprWithType(c, x, flags*{efAllowDestructor})
@ -471,13 +471,13 @@ proc isAssignable(c: PContext, n: PNode; isUnsafeAddr=false): TAssignableResult
proc newHiddenAddrTaken(c: PContext, n: PNode): PNode = proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
if n.kind == nkHiddenDeref and not (gCmd == cmdCompileToCpp or if n.kind == nkHiddenDeref and not (gCmd == cmdCompileToCpp or
sfCompileToCpp in c.module.flags): sfCompileToCpp in c.module.flags):
checkSonsLen(n, 1) checkSonsLen(n, 1, c.config)
result = n.sons[0] result = n.sons[0]
else: else:
result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ)) result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ))
addSon(result, n) addSon(result, n)
if isAssignable(c, n) notin {arLValue, arLocalLValue}: if isAssignable(c, n) notin {arLValue, arLocalLValue}:
localError(n.info, errVarForOutParamNeededX, renderNotLValue(n)) localError(c.config, n.info, errVarForOutParamNeededX, renderNotLValue(n))
proc analyseIfAddressTaken(c: PContext, n: PNode): PNode = proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
result = n result = n
@ -489,7 +489,7 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
incl(n.sym.flags, sfAddrTaken) incl(n.sym.flags, sfAddrTaken)
result = newHiddenAddrTaken(c, n) result = newHiddenAddrTaken(c, n)
of nkDotExpr: of nkDotExpr:
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
if n.sons[1].kind != nkSym: if n.sons[1].kind != nkSym:
internalError(n.info, "analyseIfAddressTaken") internalError(n.info, "analyseIfAddressTaken")
return return
@ -497,7 +497,7 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
incl(n.sons[1].sym.flags, sfAddrTaken) incl(n.sons[1].sym.flags, sfAddrTaken)
result = newHiddenAddrTaken(c, n) result = newHiddenAddrTaken(c, n)
of nkBracketExpr: of nkBracketExpr:
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1, c.config)
if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind notin {tyVar, tyLent}: if skipTypes(n.sons[0].typ, abstractInst-{tyTypeDesc}).kind notin {tyVar, tyLent}:
if n.sons[0].kind == nkSym: incl(n.sons[0].sym.flags, sfAddrTaken) if n.sons[0].kind == nkSym: incl(n.sons[0].sym.flags, sfAddrTaken)
result = newHiddenAddrTaken(c, n) result = newHiddenAddrTaken(c, n)
@ -505,7 +505,7 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
result = newHiddenAddrTaken(c, n) result = newHiddenAddrTaken(c, n)
proc analyseIfAddressTakenInCall(c: PContext, n: PNode) = proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1, c.config)
const const
FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl, FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl,
mSetLengthStr, mSetLengthSeq, mAppendStrCh, mAppendStrStr, mSwap, mSetLengthStr, mSetLengthSeq, mAppendStrCh, mAppendStrStr, mSwap,
@ -524,14 +524,14 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
let it = n[i] let it = n[i]
if isAssignable(c, it) notin {arLValue, arLocalLValue}: if isAssignable(c, it) notin {arLValue, arLocalLValue}:
if it.kind != nkHiddenAddr: if it.kind != nkHiddenAddr:
localError(it.info, errVarForOutParamNeededX, $it) localError(c.config, it.info, errVarForOutParamNeededX % $it)
# bug #5113: disallow newSeq(result) where result is a 'var T': # bug #5113: disallow newSeq(result) where result is a 'var T':
if n[0].sym.magic in {mNew, mNewFinalize, mNewSeq}: if n[0].sym.magic in {mNew, mNewFinalize, mNewSeq}:
var arg = n[1] #.skipAddr var arg = n[1] #.skipAddr
if arg.kind == nkHiddenDeref: arg = arg[0] if arg.kind == nkHiddenDeref: arg = arg[0]
if arg.kind == nkSym and arg.sym.kind == skResult and if arg.kind == nkSym and arg.sym.kind == skResult and
arg.typ.skipTypes(abstractInst).kind in {tyVar, tyLent}: arg.typ.skipTypes(abstractInst).kind in {tyVar, tyLent}:
localError(n.info, errXStackEscape, renderTree(n[1], {renderNoComments})) localError(c.config, n.info, errXStackEscape % renderTree(n[1], {renderNoComments}))
return return
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
@ -560,14 +560,14 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
call.add(n.sons[0]) call.add(n.sons[0])
var allConst = true var allConst = true
for i in 1 ..< n.len: for i in 1 ..< n.len:
var a = getConstExpr(c.module, n.sons[i]) var a = getConstExpr(c.module, n.sons[i], c.graph)
if a == nil: if a == nil:
allConst = false allConst = false
a = n.sons[i] a = n.sons[i]
if a.kind == nkHiddenStdConv: a = a.sons[1] if a.kind == nkHiddenStdConv: a = a.sons[1]
call.add(a) call.add(a)
if allConst: if allConst:
result = semfold.getConstExpr(c.module, call) result = semfold.getConstExpr(c.module, call, c.graph)
if result.isNil: result = n if result.isNil: result = n
else: return result else: return result
@ -607,7 +607,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
if sfCompileTime in callee.flags: if sfCompileTime in callee.flags:
result = evalStaticExpr(c.module, c.cache, c.graph.config, call, c.p.owner) result = evalStaticExpr(c.module, c.cache, c.graph.config, call, c.p.owner)
if result.isNil: if result.isNil:
localError(n.info, errCannotInterpretNodeX, renderTree(call)) localError(c.config, n.info, errCannotInterpretNodeX, renderTree(call))
else: result = fixupTypeAfterEval(c, result, n) else: result = fixupTypeAfterEval(c, result, n)
else: else:
result = evalConstExpr(c.module, c.cache, c.graph.config, call) result = evalConstExpr(c.module, c.cache, c.graph.config, call)
@ -621,7 +621,7 @@ proc semStaticExpr(c: PContext, n: PNode): PNode =
if a.findUnresolvedStatic != nil: return a if a.findUnresolvedStatic != nil: return a
result = evalStaticExpr(c.module, c.cache, c.graph.config, a, c.p.owner) result = evalStaticExpr(c.module, c.cache, c.graph.config, a, c.p.owner)
if result.isNil: if result.isNil:
localError(n.info, errCannotInterpretNodeX, renderTree(n)) localError(c.config, n.info, errCannotInterpretNodeX, renderTree(n))
result = emptyNode result = emptyNode
else: else:
result = fixupTypeAfterEval(c, result, a) result = fixupTypeAfterEval(c, result, a)
@ -648,7 +648,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
of skMacro, skTemplate: discard of skMacro, skTemplate: discard
else: else:
if callee.kind == skIterator and callee.id == c.p.owner.id: if callee.kind == skIterator and callee.id == c.p.owner.id:
localError(n.info, errRecursiveDependencyX, callee.name.s) localError(c.config, n.info, errRecursiveDependencyX, callee.name.s)
# error correction, prevents endless for loop elimination in transf. # error correction, prevents endless for loop elimination in transf.
# See bug #2051: # See bug #2051:
result.sons[0] = newSymNode(errorSym(c, n)) result.sons[0] = newSymNode(errorSym(c, n))
@ -696,10 +696,10 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = nil result = nil
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1, c.config)
var prc = n.sons[0] var prc = n.sons[0]
if n.sons[0].kind == nkDotExpr: if n.sons[0].kind == nkDotExpr:
checkSonsLen(n.sons[0], 2) checkSonsLen(n.sons[0], 2, c.config)
let n0 = semFieldAccess(c, n.sons[0]) let n0 = semFieldAccess(c, n.sons[0])
if n0.kind == nkDotCall: if n0.kind == nkDotCall:
# it is a static call! # it is a static call!
@ -732,7 +732,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
if m.state != csMatch: if m.state != csMatch:
if errorOutputs == {}: if errorOutputs == {}:
# speed up error generation: # speed up error generation:
globalError(n.info, errTypeMismatch, "") globalError(c.config, n.info, "type mismatch")
return emptyNode return emptyNode
else: else:
var hasErrorType = false var hasErrorType = false
@ -747,7 +747,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
if not hasErrorType: if not hasErrorType:
add(msg, ">\n" & msgKindToString(errButExpected) & "\n" & add(msg, ">\n" & msgKindToString(errButExpected) & "\n" &
typeToString(n.sons[0].typ)) typeToString(n.sons[0].typ))
localError(n.info, errGenerated, msg) localError(c.config, n.info, msg)
return errorNode(c, n) return errorNode(c, n)
result = nil result = nil
else: else:
@ -794,7 +794,7 @@ proc buildEchoStmt(c: PContext, n: PNode): PNode =
if e != nil: if e != nil:
add(result, newSymNode(e)) add(result, newSymNode(e))
else: else:
localError(n.info, errSystemNeeds, "echo") localError(c.config, n.info, "system needs: echo")
add(result, errorNode(c, n)) add(result, errorNode(c, n))
add(result, n) add(result, n)
result = semExpr(c, result) result = semExpr(c, result)
@ -838,8 +838,8 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
result = lookupInRecordAndBuildCheck(c, n, r.sons[i], field, check) result = lookupInRecordAndBuildCheck(c, n, r.sons[i], field, check)
if result != nil: return if result != nil: return
of nkRecCase: of nkRecCase:
checkMinSonsLen(r, 2) checkMinSonsLen(r, 2, c.config)
if (r.sons[0].kind != nkSym): illFormedAst(r) if (r.sons[0].kind != nkSym): illFormedAst(r, c.config)
result = lookupInRecordAndBuildCheck(c, n, r.sons[0], field, check) result = lookupInRecordAndBuildCheck(c, n, r.sons[0], field, check)
if result != nil: return if result != nil: return
let setType = createSetType(c, r.sons[0].typ) let setType = createSetType(c, r.sons[0].typ)
@ -879,10 +879,10 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent,
addSon(notExpr, inExpr) addSon(notExpr, inExpr)
addSon(check, notExpr) addSon(check, notExpr)
return return
else: illFormedAst(it) else: illFormedAst(it, c.config)
of nkSym: of nkSym:
if r.sym.name.id == field.id: result = r.sym if r.sym.name.id == field.id: result = r.sym
else: illFormedAst(n) else: illFormedAst(n, c.config)
const const
tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass} tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass}
@ -995,7 +995,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
of skVar, skLet, skResult, skForVar: of skVar, skLet, skResult, skForVar:
if s.magic == mNimvm: if s.magic == mNimvm:
localError(n.info, "illegal context for 'nimvm' magic") localError(c.config, n.info, "illegal context for 'nimvm' magic")
markUsed(n.info, s, c.graph.usageSym) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
@ -1060,7 +1060,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
## returns nil if it's not a built-in field access ## returns nil if it's not a built-in field access
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
# tests/bind/tbindoverload.nim wants an early exit here, but seems to # tests/bind/tbindoverload.nim wants an early exit here, but seems to
# work without now. template/tsymchoicefield doesn't like an early exit # work without now. template/tsymchoicefield doesn't like an early exit
# here at all! # here at all!
@ -1222,7 +1222,7 @@ proc buildOverloadedSubscripts(n: PNode, ident: PIdent): PNode =
for i in 0 .. n.len-1: result.add(n[i]) for i in 0 .. n.len-1: result.add(n[i])
proc semDeref(c: PContext, n: PNode): PNode = proc semDeref(c: PContext, n: PNode): PNode =
checkSonsLen(n, 1) checkSonsLen(n, 1, c.config)
n.sons[0] = semExprWithType(c, n.sons[0]) n.sons[0] = semExprWithType(c, n.sons[0])
result = n result = n
var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyLent, tyAlias, tySink}) var t = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyLent, tyAlias, tySink})
@ -1240,7 +1240,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = newNodeIT(nkDerefExpr, x.info, x.typ) result = newNodeIT(nkDerefExpr, x.info, x.typ)
result.add(x[0]) result.add(x[0])
return return
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2, c.config)
# make sure we don't evaluate generic macros/templates # make sure we don't evaluate generic macros/templates
n.sons[0] = semExprWithType(c, n.sons[0], n.sons[0] = semExprWithType(c, n.sons[0],
{efNoEvaluateGeneric}) {efNoEvaluateGeneric})
@ -1277,7 +1277,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
{tyInt..tyInt64}: {tyInt..tyInt64}:
var idx = getOrdValue(n.sons[1]) var idx = getOrdValue(n.sons[1])
if idx >= 0 and idx < sonsLen(arr): n.typ = arr.sons[int(idx)] if idx >= 0 and idx < sonsLen(arr): n.typ = arr.sons[int(idx)]
else: localError(n.info, errInvalidIndexValueForTuple) else: localError(c.config, n.info, errInvalidIndexValueForTuple)
result = n result = n
else: else:
result = nil result = nil
@ -1340,10 +1340,10 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
let root = exprRoot(n) let root = exprRoot(n)
if root != nil and root.owner == c.p.owner: if root != nil and root.owner == c.p.owner:
if root.kind in {skLet, skVar, skTemp} and sfGlobal notin root.flags: if root.kind in {skLet, skVar, skTemp} and sfGlobal notin root.flags:
localError(n.info, "'$1' escapes its stack frame; context: '$2'; see $3/var_t_return.html" % [ localError(c.config, n.info, "'$1' escapes its stack frame; context: '$2'; see $3/var_t_return.html" % [
root.name.s, renderTree(n, {renderNoComments}), explanationsBaseUrl]) root.name.s, renderTree(n, {renderNoComments}), explanationsBaseUrl])
elif root.kind == skParam and root.position != 0: elif root.kind == skParam and root.position != 0:
localError(n.info, "'$1' is not the first parameter; context: '$2'; see $3/var_t_return.html" % [ localError(c.config, n.info, "'$1' is not the first parameter; context: '$2'; see $3/var_t_return.html" % [
root.name.s, renderTree(n, {renderNoComments}), explanationsBaseUrl]) root.name.s, renderTree(n, {renderNoComments}), explanationsBaseUrl])
case n.kind case n.kind
of nkHiddenAddr, nkAddr: return n of nkHiddenAddr, nkAddr: return n
@ -1354,9 +1354,9 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
let valid = isAssignable(c, n) let valid = isAssignable(c, n)
if valid != arLValue: if valid != arLValue:
if valid == arLocalLValue: if valid == arLocalLValue:
localError(n.info, errXStackEscape, renderTree(n, {renderNoComments})) localError(c.config, n.info, errXStackEscape, renderTree(n, {renderNoComments}))
elif not isLent: elif not isLent:
localError(n.info, errExprHasNoAddress) localError(c.config, n.info, errExprHasNoAddress)
result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ)) result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ))
result.add(n) result.add(n)
@ -1373,7 +1373,7 @@ template resultTypeIsInferrable(typ: PType): untyped =
typ.isMetaType and typ.kind != tyTypeDesc typ.isMetaType and typ.kind != tyTypeDesc
proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode = proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
var a = n.sons[0] var a = n.sons[0]
case a.kind case a.kind
of nkDotExpr: of nkDotExpr:
@ -1426,7 +1426,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
isAssignable(c, a) == arNone) or isAssignable(c, a) == arNone) or
skipTypes(le, abstractVar).kind in {tyOpenArray, tyVarargs}: skipTypes(le, abstractVar).kind in {tyOpenArray, tyVarargs}:
# Direct assignment to a discriminant is allowed! # Direct assignment to a discriminant is allowed!
localError(a.info, errXCannotBeAssignedTo, localError(c.config, a.info, errXCannotBeAssignedTo,
renderTree(a, {renderNoComments})) renderTree(a, {renderNoComments}))
else: else:
let let
@ -1463,7 +1463,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
proc semReturn(c: PContext, n: PNode): PNode = proc semReturn(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 1) checkSonsLen(n, 1, c.config)
if c.p.owner.kind in {skConverter, skMethod, skProc, skFunc, skMacro} or ( if c.p.owner.kind in {skConverter, skMethod, skProc, skFunc, skMacro} or (
c.p.owner.kind == skIterator and c.p.owner.typ.callConv == ccClosure): c.p.owner.kind == skIterator and c.p.owner.typ.callConv == ccClosure):
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
@ -1477,9 +1477,9 @@ proc semReturn(c: PContext, n: PNode): PNode =
if n[0][1].kind == nkSym and n[0][1].sym == c.p.resultSym: if n[0][1].kind == nkSym and n[0][1].sym == c.p.resultSym:
n.sons[0] = ast.emptyNode n.sons[0] = ast.emptyNode
else: else:
localError(n.info, errNoReturnTypeDeclared) localError(c.config, n.info, errNoReturnTypeDeclared)
else: else:
localError(n.info, errXNotAllowedHere, "\'return\'") localError(c.config, n.info, errXNotAllowedHere, "\'return\'")
proc semProcBody(c: PContext, n: PNode): PNode = proc semProcBody(c: PContext, n: PNode): PNode =
openScope(c) openScope(c)
@ -1510,7 +1510,7 @@ proc semProcBody(c: PContext, n: PNode): PNode =
c.p.resultSym.typ = errorType(c) c.p.resultSym.typ = errorType(c)
c.p.owner.typ.sons[0] = nil c.p.owner.typ.sons[0] = nil
else: else:
localError(c.p.resultSym.info, errCannotInferReturnType) localError(c.config, c.p.resultSym.info, errCannotInferReturnType)
closeScope(c) closeScope(c)
@ -1534,16 +1534,16 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
var a = n.sons[0].sons[1] var a = n.sons[0].sons[1]
a.sons[i] = takeImplicitAddr(c, a.sons[i], false) a.sons[i] = takeImplicitAddr(c, a.sons[i], false)
else: else:
localError(n.sons[0].info, errXExpected, "tuple constructor") localError(c.config, n.sons[0].info, errXExpected, "tuple constructor")
else: discard else: discard
proc semYield(c: PContext, n: PNode): PNode = proc semYield(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 1) checkSonsLen(n, 1, c.config)
if c.p.owner == nil or c.p.owner.kind != skIterator: if c.p.owner == nil or c.p.owner.kind != skIterator:
localError(n.info, errYieldNotAllowedHere) localError(c.config, n.info, errYieldNotAllowedHere)
elif c.p.inTryStmt > 0 and c.p.owner.typ.callConv != ccInline: elif c.p.inTryStmt > 0 and c.p.owner.typ.callConv != ccInline:
localError(n.info, errYieldNotAllowedInTryStmt) localError(c.config, n.info, errYieldNotAllowedInTryStmt)
elif n.sons[0].kind != nkEmpty: elif n.sons[0].kind != nkEmpty:
n.sons[0] = semExprWithType(c, n.sons[0]) # check for type compatibility: n.sons[0] = semExprWithType(c, n.sons[0]) # check for type compatibility:
var iterType = c.p.owner.typ var iterType = c.p.owner.typ
@ -1559,9 +1559,9 @@ proc semYield(c: PContext, n: PNode): PNode =
semYieldVarResult(c, n, restype) semYieldVarResult(c, n, restype)
else: else:
localError(n.info, errCannotReturnExpr) localError(c.config, n.info, errCannotReturnExpr)
elif c.p.owner.typ.sons[0] != nil: elif c.p.owner.typ.sons[0] != nil:
localError(n.info, errGenerated, "yield statement must yield a value") localError(c.config, n.info, errGenerated, "yield statement must yield a value")
proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym = proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
if onlyCurrentScope: if onlyCurrentScope:
@ -1576,7 +1576,7 @@ proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
of nkDotExpr: of nkDotExpr:
result = nil result = nil
if onlyCurrentScope: return if onlyCurrentScope: return
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
var m = lookUpForDefined(c, n.sons[0], onlyCurrentScope) var m = lookUpForDefined(c, n.sons[0], onlyCurrentScope)
if m != nil and m.kind == skModule: if m != nil and m.kind == skModule:
let ident = considerQuotedIdent(n[1], n) let ident = considerQuotedIdent(n[1], n)
@ -1591,16 +1591,16 @@ proc lookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
of nkOpenSymChoice, nkClosedSymChoice: of nkOpenSymChoice, nkClosedSymChoice:
result = n.sons[0].sym result = n.sons[0].sym
else: else:
localError(n.info, errIdentifierExpected, renderTree(n)) localError(c.config, n.info, errIdentifierExpected, renderTree(n))
result = nil result = nil
proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode = proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
# we replace this node by a 'true' or 'false' node: # we replace this node by a 'true' or 'false' node:
result = newIntNode(nkIntLit, 0) result = newIntNode(nkIntLit, 0)
if not onlyCurrentScope and considerQuotedIdent(n[0], n).s == "defined": if not onlyCurrentScope and considerQuotedIdent(c.config, n[0], n).s == "defined":
if n.sons[1].kind != nkIdent: if n.sons[1].kind != nkIdent:
localError(n.info, "obsolete usage of 'defined', use 'declared' instead") localError(c.config, n.info, "obsolete usage of 'defined', use 'declared' instead")
elif condsyms.isDefined(n.sons[1].ident): elif condsyms.isDefined(n.sons[1].ident):
result.intVal = 1 result.intVal = 1
elif lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil: elif lookUpForDefined(c, n.sons[1], onlyCurrentScope) != nil:
@ -1618,12 +1618,12 @@ proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym =
return errorSym(c, n[0]) return errorSym(c, n[0])
if expandedSym.kind notin {skMacro, skTemplate}: if expandedSym.kind notin {skMacro, skTemplate}:
localError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s) localError(c.config, n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
return errorSym(c, n[0]) return errorSym(c, n[0])
result = expandedSym result = expandedSym
else: else:
localError(n.info, errXisNoMacroOrTemplate, n.renderTree) localError(c.config, n.info, errXisNoMacroOrTemplate, n.renderTree)
result = errorSym(c, n) result = errorSym(c, n)
proc expectString(c: PContext, n: PNode): string = proc expectString(c: PContext, n: PNode): string =
@ -1631,7 +1631,7 @@ proc expectString(c: PContext, n: PNode): string =
if n.kind in nkStrKinds: if n.kind in nkStrKinds:
return n.strVal return n.strVal
else: else:
localError(n.info, errStringLiteralExpected) localError(c.config, n.info, errStringLiteralExpected)
proc getMagicSym(magic: TMagic): PSym = proc getMagicSym(magic: TMagic): PSym =
result = newSym(skProc, getIdent($magic), systemModule, gCodegenLineInfo) result = newSym(skProc, getIdent($magic), systemModule, gCodegenLineInfo)
@ -1668,9 +1668,9 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
inc cands inc cands
symx = nextOverloadIter(o, c, headSymbol) symx = nextOverloadIter(o, c, headSymbol)
if cands == 0: if cands == 0:
localError(n.info, "expected a template that takes " & $(macroCall.len-1) & " arguments") localError(c.config, n.info, "expected a template that takes " & $(macroCall.len-1) & " arguments")
elif cands >= 2: elif cands >= 2:
localError(n.info, "ambiguous symbol in 'getAst' context: " & $macroCall) localError(c.config, n.info, "ambiguous symbol in 'getAst' context: " & $macroCall)
else: else:
let info = macroCall.sons[0].info let info = macroCall.sons[0].info
macroCall.sons[0] = newSymNode(cand, info) macroCall.sons[0] = newSymNode(cand, info)
@ -1680,7 +1680,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
# we just perform overloading resolution here: # we just perform overloading resolution here:
#n.sons[1] = semOverloadedCall(c, macroCall, macroCall, {skTemplate, skMacro}) #n.sons[1] = semOverloadedCall(c, macroCall, macroCall, {skTemplate, skMacro})
else: else:
localError(n.info, "getAst takes a call, but got " & n.renderTree) localError(c.config, n.info, "getAst takes a call, but got " & n.renderTree)
# Preserve the magic symbol in order to be handled in evals.nim # Preserve the magic symbol in order to be handled in evals.nim
internalAssert n.sons[0].sym.magic == mExpandToAst internalAssert n.sons[0].sym.magic == mExpandToAst
#n.typ = getSysSym("NimNode").typ # expandedSym.getReturnType #n.typ = getSysSym("NimNode").typ # expandedSym.getReturnType
@ -1707,7 +1707,7 @@ proc processQuotations(n: var PNode, op: string,
return return
if n.kind == nkPrefix: if n.kind == nkPrefix:
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
if n[0].kind == nkIdent: if n[0].kind == nkIdent:
var examinedOp = n[0].ident.s var examinedOp = n[0].ident.s
if examinedOp == op: if examinedOp == op:
@ -1734,7 +1734,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
# this will store the generated param names # this will store the generated param names
if quotedBlock.kind != nkStmtList: if quotedBlock.kind != nkStmtList:
localError(n.info, errXExpected, "block") localError(c.config, n.info, errXExpected, "block")
processQuotations(quotedBlock, op, quotes, ids) processQuotations(quotedBlock, op, quotes, ids)
@ -1829,7 +1829,7 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType;
info: TLineInfo): PSym = info: TLineInfo): PSym =
let sym = magicsys.getCompilerProc("nimCreateFlowVar") let sym = magicsys.getCompilerProc("nimCreateFlowVar")
if sym == nil: if sym == nil:
localError(info, errSystemNeeds, "nimCreateFlowVar") localError(c.config, info, errSystemNeeds, "nimCreateFlowVar")
var bindings: TIdTable var bindings: TIdTable
initIdTable(bindings) initIdTable(bindings)
bindings.idTablePut(sym.ast[genericParamsPos].sons[0].typ, t) bindings.idTablePut(sym.ast[genericParamsPos].sons[0].typ, t)
@ -1858,10 +1858,10 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result = n result = n
case s.magic # magics that need special treatment case s.magic # magics that need special treatment
of mAddr: of mAddr:
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
result = semAddr(c, n.sons[1], s.name.s == "unsafeAddr") result = semAddr(c, n.sons[1], s.name.s == "unsafeAddr")
of mTypeOf: of mTypeOf:
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
result = semTypeOf(c, n.sons[1]) result = semTypeOf(c, n.sons[1])
#of mArrGet: result = semArrGet(c, n, flags) #of mArrGet: result = semArrGet(c, n, flags)
#of mArrPut: result = semArrPut(c, n, flags) #of mArrPut: result = semArrPut(c, n, flags)
@ -1878,12 +1878,12 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
of mExpandToAst: result = semExpandToAst(c, n, s, flags) of mExpandToAst: result = semExpandToAst(c, n, s, flags)
of mQuoteAst: result = semQuoteAst(c, n) of mQuoteAst: result = semQuoteAst(c, n)
of mAstToStr: of mAstToStr:
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n) result = newStrNodeT(renderTree(n[1], {renderNoComments}), n)
result.typ = getSysType(tyString) result.typ = getSysType(tyString)
of mParallel: of mParallel:
if parallel notin c.features: if parallel notin c.features:
localError(n.info, "use the {.experimental.} pragma to enable 'parallel'") localError(c.config, n.info, "use the {.experimental.} pragma to enable 'parallel'")
result = setMs(n, s) result = setMs(n, s)
var x = n.lastSon var x = n.lastSon
if x.kind == nkDo: x = x.sons[bodyPos] if x.kind == nkDo: x = x.sons[bodyPos]
@ -1969,7 +1969,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
var it = n.sons[i] var it = n.sons[i]
case it.kind case it.kind
of nkElifBranch, nkElifExpr: of nkElifBranch, nkElifExpr:
checkSonsLen(it, 2) checkSonsLen(it, 2, c.config)
if whenNimvm: if whenNimvm:
if semCheck: if semCheck:
it.sons[1] = semExpr(c, it.sons[1]) it.sons[1] = semExpr(c, it.sons[1])
@ -1984,14 +1984,14 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
elif e.intVal != 0 and result == nil: elif e.intVal != 0 and result == nil:
setResult(it.sons[1]) setResult(it.sons[1])
of nkElse, nkElseExpr: of nkElse, nkElseExpr:
checkSonsLen(it, 1) checkSonsLen(it, 1, c.config)
if result == nil or whenNimvm: if result == nil or whenNimvm:
if semCheck: if semCheck:
it.sons[0] = semExpr(c, it.sons[0]) it.sons[0] = semExpr(c, it.sons[0])
typ = commonType(typ, it.sons[0].typ) typ = commonType(typ, it.sons[0].typ)
if result == nil: if result == nil:
result = it.sons[0] result = it.sons[0]
else: illFormedAst(n) else: illFormedAst(n, c.config)
if result == nil: if result == nil:
result = newNodeI(nkEmpty, n.info) result = newNodeI(nkEmpty, n.info)
if whenNimvm: result.typ = typ if whenNimvm: result.typ = typ
@ -2010,7 +2010,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
var typ: PType = nil var typ: PType = nil
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
if isRange(n.sons[i]): if isRange(n.sons[i]):
checkSonsLen(n.sons[i], 3) checkSonsLen(n.sons[i], 3, c.config)
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1]) n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1])
n.sons[i].sons[2] = semExprWithType(c, n.sons[i].sons[2]) n.sons[i].sons[2] = semExprWithType(c, n.sons[i].sons[2])
if typ == nil: if typ == nil:
@ -2027,7 +2027,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
if typ == nil: if typ == nil:
typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink}) typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink})
if not isOrdinalType(typ): if not isOrdinalType(typ):
localError(n.info, errOrdinalTypeExpected) localError(c.config, n.info, errOrdinalTypeExpected)
typ = makeRangeType(c, 0, MaxSetElements-1, n.info) typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
elif lengthOrd(typ) > MaxSetElements: elif lengthOrd(typ) > MaxSetElements:
typ = makeRangeType(c, 0, MaxSetElements-1, n.info) typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
@ -2065,7 +2065,7 @@ proc semTableConstr(c: PContext, n: PNode): PNode =
lastKey = i+1 lastKey = i+1
if lastKey != n.len: illFormedAst(n) if lastKey != n.len: illFormedAst(n, c.config)
result = semExpr(c, result) result = semExpr(c, result)
type type
@ -2087,11 +2087,11 @@ proc checkPar(n: PNode): TParKind =
if result == paTupleFields: if result == paTupleFields:
if (n.sons[i].kind != nkExprColonExpr) or if (n.sons[i].kind != nkExprColonExpr) or
not (n.sons[i].sons[0].kind in {nkSym, nkIdent}): not (n.sons[i].sons[0].kind in {nkSym, nkIdent}):
localError(n.sons[i].info, errNamedExprExpected) localError(c.config, n.sons[i].info, errNamedExprExpected)
return paNone return paNone
else: else:
if n.sons[i].kind == nkExprColonExpr: if n.sons[i].kind == nkExprColonExpr:
localError(n.sons[i].info, errNamedExprNotAllowed) localError(c.config, n.sons[i].info, errNamedExprNotAllowed)
return paNone return paNone
proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
@ -2101,12 +2101,12 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
var ids = initIntSet() var ids = initIntSet()
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
if n[i].kind != nkExprColonExpr or n[i][0].kind notin {nkSym, nkIdent}: if n[i].kind != nkExprColonExpr or n[i][0].kind notin {nkSym, nkIdent}:
illFormedAst(n.sons[i]) illFormedAst(n.sons[i], c.config)
var id: PIdent var id: PIdent
if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident if n.sons[i].sons[0].kind == nkIdent: id = n.sons[i].sons[0].ident
else: id = n.sons[i].sons[0].sym.name else: id = n.sons[i].sons[0].sym.name
if containsOrIncl(ids, id.id): if containsOrIncl(ids, id.id):
localError(n.sons[i].info, errFieldInitTwice, id.s) localError(c.config, n.sons[i].info, errFieldInitTwice, id.s)
n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1], n.sons[i].sons[1] = semExprWithType(c, n.sons[i].sons[1],
flags*{efAllowDestructor}) flags*{efAllowDestructor})
var f = newSymS(skField, n.sons[i].sons[0], c) var f = newSymS(skField, n.sons[i].sons[0], c)
@ -2140,7 +2140,7 @@ include semobjconstr
proc semBlock(c: PContext, n: PNode): PNode = proc semBlock(c: PContext, n: PNode): PNode =
result = n result = n
inc(c.p.nestedBlockCounter) inc(c.p.nestedBlockCounter)
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
openScope(c) # BUGFIX: label is in the scope of block! openScope(c) # BUGFIX: label is in the scope of block!
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
var labl = newSymG(skLabel, n.sons[0], c) var labl = newSymG(skLabel, n.sons[0], c)
@ -2164,7 +2164,7 @@ proc semExport(c: PContext, n: PNode): PNode =
var o: TOverloadIter var o: TOverloadIter
var s = initOverloadIter(o, c, a) var s = initOverloadIter(o, c, a)
if s == nil: if s == nil:
localError(a.info, errGenerated, "cannot export: " & renderTree(a)) localError(c.config, a.info, errGenerated, "cannot export: " & renderTree(a))
elif s.kind == skModule: elif s.kind == skModule:
# forward everything from that module: # forward everything from that module:
strTableAdd(c.module.tab, s) strTableAdd(c.module.tab, s)
@ -2217,7 +2217,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
if result.kind == nkSym: if result.kind == nkSym:
markIndirect(c, result.sym) markIndirect(c, result.sym)
# if isGenericRoutine(result.sym): # if isGenericRoutine(result.sym):
# localError(n.info, errInstantiateXExplicitly, s.name.s) # localError(c.config, n.info, errInstantiateXExplicitly, s.name.s)
of nkSym: of nkSym:
# because of the changed symbol binding, this does not mean that we # because of the changed symbol binding, this does not mean that we
# don't have to check the symbol for semantics here again! # don't have to check the symbol for semantics here again!
@ -2277,7 +2277,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result.typ = makeTypeDesc(c, typ) result.typ = makeTypeDesc(c, typ)
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
# check if it is an expression macro: # check if it is an expression macro:
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1, c.config)
#when defined(nimsuggest): #when defined(nimsuggest):
# if gIdeCmd == ideCon and gTrackPos == n.info: suggestExprNoCheck(c, n) # if gIdeCmd == ideCon and gTrackPos == n.info: suggestExprNoCheck(c, n)
let mode = if nfDotField in n.flags: {} else: {checkUndeclared} let mode = if nfDotField in n.flags: {} else: {checkUndeclared}
@ -2333,7 +2333,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
else: else:
result = semExpr(c, result, flags) result = semExpr(c, result, flags)
of nkBracketExpr: of nkBracketExpr:
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1, c.config)
result = semArrayAccess(c, n, flags) result = semArrayAccess(c, n, flags)
of nkCurlyExpr: of nkCurlyExpr:
result = semExpr(c, buildOverloadedSubscripts(n, getIdent"{}"), flags) result = semExpr(c, buildOverloadedSubscripts(n, getIdent"{}"), flags)
@ -2372,24 +2372,24 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkDerefExpr: result = semDeref(c, n) of nkDerefExpr: result = semDeref(c, n)
of nkAddr: of nkAddr:
result = n result = n
checkSonsLen(n, 1) checkSonsLen(n, 1, c.config)
result = semAddr(c, n.sons[0]) result = semAddr(c, n.sons[0])
of nkHiddenAddr, nkHiddenDeref: of nkHiddenAddr, nkHiddenDeref:
checkSonsLen(n, 1) checkSonsLen(n, 1, c.config)
n.sons[0] = semExpr(c, n.sons[0], flags) n.sons[0] = semExpr(c, n.sons[0], flags)
of nkCast: result = semCast(c, n) of nkCast: result = semCast(c, n)
of nkIfExpr, nkIfStmt: result = semIf(c, n) of nkIfExpr, nkIfStmt: result = semIf(c, n)
of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkHiddenCallConv: of nkHiddenStdConv, nkHiddenSubConv, nkConv, nkHiddenCallConv:
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
considerGenSyms(c, n) considerGenSyms(c, n)
of nkStringToCString, nkCStringToString, nkObjDownConv, nkObjUpConv: of nkStringToCString, nkCStringToString, nkObjDownConv, nkObjUpConv:
checkSonsLen(n, 1) checkSonsLen(n, 1, c.config)
considerGenSyms(c, n) considerGenSyms(c, n)
of nkChckRangeF, nkChckRange64, nkChckRange: of nkChckRangeF, nkChckRange64, nkChckRange:
checkSonsLen(n, 3) checkSonsLen(n, 3, c.config)
considerGenSyms(c, n) considerGenSyms(c, n)
of nkCheckedFieldExpr: of nkCheckedFieldExpr:
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2, c.config)
considerGenSyms(c, n) considerGenSyms(c, n)
of nkTableConstr: of nkTableConstr:
result = semTableConstr(c, n) result = semTableConstr(c, n)
@ -2433,19 +2433,19 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# #
# works: # works:
if c.currentScope.depthLevel > 2 + c.compilesContextId: if c.currentScope.depthLevel > 2 + c.compilesContextId:
localError(n.info, errXOnlyAtModuleScope, "import") localError(c.config, n.info, errXOnlyAtModuleScope, "import")
result = evalImport(c, n) result = evalImport(c, n)
of nkImportExceptStmt: of nkImportExceptStmt:
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "import") if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope, "import")
result = evalImportExcept(c, n) result = evalImportExcept(c, n)
of nkFromStmt: of nkFromStmt:
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "from") if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope, "from")
result = evalFrom(c, n) result = evalFrom(c, n)
of nkIncludeStmt: of nkIncludeStmt:
#if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "include") #if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope, "include")
result = evalInclude(c, n) result = evalInclude(c, n)
of nkExportStmt, nkExportExceptStmt: of nkExportStmt, nkExportExceptStmt:
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "export") if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope, "export")
result = semExport(c, n) result = semExport(c, n)
of nkPragmaBlock: of nkPragmaBlock:
result = semPragmaBlock(c, n) result = semPragmaBlock(c, n)
@ -2454,14 +2454,14 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkDefer: of nkDefer:
n.sons[0] = semExpr(c, n.sons[0]) n.sons[0] = semExpr(c, n.sons[0])
if not n.sons[0].typ.isEmptyType and not implicitlyDiscardable(n.sons[0]): if not n.sons[0].typ.isEmptyType and not implicitlyDiscardable(n.sons[0]):
localError(n.info, errGenerated, "'defer' takes a 'void' expression") localError(c.config, n.info, errGenerated, "'defer' takes a 'void' expression")
#localError(n.info, errGenerated, "'defer' not allowed in this context") #localError(c.config, n.info, errGenerated, "'defer' not allowed in this context")
of nkGotoState, nkState: of nkGotoState, nkState:
if n.len != 1 and n.len != 2: illFormedAst(n) if n.len != 1 and n.len != 2: illFormedAst(n, c.config)
for i in 0 ..< n.len: for i in 0 ..< n.len:
n.sons[i] = semExpr(c, n.sons[i]) n.sons[i] = semExpr(c, n.sons[i])
of nkComesFrom: discard "ignore the comes from information for now" of nkComesFrom: discard "ignore the comes from information for now"
else: else:
localError(n.info, errInvalidExpressionX, localError(c.config, n.info, errInvalidExpressionX,
renderTree(n, {renderNoComments})) renderTree(n, {renderNoComments}))
if result != nil: incl(result.flags, nfSem) if result != nil: incl(result.flags, nfSem)

View file

@ -47,7 +47,7 @@ proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
break break
else: else:
if n.kind == nkContinueStmt: if n.kind == nkContinueStmt:
localError(n.info, errGenerated, localError(c.config, n.info, errGenerated,
"'continue' not supported in a 'fields' loop") "'continue' not supported in a 'fields' loop")
result = copyNode(n) result = copyNode(n)
newSons(result, sonsLen(n)) newSons(result, sonsLen(n))
@ -76,7 +76,7 @@ proc semForObjectFields(c: TFieldsCtx, typ, forLoop, father: PNode) =
let L = forLoop.len let L = forLoop.len
let call = forLoop.sons[L-2] let call = forLoop.sons[L-2]
if call.len > 2: if call.len > 2:
localError(forLoop.info, errGenerated, localError(c.config, forLoop.info, errGenerated,
"parallel 'fields' iterator does not work for 'case' objects") "parallel 'fields' iterator does not work for 'case' objects")
return return
# iterate over the selector: # iterate over the selector:
@ -107,7 +107,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
result = newNodeI(nkWhileStmt, n.info, 2) result = newNodeI(nkWhileStmt, n.info, 2)
var trueSymbol = strTableGet(magicsys.systemModule.tab, getIdent"true") var trueSymbol = strTableGet(magicsys.systemModule.tab, getIdent"true")
if trueSymbol == nil: if trueSymbol == nil:
localError(n.info, errSystemNeeds, "true") localError(c.config, n.info, errSystemNeeds, "true")
trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner(c), n.info) trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner(c), n.info)
trueSymbol.typ = getSysType(tyBool) trueSymbol.typ = getSysType(tyBool)
@ -118,13 +118,13 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
var length = sonsLen(n) var length = sonsLen(n)
var call = n.sons[length-2] var call = n.sons[length-2]
if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs): if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs):
localError(n.info, errWrongNumberOfVariables) localError(c.config, n.info, errWrongNumberOfVariables)
return result return result
const skippedTypesForFields = abstractVar - {tyTypeDesc} + tyUserTypeClasses const skippedTypesForFields = abstractVar - {tyTypeDesc} + tyUserTypeClasses
var tupleTypeA = skipTypes(call.sons[1].typ, skippedTypesForFields) var tupleTypeA = skipTypes(call.sons[1].typ, skippedTypesForFields)
if tupleTypeA.kind notin {tyTuple, tyObject}: if tupleTypeA.kind notin {tyTuple, tyObject}:
localError(n.info, errGenerated, "no object or tuple type") localError(c.config, n.info, errGenerated, "no object or tuple type")
return result return result
for i in 1..call.len-1: for i in 1..call.len-1:
var tupleTypeB = skipTypes(call.sons[i].typ, skippedTypesForFields) var tupleTypeB = skipTypes(call.sons[i].typ, skippedTypesForFields)

View file

@ -54,10 +54,13 @@ proc pushProcCon*(c: PContext; owner: PSym) =
rawPushProcCon(c, owner) rawPushProcCon(c, owner)
rawHandleSelf(c, owner) rawHandleSelf(c, owner)
const
errCannotInstantiateX = "cannot instantiate: '$1'"
iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym = iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym =
internalAssert n.kind == nkGenericParams internalAssert c.config, n.kind == nkGenericParams
for i, a in n.pairs: for i, a in n.pairs:
internalAssert a.kind == nkSym internalAssert c.config, a.kind == nkSym
var q = a.sym var q = a.sym
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic}+tyTypeClasses: if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic}+tyTypeClasses:
continue continue
@ -71,10 +74,10 @@ iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym
# later by semAsgn in return type inference scenario # later by semAsgn in return type inference scenario
t = q.typ t = q.typ
else: else:
localError(a.info, errCannotInstantiateX, s.name.s) localError(c.config, a.info, errCannotInstantiateX & s.name.s)
t = errorType(c) t = errorType(c)
elif t.kind == tyGenericParam: elif t.kind == tyGenericParam:
localError(a.info, errCannotInstantiateX, q.name.s) localError(c.config, a.info, errCannotInstantiateX & q.name.s)
t = errorType(c) t = errorType(c)
elif t.kind == tyGenericInvocation: elif t.kind == tyGenericInvocation:
#t = instGenericContainer(c, a, t) #t = instGenericContainer(c, a, t)
@ -145,7 +148,7 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) =
freshGenSyms(b, result, orig, symMap) freshGenSyms(b, result, orig, symMap)
b = semProcBody(c, b) b = semProcBody(c, b)
b = hloBody(c, b) b = hloBody(c, b)
n.sons[bodyPos] = transformBody(c.module, b, result) n.sons[bodyPos] = transformBody(c.graph, c.module, b, result)
#echo "code instantiated ", result.name.s #echo "code instantiated ", result.name.s
excl(result.flags, sfForward) excl(result.flags, sfForward)
dec c.inGenericInst dec c.inGenericInst
@ -174,7 +177,7 @@ proc sideEffectsCheck(c: PContext, s: PSym) =
proc instGenericContainer(c: PContext, info: TLineInfo, header: PType, proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
allowMetaTypes = false): PType = allowMetaTypes = false): PType =
internalAssert header.kind == tyGenericInvocation internalAssert c.config, header.kind == tyGenericInvocation
var var
typeMap: LayeredIdTable typeMap: LayeredIdTable
@ -199,7 +202,7 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
var param: PSym var param: PSym
template paramSym(kind): untyped = template paramSym(kind): untyped =
newSym(kind, genParam.sym.name, genericTyp.sym, genParam.sym.info) newSym(kind, genParam.sym.name, genericTyp.sym, genParam.sym.info)
if genParam.kind == tyStatic: if genParam.kind == tyStatic:
param = paramSym skConst param = paramSym skConst
@ -233,14 +236,12 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
# at this point semtypinst have to become part of sem, because it # at this point semtypinst have to become part of sem, because it
# will need to use openScope, addDecl, etc. # will need to use openScope, addDecl, etc.
#addDecl(c, prc) #addDecl(c, prc)
pushInfoContext(info) pushInfoContext(info)
var typeMap = initLayeredTypeMap(pt) var typeMap = initLayeredTypeMap(pt)
var cl = initTypeVars(c, addr(typeMap), info, nil) var cl = initTypeVars(c, addr(typeMap), info, nil)
var result = instCopyType(cl, prc.typ) var result = instCopyType(cl, prc.typ)
let originalParams = result.n let originalParams = result.n
result.n = originalParams.shallowCopy result.n = originalParams.shallowCopy
for i in 1 ..< result.len: for i in 1 ..< result.len:
# twrong_field_caching requires these 'resetIdTable' calls: # twrong_field_caching requires these 'resetIdTable' calls:
if i > 1: if i > 1:
@ -248,7 +249,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
resetIdTable(cl.localCache) resetIdTable(cl.localCache)
result.sons[i] = replaceTypeVarsT(cl, result.sons[i]) result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
propagateToOwner(result, result.sons[i]) propagateToOwner(result, result.sons[i])
internalAssert originalParams[i].kind == nkSym internalAssert c.config, originalParams[i].kind == nkSym
when true: when true:
let oldParam = originalParams[i].sym let oldParam = originalParams[i].sym
let param = copySym(oldParam) let param = copySym(oldParam)
@ -285,9 +286,9 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
## The `pt` parameter is a type-unsafe mapping table used to link generic ## The `pt` parameter is a type-unsafe mapping table used to link generic
## parameters to their concrete types within the generic instance. ## parameters to their concrete types within the generic instance.
# no need to instantiate generic templates/macros: # no need to instantiate generic templates/macros:
internalAssert fn.kind notin {skMacro, skTemplate} internalAssert c.config, fn.kind notin {skMacro, skTemplate}
# generates an instantiated proc # generates an instantiated proc
if c.instCounter > 1000: internalError(fn.ast.info, "nesting too deep") if c.instCounter > 1000: internalError(c.config, fn.ast.info, "nesting too deep")
inc(c.instCounter) inc(c.instCounter)
# careful! we copy the whole AST including the possibly nil body! # careful! we copy the whole AST including the possibly nil body!
var n = copyTree(fn.ast) var n = copyTree(fn.ast)
@ -306,7 +307,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
openScope(c) openScope(c)
let gp = n.sons[genericParamsPos] let gp = n.sons[genericParamsPos]
internalAssert gp.kind != nkEmpty internalAssert c.config, gp.kind != nkEmpty
n.sons[namePos] = newSymNode(result) n.sons[namePos] = newSymNode(result)
pushInfoContext(info) pushInfoContext(info)
var entry = TInstantiation.new var entry = TInstantiation.new

View file

@ -16,7 +16,7 @@ proc semAddr(c: PContext; n: PNode; isUnsafeAddr=false): PNode =
if x.kind == nkSym: if x.kind == nkSym:
x.sym.flags.incl(sfAddrTaken) x.sym.flags.incl(sfAddrTaken)
if isAssignable(c, x, isUnsafeAddr) notin {arLValue, arLocalLValue}: if isAssignable(c, x, isUnsafeAddr) notin {arLValue, arLocalLValue}:
localError(n.info, errExprHasNoAddress) localError(c.config, n.info, errExprHasNoAddress)
result.add x result.add x
result.typ = makePtrType(c, x.typ) result.typ = makePtrType(c, x.typ)
@ -43,7 +43,7 @@ proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
let x = copyTree(n) let x = copyTree(n)
x.sons[0] = newIdentNode(getIdent"[]", n.info) x.sons[0] = newIdentNode(getIdent"[]", n.info)
bracketNotFoundError(c, x) bracketNotFoundError(c, x)
#localError(n.info, "could not resolve: " & $n) #localError(c.config, n.info, "could not resolve: " & $n)
result = n result = n
proc semArrPut(c: PContext; n: PNode; flags: TExprFlags): PNode = proc semArrPut(c: PContext; n: PNode; flags: TExprFlags): PNode =
@ -70,7 +70,7 @@ proc expectIntLit(c: PContext, n: PNode): int =
let x = c.semConstExpr(c, n) let x = c.semConstExpr(c, n)
case x.kind case x.kind
of nkIntLit..nkInt64Lit: result = int(x.intVal) of nkIntLit..nkInt64Lit: result = int(x.intVal)
else: localError(n.info, errIntLiteralExpected) else: localError(c.config, n.info, errIntLiteralExpected)
proc semInstantiationInfo(c: PContext, n: PNode): PNode = proc semInstantiationInfo(c: PContext, n: PNode): PNode =
result = newNodeIT(nkTupleConstr, n.info, n.typ) result = newNodeIT(nkTupleConstr, n.info, n.typ)
@ -140,7 +140,7 @@ proc evalTypeTrait(traitCall: PNode, operand: PType, context: PSym): PNode =
of "genericHead": of "genericHead":
var res = uninstantiate(operand) var res = uninstantiate(operand)
if res == operand and res.kind notin tyMagicGenerics: if res == operand and res.kind notin tyMagicGenerics:
localError(traitCall.info, localError(c.config, traitCall.info,
"genericHead expects a generic type. The given type was " & "genericHead expects a generic type. The given type was " &
typeToString(operand)) typeToString(operand))
return newType(tyError, context).toNode(traitCall.info) return newType(tyError, context).toNode(traitCall.info)
@ -153,7 +153,7 @@ proc evalTypeTrait(traitCall: PNode, operand: PType, context: PSym): PNode =
hasDestructor(t) hasDestructor(t)
result = newIntNodeT(ord(not complexObj), traitCall) result = newIntNodeT(ord(not complexObj), traitCall)
else: else:
localError(traitCall.info, "unknown trait") localError(c.config, traitCall.info, "unknown trait")
result = emptyNode result = emptyNode
proc semTypeTraits(c: PContext, n: PNode): PNode = proc semTypeTraits(c: PContext, n: PNode): PNode =
@ -176,7 +176,7 @@ proc semOrd(c: PContext, n: PNode): PNode =
elif parType.kind == tySet: elif parType.kind == tySet:
result.typ = makeRangeType(c, firstOrd(parType), lastOrd(parType), n.info) result.typ = makeRangeType(c, firstOrd(parType), lastOrd(parType), n.info)
else: else:
localError(n.info, errOrdinalTypeExpected) localError(c.config, n.info, errOrdinalTypeExpected)
result.typ = errorType(c) result.typ = errorType(c)
proc semBindSym(c: PContext, n: PNode): PNode = proc semBindSym(c: PContext, n: PNode): PNode =
@ -185,13 +185,13 @@ proc semBindSym(c: PContext, n: PNode): PNode =
let sl = semConstExpr(c, n.sons[1]) let sl = semConstExpr(c, n.sons[1])
if sl.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}: if sl.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}:
localError(n.sons[1].info, errStringLiteralExpected) localError(c.config, n.sons[1].info, errStringLiteralExpected)
return errorNode(c, n) return errorNode(c, n)
let isMixin = semConstExpr(c, n.sons[2]) let isMixin = semConstExpr(c, n.sons[2])
if isMixin.kind != nkIntLit or isMixin.intVal < 0 or if isMixin.kind != nkIntLit or isMixin.intVal < 0 or
isMixin.intVal > high(TSymChoiceRule).int: isMixin.intVal > high(TSymChoiceRule).int:
localError(n.sons[2].info, errConstExprExpected) localError(c.config, n.sons[2].info, errConstExprExpected)
return errorNode(c, n) return errorNode(c, n)
let id = newIdentNode(getIdent(sl.strVal), n.info) let id = newIdentNode(getIdent(sl.strVal), n.info)
@ -221,9 +221,9 @@ proc semOf(c: PContext, n: PNode): PNode =
let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc}) let y = skipTypes(n.sons[2].typ, abstractPtrs-{tyTypeDesc})
if x.kind == tyTypeDesc or y.kind != tyTypeDesc: if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
localError(n.info, errXExpectsObjectTypes, "of") localError(c.config, n.info, errXExpectsObjectTypes, "of")
elif b.kind != tyObject or a.kind != tyObject: elif b.kind != tyObject or a.kind != tyObject:
localError(n.info, errXExpectsObjectTypes, "of") localError(c.config, n.info, errXExpectsObjectTypes, "of")
else: else:
let diff = inheritanceDiff(a, b) let diff = inheritanceDiff(a, b)
# | returns: 0 iff `a` == `b` # | returns: 0 iff `a` == `b`
@ -238,9 +238,9 @@ proc semOf(c: PContext, n: PNode): PNode =
result.typ = getSysType(tyBool) result.typ = getSysType(tyBool)
return result return result
elif diff == high(int): elif diff == high(int):
localError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a)) localError(c.config, n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
else: else:
localError(n.info, errXExpectsTwoArguments, "of") localError(c.config, n.info, errXExpectsTwoArguments, "of")
n.typ = getSysType(tyBool) n.typ = getSysType(tyBool)
result = n result = n
@ -277,11 +277,11 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
of mDotDot: of mDotDot:
result = n result = n
of mRoof: of mRoof:
localError(n.info, "builtin roof operator is not supported anymore") localError(c.config, n.info, "builtin roof operator is not supported anymore")
of mPlugin: of mPlugin:
let plugin = getPlugin(n[0].sym) let plugin = getPlugin(n[0].sym)
if plugin.isNil: if plugin.isNil:
localError(n.info, "cannot find plugin " & n[0].sym.name.s) localError(c.config, n.info, "cannot find plugin " & n[0].sym.name.s)
result = n result = n
else: else:
result = plugin(c, n) result = plugin(c, n)

View file

@ -41,9 +41,9 @@ proc mergeInitStatus(existing: var InitStatus, newStatus: InitStatus) =
proc invalidObjConstr(n: PNode) = proc invalidObjConstr(n: PNode) =
if n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.s[0] == ':': if n.kind == nkInfix and n[0].kind == nkIdent and n[0].ident.s[0] == ':':
localError(n.info, "incorrect object construction syntax; use a space after the colon") localError(c.config, n.info, "incorrect object construction syntax; use a space after the colon")
else: else:
localError(n.info, "incorrect object construction syntax") localError(c.config, n.info, "incorrect object construction syntax")
proc locateFieldInInitExpr(field: PSym, initExpr: PNode): PNode = proc locateFieldInInitExpr(field: PSym, initExpr: PNode): PNode =
# Returns the assignment nkExprColonExpr node or nil # Returns the assignment nkExprColonExpr node or nil
@ -63,7 +63,7 @@ proc semConstrField(c: PContext, flags: TExprFlags,
if assignment != nil: if assignment != nil:
if nfSem in assignment.flags: return assignment[1] if nfSem in assignment.flags: return assignment[1]
if not fieldVisible(c, field): if not fieldVisible(c, field):
localError(initExpr.info, localError(c.config, initExpr.info,
"the field '$1' is not accessible.", [field.name.s]) "the field '$1' is not accessible.", [field.name.s])
return return
@ -130,7 +130,7 @@ proc missingMandatoryFields(fieldsRecList, initExpr: PNode): string =
proc checkForMissingFields(recList, initExpr: PNode) = proc checkForMissingFields(recList, initExpr: PNode) =
let missing = missingMandatoryFields(recList, initExpr) let missing = missingMandatoryFields(recList, initExpr)
if missing != nil: if missing != nil:
localError(initExpr.info, "fields not initialized: $1.", [missing]) localError(c.config, initExpr.info, "fields not initialized: $1.", [missing])
proc semConstructFields(c: PContext, recNode: PNode, proc semConstructFields(c: PContext, recNode: PNode,
initExpr: PNode, flags: TExprFlags): InitStatus = initExpr: PNode, flags: TExprFlags): InitStatus =
@ -164,7 +164,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
if selectedBranch != -1: if selectedBranch != -1:
let prevFields = fieldsPresentInBranch(selectedBranch) let prevFields = fieldsPresentInBranch(selectedBranch)
let currentFields = fieldsPresentInBranch(i) let currentFields = fieldsPresentInBranch(i)
localError(initExpr.info, localError(c.config, initExpr.info,
"The fields ($1) and ($2) cannot be initialized together, " & "The fields ($1) and ($2) cannot be initialized together, " &
"because they are from conflicting branches in the case object.", "because they are from conflicting branches in the case object.",
[prevFields, currentFields]) [prevFields, currentFields])
@ -179,7 +179,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
discriminator.sym, initExpr) discriminator.sym, initExpr)
if discriminatorVal == nil: if discriminatorVal == nil:
let fields = fieldsPresentInBranch(selectedBranch) let fields = fieldsPresentInBranch(selectedBranch)
localError(initExpr.info, localError(c.config, initExpr.info,
"you must provide a compile-time value for the discriminator '$1' " & "you must provide a compile-time value for the discriminator '$1' " &
"in order to prove that it's safe to initialize $2.", "in order to prove that it's safe to initialize $2.",
[discriminator.sym.name.s, fields]) [discriminator.sym.name.s, fields])
@ -189,7 +189,7 @@ proc semConstructFields(c: PContext, recNode: PNode,
template wrongBranchError(i) = template wrongBranchError(i) =
let fields = fieldsPresentInBranch(i) let fields = fieldsPresentInBranch(i)
localError(initExpr.info, localError(c.config, initExpr.info,
"a case selecting discriminator '$1' with value '$2' " & "a case selecting discriminator '$1' with value '$2' " &
"appears in the object construction, but the field(s) $3 " & "appears in the object construction, but the field(s) $3 " &
"are in conflict with this value.", "are in conflict with this value.",
@ -263,13 +263,13 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
for child in n: result.add child for child in n: result.add child
if t == nil: if t == nil:
localError(n.info, errGenerated, "object constructor needs an object type") localError(c.config, n.info, errGenerated, "object constructor needs an object type")
return return
t = skipTypes(t, {tyGenericInst, tyAlias, tySink}) t = skipTypes(t, {tyGenericInst, tyAlias, tySink})
if t.kind == tyRef: t = skipTypes(t.sons[0], {tyGenericInst, tyAlias, tySink}) if t.kind == tyRef: t = skipTypes(t.sons[0], {tyGenericInst, tyAlias, tySink})
if t.kind != tyObject: if t.kind != tyObject:
localError(n.info, errGenerated, "object constructor needs an object type") localError(c.config, n.info, errGenerated, "object constructor needs an object type")
return return
# Check if the object is fully initialized by recursively testing each # Check if the object is fully initialized by recursively testing each
@ -304,9 +304,9 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
for j in 1 ..< i: for j in 1 ..< i:
let prevId = considerQuotedIdent(result[j][0]) let prevId = considerQuotedIdent(result[j][0])
if prevId.id == id.id: if prevId.id == id.id:
localError(field.info, errFieldInitTwice, id.s) localError(c.config, field.info, errFieldInitTwice, id.s)
return return
# 2) No such field exists in the constructed type # 2) No such field exists in the constructed type
localError(field.info, errUndeclaredFieldX, id.s) localError(c.config, field.info, errUndeclaredFieldX, id.s)
return return

View file

@ -14,22 +14,22 @@ var enforceVoidContext = PType(kind: tyStmt)
proc semDiscard(c: PContext, n: PNode): PNode = proc semDiscard(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 1) checkSonsLen(n, 1, c.config)
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
n.sons[0] = semExprWithType(c, n.sons[0]) n.sons[0] = semExprWithType(c, n.sons[0])
if isEmptyType(n.sons[0].typ) or n.sons[0].typ.kind == tyNone or n.sons[0].kind == nkTypeOfExpr: if isEmptyType(n.sons[0].typ) or n.sons[0].typ.kind == tyNone or n.sons[0].kind == nkTypeOfExpr:
localError(n.info, errInvalidDiscard) localError(c.config, n.info, errInvalidDiscard)
proc semBreakOrContinue(c: PContext, n: PNode): PNode = proc semBreakOrContinue(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 1) checkSonsLen(n, 1, c.config)
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
if n.kind != nkContinueStmt: if n.kind != nkContinueStmt:
var s: PSym var s: PSym
case n.sons[0].kind case n.sons[0].kind
of nkIdent: s = lookUp(c, n.sons[0]) of nkIdent: s = lookUp(c, n.sons[0])
of nkSym: s = n.sons[0].sym of nkSym: s = n.sons[0].sym
else: illFormedAst(n) else: illFormedAst(n, c.config)
s = getGenSym(c, s) s = getGenSym(c, s)
if s.kind == skLabel and s.owner.id == c.p.owner.id: if s.kind == skLabel and s.owner.id == c.p.owner.id:
var x = newSymNode(s) var x = newSymNode(s)
@ -39,22 +39,22 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
suggestSym(x.info, s, c.graph.usageSym) suggestSym(x.info, s, c.graph.usageSym)
styleCheckUse(x.info, s) styleCheckUse(x.info, s)
else: else:
localError(n.info, errInvalidControlFlowX, s.name.s) localError(c.config, n.info, errInvalidControlFlowX, s.name.s)
else: else:
localError(n.info, errGenerated, "'continue' cannot have a label") localError(c.config, n.info, errGenerated, "'continue' cannot have a label")
elif (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0): elif (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0):
localError(n.info, errInvalidControlFlowX, localError(c.config, n.info, errInvalidControlFlowX,
renderTree(n, {renderNoComments})) renderTree(n, {renderNoComments}))
proc semAsm(con: PContext, n: PNode): PNode = proc semAsm(con: PContext, n: PNode): PNode =
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
var marker = pragmaAsm(con, n.sons[0]) var marker = pragmaAsm(con, n.sons[0])
if marker == '\0': marker = '`' # default marker if marker == '\0': marker = '`' # default marker
result = semAsmOrEmit(con, n, marker) result = semAsmOrEmit(con, n, marker)
proc semWhile(c: PContext, n: PNode): PNode = proc semWhile(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
openScope(c) openScope(c)
n.sons[0] = forceBool(c, semExprWithType(c, n.sons[0])) n.sons[0] = forceBool(c, semExprWithType(c, n.sons[0]))
inc(c.p.nestedLoopCounter) inc(c.p.nestedLoopCounter)
@ -98,7 +98,7 @@ proc implicitlyDiscardable(n: PNode): bool =
proc fixNilType(n: PNode) = proc fixNilType(n: PNode) =
if isAtom(n): if isAtom(n):
if n.kind != nkNilLit and n.typ != nil: if n.kind != nkNilLit and n.typ != nil:
localError(n.info, errDiscardValueX, n.typ.typeToString) localError(c.config, n.info, errDiscardValueX, n.typ.typeToString)
elif n.kind in {nkStmtList, nkStmtListExpr}: elif n.kind in {nkStmtList, nkStmtListExpr}:
n.kind = nkStmtList n.kind = nkStmtList
for it in n: fixNilType(it) for it in n: fixNilType(it)
@ -123,7 +123,7 @@ proc discardCheck(c: PContext, result: PNode) =
s.add "; start of expression here: " & $result.info s.add "; start of expression here: " & $result.info
if result.typ.kind == tyProc: if result.typ.kind == tyProc:
s.add "; for a function call use ()" s.add "; for a function call use ()"
localError(n.info, s) localError(c.config, n.info, s)
proc semIf(c: PContext, n: PNode): PNode = proc semIf(c: PContext, n: PNode): PNode =
result = n result = n
@ -142,7 +142,7 @@ proc semIf(c: PContext, n: PNode): PNode =
hasElse = true hasElse = true
it.sons[0] = semExprBranchScope(c, it.sons[0]) it.sons[0] = semExprBranchScope(c, it.sons[0])
typ = commonType(typ, it.sons[0]) typ = commonType(typ, it.sons[0])
else: illFormedAst(it) else: illFormedAst(it, c.config)
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse: if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse:
for it in n: discardCheck(c, it.lastSon) for it in n: discardCheck(c, it.lastSon)
result.kind = nkIfStmt result.kind = nkIfStmt
@ -158,7 +158,7 @@ proc semIf(c: PContext, n: PNode): PNode =
proc semCase(c: PContext, n: PNode): PNode = proc semCase(c: PContext, n: PNode): PNode =
result = n result = n
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2, c.config)
openScope(c) openScope(c)
n.sons[0] = semExprWithType(c, n.sons[0]) n.sons[0] = semExprWithType(c, n.sons[0])
var chckCovered = false var chckCovered = false
@ -172,7 +172,7 @@ proc semCase(c: PContext, n: PNode): PNode =
of tyFloat..tyFloat128, tyString, tyError: of tyFloat..tyFloat128, tyString, tyError:
discard discard
else: else:
localError(n.info, errSelectorMustBeOfCertainTypes) localError(c.config, n.info, errSelectorMustBeOfCertainTypes)
return return
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
var x = n.sons[i] var x = n.sons[i]
@ -181,14 +181,14 @@ proc semCase(c: PContext, n: PNode): PNode =
suggestEnum(c, x, caseTyp) suggestEnum(c, x, caseTyp)
case x.kind case x.kind
of nkOfBranch: of nkOfBranch:
checkMinSonsLen(x, 2) checkMinSonsLen(x, 2, c.config)
semCaseBranch(c, n, x, i, covered) semCaseBranch(c, n, x, i, covered)
var last = sonsLen(x)-1 var last = sonsLen(x)-1
x.sons[last] = semExprBranchScope(c, x.sons[last]) x.sons[last] = semExprBranchScope(c, x.sons[last])
typ = commonType(typ, x.sons[last]) typ = commonType(typ, x.sons[last])
of nkElifBranch: of nkElifBranch:
chckCovered = false chckCovered = false
checkSonsLen(x, 2) checkSonsLen(x, 2, c.config)
when newScopeForIf: openScope(c) when newScopeForIf: openScope(c)
x.sons[0] = forceBool(c, semExprWithType(c, x.sons[0])) x.sons[0] = forceBool(c, semExprWithType(c, x.sons[0]))
when not newScopeForIf: openScope(c) when not newScopeForIf: openScope(c)
@ -197,17 +197,17 @@ proc semCase(c: PContext, n: PNode): PNode =
closeScope(c) closeScope(c)
of nkElse: of nkElse:
chckCovered = false chckCovered = false
checkSonsLen(x, 1) checkSonsLen(x, 1, c.config)
x.sons[0] = semExprBranchScope(c, x.sons[0]) x.sons[0] = semExprBranchScope(c, x.sons[0])
typ = commonType(typ, x.sons[0]) typ = commonType(typ, x.sons[0])
hasElse = true hasElse = true
else: else:
illFormedAst(x) illFormedAst(x, c.config)
if chckCovered: if chckCovered:
if covered == toCover(n.sons[0].typ): if covered == toCover(n.sons[0].typ):
hasElse = true hasElse = true
else: else:
localError(n.info, errNotAllCasesCovered) localError(c.config, n.info, errNotAllCasesCovered)
closeScope(c) closeScope(c)
if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse: if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or not hasElse:
for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon) for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon)
@ -232,16 +232,16 @@ proc semTry(c: PContext, n: PNode): PNode =
if isImportedException(typ): if isImportedException(typ):
is_imported = true is_imported = true
elif not isException(typ): elif not isException(typ):
localError(typeNode.info, errExprCannotBeRaised) localError(c.config, typeNode.info, errExprCannotBeRaised)
if containsOrIncl(check, typ.id): if containsOrIncl(check, typ.id):
localError(typeNode.info, errExceptionAlreadyHandled) localError(c.config, typeNode.info, errExceptionAlreadyHandled)
typeNode = newNodeIT(nkType, typeNode.info, typ) typeNode = newNodeIT(nkType, typeNode.info, typ)
is_imported is_imported
result = n result = n
inc c.p.inTryStmt inc c.p.inTryStmt
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2, c.config)
var typ = commonTypeBegin var typ = commonTypeBegin
n[0] = semExprBranchScope(c, n[0]) n[0] = semExprBranchScope(c, n[0])
@ -250,7 +250,7 @@ proc semTry(c: PContext, n: PNode): PNode =
var last = sonsLen(n) - 1 var last = sonsLen(n) - 1
for i in countup(1, last): for i in countup(1, last):
let a = n.sons[i] let a = n.sons[i]
checkMinSonsLen(a, 1) checkMinSonsLen(a, 1, c.config)
openScope(c) openScope(c)
if a.kind == nkExceptBranch: if a.kind == nkExceptBranch:
@ -277,10 +277,10 @@ proc semTry(c: PContext, n: PNode): PNode =
else: is_native = true else: is_native = true
if is_native and is_imported: if is_native and is_imported:
localError(a[0].info, "Mix of imported and native exception types is not allowed in one except branch") localError(c.config, a[0].info, "Mix of imported and native exception types is not allowed in one except branch")
elif a.kind != nkFinally: elif a.kind != nkFinally:
illFormedAst(n) illFormedAst(n, c.config)
# last child of an nkExcept/nkFinally branch is a statement: # last child of an nkExcept/nkFinally branch is a statement:
a[^1] = semExprBranchScope(c, a[^1]) a[^1] = semExprBranchScope(c, a[^1])
@ -339,7 +339,7 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
result = semIdentWithPragma(c, kind, n, {}) result = semIdentWithPragma(c, kind, n, {})
if result.owner.kind == skModule: if result.owner.kind == skModule:
incl(result.flags, sfGlobal) incl(result.flags, sfGlobal)
suggestSym(n.info, result, c.graph.usageSym) suggestSym(c.config, n.info, result, c.graph.usageSym)
styleCheckDef(result) styleCheckDef(result)
proc checkNilable(v: PSym) = proc checkNilable(v: PSym) =
@ -369,13 +369,13 @@ proc isDiscardUnderscore(v: PSym): bool =
proc semUsing(c: PContext; n: PNode): PNode = proc semUsing(c: PContext; n: PNode): PNode =
result = ast.emptyNode result = ast.emptyNode
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "using") if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope, "using")
for i in countup(0, sonsLen(n)-1): for i in countup(0, sonsLen(n)-1):
var a = n.sons[i] var a = n.sons[i]
if gCmd == cmdIdeTools: suggestStmt(c, a) if gCmd == cmdIdeTools: suggestStmt(c, a)
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a) if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3, c.config)
var length = sonsLen(a) var length = sonsLen(a)
if a.sons[length-2].kind != nkEmpty: if a.sons[length-2].kind != nkEmpty:
let typ = semTypeNode(c, a.sons[length-2], nil) let typ = semTypeNode(c, a.sons[length-2], nil)
@ -384,10 +384,10 @@ proc semUsing(c: PContext; n: PNode): PNode =
v.typ = typ v.typ = typ
strTableIncl(c.signatures, v) strTableIncl(c.signatures, v)
else: else:
localError(a.info, "'using' section must have a type") localError(c.config, a.info, "'using' section must have a type")
var def: PNode var def: PNode
if a.sons[length-1].kind != nkEmpty: if a.sons[length-1].kind != nkEmpty:
localError(a.info, "'using' sections cannot contain assignments") localError(c.config, a.info, "'using' sections cannot contain assignments")
proc hasEmpty(typ: PType): bool = proc hasEmpty(typ: PType): bool =
if typ.kind in {tySequence, tyArray, tySet}: if typ.kind in {tySequence, tyArray, tySet}:
@ -416,7 +416,7 @@ proc makeDeref(n: PNode): PNode =
proc fillPartialObject(c: PContext; n: PNode; typ: PType) = proc fillPartialObject(c: PContext; n: PNode; typ: PType) =
if n.len == 2: if n.len == 2:
let x = semExprWithType(c, n[0]) let x = semExprWithType(c, n[0])
let y = considerQuotedIdent(n[1]) let y = considerQuotedIdent(c.config, n[1])
let obj = x.typ.skipTypes(abstractPtrs) let obj = x.typ.skipTypes(abstractPtrs)
if obj.kind == tyObject and tfPartial in obj.flags: if obj.kind == tyObject and tfPartial in obj.flags:
let field = newSym(skField, getIdent(y.s), obj.sym, n[1].info) let field = newSym(skField, getIdent(y.s), obj.sym, n[1].info)
@ -427,14 +427,14 @@ proc fillPartialObject(c: PContext; n: PNode; typ: PType) =
n.sons[1] = newSymNode(field) n.sons[1] = newSymNode(field)
n.typ = field.typ n.typ = field.typ
else: else:
localError(n.info, "implicit object field construction " & localError(c.config, n.info, "implicit object field construction " &
"requires a .partial object, but got " & typeToString(obj)) "requires a .partial object, but got " & typeToString(obj))
else: else:
localError(n.info, "nkDotNode requires 2 children") localError(c.config, n.info, "nkDotNode requires 2 children")
proc setVarType(v: PSym, typ: PType) = proc setVarType(v: PSym, typ: PType) =
if v.typ != nil and not sameTypeOrNil(v.typ, typ): if v.typ != nil and not sameTypeOrNil(v.typ, typ):
localError(v.info, "inconsistent typing for reintroduced symbol '" & localError(c.config, v.info, "inconsistent typing for reintroduced symbol '" &
v.name.s & "': previous type was: " & typeToString(v.typ) & v.name.s & "': previous type was: " & typeToString(v.typ) &
"; new type is: " & typeToString(typ)) "; new type is: " & typeToString(typ))
v.typ = typ v.typ = typ
@ -447,8 +447,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var a = n.sons[i] var a = n.sons[i]
if gCmd == cmdIdeTools: suggestStmt(c, a) if gCmd == cmdIdeTools: suggestStmt(c, a)
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a) if a.kind notin {nkIdentDefs, nkVarTuple, nkConstDef}: illFormedAst(a, c.config)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3, c.config)
var length = sonsLen(a) var length = sonsLen(a)
var typ: PType var typ: PType
if a.sons[length-2].kind != nkEmpty: if a.sons[length-2].kind != nkEmpty:
@ -460,7 +460,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
def = semExprWithType(c, a.sons[length-1], {efAllowDestructor}) def = semExprWithType(c, a.sons[length-1], {efAllowDestructor})
if def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro: if def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro:
# prevent the all too common 'var x = int' bug: # prevent the all too common 'var x = int' bug:
localError(def.info, "'typedesc' metatype is not valid here; typed '=' instead of ':'?") localError(c.config, def.info, "'typedesc' metatype is not valid here; typed '=' instead of ':'?")
def.typ = errorType(c) def.typ = errorType(c)
if typ != nil: if typ != nil:
if typ.isMetaType: if typ.isMetaType:
@ -476,12 +476,12 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
if typ.kind in tyUserTypeClasses and typ.isResolvedUserTypeClass: if typ.kind in tyUserTypeClasses and typ.isResolvedUserTypeClass:
typ = typ.lastSon typ = typ.lastSon
if hasEmpty(typ): if hasEmpty(typ):
localError(def.info, errCannotInferTypeOfTheLiteral, localError(c.config, def.info, errCannotInferTypeOfTheLiteral,
($typ.kind).substr(2).toLowerAscii) ($typ.kind).substr(2).toLowerAscii)
elif typ.kind == tyProc and tfUnresolved in typ.flags: elif typ.kind == tyProc and tfUnresolved in typ.flags:
localError(def.info, errProcHasNoConcreteType, def.renderTree) localError(c.config, def.info, errProcHasNoConcreteType, def.renderTree)
else: else:
if symkind == skLet: localError(a.info, errLetNeedsInit) if symkind == skLet: localError(c.config, a.info, errLetNeedsInit)
# this can only happen for errornous var statements: # this can only happen for errornous var statements:
if typ == nil: continue if typ == nil: continue
@ -490,9 +490,9 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var tup = skipTypes(typ, {tyGenericInst, tyAlias, tySink}) var tup = skipTypes(typ, {tyGenericInst, tyAlias, tySink})
if a.kind == nkVarTuple: if a.kind == nkVarTuple:
if tup.kind != tyTuple: if tup.kind != tyTuple:
localError(a.info, errXExpected, "tuple") localError(c.config, a.info, errXExpected, "tuple")
elif length-2 != sonsLen(tup): elif length-2 != sonsLen(tup):
localError(a.info, errWrongNumberOfVariables) localError(c.config, a.info, errWrongNumberOfVariables)
b = newNodeI(nkVarTuple, a.info) b = newNodeI(nkVarTuple, a.info)
newSons(b, length) newSons(b, length)
b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator
@ -527,10 +527,10 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
if def.kind != nkEmpty: if def.kind != nkEmpty:
# this is needed for the evaluation pass and for the guard checking: # this is needed for the evaluation pass and for the guard checking:
v.ast = def v.ast = def
if sfThread in v.flags: localError(def.info, errThreadvarCannotInit) if sfThread in v.flags: localError(c.config, def.info, errThreadvarCannotInit)
setVarType(v, typ) setVarType(v, typ)
b = newNodeI(nkIdentDefs, a.info) b = newNodeI(nkIdentDefs, a.info)
if importantComments(): if importantComments(c.config):
# keep documentation information: # keep documentation information:
b.comment = a.comment b.comment = a.comment
addSon(b, newSymNode(v)) addSon(b, newSymNode(v))
@ -554,15 +554,15 @@ proc semConst(c: PContext, n: PNode): PNode =
var a = n.sons[i] var a = n.sons[i]
if gCmd == cmdIdeTools: suggestStmt(c, a) if gCmd == cmdIdeTools: suggestStmt(c, a)
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if (a.kind != nkConstDef): illFormedAst(a) if a.kind != nkConstDef: illFormedAst(a, c.config)
checkSonsLen(a, 3) checkSonsLen(a, 3, c.config)
var v = semIdentDef(c, a.sons[0], skConst) var v = semIdentDef(c, a.sons[0], skConst)
var typ: PType = nil var typ: PType = nil
if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil) if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
var def = semConstExpr(c, a.sons[2]) var def = semConstExpr(c, a.sons[2])
if def == nil: if def == nil:
localError(a.sons[2].info, errConstExprExpected) localError(c.config, a.sons[2].info, errConstExprExpected)
continue continue
# check type compatibility between def.typ and typ: # check type compatibility between def.typ and typ:
if typ != nil: if typ != nil:
@ -570,10 +570,10 @@ proc semConst(c: PContext, n: PNode): PNode =
else: else:
typ = def.typ typ = def.typ
if typ == nil: if typ == nil:
localError(a.sons[2].info, errConstExprExpected) localError(c.config, a.sons[2].info, errConstExprExpected)
continue continue
if typeAllowed(typ, skConst) != nil and def.kind != nkNilLit: if typeAllowed(typ, skConst) != nil and def.kind != nkNilLit:
localError(a.info, "invalid type for const: " & typeToString(typ)) localError(c.config, a.info, "invalid type for const: " & typeToString(typ))
continue continue
setVarType(v, typ) setVarType(v, typ)
v.ast = def # no need to copy v.ast = def # no need to copy
@ -619,9 +619,9 @@ proc semForVars(c: PContext, n: PNode): PNode =
n.sons[0] = newSymNode(v) n.sons[0] = newSymNode(v)
if sfGenSym notin v.flags: addForVarDecl(c, v) if sfGenSym notin v.flags: addForVarDecl(c, v)
else: else:
localError(n.info, errWrongNumberOfVariables) localError(c.config, n.info, errWrongNumberOfVariables)
elif length-2 != sonsLen(iter): elif length-2 != sonsLen(iter):
localError(n.info, errWrongNumberOfVariables) localError(c.config, n.info, errWrongNumberOfVariables)
else: else:
for i in countup(0, length - 3): for i in countup(0, length - 3):
var v = symForVar(c, n.sons[i]) var v = symForVar(c, n.sons[i])
@ -671,7 +671,7 @@ proc handleForLoopMacro(c: PContext; n: PNode): PNode =
if match == nil: if match == nil:
match = symx match = symx
else: else:
localError(n.info, errGenerated, msgKindToString(errAmbiguousCallXYZ) % [ localError(c.config, n.info, errAmbiguousCallXYZ % [
getProcHeader(match), getProcHeader(symx), $iterExpr]) getProcHeader(match), getProcHeader(symx), $iterExpr])
symx = nextOverloadIter(o, c, headSymbol) symx = nextOverloadIter(o, c, headSymbol)
@ -685,7 +685,7 @@ proc handleForLoopMacro(c: PContext; n: PNode): PNode =
else: result = nil else: result = nil
proc semFor(c: PContext, n: PNode): PNode = proc semFor(c: PContext, n: PNode): PNode =
checkMinSonsLen(n, 3) checkMinSonsLen(n, 3, c.config)
var length = sonsLen(n) var length = sonsLen(n)
result = handleForLoopMacro(c, n) result = handleForLoopMacro(c, n)
if result != nil: return result if result != nil: return result
@ -715,7 +715,7 @@ proc semFor(c: PContext, n: PNode): PNode =
elif length == 4: elif length == 4:
n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2]) n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2])
else: else:
localError(n.sons[length-2].info, errIteratorExpected) localError(c.config, n.sons[length-2].info, errIteratorExpected)
result = semForVars(c, n) result = semForVars(c, n)
else: else:
result = semForVars(c, n) result = semForVars(c, n)
@ -726,31 +726,31 @@ proc semFor(c: PContext, n: PNode): PNode =
proc semRaise(c: PContext, n: PNode): PNode = proc semRaise(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 1) checkSonsLen(n, 1, c.config)
if n[0].kind != nkEmpty: if n[0].kind != nkEmpty:
n[0] = semExprWithType(c, n[0]) n[0] = semExprWithType(c, n[0])
let typ = n[0].typ let typ = n[0].typ
if not isImportedException(typ): if not isImportedException(typ):
if typ.kind != tyRef or typ.lastSon.kind != tyObject: if typ.kind != tyRef or typ.lastSon.kind != tyObject:
localError(n.info, errExprCannotBeRaised) localError(c.config, n.info, errExprCannotBeRaised)
if not isException(typ.lastSon): if not isException(typ.lastSon):
localError(n.info, "raised object of type $1 does not inherit from Exception", localError(c.config, n.info, "raised object of type $1 does not inherit from Exception",
[typeToString(typ)]) [typeToString(typ)])
proc addGenericParamListToScope(c: PContext, n: PNode) = proc addGenericParamListToScope(c: PContext, n: PNode) =
if n.kind != nkGenericParams: illFormedAst(n) if n.kind != nkGenericParams: illFormedAst(n, c.config)
for i in countup(0, sonsLen(n)-1): for i in countup(0, sonsLen(n)-1):
var a = n.sons[i] var a = n.sons[i]
if a.kind == nkSym: addDecl(c, a.sym) if a.kind == nkSym: addDecl(c, a.sym)
else: illFormedAst(a) else: illFormedAst(a, c.config)
proc typeSectionTypeName(n: PNode): PNode = proc typeSectionTypeName(n: PNode): PNode =
if n.kind == nkPragmaExpr: if n.kind == nkPragmaExpr:
if n.len == 0: illFormedAst(n) if n.len == 0: illFormedAst(n, c.config)
result = n.sons[0] result = n.sons[0]
else: else:
result = n result = n
if result.kind != nkSym: illFormedAst(n) if result.kind != nkSym: illFormedAst(n, c.config)
proc typeSectionLeftSidePass(c: PContext, n: PNode) = proc typeSectionLeftSidePass(c: PContext, n: PNode) =
@ -764,16 +764,16 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
suggestStmt(c, a) suggestStmt(c, a)
dec c.inTypeContext dec c.inTypeContext
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if a.kind != nkTypeDef: illFormedAst(a) if a.kind != nkTypeDef: illFormedAst(a, c.config)
checkSonsLen(a, 3) checkSonsLen(a, 3, c.config)
let name = a.sons[0] let name = a.sons[0]
var s: PSym var s: PSym
if name.kind == nkDotExpr and a[2].kind == nkObjectTy: if name.kind == nkDotExpr and a[2].kind == nkObjectTy:
let pkgName = considerQuotedIdent(name[0]) let pkgName = considerQuotedIdent(c.config, name[0])
let typName = considerQuotedIdent(name[1]) let typName = considerQuotedIdent(c.config, name[1])
let pkg = c.graph.packageSyms.strTableGet(pkgName) let pkg = c.graph.packageSyms.strTableGet(pkgName)
if pkg.isNil or pkg.kind != skPackage: if pkg.isNil or pkg.kind != skPackage:
localError(name.info, "unknown package name: " & pkgName.s) localError(c.config, name.info, "unknown package name: " & pkgName.s)
else: else:
let typsym = pkg.tab.strTableGet(typName) let typsym = pkg.tab.strTableGet(typName)
if typsym.isNil: if typsym.isNil:
@ -787,7 +787,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
s = typsym s = typsym
addInterfaceDecl(c, s) addInterfaceDecl(c, s)
else: else:
localError(name.info, typsym.name.s & " is not a type that can be forwarded") localError(c.config, name.info, typsym.name.s & " is not a type that can be forwarded")
s = typsym s = typsym
else: else:
s = semIdentDef(c, name, skType) s = semIdentDef(c, name, skType)
@ -799,7 +799,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
# check if the symbol already exists: # check if the symbol already exists:
let pkg = c.module.owner let pkg = c.module.owner
if not isTopLevel(c) or pkg.isNil: if not isTopLevel(c) or pkg.isNil:
localError(name.info, "only top level types in a package can be 'package'") localError(c.config, name.info, "only top level types in a package can be 'package'")
else: else:
let typsym = pkg.tab.strTableGet(s.name) let typsym = pkg.tab.strTableGet(s.name)
if typsym != nil: if typsym != nil:
@ -807,7 +807,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
typeCompleted(typsym) typeCompleted(typsym)
typsym.info = s.info typsym.info = s.info
else: else:
localError(name.info, "cannot complete type '" & s.name.s & "' twice; " & localError(c.config, name.info, "cannot complete type '" & s.name.s & "' twice; " &
"previous type completion was here: " & $typsym.info) "previous type completion was here: " & $typsym.info)
s = typsym s = typsym
# add it here, so that recursive types are possible: # add it here, so that recursive types are possible:
@ -822,7 +822,7 @@ proc checkCovariantParamsUsages(genericType: PType) =
var body = genericType[^1] var body = genericType[^1]
proc traverseSubTypes(t: PType): bool = proc traverseSubTypes(t: PType): bool =
template error(msg) = localError(genericType.sym.info, msg) template error(msg) = localError(c.config, genericType.sym.info, msg)
result = false result = false
@ -903,12 +903,12 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i] var a = n.sons[i]
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if (a.kind != nkTypeDef): illFormedAst(a) if a.kind != nkTypeDef: illFormedAst(a, c.config)
checkSonsLen(a, 3) checkSonsLen(a, 3, c.config)
let name = typeSectionTypeName(a.sons[0]) let name = typeSectionTypeName(a.sons[0])
var s = name.sym var s = name.sym
if s.magic == mNone and a.sons[2].kind == nkEmpty: if s.magic == mNone and a.sons[2].kind == nkEmpty:
localError(a.info, errImplOfXexpected, s.name.s) localError(c.config, a.info, errImplOfXexpected, s.name.s)
if s.magic != mNone: processMagicType(c, s) if s.magic != mNone: processMagicType(c, s)
if a.sons[1].kind != nkEmpty: if a.sons[1].kind != nkEmpty:
# We have a generic type declaration here. In generic types, # We have a generic type declaration here. In generic types,
@ -986,7 +986,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
proc checkForMetaFields(n: PNode) = proc checkForMetaFields(n: PNode) =
template checkMeta(t) = template checkMeta(t) =
if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags: if t != nil and t.isMetaType and tfGenericTypeParam notin t.flags:
localError(n.info, errTIsNotAConcreteType, t.typeToString) localError(c.config, n.info, errTIsNotAConcreteType, t.typeToString)
if n.isNil: return if n.isNil: return
case n.kind case n.kind
@ -1045,7 +1045,7 @@ proc semAllTypeSections(c: PContext; n: PNode): PNode =
var f = checkModuleName(n.sons[i]) var f = checkModuleName(n.sons[i])
if f != InvalidFileIDX: if f != InvalidFileIDX:
if containsOrIncl(c.includedFiles, f.int): if containsOrIncl(c.includedFiles, f.int):
localError(n.info, errRecursiveDependencyX, f.toFilename) localError(c.config, n.info, errRecursiveDependencyX, f.toFilename)
else: else:
let code = gIncludeFile(c.graph, c.module, f, c.cache) let code = gIncludeFile(c.graph, c.module, f, c.cache)
gatherStmts c, code, result gatherStmts c, code, result
@ -1101,12 +1101,12 @@ proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) =
s.typ = semProcTypeNode(c, n, genericParams, nil, s.kind) s.typ = semProcTypeNode(c, n, genericParams, nil, s.kind)
if s.kind notin {skMacro, skTemplate}: if s.kind notin {skMacro, skTemplate}:
if s.typ.sons[0] != nil and s.typ.sons[0].kind == tyStmt: if s.typ.sons[0] != nil and s.typ.sons[0].kind == tyStmt:
localError(n.info, errGenerated, "invalid return type: 'stmt'") localError(c.config, n.info, "invalid return type: 'stmt'")
proc addParams(c: PContext, n: PNode, kind: TSymKind) = proc addParams(c: PContext, n: PNode, kind: TSymKind) =
for i in countup(1, sonsLen(n)-1): for i in countup(1, sonsLen(n)-1):
if n.sons[i].kind == nkSym: addParamOrResult(c, n.sons[i].sym, kind) if n.sons[i].kind == nkSym: addParamOrResult(c, n.sons[i].sym, kind)
else: illFormedAst(n) else: illFormedAst(n, c.config)
proc semBorrow(c: PContext, n: PNode, s: PSym) = proc semBorrow(c: PContext, n: PNode, s: PSym) =
# search for the correct alias: # search for the correct alias:
@ -1115,7 +1115,7 @@ proc semBorrow(c: PContext, n: PNode, s: PSym) =
# store the alias: # store the alias:
n.sons[bodyPos] = newSymNode(b) n.sons[bodyPos] = newSymNode(b)
else: else:
localError(n.info, errNoSymbolToBorrowFromFound) localError(c.config, n.info, errNoSymbolToBorrowFromFound)
proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind) = proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind) =
if t != nil: if t != nil:
@ -1138,7 +1138,7 @@ proc lookupMacro(c: PContext, n: PNode): PSym =
result = n.sym result = n.sym
if result.kind notin {skMacro, skTemplate}: result = nil if result.kind notin {skMacro, skTemplate}: result = nil
else: else:
result = searchInScopes(c, considerQuotedIdent(n), {skMacro, skTemplate}) result = searchInScopes(c, considerQuotedIdent(c.config, n), {skMacro, skTemplate})
proc semProcAnnotation(c: PContext, prc: PNode; proc semProcAnnotation(c: PContext, prc: PNode;
validPragmas: TSpecialWords): PNode = validPragmas: TSpecialWords): PNode =
@ -1150,11 +1150,11 @@ proc semProcAnnotation(c: PContext, prc: PNode;
let m = lookupMacro(c, key) let m = lookupMacro(c, key)
if m == nil: if m == nil:
if key.kind == nkIdent and key.ident.id == ord(wDelegator): if key.kind == nkIdent and key.ident.id == ord(wDelegator):
if considerQuotedIdent(prc.sons[namePos]).s == "()": if considerQuotedIdent(c.config, prc.sons[namePos]).s == "()":
prc.sons[namePos] = newIdentNode(c.cache.idDelegator, prc.info) prc.sons[namePos] = newIdentNode(c.cache.idDelegator, prc.info)
prc.sons[pragmasPos] = copyExcept(n, i) prc.sons[pragmasPos] = copyExcept(n, i)
else: else:
localError(prc.info, errOnlyACallOpCanBeDelegator) localError(c.config, prc.info, errOnlyACallOpCanBeDelegator)
continue continue
elif sfCustomPragma in m.flags: elif sfCustomPragma in m.flags:
continue # semantic check for custom pragma happens later in semProcAux continue # semantic check for custom pragma happens later in semProcAux
@ -1199,7 +1199,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = semProcAnnotation(c, n, lambdaPragmas) result = semProcAnnotation(c, n, lambdaPragmas)
if result != nil: return result if result != nil: return result
result = n result = n
checkSonsLen(n, bodyPos + 1) checkSonsLen(n, bodyPos + 1, c.config)
var s: PSym var s: PSym
if n[namePos].kind != nkSym: if n[namePos].kind != nkSym:
s = newSym(skProc, c.cache.idAnon, getCurrOwner(c), n.info) s = newSym(skProc, c.cache.idAnon, getCurrOwner(c), n.info)
@ -1228,7 +1228,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
s.options = gOptions s.options = gOptions
if n.sons[bodyPos].kind != nkEmpty: if n.sons[bodyPos].kind != nkEmpty:
if sfImportc in s.flags: if sfImportc in s.flags:
localError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s) localError(c.config, n.sons[bodyPos].info, errImplOfXNotAllowed % s.name.s)
#if efDetermineType notin flags: #if efDetermineType notin flags:
# XXX not good enough; see tnamedparamanonproc.nim # XXX not good enough; see tnamedparamanonproc.nim
if gp.len == 0 or (gp.len == 1 and tfRetType in gp[0].typ.flags): if gp.len == 0 or (gp.len == 1 and tfRetType in gp[0].typ.flags):
@ -1239,10 +1239,10 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
n.sons[bodyPos] = transformBody(c.module, semBody, s) n.sons[bodyPos] = transformBody(c.module, semBody, s)
popProcCon(c) popProcCon(c)
elif efOperand notin flags: elif efOperand notin flags:
localError(n.info, errGenericLambdaNotAllowed) localError(c.config, n.info, errGenericLambdaNotAllowed)
sideEffectsCheck(c, s) sideEffectsCheck(c, s)
else: else:
localError(n.info, errImplOfXexpected, s.name.s) localError(c.config, n.info, errImplOfXexpected, s.name.s)
closeScope(c) # close scope for parameters closeScope(c) # close scope for parameters
popOwner(c) popOwner(c)
result.typ = s.typ result.typ = s.typ
@ -1267,7 +1267,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
for i in 1..<params.len: for i in 1..<params.len:
if params[i].typ.kind in {tyTypeDesc, tyGenericParam, if params[i].typ.kind in {tyTypeDesc, tyGenericParam,
tyFromExpr}+tyTypeClasses: tyFromExpr}+tyTypeClasses:
localError(params[i].info, "cannot infer type of parameter: " & localError(c.config, params[i].info, "cannot infer type of parameter: " &
params[i].sym.name.s) params[i].sym.name.s)
#params[i].sym.owner = s #params[i].sym.owner = s
openScope(c) openScope(c)
@ -1323,11 +1323,11 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
if obj.destructor.isNil: if obj.destructor.isNil:
obj.destructor = s obj.destructor = s
else: else:
localError(n.info, errGenerated, localError(c.config, n.info, errGenerated,
"cannot bind another '" & s.name.s & "' to: " & typeToString(obj)) "cannot bind another '" & s.name.s & "' to: " & typeToString(obj))
noError = true noError = true
if not noError and sfSystemModule notin s.owner.flags: if not noError and sfSystemModule notin s.owner.flags:
localError(n.info, errGenerated, localError(c.config, n.info, errGenerated,
"signature for '" & s.name.s & "' must be proc[T: object](x: var T)") "signature for '" & s.name.s & "' must be proc[T: object](x: var T)")
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
of "deepcopy", "=deepcopy": of "deepcopy", "=deepcopy":
@ -1344,13 +1344,13 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
if t.kind in {tyObject, tyDistinct, tyEnum}: if t.kind in {tyObject, tyDistinct, tyEnum}:
if t.deepCopy.isNil: t.deepCopy = s if t.deepCopy.isNil: t.deepCopy = s
else: else:
localError(n.info, errGenerated, localError(c.config, n.info, errGenerated,
"cannot bind another 'deepCopy' to: " & typeToString(t)) "cannot bind another 'deepCopy' to: " & typeToString(t))
else: else:
localError(n.info, errGenerated, localError(c.config, n.info, errGenerated,
"cannot bind 'deepCopy' to: " & typeToString(t)) "cannot bind 'deepCopy' to: " & typeToString(t))
else: else:
localError(n.info, errGenerated, localError(c.config, n.info, errGenerated,
"signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T") "signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T")
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
of "=", "=sink": of "=", "=sink":
@ -1375,15 +1375,15 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
if opr[].isNil: if opr[].isNil:
opr[] = s opr[] = s
else: else:
localError(n.info, errGenerated, localError(c.config, n.info, errGenerated,
"cannot bind another '" & s.name.s & "' to: " & typeToString(obj)) "cannot bind another '" & s.name.s & "' to: " & typeToString(obj))
return return
if sfSystemModule notin s.owner.flags: if sfSystemModule notin s.owner.flags:
localError(n.info, errGenerated, localError(c.config, n.info, errGenerated,
"signature for '" & s.name.s & "' must be proc[T: object](x: var T; y: T)") "signature for '" & s.name.s & "' must be proc[T: object](x: var T; y: T)")
else: else:
if sfOverriden in s.flags: if sfOverriden in s.flags:
localError(n.info, errGenerated, localError(c.config, n.info, errGenerated,
"'destroy' or 'deepCopy' expected for 'override'") "'destroy' or 'deepCopy' expected for 'override'")
proc cursorInProcAux(n: PNode): bool = proc cursorInProcAux(n: PNode): bool =
@ -1434,7 +1434,7 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
if hasObjParam(s): if hasObjParam(s):
methodDef(c.graph, s, fromCache=false) methodDef(c.graph, s, fromCache=false)
else: else:
localError(n.info, errXNeedsParamObjectType, "method") localError(c.config, n.info, errXNeedsParamObjectType, "method")
proc semProcAux(c: PContext, n: PNode, kind: TSymKind, proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
validPragmas: TSpecialWords, validPragmas: TSpecialWords,
@ -1442,7 +1442,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
result = semProcAnnotation(c, n, validPragmas) result = semProcAnnotation(c, n, validPragmas)
if result != nil: return result if result != nil: return result
result = n result = n
checkSonsLen(n, bodyPos + 1) checkSonsLen(n, bodyPos + 1, c.config)
var s: PSym var s: PSym
var typeIsDetermined = false var typeIsDetermined = false
var isAnon = false var isAnon = false
@ -1531,10 +1531,10 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
# XXX This needs more checks eventually, for example that external # XXX This needs more checks eventually, for example that external
# linking names do agree: # linking names do agree:
if proto.typ.callConv != s.typ.callConv or proto.typ.flags < s.typ.flags: if proto.typ.callConv != s.typ.callConv or proto.typ.flags < s.typ.flags:
localError(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProcX, localError(c.config, n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProcX %
"'" & proto.name.s & "' from " & $proto.info) ("'" & proto.name.s & "' from " & $proto.info))
if sfForward notin proto.flags: if sfForward notin proto.flags:
wrongRedefinition(n.info, proto.name.s) wrongRedefinition(c, n.info, proto.name.s)
excl(proto.flags, sfForward) excl(proto.flags, sfForward)
closeScope(c) # close scope with wrong parameter symbols closeScope(c) # close scope with wrong parameter symbols
openScope(c) # open scope for old (correct) parameter symbols openScope(c) # open scope for old (correct) parameter symbols
@ -1549,7 +1549,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
n.sons[pragmasPos] = proto.ast.sons[pragmasPos] n.sons[pragmasPos] = proto.ast.sons[pragmasPos]
if n.sons[namePos].kind != nkSym: internalError(n.info, "semProcAux") if n.sons[namePos].kind != nkSym: internalError(n.info, "semProcAux")
n.sons[namePos].sym = proto n.sons[namePos].sym = proto
if importantComments() and not isNil(proto.ast.comment): if importantComments(c.config) and not isNil(proto.ast.comment):
n.comment = proto.ast.comment n.comment = proto.ast.comment
proto.ast = n # needed for code generation proto.ast = n # needed for code generation
popOwner(c) popOwner(c)
@ -1558,21 +1558,21 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n) if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
if s.name.s[0] in {'.', '('}: if s.name.s[0] in {'.', '('}:
if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}: if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}:
localError(n.info, "the overloaded " & s.name.s & localError(c.config, n.info, "the overloaded " & s.name.s &
" operator has to be enabled with {.experimental: \"dotOperators\".}") " operator has to be enabled with {.experimental: \"dotOperators\".}")
elif s.name.s == "()" and callOperator notin c.features: elif s.name.s == "()" and callOperator notin c.features:
localError(n.info, "the overloaded " & s.name.s & localError(c.config, n.info, "the overloaded " & s.name.s &
" operator has to be enabled with {.experimental: \"callOperator\".}") " operator has to be enabled with {.experimental: \"callOperator\".}")
if n.sons[bodyPos].kind != nkEmpty: if n.sons[bodyPos].kind != nkEmpty:
# for DLL generation it is annoying to check for sfImportc! # for DLL generation it is annoying to check for sfImportc!
if sfBorrow in s.flags: if sfBorrow in s.flags:
localError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s) localError(c.config, n.sons[bodyPos].info, errImplOfXNotAllowed % s.name.s)
let usePseudoGenerics = kind in {skMacro, skTemplate} let usePseudoGenerics = kind in {skMacro, skTemplate}
# Macros and Templates can have generic parameters, but they are # Macros and Templates can have generic parameters, but they are
# only used for overload resolution (there is no instantiation of # only used for overload resolution (there is no instantiation of
# the symbol, so we must process the body now) # the symbol, so we must process the body now)
if not usePseudoGenerics and gIdeCmd in {ideSug, ideCon} and not if not usePseudoGenerics and c.config.ideCmd in {ideSug, ideCon} and not
cursorInProc(n.sons[bodyPos]): cursorInProc(n.sons[bodyPos]):
discard "speed up nimsuggest" discard "speed up nimsuggest"
if s.kind == skMethod: semMethodPrototype(c, s, n) if s.kind == skMethod: semMethodPrototype(c, s, n)
@ -1590,7 +1590,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
# unfortunately we cannot skip this step when in 'system.compiles' # unfortunately we cannot skip this step when in 'system.compiles'
# context as it may even be evaluated in 'system.compiles': # context as it may even be evaluated in 'system.compiles':
n.sons[bodyPos] = transformBody(c.module, semBody, s) n.sons[bodyPos] = transformBody(c.graph, c.module, semBody, s)
else: else:
if s.typ.sons[0] != nil and kind != skIterator: if s.typ.sons[0] != nil and kind != skIterator:
addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info)) addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
@ -1606,7 +1606,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
popProcCon(c) popProcCon(c)
else: else:
if s.kind == skMethod: semMethodPrototype(c, s, n) if s.kind == skMethod: semMethodPrototype(c, s, n)
if proto != nil: localError(n.info, errImplOfXexpected, proto.name.s) if proto != nil: localError(c.config, n.info, errImplOfXexpected, proto.name.s)
if {sfImportc, sfBorrow} * s.flags == {} and s.magic == mNone: if {sfImportc, sfBorrow} * s.flags == {} and s.magic == mNone:
incl(s.flags, sfForward) incl(s.flags, sfForward)
elif sfBorrow in s.flags: semBorrow(c, n, s) elif sfBorrow in s.flags: semBorrow(c, n, s)
@ -1621,7 +1621,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
result.typ = s.typ result.typ = s.typ
if isTopLevel(c) and s.kind != skIterator and if isTopLevel(c) and s.kind != skIterator and
s.typ.callConv == ccClosure: s.typ.callConv == ccClosure:
localError(s.info, "'.closure' calling convention for top level routines is invalid") localError(c.config, s.info, "'.closure' calling convention for top level routines is invalid")
proc determineType(c: PContext, s: PSym) = proc determineType(c: PContext, s: PSym) =
if s.typ != nil: return if s.typ != nil: return
@ -1644,9 +1644,9 @@ proc semIterator(c: PContext, n: PNode): PNode =
var s = result.sons[namePos].sym var s = result.sons[namePos].sym
var t = s.typ var t = s.typ
if t.sons[0] == nil and s.typ.callConv != ccClosure: if t.sons[0] == nil and s.typ.callConv != ccClosure:
localError(n.info, errXNeedsReturnType, "iterator") localError(c.config, n.info, "iterator needs a return type")
if isAnon and s.typ.callConv == ccInline: if isAnon and s.typ.callConv == ccInline:
localError(n.info, "inline iterators are not first-class / cannot be assigned to variables") localError(c.config, n.info, "inline iterators are not first-class / cannot be assigned to variables")
# iterators are either 'inline' or 'closure'; for backwards compatibility, # iterators are either 'inline' or 'closure'; for backwards compatibility,
# we require first class iterators to be marked with 'closure' explicitly # we require first class iterators to be marked with 'closure' explicitly
# -- at least for 0.9.2. # -- at least for 0.9.2.
@ -1655,7 +1655,7 @@ proc semIterator(c: PContext, n: PNode): PNode =
else: else:
s.typ.callConv = ccInline s.typ.callConv = ccInline
if n.sons[bodyPos].kind == nkEmpty and s.magic == mNone: if n.sons[bodyPos].kind == nkEmpty and s.magic == mNone:
localError(n.info, errImplOfXexpected, s.name.s) localError(c.config, n.info, errImplOfXexpected, s.name.s)
proc semProc(c: PContext, n: PNode): PNode = proc semProc(c: PContext, n: PNode): PNode =
result = semProcAux(c, n, skProc, procPragmas) result = semProcAux(c, n, skProc, procPragmas)
@ -1664,7 +1664,7 @@ proc semFunc(c: PContext, n: PNode): PNode =
result = semProcAux(c, n, skFunc, procPragmas) result = semProcAux(c, n, skFunc, procPragmas)
proc semMethod(c: PContext, n: PNode): PNode = proc semMethod(c: PContext, n: PNode): PNode =
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "method") if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope, "method")
result = semProcAux(c, n, skMethod, methodPragmas) result = semProcAux(c, n, skMethod, methodPragmas)
# macros can transform converters to nothing: # macros can transform converters to nothing:
if namePos >= result.safeLen: return result if namePos >= result.safeLen: return result
@ -1685,8 +1685,8 @@ proc semMethod(c: PContext, n: PNode): PNode =
else: disp.ast[resultPos].sym.typ = ret else: disp.ast[resultPos].sym.typ = ret
proc semConverterDef(c: PContext, n: PNode): PNode = proc semConverterDef(c: PContext, n: PNode): PNode =
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "converter") if not isTopLevel(c): localError(c.config, n.info, errXOnlyAtModuleScope, "converter")
checkSonsLen(n, bodyPos + 1) checkSonsLen(n, bodyPos + 1, c.config)
result = semProcAux(c, n, skConverter, converterPragmas) result = semProcAux(c, n, skConverter, converterPragmas)
# macros can transform converters to nothing: # macros can transform converters to nothing:
if namePos >= result.safeLen: return result if namePos >= result.safeLen: return result
@ -1696,12 +1696,12 @@ proc semConverterDef(c: PContext, n: PNode): PNode =
if result.kind != nkConverterDef: return if result.kind != nkConverterDef: return
var s = result.sons[namePos].sym var s = result.sons[namePos].sym
var t = s.typ var t = s.typ
if t.sons[0] == nil: localError(n.info, errXNeedsReturnType, "converter") if t.sons[0] == nil: localError(c.config, n.info, errXNeedsReturnType, "converter")
if sonsLen(t) != 2: localError(n.info, errXRequiresOneArgument, "converter") if sonsLen(t) != 2: localError(c.config, n.info, errXRequiresOneArgument, "converter")
addConverter(c, s) addConverter(c, s)
proc semMacroDef(c: PContext, n: PNode): PNode = proc semMacroDef(c: PContext, n: PNode): PNode =
checkSonsLen(n, bodyPos + 1) checkSonsLen(n, bodyPos + 1, c.config)
result = semProcAux(c, n, skMacro, macroPragmas) result = semProcAux(c, n, skMacro, macroPragmas)
# macros can transform macros to nothing: # macros can transform macros to nothing:
if namePos >= result.safeLen: return result if namePos >= result.safeLen: return result
@ -1716,18 +1716,18 @@ proc semMacroDef(c: PContext, n: PNode): PNode =
let param = t.n.sons[i].sym let param = t.n.sons[i].sym
if param.typ.kind != tyExpr: allUntyped = false if param.typ.kind != tyExpr: allUntyped = false
if allUntyped: incl(s.flags, sfAllUntyped) if allUntyped: incl(s.flags, sfAllUntyped)
if t.sons[0] == nil: localError(n.info, errXNeedsReturnType, "macro") if t.sons[0] == nil: localError(c.config, n.info, "macro needs a return type")
if n.sons[bodyPos].kind == nkEmpty: if n.sons[bodyPos].kind == nkEmpty:
localError(n.info, errImplOfXexpected, s.name.s) localError(c.config, n.info, errImplOfXexpected, s.name.s)
proc evalInclude(c: PContext, n: PNode): PNode = proc evalInclude(c: PContext, n: PNode): PNode =
result = newNodeI(nkStmtList, n.info) result = newNodeI(nkStmtList, n.info)
addSon(result, n) addSon(result, n)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var f = checkModuleName(n.sons[i]) var f = checkModuleName(c.config, n.sons[i])
if f != InvalidFileIDX: if f != InvalidFileIDX:
if containsOrIncl(c.includedFiles, f.int): if containsOrIncl(c.includedFiles, f.int):
localError(n.info, errRecursiveDependencyX, f.toFilename) localError(c.config, n.info, errRecursiveDependencyX % f.toFilename)
else: else:
addSon(result, semStmt(c, gIncludeFile(c.graph, c.module, f, c.cache))) addSon(result, semStmt(c, gIncludeFile(c.graph, c.module, f, c.cache)))
excl(c.includedFiles, f.int) excl(c.includedFiles, f.int)
@ -1777,7 +1777,7 @@ proc inferConceptStaticParam(c: PContext, inferred, n: PNode) =
var typ = inferred.typ var typ = inferred.typ
let res = semConstExpr(c, n) let res = semConstExpr(c, n)
if not sameType(res.typ, typ.base): if not sameType(res.typ, typ.base):
localError(n.info, localError(c.config, n.info,
"cannot infer the concept parameter '%s', due to a type mismatch. " & "cannot infer the concept parameter '%s', due to a type mismatch. " &
"attempt to equate '%s' and '%s'.", "attempt to equate '%s' and '%s'.",
[inferred.renderTree, $res.typ, $typ.base]) [inferred.renderTree, $res.typ, $typ.base])
@ -1818,7 +1818,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
let verdict = semConstExpr(c, n[i]) let verdict = semConstExpr(c, n[i])
if verdict.intVal == 0: if verdict.intVal == 0:
localError(result.info, "concept predicate failed") localError(c.config, result.info, "concept predicate failed")
of tyUnknown: continue of tyUnknown: continue
else: discard else: discard
if n.sons[i].typ == enforceVoidContext: #or usesResult(n.sons[i]): if n.sons[i].typ == enforceVoidContext: #or usesResult(n.sons[i]):
@ -1839,7 +1839,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
case n.sons[j].kind case n.sons[j].kind
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty, nkBlockExpr, of nkPragma, nkCommentStmt, nkNilLit, nkEmpty, nkBlockExpr,
nkBlockStmt, nkState: discard nkBlockStmt, nkState: discard
else: localError(n.sons[j].info, errStmtInvalidAfterReturn) else: localError(c.config, n.sons[j].info, errStmtInvalidAfterReturn)
else: discard else: discard
if result.len == 1 and if result.len == 1 and

View file

@ -26,6 +26,9 @@ discard """
a way to achieve lexical scoping at compile time. a way to achieve lexical scoping at compile time.
""" """
const
errImplOfXNotAllowed = "implementation of '$1' is not allowed"
type type
TSymBinding = enum TSymBinding = enum
spNone, spGenSym, spInject spNone, spGenSym, spInject
@ -60,7 +63,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
# (s.kind notin routineKinds or s.magic != mNone): # (s.kind notin routineKinds or s.magic != mNone):
# for instance 'nextTry' is both in tables.nim and astalgo.nim ... # for instance 'nextTry' is both in tables.nim and astalgo.nim ...
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
markUsed(n.info, s, c.graph.usageSym) markUsed(c.config, n.info, s, c.graph.usageSym)
else: else:
# semantic checking requires a type; ``fitNode`` deals with it # semantic checking requires a type; ``fitNode`` deals with it
# appropriately # appropriately
@ -91,20 +94,20 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var IntSet): PNode =
else: else:
for x in items(sc): toBind.incl(x.sym.id) for x in items(sc): toBind.incl(x.sym.id)
else: else:
illFormedAst(a) illFormedAst(a, c.config)
result = newNodeI(nkEmpty, n.info) result = newNodeI(nkEmpty, n.info)
proc semMixinStmt(c: PContext, n: PNode, toMixin: var IntSet): PNode = proc semMixinStmt(c: PContext, n: PNode, toMixin: var IntSet): PNode =
for i in 0 ..< n.len: for i in 0 ..< n.len:
toMixin.incl(considerQuotedIdent(n.sons[i]).id) toMixin.incl(considerQuotedIdent(c.config, n.sons[i]).id)
result = newNodeI(nkEmpty, n.info) result = newNodeI(nkEmpty, n.info)
proc replaceIdentBySym(n: var PNode, s: PNode) = proc replaceIdentBySym(c: PContext; n: var PNode, s: PNode) =
case n.kind case n.kind
of nkPostfix: replaceIdentBySym(n.sons[1], s) of nkPostfix: replaceIdentBySym(c, n.sons[1], s)
of nkPragmaExpr: replaceIdentBySym(n.sons[0], s) of nkPragmaExpr: replaceIdentBySym(c, n.sons[0], s)
of nkIdent, nkAccQuoted, nkSym: n = s of nkIdent, nkAccQuoted, nkSym: n = s
else: illFormedAst(n) else: illFormedAst(n, c.config)
type type
TemplCtx = object TemplCtx = object
@ -129,7 +132,7 @@ proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
of nkAccQuoted, nkSym: result = n of nkAccQuoted, nkSym: result = n
else: else:
illFormedAst(n) illFormedAst(n, c.c.config)
result = n result = n
proc isTemplParam(c: TemplCtx, n: PNode): bool {.inline.} = proc isTemplParam(c: TemplCtx, n: PNode): bool {.inline.} =
@ -163,7 +166,7 @@ proc onlyReplaceParams(c: var TemplCtx, n: PNode): PNode =
result.sons[i] = onlyReplaceParams(c, n.sons[i]) result.sons[i] = onlyReplaceParams(c, n.sons[i])
proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym = proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
result = newSym(kind, considerQuotedIdent(n), c.owner, n.info) result = newSym(kind, considerQuotedIdent(c.c.config, n), c.owner, n.info)
incl(result.flags, sfGenSym) incl(result.flags, sfGenSym)
incl(result.flags, sfShadowed) incl(result.flags, sfShadowed)
@ -184,12 +187,12 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
n = onlyReplaceParams(c, n) n = onlyReplaceParams(c, n)
return return
else: else:
illFormedAst(x) illFormedAst(x, c.c.config)
let ident = getIdentNode(c, x) let ident = getIdentNode(c, x)
if not isTemplParam(c, ident): if not isTemplParam(c, ident):
c.toInject.incl(x.ident.id) c.toInject.incl(x.ident.id)
else: else:
replaceIdentBySym(n, ident) replaceIdentBySym(c.c, n, ident)
else: else:
let ident = getIdentNode(c, n) let ident = getIdentNode(c, n)
if not isTemplParam(c, ident): if not isTemplParam(c, ident):
@ -203,17 +206,17 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
# #
# We need to ensure that both 'a' produce the same gensym'ed symbol. # We need to ensure that both 'a' produce the same gensym'ed symbol.
# So we need only check the *current* scope. # So we need only check the *current* scope.
let s = localSearchInScope(c.c, considerQuotedIdent ident) let s = localSearchInScope(c.c, considerQuotedIdent(c.c.config, ident))
if s != nil and s.owner == c.owner and sfGenSym in s.flags: if s != nil and s.owner == c.owner and sfGenSym in s.flags:
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
replaceIdentBySym(n, newSymNode(s, n.info)) replaceIdentBySym(c.c, n, newSymNode(s, n.info))
else: else:
let local = newGenSym(k, ident, c) let local = newGenSym(k, ident, c)
addPrelimDecl(c.c, local) addPrelimDecl(c.c, local)
styleCheckDef(n.info, local) styleCheckDef(n.info, local)
replaceIdentBySym(n, newSymNode(local, n.info)) replaceIdentBySym(c.c, n, newSymNode(local, n.info))
else: else:
replaceIdentBySym(n, ident) replaceIdentBySym(c.c, n, ident)
proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode = proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode =
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
@ -249,7 +252,7 @@ proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode =
proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode = proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
result = n result = n
checkSonsLen(n, bodyPos + 1) checkSonsLen(n, bodyPos + 1, c.c.config)
# routines default to 'inject': # routines default to 'inject':
if n.kind notin nkLambdaKinds and symBinding(n.sons[pragmasPos]) == spGenSym: if n.kind notin nkLambdaKinds and symBinding(n.sons[pragmasPos]) == spGenSym:
let ident = getIdentNode(c, n.sons[namePos]) let ident = getIdentNode(c, n.sons[namePos])
@ -281,8 +284,8 @@ proc semTemplSomeDecl(c: var TemplCtx, n: PNode, symKind: TSymKind; start=0) =
for i in countup(start, sonsLen(n) - 1): for i in countup(start, sonsLen(n) - 1):
var a = n.sons[i] var a = n.sons[i]
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a) if (a.kind != nkIdentDefs) and (a.kind != nkVarTuple): illFormedAst(a, c.c.config)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3, c.c.config)
var L = sonsLen(a) var L = sonsLen(a)
when defined(nimsuggest): when defined(nimsuggest):
inc c.c.inTypeContext inc c.c.inTypeContext
@ -354,7 +357,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
n.sons[0] = semTemplBody(c, n.sons[0]) n.sons[0] = semTemplBody(c, n.sons[0])
for i in countup(1, sonsLen(n)-1): for i in countup(1, sonsLen(n)-1):
var a = n.sons[i] var a = n.sons[i]
checkMinSonsLen(a, 1) checkMinSonsLen(a, 1, c.c.config)
var L = sonsLen(a) var L = sonsLen(a)
for j in countup(0, L-2): for j in countup(0, L-2):
a.sons[j] = semTemplBody(c, a.sons[j]) a.sons[j] = semTemplBody(c, a.sons[j])
@ -371,7 +374,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
closeScope(c) closeScope(c)
closeScope(c) closeScope(c)
of nkBlockStmt, nkBlockExpr, nkBlockType: of nkBlockStmt, nkBlockExpr, nkBlockType:
checkSonsLen(n, 2) checkSonsLen(n, 2, c.c.config)
openScope(c) openScope(c)
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
addLocalDecl(c, n.sons[0], skLabel) addLocalDecl(c, n.sons[0], skLabel)
@ -384,11 +387,11 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
n.sons[1] = semTemplBody(c, n.sons[1]) n.sons[1] = semTemplBody(c, n.sons[1])
closeScope(c) closeScope(c)
of nkTryStmt: of nkTryStmt:
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2, c.c.config)
n.sons[0] = semTemplBodyScope(c, n.sons[0]) n.sons[0] = semTemplBodyScope(c, n.sons[0])
for i in countup(1, sonsLen(n)-1): for i in countup(1, sonsLen(n)-1):
var a = n.sons[i] var a = n.sons[i]
checkMinSonsLen(a, 1) checkMinSonsLen(a, 1, c.c.config)
var L = sonsLen(a) var L = sonsLen(a)
openScope(c) openScope(c)
for j in countup(0, L-2): for j in countup(0, L-2):
@ -402,15 +405,15 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
of nkVarSection: semTemplSomeDecl(c, n, skVar) of nkVarSection: semTemplSomeDecl(c, n, skVar)
of nkLetSection: semTemplSomeDecl(c, n, skLet) of nkLetSection: semTemplSomeDecl(c, n, skLet)
of nkFormalParams: of nkFormalParams:
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1, c.c.config)
n.sons[0] = semTemplBody(c, n.sons[0]) n.sons[0] = semTemplBody(c, n.sons[0])
semTemplSomeDecl(c, n, skParam, 1) semTemplSomeDecl(c, n, skParam, 1)
of nkConstSection: of nkConstSection:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i] var a = n.sons[i]
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if (a.kind != nkConstDef): illFormedAst(a) if (a.kind != nkConstDef): illFormedAst(a, c.c.config)
checkSonsLen(a, 3) checkSonsLen(a, 3, c.c.config)
addLocalDecl(c, a.sons[0], skConst) addLocalDecl(c, a.sons[0], skConst)
a.sons[1] = semTemplBody(c, a.sons[1]) a.sons[1] = semTemplBody(c, a.sons[1])
a.sons[2] = semTemplBody(c, a.sons[2]) a.sons[2] = semTemplBody(c, a.sons[2])
@ -418,14 +421,14 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i] var a = n.sons[i]
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if (a.kind != nkTypeDef): illFormedAst(a) if (a.kind != nkTypeDef): illFormedAst(a, c.c.config)
checkSonsLen(a, 3) checkSonsLen(a, 3, c.c.config)
addLocalDecl(c, a.sons[0], skType) addLocalDecl(c, a.sons[0], skType)
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var a = n.sons[i] var a = n.sons[i]
if a.kind == nkCommentStmt: continue if a.kind == nkCommentStmt: continue
if (a.kind != nkTypeDef): illFormedAst(a) if (a.kind != nkTypeDef): illFormedAst(a, c.c.config)
checkSonsLen(a, 3) checkSonsLen(a, 3, c.c.config)
if a.sons[1].kind != nkEmpty: if a.sons[1].kind != nkEmpty:
openScope(c) openScope(c)
a.sons[1] = semTemplBody(c, a.sons[1]) a.sons[1] = semTemplBody(c, a.sons[1])
@ -468,7 +471,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
for i in 0 ..< n.len: result.add(n[i]) for i in 0 ..< n.len: result.add(n[i])
result = semTemplBodySons(c, result) result = semTemplBodySons(c, result)
of nkAsgn, nkFastAsgn: of nkAsgn, nkFastAsgn:
checkSonsLen(n, 2) checkSonsLen(n, 2, c.c.config)
let a = n.sons[0] let a = n.sons[0]
let b = n.sons[1] let b = n.sons[1]
@ -610,9 +613,9 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
result = n result = n
if sfCustomPragma in s.flags: if sfCustomPragma in s.flags:
if n.sons[bodyPos].kind != nkEmpty: if n.sons[bodyPos].kind != nkEmpty:
localError(n.sons[bodyPos].info, errImplOfXNotAllowed, s.name.s) localError(c.config, n.sons[bodyPos].info, errImplOfXNotAllowed % s.name.s)
elif n.sons[bodyPos].kind == nkEmpty: elif n.sons[bodyPos].kind == nkEmpty:
localError(n.info, errImplOfXexpected, s.name.s) localError(c.config, n.info, "implementation of '$1' expected" % s.name.s)
var proto = searchForProc(c, c.currentScope, s) var proto = searchForProc(c, c.currentScope, s)
if proto == nil: if proto == nil:
addInterfaceOverloadableSymAt(c, c.currentScope, s) addInterfaceOverloadableSymAt(c, c.currentScope, s)
@ -655,7 +658,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
if s != nil and s.owner == c.owner and s.kind == skParam: if s != nil and s.owner == c.owner and s.kind == skParam:
result = newParam(c, n, s) result = newParam(c, n, s)
else: else:
localError(n.info, errInvalidExpression) localError(c.c.config, n.info, "invalid expression")
result = n result = n
proc stupidStmtListExpr(n: PNode): bool = proc stupidStmtListExpr(n: PNode): bool =
@ -675,7 +678,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
# we support '(pattern){x}' to bind a subpattern to a parameter 'x'; # we support '(pattern){x}' to bind a subpattern to a parameter 'x';
# '(pattern){|x}' does the same but the matches will be gathered in 'x' # '(pattern){|x}' does the same but the matches will be gathered in 'x'
if n.len != 2: if n.len != 2:
localError(n.info, errInvalidExpression) localError(c.c.config, n.info, "invalid expression")
elif n.sons[1].kind == nkIdent: elif n.sons[1].kind == nkIdent:
n.sons[0] = semPatternBody(c, n.sons[0]) n.sons[0] = semPatternBody(c, n.sons[0])
n.sons[1] = expectParam(c, n.sons[1]) n.sons[1] = expectParam(c, n.sons[1])
@ -685,9 +688,9 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
n.sons[0] = semPatternBody(c, n.sons[0]) n.sons[0] = semPatternBody(c, n.sons[0])
n.sons[1].sons[1] = expectParam(c, n.sons[1].sons[1]) n.sons[1].sons[1] = expectParam(c, n.sons[1].sons[1])
else: else:
localError(n.info, errInvalidExpression) localError(c.c.config, n.info, "invalid expression")
else: else:
localError(n.info, errInvalidExpression) localError(c.c.config, n.info, "invalid expression")
of nkStmtList, nkStmtListExpr: of nkStmtList, nkStmtListExpr:
if stupidStmtListExpr(n): if stupidStmtListExpr(n):
result = semPatternBody(c, n.lastSon) result = semPatternBody(c, n.lastSon)
@ -759,5 +762,5 @@ proc semPattern(c: PContext, n: PNode): PNode =
if result.len == 1: if result.len == 1:
result = result.sons[0] result = result.sons[0]
elif result.len == 0: elif result.len == 0:
localError(n.info, errInvalidExpression) localError(c.config, n.info, "a pattern cannot be empty")
closeScope(c) closeScope(c)

View file

@ -10,6 +10,33 @@
# this module does the semantic checking of type declarations # this module does the semantic checking of type declarations
# included from sem.nim # included from sem.nim
const
errStringLiteralExpected = "string literal expected"
errIntLiteralExpected = "integer literal expected"
errWrongNumberOfVariables = "wrong number of variables"
errInvalidOrderInEnumX = "invalid order in enum '$1'"
errOrdinalTypeExpected = "ordinal type expected"
errSetTooBig = "set is too large"
errBaseTypeMustBeOrdinal = "base type of a set must be an ordinal"
errInheritanceOnlyWithNonFinalObjects = "inheritance only works with non-final objects"
errXExpectsOneTypeParam = "'$1' expects one type parameter"
errArrayExpectsTwoTypeParams = "array expects two type parameters"
errInvalidVisibilityX = "invalid visibility: '$1'"
errInitHereNotAllowed = "initialization not allowed here"
errXCannotBeAssignedTo = "'$1' cannot be assigned to"
errIteratorNotAllowed = "iterators can only be defined at the module's top level"
errXNeedsReturnType = "$1 needs a return type"
errNoReturnTypeDeclared = "no return type declared"
errTIsNotAConcreteType = "'$1' is not a concrete type"
errTypeExpected = "type expected"
errXOnlyAtModuleScope = "'$1' is only allowed at top level"
errDuplicateCaseLabel = "duplicate case label"
errMacroBodyDependsOnGenericTypes = "the macro body cannot be compiled, " &
"because the parameter '$1' has a generic type"
errIllegalRecursionInTypeX = "illegal recursion in type '$1'"
errNoGenericParamsAllowedForX = "no generic parameters allowed for $1"
errInOutFlagNotExtern = "the '$1' modifier can be used only with imported types"
proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType = proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
if prev == nil: if prev == nil:
result = newTypeS(kind, c) result = newTypeS(kind, c)
@ -34,11 +61,11 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
base = nil base = nil
result = newOrPrevType(tyEnum, prev, c) result = newOrPrevType(tyEnum, prev, c)
result.n = newNodeI(nkEnumTy, n.info) result.n = newNodeI(nkEnumTy, n.info)
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1, c.config)
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
base = semTypeNode(c, n.sons[0].sons[0], nil) base = semTypeNode(c, n.sons[0].sons[0], nil)
if base.kind != tyEnum: if base.kind != tyEnum:
localError(n.sons[0].info, errInheritanceOnlyWithEnums) localError(c.config, n.sons[0].info, "inheritance only works with an enum")
counter = lastOrd(base) + 1 counter = lastOrd(base) + 1
rawAddSon(result, base) rawAddSon(result, base)
let isPure = result.sym != nil and sfPure in result.sym.flags let isPure = result.sym != nil and sfPure in result.sym.flags
@ -58,9 +85,9 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}: if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}:
x = getOrdValue(v.sons[0]) # first tuple part is the ordinal x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
else: else:
localError(strVal.info, errStringLiteralExpected) localError(c.config, strVal.info, errStringLiteralExpected)
else: else:
localError(v.info, errWrongNumberOfVariables) localError(c.config, v.info, errWrongNumberOfVariables)
of tyString, tyCString: of tyString, tyCString:
strVal = v strVal = v
x = counter x = counter
@ -69,7 +96,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
if i != 1: if i != 1:
if x != counter: incl(result.flags, tfEnumHasHoles) if x != counter: incl(result.flags, tfEnumHasHoles)
if x < counter: if x < counter:
localError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s) localError(c.config, n.sons[i].info, errInvalidOrderInEnumX % e.name.s)
x = counter x = counter
e.ast = strVal # might be nil e.ast = strVal # might be nil
counter = x counter = x
@ -78,7 +105,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
of nkIdent, nkAccQuoted: of nkIdent, nkAccQuoted:
e = newSymS(skEnumField, n.sons[i], c) e = newSymS(skEnumField, n.sons[i], c)
else: else:
illFormedAst(n[i]) illFormedAst(n[i], c.config)
e.typ = result e.typ = result
e.position = int(counter) e.position = int(counter)
if e.position == 0: hasNull = true if e.position == 0: hasNull = true
@ -87,12 +114,13 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
incl(e.flags, sfExported) incl(e.flags, sfExported)
if not isPure: strTableAdd(c.module.tab, e) if not isPure: strTableAdd(c.module.tab, e)
addSon(result.n, newSymNode(e)) addSon(result.n, newSymNode(e))
let conf = c.config
styleCheckDef(e) styleCheckDef(e)
if sfGenSym notin e.flags: if sfGenSym notin e.flags:
if not isPure: addDecl(c, e) if not isPure: addDecl(c, e)
else: importPureEnumField(c, e) else: importPureEnumField(c, e)
if isPure and strTableIncl(symbols, e): if isPure and strTableIncl(symbols, e):
wrongRedefinition(e.info, e.name.s) wrongRedefinition(c, e.info, e.name.s)
inc(counter) inc(counter)
if not hasNull: incl(result.flags, tfNeedsInit) if not hasNull: incl(result.flags, tfNeedsInit)
@ -104,11 +132,11 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
if base.kind in {tyGenericInst, tyAlias, tySink}: base = lastSon(base) if base.kind in {tyGenericInst, tyAlias, tySink}: base = lastSon(base)
if base.kind != tyGenericParam: if base.kind != tyGenericParam:
if not isOrdinalType(base): if not isOrdinalType(base):
localError(n.info, errOrdinalTypeExpected) localError(c.config, n.info, errOrdinalTypeExpected)
elif lengthOrd(base) > MaxSetElements: elif lengthOrd(base) > MaxSetElements:
localError(n.info, errSetTooBig) localError(c.config, n.info, errSetTooBig)
else: else:
localError(n.info, errXExpectsOneTypeParam, "set") localError(c.config, n.info, errXExpectsOneTypeParam % "set")
addSonSkipIntLit(result, errorType(c)) addSonSkipIntLit(result, errorType(c))
proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
@ -117,10 +145,10 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
if sonsLen(n) == 2: if sonsLen(n) == 2:
var base = semTypeNode(c, n.sons[1], nil) var base = semTypeNode(c, n.sons[1], nil)
if base.kind == tyVoid: if base.kind == tyVoid:
localError(n.info, errTIsNotAConcreteType, typeToString(base)) localError(c.config, n.info, errTIsNotAConcreteType % typeToString(base))
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base)
else: else:
localError(n.info, errXExpectsOneTypeParam, kindStr) localError(c.config, n.info, errXExpectsOneTypeParam % kindStr)
addSonSkipIntLit(result, errorType(c)) addSonSkipIntLit(result, errorType(c))
proc semVarargs(c: PContext, n: PNode, prev: PType): PType = proc semVarargs(c: PContext, n: PNode, prev: PType): PType =
@ -129,9 +157,9 @@ proc semVarargs(c: PContext, n: PNode, prev: PType): PType =
var base = semTypeNode(c, n.sons[1], nil) var base = semTypeNode(c, n.sons[1], nil)
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base)
if sonsLen(n) == 3: if sonsLen(n) == 3:
result.n = newIdentNode(considerQuotedIdent(n.sons[2]), n.sons[2].info) result.n = newIdentNode(considerQuotedIdent(c.config, n.sons[2]), n.sons[2].info)
else: else:
localError(n.info, errXExpectsOneTypeParam, "varargs") localError(c.config, n.info, errXExpectsOneTypeParam % "varargs")
addSonSkipIntLit(result, errorType(c)) addSonSkipIntLit(result, errorType(c))
proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType = proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
@ -140,7 +168,7 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
else: else:
let isCall = int ord(n.kind in nkCallKinds+{nkBracketExpr}) let isCall = int ord(n.kind in nkCallKinds+{nkBracketExpr})
let n = if n[0].kind == nkBracket: n[0] else: n let n = if n[0].kind == nkBracket: n[0] else: n
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1, c.config)
var t = semTypeNode(c, n.lastSon, nil) var t = semTypeNode(c, n.lastSon, nil)
if t.kind == tyTypeDesc and tfUnresolved notin t.flags: if t.kind == tyTypeDesc and tfUnresolved notin t.flags:
t = t.base t = t.base
@ -155,7 +183,7 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType =
let region = semTypeNode(c, ni, nil) let region = semTypeNode(c, ni, nil)
if region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin { if region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin {
tyError, tyObject}: tyError, tyObject}:
message n[i].info, errGenerated, "region needs to be an object type" message c.config, n[i].info, errGenerated, "region needs to be an object type"
addSonSkipIntLit(result, region) addSonSkipIntLit(result, region)
addSonSkipIntLit(result, t) addSonSkipIntLit(result, t)
if tfPartial in result.flags: if tfPartial in result.flags:
@ -167,7 +195,7 @@ proc semVarType(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyVar, prev, c) result = newOrPrevType(tyVar, prev, c)
var base = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc}) var base = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc})
if base.kind == tyVar: if base.kind == tyVar:
localError(n.info, errVarVarTypeNotAllowed) localError(c.config, n.info, "type 'var var' is not allowed")
base = base.sons[0] base = base.sons[0]
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base)
else: else:
@ -181,7 +209,7 @@ proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
assert isRange(n) assert isRange(n)
checkSonsLen(n, 3) checkSonsLen(n, 3, c.config)
result = newOrPrevType(tyRange, prev, c) result = newOrPrevType(tyRange, prev, c)
result.n = newNodeI(nkRange, n.info) result.n = newNodeI(nkRange, n.info)
# always create a 'valid' range type, but overwrite it later # always create a 'valid' range type, but overwrite it later
@ -189,7 +217,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
addSonSkipIntLit(result, errorType(c)) addSonSkipIntLit(result, errorType(c))
if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty): if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty):
localError(n.info, errRangeIsEmpty) localError(c.config, n.info, "range is empty")
var range: array[2, PNode] var range: array[2, PNode]
range[0] = semExprWithType(c, n[1], {efDetermineType}) range[0] = semExprWithType(c, n[1], {efDetermineType})
@ -204,11 +232,11 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
if not hasUnknownTypes: if not hasUnknownTypes:
if not sameType(rangeT[0].skipTypes({tyRange}), rangeT[1].skipTypes({tyRange})): if not sameType(rangeT[0].skipTypes({tyRange}), rangeT[1].skipTypes({tyRange})):
localError(n.info, errPureTypeMismatch) localError(c.config, n.info, "type mismatch")
elif not rangeT[0].isOrdinalType: elif not rangeT[0].isOrdinalType:
localError(n.info, errOrdinalTypeExpected) localError(c.config, n.info, "ordinal type expected")
elif enumHasHoles(rangeT[0]): elif enumHasHoles(rangeT[0]):
localError(n.info, errEnumXHasHoles, rangeT[0].sym.name.s) localError(c.config, n.info, "enum '$1' has holes" % typeToString(rangeT[0]))
for i in 0..1: for i in 0..1:
if hasGenericArguments(range[i]): if hasGenericArguments(range[i]):
@ -218,7 +246,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
result.n.addSon semConstExpr(c, range[i]) result.n.addSon semConstExpr(c, range[i])
if weakLeValue(result.n[0], result.n[1]) == impNo: if weakLeValue(result.n[0], result.n[1]) == impNo:
localError(n.info, errRangeIsEmpty) localError(c.config, n.info, "range is empty")
result[0] = rangeT[0] result[0] = rangeT[0]
@ -239,13 +267,13 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType =
n.sons[1].floatVal < 0.0: n.sons[1].floatVal < 0.0:
incl(result.flags, tfNeedsInit) incl(result.flags, tfNeedsInit)
else: else:
if n[1].kind == nkInfix and considerQuotedIdent(n[1][0]).s == "..<": if n[1].kind == nkInfix and considerQuotedIdent(c.config, n[1][0]).s == "..<":
localError(n[0].info, "range types need to be constructed with '..', '..<' is not supported") localError(c.config, n[0].info, "range types need to be constructed with '..', '..<' is not supported")
else: else:
localError(n.sons[0].info, errRangeExpected) localError(c.config, n.sons[0].info, "expected range")
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
else: else:
localError(n.info, errXExpectsOneTypeParam, "range") localError(c.config, n.info, errXExpectsOneTypeParam % "range")
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
proc semArrayIndex(c: PContext, n: PNode): PType = proc semArrayIndex(c: PContext, n: PNode): PType =
@ -257,7 +285,7 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
result = makeRangeWithStaticExpr(c, e.typ.n) result = makeRangeWithStaticExpr(c, e.typ.n)
elif e.kind in {nkIntLit..nkUInt64Lit}: elif e.kind in {nkIntLit..nkUInt64Lit}:
if e.intVal < 0: if e.intVal < 0:
localError(n[1].info, localError(c.config, n[1].info,
"Array length can't be negative, but was " & $e.intVal) "Array length can't be negative, but was " & $e.intVal)
result = makeRangeType(c, 0, e.intVal-1, n.info, e.typ) result = makeRangeType(c, 0, e.intVal-1, n.info, e.typ)
elif e.kind == nkSym and e.typ.kind == tyStatic: elif e.kind == nkSym and e.typ.kind == tyStatic:
@ -265,12 +293,12 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
return semArrayIndex(c, e.sym.ast) return semArrayIndex(c, e.sym.ast)
if not isOrdinalType(e.typ.lastSon): if not isOrdinalType(e.typ.lastSon):
let info = if n.safeLen > 1: n[1].info else: n.info let info = if n.safeLen > 1: n[1].info else: n.info
localError(info, errOrdinalTypeExpected) localError(c.config, info, errOrdinalTypeExpected)
result = makeRangeWithStaticExpr(c, e) result = makeRangeWithStaticExpr(c, e)
if c.inGenericContext > 0: result.flags.incl tfUnresolved if c.inGenericContext > 0: result.flags.incl tfUnresolved
elif e.kind in nkCallKinds and hasGenericArguments(e): elif e.kind in nkCallKinds and hasGenericArguments(e):
if not isOrdinalType(e.typ): if not isOrdinalType(e.typ):
localError(n[1].info, errOrdinalTypeExpected) localError(c.config, n[1].info, errOrdinalTypeExpected)
# This is an int returning call, depending on an # This is an int returning call, depending on an
# yet unknown generic param (see tgenericshardcases). # yet unknown generic param (see tgenericshardcases).
# We are going to construct a range type that will be # We are going to construct a range type that will be
@ -286,7 +314,7 @@ proc semArrayIndex(c: PContext, n: PNode): PType =
x.typ.skipTypes({tyTypeDesc})) x.typ.skipTypes({tyTypeDesc}))
else: else:
result = x.typ.skipTypes({tyTypeDesc}) result = x.typ.skipTypes({tyTypeDesc})
#localError(n[1].info, errConstExprExpected) #localError(c.config, n[1].info, errConstExprExpected)
proc semArray(c: PContext, n: PNode, prev: PType): PType = proc semArray(c: PContext, n: PNode, prev: PType): PType =
var base: PType var base: PType
@ -299,9 +327,9 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
if indxB.skipTypes({tyRange}).kind in {tyUInt, tyUInt64}: if indxB.skipTypes({tyRange}).kind in {tyUInt, tyUInt64}:
discard discard
elif not isOrdinalType(indxB): elif not isOrdinalType(indxB):
localError(n.sons[1].info, errOrdinalTypeExpected) localError(c.config, n.sons[1].info, errOrdinalTypeExpected)
elif enumHasHoles(indxB): elif enumHasHoles(indxB):
localError(n.sons[1].info, errEnumXHasHoles, localError(c.config, n.sons[1].info, "enum '$1' has holes" %
typeToString(indxB.skipTypes({tyRange}))) typeToString(indxB.skipTypes({tyRange})))
base = semTypeNode(c, n.sons[2], nil) base = semTypeNode(c, n.sons[2], nil)
# ensure we only construct a tyArray when there was no error (bug #3048): # ensure we only construct a tyArray when there was no error (bug #3048):
@ -311,7 +339,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
rawAddSonNoPropagationOfTypeFlags(result, indx) rawAddSonNoPropagationOfTypeFlags(result, indx)
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base)
else: else:
localError(n.info, errArrayExpectsTwoTypeParams) localError(c.config, n.info, errArrayExpectsTwoTypeParams)
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
@ -320,10 +348,10 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
var base = semTypeNode(c, n.sons[1], nil) var base = semTypeNode(c, n.sons[1], nil)
if base.kind != tyGenericParam: if base.kind != tyGenericParam:
if not isOrdinalType(base): if not isOrdinalType(base):
localError(n.sons[1].info, errOrdinalTypeExpected) localError(c.config, n.sons[1].info, errOrdinalTypeExpected)
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base)
else: else:
localError(n.info, errXExpectsOneTypeParam, "ordinal") localError(c.config, n.info, errXExpectsOneTypeParam % "ordinal")
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
proc semTypeIdent(c: PContext, n: PNode): PSym = proc semTypeIdent(c: PContext, n: PNode): PSym =
@ -334,7 +362,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
if result.isNil: if result.isNil:
result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared}) result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
if result != nil: if result != nil:
markUsed(n.info, result, c.graph.usageSym) markUsed(c.config, n.info, result, c.graph.usageSym)
styleCheckUse(n.info, result) styleCheckUse(n.info, result)
if result.kind == skParam and result.typ.kind == tyTypeDesc: if result.kind == skParam and result.typ.kind == tyTypeDesc:
# This is a typedesc param. is it already bound? # This is a typedesc param. is it already bound?
@ -345,7 +373,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
if bound != nil: return bound if bound != nil: return bound
return result return result
if result.typ.sym == nil: if result.typ.sym == nil:
localError(n.info, errTypeExpected) localError(c.config, n.info, errTypeExpected)
return errorSym(c, n) return errorSym(c, n)
result = result.typ.sym.copySym result = result.typ.sym.copySym
result.typ = copyType(result.typ, result.typ.owner, true) result.typ = copyType(result.typ, result.typ.owner, true)
@ -359,7 +387,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
result.typ.flags.excl tfWildcard result.typ.flags.excl tfWildcard
return return
else: else:
localError(n.info, errTypeExpected) localError(c.config, n.info, errTypeExpected)
return errorSym(c, n) return errorSym(c, n)
if result.kind != skType: if result.kind != skType:
@ -370,7 +398,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
amb = nextOverloadIter(ov, c, n) amb = nextOverloadIter(ov, c, n)
if amb != nil: result = amb if amb != nil: result = amb
else: else:
if result.kind != skError: localError(n.info, errTypeExpected) if result.kind != skError: localError(c.config, n.info, errTypeExpected)
return errorSym(c, n) return errorSym(c, n)
if result.typ.kind != tyGenericParam: if result.typ.kind != tyGenericParam:
# XXX get rid of this hack! # XXX get rid of this hack!
@ -385,12 +413,12 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
n.info = oldInfo n.info = oldInfo
n.typ = result.typ n.typ = result.typ
else: else:
localError(n.info, errIdentifierExpected) localError(c.config, n.info, "identifier expected")
result = errorSym(c, n) result = errorSym(c, n)
proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType = proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType =
if sonsLen(n) == 0: if sonsLen(n) == 0:
localError(n.info, errTypeExpected) localError(c.config, n.info, errTypeExpected)
result = newOrPrevType(tyTuple, prev, c) result = newOrPrevType(tyTuple, prev, c)
for it in n: for it in n:
addSonSkipIntLit(result, semTypeNode(c, it, nil)) addSonSkipIntLit(result, semTypeNode(c, it, nil))
@ -403,23 +431,23 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
var counter = 0 var counter = 0
for i in countup(ord(n.kind == nkBracketExpr), sonsLen(n) - 1): for i in countup(ord(n.kind == nkBracketExpr), sonsLen(n) - 1):
var a = n.sons[i] var a = n.sons[i]
if (a.kind != nkIdentDefs): illFormedAst(a) if (a.kind != nkIdentDefs): illFormedAst(a, c.config)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3, c.config)
var length = sonsLen(a) var length = sonsLen(a)
if a.sons[length - 2].kind != nkEmpty: if a.sons[length - 2].kind != nkEmpty:
typ = semTypeNode(c, a.sons[length - 2], nil) typ = semTypeNode(c, a.sons[length - 2], nil)
else: else:
localError(a.info, errTypeExpected) localError(c.config, a.info, errTypeExpected)
typ = errorType(c) typ = errorType(c)
if a.sons[length - 1].kind != nkEmpty: if a.sons[length - 1].kind != nkEmpty:
localError(a.sons[length - 1].info, errInitHereNotAllowed) localError(c.config, a.sons[length - 1].info, errInitHereNotAllowed)
for j in countup(0, length - 3): for j in countup(0, length - 3):
var field = newSymG(skField, a.sons[j], c) var field = newSymG(skField, a.sons[j], c)
field.typ = typ field.typ = typ
field.position = counter field.position = counter
inc(counter) inc(counter)
if containsOrIncl(check, field.name.id): if containsOrIncl(check, field.name.id):
localError(a.sons[j].info, errAttemptToRedefine, field.name.s) localError(c.config, a.sons[j].info, "attempt to redefine: " & field.name.s)
else: else:
addSon(result.n, newSymNode(field)) addSon(result.n, newSymNode(field))
addSonSkipIntLit(result, typ) addSonSkipIntLit(result, typ)
@ -434,23 +462,23 @@ proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
# for gensym'ed identifiers the identifier may already have been # for gensym'ed identifiers the identifier may already have been
# transformed to a symbol and we need to use that here: # transformed to a symbol and we need to use that here:
result = newSymG(kind, n.sons[1], c) result = newSymG(kind, n.sons[1], c)
var v = considerQuotedIdent(n.sons[0]) var v = considerQuotedIdent(c.config, n.sons[0])
if sfExported in allowed and v.id == ord(wStar): if sfExported in allowed and v.id == ord(wStar):
incl(result.flags, sfExported) incl(result.flags, sfExported)
else: else:
if not (sfExported in allowed): if not (sfExported in allowed):
localError(n.sons[0].info, errXOnlyAtModuleScope, "export") localError(c.config, n.sons[0].info, errXOnlyAtModuleScope % "export")
else: else:
localError(n.sons[0].info, errInvalidVisibilityX, renderTree(n[0])) localError(c.config, n.sons[0].info, errInvalidVisibilityX % renderTree(n[0]))
else: else:
illFormedAst(n) illFormedAst(n, c.config)
else: else:
result = newSymG(kind, n, c) result = newSymG(kind, n, c)
proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
allowed: TSymFlags): PSym = allowed: TSymFlags): PSym =
if n.kind == nkPragmaExpr: if n.kind == nkPragmaExpr:
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
result = semIdentVis(c, kind, n.sons[0], allowed) result = semIdentVis(c, kind, n.sons[0], allowed)
case kind case kind
of skType: of skType:
@ -471,10 +499,10 @@ proc checkForOverlap(c: PContext, t: PNode, currentEx, branchIndex: int) =
for j in countup(0, sonsLen(t.sons[i]) - 2): for j in countup(0, sonsLen(t.sons[i]) - 2):
if i == branchIndex and j == currentEx: break if i == branchIndex and j == currentEx: break
if overlap(t.sons[i].sons[j].skipConv, ex): if overlap(t.sons[i].sons[j].skipConv, ex):
localError(ex.info, errDuplicateCaseLabel) localError(c.config, ex.info, errDuplicateCaseLabel)
proc semBranchRange(c: PContext, t, a, b: PNode, covered: var BiggestInt): PNode = proc semBranchRange(c: PContext, t, a, b: PNode, covered: var BiggestInt): PNode =
checkMinSonsLen(t, 1) checkMinSonsLen(t, 1, c.config)
let ac = semConstExpr(c, a) let ac = semConstExpr(c, a)
let bc = semConstExpr(c, b) let bc = semConstExpr(c, b)
let at = fitNode(c, t.sons[0].typ, ac, ac.info).skipConvTakeType let at = fitNode(c, t.sons[0].typ, ac, ac.info).skipConvTakeType
@ -483,21 +511,21 @@ proc semBranchRange(c: PContext, t, a, b: PNode, covered: var BiggestInt): PNode
result = newNodeI(nkRange, a.info) result = newNodeI(nkRange, a.info)
result.add(at) result.add(at)
result.add(bt) result.add(bt)
if emptyRange(ac, bc): localError(b.info, errRangeIsEmpty) if emptyRange(ac, bc): localError(c.config, b.info, "range is empty")
else: covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1 else: covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1
proc semCaseBranchRange(c: PContext, t, b: PNode, proc semCaseBranchRange(c: PContext, t, b: PNode,
covered: var BiggestInt): PNode = covered: var BiggestInt): PNode =
checkSonsLen(b, 3) checkSonsLen(b, 3, c.config)
result = semBranchRange(c, t, b.sons[1], b.sons[2], covered) result = semBranchRange(c, t, b.sons[1], b.sons[2], covered)
proc semCaseBranchSetElem(c: PContext, t, b: PNode, proc semCaseBranchSetElem(c: PContext, t, b: PNode,
covered: var BiggestInt): PNode = covered: var BiggestInt): PNode =
if isRange(b): if isRange(b):
checkSonsLen(b, 3) checkSonsLen(b, 3, c.config)
result = semBranchRange(c, t, b.sons[1], b.sons[2], covered) result = semBranchRange(c, t, b.sons[1], b.sons[2], covered)
elif b.kind == nkRange: elif b.kind == nkRange:
checkSonsLen(b, 2) checkSonsLen(b, 2, c.config)
result = semBranchRange(c, t, b.sons[0], b.sons[1], covered) result = semBranchRange(c, t, b.sons[0], b.sons[1], covered)
else: else:
result = fitNode(c, t.sons[0].typ, b, b.info) result = fitNode(c, t.sons[0].typ, b, b.info)
@ -520,7 +548,7 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
delSon(branch, 0) delSon(branch, 0)
return return
elif r.kind notin {nkCurly, nkBracket} or len(r) == 0: elif r.kind notin {nkCurly, nkBracket} or len(r) == 0:
checkMinSonsLen(t, 1) checkMinSonsLen(t, 1, c.config)
branch.sons[i] = skipConv(fitNode(c, t.sons[0].typ, r, r.info)) branch.sons[i] = skipConv(fitNode(c, t.sons[0].typ, r, r.info))
inc(covered) inc(covered)
else: else:
@ -546,37 +574,37 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int, proc semRecordCase(c: PContext, n: PNode, check: var IntSet, pos: var int,
father: PNode, rectype: PType) = father: PNode, rectype: PType) =
var a = copyNode(n) var a = copyNode(n)
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2, c.config)
semRecordNodeAux(c, n.sons[0], check, pos, a, rectype) semRecordNodeAux(c, n.sons[0], check, pos, a, rectype)
if a.sons[0].kind != nkSym: if a.sons[0].kind != nkSym:
internalError("semRecordCase: discriminant is no symbol") internalError(c.config, "semRecordCase: discriminant is no symbol")
return return
incl(a.sons[0].sym.flags, sfDiscriminant) incl(a.sons[0].sym.flags, sfDiscriminant)
var covered: BiggestInt = 0 var covered: BiggestInt = 0
var typ = skipTypes(a.sons[0].typ, abstractVar-{tyTypeDesc}) var typ = skipTypes(a.sons[0].typ, abstractVar-{tyTypeDesc})
if not isOrdinalType(typ): if not isOrdinalType(typ):
localError(n.info, errSelectorMustBeOrdinal) localError(c.config, n.info, "selector must be of an ordinal type")
elif firstOrd(typ) != 0: elif firstOrd(typ) != 0:
localError(n.info, errGenerated, "low(" & $a.sons[0].sym.name.s & localError(c.config, n.info, "low(" & $a.sons[0].sym.name.s &
") must be 0 for discriminant") ") must be 0 for discriminant")
elif lengthOrd(typ) > 0x00007FFF: elif lengthOrd(typ) > 0x00007FFF:
localError(n.info, errLenXinvalid, a.sons[0].sym.name.s) localError(c.config, n.info, "len($1) must be less than 32768" % a.sons[0].sym.name.s)
var chckCovered = true var chckCovered = true
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
var b = copyTree(n.sons[i]) var b = copyTree(n.sons[i])
addSon(a, b) addSon(a, b)
case n.sons[i].kind case n.sons[i].kind
of nkOfBranch: of nkOfBranch:
checkMinSonsLen(b, 2) checkMinSonsLen(b, 2, c.config)
semCaseBranch(c, a, b, i, covered) semCaseBranch(c, a, b, i, covered)
of nkElse: of nkElse:
chckCovered = false chckCovered = false
checkSonsLen(b, 1) checkSonsLen(b, 1, c.config)
else: illFormedAst(n) else: illFormedAst(n, c.config)
delSon(b, sonsLen(b) - 1) delSon(b, sonsLen(b) - 1)
semRecordNodeAux(c, lastSon(n.sons[i]), check, pos, b, rectype) semRecordNodeAux(c, lastSon(n.sons[i]), check, pos, b, rectype)
if chckCovered and (covered != lengthOrd(a.sons[0].typ)): if chckCovered and covered != lengthOrd(a.sons[0].typ):
localError(a.info, errNotAllCasesCovered) localError(c.config, a.info, "not all cases are covered")
addSon(father, a) addSon(father, a)
proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int, proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
@ -587,22 +615,22 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
var branch: PNode = nil # the branch to take var branch: PNode = nil # the branch to take
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
var it = n.sons[i] var it = n.sons[i]
if it == nil: illFormedAst(n) if it == nil: illFormedAst(n, c.config)
var idx = 1 var idx = 1
case it.kind case it.kind
of nkElifBranch: of nkElifBranch:
checkSonsLen(it, 2) checkSonsLen(it, 2, c.config)
if c.inGenericContext == 0: if c.inGenericContext == 0:
var e = semConstBoolExpr(c, it.sons[0]) var e = semConstBoolExpr(c, it.sons[0])
if e.kind != nkIntLit: internalError(e.info, "semRecordNodeAux") if e.kind != nkIntLit: internalError(c.config, e.info, "semRecordNodeAux")
elif e.intVal != 0 and branch == nil: branch = it.sons[1] elif e.intVal != 0 and branch == nil: branch = it.sons[1]
else: else:
it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0])) it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
of nkElse: of nkElse:
checkSonsLen(it, 1) checkSonsLen(it, 1, c.config)
if branch == nil: branch = it.sons[0] if branch == nil: branch = it.sons[0]
idx = 0 idx = 0
else: illFormedAst(n) else: illFormedAst(n, c.config)
if c.inGenericContext > 0: if c.inGenericContext > 0:
# use a new check intset here for each branch: # use a new check intset here for each branch:
var newCheck: IntSet var newCheck: IntSet
@ -626,16 +654,16 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
semRecordNodeAux(c, n.sons[i], check, pos, a, rectype) semRecordNodeAux(c, n.sons[i], check, pos, a, rectype)
if a != father: addSon(father, a) if a != father: addSon(father, a)
of nkIdentDefs: of nkIdentDefs:
checkMinSonsLen(n, 3) checkMinSonsLen(n, 3, c.config)
var length = sonsLen(n) var length = sonsLen(n)
var a: PNode var a: PNode
if father.kind != nkRecList and length>=4: a = newNodeI(nkRecList, n.info) if father.kind != nkRecList and length>=4: a = newNodeI(nkRecList, n.info)
else: a = ast.emptyNode else: a = ast.emptyNode
if n.sons[length-1].kind != nkEmpty: if n.sons[length-1].kind != nkEmpty:
localError(n.sons[length-1].info, errInitHereNotAllowed) localError(c.config, n.sons[length-1].info, errInitHereNotAllowed)
var typ: PType var typ: PType
if n.sons[length-2].kind == nkEmpty: if n.sons[length-2].kind == nkEmpty:
localError(n.info, errTypeExpected) localError(c.config, n.info, errTypeExpected)
typ = errorType(c) typ = errorType(c)
else: else:
typ = semTypeNode(c, n.sons[length-2], nil) typ = semTypeNode(c, n.sons[length-2], nil)
@ -654,7 +682,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
f.flags = f.flags + ({sfImportc, sfExportc} * fieldOwner.flags) f.flags = f.flags + ({sfImportc, sfExportc} * fieldOwner.flags)
inc(pos) inc(pos)
if containsOrIncl(check, f.name.id): if containsOrIncl(check, f.name.id):
localError(n.sons[i].info, errAttemptToRedefine, f.name.s) localError(c.config, n.sons[i].info, "attempt to redefine: " & f.name.s)
if a.kind == nkEmpty: addSon(father, newSymNode(f)) if a.kind == nkEmpty: addSon(father, newSymNode(f))
else: addSon(a, newSymNode(f)) else: addSon(a, newSymNode(f))
styleCheckDef(f) styleCheckDef(f)
@ -664,29 +692,29 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
# inherited from generic/partial specialized parent second check. # inherited from generic/partial specialized parent second check.
# There is no branch validity check here # There is no branch validity check here
if containsOrIncl(check, n.sym.name.id): if containsOrIncl(check, n.sym.name.id):
localError(n.info, errAttemptToRedefine, n.sym.name.s) localError(c.config, n.info, "attempt to redefine: " & n.sym.name.s)
addSon(father, n) addSon(father, n)
of nkEmpty: discard of nkEmpty: discard
else: illFormedAst(n) 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,
n: PNode) = n: PNode) =
case n.kind case n.kind
of nkRecCase: of nkRecCase:
if (n.sons[0].kind != nkSym): internalError(n.info, "addInheritedFieldsAux") if (n.sons[0].kind != nkSym): internalError(c.config, n.info, "addInheritedFieldsAux")
addInheritedFieldsAux(c, check, pos, n.sons[0]) addInheritedFieldsAux(c, check, pos, n.sons[0])
for i in countup(1, sonsLen(n) - 1): for i in countup(1, sonsLen(n) - 1):
case n.sons[i].kind case n.sons[i].kind
of nkOfBranch, nkElse: of nkOfBranch, nkElse:
addInheritedFieldsAux(c, check, pos, lastSon(n.sons[i])) addInheritedFieldsAux(c, check, pos, lastSon(n.sons[i]))
else: internalError(n.info, "addInheritedFieldsAux(record case branch)") else: internalError(c.config, n.info, "addInheritedFieldsAux(record case branch)")
of nkRecList: of nkRecList:
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
addInheritedFieldsAux(c, check, pos, n.sons[i]) addInheritedFieldsAux(c, check, pos, n.sons[i])
of nkSym: of nkSym:
incl(check, n.sym.name.id) incl(check, n.sym.name.id)
inc(pos) inc(pos)
else: internalError(n.info, "addInheritedFieldsAux()") else: internalError(c.config, n.info, "addInheritedFieldsAux()")
proc skipGenericInvocation(t: PType): PType {.inline.} = proc skipGenericInvocation(t: PType): PType {.inline.} =
result = t result = t
@ -709,12 +737,12 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
var pos = 0 var pos = 0
var base, realBase: PType = nil var base, realBase: PType = nil
# n.sons[0] contains the pragmas (if any). We process these later... # n.sons[0] contains the pragmas (if any). We process these later...
checkSonsLen(n, 3) checkSonsLen(n, 3, c.config)
if n.sons[1].kind != nkEmpty: if n.sons[1].kind != nkEmpty:
realBase = semTypeNode(c, n.sons[1].sons[0], nil) realBase = semTypeNode(c, n.sons[1].sons[0], nil)
base = skipTypesOrNil(realBase, skipPtrs) base = skipTypesOrNil(realBase, skipPtrs)
if base.isNil: if base.isNil:
localError(n.info, errIllegalRecursionInTypeX, "object") localError(c.config, n.info, "cannot inherit from a type that is not an object type")
else: else:
var concreteBase = skipGenericInvocation(base) var concreteBase = skipGenericInvocation(base)
if concreteBase.kind in {tyObject, tyGenericParam, if concreteBase.kind in {tyObject, tyGenericParam,
@ -727,11 +755,11 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
addInheritedFields(c, check, pos, concreteBase) addInheritedFields(c, check, pos, concreteBase)
else: else:
if concreteBase.kind != tyError: if concreteBase.kind != tyError:
localError(n.sons[1].info, "inheritance only works with non-final objects; " & localError(c.config, n.sons[1].info, "inheritance only works with non-final objects; " &
"to enable inheritance write '" & typeToString(realBase) & " of RootObj'") "to enable inheritance write '" & typeToString(realBase) & " of RootObj'")
base = nil base = nil
realBase = nil realBase = nil
if n.kind != nkObjectTy: internalError(n.info, "semObjectNode") if n.kind != nkObjectTy: internalError(c.config, n.info, "semObjectNode")
result = newOrPrevType(tyObject, prev, c) result = newOrPrevType(tyObject, prev, c)
rawAddSon(result, realBase) rawAddSon(result, realBase)
if result.n.isNil: if result.n.isNil:
@ -769,8 +797,7 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
addDecl(c, param) addDecl(c, param)
else: else:
# within a macro, every param has the type NimNode! # within a macro, every param has the type NimNode!
let nn = if getCompilerProc("NimNode") != nil: getSysSym"NimNode" let nn = getSysSym(c.graph, param.info, "NimNode")
else: getSysSym"PNimrodNode"
var a = copySym(param) var a = copySym(param)
a.typ = nn.typ a.typ = nn.typ
addDecl(c, a) addDecl(c, a)
@ -780,7 +807,7 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
let typedescId = getIdent"typedesc" let typedescId = getIdent"typedesc"
template shouldHaveMeta(t) = template shouldHaveMeta(t) =
internalAssert tfHasMeta in t.flags internalAssert c.config, tfHasMeta in t.flags
# result.lastSon.flags.incl tfHasMeta # result.lastSon.flags.incl tfHasMeta
proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
@ -838,7 +865,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
if tfUnresolved in paramType.flags: return # already lifted if tfUnresolved in paramType.flags: return # already lifted
let base = paramType.base.maybeLift let base = paramType.base.maybeLift
if base.isMetaType and procKind == skMacro: if base.isMetaType and procKind == skMacro:
localError(info, errMacroBodyDependsOnGenericTypes, paramName) localError(c.config, info, errMacroBodyDependsOnGenericTypes % paramName)
result = addImplicitGeneric(c.newTypeWithSons(tyStatic, @[base])) result = addImplicitGeneric(c.newTypeWithSons(tyStatic, @[base]))
result.flags.incl({tfHasStatic, tfUnresolved}) result.flags.incl({tfHasStatic, tfUnresolved})
@ -870,7 +897,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
else: else:
for i in 0 ..< paramType.len: for i in 0 ..< paramType.len:
if paramType.sons[i] == paramType: if paramType.sons[i] == paramType:
globalError(info, errIllegalRecursionInTypeX, typeToString(paramType)) globalError(c.config, info, errIllegalRecursionInTypeX % typeToString(paramType))
var lifted = liftingWalk(paramType.sons[i]) var lifted = liftingWalk(paramType.sons[i])
if lifted != nil: if lifted != nil:
paramType.sons[i] = lifted paramType.sons[i] = lifted
@ -939,7 +966,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
result = addImplicitGeneric(copyType(paramType, getCurrOwner(c), false)) result = addImplicitGeneric(copyType(paramType, getCurrOwner(c), false))
of tyGenericParam: of tyGenericParam:
markUsed(info, paramType.sym, c.graph.usageSym) markUsed(c.config, info, paramType.sym, c.graph.usageSym)
styleCheckUse(info, paramType.sym) styleCheckUse(info, paramType.sym)
if tfWildcard in paramType.flags: if tfWildcard in paramType.flags:
paramType.flags.excl tfWildcard paramType.flags.excl tfWildcard
@ -952,7 +979,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType = proc semParamType(c: PContext, n: PNode, constraint: var PNode): PType =
if n.kind == nkCurlyExpr: if n.kind == nkCurlyExpr:
result = semTypeNode(c, n.sons[0], nil) result = semTypeNode(c, n.sons[0], nil)
constraint = semNodeKindConstraints(n) constraint = semNodeKindConstraints(n, c.config)
else: else:
result = semTypeNode(c, n, nil) result = semTypeNode(c, n, nil)
@ -971,7 +998,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
# for historical reasons (code grows) this is invoked for parameter # for historical reasons (code grows) this is invoked for parameter
# lists too and then 'isType' is false. # lists too and then 'isType' is false.
var cl: IntSet var cl: IntSet
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1, c.config)
result = newProcType(c, n.info, prev) result = newProcType(c, n.info, prev)
if genericParams != nil and sonsLen(genericParams) == 0: if genericParams != nil and sonsLen(genericParams) == 0:
cl = initIntSet() cl = initIntSet()
@ -985,8 +1012,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
# skip this parameter here. It'll then be re-generated in another LL # skip this parameter here. It'll then be re-generated in another LL
# pass over this instantiation: # pass over this instantiation:
if a.kind == nkSym and sfFromGeneric in a.sym.flags: continue if a.kind == nkSym and sfFromGeneric in a.sym.flags: continue
illFormedAst(a) illFormedAst(a, c.config)
checkMinSonsLen(a, 3) checkMinSonsLen(a, 3, c.config)
var var
typ: PType = nil typ: PType = nil
def: PNode = nil def: PNode = nil
@ -1009,7 +1036,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
if not containsGenericType(typ): if not containsGenericType(typ):
def = fitNode(c, typ, def, def.info) def = fitNode(c, typ, def, def.info)
if not hasType and not hasDefault: if not hasType and not hasDefault:
if isType: localError(a.info, "':' expected") if isType: localError(c.config, a.info, "':' expected")
if kind in {skTemplate, skMacro}: if kind in {skTemplate, skMacro}:
typ = newTypeS(tyExpr, c) typ = newTypeS(tyExpr, c)
elif skipTypes(typ, {tyGenericInst, tyAlias, tySink}).kind == tyVoid: elif skipTypes(typ, {tyGenericInst, tyAlias, tySink}).kind == tyVoid:
@ -1020,7 +1047,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
let param = strTableGet(c.signatures, arg.name) let param = strTableGet(c.signatures, arg.name)
if param != nil: typ = param.typ if param != nil: typ = param.typ
else: else:
localError(a.info, "typeless parameters are obsolete") localError(c.config, a.info, "typeless parameters are obsolete")
typ = errorType(c) typ = errorType(c)
let lifted = liftParamType(c, kind, genericParams, typ, let lifted = liftParamType(c, kind, genericParams, typ,
arg.name.s, arg.info) arg.name.s, arg.info)
@ -1031,7 +1058,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
inc(counter) inc(counter)
if def != nil and def.kind != nkEmpty: arg.ast = copyTree(def) if def != nil and def.kind != nkEmpty: arg.ast = copyTree(def)
if containsOrIncl(check, arg.name.id): if containsOrIncl(check, arg.name.id):
localError(a.sons[j].info, errAttemptToRedefine, arg.name.s) localError(c.config, a.sons[j].info, "attempt to redefine: " & arg.name.s)
addSon(result.n, newSymNode(arg)) addSon(result.n, newSymNode(arg))
rawAddSon(result, finalType) rawAddSon(result, finalType)
addParamOrResult(c, arg, kind) addParamOrResult(c, arg, kind)
@ -1085,7 +1112,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
n.sym.typ.flags.excl tfWildcard n.sym.typ.flags.excl tfWildcard
proc semStmtListType(c: PContext, n: PNode, prev: PType): PType = proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1, c.config)
var length = sonsLen(n) var length = sonsLen(n)
for i in countup(0, length - 2): for i in countup(0, length - 2):
n.sons[i] = semStmt(c, n.sons[i]) n.sons[i] = semStmt(c, n.sons[i])
@ -1098,7 +1125,7 @@ proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
proc semBlockType(c: PContext, n: PNode, prev: PType): PType = proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
inc(c.p.nestedBlockCounter) inc(c.p.nestedBlockCounter)
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
openScope(c) openScope(c)
if n.sons[0].kind notin {nkEmpty, nkSym}: if n.sons[0].kind notin {nkEmpty, nkSym}:
addDecl(c, newSymS(skLabel, n.sons[0], c)) addDecl(c, newSymS(skLabel, n.sons[0], c))
@ -1120,20 +1147,20 @@ proc semObjectTypeForInheritedGenericInst(c: PContext, n: PNode, t: PType) =
realBase = t.sons[0] realBase = t.sons[0]
base = skipTypesOrNil(realBase, skipPtrs) base = skipTypesOrNil(realBase, skipPtrs)
if base.isNil: if base.isNil:
localError(n.info, errIllegalRecursionInTypeX, "object") localError(c.config, n.info, errIllegalRecursionInTypeX % "object")
else: else:
let concreteBase = skipGenericInvocation(base) let concreteBase = skipGenericInvocation(base)
if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags: if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags:
addInheritedFields(c, check, pos, concreteBase) addInheritedFields(c, check, pos, concreteBase)
else: else:
if concreteBase.kind != tyError: if concreteBase.kind != tyError:
localError(n.info, errInheritanceOnlyWithNonFinalObjects) localError(c.config, n.info, errInheritanceOnlyWithNonFinalObjects)
var newf = newNodeI(nkRecList, n.info) var newf = newNodeI(nkRecList, n.info)
semRecordNodeAux(c, t.n, check, pos, newf, t) semRecordNodeAux(c, t.n, check, pos, newf, t)
proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
if s.typ == nil: if s.typ == nil:
localError(n.info, "cannot instantiate the '$1' $2" % localError(c.config, n.info, "cannot instantiate the '$1' $2" %
[s.name.s, ($s.kind).substr(2).toLowerAscii]) [s.name.s, ($s.kind).substr(2).toLowerAscii])
return newOrPrevType(tyError, prev, c) return newOrPrevType(tyError, prev, c)
@ -1146,7 +1173,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
template addToResult(typ) = template addToResult(typ) =
if typ.isNil: if typ.isNil:
internalAssert false internalAssert c.config, false
rawAddSon(result, typ) rawAddSon(result, typ)
else: addSonSkipIntLit(result, typ) else: addSonSkipIntLit(result, typ)
@ -1158,7 +1185,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
elif t.kind != tyGenericBody: elif t.kind != tyGenericBody:
# we likely got code of the form TypeA[TypeB] where TypeA is # we likely got code of the form TypeA[TypeB] where TypeA is
# not generic. # not generic.
localError(n.info, errNoGenericParamsAllowedForX, s.name.s) localError(c.config, n.info, errNoGenericParamsAllowedForX % s.name.s)
return newOrPrevType(tyError, prev, c) return newOrPrevType(tyError, prev, c)
else: else:
var m = newCandidate(c, t) var m = newCandidate(c, t)
@ -1169,7 +1196,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
let err = "cannot instantiate " & typeToString(t) & "\n" & let err = "cannot instantiate " & typeToString(t) & "\n" &
"got: <" & describeArgs(c, n) & ">\n" & "got: <" & describeArgs(c, n) & ">\n" &
"but expected: <" & describeArgs(c, t.n, 0) & ">" "but expected: <" & describeArgs(c, t.n, 0) & ">"
localError(n.info, errGenerated, err) localError(c.config, n.info, errGenerated, err)
return newOrPrevType(tyError, prev, c) return newOrPrevType(tyError, prev, c)
var isConcrete = true var isConcrete = true
@ -1187,7 +1214,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
if isConcrete: if isConcrete:
if s.ast == nil and s.typ.kind != tyCompositeTypeClass: if s.ast == nil and s.typ.kind != tyCompositeTypeClass:
# XXX: What kind of error is this? is it still relevant? # XXX: What kind of error is this? is it still relevant?
localError(n.info, errCannotInstantiateX, s.name.s) localError(c.config, n.info, errCannotInstantiateX % s.name.s)
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
else: else:
result = instGenericContainer(c, n.info, result, result = instGenericContainer(c, n.info, result,
@ -1197,7 +1224,7 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
# generic/partial specialized parent # generic/partial specialized parent
let tx = result.skipTypes(abstractPtrs, 50) let tx = result.skipTypes(abstractPtrs, 50)
if tx.isNil: if tx.isNil:
localError(n.info, "invalid recursion in type '$1'" % typeToString(result[0])) localError(c.config, n.info, "invalid recursion in type '$1'" % typeToString(result[0]))
return errorType(c) return errorType(c)
if tx != result and tx.kind == tyObject and tx.sons[0] != nil: if tx != result and tx.kind == tyObject and tx.sons[0] != nil:
semObjectTypeForInheritedGenericInst(c, n, tx) semObjectTypeForInheritedGenericInst(c, n, tx)
@ -1226,7 +1253,7 @@ proc semTypeExpr(c: PContext, n: PNode; prev: PType): PType =
let alias = maybeAliasType(c, result, prev) let alias = maybeAliasType(c, result, prev)
if alias != nil: result = alias if alias != nil: result = alias
else: else:
localError(n.info, errTypeExpected, n.renderTree) localError(c.config, n.info, "expected type, but got: " & n.renderTree)
result = errorType(c) result = errorType(c)
proc freshType(res, prev: PType): PType {.inline.} = proc freshType(res, prev: PType): PType {.inline.} =
@ -1277,7 +1304,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
dummyName = param dummyName = param
dummyType = candidateTypeSlot dummyType = candidateTypeSlot
internalAssert dummyName.kind == nkIdent internalAssert c.config, dummyName.kind == nkIdent
var dummyParam = newSym(if modifier == tyTypeDesc: skType else: skVar, var dummyParam = newSym(if modifier == tyTypeDesc: skType else: skVar,
dummyName.ident, owner, param.info) dummyName.ident, owner, param.info)
dummyParam.typ = dummyType dummyParam.typ = dummyType
@ -1289,7 +1316,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
proc semProcTypeWithScope(c: PContext, n: PNode, proc semProcTypeWithScope(c: PContext, n: PNode,
prev: PType, kind: TSymKind): PType = prev: PType, kind: TSymKind): PType =
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
openScope(c) openScope(c)
result = semProcTypeNode(c, n.sons[0], nil, prev, kind, isType=true) result = semProcTypeNode(c, n.sons[0], nil, prev, kind, isType=true)
# start with 'ccClosure', but of course pragmas can overwrite this: # start with 'ccClosure', but of course pragmas can overwrite this:
@ -1299,7 +1326,7 @@ proc semProcTypeWithScope(c: PContext, n: PNode,
s.typ = result s.typ = result
if n.sons[1].kind != nkEmpty and n.sons[1].len > 0: if n.sons[1].kind != nkEmpty and n.sons[1].len > 0:
pragma(c, s, n.sons[1], procTypePragmas) pragma(c, s, n.sons[1], procTypePragmas)
when useEffectSystem: setEffectsForProcType(result, n.sons[1]) when useEffectSystem: setEffectsForProcType(c.graph, result, n.sons[1])
closeScope(c) closeScope(c)
proc maybeAliasType(c: PContext; typeExpr, prev: PType): PType = proc maybeAliasType(c: PContext; typeExpr, prev: PType): PType =
@ -1320,7 +1347,7 @@ proc symFromExpectedTypeNode(c: PContext, n: PNode): PSym =
if n.kind == nkType: if n.kind == nkType:
result = symFromType(n.typ, n.info) result = symFromType(n.typ, n.info)
else: else:
localError(n.info, errTypeExpected) localError(c.config, n.info, errTypeExpected)
result = errorSym(c, n) result = errorSym(c, n)
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
@ -1332,7 +1359,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkEmpty: discard of nkEmpty: discard
of nkTypeOfExpr: of nkTypeOfExpr:
# for ``type(countup(1,3))``, see ``tests/ttoseq``. # for ``type(countup(1,3))``, see ``tests/ttoseq``.
checkSonsLen(n, 1) checkSonsLen(n, 1, c.config)
let typExpr = semExprWithType(c, n.sons[0], {efInTypeof}) let typExpr = semExprWithType(c, n.sons[0], {efInTypeof})
fixupTypeOf(c, prev, typExpr) fixupTypeOf(c, prev, typExpr)
result = typExpr.typ result = typExpr.typ
@ -1362,21 +1389,21 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = freshType(result, prev) result = freshType(result, prev)
result.flags.excl(tfNotNil) result.flags.excl(tfNotNil)
else: else:
localError(n.info, errGenerated, "invalid type") localError(c.config, n.info, errGenerated, "invalid type")
elif n[0].kind notin nkIdentKinds: elif n[0].kind notin nkIdentKinds:
result = semTypeExpr(c, n, prev) result = semTypeExpr(c, n, prev)
else: else:
let op = considerQuotedIdent(n.sons[0]) let op = considerQuotedIdent(c.config, n.sons[0])
if op.id in {ord(wAnd), ord(wOr)} or op.s == "|": if op.id in {ord(wAnd), ord(wOr)} or op.s == "|":
checkSonsLen(n, 3) checkSonsLen(n, 3, c.config)
var var
t1 = semTypeNode(c, n.sons[1], nil) t1 = semTypeNode(c, n.sons[1], nil)
t2 = semTypeNode(c, n.sons[2], nil) t2 = semTypeNode(c, n.sons[2], nil)
if t1 == nil: if t1 == nil:
localError(n.sons[1].info, errTypeExpected) localError(c.config, n.sons[1].info, errTypeExpected)
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
elif t2 == nil: elif t2 == nil:
localError(n.sons[2].info, errTypeExpected) localError(c.config, n.sons[2].info, errTypeExpected)
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
else: else:
result = if op.id == ord(wAnd): makeAndType(c, t1, t2) result = if op.id == ord(wAnd): makeAndType(c, t1, t2)
@ -1390,20 +1417,20 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = freshType(result, prev) result = freshType(result, prev)
result.flags.incl(tfNotNil) result.flags.incl(tfNotNil)
if notnil notin c.features: if notnil notin c.features:
localError(n.info, "enable the 'not nil' annotation with {.experimental: \"notnil\".}") localError(c.config, n.info, "enable the 'not nil' annotation with {.experimental: \"notnil\".}")
else: else:
localError(n.info, errGenerated, "invalid type") localError(c.config, n.info, errGenerated, "invalid type")
of 2: of 2:
let negated = semTypeNode(c, n.sons[1], prev) let negated = semTypeNode(c, n.sons[1], prev)
result = makeNotType(c, negated) result = makeNotType(c, negated)
else: else:
localError(n.info, errGenerated, "invalid type") localError(c.config, n.info, errGenerated, "invalid type")
elif op.id == ord(wPtr): elif op.id == ord(wPtr):
result = semAnyRef(c, n, tyPtr, prev) result = semAnyRef(c, n, tyPtr, prev)
elif op.id == ord(wRef): elif op.id == ord(wRef):
result = semAnyRef(c, n, tyRef, prev) result = semAnyRef(c, n, tyRef, prev)
elif op.id == ord(wType): elif op.id == ord(wType):
checkSonsLen(n, 2) checkSonsLen(n, 2, c.config)
let typExpr = semExprWithType(c, n.sons[1], {efInTypeof}) let typExpr = semExprWithType(c, n.sons[1], {efInTypeof})
fixupTypeOf(c, prev, typExpr) fixupTypeOf(c, prev, typExpr)
result = typExpr.typ result = typExpr.typ
@ -1417,7 +1444,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
if whenResult.kind == nkStmtList: whenResult.kind = nkStmtListType if whenResult.kind == nkStmtList: whenResult.kind = nkStmtListType
result = semTypeNode(c, whenResult, prev) result = semTypeNode(c, whenResult, prev)
of nkBracketExpr: of nkBracketExpr:
checkMinSonsLen(n, 2) checkMinSonsLen(n, 2, c.config)
var head = n.sons[0] var head = n.sons[0]
var s = if head.kind notin nkCallKinds: semTypeIdent(c, head) var s = if head.kind notin nkCallKinds: semTypeIdent(c, head)
else: symFromExpectedTypeNode(c, semExpr(c, head)) else: symFromExpectedTypeNode(c, semExpr(c, head))
@ -1444,7 +1471,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyVar, prev, c) result = newOrPrevType(tyVar, prev, c)
var base = semTypeNode(c, n.sons[1], nil) var base = semTypeNode(c, n.sons[1], nil)
if base.kind in {tyVar, tyLent}: if base.kind in {tyVar, tyLent}:
localError(n.info, errVarVarTypeNotAllowed) localError(c.config, n.info, "type 'var var' is not allowed")
base = base.sons[0] base = base.sons[0]
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base)
of mRef: result = semAnyRef(c, n, tyRef, prev) of mRef: result = semAnyRef(c, n, tyRef, prev)
@ -1454,13 +1481,13 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkDotExpr: of nkDotExpr:
let typeExpr = semExpr(c, n) let typeExpr = semExpr(c, n)
if typeExpr.typ.isNil: if typeExpr.typ.isNil:
localError(n.info, "object constructor needs an object type;" & localError(c.config, n.info, "object constructor needs an object type;" &
" for named arguments use '=' instead of ':'") " for named arguments use '=' instead of ':'")
result = errorType(c) result = errorType(c)
elif typeExpr.typ.kind == tyFromExpr: elif typeExpr.typ.kind == tyFromExpr:
result = typeExpr.typ result = typeExpr.typ
elif typeExpr.typ.kind != tyTypeDesc: elif typeExpr.typ.kind != tyTypeDesc:
localError(n.info, errTypeExpected) localError(c.config, n.info, errTypeExpected)
result = errorType(c) result = errorType(c)
else: else:
result = typeExpr.typ.base result = typeExpr.typ.base
@ -1476,10 +1503,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkIdent, nkAccQuoted: of nkIdent, nkAccQuoted:
var s = semTypeIdent(c, n) var s = semTypeIdent(c, n)
if s.typ == nil: if s.typ == nil:
if s.kind != skError: localError(n.info, errTypeExpected) if s.kind != skError: localError(c.config, n.info, errTypeExpected)
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
elif s.kind == skParam and s.typ.kind == tyTypeDesc: elif s.kind == skParam and s.typ.kind == tyTypeDesc:
internalAssert s.typ.base.kind != tyNone and prev == nil internalAssert c.config, s.typ.base.kind != tyNone and prev == nil
result = s.typ.base result = s.typ.base
elif prev == nil: elif prev == nil:
result = s.typ result = s.typ
@ -1506,10 +1533,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
else: else:
assignType(prev, t) assignType(prev, t)
result = prev result = prev
markUsed(n.info, n.sym, c.graph.usageSym) markUsed(c.config, n.info, n.sym, c.graph.usageSym)
styleCheckUse(n.info, n.sym) styleCheckUse(n.info, n.sym)
else: else:
if s.kind != skError: localError(n.info, errTypeExpected) if s.kind != skError: localError(c.config, n.info, errTypeExpected)
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
of nkObjectTy: result = semObjectNode(c, n, prev) of nkObjectTy: result = semObjectNode(c, n, prev)
of nkTupleTy: result = semTuple(c, n, prev) of nkTupleTy: result = semTuple(c, n, prev)
@ -1547,7 +1574,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of nkStmtListType: result = semStmtListType(c, n, prev) of nkStmtListType: result = semStmtListType(c, n, prev)
of nkBlockType: result = semBlockType(c, n, prev) of nkBlockType: result = semBlockType(c, n, prev)
else: else:
localError(n.info, errTypeExpected) localError(c.config, n.info, errTypeExpected)
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
n.typ = result n.typ = result
dec c.inTypeContext dec c.inTypeContext
@ -1600,10 +1627,10 @@ proc processMagicType(c: PContext, m: PSym) =
of mChar: setMagicType(m, tyChar, 1) of mChar: setMagicType(m, tyChar, 1)
of mString: of mString:
setMagicType(m, tyString, ptrSize) setMagicType(m, tyString, ptrSize)
rawAddSon(m.typ, getSysType(tyChar)) rawAddSon(m.typ, getSysType(c.graph, m.info, tyChar))
of mCstring: of mCstring:
setMagicType(m, tyCString, ptrSize) setMagicType(m, tyCString, ptrSize)
rawAddSon(m.typ, getSysType(tyChar)) rawAddSon(m.typ, getSysType(c.graph, m.info, tyChar))
of mPointer: setMagicType(m, tyPointer, ptrSize) of mPointer: setMagicType(m, tyPointer, ptrSize)
of mEmptySet: of mEmptySet:
setMagicType(m, tySet, 1) setMagicType(m, tySet, 1)
@ -1649,8 +1676,8 @@ proc processMagicType(c: PContext, m: PSym) =
case m.name.s case m.name.s
of "lent": setMagicType(m, tyLent, ptrSize) of "lent": setMagicType(m, tyLent, ptrSize)
of "sink": setMagicType(m, tySink, 0) of "sink": setMagicType(m, tySink, 0)
else: localError(m.info, errTypeExpected) else: localError(c.config, m.info, errTypeExpected)
else: localError(m.info, errTypeExpected) else: localError(c.config, m.info, errTypeExpected)
proc semGenericConstraints(c: PContext, x: PType): PType = proc semGenericConstraints(c: PContext, x: PType): PType =
result = newTypeWithSons(c, tyGenericParam, @[x]) result = newTypeWithSons(c, tyGenericParam, @[x])
@ -1658,11 +1685,11 @@ proc semGenericConstraints(c: PContext, x: PType): PType =
proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
result = copyNode(n) result = copyNode(n)
if n.kind != nkGenericParams: if n.kind != nkGenericParams:
illFormedAst(n) illFormedAst(n, c.config)
return return
for i in countup(0, sonsLen(n)-1): for i in countup(0, sonsLen(n)-1):
var a = n.sons[i] var a = n.sons[i]
if a.kind != nkIdentDefs: illFormedAst(n) if a.kind != nkIdentDefs: illFormedAst(n, c.config)
let L = a.len let L = a.len
var def = a[^1] var def = a[^1]
let constraint = a[^2] let constraint = a[^2]
@ -1708,7 +1735,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
if paramName.safeLen == 2: if paramName.safeLen == 2:
if not nimEnableCovariance or paramName[0].ident.s == "in": if not nimEnableCovariance or paramName[0].ident.s == "in":
if father == nil or sfImportc notin father.sym.flags: if father == nil or sfImportc notin father.sym.flags:
localError(paramName.info, errInOutFlagNotExtern, paramName[0].ident.s) localError(c.config, paramName.info, errInOutFlagNotExtern % $paramName[0])
covarianceFlag = if paramName[0].ident.s == "in": tfContravariant covarianceFlag = if paramName[0].ident.s == "in": tfContravariant
else: tfCovariant else: tfCovariant
if father != nil: father.flags.incl tfCovariant if father != nil: father.flags.incl tfCovariant

View file

@ -1676,7 +1676,7 @@ proc myProcess(c: PPassContext, n: PNode): PNode =
let c = PCtx(c) let c = PCtx(c)
# don't eval errornous code: # don't eval errornous code:
if c.oldErrorCount == c.config.errorCounter: if c.oldErrorCount == c.config.errorCounter:
evalStmt(PCtx(c), n) evalStmt(c, n)
result = emptyNode result = emptyNode
else: else:
result = n result = n