mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-23 03:16:53 +00:00
Merge remote-tracking branch 'nim-lang/devel' into emscripten-support
This commit is contained in:
@@ -477,6 +477,8 @@ type
|
||||
# wildcard type.
|
||||
tfHasAsgn # type has overloaded assignment operator
|
||||
tfBorrowDot # distinct type borrows '.'
|
||||
tfTriggersCompileTime # uses the NimNode type which make the proc
|
||||
# implicitly '.compiletime'
|
||||
|
||||
TTypeFlags* = set[TTypeFlag]
|
||||
|
||||
@@ -1380,6 +1382,9 @@ proc propagateToOwner*(owner, elem: PType) =
|
||||
o2.flags.incl tfHasAsgn
|
||||
owner.flags.incl tfHasAsgn
|
||||
|
||||
if tfTriggersCompileTime in elem.flags:
|
||||
owner.flags.incl tfTriggersCompileTime
|
||||
|
||||
if owner.kind notin {tyProc, tyGenericInst, tyGenericBody,
|
||||
tyGenericInvocation, tyPtr}:
|
||||
let elemB = elem.skipTypes({tyGenericInst})
|
||||
|
||||
@@ -1741,6 +1741,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mEcho: genEcho(p, e[1].skipConv)
|
||||
of mArrToSeq: genArrToSeq(p, e, d)
|
||||
of mNLen..mNError, mSlurp..mQuoteAst:
|
||||
echo "from here ", p.prc.name.s, " ", p.prc.info
|
||||
writestacktrace()
|
||||
localError(e.info, errXMustBeCompileTime, e.sons[0].sym.name.s)
|
||||
of mSpawn:
|
||||
let n = lowerings.wrapProcForSpawn(p.module.module, e, e.typ, nil, nil)
|
||||
@@ -1973,6 +1975,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
genProc(p.module, sym)
|
||||
putLocIntoDest(p, d, sym.loc)
|
||||
of skProc, skConverter, skIterators:
|
||||
if sfCompileTime in sym.flags:
|
||||
localError(n.info, "request to generate code for .compileTime proc: " &
|
||||
sym.name.s)
|
||||
genProc(p.module, sym)
|
||||
if sym.loc.r == nil or sym.loc.t == nil:
|
||||
internalError(n.info, "expr: proc not init " & sym.name.s)
|
||||
@@ -2126,7 +2131,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
# due to a bug/limitation in the lambda lifting, unused inner procs
|
||||
# are not transformed correctly. We work around this issue (#411) here
|
||||
# by ensuring it's no inner proc (owner is a module):
|
||||
if prc.skipGenericOwner.kind == skModule:
|
||||
if prc.skipGenericOwner.kind == skModule and sfCompileTime notin prc.flags:
|
||||
if (optDeadCodeElim notin gGlobalOptions and
|
||||
sfDeadCodeElim notin getModule(prc).flags) or
|
||||
({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
|
||||
|
||||
@@ -1110,7 +1110,7 @@ proc rawNewModule(module: PSym, filename: string): BModule =
|
||||
|
||||
proc nullify[T](arr: var T) =
|
||||
for i in low(arr)..high(arr):
|
||||
arr[i] = nil
|
||||
arr[i] = Rope(nil)
|
||||
|
||||
proc resetModule*(m: BModule) =
|
||||
# between two compilations in CAAS mode, we can throw
|
||||
|
||||
@@ -92,3 +92,4 @@ proc initDefines*() =
|
||||
defineSymbol("nimvarargstyped")
|
||||
defineSymbol("nimtypedescfixed")
|
||||
defineSymbol("nimKnowsNimvm")
|
||||
defineSymbol("nimArrIdx")
|
||||
|
||||
@@ -514,6 +514,7 @@ const
|
||||
{low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent, warnUninit,
|
||||
warnProveField, warnProveIndex,
|
||||
warnGcUnsafe,
|
||||
hintPath, hintConf,
|
||||
hintDependency,
|
||||
hintExecuting,
|
||||
hintCodeBegin, hintCodeEnd,
|
||||
|
||||
@@ -308,7 +308,10 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
|
||||
let gp = finalCallee.ast.sons[genericParamsPos]
|
||||
if gp.kind != nkEmpty:
|
||||
if x.calleeSym.kind notin {skMacro, skTemplate}:
|
||||
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
|
||||
if x.calleeSym.magic in {mArrGet, mArrPut}:
|
||||
finalCallee = x.calleeSym
|
||||
else:
|
||||
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
|
||||
else:
|
||||
# For macros and templates, the resolved generic params
|
||||
# are added as normal params.
|
||||
|
||||
@@ -45,7 +45,8 @@ type
|
||||
TExprFlag* = enum
|
||||
efLValue, efWantIterator, efInTypeof,
|
||||
efWantStmt, efAllowStmt, efDetermineType,
|
||||
efAllowDestructor, efWantValue, efOperand, efNoSemCheck
|
||||
efAllowDestructor, efWantValue, efOperand, efNoSemCheck,
|
||||
efNoProcvarCheck
|
||||
TExprFlags* = set[TExprFlag]
|
||||
|
||||
TTypeAttachedOp* = enum
|
||||
|
||||
@@ -52,7 +52,7 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result.typ = errorType(c)
|
||||
else:
|
||||
# XXX tyGenericInst here?
|
||||
semProcvarCheck(c, result)
|
||||
if efNoProcvarCheck notin flags: semProcvarCheck(c, result)
|
||||
if result.typ.kind == tyVar: result = newDeref(result)
|
||||
semDestructorCheck(c, result, flags)
|
||||
|
||||
@@ -452,18 +452,18 @@ proc changeType(n: PNode, newType: PType, check: bool) =
|
||||
let tup = newType.skipTypes({tyGenericInst})
|
||||
if tup.kind != tyTuple:
|
||||
if tup.kind == tyObject: return
|
||||
internalError(n.info, "changeType: no tuple type for constructor")
|
||||
globalError(n.info, "no tuple type for constructor")
|
||||
elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr:
|
||||
# named tuple?
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
var m = n.sons[i].sons[0]
|
||||
if m.kind != nkSym:
|
||||
internalError(m.info, "changeType(): invalid tuple constr")
|
||||
globalError(m.info, "invalid tuple constructor")
|
||||
return
|
||||
if tup.n != nil:
|
||||
var f = getSymFromList(tup.n, m.sym.name)
|
||||
if f == nil:
|
||||
internalError(m.info, "changeType(): invalid identifier")
|
||||
globalError(m.info, "unknown identifier: " & m.sym.name.s)
|
||||
return
|
||||
changeType(n.sons[i].sons[1], f.typ, check)
|
||||
else:
|
||||
@@ -1156,7 +1156,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result.add(x[0])
|
||||
return
|
||||
checkMinSonsLen(n, 2)
|
||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||
n.sons[0] = semExprWithType(c, n.sons[0], {efNoProcvarCheck})
|
||||
let arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
|
||||
case arr.kind
|
||||
of tyArray, tyOpenArray, tyVarargs, tyArrayConstr, tySequence, tyString,
|
||||
@@ -1196,7 +1196,17 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
localError(n.info, errIndexTypesDoNotMatch)
|
||||
result = n
|
||||
else:
|
||||
c.p.bracketExpr = n.sons[0]
|
||||
let s = if n.sons[0].kind == nkSym: n.sons[0].sym
|
||||
elif n[0].kind in nkSymChoices: n.sons[0][0].sym
|
||||
else: nil
|
||||
if s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators:
|
||||
# type parameters: partial generic specialization
|
||||
n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
|
||||
result = explicitGenericInstantiation(c, n, s)
|
||||
elif s != nil and s.kind == skType:
|
||||
result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
|
||||
else:
|
||||
c.p.bracketExpr = n.sons[0]
|
||||
|
||||
proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
let oldBracketExpr = c.p.bracketExpr
|
||||
@@ -1250,7 +1260,7 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
|
||||
template resultTypeIsInferrable(typ: PType): expr =
|
||||
typ.isMetaType and typ.kind != tyTypeDesc
|
||||
|
||||
proc semAsgn(c: PContext, n: PNode): PNode =
|
||||
proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||
checkSonsLen(n, 2)
|
||||
var a = n.sons[0]
|
||||
case a.kind
|
||||
@@ -1273,12 +1283,15 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||
# --> `[]=`(a, i, x)
|
||||
let oldBracketExpr = c.p.bracketExpr
|
||||
a = semSubscript(c, a, {efLValue})
|
||||
if a == nil:
|
||||
if a == nil and mode != noOverloadedSubscript:
|
||||
result = buildOverloadedSubscripts(n.sons[0], getIdent"[]=")
|
||||
add(result, n[1])
|
||||
result = semExprNoType(c, result)
|
||||
c.p.bracketExpr = oldBracketExpr
|
||||
return result
|
||||
elif a == nil:
|
||||
localError(n.info, "could not resolve: " & $n[0])
|
||||
return n
|
||||
c.p.bracketExpr = oldBracketExpr
|
||||
of nkCurlyExpr:
|
||||
# a{i} = x --> `{}=`(a, i, x)
|
||||
@@ -1323,7 +1336,8 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||
typeMismatch(n, lhs.typ, rhs.typ)
|
||||
|
||||
n.sons[1] = fitNode(c, le, rhs)
|
||||
if tfHasAsgn in lhs.typ.flags and not lhsIsResult:
|
||||
if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
|
||||
mode != noOverloadedAsgn:
|
||||
return overloadedAsgn(c, lhs, n.sons[1])
|
||||
|
||||
fixAbstractType(c, n)
|
||||
@@ -1715,6 +1729,9 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
of mTypeOf:
|
||||
checkSonsLen(n, 2)
|
||||
result = semTypeOf(c, n.sons[1])
|
||||
#of mArrGet: result = semArrGet(c, n, flags)
|
||||
#of mArrPut: result = semArrPut(c, n, flags)
|
||||
#of mAsgn: result = semAsgnOpr(c, n)
|
||||
of mDefined: result = semDefined(c, setMs(n, s), false)
|
||||
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
|
||||
of mCompiles: result = semCompiles(c, setMs(n, s), flags)
|
||||
@@ -2066,6 +2083,19 @@ proc semExport(c: PContext, n: PNode): PNode =
|
||||
c.module.ast.add x
|
||||
result = n
|
||||
|
||||
proc shouldBeBracketExpr(n: PNode): bool =
|
||||
assert n.kind in nkCallKinds
|
||||
let a = n.sons[0]
|
||||
if a.kind in nkCallKinds:
|
||||
let b = a[0]
|
||||
if b.kind in nkSymChoices:
|
||||
for i in 0..<b.len:
|
||||
if b[i].sym.magic == mArrGet:
|
||||
let be = newNodeI(nkBracketExpr, n.info)
|
||||
for i in 1..<a.len: be.add(a[i])
|
||||
n.sons[0] = be
|
||||
return true
|
||||
|
||||
proc setGenericParams(c: PContext, n: PNode) =
|
||||
for i in 1 .. <n.len:
|
||||
n[i].typ = semTypeNode(c, n[i], nil)
|
||||
@@ -2173,7 +2203,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
else:
|
||||
#liMessage(n.info, warnUser, renderTree(n));
|
||||
result = semIndirectOp(c, n, flags)
|
||||
elif n[0].kind == nkBracketExpr and isSymChoice(n[0][0]):
|
||||
elif (n[0].kind == nkBracketExpr or shouldBeBracketExpr(n)) and
|
||||
isSymChoice(n[0][0]):
|
||||
# indirectOp can deal with explicit instantiations; the fixes
|
||||
# the 'newSeq[T](x)' bug
|
||||
setGenericParams(c, n.sons[0])
|
||||
@@ -2194,16 +2225,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
result = semExpr(c, result, flags)
|
||||
of nkBracketExpr:
|
||||
checkMinSonsLen(n, 1)
|
||||
var s = qualifiedLookUp(c, n.sons[0], {checkUndeclared})
|
||||
if (s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators) or
|
||||
n[0].kind in nkSymChoices:
|
||||
# type parameters: partial generic specialization
|
||||
n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
|
||||
result = explicitGenericInstantiation(c, n, s)
|
||||
elif s != nil and s.kind in {skType}:
|
||||
result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
|
||||
else:
|
||||
result = semArrayAccess(c, n, flags)
|
||||
result = semArrayAccess(c, n, flags)
|
||||
of nkCurlyExpr:
|
||||
result = semExpr(c, buildOverloadedSubscripts(n, getIdent"{}"), flags)
|
||||
of nkPragmaExpr:
|
||||
|
||||
@@ -430,17 +430,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||
of mCompileOptionArg:
|
||||
result = newIntNodeT(ord(
|
||||
testCompileOptionArg(getStr(a), getStr(b), n.info)), n)
|
||||
of mNewString, mNewStringOfCap,
|
||||
mExit, mInc, ast.mDec, mEcho, mSwap, mAppendStrCh,
|
||||
mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
|
||||
mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait, mDotDot,
|
||||
mNLen..mNError, mEqRef, mSlurp, mStaticExec, mNGenSym, mSpawn,
|
||||
mParallel, mPlugin, mGetTypeInfo, mTypeOf:
|
||||
discard
|
||||
of mEqProc:
|
||||
result = newIntNodeT(ord(
|
||||
exprStructuralEquivalent(a, b, strictSymEquality=true)), n)
|
||||
else: internalError(a.info, "evalOp(" & $m & ')')
|
||||
else: discard
|
||||
|
||||
proc getConstIfExpr(c: PSym, n: PNode): PNode =
|
||||
result = nil
|
||||
|
||||
@@ -30,6 +30,13 @@ type
|
||||
GenericCtx = object
|
||||
toMixin: IntSet
|
||||
cursorInBody: bool # only for nimsuggest
|
||||
bracketExpr: PNode
|
||||
|
||||
template withBracketExpr(x, body: untyped) =
|
||||
let old = ctx.bracketExpr
|
||||
ctx.bracketExpr = x
|
||||
body
|
||||
ctx.bracketExpr = old
|
||||
|
||||
type
|
||||
TSemGenericFlag = enum
|
||||
@@ -227,6 +234,10 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
discard
|
||||
of skProc, skMethod, skIterators, skConverter, skModule:
|
||||
result.sons[0] = symChoice(c, fn, s, scOption)
|
||||
# do check of 's.magic==mRoof' here because it might be some
|
||||
# other '^' but after overload resolution the proper one:
|
||||
if ctx.bracketExpr != nil and n.len == 2 and s.name.s == "^":
|
||||
result.add ctx.bracketExpr
|
||||
first = 1
|
||||
of skGenericParam:
|
||||
result.sons[0] = newSymNodeTypeDesc(s, fn.info)
|
||||
@@ -251,6 +262,40 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
let flags = if mixinContext: flags+{withinMixin} else: flags
|
||||
for i in countup(first, sonsLen(result) - 1):
|
||||
result.sons[i] = semGenericStmt(c, result.sons[i], flags, ctx)
|
||||
of nkCurlyExpr:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(getIdent("{}"), n.info)
|
||||
for i in 0 ..< n.len: result.add(n[i])
|
||||
result = semGenericStmt(c, result, flags, ctx)
|
||||
of nkBracketExpr:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(getIdent("[]"), n.info)
|
||||
for i in 0 ..< n.len: result.add(n[i])
|
||||
withBracketExpr n.sons[0]:
|
||||
result = semGenericStmt(c, result, flags, ctx)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
checkSonsLen(n, 2)
|
||||
let a = n.sons[0]
|
||||
let b = n.sons[1]
|
||||
|
||||
let k = a.kind
|
||||
case k
|
||||
of nkCurlyExpr:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(getIdent("{}="), n.info)
|
||||
for i in 0 ..< a.len: result.add(a[i])
|
||||
result.add(b)
|
||||
result = semGenericStmt(c, result, flags, ctx)
|
||||
of nkBracketExpr:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(getIdent("[]="), n.info)
|
||||
for i in 0 ..< a.len: result.add(a[i])
|
||||
result.add(b)
|
||||
withBracketExpr a.sons[0]:
|
||||
result = semGenericStmt(c, result, flags, ctx)
|
||||
else:
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
|
||||
of nkIfStmt:
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, ctx)
|
||||
|
||||
@@ -246,6 +246,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||
inc i
|
||||
pushProcCon(c, result)
|
||||
instantiateProcType(c, pt, result, info)
|
||||
if tfTriggersCompileTime in result.typ.flags:
|
||||
incl(result.flags, sfCompileTime)
|
||||
n.sons[genericParamsPos] = ast.emptyNode
|
||||
var oldPrc = genericCacheGet(fn, entry[])
|
||||
if oldPrc == nil:
|
||||
|
||||
@@ -26,6 +26,41 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
|
||||
result.add typExpr
|
||||
result.typ = makeTypeDesc(c, typExpr.typ.skipTypes({tyTypeDesc, tyIter}))
|
||||
|
||||
type
|
||||
SemAsgnMode = enum asgnNormal, noOverloadedSubscript, noOverloadedAsgn
|
||||
|
||||
proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode
|
||||
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
|
||||
proc skipAddr(n: PNode): PNode {.inline.} =
|
||||
(if n.kind == nkHiddenAddr: n.sons[0] else: n)
|
||||
|
||||
proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
|
||||
result = newNodeI(nkBracketExpr, n.info)
|
||||
for i in 1..<n.len: result.add(n[i])
|
||||
let oldBracketExpr = c.p.bracketExpr
|
||||
result = semSubscript(c, result, flags)
|
||||
c.p.bracketExpr = oldBracketExpr
|
||||
if result.isNil:
|
||||
localError(n.info, "could not resolve: " & $n)
|
||||
result = n
|
||||
|
||||
proc semArrPut(c: PContext; n: PNode; flags: TExprFlags): PNode =
|
||||
# rewrite `[]=`(a, i, x) back to ``a[i] = x``.
|
||||
let b = newNodeI(nkBracketExpr, n.info)
|
||||
b.add(n[1].skipAddr)
|
||||
for i in 2..n.len-2: b.add(n[i])
|
||||
result = newNodeI(nkAsgn, n.info, 2)
|
||||
result.sons[0] = b
|
||||
result.sons[1] = n.lastSon
|
||||
result = semAsgn(c, result, noOverloadedSubscript)
|
||||
|
||||
proc semAsgnOpr(c: PContext; n: PNode): PNode =
|
||||
result = newNodeI(nkAsgn, n.info, 2)
|
||||
result.sons[0] = n[1]
|
||||
result.sons[1] = n[2]
|
||||
result = semAsgn(c, result, noOverloadedAsgn)
|
||||
|
||||
proc semIsPartOf(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
var r = isPartOf(n[1], n[2])
|
||||
result = newIntNodeT(ord(r), n)
|
||||
@@ -125,6 +160,9 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
of mTypeOf:
|
||||
checkSonsLen(n, 2)
|
||||
result = semTypeOf(c, n.sons[1])
|
||||
of mArrGet: result = semArrGet(c, n, flags)
|
||||
of mArrPut: result = semArrPut(c, n, flags)
|
||||
of mAsgn: result = semAsgnOpr(c, n)
|
||||
of mIsPartOf: result = semIsPartOf(c, n, flags)
|
||||
of mTypeTrait: result = semTypeTraits(c, n)
|
||||
of mAstToStr:
|
||||
@@ -145,25 +183,28 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
if isNegative(n.sons[1]) or (n.len > 2 and isNegative(n.sons[2])):
|
||||
localError(n.info, "use '^' instead of '-'; negative indexing is obsolete")
|
||||
of mRoof:
|
||||
# error correction:
|
||||
result = n.sons[1]
|
||||
if c.p.bracketExpr.isNil:
|
||||
let bracketExpr = if n.len == 3: n.sons[2] else: c.p.bracketExpr
|
||||
if bracketExpr.isNil:
|
||||
localError(n.info, "no surrounding array access context for '^'")
|
||||
elif c.p.bracketExpr.checkForSideEffects != seNoSideEffect:
|
||||
result = n.sons[1]
|
||||
elif bracketExpr.checkForSideEffects != seNoSideEffect:
|
||||
localError(n.info, "invalid context for '^' as '$#' has side effects" %
|
||||
renderTree(c.p.bracketExpr))
|
||||
elif c.p.bracketExpr.typ.isStrangeArray:
|
||||
renderTree(bracketExpr))
|
||||
result = n.sons[1]
|
||||
elif bracketExpr.typ.isStrangeArray:
|
||||
localError(n.info, "invalid context for '^' as len!=high+1 for '$#'" %
|
||||
renderTree(c.p.bracketExpr))
|
||||
renderTree(bracketExpr))
|
||||
result = n.sons[1]
|
||||
else:
|
||||
# ^x is rewritten to: len(a)-x
|
||||
let lenExpr = newNodeI(nkCall, n.info)
|
||||
lenExpr.add newIdentNode(getIdent"len", n.info)
|
||||
lenExpr.add c.p.bracketExpr
|
||||
lenExpr.add bracketExpr
|
||||
let lenExprB = semExprWithType(c, lenExpr)
|
||||
if lenExprB.typ.isNil or not isOrdinalType(lenExprB.typ):
|
||||
localError(n.info, "'$#' has to be of an ordinal type for '^'" %
|
||||
renderTree(lenExpr))
|
||||
result = n.sons[1]
|
||||
else:
|
||||
result = newNodeIT(nkCall, n.info, getSysType(tyInt))
|
||||
result.add newSymNode(createMagic("-", mSubI), n.info)
|
||||
|
||||
@@ -1033,6 +1033,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
|
||||
"signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T")
|
||||
incl(s.flags, sfUsed)
|
||||
of "=":
|
||||
if s.magic == mAsgn: return
|
||||
incl(s.flags, sfUsed)
|
||||
let t = s.typ
|
||||
if t.len == 3 and t.sons[0] == nil and t.sons[1].kind == tyVar:
|
||||
@@ -1131,6 +1132,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
# semParamList(c, n.sons[ParamsPos], nil, s)
|
||||
else:
|
||||
s.typ = newProcType(c, n.info)
|
||||
if tfTriggersCompileTime in s.typ.flags: incl(s.flags, sfCompileTime)
|
||||
if n.sons[patternPos].kind != nkEmpty:
|
||||
n.sons[patternPos] = semPattern(c, n.sons[patternPos])
|
||||
if s.kind in skIterators:
|
||||
|
||||
@@ -281,6 +281,35 @@ proc semTemplBodySons(c: var TemplCtx, n: PNode): PNode =
|
||||
for i in 0.. < n.len:
|
||||
result.sons[i] = semTemplBody(c, n.sons[i])
|
||||
|
||||
proc wrapInBind(c: var TemplCtx; n: PNode; opr: string): PNode =
|
||||
let ident = getIdent(opr)
|
||||
if ident.id in c.toInject: return n
|
||||
|
||||
let s = searchInScopes(c.c, ident)
|
||||
if s != nil:
|
||||
var callee: PNode
|
||||
if contains(c.toBind, s.id):
|
||||
callee = symChoice(c.c, n, s, scClosed)
|
||||
elif contains(c.toMixin, s.name.id):
|
||||
callee = symChoice(c.c, n, s, scForceOpen)
|
||||
elif s.owner == c.owner and sfGenSym in s.flags:
|
||||
# template tmp[T](x: var seq[T]) =
|
||||
# var yz: T
|
||||
incl(s.flags, sfUsed)
|
||||
callee = newSymNode(s, n.info)
|
||||
styleCheckUse(n.info, s)
|
||||
else:
|
||||
callee = semTemplSymbol(c.c, n, s)
|
||||
|
||||
let call = newNodeI(nkCall, n.info)
|
||||
call.add(callee)
|
||||
for i in 0 .. n.len-1: call.add(n[i])
|
||||
result = newNodeI(nkBind, n.info, 2)
|
||||
result.sons[0] = n
|
||||
result.sons[1] = call
|
||||
else:
|
||||
result = n
|
||||
|
||||
proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
result = n
|
||||
semIdeForTemplateOrGenericCheck(n, c.cursorInBody)
|
||||
@@ -423,6 +452,28 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
result.sons[1] = semTemplBody(c, n.sons[1])
|
||||
of nkPragma:
|
||||
result = onlyReplaceParams(c, n)
|
||||
of nkBracketExpr, nkCurlyExpr:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(getIdent(if n.kind == nkBracketExpr:"[]" else:"{}"),
|
||||
n.info)
|
||||
for i in 0 ..< n.len: result.add(n[i])
|
||||
result = semTemplBodySons(c, result)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
checkSonsLen(n, 2)
|
||||
let a = n.sons[0]
|
||||
let b = n.sons[1]
|
||||
|
||||
let k = a.kind
|
||||
case k
|
||||
of nkBracketExpr, nkCurlyExpr:
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add newIdentNode(getIdent(if k == nkBracketExpr:"[]=" else:"{}="),
|
||||
n.info)
|
||||
for i in 0 ..< a.len: result.add(a[i])
|
||||
result.add(b)
|
||||
else:
|
||||
result = n
|
||||
result = semTemplBodySons(c, result)
|
||||
else:
|
||||
# dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
|
||||
# so we use the generic code for nkDotExpr too
|
||||
|
||||
@@ -718,12 +718,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
if paramType == nil: return # (e.g. proc return type)
|
||||
|
||||
proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType =
|
||||
let finalTypId = if typId != nil: typId
|
||||
else: getIdent(paramName & ":type")
|
||||
if genericParams == nil:
|
||||
# This happens with anonymous proc types appearing in signatures
|
||||
# XXX: we need to lift these earlier
|
||||
return
|
||||
let finalTypId = if typId != nil: typId
|
||||
else: getIdent(paramName & ":type")
|
||||
# is this a bindOnce type class already present in the param list?
|
||||
for i in countup(0, genericParams.len - 1):
|
||||
if genericParams.sons[i].sym.name.id == finalTypId.id:
|
||||
@@ -757,7 +757,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
|
||||
case paramType.kind:
|
||||
of tyAnything:
|
||||
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
|
||||
result = addImplicitGenericImpl(newTypeS(tyGenericParam, c), nil)
|
||||
|
||||
of tyStatic:
|
||||
# proc(a: expr{string}, b: expr{nkLambda})
|
||||
@@ -868,6 +868,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||
of tyExpr:
|
||||
if procKind notin {skMacro, skTemplate}:
|
||||
result = addImplicitGeneric(newTypeS(tyAnything, c))
|
||||
#result = addImplicitGenericImpl(newTypeS(tyGenericParam, c), nil)
|
||||
|
||||
of tyGenericParam:
|
||||
markUsed(info, paramType.sym)
|
||||
@@ -977,7 +978,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
# compiler only checks for 'nil':
|
||||
if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
|
||||
# 'auto' as a return type does not imply a generic:
|
||||
if r.kind != tyExpr:
|
||||
if r.kind == tyAnything:
|
||||
# 'p(): auto' and 'p(): expr' are equivalent, but the rest of the
|
||||
# compiler is hardly aware of 'auto':
|
||||
r = newTypeS(tyExpr, c)
|
||||
elif r.kind != tyExpr:
|
||||
if r.sym == nil or sfAnon notin r.sym.flags:
|
||||
let lifted = liftParamType(c, kind, genericParams, r, "result",
|
||||
n.sons[0].info)
|
||||
@@ -1149,7 +1154,17 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
else:
|
||||
result = semAnonTuple(c, n, prev)
|
||||
of nkCallKinds:
|
||||
if isRange(n):
|
||||
let x = n[0]
|
||||
let ident = case x.kind
|
||||
of nkIdent: x.ident
|
||||
of nkSym: x.sym.name
|
||||
of nkClosedSymChoice, nkOpenSymChoice: x[0].sym.name
|
||||
else: nil
|
||||
if ident != nil and ident.s == "[]":
|
||||
let b = newNodeI(nkBracketExpr, n.info)
|
||||
for i in 1..<n.len: b.add(n[i])
|
||||
result = semTypeNode(c, b, prev)
|
||||
elif ident != nil and ident.id == ord(wDotDot):
|
||||
result = semRangeAux(c, n, prev)
|
||||
elif n[0].kind notin nkIdentKinds:
|
||||
result = semTypeExpr(c, n)
|
||||
@@ -1336,8 +1351,11 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||
of mIntSetBaseType: setMagicType(m, tyRange, intSize)
|
||||
of mNil: setMagicType(m, tyNil, ptrSize)
|
||||
of mExpr:
|
||||
setMagicType(m, tyExpr, 0)
|
||||
if m.name.s == "expr": m.typ.flags.incl tfOldSchoolExprStmt
|
||||
if m.name.s == "auto":
|
||||
setMagicType(m, tyAnything, 0)
|
||||
else:
|
||||
setMagicType(m, tyExpr, 0)
|
||||
if m.name.s == "expr": m.typ.flags.incl tfOldSchoolExprStmt
|
||||
of mStmt:
|
||||
setMagicType(m, tyStmt, 0)
|
||||
if m.name.s == "stmt": m.typ.flags.incl tfOldSchoolExprStmt
|
||||
@@ -1365,7 +1383,8 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||
of mOrdinal:
|
||||
setMagicType(m, tyOrdinal, 0)
|
||||
rawAddSon(m.typ, newTypeS(tyNone, c))
|
||||
of mPNimrodNode: discard
|
||||
of mPNimrodNode:
|
||||
incl m.typ.flags, tfTriggersCompileTime
|
||||
of mShared:
|
||||
setMagicType(m, tyObject, 0)
|
||||
m.typ.n = newNodeI(nkRecList, m.info)
|
||||
|
||||
@@ -1691,6 +1691,10 @@ proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||
matchesAux(c, n, nOrig, m, marker)
|
||||
|
||||
proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||
if m.calleeSym != nil and m.calleeSym.magic in {mArrGet, mArrPut}:
|
||||
m.state = csMatch
|
||||
m.call = n
|
||||
return
|
||||
var marker = initIntSet()
|
||||
matchesAux(c, n, nOrig, m, marker)
|
||||
if m.state == csNoMatch: return
|
||||
|
||||
@@ -116,7 +116,7 @@ type class matches
|
||||
``array`` any array type
|
||||
``set`` any set type
|
||||
``seq`` any seq type
|
||||
``auto`` any type
|
||||
``any`` any type
|
||||
================== ===================================================
|
||||
|
||||
Furthermore, every generic type automatically creates a type class of the same
|
||||
@@ -163,15 +163,6 @@ module to illustrate this:
|
||||
Alternatively, the ``distinct`` type modifier can be applied to the type class
|
||||
to allow each param matching the type class to bind to a different type.
|
||||
|
||||
If a proc param doesn't have a type specified, Nim will use the
|
||||
``distinct auto`` type class (also known as ``any``). Note this behavior is
|
||||
deprecated for procs; templates, however, support them:
|
||||
|
||||
.. code-block:: nim
|
||||
# allow any combination of param types
|
||||
proc concat(a, b): string = $a & $b # deprecated
|
||||
proc concat(a, b: any): string = $a & $b # preferred
|
||||
|
||||
Procs written with the implicitly generic style will often need to refer to the
|
||||
type parameters of the matched generic type. They can be easily accessed using
|
||||
the dot syntax:
|
||||
|
||||
@@ -72,7 +72,20 @@ compileTime pragma
|
||||
------------------
|
||||
The ``compileTime`` pragma is used to mark a proc or variable to be used at
|
||||
compile time only. No code will be generated for it. Compile time procs are
|
||||
useful as helpers for macros.
|
||||
useful as helpers for macros. Since version 0.12.0 of the language, a proc
|
||||
that uses ``system.NimNode`` within its parameter types is implictly declared
|
||||
``compileTime``:
|
||||
|
||||
.. code-block:: nim
|
||||
proc astHelper(n: NimNode): NimNode =
|
||||
result = n
|
||||
|
||||
Is the same as:
|
||||
|
||||
.. code-block:: nim
|
||||
proc astHelper(n: NimNode): NimNode {.compileTime.} =
|
||||
result = n
|
||||
|
||||
|
||||
noReturn pragma
|
||||
---------------
|
||||
|
||||
@@ -1228,3 +1228,27 @@ However, a ``void`` type cannot be inferred in generic code:
|
||||
|
||||
The ``void`` type is only valid for parameters and return types; other symbols
|
||||
cannot have the type ``void``.
|
||||
|
||||
|
||||
Auto type
|
||||
---------
|
||||
|
||||
The ``auto`` type can only be used for return types and parameters. For return
|
||||
types it causes the compiler to infer the type from the routine body:
|
||||
|
||||
.. code-block:: nim
|
||||
proc returnsInt(): auto = 1984
|
||||
|
||||
For parameters it currently creates implicitly generic routines:
|
||||
|
||||
.. code-block:: nim
|
||||
proc foo(a, b: auto) = discard
|
||||
|
||||
Is the same as:
|
||||
|
||||
.. code-block:: nim
|
||||
proc foo[T1, T2](a: T1, b: T2) = discard
|
||||
|
||||
However later versions of the language might change this to mean "infer the
|
||||
parameters' types from the body". Then the above ``foo`` would be rejected as
|
||||
the parameters' types can not be infered from an empty ``discard`` statement.
|
||||
|
||||
@@ -2316,7 +2316,7 @@ proc timer_settime*(a1: Timer, a2: cint, a3: var Itimerspec,
|
||||
proc tzset*() {.importc, header: "<time.h>".}
|
||||
|
||||
|
||||
proc wait*(a1: var cint): Pid {.importc, header: "<sys/wait.h>".}
|
||||
proc wait*(a1: ptr cint): Pid {.importc, discardable, header: "<sys/wait.h>".}
|
||||
proc waitid*(a1: cint, a2: Id, a3: var SigInfo, a4: cint): cint {.
|
||||
importc, header: "<sys/wait.h>".}
|
||||
proc waitpid*(a1: Pid, a2: var cint, a3: cint): Pid {.
|
||||
|
||||
@@ -533,6 +533,18 @@ proc getSockOpt*(socket: Socket, opt: SOBool, level = SOL_SOCKET): bool {.
|
||||
var res = getSockOptInt(socket.fd, cint(level), toCInt(opt))
|
||||
result = res != 0
|
||||
|
||||
proc getLocalAddr*(socket: Socket): (string, Port) =
|
||||
## Get the socket's local address and port number.
|
||||
##
|
||||
## This is high-level interface for `getsockname`:idx:.
|
||||
getLocalAddr(socket.fd, socket.domain)
|
||||
|
||||
proc getPeerAddr*(socket: Socket): (string, Port) =
|
||||
## Get the socket's peer address and port number.
|
||||
##
|
||||
## This is high-level interface for `getpeername`:idx:.
|
||||
getPeerAddr(socket.fd, socket.domain)
|
||||
|
||||
proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) {.
|
||||
tags: [WriteIOEffect].} =
|
||||
## Sets option ``opt`` to a boolean value specified by ``value``.
|
||||
|
||||
@@ -371,6 +371,76 @@ proc getSockName*(socket: SocketHandle): Port =
|
||||
raiseOSError(osLastError())
|
||||
result = Port(rawsockets.ntohs(name.sin_port))
|
||||
|
||||
proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
|
||||
## returns the socket's local address and port number.
|
||||
##
|
||||
## Similar to POSIX's `getsockname`:idx:.
|
||||
case domain
|
||||
of AF_INET:
|
||||
var name: Sockaddr_in
|
||||
when useWinVersion:
|
||||
name.sin_family = int16(ord(AF_INET))
|
||||
else:
|
||||
name.sin_family = posix.AF_INET
|
||||
var namelen = sizeof(name).SockLen
|
||||
if getsockname(socket, cast[ptr SockAddr](addr(name)),
|
||||
addr(namelen)) == -1'i32:
|
||||
raiseOSError(osLastError())
|
||||
result = ($inet_ntoa(name.sin_addr), Port(rawsockets.ntohs(name.sin_port)))
|
||||
of AF_INET6:
|
||||
var name: Sockaddr_in6
|
||||
when useWinVersion:
|
||||
name.sin6_family = int16(ord(AF_INET6))
|
||||
else:
|
||||
name.sin6_family = posix.AF_INET6
|
||||
var namelen = sizeof(name).SockLen
|
||||
if getsockname(socket, cast[ptr SockAddr](addr(name)),
|
||||
addr(namelen)) == -1'i32:
|
||||
raiseOSError(osLastError())
|
||||
# Cannot use INET6_ADDRSTRLEN here, because it's a C define.
|
||||
var buf: array[64, char]
|
||||
if inet_ntop(name.sin6_family.cint,
|
||||
addr name, buf.cstring, sizeof(buf).int32).isNil:
|
||||
raiseOSError(osLastError())
|
||||
result = ($buf, Port(rawsockets.ntohs(name.sin6_port)))
|
||||
else:
|
||||
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
|
||||
|
||||
proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
|
||||
## returns the socket's peer address and port number.
|
||||
##
|
||||
## Similar to POSIX's `getpeername`:idx:
|
||||
case domain
|
||||
of AF_INET:
|
||||
var name: Sockaddr_in
|
||||
when useWinVersion:
|
||||
name.sin_family = int16(ord(AF_INET))
|
||||
else:
|
||||
name.sin_family = posix.AF_INET
|
||||
var namelen = sizeof(name).SockLen
|
||||
if getpeername(socket, cast[ptr SockAddr](addr(name)),
|
||||
addr(namelen)) == -1'i32:
|
||||
raiseOSError(osLastError())
|
||||
result = ($inet_ntoa(name.sin_addr), Port(rawsockets.ntohs(name.sin_port)))
|
||||
of AF_INET6:
|
||||
var name: Sockaddr_in6
|
||||
when useWinVersion:
|
||||
name.sin6_family = int16(ord(AF_INET6))
|
||||
else:
|
||||
name.sin6_family = posix.AF_INET6
|
||||
var namelen = sizeof(name).SockLen
|
||||
if getpeername(socket, cast[ptr SockAddr](addr(name)),
|
||||
addr(namelen)) == -1'i32:
|
||||
raiseOSError(osLastError())
|
||||
# Cannot use INET6_ADDRSTRLEN here, because it's a C define.
|
||||
var buf: array[64, char]
|
||||
if inet_ntop(name.sin6_family.cint,
|
||||
addr name, buf.cstring, sizeof(buf).int32).isNil:
|
||||
raiseOSError(osLastError())
|
||||
result = ($buf, Port(rawsockets.ntohs(name.sin6_port)))
|
||||
else:
|
||||
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
|
||||
|
||||
proc getSockOptInt*(socket: SocketHandle, level, optname: int): int {.
|
||||
tags: [ReadIOEffect].} =
|
||||
## getsockopt for integer options.
|
||||
|
||||
@@ -78,7 +78,7 @@ type
|
||||
stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates)
|
||||
typedesc* {.magic: TypeDesc.} ## meta type to denote a type description
|
||||
void* {.magic: "VoidType".} ## meta type to denote the absence of any type
|
||||
auto* = expr ## meta type for automatic type determination
|
||||
auto* {.magic: Expr.} ## meta type for automatic type determination
|
||||
any* = distinct auto ## meta type for any supported type
|
||||
untyped* {.magic: Expr.} ## meta type to denote an expression that
|
||||
## is not resolved (for templates)
|
||||
@@ -104,7 +104,7 @@ type
|
||||
SomeNumber* = SomeInteger|SomeReal
|
||||
## type class matching all number types
|
||||
|
||||
proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
|
||||
proc defined*(x: expr): bool {.magic: "Defined", noSideEffect, compileTime.}
|
||||
## Special compile-time procedure that checks whether `x` is
|
||||
## defined.
|
||||
## `x` is an external symbol introduced through the compiler's
|
||||
@@ -125,7 +125,7 @@ when defined(nimalias):
|
||||
TNumber: SomeNumber,
|
||||
TOrdinal: SomeOrdinal].}
|
||||
|
||||
proc declared*(x: expr): bool {.magic: "Defined", noSideEffect.}
|
||||
proc declared*(x: expr): bool {.magic: "Defined", noSideEffect, compileTime.}
|
||||
## Special compile-time procedure that checks whether `x` is
|
||||
## declared. `x` has to be an identifier or a qualified identifier.
|
||||
## This can be used to check whether a library provides a certain
|
||||
@@ -140,11 +140,11 @@ when defined(useNimRtl):
|
||||
{.deadCodeElim: on.}
|
||||
|
||||
proc definedInScope*(x: expr): bool {.
|
||||
magic: "DefinedInScope", noSideEffect, deprecated.}
|
||||
magic: "DefinedInScope", noSideEffect, deprecated, compileTime.}
|
||||
## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead.
|
||||
|
||||
proc declaredInScope*(x: expr): bool {.
|
||||
magic: "DefinedInScope", noSideEffect.}
|
||||
magic: "DefinedInScope", noSideEffect, compileTime.}
|
||||
## Special compile-time procedure that checks whether `x` is
|
||||
## declared in the current scope. `x` has to be an identifier.
|
||||
|
||||
@@ -160,7 +160,7 @@ proc unsafeAddr*[T](x: var T): ptr T {.magic: "Addr", noSideEffect.} =
|
||||
## Cannot be overloaded.
|
||||
discard
|
||||
|
||||
proc `type`*(x: expr): typeDesc {.magic: "TypeOf", noSideEffect.} =
|
||||
proc `type`*(x: expr): typeDesc {.magic: "TypeOf", noSideEffect, compileTime.} =
|
||||
## Builtin 'type' operator for accessing the type of an expression.
|
||||
## Cannot be overloaded.
|
||||
discard
|
||||
@@ -239,6 +239,14 @@ type
|
||||
seq*{.magic: "Seq".}[T] ## Generic type to construct sequences.
|
||||
set*{.magic: "Set".}[T] ## Generic type to construct bit sets.
|
||||
|
||||
when defined(nimArrIdx):
|
||||
# :array|openarray|string|seq|cstring|tuple
|
||||
proc `[]`*[I: Ordinal;T](a: T; i: I): T {.
|
||||
noSideEffect, magic: "ArrGet".}
|
||||
proc `[]=`*[I: Ordinal;T,S](a: var T; i: I;
|
||||
x: S) {.noSideEffect, magic: "ArrPut".}
|
||||
proc `=`*[T](dest: var T; src: T) {.noSideEffect, magic: "Asgn".}
|
||||
|
||||
type
|
||||
Slice*[T] = object ## builtin slice type
|
||||
a*, b*: T ## the bounds
|
||||
@@ -3384,7 +3392,7 @@ when hasAlloc:
|
||||
x[j+i] = item[j]
|
||||
inc(j)
|
||||
|
||||
proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} =
|
||||
proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect, compileTime.} =
|
||||
## Special compile-time procedure that checks whether `x` can be compiled
|
||||
## without any semantic error.
|
||||
## This can be used to check whether a type supports some operation:
|
||||
@@ -3448,7 +3456,7 @@ when hasAlloc and not defined(nimscript) and not defined(JS):
|
||||
|
||||
include "system/deepcopy"
|
||||
|
||||
proc procCall*(x: expr) {.magic: "ProcCall".} =
|
||||
proc procCall*(x: expr) {.magic: "ProcCall", compileTime.} =
|
||||
## special magic to prohibit dynamic binding for `method`:idx: calls.
|
||||
## This is similar to `super`:idx: in ordinary OO languages.
|
||||
##
|
||||
@@ -3457,6 +3465,7 @@ proc procCall*(x: expr) {.magic: "ProcCall".} =
|
||||
## procCall someMethod(a, b)
|
||||
discard
|
||||
|
||||
proc `^`*[T](x: int; y: openArray[T]): int {.noSideEffect, magic: "Roof".}
|
||||
proc `^`*(x: int): int {.noSideEffect, magic: "Roof".} =
|
||||
## builtin `roof`:idx: operator that can be used for convenient array access.
|
||||
## ``a[^x]`` is rewritten to ``a[a.len-x]``. However currently the ``a``
|
||||
|
||||
@@ -409,7 +409,7 @@ type
|
||||
bytes*: array[0..15, char]
|
||||
|
||||
Sockaddr_in6* {.importc: "SOCKADDR_IN6",
|
||||
header: "winsock2.h".} = object
|
||||
header: "ws2tcpip.h".} = object
|
||||
sin6_family*: int16
|
||||
sin6_port*: int16 # unsigned
|
||||
sin6_flowinfo*: int32 # unsigned
|
||||
@@ -511,6 +511,9 @@ proc connect*(s: SocketHandle, name: ptr SockAddr, namelen: SockLen): cint {.
|
||||
proc getsockname*(s: SocketHandle, name: ptr SockAddr,
|
||||
namelen: ptr SockLen): cint {.
|
||||
stdcall, importc: "getsockname", dynlib: ws2dll.}
|
||||
proc getpeername*(s: SocketHandle, name: ptr SockAddr,
|
||||
namelen: ptr SockLen): cint {.
|
||||
stdcall, importc, dynlib: ws2dll.}
|
||||
proc getsockopt*(s: SocketHandle, level, optname: cint, optval: pointer,
|
||||
optlen: ptr SockLen): cint {.
|
||||
stdcall, importc: "getsockopt", dynlib: ws2dll.}
|
||||
@@ -572,6 +575,9 @@ proc freeaddrinfo*(ai: ptr AddrInfo) {.
|
||||
proc inet_ntoa*(i: InAddr): cstring {.
|
||||
stdcall, importc, dynlib: ws2dll.}
|
||||
|
||||
proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring,
|
||||
stringBufSize: int32): cstring {.stdcall, importc, dynlib: ws2dll.}
|
||||
|
||||
const
|
||||
MAXIMUM_WAIT_OBJECTS* = 0x00000040
|
||||
|
||||
|
||||
9
tests/ccgbugs/tnocodegen_for_compiletime.nim
Normal file
9
tests/ccgbugs/tnocodegen_for_compiletime.nim
Normal file
@@ -0,0 +1,9 @@
|
||||
# bug #1679
|
||||
import macros, tables, hashes
|
||||
proc hash(v: NimNode): Hash = 4 # performance is for suckers
|
||||
macro test(body: stmt): stmt {.immediate.} =
|
||||
var a = initCountTable[NimNode]()
|
||||
a.inc(body)
|
||||
|
||||
test:
|
||||
1 + 1
|
||||
17
tests/generics/mbind_bracket.nim
Normal file
17
tests/generics/mbind_bracket.nim
Normal file
@@ -0,0 +1,17 @@
|
||||
|
||||
import tables
|
||||
|
||||
type
|
||||
UUIDObject* = ref object
|
||||
uuid: string
|
||||
|
||||
Registry*[T] = ref object
|
||||
objects: Table[string, T]
|
||||
|
||||
proc newRegistry*[T](): Registry[T] =
|
||||
result = Registry[T]()
|
||||
result.objects = initTable[string, T](128)
|
||||
|
||||
proc register*[T](self: Registry[T], obj: T) =
|
||||
self.objects[obj.uuid] = obj
|
||||
|
||||
20
tests/generics/tbind_bracket.nim
Normal file
20
tests/generics/tbind_bracket.nim
Normal file
@@ -0,0 +1,20 @@
|
||||
discard """
|
||||
output: "317"
|
||||
"""
|
||||
|
||||
# bug #2599
|
||||
|
||||
import mbind_bracket
|
||||
|
||||
# also test that `[]` can be passed now as a first class construct:
|
||||
|
||||
template takeBracket(x, a, i: untyped) =
|
||||
echo x(a, i)
|
||||
|
||||
var a: array[10, int]
|
||||
a[8] = 317
|
||||
|
||||
takeBracket(`[]`, a, 8)
|
||||
|
||||
let reg = newRegistry[UUIDObject]()
|
||||
reg.register(UUIDObject())
|
||||
@@ -3,7 +3,7 @@ discard """
|
||||
"""
|
||||
|
||||
type
|
||||
TThreadFuncArgs[T] = object of TObject
|
||||
TThreadFuncArgs[T] = object of RootObj
|
||||
a: proc(): T {.thread.}
|
||||
b: proc(val: T) {.thread.}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ type
|
||||
|
||||
proc getTypeName(t: typedesc): string = t.name
|
||||
|
||||
proc foo(T: typedesc[float], a: expr): string =
|
||||
proc foo(T: typedesc[float], a: auto): string =
|
||||
result = "float " & $(a.len > 5)
|
||||
|
||||
proc foo(T: typedesc[TFoo], a: int): string =
|
||||
|
||||
20
tests/types/tauto_excessive.nim
Normal file
20
tests/types/tauto_excessive.nim
Normal file
@@ -0,0 +1,20 @@
|
||||
discard """
|
||||
output: '''10
|
||||
10.0
|
||||
1.0hiho'''
|
||||
"""
|
||||
|
||||
# bug #3224
|
||||
proc f(x: auto): auto =
|
||||
result = $(x+10)
|
||||
|
||||
proc f(x, y: auto): auto =
|
||||
result = $(x+y)
|
||||
|
||||
|
||||
echo f(0) # prints 10
|
||||
echo f(0.0) # prints 10.0
|
||||
|
||||
proc `+`(a, b: string): string = a & b
|
||||
|
||||
echo f(0.7, 0.3), f("hi", "ho")
|
||||
1
todo.txt
1
todo.txt
@@ -24,7 +24,6 @@ version 1.0
|
||||
- The bitwise 'not' operator will be renamed to 'bnot' to
|
||||
prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!
|
||||
- split docgen into separate tool
|
||||
- special rule for ``[]=``, items, pairs
|
||||
- BUG: echo with template `$`*(info: TLineInfo): expr = toFileLineCol(info)
|
||||
- make 'nil' work for 'add':
|
||||
- resizeString
|
||||
|
||||
55
web/news.txt
55
web/news.txt
@@ -3,7 +3,7 @@ News
|
||||
====
|
||||
|
||||
..
|
||||
2015-05-05 Version 0.11.4 released
|
||||
2015-09-14 Version 0.11.4 released
|
||||
==================================
|
||||
|
||||
Changes affecting backwards compatibility
|
||||
@@ -58,7 +58,7 @@ News
|
||||
of all the DLLs the standard library needs. This means that the following
|
||||
DLLs are now split into 32 and 64 versions:
|
||||
|
||||
* ``prce.dll``: Split into ``prce32.dll`` and ``prce64.dll``.
|
||||
* ``pcre.dll``: Split into ``pcre32.dll`` and ``pcre64.dll``.
|
||||
* ``pdcurses.dll``: Split into ``pdcurses32.dll`` and ``pdcurses64.dll``.
|
||||
* ``sqlite3.dll``: Split into ``sqlite3_32.dll`` and ``sqlite3_64.dll``.
|
||||
* ``ssleay32.dll``: Split into ``ssleay32.dll`` and ``ssleay64.dll``.
|
||||
@@ -75,6 +75,13 @@ News
|
||||
with Unix's ``#!``.
|
||||
- An implicit return type for an iterator is now deprecated. Use ``auto`` if
|
||||
you want more type inference.
|
||||
- The type ``auto`` is now a "multi-bind" metatype, so the following compiles:
|
||||
|
||||
.. code-block:: nim
|
||||
proc f(x, y: auto): auto =
|
||||
result = $x & y
|
||||
|
||||
echo f(0, "abc")
|
||||
|
||||
|
||||
Library Additions
|
||||
@@ -95,6 +102,9 @@ News
|
||||
|
||||
- The compiler now supports a new configuration system based on
|
||||
`NimScript <docs/nims.html>`_.
|
||||
- The compiler finally considers symbol binding rules in templates and
|
||||
generics for overloaded ``[]``, ``[]=``, ``{}``, ``{}=`` operators
|
||||
(issue `#2599 <https://github.com/nim-lang/Nim/issues/2599>`_).
|
||||
|
||||
|
||||
Language Additions
|
||||
@@ -112,22 +122,21 @@ News
|
||||
this ``let (x, y) == f()`` still needs to be used.
|
||||
- ``when nimvm`` can now be used for compiletime versions of some code
|
||||
sections. Click `here <docs/manual.html#when-nimvm-statement>`_ for details.
|
||||
- Usage of the type ``NimNode`` in a proc now implicitly annotates the proc
|
||||
with ``.compileTime``. This means generics work much better for ``NimNode``.
|
||||
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
- Fixed "Compiler internal error on iterator it(T: typedesc[Base]) called with
|
||||
it(Child), where Child = object of Base"
|
||||
- Fixed "Compiler internal error on iterator it(T: typedesc[Base]) called with it(Child), where Child = object of Base"
|
||||
(`#2662 <https://github.com/Araq/Nim/issues/2662>`_)
|
||||
- Fixed "repr() misses base object field in 2nd level derived object"
|
||||
(`#2749 <https://github.com/Araq/Nim/issues/2749>`_)
|
||||
- Fixed "nimsuggest doesn't work more than once on the non-main file"
|
||||
(`#2694 <https://github.com/Araq/Nim/issues/2694>`_)
|
||||
- Fixed "JS Codegen. Passing arguments by var in certain cases leads to invali
|
||||
d JS."
|
||||
- Fixed "JS Codegen. Passing arguments by var in certain cases leads to invalid JS."
|
||||
(`#2798 <https://github.com/Araq/Nim/issues/2798>`_)
|
||||
- Fixed ""check" proc in unittest.nim prevents the propagation of changes to v
|
||||
ar parameters."
|
||||
- Fixed ""check" proc in unittest.nim prevents the propagation of changes to var parameters."
|
||||
(`#964 <https://github.com/Araq/Nim/issues/964>`_)
|
||||
- Fixed "Excessive letters in integer literals are not an error"
|
||||
(`#2523 <https://github.com/Araq/Nim/issues/2523>`_)
|
||||
@@ -141,8 +150,7 @@ ar parameters."
|
||||
(`#2687 <https://github.com/Araq/Nim/issues/2687>`_)
|
||||
- Fixed "Compile error using object in const array"
|
||||
(`#2774 <https://github.com/Araq/Nim/issues/2774>`_)
|
||||
- Fixed "httpclient async requests with method httpPOST isn't sending Content-
|
||||
Length header"
|
||||
- Fixed "httpclient async requests with method httpPOST isn't sending Content-Length header"
|
||||
(`#2884 <https://github.com/Araq/Nim/issues/2884>`_)
|
||||
- Fixed "Streams module not working with JS backend"
|
||||
(`#2148 <https://github.com/Araq/Nim/issues/2148>`_)
|
||||
@@ -173,8 +181,7 @@ Length header"
|
||||
(`#2974 <https://github.com/Araq/Nim/issues/2974>`_)
|
||||
- Fixed "repr is broken"
|
||||
(`#2992 <https://github.com/Araq/Nim/issues/2992>`_)
|
||||
- Fixed "Ipv6 devel - add IPv6 support for asyncsockets, make AF_INET6 a defau
|
||||
lt"
|
||||
- Fixed "Ipv6 devel - add IPv6 support for asyncsockets, make AF_INET6 a default"
|
||||
(`#2976 <https://github.com/Araq/Nim/issues/2976>`_)
|
||||
- Fixed "Compilation broken on windows"
|
||||
(`#2996 <https://github.com/Araq/Nim/issues/2996>`_)
|
||||
@@ -184,8 +191,7 @@ lt"
|
||||
(`#2672 <https://github.com/Araq/Nim/issues/2672>`_)
|
||||
- Fixed "Uncatched exception in async procedure on raise statement"
|
||||
(`#3014 <https://github.com/Araq/Nim/issues/3014>`_)
|
||||
- Fixed "nim doc2 fails in Mac OS X due to system.nim (possibly related to #18
|
||||
98)"
|
||||
- Fixed "nim doc2 fails in Mac OS X due to system.nim (possibly related to #1898)"
|
||||
(`#3005 <https://github.com/Araq/Nim/issues/3005>`_)
|
||||
- Fixed "IndexError when rebuilding Nim on iteration 2"
|
||||
(`#3018 <https://github.com/Araq/Nim/issues/3018>`_)
|
||||
@@ -233,8 +239,7 @@ lt"
|
||||
(`#3054 <https://github.com/Araq/Nim/issues/3054>`_)
|
||||
- Fixed "Wrong sharing of static_t instantations"
|
||||
(`#3112 <https://github.com/Araq/Nim/issues/3112>`_)
|
||||
- Fixed "Automatically generated proc conflicts with user-defined proc when .e
|
||||
xportc.'ed"
|
||||
- Fixed "Automatically generated proc conflicts with user-defined proc when .exportc.'ed"
|
||||
(`#3134 <https://github.com/Araq/Nim/issues/3134>`_)
|
||||
- Fixed "getTypeInfo call crashes nim"
|
||||
(`#3099 <https://github.com/Araq/Nim/issues/3099>`_)
|
||||
@@ -254,15 +259,13 @@ xportc.'ed"
|
||||
(`#3149 <https://github.com/Araq/Nim/issues/3149>`_)
|
||||
- Fixed "Inference of `static[T]` in sequences"
|
||||
(`#3144 <https://github.com/Araq/Nim/issues/3144>`_)
|
||||
- Fixed "Argument named "closure" to proc inside template interfere with closu
|
||||
re pragma"
|
||||
- Fixed "Argument named "closure" to proc inside template interfere with closure pragma"
|
||||
(`#3171 <https://github.com/Araq/Nim/issues/3171>`_)
|
||||
- Fixed "Internal error with aliasing inside template"
|
||||
(`#3158 <https://github.com/Araq/Nim/issues/3158>`_)
|
||||
- Fixed "Cardinality of sets prints unexpected value"
|
||||
(`#3135 <https://github.com/Araq/Nim/issues/3135>`_)
|
||||
- Fixed "Nim crashes on const assignment from function returning var ref objec
|
||||
t"
|
||||
- Fixed "Nim crashes on const assignment from function returning var ref object"
|
||||
(`#3103 <https://github.com/Araq/Nim/issues/3103>`_)
|
||||
- Fixed "`repr` cstring"
|
||||
(`#3080 <https://github.com/Araq/Nim/issues/3080>`_)
|
||||
@@ -270,8 +273,7 @@ t"
|
||||
(`#3052 <https://github.com/Araq/Nim/issues/3052>`_)
|
||||
- Fixed "Compiler assertion when evaluating template with static[T]"
|
||||
(`#1858 <https://github.com/Araq/Nim/issues/1858>`_)
|
||||
- Fixed "Erroneous overflow in iterators when compiler built with overflowChec
|
||||
ks enabled"
|
||||
- Fixed "Erroneous overflow in iterators when compiler built with overflowChecks enabled"
|
||||
(`#3140 <https://github.com/Araq/Nim/issues/3140>`_)
|
||||
- Fixed "Unicode dashes as "lisp'ish" alternative to hump and snake notation"
|
||||
(`#2811 <https://github.com/Araq/Nim/issues/2811>`_)
|
||||
@@ -283,8 +285,7 @@ ks enabled"
|
||||
(`#3193 <https://github.com/Araq/Nim/issues/3193>`_)
|
||||
- Fixed "VM crash when accessing array's element"
|
||||
(`#3192 <https://github.com/Araq/Nim/issues/3192>`_)
|
||||
- Fixed "Unexpected proc invoked when different modules add procs to a type fr
|
||||
om a 3rd module"
|
||||
- Fixed "Unexpected proc invoked when different modules add procs to a type from a 3rd module"
|
||||
(`#2664 <https://github.com/Araq/Nim/issues/2664>`_)
|
||||
- Fixed "Nim crashes on conditional declaration inside a template"
|
||||
(`#2670 <https://github.com/Araq/Nim/issues/2670>`_)
|
||||
@@ -292,8 +293,7 @@ om a 3rd module"
|
||||
(`#2752 <https://github.com/Araq/Nim/issues/2752>`_)
|
||||
- Fixed "VM: Cannot assign int value to ref variable"
|
||||
(`#1329 <https://github.com/Araq/Nim/issues/1329>`_)
|
||||
- Fixed "Incorrect code generated for tagged unions with enums not starting at
|
||||
zero"
|
||||
- Fixed "Incorrect code generated for tagged unions with enums not starting at zero"
|
||||
(`#3096 <https://github.com/Araq/Nim/issues/3096>`_)
|
||||
- Fixed "Compile time procs using forward declarations are silently ignored"
|
||||
(`#3066 <https://github.com/Araq/Nim/issues/3066>`_)
|
||||
@@ -301,8 +301,7 @@ om a 3rd module"
|
||||
(`#1965 <https://github.com/Araq/Nim/issues/1965>`_)
|
||||
- Fixed "os.getCreationTime is incorrect/impossible on Posix systems"
|
||||
(`#1058 <https://github.com/Araq/Nim/issues/1058>`_)
|
||||
- Fixed "Improve error message for osproc.startProcess when command does not e
|
||||
xist"
|
||||
- Fixed "Improve error message for osproc.startProcess when command does not exist"
|
||||
(`#2183 <https://github.com/Araq/Nim/issues/2183>`_)
|
||||
- Fixed "gctest segfaults with --gc:markandsweep on x86_64"
|
||||
(`#2305 <https://github.com/Araq/Nim/issues/2305>`_)
|
||||
|
||||
Reference in New Issue
Block a user