Merge remote-tracking branch 'nim-lang/devel' into emscripten-support
This commit is contained in:
commit
5859fcbabb
32 changed files with 484 additions and 100 deletions
|
|
@ -477,6 +477,8 @@ type
|
||||||
# wildcard type.
|
# wildcard type.
|
||||||
tfHasAsgn # type has overloaded assignment operator
|
tfHasAsgn # type has overloaded assignment operator
|
||||||
tfBorrowDot # distinct type borrows '.'
|
tfBorrowDot # distinct type borrows '.'
|
||||||
|
tfTriggersCompileTime # uses the NimNode type which make the proc
|
||||||
|
# implicitly '.compiletime'
|
||||||
|
|
||||||
TTypeFlags* = set[TTypeFlag]
|
TTypeFlags* = set[TTypeFlag]
|
||||||
|
|
||||||
|
|
@ -1380,6 +1382,9 @@ proc propagateToOwner*(owner, elem: PType) =
|
||||||
o2.flags.incl tfHasAsgn
|
o2.flags.incl tfHasAsgn
|
||||||
owner.flags.incl tfHasAsgn
|
owner.flags.incl tfHasAsgn
|
||||||
|
|
||||||
|
if tfTriggersCompileTime in elem.flags:
|
||||||
|
owner.flags.incl tfTriggersCompileTime
|
||||||
|
|
||||||
if owner.kind notin {tyProc, tyGenericInst, tyGenericBody,
|
if owner.kind notin {tyProc, tyGenericInst, tyGenericBody,
|
||||||
tyGenericInvocation, tyPtr}:
|
tyGenericInvocation, tyPtr}:
|
||||||
let elemB = elem.skipTypes({tyGenericInst})
|
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 mEcho: genEcho(p, e[1].skipConv)
|
||||||
of mArrToSeq: genArrToSeq(p, e, d)
|
of mArrToSeq: genArrToSeq(p, e, d)
|
||||||
of mNLen..mNError, mSlurp..mQuoteAst:
|
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)
|
localError(e.info, errXMustBeCompileTime, e.sons[0].sym.name.s)
|
||||||
of mSpawn:
|
of mSpawn:
|
||||||
let n = lowerings.wrapProcForSpawn(p.module.module, e, e.typ, nil, nil)
|
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)
|
genProc(p.module, sym)
|
||||||
putLocIntoDest(p, d, sym.loc)
|
putLocIntoDest(p, d, sym.loc)
|
||||||
of skProc, skConverter, skIterators:
|
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)
|
genProc(p.module, sym)
|
||||||
if sym.loc.r == nil or sym.loc.t == nil:
|
if sym.loc.r == nil or sym.loc.t == nil:
|
||||||
internalError(n.info, "expr: proc not init " & sym.name.s)
|
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
|
# due to a bug/limitation in the lambda lifting, unused inner procs
|
||||||
# are not transformed correctly. We work around this issue (#411) here
|
# are not transformed correctly. We work around this issue (#411) here
|
||||||
# by ensuring it's no inner proc (owner is a module):
|
# 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
|
if (optDeadCodeElim notin gGlobalOptions and
|
||||||
sfDeadCodeElim notin getModule(prc).flags) or
|
sfDeadCodeElim notin getModule(prc).flags) or
|
||||||
({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
|
({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
|
||||||
|
|
|
||||||
|
|
@ -1110,7 +1110,7 @@ proc rawNewModule(module: PSym, filename: string): BModule =
|
||||||
|
|
||||||
proc nullify[T](arr: var T) =
|
proc nullify[T](arr: var T) =
|
||||||
for i in low(arr)..high(arr):
|
for i in low(arr)..high(arr):
|
||||||
arr[i] = nil
|
arr[i] = Rope(nil)
|
||||||
|
|
||||||
proc resetModule*(m: BModule) =
|
proc resetModule*(m: BModule) =
|
||||||
# between two compilations in CAAS mode, we can throw
|
# between two compilations in CAAS mode, we can throw
|
||||||
|
|
|
||||||
|
|
@ -92,3 +92,4 @@ proc initDefines*() =
|
||||||
defineSymbol("nimvarargstyped")
|
defineSymbol("nimvarargstyped")
|
||||||
defineSymbol("nimtypedescfixed")
|
defineSymbol("nimtypedescfixed")
|
||||||
defineSymbol("nimKnowsNimvm")
|
defineSymbol("nimKnowsNimvm")
|
||||||
|
defineSymbol("nimArrIdx")
|
||||||
|
|
|
||||||
|
|
@ -514,6 +514,7 @@ const
|
||||||
{low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent, warnUninit,
|
{low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent, warnUninit,
|
||||||
warnProveField, warnProveIndex,
|
warnProveField, warnProveIndex,
|
||||||
warnGcUnsafe,
|
warnGcUnsafe,
|
||||||
|
hintPath, hintConf,
|
||||||
hintDependency,
|
hintDependency,
|
||||||
hintExecuting,
|
hintExecuting,
|
||||||
hintCodeBegin, hintCodeEnd,
|
hintCodeBegin, hintCodeEnd,
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,10 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
|
||||||
let gp = finalCallee.ast.sons[genericParamsPos]
|
let gp = finalCallee.ast.sons[genericParamsPos]
|
||||||
if gp.kind != nkEmpty:
|
if gp.kind != nkEmpty:
|
||||||
if x.calleeSym.kind notin {skMacro, skTemplate}:
|
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:
|
else:
|
||||||
# For macros and templates, the resolved generic params
|
# For macros and templates, the resolved generic params
|
||||||
# are added as normal params.
|
# are added as normal params.
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,8 @@ type
|
||||||
TExprFlag* = enum
|
TExprFlag* = enum
|
||||||
efLValue, efWantIterator, efInTypeof,
|
efLValue, efWantIterator, efInTypeof,
|
||||||
efWantStmt, efAllowStmt, efDetermineType,
|
efWantStmt, efAllowStmt, efDetermineType,
|
||||||
efAllowDestructor, efWantValue, efOperand, efNoSemCheck
|
efAllowDestructor, efWantValue, efOperand, efNoSemCheck,
|
||||||
|
efNoProcvarCheck
|
||||||
TExprFlags* = set[TExprFlag]
|
TExprFlags* = set[TExprFlag]
|
||||||
|
|
||||||
TTypeAttachedOp* = enum
|
TTypeAttachedOp* = enum
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
else:
|
else:
|
||||||
# XXX tyGenericInst here?
|
# XXX tyGenericInst here?
|
||||||
semProcvarCheck(c, result)
|
if efNoProcvarCheck notin flags: semProcvarCheck(c, result)
|
||||||
if result.typ.kind == tyVar: result = newDeref(result)
|
if result.typ.kind == tyVar: result = newDeref(result)
|
||||||
semDestructorCheck(c, result, flags)
|
semDestructorCheck(c, result, flags)
|
||||||
|
|
||||||
|
|
@ -452,18 +452,18 @@ proc changeType(n: PNode, newType: PType, check: bool) =
|
||||||
let tup = newType.skipTypes({tyGenericInst})
|
let tup = newType.skipTypes({tyGenericInst})
|
||||||
if tup.kind != tyTuple:
|
if tup.kind != tyTuple:
|
||||||
if tup.kind == tyObject: return
|
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:
|
elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr:
|
||||||
# named tuple?
|
# named tuple?
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var m = n.sons[i].sons[0]
|
var m = n.sons[i].sons[0]
|
||||||
if m.kind != nkSym:
|
if m.kind != nkSym:
|
||||||
internalError(m.info, "changeType(): invalid tuple constr")
|
globalError(m.info, "invalid tuple constructor")
|
||||||
return
|
return
|
||||||
if tup.n != nil:
|
if tup.n != nil:
|
||||||
var f = getSymFromList(tup.n, m.sym.name)
|
var f = getSymFromList(tup.n, m.sym.name)
|
||||||
if f == nil:
|
if f == nil:
|
||||||
internalError(m.info, "changeType(): invalid identifier")
|
globalError(m.info, "unknown identifier: " & m.sym.name.s)
|
||||||
return
|
return
|
||||||
changeType(n.sons[i].sons[1], f.typ, check)
|
changeType(n.sons[i].sons[1], f.typ, check)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1156,7 +1156,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
result.add(x[0])
|
result.add(x[0])
|
||||||
return
|
return
|
||||||
checkMinSonsLen(n, 2)
|
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})
|
let arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
|
||||||
case arr.kind
|
case arr.kind
|
||||||
of tyArray, tyOpenArray, tyVarargs, tyArrayConstr, tySequence, tyString,
|
of tyArray, tyOpenArray, tyVarargs, tyArrayConstr, tySequence, tyString,
|
||||||
|
|
@ -1196,7 +1196,17 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
localError(n.info, errIndexTypesDoNotMatch)
|
localError(n.info, errIndexTypesDoNotMatch)
|
||||||
result = n
|
result = n
|
||||||
else:
|
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 =
|
proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
let oldBracketExpr = c.p.bracketExpr
|
let oldBracketExpr = c.p.bracketExpr
|
||||||
|
|
@ -1250,7 +1260,7 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
|
||||||
template resultTypeIsInferrable(typ: PType): expr =
|
template resultTypeIsInferrable(typ: PType): expr =
|
||||||
typ.isMetaType and typ.kind != tyTypeDesc
|
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)
|
checkSonsLen(n, 2)
|
||||||
var a = n.sons[0]
|
var a = n.sons[0]
|
||||||
case a.kind
|
case a.kind
|
||||||
|
|
@ -1273,12 +1283,15 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||||
# --> `[]=`(a, i, x)
|
# --> `[]=`(a, i, x)
|
||||||
let oldBracketExpr = c.p.bracketExpr
|
let oldBracketExpr = c.p.bracketExpr
|
||||||
a = semSubscript(c, a, {efLValue})
|
a = semSubscript(c, a, {efLValue})
|
||||||
if a == nil:
|
if a == nil and mode != noOverloadedSubscript:
|
||||||
result = buildOverloadedSubscripts(n.sons[0], getIdent"[]=")
|
result = buildOverloadedSubscripts(n.sons[0], getIdent"[]=")
|
||||||
add(result, n[1])
|
add(result, n[1])
|
||||||
result = semExprNoType(c, result)
|
result = semExprNoType(c, result)
|
||||||
c.p.bracketExpr = oldBracketExpr
|
c.p.bracketExpr = oldBracketExpr
|
||||||
return result
|
return result
|
||||||
|
elif a == nil:
|
||||||
|
localError(n.info, "could not resolve: " & $n[0])
|
||||||
|
return n
|
||||||
c.p.bracketExpr = oldBracketExpr
|
c.p.bracketExpr = oldBracketExpr
|
||||||
of nkCurlyExpr:
|
of nkCurlyExpr:
|
||||||
# a{i} = x --> `{}=`(a, i, x)
|
# a{i} = x --> `{}=`(a, i, x)
|
||||||
|
|
@ -1323,7 +1336,8 @@ proc semAsgn(c: PContext, n: PNode): PNode =
|
||||||
typeMismatch(n, lhs.typ, rhs.typ)
|
typeMismatch(n, lhs.typ, rhs.typ)
|
||||||
|
|
||||||
n.sons[1] = fitNode(c, le, rhs)
|
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])
|
return overloadedAsgn(c, lhs, n.sons[1])
|
||||||
|
|
||||||
fixAbstractType(c, n)
|
fixAbstractType(c, n)
|
||||||
|
|
@ -1715,6 +1729,9 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
of mTypeOf:
|
of mTypeOf:
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
result = semTypeOf(c, n.sons[1])
|
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 mDefined: result = semDefined(c, setMs(n, s), false)
|
||||||
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
|
of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
|
||||||
of mCompiles: result = semCompiles(c, setMs(n, s), flags)
|
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
|
c.module.ast.add x
|
||||||
result = n
|
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) =
|
proc setGenericParams(c: PContext, n: PNode) =
|
||||||
for i in 1 .. <n.len:
|
for i in 1 .. <n.len:
|
||||||
n[i].typ = semTypeNode(c, n[i], nil)
|
n[i].typ = semTypeNode(c, n[i], nil)
|
||||||
|
|
@ -2173,7 +2203,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
else:
|
else:
|
||||||
#liMessage(n.info, warnUser, renderTree(n));
|
#liMessage(n.info, warnUser, renderTree(n));
|
||||||
result = semIndirectOp(c, n, flags)
|
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
|
# indirectOp can deal with explicit instantiations; the fixes
|
||||||
# the 'newSeq[T](x)' bug
|
# the 'newSeq[T](x)' bug
|
||||||
setGenericParams(c, n.sons[0])
|
setGenericParams(c, n.sons[0])
|
||||||
|
|
@ -2194,16 +2225,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
result = semExpr(c, result, flags)
|
result = semExpr(c, result, flags)
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
var s = qualifiedLookUp(c, n.sons[0], {checkUndeclared})
|
result = semArrayAccess(c, n, flags)
|
||||||
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)
|
|
||||||
of nkCurlyExpr:
|
of nkCurlyExpr:
|
||||||
result = semExpr(c, buildOverloadedSubscripts(n, getIdent"{}"), flags)
|
result = semExpr(c, buildOverloadedSubscripts(n, getIdent"{}"), flags)
|
||||||
of nkPragmaExpr:
|
of nkPragmaExpr:
|
||||||
|
|
|
||||||
|
|
@ -430,17 +430,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||||
of mCompileOptionArg:
|
of mCompileOptionArg:
|
||||||
result = newIntNodeT(ord(
|
result = newIntNodeT(ord(
|
||||||
testCompileOptionArg(getStr(a), getStr(b), n.info)), n)
|
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:
|
of mEqProc:
|
||||||
result = newIntNodeT(ord(
|
result = newIntNodeT(ord(
|
||||||
exprStructuralEquivalent(a, b, strictSymEquality=true)), n)
|
exprStructuralEquivalent(a, b, strictSymEquality=true)), n)
|
||||||
else: internalError(a.info, "evalOp(" & $m & ')')
|
else: discard
|
||||||
|
|
||||||
proc getConstIfExpr(c: PSym, n: PNode): PNode =
|
proc getConstIfExpr(c: PSym, n: PNode): PNode =
|
||||||
result = nil
|
result = nil
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,13 @@ type
|
||||||
GenericCtx = object
|
GenericCtx = object
|
||||||
toMixin: IntSet
|
toMixin: IntSet
|
||||||
cursorInBody: bool # only for nimsuggest
|
cursorInBody: bool # only for nimsuggest
|
||||||
|
bracketExpr: PNode
|
||||||
|
|
||||||
|
template withBracketExpr(x, body: untyped) =
|
||||||
|
let old = ctx.bracketExpr
|
||||||
|
ctx.bracketExpr = x
|
||||||
|
body
|
||||||
|
ctx.bracketExpr = old
|
||||||
|
|
||||||
type
|
type
|
||||||
TSemGenericFlag = enum
|
TSemGenericFlag = enum
|
||||||
|
|
@ -227,6 +234,10 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
discard
|
discard
|
||||||
of skProc, skMethod, skIterators, skConverter, skModule:
|
of skProc, skMethod, skIterators, skConverter, skModule:
|
||||||
result.sons[0] = symChoice(c, fn, s, scOption)
|
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
|
first = 1
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
result.sons[0] = newSymNodeTypeDesc(s, fn.info)
|
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
|
let flags = if mixinContext: flags+{withinMixin} else: flags
|
||||||
for i in countup(first, sonsLen(result) - 1):
|
for i in countup(first, sonsLen(result) - 1):
|
||||||
result.sons[i] = semGenericStmt(c, result.sons[i], flags, ctx)
|
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:
|
of nkIfStmt:
|
||||||
for i in countup(0, sonsLen(n)-1):
|
for i in countup(0, sonsLen(n)-1):
|
||||||
n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, ctx)
|
n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, ctx)
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
|
||||||
inc i
|
inc i
|
||||||
pushProcCon(c, result)
|
pushProcCon(c, result)
|
||||||
instantiateProcType(c, pt, result, info)
|
instantiateProcType(c, pt, result, info)
|
||||||
|
if tfTriggersCompileTime in result.typ.flags:
|
||||||
|
incl(result.flags, sfCompileTime)
|
||||||
n.sons[genericParamsPos] = ast.emptyNode
|
n.sons[genericParamsPos] = ast.emptyNode
|
||||||
var oldPrc = genericCacheGet(fn, entry[])
|
var oldPrc = genericCacheGet(fn, entry[])
|
||||||
if oldPrc == nil:
|
if oldPrc == nil:
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,41 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
|
||||||
result.add typExpr
|
result.add typExpr
|
||||||
result.typ = makeTypeDesc(c, typExpr.typ.skipTypes({tyTypeDesc, tyIter}))
|
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 =
|
proc semIsPartOf(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
var r = isPartOf(n[1], n[2])
|
var r = isPartOf(n[1], n[2])
|
||||||
result = newIntNodeT(ord(r), n)
|
result = newIntNodeT(ord(r), n)
|
||||||
|
|
@ -125,6 +160,9 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||||
of mTypeOf:
|
of mTypeOf:
|
||||||
checkSonsLen(n, 2)
|
checkSonsLen(n, 2)
|
||||||
result = semTypeOf(c, n.sons[1])
|
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 mIsPartOf: result = semIsPartOf(c, n, flags)
|
||||||
of mTypeTrait: result = semTypeTraits(c, n)
|
of mTypeTrait: result = semTypeTraits(c, n)
|
||||||
of mAstToStr:
|
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])):
|
if isNegative(n.sons[1]) or (n.len > 2 and isNegative(n.sons[2])):
|
||||||
localError(n.info, "use '^' instead of '-'; negative indexing is obsolete")
|
localError(n.info, "use '^' instead of '-'; negative indexing is obsolete")
|
||||||
of mRoof:
|
of mRoof:
|
||||||
# error correction:
|
let bracketExpr = if n.len == 3: n.sons[2] else: c.p.bracketExpr
|
||||||
result = n.sons[1]
|
if bracketExpr.isNil:
|
||||||
if c.p.bracketExpr.isNil:
|
|
||||||
localError(n.info, "no surrounding array access context for '^'")
|
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" %
|
localError(n.info, "invalid context for '^' as '$#' has side effects" %
|
||||||
renderTree(c.p.bracketExpr))
|
renderTree(bracketExpr))
|
||||||
elif c.p.bracketExpr.typ.isStrangeArray:
|
result = n.sons[1]
|
||||||
|
elif bracketExpr.typ.isStrangeArray:
|
||||||
localError(n.info, "invalid context for '^' as len!=high+1 for '$#'" %
|
localError(n.info, "invalid context for '^' as len!=high+1 for '$#'" %
|
||||||
renderTree(c.p.bracketExpr))
|
renderTree(bracketExpr))
|
||||||
|
result = n.sons[1]
|
||||||
else:
|
else:
|
||||||
# ^x is rewritten to: len(a)-x
|
# ^x is rewritten to: len(a)-x
|
||||||
let lenExpr = newNodeI(nkCall, n.info)
|
let lenExpr = newNodeI(nkCall, n.info)
|
||||||
lenExpr.add newIdentNode(getIdent"len", n.info)
|
lenExpr.add newIdentNode(getIdent"len", n.info)
|
||||||
lenExpr.add c.p.bracketExpr
|
lenExpr.add bracketExpr
|
||||||
let lenExprB = semExprWithType(c, lenExpr)
|
let lenExprB = semExprWithType(c, lenExpr)
|
||||||
if lenExprB.typ.isNil or not isOrdinalType(lenExprB.typ):
|
if lenExprB.typ.isNil or not isOrdinalType(lenExprB.typ):
|
||||||
localError(n.info, "'$#' has to be of an ordinal type for '^'" %
|
localError(n.info, "'$#' has to be of an ordinal type for '^'" %
|
||||||
renderTree(lenExpr))
|
renderTree(lenExpr))
|
||||||
|
result = n.sons[1]
|
||||||
else:
|
else:
|
||||||
result = newNodeIT(nkCall, n.info, getSysType(tyInt))
|
result = newNodeIT(nkCall, n.info, getSysType(tyInt))
|
||||||
result.add newSymNode(createMagic("-", mSubI), n.info)
|
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")
|
"signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T")
|
||||||
incl(s.flags, sfUsed)
|
incl(s.flags, sfUsed)
|
||||||
of "=":
|
of "=":
|
||||||
|
if s.magic == mAsgn: return
|
||||||
incl(s.flags, sfUsed)
|
incl(s.flags, sfUsed)
|
||||||
let t = s.typ
|
let t = s.typ
|
||||||
if t.len == 3 and t.sons[0] == nil and t.sons[1].kind == tyVar:
|
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)
|
# semParamList(c, n.sons[ParamsPos], nil, s)
|
||||||
else:
|
else:
|
||||||
s.typ = newProcType(c, n.info)
|
s.typ = newProcType(c, n.info)
|
||||||
|
if tfTriggersCompileTime in s.typ.flags: incl(s.flags, sfCompileTime)
|
||||||
if n.sons[patternPos].kind != nkEmpty:
|
if n.sons[patternPos].kind != nkEmpty:
|
||||||
n.sons[patternPos] = semPattern(c, n.sons[patternPos])
|
n.sons[patternPos] = semPattern(c, n.sons[patternPos])
|
||||||
if s.kind in skIterators:
|
if s.kind in skIterators:
|
||||||
|
|
|
||||||
|
|
@ -281,6 +281,35 @@ proc semTemplBodySons(c: var TemplCtx, n: PNode): PNode =
|
||||||
for i in 0.. < n.len:
|
for i in 0.. < n.len:
|
||||||
result.sons[i] = semTemplBody(c, n.sons[i])
|
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 =
|
proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
semIdeForTemplateOrGenericCheck(n, c.cursorInBody)
|
semIdeForTemplateOrGenericCheck(n, c.cursorInBody)
|
||||||
|
|
@ -423,6 +452,28 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
result.sons[1] = semTemplBody(c, n.sons[1])
|
result.sons[1] = semTemplBody(c, n.sons[1])
|
||||||
of nkPragma:
|
of nkPragma:
|
||||||
result = onlyReplaceParams(c, n)
|
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:
|
else:
|
||||||
# dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
|
# dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
|
||||||
# so we use the generic code for nkDotExpr too
|
# 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)
|
if paramType == nil: return # (e.g. proc return type)
|
||||||
|
|
||||||
proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType =
|
proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType =
|
||||||
let finalTypId = if typId != nil: typId
|
|
||||||
else: getIdent(paramName & ":type")
|
|
||||||
if genericParams == nil:
|
if genericParams == nil:
|
||||||
# This happens with anonymous proc types appearing in signatures
|
# This happens with anonymous proc types appearing in signatures
|
||||||
# XXX: we need to lift these earlier
|
# XXX: we need to lift these earlier
|
||||||
return
|
return
|
||||||
|
let finalTypId = if typId != nil: typId
|
||||||
|
else: getIdent(paramName & ":type")
|
||||||
# is this a bindOnce type class already present in the param list?
|
# is this a bindOnce type class already present in the param list?
|
||||||
for i in countup(0, genericParams.len - 1):
|
for i in countup(0, genericParams.len - 1):
|
||||||
if genericParams.sons[i].sym.name.id == finalTypId.id:
|
if genericParams.sons[i].sym.name.id == finalTypId.id:
|
||||||
|
|
@ -757,7 +757,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
|
|
||||||
case paramType.kind:
|
case paramType.kind:
|
||||||
of tyAnything:
|
of tyAnything:
|
||||||
result = addImplicitGeneric(newTypeS(tyGenericParam, c))
|
result = addImplicitGenericImpl(newTypeS(tyGenericParam, c), nil)
|
||||||
|
|
||||||
of tyStatic:
|
of tyStatic:
|
||||||
# proc(a: expr{string}, b: expr{nkLambda})
|
# proc(a: expr{string}, b: expr{nkLambda})
|
||||||
|
|
@ -868,6 +868,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
of tyExpr:
|
of tyExpr:
|
||||||
if procKind notin {skMacro, skTemplate}:
|
if procKind notin {skMacro, skTemplate}:
|
||||||
result = addImplicitGeneric(newTypeS(tyAnything, c))
|
result = addImplicitGeneric(newTypeS(tyAnything, c))
|
||||||
|
#result = addImplicitGenericImpl(newTypeS(tyGenericParam, c), nil)
|
||||||
|
|
||||||
of tyGenericParam:
|
of tyGenericParam:
|
||||||
markUsed(info, paramType.sym)
|
markUsed(info, paramType.sym)
|
||||||
|
|
@ -977,7 +978,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
# compiler only checks for 'nil':
|
# compiler only checks for 'nil':
|
||||||
if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
|
if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
|
||||||
# 'auto' as a return type does not imply a generic:
|
# '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:
|
if r.sym == nil or sfAnon notin r.sym.flags:
|
||||||
let lifted = liftParamType(c, kind, genericParams, r, "result",
|
let lifted = liftParamType(c, kind, genericParams, r, "result",
|
||||||
n.sons[0].info)
|
n.sons[0].info)
|
||||||
|
|
@ -1149,7 +1154,17 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
else:
|
else:
|
||||||
result = semAnonTuple(c, n, prev)
|
result = semAnonTuple(c, n, prev)
|
||||||
of nkCallKinds:
|
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)
|
result = semRangeAux(c, n, prev)
|
||||||
elif n[0].kind notin nkIdentKinds:
|
elif n[0].kind notin nkIdentKinds:
|
||||||
result = semTypeExpr(c, n)
|
result = semTypeExpr(c, n)
|
||||||
|
|
@ -1336,8 +1351,11 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||||
of mIntSetBaseType: setMagicType(m, tyRange, intSize)
|
of mIntSetBaseType: setMagicType(m, tyRange, intSize)
|
||||||
of mNil: setMagicType(m, tyNil, ptrSize)
|
of mNil: setMagicType(m, tyNil, ptrSize)
|
||||||
of mExpr:
|
of mExpr:
|
||||||
setMagicType(m, tyExpr, 0)
|
if m.name.s == "auto":
|
||||||
if m.name.s == "expr": m.typ.flags.incl tfOldSchoolExprStmt
|
setMagicType(m, tyAnything, 0)
|
||||||
|
else:
|
||||||
|
setMagicType(m, tyExpr, 0)
|
||||||
|
if m.name.s == "expr": m.typ.flags.incl tfOldSchoolExprStmt
|
||||||
of mStmt:
|
of mStmt:
|
||||||
setMagicType(m, tyStmt, 0)
|
setMagicType(m, tyStmt, 0)
|
||||||
if m.name.s == "stmt": m.typ.flags.incl tfOldSchoolExprStmt
|
if m.name.s == "stmt": m.typ.flags.incl tfOldSchoolExprStmt
|
||||||
|
|
@ -1365,7 +1383,8 @@ proc processMagicType(c: PContext, m: PSym) =
|
||||||
of mOrdinal:
|
of mOrdinal:
|
||||||
setMagicType(m, tyOrdinal, 0)
|
setMagicType(m, tyOrdinal, 0)
|
||||||
rawAddSon(m.typ, newTypeS(tyNone, c))
|
rawAddSon(m.typ, newTypeS(tyNone, c))
|
||||||
of mPNimrodNode: discard
|
of mPNimrodNode:
|
||||||
|
incl m.typ.flags, tfTriggersCompileTime
|
||||||
of mShared:
|
of mShared:
|
||||||
setMagicType(m, tyObject, 0)
|
setMagicType(m, tyObject, 0)
|
||||||
m.typ.n = newNodeI(nkRecList, m.info)
|
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)
|
matchesAux(c, n, nOrig, m, marker)
|
||||||
|
|
||||||
proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
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()
|
var marker = initIntSet()
|
||||||
matchesAux(c, n, nOrig, m, marker)
|
matchesAux(c, n, nOrig, m, marker)
|
||||||
if m.state == csNoMatch: return
|
if m.state == csNoMatch: return
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ type class matches
|
||||||
``array`` any array type
|
``array`` any array type
|
||||||
``set`` any set type
|
``set`` any set type
|
||||||
``seq`` any seq type
|
``seq`` any seq type
|
||||||
``auto`` any type
|
``any`` any type
|
||||||
================== ===================================================
|
================== ===================================================
|
||||||
|
|
||||||
Furthermore, every generic type automatically creates a type class of the same
|
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
|
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.
|
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
|
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
|
type parameters of the matched generic type. They can be easily accessed using
|
||||||
the dot syntax:
|
the dot syntax:
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,20 @@ compileTime pragma
|
||||||
------------------
|
------------------
|
||||||
The ``compileTime`` pragma is used to mark a proc or variable to be used at
|
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
|
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
|
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
|
The ``void`` type is only valid for parameters and return types; other symbols
|
||||||
cannot have the type ``void``.
|
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 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 {.
|
proc waitid*(a1: cint, a2: Id, a3: var SigInfo, a4: cint): cint {.
|
||||||
importc, header: "<sys/wait.h>".}
|
importc, header: "<sys/wait.h>".}
|
||||||
proc waitpid*(a1: Pid, a2: var cint, a3: cint): Pid {.
|
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))
|
var res = getSockOptInt(socket.fd, cint(level), toCInt(opt))
|
||||||
result = res != 0
|
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) {.
|
proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) {.
|
||||||
tags: [WriteIOEffect].} =
|
tags: [WriteIOEffect].} =
|
||||||
## Sets option ``opt`` to a boolean value specified by ``value``.
|
## Sets option ``opt`` to a boolean value specified by ``value``.
|
||||||
|
|
|
||||||
|
|
@ -371,6 +371,76 @@ proc getSockName*(socket: SocketHandle): Port =
|
||||||
raiseOSError(osLastError())
|
raiseOSError(osLastError())
|
||||||
result = Port(rawsockets.ntohs(name.sin_port))
|
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 {.
|
proc getSockOptInt*(socket: SocketHandle, level, optname: int): int {.
|
||||||
tags: [ReadIOEffect].} =
|
tags: [ReadIOEffect].} =
|
||||||
## getsockopt for integer options.
|
## getsockopt for integer options.
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,7 @@ type
|
||||||
stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates)
|
stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates)
|
||||||
typedesc* {.magic: TypeDesc.} ## meta type to denote a type description
|
typedesc* {.magic: TypeDesc.} ## meta type to denote a type description
|
||||||
void* {.magic: "VoidType".} ## meta type to denote the absence of any type
|
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
|
any* = distinct auto ## meta type for any supported type
|
||||||
untyped* {.magic: Expr.} ## meta type to denote an expression that
|
untyped* {.magic: Expr.} ## meta type to denote an expression that
|
||||||
## is not resolved (for templates)
|
## is not resolved (for templates)
|
||||||
|
|
@ -104,7 +104,7 @@ type
|
||||||
SomeNumber* = SomeInteger|SomeReal
|
SomeNumber* = SomeInteger|SomeReal
|
||||||
## type class matching all number types
|
## 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
|
## Special compile-time procedure that checks whether `x` is
|
||||||
## defined.
|
## defined.
|
||||||
## `x` is an external symbol introduced through the compiler's
|
## `x` is an external symbol introduced through the compiler's
|
||||||
|
|
@ -125,7 +125,7 @@ when defined(nimalias):
|
||||||
TNumber: SomeNumber,
|
TNumber: SomeNumber,
|
||||||
TOrdinal: SomeOrdinal].}
|
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
|
## Special compile-time procedure that checks whether `x` is
|
||||||
## declared. `x` has to be an identifier or a qualified identifier.
|
## declared. `x` has to be an identifier or a qualified identifier.
|
||||||
## This can be used to check whether a library provides a certain
|
## This can be used to check whether a library provides a certain
|
||||||
|
|
@ -140,11 +140,11 @@ when defined(useNimRtl):
|
||||||
{.deadCodeElim: on.}
|
{.deadCodeElim: on.}
|
||||||
|
|
||||||
proc definedInScope*(x: expr): bool {.
|
proc definedInScope*(x: expr): bool {.
|
||||||
magic: "DefinedInScope", noSideEffect, deprecated.}
|
magic: "DefinedInScope", noSideEffect, deprecated, compileTime.}
|
||||||
## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead.
|
## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead.
|
||||||
|
|
||||||
proc declaredInScope*(x: expr): bool {.
|
proc declaredInScope*(x: expr): bool {.
|
||||||
magic: "DefinedInScope", noSideEffect.}
|
magic: "DefinedInScope", noSideEffect, compileTime.}
|
||||||
## Special compile-time procedure that checks whether `x` is
|
## Special compile-time procedure that checks whether `x` is
|
||||||
## declared in the current scope. `x` has to be an identifier.
|
## 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.
|
## Cannot be overloaded.
|
||||||
discard
|
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.
|
## Builtin 'type' operator for accessing the type of an expression.
|
||||||
## Cannot be overloaded.
|
## Cannot be overloaded.
|
||||||
discard
|
discard
|
||||||
|
|
@ -239,6 +239,14 @@ type
|
||||||
seq*{.magic: "Seq".}[T] ## Generic type to construct sequences.
|
seq*{.magic: "Seq".}[T] ## Generic type to construct sequences.
|
||||||
set*{.magic: "Set".}[T] ## Generic type to construct bit sets.
|
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
|
type
|
||||||
Slice*[T] = object ## builtin slice type
|
Slice*[T] = object ## builtin slice type
|
||||||
a*, b*: T ## the bounds
|
a*, b*: T ## the bounds
|
||||||
|
|
@ -3384,7 +3392,7 @@ when hasAlloc:
|
||||||
x[j+i] = item[j]
|
x[j+i] = item[j]
|
||||||
inc(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
|
## Special compile-time procedure that checks whether `x` can be compiled
|
||||||
## without any semantic error.
|
## without any semantic error.
|
||||||
## This can be used to check whether a type supports some operation:
|
## 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"
|
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.
|
## special magic to prohibit dynamic binding for `method`:idx: calls.
|
||||||
## This is similar to `super`:idx: in ordinary OO languages.
|
## This is similar to `super`:idx: in ordinary OO languages.
|
||||||
##
|
##
|
||||||
|
|
@ -3457,6 +3465,7 @@ proc procCall*(x: expr) {.magic: "ProcCall".} =
|
||||||
## procCall someMethod(a, b)
|
## procCall someMethod(a, b)
|
||||||
discard
|
discard
|
||||||
|
|
||||||
|
proc `^`*[T](x: int; y: openArray[T]): int {.noSideEffect, magic: "Roof".}
|
||||||
proc `^`*(x: int): int {.noSideEffect, magic: "Roof".} =
|
proc `^`*(x: int): int {.noSideEffect, magic: "Roof".} =
|
||||||
## builtin `roof`:idx: operator that can be used for convenient array access.
|
## 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``
|
## ``a[^x]`` is rewritten to ``a[a.len-x]``. However currently the ``a``
|
||||||
|
|
|
||||||
|
|
@ -409,7 +409,7 @@ type
|
||||||
bytes*: array[0..15, char]
|
bytes*: array[0..15, char]
|
||||||
|
|
||||||
Sockaddr_in6* {.importc: "SOCKADDR_IN6",
|
Sockaddr_in6* {.importc: "SOCKADDR_IN6",
|
||||||
header: "winsock2.h".} = object
|
header: "ws2tcpip.h".} = object
|
||||||
sin6_family*: int16
|
sin6_family*: int16
|
||||||
sin6_port*: int16 # unsigned
|
sin6_port*: int16 # unsigned
|
||||||
sin6_flowinfo*: int32 # 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,
|
proc getsockname*(s: SocketHandle, name: ptr SockAddr,
|
||||||
namelen: ptr SockLen): cint {.
|
namelen: ptr SockLen): cint {.
|
||||||
stdcall, importc: "getsockname", dynlib: ws2dll.}
|
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,
|
proc getsockopt*(s: SocketHandle, level, optname: cint, optval: pointer,
|
||||||
optlen: ptr SockLen): cint {.
|
optlen: ptr SockLen): cint {.
|
||||||
stdcall, importc: "getsockopt", dynlib: ws2dll.}
|
stdcall, importc: "getsockopt", dynlib: ws2dll.}
|
||||||
|
|
@ -572,6 +575,9 @@ proc freeaddrinfo*(ai: ptr AddrInfo) {.
|
||||||
proc inet_ntoa*(i: InAddr): cstring {.
|
proc inet_ntoa*(i: InAddr): cstring {.
|
||||||
stdcall, importc, dynlib: ws2dll.}
|
stdcall, importc, dynlib: ws2dll.}
|
||||||
|
|
||||||
|
proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring,
|
||||||
|
stringBufSize: int32): cstring {.stdcall, importc, dynlib: ws2dll.}
|
||||||
|
|
||||||
const
|
const
|
||||||
MAXIMUM_WAIT_OBJECTS* = 0x00000040
|
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
|
type
|
||||||
TThreadFuncArgs[T] = object of TObject
|
TThreadFuncArgs[T] = object of RootObj
|
||||||
a: proc(): T {.thread.}
|
a: proc(): T {.thread.}
|
||||||
b: proc(val: T) {.thread.}
|
b: proc(val: T) {.thread.}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ type
|
||||||
|
|
||||||
proc getTypeName(t: typedesc): string = t.name
|
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)
|
result = "float " & $(a.len > 5)
|
||||||
|
|
||||||
proc foo(T: typedesc[TFoo], a: int): string =
|
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
|
- The bitwise 'not' operator will be renamed to 'bnot' to
|
||||||
prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!
|
prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!
|
||||||
- split docgen into separate tool
|
- split docgen into separate tool
|
||||||
- special rule for ``[]=``, items, pairs
|
|
||||||
- BUG: echo with template `$`*(info: TLineInfo): expr = toFileLineCol(info)
|
- BUG: echo with template `$`*(info: TLineInfo): expr = toFileLineCol(info)
|
||||||
- make 'nil' work for 'add':
|
- make 'nil' work for 'add':
|
||||||
- resizeString
|
- 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
|
Changes affecting backwards compatibility
|
||||||
|
|
@ -58,7 +58,7 @@ News
|
||||||
of all the DLLs the standard library needs. This means that the following
|
of all the DLLs the standard library needs. This means that the following
|
||||||
DLLs are now split into 32 and 64 versions:
|
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``.
|
* ``pdcurses.dll``: Split into ``pdcurses32.dll`` and ``pdcurses64.dll``.
|
||||||
* ``sqlite3.dll``: Split into ``sqlite3_32.dll`` and ``sqlite3_64.dll``.
|
* ``sqlite3.dll``: Split into ``sqlite3_32.dll`` and ``sqlite3_64.dll``.
|
||||||
* ``ssleay32.dll``: Split into ``ssleay32.dll`` and ``ssleay64.dll``.
|
* ``ssleay32.dll``: Split into ``ssleay32.dll`` and ``ssleay64.dll``.
|
||||||
|
|
@ -75,6 +75,13 @@ News
|
||||||
with Unix's ``#!``.
|
with Unix's ``#!``.
|
||||||
- An implicit return type for an iterator is now deprecated. Use ``auto`` if
|
- An implicit return type for an iterator is now deprecated. Use ``auto`` if
|
||||||
you want more type inference.
|
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
|
Library Additions
|
||||||
|
|
@ -95,6 +102,9 @@ News
|
||||||
|
|
||||||
- The compiler now supports a new configuration system based on
|
- The compiler now supports a new configuration system based on
|
||||||
`NimScript <docs/nims.html>`_.
|
`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
|
Language Additions
|
||||||
|
|
@ -112,22 +122,21 @@ News
|
||||||
this ``let (x, y) == f()`` still needs to be used.
|
this ``let (x, y) == f()`` still needs to be used.
|
||||||
- ``when nimvm`` can now be used for compiletime versions of some code
|
- ``when nimvm`` can now be used for compiletime versions of some code
|
||||||
sections. Click `here <docs/manual.html#when-nimvm-statement>`_ for details.
|
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
|
Bugfixes
|
||||||
--------
|
--------
|
||||||
- Fixed "Compiler internal error on iterator it(T: typedesc[Base]) called with
|
- Fixed "Compiler internal error on iterator it(T: typedesc[Base]) called with it(Child), where Child = object of Base"
|
||||||
it(Child), where Child = object of Base"
|
|
||||||
(`#2662 <https://github.com/Araq/Nim/issues/2662>`_)
|
(`#2662 <https://github.com/Araq/Nim/issues/2662>`_)
|
||||||
- Fixed "repr() misses base object field in 2nd level derived object"
|
- Fixed "repr() misses base object field in 2nd level derived object"
|
||||||
(`#2749 <https://github.com/Araq/Nim/issues/2749>`_)
|
(`#2749 <https://github.com/Araq/Nim/issues/2749>`_)
|
||||||
- Fixed "nimsuggest doesn't work more than once on the non-main file"
|
- Fixed "nimsuggest doesn't work more than once on the non-main file"
|
||||||
(`#2694 <https://github.com/Araq/Nim/issues/2694>`_)
|
(`#2694 <https://github.com/Araq/Nim/issues/2694>`_)
|
||||||
- Fixed "JS Codegen. Passing arguments by var in certain cases leads to invali
|
- Fixed "JS Codegen. Passing arguments by var in certain cases leads to invalid JS."
|
||||||
d JS."
|
|
||||||
(`#2798 <https://github.com/Araq/Nim/issues/2798>`_)
|
(`#2798 <https://github.com/Araq/Nim/issues/2798>`_)
|
||||||
- Fixed ""check" proc in unittest.nim prevents the propagation of changes to v
|
- Fixed ""check" proc in unittest.nim prevents the propagation of changes to var parameters."
|
||||||
ar parameters."
|
|
||||||
(`#964 <https://github.com/Araq/Nim/issues/964>`_)
|
(`#964 <https://github.com/Araq/Nim/issues/964>`_)
|
||||||
- Fixed "Excessive letters in integer literals are not an error"
|
- Fixed "Excessive letters in integer literals are not an error"
|
||||||
(`#2523 <https://github.com/Araq/Nim/issues/2523>`_)
|
(`#2523 <https://github.com/Araq/Nim/issues/2523>`_)
|
||||||
|
|
@ -141,8 +150,7 @@ ar parameters."
|
||||||
(`#2687 <https://github.com/Araq/Nim/issues/2687>`_)
|
(`#2687 <https://github.com/Araq/Nim/issues/2687>`_)
|
||||||
- Fixed "Compile error using object in const array"
|
- Fixed "Compile error using object in const array"
|
||||||
(`#2774 <https://github.com/Araq/Nim/issues/2774>`_)
|
(`#2774 <https://github.com/Araq/Nim/issues/2774>`_)
|
||||||
- Fixed "httpclient async requests with method httpPOST isn't sending Content-
|
- Fixed "httpclient async requests with method httpPOST isn't sending Content-Length header"
|
||||||
Length header"
|
|
||||||
(`#2884 <https://github.com/Araq/Nim/issues/2884>`_)
|
(`#2884 <https://github.com/Araq/Nim/issues/2884>`_)
|
||||||
- Fixed "Streams module not working with JS backend"
|
- Fixed "Streams module not working with JS backend"
|
||||||
(`#2148 <https://github.com/Araq/Nim/issues/2148>`_)
|
(`#2148 <https://github.com/Araq/Nim/issues/2148>`_)
|
||||||
|
|
@ -173,8 +181,7 @@ Length header"
|
||||||
(`#2974 <https://github.com/Araq/Nim/issues/2974>`_)
|
(`#2974 <https://github.com/Araq/Nim/issues/2974>`_)
|
||||||
- Fixed "repr is broken"
|
- Fixed "repr is broken"
|
||||||
(`#2992 <https://github.com/Araq/Nim/issues/2992>`_)
|
(`#2992 <https://github.com/Araq/Nim/issues/2992>`_)
|
||||||
- Fixed "Ipv6 devel - add IPv6 support for asyncsockets, make AF_INET6 a defau
|
- Fixed "Ipv6 devel - add IPv6 support for asyncsockets, make AF_INET6 a default"
|
||||||
lt"
|
|
||||||
(`#2976 <https://github.com/Araq/Nim/issues/2976>`_)
|
(`#2976 <https://github.com/Araq/Nim/issues/2976>`_)
|
||||||
- Fixed "Compilation broken on windows"
|
- Fixed "Compilation broken on windows"
|
||||||
(`#2996 <https://github.com/Araq/Nim/issues/2996>`_)
|
(`#2996 <https://github.com/Araq/Nim/issues/2996>`_)
|
||||||
|
|
@ -184,8 +191,7 @@ lt"
|
||||||
(`#2672 <https://github.com/Araq/Nim/issues/2672>`_)
|
(`#2672 <https://github.com/Araq/Nim/issues/2672>`_)
|
||||||
- Fixed "Uncatched exception in async procedure on raise statement"
|
- Fixed "Uncatched exception in async procedure on raise statement"
|
||||||
(`#3014 <https://github.com/Araq/Nim/issues/3014>`_)
|
(`#3014 <https://github.com/Araq/Nim/issues/3014>`_)
|
||||||
- Fixed "nim doc2 fails in Mac OS X due to system.nim (possibly related to #18
|
- Fixed "nim doc2 fails in Mac OS X due to system.nim (possibly related to #1898)"
|
||||||
98)"
|
|
||||||
(`#3005 <https://github.com/Araq/Nim/issues/3005>`_)
|
(`#3005 <https://github.com/Araq/Nim/issues/3005>`_)
|
||||||
- Fixed "IndexError when rebuilding Nim on iteration 2"
|
- Fixed "IndexError when rebuilding Nim on iteration 2"
|
||||||
(`#3018 <https://github.com/Araq/Nim/issues/3018>`_)
|
(`#3018 <https://github.com/Araq/Nim/issues/3018>`_)
|
||||||
|
|
@ -233,8 +239,7 @@ lt"
|
||||||
(`#3054 <https://github.com/Araq/Nim/issues/3054>`_)
|
(`#3054 <https://github.com/Araq/Nim/issues/3054>`_)
|
||||||
- Fixed "Wrong sharing of static_t instantations"
|
- Fixed "Wrong sharing of static_t instantations"
|
||||||
(`#3112 <https://github.com/Araq/Nim/issues/3112>`_)
|
(`#3112 <https://github.com/Araq/Nim/issues/3112>`_)
|
||||||
- Fixed "Automatically generated proc conflicts with user-defined proc when .e
|
- Fixed "Automatically generated proc conflicts with user-defined proc when .exportc.'ed"
|
||||||
xportc.'ed"
|
|
||||||
(`#3134 <https://github.com/Araq/Nim/issues/3134>`_)
|
(`#3134 <https://github.com/Araq/Nim/issues/3134>`_)
|
||||||
- Fixed "getTypeInfo call crashes nim"
|
- Fixed "getTypeInfo call crashes nim"
|
||||||
(`#3099 <https://github.com/Araq/Nim/issues/3099>`_)
|
(`#3099 <https://github.com/Araq/Nim/issues/3099>`_)
|
||||||
|
|
@ -254,15 +259,13 @@ xportc.'ed"
|
||||||
(`#3149 <https://github.com/Araq/Nim/issues/3149>`_)
|
(`#3149 <https://github.com/Araq/Nim/issues/3149>`_)
|
||||||
- Fixed "Inference of `static[T]` in sequences"
|
- Fixed "Inference of `static[T]` in sequences"
|
||||||
(`#3144 <https://github.com/Araq/Nim/issues/3144>`_)
|
(`#3144 <https://github.com/Araq/Nim/issues/3144>`_)
|
||||||
- Fixed "Argument named "closure" to proc inside template interfere with closu
|
- Fixed "Argument named "closure" to proc inside template interfere with closure pragma"
|
||||||
re pragma"
|
|
||||||
(`#3171 <https://github.com/Araq/Nim/issues/3171>`_)
|
(`#3171 <https://github.com/Araq/Nim/issues/3171>`_)
|
||||||
- Fixed "Internal error with aliasing inside template"
|
- Fixed "Internal error with aliasing inside template"
|
||||||
(`#3158 <https://github.com/Araq/Nim/issues/3158>`_)
|
(`#3158 <https://github.com/Araq/Nim/issues/3158>`_)
|
||||||
- Fixed "Cardinality of sets prints unexpected value"
|
- Fixed "Cardinality of sets prints unexpected value"
|
||||||
(`#3135 <https://github.com/Araq/Nim/issues/3135>`_)
|
(`#3135 <https://github.com/Araq/Nim/issues/3135>`_)
|
||||||
- Fixed "Nim crashes on const assignment from function returning var ref objec
|
- Fixed "Nim crashes on const assignment from function returning var ref object"
|
||||||
t"
|
|
||||||
(`#3103 <https://github.com/Araq/Nim/issues/3103>`_)
|
(`#3103 <https://github.com/Araq/Nim/issues/3103>`_)
|
||||||
- Fixed "`repr` cstring"
|
- Fixed "`repr` cstring"
|
||||||
(`#3080 <https://github.com/Araq/Nim/issues/3080>`_)
|
(`#3080 <https://github.com/Araq/Nim/issues/3080>`_)
|
||||||
|
|
@ -270,8 +273,7 @@ t"
|
||||||
(`#3052 <https://github.com/Araq/Nim/issues/3052>`_)
|
(`#3052 <https://github.com/Araq/Nim/issues/3052>`_)
|
||||||
- Fixed "Compiler assertion when evaluating template with static[T]"
|
- Fixed "Compiler assertion when evaluating template with static[T]"
|
||||||
(`#1858 <https://github.com/Araq/Nim/issues/1858>`_)
|
(`#1858 <https://github.com/Araq/Nim/issues/1858>`_)
|
||||||
- Fixed "Erroneous overflow in iterators when compiler built with overflowChec
|
- Fixed "Erroneous overflow in iterators when compiler built with overflowChecks enabled"
|
||||||
ks enabled"
|
|
||||||
(`#3140 <https://github.com/Araq/Nim/issues/3140>`_)
|
(`#3140 <https://github.com/Araq/Nim/issues/3140>`_)
|
||||||
- Fixed "Unicode dashes as "lisp'ish" alternative to hump and snake notation"
|
- Fixed "Unicode dashes as "lisp'ish" alternative to hump and snake notation"
|
||||||
(`#2811 <https://github.com/Araq/Nim/issues/2811>`_)
|
(`#2811 <https://github.com/Araq/Nim/issues/2811>`_)
|
||||||
|
|
@ -283,8 +285,7 @@ ks enabled"
|
||||||
(`#3193 <https://github.com/Araq/Nim/issues/3193>`_)
|
(`#3193 <https://github.com/Araq/Nim/issues/3193>`_)
|
||||||
- Fixed "VM crash when accessing array's element"
|
- Fixed "VM crash when accessing array's element"
|
||||||
(`#3192 <https://github.com/Araq/Nim/issues/3192>`_)
|
(`#3192 <https://github.com/Araq/Nim/issues/3192>`_)
|
||||||
- Fixed "Unexpected proc invoked when different modules add procs to a type fr
|
- Fixed "Unexpected proc invoked when different modules add procs to a type from a 3rd module"
|
||||||
om a 3rd module"
|
|
||||||
(`#2664 <https://github.com/Araq/Nim/issues/2664>`_)
|
(`#2664 <https://github.com/Araq/Nim/issues/2664>`_)
|
||||||
- Fixed "Nim crashes on conditional declaration inside a template"
|
- Fixed "Nim crashes on conditional declaration inside a template"
|
||||||
(`#2670 <https://github.com/Araq/Nim/issues/2670>`_)
|
(`#2670 <https://github.com/Araq/Nim/issues/2670>`_)
|
||||||
|
|
@ -292,8 +293,7 @@ om a 3rd module"
|
||||||
(`#2752 <https://github.com/Araq/Nim/issues/2752>`_)
|
(`#2752 <https://github.com/Araq/Nim/issues/2752>`_)
|
||||||
- Fixed "VM: Cannot assign int value to ref variable"
|
- Fixed "VM: Cannot assign int value to ref variable"
|
||||||
(`#1329 <https://github.com/Araq/Nim/issues/1329>`_)
|
(`#1329 <https://github.com/Araq/Nim/issues/1329>`_)
|
||||||
- Fixed "Incorrect code generated for tagged unions with enums not starting at
|
- Fixed "Incorrect code generated for tagged unions with enums not starting at zero"
|
||||||
zero"
|
|
||||||
(`#3096 <https://github.com/Araq/Nim/issues/3096>`_)
|
(`#3096 <https://github.com/Araq/Nim/issues/3096>`_)
|
||||||
- Fixed "Compile time procs using forward declarations are silently ignored"
|
- Fixed "Compile time procs using forward declarations are silently ignored"
|
||||||
(`#3066 <https://github.com/Araq/Nim/issues/3066>`_)
|
(`#3066 <https://github.com/Araq/Nim/issues/3066>`_)
|
||||||
|
|
@ -301,8 +301,7 @@ om a 3rd module"
|
||||||
(`#1965 <https://github.com/Araq/Nim/issues/1965>`_)
|
(`#1965 <https://github.com/Araq/Nim/issues/1965>`_)
|
||||||
- Fixed "os.getCreationTime is incorrect/impossible on Posix systems"
|
- Fixed "os.getCreationTime is incorrect/impossible on Posix systems"
|
||||||
(`#1058 <https://github.com/Araq/Nim/issues/1058>`_)
|
(`#1058 <https://github.com/Araq/Nim/issues/1058>`_)
|
||||||
- Fixed "Improve error message for osproc.startProcess when command does not e
|
- Fixed "Improve error message for osproc.startProcess when command does not exist"
|
||||||
xist"
|
|
||||||
(`#2183 <https://github.com/Araq/Nim/issues/2183>`_)
|
(`#2183 <https://github.com/Araq/Nim/issues/2183>`_)
|
||||||
- Fixed "gctest segfaults with --gc:markandsweep on x86_64"
|
- Fixed "gctest segfaults with --gc:markandsweep on x86_64"
|
||||||
(`#2305 <https://github.com/Araq/Nim/issues/2305>`_)
|
(`#2305 <https://github.com/Araq/Nim/issues/2305>`_)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue