Compare commits

..

3 commits

25 changed files with 46 additions and 409 deletions

View file

@ -1085,7 +1085,13 @@ proc inst(g: ModuleGraph; c: PContext; t: PType; kind: TTypeAttachedOp; idgen: I
let op = getAttachedOp(g, t, kind) let op = getAttachedOp(g, t, kind)
if op != nil and op.ast != nil and op.ast.isGenericRoutine: if op != nil and op.ast != nil and op.ast.isGenericRoutine:
if t.typeInst != nil: if t.typeInst != nil:
var a = TLiftCtx(info: info, g: g, kind: kind, c: c, idgen: idgen) var a: TLiftCtx
a.info = info
a.g = g
a.kind = kind
a.c = c
a.idgen = idgen
let opInst = instantiateGeneric(a, op, t, t.typeInst) let opInst = instantiateGeneric(a, op, t, t.typeInst)
if opInst.ast != nil: if opInst.ast != nil:
patchBody(g, c, opInst.ast, info, a.idgen) patchBody(g, c, opInst.ast, info, a.idgen)

View file

@ -343,8 +343,7 @@ proc addDeclAt*(c: PContext; scope: PScope, sym: PSym, info: TLineInfo) =
if sym.name.s == "_": return if sym.name.s == "_": return
let conflict = scope.addUniqueSym(sym) let conflict = scope.addUniqueSym(sym)
if conflict != nil: if conflict != nil:
if sym.kind == skModule and conflict.kind == skModule and if sym.kind == skModule and conflict.kind == skModule and sym.owner == conflict.owner:
sym.position == conflict.position:
# e.g.: import foo; import foo # e.g.: import foo; import foo
# xxx we could refine this by issuing a different hint for the case # xxx we could refine this by issuing a different hint for the case
# where a duplicate import happens inside an include. # where a duplicate import happens inside an include.

View file

@ -71,13 +71,6 @@ proc commandGenDepend(graph: ModuleGraph) =
let project = graph.config.projectFull let project = graph.config.projectFull
writeDepsFile(graph) writeDepsFile(graph)
generateDot(graph, project) generateDot(graph, project)
# dot in graphivz tool kit is required
let graphvizDotPath = findExe("dot")
if graphvizDotPath.len == 0:
quit("gendepend: Graphviz's tool dot is required," &
"see https://graphviz.org/download for downloading")
execExternalProgram(graph.config, "dot -Tpng -o" & execExternalProgram(graph.config, "dot -Tpng -o" &
changeFileExt(project, "png").string & changeFileExt(project, "png").string &
' ' & changeFileExt(project, "dot").string) ' ' & changeFileExt(project, "dot").string)

View file

@ -7,4 +7,4 @@ proc findNodeJs*(): string {.inline.} =
result = findExe("node") result = findExe("node")
if result.len == 0: if result.len == 0:
echo "Please install NodeJS first, see https://nodejs.org/en/download" echo "Please install NodeJS first, see https://nodejs.org/en/download"
raise newException(IOError, "NodeJS not found in PATH") raise newException(IOError, "NodeJS not found in PATH: " & result)

View file

@ -998,7 +998,7 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags; expectedTy
fixAbstractType(c, result) fixAbstractType(c, result)
analyseIfAddressTakenInCall(c, result) analyseIfAddressTakenInCall(c, result)
if callee.magic != mNone: if callee.magic != mNone:
result = magicsAfterOverloadResolution(c, result, flags, expectedType) result = magicsAfterOverloadResolution(c, result, flags)
when false: when false:
if result.typ != nil and if result.typ != nil and
not (result.typ.kind == tySequence and result.typ[0].kind == tyEmpty): not (result.typ.kind == tySequence and result.typ[0].kind == tyEmpty):
@ -2206,7 +2206,7 @@ proc semQuoteAst(c: PContext, n: PNode): PNode =
dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids[0], getSysSym(c.graph, n.info, "typed").newSymNode, c.graph.emptyNode) dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids[0], getSysSym(c.graph, n.info, "typed").newSymNode, c.graph.emptyNode)
for i in 1..<ids.len: for i in 1..<ids.len:
let typ = semExprWithType(c, quotes[i+1], {}).typ let typ = semExprWithType(c, quotes[i+1], {}).typ
if tfTriggersCompileTime notin typ.flags and typ.kind != tyTypeDesc: if tfTriggersCompileTime notin typ.flags:
dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids[i], newNodeIT(nkType, n.info, typ), c.graph.emptyNode) dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids[i], newNodeIT(nkType, n.info, typ), c.graph.emptyNode)
else: else:
dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids[i], getSysSym(c.graph, n.info, "typed").newSymNode, c.graph.emptyNode) dummyTemplate[paramsPos].add newTreeI(nkIdentDefs, n.info, ids[i], getSysSym(c.graph, n.info, "typed").newSymNode, c.graph.emptyNode)

View file

@ -131,14 +131,7 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) =
if sfBorrow notin orig.flags: if sfBorrow notin orig.flags:
# We do not want to generate a body for generic borrowed procs. # We do not want to generate a body for generic borrowed procs.
# As body is a sym to the borrowed proc. # As body is a sym to the borrowed proc.
let resultType = # todo probably refactor it into a function b = semProcBody(c, b)
if result.kind == skMacro:
sysTypeFromName(c.graph, n.info, "NimNode")
elif not isInlineIterator(result.typ):
result.typ[0]
else:
nil
b = semProcBody(c, b, resultType)
result.ast[bodyPos] = hloBody(c, b) result.ast[bodyPos] = hloBody(c, b)
excl(result.flags, sfForward) excl(result.flags, sfForward)
trackProc(c, result, result.ast[bodyPos]) trackProc(c, result, result.ast[bodyPos])

View file

@ -526,7 +526,7 @@ proc checkDefault(c: PContext, n: PNode): PNode =
message(c.config, n.info, warnUnsafeDefault, typeToString(constructed)) message(c.config, n.info, warnUnsafeDefault, typeToString(constructed))
proc magicsAfterOverloadResolution(c: PContext, n: PNode, proc magicsAfterOverloadResolution(c: PContext, n: PNode,
flags: TExprFlags; expectedType: PType = nil): PNode = flags: TExprFlags): PNode =
## This is the preferred code point to implement magics. ## This is the preferred code point to implement magics.
## ``c`` the current module, a symbol table to a very good approximation ## ``c`` the current module, a symbol table to a very good approximation
## ``n`` the ast like it would be passed to a real macro ## ``n`` the ast like it would be passed to a real macro
@ -635,9 +635,5 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
result = n result = n
of mPrivateAccess: of mPrivateAccess:
result = semPrivateAccess(c, n) result = semPrivateAccess(c, n)
of mArrToSeq:
result = n
if result.typ != nil and expectedType != nil and result.typ.kind == tySequence and expectedType.kind == tySequence and result.typ[0].kind == tyEmpty:
result.typ = expectedType # type inference for empty sequence # bug #21377
else: else:
result = n result = n

View file

