Merge branch 'devel' into araq

This commit is contained in:
Andreas Rumpf 2017-11-07 11:17:20 +01:00
commit 617ba1a209
37 changed files with 353 additions and 69 deletions

View file

@ -1067,7 +1067,7 @@ proc genArrayAddr(p: PProc, n: PNode, r: var TCompRes) =
else:
r.res = "chckIndx($1, $2, strlen($3))-$2" % [b.res, rope(first), a.res]
else:
r.res = "chckIndx($1, $2, $3.length-1)-$2" % [b.res, rope(first), a.res]
r.res = "chckIndx($1, $2, $3.length+$2-1)-$2" % [b.res, rope(first), a.res]
elif first != 0:
r.res = "($1)-$2" % [b.res, rope(first)]
else:

View file

@ -764,7 +764,10 @@ proc semCaptureSym*(s, owner: PSym) =
var o = owner.skipGenericOwner
while o.kind != skModule and o != nil:
if s.owner == o:
owner.typ.callConv = ccClosure
if owner.typ.callConv in {ccClosure, ccDefault} or owner.kind == skIterator:
owner.typ.callConv = ccClosure
else:
discard "do not produce an error here, but later"
#echo "computing .closure for ", owner.name.s, " ", owner.info, " because of ", s.name.s
o = o.skipGenericOwner
# since the analysis is not entirely correct, we don't set 'tfCapturesEnv'

View file

@ -52,17 +52,19 @@ proc lookupParam(params, dest: PNode): PSym =
if params[i].kind == nkSym and params[i].sym.name.id == dest.ident.id:
return params[i].sym
proc liftLocalsIfRequested*(prc: PSym) =
proc liftLocalsIfRequested*(prc: PSym; n: PNode): PNode =
let liftDest = getPragmaVal(prc.ast, wLiftLocals)
if liftDest == nil: return
if liftDest == nil: return n
let partialParam = lookupParam(prc.typ.n, liftDest)
if partialParam.isNil:
localError(liftDest.info, "'$1' is not a parameter of '$2'" %
[$liftDest, prc.name.s])
return
return n
let objType = partialParam.typ.skipTypes(abstractPtrs)
if objType.kind != tyObject or tfPartial notin objType.flags:
localError(liftDest.info, "parameter '$1' is not a pointer to a partial object" % $liftDest)
return
return n
var c = Ctx(partialParam: partialParam, objType: objType)
liftLocals(prc.ast, bodyPos, c)
let w = newTree(nkStmtList, n)
liftLocals(w, 0, c)
result = w[0]

View file

@ -98,6 +98,7 @@ proc resolveDollar(project, source, pkg, subdir: string; info: TLineInfo): strin
proc scriptableImport(pkg, sub: string; info: TLineInfo): string =
result = resolveDollar(gProjectFull, info.toFullPath(), pkg, sub, info)
if result.isNil: result = ""
proc lookupPackage(pkg, subdir: PNode): string =
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""
@ -166,7 +167,8 @@ proc checkModuleName*(n: PNode; doLocalError=true): int32 =
let fullPath = findModule(modulename, n.info.toFullPath)
if fullPath.len == 0:
if doLocalError:
localError(n.info, errCannotOpenFile, modulename)
let m = if modulename.len > 0: modulename else: $n
localError(n.info, errCannotOpenFile, m)
result = InvalidFileIDX
else:
result = fullPath.fileInfoIdx
result = fullPath.fileInfoIdx

View file

@ -61,7 +61,7 @@ type
errBaseTypeMustBeOrdinal, errInheritanceOnlyWithNonFinalObjects,
errInheritanceOnlyWithEnums, errIllegalRecursionInTypeX,
errCannotInstantiateX, errExprHasNoAddress, errXStackEscape,
errVarForOutParamNeeded,
errVarForOutParamNeededX,
errPureTypeMismatch, errTypeMismatch, errButExpected, errButExpectedX,
errAmbiguousCallXYZ, errWrongNumberOfArguments,
errWrongNumberOfArgumentsInCall,
@ -268,7 +268,7 @@ const
errCannotInstantiateX: "cannot instantiate: \'$1\'",
errExprHasNoAddress: "expression has no address",
errXStackEscape: "address of '$1' may not escape its stack frame",
errVarForOutParamNeeded: "for a \'var\' type a variable needs to be passed",
errVarForOutParamNeededX: "for a \'var\' type a variable needs to be passed; but '$1' is immutable",
errPureTypeMismatch: "type mismatch",
errTypeMismatch: "type mismatch: got (",
errButExpected: "but expected one of: ",

View file

@ -785,21 +785,58 @@ proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
#| 'else' colcom expr
#| ifExpr = 'if' condExpr
#| whenExpr = 'when' condExpr
result = newNodeP(kind, p)
while true:
getTok(p) # skip `if`, `elif`
var branch = newNodeP(nkElifExpr, p)
when true:
result = newNodeP(kind, p)
while true:
getTok(p) # skip `if`, `when`, `elif`
var branch = newNodeP(nkElifExpr, p)
optInd(p, branch)
addSon(branch, parseExpr(p))
colcom(p, branch)
addSon(branch, parseStmt(p))
skipComment(p, branch)
addSon(result, branch)
if p.tok.tokType != tkElif: break # or not sameOrNoInd(p): break
if p.tok.tokType == tkElse: # and sameOrNoInd(p):
var branch = newNodeP(nkElseExpr, p)
eat(p, tkElse)
colcom(p, branch)
addSon(branch, parseStmt(p))
addSon(result, branch)
else:
var
b: PNode
wasIndented = false
result = newNodeP(kind, p)
getTok(p)
let branch = newNodeP(nkElifExpr, p)
addSon(branch, parseExpr(p))
colcom(p, branch)
let oldInd = p.currInd
if realInd(p):
p.currInd = p.tok.indent
wasIndented = true
echo result.info, " yes ", p.currInd
addSon(branch, parseExpr(p))
optInd(p, branch)
addSon(result, branch)
if p.tok.tokType != tkElif: break
var branch = newNodeP(nkElseExpr, p)
eat(p, tkElse)
colcom(p, branch)
addSon(branch, parseExpr(p))
addSon(result, branch)
result.add branch
while sameInd(p) or not wasIndented:
case p.tok.tokType
of tkElif:
b = newNodeP(nkElifExpr, p)
getTok(p)
optInd(p, b)
addSon(b, parseExpr(p))
of tkElse:
b = newNodeP(nkElseExpr, p)
getTok(p)
else: break
colcom(p, b)
addSon(b, parseStmt(p))
addSon(result, b)
if b.kind == nkElseExpr: break
if wasIndented:
p.currInd = oldInd
proc parsePragma(p: var TParser): PNode =
#| pragma = '{.' optInd (exprColonExpr comma?)* optPar ('.}' | '}')
@ -2036,8 +2073,13 @@ proc parseStmt(p: var TParser): PNode =
if a.kind != nkEmpty:
addSon(result, a)
else:
parMessage(p, errExprExpected, p.tok)
getTok(p)
# This is done to make the new 'if' expressions work better.
# XXX Eventually we need to be more strict here.
if p.tok.tokType notin {tkElse, tkElif}:
parMessage(p, errExprExpected, p.tok)
getTok(p)
else:
break
if not p.hasProgress and p.tok.tokType == tkEof: break
else:
# the case statement is only needed for better error messages:

View file

@ -465,7 +465,7 @@ proc newHiddenAddrTaken(c: PContext, n: PNode): PNode =
result = newNodeIT(nkHiddenAddr, n.info, makeVarType(c, n.typ))
addSon(result, n)
if isAssignable(c, n) notin {arLValue, arLocalLValue}:
localError(n.info, errVarForOutParamNeeded)
localError(n.info, errVarForOutParamNeededX, $n)
proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
result = n
@ -509,9 +509,10 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
for i in countup(1, sonsLen(n) - 1):
if i < sonsLen(t) and t.sons[i] != nil and
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
if isAssignable(c, n.sons[i]) notin {arLValue, arLocalLValue}:
if n.sons[i].kind != nkHiddenAddr:
localError(n.sons[i].info, errVarForOutParamNeeded)
let it = n[i]
if isAssignable(c, it) notin {arLValue, arLocalLValue}:
if it.kind != nkHiddenAddr:
localError(it.info, errVarForOutParamNeededX, $it)
return
for i in countup(1, sonsLen(n) - 1):
if n.sons[i].kind == nkHiddenCallConv:

View file

@ -335,8 +335,10 @@ proc semGenericStmt(c: PContext, n: PNode,
n.sons[L - 2] = semGenericStmt(c, n.sons[L-2], flags, ctx)
for i in countup(0, L - 3):
addTempDecl(c, n.sons[i], skForVar)
openScope(c)
n.sons[L - 1] = semGenericStmt(c, n.sons[L-1], flags, ctx)
closeScope(c)
closeScope(c)
of nkBlockStmt, nkBlockExpr, nkBlockType:
checkSonsLen(n, 2)
openScope(c)

View file

@ -697,7 +697,9 @@ proc semForVars(c: PContext, n: PNode): PNode =
if sfGenSym notin v.flags and not isDiscardUnderscore(v):
addForVarDecl(c, v)
inc(c.p.nestedLoopCounter)
openScope(c)
n.sons[length-1] = semStmt(c, n.sons[length-1])
closeScope(c)
dec(c.p.nestedLoopCounter)
proc implicitIterator(c: PContext, it: string, arg: PNode): PNode =

View file

@ -366,8 +366,10 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
n.sons[L-2] = semTemplBody(c, n.sons[L-2])
for i in countup(0, L - 3):
addLocalDecl(c, n.sons[i], skForVar)
openScope(c)
n.sons[L-1] = semTemplBody(c, n.sons[L-1])
closeScope(c)
closeScope(c)
of nkBlockStmt, nkBlockExpr, nkBlockType:
checkSonsLen(n, 2)
openScope(c)

View file

@ -1057,9 +1057,10 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
else: isNone
of tyUserTypeClass, tyUserTypeClassInst:
if c.c.matchedConcept != nil:
if c.c.matchedConcept != nil and c.c.matchedConcept.depth <= 4:
# consider this: 'var g: Node' *within* a concept where 'Node'
# is a concept too (tgraph)
inc c.c.matchedConcept.depth
let x = typeRel(c, a, f, flags + {trDontBind})
if x >= isGeneric:
return isGeneric

View file

@ -978,7 +978,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
liftDefer(c, result)
#result = liftLambdas(prc, result)
when useEffectSystem: trackProc(prc, result)
liftLocalsIfRequested(prc)
result = liftLocalsIfRequested(prc, result)
if c.needsDestroyPass and newDestructors:
result = injectDestructorCalls(prc, result)
incl(result.flags, nfTransf)