mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-16 18:22:11 +00:00
progress with futures
This commit is contained in:
@@ -605,7 +605,7 @@ const
|
||||
# thus cannot be overloaded (also documented in the spec!):
|
||||
SpecialSemMagics* = {
|
||||
mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf,
|
||||
mEcho, mShallowCopy, mExpandToAst, mParallel}
|
||||
mEcho, mShallowCopy, mExpandToAst, mParallel, mSpawn}
|
||||
|
||||
type
|
||||
PNode* = ref TNode
|
||||
|
||||
@@ -86,8 +86,14 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo): PNode =
|
||||
# returns a[].b as a node
|
||||
var deref = newNodeI(nkHiddenDeref, info)
|
||||
deref.typ = a.typ.skipTypes(abstractInst).sons[0]
|
||||
assert deref.typ.kind == tyObject
|
||||
let field = getSymFromList(deref.typ.n, getIdent(b))
|
||||
var t = deref.typ
|
||||
var field: PSym
|
||||
while true:
|
||||
assert t.kind == tyObject
|
||||
field = getSymFromList(t.n, getIdent(b))
|
||||
if field != nil: break
|
||||
t = t.sons[0]
|
||||
if t == nil: break
|
||||
assert field != nil, b
|
||||
addSon(deref, a)
|
||||
result = newNodeI(nkDotExpr, info)
|
||||
@@ -124,6 +130,7 @@ proc callCodegenProc*(name: string, arg1: PNode;
|
||||
result.add arg1
|
||||
if arg2 != nil: result.add arg2
|
||||
if arg3 != nil: result.add arg3
|
||||
result.typ = sym.typ.sons[0]
|
||||
|
||||
# we have 4 cases to consider:
|
||||
# - a void proc --> nothing to do
|
||||
@@ -152,15 +159,21 @@ discard """
|
||||
We generate roughly this:
|
||||
|
||||
proc f_wrapper(args) =
|
||||
barrierEnter(args.barrier) # for parallel statement
|
||||
var a = args.a # copy strings/seqs; thread transfer; not generated for
|
||||
# the 'parallel' statement
|
||||
var b = args.b
|
||||
|
||||
args.fut = createFuture(thread, sizeof(T)) # optional
|
||||
args.fut = nimCreateFuture(thread, sizeof(T)) # optional
|
||||
nimFutureCreateCondVar(args.fut) # optional
|
||||
nimArgsPassingDone() # signal parent that the work is done
|
||||
#
|
||||
args.fut.blob = f(a, b, ...)
|
||||
nimFutureSignal(args.fut)
|
||||
|
||||
# - or -
|
||||
f(a, b, ...)
|
||||
barrierLeave(args.barrier) # for parallel statement
|
||||
|
||||
stmtList:
|
||||
var scratchObj
|
||||
@@ -196,8 +209,12 @@ proc createWrapperProc(f: PNode; threadParam, argsParam: PSym;
|
||||
|
||||
body.add callCodeGenProc("nimArgsPassingDone", threadParam.newSymNode)
|
||||
if fut != nil:
|
||||
body.add newAsgnStmt(indirectAccess(fut,
|
||||
if fut.typ.futureKind==futGC: "data" else: "blob", fut.info), call)
|
||||
let fk = fut.typ.sons[1].futureKind
|
||||
if fk == futInvalid:
|
||||
localError(f.info, "cannot create a future of type: " &
|
||||
typeToString(fut.typ.sons[1]))
|
||||
body.add newAsgnStmt(indirectAccess(fut,
|
||||
if fk == futGC: "data" else: "blob", fut.info), call)
|
||||
if barrier == nil:
|
||||
body.add callCodeGenProc("nimFutureSignal", fut)
|
||||
else:
|
||||
|
||||
@@ -1579,6 +1579,12 @@ proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
else:
|
||||
result = semDirectOp(c, n, flags)
|
||||
|
||||
proc createFuture(c: PContext; t: PType; info: TLineInfo): PType =
|
||||
result = newType(tyGenericInvokation, c.module)
|
||||
addSonSkipIntLit(result, magicsys.getCompilerProc("Future").typ)
|
||||
addSonSkipIntLit(result, t)
|
||||
result = instGenericContainer(c, info, result, allowMetaTypes = false)
|
||||
|
||||
proc setMs(n: PNode, s: PSym): PNode =
|
||||
result = n
|
||||
n.sons[0] = newSymNode(s)
|
||||
@@ -1610,6 +1616,12 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||
var x = n.lastSon
|
||||
if x.kind == nkDo: x = x.sons[bodyPos]
|
||||
result.sons[1] = semStmt(c, x)
|
||||
of mSpawn:
|
||||
result = setMs(n, s)
|
||||
result.sons[1] = semExpr(c, n.sons[1])
|
||||
# later passes may transform the type 'Future[T]' back into 'T'
|
||||
if not result[1].typ.isEmptyType:
|
||||
result.typ = createFuture(c, result[1].typ, n.info)
|
||||
else: result = semDirectOp(c, n, flags)
|
||||
|
||||
proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
|
||||
@@ -115,12 +115,6 @@ proc semLocals(c: PContext, n: PNode): PNode =
|
||||
if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a)
|
||||
result.add(a)
|
||||
|
||||
proc createFuture(c: PContext; t: PType; info: TLineInfo): PType =
|
||||
result = newType(tyGenericInvokation, c.module)
|
||||
addSonSkipIntLit(result, magicsys.getCompilerProc("Future").typ)
|
||||
addSonSkipIntLit(result, t)
|
||||
result = instGenericContainer(c, info, result, allowMetaTypes = false)
|
||||
|
||||
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
flags: TExprFlags): PNode =
|
||||
@@ -136,9 +130,4 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||
of mNBindSym: result = semBindSym(c, n)
|
||||
of mLocals: result = semLocals(c, n)
|
||||
of mSpawn:
|
||||
result = n
|
||||
# later passes may transform the type 'Future[T]' back into 'T'
|
||||
if not n[1].typ.isEmptyType:
|
||||
result.typ = createFuture(c, n[1].typ, n.info)
|
||||
else: result = n
|
||||
|
||||
Reference in New Issue
Block a user