@ -142,45 +142,15 @@ proc fieldsPresentInInitExpr(c: PContext, fieldsRecList, initExpr: PNode): strin
if result.len != 0: result.add ", " if result.len != 0: result.add ", "
result.add field.sym.name.s.quoteStr result.add field.sym.name.s.quoteStr
proc locateFieldInDefaults(sym: PSym, defaults: seq[PNode]): bool =
result = false
for d in defaults:
if sym.id == d[0].sym.id:
return true
proc collectMissingFields(c: PContext, fieldsRecList: PNode, proc collectMissingFields(c: PContext, fieldsRecList: PNode,
constrCtx: var ObjConstrContext, defaults: seq[PNode] constrCtx: var ObjConstrContext) =
): seq[PSym] = for r in directFieldsInRecList(fieldsRecList):
for r in directFieldsInRecList(fieldsRecList): if constrCtx.needsFullInit or
sfRequiresInit in r.sym.flags or
r.sym.typ.requiresInit:
let assignment = locateFieldInInitExpr(c, r.sym, constrCtx.initExpr) let assignment = locateFieldInInitExpr(c, r.sym, constrCtx.initExpr)
if assignment == nil and not locateFieldInDefaults(r.sym, defaults): if assignment == nil:
if constrCtx.needsFullInit or constrCtx.missingFields.add r.sym
sfRequiresInit in r.sym.flags or
r.sym.typ.requiresInit:
constrCtx.missingFields.add r.sym
else:
result.add r.sym
proc collectMissingCaseFields(c: PContext, branchNode: PNode,
constrCtx: var ObjConstrContext, defaults: seq[PNode]): seq[PSym] =
if branchNode != nil:
let fieldsRecList = branchNode[^1]
result = collectMissingFields(c, fieldsRecList, constrCtx, defaults)
proc collectOrAddMissingCaseFields(c: PContext, branchNode: PNode,
constrCtx: var ObjConstrContext, defaults: var seq[PNode]) =
let res = collectMissingCaseFields(c, branchNode, constrCtx, defaults)
for sym in res:
let asgnType = newType(tyTypeDesc, nextTypeId(c.idgen), sym.typ.owner)
let recTyp = sym.typ.skipTypes(defaultFieldsSkipTypes)
rawAddSon(asgnType, recTyp)
let asgnExpr = newTree(nkCall,
newSymNode(getSysMagic(c.graph, constrCtx.initExpr.info, "zeroDefault", mZeroDefault)),
newNodeIT(nkType, constrCtx.initExpr.info, asgnType)
)
asgnExpr.flags.incl nfUseDefaultField
asgnExpr.typ = recTyp
defaults.add newTree(nkExprColonExpr, newSymNode(sym), asgnExpr)
proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext, proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
flags: TExprFlags): tuple[status: InitStatus, defaults: seq[PNode]] = flags: TExprFlags): tuple[status: InitStatus, defaults: seq[PNode]] =
@ -196,6 +166,11 @@ proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
let fields = branch[^1] let fields = branch[^1]
fieldsPresentInInitExpr(c, fields, constrCtx.initExpr) fieldsPresentInInitExpr(c, fields, constrCtx.initExpr)
template collectMissingFields(branchNode: PNode) =
if branchNode != nil:
let fields = branchNode[^1]
collectMissingFields(c, fields, constrCtx)
let discriminator = n[0] let discriminator = n[0]
internalAssert c.config, discriminator.kind == nkSym internalAssert c.config, discriminator.kind == nkSym
var selectedBranch = -1 var selectedBranch = -1
@ -313,7 +288,8 @@ proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
# When a branch is selected with a partial match, some of the fields # When a branch is selected with a partial match, some of the fields
# that were not initialized may be mandatory. We must check for this: # that were not initialized may be mandatory. We must check for this:
if result.status == initPartial: if result.status == initPartial:
collectOrAddMissingCaseFields(c, branchNode, constrCtx, result.defaults) collectMissingFields branchNode
else: else:
result.status = initNone result.status = initNone
let discriminatorVal = semConstrField(c, flags + {efPreferStatic}, let discriminatorVal = semConstrField(c, flags + {efPreferStatic},
@ -326,7 +302,7 @@ proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
# a result: # a result:
let defaultValue = newIntLit(c.graph, constrCtx.initExpr.info, 0) let defaultValue = newIntLit(c.graph, constrCtx.initExpr.info, 0)
let matchedBranch = n.pickCaseBranch defaultValue let matchedBranch = n.pickCaseBranch defaultValue
discard collectMissingCaseFields(c, matchedBranch, constrCtx, @[]) collectMissingFields matchedBranch
else: else:
result.status = initPartial result.status = initPartial
if discriminatorVal.kind == nkIntLit: if discriminatorVal.kind == nkIntLit:
@ -336,12 +312,11 @@ proc semConstructFields(c: PContext, n: PNode, constrCtx: var ObjConstrContext,
if matchedBranch != nil: if matchedBranch != nil:
let (_, defaults) = semConstructFields(c, matchedBranch[^1], constrCtx, flags) let (_, defaults) = semConstructFields(c, matchedBranch[^1], constrCtx, flags)
result.defaults.add defaults result.defaults.add defaults
collectOrAddMissingCaseFields(c, matchedBranch, constrCtx, result.defaults) collectMissingFields matchedBranch
else: else:
# All bets are off. If any of the branches has a mandatory # All bets are off. If any of the branches has a mandatory
# fields we must produce an error: # fields we must produce an error:
for i in 1..<n.len: for i in 1..<n.len: collectMissingFields n[i]
discard collectMissingCaseFields(c, n[i], constrCtx, @[])
of nkSym: of nkSym:
let field = n.sym let field = n.sym
let e = semConstrField(c, flags, field, constrCtx.initExpr) let e = semConstrField(c, flags, field, constrCtx.initExpr)
@ -373,7 +348,7 @@ proc semConstructTypeAux(c: PContext,
result.status.mergeInitStatus status result.status.mergeInitStatus status
result.defaults.add defaults result.defaults.add defaults
if status in {initPartial, initNone, initUnknown}: if status in {initPartial, initNone, initUnknown}:
discard collectMissingFields(c, t.n, constrCtx, result.defaults) collectMissingFields c, t.n, constrCtx
let base = t[0] let base = t[0]
if base == nil: break if base == nil: break
t = skipTypes(base, skipPtrs) t = skipTypes(base, skipPtrs)

View file

@ -50,7 +50,6 @@ type
module: PSym module: PSym
transCon: PTransCon # top of a TransCon stack transCon: PTransCon # top of a TransCon stack
inlining: int # > 0 if we are in inlining context (copy vars) inlining: int # > 0 if we are in inlining context (copy vars)
isIntroducingNewLocalVars: bool # true if we are in `introducingNewLocalVars` (don't transform yields)
contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break' contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break'
deferDetected, tooEarly: bool deferDetected, tooEarly: bool
graph: ModuleGraph graph: ModuleGraph
@ -451,9 +450,7 @@ proc transformYield(c: PTransf, n: PNode): PNode =
result.add(c.transCon.forLoopBody) result.add(c.transCon.forLoopBody)
else: else:
# we need to introduce new local variables: # we need to introduce new local variables:
c.isIntroducingNewLocalVars = true # don't transform yields when introducing new local vars
result.add(introduceNewLocalVars(c, c.transCon.forLoopBody)) result.add(introduceNewLocalVars(c, c.transCon.forLoopBody))
c.isIntroducingNewLocalVars = false
for idx in 0 ..< result.len: for idx in 0 ..< result.len:
var changeNode = result[idx] var changeNode = result[idx]
@ -1039,7 +1036,7 @@ proc transform(c: PTransf, n: PNode): PNode =
else: else:
result = transformSons(c, n) result = transformSons(c, n)
of nkYieldStmt: of nkYieldStmt:
if c.inlining > 0 and not c.isIntroducingNewLocalVars: if c.inlining > 0:
result = transformYield(c, n) result = transformYield(c, n)
else: else:
result = transformSons(c, n) result = transformSons(c, n)

View file

@ -1909,8 +1909,7 @@ proc genVarSection(c: PCtx; n: PNode) =
c.genAdditionalCopy(a[2], opcWrDeref, tmp, 0, val) c.genAdditionalCopy(a[2], opcWrDeref, tmp, 0, val)
c.freeTemp(val) c.freeTemp(val)
c.freeTemp(tmp) c.freeTemp(tmp)
elif not importcCondVar(s) and not (s.typ.kind == tyProc and s.typ.callConv == ccClosure) and elif not importcCondVar(s) and not (s.typ.kind == tyProc and s.typ.callConv == ccClosure): # fixes #10938
sfPure notin s.flags: # fixes #10938
# there is a pre-existing issue with closure types in VM # there is a pre-existing issue with closure types in VM
# if `(var s: proc () = default(proc ()); doAssert s == nil)` works for you; # if `(var s: proc () = default(proc ()); doAssert s == nil)` works for you;
# you might remove the second condition. # you might remove the second condition.

View file

@ -172,6 +172,6 @@ Advanced options:
--useVersion:1.0|1.2|1.6 emulate Nim version X of the Nim compiler, for testing --useVersion:1.0|1.2|1.6 emulate Nim version X of the Nim compiler, for testing
--benchmarkVM:on|off turn benchmarking of VM code with cpuTime() on|off --benchmarkVM:on|off turn benchmarking of VM code with cpuTime() on|off
--profileVM:on|off turn compile time VM profiler on|off --profileVM:on|off turn compile time VM profiler on|off
--sinkInference:on|off turn sink parameter inference on|off (default: off) --sinkInference:on|off turn sink parameter inference on|off (default: on)
--panics:on|off turn panics into process terminations (default: off) --panics:on|off turn panics into process terminations (default: off)
--deepcopy:on|off enable 'system.deepCopy' for ``--mm:arc|orc`` --deepcopy:on|off enable 'system.deepCopy' for ``--mm:arc|orc``

View file

@ -408,16 +408,6 @@ const unitWeights: array[FixedTimeUnit, int64] = [
7 * secondsInDay * 1e9.int64, 7 * secondsInDay * 1e9.int64,
] ]
when (NimMajor, NimMinor) >= (1, 4):
# Newer versions of Nim don't track defects
{.pragma: parseFormatRaises, raises: [TimeParseError, TimeFormatParseError].}
{.pragma: parseRaises, raises: [TimeParseError].}
else:
# Still track when using older versions
{.pragma: parseFormatRaises, raises: [TimeParseError, TimeFormatParseError, Defect].}
{.pragma: parseRaises, raises: [TimeParseError, Defect].}
# #
# Helper procs # Helper procs
# #
@ -2144,7 +2134,8 @@ proc format*(time: Time, f: static[string], zone: Timezone = local()): string
result = time.inZone(zone).format(f2) result = time.inZone(zone).format(f2)
proc parse*(input: string, f: TimeFormat, zone: Timezone = local(), proc parse*(input: string, f: TimeFormat, zone: Timezone = local(),
loc: DateTimeLocale = DefaultLocale): DateTime {.parseRaises.} = loc: DateTimeLocale = DefaultLocale): DateTime
{.raises: [TimeParseError, Defect].} =
## Parses `input` as a `DateTime` using the format specified by `f`. ## Parses `input` as a `DateTime` using the format specified by `f`.
## If no UTC offset was parsed, then `input` is assumed to be specified in ## If no UTC offset was parsed, then `input` is assumed to be specified in
## the `zone` timezone. If a UTC offset was parsed, the result will be ## the `zone` timezone. If a UTC offset was parsed, the result will be
@ -2187,7 +2178,8 @@ proc parse*(input: string, f: TimeFormat, zone: Timezone = local(),
result = toDateTime(parsed, zone, f, input) result = toDateTime(parsed, zone, f, input)
proc parse*(input, f: string, tz: Timezone = local(), proc parse*(input, f: string, tz: Timezone = local(),
loc: DateTimeLocale = DefaultLocale): DateTime {.parseFormatRaises.} = loc: DateTimeLocale = DefaultLocale): DateTime
{.raises: [TimeParseError, TimeFormatParseError, Defect].} =
## Shorthand for constructing a `TimeFormat` and using it to parse ## Shorthand for constructing a `TimeFormat` and using it to parse
## `input` as a `DateTime`. ## `input` as a `DateTime`.
## ##
@ -2200,12 +2192,14 @@ proc parse*(input, f: string, tz: Timezone = local(),
result = input.parse(dtFormat, tz, loc = loc) result = input.parse(dtFormat, tz, loc = loc)
proc parse*(input: string, f: static[string], zone: Timezone = local(), proc parse*(input: string, f: static[string], zone: Timezone = local(),
loc: DateTimeLocale = DefaultLocale): DateTime {.parseRaises.} = loc: DateTimeLocale = DefaultLocale):
DateTime {.raises: [TimeParseError, Defect].} =
## Overload that validates `f` at compile time. ## Overload that validates `f` at compile time.
const f2 = initTimeFormat(f) const f2 = initTimeFormat(f)
result = input.parse(f2, zone, loc = loc) result = input.parse(f2, zone, loc = loc)
proc parseTime*(input, f: string, zone: Timezone): Time {.parseFormatRaises.} = proc parseTime*(input, f: string, zone: Timezone): Time
{.raises: [TimeParseError, TimeFormatParseError, Defect].} =
## Shorthand for constructing a `TimeFormat` and using it to parse ## Shorthand for constructing a `TimeFormat` and using it to parse
## `input` as a `DateTime`, then converting it a `Time`. ## `input` as a `DateTime`, then converting it a `Time`.
## ##
@ -2217,7 +2211,7 @@ proc parseTime*(input, f: string, zone: Timezone): Time {.parseFormatRaises.} =
parse(input, f, zone).toTime() parse(input, f, zone).toTime()
proc parseTime*(input: string, f: static[string], zone: Timezone): Time proc parseTime*(input: string, f: static[string], zone: Timezone): Time
{.parseRaises.} = {.raises: [TimeParseError, Defect].} =
## Overload that validates `format` at compile time. ## Overload that validates `format` at compile time.
const f2 = initTimeFormat(f) const f2 = initTimeFormat(f)
result = input.parse(f2, zone).toTime() result = input.parse(f2, zone).toTime()

View file

@ -269,64 +269,3 @@ proc bug20305 =
echo x.pChildren echo x.pChildren
bug20305() bug20305()
# bug #21023
block:
block:
type
MGErrorKind = enum
mgeUnexpected, mgeNotFound
type Foo = object
kind: MGErrorKind
ex: Exception
type Boo = object
a: seq[int]
type
Result2 = object
case o: bool
of false:
e: Foo
of true:
v: Boo
proc startSessionSync(): Result2 =
return Result2(o: true)
proc mainSync =
let ff = startSessionSync()
doAssert ff.o == true
mainSync()
block:
type
MGErrorKind = enum
mgeUnexpected, mgeNotFound
type Foo = object
kind: MGErrorKind
ex: Exception
type Boo = object
a: seq[int]
type
Result2 = object
case o: bool
of false:
e: Foo
of true:
v: Boo
s: int
proc startSessionSync(): Result2 =
return Result2(o: true, s: 12)
proc mainSync =
let ff = startSessionSync()
doAssert ff.s == 12
mainSync()

View file

@ -1,12 +0,0 @@
discard """
cmd: "nim check $options $file"
errormsg: "type mismatch: got <int> but expected 'float'"
"""
when true: # bug #16654
func fn[T](a: T, op: proc(a: T): float) = discard
proc main() =
let v = 1
proc bar(r: auto): auto = v
fn(1, bar)
main()

View file

@ -153,16 +153,3 @@ proc unzip*[T,U](xs: List[tuple[t: T, u: U]]): (List[T], List[U]) = discard
proc unzip2*[T,U](xs: List[(T,U)]): (List[T], List[U]) = discard proc unzip2*[T,U](xs: List[(T,U)]): (List[T], List[U]) = discard
type
AtomicType = pointer|ptr|int
Atomic[T: AtomicType] = distinct T
Block[T: AtomicType] = object
AtomicContainer[T: AtomicType] = object
b: Atomic[ptr Block[T]]
# bug #8295
var x = AtomicContainer[int]()
doAssert (ptr Block[int])(x.b) == nil

View file

@ -262,8 +262,3 @@ proc doSomething[A, B](t: tuple[a: A, b: B]) = discard
discard identity((c: 1, d: 2)) discard identity((c: 1, d: 2))
doSomething(identity((1, 2))) doSomething(identity((1, 2)))
# bug #6231
proc myProc[T, U](x: T or U) = discard
myProc[int, string](x = 2)

View file

@ -1 +0,0 @@
proc fb* = echo "buzz!"

View file

@ -1 +0,0 @@
proc fb* = echo "fizz!"

View file

@ -1,9 +0,0 @@
discard """
errormsg: "redefinition of 'm21496'; previous declaration here: t21496.nim(5, 12)"
"""
import fizz/m21496, buzz/m21496
# bug #21496
m21496.fb()

View file

@ -1,114 +0,0 @@
# bug #21306
type
FutureState {.pure.} = enum
Pending, Finished, Cancelled, Failed
FutureBase = ref object of RootObj
state: FutureState
error: ref CatchableError
id: uint
Future[T] = ref object of FutureBase
closure: iterator(f: Future[T]): FutureBase {.raises: [Defect, CatchableError, Exception], gcsafe.}
value: T
template setupFutureBase() =
new(result)
result.state = FutureState.Pending
proc newFutureImpl[T](): Future[T] =
setupFutureBase()
template newFuture[T](fromProc: static[string] = ""): Future[T] =
newFutureImpl[T]()
proc internalRead[T](fut: Future[T]): T =
when T isnot void:
return fut.value
template await[T](f: Future[T]): untyped =
when declared(chronosInternalRetFuture):
when not declaredInScope(chronosInternalTmpFuture):
var chronosInternalTmpFuture {.inject.}: FutureBase = f
else:
chronosInternalTmpFuture = f
yield chronosInternalTmpFuture
when T isnot void:
cast[type(f)](chronosInternalTmpFuture).internalRead()
type
VerifierError {.pure.} = enum
Invalid
MissingParent
UnviableFork
Duplicate
ProcessingCallback = proc() {.gcsafe, raises: [Defect].}
BlockVerifier =
proc(signedBlock: int):
Future[VerifierError] {.gcsafe, raises: [Defect].}
SyncQueueKind {.pure.} = enum
Forward, Backward
SyncRequest[T] = object
kind: SyncQueueKind
index: uint64
slot: uint64
count: uint64
item: T
SyncResult[T] = object
request: SyncRequest[T]
data: seq[ref int]
SyncQueue[T] = ref object
kind: SyncQueueKind
readyQueue: seq[SyncResult[T]]
blockVerifier: BlockVerifier
iterator blocks[T](sq: SyncQueue[T],
sr: SyncResult[T]): ref int =
case sq.kind
of SyncQueueKind.Forward:
for i in countup(0, len(sr.data) - 1):
yield sr.data[i]
of SyncQueueKind.Backward:
for i in countdown(len(sr.data) - 1, 0):
yield sr.data[i]
proc push[T](sq: SyncQueue[T]; sr: SyncRequest[T]; data: seq[ref int];
processingCb: ProcessingCallback = nil): Future[void] {.
stackTrace: off, gcsafe.} =
iterator push_436208182(chronosInternalRetFuture: Future[void]): FutureBase {.
closure, gcsafe, raises: [Defect, CatchableError, Exception].} =
block:
template result(): auto {.used.} =
{.fatal: "You should not reference the `result` variable inside" &
" a void async proc".}
let item = default(SyncResult[T])
for blk in sq.blocks(item):
let res = await sq.blockVerifier(blk[])
var resultFuture = newFuture[void]("push")
resultFuture.closure = push_436208182
return resultFuture
type
SomeTPeer = ref object
score: int
proc getSlice(): seq[ref int] =
discard
template smokeTest(kkind: SyncQueueKind, start, finish: uint64,
chunkSize: uint64) =
var queue: SyncQueue[SomeTPeer]
var request: SyncRequest[SomeTPeer]
discard queue.push(request, getSlice())
for k in {SyncQueueKind.Forward}:
for item in [(uint64(1181), uint64(1399), 41'u64)]:
smokeTest(k, item[0], item[1], item[2])

View file

@ -559,38 +559,6 @@ template main {.dirty.} =
let x = default(Default) let x = default(Default)
doAssert x.data is DjangoDateTime doAssert x.data is DjangoDateTime
block:
type
Result2 = object
case o: bool
of false:
e: float
of true:
v {.requiresInit.} : int = 1
proc startSessionSync(): Result2 =
return Result2(o: true)
proc mainSync =
let ff = startSessionSync()
doAssert ff.v == 1
mainSync()
block:
type
Result2 = object
v {.requiresInit.} : int = 1
proc startSessionSync(): Result2 =
return Result2()
proc mainSync =
let ff = startSessionSync()
doAssert ff.v == 1
mainSync()
static: main() static: main()
main() main()

View file

@ -311,11 +311,3 @@ block: # bug #9607
doAssert echoL() == "bar" doAssert echoL() == "bar"
doAssert echoM() == "bar" doAssert echoM() == "bar"
block:
macro hello[T](x: T): untyped =
result = quote do:
let m: `T` = `x`
discard m
hello(12)

View file

@ -3,7 +3,7 @@ discard """
x + y = 30 x + y = 30
''' '''
""" """
import std/[sugar, algorithm, random, sets, tables, strutils, sequtils] import std/[sugar, algorithm, random, sets, tables, strutils]
import std/[syncio, assertions] import std/[syncio, assertions]
type # for capture test, ref #20679 type # for capture test, ref #20679
@ -287,17 +287,6 @@ proc mainProc() =
doAssertRaises(AssertionDefect): doAssert false doAssertRaises(AssertionDefect): doAssert false
doAssert "except AssertionDefect" in s2 doAssert "except AssertionDefect" in s2
block: # bug #20704
proc test() =
var xs, ys: seq[int]
for i in 0..5:
xs.add(i)
xs.apply(d => ys.add(d))
doAssert ys == @[0, 1, 2, 3, 4, 5]
test()
static: static:
main() main()
mainProc() mainProc()

View file

@ -245,7 +245,7 @@ block: # bug #11777
var s: S = {1, 2} var s: S = {1, 2}
doAssert 1 in s doAssert 1 in s
block: # bug #20807 block: # regression #20807
var s: seq[string] var s: seq[string]
template fail = template fail =
s = @[] s = @[]
@ -255,38 +255,3 @@ block: # bug #20807
test: fail() test: fail()
doAssert not (compiles do: doAssert not (compiles do:
let x: seq[int] = `@`[string]([])) let x: seq[int] = `@`[string]([]))
block: # bug #21377
proc b[T](v: T): seq[int] =
let x = 0
@[]
doAssert b(0) == @[]
block: # bug #21377
proc b[T](v: T): seq[T] =
let x = 0
@[]
doAssert b(0) == @[]
block: # bug #21377
proc b[T](v: T): set[bool] =
let x = 0
{}
doAssert b(0) == {}
block: # bug #21377
proc b[T](v: T): array[0, int] =
let x = 0
[]
doAssert b(0) == []
block: # bug #21377
proc b[T](v: T): array[0, (string, string)] =
let x = 0
{:}
doAssert b(0) == {:}

View file

@ -643,16 +643,3 @@ const b = block:
doAssert a == @[@[0, 1, 2], @[0, 1, 2], @[0, 1, 2]] doAssert a == @[@[0, 1, 2], @[0, 1, 2], @[0, 1, 2]]
doAssert b == @[@[0, 1, 2], @[0, 1, 2], @[0, 1, 2]] doAssert b == @[@[0, 1, 2], @[0, 1, 2], @[0, 1, 2]]
macro m1(s: string): int =
var ProcID {.global, compileTime.}: int
inc(ProcID)
result = newLit(ProcID)
proc macroGlobal =
doAssert m1("Macro argument") == 1
doAssert m1("Macro argument") == 2
doAssert m1("Macro argument") == 3
static: macroGlobal()
macroGlobal()