Merge branch 'devel' of https://github.com/Araq/Nimrod into devel
This commit is contained in:
commit
dd216755ff
33 changed files with 310 additions and 112 deletions
|
|
@ -469,7 +469,8 @@ type
|
||||||
skResult, # special 'result' variable
|
skResult, # special 'result' variable
|
||||||
skProc, # a proc
|
skProc, # a proc
|
||||||
skMethod, # a method
|
skMethod, # a method
|
||||||
skIterator, # an iterator
|
skIterator, # an inline iterator
|
||||||
|
skClosureIterator, # a resumable closure iterator
|
||||||
skConverter, # a type converter
|
skConverter, # a type converter
|
||||||
skMacro, # a macro
|
skMacro, # a macro
|
||||||
skTemplate, # a template; currently also misused for user-defined
|
skTemplate, # a template; currently also misused for user-defined
|
||||||
|
|
@ -485,8 +486,8 @@ type
|
||||||
TSymKinds* = set[TSymKind]
|
TSymKinds* = set[TSymKind]
|
||||||
|
|
||||||
const
|
const
|
||||||
routineKinds* = {skProc, skMethod, skIterator, skConverter,
|
routineKinds* = {skProc, skMethod, skIterator, skClosureIterator,
|
||||||
skMacro, skTemplate}
|
skConverter, skMacro, skTemplate}
|
||||||
tfIncompleteStruct* = tfVarargs
|
tfIncompleteStruct* = tfVarargs
|
||||||
tfUncheckedArray* = tfVarargs
|
tfUncheckedArray* = tfVarargs
|
||||||
tfUnion* = tfNoSideEffect
|
tfUnion* = tfNoSideEffect
|
||||||
|
|
@ -822,8 +823,8 @@ type
|
||||||
# the poor naming choices in the standard library.
|
# the poor naming choices in the standard library.
|
||||||
|
|
||||||
const
|
const
|
||||||
OverloadableSyms* = {skProc, skMethod, skIterator, skConverter,
|
OverloadableSyms* = {skProc, skMethod, skIterator, skClosureIterator,
|
||||||
skModule, skTemplate, skMacro}
|
skConverter, skModule, skTemplate, skMacro}
|
||||||
|
|
||||||
GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody,
|
GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody,
|
||||||
tyGenericParam}
|
tyGenericParam}
|
||||||
|
|
@ -845,7 +846,8 @@ const
|
||||||
tyTuple, tySequence}
|
tyTuple, tySequence}
|
||||||
NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence,
|
NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence,
|
||||||
tyProc, tyString, tyError}
|
tyProc, tyString, tyError}
|
||||||
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator,
|
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType,
|
||||||
|
skIterator, skClosureIterator,
|
||||||
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub}
|
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub}
|
||||||
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
|
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
|
||||||
nfDotSetter, nfDotField,
|
nfDotSetter, nfDotField,
|
||||||
|
|
@ -871,7 +873,10 @@ const
|
||||||
nkStrKinds* = {nkStrLit..nkTripleStrLit}
|
nkStrKinds* = {nkStrLit..nkTripleStrLit}
|
||||||
|
|
||||||
skLocalVars* = {skVar, skLet, skForVar, skParam, skResult}
|
skLocalVars* = {skVar, skLet, skForVar, skParam, skResult}
|
||||||
skProcKinds* = {skProc, skTemplate, skMacro, skIterator, skMethod, skConverter}
|
skProcKinds* = {skProc, skTemplate, skMacro, skIterator, skClosureIterator,
|
||||||
|
skMethod, skConverter}
|
||||||
|
|
||||||
|
skIterators* = {skIterator, skClosureIterator}
|
||||||
|
|
||||||
lfFullExternalName* = lfParamCopy # \
|
lfFullExternalName* = lfParamCopy # \
|
||||||
# only used when 'gCmd == cmdPretty': Indicates that the symbol has been
|
# only used when 'gCmd == cmdPretty': Indicates that the symbol has been
|
||||||
|
|
@ -1481,8 +1486,7 @@ proc originatingModule*(s: PSym): PSym =
|
||||||
while result.kind != skModule: result = result.owner
|
while result.kind != skModule: result = result.owner
|
||||||
|
|
||||||
proc isRoutine*(s: PSym): bool {.inline.} =
|
proc isRoutine*(s: PSym): bool {.inline.} =
|
||||||
result = s.kind in {skProc, skTemplate, skMacro, skIterator, skMethod,
|
result = s.kind in skProcKinds
|
||||||
skConverter}
|
|
||||||
|
|
||||||
proc hasPattern*(s: PSym): bool {.inline.} =
|
proc hasPattern*(s: PSym): bool {.inline.} =
|
||||||
result = isRoutine(s) and s.ast.sons[patternPos].kind != nkEmpty
|
result = isRoutine(s) and s.ast.sons[patternPos].kind != nkEmpty
|
||||||
|
|
|
||||||
|
|
@ -1803,7 +1803,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
else:
|
else:
|
||||||
genProc(p.module, sym)
|
genProc(p.module, sym)
|
||||||
putLocIntoDest(p, d, sym.loc)
|
putLocIntoDest(p, d, sym.loc)
|
||||||
of skProc, skConverter, skIterator:
|
of skProc, skConverter, skIterators:
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -863,7 +863,7 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope =
|
||||||
res.add(t.sons[i].strVal)
|
res.add(t.sons[i].strVal)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
var sym = t.sons[i].sym
|
var sym = t.sons[i].sym
|
||||||
if sym.kind in {skProc, skIterator, skMethod}:
|
if sym.kind in {skProc, skIterator, skClosureIterator, skMethod}:
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, t.sons[i], a)
|
initLocExpr(p, t.sons[i], a)
|
||||||
res.add(rdLoc(a).ropeToStr)
|
res.add(rdLoc(a).ropeToStr)
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ proc mangleName(s: PSym): PRope =
|
||||||
if result == nil:
|
if result == nil:
|
||||||
if gCmd == cmdCompileToLLVM:
|
if gCmd == cmdCompileToLLVM:
|
||||||
case s.kind
|
case s.kind
|
||||||
of skProc, skMethod, skConverter, skConst, skIterator:
|
of skProc, skMethod, skConverter, skConst, skIterators:
|
||||||
result = ~"@"
|
result = ~"@"
|
||||||
of skVar, skForVar, skResult, skLet:
|
of skVar, skForVar, skResult, skLet:
|
||||||
if sfGlobal in s.flags: result = ~"@"
|
if sfGlobal in s.flags: result = ~"@"
|
||||||
|
|
|
||||||
|
|
@ -705,7 +705,7 @@ proc cgsym(m: BModule, name: string): PRope =
|
||||||
var sym = magicsys.getCompilerProc(name)
|
var sym = magicsys.getCompilerProc(name)
|
||||||
if sym != nil:
|
if sym != nil:
|
||||||
case sym.kind
|
case sym.kind
|
||||||
of skProc, skMethod, skConverter, skIterator: genProc(m, sym)
|
of skProc, skMethod, skConverter, skIterators: genProc(m, sym)
|
||||||
of skVar, skResult, skLet: genVarPrototype(m, sym)
|
of skVar, skResult, skLet: genVarPrototype(m, sym)
|
||||||
of skType: discard getTypeDesc(m, sym.typ)
|
of skType: discard getTypeDesc(m, sym.typ)
|
||||||
else: internalError("cgsym: " & name)
|
else: internalError("cgsym: " & name)
|
||||||
|
|
@ -1192,7 +1192,7 @@ 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] = nil
|
||||||
|
|
||||||
proc resetModule*(m: var BModule) =
|
proc resetModule*(m: BModule) =
|
||||||
# between two compilations in CAAS mode, we can throw
|
# between two compilations in CAAS mode, we can throw
|
||||||
# away all the data that was written to disk
|
# away all the data that was written to disk
|
||||||
initLinkedList(m.headerFiles)
|
initLinkedList(m.headerFiles)
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ proc newProc*(prc: PSym, module: BModule): BProc =
|
||||||
result.nestedTryStmts = @[]
|
result.nestedTryStmts = @[]
|
||||||
result.finallySafePoints = @[]
|
result.finallySafePoints = @[]
|
||||||
|
|
||||||
iterator cgenModules*: var BModule =
|
iterator cgenModules*: BModule =
|
||||||
for i in 0..high(gModules):
|
for i in 0..high(gModules):
|
||||||
# ultimately, we are iterating over the file ids here.
|
# ultimately, we are iterating over the file ids here.
|
||||||
# some "files" won't have an associated cgen module (like stdin)
|
# some "files" won't have an associated cgen module (like stdin)
|
||||||
|
|
|
||||||
|
|
@ -366,7 +366,7 @@ proc generateJson(d: PDoc, n: PNode, jArray: PJsonNode = nil): PJsonNode =
|
||||||
proc genSection(d: PDoc, kind: TSymKind) =
|
proc genSection(d: PDoc, kind: TSymKind) =
|
||||||
const sectionNames: array[skModule..skTemplate, string] = [
|
const sectionNames: array[skModule..skTemplate, string] = [
|
||||||
"Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Methods",
|
"Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Methods",
|
||||||
"Iterators", "Converters", "Macros", "Templates"
|
"Iterators", "Iterators", "Converters", "Macros", "Templates"
|
||||||
]
|
]
|
||||||
if d.section[kind] == nil: return
|
if d.section[kind] == nil: return
|
||||||
var title = sectionNames[kind].toRope
|
var title = sectionNames[kind].toRope
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
|
||||||
internalError(n.info, "importSymbol: 2")
|
internalError(n.info, "importSymbol: 2")
|
||||||
# for an enumeration we have to add all identifiers
|
# for an enumeration we have to add all identifiers
|
||||||
case s.kind
|
case s.kind
|
||||||
of skProc, skMethod, skIterator, skMacro, skTemplate, skConverter:
|
of skProcKinds:
|
||||||
# for a overloadable syms add all overloaded routines
|
# for a overloadable syms add all overloaded routines
|
||||||
var it: TIdentIter
|
var it: TIdentIter
|
||||||
var e = initIdentIter(it, fromMod.tab, s.name)
|
var e = initIdentIter(it, fromMod.tab, s.name)
|
||||||
|
|
|
||||||
|
|
@ -1154,7 +1154,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): PRope =
|
||||||
|
|
||||||
proc isIndirect(v: PSym): bool =
|
proc isIndirect(v: PSym): bool =
|
||||||
result = (sfAddrTaken in v.flags) and (mapType(v.typ) != etyObject) and
|
result = (sfAddrTaken in v.flags) and (mapType(v.typ) != etyObject) and
|
||||||
v.kind notin {skProc, skConverter, skMethod, skIterator}
|
v.kind notin {skProc, skConverter, skMethod, skIterator, skClosureIterator}
|
||||||
|
|
||||||
proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||||
var
|
var
|
||||||
|
|
|
||||||
|
|
@ -232,9 +232,9 @@ proc newOuterContext(fn: PSym, up: POuterContext = nil): POuterContext =
|
||||||
initIdNodeTable(result.localsToAccess)
|
initIdNodeTable(result.localsToAccess)
|
||||||
initIdTable(result.localsToEnv)
|
initIdTable(result.localsToEnv)
|
||||||
initIdTable(result.lambdasToEnv)
|
initIdTable(result.lambdasToEnv)
|
||||||
result.isIter = fn.kind == skIterator and fn.typ.callConv == ccClosure
|
result.isIter = fn.kind == skClosureIterator
|
||||||
if result.isIter: initIterContext(result, fn)
|
if result.isIter: initIterContext(result, fn)
|
||||||
|
|
||||||
proc newInnerContext(fn: PSym): PInnerContext =
|
proc newInnerContext(fn: PSym): PInnerContext =
|
||||||
new(result)
|
new(result)
|
||||||
result.fn = fn
|
result.fn = fn
|
||||||
|
|
@ -292,8 +292,7 @@ proc newCall(a, b: PSym): PNode =
|
||||||
result.add newSymNode(b)
|
result.add newSymNode(b)
|
||||||
|
|
||||||
proc isInnerProc(s, outerProc: PSym): bool {.inline.} =
|
proc isInnerProc(s, outerProc: PSym): bool {.inline.} =
|
||||||
result = (s.kind in {skProc, skMethod, skConverter} or
|
result = s.kind in {skProc, skMethod, skConverter, skClosureIterator} and
|
||||||
s.kind == skIterator and s.typ.callConv == ccClosure) and
|
|
||||||
s.skipGenericOwner == outerProc
|
s.skipGenericOwner == outerProc
|
||||||
#s.typ.callConv == ccClosure
|
#s.typ.callConv == ccClosure
|
||||||
|
|
||||||
|
|
@ -653,7 +652,7 @@ proc outerProcSons(o: POuterContext, n: PNode) =
|
||||||
proc liftIterSym*(n: PNode): PNode =
|
proc liftIterSym*(n: PNode): PNode =
|
||||||
# transforms (iter) to (let env = newClosure[iter](); (iter, env))
|
# transforms (iter) to (let env = newClosure[iter](); (iter, env))
|
||||||
let iter = n.sym
|
let iter = n.sym
|
||||||
assert iter.kind == skIterator
|
assert iter.kind == skClosureIterator
|
||||||
|
|
||||||
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
||||||
|
|
||||||
|
|
@ -679,7 +678,7 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
|
||||||
|
|
||||||
var closure = PEnv(idTableGet(o.lambdasToEnv, local))
|
var closure = PEnv(idTableGet(o.lambdasToEnv, local))
|
||||||
|
|
||||||
if local.kind == skIterator and local.typ.callConv == ccClosure:
|
if local.kind == skClosureIterator:
|
||||||
# consider: [i1, i2, i1] Since we merged the iterator's closure
|
# consider: [i1, i2, i1] Since we merged the iterator's closure
|
||||||
# with the captured owning variables, we need to generate the
|
# with the captured owning variables, we need to generate the
|
||||||
# closure generation code again:
|
# closure generation code again:
|
||||||
|
|
@ -843,10 +842,10 @@ proc liftForLoop*(body: PNode): PNode =
|
||||||
|
|
||||||
# static binding?
|
# static binding?
|
||||||
var env: PSym
|
var env: PSym
|
||||||
if call[0].kind == nkSym and call[0].sym.kind == skIterator:
|
if call[0].kind == nkSym and call[0].sym.kind == skClosureIterator:
|
||||||
# createClosure()
|
# createClosure()
|
||||||
let iter = call[0].sym
|
let iter = call[0].sym
|
||||||
assert iter.kind == skIterator
|
assert iter.kind == skClosureIterator
|
||||||
env = copySym(getHiddenParam(iter))
|
env = copySym(getHiddenParam(iter))
|
||||||
|
|
||||||
var v = newNodeI(nkVarSection, body.info)
|
var v = newNodeI(nkVarSection, body.info)
|
||||||
|
|
|
||||||
|
|
@ -109,7 +109,7 @@ type
|
||||||
|
|
||||||
proc getSymRepr*(s: PSym): string =
|
proc getSymRepr*(s: PSym): string =
|
||||||
case s.kind
|
case s.kind
|
||||||
of skProc, skMethod, skConverter, skIterator: result = getProcHeader(s)
|
of skProc, skMethod, skConverter, skIterators: result = getProcHeader(s)
|
||||||
else: result = s.name.s
|
else: result = s.name.s
|
||||||
|
|
||||||
proc ensureNoMissingOrUnusedSymbols(scope: PScope) =
|
proc ensureNoMissingOrUnusedSymbols(scope: PScope) =
|
||||||
|
|
|
||||||
|
|
@ -776,6 +776,17 @@ proc implictPragmas*(c: PContext, sym: PSym, n: PNode,
|
||||||
addToLib(lib, sym)
|
addToLib(lib, sym)
|
||||||
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
|
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
|
||||||
|
|
||||||
|
proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
|
||||||
|
if n == nil or n.sons == nil:
|
||||||
|
return false
|
||||||
|
|
||||||
|
for p in n.sons:
|
||||||
|
var key = if p.kind == nkExprColonExpr: p[0] else: p
|
||||||
|
if key.kind == nkIdent and whichKeyword(key.ident) == pragma:
|
||||||
|
return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
|
||||||
if n == nil: return
|
if n == nil: return
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
errors[errors.len - 1].add("\n " & err)
|
errors[errors.len - 1].add("\n " & err)
|
||||||
if z.state == csMatch:
|
if z.state == csMatch:
|
||||||
# little hack so that iterators are preferred over everything else:
|
# little hack so that iterators are preferred over everything else:
|
||||||
if sym.kind == skIterator: inc(z.exactMatches, 200)
|
if sym.kind in skIterators: inc(z.exactMatches, 200)
|
||||||
case best.state
|
case best.state
|
||||||
of csEmpty, csNoMatch: best = z
|
of csEmpty, csNoMatch: best = z
|
||||||
of csMatch:
|
of csMatch:
|
||||||
|
|
@ -289,8 +289,9 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
result = newNodeI(a.kind, n.info)
|
result = newNodeI(a.kind, n.info)
|
||||||
for i in countup(0, len(a)-1):
|
for i in countup(0, len(a)-1):
|
||||||
var candidate = a.sons[i].sym
|
var candidate = a.sons[i].sym
|
||||||
if candidate.kind in {skProc, skMethod, skConverter, skIterator}:
|
if candidate.kind in {skProc, skMethod, skConverter,
|
||||||
# if suffices that the candidate has the proper number of generic
|
skIterator, skClosureIterator}:
|
||||||
|
# it suffices that the candidate has the proper number of generic
|
||||||
# type parameters:
|
# type parameters:
|
||||||
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
|
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
|
||||||
result.add(explicitGenericSym(c, n, candidate))
|
result.add(explicitGenericSym(c, n, candidate))
|
||||||
|
|
|
||||||
|
|
@ -274,7 +274,7 @@ proc makeRangeType*(c: PContext; first, last: BiggestInt;
|
||||||
addSonSkipIntLit(result, intType) # basetype of range
|
addSonSkipIntLit(result, intType) # basetype of range
|
||||||
|
|
||||||
proc markIndirect*(c: PContext, s: PSym) {.inline.} =
|
proc markIndirect*(c: PContext, s: PSym) {.inline.} =
|
||||||
if s.kind in {skProc, skConverter, skMethod, skIterator}:
|
if s.kind in {skProc, skConverter, skMethod, skIterator, skClosureIterator}:
|
||||||
incl(s.flags, sfAddrTaken)
|
incl(s.flags, sfAddrTaken)
|
||||||
# XXX add to 'c' for global analysis
|
# XXX add to 'c' for global analysis
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -323,11 +323,6 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
|
||||||
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
|
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
|
||||||
t.callConv == ccClosure and
|
t.callConv == ccClosure and
|
||||||
tfIterator notin t.flags))
|
tfIterator notin t.flags))
|
||||||
of "iterator":
|
|
||||||
let t = skipTypes(t1, abstractRange)
|
|
||||||
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
|
|
||||||
t.callConv == ccClosure and
|
|
||||||
tfIterator in t.flags))
|
|
||||||
else:
|
else:
|
||||||
var t2 = n[2].typ.skipTypes({tyTypeDesc})
|
var t2 = n[2].typ.skipTypes({tyTypeDesc})
|
||||||
let lifted = liftParamType(c, skType, newNodeI(nkArgList, n.info),
|
let lifted = liftParamType(c, skType, newNodeI(nkArgList, n.info),
|
||||||
|
|
@ -662,11 +657,11 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||||
flags: TExprFlags): PNode =
|
flags: TExprFlags): PNode =
|
||||||
if flags*{efInTypeof, efWantIterator} != {}:
|
if flags*{efInTypeof, efWantIterator} != {}:
|
||||||
# consider: 'for x in pReturningArray()' --> we don't want the restriction
|
# consider: 'for x in pReturningArray()' --> we don't want the restriction
|
||||||
# to 'skIterator' anymore; skIterator is preferred in sigmatch already for
|
# to 'skIterators' anymore; skIterators are preferred in sigmatch already
|
||||||
# typeof support.
|
# for typeof support.
|
||||||
# for ``type(countup(1,3))``, see ``tests/ttoseq``.
|
# for ``type(countup(1,3))``, see ``tests/ttoseq``.
|
||||||
result = semOverloadedCall(c, n, nOrig,
|
result = semOverloadedCall(c, n, nOrig,
|
||||||
{skProc, skMethod, skConverter, skMacro, skTemplate, skIterator})
|
{skProc, skMethod, skConverter, skMacro, skTemplate}+skIterators)
|
||||||
else:
|
else:
|
||||||
result = semOverloadedCall(c, n, nOrig,
|
result = semOverloadedCall(c, n, nOrig,
|
||||||
{skProc, skMethod, skConverter, skMacro, skTemplate})
|
{skProc, skMethod, skConverter, skMacro, skTemplate})
|
||||||
|
|
@ -679,7 +674,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||||
case callee.kind
|
case callee.kind
|
||||||
of skMacro, skTemplate: discard
|
of skMacro, skTemplate: discard
|
||||||
else:
|
else:
|
||||||
if (callee.kind == skIterator) and (callee.id == c.p.owner.id):
|
if (callee.kind in skIterators) and (callee.id == c.p.owner.id):
|
||||||
localError(n.info, errRecursiveDependencyX, callee.name.s)
|
localError(n.info, errRecursiveDependencyX, callee.name.s)
|
||||||
if sfNoSideEffect notin callee.flags:
|
if sfNoSideEffect notin callee.flags:
|
||||||
if {sfImportc, sfSideEffect} * callee.flags != {}:
|
if {sfImportc, sfSideEffect} * callee.flags != {}:
|
||||||
|
|
@ -1193,7 +1188,7 @@ proc semReturn(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
checkSonsLen(n, 1)
|
checkSonsLen(n, 1)
|
||||||
if c.p.owner.kind in {skConverter, skMethod, skProc, skMacro} or
|
if c.p.owner.kind in {skConverter, skMethod, skProc, skMacro} or
|
||||||
(c.p.owner.kind == skIterator and c.p.owner.typ.callConv == ccClosure):
|
c.p.owner.kind == skClosureIterator:
|
||||||
if n.sons[0].kind != nkEmpty:
|
if n.sons[0].kind != nkEmpty:
|
||||||
# transform ``return expr`` to ``result = expr; return``
|
# transform ``return expr`` to ``result = expr; return``
|
||||||
if c.p.resultSym != nil:
|
if c.p.resultSym != nil:
|
||||||
|
|
@ -1258,7 +1253,7 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
|
||||||
proc semYield(c: PContext, n: PNode): PNode =
|
proc semYield(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
checkSonsLen(n, 1)
|
checkSonsLen(n, 1)
|
||||||
if c.p.owner == nil or c.p.owner.kind != skIterator:
|
if c.p.owner == nil or c.p.owner.kind notin skIterators:
|
||||||
localError(n.info, errYieldNotAllowedHere)
|
localError(n.info, errYieldNotAllowedHere)
|
||||||
elif c.p.inTryStmt > 0 and c.p.owner.typ.callConv != ccInline:
|
elif c.p.inTryStmt > 0 and c.p.owner.typ.callConv != ccInline:
|
||||||
localError(n.info, errYieldNotAllowedInTryStmt)
|
localError(n.info, errYieldNotAllowedInTryStmt)
|
||||||
|
|
@ -1266,9 +1261,11 @@ proc semYield(c: PContext, n: PNode): PNode =
|
||||||
n.sons[0] = semExprWithType(c, n.sons[0]) # check for type compatibility:
|
n.sons[0] = semExprWithType(c, n.sons[0]) # check for type compatibility:
|
||||||
var restype = c.p.owner.typ.sons[0]
|
var restype = c.p.owner.typ.sons[0]
|
||||||
if restype != nil:
|
if restype != nil:
|
||||||
n.sons[0] = fitNode(c, restype, n.sons[0])
|
let adjustedRes = if c.p.owner.kind == skIterator: restype.base
|
||||||
|
else: restype
|
||||||
|
n.sons[0] = fitNode(c, adjustedRes, n.sons[0])
|
||||||
if n.sons[0].typ == nil: internalError(n.info, "semYield")
|
if n.sons[0].typ == nil: internalError(n.info, "semYield")
|
||||||
semYieldVarResult(c, n, restype)
|
semYieldVarResult(c, n, adjustedRes)
|
||||||
else:
|
else:
|
||||||
localError(n.info, errCannotReturnExpr)
|
localError(n.info, errCannotReturnExpr)
|
||||||
elif c.p.owner.typ.sons[0] != nil:
|
elif c.p.owner.typ.sons[0] != nil:
|
||||||
|
|
@ -1828,7 +1825,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
var s = lookUp(c, n)
|
var s = lookUp(c, n)
|
||||||
semCaptureSym(s, c.p.owner)
|
semCaptureSym(s, c.p.owner)
|
||||||
result = semSym(c, n, s, flags)
|
result = semSym(c, n, s, flags)
|
||||||
if s.kind in {skProc, skMethod, skIterator, skConverter}:
|
if s.kind in {skProc, skMethod, skConverter}+skIterators:
|
||||||
#performProcvarCheck(c, n, s)
|
#performProcvarCheck(c, n, s)
|
||||||
result = symChoice(c, n, s, scClosed)
|
result = symChoice(c, n, s, scClosed)
|
||||||
if result.kind == nkSym:
|
if result.kind == nkSym:
|
||||||
|
|
@ -1884,7 +1881,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
message(n.info, warnDeprecated, "bind")
|
message(n.info, warnDeprecated, "bind")
|
||||||
result = semExpr(c, n.sons[0], flags)
|
result = semExpr(c, n.sons[0], flags)
|
||||||
of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy, nkStaticTy:
|
of nkTypeOfExpr, nkTupleTy, nkRefTy..nkEnumTy, nkStaticTy:
|
||||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc, tyIter})
|
||||||
result.typ = makeTypeDesc(c, typ)
|
result.typ = makeTypeDesc(c, typ)
|
||||||
#result = symNodeFromType(c, typ, n.info)
|
#result = symNodeFromType(c, typ, n.info)
|
||||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
||||||
|
|
@ -1918,7 +1915,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
localError(n.info, errUseQualifier, s.name.s)
|
localError(n.info, errUseQualifier, s.name.s)
|
||||||
elif s.magic == mNone: result = semDirectOp(c, n, flags)
|
elif s.magic == mNone: result = semDirectOp(c, n, flags)
|
||||||
else: result = semMagic(c, n, s, flags)
|
else: result = semMagic(c, n, s, flags)
|
||||||
of skProc, skMethod, skConverter, skIterator:
|
of skProc, skMethod, skConverter, skIterators:
|
||||||
if s.magic == mNone: result = semDirectOp(c, n, flags)
|
if s.magic == mNone: result = semDirectOp(c, n, flags)
|
||||||
else: result = semMagic(c, n, s, flags)
|
else: result = semMagic(c, n, s, flags)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1942,7 +1939,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
var s = qualifiedLookUp(c, n.sons[0], {checkUndeclared})
|
var s = qualifiedLookUp(c, n.sons[0], {checkUndeclared})
|
||||||
if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}:
|
if s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators:
|
||||||
# type parameters: partial generic specialization
|
# type parameters: partial generic specialization
|
||||||
n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
|
n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
|
||||||
result = explicitGenericInstantiation(c, n, s)
|
result = explicitGenericInstantiation(c, n, s)
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
of skUnknown:
|
of skUnknown:
|
||||||
# Introduced in this pass! Leave it as an identifier.
|
# Introduced in this pass! Leave it as an identifier.
|
||||||
result = n
|
result = n
|
||||||
of skProc, skMethod, skIterator, skConverter:
|
of skProc, skMethod, skIterators, skConverter:
|
||||||
result = symChoice(c, n, s, scOpen)
|
result = symChoice(c, n, s, scOpen)
|
||||||
of skTemplate:
|
of skTemplate:
|
||||||
if macroToExpand(s):
|
if macroToExpand(s):
|
||||||
|
|
@ -141,7 +141,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||||
# symbol lookup ...
|
# symbol lookup ...
|
||||||
of skUnknown, skParam:
|
of skUnknown, skParam:
|
||||||
# Leave it as an identifier.
|
# Leave it as an identifier.
|
||||||
of skProc, skMethod, skIterator, skConverter:
|
of skProc, skMethod, skIterators, skConverter:
|
||||||
result.sons[0] = symChoice(c, n.sons[0], s, scOption)
|
result.sons[0] = symChoice(c, n.sons[0], s, scOption)
|
||||||
first = 1
|
first = 1
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
|
|
|
||||||
|
|
@ -76,8 +76,8 @@ proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
|
||||||
|
|
||||||
proc semProcvarCheck(c: PContext, n: PNode) =
|
proc semProcvarCheck(c: PContext, n: PNode) =
|
||||||
let n = n.skipConv
|
let n = n.skipConv
|
||||||
if n.kind == nkSym and n.sym.kind in {skProc, skMethod, skIterator,
|
if n.kind == nkSym and n.sym.kind in {skProc, skMethod, skConverter,
|
||||||
skConverter}:
|
skIterator, skClosureIterator}:
|
||||||
performProcvarCheck(c, n, n.sym)
|
performProcvarCheck(c, n, n.sym)
|
||||||
|
|
||||||
proc semProc(c: PContext, n: PNode): PNode
|
proc semProc(c: PContext, n: PNode): PNode
|
||||||
|
|
@ -616,7 +616,8 @@ proc symForVar(c: PContext, n: PNode): PSym =
|
||||||
proc semForVars(c: PContext, n: PNode): PNode =
|
proc semForVars(c: PContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
var length = sonsLen(n)
|
var length = sonsLen(n)
|
||||||
var iter = skipTypes(n.sons[length-2].typ, {tyGenericInst})
|
let iterBase = n.sons[length-2].typ.skipTypes({tyIter})
|
||||||
|
var iter = skipTypes(iterBase, {tyGenericInst})
|
||||||
# length == 3 means that there is one for loop variable
|
# length == 3 means that there is one for loop variable
|
||||||
# and thus no tuple unpacking:
|
# and thus no tuple unpacking:
|
||||||
if iter.kind != tyTuple or length == 3:
|
if iter.kind != tyTuple or length == 3:
|
||||||
|
|
@ -626,7 +627,7 @@ proc semForVars(c: PContext, n: PNode): PNode =
|
||||||
# BUGFIX: don't use `iter` here as that would strip away
|
# BUGFIX: don't use `iter` here as that would strip away
|
||||||
# the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
|
# the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
|
||||||
# for an example:
|
# for an example:
|
||||||
v.typ = n.sons[length-2].typ
|
v.typ = iterBase
|
||||||
n.sons[0] = newSymNode(v)
|
n.sons[0] = newSymNode(v)
|
||||||
if sfGenSym notin v.flags: addForVarDecl(c, v)
|
if sfGenSym notin v.flags: addForVarDecl(c, v)
|
||||||
else:
|
else:
|
||||||
|
|
@ -664,7 +665,7 @@ proc semFor(c: PContext, n: PNode): PNode =
|
||||||
# first class iterator:
|
# first class iterator:
|
||||||
result = semForVars(c, n)
|
result = semForVars(c, n)
|
||||||
elif call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
|
elif call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
|
||||||
call.sons[0].sym.kind != skIterator:
|
call.sons[0].sym.kind notin skIterators:
|
||||||
if length == 3:
|
if length == 3:
|
||||||
n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2])
|
n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2])
|
||||||
elif length == 4:
|
elif length == 4:
|
||||||
|
|
@ -997,8 +998,7 @@ proc activate(c: PContext, n: PNode) =
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
|
proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
|
||||||
if s.typ.sons[0] != nil and
|
if s.typ.sons[0] != nil and s.kind != skIterator:
|
||||||
(s.kind != skIterator or s.typ.callConv == ccClosure):
|
|
||||||
addResult(c, s.typ.sons[0], n.info, s.kind)
|
addResult(c, s.typ.sons[0], n.info, s.kind)
|
||||||
addResultNode(c, n)
|
addResultNode(c, n)
|
||||||
|
|
||||||
|
|
@ -1073,12 +1073,12 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
rawAddSon(s.typ, nil)
|
rawAddSon(s.typ, nil)
|
||||||
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 == skIterator:
|
if s.kind in skIterators:
|
||||||
s.typ.flags.incl(tfIterator)
|
s.typ.flags.incl(tfIterator)
|
||||||
|
|
||||||
var proto = searchForProc(c, s.scope, s)
|
var proto = searchForProc(c, s.scope, s)
|
||||||
if proto == nil:
|
if proto == nil:
|
||||||
if s.kind == skIterator and isAnon: s.typ.callConv = ccClosure
|
if s.kind == skClosureIterator: s.typ.callConv = ccClosure
|
||||||
else: s.typ.callConv = lastOptionEntry(c).defaultCC
|
else: s.typ.callConv = lastOptionEntry(c).defaultCC
|
||||||
# add it here, so that recursive procs are possible:
|
# add it here, so that recursive procs are possible:
|
||||||
if sfGenSym in s.flags: discard
|
if sfGenSym in s.flags: discard
|
||||||
|
|
@ -1138,7 +1138,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
n.sons[bodyPos] = transformBody(c.module, semBody, s)
|
n.sons[bodyPos] = transformBody(c.module, semBody, s)
|
||||||
popProcCon(c)
|
popProcCon(c)
|
||||||
else:
|
else:
|
||||||
if s.typ.sons[0] != nil and kind != skIterator:
|
if s.typ.sons[0] != nil and kind notin skIterators:
|
||||||
addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
|
addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
|
||||||
var toBind = initIntSet()
|
var toBind = initIntSet()
|
||||||
n.sons[bodyPos] = semGenericStmtScope(c, n.sons[bodyPos], {}, toBind)
|
n.sons[bodyPos] = semGenericStmtScope(c, n.sons[bodyPos], {}, toBind)
|
||||||
|
|
@ -1165,7 +1165,10 @@ proc determineType(c: PContext, s: PSym) =
|
||||||
discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType)
|
discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType)
|
||||||
|
|
||||||
proc semIterator(c: PContext, n: PNode): PNode =
|
proc semIterator(c: PContext, n: PNode): PNode =
|
||||||
result = semProcAux(c, n, skIterator, iteratorPragmas)
|
let kind = if hasPragma(n[pragmasPos], wClosure) or
|
||||||
|
n[namePos].kind == nkEmpty: skClosureIterator
|
||||||
|
else: skIterator
|
||||||
|
result = semProcAux(c, n, kind, iteratorPragmas)
|
||||||
var s = result.sons[namePos].sym
|
var s = result.sons[namePos].sym
|
||||||
var t = s.typ
|
var t = s.typ
|
||||||
if t.sons[0] == nil and s.typ.callConv != ccClosure:
|
if t.sons[0] == nil and s.typ.callConv != ccClosure:
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
of skUnknown:
|
of skUnknown:
|
||||||
# Introduced in this pass! Leave it as an identifier.
|
# Introduced in this pass! Leave it as an identifier.
|
||||||
result = n
|
result = n
|
||||||
of skProc, skMethod, skIterator, skConverter, skTemplate, skMacro:
|
of OverloadableSyms:
|
||||||
result = symChoice(c, n, s, scOpen)
|
result = symChoice(c, n, s, scOpen)
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
result = newSymNodeTypeDesc(s, n.info)
|
result = newSymNodeTypeDesc(s, n.info)
|
||||||
|
|
@ -348,7 +348,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
of nkMethodDef:
|
of nkMethodDef:
|
||||||
result = semRoutineInTemplBody(c, n, skMethod)
|
result = semRoutineInTemplBody(c, n, skMethod)
|
||||||
of nkIteratorDef:
|
of nkIteratorDef:
|
||||||
result = semRoutineInTemplBody(c, n, skIterator)
|
result = semRoutineInTemplBody(c, n, n[namePos].sym.kind)
|
||||||
of nkTemplateDef:
|
of nkTemplateDef:
|
||||||
result = semRoutineInTemplBody(c, n, skTemplate)
|
result = semRoutineInTemplBody(c, n, skTemplate)
|
||||||
of nkMacroDef:
|
of nkMacroDef:
|
||||||
|
|
|
||||||
|
|
@ -711,6 +711,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
for i in 0 .. paramType.sonsLen - 2:
|
for i in 0 .. paramType.sonsLen - 2:
|
||||||
result.rawAddSon newTypeS(tyAnything, c)
|
result.rawAddSon newTypeS(tyAnything, c)
|
||||||
# result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true))
|
# result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true))
|
||||||
|
|
||||||
|
if paramType.lastSon.kind == tyUserTypeClass:
|
||||||
|
result.kind = tyUserTypeClassInst
|
||||||
|
result.rawAddSon paramType.lastSon
|
||||||
|
return addImplicitGeneric(result)
|
||||||
|
|
||||||
result = instGenericContainer(c, paramType.sym.info, result,
|
result = instGenericContainer(c, paramType.sym.info, result,
|
||||||
allowMetaTypes = true)
|
allowMetaTypes = true)
|
||||||
result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result])
|
result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result])
|
||||||
|
|
@ -845,8 +851,10 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||||
n.sons[0].info)
|
n.sons[0].info)
|
||||||
if lifted != nil: r = lifted
|
if lifted != nil: r = lifted
|
||||||
r.flags.incl tfRetType
|
r.flags.incl tfRetType
|
||||||
result.sons[0] = skipIntLit(r)
|
r = skipIntLit(r)
|
||||||
res.typ = result.sons[0]
|
if kind == skIterator: r = newTypeWithSons(c, tyIter, @[r])
|
||||||
|
result.sons[0] = r
|
||||||
|
res.typ = r
|
||||||
|
|
||||||
proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
|
proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
|
||||||
checkMinSonsLen(n, 1)
|
checkMinSonsLen(n, 1)
|
||||||
|
|
@ -951,6 +959,23 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
|
||||||
let typ = semTypeNode(c, n, nil)
|
let typ = semTypeNode(c, n, nil)
|
||||||
result.sons.safeAdd(typ)
|
result.sons.safeAdd(typ)
|
||||||
|
|
||||||
|
proc semProcTypeWithScope(c: PContext, n: PNode,
|
||||||
|
prev: PType, kind: TSymKind): PType =
|
||||||
|
checkSonsLen(n, 2)
|
||||||
|
openScope(c)
|
||||||
|
result = semProcTypeNode(c, n.sons[0], nil, prev, kind)
|
||||||
|
# dummy symbol for `pragma`:
|
||||||
|
var s = newSymS(kind, newIdentNode(getIdent("dummy"), n.info), c)
|
||||||
|
s.typ = result
|
||||||
|
if n.sons[1].kind == nkEmpty or n.sons[1].len == 0:
|
||||||
|
if result.callConv == ccDefault:
|
||||||
|
result.callConv = ccClosure
|
||||||
|
#Message(n.info, warnImplicitClosure, renderTree(n))
|
||||||
|
else:
|
||||||
|
pragma(c, s, n.sons[1], procTypePragmas)
|
||||||
|
when useEffectSystem: setEffectsForProcType(result, n.sons[1])
|
||||||
|
closeScope(c)
|
||||||
|
|
||||||
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
result = nil
|
result = nil
|
||||||
if gCmd == cmdIdeTools: suggestExpr(c, n)
|
if gCmd == cmdIdeTools: suggestExpr(c, n)
|
||||||
|
|
@ -959,7 +984,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
of nkTypeOfExpr:
|
of nkTypeOfExpr:
|
||||||
# for ``type(countup(1,3))``, see ``tests/ttoseq``.
|
# for ``type(countup(1,3))``, see ``tests/ttoseq``.
|
||||||
checkSonsLen(n, 1)
|
checkSonsLen(n, 1)
|
||||||
result = semExprWithType(c, n.sons[0], {efInTypeof}).typ
|
result = semExprWithType(c, n.sons[0], {efInTypeof}).typ.skipTypes({tyIter})
|
||||||
of nkPar:
|
of nkPar:
|
||||||
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1073,27 +1098,18 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
var base = semTypeNode(c, n.sons[0], nil)
|
var base = semTypeNode(c, n.sons[0], nil)
|
||||||
result.rawAddSon(base)
|
result.rawAddSon(base)
|
||||||
result.flags.incl tfHasStatic
|
result.flags.incl tfHasStatic
|
||||||
of nkProcTy, nkIteratorTy:
|
of nkIteratorTy:
|
||||||
|
if n.sonsLen == 0:
|
||||||
|
result = newConstraint(c, tyIter)
|
||||||
|
else:
|
||||||
|
result = semProcTypeWithScope(c, n, prev, skClosureIterator)
|
||||||
|
result.flags.incl(tfIterator)
|
||||||
|
result.callConv = ccClosure
|
||||||
|
of nkProcTy:
|
||||||
if n.sonsLen == 0:
|
if n.sonsLen == 0:
|
||||||
result = newConstraint(c, tyProc)
|
result = newConstraint(c, tyProc)
|
||||||
else:
|
else:
|
||||||
checkSonsLen(n, 2)
|
result = semProcTypeWithScope(c, n, prev, skProc)
|
||||||
openScope(c)
|
|
||||||
result = semProcTypeNode(c, n.sons[0], nil, prev, skProc)
|
|
||||||
# dummy symbol for `pragma`:
|
|
||||||
var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
|
|
||||||
s.typ = result
|
|
||||||
if n.sons[1].kind == nkEmpty or n.sons[1].len == 0:
|
|
||||||
if result.callConv == ccDefault:
|
|
||||||
result.callConv = ccClosure
|
|
||||||
#Message(n.info, warnImplicitClosure, renderTree(n))
|
|
||||||
else:
|
|
||||||
pragma(c, s, n.sons[1], procTypePragmas)
|
|
||||||
when useEffectSystem: setEffectsForProcType(result, n.sons[1])
|
|
||||||
closeScope(c)
|
|
||||||
if n.kind == nkIteratorTy:
|
|
||||||
result.flags.incl(tfIterator)
|
|
||||||
result.callConv = ccClosure
|
|
||||||
of nkEnumTy: result = semEnum(c, n, prev)
|
of nkEnumTy: result = semEnum(c, n, prev)
|
||||||
of nkType: result = n.typ
|
of nkType: result = n.typ
|
||||||
of nkStmtListType: result = semStmtListType(c, n, prev)
|
of nkStmtListType: result = semStmtListType(c, n, prev)
|
||||||
|
|
|
||||||
|
|
@ -410,7 +410,10 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
return isNone
|
return isNone
|
||||||
when useEffectSystem:
|
when useEffectSystem:
|
||||||
if not compatibleEffects(f, a): return isNone
|
if not compatibleEffects(f, a): return isNone
|
||||||
of tyNil: result = f.allowsNil
|
of tyNil:
|
||||||
|
result = f.allowsNil
|
||||||
|
of tyIter:
|
||||||
|
if tfIterator in f.flags: result = typeRel(c, f.base, a.base)
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
|
proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
|
||||||
|
|
@ -921,14 +924,21 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||||
result = typeRel(c, prev.base, a.base)
|
result = typeRel(c, prev.base, a.base)
|
||||||
else:
|
else:
|
||||||
result = isNone
|
result = isNone
|
||||||
|
|
||||||
|
of tyIter:
|
||||||
|
if a.kind == tyIter or
|
||||||
|
(a.kind == tyProc and tfIterator in a.flags):
|
||||||
|
result = typeRel(c, f.base, a.base)
|
||||||
|
else:
|
||||||
|
result = isNone
|
||||||
|
|
||||||
of tyStmt:
|
of tyStmt:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
|
|
||||||
of tyProxy:
|
of tyProxy:
|
||||||
result = isEqual
|
result = isEqual
|
||||||
|
|
||||||
else: internalError("typeRel: " & $f.kind)
|
else: internalAssert false
|
||||||
|
|
||||||
proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation =
|
proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation =
|
||||||
var m: TCandidate
|
var m: TCandidate
|
||||||
|
|
@ -1138,7 +1148,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
||||||
z.calleeSym = m.calleeSym
|
z.calleeSym = m.calleeSym
|
||||||
var best = -1
|
var best = -1
|
||||||
for i in countup(0, sonsLen(arg) - 1):
|
for i in countup(0, sonsLen(arg) - 1):
|
||||||
if arg.sons[i].sym.kind in {skProc, skIterator, skMethod, skConverter}:
|
if arg.sons[i].sym.kind in {skProc, skMethod, skConverter}+skIterators:
|
||||||
copyCandidate(z, m)
|
copyCandidate(z, m)
|
||||||
var r = typeRel(z, f, arg.sons[i].typ)
|
var r = typeRel(z, f, arg.sons[i].typ)
|
||||||
if r != isNone:
|
if r != isNone:
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ proc newAsgnStmt(c: PTransf, le: PNode, ri: PTransNode): PTransNode =
|
||||||
result[1] = ri
|
result[1] = ri
|
||||||
|
|
||||||
proc transformSymAux(c: PTransf, n: PNode): PNode =
|
proc transformSymAux(c: PTransf, n: PNode): PNode =
|
||||||
#if n.sym.kind == skIterator and n.sym.typ.callConv == ccClosure:
|
#if n.sym.kind == skClosureIterator:
|
||||||
# return liftIterSym(n)
|
# return liftIterSym(n)
|
||||||
var b: PNode
|
var b: PNode
|
||||||
var tc = c.transCon
|
var tc = c.transCon
|
||||||
|
|
@ -434,7 +434,6 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
|
||||||
var length = sonsLen(n)
|
var length = sonsLen(n)
|
||||||
var call = n.sons[length - 2]
|
var call = n.sons[length - 2]
|
||||||
if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
|
if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
|
||||||
call.sons[0].typ.callConv == ccClosure or
|
|
||||||
call.sons[0].sym.kind != skIterator:
|
call.sons[0].sym.kind != skIterator:
|
||||||
n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode
|
n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode
|
||||||
return lambdalifting.liftForLoop(n).PTransNode
|
return lambdalifting.liftForLoop(n).PTransNode
|
||||||
|
|
@ -454,7 +453,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
|
||||||
var newC = newTransCon(getCurrOwner(c))
|
var newC = newTransCon(getCurrOwner(c))
|
||||||
newC.forStmt = n
|
newC.forStmt = n
|
||||||
newC.forLoopBody = loopBody
|
newC.forLoopBody = loopBody
|
||||||
if iter.kind != skIterator: internalError(call.info, "transformFor")
|
internalAssert iter.kind == skIterator
|
||||||
# generate access statements for the parameters (unless they are constant)
|
# generate access statements for the parameters (unless they are constant)
|
||||||
pushTransCon(c, newC)
|
pushTransCon(c, newC)
|
||||||
for i in countup(1, sonsLen(call) - 1):
|
for i in countup(1, sonsLen(call) - 1):
|
||||||
|
|
@ -741,7 +740,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
|
||||||
var c = openTransf(module, "")
|
var c = openTransf(module, "")
|
||||||
result = processTransf(c, n, prc)
|
result = processTransf(c, n, prc)
|
||||||
result = liftLambdas(prc, result)
|
result = liftLambdas(prc, result)
|
||||||
#if prc.kind == skIterator and prc.typ.callConv == ccClosure:
|
#if prc.kind == skClosureIterator:
|
||||||
# result = lambdalifting.liftIterator(prc, result)
|
# result = lambdalifting.liftIterator(prc, result)
|
||||||
incl(result.flags, nfTransf)
|
incl(result.flags, nfTransf)
|
||||||
when useEffectSystem: trackProc(prc, result)
|
when useEffectSystem: trackProc(prc, result)
|
||||||
|
|
|
||||||
|
|
@ -1247,7 +1247,7 @@ proc computeSize(typ: PType): BiggestInt =
|
||||||
|
|
||||||
proc getReturnType*(s: PSym): PType =
|
proc getReturnType*(s: PSym): PType =
|
||||||
# Obtains the return type of a iterator/proc/macro/template
|
# Obtains the return type of a iterator/proc/macro/template
|
||||||
assert s.kind in {skProc, skTemplate, skMacro, skIterator}
|
assert s.kind in skProcKinds
|
||||||
result = s.typ.sons[0]
|
result = s.typ.sons[0]
|
||||||
|
|
||||||
proc getSize(typ: PType): BiggestInt =
|
proc getSize(typ: PType): BiggestInt =
|
||||||
|
|
|
||||||
|
|
@ -1330,7 +1330,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||||
case s.kind
|
case s.kind
|
||||||
of skVar, skForVar, skTemp, skLet, skParam, skResult:
|
of skVar, skForVar, skTemp, skLet, skParam, skResult:
|
||||||
genRdVar(c, n, dest, flags)
|
genRdVar(c, n, dest, flags)
|
||||||
of skProc, skConverter, skMacro, skTemplate, skMethod, skIterator:
|
of skProc, skConverter, skMacro, skTemplate, skMethod, skIterators:
|
||||||
# 'skTemplate' is only allowed for 'getAst' support:
|
# 'skTemplate' is only allowed for 'getAst' support:
|
||||||
if sfImportc in s.flags: c.importcSym(n.info, s)
|
if sfImportc in s.flags: c.importcSym(n.info, s)
|
||||||
genLit(c, n, dest)
|
genLit(c, n, dest)
|
||||||
|
|
|
||||||
|
|
@ -279,8 +279,8 @@ skForVar
|
||||||
col 7: ""
|
col 7: ""
|
||||||
|
|
||||||
|
|
||||||
skIterator
|
skIterator, skClosureIterator
|
||||||
----------
|
-----------------------------
|
||||||
|
|
||||||
The fourth column will be the empty string if the iterator is being
|
The fourth column will be the empty string if the iterator is being
|
||||||
defined, since at that point in the file the parser hasn't processed
|
defined, since at that point in the file the parser hasn't processed
|
||||||
|
|
|
||||||
|
|
@ -3481,7 +3481,7 @@ Declarative type classes are written in the following form:
|
||||||
c.len is ordinal
|
c.len is ordinal
|
||||||
items(c) is iterator
|
items(c) is iterator
|
||||||
for value in c:
|
for value in c:
|
||||||
type(value) is T
|
value.type is T
|
||||||
|
|
||||||
The type class will be matched if:
|
The type class will be matched if:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ type
|
||||||
nskUnknown, nskConditional, nskDynLib, nskParam,
|
nskUnknown, nskConditional, nskDynLib, nskParam,
|
||||||
nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet,
|
nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet,
|
||||||
nskConst, nskResult,
|
nskConst, nskResult,
|
||||||
nskProc, nskMethod, nskIterator,
|
nskProc, nskMethod, nskIterator, nskClosureIterator,
|
||||||
nskConverter, nskMacro, nskTemplate, nskField,
|
nskConverter, nskMacro, nskTemplate, nskField,
|
||||||
nskEnumField, nskForVar, nskLabel,
|
nskEnumField, nskForVar, nskLabel,
|
||||||
nskStub
|
nskStub
|
||||||
|
|
|
||||||
|
|
@ -373,5 +373,8 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); }
|
||||||
# define GC_GUARD
|
# define GC_GUARD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Test to see if nimrod and the C compiler agrees on the size of a pointer.
|
||||||
|
On disagreement, your C compiler will say something like:
|
||||||
|
"error: 'assert_numbits' declared as an array with a negative size" */
|
||||||
typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
|
typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1164,6 +1164,14 @@ when not defined(nimrodVM):
|
||||||
## from it before writing to it is undefined behaviour!
|
## from it before writing to it is undefined behaviour!
|
||||||
## The allocated memory belongs to its allocating thread!
|
## The allocated memory belongs to its allocating thread!
|
||||||
## Use `allocShared` to allocate from a shared heap.
|
## Use `allocShared` to allocate from a shared heap.
|
||||||
|
proc alloc*(T: typedesc, size = 1): ptr T {.inline.} =
|
||||||
|
## allocates a new memory block with at least ``T.sizeof * size``
|
||||||
|
## bytes. The block has to be freed with ``realloc(block, 0)`` or
|
||||||
|
## ``dealloc(block)``. The block is not initialized, so reading
|
||||||
|
## from it before writing to it is undefined behaviour!
|
||||||
|
## The allocated memory belongs to its allocating thread!
|
||||||
|
## Use `allocShared` to allocate from a shared heap.
|
||||||
|
cast[ptr T](alloc(T.sizeof * size))
|
||||||
proc alloc0*(size: int): pointer {.noconv, rtl, tags: [].}
|
proc alloc0*(size: int): pointer {.noconv, rtl, tags: [].}
|
||||||
## allocates a new memory block with at least ``size`` bytes. The
|
## allocates a new memory block with at least ``size`` bytes. The
|
||||||
## block has to be freed with ``realloc(block, 0)`` or
|
## block has to be freed with ``realloc(block, 0)`` or
|
||||||
|
|
@ -1171,14 +1179,31 @@ when not defined(nimrodVM):
|
||||||
## containing zero, so it is somewhat safer than ``alloc``.
|
## containing zero, so it is somewhat safer than ``alloc``.
|
||||||
## The allocated memory belongs to its allocating thread!
|
## The allocated memory belongs to its allocating thread!
|
||||||
## Use `allocShared0` to allocate from a shared heap.
|
## Use `allocShared0` to allocate from a shared heap.
|
||||||
proc realloc*(p: pointer, newsize: int): pointer {.noconv, rtl, tags: [].}
|
proc alloc0*(T: typedesc, size = 1): ptr T {.inline.} =
|
||||||
|
## allocates a new memory block with at least ``T.sizeof * size``
|
||||||
|
## bytes. The block has to be freed with ``realloc(block, 0)`` or
|
||||||
|
## ``dealloc(block)``. The block is initialized with all bytes
|
||||||
|
## containing zero, so it is somewhat safer than ``alloc``.
|
||||||
|
## The allocated memory belongs to its allocating thread!
|
||||||
|
## Use `allocShared0` to allocate from a shared heap.
|
||||||
|
cast[ptr T](alloc0(T.sizeof * size))
|
||||||
|
proc realloc*(p: pointer, newSize: int): pointer {.noconv, rtl, tags: [].}
|
||||||
## grows or shrinks a given memory block. If p is **nil** then a new
|
## grows or shrinks a given memory block. If p is **nil** then a new
|
||||||
## memory block is returned. In either way the block has at least
|
## memory block is returned. In either way the block has at least
|
||||||
## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil**
|
## ``newSize`` bytes. If ``newSize == 0`` and p is not **nil**
|
||||||
## ``realloc`` calls ``dealloc(p)``. In other cases the block has to
|
## ``realloc`` calls ``dealloc(p)``. In other cases the block has to
|
||||||
## be freed with ``dealloc``.
|
## be freed with ``dealloc``.
|
||||||
## The allocated memory belongs to its allocating thread!
|
## The allocated memory belongs to its allocating thread!
|
||||||
## Use `reallocShared` to reallocate from a shared heap.
|
## Use `reallocShared` to reallocate from a shared heap.
|
||||||
|
proc reallocType*[T](p: ptr T, newSize: int): ptr T {.inline.} =
|
||||||
|
## grows or shrinks a given memory block. If p is **nil** then a new
|
||||||
|
## memory block is returned. In either way the block has at least
|
||||||
|
## ``T.sizeof * newSize`` bytes. If ``newSize == 0`` and p is not
|
||||||
|
## **nil** ``realloc`` calls ``dealloc(p)``. In other cases the block
|
||||||
|
## has to be freed with ``dealloc``. The allocated memory belongs to
|
||||||
|
## its allocating thread!
|
||||||
|
## Use `reallocShared` to reallocate from a shared heap.
|
||||||
|
cast[ptr T](realloc(p, T.sizeof * newSize))
|
||||||
proc dealloc*(p: pointer) {.noconv, rtl, tags: [].}
|
proc dealloc*(p: pointer) {.noconv, rtl, tags: [].}
|
||||||
## frees the memory allocated with ``alloc``, ``alloc0`` or
|
## frees the memory allocated with ``alloc``, ``alloc0`` or
|
||||||
## ``realloc``. This procedure is dangerous! If one forgets to
|
## ``realloc``. This procedure is dangerous! If one forgets to
|
||||||
|
|
@ -1187,25 +1212,45 @@ when not defined(nimrodVM):
|
||||||
## or other memory may be corrupted.
|
## or other memory may be corrupted.
|
||||||
## The freed memory must belong to its allocating thread!
|
## The freed memory must belong to its allocating thread!
|
||||||
## Use `deallocShared` to deallocate from a shared heap.
|
## Use `deallocShared` to deallocate from a shared heap.
|
||||||
|
|
||||||
proc allocShared*(size: int): pointer {.noconv, rtl.}
|
proc allocShared*(size: int): pointer {.noconv, rtl.}
|
||||||
## allocates a new memory block on the shared heap with at
|
## allocates a new memory block on the shared heap with at
|
||||||
## least ``size`` bytes. The block has to be freed with
|
## least ``size`` bytes. The block has to be freed with
|
||||||
## ``reallocShared(block, 0)`` or ``deallocShared(block)``. The block
|
## ``reallocShared(block, 0)`` or ``deallocShared(block)``. The block
|
||||||
## is not initialized, so reading from it before writing to it is
|
## is not initialized, so reading from it before writing to it is
|
||||||
## undefined behaviour!
|
## undefined behaviour!
|
||||||
|
proc allocShared*(T: typedesc, size: int): ptr T {.inline.} =
|
||||||
|
## allocates a new memory block on the shared heap with at
|
||||||
|
## least ``T.sizeof * size`` bytes. The block has to be freed with
|
||||||
|
## ``reallocShared(block, 0)`` or ``deallocShared(block)``. The block
|
||||||
|
## is not initialized, so reading from it before writing to it is
|
||||||
|
## undefined behaviour!
|
||||||
|
cast[ptr T](allocShared(T.sizeof * size))
|
||||||
proc allocShared0*(size: int): pointer {.noconv, rtl.}
|
proc allocShared0*(size: int): pointer {.noconv, rtl.}
|
||||||
## allocates a new memory block on the shared heap with at
|
## allocates a new memory block on the shared heap with at
|
||||||
## least ``size`` bytes. The block has to be freed with
|
## least ``size`` bytes. The block has to be freed with
|
||||||
## ``reallocShared(block, 0)`` or ``deallocShared(block)``.
|
## ``reallocShared(block, 0)`` or ``deallocShared(block)``.
|
||||||
## The block is initialized with all bytes
|
## The block is initialized with all bytes
|
||||||
## containing zero, so it is somewhat safer than ``allocShared``.
|
## containing zero, so it is somewhat safer than ``allocShared``.
|
||||||
proc reallocShared*(p: pointer, newsize: int): pointer {.noconv, rtl.}
|
proc allocShared0*(T: typedesc, size: int): ptr T {.inline.} =
|
||||||
|
## allocates a new memory block on the shared heap with at
|
||||||
|
## least ``T.sizeof * size`` bytes. The block has to be freed with
|
||||||
|
## ``reallocShared(block, 0)`` or ``deallocShared(block)``.
|
||||||
|
## The block is initialized with all bytes
|
||||||
|
## containing zero, so it is somewhat safer than ``allocShared``.
|
||||||
|
cast[ptr T](allocShared(T.sizeof * size))
|
||||||
|
proc reallocShared*(p: pointer, newSize: int): pointer {.noconv, rtl.}
|
||||||
## grows or shrinks a given memory block on the heap. If p is **nil**
|
## grows or shrinks a given memory block on the heap. If p is **nil**
|
||||||
## then a new memory block is returned. In either way the block has at least
|
## then a new memory block is returned. In either way the block has at
|
||||||
## ``newsize`` bytes. If ``newsize == 0`` and p is not **nil**
|
## least ``newSize`` bytes. If ``newSize == 0`` and p is not **nil**
|
||||||
## ``reallocShared`` calls ``deallocShared(p)``. In other cases the
|
## ``reallocShared`` calls ``deallocShared(p)``. In other cases the
|
||||||
## block has to be freed with ``deallocShared``.
|
## block has to be freed with ``deallocShared``.
|
||||||
|
proc reallocSharedType*[T](p: ptr T, newSize: int): ptr T {.inline.} =
|
||||||
|
## grows or shrinks a given memory block on the heap. If p is **nil**
|
||||||
|
## then a new memory block is returned. In either way the block has at
|
||||||
|
## least ``T.sizeof * newSize`` bytes. If ``newSize == 0`` and p is
|
||||||
|
## not **nil** ``reallocShared`` calls ``deallocShared(p)``. In other
|
||||||
|
## cases the block has to be freed with ``deallocShared``.
|
||||||
|
cast[ptr T](reallocShared(p, T.sizeof * newSize))
|
||||||
proc deallocShared*(p: pointer) {.noconv, rtl.}
|
proc deallocShared*(p: pointer) {.noconv, rtl.}
|
||||||
## frees the memory allocated with ``allocShared``, ``allocShared0`` or
|
## frees the memory allocated with ``allocShared``, ``allocShared0`` or
|
||||||
## ``reallocShared``. This procedure is dangerous! If one forgets to
|
## ``reallocShared``. This procedure is dangerous! If one forgets to
|
||||||
|
|
|
||||||
|
|
@ -299,12 +299,12 @@ proc open*(address: string, server: bool, mode: TConnectionMode = conDEALER,
|
||||||
else:
|
else:
|
||||||
if connect(result.s, address) != 0'i32: zmqError()
|
if connect(result.s, address) != 0'i32: zmqError()
|
||||||
|
|
||||||
proc close*(c: var TConnection) =
|
proc close*(c: TConnection) =
|
||||||
## closes the connection.
|
## closes the connection.
|
||||||
if close(c.s) != 0'i32: zmqError()
|
if close(c.s) != 0'i32: zmqError()
|
||||||
if term(c.c) != 0'i32: zmqError()
|
if term(c.c) != 0'i32: zmqError()
|
||||||
|
|
||||||
proc send*(c: var TConnection, msg: string) =
|
proc send*(c: TConnection, msg: string) =
|
||||||
## sends a message over the connection.
|
## sends a message over the connection.
|
||||||
var m: TMsg
|
var m: TMsg
|
||||||
if msg_init(m, msg.len) != 0'i32: zmqError()
|
if msg_init(m, msg.len) != 0'i32: zmqError()
|
||||||
|
|
@ -312,7 +312,7 @@ proc send*(c: var TConnection, msg: string) =
|
||||||
if send(c.s, m, 0'i32) != 0'i32: zmqError()
|
if send(c.s, m, 0'i32) != 0'i32: zmqError()
|
||||||
discard msg_close(m)
|
discard msg_close(m)
|
||||||
|
|
||||||
proc receive*(c: var TConnection): string =
|
proc receive*(c: TConnection): string =
|
||||||
## receives a message from a connection.
|
## receives a message from a connection.
|
||||||
var m: TMsg
|
var m: TMsg
|
||||||
if msg_init(m) != 0'i32: zmqError()
|
if msg_init(m) != 0'i32: zmqError()
|
||||||
|
|
@ -320,4 +320,3 @@ proc receive*(c: var TConnection): string =
|
||||||
result = newString(msg_size(m))
|
result = newString(msg_size(m))
|
||||||
copyMem(addr(result[0]), msg_data(m), result.len)
|
copyMem(addr(result[0]), msg_data(m), result.len)
|
||||||
discard msg_close(m)
|
discard msg_close(m)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ discard """
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc factory(a, b: int): iterator (): int =
|
proc factory(a, b: int): iterator (): int =
|
||||||
iterator foo(): int =
|
iterator foo(): int {.closure.} =
|
||||||
var x = a
|
var x = a
|
||||||
while x <= b:
|
while x <= b:
|
||||||
yield x
|
yield x
|
||||||
|
|
|
||||||
43
tests/metatype/udtcmanual.nim
Normal file
43
tests/metatype/udtcmanual.nim
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
discard """
|
||||||
|
output: '''1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
4
|
||||||
|
5
|
||||||
|
6
|
||||||
|
a
|
||||||
|
b
|
||||||
|
t
|
||||||
|
e
|
||||||
|
s
|
||||||
|
t
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
template accept(e: expr) =
|
||||||
|
static: assert compiles(e)
|
||||||
|
|
||||||
|
template reject(e: expr) =
|
||||||
|
static: assert(not compiles(e))
|
||||||
|
|
||||||
|
type
|
||||||
|
Container[T] = generic C
|
||||||
|
C.len is Ordinal
|
||||||
|
items(c) is iterator
|
||||||
|
for value in C:
|
||||||
|
value.type is T
|
||||||
|
|
||||||
|
proc takesIntContainer(c: Container[int]) =
|
||||||
|
for e in c: echo e
|
||||||
|
|
||||||
|
takesIntContainer(@[1, 2, 3])
|
||||||
|
reject takesIntContainer(@["x", "y"])
|
||||||
|
|
||||||
|
proc takesContainer(c: Container) =
|
||||||
|
for e in c: echo e
|
||||||
|
|
||||||
|
takesContainer(@[4, 5, 6])
|
||||||
|
takesContainer(@["a", "b"])
|
||||||
|
takesContainer "test"
|
||||||
|
reject takesContainer(10)
|
||||||
|
|
||||||
45
tests/system/alloc.nim
Normal file
45
tests/system/alloc.nim
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
var x: ptr int
|
||||||
|
|
||||||
|
x = cast[ptr int](alloc(7))
|
||||||
|
assert x != nil
|
||||||
|
|
||||||
|
x = alloc(int, 3)
|
||||||
|
assert x != nil
|
||||||
|
x.dealloc()
|
||||||
|
|
||||||
|
x = alloc0(int, 4)
|
||||||
|
assert cast[ptr array[4, int]](x)[0] == 0
|
||||||
|
assert cast[ptr array[4, int]](x)[1] == 0
|
||||||
|
assert cast[ptr array[4, int]](x)[2] == 0
|
||||||
|
assert cast[ptr array[4, int]](x)[3] == 0
|
||||||
|
|
||||||
|
x = cast[ptr int](x.realloc(2))
|
||||||
|
assert x != nil
|
||||||
|
|
||||||
|
x = x.reallocType(4)
|
||||||
|
assert x != nil
|
||||||
|
x.dealloc()
|
||||||
|
|
||||||
|
x = cast[ptr int](allocShared(100))
|
||||||
|
assert x != nil
|
||||||
|
deallocShared(x)
|
||||||
|
|
||||||
|
x = allocShared(int, 3)
|
||||||
|
assert x != nil
|
||||||
|
x.deallocShared()
|
||||||
|
|
||||||
|
x = allocShared0(int, 3)
|
||||||
|
assert x != nil
|
||||||
|
assert cast[ptr array[3, int]](x)[0] == 0
|
||||||
|
assert cast[ptr array[3, int]](x)[1] == 0
|
||||||
|
assert cast[ptr array[3, int]](x)[2] == 0
|
||||||
|
|
||||||
|
x = cast[ptr int](reallocShared(x, 2))
|
||||||
|
assert x != nil
|
||||||
|
|
||||||
|
x = reallocType(x, 12)
|
||||||
|
assert x != nil
|
||||||
|
|
||||||
|
x = reallocSharedType(x, 1)
|
||||||
|
assert x != nil
|
||||||
|
x.deallocShared()
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
discard """
|
discard """
|
||||||
output: "true true false yes"
|
output: '''true true false yes'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc IsVoid[T](): string =
|
proc IsVoid[T](): string =
|
||||||
when T is void:
|
when T is void:
|
||||||
result = "yes"
|
result = "yes"
|
||||||
else:
|
else:
|
||||||
|
|
@ -11,3 +11,26 @@ proc IsVoid[T](): string =
|
||||||
const x = int is int
|
const x = int is int
|
||||||
echo x, " ", float is float, " ", float is string, " ", IsVoid[void]()
|
echo x, " ", float is float, " ", float is string, " ", IsVoid[void]()
|
||||||
|
|
||||||
|
template yes(e: expr): stmt =
|
||||||
|
static: assert e
|
||||||
|
|
||||||
|
template no(e: expr): stmt =
|
||||||
|
static: assert(not e)
|
||||||
|
|
||||||
|
var s = @[1, 2, 3]
|
||||||
|
|
||||||
|
yes s.items is iterator
|
||||||
|
no s.items is proc
|
||||||
|
|
||||||
|
yes s.items is iterator: int
|
||||||
|
no s.items is iterator: float
|
||||||
|
|
||||||
|
yes s.items is iterator: TNumber
|
||||||
|
no s.items is iterator: object
|
||||||
|
|
||||||
|
type
|
||||||
|
Iter[T] = iterator: T
|
||||||
|
|
||||||
|
yes s.items is Iter[TNumber]
|
||||||
|
no s.items is Iter[float]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue